|
@@ -0,0 +1,453 @@
|
|
|
|
|
+import React, {Component} from 'react';
|
|
|
|
|
+
|
|
|
|
|
+import {Row, Col, Input, Icon, Button, Spin} from 'antd';
|
|
|
|
|
+import './index.css';
|
|
|
|
|
+import SchemaChange from './change/SchemaChange';
|
|
|
|
|
+import gql from "graphql-tag";
|
|
|
|
|
+import {Mutation, Query} from "react-apollo";
|
|
|
|
|
+
|
|
|
|
|
+const Search = Input.Search;
|
|
|
|
|
+
|
|
|
|
|
+const idGen = (kind) => {
|
|
|
|
|
+ return kind + '_' + Date.now() + '_' + Math.random().toString().slice(-8);
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+class Schema extends Component {
|
|
|
|
|
+ constructor(props) {
|
|
|
|
|
+ super(props);
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ currentSchema: '',
|
|
|
|
|
+ currentTable: '',
|
|
|
|
|
+ schemas: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'magazineApp',
|
|
|
|
|
+ tables: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'magazine',
|
|
|
|
|
+ remark: 'magazine list',
|
|
|
|
|
+ cols: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'id',
|
|
|
|
|
+ type: 'ID',
|
|
|
|
|
+ desc: 'key'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'name',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ desc: 'non-null'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'suitableGrade',
|
|
|
|
|
+ type: 'int',
|
|
|
|
|
+ desc: 'non-null-list'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'picture',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ desc: 'description'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'magazineIntro',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ desc: 'description'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'unitPrice',
|
|
|
|
|
+ type: 'float',
|
|
|
|
|
+ desc: 'description'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'enableSub',
|
|
|
|
|
+ type: 'int',
|
|
|
|
|
+ desc: 'list'
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'slideshow',
|
|
|
|
|
+ remark: 'slideshow list',
|
|
|
|
|
+ cols: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'id',
|
|
|
|
|
+ type: 'ID',
|
|
|
|
|
+ desc: 'key'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'briefIntro',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ desc: 'description'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'picture',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ desc: 'description'
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'onlineApp',
|
|
|
|
|
+ tables: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'database',
|
|
|
|
|
+ remark: 'database configs',
|
|
|
|
|
+ cols: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'dbname',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ desc: 'non-null'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'dbConfig',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ desc: 'non-null'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'createdAt',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ desc: 'description'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'updatedAt',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ desc: 'description'
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'deploy',
|
|
|
|
|
+ remark: 'deploy\'s collections ',
|
|
|
|
|
+ cols: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'cloud_id',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ desc: 'non-null'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'schema_id',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ desc: 'non-null'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'user_id',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ desc: 'description'
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ };
|
|
|
|
|
+ if (this.state.schemas.length !== 0) {
|
|
|
|
|
+ this.state.currentSchema = this.state.schemas[0].name;
|
|
|
|
|
+ this.state.currentTable = this.state.schemas[0].tables[0].name;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ addTable = (columns, remark, tableName, schemaName) => {
|
|
|
|
|
+ let schemas = this.state.schemas;
|
|
|
|
|
+ let targetSchema = schemas.find(obj => obj.name === schemaName);
|
|
|
|
|
+ let targetTable = targetSchema.tables.find(obj => obj.name === tableName);
|
|
|
|
|
+ if (targetTable === undefined) {
|
|
|
|
|
+ targetSchema.tables.push({name: tableName, remark, cols: columns})
|
|
|
|
|
+ } else {
|
|
|
|
|
+ targetTable.remark = remark;
|
|
|
|
|
+ targetTable.cols = columns;
|
|
|
|
|
+ }
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ schemas
|
|
|
|
|
+ })
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ deleteTable = (tableName, schemaName) => {
|
|
|
|
|
+ let schemas = this.state.schemas;
|
|
|
|
|
+ let targetSchemaIndex = schemas.findIndex(obj => obj.name === schemaName);
|
|
|
|
|
+ let targetTableIndex = schemas.find(obj => obj.name === schemaName).tables.findIndex(obj => obj.name === tableName);
|
|
|
|
|
+ schemas[targetSchemaIndex].tables.splice(targetTableIndex, 1);
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ schemas
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ let tables = this.state.schemas.find(obj => obj.name === this.state.currentSchema).tables;
|
|
|
|
|
+ if (tables.length !== 0) {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ currentTable: tables[0].name
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ currentTable: ''
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ switchTable = (table) => {
|
|
|
|
|
+ return () => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ currentTable: table
|
|
|
|
|
+ })
|
|
|
|
|
+ };
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ addSchema = (name) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ schemas: [...this.state.schemas, {
|
|
|
|
|
+ name,
|
|
|
|
|
+ tables: []
|
|
|
|
|
+ }]
|
|
|
|
|
+ });
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ findColumns = () => {
|
|
|
|
|
+ let schema = this.state.schemas.find(schema => schema.name === this.state.currentSchema);
|
|
|
|
|
+ if (schema === undefined) return [];
|
|
|
|
|
+ // if user insert a new schema, after merge to schemas with a {name: 'xx', tables: []}
|
|
|
|
|
+ // you can find the following table is undefined.
|
|
|
|
|
+ // so give a state here if you want add a tip!
|
|
|
|
|
+ else {
|
|
|
|
|
+ let table = schema.tables.find(table => table.name === this.state.currentTable);
|
|
|
|
|
+ if (table === undefined) return [];
|
|
|
|
|
+ else return table.cols;
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ findRemark = () => {
|
|
|
|
|
+ let schema = this.state.schemas.find(schema => schema.name === this.state.currentSchema);
|
|
|
|
|
+ if (schema === undefined) return '';
|
|
|
|
|
+ else {
|
|
|
|
|
+ let table = schema.tables.find(table => table.name === this.state.currentTable);
|
|
|
|
|
+ if (table === undefined) return '';
|
|
|
|
|
+ else return table.remark;
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <Row>
|
|
|
|
|
+ <Col span={6}>
|
|
|
|
|
+ <div className='wrapper'>
|
|
|
|
|
+ <div className='current'>{this.state.currentSchema}</div>
|
|
|
|
|
+ <AddSchemaInput userID={this.props.userID} addSchema={this.addSchema}/>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <ShowSchemaList fetchSchemas={this.fetchSchemas}/>
|
|
|
|
|
+ </Col>
|
|
|
|
|
+
|
|
|
|
|
+ <Col span={18}>
|
|
|
|
|
+ {
|
|
|
|
|
+ this.state.currentTable === 'add' ?
|
|
|
|
|
+ <SchemaChange currentSchema={this.state.currentSchema} columns={[]} remark='' addTable={this.addTable}
|
|
|
|
|
+ deleteTable={this.deleteTable}/> :
|
|
|
|
|
+ <SchemaChange currentSchema={this.state.currentSchema} currentTable={this.state.currentTable}
|
|
|
|
|
+ columns={this.findColumns()} remark={this.findRemark()} addTable={this.addTable}
|
|
|
|
|
+ deleteTable={this.deleteTable}/>
|
|
|
|
|
+ }
|
|
|
|
|
+ </Col>
|
|
|
|
|
+ </Row>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export default Schema;
|
|
|
|
|
+
|
|
|
|
|
+class AddSchemaInput extends Component {
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ let varobj = {
|
|
|
|
|
+ id: idGen('schema'),
|
|
|
|
|
+ user_id: this.props.userID,
|
|
|
|
|
+ createdAt: new Date().getTime(),
|
|
|
|
|
+ updatedAt: '',
|
|
|
|
|
+ schemaState: 'create',
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const ADD_SCHEMA = gql`
|
|
|
|
|
+ mutation SCHEMA($id: ID!, $user_id: String!, $schemaName: String!, $schemaData: String!, $createdAt: String, $updatedAt: String, $schemaState: String) {
|
|
|
|
|
+ create_schema(
|
|
|
|
|
+ id: $id,
|
|
|
|
|
+ user_id: $user_id,
|
|
|
|
|
+ schemaName: $schemaName,
|
|
|
|
|
+ createdAt: $createdAt,
|
|
|
|
|
+ updatedAt: $updatedAt,
|
|
|
|
|
+ schemaData: $schemaData,
|
|
|
|
|
+ schemaState: $schemaState
|
|
|
|
|
+ ) {
|
|
|
|
|
+ id,
|
|
|
|
|
+ schemaName
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ `;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Mutation mutation={ADD_SCHEMA}>
|
|
|
|
|
+ {(create_schema, {loading, error}) => {
|
|
|
|
|
+ if (loading)
|
|
|
|
|
+ return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
|
|
|
|
|
+ if (error)
|
|
|
|
|
+ return 'error';
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <Search
|
|
|
|
|
+ className='add-input'
|
|
|
|
|
+ placeholder="input schema_name"
|
|
|
|
|
+ enterButton="Confirm"
|
|
|
|
|
+ onSearch={value => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ switch: true,
|
|
|
|
|
+ currentSchema: value,
|
|
|
|
|
+ currentTable: ''
|
|
|
|
|
+ });
|
|
|
|
|
+ this.props.addSchema(value);
|
|
|
|
|
+ create_schema({
|
|
|
|
|
+ variables: {
|
|
|
|
|
+ ...varobj,
|
|
|
|
|
+ schemaName: value,
|
|
|
|
|
+ schemaData: {
|
|
|
|
|
+ value,
|
|
|
|
|
+ tables: []
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>)
|
|
|
|
|
+ }}
|
|
|
|
|
+ </Mutation>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+class ShowSchemaList extends Component {
|
|
|
|
|
+
|
|
|
|
|
+ switchSchema = (schema) => {
|
|
|
|
|
+ return () => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ currentSchema: schema
|
|
|
|
|
+ });
|
|
|
|
|
+ // when this schema has no table, show new
|
|
|
|
|
+ if (this.state.schemas.find(obj => obj.name === schema).tables.length === 0) {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ currentTable: ''
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ deleteSchema = (e, schemaName) => {
|
|
|
|
|
+ e.stopPropagation();
|
|
|
|
|
+ let schemas = this.state.schemas;
|
|
|
|
|
+ let targetSchemaIndex = schemas.findIndex(obj => obj.name === schemaName);
|
|
|
|
|
+ if (targetSchemaIndex !== -1) {
|
|
|
|
|
+ schemas.splice(targetSchemaIndex, 1);
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ schemas
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.state.schemas.length !== 0) {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ currentSchema: this.state.schemas[0].name,
|
|
|
|
|
+ currentTable: this.state.schemas[0].tables[0] ? this.state.schemas[0].tables[0].name : ''
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ currentSchema: '',
|
|
|
|
|
+ currentTable: ''
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ const SHOW_SCHEMA = gql`
|
|
|
|
|
+ query SCHEMA($user_id: String) {
|
|
|
|
|
+ schema_by_props(user_id: $user_id) {
|
|
|
|
|
+ schemaData
|
|
|
|
|
+ schemaName
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ `;
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Query query={SHOW_SCHEMA} variables={{user_id: this.props.userID}}>
|
|
|
|
|
+ {
|
|
|
|
|
+ ({loading, error, data}) => {
|
|
|
|
|
+ if (loading) {
|
|
|
|
|
+ return <Spin style={{marginLeft: 3}}/>
|
|
|
|
|
+ }
|
|
|
|
|
+ if (error) {
|
|
|
|
|
+ return 'error!';
|
|
|
|
|
+ }
|
|
|
|
|
+ console.log(data);
|
|
|
|
|
+ if (data.schema_by_props.length === 0)
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span>no schemas, create one</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
|
|
+ else {
|
|
|
|
|
+ console.log('getttttttttt', data);
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div>
|
|
|
|
|
+ {
|
|
|
|
|
+ data.schema_by_props.map((schema) => {
|
|
|
|
|
+ return <div key={schema.schemaName} className='title' onClick={this.switchSchema(schema.schemaName)}>
|
|
|
|
|
+ <Row>
|
|
|
|
|
+ <Col span={20}>{schema.schemaName}</Col>
|
|
|
|
|
+ <Col span={4}>
|
|
|
|
|
+ <Button onClick={() => this.setState({currentTable: 'add'})} type="primary"
|
|
|
|
|
+ shape="circle" icon="plus" size='small'/>
|
|
|
|
|
+ <DeleteSchemaButton schemaName={schema.schemaName} deleteSchema={this.deleteSchema}/>
|
|
|
|
|
+ </Col>
|
|
|
|
|
+ </Row>
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ {
|
|
|
|
|
+ schema.tables.map((table) =>
|
|
|
|
|
+ <p onClick={this.switchTable(table.name)} key={table.name} className='show'>
|
|
|
|
|
+ <Icon type="ordered-list" theme="outlined"/> {table.name}
|
|
|
|
|
+ <span className='remark'><i> {table.remark}</i></span>
|
|
|
|
|
+ </p>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ </div>
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ </Query>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+class DeleteSchemaButton extends Component {
|
|
|
|
|
+ render() {
|
|
|
|
|
+ const DELETE_SCHEMA = gql`
|
|
|
|
|
+ mutation SCHEMA($schemaName: String) {
|
|
|
|
|
+ delete_schema(schemaName: $schemaName)
|
|
|
|
|
+ }
|
|
|
|
|
+ `;
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Mutation mutation={DELETE_SCHEMA}>
|
|
|
|
|
+ {(delete_schema, {loading, error}) => {
|
|
|
|
|
+ if (error)
|
|
|
|
|
+ return 'error';
|
|
|
|
|
+ if (loading)
|
|
|
|
|
+ return <Spin style={{marginLeft: 3}}/>;
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Button onClick={(e) => {
|
|
|
|
|
+ this.props.deleteSchema(e, this.props.schemaName);
|
|
|
|
|
+ delete_schema({variables: {schemaName: this.props.schemaName}});
|
|
|
|
|
+ }} type="danger" shape="circle" icon="delete" size='small' style={{marginLeft: 3}}/>
|
|
|
|
|
+ )
|
|
|
|
|
+ }}
|
|
|
|
|
+ </Mutation>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|