Schema.jsx 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. import React, {Component} from 'react';
  2. import {Button, Col, Icon, Modal, Pagination, Row, Spin, Input} from 'antd';
  3. import './index.css';
  4. import {Mutation, Query} from "react-apollo";
  5. import gql from "graphql-tag";
  6. import {DELETE_SCHEMA, SHOW_SCHEMA, SHOW_TABLE, UPDATE_SCHEMA} from '../../gql'
  7. import Table from "./Table";
  8. const confirm = Modal.confirm;
  9. const Search = Input.Search;
  10. class Schema extends Component {
  11. constructor(props) {
  12. super(props);
  13. this.state = {
  14. currentTable: props.location.state === undefined ? '' : props.location.state.create ? 'add' : '',
  15. // default schemaID and schemaName
  16. schemaID: props.schemaID || props.location.state.schemaID,
  17. schemaName: props.schemaName || props.location.state.schemaName,
  18. editSchemaName: '',
  19. data: '',
  20. page: '',
  21. pageSize: ''
  22. };
  23. }
  24. switchTable = (table) => {
  25. this.setState({
  26. currentTable: table
  27. })
  28. };
  29. findColumns = data => this.state.currentTable === '' ? [] : data.find(table => table.name === this.state.currentTable) ? data.find(table => table.name === this.state.currentTable).cols : [];
  30. findRemark = data => this.state.currentTable === '' ? '' : data.find(table => table.name === this.state.currentTable) ? data.find(table => table.name === this.state.currentTable).remark : '';
  31. goBack = () => {
  32. this.setState({
  33. currentTable: ''
  34. })
  35. };
  36. showTablePagination = (page, pageSize, data) => {
  37. // console.log(page);
  38. // console.log(pageSize);
  39. // console.log(data);
  40. // 这个之所以这么麻烦,是因为 'apollo 不能存数据' 而 '分页又得用数据展示',
  41. // 所以展示 table 的时候分了两个,
  42. // 首先进入展示 15个 , 这前 15 个没有任何问题。
  43. // 如果数据多于 15个,在按下第二页的时候 将数据通过 antd 的分页组件的回调函数传入 state,之后 table 的展示由 this.state.data 来接管
  44. // 但是这又引起一个问题,通过 this.state.data 的展示如果进行删除,是不会通过 apollo 的,这也意味着数据库被删除了,而页面还存在
  45. // 于是,在使用 this.state.data 的页面的 deleteTableButton 组件内调用该函数,重新刷新 this.state.data
  46. this.setState({
  47. page,
  48. pageSize,
  49. data: data.slice((page-1)*pageSize, page*pageSize)
  50. })
  51. };
  52. componentWillReceiveProps(next) {
  53. this.setState({
  54. currentTable: next.location.state === undefined ? '' : next.location.state.create ? 'add' : '',
  55. schemaID: next.schemaID,
  56. schemaName: next.schemaName,
  57. data: ''
  58. });
  59. }
  60. render() {
  61. let userID = this.props.userID;
  62. return (
  63. <Query query={gql(SHOW_TABLE)} variables={{schema_id: this.state.schemaID}}>
  64. {
  65. ({loading, error, data}) => {
  66. if (loading) {
  67. return <Spin style={{marginLeft: 3}}/>
  68. }
  69. if (error) {
  70. return 'error!';
  71. }
  72. // let schemaName = data.schema_by_id.schemaName;
  73. if (data.schema_by_id === null) data = [];
  74. else data = JSON.parse(data.schema_by_id.schemaData);
  75. return (
  76. <div>
  77. {
  78. this.state.currentTable === '' ?
  79. <div>
  80. {
  81. this.state.editSchemaName?
  82. <div className={'schema'}>
  83. <Search
  84. value={this.state.editSchemaName}
  85. enterButton="Confirm"
  86. style={{width: 500}}
  87. size="large"
  88. onChange={e => this.setState({
  89. editSchemaName: e.target.value
  90. })}
  91. onSearch={value => {
  92. this.setState({
  93. editSchemaName: ''
  94. });
  95. console.log('我还没做 value = ', value)
  96. }}
  97. />
  98. </div>
  99. :
  100. <div className={'schema'}>
  101. <span className={'schema-name'}>{this.state.schemaName}</span>
  102. <Icon style={{marginLeft: 15}} type="edit" theme="twoTone" onClick={()=>{this.setState({editSchemaName:this.state.schemaName})}
  103. }/>
  104. </div>
  105. }
  106. <div className={'schema-table-list-title'}>
  107. <Row>
  108. <Col span={10}><span
  109. className={'schema-table-title'}>Name</span></Col>
  110. <Col span={10}><span
  111. className={'schema-table-title'}>Remark</span></Col>
  112. <Col span={2} offset={2}>
  113. <span
  114. className={'schema-table-title'}
  115. onClick={() => {
  116. this.setState({
  117. currentTable: 'add'
  118. })
  119. }}>
  120. <Icon type="plus"/>
  121. </span>
  122. </Col>
  123. </Row>
  124. </div>
  125. <div>
  126. {
  127. this.state.data ?
  128. this.state.data.map(table => (
  129. <div key={table.name}
  130. className={'schema-table-list-content'}>
  131. <Row>
  132. <Col
  133. span={10}
  134. onClick={() => this.switchTable(table.name)}
  135. >
  136. <span
  137. className={'schema-table-content name'}>{table.name}</span>
  138. </Col>
  139. <Col span={10}>
  140. <span
  141. className={'schema-table-content'}>{table.remark}</span>
  142. </Col>
  143. <Col span={2} offset={2}>
  144. <span className={'schema-table-content'}>
  145. <DeleteTableButton
  146. currentTable={table.name}
  147. currentTableIndex={data.findIndex(obj => obj.name === table.name)}
  148. schemaID={this.state.schemaID}
  149. userID={userID}
  150. showTablePagination={this.showTablePagination}
  151. page={this.state.page}
  152. pageSize={this.state.pageSize}
  153. />
  154. </span>
  155. </Col>
  156. </Row>
  157. </div>
  158. ))
  159. :
  160. data.slice(0, 15).map(table => (
  161. <div key={table.name}
  162. className={'schema-table-list-content'}>
  163. <Row>
  164. <Col
  165. span={10}
  166. onClick={() => this.switchTable(table.name)}
  167. >
  168. <span
  169. className={'schema-table-content name'}>{table.name}</span>
  170. </Col>
  171. <Col span={10}>
  172. <span
  173. className={'schema-table-content'}>{table.remark}</span>
  174. </Col>
  175. <Col span={2} offset={2}>
  176. <span className={'schema-table-content'}>
  177. <DeleteTableButton
  178. currentTable={table.name}
  179. currentTableIndex={data.findIndex(obj => obj.name === table.name)}
  180. schemaID={this.state.schemaID}
  181. userID={userID}
  182. />
  183. </span>
  184. </Col>
  185. </Row>
  186. </div>
  187. ))
  188. }
  189. </div>
  190. <div className={'schema-bottom'}>
  191. <Row>
  192. <Col span={4}>
  193. <div className={'delete-schema'}>
  194. <DeleteSchemaButton
  195. userID={userID}
  196. schemaName={this.state.schemaName}
  197. />
  198. </div>
  199. </Col>
  200. <Col span={4} offset={16}>
  201. <div className={'pagination'}>
  202. <Pagination
  203. simple
  204. defaultCurrent={1}
  205. hideOnSinglePage={true}
  206. defaultPageSize={15}
  207. total={data.length}
  208. onChange={(page, pageSize) => {
  209. this.showTablePagination(page, pageSize, data)
  210. }}
  211. />
  212. </div>
  213. </Col>
  214. </Row>
  215. </div>
  216. </div>
  217. :
  218. this.state.currentTable === 'add' ?
  219. <Table
  220. currentTable={''}
  221. currentTableIndex={-2}
  222. columns={[]}
  223. remark=''
  224. schemaID={this.state.schemaID}
  225. schemaName={this.state.schemaName}
  226. userID={userID}
  227. goBack={this.goBack}
  228. /> :
  229. <Table
  230. currentTable={this.state.currentTable}
  231. currentTableIndex={this.state.currentTable === '' ? -2 : data.findIndex(obj => obj.name === this.state.currentTable)}
  232. columns={this.findColumns(data)}
  233. remark={this.findRemark(data)}
  234. schemaID={this.state.schemaID}
  235. schemaName={this.state.schemaName}
  236. userID={userID}
  237. goBack={this.goBack}
  238. />
  239. }
  240. </div>
  241. );
  242. }
  243. }
  244. </Query>
  245. )
  246. }
  247. }
  248. export default Schema;
  249. class DeleteSchemaButton extends Component {
  250. constructor(props) {
  251. super(props);
  252. this.state = {
  253. schemaName: props.schemaName
  254. }
  255. }
  256. showConfirm = (delete_schema, schemaName) => {
  257. confirm({
  258. title: 'Do you want to delete this schema?',
  259. content: 'It cannot be find back!',
  260. onOk() {
  261. delete_schema({variables: {schemaName}});
  262. },
  263. onCancel() {
  264. },
  265. });
  266. };
  267. render() {
  268. let userID = this.props.userID;
  269. return (
  270. <Mutation
  271. mutation={gql(DELETE_SCHEMA)}
  272. update={(cache) => {
  273. let data = cache.readQuery({query: gql(SHOW_SCHEMA), variables: {user_id: userID}});
  274. data.schema_by_props.splice(data.schema_by_props.findIndex(obj => obj.schemaName === this.state.schemaName), 1);
  275. cache.writeQuery({
  276. query: gql(SHOW_SCHEMA),
  277. variables: {user_id: userID},
  278. data
  279. });
  280. }}
  281. >
  282. {(delete_schema, {loading, error}) => {
  283. if (error)
  284. return 'error';
  285. if (loading)
  286. return <Spin style={{marginLeft: 3}}/>;
  287. return (
  288. <Button
  289. type="danger"
  290. onClick={() => {
  291. this.showConfirm(delete_schema, this.props.schemaName);
  292. }}
  293. >
  294. delete
  295. </Button>
  296. )
  297. }}
  298. </Mutation>
  299. )
  300. }
  301. }
  302. class DeleteTableButton extends Component {
  303. render() {
  304. let schemaID = this.props.schemaID;
  305. let userID = this.props.userID;
  306. let varobj = {
  307. id: schemaID,
  308. updatedAt: new Date().getTime(),
  309. schemaState: 'updated-delete-table',
  310. };
  311. return (
  312. <Query query={gql(SHOW_TABLE)} variables={{schema_id: schemaID}}>
  313. {
  314. ({loading, error, data}) => {
  315. if (loading)
  316. return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
  317. if (error)
  318. return 'error';
  319. let schemaData = data;
  320. return (
  321. <Mutation
  322. mutation={gql(UPDATE_SCHEMA)}
  323. update={(cache, {data: {update_schema}}) => {
  324. let data = cache.readQuery({
  325. query: gql(SHOW_TABLE),
  326. variables: {schema_id: schemaID}
  327. });
  328. data.schema_by_id = update_schema;
  329. let showSchemaData = cache.readQuery({
  330. query: gql(SHOW_SCHEMA),
  331. variables: {user_id: userID}
  332. });
  333. let schemas = showSchemaData.schema_by_props;
  334. // console.log('schemas', schemas);
  335. let targetSchema = schemas.find(obj => obj.schemaName === update_schema.schemaName);
  336. // console.log('targetSchema', targetSchema);
  337. let targetSchemaIndex = schemas.findIndex(obj => obj.schemaName === update_schema.schemaName);
  338. // console.log('targetSchemaIndex', targetSchemaIndex);
  339. let targetTables = JSON.parse(schemas[targetSchemaIndex].schemaData);
  340. // console.log('targetTables', targetTables);
  341. let targetTableIndex = targetTables.findIndex(obj => obj.name === this.props.currentTable);
  342. // console.log('targetTableIndex', targetTableIndex);
  343. targetTables.splice(targetTableIndex, 1);
  344. // console.log('targetTablesAfterDelete', targetTables);
  345. let temp = {schemaData: JSON.stringify(targetTables)};
  346. // console.log('temp', temp);
  347. let tempSchema = {...targetSchema, ...temp};
  348. // console.log('tempSchema', tempSchema);
  349. showSchemaData.schema_by_props.splice(targetSchemaIndex, 1, tempSchema);
  350. cache.writeQuery(
  351. {
  352. query: gql(SHOW_TABLE),
  353. variables: {schema_id: schemaID},
  354. data
  355. },
  356. {
  357. query: gql(SHOW_SCHEMA),
  358. variables: {user_id: userID},
  359. showSchemaData
  360. }
  361. );
  362. }}
  363. >
  364. {(update_schema, {loading, error}) => {
  365. if (loading)
  366. return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
  367. if (error)
  368. return 'error';
  369. // 先 query 再 mutation,然后删除
  370. let schemaCols;
  371. if (schemaData.schema_by_id === null) schemaCols = [];
  372. else schemaCols = JSON.parse(schemaData.schema_by_id.schemaData);
  373. const index = this.props.currentTableIndex;
  374. if (index === -1) {
  375. console.log('数据库信息不匹配');
  376. } else {
  377. schemaCols.splice(index, 1);
  378. }
  379. return (
  380. <Icon type="delete"
  381. onClick={() => {
  382. update_schema({
  383. variables: {
  384. ...varobj,
  385. schemaData: JSON.stringify(schemaCols)
  386. }
  387. });
  388. this.props.showTablePagination?
  389. this.props.showTablePagination(this.props.page, this.props.pageSize, schemaCols):(()=>{})()
  390. }}>
  391. </Icon>
  392. )
  393. }}
  394. </Mutation>
  395. )
  396. }
  397. }
  398. </Query>
  399. )
  400. }
  401. }