mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-19 17:46:00 +00:00
dictionary descriptions saved to app
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
import { subscribeConnectionPingers } from './utility/connectionsPinger';
|
||||
import { subscribePermissionCompiler } from './utility/hasPermission';
|
||||
import { apiCall } from './utility/api';
|
||||
import { getUsedApps } from './utility/metadataLoaders';
|
||||
|
||||
let loadedApi = false;
|
||||
|
||||
@@ -30,7 +31,8 @@
|
||||
const settings = await apiCall('config/get-settings');
|
||||
const connections = await apiCall('connections/list');
|
||||
const config = await apiCall('config/get');
|
||||
loadedApi = settings && connections && config;
|
||||
const apps = await getUsedApps();
|
||||
loadedApi = settings && connections && config && apps;
|
||||
|
||||
if (loadedApi) {
|
||||
subscribeApiDependendStores();
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
<script lang="ts" context="module">
|
||||
export const extractKey = props => props.name;
|
||||
|
||||
export function filterAppsForDatabase(connection, database, $apps) {
|
||||
const db = (connection?.databases || []).find(x => x.name == database);
|
||||
return $apps.filter(app => db && db[`useApp:${app.name}`]);
|
||||
}
|
||||
|
||||
export function getDatabaseMenuItems(connection, name, $extensions, $currentDatabase, $apps) {
|
||||
const apps = filterAppsForDatabase(connection, name, $apps);
|
||||
const handleNewQuery = () => {
|
||||
@@ -244,6 +239,7 @@
|
||||
import { apiCall } from '../utility/api';
|
||||
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
|
||||
import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte';
|
||||
import { filterAppsForDatabase } from '../utility/appTools';
|
||||
|
||||
export let data;
|
||||
export let passProps;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import {
|
||||
useConnectionInfo,
|
||||
useConnectionList,
|
||||
useDatabaseInfo,
|
||||
useDatabaseServerVersion,
|
||||
useServerVersion,
|
||||
@@ -49,6 +50,7 @@
|
||||
$: serverVersion = useDatabaseServerVersion({ conid, database });
|
||||
$: apps = useUsedApps();
|
||||
$: extendedDbInfo = extendDatabaseInfoFromApps($dbinfo, $apps);
|
||||
$: connections = useConnectionList();
|
||||
|
||||
// $: console.log('serverVersion', $serverVersion);
|
||||
|
||||
@@ -70,7 +72,7 @@
|
||||
extendedDbInfo,
|
||||
{ showHintColumns: getBoolSettingsValue('dataGrid.showHintColumns', true) },
|
||||
$serverVersion,
|
||||
table => getDictionaryDescription(table, conid, database)
|
||||
table => getDictionaryDescription(table, conid, database, $apps, $connections)
|
||||
)
|
||||
: null;
|
||||
|
||||
@@ -86,7 +88,7 @@
|
||||
extendedDbInfo,
|
||||
{ showHintColumns: getBoolSettingsValue('dataGrid.showHintColumns', true) },
|
||||
$serverVersion,
|
||||
table => getDictionaryDescription(table, conid, database)
|
||||
table => getDictionaryDescription(table, conid, database, $apps, $connections)
|
||||
)
|
||||
: null;
|
||||
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
export let name;
|
||||
export let options;
|
||||
export let isClearable = false;
|
||||
export let selectFieldComponent = SelectField;
|
||||
|
||||
const { values, setFieldValue } = getFormContext();
|
||||
</script>
|
||||
|
||||
<SelectField
|
||||
<svelte:component
|
||||
this={selectFieldComponent}
|
||||
{...$$restProps}
|
||||
value={$values && $values[name]}
|
||||
options={_.compact(options)}
|
||||
|
||||
@@ -1,47 +1,22 @@
|
||||
<script lang="ts" context="module">
|
||||
export async function saveDbToApp(conid, database, app) {
|
||||
if (app == '#new') {
|
||||
const folder = await apiCall('apps/create-folder', { folder: database });
|
||||
|
||||
await apiCall('connections/update-database', {
|
||||
conid,
|
||||
database,
|
||||
values: {
|
||||
[`useApp:${folder}`]: true,
|
||||
},
|
||||
});
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
await apiCall('connections/update-database', {
|
||||
conid,
|
||||
database,
|
||||
values: {
|
||||
[`useApp:${app}`]: true,
|
||||
},
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import _ from 'lodash';
|
||||
import { filterAppsForDatabase } from '../appobj/DatabaseAppObject.svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
import SelectField from '../forms/SelectField.svelte';
|
||||
import { currentDatabase } from '../stores';
|
||||
import { apiCall } from '../utility/api';
|
||||
import { filterAppsForDatabase } from '../utility/appTools';
|
||||
import { useAppFolders, useUsedApps } from '../utility/metadataLoaders';
|
||||
|
||||
export let value = '#new';
|
||||
export let disableInitialize = false;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
$: appFolders = useAppFolders();
|
||||
$: usedApps = useUsedApps();
|
||||
|
||||
$: {
|
||||
if (value == '#new' && $currentDatabase) {
|
||||
if (!disableInitialize && value == '#new' && $currentDatabase) {
|
||||
const filtered = filterAppsForDatabase($currentDatabase.connection, $currentDatabase.name, $usedApps || []);
|
||||
const common = _.intersection(
|
||||
($appFolders || []).map(x => x.name),
|
||||
@@ -49,6 +24,7 @@
|
||||
);
|
||||
if (common.length > 0) {
|
||||
value = common[0] as string;
|
||||
dispatch('change', value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,6 +36,7 @@
|
||||
{value}
|
||||
on:change={e => {
|
||||
value = e.detail;
|
||||
dispatch('change', value);
|
||||
}}
|
||||
options={[
|
||||
{ label: '(New application linked to current DB)', value: '#new' },
|
||||
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import FormProvider from '../forms/FormProvider.svelte';
|
||||
import _ from 'lodash';
|
||||
import FormSubmit from '../forms/FormSubmit.svelte';
|
||||
import FormStyledButton from '../elements/FormStyledButton.svelte';
|
||||
import ModalBase from './ModalBase.svelte';
|
||||
import { closeCurrentModal } from './modalTools';
|
||||
import { useTableInfo } from '../utility/metadataLoaders';
|
||||
import { useAppFolders, useConnectionList, useTableInfo, useUsedApps } from '../utility/metadataLoaders';
|
||||
import TableControl from '../elements/TableControl.svelte';
|
||||
import TextField from '../forms/TextField.svelte';
|
||||
import FormTextField from '../forms/FormTextField.svelte';
|
||||
@@ -19,6 +20,10 @@
|
||||
} from '../utility/dictionaryDescriptionTools';
|
||||
import { includes } from 'lodash';
|
||||
import FormCheckboxField from '../forms/FormCheckboxField.svelte';
|
||||
import FormSelectField from '../forms/FormSelectField.svelte';
|
||||
import TargetApplicationSelect from '../forms/TargetApplicationSelect.svelte';
|
||||
import { currentDatabase } from '../stores';
|
||||
import { filterAppsForDatabase } from '../utility/appTools';
|
||||
|
||||
export let conid;
|
||||
export let database;
|
||||
@@ -28,18 +33,41 @@
|
||||
|
||||
$: tableInfo = useTableInfo({ conid, database, schemaName, pureName });
|
||||
|
||||
$: descriptionInfo = getDictionaryDescription($tableInfo, conid, database, true);
|
||||
$: apps = useUsedApps();
|
||||
$: appFolders = useAppFolders();
|
||||
$: connections = useConnectionList();
|
||||
|
||||
const values = writable({});
|
||||
$: descriptionInfo = getDictionaryDescription($tableInfo, conid, database, $apps, $connections, true);
|
||||
|
||||
const values = writable({ targetApplication: '#new' } as any);
|
||||
|
||||
function initValues(descriptionInfo) {
|
||||
$values = {
|
||||
targetApplication: $values.targetApplication,
|
||||
columns: descriptionInfo.expression,
|
||||
delimiter: descriptionInfo.delimiter,
|
||||
};
|
||||
}
|
||||
|
||||
$: if (descriptionInfo) initValues(descriptionInfo);
|
||||
$: {
|
||||
if (descriptionInfo) initValues(descriptionInfo);
|
||||
}
|
||||
|
||||
$: {
|
||||
if ($values.targetApplication == '#new' && $currentDatabase) {
|
||||
const filtered = filterAppsForDatabase($currentDatabase.connection, $currentDatabase.name, $apps || []);
|
||||
const common = _.intersection(
|
||||
($appFolders || []).map(x => x.name),
|
||||
filtered.map(x => x.name)
|
||||
);
|
||||
if (common.length > 0) {
|
||||
$values = {
|
||||
...$values,
|
||||
targetApplication: common[0],
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<FormProviderCore {values}>
|
||||
@@ -75,7 +103,14 @@
|
||||
|
||||
<FormTextField name="delimiter" label="Delimiter" />
|
||||
|
||||
<FormCheckboxField name="useForAllDatabases" label="Use for all databases" />
|
||||
<FormSelectField
|
||||
label="Target application"
|
||||
name="targetApplication"
|
||||
disableInitialize
|
||||
selectFieldComponent={TargetApplicationSelect}
|
||||
/>
|
||||
|
||||
<!-- <FormCheckboxField name="useForAllDatabases" label="Use for all databases" /> -->
|
||||
|
||||
<svelte:fragment slot="footer">
|
||||
<FormSubmit
|
||||
@@ -89,7 +124,7 @@
|
||||
database,
|
||||
$values.columns,
|
||||
$values.delimiter,
|
||||
$values.useForAllDatabases
|
||||
$values.targetApplication
|
||||
);
|
||||
onConfirm();
|
||||
}}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { closeCurrentModal, showModal } from './modalTools';
|
||||
import DefineDictionaryDescriptionModal from './DefineDictionaryDescriptionModal.svelte';
|
||||
import ScrollableTableControl from '../elements/ScrollableTableControl.svelte';
|
||||
import { getTableInfo } from '../utility/metadataLoaders';
|
||||
import { getTableInfo, useConnectionList, useUsedApps } from '../utility/metadataLoaders';
|
||||
import { getDictionaryDescription } from '../utility/dictionaryDescriptionTools';
|
||||
import { onMount } from 'svelte';
|
||||
import { dumpSqlSelect } from 'dbgate-sqltree';
|
||||
@@ -33,6 +33,9 @@
|
||||
|
||||
let checkedKeys = [];
|
||||
|
||||
$: apps = useUsedApps();
|
||||
$: connections = useConnectionList();
|
||||
|
||||
function defineDescription() {
|
||||
showModal(DefineDictionaryDescriptionModal, {
|
||||
conid,
|
||||
@@ -45,7 +48,7 @@
|
||||
|
||||
async function reload() {
|
||||
tableInfo = await getTableInfo({ conid, database, schemaName, pureName });
|
||||
description = getDictionaryDescription(tableInfo, conid, database);
|
||||
description = getDictionaryDescription(tableInfo, conid, database, $apps, $connections);
|
||||
|
||||
if (!tableInfo || !description) return;
|
||||
if (tableInfo?.primaryKey?.columns?.length != 1) return;
|
||||
@@ -112,6 +115,8 @@
|
||||
|
||||
$: {
|
||||
search;
|
||||
$apps;
|
||||
$connections;
|
||||
reload();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
import _ from 'lodash';
|
||||
import { useDatabaseInfo, useTableInfo } from '../utility/metadataLoaders';
|
||||
import { onMount } from 'svelte';
|
||||
import TargetApplicationSelect, { saveDbToApp } from '../elements/TargetApplicationSelect.svelte';
|
||||
import TargetApplicationSelect from '../forms/TargetApplicationSelect.svelte';
|
||||
import { apiCall } from '../utility/api';
|
||||
import { saveDbToApp } from '../utility/appTools';
|
||||
|
||||
export let conid;
|
||||
export let database;
|
||||
@@ -155,7 +156,7 @@
|
||||
value={'Save'}
|
||||
on:click={async () => {
|
||||
const appFolder = await saveDbToApp(conid, database, dstApp);
|
||||
await apiCall('apps/save-vfk', {
|
||||
await apiCall('apps/save-virtual-reference', {
|
||||
appFolder,
|
||||
schemaName,
|
||||
pureName,
|
||||
|
||||
33
packages/web/src/utility/appTools.ts
Normal file
33
packages/web/src/utility/appTools.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { ApplicationDefinition, StoredConnection } from 'dbgate-types';
|
||||
import { apiCall } from '../utility/api';
|
||||
|
||||
export async function saveDbToApp(conid: string, database: string, app: string) {
|
||||
if (app == '#new') {
|
||||
const folder = await apiCall('apps/create-folder', { folder: database });
|
||||
|
||||
await apiCall('connections/update-database', {
|
||||
conid,
|
||||
database,
|
||||
values: {
|
||||
[`useApp:${folder}`]: true,
|
||||
},
|
||||
});
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
await apiCall('connections/update-database', {
|
||||
conid,
|
||||
database,
|
||||
values: {
|
||||
[`useApp:${app}`]: true,
|
||||
},
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
export function filterAppsForDatabase(connection, database: string, $apps): ApplicationDefinition[] {
|
||||
const db = (connection?.databases || []).find(x => x.name == database);
|
||||
return $apps.filter(app => db && db[`useApp:${app.name}`]);
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
import { DictionaryDescription } from 'dbgate-datalib';
|
||||
import { TableInfo } from 'dbgate-types';
|
||||
import { ApplicationDefinition, TableInfo } from 'dbgate-types';
|
||||
import _ from 'lodash';
|
||||
import { getLocalStorage, setLocalStorage, removeLocalStorage } from './storageCache';
|
||||
import { apiCall } from './api';
|
||||
import { filterAppsForDatabase, saveDbToApp } from './appTools';
|
||||
|
||||
function checkDescriptionColumns(columns: string[], table: TableInfo) {
|
||||
if (!columns?.length) return false;
|
||||
@@ -14,17 +15,20 @@ export function getDictionaryDescription(
|
||||
table: TableInfo,
|
||||
conid: string,
|
||||
database: string,
|
||||
apps: ApplicationDefinition[],
|
||||
connections,
|
||||
skipCheckSaved: boolean = false
|
||||
): DictionaryDescription {
|
||||
const keySpecific = `dictionary_spec_${table.schemaName}||${table.pureName}||${conid}||${database}`;
|
||||
const keyCommon = `dictionary_spec_${table.schemaName}||${table.pureName}`;
|
||||
const conn = connections.find(x => x._id == conid);
|
||||
const dbApps = filterAppsForDatabase(conn, database, apps);
|
||||
|
||||
const cachedSpecific = getLocalStorage(keySpecific);
|
||||
const cachedCommon = getLocalStorage(keyCommon);
|
||||
const cached = _.flatten(dbApps.map(x => x.dictionaryDescriptions || [])).find(
|
||||
x => x.pureName == table.pureName && x.schemaName == table.schemaName
|
||||
);
|
||||
|
||||
if (cachedSpecific && (skipCheckSaved || checkDescriptionColumns(cachedSpecific.columns, table)))
|
||||
return cachedSpecific;
|
||||
if (cachedCommon && (skipCheckSaved || checkDescriptionColumns(cachedCommon.columns, table))) return cachedCommon;
|
||||
if (cached && (skipCheckSaved || checkDescriptionColumns(cached.columns, table))) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
const descColumn = table.columns.find(x => x?.dataType?.toLowerCase()?.includes('char'));
|
||||
if (descColumn) {
|
||||
@@ -57,29 +61,22 @@ export function changeDelimitedColumnList(columns, columnName, isChecked) {
|
||||
return parsed.join(',');
|
||||
}
|
||||
|
||||
export function saveDictionaryDescription(
|
||||
export async function saveDictionaryDescription(
|
||||
table: TableInfo,
|
||||
conid: string,
|
||||
database: string,
|
||||
expression: string,
|
||||
delimiter: string,
|
||||
useForAllDatabases: boolean
|
||||
targetApplication: string
|
||||
) {
|
||||
const keySpecific = `dictionary_spec_${table.schemaName}||${table.pureName}||${conid}||${database}`;
|
||||
const keyCommon = `dictionary_spec_${table.schemaName}||${table.pureName}`;
|
||||
const appFolder = await saveDbToApp(conid, database, targetApplication);
|
||||
|
||||
removeLocalStorage(keySpecific);
|
||||
if (useForAllDatabases) removeLocalStorage(keyCommon);
|
||||
|
||||
const description = {
|
||||
await apiCall('apps/save-dictionary-description', {
|
||||
appFolder,
|
||||
schemaName: table.schemaName,
|
||||
pureName: table.pureName,
|
||||
columns: parseDelimitedColumnList(expression),
|
||||
expression,
|
||||
delimiter,
|
||||
};
|
||||
|
||||
if (useForAllDatabases) {
|
||||
setLocalStorage(keyCommon, description);
|
||||
} else {
|
||||
setLocalStorage(keySpecific, description);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user