perspective custom join editing & removing

This commit is contained in:
Jan Prochazka
2022-07-31 20:53:22 +02:00
parent 091e91556d
commit b05d260caa
5 changed files with 180 additions and 41 deletions

View File

@@ -1,6 +1,11 @@
import { ColumnInfo, DatabaseInfo, ForeignKeyInfo, RangeDefinition, TableInfo, ViewInfo } from 'dbgate-types'; import { ColumnInfo, DatabaseInfo, ForeignKeyInfo, RangeDefinition, TableInfo, ViewInfo } from 'dbgate-types';
import { clearConfigCache } from 'prettier'; import { clearConfigCache } from 'prettier';
import { ChangePerspectiveConfigFunc, PerspectiveConfig, PerspectiveConfigColumns } from './PerspectiveConfig'; import {
ChangePerspectiveConfigFunc,
PerspectiveConfig,
PerspectiveConfigColumns,
PerspectiveCustomJoinConfig,
} from './PerspectiveConfig';
import _isEqual from 'lodash/isEqual'; import _isEqual from 'lodash/isEqual';
import _cloneDeep from 'lodash/cloneDeep'; import _cloneDeep from 'lodash/cloneDeep';
import _compact from 'lodash/compact'; import _compact from 'lodash/compact';
@@ -98,6 +103,9 @@ export abstract class PerspectiveTreeNode {
get columnName() { get columnName() {
return null; return null;
} }
get customJoinConfig(): PerspectiveCustomJoinConfig {
return null;
}
getChildMatchColumns() { getChildMatchColumns() {
return []; return [];
@@ -512,6 +520,77 @@ export class PerspectiveTableReferenceNode extends PerspectiveTableNode {
} }
} }
export class PerspectiveCustomJoinTreeNode extends PerspectiveTableNode {
constructor(
public customJoin: PerspectiveCustomJoinConfig,
db: DatabaseInfo,
config: PerspectiveConfig,
setConfig: ChangePerspectiveConfigFunc,
public dataProvider: PerspectiveDataProvider,
databaseConfig: PerspectiveDatabaseConfig,
parentNode: PerspectiveTreeNode
) {
super(
db.tables.find(x => x.pureName == customJoin.refTableName && x.schemaName == customJoin.refSchemaName),
db,
config,
setConfig,
dataProvider,
databaseConfig,
parentNode
);
}
matchChildRow(parentRow: any, childRow: any): boolean {
for (const column of this.customJoin.columns) {
if (parentRow[column.baseColumnName] != childRow[column.refColumnName]) {
return false;
}
}
return true;
}
getChildMatchColumns() {
return this.customJoin.columns.map(x => x.refColumnName);
}
getParentMatchColumns() {
return this.customJoin.columns.map(x => x.baseColumnName);
}
getNodeLoadProps(parentRows: any[]): PerspectiveDataLoadProps {
return {
schemaName: this.table.schemaName,
pureName: this.table.pureName,
bindingColumns: this.getChildMatchColumns(),
bindingValues: _uniqBy(
parentRows.map(row => this.customJoin.columns.map(x => row[x.baseColumnName])),
stableStringify
),
dataColumns: this.getDataLoadColumns(),
databaseConfig: this.databaseConfig,
orderBy: this.getOrderBy(this.table),
condition: this.getChildrenCondition(),
};
}
get title() {
return this.customJoin.joinName;
}
get icon() {
return 'icon custom-join';
}
get codeName() {
return this.customJoin.joinid;
}
get customJoinConfig(): PerspectiveCustomJoinConfig {
return this.customJoin;
}
}
export function getTableChildPerspectiveNodes( export function getTableChildPerspectiveNodes(
table: TableInfo | ViewInfo, table: TableInfo | ViewInfo,
db: DatabaseInfo, db: DatabaseInfo,
@@ -551,5 +630,14 @@ export function getTableChildPerspectiveNodes(
); );
} }
} }
for (const join of config.customJoins || []) {
if (join.baseUniqueName == parentColumn.uniqueName) {
res.push(
new PerspectiveCustomJoinTreeNode(join, db, config, setConfig, dataProvider, databaseConfig, parentColumn)
);
}
}
return res; return res;
} }

View File

@@ -10,12 +10,12 @@
import _ from 'lodash'; import _ from 'lodash';
import { useConnectionList, useDatabaseInfo, useDatabaseList, useTableInfo } from '../utility/metadataLoaders'; import { useConnectionList, useDatabaseInfo, useDatabaseList, useTableInfo } from '../utility/metadataLoaders';
import { onMount, tick } from 'svelte'; import { onMount, tick } from 'svelte';
import TargetApplicationSelect from '../forms/TargetApplicationSelect.svelte'; import {
import { apiCall } from '../utility/api'; ChangePerspectiveConfigFunc,
import { saveDbToApp } from '../utility/appTools'; PerspectiveConfig,
import { ChangePerspectiveConfigFunc, PerspectiveConfig, PerspectiveTreeNode } from 'dbgate-datalib'; PerspectiveCustomJoinConfig,
import FormConnectionSelect from '../impexp/FormConnectionSelect.svelte'; PerspectiveTreeNode,
import FormDatabaseSelect from '../impexp/FormDatabaseSelect.svelte'; } from 'dbgate-datalib';
import getConnectionLabel from '../utility/getConnectionLabel'; import getConnectionLabel from '../utility/getConnectionLabel';
import uuidv1 from 'uuid/v1'; import uuidv1 from 'uuid/v1';
import TextField from '../forms/TextField.svelte'; import TextField from '../forms/TextField.svelte';
@@ -25,15 +25,16 @@
export let root: PerspectiveTreeNode; export let root: PerspectiveTreeNode;
export let setConfig: ChangePerspectiveConfigFunc; export let setConfig: ChangePerspectiveConfigFunc;
export let config: PerspectiveConfig; export let config: PerspectiveConfig;
export let editValue: PerspectiveCustomJoinConfig = null;
let conidOverride = null; let conidOverride = editValue?.conid || null;
let databaseOverride = null; let databaseOverride = editValue?.database || null;
let joinid = uuidv1(); let joinid = editValue?.joinid || uuidv1();
$: fromDbInfo = useDatabaseInfo({ // $: fromDbInfo = useDatabaseInfo({
conid, // conid,
database, // database,
}); // });
// $: fromTableInfo = useTableInfo({ // $: fromTableInfo = useTableInfo({
// conid: conidOverride || conid, // conid: conidOverride || conid,
// database: databaseOverride || database, // database: databaseOverride || database,
@@ -52,15 +53,16 @@
pureName: refTableName, pureName: refTableName,
}); });
let columns = []; let columns = editValue?.columns || [];
// let fromTableName = pureName; // let fromTableName = pureName;
// let fromSchemaName = schemaName; // let fromSchemaName = schemaName;
let fromUniuqeName = root.uniqueName; let fromUniuqeName = editValue?.baseUniqueName || root.uniqueName;
let refTableName = null; let refTableName = editValue?.refTableName || null;
let refSchemaName = null; let refSchemaName = editValue?.refSchemaName || null;
let joinName; let joinName = editValue?.joinName || '';
onMount(() => { onMount(() => {
if (editValue) return;
let index = 1; let index = 1;
while (config.customJoins?.find(x => x.joinName == `Custom join ${index}`)) { while (config.customJoins?.find(x => x.joinName == `Custom join ${index}`)) {
index += 1; index += 1;
@@ -240,9 +242,9 @@
{#each columns as column, index} {#each columns as column, index}
<div class="row"> <div class="row">
<div class="col-5 mr-1"> <div class="col-5 mr-1">
{#key column.columnName} {#key column.baseColumnName}
<SelectField <SelectField
value={column.columnName} value={column.baseColumnName}
isNative isNative
notSelected notSelected
options={(fromTableInfo?.columns || []).map(col => ({ options={(fromTableInfo?.columns || []).map(col => ({
@@ -251,7 +253,7 @@
}))} }))}
on:change={e => { on:change={e => {
if (e.detail) { if (e.detail) {
columns = columns.map((col, i) => (i == index ? { ...col, columnName: e.detail } : col)); columns = columns.map((col, i) => (i == index ? { ...col, baseColumnName: e.detail } : col));
} }
}} }}
/> />
@@ -292,7 +294,13 @@
type="button" type="button"
value="Add column" value="Add column"
on:click={() => { on:click={() => {
columns = [...columns, {}]; columns = [
...columns,
{
baseColumnName: '',
refColumnName: '',
},
];
}} }}
/> />
</div> </div>
@@ -301,20 +309,19 @@
<FormSubmit <FormSubmit
value={'Save'} value={'Save'}
on:click={async () => { on:click={async () => {
setConfig(cfg => ({ const newJoin = {
...cfg, joinid,
customJoins: [ joinName,
...(cfg.customJoins || []),
{
baseUniqueName: fromUniuqeName, baseUniqueName: fromUniuqeName,
refTableName, refTableName,
refSchemaName, refSchemaName,
columns: columns.map(col => ({ columns,
baseColumnName: col.columnName, };
refColumnName: col.refColumnName, setConfig(cfg => ({
})), ...cfg,
}, customJoins: editValue
], ? cfg.customJoins.map(x => (x.joinid == editValue.joinid ? newJoin : x))
: [...(cfg.customJoins || []), newJoin],
})); }));
closeCurrentModal(); closeCurrentModal();
}} }}

View File

@@ -1,14 +1,48 @@
<script lang="ts"> <script lang="ts">
import { PerspectiveTreeNode } from 'dbgate-datalib'; import { ChangePerspectiveConfigFunc, PerspectiveConfig, PerspectiveTreeNode } from 'dbgate-datalib';
import ColumnLabel from '../elements/ColumnLabel.svelte'; import ColumnLabel from '../elements/ColumnLabel.svelte';
import { plusExpandIcon } from '../icons/expandIcons'; import { plusExpandIcon } from '../icons/expandIcons';
import FontIcon from '../icons/FontIcon.svelte'; import FontIcon from '../icons/FontIcon.svelte';
import { showModal } from '../modals/modalTools';
import contextMenu from '../utility/contextMenu';
import CustomJoinModal from './CustomJoinModal.svelte';
export let conid;
export let database;
export let node: PerspectiveTreeNode; export let node: PerspectiveTreeNode;
export let root: PerspectiveTreeNode;
export let config: PerspectiveConfig;
export let setConfig: ChangePerspectiveConfigFunc;
function createMenu() {
const customJoin = node.customJoinConfig;
return [
customJoin && {
text: 'Remove custom join',
onClick: () =>
setConfig(cfg => ({
...cfg,
customJoins: (cfg.customJoins || []).filter(x => x.joinid != customJoin.joinid),
})),
},
customJoin && {
text: 'Edit custom join',
onClick: () =>
showModal(CustomJoinModal, {
config,
setConfig,
conid,
database,
root,
editValue: customJoin,
}),
},
];
}
</script> </script>
<div class="row"> <div class="row" use:contextMenu={createMenu}>
<span class="expandColumnIcon" style={`margin-right: ${5 + node.level * 10}px`}> <span class="expandColumnIcon" style={`margin-right: ${5 + node.level * 10}px`}>
<FontIcon <FontIcon
icon={node.isExpandable ? plusExpandIcon(node.isExpanded) : 'icon invisible-box'} icon={node.isExpandable ? plusExpandIcon(node.isExpanded) : 'icon invisible-box'}

View File

@@ -1,7 +1,13 @@
<script lang="ts"> <script lang="ts">
import { ChangeConfigFunc, ChangePerspectiveConfigFunc, GridConfig, PerspectiveConfig } from 'dbgate-datalib';
import PerspectiveNodeRow from './PerspectiveNodeRow.svelte'; import PerspectiveNodeRow from './PerspectiveNodeRow.svelte';
export let root; export let root;
export let config: PerspectiveConfig;
export let setConfig: ChangePerspectiveConfigFunc;
export let conid;
export let database;
function processFlatColumns(res, columns) { function processFlatColumns(res, columns) {
for (const col of columns) { for (const col of columns) {
@@ -20,5 +26,5 @@
</script> </script>
{#each getFlatColumns(root) as node} {#each getFlatColumns(root) as node}
<PerspectiveNodeRow {node} /> <PerspectiveNodeRow {node} {config} {setConfig} {root} {conid} {database} />
{/each} {/each}

View File

@@ -15,7 +15,11 @@
<script lang="ts"> <script lang="ts">
import { import {
ChangeConfigFunc,
ChangePerspectiveConfigFunc,
getTableChildPerspectiveNodes, getTableChildPerspectiveNodes,
GridConfig,
PerspectiveConfig,
PerspectiveDataLoadProps, PerspectiveDataLoadProps,
PerspectiveDataProvider, PerspectiveDataProvider,
PerspectiveTableColumnNode, PerspectiveTableColumnNode,
@@ -53,8 +57,8 @@
export let schemaName; export let schemaName;
export let pureName; export let pureName;
export let config; export let config: PerspectiveConfig;
export let setConfig; export let setConfig: ChangePerspectiveConfigFunc;
export let loadedCounts; export let loadedCounts;
export let cache; export let cache;
@@ -106,7 +110,7 @@
<WidgetColumnBarItem title="Choose data" name="perspectiveTree" height="45%"> <WidgetColumnBarItem title="Choose data" name="perspectiveTree" height="45%">
<ManagerInnerContainer width={managerSize}> <ManagerInnerContainer width={managerSize}>
{#if root} {#if root}
<PerspectiveTree {root} /> <PerspectiveTree {root} {config} {setConfig} {conid} {database} />
{/if} {/if}
</ManagerInnerContainer> </ManagerInnerContainer>
</WidgetColumnBarItem> </WidgetColumnBarItem>