diff --git a/packages/web/src/appobj/AppObjectCore.svelte b/packages/web/src/appobj/AppObjectCore.svelte
index 02ed23eaa..de91a73e2 100644
--- a/packages/web/src/appobj/AppObjectCore.svelte
+++ b/packages/web/src/appobj/AppObjectCore.svelte
@@ -14,6 +14,7 @@
export let module = null;
export let isBold = false;
+ export let isChoosed = false;
export let isBusy = false;
export let statusIcon = undefined;
export let statusIconBefore = undefined;
@@ -66,11 +67,21 @@
}
// $: console.log(title, indentLevel);
+ let domDiv;
+
+ $: if (isBold && domDiv) {
+ domDiv.scrollIntoView({ block: 'nearest', inline: 'nearest' });
+ }
+
+ $: if (isChoosed && domDiv) {
+ domDiv.scrollIntoView({ block: 'nearest', inline: 'nearest' });
+ }
{#if checkedObjectsStore}
{
diff --git a/packages/web/src/appobj/DatabaseAppObject.svelte b/packages/web/src/appobj/DatabaseAppObject.svelte
index 87bbbe4be..4e1cb7339 100644
--- a/packages/web/src/appobj/DatabaseAppObject.svelte
+++ b/packages/web/src/appobj/DatabaseAppObject.svelte
@@ -509,9 +509,9 @@ await dbgateApi.dropAllDbObjects(${JSON.stringify(
extInfo={data.extInfo}
icon="img database"
colorMark={passProps?.connectionColorFactory &&
- passProps?.connectionColorFactory({ conid: _.get(data.connection, '_id'), database: data.name }, null, null, false)}
- isBold={_.get($currentDatabase, 'connection._id') == _.get(data.connection, '_id') &&
- extractDbNameFromComposite(_.get($currentDatabase, 'name')) == data.name}
+ passProps?.connectionColorFactory({ conid: data?.connection?._id, database: data.name }, null, null, false)}
+ isBold={$currentDatabase?.connection?._id == data?.connection?._id &&
+ extractDbNameFromComposite($currentDatabase?.name) == data.name}
on:click={() => switchCurrentDatabase(data)}
on:dragstart
on:dragenter
diff --git a/packages/web/src/appobj/DatabaseObjectAppObject.svelte b/packages/web/src/appobj/DatabaseObjectAppObject.svelte
index f0de19506..352e4f6c9 100644
--- a/packages/web/src/appobj/DatabaseObjectAppObject.svelte
+++ b/packages/web/src/appobj/DatabaseObjectAppObject.svelte
@@ -29,12 +29,18 @@
views: 'ViewDataTab',
matviews: 'ViewDataTab',
queries: 'QueryDataTab',
+ procedures: 'SqlObjectTab',
+ functions: 'SqlObjectTab',
};
- function createMenusCore(
- objectTypeField,
- driver
- ): {
+ function createScriptTemplatesSubmenu(objectTypeField) {
+ return {
+ label: 'SQL template',
+ submenu: getSupportedScriptTemplates(objectTypeField),
+ };
+ }
+
+ interface DbObjMenuItem {
label?: string;
tab?: string;
forceNewTab?: boolean;
@@ -53,34 +59,22 @@
isExport?: boolean;
isImport?: boolean;
isActiveChart?: boolean;
+ isShowSql?: boolean;
scriptTemplate?: string;
sqlGeneratorProps?: any;
isDropCollection?: boolean;
isRenameCollection?: boolean;
isDuplicateCollection?: boolean;
- }[] {
+ submenu?: DbObjMenuItem[];
+ }
+
+ function createMenusCore(objectTypeField, driver): DbObjMenuItem[] {
switch (objectTypeField) {
case 'tables':
return [
+ ...defaultDatabaseObjectAppObjectActions['tables'],
{
- label: 'Open data',
- tab: 'TableDataTab',
- forceNewTab: true,
- },
- {
- label: 'Open form',
- tab: 'TableDataTab',
- forceNewTab: true,
- initialData: {
- grid: {
- isFormView: true,
- },
- },
- },
- {
- label: 'Open structure',
- tab: 'TableStructureTab',
- icon: 'img table-structure',
+ divider: true,
},
{
label: 'Design query',
@@ -93,6 +87,33 @@
forceNewTab: true,
icon: 'img perspective',
},
+ createScriptTemplatesSubmenu('tables'),
+ {
+ label: 'SQL generator',
+ submenu: [
+ {
+ label: 'CREATE TABLE',
+ sqlGeneratorProps: {
+ createTables: true,
+ createIndexes: true,
+ createForeignKeys: true,
+ },
+ },
+ {
+ label: 'DROP TABLE',
+ sqlGeneratorProps: {
+ dropTables: true,
+ dropReferences: true,
+ },
+ },
+ {
+ label: 'INSERT',
+ sqlGeneratorProps: {
+ insert: true,
+ },
+ },
+ ],
+ },
{
divider: true,
},
@@ -142,50 +163,12 @@
label: 'Open active chart',
isActiveChart: true,
},
- {
- divider: true,
- },
- {
- label: 'SQL: CREATE TABLE',
- scriptTemplate: 'CREATE TABLE',
- },
- {
- label: 'SQL: SELECT',
- scriptTemplate: 'SELECT',
- },
- {
- label: 'SQL Generator: CREATE TABLE',
- sqlGeneratorProps: {
- createTables: true,
- createIndexes: true,
- createForeignKeys: true,
- },
- },
- {
- label: 'SQL Generator: DROP TABLE',
- sqlGeneratorProps: {
- dropTables: true,
- dropReferences: true,
- },
- },
- {
- label: 'SQL Generator: INSERT',
- sqlGeneratorProps: {
- insert: true,
- },
- },
];
case 'views':
return [
+ ...defaultDatabaseObjectAppObjectActions['views'],
{
- label: 'Open data',
- tab: 'ViewDataTab',
- forceNewTab: true,
- },
- {
- label: 'Open structure',
- tab: 'TableStructureTab',
- icon: 'img view-structure',
+ divider: true,
},
{
label: 'Design query',
@@ -197,6 +180,27 @@
forceNewTab: true,
icon: 'img perspective',
},
+ createScriptTemplatesSubmenu('views'),
+ {
+ label: 'SQL generator',
+ submenu: [
+ {
+ label: 'CREATE VIEW',
+ sqlGeneratorProps: {
+ createViews: true,
+ },
+ },
+ {
+ label: 'DROP VIEW',
+ sqlGeneratorProps: {
+ dropViews: true,
+ },
+ },
+ ],
+ },
+ {
+ divider: true,
+ },
hasPermission('dbops/model/edit') && {
label: 'Drop view',
isDrop: true,
@@ -219,48 +223,12 @@
label: 'Open active chart',
isActiveChart: true,
},
- {
- divider: true,
- },
- {
- label: 'SQL: CREATE VIEW',
- scriptTemplate: 'CREATE OBJECT',
- },
- {
- label: 'SQL: ALTER VIEW',
- scriptTemplate: 'ALTER OBJECT',
- },
- {
- label: 'SQL: CREATE TABLE',
- scriptTemplate: 'CREATE TABLE',
- },
- {
- label: 'SQL: SELECT',
- scriptTemplate: 'SELECT',
- },
- {
- label: 'SQL Generator: CREATE VIEW',
- sqlGeneratorProps: {
- createViews: true,
- },
- },
- {
- label: 'SQL Generator: DROP VIEW',
- sqlGeneratorProps: {
- dropViews: true,
- },
- },
];
case 'matviews':
return [
+ ...defaultDatabaseObjectAppObjectActions['matviews'],
{
- label: 'Open data',
- tab: 'ViewDataTab',
- forceNewTab: true,
- },
- {
- label: 'Open structure',
- tab: 'TableStructureTab',
+ divider: true,
},
hasPermission('dbops/model/edit') && {
label: 'Drop view',
@@ -272,10 +240,31 @@
isRename: true,
requiresWriteAccess: true,
},
+ {
+ divider: true,
+ },
{
label: 'Query designer',
isQueryDesigner: true,
},
+ createScriptTemplatesSubmenu('matviews'),
+ {
+ label: 'SQL generator',
+ submenu: [
+ {
+ label: 'CREATE MATERIALIZED VIEW',
+ sqlGeneratorProps: {
+ createMatviews: true,
+ },
+ },
+ {
+ label: 'DROP MATERIALIZED VIEW',
+ sqlGeneratorProps: {
+ dropMatviews: true,
+ },
+ },
+ ],
+ },
{
divider: true,
},
@@ -288,37 +277,6 @@
label: 'Open active chart',
isActiveChart: true,
},
- {
- divider: true,
- },
- {
- label: 'SQL: CREATE MATERIALIZED VIEW',
- scriptTemplate: 'CREATE OBJECT',
- },
- {
- label: 'SQL: ALTER MATERIALIZED VIEW',
- scriptTemplate: 'ALTER OBJECT',
- },
- {
- label: 'SQL: CREATE TABLE',
- scriptTemplate: 'CREATE TABLE',
- },
- {
- label: 'SQL: SELECT',
- scriptTemplate: 'SELECT',
- },
- {
- label: 'SQL Generator: CREATE MATERIALIZED VIEW',
- sqlGeneratorProps: {
- createMatviews: true,
- },
- },
- {
- label: 'SQL Generator: DROP MATERIALIZED VIEW',
- sqlGeneratorProps: {
- dropMatviews: true,
- },
- },
];
case 'queries':
return [
@@ -330,6 +288,10 @@
];
case 'procedures':
return [
+ ...defaultDatabaseObjectAppObjectActions['procedures'],
+ {
+ divider: true,
+ },
hasPermission('dbops/model/edit') && {
label: 'Drop procedure',
isDrop: true,
@@ -340,33 +302,31 @@
isRename: true,
requiresWriteAccess: true,
},
+ createScriptTemplatesSubmenu('procedures'),
{
- label: 'SQL: CREATE PROCEDURE',
- scriptTemplate: 'CREATE OBJECT',
- },
- {
- label: 'SQL: ALTER PROCEDURE',
- scriptTemplate: 'ALTER OBJECT',
- },
- {
- label: 'SQL: EXECUTE',
- scriptTemplate: 'EXECUTE PROCEDURE',
- },
- {
- label: 'SQL Generator: CREATE PROCEDURE',
- sqlGeneratorProps: {
- createProcedures: true,
- },
- },
- {
- label: 'SQL Generator: DROP PROCEDURE',
- sqlGeneratorProps: {
- dropProcedures: true,
- },
+ label: 'SQL generator',
+ submenu: [
+ {
+ label: 'CREATE PROCEDURE',
+ sqlGeneratorProps: {
+ createProcedures: true,
+ },
+ },
+ {
+ label: 'DROP PROCEDURE',
+ sqlGeneratorProps: {
+ dropProcedures: true,
+ },
+ },
+ ],
},
];
case 'functions':
return [
+ ...defaultDatabaseObjectAppObjectActions['functions'],
+ {
+ divider: true,
+ },
hasPermission('dbops/model/edit') && {
label: 'Drop function',
isDrop: true,
@@ -377,43 +337,30 @@
isRename: true,
requiresWriteAccess: true,
},
+ createScriptTemplatesSubmenu('functions'),
{
- label: 'SQL: CREATE FUNCTION',
- scriptTemplate: 'CREATE OBJECT',
- },
- {
- label: 'SQL: ALTER FUNCTION',
- scriptTemplate: 'ALTER OBJECT',
- },
- {
- label: 'SQL Generator: CREATE FUNCTION',
- sqlGeneratorProps: {
- createFunctions: true,
- },
- },
- {
- label: 'SQL Generator: DROP FUNCTION',
- sqlGeneratorProps: {
- dropFunctions: true,
- },
+ label: 'SQL generator',
+ submenu: [
+ {
+ label: 'CREATE FUNCTION',
+ sqlGeneratorProps: {
+ createFunctions: true,
+ },
+ },
+ {
+ label: 'DROP FUNCTION',
+ sqlGeneratorProps: {
+ dropFunctions: true,
+ },
+ },
+ ],
},
];
case 'collections':
return [
+ ...defaultDatabaseObjectAppObjectActions['collections'],
{
- label: 'Open data',
- tab: 'CollectionDataTab',
- forceNewTab: true,
- },
- {
- label: 'Open JSON',
- tab: 'CollectionDataTab',
- forceNewTab: true,
- initialData: {
- grid: {
- isJsonView: true,
- },
- },
+ divider: true,
},
{
label: 'Design perspective query',
@@ -659,15 +606,30 @@
// fixedTargetPureName: data.pureName,
// },
// });
+ // } else if (menu.isShowSql) {
+ // openNewTab({
+ // title: data.pureName,
+ // icon: 'img sql-file',
+ // tabComponent: 'SqlObjectTab',
+ // tabPreviewMode: true,
+ // props: {
+ // conid: data.conid,
+ // database: data.database,
+ // schemaName: data.schemaName,
+ // pureName: data.pureName,
+ // objectTypeField: data.objectTypeField,
+ // },
+ // });
} else {
openDatabaseObjectDetail(
menu.tab,
menu.scriptTemplate,
- data,
+ { ...data, defaultActionId: menu.defaultActionId },
menu.forceNewTab,
menu.initialData,
menu.icon,
- data
+ data,
+ !!menu.defaultActionId
);
}
}
@@ -697,11 +659,12 @@
export async function openDatabaseObjectDetail(
tabComponent,
scriptTemplate,
- { schemaName, pureName, conid, database, objectTypeField },
+ { schemaName, pureName, conid, database, objectTypeField, defaultActionId },
forceNewTab?,
initialData?,
icon?,
- appObjectData?
+ appObjectData?,
+ tabPreviewMode?
) {
const connection = await getConnectionInfo({ conid });
const tooltip = `${getConnectionLabel(connection)}\n${database}\n${fullDisplayName({
@@ -711,12 +674,16 @@
openNewTab(
{
- title: scriptTemplate ? 'Query #' : getObjectTitle(connection, schemaName, pureName),
+ // title: getObjectTitle(connection, schemaName, pureName),
+ title: tabComponent ? getObjectTitle(connection, schemaName, pureName) : 'Query #',
tooltip,
- icon: icon || (scriptTemplate ? 'img sql-file' : databaseObjectIcons[objectTypeField]),
- tabComponent: scriptTemplate ? 'QueryTab' : tabComponent,
+ icon:
+ icon ||
+ (scriptTemplate || tabComponent == 'SqlObjectTab' ? 'img sql-file' : databaseObjectIcons[objectTypeField]),
+ tabComponent: tabComponent ?? 'QueryTab',
appObject: 'DatabaseObjectAppObject',
appObjectData,
+ tabPreviewMode,
props: {
schemaName,
pureName,
@@ -724,6 +691,7 @@
database,
objectTypeField,
initialArgs: scriptTemplate ? { scriptTemplate } : null,
+ defaultActionId,
},
},
initialData,
@@ -731,31 +699,62 @@
);
}
- export function handleDatabaseObjectClick(data, forceNewTab = false) {
+ export function handleDatabaseObjectClick(
+ data,
+ { forceNewTab = false, tabPreviewMode = false, focusTab = false } = {}
+ ) {
const { schemaName, pureName, conid, database, objectTypeField } = data;
const driver = findEngineDriver(data, getExtensions());
- const configuredAction = getCurrentSettings()[`defaultAction.dbObjectClick.${objectTypeField}`];
- const overrideMenu = createMenus(objectTypeField, driver).find(x => x.label && x.label == configuredAction);
- if (overrideMenu) {
- databaseObjectMenuClickHandler(data, overrideMenu);
+ const activeTab = getActiveTab();
+ const activeTabProps = activeTab?.props || {};
+ const activeDefaultActionId = activeTab?.props?.defaultActionId;
+
+ if (matchDatabaseObjectAppObject(data, activeTabProps)) {
+ if (!tabPreviewMode) {
+ openedTabs.update(tabs => {
+ return tabs.map(tab => ({
+ ...tab,
+ tabPreviewMode: tab.tabid == activeTab.tabid ? false : tab.tabPreviewMode,
+ focused: focusTab && tab.tabid == activeTab.tabid ? true : tab.focused,
+ }));
+ });
+ }
return;
}
+ const availableDefaultActions = defaultDatabaseObjectAppObjectActions[objectTypeField];
+
+ const configuredActionId = getCurrentSettings()[`defaultAction.dbObjectClick.${objectTypeField}`];
+ const prefferedAction =
+ availableDefaultActions.find(x => x.defaultActionId == activeDefaultActionId) ??
+ availableDefaultActions.find(x => x.defaultActionId == configuredActionId) ??
+ availableDefaultActions[0];
+
+ // console.log('activeTab', activeTab);
+
+ // const overrideMenu = createMenus(objectTypeField, driver).find(x => x.label && x.label == configuredAction);
+ // if (overrideMenu) {
+ // databaseObjectMenuClickHandler(data, overrideMenu);
+ // return;
+ // }
+
openDatabaseObjectDetail(
- defaultTabs[objectTypeField],
- defaultTabs[objectTypeField] ? null : 'CREATE OBJECT',
+ prefferedAction.tab,
+ activeTabProps?.scriptTemplate,
{
schemaName,
pureName,
conid,
database,
objectTypeField,
+ defaultActionId: prefferedAction.defaultActionId,
},
forceNewTab,
null,
null,
- data
+ data,
+ tabPreviewMode
);
}
@@ -769,64 +768,74 @@
);
}
+ function menuItemMapper(menu, data, connection) {
+ if (menu.divider) return menu;
+
+ if (menu.isExport) {
+ return createQuickExportMenu(
+ fmt => async () => {
+ const coninfo = await getConnectionInfo(data);
+ exportQuickExportFile(
+ data.pureName,
+ {
+ functionName: menu.functionName,
+ props: {
+ connection: extractShellConnection(coninfo, data.database),
+ ..._.pick(data, ['pureName', 'schemaName']),
+ },
+ },
+ fmt
+ );
+ },
+ {
+ onClick: () => {
+ openImportExportTab({
+ sourceStorageType: 'database',
+ sourceConnectionId: data.conid,
+ sourceDatabaseName: extractDbNameFromComposite(data.database),
+ sourceSchemaName: data.schemaName,
+ sourceList: [data.pureName],
+ });
+ // showModal(ImportExportModal, {
+ // initialValues: {
+ // sourceStorageType: 'database',
+ // sourceConnectionId: data.conid,
+ // sourceDatabaseName: data.database,
+ // sourceSchemaName: data.schemaName,
+ // sourceList: [data.pureName],
+ // },
+ // });
+ },
+ }
+ );
+ }
+
+ if (connection?.isReadOnly && menu.requiresWriteAccess) {
+ return null;
+ }
+
+ if (menu.submenu) {
+ return {
+ ...menu,
+ submenu: menu.submenu.map(x => menuItemMapper(x, data, connection)),
+ };
+ }
+
+ return {
+ text: menu.label,
+ onClick: () => {
+ databaseObjectMenuClickHandler(data, menu);
+ },
+ };
+ }
+
export function createDatabaseObjectMenu(data, connection = null) {
const driver = findEngineDriver(data, getExtensions());
const { objectTypeField } = data;
return createMenus(objectTypeField, driver)
.filter(x => x)
- .map(menu => {
- if (menu.divider) return menu;
-
- if (menu.isExport) {
- return createQuickExportMenu(
- fmt => async () => {
- const coninfo = await getConnectionInfo(data);
- exportQuickExportFile(
- data.pureName,
- {
- functionName: menu.functionName,
- props: {
- connection: extractShellConnection(coninfo, data.database),
- ..._.pick(data, ['pureName', 'schemaName']),
- },
- },
- fmt
- );
- },
- {
- onClick: () => {
- openImportExportTab({
- sourceStorageType: 'database',
- sourceConnectionId: data.conid,
- sourceDatabaseName: extractDbNameFromComposite(data.database),
- sourceSchemaName: data.schemaName,
- sourceList: [data.pureName],
- });
- // showModal(ImportExportModal, {
- // initialValues: {
- // sourceStorageType: 'database',
- // sourceConnectionId: data.conid,
- // sourceDatabaseName: data.database,
- // sourceSchemaName: data.schemaName,
- // sourceList: [data.pureName],
- // },
- // });
- },
- }
- );
- }
-
- if (connection?.isReadOnly && menu.requiresWriteAccess) {
- return null;
- }
- return {
- text: menu.label,
- onClick: () => {
- databaseObjectMenuClickHandler(data, menu);
- },
- };
- });
+ .map(menu => menuItemMapper(menu, data, connection));
}
function formatRowCount(value) {
@@ -838,6 +847,10 @@
export function createAppObjectMenu(data) {
return createDatabaseObjectMenu(data);
}
+
+ export function handleObjectClick(data, { forceNewTab = false, tabPreviewMode = false, focusTab = false }) {
+ return handleDatabaseObjectClick(data, { forceNewTab, tabPreviewMode, focusTab });
+ }
{#if allowChangeChangeSetStructure}
@@ -207,9 +209,13 @@
bind:this={domFocusField}
on:keydown={handleKeyDown}
on:focus={() => {
+ isColumnManagerFocused = true;
// activator.activate();
// invalidateCommands();
}}
+ on:blur={() => {
+ isColumnManagerFocused = false;
+ }}
on:copy={copyToClipboard}
/>
@@ -224,6 +230,7 @@
{database}
{tableInfo}
{setTableInfo}
+ {isColumnManagerFocused}
columnInfo={tableInfo?.columns?.[columnIndex]}
{columnIndex}
{allowChangeChangeSetStructure}
diff --git a/packages/web/src/datagrid/ColumnManagerRow.svelte b/packages/web/src/datagrid/ColumnManagerRow.svelte
index 5ec95caf2..864f6c60d 100644
--- a/packages/web/src/datagrid/ColumnManagerRow.svelte
+++ b/packages/web/src/datagrid/ColumnManagerRow.svelte
@@ -22,6 +22,8 @@
export let columnInfo = null;
export let columnIndex = -1;
+ export let isColumnManagerFocused = false;
+
export let allowChangeChangeSetStructure = false;
$: addDataCommand = allowChangeChangeSetStructure;
@@ -49,6 +51,7 @@
else display.focusColumns([column.uniqueName]);
}}
class:isSelected
+ class:isFocused={isColumnManagerFocused}
on:click
on:mousedown
on:mousemove
@@ -123,6 +126,10 @@
}
.row.isSelected {
+ background: var(--theme-bg-3);
+ }
+
+ .row.isSelected.isFocused {
background: var(--theme-bg-selected);
}
diff --git a/packages/web/src/datagrid/DataGridCell.svelte b/packages/web/src/datagrid/DataGridCell.svelte
index 657d9f39b..12100ddbb 100644
--- a/packages/web/src/datagrid/DataGridCell.svelte
+++ b/packages/web/src/datagrid/DataGridCell.svelte
@@ -173,6 +173,9 @@
background: var(--theme-bg-volcano);
}
td.isSelected {
+ background: var(--theme-bg-3);
+ }
+ :global(.data-grid-focused) td.isSelected {
background: var(--theme-bg-selected);
}
td.isDeleted {
diff --git a/packages/web/src/datagrid/DataGridCore.svelte b/packages/web/src/datagrid/DataGridCore.svelte
index d5b54d698..787708194 100644
--- a/packages/web/src/datagrid/DataGridCore.svelte
+++ b/packages/web/src/datagrid/DataGridCore.svelte
@@ -472,7 +472,7 @@
export let dataEditorTypesBehaviourOverride = null;
const wheelRowCount = 5;
- const tabVisible: any = getContext('tabVisible');
+ const tabFocused: any = getContext('tabFocused');
let containerHeight = 0;
let containerWidth = 0;
@@ -492,6 +492,8 @@
let autofillSelectedCells = emptyCellArray;
const domFilterControlsRef = createRef({});
+ let isGridFocused=false;
+
const tabid = getContext('tabid');
let unsubscribeDbRefresh;
@@ -1041,7 +1043,6 @@
return !hideGridLeftColumn;
}
-
$: autofillMarkerCell =
selectedCells && selectedCells.length > 0 && _.uniq(selectedCells.map(x => x[0])).length == 1
? [_.max(selectedCells.map(x => x[0])), _.max(selectedCells.map(x => x[1]))]
@@ -1134,7 +1135,7 @@
}
}
- $: if ($tabVisible && domFocusField && focusOnVisible) {
+ $: if ($tabFocused && domFocusField && focusOnVisible) {
domFocusField.focus();
}
@@ -1863,6 +1864,7 @@
{:else}
{
activator.activate();
invalidateCommands();
+ isGridFocused = true;
}}
+ on:blur
on:paste={handlePaste}
on:copy={copyToClipboard}
- on:blur={handleBlur}
+ on:blur={() => {
+ isGridFocused = false;
+ }}
/>
(value = x), 500);
+
+ export function focus() {
+ domInput.focus();
+ }
+ import { defaultDatabaseObjectAppObjectActions } from '../appobj/appObjectTools';
+ import FormSelectField from '../forms/FormSelectField.svelte';
+
+ export let label;
+ export let objectTypeField;
+
+
+ ({
+ value: x.defaultActionId,
+ label: x.label,
+ }))}
+/>
diff --git a/packages/web/src/settings/SettingsModal.svelte b/packages/web/src/settings/SettingsModal.svelte
index fc4ba2773..362047098 100644
--- a/packages/web/src/settings/SettingsModal.svelte
+++ b/packages/web/src/settings/SettingsModal.svelte
@@ -38,6 +38,7 @@
import { useSettings } from '../utility/metadataLoaders';
import { derived } from 'svelte/store';
import { safeFormatDate } from 'dbgate-tools';
+ import FormDefaultActionField from './FormDefaultActionField.svelte';
const electron = getElectron();
let restartWarning = false;
@@ -288,56 +289,11 @@ ORDER BY
]}
/>
-
-
-
-
-
-
-
+
+
+
+
+
Confirmations
diff --git a/packages/web/src/stores.ts b/packages/web/src/stores.ts
index 98d7ae912..76dd67dc1 100644
--- a/packages/web/src/stores.ts
+++ b/packages/web/src/stores.ts
@@ -22,6 +22,8 @@ export interface TabDefinition {
tabOrder?: number;
multiTabIndex?: number;
unsaved?: boolean;
+ tabPreviewMode?: boolean;
+ focused?: boolean;
}
export function writableWithStorage(defaultValue: T, storageName) {
@@ -91,7 +93,7 @@ export const openedConnections = writable([]);
export const temporaryOpenedConnections = writable([]);
export const openedSingleDatabaseConnections = writable([]);
export const expandedConnections = writable([]);
-export const currentDatabase = writable(null);
+export const currentDatabase = writableWithForage(null, 'currentDatabase');
export const openedTabs = writableWithForage([], getOpenedTabsStorageName(), x => [...(x || [])]);
export const copyRowsFormat = writableWithStorage('textWithoutHeaders', 'copyRowsFormat');
export const extensions = writable(null);
@@ -155,6 +157,8 @@ export const activeDbKeysStore = writableWithStorage({}, 'activeDbKeysStore');
export const appliedCurrentSchema = writable(null);
export const loadingSchemaLists = writable({}); // dict [`${conid}::${database}`]: true
+export const selectedDatabaseObjectAppObject = writable(null);
+
export const currentThemeDefinition = derived([currentTheme, extensions], ([$currentTheme, $extensions]) =>
$extensions.themes.find(x => x.themeClassName == $currentTheme)
);
@@ -324,6 +328,12 @@ appliedCurrentSchema.subscribe(value => {
});
export const getAppliedCurrentSchema = () => appliedCurrentSchemaValue;
+let selectedDatabaseObjectAppObjectValue = null;
+selectedDatabaseObjectAppObject.subscribe(value => {
+ selectedDatabaseObjectAppObjectValue = value;
+});
+export const getSelectedDatabaseObjectAppObject = () => selectedDatabaseObjectAppObjectValue;
+
let openedModalsValue = [];
openedModals.subscribe(value => {
openedModalsValue = value;
diff --git a/packages/web/src/tabpanel/TabContent.svelte b/packages/web/src/tabpanel/TabContent.svelte
index bff6f575e..8eac0de10 100644
--- a/packages/web/src/tabpanel/TabContent.svelte
+++ b/packages/web/src/tabpanel/TabContent.svelte
@@ -4,17 +4,22 @@
export let tabid;
export let tabVisible;
+ export let tabFocused;
export let tabComponent;
- const tabVisibleStore = writable(tabVisible);
setContext('tabid', tabid);
- setContext('tabVisible', tabVisibleStore);
+ const tabVisibleStore = writable(tabVisible);
+ setContext('tabVisible', tabVisibleStore);
$: tabVisibleStore.set(tabVisible);
+
+ const tabFocusedStore = writable(tabFocused);
+ setContext('tabFocused', tabFocusedStore);
+ $: tabFocusedStore.set(tabFocused);
-
+
diff --git a/packages/web/src/widgets/SqlObjectList.svelte b/packages/web/src/widgets/SqlObjectList.svelte
index 8704e94b7..d829b5d52 100644
--- a/packages/web/src/widgets/SqlObjectList.svelte
+++ b/packages/web/src/widgets/SqlObjectList.svelte
@@ -36,18 +36,28 @@
import FontIcon from '../icons/FontIcon.svelte';
import CloseSearchButton from '../buttons/CloseSearchButton.svelte';
import { findEngineDriver } from 'dbgate-tools';
- import { currentDatabase, extensions } from '../stores';
+ import {
+ currentDatabase,
+ extensions,
+ getSelectedDatabaseObjectAppObject,
+ selectedDatabaseObjectAppObject,
+ } from '../stores';
import newQuery from '../query/newQuery';
import runCommand from '../commands/runCommand';
import { apiCall } from '../utility/api';
import { filterAppsForDatabase } from '../utility/appTools';
import SchemaSelector from './SchemaSelector.svelte';
import { appliedCurrentSchema } from '../stores';
+ import AppObjectListHandler from './AppObjectListHandler.svelte';
+ import { matchDatabaseObjectAppObject } from '../appobj/appObjectTools';
export let conid;
export let database;
let filter = '';
+ let domContainer = null;
+ let domFilter = null;
+ let domListHandler;
$: objects = useDatabaseInfo({ conid, database });
$: status = useDatabaseStatus({ conid, database });
@@ -151,7 +161,14 @@
{:else}
-
+ {
+ domListHandler?.focusFirst();
+ }}
+ />
@@ -168,27 +185,42 @@
negativeMarginTop
/>
-
+
{#if ($status && ($status.name == 'pending' || $status.name == 'checkStructure' || $status.name == 'loadStructure') && $objects) || !$objects}
{:else}
- ($appliedCurrentSchema ? x.schemaName == $appliedCurrentSchema : true))
- .map(x => ({ ...x, conid, database }))}
+ ({ ...x, conid, database }))}
+ selectedObjectStore={selectedDatabaseObjectAppObject}
+ getSelectedObject={getSelectedDatabaseObjectAppObject}
+ selectedObjectMatcher={matchDatabaseObjectAppObject}
module={databaseObjectAppObject}
- groupFunc={data => getObjectTypeFieldLabel(data.objectTypeField, driver)}
- subItemsComponent={SubColumnParamList}
- isExpandable={data =>
- data.objectTypeField == 'tables' || data.objectTypeField == 'views' || data.objectTypeField == 'matviews'}
- expandIconFunc={chevronExpandIcon}
- {filter}
- passProps={{
- showPinnedInsteadOfUnpin: true,
- connection: $connection,
- hideSchemaName: !!$appliedCurrentSchema,
+ onScrollTop={() => {
+ domContainer?.scrollTop();
}}
- />
+ onFocusFilterBox={() => {
+ domFilter?.focus();
+ }}
+ >
+ ($appliedCurrentSchema ? x.schemaName == $appliedCurrentSchema : true))
+ .map(x => ({ ...x, conid, database }))}
+ module={databaseObjectAppObject}
+ groupFunc={data => getObjectTypeFieldLabel(data.objectTypeField, driver)}
+ subItemsComponent={SubColumnParamList}
+ isExpandable={data =>
+ data.objectTypeField == 'tables' || data.objectTypeField == 'views' || data.objectTypeField == 'matviews'}
+ expandIconFunc={chevronExpandIcon}
+ {filter}
+ passProps={{
+ showPinnedInsteadOfUnpin: true,
+ connection: $connection,
+ hideSchemaName: !!$appliedCurrentSchema,
+ }}
+ />
+
{/if}
{/if}
diff --git a/packages/web/src/widgets/WidgetsInnerContainer.svelte b/packages/web/src/widgets/WidgetsInnerContainer.svelte
index 498f333e0..76f7f2895 100644
--- a/packages/web/src/widgets/WidgetsInnerContainer.svelte
+++ b/packages/web/src/widgets/WidgetsInnerContainer.svelte
@@ -1,4 +1,12 @@
-
+
+
+