mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-29 20:23:59 +00:00
configurable dictionary description
This commit is contained in:
@@ -29,7 +29,7 @@ export interface DisplayColumn {
|
|||||||
foreignKey?: ForeignKeyInfo;
|
foreignKey?: ForeignKeyInfo;
|
||||||
isExpandable?: boolean;
|
isExpandable?: boolean;
|
||||||
isChecked?: boolean;
|
isChecked?: boolean;
|
||||||
hintColumnName?: string;
|
hintColumnNames?: string[];
|
||||||
dataType?: string;
|
dataType?: string;
|
||||||
filterType?: boolean;
|
filterType?: boolean;
|
||||||
isStructured?: boolean;
|
isStructured?: boolean;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
import { TableGridDisplay } from './TableGridDisplay';
|
import { TableGridDisplay } from './TableGridDisplay';
|
||||||
import stableStringify from 'json-stable-stringify';
|
import stableStringify from 'json-stable-stringify';
|
||||||
import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet';
|
import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet';
|
||||||
|
import { DictionaryDescriptionFunc } from '.';
|
||||||
|
|
||||||
export class TableFormViewDisplay extends FormViewDisplay {
|
export class TableFormViewDisplay extends FormViewDisplay {
|
||||||
// use utility functions from GridDisplay and publish result in FromViewDisplay interface
|
// use utility functions from GridDisplay and publish result in FromViewDisplay interface
|
||||||
@@ -29,7 +30,8 @@ export class TableFormViewDisplay extends FormViewDisplay {
|
|||||||
setCache: ChangeCacheFunc,
|
setCache: ChangeCacheFunc,
|
||||||
dbinfo: DatabaseInfo,
|
dbinfo: DatabaseInfo,
|
||||||
displayOptions,
|
displayOptions,
|
||||||
serverVersion
|
serverVersion,
|
||||||
|
getDictionaryDescription: DictionaryDescriptionFunc = null
|
||||||
) {
|
) {
|
||||||
super(config, setConfig, cache, setCache, driver, dbinfo, serverVersion);
|
super(config, setConfig, cache, setCache, driver, dbinfo, serverVersion);
|
||||||
this.gridDisplay = new TableGridDisplay(
|
this.gridDisplay = new TableGridDisplay(
|
||||||
@@ -41,7 +43,8 @@ export class TableFormViewDisplay extends FormViewDisplay {
|
|||||||
setCache,
|
setCache,
|
||||||
dbinfo,
|
dbinfo,
|
||||||
displayOptions,
|
displayOptions,
|
||||||
serverVersion
|
serverVersion,
|
||||||
|
getDictionaryDescription
|
||||||
);
|
);
|
||||||
this.gridDisplay.addAllExpandedColumnsToSelected = true;
|
this.gridDisplay.addAllExpandedColumnsToSelected = true;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,25 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { filterName } from 'dbgate-tools';
|
import { filterName } from 'dbgate-tools';
|
||||||
import { GridDisplay, ChangeCacheFunc, DisplayColumn, DisplayedColumnInfo, ChangeConfigFunc } from './GridDisplay';
|
import { GridDisplay, ChangeCacheFunc, DisplayColumn, DisplayedColumnInfo, ChangeConfigFunc } from './GridDisplay';
|
||||||
import { TableInfo, EngineDriver, ViewInfo, ColumnInfo, NamedObjectInfo, DatabaseInfo } from 'dbgate-types';
|
import {
|
||||||
|
TableInfo,
|
||||||
|
EngineDriver,
|
||||||
|
ViewInfo,
|
||||||
|
ColumnInfo,
|
||||||
|
NamedObjectInfo,
|
||||||
|
DatabaseInfo,
|
||||||
|
ForeignKeyInfo,
|
||||||
|
} from 'dbgate-types';
|
||||||
import { GridConfig, GridCache, createGridCache } from './GridConfig';
|
import { GridConfig, GridCache, createGridCache } from './GridConfig';
|
||||||
import { Expression, Select, treeToSql, dumpSqlSelect } from 'dbgate-sqltree';
|
import { Expression, Select, treeToSql, dumpSqlSelect, ColumnRefExpression } from 'dbgate-sqltree';
|
||||||
|
|
||||||
|
export interface DictionaryDescription {
|
||||||
|
expression: string;
|
||||||
|
columns: string[];
|
||||||
|
delimiter: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DictionaryDescriptionFunc = (table: TableInfo) => DictionaryDescription;
|
||||||
|
|
||||||
export class TableGridDisplay extends GridDisplay {
|
export class TableGridDisplay extends GridDisplay {
|
||||||
public table: TableInfo;
|
public table: TableInfo;
|
||||||
@@ -19,7 +35,8 @@ export class TableGridDisplay extends GridDisplay {
|
|||||||
setCache: ChangeCacheFunc,
|
setCache: ChangeCacheFunc,
|
||||||
dbinfo: DatabaseInfo,
|
dbinfo: DatabaseInfo,
|
||||||
public displayOptions: any,
|
public displayOptions: any,
|
||||||
serverVersion
|
serverVersion,
|
||||||
|
public getDictionaryDescription: DictionaryDescriptionFunc = null
|
||||||
) {
|
) {
|
||||||
super(config, setConfig, cache, setCache, driver, dbinfo, serverVersion);
|
super(config, setConfig, cache, setCache, driver, dbinfo, serverVersion);
|
||||||
|
|
||||||
@@ -61,7 +78,11 @@ export class TableGridDisplay extends GridDisplay {
|
|||||||
?.map(col => ({
|
?.map(col => ({
|
||||||
...col,
|
...col,
|
||||||
isChecked: this.isColumnChecked(col),
|
isChecked: this.isColumnChecked(col),
|
||||||
hintColumnName: col.foreignKey ? `hint_${col.uniqueName}` : null,
|
hintColumnNames:
|
||||||
|
this.getFkDictionaryDescription(col.foreignKey)?.columns?.map(
|
||||||
|
columnName => `hint_${col.uniqueName}_${columnName}`
|
||||||
|
) || null,
|
||||||
|
hintColumnDelimiter: this.getFkDictionaryDescription(col.foreignKey)?.delimiter,
|
||||||
isExpandable: !!col.foreignKey,
|
isExpandable: !!col.foreignKey,
|
||||||
})) || []
|
})) || []
|
||||||
);
|
);
|
||||||
@@ -116,6 +137,19 @@ export class TableGridDisplay extends GridDisplay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFkDictionaryDescription(foreignKey: ForeignKeyInfo) {
|
||||||
|
if (!foreignKey) return null;
|
||||||
|
const pureName = foreignKey.refTableName;
|
||||||
|
const schemaName = foreignKey.refSchemaName;
|
||||||
|
const table = this.findTable({ schemaName, pureName });
|
||||||
|
|
||||||
|
if (table && table.columns && table.columns.length > 0 && table.primaryKey) {
|
||||||
|
const hintDescription = this.getDictionaryDescription(table);
|
||||||
|
return hintDescription;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
addHintsToSelect(select: Select): boolean {
|
addHintsToSelect(select: Select): boolean {
|
||||||
let res = false;
|
let res = false;
|
||||||
const groupColumns = this.groupColumns;
|
const groupColumns = this.groupColumns;
|
||||||
@@ -126,17 +160,23 @@ export class TableGridDisplay extends GridDisplay {
|
|||||||
}
|
}
|
||||||
const table = this.getFkTarget(column);
|
const table = this.getFkTarget(column);
|
||||||
if (table && table.columns && table.columns.length > 0 && table.primaryKey) {
|
if (table && table.columns && table.columns.length > 0 && table.primaryKey) {
|
||||||
const hintColumn = table.columns.find(x => x?.dataType?.toLowerCase()?.includes('char'));
|
// const hintColumn = table.columns.find(x => x?.dataType?.toLowerCase()?.includes('char'));
|
||||||
if (hintColumn) {
|
const hintDescription = this.getDictionaryDescription(table);
|
||||||
|
if (hintDescription) {
|
||||||
const parentUniqueName = column.uniquePath.slice(0, -1).join('.');
|
const parentUniqueName = column.uniquePath.slice(0, -1).join('.');
|
||||||
this.addReferenceToSelect(select, parentUniqueName ? `${parentUniqueName}_ref` : 'basetbl', column);
|
this.addReferenceToSelect(select, parentUniqueName ? `${parentUniqueName}_ref` : 'basetbl', column);
|
||||||
const childAlias = `${column.uniqueName}_ref`;
|
const childAlias = `${column.uniqueName}_ref`;
|
||||||
select.columns.push({
|
select.columns.push(
|
||||||
|
...hintDescription.columns.map(
|
||||||
|
columnName =>
|
||||||
|
({
|
||||||
exprType: 'column',
|
exprType: 'column',
|
||||||
columnName: hintColumn.columnName,
|
columnName,
|
||||||
alias: `hint_${column.uniqueName}`,
|
alias: `hint_${column.uniqueName}_${columnName}`,
|
||||||
source: { alias: childAlias },
|
source: { alias: childAlias },
|
||||||
});
|
} as ColumnRefExpression)
|
||||||
|
)
|
||||||
|
);
|
||||||
res = true;
|
res = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,8 +113,10 @@
|
|||||||
{value.toString()}
|
{value.toString()}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if allowHintField && rowData && rowData[col.hintColumnName]}
|
{#if allowHintField && rowData && _.some(col.hintColumnNames, hintColumnName => rowData[hintColumnName])}
|
||||||
<span class="hint">{rowData[col.hintColumnName]}</span>
|
<span class="hint"
|
||||||
|
>{col.hintColumnNames.map(hintColumnName => rowData[hintColumnName]).join(col.hintColumnDelimiter || ' ')}</span
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if col.foreignKey && rowData && rowData[col.uniqueName]}
|
{#if col.foreignKey && rowData && rowData[col.uniqueName]}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
$: hintFieldsAllowed = visibleRealColumns
|
$: hintFieldsAllowed = visibleRealColumns
|
||||||
.filter(col => {
|
.filter(col => {
|
||||||
if (!col.hintColumnName) return false;
|
if (!col.hintColumnNames) return false;
|
||||||
if (rowStatus.modifiedFields && rowStatus.modifiedFields.has(col.uniqueName)) return false;
|
if (rowStatus.modifiedFields && rowStatus.modifiedFields.has(col.uniqueName)) return false;
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
import SqlDataGridCore from './SqlDataGridCore.svelte';
|
import SqlDataGridCore from './SqlDataGridCore.svelte';
|
||||||
import SqlFormView from '../formview/SqlFormView.svelte';
|
import SqlFormView from '../formview/SqlFormView.svelte';
|
||||||
import { getBoolSettingsValue } from '../settings/settingsTools';
|
import { getBoolSettingsValue } from '../settings/settingsTools';
|
||||||
|
import { getDictionaryDescription } from '../utility/dictionaryDescriptionTools';
|
||||||
|
|
||||||
export let conid;
|
export let conid;
|
||||||
export let database;
|
export let database;
|
||||||
@@ -64,7 +65,8 @@
|
|||||||
setCache,
|
setCache,
|
||||||
$dbinfo,
|
$dbinfo,
|
||||||
{ showHintColumns: getBoolSettingsValue('dataGrid.showHintColumns', true) },
|
{ showHintColumns: getBoolSettingsValue('dataGrid.showHintColumns', true) },
|
||||||
$serverVersion
|
$serverVersion,
|
||||||
|
table => getDictionaryDescription(table, conid, database)
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
@@ -79,7 +81,8 @@
|
|||||||
setCache,
|
setCache,
|
||||||
$dbinfo,
|
$dbinfo,
|
||||||
{ showHintColumns: getBoolSettingsValue('dataGrid.showHintColumns', true) },
|
{ showHintColumns: getBoolSettingsValue('dataGrid.showHintColumns', true) },
|
||||||
$serverVersion
|
$serverVersion,
|
||||||
|
table => getDictionaryDescription(table, conid, database)
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
import FormProviderCore from '../forms/FormProviderCore.svelte';
|
import FormProviderCore from '../forms/FormProviderCore.svelte';
|
||||||
import {
|
import {
|
||||||
changeDelimitedColumnList,
|
changeDelimitedColumnList,
|
||||||
|
checkDescriptionExpression,
|
||||||
getDictionaryDescription,
|
getDictionaryDescription,
|
||||||
parseDelimitedColumnList,
|
parseDelimitedColumnList,
|
||||||
saveDictionaryDescription,
|
saveDictionaryDescription,
|
||||||
@@ -27,7 +28,7 @@
|
|||||||
|
|
||||||
$: tableInfo = useTableInfo({ conid, database, schemaName, pureName });
|
$: tableInfo = useTableInfo({ conid, database, schemaName, pureName });
|
||||||
|
|
||||||
$: descriptionInfo = getDictionaryDescription($tableInfo, conid, database);
|
$: descriptionInfo = getDictionaryDescription($tableInfo, conid, database, true);
|
||||||
|
|
||||||
const values = writable({});
|
const values = writable({});
|
||||||
|
|
||||||
@@ -78,6 +79,7 @@
|
|||||||
<svelte:fragment slot="footer">
|
<svelte:fragment slot="footer">
|
||||||
<FormSubmit
|
<FormSubmit
|
||||||
value="OK"
|
value="OK"
|
||||||
|
disabled={!checkDescriptionExpression($values?.columns, $tableInfo)}
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
closeCurrentModal();
|
closeCurrentModal();
|
||||||
saveDictionaryDescription(
|
saveDictionaryDescription(
|
||||||
|
|||||||
@@ -1,26 +1,27 @@
|
|||||||
|
import { DictionaryDescription } from 'dbgate-datalib';
|
||||||
import { TableInfo } from 'dbgate-types';
|
import { TableInfo } from 'dbgate-types';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { getLocalStorage, setLocalStorage, removeLocalStorage } from './storageCache';
|
import { getLocalStorage, setLocalStorage, removeLocalStorage } from './storageCache';
|
||||||
|
|
||||||
interface DictionaryDescription {
|
function checkDescriptionColumns(columns: string[], table: TableInfo) {
|
||||||
expression: string;
|
return columns.length > 0 && columns.every(x => table.columns.find(y => y.columnName == x));
|
||||||
columns: string[];
|
|
||||||
delimiter: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkDescription(desc: DictionaryDescription, table: TableInfo) {
|
export function getDictionaryDescription(
|
||||||
return desc.columns.length > 0 && desc.columns.every(x => table.columns.find(y => y.columnName == x));
|
table: TableInfo,
|
||||||
}
|
conid: string,
|
||||||
|
database: string,
|
||||||
export function getDictionaryDescription(table: TableInfo, conid: string, database: string): DictionaryDescription {
|
skipCheckSaved: boolean = false
|
||||||
|
): DictionaryDescription {
|
||||||
const keySpecific = `dictionary_spec_${table.schemaName}||${table.pureName}||${conid}||${database}`;
|
const keySpecific = `dictionary_spec_${table.schemaName}||${table.pureName}||${conid}||${database}`;
|
||||||
const keyCommon = `dictionary_spec_${table.schemaName}||${table.pureName}`;
|
const keyCommon = `dictionary_spec_${table.schemaName}||${table.pureName}`;
|
||||||
|
|
||||||
const cachedSpecific = getLocalStorage(keySpecific);
|
const cachedSpecific = getLocalStorage(keySpecific);
|
||||||
const cachedCommon = getLocalStorage(keyCommon);
|
const cachedCommon = getLocalStorage(keyCommon);
|
||||||
|
|
||||||
if (cachedSpecific && checkDescription(cachedSpecific, table)) return cachedSpecific;
|
if (cachedSpecific && (skipCheckSaved || checkDescriptionColumns(cachedSpecific.columns, table)))
|
||||||
if (cachedCommon && checkDescription(cachedCommon, table)) return cachedCommon;
|
return cachedSpecific;
|
||||||
|
if (cachedCommon && (skipCheckSaved || checkDescriptionColumns(cachedCommon.columns, table))) return cachedCommon;
|
||||||
|
|
||||||
const descColumn = table.columns.find(x => x?.dataType?.toLowerCase()?.includes('char'));
|
const descColumn = table.columns.find(x => x?.dataType?.toLowerCase()?.includes('char'));
|
||||||
if (descColumn) {
|
if (descColumn) {
|
||||||
@@ -34,10 +35,16 @@ export function getDictionaryDescription(table: TableInfo, conid: string, databa
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseDelimitedColumnList(columns) {
|
export function parseDelimitedColumnList(columns): string[] {
|
||||||
return _.compact((columns || '').split(',').map(x => x.trim()));
|
return _.compact((columns || '').split(',').map(x => x.trim()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function checkDescriptionExpression(expression: string, table: TableInfo) {
|
||||||
|
if (!expression) return false;
|
||||||
|
if (!table) return false;
|
||||||
|
return checkDescriptionColumns(parseDelimitedColumnList(expression), table);
|
||||||
|
}
|
||||||
|
|
||||||
export function changeDelimitedColumnList(columns, columnName, isChecked) {
|
export function changeDelimitedColumnList(columns, columnName, isChecked) {
|
||||||
const parsed = parseDelimitedColumnList(columns);
|
const parsed = parseDelimitedColumnList(columns);
|
||||||
const includes = parsed.includes(columnName);
|
const includes = parsed.includes(columnName);
|
||||||
|
|||||||
Reference in New Issue
Block a user