Table.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. import React, {Component} from 'react';
  2. import {Layout, Select, Input, Icon, Button, notification, Spin, Modal} from 'antd';
  3. import {UPDATE_SCHEMA, SHOW_SCHEMA, SHOW_TABLE} from "../../../../gql";
  4. import gql from "graphql-tag";
  5. import {FormattedMessage} from 'react-intl';
  6. import {Mutation, Query} from "react-apollo";
  7. import {getCookie} from "../../../../cookie";
  8. import {manageUsers} from "../../../../config";
  9. const Option = Select.Option;
  10. const {Content} = Layout;
  11. const confirm = Modal.confirm;
  12. class Table extends Component {
  13. constructor(props) {
  14. super(props);
  15. this.state = {
  16. currentTable: props.currentTable,
  17. remark: props.remark,
  18. columns: props.columns,
  19. newColName: '',
  20. newColType: 'type',
  21. types: ['ID', 'String', 'Int', 'Float', 'Boolean', 'DateTime'],
  22. descriptions: ['description', 'key', 'non-null', 'non-null-list', 'list'],
  23. characterTips: false
  24. }
  25. }
  26. // 下面的 handlexxxx 全是 state 内部方法,用于操作视图
  27. // cache 仅在提交删除整体使用
  28. handleNameChange = (index) => {
  29. return (e) => {
  30. let columns = this.state.columns;
  31. columns[index].name = e.target.value;
  32. this.setState({
  33. columns
  34. })
  35. };
  36. };
  37. handleNameNew = (e) => {
  38. let r = /^[^\u4e00-\u9fa5]*$/;
  39. if (r.test(e.target.value)) {
  40. this.setState({
  41. newColName: e.target.value,
  42. })
  43. } else {
  44. this.setState({
  45. characterTips: true
  46. });
  47. setTimeout(() => {
  48. this.setState({
  49. characterTips: false
  50. })
  51. }, 2000)
  52. }
  53. };
  54. handleTypeChange = (index) => {
  55. return (value) => {
  56. let columns = this.state.columns;
  57. columns[index].type = value;
  58. this.setState({
  59. columns
  60. });
  61. }
  62. };
  63. handleTypeNew = (value) => {
  64. if (this.state.newColName !== '') {
  65. let columns = this.state.columns;
  66. columns.push({name: this.state.newColName, type: value, description: 'description'});
  67. this.setState({
  68. columns,
  69. newColName: '',
  70. newColType: 'type'
  71. })
  72. } else {
  73. notification['warning']({
  74. message: 'Notification',
  75. description: 'Input a field name first.',
  76. });
  77. }
  78. };
  79. handleDescChange = (index) => {
  80. return (value) => {
  81. let columns = this.state.columns;
  82. columns[index].description = value;
  83. this.setState({
  84. columns
  85. });
  86. };
  87. };
  88. handleColDelete = (index) => {
  89. return () => {
  90. let columns = this.state.columns;
  91. columns.splice(index, 1);
  92. this.setState({
  93. columns
  94. });
  95. }
  96. };
  97. componentWillReceiveProps(next) {
  98. this.setState({
  99. currentTable: next.currentTable,
  100. columns: next.columns,
  101. remark: next.remark
  102. });
  103. };
  104. render() {
  105. let schemaID = this.props.schemaID || this.props.history.location.state.schemaID;
  106. let schemaName = this.props.schemaName || this.props.history.location.state.schemaName;
  107. let userID = this.props.userID || getCookie('user_id');
  108. let trialcase = this.props.trialcase;
  109. return (
  110. <div>
  111. <div className="column-menu" onClick={this.props.goBack}>
  112. <Icon type="left" style={{color: '#3187FA'}}/> {schemaName}
  113. </div>
  114. <Layout style={{zIndex: '0'}}>
  115. <Content style={{padding: '24px', minHeight: 280, background: '#fff'}}>
  116. <div className="column-content">
  117. <span className='table-title'> <FormattedMessage id="Table name"/></span>
  118. <FormattedMessage id="please input table name">
  119. {(msg) => (<Input
  120. value={this.state.currentTable}
  121. placeholder={msg}
  122. style={{width: 200, margin: '10px 0'}}
  123. onChange={(e) => {
  124. this.setState({currentTable: e.target.value})
  125. }}/>)}
  126. </FormattedMessage>
  127. </div>
  128. <div style={{marginBottom: 20}}>
  129. <span className='table-title'> <FormattedMessage id="Table remark"/></span>
  130. <FormattedMessage id="please input table remark">
  131. {(msg) => (<Input
  132. value={this.state.remark}
  133. placeholder={msg}
  134. style={{width: 250, margin: '10px 0'}}
  135. onChange={(e) => {
  136. this.setState({remark: e.target.value})
  137. }}/>)}
  138. </FormattedMessage>
  139. </div>
  140. <div>
  141. <span className='table-title'> <FormattedMessage id="Table fields"/></span>
  142. <span className='column-title'><FormattedMessage id="name"/></span>
  143. <span className='column-title'><FormattedMessage id="type"/></span>
  144. <span className='column-title'><FormattedMessage id="description"/></span>
  145. {
  146. this.state.columns.map((col, index) =>
  147. <div key={index} style={{marginBottom: 3}}>
  148. <Input
  149. className="column-details"
  150. value={col.name}
  151. onChange={this.handleNameChange(index)}
  152. />
  153. <Select
  154. className="column-details"
  155. defaultValue={col.type}
  156. onChange={this.handleTypeChange(index)}>
  157. {
  158. this.state.types.map((value) =>
  159. <Option key={Math.random() + 'types'}
  160. value={value.toLowerCase()}>{value}</Option>
  161. )
  162. }
  163. </Select>
  164. <Select
  165. className="column-details"
  166. defaultValue={col.description}
  167. onChange={this.handleDescChange(index)}>
  168. {
  169. this.state.descriptions.map((value) =>
  170. <Option key={Math.random() + 'descriptions'}
  171. value={value.toLowerCase()}>{value}</Option>
  172. )
  173. }
  174. </Select>
  175. {
  176. userID.indexOf(manageUsers) > -1 ?
  177. <Icon type="delete" theme="twoTone" style={{cursor: 'pointer'}}
  178. onClick={this.handleColDelete(index)}/>
  179. :
  180. trialcase ?
  181. ''
  182. :
  183. <Icon type="delete" theme="twoTone" style={{cursor: 'pointer'}}
  184. onClick={this.handleColDelete(index)}/>
  185. }
  186. </div>
  187. )
  188. }
  189. <div>
  190. <FormattedMessage id="field name">
  191. {(msg) => (<Input
  192. className="column-details"
  193. placeholder={msg}
  194. onChange={this.handleNameNew}
  195. value={this.state.newColName}
  196. />)}
  197. </FormattedMessage>
  198. <Select
  199. className="column-details"
  200. defaultValue="type"
  201. onChange={this.handleTypeNew}
  202. value={this.state.newColType}>
  203. {
  204. this.state.types.map((value) =>
  205. <Option key={Math.random()} value={value.toLowerCase()}>{value}</Option>
  206. )
  207. }
  208. </Select>
  209. </div>
  210. </div>
  211. {
  212. userID.indexOf(manageUsers) > -1 ?
  213. <div style={{marginTop: 20}}>
  214. <UpdateTableButton
  215. currentTable={this.state.currentTable}
  216. columns={this.state.columns}
  217. remark={this.state.remark}
  218. schemaID={schemaID}
  219. userID={userID}
  220. schemaData={this.props.schemaData}
  221. fetchData={this.props.fetchData}
  222. showTablePagination={this.props.showTablePagination}
  223. page={this.props.page}
  224. pageSize={this.props.pageSize}
  225. history={this.props.history}
  226. schemaName={schemaName}
  227. add={this.props.add}
  228. />
  229. </div>
  230. :
  231. trialcase ?
  232. ''
  233. :
  234. <div style={{marginTop: 20}}>
  235. <UpdateTableButton
  236. currentTable={this.state.currentTable}
  237. columns={this.state.columns}
  238. remark={this.state.remark}
  239. schemaID={schemaID}
  240. userID={userID}
  241. schemaData={this.props.schemaData}
  242. fetchData={this.props.fetchData}
  243. showTablePagination={this.props.showTablePagination}
  244. page={this.props.page}
  245. pageSize={this.props.pageSize}
  246. history={this.props.history}
  247. schemaName={schemaName}
  248. add={this.props.add}
  249. />
  250. </div>
  251. }
  252. </Content>
  253. </Layout>
  254. </div>
  255. )
  256. }
  257. }
  258. export default Table;
  259. class UpdateTableButton extends Component {
  260. constructor(props) {
  261. super(props);
  262. this.state = {
  263. originTableName: props.currentTable
  264. }
  265. }
  266. showConfirm = (schemaName, schemaID) => {
  267. let _this = this;
  268. if (this.props.add !== 'add') {
  269. this.props.history.push({
  270. pathname: `/graphql-service/my-create/${schemaName}`,
  271. state: {
  272. schemaName,
  273. schemaID
  274. }
  275. });
  276. } else {
  277. confirm({
  278. title: '添加成功',
  279. content: '继续添加数据表?',
  280. onOk() {
  281. console.log('继续添加');
  282. },
  283. onCancel() {
  284. _this.props.history.push({
  285. pathname: `/graphql-service/my-create/${schemaName}`,
  286. state: {
  287. schemaName,
  288. schemaID
  289. }
  290. });
  291. }
  292. });
  293. }
  294. };
  295. render() {
  296. let schemaID = this.props.schemaID;
  297. let schemaName = this.props.schemaName;
  298. let userID = this.props.userID;
  299. let varobj = {
  300. id: schemaID,
  301. updatedAt: new Date().getTime(),
  302. schemaState: 'updated-update-table',
  303. };
  304. return (
  305. <Query query={gql(SHOW_TABLE)} variables={{schema_id: schemaID}}>
  306. {
  307. ({loading, error, data}) => {
  308. if (loading)
  309. return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
  310. if (error)
  311. return 'error';
  312. let schemaData = data;
  313. let referenceID = '';
  314. if (data.schema_by_id)
  315. referenceID = data.schema_by_id.reference;
  316. return (
  317. <Mutation
  318. mutation={gql(UPDATE_SCHEMA)}
  319. onCompleted={() => this.showConfirm(schemaName, schemaID)}
  320. refetchQueries={[{query: gql(SHOW_TABLE), variables: {schema_id: schemaID}}]}
  321. >
  322. {(update_schema, {loading, error}) => {
  323. if (loading)
  324. return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
  325. if (error)
  326. return 'error';
  327. // 更新代码
  328. // 先 query 再 mutation,然后替换,做一个判断
  329. let schemaCols;
  330. if (schemaData.schema_by_id === null) schemaCols = [];
  331. else schemaCols = JSON.parse(schemaData.schema_by_id.schemaData);
  332. // 处理一下description的问题
  333. let cols = this.props.columns;
  334. cols.map(obj => {
  335. if (obj.description === 'description')
  336. obj.description = '';
  337. return obj
  338. });
  339. let newTable = {
  340. name: this.props.currentTable,
  341. remark: this.props.remark,
  342. cols
  343. };
  344. const index = this.state.originTableName === '' ? -2 : this.props.schemaData.findIndex(obj => obj.name === this.state.originTableName);
  345. if (index === -2) {
  346. if (referenceID !== '' && schemaCols.length === 0) {
  347. this.props.fetchData(referenceID).then(value => {
  348. schemaCols = JSON.parse(value);
  349. schemaCols.push(newTable);
  350. });
  351. } else {
  352. schemaCols.push(newTable);
  353. }
  354. } else if (index === -1) {
  355. // 先取数据,然后替换,然后填充
  356. this.props.fetchData(referenceID).then(value => {
  357. schemaCols = JSON.parse(value);
  358. const index = schemaCols.findIndex(obj => obj.name === this.state.originTableName);
  359. schemaCols.splice(index, 1, newTable);
  360. });
  361. } else {
  362. schemaCols.splice(index, 1, newTable);
  363. }
  364. return (
  365. <div style={{display: 'inline-block'}}>
  366. <Button type="primary" onClick={() => {
  367. update_schema({
  368. variables: {
  369. ...varobj,
  370. schemaData: JSON.stringify(schemaCols)
  371. }
  372. });
  373. this.props.showTablePagination(this.props.page, this.props.pageSize, schemaCols);
  374. }}>
  375. save
  376. </Button>
  377. </div>
  378. )
  379. }}
  380. </Mutation>
  381. )
  382. }
  383. }
  384. </Query>
  385. )
  386. }
  387. }