From daf7629f5f024d58c42d561a6846d2ff27d612a1 Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Thu, 25 Aug 2022 15:20:16 +0200 Subject: [PATCH] perspective designer WIP --- packages/datalib/src/PerspectiveConfig.ts | 12 +- packages/datalib/src/PerspectiveTreeNode.ts | 194 +++++++++++++------- 2 files changed, 139 insertions(+), 67 deletions(-) diff --git a/packages/datalib/src/PerspectiveConfig.ts b/packages/datalib/src/PerspectiveConfig.ts index 3b4855f1..14a82f70 100644 --- a/packages/datalib/src/PerspectiveConfig.ts +++ b/packages/datalib/src/PerspectiveConfig.ts @@ -88,9 +88,9 @@ export interface PerspectiveConfig { references: PerspectiveReferenceConfig[]; } -export function createPerspectiveConfig(rootObject: { schemaName?: string; pureName: string }): PerspectiveConfig { - const rootNode: PerspectiveNodeConfig = { - ...rootObject, +export function createPerspectiveNodeConfig(name: { schemaName?: string; pureName: string }) { + const node: PerspectiveNodeConfig = { + ...name, designerId: uuidv1(), expandedNodes: [], @@ -100,6 +100,12 @@ export function createPerspectiveConfig(rootObject: { schemaName?: string; pureN sort: [], filters: {}, }; + + return node; +} + +export function createPerspectiveConfig(rootObject: { schemaName?: string; pureName: string }): PerspectiveConfig { + const rootNode = createPerspectiveNodeConfig(rootObject); return { nodes: [rootNode], references: [], diff --git a/packages/datalib/src/PerspectiveTreeNode.ts b/packages/datalib/src/PerspectiveTreeNode.ts index 3ff2e52c..d8bdf4cb 100644 --- a/packages/datalib/src/PerspectiveTreeNode.ts +++ b/packages/datalib/src/PerspectiveTreeNode.ts @@ -9,11 +9,13 @@ import { } from 'dbgate-types'; import { ChangePerspectiveConfigFunc, + createPerspectiveNodeConfig, MultipleDatabaseInfo, PerspectiveConfig, PerspectiveCustomJoinConfig, PerspectiveFilterColumnInfo, PerspectiveNodeConfig, + PerspectiveReferenceConfig, } from './PerspectiveConfig'; import _isEqual from 'lodash/isEqual'; import _cloneDeep from 'lodash/cloneDeep'; @@ -33,6 +35,7 @@ import { getFilterType, parseFilter } from 'dbgate-filterparser'; import { FilterType } from 'dbgate-filterparser/lib/types'; import { Condition, Expression, Select } from 'dbgate-sqltree'; import { getPerspectiveDefaultColumns } from './getPerspectiveDefaultColumns'; +import uuidv1 from 'uuid/v1'; export interface PerspectiveDataLoadPropsWithNode { props: PerspectiveDataLoadProps; @@ -182,51 +185,50 @@ export abstract class PerspectiveTreeNode { } } - includeInNodeSet(field: 'expandedNodes' | 'uncheckedNodes' | 'checkedNodes', isIncluded: boolean) { - // this.setConfig(cfg => { - // const node = cfg.nodes.find(x=>x.designerId==this.designerId); - // if (!node) { + createReferenceConfigColumns(): PerspectiveReferenceConfig['columns'] { + return null; + } - // } - - // return { - // ...cfg, - // nodes: cfg.nodes.map(node => - // node.designerId == this.parentNode?.designerId - // ? { - // ...node, - // [field]: [...(node[field] || []), this.codeName], - // } - // : node - // ), - // }; - // }); - - if (isIncluded) { - this.setConfig(cfg => ({ + ensureNodeConfig(cfg: PerspectiveConfig): PerspectiveConfig { + let node = cfg.nodes.find(x => x.designerId == this.designerId); + if (!node) { + const nodeConfig: PerspectiveNodeConfig = { + ...createPerspectiveNodeConfig(this.namedObject), + isAutoGenerated: true, + }; + const refConfig: PerspectiveReferenceConfig = { + designerId: uuidv1(), + sourceId: this.parentNode.designerId, + targetId: nodeConfig.designerId, + isAutoGenerated: true, + columns: this.createReferenceConfigColumns(), + }; + return { ...cfg, - nodes: cfg.nodes.map(node => - node.designerId == this.parentNode?.designerId - ? { - ...node, - [field]: [...(node[field] || []), this.codeName], - } - : node - ), - })); - } else { - this.setConfig(cfg => ({ - ...cfg, - nodes: cfg.nodes.map(node => - node.designerId == this.parentNode?.designerId - ? { - ...node, - [field]: (node[field] || []).filter(x => x != this.codeName), - } - : node - ), - })); + nodes: [...cfg.nodes, nodeConfig], + references: [...cfg.references, refConfig], + }; } + return cfg; + } + + includeInNodeSet(field: 'expandedNodes' | 'uncheckedNodes' | 'checkedNodes', isIncluded: boolean) { + this.setConfig(cfg => { + const changedFields = n => ({ + ...n, + [field]: isIncluded ? [...(n[field] || []), this.codeName] : (n[field] || []).filter(x => x != this.codeName), + }); + + cfg = this.parentNode?.ensureNodeConfig(cfg); + if (isIncluded && field == 'expandedNodes') { + cfg = this.ensureNodeConfig(cfg); + } + + return { + ...cfg, + nodes: cfg.nodes.map(n => (n.designerId == this.parentNode?.designerId ? changedFields(n) : n)), + }; + }); } getFilter() { @@ -463,6 +465,13 @@ export class PerspectiveTableColumnNode extends PerspectiveTreeNode { }); } + createReferenceConfigColumns(): PerspectiveReferenceConfig['columns'] { + return this.foreignKey?.columns?.map(col => ({ + source: col.columnName, + target: col.refColumnName, + })); + } + getNodeLoadProps(parentRows: any[]): PerspectiveDataLoadProps { if (!this.foreignKey) return null; return { @@ -775,6 +784,13 @@ export class PerspectiveTableReferenceNode extends PerspectiveTableNode { }; } + createReferenceConfigColumns(): PerspectiveReferenceConfig['columns'] { + return this.foreignKey?.columns?.map(col => ({ + source: col.refColumnName, + target: col.columnName, + })); + } + get columnTitle() { return this.table.pureName; } @@ -902,6 +918,47 @@ export class PerspectiveCustomJoinTreeNode extends PerspectiveTableNode { } } +function findDesignerIdForNode( + config: PerspectiveConfig, + parentNode: PerspectiveTreeNode, + nodeCreateFunc: (designerId: string) => T +): T { + const node = nodeCreateFunc(null); + const refColumns = node.createReferenceConfigColumns(); + if (!refColumns?.length) { + return node; + } + const ref1 = config.references.find( + x => + x.sourceId == parentNode.designerId && + _isEqual( + refColumns.map(x => x.source), + x.columns.map(x => x.source) + ) && + _isEqual( + refColumns.map(x => x.target), + x.columns.map(x => x.target) + ) + ); + if (ref1) return nodeCreateFunc(ref1.targetId); + + const ref2 = config.references.find( + x => + x.targetId == parentNode.designerId && + _isEqual( + refColumns.map(x => x.target), + x.columns.map(x => x.source) + ) && + _isEqual( + refColumns.map(x => x.source), + x.columns.map(x => x.target) + ) + ); + if (ref2) return nodeCreateFunc(ref2.sourceId); + + return node; +} + export function getTableChildPerspectiveNodes( table: TableInfo | ViewInfo, dbs: MultipleDatabaseInfo, @@ -914,19 +971,23 @@ export function getTableChildPerspectiveNodes( if (!table) return []; const db = parentColumn.db; - const columnNodes = table.columns.map( - col => - new PerspectiveTableColumnNode( - col, - table, - dbs, - config, - setConfig, - dataProvider, - databaseConfig, - parentColumn, - null - ) + const columnNodes = table.columns.map(col => + findDesignerIdForNode( + config, + parentColumn, + designerId => + new PerspectiveTableColumnNode( + col, + table, + dbs, + config, + setConfig, + dataProvider, + databaseConfig, + parentColumn, + designerId + ) + ) ); const circularColumns = columnNodes.filter(x => x.isCircular).map(x => x.columnName); const defaultColumns = getPerspectiveDefaultColumns(table, db, circularColumns); @@ -945,17 +1006,22 @@ export function getTableChildPerspectiveNodes( (table as TableInfo)?.dependencies.filter(x => x.pureName == fk.pureName && x.schemaName == fk.schemaName) .length >= 2; dependencies.push( - new PerspectiveTableReferenceNode( - fk, - tbl, - dbs, + findDesignerIdForNode( config, - setConfig, - dataProvider, - databaseConfig, - isMultiple, parentColumn, - null + designerId => + new PerspectiveTableReferenceNode( + fk, + tbl, + dbs, + config, + setConfig, + dataProvider, + databaseConfig, + isMultiple, + parentColumn, + designerId + ) ) ); }