|
|
@@ -0,0 +1,463 @@
|
|
|
+import React, {Component} from 'react';
|
|
|
+
|
|
|
+import {Layout,Select, Input, Icon, Button, notification, Spin} from 'antd';
|
|
|
+import {UPDATE_SCHEMA, SHOW_SCHEMA, SHOW_TABLE} from "../../gql";
|
|
|
+import gql from "graphql-tag";
|
|
|
+
|
|
|
+import {Mutation, Query} from "react-apollo";
|
|
|
+import {getCookie} from "../../cookie";
|
|
|
+
|
|
|
+const Option = Select.Option;
|
|
|
+const {Content} = Layout;
|
|
|
+
|
|
|
+class Column extends Component {
|
|
|
+ constructor(props) {
|
|
|
+ super(props);
|
|
|
+ console.log('column props',props);
|
|
|
+ this.state = {
|
|
|
+ currentSchema: props.currentSchema || [{}],
|
|
|
+ currentTable: props.currentTable || ' ',
|
|
|
+ remark: props.remark || '',
|
|
|
+ columns: props.columns || [],
|
|
|
+ newColName: '',
|
|
|
+ newColType: 'type',
|
|
|
+ types: ['ID', 'String', 'Int', 'Float', 'Boolean', 'DateTime'],
|
|
|
+ descriptions: ['description', 'key', 'non-null', 'non-null-list', 'list']
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 下面的 handlexxxx 全是 state 内部方法,用于操作视图
|
|
|
+ // cache 仅在提交删除整体使用
|
|
|
+
|
|
|
+ handleNameChange = (index) => {
|
|
|
+ return (e) => {
|
|
|
+ let columns = this.state.columns;
|
|
|
+ columns[index].name = e.target.value;
|
|
|
+ this.setState({
|
|
|
+ columns
|
|
|
+ })
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ handleNameNew = (e) => {
|
|
|
+ this.setState({
|
|
|
+ newColName: e.target.value,
|
|
|
+ showNewColumn: false
|
|
|
+ })
|
|
|
+ };
|
|
|
+
|
|
|
+ handleTypeChange = (index) => {
|
|
|
+ return (value) => {
|
|
|
+ let columns = this.state.columns;
|
|
|
+ columns[index].type = value;
|
|
|
+ this.setState({
|
|
|
+ columns
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ handleTypeNew = (value) => {
|
|
|
+ if (this.state.newColName !== '') {
|
|
|
+ let columns = this.state.columns;
|
|
|
+ columns.push({name: this.state.newColName, type: value, description: 'description'});
|
|
|
+ this.setState({
|
|
|
+ columns,
|
|
|
+ newColName: '',
|
|
|
+ newColType: 'type'
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ notification['warning']({
|
|
|
+ message: 'Notification',
|
|
|
+ description: 'Input a field name first.',
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ handleDescChange = (index) => {
|
|
|
+ return (value) => {
|
|
|
+ let columns = this.state.columns;
|
|
|
+ columns[index].description = value;
|
|
|
+ this.setState({
|
|
|
+ columns
|
|
|
+ });
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ handleColDelete = (index) => {
|
|
|
+ return () => {
|
|
|
+ let columns = this.state.columns;
|
|
|
+ columns.splice(index, 1);
|
|
|
+ this.setState({
|
|
|
+ columns
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ componentWillReceiveProps(next) {
|
|
|
+ this.setState({
|
|
|
+ currentTable: next.currentTable,
|
|
|
+ currentSchema: next.currentSchema,
|
|
|
+ columns: next.columns || [],
|
|
|
+ remark: next.remark
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ render() {
|
|
|
+ console.log('columns',this.state.columns);
|
|
|
+ let schemaID = this.props.location.search.substr(this.props.location.search.indexOf("=")+1);
|
|
|
+ let userID = this.props.userID || getCookie('user_id');
|
|
|
+ console.log('schemaID',schemaID,'userID',userID);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <div className="column-menu" onClick={()=>this.props.history.goBack()}>
|
|
|
+ <Icon type="left" style={{color:'#3187FA'}} /> {this.props.match.params.name}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <Layout style={{padding: '24px', zIndex: '0'}}>
|
|
|
+ <Content style={{padding: '24px', minHeight: 280, background: '#fff', marginTop: '48px'}}>
|
|
|
+ <div className="column-content">
|
|
|
+ <span className='table-title'> Table name</span>
|
|
|
+ <Input
|
|
|
+ value={this.state.currentTable}
|
|
|
+ placeholder="please input table name"
|
|
|
+ style={{width: 200, margin:'10px 0'}}
|
|
|
+ onChange={(e) => {
|
|
|
+ this.setState({currentTable: e.target.value})
|
|
|
+ }}/>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div style={{marginBottom: 20}}>
|
|
|
+ <span className='table-title'> Table remark</span>
|
|
|
+ <Input
|
|
|
+ value={this.state.remark}
|
|
|
+ placeholder="please input table remark"
|
|
|
+ style={{width: 250, margin:'10px 0'}}
|
|
|
+ onChange={(e) => {
|
|
|
+ this.setState({remark: e.target.value})
|
|
|
+ }}/>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <span className='table-title'> Table fields</span>
|
|
|
+ <span className='column-title'>name</span>
|
|
|
+ <span className='column-title'>type</span>
|
|
|
+ <span className='column-title'>description</span>
|
|
|
+ {
|
|
|
+ this.state.columns.map((col, index) =>
|
|
|
+ <div key={index} style={{marginBottom: 3}}>
|
|
|
+ <Input
|
|
|
+ className="column-details"
|
|
|
+ value={col.name}
|
|
|
+ onChange={this.handleNameChange(index)}
|
|
|
+ />
|
|
|
+ <Select
|
|
|
+ className="column-details"
|
|
|
+ defaultValue={col.type}
|
|
|
+ onChange={this.handleTypeChange(index)}>
|
|
|
+ {
|
|
|
+ this.state.types.map((value) =>
|
|
|
+ <Option key={Math.random()+'types'} value={value.toLowerCase()}>{value}</Option>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ </Select>
|
|
|
+ <Select
|
|
|
+ className="column-details"
|
|
|
+ defaultValue={col.description}
|
|
|
+ onChange={this.handleDescChange(index)}>
|
|
|
+ {
|
|
|
+ this.state.descriptions.map((value) =>
|
|
|
+ <Option key={Math.random()+'descriptions'} value={value.toLowerCase()}>{value}</Option>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ </Select>
|
|
|
+ <Icon type="delete" theme="twoTone" style={{cursor: 'pointer'}} onClick={this.handleColDelete(index)}/>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ <div>
|
|
|
+ <Input
|
|
|
+ className="column-details"
|
|
|
+ placeholder="field name"
|
|
|
+ onChange={this.handleNameNew}
|
|
|
+ value={this.state.newColName}
|
|
|
+ />
|
|
|
+ <Select
|
|
|
+ className="column-details"
|
|
|
+ defaultValue="type"
|
|
|
+ onChange={this.handleTypeNew}
|
|
|
+ value={this.state.newColType}>
|
|
|
+ {
|
|
|
+ this.state.types.map((value) =>
|
|
|
+ <Option key={Math.random()} value={value.toLowerCase()}>{value}</Option>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ </Select>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div style={{marginTop: 20}}>
|
|
|
+ <UpdateTableButton
|
|
|
+ currentTable={this.state.currentTable}
|
|
|
+ columns={this.state.columns}
|
|
|
+ remark={this.state.remark}
|
|
|
+ currentTableIndex={this.props.currentTableIndex}
|
|
|
+ schemaID={schemaID}
|
|
|
+ userID={userID}
|
|
|
+ />
|
|
|
+ {/*{*/}
|
|
|
+ {/*// undefined的时候 上层未传进来 currentTable === 'add',为的是输入框内不默认显示 add*/}
|
|
|
+ {/*this.state.currentTable === '' ? '' : this.state.currentTable === undefined ? '' :*/}
|
|
|
+ {/*<DeleteTableButton*/}
|
|
|
+ {/*currentTable={this.state.currentTable}*/}
|
|
|
+ {/*currentTableIndex={this.props.currentTableIndex}*/}
|
|
|
+ {/*schemaID={schemaID}*/}
|
|
|
+ {/*userID={userID}*/}
|
|
|
+ {/*/>*/}
|
|
|
+ {/*}*/}
|
|
|
+ </div>
|
|
|
+ </Content>
|
|
|
+ </Layout>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export default Column;
|
|
|
+
|
|
|
+
|
|
|
+class UpdateTableButton extends Component {
|
|
|
+
|
|
|
+ render() {
|
|
|
+ let schemaID = this.props.schemaID;
|
|
|
+ let userID = this.props.userID;
|
|
|
+
|
|
|
+ let varobj = {
|
|
|
+ id: schemaID,
|
|
|
+ updatedAt: new Date().getTime(),
|
|
|
+ schemaState: 'updated-update-table',
|
|
|
+ };
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Query query={gql(SHOW_TABLE)} variables={{schema_id: schemaID}}>
|
|
|
+
|
|
|
+ {
|
|
|
+ ({loading, error, data}) => {
|
|
|
+ if (loading)
|
|
|
+ return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
|
|
|
+ if (error)
|
|
|
+ return 'error';
|
|
|
+
|
|
|
+ let schemaData = data;
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Mutation
|
|
|
+ mutation={gql(UPDATE_SCHEMA)}
|
|
|
+ update={(cache, {data: {update_schema}}) => {
|
|
|
+ let data = cache.readQuery({
|
|
|
+ query: gql(SHOW_TABLE),
|
|
|
+ variables: {schema_id: schemaID}
|
|
|
+ });
|
|
|
+
|
|
|
+ data.schema_by_id = update_schema;
|
|
|
+
|
|
|
+ let showSchemaData = cache.readQuery({
|
|
|
+ query: gql(SHOW_SCHEMA),
|
|
|
+ variables: {user_id: userID}
|
|
|
+ });
|
|
|
+
|
|
|
+ let index = showSchemaData.schema_by_props.findIndex(obj => obj.schemaName === update_schema.schemaName);
|
|
|
+ showSchemaData.schema_by_props.splice(index, 1, update_schema);
|
|
|
+
|
|
|
+ cache.writeQuery(
|
|
|
+ {
|
|
|
+ query: gql(SHOW_TABLE),
|
|
|
+ variables: {schema_id: schemaID},
|
|
|
+ data
|
|
|
+ },
|
|
|
+ {
|
|
|
+ query: gql(SHOW_SCHEMA),
|
|
|
+ variables: {user_id: userID},
|
|
|
+ showSchemaData
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ }}
|
|
|
+ >
|
|
|
+
|
|
|
+ {(update_schema, {loading, error}) => {
|
|
|
+ if (loading)
|
|
|
+ return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
|
|
|
+ if (error)
|
|
|
+ return 'error';
|
|
|
+
|
|
|
+ // 更新代码
|
|
|
+ // 先 query 再 mutation,然后替换,做一个判断
|
|
|
+ let schemaCols;
|
|
|
+ if (schemaData.schema_by_id === null) schemaCols = [];
|
|
|
+ else schemaCols = JSON.parse(schemaData.schema_by_id.schemaData);
|
|
|
+
|
|
|
+ // 处理一下description的问题
|
|
|
+ let cols = this.props.columns;
|
|
|
+ cols.map(obj => {
|
|
|
+ if (obj.description === 'description')
|
|
|
+ obj.description = '';
|
|
|
+ return obj
|
|
|
+ });
|
|
|
+
|
|
|
+ let newTable = {
|
|
|
+ name: this.props.currentTable,
|
|
|
+ remark: this.props.remark,
|
|
|
+ cols
|
|
|
+ };
|
|
|
+
|
|
|
+ const index = this.props.currentTableIndex;
|
|
|
+ if (index === -2) {
|
|
|
+ schemaCols.push(newTable);
|
|
|
+ } else if (index === -1) {
|
|
|
+ console.log('进行了一次删除操作 或 未知错误,数据库信息不匹配');
|
|
|
+ } else {
|
|
|
+ schemaCols.splice(index, 1, newTable);
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div style={{display: 'inline-block'}}>
|
|
|
+ <Button type="primary" onClick={() => {
|
|
|
+ update_schema({
|
|
|
+ variables: {
|
|
|
+ ...varobj,
|
|
|
+ schemaData: JSON.stringify(schemaCols)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }}>
|
|
|
+ save
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </Mutation>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ </Query>
|
|
|
+ )
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class DeleteTableButton extends Component {
|
|
|
+ render() {
|
|
|
+ let schemaID = this.props.schemaID;
|
|
|
+ let userID = this.props.userID;
|
|
|
+
|
|
|
+ let varobj = {
|
|
|
+ id: schemaID,
|
|
|
+ updatedAt: new Date().getTime(),
|
|
|
+ schemaState: 'updated-delete-table',
|
|
|
+ };
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Query query={gql(SHOW_TABLE)} variables={{schema_id: schemaID}}>
|
|
|
+
|
|
|
+ {
|
|
|
+ ({loading, error, data}) => {
|
|
|
+ if (loading)
|
|
|
+ return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
|
|
|
+ if (error)
|
|
|
+ return 'error';
|
|
|
+
|
|
|
+ let schemaData = data;
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Mutation
|
|
|
+ mutation={gql(UPDATE_SCHEMA)}
|
|
|
+ update={(cache, {data: {update_schema}}) => {
|
|
|
+ let data = cache.readQuery({
|
|
|
+ query: gql(SHOW_TABLE),
|
|
|
+ variables: {schema_id: schemaID}
|
|
|
+ });
|
|
|
+ data.schema_by_id = update_schema;
|
|
|
+
|
|
|
+ let showSchemaData = cache.readQuery({
|
|
|
+ query: gql(SHOW_SCHEMA),
|
|
|
+ variables: {user_id: userID}
|
|
|
+ });
|
|
|
+ let schemas = showSchemaData.schema_by_props;
|
|
|
+ // console.log('schemas', schemas);
|
|
|
+ let targetSchema = schemas.find(obj => obj.schemaName === update_schema.schemaName);
|
|
|
+ // console.log('targetSchema', targetSchema);
|
|
|
+ let targetSchemaIndex = schemas.findIndex(obj => obj.schemaName === update_schema.schemaName);
|
|
|
+ // console.log('targetSchemaIndex', targetSchemaIndex);
|
|
|
+ let targetTables = JSON.parse(schemas[targetSchemaIndex].schemaData);
|
|
|
+ // console.log('targetTables', targetTables);
|
|
|
+ let targetTableIndex = targetTables.findIndex(obj => obj.name === this.props.currentTable);
|
|
|
+ // console.log('targetTableIndex', targetTableIndex);
|
|
|
+ targetTables.splice(targetTableIndex, 1);
|
|
|
+ // console.log('targetTablesAfterDelete', targetTables);
|
|
|
+ let temp = {schemaData: JSON.stringify(targetTables)};
|
|
|
+ // console.log('temp', temp);
|
|
|
+ let tempSchema = {...targetSchema, ...temp};
|
|
|
+ // console.log('tempSchema', tempSchema);
|
|
|
+ showSchemaData.schema_by_props.splice(targetSchemaIndex, 1, tempSchema);
|
|
|
+
|
|
|
+ cache.writeQuery(
|
|
|
+ {
|
|
|
+ query: gql(SHOW_TABLE),
|
|
|
+ variables: {schema_id: schemaID},
|
|
|
+ data
|
|
|
+ },
|
|
|
+ {
|
|
|
+ query: gql(SHOW_SCHEMA),
|
|
|
+ variables: {user_id: userID},
|
|
|
+ showSchemaData
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }}
|
|
|
+ >
|
|
|
+
|
|
|
+ {(update_schema, {loading, error}) => {
|
|
|
+ if (loading)
|
|
|
+ return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
|
|
|
+ if (error)
|
|
|
+ return 'error';
|
|
|
+
|
|
|
+ // 先 query 再 mutation,然后删除
|
|
|
+ let schemaCols;
|
|
|
+ if (schemaData.schema_by_id === null) schemaCols = [];
|
|
|
+ else schemaCols = JSON.parse(schemaData.schema_by_id.schemaData);
|
|
|
+
|
|
|
+ const index = this.props.currentTableIndex;
|
|
|
+ // 设置-2 标志为新建页面,防止通过 tablename 被修改导致每次 index 都为 -1 从而修改最后一个
|
|
|
+ if (index === -2) {
|
|
|
+ console.log('初始页面')
|
|
|
+ } else if (index === -1) {
|
|
|
+ console.log('进行了一次删除操作 或 数据库信息不匹配');
|
|
|
+ } else {
|
|
|
+ schemaCols.splice(index, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div style={{display: 'inline-block'}}>
|
|
|
+ <Button type="danger"
|
|
|
+ onClick={() => {
|
|
|
+ update_schema({
|
|
|
+ variables: {
|
|
|
+ ...varobj,
|
|
|
+ schemaData: JSON.stringify(schemaCols)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }}>
|
|
|
+ DELETE
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </Mutation>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ </Query>
|
|
|
+ )
|
|
|
+ }
|
|
|
+}
|