diff --git a/packages/datalib/src/PerspectiveConfig.ts b/packages/datalib/src/PerspectiveConfig.ts index 2067c8188..a3e836d0f 100644 --- a/packages/datalib/src/PerspectiveConfig.ts +++ b/packages/datalib/src/PerspectiveConfig.ts @@ -4,6 +4,19 @@ export interface PerspectiveConfigColumns { uncheckedColumns: string[]; } +export interface PerspectiveCustomJoinConfig { + joinid: string; + joinName: string; + baseUniqueName: string; + conid?: string; + database?: string; + refSchemaName?: string; + refTableName: string; + columns: { + baseColumnName: string; + refColumnName: string; + }[]; +} export interface PerspectiveConfig extends PerspectiveConfigColumns { filters: { [uniqueName: string]: string }; sort: { @@ -12,6 +25,7 @@ export interface PerspectiveConfig extends PerspectiveConfigColumns { order: 'ASC' | 'DESC'; }[]; }; + customJoins: PerspectiveCustomJoinConfig[]; } export function createPerspectiveConfig(): PerspectiveConfig { @@ -19,6 +33,7 @@ export function createPerspectiveConfig(): PerspectiveConfig { expandedColumns: [], checkedColumns: [], uncheckedColumns: [], + customJoins: [], filters: {}, sort: {}, }; diff --git a/packages/datalib/src/PerspectiveTreeNode.ts b/packages/datalib/src/PerspectiveTreeNode.ts index efc19c4d6..960b33260 100644 --- a/packages/datalib/src/PerspectiveTreeNode.ts +++ b/packages/datalib/src/PerspectiveTreeNode.ts @@ -203,6 +203,20 @@ export abstract class PerspectiveTreeNode { { columnName: table?.columns[0].columnName, order: 'ASC' }, ]; } + + getBaseTables() { + const res = []; + const table = this.getBaseTableFromThis(); + if (table) res.push({ table, node: this }); + for (const child of this.childNodes) { + if (!child.isChecked) continue; + res.push(...child.getBaseTables()); + } + return res; + } + getBaseTableFromThis() { + return null; + } } export class PerspectiveTableColumnNode extends PerspectiveTreeNode { @@ -311,6 +325,10 @@ export class PerspectiveTableColumnNode extends PerspectiveTreeNode { ); } + getBaseTableFromThis() { + return this.refTable; + } + parseFilterCondition() { const filter = this.getFilter(); if (!filter) return null; @@ -380,6 +398,10 @@ export class PerspectiveTableNode extends PerspectiveTreeNode { get icon() { return 'img table'; } + + getBaseTableFromThis() { + return this.table; + } } export class PerspectiveViewNode extends PerspectiveTreeNode { @@ -433,6 +455,10 @@ export class PerspectiveViewNode extends PerspectiveTreeNode { get icon() { return 'img table'; } + + getBaseTableFromThis() { + return this.view; + } } export class PerspectiveTableReferenceNode extends PerspectiveTableNode { diff --git a/packages/web/src/icons/FontIcon.svelte b/packages/web/src/icons/FontIcon.svelte index dedaa49f0..96ddeaf07 100644 --- a/packages/web/src/icons/FontIcon.svelte +++ b/packages/web/src/icons/FontIcon.svelte @@ -94,6 +94,7 @@ 'icon add': 'mdi mdi-plus-circle', 'icon json': 'mdi mdi-code-json', 'icon lock': 'mdi mdi-lock', + 'icon custom-join': 'mdi mdi-arrow-left-right-bold', 'icon run': 'mdi mdi-play', 'icon chevron-down': 'mdi mdi-chevron-down', diff --git a/packages/web/src/impexp/FormConnectionSelect.svelte b/packages/web/src/impexp/FormConnectionSelect.svelte index c87d144c4..0f71c9925 100644 --- a/packages/web/src/impexp/FormConnectionSelect.svelte +++ b/packages/web/src/impexp/FormConnectionSelect.svelte @@ -12,7 +12,7 @@ ...(allowChooseModel ? [{ label: '(DB Model)', value: '__model' }] : []), ..._.sortBy( ($connections || []) - .filter(conn => (direction == 'target' ? !conn.isReadOnly : true)) + .filter(conn => !conn.unsaved && (direction == 'target' ? !conn.isReadOnly : true)) .map(conn => ({ value: conn._id, label: getConnectionLabel(conn), diff --git a/packages/web/src/perspectives/CustomJoinModal.svelte b/packages/web/src/perspectives/CustomJoinModal.svelte new file mode 100644 index 000000000..d7747b66b --- /dev/null +++ b/packages/web/src/perspectives/CustomJoinModal.svelte @@ -0,0 +1,343 @@ + + + + + Define custom join + +
+
+
Join name
+
+ { + joinName = e.target['value']; + }} + /> +
+
+ +
+
Base table
+
+ { + if (e.detail) { + fromUniuqeName = e.detail; + } + }} + /> +
+
+ +
+
Connection
+
+ { + conidOverride = e.detail; + }} + /> +
+
+ +
+
Database
+
+ { + databaseOverride = e.detail; + }} + /> +
+
+ + + +
+
Referenced table
+
+ { + if (e.detail) { + const name = fullNameFromString(e.detail); + refTableName = name.pureName; + refSchemaName = name.schemaName; + const refTable = $refDbInfo?.tables?.find( + x => x.pureName == refTableName && x.schemaName == refSchemaName + ); + columns = refTable?.primaryKey?.columns?.map(col => ({ + refColumnName: col.columnName, + })); + } + }} + /> +
+
+ +
+
+ Base column - {fromTableInfo?.pureName} +
+
+ Ref column - {refTableName || '(table not set)'} +
+
+ + {#each columns as column, index} +
+
+ {#key column.columnName} + ({ + label: col.columnName, + value: col.columnName, + }))} + on:change={e => { + if (e.detail) { + columns = columns.map((col, i) => (i == index ? { ...col, columnName: e.detail } : col)); + } + }} + /> + {/key} +
+
+ {#key column.refColumnName} + ({ + label: col.columnName, + value: col.columnName, + }))} + on:change={e => { + if (e.detail) { + columns = columns.map((col, i) => (i == index ? { ...col, refColumnName: e.detail } : col)); + } + }} + /> + {/key} +
+
+ { + const x = [...columns]; + x.splice(index, 1); + columns = x; + }} + /> +
+
+ {/each} + + { + columns = [...columns, {}]; + }} + /> +
+ + + { + setConfig(cfg => ({ + ...cfg, + customJoins: [ + ...(cfg.customJoins || []), + { + baseUniqueName: fromUniuqeName, + refTableName, + refSchemaName, + columns: columns.map(col => ({ + baseColumnName: col.columnName, + refColumnName: col.refColumnName, + })), + }, + ], + })); + closeCurrentModal(); + }} + /> + + + +
+
+ + diff --git a/packages/web/src/perspectives/PerspectiveTable.svelte b/packages/web/src/perspectives/PerspectiveTable.svelte index c6909aa66..ed7c7e18d 100644 --- a/packages/web/src/perspectives/PerspectiveTable.svelte +++ b/packages/web/src/perspectives/PerspectiveTable.svelte @@ -155,6 +155,9 @@ { command: 'perspective.openJson', }, + { + command: 'perspective.customJoin', + }, ]; } diff --git a/packages/web/src/perspectives/PerspectiveView.svelte b/packages/web/src/perspectives/PerspectiveView.svelte index 19745a4e1..6e63d14dd 100644 --- a/packages/web/src/perspectives/PerspectiveView.svelte +++ b/packages/web/src/perspectives/PerspectiveView.svelte @@ -1,3 +1,18 @@ + +