|
|
@@ -10,112 +10,300 @@ const MenuItemGroup = Menu.ItemGroup;
|
|
|
import { connect } from 'dva'
|
|
|
import dataSource from '../../models/dataSource'
|
|
|
|
|
|
-const DataSourceColumnConfig = ({ dataSource, dispatch }) => {
|
|
|
-
|
|
|
- const formItemLayout = {
|
|
|
- labelCol: { span: 4 },
|
|
|
- wrapperCol: { span: 20 },
|
|
|
- };
|
|
|
-
|
|
|
- const dataSourceLinkMenu = (
|
|
|
- <Menu
|
|
|
- className='menu-datasource-link'
|
|
|
- onClick={() => {
|
|
|
- dispatch({ type: 'dataSource/setNewModelField', name: 'address', value: '1111adddd' });
|
|
|
- dispatch({ type: 'dataSource/setNewModelField', name: 'port', value: '1234' });
|
|
|
- dispatch({ type: 'dataSource/setNewModelField', name: 'type', value: {
|
|
|
- key: 'oracle',
|
|
|
- label: 'ORACLE'
|
|
|
- } });
|
|
|
- dispatch({ type: 'dataSource/setNewModelField', name: 'dbName', value: 'orcl' });
|
|
|
- dispatch({ type: 'dataSource/setNewModelField', name: 'userName', value: 'UAS' });
|
|
|
- dispatch({ type: 'dataSource/setNewModelField', name: 'password', value: 'select!#%*(' });
|
|
|
- }}
|
|
|
- >
|
|
|
- <MenuItem>1111</MenuItem>
|
|
|
- <MenuItem>2222</MenuItem>
|
|
|
- <MenuItem>33333</MenuItem>
|
|
|
- <MenuItem>44</MenuItem>
|
|
|
- </Menu>
|
|
|
- );
|
|
|
-
|
|
|
- const columns = [{
|
|
|
- title: <div><Checkbox
|
|
|
- style={{ margin: '0 8px 0 0' }}
|
|
|
- indeterminate={dataSource.newOne.columns?(dataSource.newOne.columns.filter(c=>c.using).length>0&&dataSource.newOne.columns.filter(c=>c.using).length<(dataSource.newOne.columns.length)):false}
|
|
|
- indeterminate={false}
|
|
|
- />启用</div>,
|
|
|
- dataIndex: 'using',
|
|
|
- key: 'using',
|
|
|
- render: () => <Checkbox
|
|
|
+class DataSourceColumnConfig extends React.Component {
|
|
|
+
|
|
|
+ constructor(props) {
|
|
|
+ super(props);
|
|
|
+ this.state = {
|
|
|
|
|
|
- />
|
|
|
- }, {
|
|
|
- title: '列名',
|
|
|
- dataIndex: 'name',
|
|
|
- key: 'name',
|
|
|
- }, {
|
|
|
- title: '别名',
|
|
|
- dataIndex: 'alias',
|
|
|
- key: 'alias',
|
|
|
- }, {
|
|
|
- title: '类型',
|
|
|
- dataIndex: 'type',
|
|
|
- key: 'type',
|
|
|
- }, {
|
|
|
- title: '允许分组',
|
|
|
- dataIndex: 'groupable',
|
|
|
- key: 'groupable',
|
|
|
- render: () => <Switch />
|
|
|
- }, {
|
|
|
- title: '允许分段',
|
|
|
- dataIndex: 'bucketizable',
|
|
|
- key: 'bucketizable',
|
|
|
- render: () => <Switch />
|
|
|
- }, {
|
|
|
- title: '备注',
|
|
|
- dataIndex: 'description',
|
|
|
- key: 'description'
|
|
|
- }];
|
|
|
-
|
|
|
- return (
|
|
|
- <div>
|
|
|
- <Form size='small'>
|
|
|
- <Divider orientation="left">数据对象</Divider>
|
|
|
- <FormItem className='textarea-target'>
|
|
|
- <Input.TextArea
|
|
|
- placeholder='输入表名或查询SQL'
|
|
|
- autosize={{ minRows: 3 }}
|
|
|
- />
|
|
|
- </FormItem>
|
|
|
- <div className='buttons'>
|
|
|
- <Button onClick={() => {
|
|
|
- dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: [
|
|
|
- { key: 0, name: 'rrrrrr', using: false },
|
|
|
- { key: 1, name: 'ttttt', using: true },
|
|
|
- { key: 2, name: 'ssssss', using: true },
|
|
|
- { key: 3, name: 'yyyyyy', using: true },
|
|
|
- { key: 4, name: 'uuuuuuu', using: true },
|
|
|
- { key: 5, name: 'ggggg', using: true }
|
|
|
- ] });
|
|
|
- }}>连接</Button>
|
|
|
- </div>
|
|
|
- </Form>
|
|
|
- <Divider orientation="left">结果集数据列</Divider>
|
|
|
- <Table
|
|
|
- className='table-columnconfig'
|
|
|
- dataSource={dataSource.newOne.columns}
|
|
|
- columns={columns}
|
|
|
- locale={{
|
|
|
- emptyText: '未连接到数据对象'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onCheckAllChange() {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ render() {
|
|
|
+ const { dataSource, dispatch } = this.props;
|
|
|
+
|
|
|
+ const columns = [{
|
|
|
+ title: <div><Checkbox
|
|
|
+ style={{ margin: '0 8px 0 0', display: dataSource.newOne.columns ? (dataSource.newOne.columns.length > 0 ? 'inline-block' : 'none') : 'none'}}
|
|
|
+ indeterminate={dataSource.newOne.columns ? (dataSource.newOne.columns.filter(c => c.using).length > 0 && dataSource.newOne.columns.filter(c => c.using).length < dataSource.newOne.columns.length) : false}
|
|
|
+ checked={dataSource.newOne.columns ? (dataSource.newOne.columns.filter(c => c.using).length == dataSource.newOne.columns.length) : false}
|
|
|
+ onChange={(e) => {
|
|
|
+ let target = e.target;
|
|
|
+ let columns = dataSource.newOne.columns ? dataSource.newOne.columns.map(c => {
|
|
|
+ c.using = target.checked;
|
|
|
+ return c;
|
|
|
+ }) : [];
|
|
|
+
|
|
|
+ dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: columns });
|
|
|
+ }}
|
|
|
+ />启用</div>,
|
|
|
+ dataIndex: 'using',
|
|
|
+ key: 'using',
|
|
|
+ width: 100,
|
|
|
+ render: (v, r) => <Checkbox
|
|
|
+ dataKey={r.key}
|
|
|
+ onChange={(e) => {
|
|
|
+ let target = e.target;
|
|
|
+ let key = target.dataKey;
|
|
|
+ let columns = dataSource.newOne.columns.map(c => {
|
|
|
+ if(c.key == key) {
|
|
|
+ c.using = target.checked;
|
|
|
+ }
|
|
|
+ return c;
|
|
|
+ });
|
|
|
+
|
|
|
+ dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: columns });
|
|
|
}}
|
|
|
+ checked={v}
|
|
|
/>
|
|
|
- </div>
|
|
|
- );
|
|
|
+ }, {
|
|
|
+ title: '列名',
|
|
|
+ dataIndex: 'name',
|
|
|
+ key: 'name',
|
|
|
+ width: 180
|
|
|
+ }, {
|
|
|
+ title: '别名',
|
|
|
+ dataIndex: 'alias',
|
|
|
+ key: 'alias',
|
|
|
+ width: 180,
|
|
|
+ render: (text, record) => {
|
|
|
+ return (<EditableCell
|
|
|
+ dispatch={dispatch}
|
|
|
+ dataSource={dataSource}
|
|
|
+ fieldName='alias'
|
|
|
+ dataKey={record.key}
|
|
|
+ type='input'
|
|
|
+ value={text}
|
|
|
+ />)
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ title: '类型',
|
|
|
+ dataIndex: 'type',
|
|
|
+ key: 'type',
|
|
|
+ width: 120,
|
|
|
+ render: (text, record) => {
|
|
|
+ return (
|
|
|
+ <Select
|
|
|
+ style={{ width: '100%' }}
|
|
|
+ value={text}
|
|
|
+ onChange={(value) => {
|
|
|
+ let columns = dataSource.newOne.columns.map(c => {
|
|
|
+ if(c.key == record.key) {
|
|
|
+ c.type = value;
|
|
|
+ c.groupable = c.type == 'categorical';
|
|
|
+ c.bucketizable = ['time', 'scale', 'ordinal'].indexOf(record.type) != -1;
|
|
|
+ }
|
|
|
+ return c;
|
|
|
+ });
|
|
|
+ dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: columns });
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <SelectOption value='index'>索引</SelectOption>
|
|
|
+ <SelectOption value='time'>时间</SelectOption>
|
|
|
+ <SelectOption value='categorical'>类别</SelectOption>
|
|
|
+ <SelectOption value='scale'>标量</SelectOption>
|
|
|
+ <SelectOption value='ordinal'>序值</SelectOption>
|
|
|
+ <SelectOption value='string'>字符串</SelectOption>
|
|
|
+ </Select>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ title: '允许分组',
|
|
|
+ dataIndex: 'groupable',
|
|
|
+ key: 'groupable',
|
|
|
+ width: 100,
|
|
|
+ render: (value, record) => <Switch disabled={record.type!='categorical'} checked={value} onChange={(checked) => {
|
|
|
+ let columns = dataSource.newOne.columns.map(c => {
|
|
|
+ if(c.key == record.key) {
|
|
|
+ c.groupable = checked;
|
|
|
+ }
|
|
|
+ return c;
|
|
|
+ });
|
|
|
+ dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: columns });
|
|
|
+ }}/>
|
|
|
+ }, {
|
|
|
+ title: '允许分段',
|
|
|
+ dataIndex: 'bucketizable',
|
|
|
+ key: 'bucketizable',
|
|
|
+ width: 100,
|
|
|
+ render: (value, record) => <Switch disabled={['time', 'scale', 'ordinal'].indexOf(record.type)==-1} checked={value} onChange={(checked) => {
|
|
|
+ let columns = dataSource.newOne.columns.map(c => {
|
|
|
+ if(c.key == record.key) {
|
|
|
+ c.bucketizable = checked;
|
|
|
+ }
|
|
|
+ return c;
|
|
|
+ });
|
|
|
+ dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: columns });
|
|
|
+ }}/>
|
|
|
+ }, {
|
|
|
+ title: '备注',
|
|
|
+ dataIndex: 'description',
|
|
|
+ key: 'description',
|
|
|
+ render: (text, record) => {
|
|
|
+ return (<EditableCell
|
|
|
+ dispatch={dispatch}
|
|
|
+ dataSource={dataSource}
|
|
|
+ fieldName='description'
|
|
|
+ dataKey={record.key}
|
|
|
+ type='input'
|
|
|
+ value={text}
|
|
|
+ />)
|
|
|
+ }
|
|
|
+ }];
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ {
|
|
|
+ dataSource.newOne.type=='database'?(
|
|
|
+ <div>
|
|
|
+ <Form size='small'>
|
|
|
+ <Divider orientation="left">数据对象</Divider>
|
|
|
+ <FormItem className='textarea-target'>
|
|
|
+ <Input.TextArea
|
|
|
+ placeholder='输入表名或查询SQL'
|
|
|
+ autosize={{ minRows: 3 }}
|
|
|
+ value={dataSource.newOne.target}
|
|
|
+ onChange={(e) => {
|
|
|
+ dispatch({ type: 'dataSource/setNewModelField', name: 'target', value: e.target.value });
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </FormItem>
|
|
|
+ <div className='buttons'>
|
|
|
+ <Button onClick={() => {
|
|
|
+ dispatch({
|
|
|
+ type: 'dataSource/setNewModelField', name: 'columns', value: [
|
|
|
+ { key: 30, name: 'rrrrrr', type: 'ordinal', using: false},
|
|
|
+ { key: 40, name: 'rrrrrr', type: 'ordinal', using: false},
|
|
|
+ { key: 50, name: 'rrrrrr', type: 'ordinal', using: false},
|
|
|
+ { key: 60, name: 'rrrrrr', type: 'ordinal', using: false},
|
|
|
+ { key: 70, name: 'rrrrrr', type: 'ordinal', using: false},
|
|
|
+ { key: 80, name: 'rrrrrr', type: 'ordinal', using: false},
|
|
|
+ { key: 120, name: 'rrrrrr', type: 'ordinal', using: false},
|
|
|
+ { key: 64, name: 'rrrrrr', type: 'ordinal', using: false},
|
|
|
+ { key: 12, name: 'rrrrrr', type: 'ordinal', using: false},
|
|
|
+ { key: 98, name: 'rrrrrr', type: 'ordinal', using: false},
|
|
|
+ { key: 630, name: 'rrrrrr', type: 'ordinal', using: false},
|
|
|
+ { key: 1, name: 'ttttt', type: 'scale', using: true},
|
|
|
+ { key: 2, name: 'ssssss', type: 'index', using: true },
|
|
|
+ { key: 3, name: 'yyyyyy', type: 'categorical', using: true, description: 'hhhhhhhhh' },
|
|
|
+ { key: 4, name: 'uuuuuuu', type: 'string', using: true },
|
|
|
+ { key: 5, name: 'ggggg', type: 'time', alias: 'gg', using: true }
|
|
|
+ ]
|
|
|
+ });
|
|
|
+ }}>刷新</Button>
|
|
|
+ </div>
|
|
|
+ </Form>
|
|
|
+ <Divider orientation="left">数据列</Divider>
|
|
|
+ </div>
|
|
|
+ ):null
|
|
|
+ }
|
|
|
+ <Table
|
|
|
+ className='table-columnconfig'
|
|
|
+ dataSource={dataSource.newOne.columns}
|
|
|
+ columns={columns}
|
|
|
+ locale={{
|
|
|
+ emptyText: '未连接到数据对象'
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-function mapStateToProps({ present: {dataSource} }) {
|
|
|
+function mapStateToProps({ present: { dataSource } }) {
|
|
|
return { dataSource }
|
|
|
}
|
|
|
|
|
|
-export default connect(mapStateToProps)(DataSourceColumnConfig);
|
|
|
+export default connect(mapStateToProps)(DataSourceColumnConfig);
|
|
|
+
|
|
|
+class EditableCell extends React.Component {
|
|
|
+ state = {
|
|
|
+ dispatch: this.props.dispatch,
|
|
|
+ dataSource: this.props.dataSource,
|
|
|
+ fieldName: this.props.fieldName,
|
|
|
+ dataKey: this.props.dataKey,
|
|
|
+ type: this.props.type,
|
|
|
+ value: this.props.value,
|
|
|
+ editable: false,
|
|
|
+ }
|
|
|
+
|
|
|
+ getEditor = (e) => {
|
|
|
+ const { type, value } = this.state;
|
|
|
+ if(type == 'input') {
|
|
|
+ return (
|
|
|
+ <Input
|
|
|
+ value={value}
|
|
|
+ onChange={this.handleChange}
|
|
|
+ onPressEnter={this.check}
|
|
|
+ suffix={(
|
|
|
+ <Icon
|
|
|
+ type="check"
|
|
|
+ className="editable-cell-icon-check"
|
|
|
+ onClick={this.check}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ )
|
|
|
+ }else if(type == 'select') {
|
|
|
+ return (
|
|
|
+ <Select
|
|
|
+ onChange={this.check}
|
|
|
+ >
|
|
|
+ <SelectOption value='index'>索引</SelectOption>
|
|
|
+ <SelectOption value='time'>时间</SelectOption>
|
|
|
+ <SelectOption value='categorical'>类别</SelectOption>
|
|
|
+ <SelectOption value='scale'>标量</SelectOption>
|
|
|
+ <SelectOption value='ordinal'>序值</SelectOption>
|
|
|
+ <SelectOption value='string'>字符串</SelectOption>
|
|
|
+ </Select>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ handleChange = (e) => {
|
|
|
+ const value = e.target.value;
|
|
|
+ this.setState({ value });
|
|
|
+ }
|
|
|
+
|
|
|
+ check = () => {
|
|
|
+ const { dispatch, dataSource, fieldName, dataKey, value } = this.state;
|
|
|
+ this.setState({ editable: false });
|
|
|
+
|
|
|
+ let columns = dataSource.newOne.columns.map(c => {
|
|
|
+ if(c.key == dataKey) {
|
|
|
+ c[fieldName] = value;
|
|
|
+ }
|
|
|
+ return c;
|
|
|
+ });
|
|
|
+
|
|
|
+ dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: columns });
|
|
|
+ }
|
|
|
+
|
|
|
+ edit = () => {
|
|
|
+ this.setState({ editable: true });
|
|
|
+ }
|
|
|
+
|
|
|
+ render() {
|
|
|
+ const { value, editable } = this.state;
|
|
|
+ return (
|
|
|
+ <div className="editable-cell">
|
|
|
+ {
|
|
|
+ editable ? this.getEditor() : (
|
|
|
+ <div style={{ paddingRight: 24 }}>
|
|
|
+ {value || ' '}
|
|
|
+ <Icon
|
|
|
+ type="edit"
|
|
|
+ className="editable-cell-icon"
|
|
|
+ onClick={this.edit}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|