Merge branch 'master' into feature/FK-test

This commit is contained in:
Stela Augustinova
2025-12-04 14:36:14 +01:00
41 changed files with 454 additions and 314 deletions

View File

@@ -43,7 +43,7 @@ jobs:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: 911941a53e91a5a777b8c7d455be0719234dde5f
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro

View File

@@ -43,7 +43,7 @@ jobs:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: 911941a53e91a5a777b8c7d455be0719234dde5f
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro

View File

@@ -39,7 +39,7 @@ jobs:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: 911941a53e91a5a777b8c7d455be0719234dde5f
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro

View File

@@ -44,7 +44,7 @@ jobs:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: 911941a53e91a5a777b8c7d455be0719234dde5f
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro

View File

@@ -35,7 +35,7 @@ jobs:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: 911941a53e91a5a777b8c7d455be0719234dde5f
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro

View File

@@ -26,7 +26,7 @@ jobs:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: 911941a53e91a5a777b8c7d455be0719234dde5f
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro

View File

@@ -8,13 +8,19 @@ Builds:
- linux - application for linux
- win - application for Windows
## 6.7.2 - not released
## 6.7.3
- FIXED: Fixed problem in analyser core - in PostgreSQL, after dropping table, dropped table still appeared in structure
- FIXED: PostgreSQL numeric columns do not align right #1254
- ADDED: Custom thousands separator #1213
## 6.7.2
- CHANGED: Settings modal redesign - now is settings opened in tab instead of modal, similarily as in VSCode
- FIXED: Fixed search in table shortcuts #1273
- CHANGED: Improved foreign key editor UX
- FIXED: Fixed incremental DB structure refresh for PostgreSQL, optimalized slow loading primary keys in PostgreSQL
- CHANGED: You could now choose, how to refresh structure, added ability to disconnect or reconnect
- ADDED: Better processing of table backups, generate table restore script #1274
- CHANGED: Improved storage of settings, especially for Team Premium edition
## 6.7.1
- ADDED: LANGUAGE environment variable for the web version. #1266

View File

@@ -10,6 +10,7 @@ module.exports = defineConfig({
// baseUrl: 'http://localhost:3000',
// trashAssetsBeforeRuns: false,
chromeWebSecurity: false,
reporter: process.env.CI ? 'mocha-reporter-gha' : 'spec',
setupNodeEvents(on, config) {
// implement node event listeners here

View File

@@ -110,7 +110,7 @@ describe('Charts', () => {
cy.themeshot('new-object-window');
});
it('Database chat - charts', () => {
it.skip('Database chat - charts', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('TabsPanel_buttonNewObject').click();
@@ -125,7 +125,7 @@ describe('Charts', () => {
cy.themeshot('database-chat-chart');
});
it('Database chat', () => {
it.skip('Database chat', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('TabsPanel_buttonNewObject').click();
@@ -146,7 +146,7 @@ describe('Charts', () => {
// cy.themeshot('database-chat');
});
it('Explain query error', () => {
it.skip('Explain query error', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('TabsPanel_buttonNewObject').click();
@@ -199,7 +199,7 @@ describe('Charts', () => {
cy.testid('WidgetIconPanel_settings');
});
it.only('Settings', () => {
it('Settings', () => {
cy.testid('WidgetIconPanel_settings').click();
cy.themeshot('app-settings-general');
@@ -234,10 +234,10 @@ describe('Charts', () => {
cy.contains('Light').click();
cy.get('body').find('.theme-light').should('exist');
// Connection
cy.contains(/^Connection$/).click();
// General
cy.contains(/^General$/).click();
cy.contains('charts_sample');
cy.get('[data-testid=ConnectionSettings_lockedDatabaseMode]').check();
cy.get('[data-testid=GeneralSettings_lockedDatabaseMode]').check();
cy.contains('Connections').click();
cy.contains('charts_sample').should('not.exist');

View File

@@ -210,7 +210,8 @@ describe('Import CSV', () => {
cy.testid('ImportExportConfigurator_tableMappingSection').contains('20 rows written').should('be.visible');
cy.testid('SqlObjectList_refreshButton').click();
cy.contains('Refresh DB structure (incremental)').click();
cy.testid('DatabasStatusMenu_refreshFull').click();
// cy.contains('Refresh DB structure (incremental)').click();
cy.testid('SqlObjectList_container').contains('customers-20').click();
cy.contains('Rows: 20').should('be.visible');

View File

@@ -10,11 +10,11 @@
"cypress-real-events": "^1.13.0",
"env-cmd": "^10.1.0",
"kill-port": "^2.0.1",
"mocha-reporter-gha": "^1.1.1",
"start-server-and-test": "^2.0.8"
},
"scripts": {
"cy:open": "cypress open --config experimentalInteractiveRunEvents=true",
"cy:run:add-connection": "cypress run --spec cypress/e2e/add-connection.cy.js",
"cy:run:portal": "cypress run --spec cypress/e2e/portal.cy.js",
"cy:run:oauth": "cypress run --spec cypress/e2e/oauth.cy.js",
@@ -23,7 +23,6 @@
"cy:run:multi-sql": "cypress run --spec cypress/e2e/multi-sql.cy.js",
"cy:run:cloud": "cypress run --spec cypress/e2e/cloud.cy.js",
"cy:run:charts": "cypress run --spec cypress/e2e/charts.cy.js",
"start:add-connection": "node clearTestingData && cd .. && node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:portal": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/portal/.env node e2e-tests/init/portal.js && env-cmd -f e2e-tests/env/portal/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:oauth": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/oauth/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
@@ -32,7 +31,6 @@
"start:multi-sql": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/multi-sql/.env node e2e-tests/init/multi-sql.js && env-cmd -f e2e-tests/env/multi-sql/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:cloud": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/cloud/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:charts": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/charts/.env node e2e-tests/init/charts.js && env-cmd -f e2e-tests/env/charts/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
"test:add-connection": "start-server-and-test start:add-connection http://localhost:3000 cy:run:add-connection",
"test:portal": "start-server-and-test start:portal http://localhost:3000 cy:run:portal",
"test:oauth": "start-server-and-test start:oauth http://localhost:3000 cy:run:oauth",
@@ -41,7 +39,6 @@
"test:multi-sql": "start-server-and-test start:multi-sql http://localhost:3000 cy:run:multi-sql",
"test:cloud": "start-server-and-test start:cloud http://localhost:3000 cy:run:cloud",
"test:charts": "start-server-and-test start:charts http://localhost:3000 cy:run:charts",
"test": "yarn test:add-connection && yarn test:portal && yarn test:oauth && yarn test:browse-data && yarn test:team && yarn test:multi-sql && yarn test:cloud && yarn test:charts",
"test:ci": "yarn test"
},

View File

@@ -2,6 +2,34 @@
# yarn lockfile v1
"@actions/core@^1.10.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.11.1.tgz#ae683aac5112438021588030efb53b1adb86f172"
integrity sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==
dependencies:
"@actions/exec" "^1.1.1"
"@actions/http-client" "^2.0.1"
"@actions/exec@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@actions/exec/-/exec-1.1.1.tgz#2e43f28c54022537172819a7cf886c844221a611"
integrity sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==
dependencies:
"@actions/io" "^1.0.1"
"@actions/http-client@^2.0.1":
version "2.2.3"
resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.2.3.tgz#31fc0b25c0e665754ed39a9f19a8611fc6dab674"
integrity sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==
dependencies:
tunnel "^0.0.6"
undici "^5.25.4"
"@actions/io@^1.0.1":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@actions/io/-/io-1.1.3.tgz#4cdb6254da7962b07473ff5c335f3da485d94d71"
integrity sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==
"@colors/colors@1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
@@ -39,6 +67,11 @@
debug "^3.1.0"
lodash.once "^4.1.1"
"@fastify/busboy@^2.0.0":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d"
integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==
"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
@@ -947,6 +980,13 @@ minimist@^1.2.8:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
mocha-reporter-gha@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/mocha-reporter-gha/-/mocha-reporter-gha-1.1.1.tgz#e1248abd0769f55b57b36ccd7db2b0b6573d5adf"
integrity sha512-CFbcgM56V4yWlbF91XuwrE6a5X/IqjVXTPefO7m8cY8Es8G1UhJ2KKOrk16AcSemRzVWXp2Fdy3bWJ7j45snWw==
dependencies:
"@actions/core" "^1.10.1"
ms@^2.1.1, ms@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
@@ -1292,6 +1332,11 @@ tunnel-agent@^0.6.0:
dependencies:
safe-buffer "^5.0.1"
tunnel@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
@@ -1307,6 +1352,13 @@ undici-types@~6.20.0:
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"
integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==
undici@^5.25.4:
version "5.29.0"
resolved "https://registry.yarnpkg.com/undici/-/undici-5.29.0.tgz#419595449ae3f2cdcba3580a2e8903399bd1f5a3"
integrity sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==
dependencies:
"@fastify/busboy" "^2.0.0"
universalify@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d"

View File

@@ -28,12 +28,12 @@ describe('Schema tests', () => {
const count = schemas1.length;
expect(structure1.tables.length).toEqual(2);
await runCommandOnDriver(conn, driver, dmp => dmp.createSchema('myschema'));
const structure2 = await driver.analyseIncremental(conn, structure1);
const schemas2 = await driver.listSchemas(conn);
expect(schemas2.find(x => x.schemaName == 'myschema')).toBeTruthy();
expect(schemas2.length).toEqual(count + 1);
expect(schemas2.find(x => x.isDefault).schemaName).toEqual(engine.defaultSchemaName);
if (!engine.skipIncrementalAnalysis) {
const structure2 = await driver.analyseIncremental(conn, structure1);
const schemas2 = await driver.listSchemas(conn);
expect(schemas2.find(x => x.schemaName == 'myschema')).toBeTruthy();
expect(schemas2.length).toEqual(count + 1);
expect(schemas2.find(x => x.isDefault).schemaName).toEqual(engine.defaultSchemaName);
expect(structure2).toBeNull();
}
})
@@ -50,10 +50,10 @@ describe('Schema tests', () => {
expect(schemas1.find(x => x.schemaName == 'myschema')).toBeTruthy();
expect(structure1.tables.length).toEqual(2);
await runCommandOnDriver(conn, driver, dmp => dmp.dropSchema('myschema'));
const structure2 = await driver.analyseIncremental(conn, structure1);
const schemas2 = await driver.listSchemas(conn);
expect(schemas2.find(x => x.schemaName == 'myschema')).toBeFalsy();
if (!engine.skipIncrementalAnalysis) {
const structure2 = await driver.analyseIncremental(conn, structure1);
const schemas2 = await driver.listSchemas(conn);
expect(schemas2.find(x => x.schemaName == 'myschema')).toBeFalsy();
expect(structure2).toBeNull();
}
})

View File

@@ -94,7 +94,7 @@ describe('Table analyse', () => {
})
);
test.each(engines.filter(x => !x.skipIncrementalAnalysis).map(engine => [engine.label, engine]))(
test.each(engines.map(engine => [engine.label, engine]))(
'Table add - incremental analysis - %s',
testWrapper(async (conn, driver, engine) => {
await runCommandOnDriver(conn, driver, dmp => dmp.put(t2Sql(engine)));
@@ -112,7 +112,7 @@ describe('Table analyse', () => {
})
);
test.each(engines.filter(x => !x.skipIncrementalAnalysis).map(engine => [engine.label, engine]))(
test.each(engines.map(engine => [engine.label, engine]))(
'Table remove - incremental analysis - %s',
testWrapper(async (conn, driver, engine) => {
await runCommandOnDriver(conn, driver, dmp => dmp.put(t1Sql(engine)));
@@ -130,7 +130,7 @@ describe('Table analyse', () => {
})
);
test.each(engines.filter(x => !x.skipIncrementalAnalysis).map(engine => [engine.label, engine]))(
test.each(engines.map(engine => [engine.label, engine]))(
'Table change - incremental analysis - %s',
testWrapper(async (conn, driver, engine) => {
await runCommandOnDriver(conn, driver, dmp => dmp.put(t1Sql(engine)));

View File

@@ -1,6 +1,6 @@
{
"private": true,
"version": "6.7.2-premium-beta.5",
"version": "6.7.3",
"name": "dbgate-all",
"workspaces": [
"packages/*",

View File

@@ -289,16 +289,11 @@ module.exports = {
const res = await lock.acquire('settings', async () => {
const currentValue = await this.loadSettings();
try {
let updated = currentValue;
let updated = {
...currentValue,
...values,
};
if (process.env.STORAGE_DATABASE) {
updated = {
...currentValue,
..._.mapValues(values, v => {
if (v === true) return 'true';
if (v === false) return 'false';
return v;
}),
};
await storage.writeConfig({
group: 'settings',
config: updated,

View File

@@ -360,6 +360,12 @@ module.exports = {
"columnName": "value",
"dataType": "varchar(1000)",
"notNull": false
},
{
"pureName": "config",
"columnName": "valueType",
"dataType": "varchar(50)",
"notNull": false
}
],
"foreignKeys": [],

View File

@@ -164,6 +164,11 @@ export class DatabaseAnalyser<TClient = any> {
const res = {};
for (const field of STRUCTURE_FIELDS) {
const isAll = this.modifications.some(x => x.action == 'all' && x.objectTypeField == field);
if (isAll) {
res[field] = newlyAnalysed[field] || [];
continue;
}
const removedIds = this.modifications
.filter(x => x.action == 'remove' && x.objectTypeField == field)
.map(x => x.objectId);

View File

@@ -45,14 +45,15 @@ export function hexStringToArray(inputString) {
export function base64ToHex(base64String) {
const binaryString = atob(base64String);
const hexString = Array.from(binaryString, c =>
c.charCodeAt(0).toString(16).padStart(2, '0')
).join('');
const hexString = Array.from(binaryString, c => c.charCodeAt(0).toString(16).padStart(2, '0')).join('');
return '0x' + hexString.toUpperCase();
};
}
export function hexToBase64(hexString) {
const binaryString = hexString.match(/.{1,2}/g).map(byte => String.fromCharCode(parseInt(byte, 16))).join('');
const binaryString = hexString
.match(/.{1,2}/g)
.map(byte => String.fromCharCode(parseInt(byte, 16)))
.join('');
return btoa(binaryString);
}
@@ -68,9 +69,9 @@ export function parseCellValue(value, editorTypes?: DataEditorTypesBehaviour) {
if (mHex) {
return {
$binary: {
base64: hexToBase64(value.substring(2))
}
}
base64: hexToBase64(value.substring(2)),
},
};
}
}
@@ -200,6 +201,26 @@ function stringifyJsonToGrid(value): ReturnType<typeof stringifyCellValue> {
return { value: '(JSON)', gridStyle: 'nullCellStyle' };
}
function formatNumberCustomSeparator(value, thousandsSeparator) {
const [intPart, decPart] = value.split('.');
const intPartWithSeparator = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator);
return decPart ? `${intPartWithSeparator}.${decPart}` : intPartWithSeparator;
}
function formatCellNumber(value, gridFormattingOptions?: { thousandsSeparator?: string }) {
const separator = gridFormattingOptions?.thousandsSeparator;
if (_isNumber(value)) {
if (separator === 'none' || (value < 1000 && value > -1000)) return value.toString();
if (separator === 'system') return value.toLocaleString();
}
// fallback for system locale
if (separator === 'space' || separator === 'system') return formatNumberCustomSeparator(value.toString(), ' ');
if (separator === 'narrowspace') return formatNumberCustomSeparator(value.toString(), '\u202F');
if (separator === 'comma') return formatNumberCustomSeparator(value.toString(), ',');
if (separator === 'dot') return formatNumberCustomSeparator(value.toString(), '.');
return value.toString();
}
export function stringifyCellValue(
value,
intent:
@@ -210,7 +231,7 @@ export function stringifyCellValue(
| 'exportIntent'
| 'clipboardIntent',
editorTypes?: DataEditorTypesBehaviour,
gridFormattingOptions?: { useThousandsSeparator?: boolean },
gridFormattingOptions?: { thousandsSeparator?: string },
jsonParsedValue?: any
): {
value: string;
@@ -256,7 +277,7 @@ export function stringifyCellValue(
// return { value: '0x' + arrayToHexString(value.data), gridStyle: 'valueCellStyle' };
// }
}
if (editorTypes?.parseObjectIdAsDollar) {
if (value?.$oid) {
switch (intent) {
@@ -270,13 +291,13 @@ export function stringifyCellValue(
}
if (value?.$bigint) {
return {
value: value.$bigint,
value: formatCellNumber(value.$bigint, gridFormattingOptions),
gridStyle: 'valueCellStyle',
};
}
if (typeof value === 'bigint') {
return {
value: value.toString(),
value: formatCellNumber(value.toString(), gridFormattingOptions),
gridStyle: 'valueCellStyle',
};
}
@@ -351,13 +372,8 @@ export function stringifyCellValue(
if (_isNumber(value)) {
switch (intent) {
case 'gridCellIntent':
return {
value:
gridFormattingOptions?.useThousandsSeparator && (value >= 10000 || value <= -10000)
? value.toLocaleString()
: value.toString(),
gridStyle: 'valueCellStyle',
};
const separator = gridFormattingOptions?.thousandsSeparator;
return { value: formatCellNumber(value, gridFormattingOptions), gridStyle: 'valueCellStyle' };
default:
return { value: value.toString() };
}

View File

@@ -40,8 +40,6 @@ import { getSettings } from '../utility/metadataLoaders';
import { isMac, switchCurrentDatabase } from '../utility/common';
import { doLogout } from '../clientAuth';
import { disconnectServerConnection } from '../appobj/ConnectionAppObject.svelte';
import UploadErrorModal from '../modals/UploadErrorModal.svelte';
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
import NewCollectionModal from '../modals/NewCollectionModal.svelte';
import ConfirmModal from '../modals/ConfirmModal.svelte';
import localforage from 'localforage';
@@ -73,7 +71,8 @@ registerCommand({
category: __t('command.theme', { defaultMessage: 'Theme' }),
name: __t('command.theme.change', { defaultMessage: 'Change' }),
toolbarName: __t('command.theme.changeToolbar', { defaultMessage: 'Change theme' }),
onClick: () => openNewTab({
onClick: () =>
openNewTab({
title: 'Settings',
icon: 'icon settings',
tabComponent: 'SettingsTab',
@@ -1230,8 +1229,7 @@ registerCommand({
},
});
if ( hasPermission('application-log'))
{
if (hasPermission('application-log')) {
registerCommand({
id: 'app.showLogs',
category: __t('command.application', { defaultMessage: 'Application' }),
@@ -1246,8 +1244,7 @@ if ( hasPermission('application-log'))
});
}
if (hasPermission('widgets/plugins'))
{
if (hasPermission('widgets/plugins')) {
registerCommand({
id: 'app.managePlugins',
category: __t('command.application', { defaultMessage: 'Application' }),

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import _ from 'lodash';
import { getBoolSettingsValue } from '../settings/settingsTools';
import { getStringSettingsValue } from '../settings/settingsTools';
import { stringifyCellValue } from 'dbgate-tools';
export let rowData;
@@ -13,7 +13,7 @@
value,
'gridCellIntent',
editorTypes,
{ useThousandsSeparator: getBoolSettingsValue('dataGrid.thousandsSeparator', false) },
{ thousandsSeparator: getStringSettingsValue('dataGrid.thousandsSeparatorChar', 'none') },
jsonParsedValue
);

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import _, { isPlainObject } from 'lodash';
import ShowFormButton from '../formview/ShowFormButton.svelte';
import { detectTypeIcon, getConvertValueMenu, isJsonLikeLongString, safeJsonParse } from 'dbgate-tools';
import { detectTypeIcon, getConvertValueMenu, isJsonLikeLongString, safeJsonParse, isTypeNumber } from 'dbgate-tools';
import { openJsonDocument } from '../tabs/JsonTab.svelte';
import CellValue from './CellValue.svelte';
import { openJsonLinesData } from '../utility/openJsonLinesData';
@@ -80,7 +80,7 @@
class:isFocusedColumn
class:hasOverlayValue
class:isMissingOverlayField
class:alignRight={_.isNumber(value) && !showHint}
class:alignRight={ (_.isNumber(value) || isTypeNumber(col.dataType)) && !showHint}
{style}
>
{#if hasOverlayValue}

View File

@@ -1,9 +1,12 @@
<script lang="ts">
import FontIcon from "../icons/FontIcon.svelte";
export let type;
export let label;
export let noMargin = false;
export let disabled = false;
export let labelProps: any = {};
export let labelIcon = null;
</script>
<div class="largeFormMarker" class:noMargin>
@@ -12,6 +15,9 @@
<span {...labelProps} on:click={labelProps.onClick} class:disabled class='checkLabel'>{label}</span>
{:else}
<div class="label" {...labelProps} on:click={labelProps.onClick}>
{#if labelIcon}
<FontIcon icon={labelIcon} padRight />
{/if}
<span {...labelProps} on:click={labelProps.onClick} class:disabled>{label}</span>
</div>
<slot />

View File

@@ -164,7 +164,12 @@
changeActiveSubmenu();
}}
>
<a on:click={e => handleClick(e, item)} class:disabled={item.disabled} class:bold={item.isBold}>
<a
on:click={e => handleClick(e, item)}
class:disabled={item.disabled}
class:bold={item.isBold}
data-testid={item.testid}
>
<span>
{#if item.switchValue && item.switchStoreGetter}
{#key switchIndex}

View File

@@ -1,81 +1,64 @@
<script lang="ts">
import CheckboxField from "../forms/CheckboxField.svelte";
import FormCheckboxField from "../forms/FormCheckboxField.svelte";
import FormFieldTemplateLarge from "../forms/FormFieldTemplateLarge.svelte";
import FormSelectField from "../forms/FormSelectField.svelte";
import FormTextField from "../forms/FormTextField.svelte";
import FormValues from "../forms/FormValues.svelte";
import { lockedDatabaseMode } from "../stores";
import { _t } from "../translations";
import CheckboxField from '../forms/CheckboxField.svelte';
import FormCheckboxField from '../forms/FormCheckboxField.svelte';
import FormFieldTemplateLarge from '../forms/FormFieldTemplateLarge.svelte';
import FormSelectField from '../forms/FormSelectField.svelte';
import FormTextField from '../forms/FormTextField.svelte';
import FormValues from '../forms/FormValues.svelte';
import { lockedDatabaseMode } from '../stores';
import { _t } from '../translations';
</script>
<div class="wrapper">
<FormValues let:values>
<FormValues let:values>
<div class="heading">{_t('settings.connection', { defaultMessage: 'Connection' })}</div>
<FormFieldTemplateLarge
label={_t('settings.connection.showOnlyTabsFromSelectedDatabase', {
defaultMessage: 'Show only tabs from selected database',
})}
type="checkbox"
labelProps={{
onClick: () => {
$lockedDatabaseMode = !$lockedDatabaseMode;
},
}}
>
<CheckboxField checked={$lockedDatabaseMode} on:change={e => ($lockedDatabaseMode = e.target.checked)} data-testid="ConnectionSettings_lockedDatabaseMode"/>
</FormFieldTemplateLarge>
<FormCheckboxField
name="connection.autoRefresh"
label={_t('settings.connection.autoRefresh', {
name="connection.autoRefresh"
label={_t('settings.connection.autoRefresh', {
defaultMessage: 'Automatic refresh of database model on background',
})}
defaultValue={false}
})}
defaultValue={false}
/>
<FormTextField
name="connection.autoRefreshInterval"
label={_t('settings.connection.autoRefreshInterval', {
name="connection.autoRefreshInterval"
label={_t('settings.connection.autoRefreshInterval', {
defaultMessage: 'Interval between automatic DB structure reloads in seconds',
})}
defaultValue="30"
disabled={values['connection.autoRefresh'] === false}
})}
defaultValue="30"
disabled={values['connection.autoRefresh'] === false}
/>
<FormSelectField
label={_t('settings.connection.sshBindHost', { defaultMessage: 'Local host address for SSH connections' })}
name="connection.sshBindHost"
isNative
defaultValue="127.0.0.1"
options={[
label={_t('settings.connection.sshBindHost', { defaultMessage: 'Local host address for SSH connections' })}
name="connection.sshBindHost"
isNative
defaultValue="127.0.0.1"
options={[
{ value: '127.0.0.1', label: '127.0.0.1 (IPv4)' },
{ value: '::1', label: '::1 (IPv6)' },
{ value: 'localhost', label: 'localhost (domain name)' },
]}
]}
/>
<div class="heading">{_t('settings.session', { defaultMessage: 'Query sessions' })}</div>
<FormCheckboxField
name="session.autoClose"
label={_t('settings.session.autoClose', {
name="session.autoClose"
label={_t('settings.session.autoClose', {
defaultMessage: 'Automatic close query sessions after period without any activity',
})}
defaultValue={true}
})}
defaultValue={true}
/>
<FormTextField
name="session.autoCloseTimeout"
label={_t('settings.session.autoCloseTimeout', {
name="session.autoCloseTimeout"
label={_t('settings.session.autoCloseTimeout', {
defaultMessage: 'Interval, after which query session without activity is closed (in minutes)',
})}
defaultValue="15"
disabled={values['session.autoClose'] === false}
})}
defaultValue="15"
disabled={values['session.autoClose'] === false}
/>
</FormValues>
</FormValues>
</div>
<style>
.heading {
font-size: 20px;
@@ -84,12 +67,11 @@
margin-top: var(--dim-large-form-margin);
}
.wrapper :global(input){
.wrapper :global(input) {
max-width: 400px;
}
.wrapper :global(select){
.wrapper :global(select) {
max-width: 400px;
}
</style>
</style>

View File

@@ -1,94 +1,105 @@
<script lang="ts">
import FormCheckboxField from "../forms/FormCheckboxField.svelte";
import FormSelectField from "../forms/FormSelectField.svelte";
import FormTextField from "../forms/FormTextField.svelte";
import { _t } from "../translations";
import { isProApp } from "../utility/proTools";
import FormCheckboxField from '../forms/FormCheckboxField.svelte';
import FormSelectField from '../forms/FormSelectField.svelte';
import FormTextField from '../forms/FormTextField.svelte';
import { _t } from '../translations';
import { isProApp } from '../utility/proTools';
</script>
<div class="wrapper">
<div class="heading">{_t('settings.dataGrid.title', { defaultMessage: 'Data grid' })}</div>
<FormTextField
name="dataGrid.pageSize"
label={_t('settings.dataGrid.pageSize', {
defaultMessage: 'Page size (number of rows for incremental loading, must be between 5 and 50000)',
})}
defaultValue="100"
/>
{#if isProApp()}
<FormCheckboxField
name="dataGrid.showHintColumns"
label={_t('settings.dataGrid.showHintColumns', { defaultMessage: 'Show foreign key hints' })}
defaultValue={true}
data-testid="DataGridSettings_showHintColumns"
/>
{/if}
<!-- <FormCheckboxField name="dataGrid.showHintColumns" label="Show foreign key hints" defaultValue={true} /> -->
<div class="heading">{_t('settings.dataGrid.title', { defaultMessage: 'Data grid' })}</div>
<FormTextField
name="dataGrid.pageSize"
label={_t('settings.dataGrid.pageSize', {
defaultMessage: 'Page size (number of rows for incremental loading, must be between 5 and 50000)',
})}
defaultValue="100"
/>
{#if isProApp()}
<FormCheckboxField
name="dataGrid.showHintColumns"
label={_t('settings.dataGrid.showHintColumns', { defaultMessage: 'Show foreign key hints' })}
defaultValue={true}
data-testid="DataGridSettings_showHintColumns"
/>
{/if}
<!-- <FormCheckboxField name="dataGrid.showHintColumns" label="Show foreign key hints" defaultValue={true} /> -->
<FormCheckboxField
name="dataGrid.thousandsSeparator"
label={_t('settings.dataGrid.thousandsSeparator', {
defaultMessage: 'Use thousands separator for numbers',
})}
/>
<FormSelectField
label={_t('settings.dataGrid.thousandsSeparator', { defaultMessage: 'Thousands separator for numbers' })}
name="dataGrid.thousandsSeparatorChar"
isNative
defaultValue="none"
options={[
{ value: 'none', label: _t('settings.dataGrid.thousandsSeparator.none', { defaultMessage: 'None' }) },
{ value: 'system', label: _t('settings.dataGrid.thousandsSeparator.system', { defaultMessage: 'System' }) },
{ value: 'space', label: _t('settings.dataGrid.thousandsSeparator.space', { defaultMessage: 'Space' }) },
{
value: 'narrowspace',
label: _t('settings.dataGrid.thousandsSeparator.narrowSpace', {
defaultMessage: 'Narrow space',
}),
},
{ value: 'comma', label: _t('settings.dataGrid.thousandsSeparator.comma', { defaultMessage: 'Comma (,)' }) },
{ value: 'dot', label: _t('settings.dataGrid.thousandsSeparator.dot', { defaultMessage: 'Dot (.)' }) },
]}
/>
<FormTextField
name="dataGrid.defaultAutoRefreshInterval"
label={_t('settings.dataGrid.defaultAutoRefreshInterval', {
defaultMessage: 'Default grid auto refresh interval in seconds',
})}
defaultValue="10"
/>
<FormTextField
name="dataGrid.defaultAutoRefreshInterval"
label={_t('settings.dataGrid.defaultAutoRefreshInterval', {
defaultMessage: 'Default grid auto refresh interval in seconds',
})}
defaultValue="10"
/>
<FormCheckboxField
name="dataGrid.alignNumbersRight"
label={_t('settings.dataGrid.alignNumbersRight', { defaultMessage: 'Align numbers to right' })}
defaultValue={false}
/>
<FormCheckboxField
name="dataGrid.alignNumbersRight"
label={_t('settings.dataGrid.alignNumbersRight', { defaultMessage: 'Align numbers to right' })}
defaultValue={false}
/>
<FormTextField
name="dataGrid.collectionPageSize"
label={_t('settings.dataGrid.collectionPageSize', {
defaultMessage: 'Collection page size (for MongoDB JSON view, must be between 5 and 1000)',
})}
defaultValue="50"
/>
<FormTextField
name="dataGrid.collectionPageSize"
label={_t('settings.dataGrid.collectionPageSize', {
defaultMessage: 'Collection page size (for MongoDB JSON view, must be between 5 and 1000)',
})}
defaultValue="50"
/>
<FormSelectField
label={_t('settings.dataGrid.coloringMode', { defaultMessage: 'Row coloring mode' })}
name="dataGrid.coloringMode"
isNative
defaultValue="36"
options={[
{
value: '36',
label: _t('settings.dataGrid.coloringMode.36', { defaultMessage: 'Every 3rd and 6th row' }),
},
{
value: '2-primary',
label: _t('settings.dataGrid.coloringMode.2-primary', {
defaultMessage: 'Every 2-nd row, primary color',
}),
},
{
value: '2-secondary',
label: _t('settings.dataGrid.coloringMode.2-secondary', {
defaultMessage: 'Every 2-nd row, secondary color',
}),
},
{ value: 'none', label: _t('settings.dataGrid.coloringMode.none', { defaultMessage: 'None' }) },
]}
/>
<FormSelectField
label={_t('settings.dataGrid.coloringMode', { defaultMessage: 'Row coloring mode' })}
name="dataGrid.coloringMode"
isNative
defaultValue="36"
options={[
{
value: '36',
label: _t('settings.dataGrid.coloringMode.36', { defaultMessage: 'Every 3rd and 6th row' }),
},
{
value: '2-primary',
label: _t('settings.dataGrid.coloringMode.2-primary', {
defaultMessage: 'Every 2-nd row, primary color',
}),
},
{
value: '2-secondary',
label: _t('settings.dataGrid.coloringMode.2-secondary', {
defaultMessage: 'Every 2-nd row, secondary color',
}),
},
{ value: 'none', label: _t('settings.dataGrid.coloringMode.none', { defaultMessage: 'None' }) },
]}
/>
<FormCheckboxField
name="dataGrid.showAllColumnsWhenSearch"
label={_t('settings.dataGrid.showAllColumnsWhenSearch', {
defaultMessage: 'Show all columns when searching',
})}
defaultValue={false}
/>
<FormCheckboxField
name="dataGrid.showAllColumnsWhenSearch"
label={_t('settings.dataGrid.showAllColumnsWhenSearch', {
defaultMessage: 'Show all columns when searching',
})}
defaultValue={false}
/>
</div>
<style>
@@ -99,11 +110,11 @@ defaultValue={false}
margin-top: var(--dim-large-form-margin);
}
.wrapper :global(select){
.wrapper :global(select) {
max-width: 400px;
}
.wrapper :global(input){
.wrapper :global(input) {
max-width: 400px;
}
</style>
</style>

View File

@@ -10,6 +10,9 @@
import { isMac } from '../utility/common';
import getElectron from '../utility/getElectron';
import ConfirmModal from '../modals/ConfirmModal.svelte';
import hasPermission from '../utility/hasPermission';
import CheckboxField from '../forms/CheckboxField.svelte';
import { lockedDatabaseMode } from '../stores';
const electron = getElectron();
let restartWarning = false;
@@ -17,7 +20,11 @@
<div class="wrapper">
<div class="heading">{_t('settings.application', { defaultMessage: 'Application' })}</div>
<FormFieldTemplateLarge label={_t('settings.localization.language', { defaultMessage: 'Language' })} type="combo">
<FormFieldTemplateLarge
label={_t('settings.localization.language', { defaultMessage: 'Language' })}
type="combo"
labelIcon="mdi mdi-translate"
>
<SelectField
isNative
data-testid="SettingsModal_languageSelect"
@@ -78,6 +85,24 @@
/>
{/if}
<FormFieldTemplateLarge
label={_t('settings.connection.showOnlyTabsFromSelectedDatabase', {
defaultMessage: 'Show only tabs from selected database',
})}
type="checkbox"
labelProps={{
onClick: () => {
$lockedDatabaseMode = !$lockedDatabaseMode;
},
}}
>
<CheckboxField
checked={$lockedDatabaseMode}
on:change={e => ($lockedDatabaseMode = e.target['checked'])}
data-testid="GeneralSettings_lockedDatabaseMode"
/>
</FormFieldTemplateLarge>
<div class="heading">{_t('settings.appearance', { defaultMessage: 'Appearance' })}</div>
{#if electron}
@@ -106,6 +131,7 @@
defaultMessage: 'Show server name alongside database name in title of the tab group',
})}
defaultValue={false}
disabled={!hasPermission('settings/change')}
/>
</div>

View File

@@ -29,6 +29,13 @@ export function getStringSettingsValue(name, defaultValue) {
return res;
}
export function getObjectSettingsValue(name, defaultValue) {
const settings = getCurrentSettings();
const res = settings[name];
if (res == null) return defaultValue;
return res;
}
export function getConnectionClickActionSetting(): 'connect' | 'openDetails' | 'none' {
return getStringSettingsValue('defaultAction.connectionClick', 'connect');
}

View File

@@ -3,111 +3,114 @@
</script>
<script lang="ts">
import SettingsMenuControl from "../elements/SettingsMenuControl.svelte";
import GeneralSettings from "../settings/GeneralSettings.svelte";
import SettingsFormProvider from "../forms/SettingsFormProvider.svelte";
import ConnectionSettings from "../settings/ConnectionSettings.svelte";
import ThemeSettings from "../settings/ThemeSettings.svelte";
import DefaultActionsSettings from "../settings/DefaultActionsSettings.svelte";
import BehaviourSettings from "../settings/BehaviourSettings.svelte";
import ExternalToolsSettings from "../settings/ExternalToolsSettings.svelte";
import LicenseSettings from "../settings/LicenseSettings.svelte";
import { isProApp } from "../utility/proTools";
import { _t } from "../translations";
import CommandListTab from "./CommandListTab.svelte";
import DataGridSettings from "../settings/DataGridSettings.svelte";
import SQLEditorSettings from "../settings/SQLEditorSettings.svelte";
import AiSettingsTab from "../settings/AiSettingsTab.svelte";
import SettingsMenuControl from '../elements/SettingsMenuControl.svelte';
import GeneralSettings from '../settings/GeneralSettings.svelte';
import SettingsFormProvider from '../forms/SettingsFormProvider.svelte';
import ConnectionSettings from '../settings/ConnectionSettings.svelte';
import ThemeSettings from '../settings/ThemeSettings.svelte';
import DefaultActionsSettings from '../settings/DefaultActionsSettings.svelte';
import BehaviourSettings from '../settings/BehaviourSettings.svelte';
import ExternalToolsSettings from '../settings/ExternalToolsSettings.svelte';
import LicenseSettings from '../settings/LicenseSettings.svelte';
import { isProApp } from '../utility/proTools';
import { _t } from '../translations';
import CommandListTab from './CommandListTab.svelte';
import DataGridSettings from '../settings/DataGridSettings.svelte';
import SQLEditorSettings from '../settings/SQLEditorSettings.svelte';
import AiSettingsTab from '../settings/AiSettingsTab.svelte';
import hasPermission from '../utility/hasPermission';
export let selectedItem = 'general';
export let selectedItem = 'general';
const menuItems = [
{
label: _t('settings.general', { defaultMessage: 'General' }),
identifier: 'general',
component: GeneralSettings,
props: {},
testid: 'settings-general',
},
{
label: _t('settings.connection', { defaultMessage: 'Connection' }),
identifier: 'connection',
component: ConnectionSettings,
props: {},
testid: 'settings-connection',
},
{
label: _t('settings.dataGrid.title', { defaultMessage: 'Data grid' }),
identifier: 'data-grid',
component: DataGridSettings,
props: {},
testid: 'settings-data-grid',
},
{
label: _t('settings.sqlEditor.title', { defaultMessage: 'SQL Editor' }),
identifier: 'sql-editor',
component: SQLEditorSettings,
props: {},
testid: 'settings-sql-editor',
},
{
label: _t('settings.theme', { defaultMessage: 'Themes' }),
identifier: 'theme',
component: ThemeSettings,
props: {},
testid: 'settings-themes',
},
{
label: _t('settings.defaultActions', { defaultMessage: 'Default Actions' }),
identifier: 'default-actions',
component: DefaultActionsSettings,
props: {},
testid: 'settings-default-actions',
},
{
label: _t('settings.behaviour', { defaultMessage: 'Behaviour' }),
identifier: 'behaviour',
component: BehaviourSettings,
props: {},
testid: 'settings-behaviour',
},
{
label: _t('settings.externalTools', { defaultMessage: 'External Tools' }),
identifier: 'external-tools',
component: ExternalToolsSettings,
props: {},
testid: 'settings-external-tools',
},
{
label: _t('command.settings.shortcuts', { defaultMessage: 'Keyboard shortcuts' }),
identifier: 'shortcuts',
component: CommandListTab,
props: {},
testid: 'settings-shortcuts',
},
isProApp() && {
label: _t('settings.license', { defaultMessage: 'License' }),
identifier: 'license',
component: LicenseSettings,
props: {},
testid: 'settings-license',
},
isProApp() && {
label: _t('settings.AI', { defaultMessage: 'AI'}),
identifier: 'ai',
component: AiSettingsTab,
props: {},
testid: 'settings-ai',
},
];
const menuItems = [
{
label: _t('settings.general', { defaultMessage: 'General' }),
identifier: 'general',
component: GeneralSettings,
props: {},
testid: 'settings-general',
},
hasPermission('settings/change') && {
label: _t('settings.connection', { defaultMessage: 'Connection' }),
identifier: 'connection',
component: ConnectionSettings,
props: {},
testid: 'settings-connection',
},
hasPermission('settings/change') && {
label: _t('settings.dataGrid.title', { defaultMessage: 'Data grid' }),
identifier: 'data-grid',
component: DataGridSettings,
props: {},
testid: 'settings-data-grid',
},
hasPermission('settings/change') && {
label: _t('settings.sqlEditor.title', { defaultMessage: 'SQL Editor' }),
identifier: 'sql-editor',
component: SQLEditorSettings,
props: {},
testid: 'settings-sql-editor',
},
{
label: _t('settings.theme', { defaultMessage: 'Themes' }),
identifier: 'theme',
component: ThemeSettings,
props: {},
testid: 'settings-themes',
},
hasPermission('settings/change') && {
label: _t('settings.defaultActions', { defaultMessage: 'Default Actions' }),
identifier: 'default-actions',
component: DefaultActionsSettings,
props: {},
testid: 'settings-default-actions',
},
hasPermission('settings/change') && {
label: _t('settings.behaviour', { defaultMessage: 'Behaviour' }),
identifier: 'behaviour',
component: BehaviourSettings,
props: {},
testid: 'settings-behaviour',
},
hasPermission('settings/change') && {
label: _t('settings.externalTools', { defaultMessage: 'External Tools' }),
identifier: 'external-tools',
component: ExternalToolsSettings,
props: {},
testid: 'settings-external-tools',
},
hasPermission('settings/change') && {
label: _t('command.settings.shortcuts', { defaultMessage: 'Keyboard shortcuts' }),
identifier: 'shortcuts',
component: CommandListTab,
props: {},
testid: 'settings-shortcuts',
},
hasPermission('settings/change') &&
isProApp() && {
label: _t('settings.license', { defaultMessage: 'License' }),
identifier: 'license',
component: LicenseSettings,
props: {},
testid: 'settings-license',
},
hasPermission('settings/change') &&
isProApp() && {
label: _t('settings.AI', { defaultMessage: 'AI' }),
identifier: 'ai',
component: AiSettingsTab,
props: {},
testid: 'settings-ai',
},
];
</script>
<SettingsFormProvider>
<SettingsMenuControl
items={menuItems}
bind:value={selectedItem}
flex1={true}
flexColContainer={true}
scrollableContentContainer={true}
<SettingsMenuControl
items={menuItems}
bind:value={selectedItem}
flex1={true}
flexColContainer={true}
scrollableContentContainer={true}
/>
</SettingsFormProvider>
</SettingsFormProvider>

View File

@@ -166,6 +166,7 @@ export function getDatabasStatusMenu(dbid, driver = null) {
apiCall('database-connections/sync-model', dbid);
callSchemalListChanged();
},
testid: 'DatabasStatusMenu_refreshIncremental',
},
{
text: driver?.supportsIncrementalAnalysis
@@ -175,6 +176,7 @@ export function getDatabasStatusMenu(dbid, driver = null) {
apiCall('database-connections/sync-model', { ...dbid, isFullRefresh: true });
callSchemalListChanged();
},
testid: 'DatabasStatusMenu_refreshFull',
},
{
text: _t('command.database.reopenConnection', { defaultMessage: 'Reopen connection' }),
@@ -182,6 +184,7 @@ export function getDatabasStatusMenu(dbid, driver = null) {
apiCall('database-connections/refresh', dbid);
callSchemalListChanged();
},
testid: 'DatabasStatusMenu_reopenConnection',
},
{
text: _t('command.database.disconnect', { defaultMessage: 'Disconnect' }),
@@ -190,6 +193,7 @@ export function getDatabasStatusMenu(dbid, driver = null) {
if (electron) apiCall('database-connections/disconnect', dbid);
switchCurrentDatabase(null);
},
testid: 'DatabasStatusMenu_disconnect',
},
]);
}

View File

@@ -171,6 +171,7 @@
"command.database.databaseSearch": "Vyhledávání v databázi",
"command.database.disconnect": "Odpojit",
"command.database.export": "Exportovat databázi",
"command.database.refresh": "Obnovit strukturu DB",
"command.database.refreshFull": "Obnovit strukturu DB (úplně)",
"command.database.refreshIncremental": "Obnovit strukturu DB (inkrementálně)",
"command.database.reopenConnection": "Znovu otevřít připojení",
@@ -1198,6 +1199,7 @@
"settings.sqlEditor.sqlCommandsCase": "Velikost písmen SQL příkazů",
"settings.sqlEditor.title": "SQL editor",
"settings.tabGroup.showServerName": "Zobrazit název serveru vedle názvu databáze v záhlaví skupiny karet",
"settings.tabPreviewMode": "Režim náhledu karet",
"settings.theme": "Vzhled",
"settings.title": "Nastavení",
"settings.useNativeWindowTitle": "Použít nativní titulek okna",

View File

@@ -171,6 +171,7 @@
"command.database.databaseSearch": "Datenbanksuche",
"command.database.disconnect": "Trennen",
"command.database.export": "Datenbank exportieren",
"command.database.refresh": "DB-Struktur aktualisieren",
"command.database.refreshFull": "DB-Struktur aktualisieren (vollständig)",
"command.database.refreshIncremental": "DB-Struktur aktualisieren (inkrementell)",
"command.database.reopenConnection": "Verbindung erneut öffnen",
@@ -1198,6 +1199,7 @@
"settings.sqlEditor.sqlCommandsCase": "Groß-/Kleinschreibung der SQL-Befehle",
"settings.sqlEditor.title": "SQL-Editor",
"settings.tabGroup.showServerName": "Servername neben Datenbankname im Titel der Tab-Gruppe anzeigen",
"settings.tabPreviewMode": "Tab-Vorschaumodus",
"settings.theme": "Designs",
"settings.title": "Einstellungen",
"settings.useNativeWindowTitle": "Nativen Fenstertitel verwenden",

View File

@@ -167,6 +167,7 @@
"command.database.databaseSearch": "Database search",
"command.database.disconnect": "Disconnect",
"command.database.export": "Export database",
"command.database.refresh": "Refresh DB structure",
"command.database.refreshFull": "Refresh DB structure (full)",
"command.database.refreshIncremental": "Refresh DB structure (incremental)",
"command.database.reopenConnection": "Reopen connection",
@@ -1190,6 +1191,7 @@
"settings.sqlEditor.sqlCommandsCase": "SQL commands case",
"settings.sqlEditor.title": "SQL Editor",
"settings.tabGroup.showServerName": "Show server name alongside database name in title of the tab group",
"settings.tabPreviewMode": "Tab Preview Mode",
"settings.theme": "Themes",
"settings.useNativeWindowTitle": "Use native window title",
"settings.useSystemNativeMenu": "Use system native menu",

View File

@@ -171,6 +171,7 @@
"command.database.databaseSearch": "Búsqueda en base de datos",
"command.database.disconnect": "Desconectar",
"command.database.export": "Exportar base de datos",
"command.database.refresh": "Refrescar estructura de BD",
"command.database.refreshFull": "Refrescar estructura de BD (completa)",
"command.database.refreshIncremental": "Refrescar estructura de BD (incremental)",
"command.database.reopenConnection": "Reabrir conexión",
@@ -1198,6 +1199,7 @@
"settings.sqlEditor.sqlCommandsCase": "Mayúsculas/minúsculas de comandos SQL",
"settings.sqlEditor.title": "Editor SQL",
"settings.tabGroup.showServerName": "Mostrar nombre del servidor junto con nombre de base de datos en el título del grupo de pestañas",
"settings.tabPreviewMode": "Modo de vista previa de pestaña",
"settings.theme": "Temas",
"settings.title": "Configuración",
"settings.useNativeWindowTitle": "Usar título de ventana nativo",

View File

@@ -171,6 +171,7 @@
"command.database.databaseSearch": "Recherche dans la base de données",
"command.database.disconnect": "Déconnecter",
"command.database.export": "Exporter la base de données",
"command.database.refresh": "Rafraîchir la structure de BD",
"command.database.refreshFull": "Rafraîchir la structure de BD (complète)",
"command.database.refreshIncremental": "Rafraîchir la structure de BD (incrémentale)",
"command.database.reopenConnection": "Rouvrir la connexion",
@@ -1198,6 +1199,7 @@
"settings.sqlEditor.sqlCommandsCase": "Casse des commandes SQL",
"settings.sqlEditor.title": "Éditeur SQL",
"settings.tabGroup.showServerName": "Afficher le nom du serveur à côté du nom de la base de données dans le titre du groupe d'onglets",
"settings.tabPreviewMode": "Mode aperçu d'onglet",
"settings.theme": "Thèmes",
"settings.title": "Paramètres",
"settings.useNativeWindowTitle": "Utiliser le titre de fenêtre natif",

View File

@@ -171,6 +171,7 @@
"command.database.databaseSearch": "Ricerca database",
"command.database.disconnect": "Disconnetti",
"command.database.export": "Esporta database",
"command.database.refresh": "Aggiorna struttura DB",
"command.database.refreshFull": "Aggiorna struttura DB (completo)",
"command.database.refreshIncremental": "Aggiorna struttura DB (incrementale)",
"command.database.reopenConnection": "Riapri connessione",
@@ -1198,6 +1199,7 @@
"settings.sqlEditor.sqlCommandsCase": "Maiuscole/minuscole comandi SQL",
"settings.sqlEditor.title": "Editor SQL",
"settings.tabGroup.showServerName": "Mostra nome server accanto al nome database nel titolo del gruppo schede",
"settings.tabPreviewMode": "Modalità anteprima scheda",
"settings.theme": "Temi",
"settings.title": "Impostazioni",
"settings.useNativeWindowTitle": "Usa titolo finestra nativo",

View File

@@ -171,6 +171,7 @@
"command.database.databaseSearch": "データベース検索",
"command.database.disconnect": "切断",
"command.database.export": "データベースをエクスポート",
"command.database.refresh": "DB構造を更新",
"command.database.refreshFull": "DB構造を更新フル",
"command.database.refreshIncremental": "DB構造を更新増分",
"command.database.reopenConnection": "接続を再度開く",
@@ -1198,6 +1199,7 @@
"settings.sqlEditor.sqlCommandsCase": "SQLコマンドの大文字小文字",
"settings.sqlEditor.title": "SQLエディター",
"settings.tabGroup.showServerName": "タブグループのタイトルにデータベース名と並んでサーバー名を表示",
"settings.tabPreviewMode": "タブプレビューモード",
"settings.theme": "テーマ",
"settings.title": "設定",
"settings.useNativeWindowTitle": "ネイティブウィンドウタイトルを使用",

View File

@@ -171,6 +171,7 @@
"command.database.databaseSearch": "Pesquisar banco de dados",
"command.database.disconnect": "Desconectar",
"command.database.export": "Exportar banco de dados",
"command.database.refresh": "Atualizar estrutura do BD",
"command.database.refreshFull": "Atualizar estrutura do BD (completa)",
"command.database.refreshIncremental": "Atualizar estrutura do BD (incremental)",
"command.database.reopenConnection": "Reabrir conexão",
@@ -1198,6 +1199,7 @@
"settings.sqlEditor.sqlCommandsCase": "Maiúsculas/minúsculas de comandos SQL",
"settings.sqlEditor.title": "Editor SQL",
"settings.tabGroup.showServerName": "Mostrar nome do servidor junto ao nome do banco de dados no título do grupo de abas",
"settings.tabPreviewMode": "Modo de visualização de aba",
"settings.theme": "Temas",
"settings.title": "Configurações",
"settings.useNativeWindowTitle": "Usar título de janela nativo",

View File

@@ -171,6 +171,7 @@
"command.database.databaseSearch": "Hľadanie v databáze",
"command.database.disconnect": "Odpojiť",
"command.database.export": "Exportovať databázu",
"command.database.refresh": "Obnoviť štruktúru DB",
"command.database.refreshFull": "Obnoviť štruktúru DB (úplne)",
"command.database.refreshIncremental": "Obnoviť štruktúru DB (inkrementálne)",
"command.database.reopenConnection": "Znovu otvoriť pripojenie",
@@ -1198,6 +1199,7 @@
"settings.sqlEditor.sqlCommandsCase": "Veľkosť písmen",
"settings.sqlEditor.title": "SQL editor",
"settings.tabGroup.showServerName": "Zobraziť názov servera vedľa názvu databázy v názve skupiny kariet",
"settings.tabPreviewMode": "Režim náhľadu kariet",
"settings.theme": "Vzhľad",
"settings.title": "Nastavenia",
"settings.useNativeWindowTitle": "Použiť natívne menu",

View File

@@ -171,6 +171,7 @@
"command.database.databaseSearch": "数据库搜索",
"command.database.disconnect": "断开连接",
"command.database.export": "导出数据库",
"command.database.refresh": "刷新数据库结构",
"command.database.refreshFull": "刷新数据库结构(完整)",
"command.database.refreshIncremental": "刷新数据库结构(增量)",
"command.database.reopenConnection": "重新打开连接",
@@ -1198,6 +1199,7 @@
"settings.sqlEditor.sqlCommandsCase": "SQL命令大小写",
"settings.sqlEditor.title": "SQL 编辑器",
"settings.tabGroup.showServerName": "在标签页组标题中显示服务器名称和数据库名称",
"settings.tabPreviewMode": "标签页预览模式",
"settings.theme": "主题",
"settings.title": "设置",
"settings.useNativeWindowTitle": "使用原生窗口标题",

View File

@@ -7,7 +7,7 @@ checkout-and-merge-pro:
repository: dbgate/dbgate-pro
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: 911941a53e91a5a777b8c7d455be0719234dde5f
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro