custom join dialog

This commit is contained in:
Jan Prochazka
2022-07-31 20:09:48 +02:00
parent 2b4120435b
commit 091e91556d
8 changed files with 422 additions and 1 deletions

View File

@@ -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',

View File

@@ -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),

View File

@@ -0,0 +1,343 @@
<script lang="ts">
import FormStyledButton from '../buttons/FormStyledButton.svelte';
import FormProvider from '../forms/FormProvider.svelte';
import FormSubmit from '../forms/FormSubmit.svelte';
import ModalBase from '../modals/ModalBase.svelte';
import { closeCurrentModal } from '../modals/modalTools';
import { fullNameFromString, fullNameToLabel, fullNameToString } from 'dbgate-tools';
import SelectField from '../forms/SelectField.svelte';
import _ from 'lodash';
import { useConnectionList, useDatabaseInfo, useDatabaseList, useTableInfo } from '../utility/metadataLoaders';
import { onMount, tick } from 'svelte';
import TargetApplicationSelect from '../forms/TargetApplicationSelect.svelte';
import { apiCall } from '../utility/api';
import { saveDbToApp } from '../utility/appTools';
import { ChangePerspectiveConfigFunc, PerspectiveConfig, PerspectiveTreeNode } from 'dbgate-datalib';
import FormConnectionSelect from '../impexp/FormConnectionSelect.svelte';
import FormDatabaseSelect from '../impexp/FormDatabaseSelect.svelte';
import getConnectionLabel from '../utility/getConnectionLabel';
import uuidv1 from 'uuid/v1';
import TextField from '../forms/TextField.svelte';
export let conid;
export let database;
export let root: PerspectiveTreeNode;
export let setConfig: ChangePerspectiveConfigFunc;
export let config: PerspectiveConfig;
let conidOverride = null;
let databaseOverride = null;
let joinid = uuidv1();
$: fromDbInfo = useDatabaseInfo({
conid,
database,
});
// $: fromTableInfo = useTableInfo({
// conid: conidOverride || conid,
// database: databaseOverride || database,
// schemaName: fromSchemaName,
// pureName: fromTableName,
// });
$: refDbInfo = useDatabaseInfo({
conid: conidOverride || conid,
database: databaseOverride || database,
});
$: refTableInfo = useTableInfo({
conid: conidOverride || conid,
database: databaseOverride || database,
schemaName: refSchemaName,
pureName: refTableName,
});
let columns = [];
// let fromTableName = pureName;
// let fromSchemaName = schemaName;
let fromUniuqeName = root.uniqueName;
let refTableName = null;
let refSchemaName = null;
let joinName;
onMount(() => {
let index = 1;
while (config.customJoins?.find(x => x.joinName == `Custom join ${index}`)) {
index += 1;
}
joinName = `Custom join ${index}`;
});
// $: fromTableList = [
// ..._.sortBy($fromDbInfo?.tables || [], ['schemaName', 'pureName']),
// // ..._.sortBy($dbInfo?.views || [], ['schemaName', 'pureName']),
// ];
$: refTableList = [
..._.sortBy($refDbInfo?.tables || [], ['schemaName', 'pureName']),
// ..._.sortBy($dbInfo?.views || [], ['schemaName', 'pureName']),
];
let refTableOptions = [];
let fromTableOptions = [];
$: connections = useConnectionList();
$: connectionOptions = [
{ value: null, label: 'The same as root' },
..._.sortBy(
($connections || [])
.filter(x => !x.unsaved)
.map(conn => ({
value: conn._id,
label: getConnectionLabel(conn),
})),
'label'
),
];
// $: fromTable = $fromDbInfo?.tables?.find(x => x.pureName == fromTableName && x.schemaName == fromSchemaName);
$: databases = useDatabaseList({ conid: conidOverride || conid });
$: databaseOptions = [
{ value: null, label: 'The same as root' },
..._.sortBy(
($databases || []).map(db => ({
value: db.name,
label: db.name,
})),
'label'
),
];
$: fromTableList = root.getBaseTables();
$: fromTableInfo = fromTableList?.find(x => x.node.uniqueName == fromUniuqeName)?.table;
$: (async () => {
// without this has svelte problem, doesn't invalidate SelectField options
await tick();
// to replicate try to invoke VFK editor after page refresh, when active widget without DB, eg. application layers
// and comment line above. Tables list in vFK editor will be empty
fromTableOptions = fromTableList.map(tbl => ({
label: fullNameToLabel(tbl.table),
value: tbl.node.uniqueName,
}));
refTableOptions = refTableList.map(tbl => ({
label: fullNameToLabel(tbl),
value: fullNameToString(tbl),
}));
})();
// $: refTableInfo = tableList.find(x => x.pureName == refTableName && x.schemaName == refSchemaName);
// $dbInfo?.views?.find(x => x.pureName == refTableName && x.schemaName == refSchemaName);
// $: console.log('conid, database', conid, database);
// $: console.log('$dbInfo?.tables', $dbInfo?.tables);
// $: console.log('tableList', tableList);
// $: console.log('tableOptions', tableOptions);
</script>
<FormProvider>
<ModalBase {...$$restProps}>
<svelte:fragment slot="header">Define custom join</svelte:fragment>
<div class="largeFormMarker">
<div class="row">
<div class="label col-3">Join name</div>
<div class="col-9">
<TextField
value={joinName}
options={fromTableOptions}
on:change={e => {
joinName = e.target['value'];
}}
/>
</div>
</div>
<div class="row">
<div class="label col-3">Base table</div>
<div class="col-9">
<SelectField
value={fromUniuqeName}
isNative
notSelected
options={fromTableOptions}
on:change={e => {
if (e.detail) {
fromUniuqeName = e.detail;
}
}}
/>
</div>
</div>
<div class="row">
<div class="label col-3">Connection</div>
<div class="col-9">
<SelectField
value={conidOverride}
isNative
options={connectionOptions}
on:change={e => {
conidOverride = e.detail;
}}
/>
</div>
</div>
<div class="row">
<div class="label col-3">Database</div>
<div class="col-9">
<SelectField
value={databaseOverride}
isNative
options={databaseOptions}
on:change={e => {
databaseOverride = e.detail;
}}
/>
</div>
</div>
<!-- <FormConnectionSelect name="conid" label="Server" {direction} />
<FormDatabaseSelect conidName={connectionIdField} name={databaseNameField} label="Database" /> -->
<div class="row">
<div class="label col-3">Referenced table</div>
<div class="col-9">
<SelectField
value={fullNameToString({ pureName: refTableName, schemaName: refSchemaName })}
isNative
notSelected
options={refTableOptions}
on:change={e => {
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,
}));
}
}}
/>
</div>
</div>
<div class="row">
<div class="col-5 mr-1">
Base column - {fromTableInfo?.pureName}
</div>
<div class="col-5 ml-1">
Ref column - {refTableName || '(table not set)'}
</div>
</div>
{#each columns as column, index}
<div class="row">
<div class="col-5 mr-1">
{#key column.columnName}
<SelectField
value={column.columnName}
isNative
notSelected
options={(fromTableInfo?.columns || []).map(col => ({
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}
</div>
<div class="col-5 ml-1">
{#key column.refColumnName}
<SelectField
value={column.refColumnName}
isNative
notSelected
options={($refTableInfo?.columns || []).map(col => ({
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}
</div>
<div class="col-2 button">
<FormStyledButton
value="Delete"
on:click={e => {
const x = [...columns];
x.splice(index, 1);
columns = x;
}}
/>
</div>
</div>
{/each}
<FormStyledButton
type="button"
value="Add column"
on:click={() => {
columns = [...columns, {}];
}}
/>
</div>
<svelte:fragment slot="footer">
<FormSubmit
value={'Save'}
on:click={async () => {
setConfig(cfg => ({
...cfg,
customJoins: [
...(cfg.customJoins || []),
{
baseUniqueName: fromUniuqeName,
refTableName,
refSchemaName,
columns: columns.map(col => ({
baseColumnName: col.columnName,
refColumnName: col.refColumnName,
})),
},
],
}));
closeCurrentModal();
}}
/>
<FormStyledButton type="button" value="Close" on:click={closeCurrentModal} />
</svelte:fragment>
</ModalBase>
</FormProvider>
<style>
.row {
margin: var(--dim-large-form-margin);
display: flex;
}
.row .label {
white-space: nowrap;
align-self: center;
}
.button {
align-self: center;
text-align: right;
}
</style>

View File

@@ -155,6 +155,9 @@
{
command: 'perspective.openJson',
},
{
command: 'perspective.customJoin',
},
];
}

View File

@@ -1,3 +1,18 @@
<script lang="ts" context="module">
const getCurrentEditor = () => getActiveComponent('PerspectiveView');
registerCommand({
id: 'perspective.customJoin',
category: 'Perspective',
name: 'Custom join',
keyText: 'CtrlOrCommand+J',
isRelatedToTab: true,
icon: 'icon custom-join',
testEnabled: () => getCurrentEditor() != null,
onClick: () => getCurrentEditor().defineCustomJoin(),
});
</script>
<script lang="ts">
import {
getTableChildPerspectiveNodes,
@@ -26,6 +41,10 @@
import stableStringify from 'json-stable-stringify';
import createRef from '../utility/createRef';
import { tick } from 'svelte';
import createActivator, { getActiveComponent } from '../utility/createActivator';
import registerCommand from '../commands/registerCommand';
import { showModal } from '../modals/modalTools';
import CustomJoinModal from './CustomJoinModal.svelte';
const dbg = debug('dbgate:PerspectiveView');
@@ -43,6 +62,8 @@
let managerSize;
let nextCacheRef = createRef(null);
export const activator = createActivator('PerspectiveView', true);
$: if (managerSize) setLocalStorage('perspectiveManagerWidth', managerSize);
function getInitialManagerSize() {
@@ -53,6 +74,17 @@
return '300px';
}
export function defineCustomJoin() {
if (!root) return;
showModal(CustomJoinModal, {
config,
setConfig,
conid,
database,
root,
});
}
const dbInfo = useDatabaseInfo({ conid, database });
const tableInfo = useTableInfo({ conid, database, schemaName, pureName });
const viewInfo = useViewInfo({ conid, database, schemaName, pureName });

View File

@@ -65,5 +65,6 @@
<svelte:fragment slot="toolstrip">
<ToolStripCommandButton command="perspective.refresh" />
<ToolStripCommandButton command="perspective.customJoin" />
</svelte:fragment>
</ToolStripContainer>