|
|
@@ -0,0 +1,215 @@
|
|
|
+import React from 'react'
|
|
|
+import { connect } from 'dva'
|
|
|
+import { Modal, Input, Form, Button, Icon, Collapse, Spin } from 'antd'
|
|
|
+import './cusFilterBox.less'
|
|
|
+
|
|
|
+class CusFilterBox extends React.Component {
|
|
|
+
|
|
|
+ constructor(props) {
|
|
|
+ super(props);
|
|
|
+ this.state = {
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ addRelationColumn = () => {
|
|
|
+ const { dispatch } = this.props;
|
|
|
+ dispatch({ type: 'dashboardDesigner/addRelationColumn' });
|
|
|
+ }
|
|
|
+
|
|
|
+ deleteRelationColumn = (e) => {
|
|
|
+ const { dispatch } = this.props;
|
|
|
+ const code = e.target.dataset.code;
|
|
|
+ dispatch({ type: 'dashboardDesigner/deleteRelationColumn', code });
|
|
|
+ }
|
|
|
+
|
|
|
+ generateRelations = () => {
|
|
|
+ const { dashboardDesigner, dispatch } = this.props;
|
|
|
+ const { editing, selectedDataSource } = this.state;
|
|
|
+ const { relationColumns, dataSources, columnFetching } = dashboardDesigner;
|
|
|
+
|
|
|
+ return relationColumns.map((r, ri) => (
|
|
|
+ <Collapse.Panel
|
|
|
+ key={r.code}
|
|
|
+ disabled={editing}
|
|
|
+ header={<Form.Item className='filtercolumn-name' label='名称' labelCol={{ span: 6 }} wrapperCol={{ span: 18 }}>
|
|
|
+ <Input size='small' value={r.name}
|
|
|
+ onChange={(e) => {
|
|
|
+ dispatch({ type: 'dashboardDesigner/setRelationColumn', code: r.code, relationColumn: { ...r, name: e.target.value } });
|
|
|
+ }} onFocus={() => {
|
|
|
+ this.setState({
|
|
|
+ editing: true,
|
|
|
+ })
|
|
|
+ }} onBlur={() => {
|
|
|
+ this.setState({
|
|
|
+ editing: false
|
|
|
+ })
|
|
|
+ }}/>
|
|
|
+ </Form.Item>}
|
|
|
+ >
|
|
|
+ {(dataSources.length > 0 ? <div className='filtercolumn-relation'>
|
|
|
+ {columnFetching && <div className='loading'>
|
|
|
+ <Spin />
|
|
|
+ </div>}
|
|
|
+ <div className='datasources'>
|
|
|
+ { dataSources.map((d, di) => (
|
|
|
+ <Button
|
|
|
+ className='datasource'
|
|
|
+ key={d.code}
|
|
|
+ type={!!selectedDataSource && selectedDataSource.code === d.code ? 'primary' : 'default'}
|
|
|
+ onClick={() => {
|
|
|
+ this.setState({
|
|
|
+ selectedDataSource: {
|
|
|
+ code: d.code,
|
|
|
+ name: d.name
|
|
|
+ },
|
|
|
+ selectedColumn: null
|
|
|
+ });
|
|
|
+ dispatch({ type: 'dashboardDesigner/remoteGetColumns', dataSourceCode: d.code });
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <span className='label'>{d.name}</span>
|
|
|
+ {r.relations.findIndex(r => r.dataSource.code === d.code) !== -1 && <Icon type='check-circle' theme={r.relations[0].dataSource.code === d.code ? 'filled' : 'outlined'} />}
|
|
|
+ </Button>
|
|
|
+ )) }
|
|
|
+ </div>
|
|
|
+ <div className='columns'>
|
|
|
+ { this.generateRelationColumns(r) }
|
|
|
+ </div>
|
|
|
+ </div> : <div className='filtercolumn-empty'>
|
|
|
+ 无关联数据源
|
|
|
+ </div>)}
|
|
|
+ <div className='filtercolumn-delete'>
|
|
|
+ <Button type='danger' className='delbtn' data-code={r.code} onClick={this.deleteRelationColumn}>
|
|
|
+ <Icon type='delete' theme='outlined' />删除
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </Collapse.Panel>
|
|
|
+ ))
|
|
|
+ }
|
|
|
+
|
|
|
+ generateRelationColumns = (r) => {
|
|
|
+ const { dashboardDesigner } = this.props;
|
|
|
+ const { selectedDataSource, selectedColumn } = this.state;
|
|
|
+ const { dataSources } = dashboardDesigner;
|
|
|
+
|
|
|
+ let flag = !!selectedDataSource && !!dataSources.find(d => d.code === selectedDataSource.code) && !!dataSources.find(d => d.code === selectedDataSource.code).columns;
|
|
|
+ if(!flag) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ let arr = dataSources.find(d => d.code === selectedDataSource.code).columns.filter(c => {
|
|
|
+ if(!!r.relations[0]) {
|
|
|
+ // 选中的不是第一个
|
|
|
+ if(r.relations[0].dataSource.code !== selectedDataSource.code) {
|
|
|
+ // 只能选用同类型的列
|
|
|
+ return c.type === r.relations[0].column.type;
|
|
|
+ }else {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return arr.map(c => (
|
|
|
+ <Button
|
|
|
+ className='column'
|
|
|
+ type={!!selectedColumn && selectedColumn.name === c.name ? 'primary' : 'default'}
|
|
|
+ key={c.name}
|
|
|
+ onClick={() => {
|
|
|
+ this.relationColumnClick(c, r)
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <span className='label'>{c.label}</span>
|
|
|
+ {r.relations.findIndex(r => r.dataSource.code === selectedDataSource.code) !== -1 && r.relations[r.relations.findIndex(r => r.dataSource.code === selectedDataSource.code)].column.name === c.name && <Icon type='check-circle' theme={r.relations[0].column.name === c.name ? 'filled' : 'outlined'} />}
|
|
|
+ </Button>
|
|
|
+ ))
|
|
|
+ }
|
|
|
+
|
|
|
+ relationColumnClick = (c, r) => {
|
|
|
+ const { dashboardDesigner, dispatch } = this.props;
|
|
|
+ const { selectedDataSource } = this.state;
|
|
|
+ const { relationColumns } = dashboardDesigner;
|
|
|
+
|
|
|
+ this.setState({
|
|
|
+ selectedColumn: {
|
|
|
+ name: c.name,
|
|
|
+ label: c.label
|
|
|
+ }
|
|
|
+ }, () => {
|
|
|
+ let { selectedColumn } = this.state;
|
|
|
+ const { relations } = r;
|
|
|
+ let idx = relations.findIndex(r => r.dataSource.code === selectedDataSource.code);
|
|
|
+ if(idx === -1){
|
|
|
+ relations.push({
|
|
|
+ dataSource: {
|
|
|
+ code: selectedDataSource.code,
|
|
|
+ name: selectedDataSource.name
|
|
|
+ },
|
|
|
+ column: {
|
|
|
+ label: c.label,
|
|
|
+ name: c.name,
|
|
|
+ type: c.type
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }else {
|
|
|
+ let cr = relations[idx];
|
|
|
+ if(cr.column.name === selectedColumn.name) {
|
|
|
+ relations.splice(idx, 1);
|
|
|
+ }else {
|
|
|
+ relations[idx] = {
|
|
|
+ dataSource: {
|
|
|
+ code: selectedDataSource.code,
|
|
|
+ name: selectedDataSource.name
|
|
|
+ },
|
|
|
+ column: {
|
|
|
+ code: c.code,
|
|
|
+ name: c.name,
|
|
|
+ type: c.type
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let index = relationColumns.findIndex(rc => rc.code === r.code);
|
|
|
+ relationColumns[index] = { ...r, relations };
|
|
|
+ dispatch({ type: 'dashboardDesigner/setField', name: 'relationColumns', value: relationColumns });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ render() {
|
|
|
+ const { visibleBox, hideBox } = this.props;
|
|
|
+ const { activeKey } = this.state;
|
|
|
+
|
|
|
+ return <Modal
|
|
|
+ className='cusfilter-box'
|
|
|
+ width={380}
|
|
|
+ height='80%'
|
|
|
+ title='自定义过滤条件'
|
|
|
+ visible={visibleBox}
|
|
|
+ footer={null}
|
|
|
+ onCancel={hideBox}
|
|
|
+ maskClosable={false}
|
|
|
+ destroyOnClose={true}
|
|
|
+ >
|
|
|
+ <Form className='config-form'>
|
|
|
+ <div className='filtercolumns'>
|
|
|
+ <Collapse key='filtercolumnscollapse' activeKey={activeKey} onChange={k => {
|
|
|
+ this.setState({
|
|
|
+ selectedDataSource: null,
|
|
|
+ selectedColumn: null,
|
|
|
+ activeKey: k[k.length - 1], // 保持只有一个展开项
|
|
|
+ });
|
|
|
+ }}>
|
|
|
+ {this.generateRelations()}
|
|
|
+ </Collapse>
|
|
|
+ <div className='bottom-btns'>
|
|
|
+ <Button className='addbtn' onClick={this.addRelationColumn}>
|
|
|
+ <Icon type='plus' theme='outlined' />添加
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </Form>
|
|
|
+ </Modal>
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export default connect(({ present: { dashboardDesigner } }) => ({ dashboardDesigner }))(CusFilterBox);
|