mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-29 22:43:58 +00:00
custom join dialog
This commit is contained in:
@@ -4,6 +4,19 @@ export interface PerspectiveConfigColumns {
|
|||||||
uncheckedColumns: string[];
|
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 {
|
export interface PerspectiveConfig extends PerspectiveConfigColumns {
|
||||||
filters: { [uniqueName: string]: string };
|
filters: { [uniqueName: string]: string };
|
||||||
sort: {
|
sort: {
|
||||||
@@ -12,6 +25,7 @@ export interface PerspectiveConfig extends PerspectiveConfigColumns {
|
|||||||
order: 'ASC' | 'DESC';
|
order: 'ASC' | 'DESC';
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
|
customJoins: PerspectiveCustomJoinConfig[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createPerspectiveConfig(): PerspectiveConfig {
|
export function createPerspectiveConfig(): PerspectiveConfig {
|
||||||
@@ -19,6 +33,7 @@ export function createPerspectiveConfig(): PerspectiveConfig {
|
|||||||
expandedColumns: [],
|
expandedColumns: [],
|
||||||
checkedColumns: [],
|
checkedColumns: [],
|
||||||
uncheckedColumns: [],
|
uncheckedColumns: [],
|
||||||
|
customJoins: [],
|
||||||
filters: {},
|
filters: {},
|
||||||
sort: {},
|
sort: {},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -203,6 +203,20 @@ export abstract class PerspectiveTreeNode {
|
|||||||
{ columnName: table?.columns[0].columnName, order: 'ASC' },
|
{ 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 {
|
export class PerspectiveTableColumnNode extends PerspectiveTreeNode {
|
||||||
@@ -311,6 +325,10 @@ export class PerspectiveTableColumnNode extends PerspectiveTreeNode {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBaseTableFromThis() {
|
||||||
|
return this.refTable;
|
||||||
|
}
|
||||||
|
|
||||||
parseFilterCondition() {
|
parseFilterCondition() {
|
||||||
const filter = this.getFilter();
|
const filter = this.getFilter();
|
||||||
if (!filter) return null;
|
if (!filter) return null;
|
||||||
@@ -380,6 +398,10 @@ export class PerspectiveTableNode extends PerspectiveTreeNode {
|
|||||||
get icon() {
|
get icon() {
|
||||||
return 'img table';
|
return 'img table';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBaseTableFromThis() {
|
||||||
|
return this.table;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PerspectiveViewNode extends PerspectiveTreeNode {
|
export class PerspectiveViewNode extends PerspectiveTreeNode {
|
||||||
@@ -433,6 +455,10 @@ export class PerspectiveViewNode extends PerspectiveTreeNode {
|
|||||||
get icon() {
|
get icon() {
|
||||||
return 'img table';
|
return 'img table';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBaseTableFromThis() {
|
||||||
|
return this.view;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PerspectiveTableReferenceNode extends PerspectiveTableNode {
|
export class PerspectiveTableReferenceNode extends PerspectiveTableNode {
|
||||||
|
|||||||
@@ -94,6 +94,7 @@
|
|||||||
'icon add': 'mdi mdi-plus-circle',
|
'icon add': 'mdi mdi-plus-circle',
|
||||||
'icon json': 'mdi mdi-code-json',
|
'icon json': 'mdi mdi-code-json',
|
||||||
'icon lock': 'mdi mdi-lock',
|
'icon lock': 'mdi mdi-lock',
|
||||||
|
'icon custom-join': 'mdi mdi-arrow-left-right-bold',
|
||||||
|
|
||||||
'icon run': 'mdi mdi-play',
|
'icon run': 'mdi mdi-play',
|
||||||
'icon chevron-down': 'mdi mdi-chevron-down',
|
'icon chevron-down': 'mdi mdi-chevron-down',
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
...(allowChooseModel ? [{ label: '(DB Model)', value: '__model' }] : []),
|
...(allowChooseModel ? [{ label: '(DB Model)', value: '__model' }] : []),
|
||||||
..._.sortBy(
|
..._.sortBy(
|
||||||
($connections || [])
|
($connections || [])
|
||||||
.filter(conn => (direction == 'target' ? !conn.isReadOnly : true))
|
.filter(conn => !conn.unsaved && (direction == 'target' ? !conn.isReadOnly : true))
|
||||||
.map(conn => ({
|
.map(conn => ({
|
||||||
value: conn._id,
|
value: conn._id,
|
||||||
label: getConnectionLabel(conn),
|
label: getConnectionLabel(conn),
|
||||||
|
|||||||
343
packages/web/src/perspectives/CustomJoinModal.svelte
Normal file
343
packages/web/src/perspectives/CustomJoinModal.svelte
Normal 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>
|
||||||
@@ -155,6 +155,9 @@
|
|||||||
{
|
{
|
||||||
command: 'perspective.openJson',
|
command: 'perspective.openJson',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
command: 'perspective.customJoin',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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">
|
<script lang="ts">
|
||||||
import {
|
import {
|
||||||
getTableChildPerspectiveNodes,
|
getTableChildPerspectiveNodes,
|
||||||
@@ -26,6 +41,10 @@
|
|||||||
import stableStringify from 'json-stable-stringify';
|
import stableStringify from 'json-stable-stringify';
|
||||||
import createRef from '../utility/createRef';
|
import createRef from '../utility/createRef';
|
||||||
import { tick } from 'svelte';
|
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');
|
const dbg = debug('dbgate:PerspectiveView');
|
||||||
|
|
||||||
@@ -43,6 +62,8 @@
|
|||||||
let managerSize;
|
let managerSize;
|
||||||
let nextCacheRef = createRef(null);
|
let nextCacheRef = createRef(null);
|
||||||
|
|
||||||
|
export const activator = createActivator('PerspectiveView', true);
|
||||||
|
|
||||||
$: if (managerSize) setLocalStorage('perspectiveManagerWidth', managerSize);
|
$: if (managerSize) setLocalStorage('perspectiveManagerWidth', managerSize);
|
||||||
|
|
||||||
function getInitialManagerSize() {
|
function getInitialManagerSize() {
|
||||||
@@ -53,6 +74,17 @@
|
|||||||
return '300px';
|
return '300px';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function defineCustomJoin() {
|
||||||
|
if (!root) return;
|
||||||
|
showModal(CustomJoinModal, {
|
||||||
|
config,
|
||||||
|
setConfig,
|
||||||
|
conid,
|
||||||
|
database,
|
||||||
|
root,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const dbInfo = useDatabaseInfo({ conid, database });
|
const dbInfo = useDatabaseInfo({ conid, database });
|
||||||
const tableInfo = useTableInfo({ conid, database, schemaName, pureName });
|
const tableInfo = useTableInfo({ conid, database, schemaName, pureName });
|
||||||
const viewInfo = useViewInfo({ conid, database, schemaName, pureName });
|
const viewInfo = useViewInfo({ conid, database, schemaName, pureName });
|
||||||
|
|||||||
@@ -65,5 +65,6 @@
|
|||||||
|
|
||||||
<svelte:fragment slot="toolstrip">
|
<svelte:fragment slot="toolstrip">
|
||||||
<ToolStripCommandButton command="perspective.refresh" />
|
<ToolStripCommandButton command="perspective.refresh" />
|
||||||
|
<ToolStripCommandButton command="perspective.customJoin" />
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</ToolStripContainer>
|
</ToolStripContainer>
|
||||||
|
|||||||
Reference in New Issue
Block a user