Table.js 15 KB

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