Schema.jsx 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  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 {
  7. DELETE_SCHEMA,
  8. SHOW_SCHEMA,
  9. SHOW_TABLE,
  10. UPDATE_SCHEMA,
  11. UPDATE_SCHEMA_NAME,
  12. SEARCH_SCHEMA,
  13. ADD_SCHEMA
  14. } from '../../../../gql'
  15. import Table from "./Table";
  16. import {request} from 'graphql-request'
  17. import {getCookie} from "../../../../cookie";
  18. import {idGen} from "../../../../func";
  19. const confirm = Modal.confirm;
  20. const Search = Input.Search;
  21. class Schema extends Component {
  22. constructor(props) {
  23. super(props);
  24. this.state = {
  25. currentTable: props.location.state === undefined ? '' : props.location.state.create ? 'add' : '',
  26. // default schemaID and schemaName
  27. schemaID: props.location.state === undefined ? props.schemaID : props.location.state.schemaID,
  28. schemaName: props.location.state === undefined ? props.schemaName : props.location.state.schemaName,
  29. editSchemaName: '',
  30. allData: '',
  31. data: '',
  32. page: '1',
  33. pageSize: '15',
  34. once: 0
  35. };
  36. }
  37. shouldComponentUpdate(nextProps,nextState) {
  38. return true;
  39. }
  40. switchTable = (table) => {
  41. this.setState({
  42. currentTable: table
  43. })
  44. };
  45. changeEditSchemaName = (e) => {
  46. this.setState({
  47. editSchemaName: e.target.value
  48. })
  49. };
  50. clearEditSchemaName = () => {
  51. this.setState({
  52. editSchemaName: ''
  53. })
  54. };
  55. findColumns = data => this.state.currentTable === '' ? [] : data.find(table => table.name === this.state.currentTable) ? data.find(table => table.name === this.state.currentTable).cols : [];
  56. findRemark = data => this.state.currentTable === '' ? '' : data.find(table => table.name === this.state.currentTable) ? data.find(table => table.name === this.state.currentTable).remark : '';
  57. goBack = () => {
  58. this.setState({
  59. currentTable: ''
  60. })
  61. };
  62. showTablePagination = (page, pageSize, data) => {
  63. // console.log(page);
  64. // console.log(pageSize);
  65. // console.log(data);
  66. // 这个之所以这么麻烦,是因为 'apollo 不能存数据' 而 '分页又得用数据展示',
  67. // 所以展示 table 的时候分了两个,
  68. // 首先进入展示 15个 , 这前 15 个没有任何问题。
  69. // 如果数据多于 15个,在按下第二页的时候 将数据通过 antd 的分页组件的回调函数传入 state,之后 table 的展示由 this.state.data 来接管
  70. // 但是这又引起一个问题,通过 this.state.data 的展示如果进行删除,是不会通过 apollo 的,这也意味着数据库被删除了,而页面还存在
  71. // 于是,在使用 this.state.data 的页面的 deleteTableButton 组件内调用该函数,重新刷新 this.state.data
  72. this.setState({
  73. page,
  74. pageSize,
  75. allData: data,
  76. data: data.slice((page - 1) * pageSize, page * pageSize)
  77. });
  78. };
  79. fetchData = (referenceID) => {
  80. let schemaData;
  81. if (localStorage.getItem('ecommerce') && localStorage.getItem('bills') && localStorage.getItem('subscribe')) {
  82. switch (referenceID) {
  83. case 'ecommerce_schemaID':
  84. schemaData = localStorage.getItem('ecommerce');
  85. break;
  86. case 'bills_schemaID':
  87. schemaData = localStorage.getItem('bills');
  88. break;
  89. case 'subscribe_schemaID':
  90. schemaData = localStorage.getItem('subscribe');
  91. break;
  92. default:
  93. schemaData = ''
  94. }
  95. return Promise.resolve(schemaData);
  96. } else {
  97. return new Promise((resolve, reject) => {
  98. request('http://123.206.193.98:3000/graphql', SEARCH_SCHEMA, {id: referenceID}).then(
  99. data => {
  100. console.log(data);
  101. if (data.schema_by_id !== null) {
  102. localStorage.setItem('ecommerce', data.caseSchema.find(obj=>obj.schemaName==='ecommerce').schemaData);
  103. localStorage.setItem('subscribe', data.caseSchema.find(obj=>obj.schemaName==='subscribe').schemaData);
  104. localStorage.setItem('bills', data.caseSchema.find(obj=>obj.schemaName==='bills').schemaData);
  105. resolve(data.schema_by_id.schemaData);
  106. }
  107. }
  108. )
  109. });
  110. }
  111. };
  112. receiveDataFromTable = (data) => {
  113. this.setState({
  114. data
  115. })
  116. };
  117. componentWillReceiveProps(next) {
  118. this.setState({
  119. currentTable: next.location.state === undefined ? '' : next.location.state.create ? 'add' : '',
  120. schemaID: next.schemaID,
  121. schemaName: next.schemaName,
  122. data: '',
  123. once: 0
  124. });
  125. }
  126. render() {
  127. let userID = this.props.userID;
  128. let trialcase = this.props.trialcase;
  129. return (
  130. <Query query={gql(SHOW_TABLE)} variables={{schema_id: this.state.schemaID}}>
  131. {
  132. ({loading, error, data}) => {
  133. if (loading) {
  134. return <Spin style={{marginLeft: 3}}/>
  135. }
  136. if (error) {
  137. return 'error!';
  138. }
  139. // let schemaName = data.schema_by_id.schemaName;
  140. let copy;
  141. if(this.props.location.state)
  142. copy = this.props.location.state.copy;
  143. // 找到 copy 一定几率不显示的 问题原因,异步导致的未存先取
  144. if (data.schema_by_id === null && copy!==true) data = [];
  145. else {
  146. let reference = data.schema_by_id ? data.schema_by_id.reference : this.props.location.state.reference;
  147. data = data.schema_by_id ? JSON.parse(data.schema_by_id.schemaData) : [];
  148. if (data.length === 0 && reference !== '' && this.state.once === 0) {
  149. this.fetchData(reference).then((data) => {
  150. // 会执行好多好多次
  151. this.setState({
  152. data: JSON.parse(data),
  153. once: 1
  154. })
  155. });
  156. }
  157. }
  158. return (
  159. <div>
  160. {
  161. this.state.currentTable === '' ?
  162. <div>
  163. {
  164. this.state.editSchemaName ?
  165. <ModifySchemaNameInput
  166. editSchemaName={this.state.editSchemaName}
  167. changeEditSchemaName={this.changeEditSchemaName}
  168. clearEditSchemaName={this.clearEditSchemaName}
  169. schemaID={this.state.schemaID}
  170. userID={userID}
  171. schemaName={this.state.schemaName}
  172. history={this.props.history}
  173. />
  174. :
  175. <div className={'schema'}>
  176. <span className={'schema-name'}>{this.state.schemaName}</span>
  177. {
  178. trialcase ?
  179. ''
  180. :
  181. <Icon style={{marginLeft: 15}}
  182. type="edit"
  183. theme="twoTone"
  184. onClick={
  185. () => {
  186. this.setState({editSchemaName: this.state.schemaName})
  187. }
  188. }
  189. />
  190. }
  191. </div>
  192. }
  193. <div className={'schema-table-list-title'}>
  194. <Row>
  195. <Col span={10}><span
  196. className={'schema-table-title'}>Name</span></Col>
  197. <Col span={10}><span
  198. className={'schema-table-title'}>Remark</span></Col>
  199. <Col span={2} offset={2}>
  200. {
  201. trialcase ?
  202. ''
  203. :
  204. <span
  205. className={'schema-table-title'}
  206. onClick={() => {
  207. this.setState({
  208. currentTable: 'add'
  209. })
  210. }}>
  211. <Icon type="plus"/>
  212. </span>
  213. }
  214. </Col>
  215. </Row>
  216. </div>
  217. <div>
  218. {
  219. this.state.data ?
  220. this.state.data.map(table => (
  221. <div key={table.name}
  222. className={'schema-table-list-content'}>
  223. <Row>
  224. <Col
  225. span={10}
  226. onClick={() => this.switchTable(table.name)}
  227. >
  228. <span
  229. className={'schema-table-content name'}>{table.name}</span>
  230. </Col>
  231. <Col span={10}>
  232. <span
  233. className={'schema-table-content'}>{table.remark}</span>
  234. </Col>
  235. <Col span={2} offset={2}>
  236. <span className={'schema-table-content'}>
  237. {
  238. trialcase ?
  239. ''
  240. :
  241. <DeleteTableButton
  242. currentTable={table.name}
  243. schemaData={data}
  244. schemaID={this.state.schemaID}
  245. userID={userID}
  246. showTablePagination={this.showTablePagination}
  247. page={this.state.page}
  248. pageSize={this.state.pageSize}
  249. fetchData={this.fetchData}
  250. location={this.props.location}
  251. />
  252. }
  253. </span>
  254. </Col>
  255. </Row>
  256. </div>
  257. ))
  258. :
  259. data.slice(0, 15).map(table => (
  260. <div key={table.name}
  261. className={'schema-table-list-content'}>
  262. <Row>
  263. <Col
  264. span={10}
  265. onClick={() => this.switchTable(table.name)}
  266. >
  267. <span
  268. className={'schema-table-content name'}>{table.name}</span>
  269. </Col>
  270. <Col span={10}>
  271. <span
  272. className={'schema-table-content'}>{table.remark}</span>
  273. </Col>
  274. <Col span={2} offset={2}>
  275. <span className={'schema-table-content'}>
  276. {
  277. trialcase ?
  278. ''
  279. :
  280. <DeleteTableButton
  281. currentTable={table.name}
  282. schemaData={data}
  283. schemaID={this.state.schemaID}
  284. showTablePagination={this.showTablePagination}
  285. page={this.state.page}
  286. pageSize={this.state.pageSize}
  287. userID={userID}
  288. fetchData={this.fetchData}
  289. location={this.props.location}
  290. />
  291. }
  292. </span>
  293. </Col>
  294. </Row>
  295. </div>
  296. ))
  297. }
  298. </div>
  299. <div className={'schema-bottom'}>
  300. <Row>
  301. <Col span={4}>
  302. {
  303. trialcase ?
  304. <div className={'delete-schema'}>
  305. <CopySchemaButton
  306. userID={userID}
  307. history={this.props.history}
  308. schemaName={this.state.schemaName}
  309. />
  310. </div>
  311. :
  312. <div className={'delete-schema'}>
  313. <DeleteSchemaButton
  314. userID={userID}
  315. schemaName={this.state.schemaName}
  316. history={this.props.history}
  317. />
  318. </div>
  319. }
  320. </Col>
  321. <Col span={4} offset={16}>
  322. <div className={'pagination'}>
  323. <Pagination
  324. simple
  325. defaultCurrent={1}
  326. hideOnSinglePage={true}
  327. defaultPageSize={15}
  328. total={data.length}
  329. onChange={(page, pageSize) => {
  330. this.showTablePagination(page, pageSize, data)
  331. }}
  332. />
  333. </div>
  334. </Col>
  335. </Row>
  336. </div>
  337. </div>
  338. :
  339. this.state.currentTable === 'add' ?
  340. <Table
  341. currentTable={''}
  342. schemaData={data}
  343. columns={[]}
  344. remark=''
  345. schemaID={this.state.schemaID}
  346. schemaName={this.state.schemaName}
  347. userID={userID}
  348. goBack={this.goBack}
  349. trialcase={trialcase}
  350. fetchData={this.fetchData}
  351. showTablePagination={this.showTablePagination}
  352. page={this.state.page}
  353. pageSize={this.state.pageSize}
  354. history={this.props.history}
  355. add={'add'}
  356. /> :
  357. <Table
  358. currentTable={this.state.currentTable}
  359. schemaData={data}
  360. columns={this.findColumns(data.length !== 0? data : this.state.data)}
  361. remark={this.findRemark(data.length !== 0? data : this.state.data)}
  362. schemaID={this.state.schemaID}
  363. schemaName={this.state.schemaName}
  364. userID={userID}
  365. goBack={this.goBack}
  366. trialcase={trialcase}
  367. fetchData={this.fetchData}
  368. showTablePagination={this.showTablePagination}
  369. page={this.state.page}
  370. pageSize={this.state.pageSize}
  371. history={this.props.history}
  372. add={'whatever but not add'}
  373. />
  374. }
  375. </div>
  376. );
  377. }
  378. }
  379. </Query>
  380. )
  381. }
  382. }
  383. export default Schema;
  384. class CopySchemaButton extends Component {
  385. constructor(props) {
  386. super(props);
  387. this.state = {
  388. schemaName: '',
  389. schemaID: '',
  390. };
  391. }
  392. render() {
  393. let userID = getCookie('user_id');
  394. let {history, schemaName} = this.props;
  395. let schemaID = schemaName + '_schemaID';
  396. return (
  397. <div>
  398. <Mutation
  399. mutation={gql(ADD_SCHEMA)}
  400. refetchQueries={[{query: gql(SHOW_SCHEMA), variables: {user_id: userID}}]}
  401. >
  402. {(create_schema, {loading, error}) => {
  403. if (loading)
  404. return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
  405. if (error)
  406. return 'error';
  407. let varObj = {
  408. id: idGen('schema'),
  409. user_id: userID,
  410. createdAt: new Date().getTime(),
  411. updatedAt: '',
  412. schemaState: 'copy',
  413. schemaData: JSON.stringify([]),
  414. reference: schemaID,
  415. schemaName: schemaName + '_' + Math.random().toString().slice(-3) + Math.random().toString().slice(-4)
  416. };
  417. return (
  418. <Button
  419. type="primary"
  420. onClick={() => {
  421. create_schema({variables: varObj});
  422. history.push({
  423. pathname: `/graphql-service/my-create/${varObj.schemaName}`,
  424. state: {
  425. schemaName: varObj.schemaName,
  426. schemaID: varObj.id,
  427. copy: true,
  428. reference: varObj.reference
  429. }
  430. });
  431. }}
  432. >copy</Button>
  433. )
  434. }}
  435. </Mutation>
  436. </div>
  437. )
  438. }
  439. }
  440. class DeleteSchemaButton extends Component {
  441. constructor(props) {
  442. super(props);
  443. this.state = {
  444. schemaName: props.schemaName
  445. }
  446. }
  447. showConfirm = (delete_schema, schemaName, userID) => {
  448. let _this = this;
  449. confirm({
  450. title: 'Do you want to delete this schema?',
  451. content: 'It cannot be found back!',
  452. onOk() {
  453. delete_schema({variables: {schemaName, user_id: userID}});
  454. _this.props.history.push({
  455. pathname: '/graphql-service',
  456. });
  457. },
  458. onCancel() {
  459. },
  460. });
  461. };
  462. render() {
  463. let userID = this.props.userID;
  464. let schemaName = this.props.schemaName;
  465. return (
  466. <Mutation
  467. mutation={gql(DELETE_SCHEMA)}
  468. update={(cache) => {
  469. let data = cache.readQuery({query: gql(SHOW_SCHEMA), variables: {user_id: userID}});
  470. data.schema_by_props.splice(data.schema_by_props.findIndex(obj => obj.schemaName === this.state.schemaName), 1);
  471. cache.writeQuery({
  472. query: gql(SHOW_SCHEMA),
  473. variables: {user_id: userID},
  474. data
  475. });
  476. }}
  477. >
  478. {(delete_schema, {loading, error}) => {
  479. if (error)
  480. return 'error';
  481. if (loading)
  482. return <Spin style={{marginLeft: 3}}/>;
  483. return (
  484. <Button
  485. type="danger"
  486. onClick={() => {
  487. this.showConfirm(delete_schema, schemaName, userID);
  488. }}
  489. >
  490. delete
  491. </Button>
  492. )
  493. }}
  494. </Mutation>
  495. )
  496. }
  497. }
  498. class DeleteTableButton extends Component {
  499. render() {
  500. let schemaID = this.props.schemaID;
  501. let userID = this.props.userID;
  502. let varobj = {
  503. id: schemaID,
  504. updatedAt: new Date().getTime(),
  505. schemaState: 'updated-delete-table',
  506. };
  507. return (
  508. <Query query={gql(SHOW_TABLE)} variables={{schema_id: schemaID}}>
  509. {
  510. ({loading, error, data}) => {
  511. if (loading)
  512. return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
  513. if (error)
  514. return 'error';
  515. let schemaData = data;
  516. let referenceID = data.schema_by_id ? data.schema_by_id.reference : this.props.location.state.reference;
  517. return (
  518. <Mutation
  519. mutation={gql(UPDATE_SCHEMA)}
  520. refetchQueries={[{query: gql(SHOW_TABLE), variables: {schema_id: schemaID}}]}
  521. >
  522. {(update_schema, {loading, error}) => {
  523. if (loading)
  524. return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
  525. if (error)
  526. return 'error';
  527. // 先 query 再 mutation,然后删除
  528. let schemaCols;
  529. if (schemaData.schema_by_id === null) schemaCols = [];
  530. else schemaCols = JSON.parse(schemaData.schema_by_id.schemaData);
  531. const index = this.props.schemaData.findIndex(obj => obj.name === this.props.currentTable);
  532. if (index === -1) {
  533. // 先取数据,然后删除,然后填充
  534. this.props.fetchData(referenceID).then(value => {
  535. schemaCols = JSON.parse(value);
  536. const index = schemaCols.findIndex(obj => obj.name === this.props.currentTable);
  537. schemaCols.splice(index, 1);
  538. });
  539. } else {
  540. schemaCols.splice(index, 1);
  541. }
  542. return (
  543. <Icon type="delete"
  544. onClick={() => {
  545. update_schema({
  546. variables: {
  547. ...varobj,
  548. schemaData: JSON.stringify(schemaCols)
  549. }
  550. });
  551. this.props.showTablePagination(this.props.page, this.props.pageSize, schemaCols)
  552. }}>
  553. </Icon>
  554. )
  555. }}
  556. </Mutation>
  557. )
  558. }
  559. }
  560. </Query>
  561. )
  562. }
  563. }
  564. class ModifySchemaNameInput extends Component {
  565. constructor(props) {
  566. super(props);
  567. this.state = {}
  568. }
  569. render() {
  570. let userID = this.props.userID;
  571. let schemaName = this.props.schemaName;
  572. return (
  573. <Mutation mutation={gql(UPDATE_SCHEMA_NAME)}>
  574. {(update_schema, {loading, error}) => {
  575. if (error)
  576. return 'error';
  577. if (loading)
  578. return <Spin style={{marginLeft: 3}}/>;
  579. return (
  580. <div className={'schema'}>
  581. <Search
  582. value={this.props.editSchemaName}
  583. enterButton="Confirm"
  584. style={{width: 500}}
  585. size="large"
  586. onChange={this.props.changeEditSchemaName}
  587. onSearch={value => {
  588. update_schema({
  589. variables: {
  590. id: this.props.schemaID,
  591. schemaName: value,
  592. updateAt: new Date().getTime()
  593. }
  594. });
  595. this.props.history.push({
  596. pathname: `/graphql-service/my-create/${value}`,
  597. state: {
  598. schemaName: value,
  599. schemaID: this.props.schemaID,
  600. }
  601. });
  602. this.props.clearEditSchemaName();
  603. }}
  604. />
  605. </div>
  606. )
  607. }}
  608. </Mutation>
  609. )
  610. }
  611. }