Table.js 16 KB

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