columnConfig.jsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. import React from 'react'
  2. import { Modal, Form, Row, Col, Input, Button, Select, Icon, Menu, Dropdown, Table, Checkbox, Switch, Divider } from 'antd'
  3. const FormItem = Form.Item
  4. const SelectOption = Select.Option
  5. const OptionGroup = Select.OptGroup
  6. const InputGroup = Input.Group
  7. const SubMenu = Menu.SubMenu
  8. const MenuItem = Menu.Item
  9. const MenuItemGroup = Menu.ItemGroup;
  10. import { connect } from 'dva'
  11. import dataSource from '../../models/dataSource'
  12. class DataSourceColumnConfig extends React.Component {
  13. constructor(props) {
  14. super(props);
  15. this.state = {
  16. }
  17. }
  18. onCheckAllChange() {
  19. }
  20. render() {
  21. const { dataSource, dispatch } = this.props;
  22. const columns = [{
  23. title: <div><Checkbox
  24. style={{ margin: '0 8px 0 0', display: dataSource.newOne.columns ? (dataSource.newOne.columns.length > 0 ? 'inline-block' : 'none') : 'none'}}
  25. 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}
  26. checked={dataSource.newOne.columns ? (dataSource.newOne.columns.filter(c => c.using).length == dataSource.newOne.columns.length) : false}
  27. onChange={(e) => {
  28. let target = e.target;
  29. let columns = dataSource.newOne.columns ? dataSource.newOne.columns.map(c => {
  30. c.using = target.checked;
  31. return c;
  32. }) : [];
  33. dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: columns });
  34. }}
  35. />启用</div>,
  36. dataIndex: 'using',
  37. key: 'using',
  38. width: 100,
  39. render: (v, r) => <Checkbox
  40. dataKey={r.key}
  41. onChange={(e) => {
  42. let target = e.target;
  43. let key = target.dataKey;
  44. let columns = dataSource.newOne.columns.map(c => {
  45. if(c.key == key) {
  46. c.using = target.checked;
  47. }
  48. return c;
  49. });
  50. dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: columns });
  51. }}
  52. checked={v}
  53. />
  54. }, {
  55. title: '列名',
  56. dataIndex: 'name',
  57. key: 'name',
  58. width: 180
  59. }, {
  60. title: '别名',
  61. dataIndex: 'alias',
  62. key: 'alias',
  63. width: 180,
  64. render: (text, record) => {
  65. return (<EditableCell
  66. dispatch={dispatch}
  67. dataSource={dataSource}
  68. fieldName='alias'
  69. dataKey={record.key}
  70. type='input'
  71. value={text}
  72. />)
  73. }
  74. }, {
  75. title: '类型',
  76. dataIndex: 'type',
  77. key: 'type',
  78. width: 120,
  79. render: (text, record) => {
  80. return (
  81. <Select
  82. style={{ width: '100%' }}
  83. value={text}
  84. onChange={(value) => {
  85. let columns = dataSource.newOne.columns.map(c => {
  86. if(c.key == record.key) {
  87. c.type = value;
  88. c.groupable = c.type == 'categorical';
  89. c.bucketizable = ['time', 'scale', 'ordinal'].indexOf(record.type) != -1;
  90. }
  91. return c;
  92. });
  93. dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: columns });
  94. }}
  95. >
  96. <SelectOption value='index'>索引</SelectOption>
  97. <SelectOption value='time'>时间</SelectOption>
  98. <SelectOption value='categorical'>类别</SelectOption>
  99. <SelectOption value='scale'>标量</SelectOption>
  100. <SelectOption value='ordinal'>序值</SelectOption>
  101. <SelectOption value='string'>字符串</SelectOption>
  102. </Select>
  103. )
  104. }
  105. }, {
  106. title: '允许分组',
  107. dataIndex: 'groupable',
  108. key: 'groupable',
  109. width: 100,
  110. render: (value, record) => <Switch disabled={record.type!='categorical'} checked={value} onChange={(checked) => {
  111. let columns = dataSource.newOne.columns.map(c => {
  112. if(c.key == record.key) {
  113. c.groupable = checked;
  114. }
  115. return c;
  116. });
  117. dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: columns });
  118. }}/>
  119. }, {
  120. title: '允许分段',
  121. dataIndex: 'bucketizable',
  122. key: 'bucketizable',
  123. width: 100,
  124. render: (value, record) => <Switch disabled={['time', 'scale', 'ordinal'].indexOf(record.type)==-1} checked={value} onChange={(checked) => {
  125. let columns = dataSource.newOne.columns.map(c => {
  126. if(c.key == record.key) {
  127. c.bucketizable = checked;
  128. }
  129. return c;
  130. });
  131. dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: columns });
  132. }}/>
  133. }, {
  134. title: '备注',
  135. dataIndex: 'description',
  136. key: 'description',
  137. render: (text, record) => {
  138. return (<EditableCell
  139. dispatch={dispatch}
  140. dataSource={dataSource}
  141. fieldName='description'
  142. dataKey={record.key}
  143. type='input'
  144. value={text}
  145. />)
  146. }
  147. }];
  148. return (
  149. <div>
  150. {
  151. dataSource.newOne.type=='database'?(
  152. <div>
  153. <Form size='small'>
  154. <Divider orientation="left">数据对象</Divider>
  155. <FormItem className='textarea-target'>
  156. <Input.TextArea
  157. placeholder='输入表名或查询SQL'
  158. autosize={{ minRows: 3 }}
  159. value={dataSource.newOne.target}
  160. onChange={(e) => {
  161. dispatch({ type: 'dataSource/setNewModelField', name: 'target', value: e.target.value });
  162. }}
  163. />
  164. </FormItem>
  165. <div className='buttons'>
  166. <Button onClick={() => {
  167. dispatch({
  168. type: 'dataSource/setNewModelField', name: 'columns', value: [
  169. { key: 30, name: 'rrrrrr', type: 'ordinal', using: false},
  170. { key: 40, name: 'rrrrrr', type: 'ordinal', using: false},
  171. { key: 50, name: 'rrrrrr', type: 'ordinal', using: false},
  172. { key: 60, name: 'rrrrrr', type: 'ordinal', using: false},
  173. { key: 70, name: 'rrrrrr', type: 'ordinal', using: false},
  174. { key: 80, name: 'rrrrrr', type: 'ordinal', using: false},
  175. { key: 120, name: 'rrrrrr', type: 'ordinal', using: false},
  176. { key: 64, name: 'rrrrrr', type: 'ordinal', using: false},
  177. { key: 12, name: 'rrrrrr', type: 'ordinal', using: false},
  178. { key: 98, name: 'rrrrrr', type: 'ordinal', using: false},
  179. { key: 630, name: 'rrrrrr', type: 'ordinal', using: false},
  180. { key: 1, name: 'ttttt', type: 'scale', using: true},
  181. { key: 2, name: 'ssssss', type: 'index', using: true },
  182. { key: 3, name: 'yyyyyy', type: 'categorical', using: true, description: 'hhhhhhhhh' },
  183. { key: 4, name: 'uuuuuuu', type: 'string', using: true },
  184. { key: 5, name: 'ggggg', type: 'time', alias: 'gg', using: true }
  185. ]
  186. });
  187. }}>刷新</Button>
  188. </div>
  189. </Form>
  190. <Divider orientation="left">数据列</Divider>
  191. </div>
  192. ):null
  193. }
  194. <Table
  195. className='table-columnconfig'
  196. dataSource={dataSource.newOne.columns}
  197. columns={columns}
  198. locale={{
  199. emptyText: '未连接到数据对象'
  200. }}
  201. />
  202. </div>
  203. );
  204. }
  205. }
  206. function mapStateToProps({ present: { dataSource } }) {
  207. return { dataSource }
  208. }
  209. export default connect(mapStateToProps)(DataSourceColumnConfig);
  210. class EditableCell extends React.Component {
  211. state = {
  212. dispatch: this.props.dispatch,
  213. dataSource: this.props.dataSource,
  214. fieldName: this.props.fieldName,
  215. dataKey: this.props.dataKey,
  216. type: this.props.type,
  217. value: this.props.value,
  218. editable: false,
  219. }
  220. getEditor = (e) => {
  221. const { type, value } = this.state;
  222. if(type == 'input') {
  223. return (
  224. <Input
  225. value={value}
  226. onChange={this.handleChange}
  227. onPressEnter={this.check}
  228. suffix={(
  229. <Icon
  230. type="check"
  231. className="editable-cell-icon-check"
  232. onClick={this.check}
  233. />
  234. )}
  235. />
  236. )
  237. }else if(type == 'select') {
  238. return (
  239. <Select
  240. onChange={this.check}
  241. >
  242. <SelectOption value='index'>索引</SelectOption>
  243. <SelectOption value='time'>时间</SelectOption>
  244. <SelectOption value='categorical'>类别</SelectOption>
  245. <SelectOption value='scale'>标量</SelectOption>
  246. <SelectOption value='ordinal'>序值</SelectOption>
  247. <SelectOption value='string'>字符串</SelectOption>
  248. </Select>
  249. )
  250. }
  251. }
  252. handleChange = (e) => {
  253. const value = e.target.value;
  254. this.setState({ value });
  255. }
  256. check = () => {
  257. const { dispatch, dataSource, fieldName, dataKey, value } = this.state;
  258. this.setState({ editable: false });
  259. let columns = dataSource.newOne.columns.map(c => {
  260. if(c.key == dataKey) {
  261. c[fieldName] = value;
  262. }
  263. return c;
  264. });
  265. dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: columns });
  266. }
  267. edit = () => {
  268. this.setState({ editable: true });
  269. }
  270. render() {
  271. const { value, editable } = this.state;
  272. return (
  273. <div className="editable-cell">
  274. {
  275. editable ? this.getEditor() : (
  276. <div style={{ paddingRight: 24 }}>
  277. {value || ' '}
  278. <Icon
  279. type="edit"
  280. className="editable-cell-icon"
  281. onClick={this.edit}
  282. />
  283. </div>
  284. )
  285. }
  286. </div>
  287. );
  288. }
  289. }