diff --git a/packages/datalib/src/PerspectiveConfig.ts b/packages/datalib/src/PerspectiveConfig.ts index b24be768..263dc0a9 100644 --- a/packages/datalib/src/PerspectiveConfig.ts +++ b/packages/datalib/src/PerspectiveConfig.ts @@ -1,16 +1,14 @@ export interface PerspectiveConfig { - hiddenColumns: string[]; - shownColumns: string[]; expandedColumns: string[]; - collapsedColumns: string[]; + checkedColumns: string[]; + uncheckedColumns: string[]; } export function createPerspectiveConfig(): PerspectiveConfig { return { - hiddenColumns: [], - shownColumns: [], expandedColumns: [], - collapsedColumns: [], + checkedColumns: [], + uncheckedColumns: [], }; } diff --git a/packages/datalib/src/PerspectiveTreeNode.ts b/packages/datalib/src/PerspectiveTreeNode.ts index 5ca5fdfc..1ea2e7f1 100644 --- a/packages/datalib/src/PerspectiveTreeNode.ts +++ b/packages/datalib/src/PerspectiveTreeNode.ts @@ -1,18 +1,62 @@ import { ColumnInfo, DatabaseInfo, ForeignKeyInfo, TableInfo } from 'dbgate-types'; import { clearConfigCache } from 'prettier'; import { ChangePerspectiveConfigFunc, PerspectiveConfig } from './PerspectiveConfig'; +import _isEqual from 'lodash/isEqual'; +import _cloneDeep from 'lodash/cloneDeep'; + +export interface PerspectiveDataLoadProps { + schemaName: string; + pureName: string; + bindingColumns?: string[]; + bindingValues?: any[][]; +} + +export interface PerspectiveDataLoadPropsWithNode { + props: PerspectiveDataLoadProps; + node: PerspectiveTreeNode; +} + +// export function groupPerspectiveLoadProps( +// ...list: PerspectiveDataLoadPropsWithNode[] +// ): PerspectiveDataLoadPropsWithNode[] { +// const res: PerspectiveDataLoadPropsWithNode[] = []; +// for (const item of list) { +// const existing = res.find( +// x => +// x.node == item.node && +// x.props.schemaName == item.props.schemaName && +// x.props.pureName == item.props.pureName && +// _isEqual(x.props.bindingColumns, item.props.bindingColumns) +// ); +// if (existing) { +// existing.props.bindingValues.push(...item.props.bindingValues); +// } else { +// res.push(_cloneDeep(item)); +// } +// } +// return res; +// } export abstract class PerspectiveTreeNode { constructor( public config: PerspectiveConfig, public setConfig: ChangePerspectiveConfigFunc, - public parentNode: PerspectiveTreeNode + public parentNode: PerspectiveTreeNode, + public loader: (props: PerspectiveDataLoadProps) => Promise ) {} abstract get title(); abstract get codeName(); abstract get isExpandable(); abstract get childNodes(): PerspectiveTreeNode[]; abstract get icon(): string; + abstract getNodeLoadProps(parentRows: any[]): PerspectiveDataLoadProps; + get isRoot() { + return this.parentNode == null; + } + matchChildRow(parentRow: any, childRow: any): boolean { + return true; + } + get uniqueName() { if (this.parentNode) return `${this.parentNode.uniqueName}.${this.codeName}`; return this.codeName; @@ -24,11 +68,18 @@ export abstract class PerspectiveTreeNode { get isExpanded() { return this.config.expandedColumns.includes(this.uniqueName); } + get isChecked() { + return this.config.checkedColumns.includes(this.uniqueName); + } toggleExpanded(value?: boolean) { this.includeInColumnSet('expandedColumns', this.uniqueName, value == null ? !this.isExpanded : value); } + toggleChecked(value?: boolean) { + this.includeInColumnSet('checkedColumns', this.uniqueName, value == null ? !this.isChecked : value); + } + includeInColumnSet(field: keyof PerspectiveConfig, uniqueName: string, isIncluded: boolean) { if (isIncluded) { this.setConfig(cfg => ({ @@ -52,15 +103,31 @@ export class PerspectiveTableColumnNode extends PerspectiveTreeNode { public db: DatabaseInfo, config: PerspectiveConfig, setConfig: ChangePerspectiveConfigFunc, - parentColumn: PerspectiveTreeNode + loader: (props: PerspectiveDataLoadProps) => Promise, + parentNode: PerspectiveTreeNode ) { - super(config, setConfig, parentColumn); + super(config, setConfig, parentNode, loader); this.foreignKey = table.foreignKeys && table.foreignKeys.find(fk => fk.columns.length == 1 && fk.columns[0].columnName == column.columnName); } + matchChildRow(parentRow: any, childRow: any): boolean { + if (!this.foreignKey) return false; + return parentRow[this.foreignKey.columns[0].columnName] == childRow[this.foreignKey.columns[0].refColumnName]; + } + + getNodeLoadProps(parentRows: any[]): PerspectiveDataLoadProps { + if (!this.foreignKey) return null; + return { + schemaName: this.foreignKey.refSchemaName, + pureName: this.foreignKey.refTableName, + bindingColumns: [this.foreignKey.columns[0].refColumnName], + bindingValues: parentRows.map(row => row[this.foreignKey.columns[0].columnName]), + }; + } + get icon() { if (this.column.autoIncrement) return 'img autoincrement'; if (this.foreignKey) return 'img foreign-key'; @@ -84,21 +151,27 @@ export class PerspectiveTableColumnNode extends PerspectiveTreeNode { const tbl = this?.db?.tables?.find( x => x.pureName == this.foreignKey?.refTableName && x.schemaName == this.foreignKey?.refSchemaName ); - return getTableChildPerspectiveNodes(tbl, this.db, this.config, this.setConfig, this); + return getTableChildPerspectiveNodes(tbl, this.db, this.config, this.setConfig, this.loader, this); } } -export class PerspectiveTableReferenceNode extends PerspectiveTreeNode { - foreignKey: ForeignKeyInfo; +export class PerspectiveTableNode extends PerspectiveTreeNode { constructor( - public fk: ForeignKeyInfo, public table: TableInfo, public db: DatabaseInfo, config: PerspectiveConfig, setConfig: ChangePerspectiveConfigFunc, - parentColumn: PerspectiveTreeNode + loader: (props: PerspectiveDataLoadProps) => Promise, + parentNode: PerspectiveTreeNode ) { - super(config, setConfig, parentColumn); + super(config, setConfig, parentNode, loader); + } + + getNodeLoadProps(parentRows: any[]) { + return { + schemaName: this.table.schemaName, + pureName: this.table.pureName, + }; } get codeName() { @@ -114,7 +187,7 @@ export class PerspectiveTableReferenceNode extends PerspectiveTreeNode { } get childNodes(): PerspectiveTreeNode[] { - return getTableChildPerspectiveNodes(this.table, this.db, this.config, this.setConfig, this); + return getTableChildPerspectiveNodes(this.table, this.db, this.config, this.setConfig, this.loader, this); } get icon() { @@ -122,22 +195,52 @@ export class PerspectiveTableReferenceNode extends PerspectiveTreeNode { } } +export class PerspectiveTableReferenceNode extends PerspectiveTableNode { + constructor( + public foreignKey: ForeignKeyInfo, + table: TableInfo, + db: DatabaseInfo, + config: PerspectiveConfig, + setConfig: ChangePerspectiveConfigFunc, + loader: (props: PerspectiveDataLoadProps) => Promise, + parentNode: PerspectiveTreeNode + ) { + super(table, db, config, setConfig, loader, parentNode); + } + + matchChildRow(parentRow: any, childRow: any): boolean { + if (!this.foreignKey) return false; + return parentRow[this.foreignKey.columns[0].refColumnName] == childRow[this.foreignKey.columns[0].columnName]; + } + + getNodeLoadProps(parentRows: any[]): PerspectiveDataLoadProps { + if (!this.foreignKey) return null; + return { + schemaName: this.table.schemaName, + pureName: this.table.pureName, + bindingColumns: [this.foreignKey.columns[0].columnName], + bindingValues: parentRows.map(row => row[this.foreignKey.columns[0].refColumnName]), + }; + } +} + export function getTableChildPerspectiveNodes( table: TableInfo, db: DatabaseInfo, config: PerspectiveConfig, setConfig: ChangePerspectiveConfigFunc, + loader: (props: PerspectiveDataLoadProps) => Promise, parentColumn: PerspectiveTreeNode ) { if (!table) return []; const res = []; res.push( - ...table.columns.map(col => new PerspectiveTableColumnNode(col, table, db, config, setConfig, parentColumn)) + ...table.columns.map(col => new PerspectiveTableColumnNode(col, table, db, config, setConfig, loader, parentColumn)) ); if (db && table.dependencies) { for (const fk of table.dependencies) { const tbl = db.tables.find(x => x.pureName == fk.pureName && x.schemaName == fk.schemaName); - if (tbl) res.push(new PerspectiveTableReferenceNode(fk, tbl, db, config, setConfig, parentColumn)); + if (tbl) res.push(new PerspectiveTableReferenceNode(fk, tbl, db, config, setConfig, loader, parentColumn)); } } return res; diff --git a/packages/sqltree/src/dumpSqlCondition.ts b/packages/sqltree/src/dumpSqlCondition.ts index a2134101..df4d2e96 100644 --- a/packages/sqltree/src/dumpSqlCondition.ts +++ b/packages/sqltree/src/dumpSqlCondition.ts @@ -68,5 +68,9 @@ export function dumpSqlCondition(dmp: SqlDumper, condition: Condition) { dmp.put(' ^and '); dumpSqlExpression(dmp, condition.right); break; + case 'in': + dumpSqlExpression(dmp, condition.expr); + dmp.put(' ^in (%,v)', condition.values); + break; } } diff --git a/packages/sqltree/src/types.ts b/packages/sqltree/src/types.ts index 4f7996c2..18f77423 100644 --- a/packages/sqltree/src/types.ts +++ b/packages/sqltree/src/types.ts @@ -99,6 +99,12 @@ export interface BetweenCondition { right: Expression; } +export interface InCondition { + conditionType: 'in'; + expr: Expression; + values: any[]; +} + export type Condition = | BinaryCondition | NotCondition @@ -107,7 +113,8 @@ export type Condition = | LikeCondition | ExistsCondition | NotExistsCondition - | BetweenCondition; + | BetweenCondition + | InCondition; export interface Source { name?: NamedObjectInfo; diff --git a/packages/web/src/perspectives/PerspectiveCore.svelte b/packages/web/src/perspectives/PerspectiveCore.svelte deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/web/src/perspectives/PerspectiveNodeRow.svelte b/packages/web/src/perspectives/PerspectiveNodeRow.svelte index 3f38fb9e..604724cf 100644 --- a/packages/web/src/perspectives/PerspectiveNodeRow.svelte +++ b/packages/web/src/perspectives/PerspectiveNodeRow.svelte @@ -1,16 +1,20 @@
node.toggleExpanded()} + on:click={() => { + node.toggleExpanded(); + }} /> @@ -24,9 +28,7 @@ e.stopPropagation(); }} on:change={() => { - const newValue = !node.isChecked; - // display.setColumnVisibility(column.uniquePath, newValue); - // dispatch('setvisibility', newValue); + node.toggleChecked(); }} /> diff --git a/packages/web/src/perspectives/PerspectiveTable.svelte b/packages/web/src/perspectives/PerspectiveTable.svelte new file mode 100644 index 00000000..083b9539 --- /dev/null +++ b/packages/web/src/perspectives/PerspectiveTable.svelte @@ -0,0 +1,76 @@ + + + + +
xxx
diff --git a/packages/web/src/perspectives/PerspectiveTree.svelte b/packages/web/src/perspectives/PerspectiveTree.svelte index 0e22efb3..030a1d29 100644 --- a/packages/web/src/perspectives/PerspectiveTree.svelte +++ b/packages/web/src/perspectives/PerspectiveTree.svelte @@ -1,7 +1,7 @@ -{#each getFlatColumns(nodes) as node} +{#each getFlatColumns(root) as node} {/each} diff --git a/packages/web/src/perspectives/PerspectiveView.svelte b/packages/web/src/perspectives/PerspectiveView.svelte index 7e5c8c84..6d9bfd66 100644 --- a/packages/web/src/perspectives/PerspectiveView.svelte +++ b/packages/web/src/perspectives/PerspectiveView.svelte @@ -1,5 +1,10 @@
- {#if nodes} - + {#if root} + {/if}
- +