Compare commits
111 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| efaa4893bf | |||
| be8580cc4b | |||
| e43bb3123b | |||
| 0dba4ba653 | |||
| 758d8689ab | |||
| 2c14530e3c | |||
| 1f19d1925a | |||
| dedfe1f421 | |||
| 1cf583d197 | |||
| 63693f908d | |||
| 4489a54e82 | |||
| 6d48915945 | |||
| 00f3a7f4db | |||
| c5ebc01978 | |||
| f29b468fc1 | |||
| e796fbb990 | |||
| 37a122c981 | |||
| 4f426a73f6 | |||
| 1bcb74cd85 | |||
| cd88c8de78 | |||
| eee288b45b | |||
| 797cb7615d | |||
| ca4667ff1e | |||
| 66d1143ca0 | |||
| f310916c76 | |||
| 5d3d8ab932 | |||
| fd91c18460 | |||
| 2a12c04518 | |||
| d08cae6fa3 | |||
| d7f9de1881 | |||
| 962190cc57 | |||
| 4527866276 | |||
| 088dfcd4dc | |||
| 6c317b6e64 | |||
| 6b66c273b4 | |||
| 60f31008c0 | |||
| 078f74db97 | |||
| a0b025cf59 | |||
| bc695f5af9 | |||
| 9685e63b09 | |||
| 142791360c | |||
| e004ed2f4b | |||
| 23ed487252 | |||
| efefec3c20 | |||
| 3d2ad1cb9b | |||
| 90d3016938 | |||
| 438f9fc94d | |||
| 82ec88cc2f | |||
| 149611041e | |||
| b12c79462e | |||
| fbf34fb730 | |||
| e1fe3eb710 | |||
| 76ae2e0e5a | |||
| a57063adf7 | |||
| ff0157e624 | |||
| af9701feb8 | |||
| 93c1f31588 | |||
| 1964e54476 | |||
| 4682255d5f | |||
| a503898b21 | |||
| 21352dae07 | |||
| 8470c7ac6b | |||
| 28aa86f0aa | |||
| 3ed214269a | |||
| a71129df4b | |||
| de6acfa1ce | |||
| ccf075dc65 | |||
| 1d8ac3cf86 | |||
| 7a8ff89c5c | |||
| eda70def2a | |||
| 08fd75edc7 | |||
| 15ea53864f | |||
| 377cd64556 | |||
| b37744d574 | |||
| a7f21fe0c6 | |||
| 955ca99cf3 | |||
| 98f5bb4124 | |||
| b3943f005d | |||
| 8d4178b984 | |||
| 2a88ed38c4 | |||
| 52dce7dfd3 | |||
| 6ebee92542 | |||
| 1b5646f526 | |||
| 7024e4b40d | |||
| bc2e27d7da | |||
| 189da2bfe2 | |||
| 12e6afbaad | |||
| 142ebe3d27 | |||
| 7579f6e42a | |||
| 38c25cae74 | |||
| 408496eb7c | |||
| 4d61c74a8b | |||
| 190c610466 | |||
| 85b7e3ebe3 | |||
| d220525ac7 | |||
| 5e4a631ff2 | |||
| 9099ce42b9 | |||
| df226fea22 | |||
| 851d2e9151 | |||
| 89121a2608 | |||
| 23cf264d4d | |||
| b3130225b5 | |||
| 65512defed | |||
| 3b1c8748f1 | |||
| aba660eddb | |||
| 137eac7dbf | |||
| fdbd08f511 | |||
| ace1cec1f6 | |||
| fa5fda0c3b | |||
| 251609e274 | |||
| c0287e49d8 |
@@ -43,7 +43,7 @@ jobs:
|
||||
repository: dbgate/dbgate-pro
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: dbgate-pro
|
||||
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
|
||||
ref: 2a71bec538f8e2cf6c1cd1322d89e64346a139fd
|
||||
- name: Merge dbgate/dbgate-pro
|
||||
run: |
|
||||
mkdir ../dbgate-pro
|
||||
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
repository: dbgate/dbgate-pro
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: dbgate-pro
|
||||
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
|
||||
ref: 2a71bec538f8e2cf6c1cd1322d89e64346a139fd
|
||||
- name: Merge dbgate/dbgate-pro
|
||||
run: |
|
||||
mkdir ../dbgate-pro
|
||||
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
repository: dbgate/dbgate-pro
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: dbgate-pro
|
||||
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
|
||||
ref: 2a71bec538f8e2cf6c1cd1322d89e64346a139fd
|
||||
- name: Merge dbgate/dbgate-pro
|
||||
run: |
|
||||
mkdir ../dbgate-pro
|
||||
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
repository: dbgate/dbgate-pro
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: dbgate-pro
|
||||
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
|
||||
ref: 2a71bec538f8e2cf6c1cd1322d89e64346a139fd
|
||||
- name: Merge dbgate/dbgate-pro
|
||||
run: |
|
||||
mkdir ../dbgate-pro
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
repository: dbgate/dbgate-pro
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: dbgate-pro
|
||||
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
|
||||
ref: 2a71bec538f8e2cf6c1cd1322d89e64346a139fd
|
||||
- name: Merge dbgate/dbgate-pro
|
||||
run: |
|
||||
mkdir ../dbgate-pro
|
||||
|
||||
@@ -9,6 +9,9 @@ name: Cypress tests with screenshots PREMIUM
|
||||
- develop
|
||||
- feature/**
|
||||
- hotfix/**
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
e2e-tests:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -26,7 +29,7 @@ jobs:
|
||||
repository: dbgate/dbgate-pro
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: dbgate-pro
|
||||
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
|
||||
ref: 2a71bec538f8e2cf6c1cd1322d89e64346a139fd
|
||||
- name: Merge dbgate/dbgate-pro
|
||||
run: |
|
||||
mkdir ../dbgate-pro
|
||||
|
||||
@@ -9,6 +9,9 @@ name: Integration and unit tests
|
||||
- develop
|
||||
- feature/**
|
||||
- hotfix/**
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
all-tests:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
+22
-1
@@ -8,6 +8,27 @@ Builds:
|
||||
- linux - application for linux
|
||||
- win - application for Windows
|
||||
|
||||
## 6.8.1
|
||||
- FIXED: Won't navigate to the relevant field on click of a field in columns #1303
|
||||
|
||||
## 6.8.0
|
||||
- ADDED: Form cell view for detailed data inspection and editing in data grids, with multi-row bulk editing support
|
||||
- CHANGED: Cell data sidebar moved to right side, now is part of data grid
|
||||
- FIXED: Improved widget resizing algorithm
|
||||
- FIXED: Word wrap feature in SQL editor
|
||||
- CHANGED: Data grid keyboard navigation improvements
|
||||
- CHANGED: Improved PostgreSQL decimal type support in data grid #1214
|
||||
- ADDED: Retrieve number of databases from Redis configuration #1278
|
||||
- ADDED: Run macro context menu (Premium)
|
||||
- ADDED: Support for skip update columns in replicator
|
||||
- FIXED: UTF-8 BOM handling in CSV input
|
||||
- CHANGED: Advanced export is now part of Community edition
|
||||
- FIXED: SQLite foreign key constraint types
|
||||
- FIXED: Double drop constraint issue
|
||||
- CHANGED: Improved map view lat/lon field autodetection
|
||||
- FIXED: Alter table operations and constraint sanitization
|
||||
- ADDED: Import connections from environment variables (Team Premium)
|
||||
|
||||
## 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
|
||||
@@ -79,7 +100,7 @@ Builds:
|
||||
- ADDED: SQL AI assistant - powered by database chat, could help you to write SQL queries (Premium)
|
||||
- ADDED: Explain SQL error (powered by AI) (Premium)
|
||||
- ADDED: Database chat (and SQL AI Assistant) now supports showing charts (Premium)
|
||||
- FIXED: Fxied editing new files and roles (Team Premium)
|
||||
- FIXED: Fixed editing new files and roles (Team Premium)
|
||||
- FIXED: Connection to standalone database could be now pinned
|
||||
- FIXED: Cannot open up large JSON file #1215
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ describe('Data browser data', () => {
|
||||
cy.themeshot('query-editor-join-wizard');
|
||||
});
|
||||
|
||||
it('Mongo JSON data view', () => {
|
||||
it('Mongo query JSON data view', () => {
|
||||
cy.contains('Mongo-connection').click();
|
||||
cy.contains('MgChinook').click();
|
||||
cy.contains('Customer').click();
|
||||
@@ -213,9 +213,10 @@ describe('Data browser data', () => {
|
||||
cy.contains('Open query').click();
|
||||
cy.wait(1000);
|
||||
cy.contains('Execute').click();
|
||||
cy.testid('WidgetIconPanel_cell-data').click();
|
||||
cy.testid('TabContent_1').contains('Leonie').rightclick();
|
||||
cy.contains('Show cell data').click();
|
||||
// test JSON view
|
||||
cy.contains('Country: "Brazil"');
|
||||
cy.contains('Country: "Germany"');
|
||||
cy.themeshot('mongo-query-json-view');
|
||||
});
|
||||
|
||||
@@ -293,7 +294,8 @@ describe('Data browser data', () => {
|
||||
// cy.contains('location').click();
|
||||
cy.contains('14.2').click();
|
||||
cy.contains('13.9').click({ shiftKey: true });
|
||||
cy.testid('WidgetIconPanel_cell-data').click();
|
||||
cy.testid('WidgetIconPanel_database').click();
|
||||
cy.testid('TableDataTab_toggleCellDataView').click();
|
||||
cy.wait(2000);
|
||||
cy.themeshot('cell-map-view');
|
||||
});
|
||||
@@ -337,7 +339,7 @@ describe('Data browser data', () => {
|
||||
cy.themeshot('save-changes-mongodb');
|
||||
});
|
||||
|
||||
it('Edit mongo data JSON', () => {
|
||||
it('Mongo JSON cell view', () => {
|
||||
// TODO FIX: Auto expand cell view
|
||||
cy.contains('Mongo-connection').click();
|
||||
cy.contains('MgRivers').click();
|
||||
@@ -347,7 +349,8 @@ describe('Data browser data', () => {
|
||||
cy.testid('ColumnManagerRow_checkbox_countries.1').click();
|
||||
cy.testid('ColumnManagerRow_checkbox__id').click();
|
||||
cy.testid('DataFilterControl_input_countries.1').type('EXISTS{enter}');
|
||||
cy.testid('WidgetIconPanel_cell-data').click();
|
||||
cy.contains('Austria').click();
|
||||
cy.testid('CollectionDataTab_toggleCellDataView').click();
|
||||
cy.themeshot('mongodb-json-cell-view');
|
||||
});
|
||||
|
||||
@@ -472,4 +475,36 @@ describe('Data browser data', () => {
|
||||
cy.testid('DataDeployTab_importIntoDb').click();
|
||||
cy.themeshot('data-replicator');
|
||||
});
|
||||
|
||||
it('Form cell view', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Invoice').click();
|
||||
cy.get('[data-row="0"][data-col="header"]').click();
|
||||
cy.contains('Autodetect - Form');
|
||||
cy.themeshot('form-cell-view');
|
||||
});
|
||||
|
||||
it('Group by', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Album').click();
|
||||
cy.testid('WidgetIconPanel_database').click();
|
||||
cy.testid('ColumnHeaderControl_dropdown_ArtistId').click();
|
||||
cy.contains('Group by').click();
|
||||
cy.testid('ColumnHeaderControl_dropdown_Title').first().click();
|
||||
cy.themeshot('data-browser-group-by');
|
||||
});
|
||||
|
||||
it('Filter by expanded column', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Album').click();
|
||||
cy.testid('WidgetIconPanel_database').click();
|
||||
cy.testid('ColumnManagerRow_expand_ArtistId').click();
|
||||
cy.testid('ColumnManagerRow_checkbox_ArtistId.Name').click();
|
||||
cy.testid('ColumnManagerRow_checkbox_ArtistId').click();
|
||||
cy.testid('DataFilterControl_input_ArtistId.Name').type('mich{enter}');
|
||||
cy.themeshot('data-browser-filter-by-expanded');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -141,7 +141,7 @@ describe('Backup table', () => {
|
||||
cy.get('body').realType('111222333{enter}');
|
||||
|
||||
cy.testid('TableDataTab_save').click();
|
||||
cy.testid('ConfirmSqlModal_okButton').click();
|
||||
cy.testid('ConfirmSqlModal_okButton', { timeout: 10000 }).click();
|
||||
cy.contains('Rows: 11').should('be.visible'); // wait for save
|
||||
|
||||
cy.testid('app-object-group-items-table-backups').contains('addresses').rightclick();
|
||||
@@ -161,7 +161,7 @@ describe('Backup table', () => {
|
||||
// cy.testid('CloseTabModal_buttonConfirm').click();
|
||||
cy.wait(1000);
|
||||
|
||||
cy.testid('app-object-group-items-tables').contains('addresses').click();
|
||||
cy.testid('app-object-group-items-tables').contains('addresses', { timeout: 10000 }).click();
|
||||
|
||||
// check whether data was successfully restored
|
||||
cy.contains('Rows: 12').should('be.visible');
|
||||
@@ -237,7 +237,7 @@ describe('Import CSV - source error', () => {
|
||||
cy.testid('ImportExportTab_preview_content').contains('Invalid Closing Quote').should('be.visible');
|
||||
|
||||
cy.testid('ImportExportTab_executeButton').click();
|
||||
cy.testid('ImportExportConfigurator_errorInfoIcon_customers-20-err').click();
|
||||
cy.testid('ImportExportConfigurator_errorInfoIcon_customers-20-err', { timeout: 10000 }).click();
|
||||
|
||||
cy.testid('ErrorMessageModal_message').contains('Invalid Closing Quote').should('be.visible');
|
||||
});
|
||||
@@ -256,7 +256,7 @@ describe('Import CSV - target error', () => {
|
||||
cy.contains('customers-20');
|
||||
cy.testid('ImportExportConfigurator_targetName_customers-20').clear().type('system."]`');
|
||||
cy.testid('ImportExportTab_executeButton').click();
|
||||
cy.testid('ImportExportConfigurator_errorInfoIcon_customers-20').click();
|
||||
cy.testid('ImportExportConfigurator_errorInfoIcon_customers-20', { timeout: 10000 }).click();
|
||||
cy.testid('ErrorMessageModal_message').should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,13 +26,15 @@ function pickImportantTableInfo(engine, table) {
|
||||
.map(props =>
|
||||
_.omitBy(props, (v, k) => k == 'defaultValue' && v == 'NULL' && engine.setNullDefaultInsteadOfDrop)
|
||||
),
|
||||
// foreignKeys: table.foreignKeys
|
||||
// .sort((a, b) => a.refTableName.localeCompare(b.refTableName))
|
||||
// .map(fk => ({
|
||||
// constraintType: fk.constraintType,
|
||||
// refTableName: fk.refTableName,
|
||||
// columns: fk.columns.map(col => ({ columnName: col.columnName, refColumnName: col.refColumnName })),
|
||||
// })),
|
||||
|
||||
// TODO:
|
||||
foreignKeys: table.foreignKeys
|
||||
.sort((a, b) => a.refTableName.localeCompare(b.refTableName))
|
||||
.map(fk => ({
|
||||
constraintType: fk.constraintType,
|
||||
refTableName: fk.refTableName,
|
||||
columns: fk.columns.map(col => ({ columnName: col.columnName, refColumnName: col.refColumnName })),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -103,6 +105,7 @@ async function testTableDiff(engine, conn, driver, mangle, changedTable = 't1')
|
||||
|
||||
await driver.script(conn, sql);
|
||||
|
||||
// TODO:
|
||||
// if (!engine.skipIncrementalAnalysis) {
|
||||
// const structure2RealIncremental = await driver.analyseIncremental(conn, structure1Source);
|
||||
// checkTableStructure(engine, tget(structure2RealIncremental), tget(structure2));
|
||||
@@ -116,6 +119,7 @@ async function testTableDiff(engine, conn, driver, mangle, changedTable = 't1')
|
||||
|
||||
const TESTED_COLUMNS = ['col_pk', 'col_std', 'col_def', 'col_fk', 'col_ref', 'col_idx', 'col_uq'];
|
||||
// const TESTED_COLUMNS = ['col_pk'];
|
||||
// const TESTED_COLUMNS = ['col_fk'];
|
||||
// const TESTED_COLUMNS = ['col_idx'];
|
||||
// const TESTED_COLUMNS = ['col_def'];
|
||||
// const TESTED_COLUMNS = ['col_std'];
|
||||
@@ -179,11 +183,25 @@ describe('Alter table', () => {
|
||||
)(
|
||||
'Drop column - %s - %s',
|
||||
testWrapper(async (conn, driver, column, engine) => {
|
||||
await testTableDiff(engine, conn, driver, tbl => (tbl.columns = tbl.columns.filter(x => x.columnName != column)));
|
||||
await testTableDiff(engine, conn, driver,
|
||||
tbl => {
|
||||
tbl.columns = tbl.columns.filter(x => x.columnName != column);
|
||||
tbl.foreignKeys = tbl.foreignKeys
|
||||
.map(fk => ({
|
||||
...fk,
|
||||
columns: fk.columns.filter(col => col.columnName != column)
|
||||
}))
|
||||
.filter(fk => fk.columns.length > 0);
|
||||
}
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
test.each(createEnginesColumnsSource(engines.filter(x => !x.skipNullable && !x.skipChangeNullability)))(
|
||||
test.each(
|
||||
createEnginesColumnsSource(engines.filter(x => !x.skipNullability && !x.skipChangeNullability)).filter(
|
||||
([_label, col]) => !col.endsWith('_pk')
|
||||
)
|
||||
)(
|
||||
'Change nullability - %s - %s',
|
||||
testWrapper(async (conn, driver, column, engine) => {
|
||||
await testTableDiff(
|
||||
@@ -202,7 +220,11 @@ describe('Alter table', () => {
|
||||
engine,
|
||||
conn,
|
||||
driver,
|
||||
tbl => (tbl.columns = tbl.columns.map(x => (x.columnName == column ? { ...x, columnName: 'col_renamed' } : x)))
|
||||
tbl => {
|
||||
tbl.columns = tbl.columns.map(x => (x.columnName == column ? { ...x, columnName: 'col_renamed' } : x));
|
||||
tbl.foreignKeys = tbl.foreignKeys.map(fk => ({...fk, columns: fk.columns.map(col => col.columnName == column ? { ...col, columnName: 'col_renamed' } : col)
|
||||
}));
|
||||
}
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
@@ -303,4 +303,52 @@ describe('Data replicator', () => {
|
||||
}),
|
||||
15 * 1000
|
||||
);
|
||||
|
||||
test.each(engines.filter(x => !x.skipDataReplicator).map(engine => [engine.label, engine]))(
|
||||
'Skip columns for update - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
runCommandOnDriver(conn, driver, dmp =>
|
||||
dmp.createTable({
|
||||
pureName: 't1',
|
||||
columns: [
|
||||
{ columnName: 'id', dataType: 'int', autoIncrement: true, notNull: true },
|
||||
{ columnName: 'key', dataType: 'varchar(50)', notNull: true },
|
||||
{ columnName: 'val', dataType: 'varchar(50)' },
|
||||
],
|
||||
primaryKey: {
|
||||
columns: [{ columnName: 'id' }],
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
const getcfg = (v1 = 'v1') => ({
|
||||
systemConnection: conn,
|
||||
driver,
|
||||
items: [
|
||||
{
|
||||
name: 't1',
|
||||
matchColumns: ['key'],
|
||||
skipUpdateColumns: ['val'],
|
||||
findExisting: true,
|
||||
updateExisting: true,
|
||||
createNew: true,
|
||||
jsonArray: [
|
||||
{ key: '1', val: v1 },
|
||||
{ key: '2', val: 'v2' },
|
||||
{ key: '3', val: 'v3' },
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await dataReplicator(getcfg('v1'));
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select ~val from ~t1 where ~key='1'`));
|
||||
expect(res1.rows[0].val).toEqual('v1');
|
||||
|
||||
await dataReplicator(getcfg('v2'));
|
||||
const res2 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select ~val from ~t1 where ~key='1'`));
|
||||
expect(res2.rows[0].val).toEqual('v1');
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
@@ -44,7 +44,7 @@ services:
|
||||
# - 15942:9042
|
||||
#
|
||||
# clickhouse:
|
||||
# image: bitnami/clickhouse:24.8.4
|
||||
# image: bitnamilegacy/clickhouse:24.8.4
|
||||
# restart: always
|
||||
# ports:
|
||||
# - 15005:8123
|
||||
|
||||
@@ -22,7 +22,9 @@ async function connect(engine, database) {
|
||||
if (engine.generateDbFile) {
|
||||
const conn = await driver.connect({
|
||||
...connection,
|
||||
databaseFile: (engine.databaseFileLocationOnServer ?? 'dbtemp/') + database,
|
||||
databaseFile:
|
||||
(engine.databaseFileLocationOnServer ?? (process.env.CITEST ? 'dbtemp/' : 'integration-tests/dbtemp/')) +
|
||||
database,
|
||||
});
|
||||
return conn;
|
||||
} else {
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"version": "6.7.3",
|
||||
"version": "6.8.2",
|
||||
"name": "dbgate-all",
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
@@ -22,6 +22,7 @@
|
||||
"start:api:auth": "yarn workspace dbgate-api start:auth | pino-pretty",
|
||||
"start:api:dblogin": "yarn workspace dbgate-api start:dblogin | pino-pretty",
|
||||
"start:api:storage": "yarn workspace dbgate-api start:storage | pino-pretty",
|
||||
"start:api:sfill": "yarn workspace dbgate-api start:sfill | pino-pretty",
|
||||
"start:api:storage:built": "yarn workspace dbgate-api start:storage:built | pino-pretty",
|
||||
"start:api:azure": "yarn workspace dbgate-api start:azure | pino-pretty",
|
||||
"start:api:e2e:team": "yarn workspace dbgate-api start:e2e:team | pino-pretty",
|
||||
|
||||
Vendored
+46
@@ -0,0 +1,46 @@
|
||||
DEVMODE=1
|
||||
DEVWEB=1
|
||||
|
||||
STORAGE_SERVER=localhost
|
||||
STORAGE_USER=root
|
||||
STORAGE_PASSWORD=Pwd2020Db
|
||||
STORAGE_PORT=3306
|
||||
STORAGE_DATABASE=dbgate-filled
|
||||
STORAGE_ENGINE=mysql@dbgate-plugin-mysql
|
||||
|
||||
CONNECTIONS=mysql,postgres,mongo,redis
|
||||
|
||||
LABEL_mysql=MySql
|
||||
SERVER_mysql=dbgatedckstage1.sprinx.cz
|
||||
USER_mysql=root
|
||||
PASSWORD_mysql=Pwd2020Db
|
||||
PORT_mysql=3306
|
||||
ENGINE_mysql=mysql@dbgate-plugin-mysql
|
||||
|
||||
LABEL_postgres=Postgres
|
||||
SERVER_postgres=dbgatedckstage1.sprinx.cz
|
||||
USER_postgres=postgres
|
||||
PASSWORD_postgres=Pwd2020Db
|
||||
PORT_postgres=5432
|
||||
ENGINE_postgres=postgres@dbgate-plugin-postgres
|
||||
|
||||
LABEL_mongo=Mongo
|
||||
SERVER_mongo=dbgatedckstage1.sprinx.cz
|
||||
USER_mongo=root
|
||||
PASSWORD_mongo=Pwd2020Db
|
||||
PORT_mongo=27017
|
||||
ENGINE_mongo=mongo@dbgate-plugin-mongo
|
||||
|
||||
LABEL_redis=Redis
|
||||
SERVER_redis=dbgatedckstage1.sprinx.cz
|
||||
ENGINE_redis=redis@dbgate-plugin-redis
|
||||
PORT_redis=6379
|
||||
|
||||
ROLE_test1_CONNECTIONS=mysql
|
||||
ROLE_test1_PERMISSIONS=widgets/*
|
||||
ROLE_test1_DATABASES_db1_CONNECTION=mysql
|
||||
ROLE_test1_DATABASES_db1_PERMISSION=run_script
|
||||
ROLE_test1_DATABASES_db1_DATABASES=db1
|
||||
ROLE_test1_DATABASES_db2_CONNECTION=redis
|
||||
ROLE_test1_DATABASES_db2_PERMISSION=run_script
|
||||
ROLE_test1_DATABASES_db2_DATABASES=db2
|
||||
@@ -75,6 +75,7 @@
|
||||
"start:dblogin": "env-cmd -f env/dblogin/.env node src/index.js --listen-api",
|
||||
"start:filedb": "env-cmd node src/index.js /home/jena/test/chinook/Chinook.db --listen-api",
|
||||
"start:storage": "env-cmd -f env/storage/.env node src/index.js --listen-api",
|
||||
"start:sfill": "env-cmd -f env/sfill/.env node src/index.js --listen-api",
|
||||
"start:storage:built": "env-cmd -f env/storage/.env cross-env DEVMODE= BUILTWEBMODE=1 node dist/bundle.js --listen-api",
|
||||
"start:singleconn": "env-cmd node src/index.js --server localhost --user root --port 3307 --engine mysql@dbgate-plugin-mysql --password test --listen-api",
|
||||
"start:azure": "env-cmd -f env/azure/.env node src/index.js --listen-api",
|
||||
|
||||
@@ -23,6 +23,7 @@ const pipeForkLogs = require('../utility/pipeForkLogs');
|
||||
const requireEngineDriver = require('../utility/requireEngineDriver');
|
||||
const { getAuthProviderById } = require('../auth/authProvider');
|
||||
const { startTokenChecking } = require('../utility/authProxy');
|
||||
const { extractConnectionsFromEnv } = require('../utility/envtools');
|
||||
|
||||
const logger = getLogger('connections');
|
||||
|
||||
@@ -61,55 +62,7 @@ function getDatabaseFileLabel(databaseFile) {
|
||||
|
||||
function getPortalCollections() {
|
||||
if (process.env.CONNECTIONS) {
|
||||
const connections = _.compact(process.env.CONNECTIONS.split(',')).map(id => ({
|
||||
_id: id,
|
||||
engine: process.env[`ENGINE_${id}`],
|
||||
server: process.env[`SERVER_${id}`],
|
||||
user: process.env[`USER_${id}`],
|
||||
password: process.env[`PASSWORD_${id}`],
|
||||
passwordMode: process.env[`PASSWORD_MODE_${id}`],
|
||||
port: process.env[`PORT_${id}`],
|
||||
databaseUrl: process.env[`URL_${id}`],
|
||||
useDatabaseUrl: !!process.env[`URL_${id}`],
|
||||
databaseFile: process.env[`FILE_${id}`]?.replace(
|
||||
'%%E2E_TEST_DATA_DIRECTORY%%',
|
||||
path.join(path.dirname(path.dirname(__dirname)), 'e2e-tests', 'tmpdata')
|
||||
),
|
||||
socketPath: process.env[`SOCKET_PATH_${id}`],
|
||||
serviceName: process.env[`SERVICE_NAME_${id}`],
|
||||
authType: process.env[`AUTH_TYPE_${id}`] || (process.env[`SOCKET_PATH_${id}`] ? 'socket' : undefined),
|
||||
defaultDatabase:
|
||||
process.env[`DATABASE_${id}`] ||
|
||||
(process.env[`FILE_${id}`] ? getDatabaseFileLabel(process.env[`FILE_${id}`]) : null),
|
||||
singleDatabase: !!process.env[`DATABASE_${id}`] || !!process.env[`FILE_${id}`],
|
||||
displayName: process.env[`LABEL_${id}`],
|
||||
isReadOnly: process.env[`READONLY_${id}`],
|
||||
databases: process.env[`DBCONFIG_${id}`] ? safeJsonParse(process.env[`DBCONFIG_${id}`]) : null,
|
||||
allowedDatabases: process.env[`ALLOWED_DATABASES_${id}`]?.replace(/\|/g, '\n'),
|
||||
allowedDatabasesRegex: process.env[`ALLOWED_DATABASES_REGEX_${id}`],
|
||||
parent: process.env[`PARENT_${id}`] || undefined,
|
||||
useSeparateSchemas: !!process.env[`USE_SEPARATE_SCHEMAS_${id}`],
|
||||
localDataCenter: process.env[`LOCAL_DATA_CENTER_${id}`],
|
||||
|
||||
// SSH tunnel
|
||||
useSshTunnel: process.env[`USE_SSH_${id}`],
|
||||
sshHost: process.env[`SSH_HOST_${id}`],
|
||||
sshPort: process.env[`SSH_PORT_${id}`],
|
||||
sshMode: process.env[`SSH_MODE_${id}`],
|
||||
sshLogin: process.env[`SSH_LOGIN_${id}`],
|
||||
sshPassword: process.env[`SSH_PASSWORD_${id}`],
|
||||
sshKeyfile: process.env[`SSH_KEY_FILE_${id}`],
|
||||
sshKeyfilePassword: process.env[`SSH_KEY_FILE_PASSWORD_${id}`],
|
||||
|
||||
// SSL
|
||||
useSsl: process.env[`USE_SSL_${id}`],
|
||||
sslCaFile: process.env[`SSL_CA_FILE_${id}`],
|
||||
sslCertFile: process.env[`SSL_CERT_FILE_${id}`],
|
||||
sslCertFilePassword: process.env[`SSL_CERT_FILE_PASSWORD_${id}`],
|
||||
sslKeyFile: process.env[`SSL_KEY_FILE_${id}`],
|
||||
sslRejectUnauthorized: process.env[`SSL_REJECT_UNAUTHORIZED_${id}`],
|
||||
trustServerCertificate: process.env[`SSL_TRUST_CERTIFICATE_${id}`],
|
||||
}));
|
||||
const connections = extractConnectionsFromEnv(process.env);
|
||||
|
||||
for (const conn of connections) {
|
||||
for (const prop in process.env) {
|
||||
@@ -229,6 +182,15 @@ module.exports = {
|
||||
);
|
||||
}
|
||||
await this.checkUnsavedConnectionsLimit();
|
||||
|
||||
if (process.env.STORAGE_DATABASE && process.env.CONNECTIONS) {
|
||||
const storage = require('./storage');
|
||||
try {
|
||||
await storage.fillStorageConnectionsFromEnv();
|
||||
} catch (err) {
|
||||
logger.error(extractErrorLogData(err), 'DBGM-00268 Error filling storage connections from env');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
list_meta: true,
|
||||
|
||||
@@ -65,6 +65,8 @@ async function copyStream(input, output, options) {
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error(extractErrorLogData(err, { progressName }), 'DBGM-00157 Import/export job failed');
|
||||
|
||||
process.send({
|
||||
msgtype: 'copyStreamError',
|
||||
copyStreamError: {
|
||||
@@ -82,8 +84,6 @@ async function copyStream(input, output, options) {
|
||||
errorMessage: extractErrorMessage(err),
|
||||
});
|
||||
}
|
||||
|
||||
logger.error(extractErrorLogData(err, { progressName }), 'DBGM-00157 Import/export job failed');
|
||||
// throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ async function dataReplicator({
|
||||
createNew: compileOperationFunction(item.createNew, item.createCondition),
|
||||
updateExisting: compileOperationFunction(item.updateExisting, item.updateCondition),
|
||||
deleteMissing: !!item.deleteMissing,
|
||||
skipUpdateColumns: item.skipUpdateColumns,
|
||||
deleteRestrictionColumns: item.deleteRestrictionColumns ?? [],
|
||||
openStream: item.openStream
|
||||
? item.openStream
|
||||
|
||||
@@ -686,9 +686,34 @@ module.exports = {
|
||||
"columnName": "connectionDefinition",
|
||||
"dataType": "text",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"pureName": "connections",
|
||||
"columnName": "import_source_id",
|
||||
"dataType": "int",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"pureName": "connections",
|
||||
"columnName": "id_original",
|
||||
"dataType": "varchar(250)",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"constraintType": "foreignKey",
|
||||
"constraintName": "FK_connections_import_source_id",
|
||||
"pureName": "connections",
|
||||
"refTableName": "import_sources",
|
||||
"columns": [
|
||||
{
|
||||
"columnName": "import_source_id",
|
||||
"refColumnName": "id"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"foreignKeys": [],
|
||||
"primaryKey": {
|
||||
"pureName": "connections",
|
||||
"constraintType": "primaryKey",
|
||||
@@ -790,6 +815,41 @@ module.exports = {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"pureName": "import_sources",
|
||||
"columns": [
|
||||
{
|
||||
"pureName": "import_sources",
|
||||
"columnName": "id",
|
||||
"dataType": "int",
|
||||
"autoIncrement": true,
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"pureName": "import_sources",
|
||||
"columnName": "name",
|
||||
"dataType": "varchar(250)",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"foreignKeys": [],
|
||||
"primaryKey": {
|
||||
"pureName": "import_sources",
|
||||
"constraintType": "primaryKey",
|
||||
"constraintName": "PK_import_sources",
|
||||
"columns": [
|
||||
{
|
||||
"columnName": "id"
|
||||
}
|
||||
]
|
||||
},
|
||||
"preloadedRows": [
|
||||
{
|
||||
"id": -1,
|
||||
"name": "env"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"pureName": "roles",
|
||||
"columns": [
|
||||
@@ -805,9 +865,34 @@ module.exports = {
|
||||
"columnName": "name",
|
||||
"dataType": "varchar(250)",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"pureName": "roles",
|
||||
"columnName": "import_source_id",
|
||||
"dataType": "int",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"pureName": "roles",
|
||||
"columnName": "id_original",
|
||||
"dataType": "varchar(250)",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"constraintType": "foreignKey",
|
||||
"constraintName": "FK_roles_import_source_id",
|
||||
"pureName": "roles",
|
||||
"refTableName": "import_sources",
|
||||
"columns": [
|
||||
{
|
||||
"columnName": "import_source_id",
|
||||
"refColumnName": "id"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"foreignKeys": [],
|
||||
"primaryKey": {
|
||||
"pureName": "roles",
|
||||
"constraintType": "primaryKey",
|
||||
@@ -854,6 +939,12 @@ module.exports = {
|
||||
"columnName": "connection_id",
|
||||
"dataType": "int",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"pureName": "role_connections",
|
||||
"columnName": "import_source_id",
|
||||
"dataType": "int",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
@@ -882,6 +973,18 @@ module.exports = {
|
||||
"refColumnName": "id"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"constraintType": "foreignKey",
|
||||
"constraintName": "FK_role_connections_import_source_id",
|
||||
"pureName": "role_connections",
|
||||
"refTableName": "import_sources",
|
||||
"columns": [
|
||||
{
|
||||
"columnName": "import_source_id",
|
||||
"refColumnName": "id"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
@@ -934,6 +1037,18 @@ module.exports = {
|
||||
"columnName": "database_permission_role_id",
|
||||
"dataType": "int",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"pureName": "role_databases",
|
||||
"columnName": "import_source_id",
|
||||
"dataType": "int",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"pureName": "role_databases",
|
||||
"columnName": "id_original",
|
||||
"dataType": "varchar(250)",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
@@ -974,6 +1089,18 @@ module.exports = {
|
||||
"refColumnName": "id"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"constraintType": "foreignKey",
|
||||
"constraintName": "FK_role_databases_import_source_id",
|
||||
"pureName": "role_databases",
|
||||
"refTableName": "import_sources",
|
||||
"columns": [
|
||||
{
|
||||
"columnName": "import_source_id",
|
||||
"refColumnName": "id"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
@@ -1087,6 +1214,12 @@ module.exports = {
|
||||
"columnName": "permission",
|
||||
"dataType": "varchar(250)",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"pureName": "role_permissions",
|
||||
"columnName": "import_source_id",
|
||||
"dataType": "int",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
@@ -1102,6 +1235,18 @@ module.exports = {
|
||||
"refColumnName": "id"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"constraintType": "foreignKey",
|
||||
"constraintName": "FK_role_permissions_import_source_id",
|
||||
"pureName": "role_permissions",
|
||||
"refTableName": "import_sources",
|
||||
"columns": [
|
||||
{
|
||||
"columnName": "import_source_id",
|
||||
"refColumnName": "id"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
@@ -1184,6 +1329,18 @@ module.exports = {
|
||||
"columnName": "table_permission_scope_id",
|
||||
"dataType": "int",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"pureName": "role_tables",
|
||||
"columnName": "import_source_id",
|
||||
"dataType": "int",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"pureName": "role_tables",
|
||||
"columnName": "id_original",
|
||||
"dataType": "varchar(250)",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
@@ -1236,6 +1393,18 @@ module.exports = {
|
||||
"refColumnName": "id"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"constraintType": "foreignKey",
|
||||
"constraintName": "FK_role_tables_import_source_id",
|
||||
"pureName": "role_tables",
|
||||
"refTableName": "import_sources",
|
||||
"columns": [
|
||||
{
|
||||
"columnName": "import_source_id",
|
||||
"refColumnName": "id"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
|
||||
@@ -0,0 +1,454 @@
|
||||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
const { safeJsonParse, getDatabaseFileLabel } = require('dbgate-tools');
|
||||
const crypto = require('crypto');
|
||||
|
||||
function extractConnectionsFromEnv(env) {
|
||||
if (!env?.CONNECTIONS) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const connections = _.compact(env.CONNECTIONS.split(',')).map(id => ({
|
||||
_id: id,
|
||||
engine: env[`ENGINE_${id}`],
|
||||
server: env[`SERVER_${id}`],
|
||||
user: env[`USER_${id}`],
|
||||
password: env[`PASSWORD_${id}`],
|
||||
passwordMode: env[`PASSWORD_MODE_${id}`],
|
||||
port: env[`PORT_${id}`],
|
||||
databaseUrl: env[`URL_${id}`],
|
||||
useDatabaseUrl: !!env[`URL_${id}`],
|
||||
databaseFile: env[`FILE_${id}`]?.replace(
|
||||
'%%E2E_TEST_DATA_DIRECTORY%%',
|
||||
path.join(path.dirname(path.dirname(__dirname)), 'e2e-tests', 'tmpdata')
|
||||
),
|
||||
socketPath: env[`SOCKET_PATH_${id}`],
|
||||
serviceName: env[`SERVICE_NAME_${id}`],
|
||||
authType: env[`AUTH_TYPE_${id}`] || (env[`SOCKET_PATH_${id}`] ? 'socket' : undefined),
|
||||
defaultDatabase: env[`DATABASE_${id}`] || (env[`FILE_${id}`] ? getDatabaseFileLabel(env[`FILE_${id}`]) : null),
|
||||
singleDatabase: !!env[`DATABASE_${id}`] || !!env[`FILE_${id}`],
|
||||
displayName: env[`LABEL_${id}`],
|
||||
isReadOnly: env[`READONLY_${id}`],
|
||||
databases: env[`DBCONFIG_${id}`] ? safeJsonParse(env[`DBCONFIG_${id}`]) : null,
|
||||
allowedDatabases: env[`ALLOWED_DATABASES_${id}`]?.replace(/\|/g, '\n'),
|
||||
allowedDatabasesRegex: env[`ALLOWED_DATABASES_REGEX_${id}`],
|
||||
parent: env[`PARENT_${id}`] || undefined,
|
||||
useSeparateSchemas: !!env[`USE_SEPARATE_SCHEMAS_${id}`],
|
||||
localDataCenter: env[`LOCAL_DATA_CENTER_${id}`],
|
||||
|
||||
// SSH tunnel
|
||||
useSshTunnel: env[`USE_SSH_${id}`],
|
||||
sshHost: env[`SSH_HOST_${id}`],
|
||||
sshPort: env[`SSH_PORT_${id}`],
|
||||
sshMode: env[`SSH_MODE_${id}`],
|
||||
sshLogin: env[`SSH_LOGIN_${id}`],
|
||||
sshPassword: env[`SSH_PASSWORD_${id}`],
|
||||
sshKeyfile: env[`SSH_KEY_FILE_${id}`],
|
||||
sshKeyfilePassword: env[`SSH_KEY_FILE_PASSWORD_${id}`],
|
||||
|
||||
// SSL
|
||||
useSsl: env[`USE_SSL_${id}`],
|
||||
sslCaFile: env[`SSL_CA_FILE_${id}`],
|
||||
sslCertFile: env[`SSL_CERT_FILE_${id}`],
|
||||
sslCertFilePassword: env[`SSL_CERT_FILE_PASSWORD_${id}`],
|
||||
sslKeyFile: env[`SSL_KEY_FILE_${id}`],
|
||||
sslRejectUnauthorized: env[`SSL_REJECT_UNAUTHORIZED_${id}`],
|
||||
trustServerCertificate: env[`SSL_TRUST_CERTIFICATE_${id}`],
|
||||
}));
|
||||
|
||||
return connections;
|
||||
}
|
||||
|
||||
function extractImportEntitiesFromEnv(env) {
|
||||
const portalConnections = extractConnectionsFromEnv(env) || [];
|
||||
|
||||
const connections = portalConnections.map((conn, index) => ({
|
||||
...conn,
|
||||
id_original: conn._id,
|
||||
import_source_id: -1,
|
||||
conid: crypto.randomUUID(),
|
||||
_id: undefined,
|
||||
id: index + 1, // autoincrement id
|
||||
|
||||
useDatabaseUrl: conn.useDatabaseUrl ? 1 : 0,
|
||||
isReadOnly: conn.isReadOnly ? 1 : 0,
|
||||
useSeparateSchemas: conn.useSeparateSchemas ? 1 : 0,
|
||||
trustServerCertificate: conn.trustServerCertificate ? 1 : 0,
|
||||
singleDatabase: conn.singleDatabase ? 1 : 0,
|
||||
useSshTunnel: conn.useSshTunnel ? 1 : 0,
|
||||
useSsl: conn.useSsl ? 1 : 0,
|
||||
sslRejectUnauthorized: conn.sslRejectUnauthorized ? 1 : 0,
|
||||
}));
|
||||
|
||||
const connectionEnvIdToDbId = {};
|
||||
for (const conn of connections) {
|
||||
connectionEnvIdToDbId[conn.id_original] = conn.id;
|
||||
}
|
||||
|
||||
const connectionsRegex = /^ROLE_(.+)_CONNECTIONS$/;
|
||||
const permissionsRegex = /^ROLE_(.+)_PERMISSIONS$/;
|
||||
|
||||
const dbConnectionRegex = /^ROLE_(.+)_DATABASES_(.+)_CONNECTION$/;
|
||||
const dbDatabasesRegex = /^ROLE_(.+)_DATABASES_(.+)_DATABASES$/;
|
||||
const dbDatabasesRegexRegex = /^ROLE_(.+)_DATABASES_(.+)_DATABASES_REGEX$/;
|
||||
const dbPermissionRegex = /^ROLE_(.+)_DATABASES_(.+)_PERMISSION$/;
|
||||
|
||||
const tableConnectionRegex = /^ROLE_(.+)_TABLES_(.+)_CONNECTION$/;
|
||||
const tableDatabasesRegex = /^ROLE_(.+)_TABLES_(.+)_DATABASES$/;
|
||||
const tableDatabasesRegexRegex = /^ROLE_(.+)_TABLES_(.+)_DATABASES_REGEX$/;
|
||||
const tableSchemasRegex = /^ROLE_(.+)_TABLES_(.+)_SCHEMAS$/;
|
||||
const tableSchemasRegexRegex = /^ROLE_(.+)_TABLES_(.+)_SCHEMAS_REGEX$/;
|
||||
const tableTablesRegex = /^ROLE_(.+)_TABLES_(.+)_TABLES$/;
|
||||
const tableTablesRegexRegex = /^ROLE_(.+)_TABLES_(.+)_TABLES_REGEX$/;
|
||||
const tablePermissionRegex = /^ROLE_(.+)_TABLES_(.+)_PERMISSION$/;
|
||||
const tableScopeRegex = /^ROLE_(.+)_TABLES_(.+)_SCOPE$/;
|
||||
|
||||
const roles = [];
|
||||
const role_connections = [];
|
||||
const role_permissions = [];
|
||||
const role_databases = [];
|
||||
const role_tables = [];
|
||||
|
||||
// Permission name to ID mappings
|
||||
const databasePermissionMap = {
|
||||
view: -1,
|
||||
read_content: -2,
|
||||
write_data: -3,
|
||||
run_script: -4,
|
||||
deny: -5,
|
||||
};
|
||||
|
||||
const tablePermissionMap = {
|
||||
read: -1,
|
||||
update_only: -2,
|
||||
create_update_delete: -3,
|
||||
run_script: -4,
|
||||
deny: -5,
|
||||
};
|
||||
|
||||
const tableScopeMap = {
|
||||
all_objects: -1,
|
||||
tables: -2,
|
||||
views: -3,
|
||||
tables_views_collections: -4,
|
||||
procedures: -5,
|
||||
functions: -6,
|
||||
triggers: -7,
|
||||
sql_objects: -8,
|
||||
collections: -9,
|
||||
};
|
||||
|
||||
// Collect database and table permissions data
|
||||
const databasePermissions = {};
|
||||
const tablePermissions = {};
|
||||
|
||||
// First pass: collect all database and table permission data
|
||||
for (const key in env) {
|
||||
const dbConnMatch = key.match(dbConnectionRegex);
|
||||
const dbDatabasesMatch = key.match(dbDatabasesRegex);
|
||||
const dbDatabasesRegexMatch = key.match(dbDatabasesRegexRegex);
|
||||
const dbPermMatch = key.match(dbPermissionRegex);
|
||||
|
||||
const tableConnMatch = key.match(tableConnectionRegex);
|
||||
const tableDatabasesMatch = key.match(tableDatabasesRegex);
|
||||
const tableDatabasesRegexMatch = key.match(tableDatabasesRegexRegex);
|
||||
const tableSchemasMatch = key.match(tableSchemasRegex);
|
||||
const tableSchemasRegexMatch = key.match(tableSchemasRegexRegex);
|
||||
const tableTablesMatch = key.match(tableTablesRegex);
|
||||
const tableTablesRegexMatch = key.match(tableTablesRegexRegex);
|
||||
const tablePermMatch = key.match(tablePermissionRegex);
|
||||
const tableScopeMatch = key.match(tableScopeRegex);
|
||||
|
||||
// Database permissions
|
||||
if (dbConnMatch) {
|
||||
const [, roleName, permId] = dbConnMatch;
|
||||
if (!databasePermissions[roleName]) databasePermissions[roleName] = {};
|
||||
if (!databasePermissions[roleName][permId]) databasePermissions[roleName][permId] = {};
|
||||
databasePermissions[roleName][permId].connection = env[key];
|
||||
}
|
||||
if (dbDatabasesMatch) {
|
||||
const [, roleName, permId] = dbDatabasesMatch;
|
||||
if (!databasePermissions[roleName]) databasePermissions[roleName] = {};
|
||||
if (!databasePermissions[roleName][permId]) databasePermissions[roleName][permId] = {};
|
||||
databasePermissions[roleName][permId].databases = env[key]?.replace(/\|/g, '\n');
|
||||
}
|
||||
if (dbDatabasesRegexMatch) {
|
||||
const [, roleName, permId] = dbDatabasesRegexMatch;
|
||||
if (!databasePermissions[roleName]) databasePermissions[roleName] = {};
|
||||
if (!databasePermissions[roleName][permId]) databasePermissions[roleName][permId] = {};
|
||||
databasePermissions[roleName][permId].databasesRegex = env[key];
|
||||
}
|
||||
if (dbPermMatch) {
|
||||
const [, roleName, permId] = dbPermMatch;
|
||||
if (!databasePermissions[roleName]) databasePermissions[roleName] = {};
|
||||
if (!databasePermissions[roleName][permId]) databasePermissions[roleName][permId] = {};
|
||||
databasePermissions[roleName][permId].permission = env[key];
|
||||
}
|
||||
|
||||
// Table permissions
|
||||
if (tableConnMatch) {
|
||||
const [, roleName, permId] = tableConnMatch;
|
||||
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||
tablePermissions[roleName][permId].connection = env[key];
|
||||
}
|
||||
if (tableDatabasesMatch) {
|
||||
const [, roleName, permId] = tableDatabasesMatch;
|
||||
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||
tablePermissions[roleName][permId].databases = env[key]?.replace(/\|/g, '\n');
|
||||
}
|
||||
if (tableDatabasesRegexMatch) {
|
||||
const [, roleName, permId] = tableDatabasesRegexMatch;
|
||||
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||
tablePermissions[roleName][permId].databasesRegex = env[key];
|
||||
}
|
||||
if (tableSchemasMatch) {
|
||||
const [, roleName, permId] = tableSchemasMatch;
|
||||
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||
tablePermissions[roleName][permId].schemas = env[key];
|
||||
}
|
||||
if (tableSchemasRegexMatch) {
|
||||
const [, roleName, permId] = tableSchemasRegexMatch;
|
||||
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||
tablePermissions[roleName][permId].schemasRegex = env[key];
|
||||
}
|
||||
if (tableTablesMatch) {
|
||||
const [, roleName, permId] = tableTablesMatch;
|
||||
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||
tablePermissions[roleName][permId].tables = env[key]?.replace(/\|/g, '\n');
|
||||
}
|
||||
if (tableTablesRegexMatch) {
|
||||
const [, roleName, permId] = tableTablesRegexMatch;
|
||||
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||
tablePermissions[roleName][permId].tablesRegex = env[key];
|
||||
}
|
||||
if (tablePermMatch) {
|
||||
const [, roleName, permId] = tablePermMatch;
|
||||
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||
tablePermissions[roleName][permId].permission = env[key];
|
||||
}
|
||||
if (tableScopeMatch) {
|
||||
const [, roleName, permId] = tableScopeMatch;
|
||||
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||
tablePermissions[roleName][permId].scope = env[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass: process roles, connections, and permissions
|
||||
for (const key in env) {
|
||||
const connMatch = key.match(connectionsRegex);
|
||||
const permMatch = key.match(permissionsRegex);
|
||||
if (connMatch) {
|
||||
const roleName = connMatch[1];
|
||||
let role = roles.find(r => r.name === roleName);
|
||||
if (!role) {
|
||||
role = {
|
||||
id: roles.length + 1,
|
||||
name: roleName,
|
||||
import_source_id: -1,
|
||||
};
|
||||
roles.push(role);
|
||||
}
|
||||
const connIds = env[key]
|
||||
.split(',')
|
||||
.map(id => id.trim())
|
||||
.filter(id => id.length > 0);
|
||||
for (const connId of connIds) {
|
||||
const dbId = connectionEnvIdToDbId[connId];
|
||||
if (dbId) {
|
||||
role_connections.push({
|
||||
role_id: role.id,
|
||||
connection_id: dbId,
|
||||
import_source_id: -1,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (permMatch) {
|
||||
const roleName = permMatch[1];
|
||||
let role = roles.find(r => r.name === roleName);
|
||||
if (!role) {
|
||||
role = {
|
||||
id: roles.length + 1,
|
||||
name: roleName,
|
||||
import_source_id: -1,
|
||||
};
|
||||
roles.push(role);
|
||||
}
|
||||
const permissions = env[key]
|
||||
.split(',')
|
||||
.map(p => p.trim())
|
||||
.filter(p => p.length > 0);
|
||||
for (const permission of permissions) {
|
||||
role_permissions.push({
|
||||
role_id: role.id,
|
||||
permission,
|
||||
import_source_id: -1,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process database permissions
|
||||
for (const roleName in databasePermissions) {
|
||||
let role = roles.find(r => r.name === roleName);
|
||||
if (!role) {
|
||||
role = {
|
||||
id: roles.length + 1,
|
||||
name: roleName,
|
||||
import_source_id: -1,
|
||||
};
|
||||
roles.push(role);
|
||||
}
|
||||
|
||||
for (const permId in databasePermissions[roleName]) {
|
||||
const perm = databasePermissions[roleName][permId];
|
||||
if (perm.connection && perm.permission) {
|
||||
const dbId = connectionEnvIdToDbId[perm.connection];
|
||||
const permissionId = databasePermissionMap[perm.permission];
|
||||
if (dbId && permissionId) {
|
||||
role_databases.push({
|
||||
role_id: role.id,
|
||||
connection_id: dbId,
|
||||
database_names_list: perm.databases || null,
|
||||
database_names_regex: perm.databasesRegex || null,
|
||||
database_permission_role_id: permissionId,
|
||||
id_original: permId,
|
||||
import_source_id: -1,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process table permissions
|
||||
for (const roleName in tablePermissions) {
|
||||
let role = roles.find(r => r.name === roleName);
|
||||
if (!role) {
|
||||
role = {
|
||||
id: roles.length + 1,
|
||||
name: roleName,
|
||||
import_source_id: -1,
|
||||
};
|
||||
roles.push(role);
|
||||
}
|
||||
|
||||
for (const permId in tablePermissions[roleName]) {
|
||||
const perm = tablePermissions[roleName][permId];
|
||||
if (perm.connection && perm.permission) {
|
||||
const dbId = connectionEnvIdToDbId[perm.connection];
|
||||
const permissionId = tablePermissionMap[perm.permission];
|
||||
const scopeId = tableScopeMap[perm.scope || 'all_objects'];
|
||||
if (dbId && permissionId && scopeId) {
|
||||
role_tables.push({
|
||||
role_id: role.id,
|
||||
connection_id: dbId,
|
||||
database_names_list: perm.databases || null,
|
||||
database_names_regex: perm.databasesRegex || null,
|
||||
schema_names_list: perm.schemas || null,
|
||||
schema_names_regex: perm.schemasRegex || null,
|
||||
table_names_list: perm.tables || null,
|
||||
table_names_regex: perm.tablesRegex || null,
|
||||
table_permission_role_id: permissionId,
|
||||
table_permission_scope_id: scopeId,
|
||||
id_original: permId,
|
||||
import_source_id: -1,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (connections.length == 0 && roles.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
connections,
|
||||
roles,
|
||||
role_connections,
|
||||
role_permissions,
|
||||
role_databases,
|
||||
role_tables,
|
||||
};
|
||||
}
|
||||
|
||||
function createStorageFromEnvReplicatorItems(importEntities) {
|
||||
return [
|
||||
{
|
||||
name: 'connections',
|
||||
findExisting: true,
|
||||
createNew: true,
|
||||
updateExisting: true,
|
||||
matchColumns: ['id_original', 'import_source_id'],
|
||||
deleteMissing: true,
|
||||
deleteRestrictionColumns: ['import_source_id'],
|
||||
skipUpdateColumns: ['conid'],
|
||||
jsonArray: importEntities.connections,
|
||||
},
|
||||
{
|
||||
name: 'roles',
|
||||
findExisting: true,
|
||||
createNew: true,
|
||||
updateExisting: true,
|
||||
matchColumns: ['name', 'import_source_id'],
|
||||
deleteMissing: true,
|
||||
deleteRestrictionColumns: ['import_source_id'],
|
||||
jsonArray: importEntities.roles,
|
||||
},
|
||||
{
|
||||
name: 'role_connections',
|
||||
findExisting: true,
|
||||
createNew: true,
|
||||
updateExisting: false,
|
||||
deleteMissing: true,
|
||||
matchColumns: ['role_id', 'connection_id', 'import_source_id'],
|
||||
jsonArray: importEntities.role_connections,
|
||||
deleteRestrictionColumns: ['import_source_id'],
|
||||
},
|
||||
{
|
||||
name: 'role_permissions',
|
||||
findExisting: true,
|
||||
createNew: true,
|
||||
updateExisting: false,
|
||||
deleteMissing: true,
|
||||
matchColumns: ['role_id', 'permission', 'import_source_id'],
|
||||
jsonArray: importEntities.role_permissions,
|
||||
deleteRestrictionColumns: ['import_source_id'],
|
||||
},
|
||||
{
|
||||
name: 'role_databases',
|
||||
findExisting: true,
|
||||
createNew: true,
|
||||
updateExisting: true,
|
||||
deleteMissing: true,
|
||||
matchColumns: ['role_id', 'id_original', 'import_source_id'],
|
||||
jsonArray: importEntities.role_databases,
|
||||
deleteRestrictionColumns: ['import_source_id'],
|
||||
},
|
||||
{
|
||||
name: 'role_tables',
|
||||
findExisting: true,
|
||||
createNew: true,
|
||||
updateExisting: true,
|
||||
deleteMissing: true,
|
||||
matchColumns: ['role_id', 'id_original', 'import_source_id'],
|
||||
jsonArray: importEntities.role_tables,
|
||||
deleteRestrictionColumns: ['import_source_id'],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
extractConnectionsFromEnv,
|
||||
extractImportEntitiesFromEnv,
|
||||
createStorageFromEnvReplicatorItems,
|
||||
};
|
||||
@@ -23,6 +23,7 @@ export interface DataReplicatorItem {
|
||||
deleteMissing: boolean;
|
||||
deleteRestrictionColumns: string[];
|
||||
matchColumns: string[];
|
||||
skipUpdateColumns?: string[];
|
||||
}
|
||||
|
||||
export interface DataReplicatorOptions {
|
||||
@@ -151,7 +152,12 @@ class ReplicatorItemHolder {
|
||||
chunk,
|
||||
this.table.columns.map(x => x.columnName)
|
||||
),
|
||||
[this.autoColumn, ...this.backReferences.map(x => x.columnName), ...this.references.map(x => x.columnName)]
|
||||
[
|
||||
this.autoColumn,
|
||||
...this.backReferences.map(x => x.columnName),
|
||||
...this.references.map(x => x.columnName),
|
||||
...(this.item.skipUpdateColumns || []),
|
||||
]
|
||||
);
|
||||
|
||||
return res;
|
||||
|
||||
@@ -26,6 +26,7 @@ import _isDate from 'lodash/isDate';
|
||||
import _isArray from 'lodash/isArray';
|
||||
import _isPlainObject from 'lodash/isPlainObject';
|
||||
import _keys from 'lodash/keys';
|
||||
import _cloneDeep from 'lodash/cloneDeep';
|
||||
import uuidv1 from 'uuid/v1';
|
||||
|
||||
export class SqlDumper implements AlterProcessor {
|
||||
@@ -667,6 +668,68 @@ export class SqlDumper implements AlterProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
sanitizeTableConstraints(table: TableInfo): TableInfo {
|
||||
// Create a deep copy of the table
|
||||
const sanitized = _cloneDeep(table);
|
||||
|
||||
// Get the set of existing column names
|
||||
const existingColumns = new Set(sanitized.columns.map(col => col.columnName));
|
||||
|
||||
// Filter primary key columns to only include existing columns
|
||||
if (sanitized.primaryKey) {
|
||||
const validPkColumns = sanitized.primaryKey.columns.filter(col => existingColumns.has(col.columnName));
|
||||
if (validPkColumns.length === 0) {
|
||||
// If no valid columns remain, remove the primary key entirely
|
||||
sanitized.primaryKey = null;
|
||||
} else if (validPkColumns.length < sanitized.primaryKey.columns.length) {
|
||||
// Update primary key with only valid columns
|
||||
sanitized.primaryKey = {
|
||||
...sanitized.primaryKey,
|
||||
columns: validPkColumns
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Filter sorting key columns to only include existing columns
|
||||
if (sanitized.sortingKey) {
|
||||
const validSkColumns = sanitized.sortingKey.columns.filter(col => existingColumns.has(col.columnName));
|
||||
if (validSkColumns.length === 0) {
|
||||
sanitized.sortingKey = null;
|
||||
} else if (validSkColumns.length < sanitized.sortingKey.columns.length) {
|
||||
sanitized.sortingKey = {
|
||||
...sanitized.sortingKey,
|
||||
columns: validSkColumns
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Filter foreign keys to only include those with all columns present
|
||||
if (sanitized.foreignKeys) {
|
||||
sanitized.foreignKeys = sanitized.foreignKeys.filter(fk =>
|
||||
fk.columns.every(col => existingColumns.has(col.columnName))
|
||||
);
|
||||
}
|
||||
|
||||
// Filter indexes to only include those with all columns present
|
||||
if (sanitized.indexes) {
|
||||
sanitized.indexes = sanitized.indexes.filter(idx =>
|
||||
idx.columns.every(col => existingColumns.has(col.columnName))
|
||||
);
|
||||
}
|
||||
|
||||
// Filter unique constraints to only include those with all columns present
|
||||
if (sanitized.uniques) {
|
||||
sanitized.uniques = sanitized.uniques.filter(uq =>
|
||||
uq.columns.every(col => existingColumns.has(col.columnName))
|
||||
);
|
||||
}
|
||||
|
||||
// Filter dependencies (references from other tables) - these should remain as-is
|
||||
// since they don't affect the CREATE TABLE statement for this table
|
||||
|
||||
return sanitized;
|
||||
}
|
||||
|
||||
recreateTable(oldTable: TableInfo, newTable: TableInfo) {
|
||||
if (!oldTable.pairingId || !newTable.pairingId || oldTable.pairingId != newTable.pairingId) {
|
||||
throw new Error('Recreate is not possible: oldTable.paringId != newTable.paringId');
|
||||
@@ -681,48 +744,51 @@ export class SqlDumper implements AlterProcessor {
|
||||
}))
|
||||
.filter(x => x.newcol);
|
||||
|
||||
// Create a sanitized version of newTable with constraints that only reference existing columns
|
||||
const sanitizedNewTable = this.sanitizeTableConstraints(newTable);
|
||||
|
||||
if (this.driver.supportsTransactions) {
|
||||
this.dropConstraints(oldTable, true);
|
||||
this.renameTable(oldTable, tmpTable);
|
||||
|
||||
this.createTable(newTable);
|
||||
this.createTable(sanitizedNewTable);
|
||||
|
||||
const autoinc = newTable.columns.find(x => x.autoIncrement);
|
||||
const autoinc = sanitizedNewTable.columns.find(x => x.autoIncrement);
|
||||
if (autoinc) {
|
||||
this.allowIdentityInsert(newTable, true);
|
||||
this.allowIdentityInsert(sanitizedNewTable, true);
|
||||
}
|
||||
|
||||
this.putCmd(
|
||||
'^insert ^into %f (%,i) select %,i ^from %f',
|
||||
newTable,
|
||||
sanitizedNewTable,
|
||||
columnPairs.map(x => x.newcol.columnName),
|
||||
columnPairs.map(x => x.oldcol.columnName),
|
||||
{ ...oldTable, pureName: tmpTable }
|
||||
);
|
||||
|
||||
if (autoinc) {
|
||||
this.allowIdentityInsert(newTable, false);
|
||||
this.allowIdentityInsert(sanitizedNewTable, false);
|
||||
}
|
||||
|
||||
if (this.dialect.dropForeignKey) {
|
||||
newTable.dependencies.forEach(cnt => this.createConstraint(cnt));
|
||||
sanitizedNewTable.dependencies.forEach(cnt => this.createConstraint(cnt));
|
||||
}
|
||||
|
||||
this.dropTable({ ...oldTable, pureName: tmpTable });
|
||||
} else {
|
||||
// we have to preserve old table as long as possible
|
||||
this.createTable({ ...newTable, pureName: tmpTable });
|
||||
this.createTable({ ...sanitizedNewTable, pureName: tmpTable });
|
||||
|
||||
this.putCmd(
|
||||
'^insert ^into %f (%,i) select %,s ^from %f',
|
||||
{ ...newTable, pureName: tmpTable },
|
||||
{ ...sanitizedNewTable, pureName: tmpTable },
|
||||
columnPairs.map(x => x.newcol.columnName),
|
||||
columnPairs.map(x => x.oldcol.columnName),
|
||||
oldTable
|
||||
);
|
||||
|
||||
this.dropTable(oldTable);
|
||||
this.renameTable({ ...newTable, pureName: tmpTable }, newTable.pureName);
|
||||
this.renameTable({ ...sanitizedNewTable, pureName: tmpTable }, newTable.pureName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+121
-45
@@ -91,8 +91,8 @@ interface AlterOperation_RenameConstraint {
|
||||
}
|
||||
interface AlterOperation_RecreateTable {
|
||||
operationType: 'recreateTable';
|
||||
table: TableInfo;
|
||||
operations: AlterOperation[];
|
||||
oldTable: TableInfo;
|
||||
newTable: TableInfo;
|
||||
}
|
||||
interface AlterOperation_FillPreloadedRows {
|
||||
operationType: 'fillPreloadedRows';
|
||||
@@ -249,11 +249,11 @@ export class AlterPlan {
|
||||
});
|
||||
}
|
||||
|
||||
recreateTable(table: TableInfo, operations: AlterOperation[]) {
|
||||
recreateTable(oldTable: TableInfo, newTable: TableInfo) {
|
||||
this.operations.push({
|
||||
operationType: 'recreateTable',
|
||||
table,
|
||||
operations,
|
||||
oldTable,
|
||||
newTable,
|
||||
});
|
||||
this.recreates.tables += 1;
|
||||
}
|
||||
@@ -337,7 +337,13 @@ export class AlterPlan {
|
||||
return opRes;
|
||||
}),
|
||||
op,
|
||||
];
|
||||
].filter(op => {
|
||||
// filter duplicated drops
|
||||
const existingDrop = this.operations.find(
|
||||
o => o.operationType == 'dropConstraint' && o.oldObject === op['oldObject']
|
||||
);
|
||||
return existingDrop == null;
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -498,53 +504,121 @@ export class AlterPlan {
|
||||
return [];
|
||||
}
|
||||
|
||||
const table = this.wholeNewDb.tables.find(
|
||||
const oldTable = this.wholeOldDb.tables.find(
|
||||
x => x.pureName == op[objectField].pureName && x.schemaName == op[objectField].schemaName
|
||||
);
|
||||
const newTable = this.wholeNewDb.tables.find(
|
||||
x => x.pureName == op[objectField].pureName && x.schemaName == op[objectField].schemaName
|
||||
);
|
||||
this.recreates.tables += 1;
|
||||
return [
|
||||
{
|
||||
operationType: 'recreateTable',
|
||||
table,
|
||||
operations: [op],
|
||||
oldTable,
|
||||
newTable,
|
||||
// operations: [op],
|
||||
},
|
||||
];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
_groupTableRecreations(): AlterOperation[] {
|
||||
const res = [];
|
||||
const recreates = {};
|
||||
_removeRecreatedTableAlters(): AlterOperation[] {
|
||||
const res: AlterOperation[] = [];
|
||||
const recreates = new Set<string>();
|
||||
for (const op of this.operations) {
|
||||
if (op.operationType == 'recreateTable' && op.table) {
|
||||
const existingRecreate = recreates[`${op.table.schemaName}||${op.table.pureName}`];
|
||||
if (existingRecreate) {
|
||||
existingRecreate.operations.push(...op.operations);
|
||||
} else {
|
||||
const recreate = {
|
||||
...op,
|
||||
operations: [...op.operations],
|
||||
};
|
||||
res.push(recreate);
|
||||
recreates[`${op.table.schemaName}||${op.table.pureName}`] = recreate;
|
||||
}
|
||||
} else {
|
||||
// @ts-ignore
|
||||
const oldObject: TableInfo = op.oldObject || op.object;
|
||||
if (oldObject) {
|
||||
const recreated = recreates[`${oldObject.schemaName}||${oldObject.pureName}`];
|
||||
if (recreated) {
|
||||
recreated.operations.push(op);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
res.push(op);
|
||||
if (op.operationType == 'recreateTable' && op.oldTable && op.newTable) {
|
||||
const key = `${op.oldTable.schemaName}||${op.oldTable.pureName}`;
|
||||
recreates.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
for (const op of this.operations) {
|
||||
switch (op.operationType) {
|
||||
case 'createColumn':
|
||||
case 'createConstraint':
|
||||
{
|
||||
const key = `${op.newObject.schemaName}||${op.newObject.pureName}`;
|
||||
if (recreates.has(key)) {
|
||||
// skip create inside recreated table
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'dropColumn':
|
||||
case 'dropConstraint':
|
||||
case 'changeColumn':
|
||||
{
|
||||
const key = `${op.oldObject.schemaName}||${op.oldObject.pureName}`;
|
||||
if (recreates.has(key)) {
|
||||
// skip drop/change inside recreated table
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'renameColumn':
|
||||
{
|
||||
const key = `${op.object.schemaName}||${op.object.pureName}`;
|
||||
if (recreates.has(key)) {
|
||||
// skip rename inside recreated table
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
res.push(op);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
_groupTableRecreations(): AlterOperation[] {
|
||||
const res = [];
|
||||
const recreates = new Set<string>();
|
||||
for (const op of this.operations) {
|
||||
if (op.operationType == 'recreateTable' && op.oldTable && op.newTable) {
|
||||
const key = `${op.oldTable.schemaName}||${op.oldTable.pureName}`;
|
||||
if (recreates.has(key)) {
|
||||
// prevent duplicate recreates
|
||||
continue;
|
||||
}
|
||||
recreates.add(key);
|
||||
}
|
||||
|
||||
res.push(op);
|
||||
}
|
||||
return res;
|
||||
|
||||
// const res = [];
|
||||
// const recreates = {};
|
||||
// for (const op of this.operations) {
|
||||
// if (op.operationType == 'recreateTable' && op.table) {
|
||||
// const existingRecreate = recreates[`${op.table.schemaName}||${op.table.pureName}`];
|
||||
// if (existingRecreate) {
|
||||
// existingRecreate.operations.push(...op.operations);
|
||||
// } else {
|
||||
// const recreate = {
|
||||
// ...op,
|
||||
// operations: [...op.operations],
|
||||
// };
|
||||
// res.push(recreate);
|
||||
// recreates[`${op.table.schemaName}||${op.table.pureName}`] = recreate;
|
||||
// }
|
||||
// } else {
|
||||
// // @ts-ignore
|
||||
// const oldObject: TableInfo = op.oldObject || op.object;
|
||||
// if (oldObject) {
|
||||
// const recreated = recreates[`${oldObject.schemaName}||${oldObject.pureName}`];
|
||||
// if (recreated) {
|
||||
// recreated.operations.push(op);
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// res.push(op);
|
||||
// }
|
||||
// }
|
||||
// return res;
|
||||
}
|
||||
|
||||
_moveForeignKeysToLast(): AlterOperation[] {
|
||||
if (!this.dialect.createForeignKey) {
|
||||
return this.operations;
|
||||
@@ -611,6 +685,8 @@ export class AlterPlan {
|
||||
|
||||
// console.log('*****************OPERATIONS3', this.operations);
|
||||
|
||||
this.operations = this._removeRecreatedTableAlters();
|
||||
|
||||
this.operations = this._moveForeignKeysToLast();
|
||||
|
||||
// console.log('*****************OPERATIONS4', this.operations);
|
||||
@@ -673,16 +749,16 @@ export function runAlterOperation(op: AlterOperation, processor: AlterProcessor)
|
||||
break;
|
||||
case 'recreateTable':
|
||||
{
|
||||
const oldTable = generateTablePairingId(op.table);
|
||||
const newTable = _.cloneDeep(oldTable);
|
||||
const newDb = DatabaseAnalyser.createEmptyStructure();
|
||||
newDb.tables.push(newTable);
|
||||
// console.log('////////////////////////////newTable1', newTable);
|
||||
op.operations.forEach(child => runAlterOperation(child, new DatabaseInfoAlterProcessor(newDb)));
|
||||
// console.log('////////////////////////////op.operations', op.operations);
|
||||
// console.log('////////////////////////////op.table', op.table);
|
||||
// console.log('////////////////////////////newTable2', newTable);
|
||||
processor.recreateTable(oldTable, newTable);
|
||||
// const oldTable = generateTablePairingId(op.table);
|
||||
// const newTable = _.cloneDeep(oldTable);
|
||||
// const newDb = DatabaseAnalyser.createEmptyStructure();
|
||||
// newDb.tables.push(newTable);
|
||||
// // console.log('////////////////////////////newTable1', newTable);
|
||||
// op.operations.forEach(child => runAlterOperation(child, new DatabaseInfoAlterProcessor(newDb)));
|
||||
// // console.log('////////////////////////////op.operations', op.operations);
|
||||
// // console.log('////////////////////////////op.table', op.table);
|
||||
// // console.log('////////////////////////////newTable2', newTable);
|
||||
processor.recreateTable(op.oldTable, op.newTable);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
export let onSetPermission;
|
||||
export let label;
|
||||
export let folder;
|
||||
export let disabled = false;
|
||||
</script>
|
||||
|
||||
<PermissionCheckBox
|
||||
@@ -15,6 +16,7 @@
|
||||
permissions={$values.permissions}
|
||||
basePermissions={$values.basePermissions}
|
||||
{onSetPermission}
|
||||
{disabled}
|
||||
/>
|
||||
|
||||
<div class="ml-4">
|
||||
@@ -24,6 +26,7 @@
|
||||
permissions={$values.permissions}
|
||||
basePermissions={$values.basePermissions}
|
||||
{onSetPermission}
|
||||
{disabled}
|
||||
/>
|
||||
<PermissionCheckBox
|
||||
label="Write"
|
||||
@@ -31,5 +34,6 @@
|
||||
permissions={$values.permissions}
|
||||
basePermissions={$values.basePermissions}
|
||||
{onSetPermission}
|
||||
{disabled}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -467,14 +467,12 @@ await dbgateApi.executeQuery(${JSON.stringify(
|
||||
|
||||
{ divider: true },
|
||||
isSqlOrDoc &&
|
||||
isProApp() &&
|
||||
!connection.isReadOnly &&
|
||||
hasPermission(`dbops/import`) && {
|
||||
onClick: handleImport,
|
||||
text: _t('database.import', { defaultMessage: 'Import' }),
|
||||
},
|
||||
isSqlOrDoc &&
|
||||
isProApp() &&
|
||||
hasPermission(`dbops/export`) && {
|
||||
onClick: handleExport,
|
||||
text: _t('database.export', { defaultMessage: 'Export' }),
|
||||
|
||||
@@ -0,0 +1,398 @@
|
||||
<script lang="ts">
|
||||
import _ from 'lodash';
|
||||
import { tick } from 'svelte';
|
||||
import CellValue from '../datagrid/CellValue.svelte';
|
||||
import { isJsonLikeLongString, safeJsonParse, parseCellValue, stringifyCellValue, filterName } from 'dbgate-tools';
|
||||
import keycodes from '../utility/keycodes';
|
||||
import createRef from '../utility/createRef';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import EditCellDataModal from '../modals/EditCellDataModal.svelte';
|
||||
import SearchBoxWrapper from '../elements/SearchBoxWrapper.svelte';
|
||||
import SearchInput from '../elements/SearchInput.svelte';
|
||||
import CloseSearchButton from '../buttons/CloseSearchButton.svelte';
|
||||
import { _t } from '../translations';
|
||||
import ColumnLabel from '../elements/ColumnLabel.svelte';
|
||||
import CheckboxField from '../forms/CheckboxField.svelte';
|
||||
import { getLocalStorage, setLocalStorage } from '../utility/storageCache';
|
||||
import JSONTree from '../jsontree/JSONTree.svelte';
|
||||
import Link from '../elements/Link.svelte';
|
||||
|
||||
export let selection;
|
||||
|
||||
$: firstSelection = selection?.[0];
|
||||
$: rowData = firstSelection?.rowData;
|
||||
$: editable = firstSelection?.editable;
|
||||
$: editorTypes = firstSelection?.editorTypes;
|
||||
$: displayColumns = firstSelection?.displayColumns || [];
|
||||
$: realColumnUniqueNames = firstSelection?.realColumnUniqueNames || [];
|
||||
$: grider = firstSelection?.grider;
|
||||
|
||||
$: uniqueRows = _.uniqBy(selection || [], 'row');
|
||||
$: isMultipleRows = uniqueRows.length > 1;
|
||||
|
||||
function areValuesEqual(val1, val2) {
|
||||
if (val1 === val2) return true;
|
||||
if (val1 == null && val2 == null) return true;
|
||||
if (val1 == null || val2 == null) return false;
|
||||
return _.isEqual(val1, val2);
|
||||
}
|
||||
|
||||
function getFieldValue(colName) {
|
||||
if (!isMultipleRows) return { value: rowData?.[colName], hasMultipleValues: false };
|
||||
|
||||
const values = uniqueRows.map(sel => sel.rowData?.[colName]);
|
||||
const firstValue = values[0];
|
||||
const allSame = values.every(v => areValuesEqual(v, firstValue));
|
||||
|
||||
return allSame ? { value: firstValue, hasMultipleValues: false } : { value: null, hasMultipleValues: true };
|
||||
}
|
||||
|
||||
let filter = '';
|
||||
let notNull = getLocalStorage('dataGridCellDataFormNotNull') === 'true';
|
||||
|
||||
$: orderedFields = realColumnUniqueNames
|
||||
.map(colName => {
|
||||
const col = displayColumns.find(c => c.uniqueName === colName);
|
||||
if (!col) return null;
|
||||
const { value, hasMultipleValues } = getFieldValue(colName);
|
||||
return {
|
||||
...col,
|
||||
value,
|
||||
hasMultipleValues,
|
||||
// columnName: col.columnName || colName,
|
||||
// uniqueName: colName,
|
||||
// value,
|
||||
// hasMultipleValues,
|
||||
// col,
|
||||
};
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
$: filteredFields = orderedFields
|
||||
.filter(field => filterName(filter, field.columnName))
|
||||
.filter(field => {
|
||||
if (notNull) {
|
||||
return field.value != null || field.hasMultipleValues;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
let editingColumn = null;
|
||||
let editValue = '';
|
||||
let domEditor = null;
|
||||
const isChangedRef = createRef(false);
|
||||
|
||||
function isJsonValue(value) {
|
||||
if (
|
||||
_.isPlainObject(value) &&
|
||||
!(value?.type == 'Buffer' && _.isArray(value.data)) &&
|
||||
!value.$oid &&
|
||||
!value.$bigint &&
|
||||
!value.$decimal
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (_.isArray(value)) return true;
|
||||
if (typeof value !== 'string') return false;
|
||||
if (!isJsonLikeLongString(value)) return false;
|
||||
const parsed = safeJsonParse(value);
|
||||
return parsed !== null && (_.isPlainObject(parsed) || _.isArray(parsed));
|
||||
}
|
||||
|
||||
function getJsonObject(value) {
|
||||
if (_.isPlainObject(value) || _.isArray(value)) return value;
|
||||
if (typeof value === 'string') return safeJsonParse(value);
|
||||
return null;
|
||||
}
|
||||
|
||||
function handleClick(field) {
|
||||
if (!editable || !grider) return;
|
||||
if (isJsonValue(field.value)) return;
|
||||
// if (isJsonValue(field.value) && !field.hasMultipleValues) {
|
||||
// openEditModal(field);
|
||||
// return;
|
||||
// }
|
||||
startEditing(field);
|
||||
}
|
||||
|
||||
function handleDoubleClick(field) {
|
||||
if (!editable || !grider) return;
|
||||
if (isJsonValue(field.value) && !field.hasMultipleValues) {
|
||||
openEditModal(field);
|
||||
return;
|
||||
}
|
||||
startEditing(field);
|
||||
}
|
||||
|
||||
function startEditing(field) {
|
||||
if (!editable || !grider) return;
|
||||
editingColumn = field.uniqueName;
|
||||
editValue = field.hasMultipleValues ? '' : stringifyCellValue(field.value, 'inlineEditorIntent', editorTypes).value;
|
||||
isChangedRef.set(false);
|
||||
tick().then(() => {
|
||||
if (!domEditor) return;
|
||||
domEditor.focus();
|
||||
if (!field.hasMultipleValues) domEditor.select();
|
||||
});
|
||||
}
|
||||
|
||||
function handleKeyDown(event, field) {
|
||||
switch (event.keyCode) {
|
||||
case keycodes.escape:
|
||||
isChangedRef.set(false);
|
||||
editingColumn = null;
|
||||
break;
|
||||
case keycodes.enter:
|
||||
if (isChangedRef.get()) {
|
||||
saveValue(field);
|
||||
}
|
||||
editingColumn = null;
|
||||
event.preventDefault();
|
||||
break;
|
||||
case keycodes.tab:
|
||||
case keycodes.upArrow:
|
||||
case keycodes.downArrow:
|
||||
const reverse = event.keyCode === keycodes.upArrow || (event.keyCode === keycodes.tab && event.shiftKey);
|
||||
event.preventDefault();
|
||||
moveToNextField(field, reverse);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function moveToNextField(field, reverse) {
|
||||
const currentIndex = filteredFields.findIndex(f => f.uniqueName === field.uniqueName);
|
||||
const nextIndex = reverse ? currentIndex - 1 : currentIndex + 1;
|
||||
const nextField = filteredFields[nextIndex];
|
||||
if (!nextField) return;
|
||||
|
||||
if (isChangedRef.get()) {
|
||||
saveValue(field);
|
||||
}
|
||||
editingColumn = null;
|
||||
if (nextIndex < 0 || nextIndex >= filteredFields.length) return;
|
||||
|
||||
tick().then(() => {
|
||||
startEditing(nextField);
|
||||
// if (isJsonValue(nextField.value)) {
|
||||
// openEditModal(nextField);
|
||||
// } else {
|
||||
// startEditing(nextField);
|
||||
// }
|
||||
});
|
||||
}
|
||||
|
||||
function handleSearchKeyDown(e) {
|
||||
if (e.keyCode === keycodes.backspace && (e.metaKey || e.ctrlKey)) {
|
||||
filter = '';
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function handleBlur(field) {
|
||||
if (isChangedRef.get()) {
|
||||
saveValue(field);
|
||||
}
|
||||
editingColumn = null;
|
||||
}
|
||||
|
||||
function setCellValue(fieldName, value) {
|
||||
if (!grider) return;
|
||||
|
||||
if (selection.length > 0) {
|
||||
const uniqueRowIndices = _.uniq(selection.map(x => x.row));
|
||||
grider.beginUpdate();
|
||||
for (const row of uniqueRowIndices) {
|
||||
grider.setCellValue(row, fieldName, value);
|
||||
}
|
||||
grider.endUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
function saveValue(field) {
|
||||
if (!grider) return;
|
||||
const parsedValue = parseCellValue(editValue, editorTypes);
|
||||
setCellValue(field.uniqueName, parsedValue);
|
||||
isChangedRef.set(false);
|
||||
}
|
||||
|
||||
function openEditModal(field) {
|
||||
if (!grider) return;
|
||||
showModal(EditCellDataModal, {
|
||||
value: field.value,
|
||||
dataEditorTypesBehaviour: editorTypes,
|
||||
onSave: value => setCellValue(field.uniqueName, value),
|
||||
});
|
||||
}
|
||||
|
||||
function getJsonParsedValue(value) {
|
||||
if (editorTypes?.explicitDataType) return null;
|
||||
if (!isJsonLikeLongString(value)) return null;
|
||||
return safeJsonParse(value);
|
||||
}
|
||||
|
||||
function handleEdit(field) {
|
||||
editingColumn = null;
|
||||
openEditModal(field);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="outer">
|
||||
<div class="content">
|
||||
{#if rowData}
|
||||
<div class="search-wrapper" on:keydown={handleSearchKeyDown}>
|
||||
<SearchBoxWrapper noMargin>
|
||||
<SearchInput
|
||||
placeholder={_t('tableCell.filterColumns', { defaultMessage: 'Filter columns' })}
|
||||
bind:value={filter}
|
||||
/>
|
||||
<CloseSearchButton bind:filter />
|
||||
</SearchBoxWrapper>
|
||||
<CheckboxField
|
||||
defaultChecked={notNull}
|
||||
on:change={e => {
|
||||
// @ts-ignore
|
||||
notNull = e.target.checked;
|
||||
setLocalStorage('dataGridCellDataFormNotNull', notNull ? 'true' : 'false');
|
||||
}}
|
||||
/>
|
||||
{_t('tableCell.hideNullValues', { defaultMessage: 'Hide NULL values' })}
|
||||
</div>
|
||||
{/if}
|
||||
<div class="inner">
|
||||
{#if !rowData}
|
||||
<div class="no-data">{_t('tableCell.noDataSelected', { defaultMessage: 'No data selected' })}</div>
|
||||
{:else}
|
||||
{#each filteredFields as field (field.uniqueName)}
|
||||
<div class="field">
|
||||
<div class="field-name">
|
||||
<ColumnLabel {...field} showDataType /><Link onClick={() => handleEdit(field)}
|
||||
>{_t('tableCell.edit', { defaultMessage: 'Edit' })}
|
||||
</Link>
|
||||
</div>
|
||||
<div class="field-value" class:editable on:click={() => handleClick(field)}>
|
||||
{#if editingColumn === field.uniqueName}
|
||||
<div class="editor-wrapper">
|
||||
<input
|
||||
type="text"
|
||||
bind:this={domEditor}
|
||||
bind:value={editValue}
|
||||
on:input={() => isChangedRef.set(true)}
|
||||
on:keydown={e => handleKeyDown(e, field)}
|
||||
on:blur={() => handleBlur(field)}
|
||||
class="inline-editor"
|
||||
/>
|
||||
</div>
|
||||
{:else if field.hasMultipleValues}
|
||||
<span class="multiple-values"
|
||||
>({_t('tableCell.multipleValues', { defaultMessage: 'Multiple values' })})</span
|
||||
>
|
||||
{:else if isJsonValue(field.value)}
|
||||
<JSONTree value={getJsonParsedValue(field.value)} />
|
||||
{:else}
|
||||
<CellValue
|
||||
{rowData}
|
||||
value={field.value}
|
||||
jsonParsedValue={getJsonParsedValue(field.value)}
|
||||
{editorTypes}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.outer {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.content {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.search-wrapper {
|
||||
padding: 4px 4px 0 4px;
|
||||
flex-shrink: 0;
|
||||
border: 1px solid var(--theme-border);
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.inner {
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.no-data {
|
||||
color: var(--theme-font-3);
|
||||
font-style: italic;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.field {
|
||||
margin-bottom: 8px;
|
||||
border: 1px solid var(--theme-border);
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.field-name {
|
||||
background: var(--theme-bg-1);
|
||||
padding: 4px 8px;
|
||||
font-weight: 500;
|
||||
font-size: 11px;
|
||||
color: var(--theme-font-2);
|
||||
border-bottom: 1px solid var(--theme-border);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.field-value {
|
||||
padding: 6px 8px;
|
||||
background: var(--theme-bg-0);
|
||||
min-height: 20px;
|
||||
word-break: break-all;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.field-value.editable {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.editor-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.inline-editor {
|
||||
flex: 1;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: var(--theme-bg-0);
|
||||
color: var(--theme-font-1);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.inline-editor:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.multiple-values {
|
||||
color: var(--theme-font-3);
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
@@ -3,12 +3,21 @@
|
||||
|
||||
export let selection;
|
||||
export let wrap;
|
||||
|
||||
$: singleSelection = selection?.length == 1 && selection?.[0];
|
||||
$: grider = singleSelection?.grider;
|
||||
$: editable = grider?.editable ?? false;
|
||||
|
||||
function setCellValue(value) {
|
||||
if (!editable) return;
|
||||
grider.setCellValue(singleSelection.row, singleSelection.column, value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<textarea
|
||||
class="flex1"
|
||||
{wrap}
|
||||
readonly
|
||||
readonly={!editable}
|
||||
value={selection
|
||||
.map(cell => {
|
||||
const { value } = cell;
|
||||
@@ -16,4 +25,5 @@
|
||||
return cell.value;
|
||||
})
|
||||
.join('\n')}
|
||||
on:input={e => setCellValue(e.target['value'])}
|
||||
/>
|
||||
|
||||
@@ -703,7 +703,7 @@ registerCommand({
|
||||
name: __t('command.database.export', { defaultMessage: 'Export database' }),
|
||||
toolbar: true,
|
||||
icon: 'icon export',
|
||||
testEnabled: () => getCurrentDatabase() != null && hasPermission(`dbops/export`) && isProApp(),
|
||||
testEnabled: () => getCurrentDatabase() != null && hasPermission(`dbops/export`),
|
||||
onClick: () => {
|
||||
openImportExportTab({
|
||||
targetStorageType: getDefaultFileFormat(getExtensions()).storageType,
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
{/if}
|
||||
</span>
|
||||
{/if}
|
||||
<DropDownButton menu={getMenu} narrow />
|
||||
<DropDownButton menu={getMenu} narrow data-testid={`ColumnHeaderControl_dropdown_${column?.uniqueName}`} />
|
||||
<div class="horizontal-split-handle resizeHandleControl" use:splitterDrag={'clientX'} on:resizeSplitter />
|
||||
</div>
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
export let setFilter;
|
||||
export let showResizeSplitter = false;
|
||||
export let onFocusGrid = null;
|
||||
export let onFocusGridHeader = null;
|
||||
export let onGetReference = null;
|
||||
export let foreignKey = null;
|
||||
export let conid = null;
|
||||
@@ -204,6 +205,11 @@
|
||||
// ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
}
|
||||
if (ev.keyCode == keycodes.upArrow) {
|
||||
if (onFocusGridHeader) onFocusGridHeader();
|
||||
// ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
}
|
||||
// if (ev.keyCode == KeyCodes.DownArrow || ev.keyCode == KeyCodes.UpArrow) {
|
||||
// if (this.props.onControlKey) this.props.onControlKey(ev.keyCode);
|
||||
// }
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
registerCommand({
|
||||
id: 'dataGrid.switchToTable',
|
||||
category: __t('command.datagrid', { defaultMessage: 'Data grid' }),
|
||||
name: __t('command.datagrid.witchToTable', { defaultMessage: 'Switch to table'}),
|
||||
name: __t('command.datagrid.witchToTable', { defaultMessage: 'Switch to table' }),
|
||||
icon: 'icon table',
|
||||
keyText: 'F4',
|
||||
testEnabled: () => getCurrentEditor()?.switchViewEnabled('table'),
|
||||
@@ -40,6 +40,17 @@
|
||||
onClick: () => getCurrentEditor().toggleLeftPanel(),
|
||||
});
|
||||
|
||||
registerCommand({
|
||||
id: 'dataGrid.toggleCellDataView',
|
||||
category: __t('command.datagrid', { defaultMessage: 'Data grid' }),
|
||||
name: __t('command.datagrid.toggleCellDataView', { defaultMessage: 'Toggle cell data view' }),
|
||||
toolbarName: __t('command.datagrid.toggleCellDataView.toolbar', { defaultMessage: 'Cell Data' }),
|
||||
menuName: __t('command.datagrid.toggleCellDataView.menu', { defaultMessage: 'Show cell data' }),
|
||||
icon: 'icon cell-data',
|
||||
testEnabled: () => !!getCurrentEditor(),
|
||||
onClick: () => getCurrentEditor().toggleCellDataView(),
|
||||
});
|
||||
|
||||
function extractMacroValuesForMacro(macroValues, macro) {
|
||||
// return {};
|
||||
if (!macro) return {};
|
||||
@@ -70,6 +81,7 @@
|
||||
import { getLocalStorage, setLocalStorage } from '../utility/storageCache';
|
||||
import { __t, _t } from '../translations';
|
||||
import { isProApp } from '../utility/proTools';
|
||||
import CellDataWidget from '../widgets/CellDataWidget.svelte';
|
||||
|
||||
export let config;
|
||||
export let setConfig;
|
||||
@@ -91,6 +103,7 @@
|
||||
export let hasMultiColumnFilter = false;
|
||||
export let setLoadedRows = null;
|
||||
export let hideGridLeftColumn = false;
|
||||
export let cellDataViewVisible = false;
|
||||
|
||||
export let onPublishedCellsChanged;
|
||||
|
||||
@@ -107,6 +120,7 @@
|
||||
setContext('macroValues', macroValues);
|
||||
|
||||
let managerSize;
|
||||
let cellViewWidth;
|
||||
const collapsedLeftColumnStore =
|
||||
getContext('collapsedLeftColumnStore') || writable(getLocalStorage('dataGrid_collapsedLeftColumn', false));
|
||||
|
||||
@@ -149,6 +163,10 @@
|
||||
collapsedLeftColumnStore.update(x => !x);
|
||||
}
|
||||
|
||||
export function toggleCellDataView() {
|
||||
cellDataViewVisible = !cellDataViewVisible;
|
||||
}
|
||||
|
||||
registerMenu(
|
||||
{ command: 'dataGrid.switchToForm', tag: 'switch', hideDisabled: true },
|
||||
{ command: 'dataGrid.switchToTable', tag: 'switch', hideDisabled: true },
|
||||
@@ -157,6 +175,7 @@
|
||||
);
|
||||
|
||||
$: if (managerSize) setLocalStorage('dataGridManagerWidth', managerSize);
|
||||
$: if (cellViewWidth) setLocalStorage('dataGridCellViewWidth', cellViewWidth);
|
||||
|
||||
function getInitialManagerSize() {
|
||||
const width = getLocalStorage('dataGridManagerWidth');
|
||||
@@ -165,6 +184,14 @@
|
||||
}
|
||||
return '300px';
|
||||
}
|
||||
|
||||
function getInitialCellViewWidth() {
|
||||
const width = getLocalStorage('dataGridCellViewWidth');
|
||||
if (_.isNumber(width) && width > 30 && width < 500) {
|
||||
return width;
|
||||
}
|
||||
return 300;
|
||||
}
|
||||
</script>
|
||||
|
||||
<HorizontalSplitter
|
||||
@@ -219,6 +246,7 @@
|
||||
skip={!(showMacros && isProApp())}
|
||||
collapsed={!expandMacros}
|
||||
data-testid="DataGrid_itemMacros"
|
||||
height="20%"
|
||||
>
|
||||
<MacroManager {...$$props} {managerSize} />
|
||||
</WidgetColumnBarItem>
|
||||
@@ -227,30 +255,49 @@
|
||||
<svelte:fragment slot="2">
|
||||
<VerticalSplitter initialValue="70%" isSplitter={!!$selectedMacro && !isFormView && showMacros}>
|
||||
<svelte:fragment slot="1">
|
||||
{#if isFormView}
|
||||
<svelte:component this={formViewComponent} {...$$props} />
|
||||
{:else if isJsonView}
|
||||
<svelte:component this={jsonViewComponent} {...$$props} {setLoadedRows} />
|
||||
{:else}
|
||||
<svelte:component
|
||||
this={gridCoreComponent}
|
||||
{...$$props}
|
||||
{collapsedLeftColumnStore}
|
||||
formViewAvailable={!!formViewComponent}
|
||||
macroValues={extractMacroValuesForMacro($macroValues, $selectedMacro)}
|
||||
macroPreview={$selectedMacro}
|
||||
{setLoadedRows}
|
||||
onPublishedCellsChanged={value => {
|
||||
publishedCells = value;
|
||||
if (onPublishedCellsChanged) {
|
||||
onPublishedCellsChanged(value);
|
||||
}
|
||||
}}
|
||||
onChangeSelectedColumns={cols => {
|
||||
if (domColumnManager) domColumnManager.setSelectedColumns(cols);
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
<HorizontalSplitter
|
||||
initialSizeRight={getInitialCellViewWidth()}
|
||||
onChangeSize={value => (cellViewWidth = value)}
|
||||
isSplitter={cellDataViewVisible && !isFormView}
|
||||
>
|
||||
<svelte:fragment slot="1">
|
||||
{#if isFormView}
|
||||
<svelte:component this={formViewComponent} {...$$props} />
|
||||
{:else if isJsonView}
|
||||
<svelte:component this={jsonViewComponent} {...$$props} {setLoadedRows} />
|
||||
{:else}
|
||||
<svelte:component
|
||||
this={gridCoreComponent}
|
||||
{...$$props}
|
||||
{collapsedLeftColumnStore}
|
||||
formViewAvailable={!!formViewComponent}
|
||||
macroValues={extractMacroValuesForMacro($macroValues, $selectedMacro)}
|
||||
macroPreview={$selectedMacro}
|
||||
{setLoadedRows}
|
||||
onPublishedCellsChanged={value => {
|
||||
publishedCells = value;
|
||||
if (onPublishedCellsChanged) {
|
||||
onPublishedCellsChanged(value);
|
||||
}
|
||||
if (value[0]?.isSelectedFullRow && !isFormView) {
|
||||
cellDataViewVisible = true;
|
||||
}
|
||||
}}
|
||||
onChangeSelectedColumns={cols => {
|
||||
if (domColumnManager) domColumnManager.setSelectedColumns(cols);
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="2">
|
||||
<CellDataWidget
|
||||
onClose={() => {
|
||||
cellDataViewVisible = false;
|
||||
}}
|
||||
selection={publishedCells}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
</HorizontalSplitter>
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="2">
|
||||
|
||||
@@ -57,7 +57,11 @@
|
||||
$: style = computeStyle(maxWidth, col);
|
||||
|
||||
$: isJson =
|
||||
_.isPlainObject(value) && !(value?.type == 'Buffer' && _.isArray(value.data)) && !value.$oid && !value.$bigint && !value.$decimal;
|
||||
_.isPlainObject(value) &&
|
||||
!(value?.type == 'Buffer' && _.isArray(value.data)) &&
|
||||
!value.$oid &&
|
||||
!value.$bigint &&
|
||||
!value.$decimal;
|
||||
|
||||
// don't parse JSON for explicit data types
|
||||
$: jsonParsedValue = !editorTypes?.explicitDataType && isJsonLikeLongString(value) ? safeJsonParse(value) : null;
|
||||
@@ -80,7 +84,7 @@
|
||||
class:isFocusedColumn
|
||||
class:hasOverlayValue
|
||||
class:isMissingOverlayField
|
||||
class:alignRight={ (_.isNumber(value) || isTypeNumber(col.dataType)) && !showHint}
|
||||
class:alignRight={(_.isNumber(value) || isTypeNumber(col.dataType)) && !showHint && !isModifiedCell}
|
||||
{style}
|
||||
>
|
||||
{#if hasOverlayValue}
|
||||
|
||||
@@ -217,7 +217,7 @@
|
||||
registerCommand({
|
||||
id: 'dataGrid.filterSelected',
|
||||
category: __t('command.datagrid', { defaultMessage: 'Data grid' }),
|
||||
name: __t('command.datagrid.filterSelected', { defaultMessage : 'Filter selected value'}),
|
||||
name: __t('command.datagrid.filterSelected', { defaultMessage: 'Filter selected value' }),
|
||||
keyText: 'CtrlOrCommand+Shift+F',
|
||||
testEnabled: () => getCurrentDataGrid()?.getDisplay().filterable,
|
||||
onClick: () => getCurrentDataGrid().filterSelectedValue(),
|
||||
@@ -225,7 +225,7 @@
|
||||
registerCommand({
|
||||
id: 'dataGrid.findColumn',
|
||||
category: __t('command.datagrid', { defaultMessage: 'Data grid' }),
|
||||
name: __t('command.datagrid.findColumn', { defaultMessage: 'Find column'}),
|
||||
name: __t('command.datagrid.findColumn', { defaultMessage: 'Find column' }),
|
||||
keyText: 'CtrlOrCommand+F',
|
||||
testEnabled: () => getCurrentDataGrid() != null,
|
||||
getSubCommands: () => getCurrentDataGrid().buildFindMenu(),
|
||||
@@ -241,7 +241,7 @@
|
||||
registerCommand({
|
||||
id: 'dataGrid.clearFilter',
|
||||
category: __t('command.datagrid', { defaultMessage: 'Data grid' }),
|
||||
name: __t('command.datagrid.clearFilter', { defaultMessage : 'Clear filter'}),
|
||||
name: __t('command.datagrid.clearFilter', { defaultMessage: 'Clear filter' }),
|
||||
keyText: 'CtrlOrCommand+Shift+E',
|
||||
testEnabled: () => getCurrentDataGrid()?.clearFilterEnabled(),
|
||||
onClick: () => getCurrentDataGrid().clearFilter(),
|
||||
@@ -249,7 +249,7 @@
|
||||
registerCommand({
|
||||
id: 'dataGrid.generateSqlFromData',
|
||||
category: __t('command.datagrid', { defaultMessage: 'Data grid' }),
|
||||
name: __t('command.datagrid.generateSql', { defaultMessage: 'Generate SQL'}),
|
||||
name: __t('command.datagrid.generateSql', { defaultMessage: 'Generate SQL' }),
|
||||
keyText: 'CtrlOrCommand+G',
|
||||
testEnabled: () => getCurrentDataGrid()?.generateSqlFromDataEnabled(),
|
||||
onClick: () => getCurrentDataGrid().generateSqlFromData(),
|
||||
@@ -257,14 +257,14 @@
|
||||
registerCommand({
|
||||
id: 'dataGrid.openFreeTable',
|
||||
category: __t('command.datagrid', { defaultMessage: 'Data grid' }),
|
||||
name: __t('command.datagrid.editSelection', { defaultMessage: 'Edit selection as table'}),
|
||||
name: __t('command.datagrid.editSelection', { defaultMessage: 'Edit selection as table' }),
|
||||
testEnabled: () => getCurrentDataGrid() != null,
|
||||
onClick: () => getCurrentDataGrid().openFreeTable(),
|
||||
});
|
||||
registerCommand({
|
||||
id: 'dataGrid.newJson',
|
||||
category: __t('command.datagrid', { defaultMessage: 'Data grid' }),
|
||||
name: __t('command.datagrid.addJsonDocument', { defaultMessage: 'Add JSON document'}),
|
||||
name: __t('command.datagrid.addJsonDocument', { defaultMessage: 'Add JSON document' }),
|
||||
testEnabled: () => getCurrentDataGrid()?.addJsonDocumentEnabled(),
|
||||
onClick: () => getCurrentDataGrid().addJsonDocument(),
|
||||
});
|
||||
@@ -354,7 +354,7 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { GridDisplay } from 'dbgate-datalib';
|
||||
import { GridDisplay, MacroDefinition } from 'dbgate-datalib';
|
||||
import {
|
||||
driverBase,
|
||||
parseCellValue,
|
||||
@@ -364,6 +364,7 @@
|
||||
base64ToHex,
|
||||
} from 'dbgate-tools';
|
||||
import { getContext, onDestroy } from 'svelte';
|
||||
import { type Writable } from 'svelte/store';
|
||||
import _, { map } from 'lodash';
|
||||
import registerCommand from '../commands/registerCommand';
|
||||
import ColumnHeaderControl from './ColumnHeaderControl.svelte';
|
||||
@@ -380,7 +381,17 @@
|
||||
filterCellsForRow,
|
||||
} from './gridutil';
|
||||
import HorizontalScrollBar from './HorizontalScrollBar.svelte';
|
||||
import { cellFromEvent, emptyCellArray, getCellRange, isRegularCell, nullCell, topLeftCell } from './selection';
|
||||
import {
|
||||
cellFromEvent,
|
||||
emptyCellArray,
|
||||
getCellRange,
|
||||
isColumnHeaderCell,
|
||||
isRegularCell,
|
||||
isRowHeaderCell,
|
||||
isTableHeaderCell,
|
||||
nullCell,
|
||||
topLeftCell,
|
||||
} from './selection';
|
||||
import VerticalScrollBar from './VerticalScrollBar.svelte';
|
||||
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
||||
import InlineButton from '../buttons/InlineButton.svelte';
|
||||
@@ -388,7 +399,7 @@
|
||||
import DataFilterControl from './DataFilterControl.svelte';
|
||||
import createReducer from '../utility/createReducer';
|
||||
import keycodes from '../utility/keycodes';
|
||||
import { copyRowsFormat, currentArchive, selectedCellsCallback } from '../stores';
|
||||
import { copyRowsFormat, currentArchive } from '../stores';
|
||||
import {
|
||||
copyRowsFormatDefs,
|
||||
copyRowsToClipboard,
|
||||
@@ -426,6 +437,7 @@
|
||||
import { isProApp } from '../utility/proTools';
|
||||
import SaveArchiveModal from '../modals/SaveArchiveModal.svelte';
|
||||
import hasPermission from '../utility/hasPermission';
|
||||
import macros from '../macro/macros';
|
||||
|
||||
export let onLoadNextData = undefined;
|
||||
export let grider = undefined;
|
||||
@@ -465,6 +477,7 @@
|
||||
export let overlayDefinition = null;
|
||||
export let onGetSelectionMenu = null;
|
||||
export let onOpenChart = null;
|
||||
export let macroCondition = null;
|
||||
|
||||
export const activator = createActivator('DataGridCore', false);
|
||||
|
||||
@@ -496,6 +509,7 @@
|
||||
let selectionMenu = null;
|
||||
|
||||
const tabid = getContext('tabid');
|
||||
const selectedMacro = getContext('selectedMacro') as Writable<MacroDefinition>;
|
||||
|
||||
let unsubscribeDbRefresh;
|
||||
|
||||
@@ -759,7 +773,7 @@
|
||||
|
||||
export function saveCellToFileEnabled() {
|
||||
const value = getSelectedExportableCell();
|
||||
return _.isString(value) || (value?.type == 'Buffer' && _.isArray(value?.data)) || (value?.$binary?.base64);
|
||||
return _.isString(value) || (value?.type == 'Buffer' && _.isArray(value?.data)) || value?.$binary?.base64;
|
||||
}
|
||||
|
||||
export async function saveCellToFile() {
|
||||
@@ -898,7 +912,7 @@
|
||||
await tick();
|
||||
const invMap = _.invert(realColumnUniqueNames);
|
||||
const colIndex = invMap[uniquePath.join('.')];
|
||||
scrollIntoView([null, colIndex]);
|
||||
scrollIntoView([null, parseInt(colIndex)]);
|
||||
|
||||
currentCell = [currentCell[0], parseInt(colIndex)];
|
||||
selectedCells = [currentCell];
|
||||
@@ -1154,7 +1168,7 @@
|
||||
const invMap = _.invert(realColumnUniqueNames);
|
||||
const colIndex = invMap[display.focusedColumns[0]];
|
||||
if (colIndex) {
|
||||
scrollIntoView([null, colIndex]);
|
||||
scrollIntoView([null, parseInt(colIndex)]);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1203,7 +1217,6 @@
|
||||
if (rowIndexes.every(x => grider.getRowData(x))) {
|
||||
lastPublishledSelectedCellsRef.set(stringified);
|
||||
changeSetValueRef.set($changeSetStore?.value);
|
||||
$selectedCellsCallback = () => getCellsPublished(selectedCells);
|
||||
|
||||
if (onChangeSelectedColumns) {
|
||||
onChangeSelectedColumns(getSelectedColumns().map(x => x.columnName));
|
||||
@@ -1244,30 +1257,59 @@
|
||||
|
||||
function getCellsPublished(cells) {
|
||||
const regular = cellsToRegularCells(cells);
|
||||
|
||||
const commonInfo = {
|
||||
engine: display?.driver,
|
||||
editable: grider.editable,
|
||||
editorTypes: display?.driver?.dataEditorTypesBehaviour,
|
||||
displayColumns: columns,
|
||||
realColumnUniqueNames,
|
||||
grider,
|
||||
};
|
||||
|
||||
const rowIndexes = _.sortBy(_.uniq(regular.map(x => x[0])));
|
||||
const fullRowIndexes = new Set(cells.filter(x => x[1] == 'header').map(x => x[0]));
|
||||
const rowInfos = rowIndexes.map(row => {
|
||||
const rowData = grider.getRowData(row);
|
||||
|
||||
return {
|
||||
row,
|
||||
rowData,
|
||||
condition: display?.getChangeSetCondition(rowData),
|
||||
insertedRowIndex: grider?.getInsertedRowIndex(row),
|
||||
rowStatus: grider.getRowStatus(row),
|
||||
isSelectedFullRow: fullRowIndexes.has(row),
|
||||
};
|
||||
});
|
||||
|
||||
const rowInfoByIndex = _.zipObject(
|
||||
rowIndexes.map(x => x.toString()),
|
||||
rowInfos
|
||||
);
|
||||
|
||||
const res = regular
|
||||
.map(cell => {
|
||||
const row = cell[0];
|
||||
const rowData = grider.getRowData(row);
|
||||
const column = realColumnUniqueNames[cell[1]];
|
||||
const rowData = rowInfoByIndex[row].rowData;
|
||||
|
||||
return {
|
||||
row,
|
||||
rowData,
|
||||
...commonInfo,
|
||||
...rowInfoByIndex[row],
|
||||
column,
|
||||
value: rowData && rowData[column],
|
||||
engine: display?.driver,
|
||||
condition: display?.getChangeSetCondition(rowData),
|
||||
insertedRowIndex: grider?.getInsertedRowIndex(row),
|
||||
rowStatus: grider.getRowStatus(row),
|
||||
onSetValue: value => grider.setCellValue(row, column, value),
|
||||
};
|
||||
})
|
||||
.filter(x => x.column);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function scrollIntoView(cell) {
|
||||
const [row, col] = cell;
|
||||
|
||||
if (row != null) {
|
||||
if (_.isNumber(row)) {
|
||||
let newRow = null;
|
||||
const rowCount = grider.rowCount;
|
||||
if (rowCount == 0) return;
|
||||
@@ -1285,7 +1327,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (col != null) {
|
||||
if (_.isNumber(col)) {
|
||||
if (col >= columnSizes.frozenCount) {
|
||||
let newColumn = columnSizes.scrollInView(
|
||||
firstVisibleColumnScrollIndex,
|
||||
@@ -1515,7 +1557,11 @@
|
||||
}
|
||||
|
||||
if (event.shiftKey) {
|
||||
if (!isRegularCell(shiftDragStartCell)) {
|
||||
if (
|
||||
!isRegularCell(shiftDragStartCell) &&
|
||||
!isColumnHeaderCell(shiftDragStartCell) &&
|
||||
!isRowHeaderCell(shiftDragStartCell)
|
||||
) {
|
||||
shiftDragStartCell = currentCell;
|
||||
}
|
||||
} else {
|
||||
@@ -1543,7 +1589,13 @@
|
||||
}
|
||||
|
||||
function handleCursorMove(event) {
|
||||
if (!isRegularCell(currentCell)) return null;
|
||||
if (
|
||||
!isRegularCell(currentCell) &&
|
||||
!isColumnHeaderCell(currentCell) &&
|
||||
!isRowHeaderCell(currentCell) &&
|
||||
!isTableHeaderCell(currentCell)
|
||||
)
|
||||
return null;
|
||||
let rowCount = grider.rowCount;
|
||||
if (isCtrlOrCommandKey(event)) {
|
||||
switch (event.keyCode) {
|
||||
@@ -1570,24 +1622,36 @@
|
||||
switch (event.keyCode) {
|
||||
case keycodes.upArrow:
|
||||
if (currentCell[0] == 0) return focusFilterEditor(currentCell[1]);
|
||||
return moveCurrentCell(currentCell[0] - 1, currentCell[1], event);
|
||||
return _.isNumber(currentCell[0]) ? moveCurrentCell(currentCell[0] - 1, currentCell[1], event) : null;
|
||||
case keycodes.downArrow:
|
||||
return moveCurrentCell(currentCell[0] + 1, currentCell[1], event);
|
||||
if (currentCell[0] == 'header') return focusFilterEditor(currentCell[1]);
|
||||
return _.isNumber(currentCell[0]) ? moveCurrentCell(currentCell[0] + 1, currentCell[1], event) : null;
|
||||
case keycodes.enter:
|
||||
if (!grider.editable) return moveCurrentCell(currentCell[0] + 1, currentCell[1], event);
|
||||
if (!grider.editable)
|
||||
return _.isNumber(currentCell[0]) ? moveCurrentCell(currentCell[0] + 1, currentCell[1], event) : null;
|
||||
break;
|
||||
case keycodes.leftArrow:
|
||||
return moveCurrentCell(currentCell[0], currentCell[1] - 1, event);
|
||||
return _.isNumber(currentCell[1])
|
||||
? moveCurrentCell(currentCell[0], currentCell[1] == 0 ? 'header' : currentCell[1] - 1, event)
|
||||
: null;
|
||||
case keycodes.rightArrow:
|
||||
return moveCurrentCell(currentCell[0], currentCell[1] + 1, event);
|
||||
return currentCell[1] == 'header'
|
||||
? moveCurrentCell(currentCell[0], 0, event)
|
||||
: _.isNumber(currentCell[1])
|
||||
? moveCurrentCell(currentCell[0], currentCell[1] + 1, event)
|
||||
: null;
|
||||
case keycodes.home:
|
||||
return moveCurrentCell(currentCell[0], 0, event);
|
||||
case keycodes.end:
|
||||
return moveCurrentCell(currentCell[0], columnSizes.realCount - 1, event);
|
||||
case keycodes.pageUp:
|
||||
return moveCurrentCell(currentCell[0] - visibleRowCountLowerBound, currentCell[1], event);
|
||||
return _.isNumber(currentCell[0])
|
||||
? moveCurrentCell(currentCell[0] - visibleRowCountLowerBound, currentCell[1], event)
|
||||
: null;
|
||||
case keycodes.pageDown:
|
||||
return moveCurrentCell(currentCell[0] + visibleRowCountLowerBound, currentCell[1], event);
|
||||
return _.isNumber(currentCell[0])
|
||||
? moveCurrentCell(currentCell[0] + visibleRowCountLowerBound, currentCell[1], event)
|
||||
: null;
|
||||
case keycodes.tab: {
|
||||
return moveCurrentCellWithTabKey(event.shiftKey);
|
||||
}
|
||||
@@ -1621,10 +1685,14 @@
|
||||
function moveCurrentCell(row, col, event = null) {
|
||||
const rowCount = grider.rowCount;
|
||||
|
||||
if (row < 0) row = 0;
|
||||
if (row >= rowCount) row = rowCount - 1;
|
||||
if (col < 0) col = 0;
|
||||
if (col >= columnSizes.realCount) col = columnSizes.realCount - 1;
|
||||
if (_.isNumber(row)) {
|
||||
if (row < 0) row = 0;
|
||||
if (row >= rowCount) row = rowCount - 1;
|
||||
}
|
||||
if (_.isNumber(col)) {
|
||||
if (col < 0) col = 0;
|
||||
if (col >= columnSizes.realCount) col = columnSizes.realCount - 1;
|
||||
}
|
||||
currentCell = [row, col];
|
||||
// setSelectedCells([...(event.ctrlKey ? selectedCells : []), [row, col]]);
|
||||
selectedCells = [[row, col]];
|
||||
@@ -1744,6 +1812,17 @@
|
||||
if (domFocusField) domFocusField.focus();
|
||||
};
|
||||
|
||||
const selectColumnHeaderCell = uniquePath => {
|
||||
const modelIndex = columns.findIndex(x => x.uniquePath == uniquePath);
|
||||
const realIndex = columnSizes.modelToReal(modelIndex);
|
||||
let cell = ['header', realIndex];
|
||||
// @ts-ignore
|
||||
currentCell = cell;
|
||||
// @ts-ignore
|
||||
selectedCells = [cell];
|
||||
if (domFocusField) domFocusField.focus();
|
||||
};
|
||||
|
||||
const [inplaceEditorState, dispatchInsplaceEditor] = createReducer((state, action) => {
|
||||
switch (action.type) {
|
||||
case 'show':
|
||||
@@ -1796,7 +1875,7 @@
|
||||
{ command: 'dataGrid.refresh' },
|
||||
{ placeTag: 'copy' },
|
||||
{
|
||||
text: _t('datagrid.copyAdvanced', { defaultMessage: 'Copy advanced'}),
|
||||
text: _t('datagrid.copyAdvanced', { defaultMessage: 'Copy advanced' }),
|
||||
submenu: [
|
||||
_.keys(copyRowsFormatDefs).map(format => ({
|
||||
text: _tval(copyRowsFormatDefs[format].label),
|
||||
@@ -1804,7 +1883,7 @@
|
||||
})),
|
||||
{ divider: true },
|
||||
_.keys(copyRowsFormatDefs).map(format => ({
|
||||
text: _t('datagrid.setFormat', { defaultMessage: 'Set format: ' }) + (_tval(copyRowsFormatDefs[format].name)),
|
||||
text: _t('datagrid.setFormat', { defaultMessage: 'Set format: ' }) + _tval(copyRowsFormatDefs[format].name),
|
||||
onClick: () => ($copyRowsFormat = format),
|
||||
})),
|
||||
|
||||
@@ -1841,6 +1920,18 @@
|
||||
{ command: 'dataGrid.openJsonArrayInSheet', hideDisabled: true },
|
||||
{ command: 'dataGrid.saveCellToFile', hideDisabled: true },
|
||||
{ command: 'dataGrid.loadCellFromFile', hideDisabled: true },
|
||||
{ command: 'dataGrid.toggleCellDataView', hideDisabled: true },
|
||||
isProApp() && {
|
||||
text: _t('datagrid.useMacro', { defaultMessage: 'Use macro' }),
|
||||
submenu: macros
|
||||
.filter(macro => !macroCondition || macroCondition(macro))
|
||||
.map(macro => ({
|
||||
text: _tval(macro.title),
|
||||
onClick: () => {
|
||||
selectedMacro.set(macro);
|
||||
},
|
||||
})),
|
||||
},
|
||||
// { command: 'dataGrid.copyJsonDocument', hideDisabled: true },
|
||||
{ divider: true },
|
||||
{ placeTag: 'export' },
|
||||
@@ -1992,6 +2083,7 @@
|
||||
data-row="header"
|
||||
data-col={col.colIndex}
|
||||
style={`width:${col.width}px; min-width:${col.width}px; max-width:${col.width}px`}
|
||||
class:active-header-cell={currentCell && currentCell[0] == 'header' && currentCell[1] == col.colIndex}
|
||||
>
|
||||
<ColumnHeaderControl
|
||||
column={col}
|
||||
@@ -2066,6 +2158,9 @@
|
||||
onFocusGrid={() => {
|
||||
selectTopmostCell(col.uniqueName);
|
||||
}}
|
||||
onFocusGridHeader={() => {
|
||||
selectColumnHeaderCell(col.uniqueName);
|
||||
}}
|
||||
dataType={col.dataType}
|
||||
filterDisabled={display.isFilterDisabled(col.uniqueName)}
|
||||
/>
|
||||
@@ -2192,6 +2287,9 @@
|
||||
background-color: var(--theme-bg-1);
|
||||
overflow: hidden;
|
||||
}
|
||||
:global(.data-grid-focused) .active-header-cell {
|
||||
background-color: var(--theme-bg-selected);
|
||||
}
|
||||
.filter-cell {
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
onShowForm={onSetFormView && !overlayDefinition ? () => onSetFormView(rowData, null) : null}
|
||||
extraIcon={overlayDefinition ? OVERLAY_STATUS_ICONS[rowStatus.status] : null}
|
||||
extraIconTooltip={overlayDefinition ? OVERLAY_STATUS_TOOLTIPS[rowStatus.status] : null}
|
||||
isSelected={frameSelection ? false : !!selectedCells?.find(cell => cell[0] == rowIndex && cell[1] == 'header')}
|
||||
/>
|
||||
{#each visibleRealColumns as col (col.uniqueName)}
|
||||
{#if inplaceEditorState.cell && rowIndex == inplaceEditorState.cell[0] && col.colIndex == inplaceEditorState.cell[1]}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
export let extraIcon = null;
|
||||
export let extraIconTooltip = null;
|
||||
export let isSelected = false;
|
||||
|
||||
let mouseIn = false;
|
||||
</script>
|
||||
@@ -14,6 +15,7 @@
|
||||
<td
|
||||
data-row={rowIndex}
|
||||
data-col="header"
|
||||
class:selected={isSelected}
|
||||
on:mouseenter={() => (mouseIn = true)}
|
||||
on:mouseleave={() => (mouseIn = false)}
|
||||
>
|
||||
@@ -43,4 +45,7 @@
|
||||
right: 0px;
|
||||
top: 1px;
|
||||
}
|
||||
:global(.data-grid-focused) td.selected {
|
||||
background-color: var(--theme-bg-selected);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -13,6 +13,24 @@ export function isRegularCell(cell: CellAddress): cell is RegularCellAddress {
|
||||
return _.isNumber(row) && _.isNumber(col);
|
||||
}
|
||||
|
||||
export function isRowHeaderCell(cell: CellAddress): boolean {
|
||||
if (!cell) return false;
|
||||
const [row, col] = cell;
|
||||
return col === 'header' && _.isNumber(row);
|
||||
}
|
||||
|
||||
export function isColumnHeaderCell(cell: CellAddress): boolean {
|
||||
if (!cell) return false;
|
||||
const [row, col] = cell;
|
||||
return row === 'header' && _.isNumber(col);
|
||||
}
|
||||
|
||||
export function isTableHeaderCell(cell: CellAddress): boolean {
|
||||
if (!cell) return false;
|
||||
const [row, col] = cell;
|
||||
return row === 'header' && col === 'header';
|
||||
}
|
||||
|
||||
function normalizeHeaderForSelection(addr: CellAddress): CellAddress {
|
||||
if (addr[0] == 'filter') return ['header', addr[1]];
|
||||
return addr;
|
||||
|
||||
@@ -1,4 +1,44 @@
|
||||
<script lang="ts" context="module">
|
||||
const LAT_PRIORITY_PATTERNS = [
|
||||
/^lat$/i,
|
||||
/^latitude$/i,
|
||||
/latitude$/i,
|
||||
/lat$/i,
|
||||
/latitude/i,
|
||||
/lat/i,
|
||||
];
|
||||
|
||||
const LON_PRIORITY_PATTERNS = [
|
||||
/^lon$/i,
|
||||
/^lng$/i,
|
||||
/^longitude$/i,
|
||||
/longitude$/i,
|
||||
/lon$/i,
|
||||
/lng$/i,
|
||||
/longitude/i,
|
||||
/lon|lng/i,
|
||||
];
|
||||
|
||||
function getFieldName(fieldPath) {
|
||||
return fieldPath.split('.').pop() || fieldPath;
|
||||
}
|
||||
|
||||
function getFieldPriority(fieldPath, patterns) {
|
||||
const name = getFieldName(fieldPath);
|
||||
for (let i = 0; i < patterns.length; i++) {
|
||||
if (patterns[i].test(name)) return i;
|
||||
}
|
||||
return patterns.length;
|
||||
}
|
||||
|
||||
function sortByPriorityThenLength(paths, patterns) {
|
||||
return paths.sort((a, b) => {
|
||||
const priorityDiff = getFieldPriority(a, patterns) - getFieldPriority(b, patterns);
|
||||
if (priorityDiff !== 0) return priorityDiff;
|
||||
return getFieldName(a).length - getFieldName(b).length;
|
||||
});
|
||||
}
|
||||
|
||||
function findLatLonPaths(obj, attrTest, res = [], prefix = '') {
|
||||
for (const key of Object.keys(obj)) {
|
||||
if (attrTest(key, obj[key])) {
|
||||
@@ -10,11 +50,15 @@
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
export function findLatPaths(obj) {
|
||||
return findLatLonPaths(obj, x => x.toLowerCase()?.includes('lat'));
|
||||
const paths = findLatLonPaths(obj, x => x.toLowerCase()?.includes('lat'));
|
||||
return sortByPriorityThenLength(paths, LAT_PRIORITY_PATTERNS);
|
||||
}
|
||||
|
||||
export function findLonPaths(obj) {
|
||||
return findLatLonPaths(obj, x => x.toLowerCase()?.includes('lon') || x.toLowerCase()?.includes('lng'));
|
||||
const paths = findLatLonPaths(obj, x => x.toLowerCase()?.includes('lon') || x.toLowerCase()?.includes('lng'));
|
||||
return sortByPriorityThenLength(paths, LON_PRIORITY_PATTERNS);
|
||||
}
|
||||
export function findAllObjectPaths(obj) {
|
||||
return findLatLonPaths(obj, (_k, v) => v != null && !_.isNaN(Number(v)));
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
import FormStringList from './FormStringList.svelte';
|
||||
import FormDropDownTextField from './FormDropDownTextField.svelte';
|
||||
import { getFormContext } from './FormProviderCore.svelte';
|
||||
import { _tval } from '../translations';
|
||||
|
||||
export let arg;
|
||||
export let namePrefix;
|
||||
export let isReadOnly = false;
|
||||
|
||||
$: name = `${namePrefix}${arg.name}`;
|
||||
|
||||
@@ -18,46 +20,52 @@
|
||||
|
||||
{#if arg.type == 'text'}
|
||||
<FormTextField
|
||||
label={arg.label}
|
||||
label={_tval(arg.label)}
|
||||
{name}
|
||||
defaultValue={arg.default}
|
||||
focused={arg.focused}
|
||||
placeholder={arg.placeholder}
|
||||
disabled={arg.disabledFn ? arg.disabledFn($values) : arg.disabled}
|
||||
disabled={isReadOnly || (arg.disabledFn ? arg.disabledFn($values) : arg.disabled)}
|
||||
/>
|
||||
{:else if arg.type == 'stringlist'}
|
||||
<FormStringList label={arg.label} addButtonLabel={arg.addButtonLabel} {name} placeholder={arg.placeholder} />
|
||||
<FormStringList
|
||||
label={_tval(arg.label)}
|
||||
addButtonLabel={_tval(arg.addButtonLabel)}
|
||||
{name}
|
||||
placeholder={arg.placeholder}
|
||||
isReadOnly={isReadOnly || (arg.disabledFn ? arg.disabledFn($values) : arg.disabled)}
|
||||
/>
|
||||
{:else if arg.type == 'number'}
|
||||
<FormTextField
|
||||
label={arg.label}
|
||||
label={_tval(arg.label)}
|
||||
type="number"
|
||||
{name}
|
||||
defaultValue={arg.default}
|
||||
focused={arg.focused}
|
||||
placeholder={arg.placeholder}
|
||||
disabled={arg.disabledFn ? arg.disabledFn($values) : arg.disabled}
|
||||
disabled={isReadOnly || (arg.disabledFn ? arg.disabledFn($values) : arg.disabled)}
|
||||
/>
|
||||
{:else if arg.type == 'checkbox'}
|
||||
<FormCheckboxField
|
||||
label={arg.label}
|
||||
label={_tval(arg.label)}
|
||||
{name}
|
||||
defaultValue={arg.default}
|
||||
disabled={arg.disabledFn ? arg.disabledFn($values) : arg.disabled}
|
||||
disabled={isReadOnly || (arg.disabledFn ? arg.disabledFn($values) : arg.disabled)}
|
||||
/>
|
||||
{:else if arg.type == 'select'}
|
||||
<FormSelectField
|
||||
label={arg.label}
|
||||
label={_tval(arg.label)}
|
||||
isNative
|
||||
{name}
|
||||
defaultValue={arg.default}
|
||||
options={arg.options.map(opt =>
|
||||
_.isString(opt) ? { label: opt, value: opt } : { label: opt.name, value: opt.value }
|
||||
)}
|
||||
disabled={arg.disabledFn ? arg.disabledFn($values) : arg.disabled}
|
||||
disabled={isReadOnly || (arg.disabledFn ? arg.disabledFn($values) : arg.disabled)}
|
||||
/>
|
||||
{:else if arg.type == 'dropdowntext'}
|
||||
<FormDropDownTextField
|
||||
label={arg.label}
|
||||
label={_tval(arg.label)}
|
||||
{name}
|
||||
defaultValue={arg.default}
|
||||
menu={() => {
|
||||
@@ -66,6 +74,6 @@
|
||||
onClick: () => setFieldValue(name, _.isString(opt) ? opt : opt.value),
|
||||
}));
|
||||
}}
|
||||
disabled={arg.disabledFn ? arg.disabledFn($values) : arg.disabled}
|
||||
disabled={isReadOnly || (arg.disabledFn ? arg.disabledFn($values) : arg.disabled)}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
|
||||
export let namePrefix = '';
|
||||
export let args: any[];
|
||||
export let isReadOnly = false;
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#each args as arg (arg.name)}
|
||||
<FormArgument {arg} {namePrefix} />
|
||||
<FormArgument {arg} {namePrefix} {isReadOnly} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
export let addButtonLabel;
|
||||
export let placeholder;
|
||||
export let templateProps;
|
||||
export let isReadOnly = false;
|
||||
|
||||
const { template, values, setFieldValue } = getFormContext();
|
||||
|
||||
@@ -20,7 +21,7 @@
|
||||
|
||||
<svelte:component this={template} type="text" {label} {...templateProps}>
|
||||
{#each stringList as value, index}
|
||||
<div class='input-line-flex'>
|
||||
<div class="input-line-flex">
|
||||
<TextField
|
||||
{value}
|
||||
{placeholder}
|
||||
@@ -28,12 +29,14 @@
|
||||
const newValues = stringList.map((v, i) => (i === index ? e.target['value'] : v));
|
||||
setFieldValue(name, newValues);
|
||||
}}
|
||||
disabled={isReadOnly}
|
||||
/>
|
||||
|
||||
<InlineButton
|
||||
on:click={() => {
|
||||
setFieldValue(name, [...stringList.slice(0, index), ...stringList.slice(index + 1)]);
|
||||
}}
|
||||
disabled={isReadOnly}
|
||||
>
|
||||
<FontIcon icon="icon delete" />
|
||||
</InlineButton>
|
||||
@@ -45,11 +48,12 @@
|
||||
on:click={() => {
|
||||
setFieldValue(name, [...stringList, '']);
|
||||
}}
|
||||
disabled={isReadOnly}
|
||||
/>
|
||||
</svelte:component>
|
||||
|
||||
<style>
|
||||
.input-line-flex {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
.input-line-flex {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { getContext } from 'svelte';
|
||||
import FontIcon from '../icons/FontIcon.svelte';
|
||||
import ToolbarButton from '../buttons/ToolbarButton.svelte';
|
||||
import { _t } from '../translations';
|
||||
import { _t, _tval } from '../translations';
|
||||
|
||||
export let onExecute;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<div class="header">
|
||||
<FontIcon icon="img macro" />
|
||||
<div class="ml-2">
|
||||
{$selectedMacro?.title}
|
||||
{_tval($selectedMacro?.title)}
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import WidgetTitle from '../widgets/WidgetTitle.svelte';
|
||||
import MacroParameters from './MacroParameters.svelte';
|
||||
import { _t } from '../translations';
|
||||
import { _t, _tval } from '../translations';
|
||||
|
||||
const selectedMacro = getContext('selectedMacro') as any;
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
<div class="section">
|
||||
<WidgetTitle>{_t('common.description', { defaultMessage: 'Description' })}</WidgetTitle>
|
||||
<div class="m-1">{$selectedMacro?.description}</div>
|
||||
<div class="m-1">{_tval($selectedMacro?.description)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -95,7 +95,6 @@
|
||||
title: _t('common.exportDatabase', { defaultMessage: 'Export database' }),
|
||||
description: _t('newObject.exportDescription', { defaultMessage: 'Export to file like CSV, JSON, Excel, or other DB' }),
|
||||
command: 'database.export',
|
||||
isProFeature: true,
|
||||
testid: 'NewObjectModal_databaseExport',
|
||||
disabledMessage: _t('newObject.exportDisabled', { defaultMessage: 'Export is not available for current database' }),
|
||||
},
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import ManagerInnerContainer from '../elements/ManagerInnerContainer.svelte';
|
||||
import FontIcon from '../icons/FontIcon.svelte';
|
||||
import PerspectiveFiltersColumn from './PerspectiveFiltersColumn.svelte';
|
||||
import { _t } from '../translations';
|
||||
|
||||
export let managerSize;
|
||||
export let config: PerspectiveConfig;
|
||||
@@ -25,8 +26,8 @@
|
||||
<ManagerInnerContainer width={managerSize} isFlex={filterCount == 0}>
|
||||
{#if filterCount == 0}
|
||||
<div class="msg">
|
||||
<div class="mb-3 bold">No Filters defined</div>
|
||||
<div><FontIcon icon="img info" /> Use context menu, command "Add to filter" in table or in tree</div>
|
||||
<div class="mb-3 bold">{_t('perspective.noFiltersDefined', { defaultMessage: "No Filters defined" })}</div>
|
||||
<div><FontIcon icon="img info" /> {_t('perspective.useContextMenuAddToFilter', { defaultMessage: 'Use context menu, command "Add to filter" in table or in tree' })}</div>
|
||||
</div>
|
||||
{:else}
|
||||
{#each config.nodes as nodeConfig}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
registerCommand({
|
||||
id: 'perspective.openJson',
|
||||
category: 'Perspective',
|
||||
name: 'Open JSON',
|
||||
category: __t('command.perspective', { defaultMessage: 'Perspective' }),
|
||||
name: __t('command.perspective.openJson', { defaultMessage: 'Open JSON' }),
|
||||
isRelatedToTab: true,
|
||||
testEnabled: () => getCurrentEditor()?.openJsonEnabled(),
|
||||
onClick: () => getCurrentEditor().openJson(),
|
||||
@@ -40,6 +40,7 @@
|
||||
import openNewTab from '../utility/openNewTab';
|
||||
import { getFilterValueExpression } from 'dbgate-filterparser';
|
||||
import StatusBarTabItem from '../widgets/StatusBarTabItem.svelte';
|
||||
import { __t } from '../translations';
|
||||
|
||||
const TABS_BY_FIELD = {
|
||||
tables: {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
registerCommand({
|
||||
id: 'perspective.customJoin',
|
||||
category: 'Perspective',
|
||||
name: 'Custom join',
|
||||
category: __t('perspective.category', { defaultMessage: 'Perspective' }),
|
||||
name: __t('perspective.customJoin', { defaultMessage: 'Custom join' }),
|
||||
keyText: 'CtrlOrCommand+J',
|
||||
isRelatedToTab: true,
|
||||
icon: 'icon custom-join',
|
||||
@@ -65,6 +65,7 @@
|
||||
import FontIcon from '../icons/FontIcon.svelte';
|
||||
import InlineButton from '../buttons/InlineButton.svelte';
|
||||
import { usePerspectiveDataPatterns } from '../utility/usePerspectiveDataPatterns';
|
||||
import { _t, __t } from '../translations';
|
||||
|
||||
const dbg = debug('dbgate:PerspectiveView');
|
||||
|
||||
@@ -168,7 +169,7 @@
|
||||
<HorizontalSplitter initialValue={getInitialManagerSize()} bind:size={managerSize} allowCollapseChild1>
|
||||
<div class="left" slot="1">
|
||||
<WidgetColumnBar>
|
||||
<WidgetColumnBarItem title="Choose data" name="perspectiveTree" height={'70%'}>
|
||||
<WidgetColumnBarItem title={_t('perspective.chooseData', { defaultMessage: "Choose data" })} name="perspectiveTree" height={'70%'}>
|
||||
{#if tempRoot && tempRoot != root}
|
||||
<div class="temp-root">
|
||||
<div>
|
||||
@@ -184,7 +185,7 @@
|
||||
{/if}
|
||||
|
||||
<SearchBoxWrapper>
|
||||
<SearchInput placeholder="Search column or table" bind:value={filter} />
|
||||
<SearchInput placeholder={_t('perspective.searchColumnOrTable', { defaultMessage: "Search column or table" })} bind:value={filter} />
|
||||
<CloseSearchButton bind:filter />
|
||||
</SearchBoxWrapper>
|
||||
|
||||
@@ -195,7 +196,7 @@
|
||||
</ManagerInnerContainer>
|
||||
</WidgetColumnBarItem>
|
||||
|
||||
<WidgetColumnBarItem title="Filters" name="tableFilters">
|
||||
<WidgetColumnBarItem title={_t('perspective.filters', { defaultMessage: "Filters" })} name="tableFilters">
|
||||
<PerspectiveFilters {managerSize} {config} {setConfig} {conid} {database} {driver} {root} />
|
||||
</WidgetColumnBarItem>
|
||||
</WidgetColumnBar>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import useEffect from '../utility/useEffect';
|
||||
import { getContext } from 'svelte';
|
||||
import { mountCodeCompletion } from './codeCompletion';
|
||||
import { getCurrentSettings } from '../stores';
|
||||
import { currentEditorWrapEnabled, getCurrentSettings } from '../stores';
|
||||
export let engine = null;
|
||||
export let conid = null;
|
||||
export let database = null;
|
||||
@@ -29,6 +29,8 @@
|
||||
mode = engineToMode[match ? match[1] : engine] || 'sql';
|
||||
}
|
||||
|
||||
$: enableWrap = $currentEditorWrapEnabled || false;
|
||||
|
||||
export function getEditor(): ace.Editor {
|
||||
return domEditor.getEditor();
|
||||
}
|
||||
@@ -63,5 +65,6 @@
|
||||
options={{
|
||||
...$$props.options,
|
||||
enableBasicAutocompletion: true,
|
||||
wrap: enableWrap,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
import FormArgumentList from '../forms/FormArgumentList.svelte';
|
||||
import { _t } from '../translations';
|
||||
|
||||
export let isFormReadOnly;
|
||||
|
||||
const { values } = getFormContext();
|
||||
|
||||
$: engine = $values.engine;
|
||||
@@ -17,9 +19,18 @@
|
||||
$: advancedFields = driver?.getAdvancedConnectionFields ? driver?.getAdvancedConnectionFields() : null;
|
||||
</script>
|
||||
|
||||
<FormTextAreaField label={_t('connection.allowedDatabases', { defaultMessage: 'Allowed databases, one per line' })} name="allowedDatabases" disabled={isConnected} rows={8} />
|
||||
<FormTextField label={_t('connection.allowedDatabasesRegex', { defaultMessage: 'Allowed databases regular expression' })} name="allowedDatabasesRegex" disabled={isConnected} />
|
||||
<FormTextAreaField
|
||||
label={_t('connection.allowedDatabases', { defaultMessage: 'Allowed databases, one per line' })}
|
||||
name="allowedDatabases"
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
rows={8}
|
||||
/>
|
||||
<FormTextField
|
||||
label={_t('connection.allowedDatabasesRegex', { defaultMessage: 'Allowed databases regular expression' })}
|
||||
name="allowedDatabasesRegex"
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
/>
|
||||
|
||||
{#if advancedFields}
|
||||
<FormArgumentList args={advancedFields} />
|
||||
<FormArgumentList args={advancedFields} isReadOnly={isFormReadOnly} />
|
||||
{/if}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
export let getDatabaseList;
|
||||
export let currentConnection;
|
||||
export let isFormReadOnly;
|
||||
|
||||
const { values, setFieldValue } = getFormContext();
|
||||
const electron = getElectron();
|
||||
@@ -90,10 +91,10 @@
|
||||
label={_t('connection.type', { defaultMessage: 'Connection type' })}
|
||||
name="engine"
|
||||
isNative
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
data-testid="ConnectionDriverFields_connectionType"
|
||||
options={[
|
||||
{ label: _t('connection.selectType', { defaultMessage: '(select connection type)' })},
|
||||
{ label: _t('connection.selectType', { defaultMessage: '(select connection type)' }) },
|
||||
..._.sortBy(
|
||||
$extensions.drivers
|
||||
// .filter(driver => !driver.isElectronOnly || electron)
|
||||
@@ -113,7 +114,7 @@
|
||||
data-testid="ConnectionDriverFields_authType"
|
||||
name="authType"
|
||||
isNative
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
defaultValue={driver?.defaultAuthTypeName}
|
||||
options={$authTypes.map(auth => ({
|
||||
value: auth.name,
|
||||
@@ -127,16 +128,18 @@
|
||||
<FormClusterNodesField
|
||||
label={_t('connection.clusterNodes', { defaultMessage: 'Cluster nodes' })}
|
||||
name="clusterNodes"
|
||||
disabled={isConnected || disabledFields.includes('clusterNodes')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('clusterNodes')}
|
||||
data-testid="ConnectionDriverFields_clusterNodes"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if driver?.showConnectionField('autoDetectNatMap', $values, showConnectionFieldArgs)}
|
||||
<FormCheckboxField
|
||||
label={_t('connection.autoDetectNatMap', { defaultMessage: 'Auto detect NAT map (use for Redis Cluster in Docker network)' })}
|
||||
label={_t('connection.autoDetectNatMap', {
|
||||
defaultMessage: 'Auto detect NAT map (use for Redis Cluster in Docker network)',
|
||||
})}
|
||||
name="autoDetectNatMap"
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
data-testid="ConnectionDriverFields_autoDetectNatMap"
|
||||
/>
|
||||
{/if}
|
||||
@@ -146,13 +149,13 @@
|
||||
<FormElectronFileSelector
|
||||
label={_t('connection.databaseFile', { defaultMessage: 'Database file' })}
|
||||
name="databaseFile"
|
||||
disabled={isConnected || disabledFields.includes('databaseFile')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('databaseFile')}
|
||||
/>
|
||||
{:else}
|
||||
<FormTextField
|
||||
label={_t('connection.databaseFilePath', { defaultMessage: 'Database file (path on server)' })}
|
||||
name="databaseFile"
|
||||
disabled={isConnected || disabledFields.includes('databaseFile')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('databaseFile')}
|
||||
/>
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -160,11 +163,15 @@
|
||||
{#if driver?.showConnectionField('useDatabaseUrl', $values, showConnectionFieldArgs)}
|
||||
<div class="radio">
|
||||
<FormRadioGroupField
|
||||
disabled={isConnected || disabledFields.includes('useDatabaseUrl')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('useDatabaseUrl')}
|
||||
name="useDatabaseUrl"
|
||||
matchValueToOption={(value, option) => !!option.value == !!value}
|
||||
options={[
|
||||
{ label: _t('connection.fillDetails', { defaultMessage: 'Fill database connection details' }), value: '', default: true },
|
||||
{
|
||||
label: _t('connection.fillDetails', { defaultMessage: 'Fill database connection details' }),
|
||||
value: '',
|
||||
default: true,
|
||||
},
|
||||
{ label: _t('connection.useUrl', { defaultMessage: 'Use database URL' }), value: '1' },
|
||||
]}
|
||||
/>
|
||||
@@ -177,7 +184,7 @@
|
||||
name="databaseUrl"
|
||||
data-testid="ConnectionDriverFields_databaseUrl"
|
||||
placeholder={driver?.databaseUrlPlaceholder}
|
||||
disabled={isConnected || disabledFields.includes('databaseUrl')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('databaseUrl')}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -187,7 +194,7 @@
|
||||
name="localDataCenter"
|
||||
data-testid="ConnectionDriverFields_localDataCenter"
|
||||
placeholder={driver?.defaultLocalDataCenter}
|
||||
disabled={isConnected || disabledFields.includes('localDataCenter')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('localDataCenter')}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -196,7 +203,7 @@
|
||||
label={_t('connection.authToken', { defaultMessage: 'Auth token' })}
|
||||
name="authToken"
|
||||
data-testid="ConnectionDriverFields_authToken"
|
||||
disabled={isConnected || disabledFields.includes('authToken')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('authToken')}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -207,7 +214,7 @@
|
||||
data-testid="ConnectionDriverFields_authType"
|
||||
name="authType"
|
||||
isNative
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
defaultValue={driver?.defaultAuthTypeName}
|
||||
options={$authTypes.map(auth => ({
|
||||
value: auth.name,
|
||||
@@ -219,9 +226,9 @@
|
||||
|
||||
{#if driver?.showConnectionField('endpoint', $values, showConnectionFieldArgs)}
|
||||
<FormTextField
|
||||
label='Endpoint'
|
||||
label="Endpoint"
|
||||
name="endpoint"
|
||||
disabled={isConnected || disabledFields.includes('endpoint')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('endpoint')}
|
||||
data-testid="ConnectionDriverFields_endpoint"
|
||||
/>
|
||||
{/if}
|
||||
@@ -230,7 +237,7 @@
|
||||
<FormTextField
|
||||
label={_t('connection.endpointKey', { defaultMessage: 'Key' })}
|
||||
name="endpointKey"
|
||||
disabled={isConnected || disabledFields.includes('endpointKey')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('endpointKey')}
|
||||
data-testid="ConnectionDriverFields_endpointKey"
|
||||
/>
|
||||
{/if}
|
||||
@@ -239,7 +246,7 @@
|
||||
<FormTextField
|
||||
label={_t('connection.clientLibraryPath', { defaultMessage: 'Client library path' })}
|
||||
name="clientLibraryPath"
|
||||
disabled={isConnected || disabledFields.includes('clientLibraryPath')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('clientLibraryPath')}
|
||||
data-testid="ConnectionDriverFields_clientLibraryPath"
|
||||
/>
|
||||
{/if}
|
||||
@@ -250,7 +257,7 @@
|
||||
<FormTextField
|
||||
label={_t('connection.server', { defaultMessage: 'Server' })}
|
||||
name="server"
|
||||
disabled={isConnected || disabledFields.includes('server')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('server')}
|
||||
templateProps={{ noMargin: true }}
|
||||
data-testid="ConnectionDriverFields_server"
|
||||
/>
|
||||
@@ -260,7 +267,7 @@
|
||||
<FormTextField
|
||||
label="Port"
|
||||
name="port"
|
||||
disabled={isConnected || disabledFields.includes('port')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('port')}
|
||||
templateProps={{ noMargin: true }}
|
||||
placeholder={driver?.defaultPort}
|
||||
data-testid="ConnectionDriverFields_port"
|
||||
@@ -271,7 +278,9 @@
|
||||
{#if getCurrentConfig().isDocker}
|
||||
<div class="row">
|
||||
<FontIcon icon="img warn" padRight />
|
||||
{ _t('connection.dockerWarning', { defaultMessage: 'Under docker, localhost and 127.0.0.1 will not work, use dockerhost instead' }) }
|
||||
{_t('connection.dockerWarning', {
|
||||
defaultMessage: 'Under docker, localhost and 127.0.0.1 will not work, use dockerhost instead',
|
||||
})}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -280,9 +289,11 @@
|
||||
<div class="row">
|
||||
<div class="col-9 mr-1">
|
||||
<FormTextField
|
||||
label={$values.serviceNameType == 'sid' ? 'SID' : _t('connection.serviceName', { defaultMessage: 'Service name' })}
|
||||
label={$values.serviceNameType == 'sid'
|
||||
? 'SID'
|
||||
: _t('connection.serviceName', { defaultMessage: 'Service name' })}
|
||||
name="serviceName"
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
templateProps={{ noMargin: true }}
|
||||
data-testid="ConnectionDriverFields_serviceName"
|
||||
/>
|
||||
@@ -293,7 +304,7 @@
|
||||
isNative
|
||||
name="serviceNameType"
|
||||
defaultValue="serviceName"
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
templateProps={{ noMargin: true }}
|
||||
options={[
|
||||
{ value: 'serviceName', label: _t('connection.serviceName', { defaultMessage: 'Service name' }) },
|
||||
@@ -309,7 +320,7 @@
|
||||
<FormTextField
|
||||
label={_t('connection.socketPath', { defaultMessage: 'Socket path' })}
|
||||
name="socketPath"
|
||||
disabled={isConnected || disabledFields.includes('socketPath')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('socketPath')}
|
||||
placeholder={driver?.defaultSocketPath}
|
||||
data-testid="ConnectionDriverFields_scoketPath"
|
||||
/>
|
||||
@@ -322,7 +333,7 @@
|
||||
<FormTextField
|
||||
label={_t('connection.user', { defaultMessage: 'User' })}
|
||||
name="user"
|
||||
disabled={isConnected || disabledFields.includes('user')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('user')}
|
||||
templateProps={{ noMargin: true }}
|
||||
data-testid="ConnectionDriverFields_user"
|
||||
/>
|
||||
@@ -333,7 +344,7 @@
|
||||
<FormPasswordField
|
||||
label={_t('connection.password', { defaultMessage: 'Password' })}
|
||||
name="password"
|
||||
disabled={isConnected || disabledFields.includes('password')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('password')}
|
||||
templateProps={{ noMargin: true }}
|
||||
data-testid="ConnectionDriverFields_password"
|
||||
/>
|
||||
@@ -345,7 +356,7 @@
|
||||
<FormTextField
|
||||
label={_t('connection.user', { defaultMessage: 'User' })}
|
||||
name="user"
|
||||
disabled={isConnected || disabledFields.includes('user')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('user')}
|
||||
data-testid="ConnectionDriverFields_user"
|
||||
/>
|
||||
{/if}
|
||||
@@ -353,7 +364,7 @@
|
||||
<FormPasswordField
|
||||
label={_t('connection.password', { defaultMessage: 'Password' })}
|
||||
name="password"
|
||||
disabled={isConnected || disabledFields.includes('password')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('password')}
|
||||
data-testid="ConnectionDriverFields_password"
|
||||
/>
|
||||
{/if}
|
||||
@@ -380,7 +391,7 @@
|
||||
<FormTextField
|
||||
label={_t('connection.accessKeyId', { defaultMessage: 'Access Key ID' })}
|
||||
name="accessKeyId"
|
||||
disabled={isConnected || disabledFields.includes('accessKeyId')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('accessKeyId')}
|
||||
templateProps={{ noMargin: true }}
|
||||
data-testid="ConnectionDriverFields_accesKeyId"
|
||||
/>
|
||||
@@ -391,7 +402,7 @@
|
||||
<FormPasswordField
|
||||
label={_t('connection.secretAccessKey', { defaultMessage: 'Secret access key' })}
|
||||
name="secretAccessKey"
|
||||
disabled={isConnected || disabledFields.includes('secretAccessKey')}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('secretAccessKey')}
|
||||
templateProps={{ noMargin: true }}
|
||||
data-testid="ConnectionDriverFields_secretAccessKey"
|
||||
/>
|
||||
@@ -405,12 +416,15 @@
|
||||
isNative
|
||||
name="passwordMode"
|
||||
defaultValue="saveEncrypted"
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
options={[
|
||||
{ value: 'saveEncrypted', label: _t('connection.saveEncrypted', { defaultMessage: 'Save and encrypt' }) },
|
||||
{ value: 'saveRaw', label: _t('connection.saveRaw', { defaultMessage: 'Save raw (UNSAFE!!)' }) },
|
||||
{ value: 'askPassword', label: _t('connection.askPassword', { defaultMessage: "Don't save, ask for password" }) },
|
||||
{ value: 'askUser', label: _t('connection.askUser', { defaultMessage: "Don't save, ask for login and password" }) },
|
||||
{
|
||||
value: 'askUser',
|
||||
label: _t('connection.askUser', { defaultMessage: "Don't save, ask for login and password" }),
|
||||
},
|
||||
]}
|
||||
data-testid="ConnectionDriverFields_passwordMode"
|
||||
/>
|
||||
@@ -420,7 +434,7 @@
|
||||
<FormTextField
|
||||
label={_t('connection.keySeparator', { defaultMessage: 'Key separator' })}
|
||||
name="treeKeySeparator"
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
placeholder=":"
|
||||
data-testid="ConnectionDriverFields_treeKeySeparator"
|
||||
/>
|
||||
@@ -430,7 +444,7 @@
|
||||
<FormTextField
|
||||
label={_t('connection.windowsDomain', { defaultMessage: 'Domain (specify to use NTLM authentication)' })}
|
||||
name="windowsDomain"
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
data-testid="ConnectionDriverFields_windowsDomain"
|
||||
/>
|
||||
{/if}
|
||||
@@ -439,7 +453,7 @@
|
||||
<FormCheckboxField
|
||||
label={_t('connection.isReadOnly', { defaultMessage: 'Is read only' })}
|
||||
name="isReadOnly"
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
data-testid="ConnectionDriverFields_isReadOnly"
|
||||
/>
|
||||
{/if}
|
||||
@@ -448,7 +462,7 @@
|
||||
<FormCheckboxField
|
||||
label={_t('connection.trustServerCertificate', { defaultMessage: 'Trust server certificate' })}
|
||||
name="trustServerCertificate"
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
data-testid="ConnectionDriverFields_trustServerCertificate"
|
||||
/>
|
||||
{/if}
|
||||
@@ -457,33 +471,42 @@
|
||||
<FormDropDownTextField
|
||||
label={_t('connection.defaultDatabase', { defaultMessage: 'Default database' })}
|
||||
name="defaultDatabase"
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly || disabledFields.includes('defaultDatabase')}
|
||||
data-testid="ConnectionDriverFields_defaultDatabase"
|
||||
asyncMenu={createDatabasesMenu}
|
||||
placeholder={_t('common.notSelectedOptional', { defaultMessage : "(not selected - optional)"})}
|
||||
placeholder={_t('common.notSelectedOptional', { defaultMessage: '(not selected - optional)' })}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if defaultDatabase && driver?.showConnectionField('singleDatabase', $values, showConnectionFieldArgs)}
|
||||
<FormCheckboxField
|
||||
label={_t('connection.singleDatabase', { defaultMessage: 'Use only database {defaultDatabase}', values: { defaultDatabase } })}
|
||||
label={_t('connection.singleDatabase', {
|
||||
defaultMessage: 'Use only database {defaultDatabase}',
|
||||
values: { defaultDatabase },
|
||||
})}
|
||||
name="singleDatabase"
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
data-testid="ConnectionDriverFields_singleDatabase"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if driver?.showConnectionField('useSeparateSchemas', $values, showConnectionFieldArgs)}
|
||||
<FormCheckboxField
|
||||
label={_t('connection.useSeparateSchemas', { defaultMessage: 'Use schemas separately (use this if you have many large schemas)' })}
|
||||
label={_t('connection.useSeparateSchemas', {
|
||||
defaultMessage: 'Use schemas separately (use this if you have many large schemas)',
|
||||
})}
|
||||
name="useSeparateSchemas"
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
data-testid="ConnectionDriverFields_useSeparateSchemas"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if driver?.showConnectionField('connectionDefinition', $values, showConnectionFieldArgs)}
|
||||
<FormFileInputField disabled={isConnected} label={_t('connection.connectionDefinition', { defaultMessage: 'Service account key JSON' })} name="connectionDefinition" />
|
||||
<FormFileInputField
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
label={_t('connection.connectionDefinition', { defaultMessage: 'Service account key JSON' })}
|
||||
name="connectionDefinition"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if driver}
|
||||
@@ -493,7 +516,7 @@
|
||||
label={_t('connection.displayName', { defaultMessage: 'Display name' })}
|
||||
name="displayName"
|
||||
templateProps={{ noMargin: true }}
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
data-testid="ConnectionDriverFields_displayName"
|
||||
placeholder={getConnectionLabel(currentConnection)}
|
||||
/>
|
||||
@@ -505,7 +528,7 @@
|
||||
name="connectionColor"
|
||||
emptyLabel="(not selected)"
|
||||
templateProps={{ noMargin: true }}
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
data-testid="ConnectionDriverFields_connectionColor"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
import { extensions, openedConnections, openedSingleDatabaseConnections } from '../stores';
|
||||
import { _t } from '../translations';
|
||||
|
||||
export let isFormReadOnly;
|
||||
|
||||
const { values, setFieldValue } = getFormContext();
|
||||
const electron = getElectron();
|
||||
|
||||
@@ -30,9 +32,9 @@
|
||||
</script>
|
||||
|
||||
<FormCheckboxField
|
||||
label={_t('connection.sshTunnel.use', {defaultMessage: "Use SSH tunnel"})}
|
||||
label={_t('connection.sshTunnel.use', { defaultMessage: 'Use SSH tunnel' })}
|
||||
name="useSshTunnel"
|
||||
disabled={isConnected}
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
data-testid="ConnectionSshTunnelFields_useSshTunnel"
|
||||
/>
|
||||
|
||||
@@ -41,7 +43,7 @@
|
||||
<FormTextField
|
||||
label="Host"
|
||||
name="sshHost"
|
||||
disabled={isConnected || !useSshTunnel}
|
||||
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||
templateProps={{ noMargin: true }}
|
||||
data-testid="ConnectionSshTunnelFields_sshHost"
|
||||
/>
|
||||
@@ -50,23 +52,30 @@
|
||||
<FormTextField
|
||||
label="Port"
|
||||
name="sshPort"
|
||||
disabled={isConnected || !useSshTunnel}
|
||||
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||
templateProps={{ noMargin: true }}
|
||||
placeholder="22"
|
||||
data-testid="ConnectionSshTunnelFields_sshPort"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<FormTextField label="Bastion host (Jump host)" name="sshBastionHost" disabled={isConnected || !useSshTunnel} />
|
||||
<FormTextField
|
||||
label="Bastion host (Jump host)"
|
||||
name="sshBastionHost"
|
||||
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||
/>
|
||||
|
||||
<FormSelectField
|
||||
label={_t('connection.sshTunnel.authentication', {defaultMessage: "SSH Authentication"})}
|
||||
label={_t('connection.sshTunnel.authentication', { defaultMessage: 'SSH Authentication' })}
|
||||
name="sshMode"
|
||||
isNative
|
||||
defaultSelectValue="userPassword"
|
||||
disabled={isConnected || !useSshTunnel}
|
||||
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||
options={[
|
||||
{ value: 'userPassword', label: _t('connection.sshTunnel.authMethod.userPassword', {defaultMessage: "Username & password"}) },
|
||||
{
|
||||
value: 'userPassword',
|
||||
label: _t('connection.sshTunnel.authMethod.userPassword', { defaultMessage: 'Username & password' }),
|
||||
},
|
||||
{ value: 'agent', label: 'SSH agent' },
|
||||
{ value: 'keyFile', label: 'Key file' },
|
||||
]}
|
||||
@@ -77,7 +86,7 @@
|
||||
<FormTextField
|
||||
label="Login"
|
||||
name="sshLogin"
|
||||
disabled={isConnected || !useSshTunnel}
|
||||
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||
data-testid="ConnectionSshTunnelFields_sshLogin"
|
||||
/>
|
||||
{/if}
|
||||
@@ -88,16 +97,16 @@
|
||||
<FormTextField
|
||||
label="Login"
|
||||
name="sshLogin"
|
||||
disabled={isConnected || !useSshTunnel}
|
||||
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||
templateProps={{ noMargin: true }}
|
||||
data-testid="ConnectionSshTunnelFields_sshLogin"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<FormPasswordField
|
||||
label={_t('connection.password', {defaultMessage: 'Password'})}
|
||||
label={_t('connection.password', { defaultMessage: 'Password' })}
|
||||
name="sshPassword"
|
||||
disabled={isConnected || !useSshTunnel}
|
||||
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||
templateProps={{ noMargin: true }}
|
||||
data-testid="ConnectionSshTunnelFields_sshPassword"
|
||||
/>
|
||||
@@ -110,18 +119,18 @@
|
||||
<div class="col-6 mr-1">
|
||||
{#if electron}
|
||||
<FormElectronFileSelector
|
||||
label={_t('connection.sshTunnel.privateKeyFile', {defaultMessage: "Private key file"})}
|
||||
label={_t('connection.sshTunnel.privateKeyFile', { defaultMessage: 'Private key file' })}
|
||||
name="sshKeyfile"
|
||||
disabled={isConnected || !useSshTunnel}
|
||||
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||
templateProps={{ noMargin: true }}
|
||||
defaultFileName={$platformInfo?.defaultKeyfile}
|
||||
data-testid="ConnectionSshTunnelFields_sshKeyfile"
|
||||
/>
|
||||
{:else}
|
||||
<FormTextField
|
||||
label={_t('connection.sshTunnel.privateKeyFilePath', {defaultMessage: "Private key file (path on server)"})}
|
||||
label={_t('connection.sshTunnel.privateKeyFilePath', { defaultMessage: 'Private key file (path on server)' })}
|
||||
name="sshKeyfile"
|
||||
disabled={isConnected || !useSshTunnel}
|
||||
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||
templateProps={{ noMargin: true }}
|
||||
placeholder={$platformInfo?.defaultKeyfile}
|
||||
data-testid="ConnectionSshTunnelFields_sshKeyfile"
|
||||
@@ -130,9 +139,9 @@
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<FormPasswordField
|
||||
label={_t('connection.sshTunnel.keyFilePassphrase', {defaultMessage: "Key file passphrase"})}
|
||||
label={_t('connection.sshTunnel.keyFilePassphrase', { defaultMessage: 'Key file passphrase' })}
|
||||
name="sshKeyfilePassword"
|
||||
disabled={isConnected || !useSshTunnel}
|
||||
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||
templateProps={{ noMargin: true }}
|
||||
data-testid="ConnectionSshTunnelFields_sshKeyfilePassword"
|
||||
/>
|
||||
@@ -143,9 +152,10 @@
|
||||
{#if useSshTunnel && $values.sshMode == 'agent'}
|
||||
<div class="ml-3 mb-3">
|
||||
{#if $platformInfo && $platformInfo.sshAuthSock}
|
||||
<FontIcon icon="img ok" /> {_t('connection.sshTunnel.agentFound', {defaultMessage: "SSH Agent found"})}
|
||||
<FontIcon icon="img ok" /> {_t('connection.sshTunnel.agentFound', { defaultMessage: 'SSH Agent found' })}
|
||||
{:else}
|
||||
<FontIcon icon="img error" /> {_t('connection.sshTunnel.agentNotFound', {defaultMessage: "SSH Agent not found"})}
|
||||
<FontIcon icon="img error" />
|
||||
{_t('connection.sshTunnel.agentNotFound', { defaultMessage: 'SSH Agent not found' })}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
import { openedConnections, openedSingleDatabaseConnections } from '../stores';
|
||||
import { _t } from '../translations';
|
||||
|
||||
export let isFormReadOnly;
|
||||
|
||||
const { values, setFieldValue } = getFormContext();
|
||||
const electron = getElectron();
|
||||
|
||||
@@ -16,21 +18,35 @@
|
||||
$: isConnected = $openedConnections.includes($values._id) || $openedSingleDatabaseConnections.includes($values._id);
|
||||
</script>
|
||||
|
||||
<FormCheckboxField label={_t('connection.ssl.use', {defaultMessage: "Use SSL"})} name="useSsl" disabled={isConnected} />
|
||||
<FormElectronFileSelector label={_t('connection.ssl.caCert', {defaultMessage: "CA Cert (optional)"})} name="sslCaFile" disabled={isConnected || !useSsl || !electron} />
|
||||
<FormCheckboxField
|
||||
label={_t('connection.ssl.use', { defaultMessage: 'Use SSL' })}
|
||||
name="useSsl"
|
||||
disabled={isConnected || isFormReadOnly}
|
||||
/>
|
||||
<FormElectronFileSelector
|
||||
label={_t('connection.ssl.certificate', {defaultMessage: "Certificate (optional)"})}
|
||||
label={_t('connection.ssl.caCert', { defaultMessage: 'CA Cert (optional)' })}
|
||||
name="sslCaFile"
|
||||
disabled={isConnected || !useSsl || !electron || isFormReadOnly}
|
||||
/>
|
||||
<FormElectronFileSelector
|
||||
label={_t('connection.ssl.certificate', { defaultMessage: 'Certificate (optional)' })}
|
||||
name="sslCertFile"
|
||||
disabled={isConnected || !useSsl || !electron}
|
||||
disabled={isConnected || !useSsl || !electron || isFormReadOnly}
|
||||
/>
|
||||
<FormPasswordField
|
||||
label={_t('connection.ssl.certificateKeyFilePassword', {defaultMessage: "Certificate key file password (optional)"})}
|
||||
label={_t('connection.ssl.certificateKeyFilePassword', {
|
||||
defaultMessage: 'Certificate key file password (optional)',
|
||||
})}
|
||||
name="sslCertFilePassword"
|
||||
disabled={isConnected || !useSsl || !electron}
|
||||
disabled={isConnected || !useSsl || !electron || isFormReadOnly}
|
||||
/>
|
||||
<FormElectronFileSelector
|
||||
label={_t('connection.ssl.keyFile', {defaultMessage: "Key file (optional)"})}
|
||||
label={_t('connection.ssl.keyFile', { defaultMessage: 'Key file (optional)' })}
|
||||
name="sslKeyFile"
|
||||
disabled={isConnected || !useSsl || !electron}
|
||||
disabled={isConnected || !useSsl || !electron || isFormReadOnly}
|
||||
/>
|
||||
<FormCheckboxField
|
||||
label={_t('connection.ssl.rejectUnauthorized', { defaultMessage: 'Reject unauthorized' })}
|
||||
name="sslRejectUnauthorized"
|
||||
disabled={isConnected || !useSsl || isFormReadOnly}
|
||||
/>
|
||||
<FormCheckboxField label={_t('connection.ssl.rejectUnauthorized', {defaultMessage: "Reject unauthorized"})} name="sslRejectUnauthorized" disabled={isConnected || !useSsl} />
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
<div class="wrapper">
|
||||
<div class="heading">{_t('settings.sqlEditor', { defaultMessage: 'SQL editor' })}</div>
|
||||
|
||||
<div class="flex">
|
||||
<div class="col-3">
|
||||
<FormSelectField
|
||||
label={_t('settings.sqlEditor.sqlCommandsCase', { defaultMessage: 'SQL commands case' })}
|
||||
name="sqlEditor.sqlCommandsCase"
|
||||
@@ -28,8 +26,6 @@
|
||||
]}
|
||||
data-testid="SQLEditorSettings_sqlCommandsCase"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<FormFieldTemplateLarge
|
||||
label={_t('settings.editor.keybinds', { defaultMessage: 'Editor keybinds' })}
|
||||
type="combo"
|
||||
@@ -42,53 +38,49 @@
|
||||
on:change={e => ($currentEditorKeybindigMode = e.detail)}
|
||||
/>
|
||||
</FormFieldTemplateLarge>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<FormFieldTemplateLarge
|
||||
label={_t('settings.editor.wordWrap', { defaultMessage: 'Enable word wrap' })}
|
||||
type="combo"
|
||||
type="checkbox"
|
||||
>
|
||||
<CheckboxField
|
||||
checked={$currentEditorWrapEnabled}
|
||||
on:change={e => ($currentEditorWrapEnabled = e.target.checked)}
|
||||
/>
|
||||
</FormFieldTemplateLarge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<FormTextField
|
||||
name="sqlEditor.limitRows"
|
||||
label={_t('settings.sqlEditor.limitRows', { defaultMessage: 'Return only N rows from query' })}
|
||||
placeholder={_t('settings.sqlEditor.limitRowsPlaceholder', { defaultMessage: '(No rows limit)' })}
|
||||
/>
|
||||
<FormTextField
|
||||
name="sqlEditor.limitRows"
|
||||
label={_t('settings.sqlEditor.limitRows', { defaultMessage: 'Return only N rows from query' })}
|
||||
placeholder={_t('settings.sqlEditor.limitRowsPlaceholder', { defaultMessage: '(No rows limit)' })}
|
||||
/>
|
||||
|
||||
<FormCheckboxField
|
||||
name="sqlEditor.showTableAliasesInCodeCompletion"
|
||||
label={_t('settings.sqlEditor.showTableAliasesInCodeCompletion', {
|
||||
defaultMessage: 'Show table aliases in code completion',
|
||||
})}
|
||||
defaultValue={false}
|
||||
/>
|
||||
<FormCheckboxField
|
||||
name="sqlEditor.showTableAliasesInCodeCompletion"
|
||||
label={_t('settings.sqlEditor.showTableAliasesInCodeCompletion', {
|
||||
defaultMessage: 'Show table aliases in code completion',
|
||||
})}
|
||||
defaultValue={false}
|
||||
/>
|
||||
|
||||
<FormCheckboxField
|
||||
name="sqlEditor.disableSplitByEmptyLine"
|
||||
label={_t('settings.sqlEditor.disableSplitByEmptyLine', { defaultMessage: 'Disable split by empty line' })}
|
||||
defaultValue={false}
|
||||
/>
|
||||
<FormCheckboxField
|
||||
name="sqlEditor.disableSplitByEmptyLine"
|
||||
label={_t('settings.sqlEditor.disableSplitByEmptyLine', { defaultMessage: 'Disable split by empty line' })}
|
||||
defaultValue={false}
|
||||
/>
|
||||
|
||||
<FormCheckboxField
|
||||
name="sqlEditor.disableExecuteCurrentLine"
|
||||
label={_t('settings.sqlEditor.disableExecuteCurrentLine', {
|
||||
defaultMessage: 'Disable current line execution (Execute current)',
|
||||
})}
|
||||
defaultValue={false}
|
||||
/>
|
||||
<FormCheckboxField
|
||||
name="sqlEditor.disableExecuteCurrentLine"
|
||||
label={_t('settings.sqlEditor.disableExecuteCurrentLine', {
|
||||
defaultMessage: 'Disable current line execution (Execute current)',
|
||||
})}
|
||||
defaultValue={false}
|
||||
/>
|
||||
|
||||
<FormCheckboxField
|
||||
name="sqlEditor.hideColumnsPanel"
|
||||
label={_t('settings.sqlEditor.hideColumnsPanel', { defaultMessage: 'Hide Columns/Filters panel by default' })}
|
||||
defaultValue={false}
|
||||
/>
|
||||
<FormCheckboxField
|
||||
name="sqlEditor.hideColumnsPanel"
|
||||
label={_t('settings.sqlEditor.hideColumnsPanel', { defaultMessage: 'Hide Columns/Filters panel by default' })}
|
||||
defaultValue={false}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@@ -102,4 +94,8 @@ defaultValue={false}
|
||||
.wrapper :global(input){
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.wrapper :global(select) {
|
||||
max-width: 400px;
|
||||
}
|
||||
</style>
|
||||
@@ -168,7 +168,6 @@ export const nullStore = readable(null, () => {});
|
||||
export const currentArchive = writableWithStorage('default', 'currentArchive');
|
||||
export const currentApplication = writableWithStorage(null, 'currentApplication');
|
||||
export const isFileDragActive = writable(false);
|
||||
export const selectedCellsCallback = writable(null);
|
||||
export const loadingPluginStore = writable({
|
||||
loaded: false,
|
||||
loadingPackageName: null,
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<script lang="ts" context="module">
|
||||
let tabContentCounter = 0;
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { setContext } from 'svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
@@ -19,7 +23,7 @@
|
||||
$: tabFocusedStore.set(tabFocused);
|
||||
</script>
|
||||
|
||||
<div class:tabVisible>
|
||||
<div class:tabVisible data-testid={`TabContent_${tabContentCounter++}`}>
|
||||
<svelte:component this={tabComponent} {...$$restProps} {tabid} {tabVisible} {tabFocused} {tabPreviewMode} />
|
||||
</div>
|
||||
|
||||
|
||||
@@ -221,5 +221,6 @@
|
||||
<ToolStripExportButton {quickExportHandlerRef} command="collectionDataGrid.export" />
|
||||
<ToolStripCommandButton command="collectionJsonView.expandAll" hideDisabled />
|
||||
<ToolStripCommandButton command="collectionJsonView.collapseAll" hideDisabled />
|
||||
<ToolStripCommandButton command="dataGrid.toggleCellDataView" hideDisabled data-testid="CollectionDataTab_toggleCellDataView" />
|
||||
</svelte:fragment>
|
||||
</ToolStripContainer>
|
||||
|
||||
@@ -59,6 +59,8 @@
|
||||
}
|
||||
);
|
||||
|
||||
$: isFormReadOnly = !!$values.import_source_id;
|
||||
|
||||
// $: console.log('ConnectionTab.$values', $values);
|
||||
// $: console.log('ConnectionTab.driver', driver);
|
||||
|
||||
@@ -302,22 +304,25 @@
|
||||
{
|
||||
label: _t('common.general', { defaultMessage: 'General' }),
|
||||
component: ConnectionDriverFields,
|
||||
props: { getDatabaseList, currentConnection },
|
||||
props: { getDatabaseList, currentConnection, isFormReadOnly },
|
||||
testid: 'ConnectionTab_tabGeneral',
|
||||
},
|
||||
driver?.showConnectionTab('sshTunnel', $values) && {
|
||||
label: 'SSH Tunnel',
|
||||
component: ConnectionSshTunnelFields,
|
||||
props: { isFormReadOnly },
|
||||
testid: 'ConnectionTab_tabSshTunnel',
|
||||
},
|
||||
driver?.showConnectionTab('ssl', $values) && {
|
||||
label: 'SSL',
|
||||
component: ConnectionSslFields,
|
||||
props: { isFormReadOnly },
|
||||
testid: 'ConnectionTab_tabSsl',
|
||||
},
|
||||
{
|
||||
label: _t('common.advanced', { defaultMessage: 'Advanced' }),
|
||||
component: ConnectionAdvancedDriverFields,
|
||||
props: { isFormReadOnly },
|
||||
testid: 'ConnectionTab_tabAdvanced',
|
||||
},
|
||||
]}
|
||||
@@ -383,7 +388,8 @@
|
||||
{/if}
|
||||
{#if isTesting}
|
||||
<div>
|
||||
<FontIcon icon="icon loading" /> {_t('common.testingConnection', { defaultMessage: 'Testing connection' })}
|
||||
<FontIcon icon="icon loading" />
|
||||
{_t('common.testingConnection', { defaultMessage: 'Testing connection' })}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -141,11 +141,10 @@
|
||||
/>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="2">
|
||||
<WidgetColumnBar>
|
||||
<WidgetColumnBar storageName="diagramSettingsWidget">
|
||||
<WidgetColumnBarItem
|
||||
title="Settings"
|
||||
name="diagramSettings"
|
||||
storageName="diagramSettingsWidget"
|
||||
onClose={() => {
|
||||
styleStore.update(x => ({ ...x, settingsVisible: false }));
|
||||
}}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
<script lang="ts" context="module">
|
||||
const getCurrentEditor = () => getActiveComponent('ImportExportTab');
|
||||
|
||||
registerFileCommands({
|
||||
idPrefix: 'impexp',
|
||||
category: 'Import & Export',
|
||||
getCurrentEditor,
|
||||
folder: 'impexp',
|
||||
format: 'json',
|
||||
fileExtension: 'impexp',
|
||||
if (isProApp()) {
|
||||
registerFileCommands({
|
||||
idPrefix: 'impexp',
|
||||
category: 'Import & Export',
|
||||
getCurrentEditor,
|
||||
folder: 'impexp',
|
||||
format: 'json',
|
||||
fileExtension: 'impexp',
|
||||
|
||||
// undoRedo: true,
|
||||
defaultTeamFolder: true,
|
||||
});
|
||||
// undoRedo: true,
|
||||
defaultTeamFolder: true,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -55,6 +57,7 @@
|
||||
import { tick } from 'svelte';
|
||||
import { showSnackbarError } from '../utility/snackbar';
|
||||
import { _t } from '../translations';
|
||||
import { isProApp } from '../utility/proTools';
|
||||
|
||||
let busy = false;
|
||||
let executeNumber = 0;
|
||||
@@ -290,21 +293,24 @@
|
||||
/>
|
||||
|
||||
{#if busy}
|
||||
<LoadingInfo wrapper message={_t('importExport.processingImportExport', { defaultMessage: "Processing import/export ..." })} />
|
||||
<LoadingInfo
|
||||
wrapper
|
||||
message={_t('importExport.processingImportExport', { defaultMessage: 'Processing import/export ...' })}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<svelte:fragment slot="2">
|
||||
<WidgetColumnBar>
|
||||
<WidgetColumnBarItem
|
||||
title={_t('importExport.outputFiles', { defaultMessage: "Output files" })}
|
||||
title={_t('importExport.outputFiles', { defaultMessage: 'Output files' })}
|
||||
name="output"
|
||||
height="20%"
|
||||
data-testid="ImportExportTab_outputFiles"
|
||||
>
|
||||
<RunnerOutputFiles {runnerId} {executeNumber} />
|
||||
</WidgetColumnBarItem>
|
||||
<WidgetColumnBarItem title={_t('importExport.messages', { defaultMessage: "Messages" })} name="messages">
|
||||
<WidgetColumnBarItem title={_t('importExport.messages', { defaultMessage: 'Messages' })} name="messages">
|
||||
<SocketMessageView
|
||||
eventName={runnerId ? `runner-info-${runnerId}` : null}
|
||||
{executeNumber}
|
||||
@@ -313,16 +319,23 @@
|
||||
/>
|
||||
</WidgetColumnBarItem>
|
||||
<WidgetColumnBarItem
|
||||
title={_t('importExport.preview', { defaultMessage: "Preview" })}
|
||||
title={_t('importExport.preview', { defaultMessage: 'Preview' })}
|
||||
name="preview"
|
||||
skip={!$previewReaderStore}
|
||||
data-testid="ImportExportTab_preview"
|
||||
>
|
||||
<PreviewDataGrid reader={$previewReaderStore} />
|
||||
</WidgetColumnBarItem>
|
||||
<WidgetColumnBarItem title={_t('importExport.advancedConfiguration', { defaultMessage: "Advanced configuration" })} name="config" collapsed>
|
||||
<FormTextField label={_t('importExport.schedule', { defaultMessage: "Schedule" })} name="schedule" />
|
||||
<FormTextField label={_t('importExport.startVariableIndex', { defaultMessage: "Start variable index" })} name="startVariableIndex" />
|
||||
<WidgetColumnBarItem
|
||||
title={_t('importExport.advancedConfiguration', { defaultMessage: 'Advanced configuration' })}
|
||||
name="config"
|
||||
collapsed
|
||||
>
|
||||
<FormTextField label={_t('importExport.schedule', { defaultMessage: 'Schedule' })} name="schedule" />
|
||||
<FormTextField
|
||||
label={_t('importExport.startVariableIndex', { defaultMessage: 'Start variable index' })}
|
||||
name="startVariableIndex"
|
||||
/>
|
||||
</WidgetColumnBarItem>
|
||||
</WidgetColumnBar>
|
||||
</svelte:fragment>
|
||||
@@ -331,17 +344,19 @@
|
||||
<svelte:fragment slot="toolstrip">
|
||||
{#if busy}
|
||||
<ToolStripButton icon="icon stop" on:click={handleCancel} data-testid="ImportExportTab_stopButton"
|
||||
>{_t('importExport.stop', { defaultMessage: "Stop" })}</ToolStripButton
|
||||
>{_t('importExport.stop', { defaultMessage: 'Stop' })}</ToolStripButton
|
||||
>
|
||||
{:else}
|
||||
<ToolStripButton on:click={handleExecute} icon="icon run" data-testid="ImportExportTab_executeButton"
|
||||
>{_t('importExport.run', { defaultMessage: "Run" })}</ToolStripButton
|
||||
>{_t('importExport.run', { defaultMessage: 'Run' })}</ToolStripButton
|
||||
>
|
||||
{/if}
|
||||
<ToolStripButton icon="img shell" on:click={handleGenerateScript} data-testid="ImportExportTab_generateScriptButton"
|
||||
>{_t('importExport.generateScript', { defaultMessage: "Generate script" })}</ToolStripButton
|
||||
>{_t('importExport.generateScript', { defaultMessage: 'Generate script' })}</ToolStripButton
|
||||
>
|
||||
<ToolStripSaveButton idPrefix="impexp" />
|
||||
{#if isProApp()}
|
||||
<ToolStripSaveButton idPrefix="impexp" />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</ToolStripContainer>
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
registerCommand({
|
||||
id: 'jsonl.save',
|
||||
group: 'save',
|
||||
category: 'JSON Lines editor',
|
||||
category: __t('command.jsonl', { defaultMessage: 'JSON Lines editor' }),
|
||||
name: __t('command.jsonl.save', { defaultMessage: 'Save' }),
|
||||
toolbar: true,
|
||||
isRelatedToTab: true,
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
registerCommand({
|
||||
id: 'jsonl.preview',
|
||||
category: 'JSON Lines editor',
|
||||
category: __t('command.jsonl', { defaultMessage: 'JSON Lines editor' }),
|
||||
name: __t('command.jsonl.preview', { defaultMessage: 'Preview' }),
|
||||
icon: 'icon preview',
|
||||
keyText: 'F5',
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
registerCommand({
|
||||
id: 'jsonl.previewNewTab',
|
||||
category: 'JSON Lines editor',
|
||||
category: __t('command.jsonl', { defaultMessage: 'JSON Lines editor' }),
|
||||
name: __t('command.jsonl.previewNewTab', { defaultMessage: 'Preview in new tab' }),
|
||||
icon: 'icon preview',
|
||||
testEnabled: () => getCurrentEditor() != null,
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
registerCommand({
|
||||
id: 'jsonl.closePreview',
|
||||
category: 'JSON Lines editor',
|
||||
category: __t('command.jsonl', { defaultMessage: 'JSON Lines editor' }),
|
||||
name: __t('command.jsonl.closePreview', { defaultMessage: 'Close preview' }),
|
||||
icon: 'icon close',
|
||||
testEnabled: () => getCurrentEditor()?.isPreview(),
|
||||
|
||||
@@ -170,6 +170,9 @@
|
||||
import QueryAiAssistant from '../ai/QueryAiAssistant.svelte';
|
||||
import { getCurrentSettings } from '../stores';
|
||||
import { Messages } from 'openai/resources/chat/completions';
|
||||
import WidgetColumnBar from '../widgets/WidgetColumnBar.svelte';
|
||||
import WidgetsInnerContainer from '../widgets/WidgetsInnerContainer.svelte';
|
||||
import WidgetColumnBarItem from '../widgets/WidgetColumnBarItem.svelte';
|
||||
|
||||
export let tabid;
|
||||
export let conid;
|
||||
@@ -717,9 +720,6 @@
|
||||
...driver?.getQuerySplitterOptions('editor'),
|
||||
splitByEmptyLine: !$settingsValue?.['sqlEditor.disableSplitByEmptyLine'],
|
||||
}}
|
||||
options={{
|
||||
wrap: enableWrap,
|
||||
}}
|
||||
value={$editorState.value || ''}
|
||||
menu={createMenu()}
|
||||
on:input={e => {
|
||||
@@ -791,33 +791,45 @@
|
||||
</VerticalSplitter>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="2">
|
||||
<QueryAiAssistant
|
||||
bind:this={domAiAssistant}
|
||||
{conid}
|
||||
{database}
|
||||
{driver}
|
||||
onClose={() => {
|
||||
isAiAssistantVisible = false;
|
||||
}}
|
||||
text={$editorValue}
|
||||
getLine={() => domEditor.getEditor().getSelectionRange().start.row}
|
||||
onInsertAtCursor={text => {
|
||||
const editor = domEditor.getEditor();
|
||||
editor.session.insert(editor.getCursorPosition(), text);
|
||||
domEditor?.getEditor()?.focus();
|
||||
}}
|
||||
getTextOrSelectedText={() => domEditor.getEditor().getSelectedText() || $editorValue}
|
||||
onSetSelectedText={text => {
|
||||
const editor = domEditor.getEditor();
|
||||
if (editor.getSelectedText()) {
|
||||
const range = editor.selection.getRange();
|
||||
editor.session.replace(range, text);
|
||||
} else {
|
||||
editor.setValue(text);
|
||||
}
|
||||
}}
|
||||
{tabid}
|
||||
/>
|
||||
<WidgetColumnBar>
|
||||
<WidgetColumnBarItem
|
||||
title={_t('query.AiAssistant', { defaultMessage: 'AI Assistant' })}
|
||||
onClose={() => {
|
||||
isAiAssistantVisible = false;
|
||||
}}
|
||||
name='aiAssistant'
|
||||
>
|
||||
<WidgetsInnerContainer skipDefineWidth flexContainer>
|
||||
<QueryAiAssistant
|
||||
bind:this={domAiAssistant}
|
||||
{conid}
|
||||
{database}
|
||||
{driver}
|
||||
onClose={() => {
|
||||
isAiAssistantVisible = false;
|
||||
}}
|
||||
text={$editorValue}
|
||||
getLine={() => domEditor.getEditor().getSelectionRange().start.row}
|
||||
onInsertAtCursor={text => {
|
||||
const editor = domEditor.getEditor();
|
||||
editor.session.insert(editor.getCursorPosition(), text);
|
||||
domEditor?.getEditor()?.focus();
|
||||
}}
|
||||
getTextOrSelectedText={() => domEditor.getEditor().getSelectedText() || $editorValue}
|
||||
onSetSelectedText={text => {
|
||||
const editor = domEditor.getEditor();
|
||||
if (editor.getSelectedText()) {
|
||||
const range = editor.selection.getRange();
|
||||
editor.session.replace(range, text);
|
||||
} else {
|
||||
editor.setValue(text);
|
||||
}
|
||||
}}
|
||||
{tabid}
|
||||
/>
|
||||
</WidgetsInnerContainer>
|
||||
</WidgetColumnBarItem>
|
||||
</WidgetColumnBar>
|
||||
</svelte:fragment>
|
||||
</HorizontalSplitter>
|
||||
<svelte:fragment slot="toolstrip">
|
||||
@@ -839,11 +851,17 @@
|
||||
},
|
||||
})}
|
||||
>
|
||||
{queryRowsLimit ? _t('query.limitRows', { defaultMessage: 'Limit {queryRowsLimit} rows', values: { queryRowsLimit } }) : _t('query.unlimitedRows', { defaultMessage: 'Unlimited rows' })}</ToolStripButton
|
||||
{queryRowsLimit
|
||||
? _t('query.limitRows', { defaultMessage: 'Limit {queryRowsLimit} rows', values: { queryRowsLimit } })
|
||||
: _t('query.unlimitedRows', { defaultMessage: 'Unlimited rows' })}</ToolStripButton
|
||||
>
|
||||
{/if}
|
||||
{#if resultCount == 1}
|
||||
<ToolStripExportButton command="jslTableGrid.export" {quickExportHandlerRef} label={_t('export.result', { defaultMessage: 'Export result' })} />
|
||||
<ToolStripExportButton
|
||||
command="jslTableGrid.export"
|
||||
{quickExportHandlerRef}
|
||||
label={_t('export.result', { defaultMessage: 'Export result' })}
|
||||
/>
|
||||
{/if}
|
||||
<ToolStripDropDownButton
|
||||
menu={() =>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
time: 60,
|
||||
name: __t('command.datagrid.setAutoRefresh.60', { defaultMessage: 'Refresh every 60 seconds' }),
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
registerCommand({
|
||||
id: 'tableData.save',
|
||||
@@ -172,7 +172,10 @@
|
||||
const resp = await apiCall('database-connections/run-script', { conid, database, sql, useTransaction: true });
|
||||
const { errorMessage } = resp || {};
|
||||
if (errorMessage) {
|
||||
showModal(ErrorMessageModal, { title: _t('tableData.errorWhenSaving', { defaultMessage: 'Error when saving' }), message: errorMessage });
|
||||
showModal(ErrorMessageModal, {
|
||||
title: _t('tableData.errorWhenSaving', { defaultMessage: 'Error when saving' }),
|
||||
message: errorMessage,
|
||||
});
|
||||
} else {
|
||||
dispatchChangeSet({ type: 'reset', value: createChangeSet() });
|
||||
cache.update(reloadDataCacheFunc);
|
||||
@@ -192,7 +195,10 @@
|
||||
});
|
||||
const { errorMessage } = resp || {};
|
||||
if (errorMessage) {
|
||||
showModal(ErrorMessageModal, { title: _t('tableData.errorWhenSaving', { defaultMessage: 'Error when saving' }), message: errorMessage });
|
||||
showModal(ErrorMessageModal, {
|
||||
title: _t('tableData.errorWhenSaving', { defaultMessage: 'Error when saving' }),
|
||||
message: errorMessage,
|
||||
});
|
||||
} else {
|
||||
dispatchChangeSet({ type: 'reset', value: createChangeSet() });
|
||||
cache.update(reloadDataCacheFunc);
|
||||
@@ -284,7 +290,10 @@
|
||||
{ command: 'tableData.stopAutoRefresh', hideDisabled: true },
|
||||
{ command: 'tableData.startAutoRefresh', hideDisabled: true },
|
||||
'tableData.setAutoRefresh.1',
|
||||
...INTERVALS.map(seconds => ({ command: `tableData.setAutoRefresh.${seconds}`, text: `...${seconds}` + ' ' + _t('command.datagrid.autoRefresh.seconds', { defaultMessage: 'seconds' }) })),
|
||||
...INTERVALS.map(seconds => ({
|
||||
command: `tableData.setAutoRefresh.${seconds}`,
|
||||
text: `...${seconds}` + ' ' + _t('command.datagrid.autoRefresh.seconds', { defaultMessage: 'seconds' }),
|
||||
})),
|
||||
];
|
||||
}
|
||||
</script>
|
||||
@@ -360,13 +369,23 @@
|
||||
>
|
||||
|
||||
<ToolStripCommandSplitButton
|
||||
buttonLabel={autoRefreshStarted ? _t('tableData.refreshEvery', { defaultMessage: 'Refresh (every {autoRefreshInterval}s)', values: { autoRefreshInterval } }) : null}
|
||||
buttonLabel={autoRefreshStarted
|
||||
? _t('tableData.refreshEvery', {
|
||||
defaultMessage: 'Refresh (every {autoRefreshInterval}s)',
|
||||
values: { autoRefreshInterval },
|
||||
})
|
||||
: null}
|
||||
commands={['dataGrid.refresh', ...createAutoRefreshMenu()]}
|
||||
hideDisabled
|
||||
data-testid="TableDataTab_refreshGrid"
|
||||
/>
|
||||
<ToolStripCommandSplitButton
|
||||
buttonLabel={autoRefreshStarted ? _t('tableData.refreshEvery', { defaultMessage: 'Refresh (every {autoRefreshInterval}s)', values: { autoRefreshInterval } }) : null}
|
||||
buttonLabel={autoRefreshStarted
|
||||
? _t('tableData.refreshEvery', {
|
||||
defaultMessage: 'Refresh (every {autoRefreshInterval}s)',
|
||||
values: { autoRefreshInterval },
|
||||
})
|
||||
: null}
|
||||
commands={['dataForm.refresh', ...createAutoRefreshMenu()]}
|
||||
hideDisabled
|
||||
data-testid="TableDataTab_refreshForm"
|
||||
@@ -402,7 +421,14 @@
|
||||
|
||||
<ToolStripButton
|
||||
icon={$collapsedLeftColumnStore ? 'icon columns-outline' : 'icon columns'}
|
||||
on:click={() => collapsedLeftColumnStore.update(x => !x)}>{_t('tableData.viewColumns', { defaultMessage: 'View columns' })}</ToolStripButton
|
||||
on:click={() => collapsedLeftColumnStore.update(x => !x)}
|
||||
>{_t('tableData.viewColumns', { defaultMessage: 'View columns' })}</ToolStripButton
|
||||
>
|
||||
|
||||
<ToolStripCommandButton
|
||||
command="dataGrid.toggleCellDataView"
|
||||
hideDisabled
|
||||
data-testid="TableDataTab_toggleCellDataView"
|
||||
/>
|
||||
</svelte:fragment>
|
||||
</ToolStripContainer>
|
||||
|
||||
@@ -129,6 +129,7 @@
|
||||
|
||||
<ToolStripCommandButton command="dataGrid.refresh" />
|
||||
<ToolStripExportButton {quickExportHandlerRef} />
|
||||
<ToolStripCommandButton command="dataGrid.toggleCellDataView" hideDisabled />
|
||||
</svelte:fragment>
|
||||
</ToolStripContainer>
|
||||
{/if}
|
||||
|
||||
@@ -124,7 +124,7 @@ export function __t(key: string, options: TranslateOptions): DefferedTranslation
|
||||
};
|
||||
}
|
||||
|
||||
export function _tval(x: string | DefferedTranslationResult): string {
|
||||
export function _tval(x: any | DefferedTranslationResult): string {
|
||||
if (typeof x === 'string') return x;
|
||||
if (typeof x?._transKey === 'string') {
|
||||
return _t(x._transKey, x._transOptions);
|
||||
@@ -132,7 +132,7 @@ export function _tval(x: string | DefferedTranslationResult): string {
|
||||
if (typeof x?._transCallback === 'function') {
|
||||
return x._transCallback();
|
||||
}
|
||||
return '';
|
||||
return x?.toString() || '';
|
||||
}
|
||||
|
||||
export function isDefferedTranslationResult(x: string | DefferedTranslationResult): x is DefferedTranslationResult {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { isProApp } from './proTools';
|
||||
export function createQuickExportMenuItems(handler: (fmt: QuickExportDefinition) => Function, advancedExportMenuItem) {
|
||||
const extensions = getExtensions();
|
||||
return [
|
||||
isProApp() && {
|
||||
{
|
||||
text: _t('export.exportAdvanced', { defaultMessage : 'Export advanced...'}),
|
||||
...advancedExportMenuItem,
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const cache = {};
|
||||
|
||||
export function getLocalStorage(key, defaultValue = undefined) {
|
||||
if (!key) return defaultValue;
|
||||
if (key in cache) return cache[key];
|
||||
const item = localStorage.getItem(key);
|
||||
if (item) {
|
||||
@@ -16,11 +17,13 @@ export function getLocalStorage(key, defaultValue = undefined) {
|
||||
}
|
||||
|
||||
export function setLocalStorage(key, value) {
|
||||
if (!key) return;
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
delete cache[key];
|
||||
}
|
||||
|
||||
export function removeLocalStorage(key) {
|
||||
if (!key) return;
|
||||
localStorage.removeItem(key);
|
||||
delete cache[key];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
import { newMatcherFn } from 'diff2html/lib/rematch';
|
||||
import _ from 'lodash';
|
||||
|
||||
export interface WidgetBarStoredProps {
|
||||
contentHeight: number;
|
||||
collapsed: boolean;
|
||||
}
|
||||
|
||||
export interface WidgetBarStoredPropsResult {
|
||||
[name: string]: WidgetBarStoredProps;
|
||||
}
|
||||
|
||||
export interface WidgetBarComputedProps {
|
||||
contentHeight: number;
|
||||
storedHeight?: number;
|
||||
visibleItemsCount: number;
|
||||
splitterVisible: boolean;
|
||||
collapsed: boolean;
|
||||
clickableTitle: boolean;
|
||||
}
|
||||
|
||||
export interface WidgetBarComputedResult {
|
||||
[name: string]: WidgetBarComputedProps;
|
||||
}
|
||||
|
||||
export interface WidgetBarItemDefinition {
|
||||
name: string;
|
||||
height?: string; // e.g. '200px' or '30%'
|
||||
collapsed: boolean; // initial value of collapsing status
|
||||
skip: boolean;
|
||||
minimalContentHeight: number;
|
||||
storeHeight: boolean;
|
||||
}
|
||||
|
||||
export type PushWidgetBarItemDefinitionFunction = (def: WidgetBarItemDefinition) => void;
|
||||
export type UpdateWidgetBarItemDefinitionFunction = (name: string, def: Partial<WidgetBarItemDefinition>) => void;
|
||||
export type ResizeWidgetItemFunction = (name: string, deltaY: number) => void;
|
||||
export type ToggleCollapseWidgetItemFunction = (name: string) => void;
|
||||
|
||||
export interface WidgetBarContainerProps {
|
||||
clientHeight: number;
|
||||
titleHeight: number;
|
||||
splitterHeight: number;
|
||||
}
|
||||
|
||||
// accordeon mode - only one item can be expanded at a time
|
||||
export function widgetShouldBeInAccordeonMode(
|
||||
container: WidgetBarContainerProps,
|
||||
definitions: WidgetBarItemDefinition[]
|
||||
): boolean {
|
||||
const visibleItems = definitions.filter(def => !def.skip);
|
||||
|
||||
const availableContentHeight =
|
||||
container.clientHeight -
|
||||
visibleItems.length * container.titleHeight -
|
||||
Math.max(0, visibleItems.length - 1) * container.splitterHeight;
|
||||
|
||||
const minimalRequiredContentHeight = _.sum(visibleItems.map(def => def.minimalContentHeight));
|
||||
return availableContentHeight < minimalRequiredContentHeight;
|
||||
}
|
||||
|
||||
export function computeInitialWidgetBarProps(
|
||||
container: WidgetBarContainerProps,
|
||||
definitions: WidgetBarItemDefinition[],
|
||||
currentProps: WidgetBarComputedResult
|
||||
): WidgetBarComputedResult {
|
||||
if (!container.clientHeight) {
|
||||
return currentProps;
|
||||
}
|
||||
const visibleItems = definitions.filter(def => !def.skip);
|
||||
const expandedItems = visibleItems.filter(def => !(currentProps[def.name]?.collapsed ?? def.collapsed));
|
||||
const res: WidgetBarComputedResult = {};
|
||||
|
||||
const availableContentHeight =
|
||||
container.clientHeight -
|
||||
visibleItems.length * container.titleHeight -
|
||||
Math.max(0, expandedItems.length - 1) * container.splitterHeight;
|
||||
|
||||
if (widgetShouldBeInAccordeonMode(container, definitions)) {
|
||||
// In accordeon mode, only the first expanded item is shown, others are collapsed
|
||||
const expandedItem = visibleItems.find(def => !def.collapsed);
|
||||
for (const def of visibleItems) {
|
||||
const isExpanded = def.name === expandedItem?.name;
|
||||
res[def.name] = {
|
||||
contentHeight: isExpanded ? availableContentHeight : 0,
|
||||
storedHeight: currentProps[def.name]?.contentHeight,
|
||||
visibleItemsCount: visibleItems.length,
|
||||
splitterVisible: false,
|
||||
collapsed: !isExpanded,
|
||||
clickableTitle: !isExpanded,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// First pass: calculate base heights
|
||||
let totalContentHeight = 0;
|
||||
const itemHeights = {};
|
||||
|
||||
const flexibleItems = [];
|
||||
for (const def of expandedItems) {
|
||||
if (def.storeHeight && currentProps[def.name]?.storedHeight > 0) {
|
||||
const storedHeight = currentProps[def.name].storedHeight;
|
||||
itemHeights[def.name] = storedHeight;
|
||||
totalContentHeight += storedHeight;
|
||||
} else if (def.height) {
|
||||
let height = 0;
|
||||
if (_.isString(def.height) && def.height.endsWith('px')) {
|
||||
height = parseInt(def.height.slice(0, -2));
|
||||
} else if (_.isString(def.height) && def.height.endsWith('%'))
|
||||
height = (availableContentHeight * parseFloat(def.height.slice(0, -1))) / 100;
|
||||
else {
|
||||
height = parseInt(def.height);
|
||||
}
|
||||
if (height < def.minimalContentHeight) {
|
||||
height = def.minimalContentHeight;
|
||||
}
|
||||
totalContentHeight += height;
|
||||
itemHeights[def.name] = height;
|
||||
} else {
|
||||
flexibleItems.push(def);
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass - distribute remaining height
|
||||
if (flexibleItems.length > 0) {
|
||||
let remainingHeight = availableContentHeight - totalContentHeight;
|
||||
for (const def of flexibleItems) {
|
||||
let height = remainingHeight / flexibleItems.length;
|
||||
if (height < def.minimalContentHeight) height = def.minimalContentHeight;
|
||||
itemHeights[def.name] = height;
|
||||
}
|
||||
}
|
||||
|
||||
// Third pass - update heights to match available height
|
||||
totalContentHeight = _.sum(Object.values(itemHeights));
|
||||
if (totalContentHeight != availableContentHeight) {
|
||||
const scale = availableContentHeight / totalContentHeight;
|
||||
for (const def of expandedItems) {
|
||||
itemHeights[def.name] = itemHeights[def.name] * scale;
|
||||
}
|
||||
}
|
||||
|
||||
// Final assembly of results
|
||||
let visibleIndex = 0;
|
||||
for (const def of visibleItems) {
|
||||
res[def.name] = {
|
||||
contentHeight: Math.round(itemHeights[def.name] || 0),
|
||||
visibleItemsCount: visibleItems.length,
|
||||
splitterVisible: visibleItems.length > 1 && visibleIndex < visibleItems.length - 1,
|
||||
collapsed: !expandedItems.includes(def),
|
||||
storedHeight: currentProps[def.name]?.storedHeight,
|
||||
clickableTitle: true,
|
||||
};
|
||||
visibleIndex += 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
export function handleResizeWidgetBar(
|
||||
container: WidgetBarContainerProps,
|
||||
definitions: WidgetBarItemDefinition[],
|
||||
currentProps: WidgetBarComputedResult,
|
||||
resizedItemName: string,
|
||||
deltaY: number
|
||||
): WidgetBarComputedResult {
|
||||
const res = _.cloneDeep(currentProps);
|
||||
const visibleItems = definitions.filter(def => !def.skip);
|
||||
const currentItemDef = definitions.find(def => def.name === resizedItemName);
|
||||
if (!currentItemDef || currentItemDef.collapsed) return res;
|
||||
const currentItemProps = res[resizedItemName];
|
||||
let itemIndex = visibleItems.findIndex(def => def.name === resizedItemName);
|
||||
const itemProps = res[currentItemDef.name];
|
||||
const nextItemDef = visibleItems[itemIndex + 1];
|
||||
const currentHeight = itemProps.contentHeight;
|
||||
const nextItemProps = res[nextItemDef.name];
|
||||
if (!nextItemDef) return res;
|
||||
|
||||
if (deltaY < 0) {
|
||||
let newHeight = currentHeight + deltaY;
|
||||
if (newHeight < currentItemDef.minimalContentHeight) {
|
||||
newHeight = currentItemDef.minimalContentHeight;
|
||||
}
|
||||
const actualDeltaY = newHeight - currentHeight;
|
||||
nextItemProps.contentHeight -= actualDeltaY;
|
||||
currentItemProps.contentHeight += actualDeltaY;
|
||||
|
||||
// // moving up - reduce height of resized item, if too small, reduce height of previous items
|
||||
// let remainingDeltaY = -deltaY;
|
||||
// let itemIndex = visibleItems.findIndex(def => def.name === resizedItemName);
|
||||
// while (remainingDeltaY > 0 && itemIndex >= 0) {
|
||||
// const itemDef = visibleItems[itemIndex];
|
||||
// const itemProps = res[itemDef.name];
|
||||
// const currentHeight = itemProps.contentHeight;
|
||||
// const minimalHeight = itemDef.minimalContentHeight;
|
||||
// const reducibleHeight = currentHeight - minimalHeight;
|
||||
// if (reducibleHeight > 0) {
|
||||
// const reduction = Math.min(reducibleHeight, remainingDeltaY);
|
||||
// itemProps.contentHeight -= reduction;
|
||||
// remainingDeltaY -= reduction;
|
||||
// }
|
||||
// itemIndex -= 1;
|
||||
// }
|
||||
} else {
|
||||
let newHeight = nextItemProps.contentHeight - deltaY;
|
||||
if (newHeight < nextItemDef.minimalContentHeight) {
|
||||
newHeight = nextItemDef.minimalContentHeight;
|
||||
}
|
||||
const actualDeltaY = nextItemProps.contentHeight - newHeight;
|
||||
nextItemProps.contentHeight -= actualDeltaY;
|
||||
currentItemProps.contentHeight += actualDeltaY;
|
||||
|
||||
// moving down - increase height of resized item, reduce size of next item, if too small, reduce size of further items
|
||||
// if all items below are at minimal height, stop
|
||||
// let remainingDeltaY = deltaY;
|
||||
// let itemIndex = visibleItems.findIndex(def => def.name === resizedItemName);
|
||||
// while (remainingDeltaY > 0 && itemIndex < visibleItems.length) {
|
||||
// const itemDef = visibleItems[itemIndex];
|
||||
// const itemProps = res[itemDef.name];
|
||||
// const currentHeight = itemProps.contentHeight;
|
||||
// const minimalHeight = itemDef.minimalContentHeight;
|
||||
// const reducibleHeight = currentHeight - minimalHeight;
|
||||
// if (reducibleHeight > 0) {
|
||||
// const reduction = Math.min(reducibleHeight, remainingDeltaY);
|
||||
// itemProps.contentHeight -= reduction;
|
||||
// resizedItemProps.contentHeight += reduction;
|
||||
// remainingDeltaY -= reduction;
|
||||
// }
|
||||
// itemIndex += 1;
|
||||
// }
|
||||
}
|
||||
|
||||
if (currentItemDef.storeHeight) {
|
||||
currentItemProps.storedHeight = currentItemProps.contentHeight;
|
||||
}
|
||||
|
||||
if (nextItemDef.storeHeight) {
|
||||
nextItemProps.storedHeight = nextItemProps.contentHeight;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
export function toggleCollapseWidgetBar(
|
||||
container: WidgetBarContainerProps,
|
||||
definitions: WidgetBarItemDefinition[],
|
||||
currentProps: WidgetBarComputedResult,
|
||||
toggledItemName: string
|
||||
): WidgetBarComputedResult {
|
||||
const visibleItems = definitions.filter(def => !def.skip);
|
||||
|
||||
if (widgetShouldBeInAccordeonMode(container, definitions)) {
|
||||
// In accordeon mode, only the first expanded item is shown, others are collapsed
|
||||
const res: WidgetBarComputedResult = {};
|
||||
for (const def of visibleItems) {
|
||||
const isExpanded = def.name === toggledItemName;
|
||||
res[def.name] = {
|
||||
contentHeight: undefined,
|
||||
visibleItemsCount: visibleItems.length,
|
||||
splitterVisible: false,
|
||||
collapsed: !isExpanded,
|
||||
clickableTitle: !isExpanded,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
const res = _.cloneDeep(currentProps);
|
||||
res[toggledItemName].collapsed = !res[toggledItemName].collapsed;
|
||||
return computeInitialWidgetBarProps(container, definitions, res);
|
||||
}
|
||||
|
||||
export function extractStoredWidgetBarProps(
|
||||
definitions: WidgetBarItemDefinition[],
|
||||
currentProps: WidgetBarComputedResult
|
||||
): WidgetBarStoredPropsResult {
|
||||
const res: WidgetBarStoredPropsResult = {};
|
||||
for (const key in currentProps) {
|
||||
const def = definitions.find(d => d.name === key);
|
||||
if (!def) continue;
|
||||
res[key] = {
|
||||
contentHeight: def.storeHeight ? currentProps[key]?.storedHeight : undefined,
|
||||
collapsed: currentProps[key]?.collapsed,
|
||||
};
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
export function createWidgetBarComputedResultFromStored(stored: WidgetBarStoredPropsResult): WidgetBarComputedResult {
|
||||
const res: WidgetBarComputedResult = {};
|
||||
if (!stored) return res;
|
||||
let visibleIndex = 0;
|
||||
const visibleCount = Object.keys(stored).length;
|
||||
for (const key in stored) {
|
||||
res[key] = {
|
||||
storedHeight: stored[key]?.contentHeight,
|
||||
contentHeight: 0,
|
||||
collapsed: stored[key]?.collapsed,
|
||||
clickableTitle: false,
|
||||
splitterVisible: visibleCount > 1 && visibleIndex < visibleCount - 1,
|
||||
visibleItemsCount: 0,
|
||||
};
|
||||
visibleIndex += 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -7,11 +7,11 @@
|
||||
import WidgetColumnBarItem from './WidgetColumnBarItem.svelte';
|
||||
</script>
|
||||
|
||||
<WidgetColumnBar>
|
||||
<WidgetColumnBarItem title="Archive folders, DB models" name="folders" height="50%" storageName='archiveFoldersWidget'>
|
||||
<WidgetColumnBar storageName="archiveWidget">
|
||||
<WidgetColumnBarItem title="Archive folders, DB models" name="folders" height="50%">
|
||||
<ArchiveFolderList />
|
||||
</WidgetColumnBarItem>
|
||||
<WidgetColumnBarItem title="Files, Tables, Views, Functions" name="files" storageName='archiveFilesWidget'>
|
||||
<WidgetColumnBarItem title="Files, Tables, Views, Functions" name="files">
|
||||
<ArchiveFilesList />
|
||||
</WidgetColumnBarItem>
|
||||
</WidgetColumnBar>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<script lang="ts" context="module">
|
||||
import { isWktGeometry } from 'dbgate-tools';
|
||||
|
||||
const formats = [
|
||||
{
|
||||
type: 'textWrap',
|
||||
@@ -14,6 +12,12 @@
|
||||
component: TextCellViewNoWrap,
|
||||
single: false,
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
title: 'Form',
|
||||
component: FormCellView,
|
||||
single: false,
|
||||
},
|
||||
{
|
||||
type: 'json',
|
||||
title: 'Json',
|
||||
@@ -59,10 +63,13 @@
|
||||
];
|
||||
|
||||
function autodetect(selection) {
|
||||
if (selection[0]?.isSelectedFullRow) {
|
||||
return 'form';
|
||||
}
|
||||
|
||||
if (selectionCouldBeShownOnMap(selection)) {
|
||||
return 'map';
|
||||
}
|
||||
|
||||
if (selection[0]?.engine?.databaseEngineTypes?.includes('document')) {
|
||||
return 'jsonRow';
|
||||
}
|
||||
@@ -92,32 +99,31 @@
|
||||
import JsonRowView from '../celldata/JsonRowView.svelte';
|
||||
import MapCellView from '../celldata/MapCellView.svelte';
|
||||
import PictureCellView from '../celldata/PictureCellView.svelte';
|
||||
import FormCellView from '../celldata/FormCellView.svelte';
|
||||
import TextCellViewNoWrap from '../celldata/TextCellViewNoWrap.svelte';
|
||||
import TextCellViewWrap from '../celldata/TextCellViewWrap.svelte';
|
||||
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
||||
import { selectionCouldBeShownOnMap } from '../elements/SelectionMapView.svelte';
|
||||
import SelectField from '../forms/SelectField.svelte';
|
||||
import { selectedCellsCallback } from '../stores';
|
||||
import WidgetTitle from './WidgetTitle.svelte';
|
||||
import JsonExpandedCellView from '../celldata/JsonExpandedCellView.svelte';
|
||||
import XmlCellView from '../celldata/XmlCellView.svelte';
|
||||
import { _t } from '../translations';
|
||||
|
||||
let selectedFormatType = 'autodetect';
|
||||
export let onClose;
|
||||
export let selection;
|
||||
|
||||
export let selection = undefined;
|
||||
let selectedFormatType = 'autodetect';
|
||||
|
||||
$: autodetectFormatType = autodetect(selection);
|
||||
$: autodetectFormat = formats.find(x => x.type == autodetectFormatType);
|
||||
|
||||
$: usedFormatType = selectedFormatType == 'autodetect' ? autodetectFormatType : selectedFormatType;
|
||||
$: usedFormat = formats.find(x => x.type == usedFormatType);
|
||||
|
||||
$: selection = $selectedCellsCallback ? $selectedCellsCallback() : [];
|
||||
</script>
|
||||
|
||||
<div class="wrapper">
|
||||
<WidgetTitle>{_t('cellDataWidget.title', { defaultMessage: "Cell data view" })}</WidgetTitle>
|
||||
<WidgetTitle {onClose}>{_t('cellDataWidget.title', { defaultMessage: 'Cell data view' })}</WidgetTitle>
|
||||
<div class="main">
|
||||
<div class="toolbar">
|
||||
Format:<span> </span>
|
||||
@@ -127,18 +133,30 @@
|
||||
on:change={e => (selectedFormatType = e.detail)}
|
||||
data-testid="CellDataWidget_selectFormat"
|
||||
options={[
|
||||
{ value: 'autodetect', label: _t('cellDataWidget.autodetect', { defaultMessage: "Autodetect - {autoDetectTitle}", values : { autoDetectTitle: autodetectFormat.title } }) },
|
||||
{
|
||||
value: 'autodetect',
|
||||
label: _t('cellDataWidget.autodetect', {
|
||||
defaultMessage: 'Autodetect - {autoDetectTitle}',
|
||||
values: { autoDetectTitle: autodetectFormat.title },
|
||||
}),
|
||||
},
|
||||
...formats.map(fmt => ({ label: fmt.title, value: fmt.type })),
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div class="data">
|
||||
{#if usedFormat.single && selection?.length != 1}
|
||||
<ErrorInfo message={_t('cellDataWidget.mustSelectOneCell', { defaultMessage: "Must be selected one cell" })} alignTop />
|
||||
<ErrorInfo
|
||||
message={_t('cellDataWidget.mustSelectOneCell', { defaultMessage: 'Must be selected one cell' })}
|
||||
alignTop
|
||||
/>
|
||||
{:else if usedFormat == null}
|
||||
<ErrorInfo message={_t('cellDataWidget.formatNotSelected', { defaultMessage: "Format not selected" })} alignTop />
|
||||
<ErrorInfo
|
||||
message={_t('cellDataWidget.formatNotSelected', { defaultMessage: 'Format not selected' })}
|
||||
alignTop
|
||||
/>
|
||||
{:else if !selection || selection.length == 0}
|
||||
<ErrorInfo message={_t('cellDataWidget.noDataSelected', { defaultMessage: "No data selected" })} alignTop />
|
||||
<ErrorInfo message={_t('cellDataWidget.noDataSelected', { defaultMessage: 'No data selected' })} alignTop />
|
||||
{:else}
|
||||
<svelte:component this={usedFormat?.component} {selection} />
|
||||
{/if}
|
||||
|
||||
@@ -17,14 +17,9 @@
|
||||
$: cloudContentList = useCloudContentList();
|
||||
</script>
|
||||
|
||||
<WidgetColumnBar {hidden}>
|
||||
<WidgetColumnBar {hidden} storageName="databaseWidget">
|
||||
{#if $config?.singleConnection}
|
||||
<WidgetColumnBarItem
|
||||
title={_t('widget.databases', { defaultMessage: 'Databases' })}
|
||||
name="databases"
|
||||
height="35%"
|
||||
storageName="databasesWidget"
|
||||
>
|
||||
<WidgetColumnBarItem title={_t('widget.databases', { defaultMessage: 'Databases' })} name="databases" height="35%">
|
||||
<SingleConnectionDatabaseList connection={$config?.singleConnection} />
|
||||
</WidgetColumnBarItem>
|
||||
{:else if !$config?.singleDbConnection}
|
||||
@@ -32,7 +27,7 @@
|
||||
title={_t('common.connections', { defaultMessage: 'Connections' })}
|
||||
name="connections"
|
||||
height="35%"
|
||||
storageName="connectionsWidget"
|
||||
storeHeight
|
||||
>
|
||||
<ConnectionList
|
||||
passProps={{
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
title={_t('widget.pinned', { defaultMessage: 'Pinned' })}
|
||||
name="pinned"
|
||||
height="15%"
|
||||
storageName="pinnedItemsWidget"
|
||||
skip={!_.compact($pinnedDatabases).length &&
|
||||
!$pinnedTables.some(x => x && x.conid == conid && x.database == $currentDatabase?.name)}
|
||||
positiveCondition={correctCloudStatus}
|
||||
@@ -46,8 +45,7 @@
|
||||
title={driver?.databaseEngineTypes?.includes('document')
|
||||
? _t('widget.collectionsContainers', { defaultMessage: 'Collections/containers' })
|
||||
: _t('widget.tablesViewsFunctions', { defaultMessage: 'Tables, views, functions' })}
|
||||
name="dbObjects"
|
||||
storageName="dbObjectsWidget"
|
||||
name="dbObjectsSql"
|
||||
skip={!(
|
||||
conid &&
|
||||
(database || singleDatabase) &&
|
||||
@@ -60,8 +58,7 @@
|
||||
|
||||
<WidgetColumnBarItem
|
||||
title={_t('widget.keys', { defaultMessage: 'Keys' })}
|
||||
name="dbObjects"
|
||||
storageName="dbObjectsWidget"
|
||||
name="dbObjectsKeyValue"
|
||||
skip={!(conid && (database || singleDatabase) && driver?.databaseEngineTypes?.includes('keyvalue'))}
|
||||
positiveCondition={correctCloudStatus}
|
||||
>
|
||||
@@ -70,8 +67,7 @@
|
||||
|
||||
<WidgetColumnBarItem
|
||||
title={_t('widget.databaseContent', { defaultMessage: 'Database content' })}
|
||||
name="dbObjects"
|
||||
storageName="dbObjectsWidget"
|
||||
name="dbObjectsFocused"
|
||||
skip={conid && (database || singleDatabase)}
|
||||
positiveCondition={correctCloudStatus}
|
||||
>
|
||||
@@ -84,8 +80,7 @@
|
||||
|
||||
<WidgetColumnBarItem
|
||||
title={_t('widget.databaseContent', { defaultMessage: 'Database content' })}
|
||||
name="dbObjects"
|
||||
storageName="dbObjectsWidget"
|
||||
name="dbObjectsError"
|
||||
skip={!(conid && (database || singleDatabase) && !driver)}
|
||||
positiveCondition={correctCloudStatus}
|
||||
>
|
||||
@@ -102,7 +97,6 @@
|
||||
title={_t('widget.databaseContent', { defaultMessage: 'Database content' })}
|
||||
name="incorrectClaudStatus"
|
||||
height="15%"
|
||||
storageName="incorrectClaudStatusWidget"
|
||||
skip={correctCloudStatus}
|
||||
>
|
||||
<WidgetsInnerContainer>
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
$: favorites = useFavorites();
|
||||
</script>
|
||||
|
||||
<WidgetColumnBar>
|
||||
<WidgetColumnBarItem title={_t('files.savedFiles', { defaultMessage: "Saved files" })} name="files" height="70%" storageName="savedFilesWidget">
|
||||
<WidgetColumnBar storageName="filesWidget">
|
||||
<WidgetColumnBarItem title={_t('files.savedFiles', { defaultMessage: 'Saved files' })} name="files" height="70%">
|
||||
<SavedFilesList />
|
||||
</WidgetColumnBarItem>
|
||||
|
||||
{#if hasPermission('files/favorites/read')}
|
||||
<WidgetColumnBarItem title={_t('files.favorites', { defaultMessage: "Favorites" })} name="favorites" storageName="favoritesWidget">
|
||||
<WidgetColumnBarItem title={_t('files.favorites', { defaultMessage: 'Favorites' })} name="favorites">
|
||||
<WidgetsInnerContainer>
|
||||
<AppObjectList list={$favorites || []} module={favoriteFileAppObject} />
|
||||
</WidgetsInnerContainer>
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
import { _t } from '../translations';
|
||||
|
||||
$: favorites = useFavorites();
|
||||
|
||||
</script>
|
||||
|
||||
<WidgetColumnBar>
|
||||
<WidgetColumnBarItem title={_t('history.recentlyClosedTabs', { defaultMessage: "Recently closed tabs" })} name="closedTabs" storageName='closedTabsWidget'>
|
||||
<WidgetColumnBar storageName="historyWidget">
|
||||
<WidgetColumnBarItem
|
||||
title={_t('history.recentlyClosedTabs', { defaultMessage: 'Recently closed tabs' })}
|
||||
name="closedTabs"
|
||||
>
|
||||
<WidgetsInnerContainer>
|
||||
<AppObjectList
|
||||
list={_.sortBy(
|
||||
@@ -31,7 +33,7 @@
|
||||
/>
|
||||
</WidgetsInnerContainer>
|
||||
</WidgetColumnBarItem>
|
||||
<WidgetColumnBarItem title={_t('history.queryHistory', { defaultMessage: "Query history" })} name="queryHistory" storageName='queryHistoryWidget'>
|
||||
<WidgetColumnBarItem title={_t('history.queryHistory', { defaultMessage: 'Query history' })} name="queryHistory">
|
||||
<QueryHistoryList />
|
||||
</WidgetColumnBarItem>
|
||||
</WidgetColumnBar>
|
||||
|
||||
@@ -8,11 +8,15 @@
|
||||
import { _t } from '../translations';
|
||||
</script>
|
||||
|
||||
<WidgetColumnBar>
|
||||
<WidgetColumnBarItem title={_t('widgets.installedExtensions', { defaultMessage: 'Installed extensions' })} name="installed" height="50%" storageName='installedPluginsWidget'>
|
||||
<WidgetColumnBar storageName="pluginsWidget">
|
||||
<WidgetColumnBarItem
|
||||
title={_t('widgets.installedExtensions', { defaultMessage: 'Installed extensions' })}
|
||||
name="installed"
|
||||
height="50%"
|
||||
>
|
||||
<InstalledPluginsList />
|
||||
</WidgetColumnBarItem>
|
||||
<WidgetColumnBarItem title={_t('widgets.availableExtensions', { defaultMessage: 'Available extensions' })} name="all" storageName='allPluginsWidget'>
|
||||
<WidgetColumnBarItem title={_t('widgets.availableExtensions', { defaultMessage: 'Available extensions' })} name="all">
|
||||
<AvailablePluginsList />
|
||||
</WidgetColumnBarItem>
|
||||
</WidgetColumnBar>
|
||||
|
||||
@@ -162,7 +162,9 @@
|
||||
text: _t('privateCloudWidget.addExistingFolder', { defaultMessage: 'Add existing folder (from link)' }),
|
||||
onClick: () => {
|
||||
showModal(InputTextModal, {
|
||||
label: _t('privateCloudWidget.yourInviteLink', { defaultMessage: 'Your invite link (in form dbgate://folder/xxx)' }),
|
||||
label: _t('privateCloudWidget.yourInviteLink', {
|
||||
defaultMessage: 'Your invite link (in form dbgate://folder/xxx)',
|
||||
}),
|
||||
header: _t('privateCloudWidget.addExistingSharedFolder', { defaultMessage: 'Add existing shared folder' }),
|
||||
onConfirm: async newFolder => {
|
||||
apiCall('cloud/grant-folder', {
|
||||
@@ -192,7 +194,10 @@
|
||||
|
||||
const handleDelete = () => {
|
||||
showModal(ConfirmModal, {
|
||||
message: _t('privateCloudWidget.deleteFolderConfirm', { defaultMessage: 'Really delete folder {folder}? All folder content will be deleted!', values: { folder: contentGroupMap[folder]?.name } }),
|
||||
message: _t('privateCloudWidget.deleteFolderConfirm', {
|
||||
defaultMessage: 'Really delete folder {folder}? All folder content will be deleted!',
|
||||
values: { folder: contentGroupMap[folder]?.name },
|
||||
}),
|
||||
header: _t('privateCloudWidget.deleteFolder', { defaultMessage: 'Delete folder' }),
|
||||
onConfirm: () => {
|
||||
apiCall('cloud/delete-folder', {
|
||||
@@ -240,19 +245,26 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<WidgetColumnBar>
|
||||
<WidgetColumnBarItem
|
||||
title="DbGate Cloud"
|
||||
name="privateCloud"
|
||||
height="50%"
|
||||
storageName="privateCloudItems"
|
||||
skip={!$cloudSigninTokenHolder}
|
||||
>
|
||||
<WidgetColumnBar storageName="privateCloudItems">
|
||||
<WidgetColumnBarItem title="DbGate Cloud" name="privateCloud" height="50%" skip={!$cloudSigninTokenHolder}>
|
||||
<SearchBoxWrapper>
|
||||
<SearchInput placeholder={_t('privateCloudWidget.searchPlaceholder', { defaultMessage: 'Search cloud connections and files' })} bind:value={filter} />
|
||||
<SearchInput
|
||||
placeholder={_t('privateCloudWidget.searchPlaceholder', {
|
||||
defaultMessage: 'Search cloud connections and files',
|
||||
})}
|
||||
bind:value={filter}
|
||||
/>
|
||||
<CloseSearchButton bind:filter />
|
||||
<DropDownButton icon="icon plus-thick" menu={createAddItemMenu} title={_t('privateCloudWidget.addNewConnectionOrFile', { defaultMessage: 'Add new connection or file' })} />
|
||||
<DropDownButton icon="icon add-folder" menu={createAddFolderMenu} title={_t('privateCloudWidget.addNewFolder', { defaultMessage: 'Add new folder' })} />
|
||||
<DropDownButton
|
||||
icon="icon plus-thick"
|
||||
menu={createAddItemMenu}
|
||||
title={_t('privateCloudWidget.addNewConnectionOrFile', { defaultMessage: 'Add new connection or file' })}
|
||||
/>
|
||||
<DropDownButton
|
||||
icon="icon add-folder"
|
||||
menu={createAddFolderMenu}
|
||||
title={_t('privateCloudWidget.addNewFolder', { defaultMessage: 'Add new folder' })}
|
||||
/>
|
||||
<InlineButton
|
||||
on:click={handleRefreshContent}
|
||||
title={_t('privateCloudWidget.refreshFiles', { defaultMessage: 'Refresh files' })}
|
||||
@@ -289,7 +301,10 @@
|
||||
/>
|
||||
|
||||
{#if !cloudContentFlat?.length}
|
||||
<ErrorInfo message={_t('privateCloudWidget.noContent', { defaultMessage: 'You have no content on DbGate cloud' })} icon="img info" />
|
||||
<ErrorInfo
|
||||
message={_t('privateCloudWidget.noContent', { defaultMessage: 'You have no content on DbGate cloud' })}
|
||||
icon="img info"
|
||||
/>
|
||||
<div class="error-info">
|
||||
<div class="m-1"></div>
|
||||
<FormStyledButton
|
||||
|
||||
@@ -26,15 +26,21 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<WidgetColumnBar>
|
||||
<WidgetColumnBarItem title={_t('publicCloudWidget.publicKnowledgeBase', { defaultMessage: "Public Knowledge Base" })} name="publicCloud" storageName="publicCloudItems">
|
||||
<WidgetColumnBar storageName="publicCloudItems">
|
||||
<WidgetColumnBarItem
|
||||
title={_t('publicCloudWidget.publicKnowledgeBase', { defaultMessage: 'Public Knowledge Base' })}
|
||||
name="publicCloud"
|
||||
>
|
||||
<WidgetsInnerContainer>
|
||||
<SearchBoxWrapper>
|
||||
<SearchInput placeholder={_t('publicCloudWidget.searchPublicFiles', { defaultMessage: "Search public files" })} bind:value={filter} />
|
||||
<SearchInput
|
||||
placeholder={_t('publicCloudWidget.searchPublicFiles', { defaultMessage: 'Search public files' })}
|
||||
bind:value={filter}
|
||||
/>
|
||||
<CloseSearchButton bind:filter />
|
||||
<InlineButton
|
||||
on:click={handleRefreshPublic}
|
||||
title={_t('publicCloudWidget.refreshFiles', { defaultMessage: "Refresh files" })}
|
||||
title={_t('publicCloudWidget.refreshFiles', { defaultMessage: 'Refresh files' })}
|
||||
data-testid="CloudItemsWidget_buttonRefreshPublic"
|
||||
>
|
||||
<FontIcon icon="icon refresh" />
|
||||
@@ -49,12 +55,21 @@
|
||||
/>
|
||||
|
||||
{#if !$publicFiles?.length}
|
||||
<ErrorInfo message={_t('publicCloudWidget.noFilesFound', { defaultMessage: "No files found for your configuration" })} />
|
||||
<ErrorInfo
|
||||
message={_t('publicCloudWidget.noFilesFound', { defaultMessage: 'No files found for your configuration' })}
|
||||
/>
|
||||
<div class="error-info">
|
||||
<div class="m-1">
|
||||
{_t('publicCloudWidget.onlyRelevantFilesListed', { defaultMessage: "Only files relevant for your connections, platform and DbGate edition are listed. Please define connections at first." })}
|
||||
{_t('publicCloudWidget.onlyRelevantFilesListed', {
|
||||
defaultMessage:
|
||||
'Only files relevant for your connections, platform and DbGate edition are listed. Please define connections at first.',
|
||||
})}
|
||||
</div>
|
||||
<FormStyledButton value={_t('publicCloudWidget.refreshList', { defaultMessage: "Refresh list" })} skipWidth on:click={handleRefreshPublic} />
|
||||
<FormStyledButton
|
||||
value={_t('publicCloudWidget.refreshList', { defaultMessage: 'Refresh list' })}
|
||||
skipWidth
|
||||
on:click={handleRefreshPublic}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</WidgetsInnerContainer>
|
||||
|
||||
@@ -1,38 +1,77 @@
|
||||
<script lang="ts">
|
||||
import { setContext } from 'svelte';
|
||||
import { onMount, setContext } from 'svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
import createRef from '../utility/createRef';
|
||||
import _, { get } from 'lodash';
|
||||
import { getLocalStorage, setLocalStorage } from '../utility/storageCache';
|
||||
import {
|
||||
computeInitialWidgetBarProps,
|
||||
createWidgetBarComputedResultFromStored,
|
||||
extractStoredWidgetBarProps,
|
||||
handleResizeWidgetBar,
|
||||
toggleCollapseWidgetBar,
|
||||
WidgetBarItemDefinition,
|
||||
} from '../utility/widgetBarResizing';
|
||||
|
||||
export let hidden = false;
|
||||
export let storageName = null;
|
||||
|
||||
let definitions = [];
|
||||
const dynamicPropsCollection = [];
|
||||
let definitions: WidgetBarItemDefinition[] = [];
|
||||
let clientHeight;
|
||||
|
||||
const widgetColumnBarHeight = writable(0);
|
||||
// const widgetColumnBarHeight = writable(0);
|
||||
const widgetColumnBarComputed = writable(createWidgetBarComputedResultFromStored(getLocalStorage(storageName)));
|
||||
|
||||
setContext('widgetColumnBarHeight', widgetColumnBarHeight);
|
||||
setContext('pushWidgetItemDefinition', (item, dynamicProps) => {
|
||||
dynamicPropsCollection.push(dynamicProps);
|
||||
definitions = [...definitions, item];
|
||||
return definitions.length - 1;
|
||||
});
|
||||
setContext('updateWidgetItemDefinition', (index, item) => {
|
||||
definitions[index] = item;
|
||||
});
|
||||
$: containerProps = {
|
||||
clientHeight,
|
||||
titleHeight: 30,
|
||||
splitterHeight: 3,
|
||||
};
|
||||
|
||||
$: $widgetColumnBarHeight = clientHeight;
|
||||
|
||||
$: computeDynamicProps(definitions);
|
||||
|
||||
function computeDynamicProps(defs: any[]) {
|
||||
const visibleItemsCount = defs.filter(x => !x.collapsed && !x.skip).length;
|
||||
for (let index = 0; index < defs.length; index++) {
|
||||
const definition = defs[index];
|
||||
const splitterVisible = !!defs.slice(index + 1).find(x => x && !x.collapsed && !x.skip && x.positiveCondition);
|
||||
dynamicPropsCollection[index].set({ splitterVisible, visibleItemsCount });
|
||||
}
|
||||
function saveStorage() {
|
||||
if (!storageName) return;
|
||||
setLocalStorage(storageName, extractStoredWidgetBarProps(definitions, $widgetColumnBarComputed));
|
||||
}
|
||||
|
||||
// setContext('widgetColumnBarHeight', widgetColumnBarHeight);
|
||||
setContext('pushWidgetItemDefinition', item => {
|
||||
definitions = [...definitions, item];
|
||||
});
|
||||
setContext('updateWidgetItemDefinition', (name, item) => {
|
||||
// console.log('WidgetColumnBar updateWidgetItemDefinition', name, item);
|
||||
definitions = definitions.map(def => (def.name === name ? { ...def, ...item } : def));
|
||||
});
|
||||
setContext('widgetColumnBarComputed', widgetColumnBarComputed);
|
||||
setContext('widgetResizeItem', (name, deltaY) => {
|
||||
$widgetColumnBarComputed = handleResizeWidgetBar(
|
||||
containerProps,
|
||||
definitions,
|
||||
$widgetColumnBarComputed,
|
||||
name,
|
||||
deltaY
|
||||
);
|
||||
saveStorage();
|
||||
});
|
||||
setContext('toggleWidgetCollapse', name => {
|
||||
$widgetColumnBarComputed = toggleCollapseWidgetBar(containerProps, definitions, $widgetColumnBarComputed, name);
|
||||
saveStorage();
|
||||
});
|
||||
|
||||
// $: $widgetColumnBarHeight = clientHeight;
|
||||
|
||||
$: {
|
||||
definitions;
|
||||
containerProps;
|
||||
recompute();
|
||||
}
|
||||
|
||||
function recompute() {
|
||||
$widgetColumnBarComputed = computeInitialWidgetBarProps(containerProps, definitions, $widgetColumnBarComputed);
|
||||
saveStorage();
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
recompute();
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="main-container" bind:clientHeight class:hidden>
|
||||
|
||||
@@ -2,92 +2,89 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
import { getContext } from 'svelte';
|
||||
|
||||
import { writable } from 'svelte/store';
|
||||
import type { Readable } from 'svelte/store';
|
||||
|
||||
import WidgetTitle from './WidgetTitle.svelte';
|
||||
import splitterDrag from '../utility/splitterDrag';
|
||||
import { getLocalStorage, setLocalStorage } from '../utility/storageCache';
|
||||
import {
|
||||
PushWidgetBarItemDefinitionFunction,
|
||||
UpdateWidgetBarItemDefinitionFunction,
|
||||
WidgetBarComputedResult,
|
||||
WidgetBarComputedProps,
|
||||
ToggleCollapseWidgetItemFunction,
|
||||
ResizeWidgetItemFunction,
|
||||
} from '../utility/widgetBarResizing';
|
||||
// import { getLocalStorage, setLocalStorage } from '../utility/storageCache';
|
||||
|
||||
export let title;
|
||||
export let name;
|
||||
export let skip = false;
|
||||
export let positiveCondition = true;
|
||||
export let height = null;
|
||||
export let collapsed = null;
|
||||
export let storeHeight = false;
|
||||
|
||||
export let storageName = null;
|
||||
// export let storageName = null;
|
||||
export let onClose = null;
|
||||
export let minimalHeight = 50;
|
||||
export let name;
|
||||
|
||||
let size = 0;
|
||||
// let size = 0;
|
||||
|
||||
const dynamicProps = writable({
|
||||
splitterVisible: false,
|
||||
visibleItemsCount: 0,
|
||||
// const dynamicProps = writable({
|
||||
// splitterVisible: false,
|
||||
// visibleItemsCount: 0,
|
||||
// });
|
||||
|
||||
const pushWidgetItemDefinition = getContext('pushWidgetItemDefinition') as PushWidgetBarItemDefinitionFunction;
|
||||
const updateWidgetItemDefinition = getContext('updateWidgetItemDefinition') as UpdateWidgetBarItemDefinitionFunction;
|
||||
// const widgetColumnBarHeight = getContext('widgetColumnBarHeight') as any;
|
||||
const widgetResizeItem = getContext('widgetResizeItem') as ResizeWidgetItemFunction;
|
||||
const widgetColumnBarComputed = getContext('widgetColumnBarComputed') as Readable<WidgetBarComputedResult>;
|
||||
const toggleWidgetCollapse = getContext('toggleWidgetCollapse') as ToggleCollapseWidgetItemFunction;
|
||||
|
||||
pushWidgetItemDefinition({
|
||||
name,
|
||||
collapsed,
|
||||
height,
|
||||
skip: skip || !positiveCondition,
|
||||
minimalContentHeight: minimalHeight,
|
||||
storeHeight,
|
||||
});
|
||||
|
||||
const pushWidgetItemDefinition = getContext('pushWidgetItemDefinition') as any;
|
||||
const updateWidgetItemDefinition = getContext('updateWidgetItemDefinition') as any;
|
||||
const widgetColumnBarHeight = getContext('widgetColumnBarHeight') as any;
|
||||
const widgetItemIndex = pushWidgetItemDefinition(
|
||||
{
|
||||
collapsed,
|
||||
height,
|
||||
skip,
|
||||
positiveCondition,
|
||||
},
|
||||
dynamicProps
|
||||
);
|
||||
$: updateWidgetItemDefinition(name, { collapsed, height, skip: skip || !positiveCondition });
|
||||
|
||||
$: updateWidgetItemDefinition(widgetItemIndex, { collapsed: !visible, height, skip, positiveCondition });
|
||||
// $: setInitialSize(height, $widgetColumnBarHeight);
|
||||
|
||||
$: setInitialSize(height, $widgetColumnBarHeight);
|
||||
// $: if (storageName && $widgetColumnBarHeight > 0) {
|
||||
// setLocalStorage(storageName, { relativeHeight: size / $widgetColumnBarHeight, visible });
|
||||
// }
|
||||
|
||||
$: if (storageName && $widgetColumnBarHeight > 0) {
|
||||
setLocalStorage(storageName, { relativeHeight: size / $widgetColumnBarHeight, visible });
|
||||
}
|
||||
|
||||
function setInitialSize(initialSize, parentHeight) {
|
||||
if (storageName) {
|
||||
const storage = getLocalStorage(storageName);
|
||||
if (storage) {
|
||||
size = parentHeight * storage.relativeHeight;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (_.isString(initialSize) && initialSize.endsWith('px')) size = parseInt(initialSize.slice(0, -2));
|
||||
else if (_.isString(initialSize) && initialSize.endsWith('%'))
|
||||
size = (parentHeight * parseFloat(initialSize.slice(0, -1))) / 100;
|
||||
else size = parentHeight / 3;
|
||||
}
|
||||
|
||||
let visible =
|
||||
storageName && getLocalStorage(storageName) && getLocalStorage(storageName).visible != null
|
||||
? getLocalStorage(storageName).visible
|
||||
: !collapsed;
|
||||
|
||||
$: collapsible = $dynamicProps.visibleItemsCount != 1 || !visible;
|
||||
$: computed = $widgetColumnBarComputed[name] || ({} as WidgetBarComputedProps);
|
||||
</script>
|
||||
|
||||
{#if !skip && positiveCondition}
|
||||
<WidgetTitle
|
||||
clickable={collapsible}
|
||||
on:click={collapsible ? () => (visible = !visible) : null}
|
||||
clickable={computed.clickableTitle}
|
||||
on:click={computed.clickableTitle ? () => toggleWidgetCollapse(name) : null}
|
||||
data-testid={$$props['data-testid']}
|
||||
{onClose}>{title}</WidgetTitle
|
||||
>
|
||||
|
||||
{#if visible}
|
||||
{#if !computed.collapsed}
|
||||
<div
|
||||
class="wrapper"
|
||||
style={$dynamicProps.splitterVisible ? `height:${size}px` : 'flex: 1 1 0'}
|
||||
style={computed.splitterVisible ? `height:${computed.contentHeight}px` : 'flex: 1 1 0'}
|
||||
data-testid={$$props['data-testid'] ? `${$$props['data-testid']}_content` : undefined}
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
{#if $dynamicProps.splitterVisible}
|
||||
<div class="vertical-split-handle" use:splitterDrag={'clientY'} on:resizeSplitter={e => (size += e.detail)} />
|
||||
{#if computed.splitterVisible}
|
||||
<div
|
||||
class="vertical-split-handle"
|
||||
use:splitterDrag={'clientY'}
|
||||
on:resizeSplitter={e => widgetResizeItem(name, e.detail)}
|
||||
/>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
import DatabaseWidget from './DatabaseWidget.svelte';
|
||||
import FilesWidget from './FilesWidget.svelte';
|
||||
import PluginsWidget from './PluginsWidget.svelte';
|
||||
import CellDataWidget from './CellDataWidget.svelte';
|
||||
import HistoryWidget from './HistoryWidget.svelte';
|
||||
import AdminMenuWidget from './AdminMenuWidget.svelte';
|
||||
import AdminPremiumPromoWidget from './AdminPremiumPromoWidget.svelte';
|
||||
@@ -29,9 +28,6 @@
|
||||
{#if $visibleSelectedWidget == 'plugins' && hasPermission('widgets/plugins')}
|
||||
<PluginsWidget />
|
||||
{/if}
|
||||
{#if $visibleSelectedWidget == 'cell-data' && hasPermission('widgets/cell-data')}
|
||||
<CellDataWidget />
|
||||
{/if}
|
||||
{#if $visibleSelectedWidget == 'admin' && hasPermission('widgets/admin')}
|
||||
<AdminMenuWidget />
|
||||
{/if}
|
||||
|
||||
@@ -72,11 +72,6 @@
|
||||
// name: 'plugins',
|
||||
// title: 'Extensions & Plugins',
|
||||
// },
|
||||
{
|
||||
icon: 'icon cell-data',
|
||||
name: 'cell-data',
|
||||
title: _t('widgets.selectedCellDataDetailView', { defaultMessage: 'Selected cell data detail view' }),
|
||||
},
|
||||
{
|
||||
name: 'cloud-public',
|
||||
title: _t('widgets.dbgateCloud', { defaultMessage: 'DbGate Cloud' }),
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
export let hideContent = false;
|
||||
export let fixedWidth = 0;
|
||||
export let skipDefineWidth = false;
|
||||
export let flexContainer = false;
|
||||
|
||||
export function scrollTop() {
|
||||
domDiv.scrollTop = 0;
|
||||
@@ -14,6 +15,7 @@
|
||||
on:drop
|
||||
bind:this={domDiv}
|
||||
class:hideContent
|
||||
class:flexContainer
|
||||
class:leftFixedWidth={!fixedWidth && !skipDefineWidth}
|
||||
data-testid={$$props['data-testid']}
|
||||
style:width={fixedWidth ? `${fixedWidth}px` : undefined}
|
||||
@@ -35,4 +37,8 @@
|
||||
div.hideContent {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
div.flexContainer {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,6 +6,56 @@ const lineReader = require('line-reader');
|
||||
|
||||
let dbgateApi;
|
||||
|
||||
class StripUtf8BomTransform extends stream.Transform {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
this._checkedBOM = false;
|
||||
this._pending = Buffer.alloc(0); // store initial bytes until we know if BOM is present
|
||||
}
|
||||
|
||||
_transform(chunk, encoding, callback) {
|
||||
if (this._checkedBOM) {
|
||||
// We already handled BOM decision, just pass through
|
||||
this.push(chunk);
|
||||
return callback();
|
||||
}
|
||||
|
||||
// Accumulate into pending until we can decide
|
||||
this._pending = Buffer.concat([this._pending, chunk]);
|
||||
|
||||
if (this._pending.length < 3) {
|
||||
// Still don't know if it's BOM or not (need at least 3 bytes)
|
||||
return callback();
|
||||
}
|
||||
|
||||
// Now we can check the first 3 bytes
|
||||
const BOM = [0xef, 0xbb, 0xbf];
|
||||
const hasBom = this._pending[0] === BOM[0] && this._pending[1] === BOM[1] && this._pending[2] === BOM[2];
|
||||
|
||||
if (hasBom) {
|
||||
// Drop the BOM, push the rest
|
||||
this.push(this._pending.slice(3));
|
||||
} else {
|
||||
// No BOM, push everything as-is
|
||||
this.push(this._pending);
|
||||
}
|
||||
|
||||
this._pending = Buffer.alloc(0);
|
||||
this._checkedBOM = true;
|
||||
callback();
|
||||
}
|
||||
|
||||
_flush(callback) {
|
||||
// Stream ended but we never had enough bytes to decide (length < 3)
|
||||
if (!this._checkedBOM && this._pending.length > 0) {
|
||||
// If it's less than 3 bytes, it can't be a UTF-8 BOM, so just pass it through
|
||||
this.push(this._pending);
|
||||
}
|
||||
this._pending = Buffer.alloc(0);
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
function readFirstLine(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
lineReader.open(file, (err, reader) => {
|
||||
@@ -95,7 +145,7 @@ async function reader({ fileName, encoding = 'utf-8', header = true, delimiter,
|
||||
});
|
||||
const fileStream = fs.createReadStream(downloadedFile, encoding);
|
||||
const csvPrepare = new CsvPrepareStream({ header });
|
||||
return [fileStream, csvStream, csvPrepare];
|
||||
return [fileStream, new StripUtf8BomTransform(), csvStream, csvPrepare];
|
||||
// fileStream.pipe(csvStream);
|
||||
// csvStream.pipe(csvPrepare);
|
||||
// return csvPrepare;
|
||||
|
||||
@@ -46,6 +46,8 @@ const dialect = {
|
||||
dropReferencesWhenDropTable: false,
|
||||
requireStandaloneSelectForScopeIdentity: true,
|
||||
|
||||
dropColumnDependencies: ['dependencies'],
|
||||
|
||||
columnProperties: {
|
||||
columnComment: true,
|
||||
isUnsigned: true,
|
||||
|
||||
@@ -64,6 +64,21 @@ class Dumper extends SqlDumper {
|
||||
this.putCmd('^alter ^table %f ^rename ^column %i ^to %i', column, column.columnName, newcol);
|
||||
}
|
||||
|
||||
createForeignKeyFore(fk) {
|
||||
if (fk.constraintName != null && !this.dialect.anonymousForeignKey) {
|
||||
this.put('^constraint %i ', fk.constraintName);
|
||||
}
|
||||
this.put(
|
||||
'^foreign ^key (%,i) ^references %f (%,i)',
|
||||
fk.columns.map(x => x.columnName),
|
||||
{ schemaName: fk.refSchemaName, pureName: fk.refTableName },
|
||||
fk.columns.map(x => x.refColumnName)
|
||||
);
|
||||
if (fk.deleteAction && fk.deleteAction.toUpperCase() !== 'NO ACTION') {
|
||||
this.put(' ^on ^delete %k', fk.deleteAction);
|
||||
}
|
||||
}
|
||||
|
||||
// dropTable(obj, options = {}) {
|
||||
// this.put('^drop ^table');
|
||||
// if (options.testIfExists) this.put(' ^if ^exists');
|
||||
|
||||
@@ -264,7 +264,15 @@ const driver = {
|
||||
async listDatabases(dbhan) {
|
||||
const info = await this.info(dbhan);
|
||||
|
||||
return _.range(16).map((index) => ({ name: `db${index}`, extInfo: info[`db${index}`], sortOrder: index }));
|
||||
let databaseCount = 16;
|
||||
try {
|
||||
const configResult = await dbhan.client.config('GET', 'databases');
|
||||
if (Array.isArray(configResult) && configResult.length >= 2) {
|
||||
databaseCount = parseInt(configResult[1], 10) || 16;
|
||||
}
|
||||
} catch {}
|
||||
|
||||
return _.range(databaseCount).map((index) => ({ name: `db${index}`, extInfo: info[`db${index}`], sortOrder: index }));
|
||||
},
|
||||
|
||||
async scanKeys(dbhan, pattern, cursor = 0, count) {
|
||||
|
||||
@@ -129,6 +129,7 @@ class Analyser extends DatabaseAnalyser {
|
||||
updateAction: fkcol.on_update,
|
||||
deleteAction: fkcol.on_delete,
|
||||
constraintName: `FK_${tableName}_${fkcol.id}`,
|
||||
constraintType: 'foreignKey',
|
||||
};
|
||||
return fk;
|
||||
});
|
||||
|
||||
@@ -137,6 +137,8 @@
|
||||
"command.archiveFile": "Archivní soubor",
|
||||
"command.archiveFile.save": "Uložit",
|
||||
"command.archiveFile.saveAs": "Uložit jako",
|
||||
"command.chart": "Graf",
|
||||
"command.chart.export": "Exportovat graf",
|
||||
"command.cloud": "Cloud",
|
||||
"command.cloud.logout": "Odhlásit",
|
||||
"command.collectionData": "Data kolekce",
|
||||
@@ -145,7 +147,21 @@
|
||||
"command.collectionData.save": "Uložit",
|
||||
"command.commandPalette": "Paleta příkazů",
|
||||
"command.commandPalette.show": "Zobrazit",
|
||||
"command.compare": "Porovnat modely",
|
||||
"command.compare.deploy": "Nasadit",
|
||||
"command.compare.refresh": "Obnovit",
|
||||
"command.compare.refreshModels": "Obnovit modely",
|
||||
"command.compare.report": "Report",
|
||||
"command.compare.reportDiff": "Report rozdílů",
|
||||
"command.compare.swap": "Prohodit",
|
||||
"command.compare.swapSource": "Prohodit zdroj a cíl",
|
||||
"command.compareDatabase": "Porovnání databází",
|
||||
"command.copy": "Kopírovat",
|
||||
"command.dataDeploy": "Data Deployer",
|
||||
"command.dataDeploy.generateShell": "Vygenerovat shell",
|
||||
"command.dataDeploy.generateSql": "Vygenerovat SQL",
|
||||
"command.dataDeploy.kill": "Ukončit nasazení",
|
||||
"command.dataDeploy.run": "Nasadit do DB",
|
||||
"command.dataForm": "Formulář dat",
|
||||
"command.dataForm.addToFilter": "Přidat do filtru",
|
||||
"command.dataForm.copyToClipboard": "Zkopírovat do schránky",
|
||||
@@ -218,6 +234,9 @@
|
||||
"command.datagrid.stopAutoRefresh": "Zastavit automatické obnovování",
|
||||
"command.datagrid.switchToJSON": "Přepnout na JSON",
|
||||
"command.datagrid.switchToform": "Přepnout na formulář",
|
||||
"command.datagrid.toggleCellDataView": "Přepnout zobrazení dat buňky",
|
||||
"command.datagrid.toggleCellDataView.menu": "Zobrazit data buňky",
|
||||
"command.datagrid.toggleCellDataView.toolbar": "Data buňky",
|
||||
"command.datagrid.toggleLeftPanel": "Přepnout levý panel",
|
||||
"command.datagrid.undo": "Krok zpět",
|
||||
"command.datagrid.viewJsonDocument": "Zobrazit řádek jako JSON dokument",
|
||||
@@ -227,6 +246,7 @@
|
||||
"command.designer": "Návrhář",
|
||||
"command.designer.arrange": "Uspořádat",
|
||||
"command.designer.exportDiagram": "Exportovat diagram",
|
||||
"command.designer.openSql": "Otevřít SQL",
|
||||
"command.designer.remove": "Odebrat",
|
||||
"command.designer.removeSelectedTables": "Odebrat vybrané tabulky",
|
||||
"command.diagram": "Diagram",
|
||||
@@ -256,6 +276,7 @@
|
||||
"command.internal": "Interní",
|
||||
"command.internal.loadCampaigns": "Načíst seznam kampaní",
|
||||
"command.internal.showCampaigns": "Zobrazit kampaně",
|
||||
"command.jsonl": "JSON Lines editor",
|
||||
"command.jsonl.closePreview": "Zavřít náhled",
|
||||
"command.jsonl.preview": "Náhled",
|
||||
"command.jsonl.previewNewTab": "Náhled v nové kartě",
|
||||
@@ -294,6 +315,13 @@
|
||||
"command.new.tableToolbar": "Nová tabulka",
|
||||
"command.openQuery": "Otevřít dotaz",
|
||||
"command.paste": "Vložit",
|
||||
"command.perspective": "Perspektiva",
|
||||
"command.perspective.openJson": "Otevřít JSON",
|
||||
"command.perspective.refresh": "Obnovit",
|
||||
"command.profiler": "Profiler",
|
||||
"command.profiler.save": "Uložit",
|
||||
"command.profiler.start": "Spustit profilování",
|
||||
"command.profiler.stop": "Zastavit profilování",
|
||||
"command.query": "Dotaz",
|
||||
"command.query.AiAssistant": "AI Asistent",
|
||||
"command.query.autocommitOffSwitch": "Automatické potvrzování: VYPNUTO",
|
||||
@@ -368,6 +396,7 @@
|
||||
"commandPalette.searchInDatabase": "Hledat v databázi",
|
||||
"common.Remove": "Odstranit",
|
||||
"common.addNew": "Přidat nový",
|
||||
"common.addProvider": "Přidat poskytovatele",
|
||||
"common.advanced": "Pokročilé",
|
||||
"common.allFields": "Všechny {field}",
|
||||
"common.allFiles": "Všechny soubory",
|
||||
@@ -395,6 +424,7 @@
|
||||
"common.done": "Hotovo",
|
||||
"common.dontAskAgain": "Znovu se neptat",
|
||||
"common.download": "Stáhnout",
|
||||
"common.edit": "Upravit",
|
||||
"common.erDiagram": "ER Diagram",
|
||||
"common.error": "Chyba",
|
||||
"common.execute": "Spustit",
|
||||
@@ -451,6 +481,57 @@
|
||||
"common.testingConnection": "Testování připojení",
|
||||
"common.uncheckAll": "Zrušit zaškrtnutí všeho",
|
||||
"common.zipFiles": "ZIP soubory",
|
||||
"compare.action": "Akce",
|
||||
"compare.added": "Přidáno",
|
||||
"compare.allowDropColumns": "Povolit odstranění sloupců",
|
||||
"compare.allowDropSqlObjects": "Povolit odstranění pohledů, procedur apod.",
|
||||
"compare.allowDropTables": "Povolit odstranění tabulek",
|
||||
"compare.allowTableRecreate": "Povolit znovuvytvoření tabulky",
|
||||
"compare.autoinc": "Autoinc",
|
||||
"compare.changed": "Změněno",
|
||||
"compare.columns": "Sloupce",
|
||||
"compare.ddl": "DDL",
|
||||
"compare.deletedPrefix": "Prefix smazaných",
|
||||
"compare.deployChanges": "Nasadit změny",
|
||||
"compare.deployingDatabaseChanges": "Nasazování změn databáze",
|
||||
"compare.dontDropColumns": "Neodstraňovat sloupce",
|
||||
"compare.dontDropConstraints": "Neodstraňovat omezení",
|
||||
"compare.dontDropSqlObjects": "Neodstraňovat objekt",
|
||||
"compare.dontDropTables": "Neodstraňovat tabulky",
|
||||
"compare.dropColumnsIfMissing": "Odstranit chybějící sloupce",
|
||||
"compare.dropSqlObjectsIfMissing": "Odstranit chybějící objekt",
|
||||
"compare.dropTablesIfMissing": "Odstranit chybějící tabulky",
|
||||
"compare.equal": "Shodné",
|
||||
"compare.errorWhenSaving": "Chyba při ukládání",
|
||||
"compare.hideRowsWithoutOperations": "Skrýt řádky bez operací",
|
||||
"compare.ignoreCase": "Ignorovat velikost písmen",
|
||||
"compare.ignoreConstraintNames": "Ignorovat názvy omezení",
|
||||
"compare.ignoreDataTypes": "Ignorovat datové typy",
|
||||
"compare.ignoreForeignKeyActions": "Ignorovat akce cizích klíčů",
|
||||
"compare.ignoreNameRegex": "Ignorovat názvy odpovídající regexu",
|
||||
"compare.ignoreSchema": "Ignorovat schéma",
|
||||
"compare.loadingDatabaseStructure": "Načítání struktury databáze",
|
||||
"compare.markColumnsAsDeleted": "Označit sloupce jako smazané",
|
||||
"compare.markSqlObjectsAsDeleted": "Označit objekt jako smazaný",
|
||||
"compare.markTablesAsDeleted": "Označit tabulky jako smazané",
|
||||
"compare.name": "Název",
|
||||
"compare.notNull": "Not null",
|
||||
"compare.operations": "Operace",
|
||||
"compare.removed": "Odstraněno",
|
||||
"compare.sameSourceAndTargetDatabasesWarning": "Zdrojová a cílová databáze jsou stejné, žádné rozdíly nebudou nalezeny. Změňte prosím zdrojovou nebo cílovou databázi.",
|
||||
"compare.savedToDatabase": "Uloženo do databáze",
|
||||
"compare.schema": "Schéma",
|
||||
"compare.searchTablesOrObjects": "Hledat tabulky nebo objekty",
|
||||
"compare.settings": "Nastavení",
|
||||
"compare.sourceDatabase": "Zdrojová databáze",
|
||||
"compare.sourceDbModel": "Zdrojový DB model",
|
||||
"compare.sourceModelTransform": "Zdrojová transformace modelu",
|
||||
"compare.sourceServer": "Zdrojový server",
|
||||
"compare.synchronizeScript": "Synchronizační skript",
|
||||
"compare.targetDatabase": "Cílová databáze",
|
||||
"compare.targetSchema": "Cílové schéma",
|
||||
"compare.targetServer": "Cílový server",
|
||||
"compare.type": "Typ",
|
||||
"connection.accessKeyId": "ID přístupového klíče",
|
||||
"connection.allowedDatabases": "Povolené databáze, jedna na řádek",
|
||||
"connection.allowedDatabasesRegex": "Regulární výraz pro povolené databáze",
|
||||
@@ -675,6 +756,7 @@
|
||||
"datagrid.searchMacros": "Hledat makra",
|
||||
"datagrid.setFormat": "Nastavit formát: ",
|
||||
"datagrid.structure": "Struktura",
|
||||
"datagrid.useMacro": "Použít makro",
|
||||
"dbKeyAddItemModal.header": "Přidat položku",
|
||||
"dbKeysTreeNode.deleteBranch": "Smazat větev",
|
||||
"dbKeysTreeNode.deleteBranchConfirm": "Opravdu smazat větev {branch} se všemi klíči?",
|
||||
@@ -755,6 +837,22 @@
|
||||
"designerTable.newAlias": "Nový alias",
|
||||
"designerTable.removeTableAlias": "Odstranit alias tabulky",
|
||||
"designerTable.setTableAlias": "Nastavit alias tabulky",
|
||||
"diagram.all": "Vše",
|
||||
"diagram.allKeys": "Všechny klíče",
|
||||
"diagram.columnFilter": "Filtr sloupců",
|
||||
"diagram.exportWatermark": "Exportovat vodoznak",
|
||||
"diagram.keysAndNotNull": "Klíče a Not Null",
|
||||
"diagram.notNull": "Not Null",
|
||||
"diagram.omitExportWatermark": "Vynechat export vodoznaku",
|
||||
"diagram.omitTablesFilter": "Vynechat tabulky",
|
||||
"diagram.primaryKey": "Primární klíč",
|
||||
"diagram.showColumns": "Zobrazit sloupce",
|
||||
"diagram.showDataType": "Zobrazit datový typ",
|
||||
"diagram.showNullability": "Zobrazit NULL/NOT NULL",
|
||||
"diagram.tableFilter": "Filtr tabulek",
|
||||
"diagram.tables": "Tabulky",
|
||||
"diagram.topTables": "Pouze N nejdůležitějších tabulek",
|
||||
"diagram.zoom": "Zoom",
|
||||
"dictionaryLookupModal.customize": "Přizpůsobit",
|
||||
"dictionaryLookupModal.description": "Popis",
|
||||
"dictionaryLookupModal.header": "Vyhledat z {pureName}",
|
||||
@@ -1032,6 +1130,16 @@
|
||||
"newObject.sqlGeneratorDisabled": "SQL generátor není pro aktuální databázi k dispozici",
|
||||
"newObject.tableDescription": "Vytvořit tabulku v aktuální databázi",
|
||||
"newObject.tableDisabled": "Vytvoření tabulky není pro aktuální databázi k dispozici",
|
||||
"perspective.arrange": "Uspořádat",
|
||||
"perspective.arranged": "(Uspořádáno)",
|
||||
"perspective.category": "Perspektiva",
|
||||
"perspective.chooseData": "Vybrat data",
|
||||
"perspective.customJoin": "Vlastní join",
|
||||
"perspective.filters": "Filtry",
|
||||
"perspective.invalidFormat": "Neplatný formát perspektivy, vytvořte prosím novou perspektivu",
|
||||
"perspective.noFiltersDefined": "Nejsou definovány žádné filtry",
|
||||
"perspective.searchColumnOrTable": "Hledat sloupec nebo tabulku",
|
||||
"perspective.useContextMenuAddToFilter": "Použijte kontextové menu, příkaz \"Přidat do filtru\" v tabulce nebo ve stromu",
|
||||
"plugins.searchExtensionsOnWeb": "Hledat rozšíření na webu",
|
||||
"privateCloudWidget.addExistingFolder": "Přidat existující složku (z odkazu)",
|
||||
"privateCloudWidget.addExistingSharedFolder": "Přidat existující sdílenou složku",
|
||||
@@ -1056,6 +1164,7 @@
|
||||
"publicCloudWidget.refreshFiles": "Obnovit soubory",
|
||||
"publicCloudWidget.refreshList": "Obnovit seznam",
|
||||
"publicCloudWidget.searchPublicFiles": "Hledat veřejné soubory",
|
||||
"query.AiAssistant": "AI Asistent",
|
||||
"query.Copy": "Kopírovat",
|
||||
"query.Download": "Stáhnout",
|
||||
"query.Messages": "Zprávy",
|
||||
@@ -1064,17 +1173,34 @@
|
||||
"query.OutputFiles": "Výstupní soubory",
|
||||
"query.Show": "Zobrazit",
|
||||
"query.Size": "Velikost",
|
||||
"query.addCustomExpression": "Přidat vlastní výraz",
|
||||
"query.addGroupOrCondition": "Přidat skupinu NEBO podmínku",
|
||||
"query.addOrCondition": "Přidat NEBO podmínku",
|
||||
"query.aggregate": "Agregace",
|
||||
"query.alias": "Alias",
|
||||
"query.columnExpression": "Sloupec/Výraz",
|
||||
"query.download": "stáhnout",
|
||||
"query.filter": "Filtr",
|
||||
"query.groupBy": "Seskupit podle",
|
||||
"query.groupFilter": "Filtr skupiny",
|
||||
"query.limitRows": "Omezit na {queryRowsLimit} řádků",
|
||||
"query.named": ":proměnná",
|
||||
"query.noParameters": "(žádné parametry)",
|
||||
"query.noRowsLimit": "(bez limitu řádků)",
|
||||
"query.orFilter": "NEBO filtr {number}",
|
||||
"query.orGroupFilter": "NEBO filtr skupiny {number}",
|
||||
"query.output": "Výstup",
|
||||
"query.positional": "? (poziční)",
|
||||
"query.queryNumber": "Dotaz #",
|
||||
"query.removeDuplicates": "Odstranit duplicity: {status}",
|
||||
"query.removeGroupOrCondition": "Odstranit skupinu NEBO podmínku",
|
||||
"query.removeOrCondition": "Odstranit NEBO podmínku",
|
||||
"query.returnOnlyNRows": "Vrátit pouze N řádků při spuštění dotazu",
|
||||
"query.rowsLimit": "Limit řádků",
|
||||
"query.save": "uložit",
|
||||
"query.show": "zobrazit",
|
||||
"query.sortOrder": "Řazení",
|
||||
"query.table": "Tabulka",
|
||||
"query.unlimitedRows": "Neomezený počet řádků",
|
||||
"query.variable": "#proměnná",
|
||||
"queryParameters.editQueryParameters": "Upravit parametry dotazu",
|
||||
@@ -1106,6 +1232,35 @@
|
||||
"serverSummaryTab.processes": "Procesy",
|
||||
"serverSummaryTab.variables": "Proměnné",
|
||||
"settings.AI": "AI",
|
||||
"settings.aiChatDefaults.heading": "Výchozí nastavení AI chatu",
|
||||
"settings.aiExecuteMode": "Režim vykonávání SQL",
|
||||
"settings.aiExecuteMode.ask": "Zeptat se před spuštěním",
|
||||
"settings.aiExecuteMode.auto": "Spouštět automaticky",
|
||||
"settings.aiExecuteMode.never": "Nikdy nespouštět SQL",
|
||||
"settings.aiProvider": "AI poskytovatel",
|
||||
"settings.aiProvider.apiKey": "API klíč",
|
||||
"settings.aiProvider.apiKeyPlaceholder": "Váš API klíč (ponechte prázdné pro lokální poskytovatele)",
|
||||
"settings.aiProvider.baseUrl": "Základní URL",
|
||||
"settings.aiProvider.connectionTest.cancel": "Zrušit test",
|
||||
"settings.aiProvider.connectionTest.retest": "Otestovat připojení znovu",
|
||||
"settings.aiProvider.connectionTest.test": "Otestovat připojení",
|
||||
"settings.aiProvider.connectionTestFailed": "Test připojení selhal:",
|
||||
"settings.aiProvider.defaultModel": "Výchozí model",
|
||||
"settings.aiProvider.gateway": "DbGate AI Gateway",
|
||||
"settings.aiProvider.name": "Název poskytovatele",
|
||||
"settings.aiProvider.newProviderName": "Poskytovatel {number}",
|
||||
"settings.aiProvider.noDefaultModel": "(Žádný výchozí model)",
|
||||
"settings.aiProvider.noModelsAvailable": "(Žádné modely nejsou k dispozici)",
|
||||
"settings.aiProvider.noUrlConfigured": "Není nastavena žádná URL",
|
||||
"settings.aiProvider.removeProviderConfirmation": "Opravdu chcete odstranit poskytovatele {provider}?",
|
||||
"settings.aiProvider.status.connectionFailed": "Připojení selhalo:",
|
||||
"settings.aiProvider.status.error": "Chyba",
|
||||
"settings.aiProvider.status.noModelsFound": "Nebyly nalezeny žádné modely",
|
||||
"settings.aiProvider.status.notConfigured": "Nenastaveno",
|
||||
"settings.aiProvider.status.testing": "Testování",
|
||||
"settings.aiProvider.status.testingConnection": "Testování připojení...",
|
||||
"settings.aiProvider.status.untested": "Netestováno",
|
||||
"settings.aiProvider.status.valid": "Platné",
|
||||
"settings.appearance": "Vzhled aplikace",
|
||||
"settings.appearance.afterInstalling": "Po instalaci pluginu témat (zkuste vyhledat \"theme\" v dostupných rozšířeních) zde budou k dispozici nová témata.",
|
||||
"settings.appearance.customSize": "Vlastní velikost",
|
||||
@@ -1130,6 +1285,8 @@
|
||||
"settings.connection.autoRefreshInterval": "Interval mezi automatickým načítáním struktury DB v sekundách",
|
||||
"settings.connection.showOnlyTabsFromSelectedDatabase": "Zobrazit pouze karty z vybrané databáze",
|
||||
"settings.connection.sshBindHost": "Lokální adresa hostitele pro SSH připojení",
|
||||
"settings.customProviders.heading": "Vlastní poskytovatelé",
|
||||
"settings.customProviders.noProvidersConfigured": "Nejsou nakonfigurováni žádní vlastní poskytovatelé. Začněte kliknutím na \"Přidat poskytovatele\".",
|
||||
"settings.dataGrid.alignNumbersRight": "Zarovnat čísla doprava",
|
||||
"settings.dataGrid.collectionPageSize": "Velikost stránky kolekce (pro MongoDB JSON zobrazení, musí být mezi 5 a 50000)",
|
||||
"settings.dataGrid.coloringMode": "Režim zabarvení řádků",
|
||||
@@ -1142,6 +1299,12 @@
|
||||
"settings.dataGrid.showAllColumnsWhenSearch": "Zobrazit všechny sloupce při hledání",
|
||||
"settings.dataGrid.showHintColumns": "Zobrazit nápovědu pro cizí klíče",
|
||||
"settings.dataGrid.thousandsSeparator": "Použít oddělovač tisíců pro čísla",
|
||||
"settings.dataGrid.thousandsSeparator.comma": "Čárka (,)",
|
||||
"settings.dataGrid.thousandsSeparator.dot": "Tečka (.)",
|
||||
"settings.dataGrid.thousandsSeparator.narrowSpace": "Úzká mezera",
|
||||
"settings.dataGrid.thousandsSeparator.none": "Žádný",
|
||||
"settings.dataGrid.thousandsSeparator.space": "Mezera",
|
||||
"settings.dataGrid.thousandsSeparator.system": "Systémový",
|
||||
"settings.dataGrid.title": "Datová mřížka",
|
||||
"settings.defaultActions": "Výchozí akce",
|
||||
"settings.defaultActions.collectionClick": "Kliknutí na kolekci",
|
||||
@@ -1198,6 +1361,9 @@
|
||||
"settings.sqlEditor.showTableAliasesInCodeCompletion": "Zobrazit aliasy tabulek v dokončování kódu",
|
||||
"settings.sqlEditor.sqlCommandsCase": "Velikost písmen SQL příkazů",
|
||||
"settings.sqlEditor.title": "SQL editor",
|
||||
"settings.supportedProviders.description": "Bude fungovat jakákoli služba kompatibilní s formátem OpenAI API, včetně:",
|
||||
"settings.supportedProviders.heading": "Podporovaní poskytovatelé",
|
||||
"settings.supportedProviders.useThisProvider": "Použít tohoto poskytovatele",
|
||||
"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",
|
||||
@@ -1267,6 +1433,11 @@
|
||||
"switchDatabase.server": "Server",
|
||||
"switchDatabase.switchDatabase": "Přepnout databázi",
|
||||
"tab.administration": "Administrace",
|
||||
"tableCell.edit": "Upravit",
|
||||
"tableCell.filterColumns": "Filtrovat sloupce",
|
||||
"tableCell.hideNullValues": "Skrýt hodnoty NULL",
|
||||
"tableCell.multipleValues": "Více hodnot",
|
||||
"tableCell.noDataSelected": "Nejsou vybrána žádná data",
|
||||
"tableData.errorWhenSaving": "Chyba při ukládání",
|
||||
"tableData.refreshEvery": "Obnovit (každých {autoRefreshInterval}s)",
|
||||
"tableData.savedToDatabase": "Uloženo do databáze",
|
||||
|
||||
@@ -137,6 +137,8 @@
|
||||
"command.archiveFile": "Archivdatei",
|
||||
"command.archiveFile.save": "Speichern",
|
||||
"command.archiveFile.saveAs": "Speichern unter",
|
||||
"command.chart": "Diagramm",
|
||||
"command.chart.export": "Diagramm exportieren",
|
||||
"command.cloud": "Cloud",
|
||||
"command.cloud.logout": "Abmelden",
|
||||
"command.collectionData": "Sammlungsdaten",
|
||||
@@ -145,7 +147,21 @@
|
||||
"command.collectionData.save": "Speichern",
|
||||
"command.commandPalette": "Befehlspalette",
|
||||
"command.commandPalette.show": "Anzeigen",
|
||||
"command.compare": "Modelle vergleichen",
|
||||
"command.compare.deploy": "Bereitstellen",
|
||||
"command.compare.refresh": "Aktualisieren",
|
||||
"command.compare.refreshModels": "Modelle aktualisieren",
|
||||
"command.compare.report": "Bericht",
|
||||
"command.compare.reportDiff": "Differenzbericht",
|
||||
"command.compare.swap": "Tauschen",
|
||||
"command.compare.swapSource": "Quelle & Ziel tauschen",
|
||||
"command.compareDatabase": "Datenbankvergleich",
|
||||
"command.copy": "Kopieren",
|
||||
"command.dataDeploy": "Data Deployer",
|
||||
"command.dataDeploy.generateShell": "Shell generieren",
|
||||
"command.dataDeploy.generateSql": "SQL generieren",
|
||||
"command.dataDeploy.kill": "Bereitstellung beenden",
|
||||
"command.dataDeploy.run": "In DB bereitstellen",
|
||||
"command.dataForm": "Datenformular",
|
||||
"command.dataForm.addToFilter": "Zu Filter hinzufügen",
|
||||
"command.dataForm.copyToClipboard": "In Zwischenablage kopieren",
|
||||
@@ -218,6 +234,9 @@
|
||||
"command.datagrid.stopAutoRefresh": "Automatische Aktualisierung stoppen",
|
||||
"command.datagrid.switchToJSON": "Zu JSON wechseln",
|
||||
"command.datagrid.switchToform": "Zu Formular wechseln",
|
||||
"command.datagrid.toggleCellDataView": "Zell-Datenansicht umschalten",
|
||||
"command.datagrid.toggleCellDataView.menu": "Zelldaten anzeigen",
|
||||
"command.datagrid.toggleCellDataView.toolbar": "Zelldaten",
|
||||
"command.datagrid.toggleLeftPanel": "Linke Leiste umschalten",
|
||||
"command.datagrid.undo": "Rückgängig",
|
||||
"command.datagrid.viewJsonDocument": "Zeile als JSON-Dokument anzeigen",
|
||||
@@ -227,6 +246,7 @@
|
||||
"command.designer": "Designer",
|
||||
"command.designer.arrange": "Anordnen",
|
||||
"command.designer.exportDiagram": "Diagramm exportieren",
|
||||
"command.designer.openSql": "SQL öffnen",
|
||||
"command.designer.remove": "Entfernen",
|
||||
"command.designer.removeSelectedTables": "Ausgewählte Tabellen entfernen",
|
||||
"command.diagram": "Diagramm",
|
||||
@@ -256,6 +276,7 @@
|
||||
"command.internal": "Intern",
|
||||
"command.internal.loadCampaigns": "Kampagnenliste laden",
|
||||
"command.internal.showCampaigns": "Kampagnen anzeigen",
|
||||
"command.jsonl": "JSON-Lines-Editor",
|
||||
"command.jsonl.closePreview": "Vorschau schließen",
|
||||
"command.jsonl.preview": "Vorschau",
|
||||
"command.jsonl.previewNewTab": "Vorschau in neuem Tab",
|
||||
@@ -294,6 +315,13 @@
|
||||
"command.new.tableToolbar": "Neue Tabelle",
|
||||
"command.openQuery": "Abfrage öffnen",
|
||||
"command.paste": "Einfügen",
|
||||
"command.perspective": "Perspektive",
|
||||
"command.perspective.openJson": "JSON öffnen",
|
||||
"command.perspective.refresh": "Aktualisieren",
|
||||
"command.profiler": "Profiler",
|
||||
"command.profiler.save": "Speichern",
|
||||
"command.profiler.start": "Profiling starten",
|
||||
"command.profiler.stop": "Profiling stoppen",
|
||||
"command.query": "Abfrage",
|
||||
"command.query.AiAssistant": "KI-Assistent",
|
||||
"command.query.autocommitOffSwitch": "Auto-Commit: AUS",
|
||||
@@ -368,6 +396,7 @@
|
||||
"commandPalette.searchInDatabase": "In Datenbank suchen",
|
||||
"common.Remove": "Entfernen",
|
||||
"common.addNew": "Neu hinzufügen",
|
||||
"common.addProvider": "Provider hinzufügen",
|
||||
"common.advanced": "Erweitert",
|
||||
"common.allFields": "Alle {field}",
|
||||
"common.allFiles": "Alle Dateien",
|
||||
@@ -395,6 +424,7 @@
|
||||
"common.done": "Fertig",
|
||||
"common.dontAskAgain": "Nicht erneut fragen",
|
||||
"common.download": "Herunterladen",
|
||||
"common.edit": "Bearbeiten",
|
||||
"common.erDiagram": "ER-Diagramm",
|
||||
"common.error": "Fehler",
|
||||
"common.execute": "Ausführen",
|
||||
@@ -451,6 +481,57 @@
|
||||
"common.testingConnection": "Verbindung wird getestet",
|
||||
"common.uncheckAll": "Alle abwählen",
|
||||
"common.zipFiles": "ZIP-Dateien",
|
||||
"compare.action": "Aktion",
|
||||
"compare.added": "Hinzugefügt",
|
||||
"compare.allowDropColumns": "Spalten löschen erlauben",
|
||||
"compare.allowDropSqlObjects": "Sicht, Prozedur usw. löschen erlauben",
|
||||
"compare.allowDropTables": "Tabellen löschen erlauben",
|
||||
"compare.allowTableRecreate": "Tabellen-Neuerstellung erlauben",
|
||||
"compare.autoinc": "Autoinc",
|
||||
"compare.changed": "Geändert",
|
||||
"compare.columns": "Spalten",
|
||||
"compare.ddl": "DDL",
|
||||
"compare.deletedPrefix": "Gelöschtes Präfix",
|
||||
"compare.deployChanges": "Änderungen bereitstellen",
|
||||
"compare.deployingDatabaseChanges": "Datenbankänderungen werden bereitgestellt",
|
||||
"compare.dontDropColumns": "Spalten nicht löschen",
|
||||
"compare.dontDropConstraints": "Constraints nicht löschen",
|
||||
"compare.dontDropSqlObjects": "Objekt nicht löschen",
|
||||
"compare.dontDropTables": "Tabellen nicht löschen",
|
||||
"compare.dropColumnsIfMissing": "Spalten löschen, wenn fehlend",
|
||||
"compare.dropSqlObjectsIfMissing": "Objekt löschen, wenn fehlend",
|
||||
"compare.dropTablesIfMissing": "Tabellen löschen, wenn fehlend",
|
||||
"compare.equal": "Gleich",
|
||||
"compare.errorWhenSaving": "Fehler beim Speichern",
|
||||
"compare.hideRowsWithoutOperations": "Zeilen ohne Operationen ausblenden",
|
||||
"compare.ignoreCase": "Groß-/Kleinschreibung ignorieren",
|
||||
"compare.ignoreConstraintNames": "Constraint-Namen ignorieren",
|
||||
"compare.ignoreDataTypes": "Datentypen ignorieren",
|
||||
"compare.ignoreForeignKeyActions": "Fremdschlüssel-Aktionen ignorieren",
|
||||
"compare.ignoreNameRegex": "Namen ignorieren, die Regex entsprechen",
|
||||
"compare.ignoreSchema": "Schema ignorieren",
|
||||
"compare.loadingDatabaseStructure": "Datenbankstruktur wird geladen",
|
||||
"compare.markColumnsAsDeleted": "Spalten als gelöscht markieren",
|
||||
"compare.markSqlObjectsAsDeleted": "Objekt als gelöscht markieren",
|
||||
"compare.markTablesAsDeleted": "Tabellen als gelöscht markieren",
|
||||
"compare.name": "Name",
|
||||
"compare.notNull": "Not null",
|
||||
"compare.operations": "Operationen",
|
||||
"compare.removed": "Entfernt",
|
||||
"compare.sameSourceAndTargetDatabasesWarning": "Quell- und Zieldatenbank sind identisch, es werden keine Unterschiede gefunden. Bitte ändern Sie die Quell- oder Zieldatenbank.",
|
||||
"compare.savedToDatabase": "In Datenbank gespeichert",
|
||||
"compare.schema": "Schema",
|
||||
"compare.searchTablesOrObjects": "Tabellen oder Objekte suchen",
|
||||
"compare.settings": "Einstellungen",
|
||||
"compare.sourceDatabase": "Quell-Datenbank",
|
||||
"compare.sourceDbModel": "Quell-DB-Modell",
|
||||
"compare.sourceModelTransform": "Quell-Modelltransformation",
|
||||
"compare.sourceServer": "Quell-Server",
|
||||
"compare.synchronizeScript": "Synchronisationsskript",
|
||||
"compare.targetDatabase": "Ziel-Datenbank",
|
||||
"compare.targetSchema": "Ziel-Schema",
|
||||
"compare.targetServer": "Ziel-Server",
|
||||
"compare.type": "Typ",
|
||||
"connection.accessKeyId": "Zugriffsschlüssel-ID",
|
||||
"connection.allowedDatabases": "Erlaubte Datenbanken, eine pro Zeile",
|
||||
"connection.allowedDatabasesRegex": "Regulärer Ausdruck für erlaubte Datenbanken",
|
||||
@@ -675,6 +756,7 @@
|
||||
"datagrid.searchMacros": "Makros suchen",
|
||||
"datagrid.setFormat": "Format festlegen: ",
|
||||
"datagrid.structure": "Struktur",
|
||||
"datagrid.useMacro": "Makro verwenden",
|
||||
"dbKeyAddItemModal.header": "Eintrag hinzufügen",
|
||||
"dbKeysTreeNode.deleteBranch": "Zweig löschen",
|
||||
"dbKeysTreeNode.deleteBranchConfirm": "Zweig {branch} mit allen Schlüsseln wirklich löschen?",
|
||||
@@ -755,6 +837,22 @@
|
||||
"designerTable.newAlias": "Neuer Alias",
|
||||
"designerTable.removeTableAlias": "Tabellenalias entfernen",
|
||||
"designerTable.setTableAlias": "Tabellenalias setzen",
|
||||
"diagram.all": "Alle",
|
||||
"diagram.allKeys": "Alle Schlüssel",
|
||||
"diagram.columnFilter": "Spaltenfilter",
|
||||
"diagram.exportWatermark": "Wasserzeichen exportieren",
|
||||
"diagram.keysAndNotNull": "Schlüssel und Not Null",
|
||||
"diagram.notNull": "Not Null",
|
||||
"diagram.omitExportWatermark": "Export-Wasserzeichen auslassen",
|
||||
"diagram.omitTablesFilter": "Tabellen auslassen",
|
||||
"diagram.primaryKey": "Primärschlüssel",
|
||||
"diagram.showColumns": "Spalten anzeigen",
|
||||
"diagram.showDataType": "Datentyp anzeigen",
|
||||
"diagram.showNullability": "NULL/NOT NULL anzeigen",
|
||||
"diagram.tableFilter": "Tabellenfilter",
|
||||
"diagram.tables": "Tabellen",
|
||||
"diagram.topTables": "Nur N wichtigste Tabellen",
|
||||
"diagram.zoom": "Zoom",
|
||||
"dictionaryLookupModal.customize": "Anpassen",
|
||||
"dictionaryLookupModal.description": "Beschreibung",
|
||||
"dictionaryLookupModal.header": "Nachschlagen aus {pureName}",
|
||||
@@ -1032,6 +1130,16 @@
|
||||
"newObject.sqlGeneratorDisabled": "SQL-Generator ist für aktuelle Datenbank nicht verfügbar",
|
||||
"newObject.tableDescription": "Tabelle in der aktuellen Datenbank erstellen",
|
||||
"newObject.tableDisabled": "Tabellenerstellung ist für aktuelle Datenbank nicht verfügbar",
|
||||
"perspective.arrange": "Anordnen",
|
||||
"perspective.arranged": "(Angeordnet)",
|
||||
"perspective.category": "Perspektive",
|
||||
"perspective.chooseData": "Daten auswählen",
|
||||
"perspective.customJoin": "Benutzerdefinierter Join",
|
||||
"perspective.filters": "Filter",
|
||||
"perspective.invalidFormat": "Ungültiges Perspektivenformat, bitte neue Perspektive erstellen",
|
||||
"perspective.noFiltersDefined": "Keine Filter definiert",
|
||||
"perspective.searchColumnOrTable": "Spalte oder Tabelle suchen",
|
||||
"perspective.useContextMenuAddToFilter": "Kontextmenü, Befehl \"Zu Filter hinzufügen\" in Tabelle oder im Baum verwenden",
|
||||
"plugins.searchExtensionsOnWeb": "Erweiterungen im Web suchen",
|
||||
"privateCloudWidget.addExistingFolder": "Vorhandenen Ordner hinzufügen (aus Link)",
|
||||
"privateCloudWidget.addExistingSharedFolder": "Vorhandenen freigegebenen Ordner hinzufügen",
|
||||
@@ -1056,6 +1164,7 @@
|
||||
"publicCloudWidget.refreshFiles": "Dateien aktualisieren",
|
||||
"publicCloudWidget.refreshList": "Liste aktualisieren",
|
||||
"publicCloudWidget.searchPublicFiles": "Öffentliche Dateien suchen",
|
||||
"query.AiAssistant": "KI-Assistent",
|
||||
"query.Copy": "Kopieren",
|
||||
"query.Download": "Herunterladen",
|
||||
"query.Messages": "Nachrichten",
|
||||
@@ -1064,17 +1173,34 @@
|
||||
"query.OutputFiles": "Ausgabedateien",
|
||||
"query.Show": "Anzeigen",
|
||||
"query.Size": "Größe",
|
||||
"query.addCustomExpression": "Benutzerdefinierten Ausdruck hinzufügen",
|
||||
"query.addGroupOrCondition": "Gruppe-ODER-Bedingung hinzufügen",
|
||||
"query.addOrCondition": "ODER-Bedingung hinzufügen",
|
||||
"query.aggregate": "Aggregation",
|
||||
"query.alias": "Alias",
|
||||
"query.columnExpression": "Spalte/Ausdruck",
|
||||
"query.download": "herunterladen",
|
||||
"query.filter": "Filter",
|
||||
"query.groupBy": "Gruppieren nach",
|
||||
"query.groupFilter": "Gruppenfilter",
|
||||
"query.limitRows": "Auf {queryRowsLimit} Zeilen begrenzen",
|
||||
"query.named": ":Variable",
|
||||
"query.noParameters": "(keine Parameter)",
|
||||
"query.noRowsLimit": "(Keine Zeilenbegrenzung)",
|
||||
"query.orFilter": "ODER-Filter {number}",
|
||||
"query.orGroupFilter": "ODER-Gruppenfilter {number}",
|
||||
"query.output": "Ausgabe",
|
||||
"query.positional": "? (positionell)",
|
||||
"query.queryNumber": "Abfrage #",
|
||||
"query.removeDuplicates": "Duplikate entfernen: {status}",
|
||||
"query.removeGroupOrCondition": "Gruppe-ODER-Bedingung entfernen",
|
||||
"query.removeOrCondition": "ODER-Bedingung entfernen",
|
||||
"query.returnOnlyNRows": "Nur N Zeilen von Abfrage zurückgeben",
|
||||
"query.rowsLimit": "Zeilenbegrenzung",
|
||||
"query.save": "speichern",
|
||||
"query.show": "anzeigen",
|
||||
"query.sortOrder": "Sortierreihenfolge",
|
||||
"query.table": "Tabelle",
|
||||
"query.unlimitedRows": "Unbegrenzte Zeilen",
|
||||
"query.variable": "#Variable",
|
||||
"queryParameters.editQueryParameters": "Abfrageparameter bearbeiten",
|
||||
@@ -1106,6 +1232,35 @@
|
||||
"serverSummaryTab.processes": "Prozesse",
|
||||
"serverSummaryTab.variables": "Variablen",
|
||||
"settings.AI": "KI",
|
||||
"settings.aiChatDefaults.heading": "Standardwerte für KI-Chat",
|
||||
"settings.aiExecuteMode": "SQL-Ausführungsmodus",
|
||||
"settings.aiExecuteMode.ask": "Vor Ausführung nachfragen",
|
||||
"settings.aiExecuteMode.auto": "Automatisch ausführen",
|
||||
"settings.aiExecuteMode.never": "SQL nie ausführen",
|
||||
"settings.aiProvider": "KI-Provider",
|
||||
"settings.aiProvider.apiKey": "API-Schlüssel",
|
||||
"settings.aiProvider.apiKeyPlaceholder": "Ihr API-Schlüssel (für lokale Provider leer lassen)",
|
||||
"settings.aiProvider.baseUrl": "Basis-URL",
|
||||
"settings.aiProvider.connectionTest.cancel": "Test abbrechen",
|
||||
"settings.aiProvider.connectionTest.retest": "Verbindung erneut testen",
|
||||
"settings.aiProvider.connectionTest.test": "Verbindung testen",
|
||||
"settings.aiProvider.connectionTestFailed": "Verbindungstest fehlgeschlagen:",
|
||||
"settings.aiProvider.defaultModel": "Standardmodell",
|
||||
"settings.aiProvider.gateway": "DbGate AI Gateway",
|
||||
"settings.aiProvider.name": "Provider-Name",
|
||||
"settings.aiProvider.newProviderName": "Provider {number}",
|
||||
"settings.aiProvider.noDefaultModel": "(Kein Standardmodell)",
|
||||
"settings.aiProvider.noModelsAvailable": "(Keine Modelle verfügbar)",
|
||||
"settings.aiProvider.noUrlConfigured": "Keine URL konfiguriert",
|
||||
"settings.aiProvider.removeProviderConfirmation": "Möchten Sie den Provider {provider} wirklich entfernen?",
|
||||
"settings.aiProvider.status.connectionFailed": "Verbindung fehlgeschlagen:",
|
||||
"settings.aiProvider.status.error": "Fehler",
|
||||
"settings.aiProvider.status.noModelsFound": "Keine Modelle gefunden",
|
||||
"settings.aiProvider.status.notConfigured": "Nicht konfiguriert",
|
||||
"settings.aiProvider.status.testing": "Wird getestet",
|
||||
"settings.aiProvider.status.testingConnection": "Verbindung wird getestet...",
|
||||
"settings.aiProvider.status.untested": "Nicht getestet",
|
||||
"settings.aiProvider.status.valid": "Gültig",
|
||||
"settings.appearance": "Anwendungs-Design",
|
||||
"settings.appearance.afterInstalling": "Nach der Installation des Design-Plugins (versuchen Sie, \"theme\" in verfügbaren Erweiterungen zu suchen) sind hier neue Designs verfügbar.",
|
||||
"settings.appearance.customSize": "Benutzerdefinierte Größe",
|
||||
@@ -1130,6 +1285,8 @@
|
||||
"settings.connection.autoRefreshInterval": "Intervall zwischen automatischen DB-Strukturaktualisierungen in Sekunden",
|
||||
"settings.connection.showOnlyTabsFromSelectedDatabase": "Nur Tabs aus ausgewählter Datenbank anzeigen",
|
||||
"settings.connection.sshBindHost": "Lokale Host-Adresse für SSH-Verbindungen",
|
||||
"settings.customProviders.heading": "Benutzerdefinierte Provider",
|
||||
"settings.customProviders.noProvidersConfigured": "Keine benutzerdefinierten Provider konfiguriert. Klicken Sie auf \"Provider hinzufügen\", um zu beginnen.",
|
||||
"settings.dataGrid.alignNumbersRight": "Zahlen rechtsbündig ausrichten",
|
||||
"settings.dataGrid.collectionPageSize": "Sammlungsseitengröße (für MongoDB JSON-Ansicht, muss zwischen 5 und 50000 liegen)",
|
||||
"settings.dataGrid.coloringMode": "Zeilen-Färbemodus",
|
||||
@@ -1142,6 +1299,12 @@
|
||||
"settings.dataGrid.showAllColumnsWhenSearch": "Alle Spalten beim Suchen anzeigen",
|
||||
"settings.dataGrid.showHintColumns": "Fremdschlüssel-Hinweise anzeigen",
|
||||
"settings.dataGrid.thousandsSeparator": "Tausendertrennzeichen für Zahlen verwenden",
|
||||
"settings.dataGrid.thousandsSeparator.comma": "Komma (,)",
|
||||
"settings.dataGrid.thousandsSeparator.dot": "Punkt (.)",
|
||||
"settings.dataGrid.thousandsSeparator.narrowSpace": "Schmales Leerzeichen",
|
||||
"settings.dataGrid.thousandsSeparator.none": "Keines",
|
||||
"settings.dataGrid.thousandsSeparator.space": "Leerzeichen",
|
||||
"settings.dataGrid.thousandsSeparator.system": "System",
|
||||
"settings.dataGrid.title": "Datentabelle",
|
||||
"settings.defaultActions": "Standardaktionen",
|
||||
"settings.defaultActions.collectionClick": "Klick auf NoSQL-Sammlung",
|
||||
@@ -1198,6 +1361,9 @@
|
||||
"settings.sqlEditor.showTableAliasesInCodeCompletion": "Tabellenaliase in Code-Vervollständigung anzeigen",
|
||||
"settings.sqlEditor.sqlCommandsCase": "Groß-/Kleinschreibung der SQL-Befehle",
|
||||
"settings.sqlEditor.title": "SQL-Editor",
|
||||
"settings.supportedProviders.description": "Jeder Dienst, der mit dem OpenAI-API-Format kompatibel ist, funktioniert, einschließlich:",
|
||||
"settings.supportedProviders.heading": "Unterstützte Provider",
|
||||
"settings.supportedProviders.useThisProvider": "Diesen Provider verwenden",
|
||||
"settings.tabGroup.showServerName": "Servername neben Datenbankname im Titel der Tab-Gruppe anzeigen",
|
||||
"settings.tabPreviewMode": "Tab-Vorschaumodus",
|
||||
"settings.theme": "Designs",
|
||||
@@ -1267,6 +1433,11 @@
|
||||
"switchDatabase.server": "Server",
|
||||
"switchDatabase.switchDatabase": "Datenbank wechseln",
|
||||
"tab.administration": "Administration",
|
||||
"tableCell.edit": "Bearbeiten",
|
||||
"tableCell.filterColumns": "Spalten filtern",
|
||||
"tableCell.hideNullValues": "NULL-Werte ausblenden",
|
||||
"tableCell.multipleValues": "Mehrere Werte",
|
||||
"tableCell.noDataSelected": "Keine Daten ausgewählt",
|
||||
"tableData.errorWhenSaving": "Fehler beim Speichern",
|
||||
"tableData.refreshEvery": "Aktualisieren (alle {autoRefreshInterval}s)",
|
||||
"tableData.savedToDatabase": "In Datenbank gespeichert",
|
||||
|
||||
+173
-3
@@ -133,6 +133,8 @@
|
||||
"command.archiveFile": "Archive file",
|
||||
"command.archiveFile.save": "Save",
|
||||
"command.archiveFile.saveAs": "Save as",
|
||||
"command.chart": "Chart",
|
||||
"command.chart.export": "Export chart",
|
||||
"command.cloud": "Cloud",
|
||||
"command.cloud.logout": "Logout",
|
||||
"command.collectionData": "Collection data",
|
||||
@@ -141,7 +143,21 @@
|
||||
"command.collectionData.save": "Save",
|
||||
"command.commandPalette": "Command palette",
|
||||
"command.commandPalette.show": "Show",
|
||||
"command.compare": "Compare models",
|
||||
"command.compare.deploy": "Deploy",
|
||||
"command.compare.refresh": "Refresh",
|
||||
"command.compare.refreshModels": "Refresh models",
|
||||
"command.compare.report": "Report",
|
||||
"command.compare.reportDiff": "Report diff",
|
||||
"command.compare.swap": "Swap",
|
||||
"command.compare.swapSource": "Swap source & target",
|
||||
"command.compareDatabase": "Database compare",
|
||||
"command.copy": "Copy",
|
||||
"command.dataDeploy": "Data deployer",
|
||||
"command.dataDeploy.generateShell": "Generate shell",
|
||||
"command.dataDeploy.generateSql": "Generate SQL",
|
||||
"command.dataDeploy.kill": "Kill deploy",
|
||||
"command.dataDeploy.run": "Deploy into DB",
|
||||
"command.dataForm": "Data form",
|
||||
"command.dataForm.addToFilter": "Add to filter",
|
||||
"command.dataForm.copyToClipboard": "Copy to clipboard",
|
||||
@@ -214,6 +230,9 @@
|
||||
"command.datagrid.stopAutoRefresh": "Stop auto refresh",
|
||||
"command.datagrid.switchToJSON": "Switch to JSON",
|
||||
"command.datagrid.switchToform": "Switch to form",
|
||||
"command.datagrid.toggleCellDataView": "Toggle cell data view",
|
||||
"command.datagrid.toggleCellDataView.menu": "Show cell data",
|
||||
"command.datagrid.toggleCellDataView.toolbar": "Cell Data",
|
||||
"command.datagrid.toggleLeftPanel": "Toggle left panel",
|
||||
"command.datagrid.undo": "Undo",
|
||||
"command.datagrid.viewJsonDocument": "View row as JSON document",
|
||||
@@ -223,6 +242,7 @@
|
||||
"command.designer": "Designer",
|
||||
"command.designer.arrange": "Arrange",
|
||||
"command.designer.exportDiagram": "Export diagram",
|
||||
"command.designer.openSql": "Open SQL",
|
||||
"command.designer.remove": "Remove",
|
||||
"command.designer.removeSelectedTables": "Remove selected tables",
|
||||
"command.diagram": "Diagram",
|
||||
@@ -252,6 +272,7 @@
|
||||
"command.internal": "Internal",
|
||||
"command.internal.loadCampaigns": "Load campaign list",
|
||||
"command.internal.showCampaigns": "Show campaigns",
|
||||
"command.jsonl": "JSON Lines editor",
|
||||
"command.jsonl.closePreview": "Close preview",
|
||||
"command.jsonl.preview": "Preview",
|
||||
"command.jsonl.previewNewTab": "Preview in new tab",
|
||||
@@ -290,6 +311,13 @@
|
||||
"command.new.tableToolbar": "New table",
|
||||
"command.openQuery": "Open query",
|
||||
"command.paste": "Paste",
|
||||
"command.perspective": "Perspective",
|
||||
"command.perspective.openJson": "Open JSON",
|
||||
"command.perspective.refresh": "Refresh",
|
||||
"command.profiler": "Profiler",
|
||||
"command.profiler.save": "Save",
|
||||
"command.profiler.start": "Start profiling",
|
||||
"command.profiler.stop": "Stop profiling",
|
||||
"command.query": "Query",
|
||||
"command.query.AiAssistant": "AI Assistant",
|
||||
"command.query.autocommitOffSwitch": "Auto commit: OFF",
|
||||
@@ -364,6 +392,7 @@
|
||||
"commandPalette.searchInDatabase": "Search in database",
|
||||
"common.Remove": "Remove",
|
||||
"common.addNew": "Add new",
|
||||
"common.addProvider": "Add Provider",
|
||||
"common.advanced": "Advanced",
|
||||
"common.allFields": "All {field}",
|
||||
"common.allFiles": "All files",
|
||||
@@ -391,6 +420,7 @@
|
||||
"common.done": "Done",
|
||||
"common.dontAskAgain": "Don't ask again",
|
||||
"common.download": "Download",
|
||||
"common.edit": "Edit",
|
||||
"common.erDiagram": "ER Diagram",
|
||||
"common.error": "Error",
|
||||
"common.execute": "Execute",
|
||||
@@ -447,6 +477,57 @@
|
||||
"common.testingConnection": "Testing connection",
|
||||
"common.uncheckAll": "Uncheck all",
|
||||
"common.zipFiles": "ZIP files",
|
||||
"compare.action": "Action",
|
||||
"compare.added": "Added",
|
||||
"compare.allowDropColumns": "Allow drop columns",
|
||||
"compare.allowDropSqlObjects": "Allow drop view, procedure, etc.",
|
||||
"compare.allowDropTables": "Allow drop tables",
|
||||
"compare.allowTableRecreate": "Allow recreate table",
|
||||
"compare.autoinc": "Autoinc",
|
||||
"compare.changed": "Changed",
|
||||
"compare.columns": "Columns",
|
||||
"compare.ddl": "DDL",
|
||||
"compare.deletedPrefix": "Deleted prefix",
|
||||
"compare.deployChanges": "Deploy changes",
|
||||
"compare.deployingDatabaseChanges": "Deploying database changes",
|
||||
"compare.dontDropColumns": "Don't drop columns",
|
||||
"compare.dontDropConstraints": "Don't drop constraints",
|
||||
"compare.dontDropSqlObjects": "Don't drop object",
|
||||
"compare.dontDropTables": "Don't drop tables",
|
||||
"compare.dropColumnsIfMissing": "Drop columns if missing",
|
||||
"compare.dropSqlObjectsIfMissing": "Drop object if missing",
|
||||
"compare.dropTablesIfMissing": "Drop tables if missing",
|
||||
"compare.equal": "Equal",
|
||||
"compare.errorWhenSaving": "Error when saving",
|
||||
"compare.hideRowsWithoutOperations": "Hide rows without operations",
|
||||
"compare.ignoreCase": "Ignore case",
|
||||
"compare.ignoreConstraintNames": "Ignore constraint names",
|
||||
"compare.ignoreDataTypes": "Ignore data types",
|
||||
"compare.ignoreForeignKeyActions": "Ignore foreign key actions",
|
||||
"compare.ignoreNameRegex": "Ignore names matching regex",
|
||||
"compare.ignoreSchema": "Ignore schema",
|
||||
"compare.loadingDatabaseStructure": "Loading database structure",
|
||||
"compare.markColumnsAsDeleted": "Mark columns as deleted",
|
||||
"compare.markSqlObjectsAsDeleted": "Mark object as deleted",
|
||||
"compare.markTablesAsDeleted": "Mark tables as deleted",
|
||||
"compare.name": "Name",
|
||||
"compare.notNull": "Not null",
|
||||
"compare.operations": "Operations",
|
||||
"compare.removed": "Removed",
|
||||
"compare.sameSourceAndTargetDatabasesWarning": "The source and target databases are the same, no difference will be found. Please change the source or target database.",
|
||||
"compare.savedToDatabase": "Saved to database",
|
||||
"compare.schema": "Schema",
|
||||
"compare.searchTablesOrObjects": "Search tables or objects",
|
||||
"compare.settings": "Settings",
|
||||
"compare.sourceDatabase": "Source database",
|
||||
"compare.sourceDbModel": "Source DB model",
|
||||
"compare.sourceModelTransform": "Source model transform",
|
||||
"compare.sourceServer": "Source server",
|
||||
"compare.synchronizeScript": "Synchronize script",
|
||||
"compare.targetDatabase": "Target database",
|
||||
"compare.targetSchema": "Target schema",
|
||||
"compare.targetServer": "Target server",
|
||||
"compare.type": "Type",
|
||||
"connection.accessKeyId": "Access Key ID",
|
||||
"connection.allowedDatabases": "Allowed databases, one per line",
|
||||
"connection.allowedDatabasesRegex": "Allowed databases regular expression",
|
||||
@@ -671,6 +752,7 @@
|
||||
"datagrid.searchMacros": "Search macros",
|
||||
"datagrid.setFormat": "Set format: ",
|
||||
"datagrid.structure": "Structure",
|
||||
"datagrid.useMacro": "Use macro",
|
||||
"dbKeyAddItemModal.header": "Add item",
|
||||
"dbKeysTreeNode.deleteBranch": "Delete branch",
|
||||
"dbKeysTreeNode.deleteBranchConfirm": "Really delete branch {branch} with all keys?",
|
||||
@@ -751,6 +833,22 @@
|
||||
"designerTable.newAlias": "New alias",
|
||||
"designerTable.removeTableAlias": "Remove table alias",
|
||||
"designerTable.setTableAlias": "Set table alias",
|
||||
"diagram.all": "All",
|
||||
"diagram.allKeys": "All Keys",
|
||||
"diagram.columnFilter": "Column filter",
|
||||
"diagram.exportWatermark": "Export watermark",
|
||||
"diagram.keysAndNotNull": "Keys And Not Null",
|
||||
"diagram.notNull": "Not Null",
|
||||
"diagram.omitExportWatermark": "Omit export watermark",
|
||||
"diagram.omitTablesFilter": "Omit tables",
|
||||
"diagram.primaryKey": "Primary Key",
|
||||
"diagram.showColumns": "Show columns",
|
||||
"diagram.showDataType": "Show data type",
|
||||
"diagram.showNullability": "Show NULL/NOT NULL",
|
||||
"diagram.tableFilter": "Table filter",
|
||||
"diagram.tables": "Tables",
|
||||
"diagram.topTables": "Only N most important tables",
|
||||
"diagram.zoom": "Zoom",
|
||||
"dictionaryLookupModal.customize": "Customize",
|
||||
"dictionaryLookupModal.description": "Description",
|
||||
"dictionaryLookupModal.header": "Lookup from {pureName}",
|
||||
@@ -1028,6 +1126,16 @@
|
||||
"newObject.sqlGeneratorDisabled": "SQL Generator is not available for current database",
|
||||
"newObject.tableDescription": "Create table in the current database",
|
||||
"newObject.tableDisabled": "Table creation is not available for current database",
|
||||
"perspective.arrange": "Arrange",
|
||||
"perspective.arranged": "(Arranged)",
|
||||
"perspective.category": "Perspective",
|
||||
"perspective.chooseData": "Choose data",
|
||||
"perspective.customJoin": "Custom join",
|
||||
"perspective.filters": "Filters",
|
||||
"perspective.invalidFormat": "Invalid perspective format, please create new perspective",
|
||||
"perspective.noFiltersDefined": "No Filters defined",
|
||||
"perspective.searchColumnOrTable": "Search column or table",
|
||||
"perspective.useContextMenuAddToFilter": "Use context menu, command \"Add to filter\" in table or in tree",
|
||||
"plugins.searchExtensionsOnWeb": "Search extensions on web",
|
||||
"privateCloudWidget.addExistingFolder": "Add existing folder (from link)",
|
||||
"privateCloudWidget.addExistingSharedFolder": "Add existing shared folder",
|
||||
@@ -1052,6 +1160,7 @@
|
||||
"publicCloudWidget.refreshFiles": "Refresh files",
|
||||
"publicCloudWidget.refreshList": "Refresh list",
|
||||
"publicCloudWidget.searchPublicFiles": "Search public files",
|
||||
"query.AiAssistant": "AI Assistant",
|
||||
"query.Copy": "Copy",
|
||||
"query.Download": "Download",
|
||||
"query.Messages": "Messages",
|
||||
@@ -1060,17 +1169,34 @@
|
||||
"query.OutputFiles": "Output files",
|
||||
"query.Show": "Show",
|
||||
"query.Size": "Size",
|
||||
"query.addCustomExpression": "Add custom expression",
|
||||
"query.addGroupOrCondition": "Add group OR condition",
|
||||
"query.addOrCondition": "Add OR condition",
|
||||
"query.aggregate": "Aggregate",
|
||||
"query.alias": "Alias",
|
||||
"query.columnExpression": "Column/Expression",
|
||||
"query.download": "download",
|
||||
"query.filter": "Filter",
|
||||
"query.groupBy": "Group by",
|
||||
"query.groupFilter": "Group filter",
|
||||
"query.limitRows": "Limit {queryRowsLimit} rows",
|
||||
"query.named": ":variable",
|
||||
"query.noParameters": "(no parameters)",
|
||||
"query.noRowsLimit": "(No rows limit)",
|
||||
"query.orFilter": "OR Filter {number}",
|
||||
"query.orGroupFilter": "OR group filter {number}",
|
||||
"query.output": "Output",
|
||||
"query.positional": "? (positional)",
|
||||
"query.queryNumber": "Query #",
|
||||
"query.removeDuplicates": "Remove duplicates: {status}",
|
||||
"query.removeGroupOrCondition": "Remove group OR condition",
|
||||
"query.removeOrCondition": "Remove OR condition",
|
||||
"query.returnOnlyNRows": "Return only N rows from query",
|
||||
"query.rowsLimit": "Rows limit",
|
||||
"query.save": "save",
|
||||
"query.show": "show",
|
||||
"query.sortOrder": "Sort order",
|
||||
"query.table": "Table",
|
||||
"query.unlimitedRows": "Unlimited rows",
|
||||
"query.variable": "#variable",
|
||||
"queryParameters.editQueryParameters": "Edit query parameters",
|
||||
@@ -1102,6 +1228,35 @@
|
||||
"serverSummaryTab.processes": "Processes",
|
||||
"serverSummaryTab.variables": "Variables",
|
||||
"settings.AI": "AI",
|
||||
"settings.aiChatDefaults.heading": "AI Chat Defaults",
|
||||
"settings.aiExecuteMode": "SQL Execution Mode",
|
||||
"settings.aiExecuteMode.ask": "Ask before execute",
|
||||
"settings.aiExecuteMode.auto": "Execute automatically",
|
||||
"settings.aiExecuteMode.never": "Never execute SQL",
|
||||
"settings.aiProvider": "AI Provider",
|
||||
"settings.aiProvider.apiKey": "API Key",
|
||||
"settings.aiProvider.apiKeyPlaceholder": "Your API key (leave empty for local providers)",
|
||||
"settings.aiProvider.baseUrl": "Base URL",
|
||||
"settings.aiProvider.connectionTest.cancel": "Cancel test",
|
||||
"settings.aiProvider.connectionTest.retest": "Retest Connection",
|
||||
"settings.aiProvider.connectionTest.test": "Test Connection",
|
||||
"settings.aiProvider.connectionTestFailed": "Connection test failed:",
|
||||
"settings.aiProvider.defaultModel": "Default Model",
|
||||
"settings.aiProvider.gateway": "DbGate AI Gateway",
|
||||
"settings.aiProvider.name": "Provider Name",
|
||||
"settings.aiProvider.newProviderName": "Provider {number}",
|
||||
"settings.aiProvider.noDefaultModel": "(No default model)",
|
||||
"settings.aiProvider.noModelsAvailable": "(No models available)",
|
||||
"settings.aiProvider.noUrlConfigured": "No URL configured",
|
||||
"settings.aiProvider.removeProviderConfirmation": "Are you sure you want to remove {provider} provider?",
|
||||
"settings.aiProvider.status.connectionFailed": "Connection failed:",
|
||||
"settings.aiProvider.status.error": "Error",
|
||||
"settings.aiProvider.status.noModelsFound": "No models found",
|
||||
"settings.aiProvider.status.notConfigured": "Not configured",
|
||||
"settings.aiProvider.status.testing": "Testing",
|
||||
"settings.aiProvider.status.testingConnection": "Testing connection...",
|
||||
"settings.aiProvider.status.untested": "Untested",
|
||||
"settings.aiProvider.status.valid": "Valid",
|
||||
"settings.appearance": "Appearance",
|
||||
"settings.appearance.afterInstalling": "After installing theme plugin (try search \"theme\" in available extensions) new themes will be available here.",
|
||||
"settings.appearance.customSize": "Custom size",
|
||||
@@ -1126,6 +1281,8 @@
|
||||
"settings.connection.autoRefreshInterval": "Interval between automatic DB structure reloads in seconds",
|
||||
"settings.connection.showOnlyTabsFromSelectedDatabase": "Show only tabs from selected database",
|
||||
"settings.connection.sshBindHost": "Local host address for SSH connections",
|
||||
"settings.customProviders.heading": "Custom Providers",
|
||||
"settings.customProviders.noProvidersConfigured": "No custom providers configured. Click \"Add Provider\" to get started.",
|
||||
"settings.dataGrid.alignNumbersRight": "Align numbers to right",
|
||||
"settings.dataGrid.collectionPageSize": "Collection page size (for MongoDB JSON view, must be between 5 and 1000)",
|
||||
"settings.dataGrid.coloringMode": "Row coloring mode",
|
||||
@@ -1137,7 +1294,13 @@
|
||||
"settings.dataGrid.pageSize": "Page size (number of rows for incremental loading, must be between 5 and 50000)",
|
||||
"settings.dataGrid.showAllColumnsWhenSearch": "Show all columns when searching",
|
||||
"settings.dataGrid.showHintColumns": "Show foreign key hints",
|
||||
"settings.dataGrid.thousandsSeparator": "Use thousands separator for numbers",
|
||||
"settings.dataGrid.thousandsSeparator": "Thousands separator for numbers",
|
||||
"settings.dataGrid.thousandsSeparator.comma": "Comma (,)",
|
||||
"settings.dataGrid.thousandsSeparator.dot": "Dot (.)",
|
||||
"settings.dataGrid.thousandsSeparator.narrowSpace": "Narrow space",
|
||||
"settings.dataGrid.thousandsSeparator.none": "None",
|
||||
"settings.dataGrid.thousandsSeparator.space": "Space",
|
||||
"settings.dataGrid.thousandsSeparator.system": "System",
|
||||
"settings.dataGrid.title": "Data grid",
|
||||
"settings.defaultActions": "Default Actions",
|
||||
"settings.defaultActions.collectionClick": "NoSQL collection click",
|
||||
@@ -1190,6 +1353,9 @@
|
||||
"settings.sqlEditor.showTableAliasesInCodeCompletion": "Show table aliases in code completion",
|
||||
"settings.sqlEditor.sqlCommandsCase": "SQL commands case",
|
||||
"settings.sqlEditor.title": "SQL Editor",
|
||||
"settings.supportedProviders.description": "Any service compatible with the OpenAI API format will work, including:",
|
||||
"settings.supportedProviders.heading": "Supported Providers",
|
||||
"settings.supportedProviders.useThisProvider": "Use this provider",
|
||||
"settings.tabGroup.showServerName": "Show server name alongside database name in title of the tab group",
|
||||
"settings.tabPreviewMode": "Tab Preview Mode",
|
||||
"settings.theme": "Themes",
|
||||
@@ -1258,6 +1424,11 @@
|
||||
"switchDatabase.server": "Server",
|
||||
"switchDatabase.switchDatabase": "Switch database",
|
||||
"tab.administration": "Administration",
|
||||
"tableCell.edit": "Edit",
|
||||
"tableCell.filterColumns": "Filter columns",
|
||||
"tableCell.hideNullValues": "Hide NULL values",
|
||||
"tableCell.multipleValues": "Multiple values",
|
||||
"tableCell.noDataSelected": "No data selected",
|
||||
"tableData.errorWhenSaving": "Error when saving",
|
||||
"tableData.refreshEvery": "Refresh (every {autoRefreshInterval}s)",
|
||||
"tableData.savedToDatabase": "Saved to database",
|
||||
@@ -1336,6 +1507,5 @@
|
||||
"widgets.favoritesAndSavedFiles": "Favorites & Saved files",
|
||||
"widgets.installedExtensions": "Installed extensions",
|
||||
"widgets.premiumPromo": "Premium promo",
|
||||
"widgets.queryHistoryAndClosedTabs": "Query history & Closed tabs",
|
||||
"widgets.selectedCellDataDetailView": "Selected cell data detail view"
|
||||
"widgets.queryHistoryAndClosedTabs": "Query history & Closed tabs"
|
||||
}
|
||||
@@ -137,6 +137,8 @@
|
||||
"command.archiveFile": "Archivo (JSONL)",
|
||||
"command.archiveFile.save": "Guardar",
|
||||
"command.archiveFile.saveAs": "Guardar como",
|
||||
"command.chart": "Gráfico",
|
||||
"command.chart.export": "Exportar gráfico",
|
||||
"command.cloud": "Nube",
|
||||
"command.cloud.logout": "Cerrar sesión",
|
||||
"command.collectionData": "Datos de colección",
|
||||
@@ -145,7 +147,21 @@
|
||||
"command.collectionData.save": "Guardar",
|
||||
"command.commandPalette": "Paleta de comandos",
|
||||
"command.commandPalette.show": "Mostrar",
|
||||
"command.compare": "Comparar modelos",
|
||||
"command.compare.deploy": "Desplegar",
|
||||
"command.compare.refresh": "Refrescar",
|
||||
"command.compare.refreshModels": "Refrescar modelos",
|
||||
"command.compare.report": "Reporte",
|
||||
"command.compare.reportDiff": "Reporte de diferencias",
|
||||
"command.compare.swap": "Intercambiar",
|
||||
"command.compare.swapSource": "Intercambiar origen y destino",
|
||||
"command.compareDatabase": "Comparar bases de datos",
|
||||
"command.copy": "Copiar",
|
||||
"command.dataDeploy": "Desplegador de datos",
|
||||
"command.dataDeploy.generateShell": "Generar shell",
|
||||
"command.dataDeploy.generateSql": "Generar SQL",
|
||||
"command.dataDeploy.kill": "Terminar despliegue",
|
||||
"command.dataDeploy.run": "Desplegar en BD",
|
||||
"command.dataForm": "Formulario de datos",
|
||||
"command.dataForm.addToFilter": "Agregar al filtro",
|
||||
"command.dataForm.copyToClipboard": "Copiar al portapapeles",
|
||||
@@ -218,6 +234,9 @@
|
||||
"command.datagrid.stopAutoRefresh": "Detener recarga automática",
|
||||
"command.datagrid.switchToJSON": "Cambiar a JSON",
|
||||
"command.datagrid.switchToform": "Cambiar a formulario",
|
||||
"command.datagrid.toggleCellDataView": "Alternar vista de datos de celda",
|
||||
"command.datagrid.toggleCellDataView.menu": "Mostrar datos de celda",
|
||||
"command.datagrid.toggleCellDataView.toolbar": "Datos de celda",
|
||||
"command.datagrid.toggleLeftPanel": "Alternar panel izquierdo",
|
||||
"command.datagrid.undo": "Deshacer",
|
||||
"command.datagrid.viewJsonDocument": "Ver fila como documento JSON",
|
||||
@@ -227,6 +246,7 @@
|
||||
"command.designer": "Diseñador",
|
||||
"command.designer.arrange": "Organizar",
|
||||
"command.designer.exportDiagram": "Exportar diagrama",
|
||||
"command.designer.openSql": "Abrir SQL",
|
||||
"command.designer.remove": "Eliminar",
|
||||
"command.designer.removeSelectedTables": "Eliminar tablas seleccionadas",
|
||||
"command.diagram": "Diagrama",
|
||||
@@ -256,6 +276,7 @@
|
||||
"command.internal": "Interno",
|
||||
"command.internal.loadCampaigns": "Cargar lista de campañas",
|
||||
"command.internal.showCampaigns": "Mostrar campañas",
|
||||
"command.jsonl": "Editor de líneas JSON",
|
||||
"command.jsonl.closePreview": "Cerrar vista previa",
|
||||
"command.jsonl.preview": "Vista previa",
|
||||
"command.jsonl.previewNewTab": "Vista previa en nueva pestaña",
|
||||
@@ -294,6 +315,13 @@
|
||||
"command.new.tableToolbar": "Nueva tabla",
|
||||
"command.openQuery": "Abrir consulta",
|
||||
"command.paste": "Pegar",
|
||||
"command.perspective": "Perspectiva",
|
||||
"command.perspective.openJson": "Abrir JSON",
|
||||
"command.perspective.refresh": "Refrescar",
|
||||
"command.profiler": "Perfilador",
|
||||
"command.profiler.save": "Guardar",
|
||||
"command.profiler.start": "Iniciar perfilado",
|
||||
"command.profiler.stop": "Detener perfilado",
|
||||
"command.query": "Consulta",
|
||||
"command.query.AiAssistant": "Asistente de IA",
|
||||
"command.query.autocommitOffSwitch": "Autoconfirmación: DESACTIVADA",
|
||||
@@ -368,6 +396,7 @@
|
||||
"commandPalette.searchInDatabase": "Buscar en base de datos",
|
||||
"common.Remove": "Eliminar",
|
||||
"common.addNew": "Agregar nuevo",
|
||||
"common.addProvider": "Agregar proveedor",
|
||||
"common.advanced": "Avanzado",
|
||||
"common.allFields": "Todos {field}",
|
||||
"common.allFiles": "Todos los archivos",
|
||||
@@ -395,6 +424,7 @@
|
||||
"common.done": "Hecho",
|
||||
"common.dontAskAgain": "No preguntar de nuevo",
|
||||
"common.download": "Descargar",
|
||||
"common.edit": "Editar",
|
||||
"common.erDiagram": "Diagrama ER",
|
||||
"common.error": "Error",
|
||||
"common.execute": "Ejecutar",
|
||||
@@ -451,6 +481,57 @@
|
||||
"common.testingConnection": "Probando conexión",
|
||||
"common.uncheckAll": "Deseleccionar todo",
|
||||
"common.zipFiles": "Archivos ZIP",
|
||||
"compare.action": "Acción",
|
||||
"compare.added": "Agregado",
|
||||
"compare.allowDropColumns": "Permitir eliminar columnas",
|
||||
"compare.allowDropSqlObjects": "Permitir eliminar vista, procedimiento, etc.",
|
||||
"compare.allowDropTables": "Permitir eliminar tablas",
|
||||
"compare.allowTableRecreate": "Permitir recrear tabla",
|
||||
"compare.autoinc": "Autoinc",
|
||||
"compare.changed": "Cambiado",
|
||||
"compare.columns": "Columnas",
|
||||
"compare.ddl": "DDL",
|
||||
"compare.deletedPrefix": "Prefijo eliminado",
|
||||
"compare.deployChanges": "Desplegar cambios",
|
||||
"compare.deployingDatabaseChanges": "Desplegando cambios de base de datos",
|
||||
"compare.dontDropColumns": "No eliminar columnas",
|
||||
"compare.dontDropConstraints": "No eliminar restricciones",
|
||||
"compare.dontDropSqlObjects": "No eliminar objeto",
|
||||
"compare.dontDropTables": "No eliminar tablas",
|
||||
"compare.dropColumnsIfMissing": "Eliminar columnas si faltan",
|
||||
"compare.dropSqlObjectsIfMissing": "Eliminar objeto si falta",
|
||||
"compare.dropTablesIfMissing": "Eliminar tablas si faltan",
|
||||
"compare.equal": "Igual",
|
||||
"compare.errorWhenSaving": "Error al guardar",
|
||||
"compare.hideRowsWithoutOperations": "Ocultar filas sin operaciones",
|
||||
"compare.ignoreCase": "Ignorar mayúsculas/minúsculas",
|
||||
"compare.ignoreConstraintNames": "Ignorar nombres de restricciones",
|
||||
"compare.ignoreDataTypes": "Ignorar tipos de datos",
|
||||
"compare.ignoreForeignKeyActions": "Ignorar acciones de claves foráneas",
|
||||
"compare.ignoreNameRegex": "Ignorar nombres que coincidan con regex",
|
||||
"compare.ignoreSchema": "Ignorar esquema",
|
||||
"compare.loadingDatabaseStructure": "Cargando estructura de base de datos",
|
||||
"compare.markColumnsAsDeleted": "Marcar columnas como eliminadas",
|
||||
"compare.markSqlObjectsAsDeleted": "Marcar objeto como eliminado",
|
||||
"compare.markTablesAsDeleted": "Marcar tablas como eliminadas",
|
||||
"compare.name": "Nombre",
|
||||
"compare.notNull": "Not null",
|
||||
"compare.operations": "Operaciones",
|
||||
"compare.removed": "Eliminado",
|
||||
"compare.sameSourceAndTargetDatabasesWarning": "Las bases de datos de origen y destino son las mismas, no se encontrarán diferencias. Cambie la base de datos de origen o destino.",
|
||||
"compare.savedToDatabase": "Guardado en base de datos",
|
||||
"compare.schema": "Esquema",
|
||||
"compare.searchTablesOrObjects": "Buscar tablas u objetos",
|
||||
"compare.settings": "Configuración",
|
||||
"compare.sourceDatabase": "Base de datos de origen",
|
||||
"compare.sourceDbModel": "Modelo de BD de origen",
|
||||
"compare.sourceModelTransform": "Transformación de modelo de origen",
|
||||
"compare.sourceServer": "Servidor de origen",
|
||||
"compare.synchronizeScript": "Sincronizar script",
|
||||
"compare.targetDatabase": "Base de datos de destino",
|
||||
"compare.targetSchema": "Esquema de destino",
|
||||
"compare.targetServer": "Servidor de destino",
|
||||
"compare.type": "Tipo",
|
||||
"connection.accessKeyId": "ID de clave de acceso",
|
||||
"connection.allowedDatabases": "Bases de datos permitidas, una por línea",
|
||||
"connection.allowedDatabasesRegex": "Expresión regular de bases de datos permitidas",
|
||||
@@ -675,6 +756,7 @@
|
||||
"datagrid.searchMacros": "Buscar macros",
|
||||
"datagrid.setFormat": "Establecer formato: ",
|
||||
"datagrid.structure": "Estructura",
|
||||
"datagrid.useMacro": "Usar macro",
|
||||
"dbKeyAddItemModal.header": "Agregar elemento",
|
||||
"dbKeysTreeNode.deleteBranch": "Eliminar rama",
|
||||
"dbKeysTreeNode.deleteBranchConfirm": "¿Realmente eliminar la rama {branch} con todas las claves?",
|
||||
@@ -755,6 +837,22 @@
|
||||
"designerTable.newAlias": "Nuevo alias",
|
||||
"designerTable.removeTableAlias": "Eliminar alias de tabla",
|
||||
"designerTable.setTableAlias": "Establecer alias de tabla",
|
||||
"diagram.all": "Todo",
|
||||
"diagram.allKeys": "Todas las claves",
|
||||
"diagram.columnFilter": "Filtro de columnas",
|
||||
"diagram.exportWatermark": "Marca de agua de exportación",
|
||||
"diagram.keysAndNotNull": "Claves y Not Null",
|
||||
"diagram.notNull": "Not Null",
|
||||
"diagram.omitExportWatermark": "Omitir marca de agua de exportación",
|
||||
"diagram.omitTablesFilter": "Omitir tablas",
|
||||
"diagram.primaryKey": "Clave primaria",
|
||||
"diagram.showColumns": "Mostrar columnas",
|
||||
"diagram.showDataType": "Mostrar tipo de dato",
|
||||
"diagram.showNullability": "Mostrar NULL/NOT NULL",
|
||||
"diagram.tableFilter": "Filtro de tablas",
|
||||
"diagram.tables": "Tablas",
|
||||
"diagram.topTables": "Solo N tablas más importantes",
|
||||
"diagram.zoom": "Zoom",
|
||||
"dictionaryLookupModal.customize": "Personalizar",
|
||||
"dictionaryLookupModal.description": "Descripción",
|
||||
"dictionaryLookupModal.header": "Búsqueda desde {pureName}",
|
||||
@@ -1032,6 +1130,16 @@
|
||||
"newObject.sqlGeneratorDisabled": "El generador SQL no está disponible para la base de datos actual",
|
||||
"newObject.tableDescription": "Crear tabla en la base de datos actual",
|
||||
"newObject.tableDisabled": "La creación de tablas no está disponible para la base de datos actual",
|
||||
"perspective.arrange": "Organizar",
|
||||
"perspective.arranged": "(Organizado)",
|
||||
"perspective.category": "Perspectiva",
|
||||
"perspective.chooseData": "Elegir datos",
|
||||
"perspective.customJoin": "Join personalizado",
|
||||
"perspective.filters": "Filtros",
|
||||
"perspective.invalidFormat": "Formato de perspectiva inválido, por favor cree una nueva perspectiva",
|
||||
"perspective.noFiltersDefined": "No hay filtros definidos",
|
||||
"perspective.searchColumnOrTable": "Buscar columna o tabla",
|
||||
"perspective.useContextMenuAddToFilter": "Use el menú contextual, comando \"Agregar al filtro\" en la tabla o en el árbol",
|
||||
"plugins.searchExtensionsOnWeb": "Buscar extensiones en la web",
|
||||
"privateCloudWidget.addExistingFolder": "Agregar carpeta existente (desde enlace)",
|
||||
"privateCloudWidget.addExistingSharedFolder": "Agregar carpeta compartida existente",
|
||||
@@ -1056,6 +1164,7 @@
|
||||
"publicCloudWidget.refreshFiles": "Refrescar archivos",
|
||||
"publicCloudWidget.refreshList": "Refrescar lista",
|
||||
"publicCloudWidget.searchPublicFiles": "Buscar archivos públicos",
|
||||
"query.AiAssistant": "Asistente de IA",
|
||||
"query.Copy": "Copiar",
|
||||
"query.Download": "Descargar",
|
||||
"query.Messages": "Mensajes",
|
||||
@@ -1064,17 +1173,34 @@
|
||||
"query.OutputFiles": "Archivos de salida",
|
||||
"query.Show": "Mostrar",
|
||||
"query.Size": "Tamaño",
|
||||
"query.addCustomExpression": "Agregar expresión personalizada",
|
||||
"query.addGroupOrCondition": "Agregar grupo O condición",
|
||||
"query.addOrCondition": "Agregar condición OR",
|
||||
"query.aggregate": "Agregar",
|
||||
"query.alias": "Alias",
|
||||
"query.columnExpression": "Columna/Expresión",
|
||||
"query.download": "descargar",
|
||||
"query.filter": "Filtro",
|
||||
"query.groupBy": "Agrupar por",
|
||||
"query.groupFilter": "Filtro de grupo",
|
||||
"query.limitRows": "Limitar {queryRowsLimit} filas",
|
||||
"query.named": ":variable",
|
||||
"query.noParameters": "(sin parámetros)",
|
||||
"query.noRowsLimit": "(Sin límite de filas)",
|
||||
"query.orFilter": "Filtro OR {number}",
|
||||
"query.orGroupFilter": "Filtro de grupo OR {number}",
|
||||
"query.output": "Salida",
|
||||
"query.positional": "? (posicional)",
|
||||
"query.queryNumber": "Consulta #",
|
||||
"query.removeDuplicates": "Eliminar duplicados: {status}",
|
||||
"query.removeGroupOrCondition": "Eliminar grupo O condición",
|
||||
"query.removeOrCondition": "Eliminar condición OR",
|
||||
"query.returnOnlyNRows": "Devolver solo N filas de la consulta",
|
||||
"query.rowsLimit": "Límite de filas",
|
||||
"query.save": "guardar",
|
||||
"query.show": "mostrar",
|
||||
"query.sortOrder": "Orden de clasificación",
|
||||
"query.table": "Tabla",
|
||||
"query.unlimitedRows": "Filas ilimitadas",
|
||||
"query.variable": "#variable",
|
||||
"queryParameters.editQueryParameters": "Editar parámetros de consulta",
|
||||
@@ -1106,6 +1232,35 @@
|
||||
"serverSummaryTab.processes": "Procesos",
|
||||
"serverSummaryTab.variables": "Variables",
|
||||
"settings.AI": "IA",
|
||||
"settings.aiChatDefaults.heading": "Valores predeterminados de chat de IA",
|
||||
"settings.aiExecuteMode": "Modo de ejecución SQL",
|
||||
"settings.aiExecuteMode.ask": "Preguntar antes de ejecutar",
|
||||
"settings.aiExecuteMode.auto": "Ejecutar automáticamente",
|
||||
"settings.aiExecuteMode.never": "Nunca ejecutar SQL",
|
||||
"settings.aiProvider": "Proveedor de IA",
|
||||
"settings.aiProvider.apiKey": "Clave API",
|
||||
"settings.aiProvider.apiKeyPlaceholder": "Su clave API (dejar vacío para proveedores locales)",
|
||||
"settings.aiProvider.baseUrl": "URL base",
|
||||
"settings.aiProvider.connectionTest.cancel": "Cancelar prueba",
|
||||
"settings.aiProvider.connectionTest.retest": "Probar conexión de nuevo",
|
||||
"settings.aiProvider.connectionTest.test": "Probar conexión",
|
||||
"settings.aiProvider.connectionTestFailed": "Prueba de conexión fallida:",
|
||||
"settings.aiProvider.defaultModel": "Modelo predeterminado",
|
||||
"settings.aiProvider.gateway": "DbGate AI Gateway",
|
||||
"settings.aiProvider.name": "Nombre del proveedor",
|
||||
"settings.aiProvider.newProviderName": "Proveedor {number}",
|
||||
"settings.aiProvider.noDefaultModel": "(Sin modelo predeterminado)",
|
||||
"settings.aiProvider.noModelsAvailable": "(No hay modelos disponibles)",
|
||||
"settings.aiProvider.noUrlConfigured": "No hay URL configurada",
|
||||
"settings.aiProvider.removeProviderConfirmation": "¿Está seguro de que desea eliminar el proveedor {provider}?",
|
||||
"settings.aiProvider.status.connectionFailed": "Conexión fallida:",
|
||||
"settings.aiProvider.status.error": "Error",
|
||||
"settings.aiProvider.status.noModelsFound": "No se encontraron modelos",
|
||||
"settings.aiProvider.status.notConfigured": "No configurado",
|
||||
"settings.aiProvider.status.testing": "Probando",
|
||||
"settings.aiProvider.status.testingConnection": "Probando conexión...",
|
||||
"settings.aiProvider.status.untested": "No probado",
|
||||
"settings.aiProvider.status.valid": "Válido",
|
||||
"settings.appearance": "Tema de aplicación",
|
||||
"settings.appearance.afterInstalling": "Después de instalar el plugin de tema (intente buscar \"theme\" en las extensiones disponibles) nuevos temas estarán disponibles aquí.",
|
||||
"settings.appearance.customSize": "Tamaño personalizado",
|
||||
@@ -1130,6 +1285,8 @@
|
||||
"settings.connection.autoRefreshInterval": "Intervalo entre recargas automáticas de estructura de BD en segundos",
|
||||
"settings.connection.showOnlyTabsFromSelectedDatabase": "Mostrar solo pestañas de la base de datos seleccionada",
|
||||
"settings.connection.sshBindHost": "Dirección de host local para conexiones SSH",
|
||||
"settings.customProviders.heading": "Proveedores personalizados",
|
||||
"settings.customProviders.noProvidersConfigured": "No hay proveedores personalizados configurados. Haga clic en \"Agregar proveedor\" para comenzar.",
|
||||
"settings.dataGrid.alignNumbersRight": "Alinear números a la derecha",
|
||||
"settings.dataGrid.collectionPageSize": "Tamaño de página de colección (para vista JSON de MongoDB, debe estar entre 5 y 1000)",
|
||||
"settings.dataGrid.coloringMode": "Modo de coloreo de filas",
|
||||
@@ -1142,6 +1299,12 @@
|
||||
"settings.dataGrid.showAllColumnsWhenSearch": "Mostrar todas las columnas al buscar",
|
||||
"settings.dataGrid.showHintColumns": "Mostrar sugerencias de claves foráneas",
|
||||
"settings.dataGrid.thousandsSeparator": "Usar separador de miles para números",
|
||||
"settings.dataGrid.thousandsSeparator.comma": "Coma (,)",
|
||||
"settings.dataGrid.thousandsSeparator.dot": "Punto (.)",
|
||||
"settings.dataGrid.thousandsSeparator.narrowSpace": "Espacio estrecho",
|
||||
"settings.dataGrid.thousandsSeparator.none": "Ninguno",
|
||||
"settings.dataGrid.thousandsSeparator.space": "Espacio",
|
||||
"settings.dataGrid.thousandsSeparator.system": "Sistema",
|
||||
"settings.dataGrid.title": "Cuadrícula de datos",
|
||||
"settings.defaultActions": "Acciones predeterminadas",
|
||||
"settings.defaultActions.collectionClick": "Clic en colección NoSQL",
|
||||
@@ -1198,6 +1361,9 @@
|
||||
"settings.sqlEditor.showTableAliasesInCodeCompletion": "Mostrar alias de tablas en completado de código",
|
||||
"settings.sqlEditor.sqlCommandsCase": "Mayúsculas/minúsculas de comandos SQL",
|
||||
"settings.sqlEditor.title": "Editor SQL",
|
||||
"settings.supportedProviders.description": "Cualquier servicio compatible con el formato de API de OpenAI funcionará, incluyendo:",
|
||||
"settings.supportedProviders.heading": "Proveedores soportados",
|
||||
"settings.supportedProviders.useThisProvider": "Usar este proveedor",
|
||||
"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",
|
||||
@@ -1267,6 +1433,11 @@
|
||||
"switchDatabase.server": "Servidor",
|
||||
"switchDatabase.switchDatabase": "Cambiar base de datos",
|
||||
"tab.administration": "Administración",
|
||||
"tableCell.edit": "Editar",
|
||||
"tableCell.filterColumns": "Filtrar columnas",
|
||||
"tableCell.hideNullValues": "Ocultar valores NULL",
|
||||
"tableCell.multipleValues": "Múltiples valores",
|
||||
"tableCell.noDataSelected": "No hay datos seleccionados",
|
||||
"tableData.errorWhenSaving": "Error al guardar",
|
||||
"tableData.refreshEvery": "Refrescar (cada {autoRefreshInterval}s)",
|
||||
"tableData.savedToDatabase": "Guardado en base de datos",
|
||||
|
||||
@@ -137,6 +137,8 @@
|
||||
"command.archiveFile": "Fichier d'archive",
|
||||
"command.archiveFile.save": "Enregistrer",
|
||||
"command.archiveFile.saveAs": "Enregistrer sous",
|
||||
"command.chart": "Graphique",
|
||||
"command.chart.export": "Exporter le graphique",
|
||||
"command.cloud": "Cloud",
|
||||
"command.cloud.logout": "Déconnexion",
|
||||
"command.collectionData": "Données de collection",
|
||||
@@ -145,7 +147,21 @@
|
||||
"command.collectionData.save": "Enregistrer",
|
||||
"command.commandPalette": "Palette de commandes",
|
||||
"command.commandPalette.show": "Afficher",
|
||||
"command.compare": "Comparer les modèles",
|
||||
"command.compare.deploy": "Déployer",
|
||||
"command.compare.refresh": "Rafraîchir",
|
||||
"command.compare.refreshModels": "Rafraîchir les modèles",
|
||||
"command.compare.report": "Rapport",
|
||||
"command.compare.reportDiff": "Rapport des différences",
|
||||
"command.compare.swap": "Inverser",
|
||||
"command.compare.swapSource": "Inverser source et cible",
|
||||
"command.compareDatabase": "Comparer les bases de données",
|
||||
"command.copy": "Copier",
|
||||
"command.dataDeploy": "Déployeur de données",
|
||||
"command.dataDeploy.generateShell": "Générer le shell",
|
||||
"command.dataDeploy.generateSql": "Générer du SQL",
|
||||
"command.dataDeploy.kill": "Arrêter le déploiement",
|
||||
"command.dataDeploy.run": "Déployer dans la BD",
|
||||
"command.dataForm": "Formulaire de données",
|
||||
"command.dataForm.addToFilter": "Ajouter au filtre",
|
||||
"command.dataForm.copyToClipboard": "Copier dans le presse-papiers",
|
||||
@@ -218,6 +234,9 @@
|
||||
"command.datagrid.stopAutoRefresh": "Arrêter le rafraîchissement automatique",
|
||||
"command.datagrid.switchToJSON": "Basculer vers JSON",
|
||||
"command.datagrid.switchToform": "Basculer vers formulaire",
|
||||
"command.datagrid.toggleCellDataView": "Basculer la vue des données de cellule",
|
||||
"command.datagrid.toggleCellDataView.menu": "Afficher les données de cellule",
|
||||
"command.datagrid.toggleCellDataView.toolbar": "Données de cellule",
|
||||
"command.datagrid.toggleLeftPanel": "Basculer le panneau gauche",
|
||||
"command.datagrid.undo": "Annuler",
|
||||
"command.datagrid.viewJsonDocument": "Afficher la ligne en tant que document JSON",
|
||||
@@ -227,6 +246,7 @@
|
||||
"command.designer": "Concepteur",
|
||||
"command.designer.arrange": "Organiser",
|
||||
"command.designer.exportDiagram": "Exporter le diagramme",
|
||||
"command.designer.openSql": "Ouvrir SQL",
|
||||
"command.designer.remove": "Supprimer",
|
||||
"command.designer.removeSelectedTables": "Supprimer les tables sélectionnées",
|
||||
"command.diagram": "Diagramme",
|
||||
@@ -256,6 +276,7 @@
|
||||
"command.internal": "Interne",
|
||||
"command.internal.loadCampaigns": "Charger la liste des campagnes",
|
||||
"command.internal.showCampaigns": "Afficher les campagnes",
|
||||
"command.jsonl": "Éditeur JSON Lines",
|
||||
"command.jsonl.closePreview": "Fermer l'aperçu",
|
||||
"command.jsonl.preview": "Aperçu",
|
||||
"command.jsonl.previewNewTab": "Aperçu dans un nouvel onglet",
|
||||
@@ -294,6 +315,13 @@
|
||||
"command.new.tableToolbar": "Nouvelle table",
|
||||
"command.openQuery": "Ouvrir la requête",
|
||||
"command.paste": "Coller",
|
||||
"command.perspective": "Perspective",
|
||||
"command.perspective.openJson": "Ouvrir JSON",
|
||||
"command.perspective.refresh": "Rafraîchir",
|
||||
"command.profiler": "Profileur",
|
||||
"command.profiler.save": "Enregistrer",
|
||||
"command.profiler.start": "Démarrer le profilage",
|
||||
"command.profiler.stop": "Arrêter le profilage",
|
||||
"command.query": "Requête",
|
||||
"command.query.AiAssistant": "Assistant IA",
|
||||
"command.query.autocommitOffSwitch": "Validation automatique : OFF",
|
||||
@@ -368,6 +396,7 @@
|
||||
"commandPalette.searchInDatabase": "Rechercher dans la base de données",
|
||||
"common.Remove": "Supprimer",
|
||||
"common.addNew": "Ajouter un nouvel élément",
|
||||
"common.addProvider": "Ajouter un fournisseur",
|
||||
"common.advanced": "Avancé",
|
||||
"common.allFields": "Tous les {field}",
|
||||
"common.allFiles": "Tous les fichiers",
|
||||
@@ -395,6 +424,7 @@
|
||||
"common.done": "Terminé",
|
||||
"common.dontAskAgain": "Ne plus demander",
|
||||
"common.download": "Télécharger",
|
||||
"common.edit": "Modifier",
|
||||
"common.erDiagram": "Diagramme ER",
|
||||
"common.error": "Erreur",
|
||||
"common.execute": "Exécuter",
|
||||
@@ -451,6 +481,57 @@
|
||||
"common.testingConnection": "Test de connexion",
|
||||
"common.uncheckAll": "Tout décocher",
|
||||
"common.zipFiles": "Fichiers ZIP",
|
||||
"compare.action": "Action",
|
||||
"compare.added": "Ajouté",
|
||||
"compare.allowDropColumns": "Autoriser la suppression de colonnes",
|
||||
"compare.allowDropSqlObjects": "Autoriser la suppression de vues, procédures, etc.",
|
||||
"compare.allowDropTables": "Autoriser la suppression de tables",
|
||||
"compare.allowTableRecreate": "Autoriser la recréation de table",
|
||||
"compare.autoinc": "Auto-incrément",
|
||||
"compare.changed": "Modifié",
|
||||
"compare.columns": "Colonnes",
|
||||
"compare.ddl": "DDL",
|
||||
"compare.deletedPrefix": "Préfixe supprimé",
|
||||
"compare.deployChanges": "Déployer les modifications",
|
||||
"compare.deployingDatabaseChanges": "Déploiement des modifications de base de données",
|
||||
"compare.dontDropColumns": "Ne pas supprimer les colonnes",
|
||||
"compare.dontDropConstraints": "Ne pas supprimer les contraintes",
|
||||
"compare.dontDropSqlObjects": "Ne pas supprimer l'objet",
|
||||
"compare.dontDropTables": "Ne pas supprimer les tables",
|
||||
"compare.dropColumnsIfMissing": "Supprimer les colonnes manquantes",
|
||||
"compare.dropSqlObjectsIfMissing": "Supprimer l'objet manquant",
|
||||
"compare.dropTablesIfMissing": "Supprimer les tables manquantes",
|
||||
"compare.equal": "Égal",
|
||||
"compare.errorWhenSaving": "Erreur lors de l'enregistrement",
|
||||
"compare.hideRowsWithoutOperations": "Masquer les lignes sans opérations",
|
||||
"compare.ignoreCase": "Ignorer la casse",
|
||||
"compare.ignoreConstraintNames": "Ignorer les noms de contraintes",
|
||||
"compare.ignoreDataTypes": "Ignorer les types de données",
|
||||
"compare.ignoreForeignKeyActions": "Ignorer les actions de clé étrangère",
|
||||
"compare.ignoreNameRegex": "Ignorer les noms correspondant à la regex",
|
||||
"compare.ignoreSchema": "Ignorer le schéma",
|
||||
"compare.loadingDatabaseStructure": "Chargement de la structure de la base de données",
|
||||
"compare.markColumnsAsDeleted": "Marquer les colonnes comme supprimées",
|
||||
"compare.markSqlObjectsAsDeleted": "Marquer l'objet comme supprimé",
|
||||
"compare.markTablesAsDeleted": "Marquer les tables comme supprimées",
|
||||
"compare.name": "Nom",
|
||||
"compare.notNull": "NOT NULL",
|
||||
"compare.operations": "Opérations",
|
||||
"compare.removed": "Supprimé",
|
||||
"compare.sameSourceAndTargetDatabasesWarning": "Les bases de données source et cible sont identiques, aucune différence ne sera trouvée. Veuillez changer la base de données source ou cible.",
|
||||
"compare.savedToDatabase": "Enregistré dans la base de données",
|
||||
"compare.schema": "Schéma",
|
||||
"compare.searchTablesOrObjects": "Rechercher des tables ou des objets",
|
||||
"compare.settings": "Paramètres",
|
||||
"compare.sourceDatabase": "Base de données source",
|
||||
"compare.sourceDbModel": "Modèle de BD source",
|
||||
"compare.sourceModelTransform": "Transformation de modèle source",
|
||||
"compare.sourceServer": "Serveur source",
|
||||
"compare.synchronizeScript": "Script de synchronisation",
|
||||
"compare.targetDatabase": "Base de données cible",
|
||||
"compare.targetSchema": "Schéma cible",
|
||||
"compare.targetServer": "Serveur cible",
|
||||
"compare.type": "Type",
|
||||
"connection.accessKeyId": "ID de clé d'accès",
|
||||
"connection.allowedDatabases": "Bases de données autorisées, une par ligne",
|
||||
"connection.allowedDatabasesRegex": "Expression régulière des bases de données autorisées",
|
||||
@@ -675,6 +756,7 @@
|
||||
"datagrid.searchMacros": "Rechercher des macros",
|
||||
"datagrid.setFormat": "Définir le format : ",
|
||||
"datagrid.structure": "Structure",
|
||||
"datagrid.useMacro": "Utiliser la macro",
|
||||
"dbKeyAddItemModal.header": "Ajouter un élément",
|
||||
"dbKeysTreeNode.deleteBranch": "Supprimer la branche",
|
||||
"dbKeysTreeNode.deleteBranchConfirm": "Vraiment supprimer la branche {branch} avec toutes les clés ?",
|
||||
@@ -755,6 +837,22 @@
|
||||
"designerTable.newAlias": "Nouvel alias",
|
||||
"designerTable.removeTableAlias": "Supprimer l'alias de table",
|
||||
"designerTable.setTableAlias": "Définir l'alias de table",
|
||||
"diagram.all": "Tout",
|
||||
"diagram.allKeys": "Toutes les clés",
|
||||
"diagram.columnFilter": "Filtre de colonnes",
|
||||
"diagram.exportWatermark": "Filigrane d'export",
|
||||
"diagram.keysAndNotNull": "Clés et NOT NULL",
|
||||
"diagram.notNull": "NOT NULL",
|
||||
"diagram.omitExportWatermark": "Omettre le filigrane d'export",
|
||||
"diagram.omitTablesFilter": "Omettre des tables",
|
||||
"diagram.primaryKey": "Clé primaire",
|
||||
"diagram.showColumns": "Afficher les colonnes",
|
||||
"diagram.showDataType": "Afficher le type de données",
|
||||
"diagram.showNullability": "Afficher NULL/NOT NULL",
|
||||
"diagram.tableFilter": "Filtre de tables",
|
||||
"diagram.tables": "Tables",
|
||||
"diagram.topTables": "Uniquement les N tables les plus importantes",
|
||||
"diagram.zoom": "Zoom",
|
||||
"dictionaryLookupModal.customize": "Personnaliser",
|
||||
"dictionaryLookupModal.description": "Description",
|
||||
"dictionaryLookupModal.header": "Recherche depuis {pureName}",
|
||||
@@ -1032,6 +1130,16 @@
|
||||
"newObject.sqlGeneratorDisabled": "Le générateur SQL n'est pas disponible pour la base de données actuelle",
|
||||
"newObject.tableDescription": "Créer une table dans la base de données actuelle",
|
||||
"newObject.tableDisabled": "La création de table n'est pas disponible pour la base de données actuelle",
|
||||
"perspective.arrange": "Organiser",
|
||||
"perspective.arranged": "(Organisé)",
|
||||
"perspective.category": "Perspective",
|
||||
"perspective.chooseData": "Choisir les données",
|
||||
"perspective.customJoin": "Jointure personnalisée",
|
||||
"perspective.filters": "Filtres",
|
||||
"perspective.invalidFormat": "Format de perspective non valide, veuillez créer une nouvelle perspective",
|
||||
"perspective.noFiltersDefined": "Aucun filtre défini",
|
||||
"perspective.searchColumnOrTable": "Rechercher une colonne ou une table",
|
||||
"perspective.useContextMenuAddToFilter": "Utilisez le menu contextuel, commande \"Ajouter au filtre\" dans la table ou dans l'arborescence",
|
||||
"plugins.searchExtensionsOnWeb": "Rechercher des extensions sur le web",
|
||||
"privateCloudWidget.addExistingFolder": "Ajouter un dossier existant (depuis un lien)",
|
||||
"privateCloudWidget.addExistingSharedFolder": "Ajouter un dossier partagé existant",
|
||||
@@ -1056,6 +1164,7 @@
|
||||
"publicCloudWidget.refreshFiles": "Rafraîchir les fichiers",
|
||||
"publicCloudWidget.refreshList": "Rafraîchir la liste",
|
||||
"publicCloudWidget.searchPublicFiles": "Rechercher des fichiers publics",
|
||||
"query.AiAssistant": "Assistant IA",
|
||||
"query.Copy": "Copier",
|
||||
"query.Download": "Télécharger",
|
||||
"query.Messages": "Messages",
|
||||
@@ -1064,17 +1173,34 @@
|
||||
"query.OutputFiles": "Fichiers de sortie",
|
||||
"query.Show": "Afficher",
|
||||
"query.Size": "Taille",
|
||||
"query.addCustomExpression": "Ajouter une expression personnalisée",
|
||||
"query.addGroupOrCondition": "Ajouter un groupe OU condition",
|
||||
"query.addOrCondition": "Ajouter une condition OU",
|
||||
"query.aggregate": "Agrégat",
|
||||
"query.alias": "Alias",
|
||||
"query.columnExpression": "Colonne/Expression",
|
||||
"query.download": "télécharger",
|
||||
"query.filter": "Filtre",
|
||||
"query.groupBy": "Grouper par",
|
||||
"query.groupFilter": "Filtre de groupe",
|
||||
"query.limitRows": "Limiter à {queryRowsLimit} lignes",
|
||||
"query.named": ":variable",
|
||||
"query.noParameters": "(aucun paramètre)",
|
||||
"query.noRowsLimit": "(Aucune limite de lignes)",
|
||||
"query.orFilter": "Filtre OU {number}",
|
||||
"query.orGroupFilter": "Filtre de groupe OU {number}",
|
||||
"query.output": "Sortie",
|
||||
"query.positional": "? (positionnel)",
|
||||
"query.queryNumber": "Requête #",
|
||||
"query.removeDuplicates": "Supprimer les doublons : {status}",
|
||||
"query.removeGroupOrCondition": "Supprimer le groupe OU condition",
|
||||
"query.removeOrCondition": "Supprimer la condition OU",
|
||||
"query.returnOnlyNRows": "Retourner uniquement N lignes de la requête",
|
||||
"query.rowsLimit": "Limite de lignes",
|
||||
"query.save": "enregistrer",
|
||||
"query.show": "afficher",
|
||||
"query.sortOrder": "Ordre de tri",
|
||||
"query.table": "Table",
|
||||
"query.unlimitedRows": "Lignes illimitées",
|
||||
"query.variable": "#variable",
|
||||
"queryParameters.editQueryParameters": "Modifier les paramètres de requête",
|
||||
@@ -1106,6 +1232,35 @@
|
||||
"serverSummaryTab.processes": "Processus",
|
||||
"serverSummaryTab.variables": "Variables",
|
||||
"settings.AI": "IA",
|
||||
"settings.aiChatDefaults.heading": "Paramètres par défaut du chat IA",
|
||||
"settings.aiExecuteMode": "Mode d'exécution SQL",
|
||||
"settings.aiExecuteMode.ask": "Demander avant d'exécuter",
|
||||
"settings.aiExecuteMode.auto": "Exécuter automatiquement",
|
||||
"settings.aiExecuteMode.never": "Ne jamais exécuter le SQL",
|
||||
"settings.aiProvider": "Fournisseur IA",
|
||||
"settings.aiProvider.apiKey": "Clé API",
|
||||
"settings.aiProvider.apiKeyPlaceholder": "Votre clé API (laisser vide pour les fournisseurs locaux)",
|
||||
"settings.aiProvider.baseUrl": "URL de base",
|
||||
"settings.aiProvider.connectionTest.cancel": "Annuler le test",
|
||||
"settings.aiProvider.connectionTest.retest": "Retester la connexion",
|
||||
"settings.aiProvider.connectionTest.test": "Tester la connexion",
|
||||
"settings.aiProvider.connectionTestFailed": "Échec du test de connexion :",
|
||||
"settings.aiProvider.defaultModel": "Modèle par défaut",
|
||||
"settings.aiProvider.gateway": "Passerelle IA DbGate",
|
||||
"settings.aiProvider.name": "Nom du fournisseur",
|
||||
"settings.aiProvider.newProviderName": "Fournisseur {number}",
|
||||
"settings.aiProvider.noDefaultModel": "(Aucun modèle par défaut)",
|
||||
"settings.aiProvider.noModelsAvailable": "(Aucun modèle disponible)",
|
||||
"settings.aiProvider.noUrlConfigured": "Aucune URL configurée",
|
||||
"settings.aiProvider.removeProviderConfirmation": "Êtes-vous sûr de vouloir supprimer le fournisseur {provider} ?",
|
||||
"settings.aiProvider.status.connectionFailed": "Échec de la connexion :",
|
||||
"settings.aiProvider.status.error": "Erreur",
|
||||
"settings.aiProvider.status.noModelsFound": "Aucun modèle trouvé",
|
||||
"settings.aiProvider.status.notConfigured": "Non configuré",
|
||||
"settings.aiProvider.status.testing": "Test en cours",
|
||||
"settings.aiProvider.status.testingConnection": "Test de connexion...",
|
||||
"settings.aiProvider.status.untested": "Non testé",
|
||||
"settings.aiProvider.status.valid": "Valide",
|
||||
"settings.appearance": "Thème de l'application",
|
||||
"settings.appearance.afterInstalling": "Après l'installation du plugin de thème (essayez de rechercher \"theme\" dans les extensions disponibles), de nouveaux thèmes seront disponibles ici.",
|
||||
"settings.appearance.customSize": "Taille personnalisée",
|
||||
@@ -1130,6 +1285,8 @@
|
||||
"settings.connection.autoRefreshInterval": "Intervalle entre les rechargements automatiques de la structure de BD en secondes",
|
||||
"settings.connection.showOnlyTabsFromSelectedDatabase": "Afficher uniquement les onglets de la base de données sélectionnée",
|
||||
"settings.connection.sshBindHost": "Adresse d'hôte locale pour les connexions SSH",
|
||||
"settings.customProviders.heading": "Fournisseurs personnalisés",
|
||||
"settings.customProviders.noProvidersConfigured": "Aucun fournisseur personnalisé configuré. Cliquez sur \"Ajouter un fournisseur\" pour commencer.",
|
||||
"settings.dataGrid.alignNumbersRight": "Aligner les nombres à droite",
|
||||
"settings.dataGrid.collectionPageSize": "Taille de page de collection (pour la vue JSON MongoDB, doit être entre 5 et 1000)",
|
||||
"settings.dataGrid.coloringMode": "Mode de coloration des lignes",
|
||||
@@ -1142,6 +1299,12 @@
|
||||
"settings.dataGrid.showAllColumnsWhenSearch": "Afficher toutes les colonnes lors de la recherche",
|
||||
"settings.dataGrid.showHintColumns": "Afficher les indices de clé étrangère",
|
||||
"settings.dataGrid.thousandsSeparator": "Utiliser le séparateur de milliers pour les nombres",
|
||||
"settings.dataGrid.thousandsSeparator.comma": "Virgule (,)",
|
||||
"settings.dataGrid.thousandsSeparator.dot": "Point (.)",
|
||||
"settings.dataGrid.thousandsSeparator.narrowSpace": "Espace fin",
|
||||
"settings.dataGrid.thousandsSeparator.none": "Aucun",
|
||||
"settings.dataGrid.thousandsSeparator.space": "Espace",
|
||||
"settings.dataGrid.thousandsSeparator.system": "Système",
|
||||
"settings.dataGrid.title": "Grille de données",
|
||||
"settings.defaultActions": "Actions par défaut",
|
||||
"settings.defaultActions.collectionClick": "Clic sur collection NoSQL",
|
||||
@@ -1198,6 +1361,9 @@
|
||||
"settings.sqlEditor.showTableAliasesInCodeCompletion": "Afficher les alias de table dans la complétion de code",
|
||||
"settings.sqlEditor.sqlCommandsCase": "Casse des commandes SQL",
|
||||
"settings.sqlEditor.title": "Éditeur SQL",
|
||||
"settings.supportedProviders.description": "Tout service compatible avec le format d'API OpenAI fonctionnera, y compris :",
|
||||
"settings.supportedProviders.heading": "Fournisseurs pris en charge",
|
||||
"settings.supportedProviders.useThisProvider": "Utiliser ce fournisseur",
|
||||
"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",
|
||||
@@ -1267,6 +1433,11 @@
|
||||
"switchDatabase.server": "Serveur",
|
||||
"switchDatabase.switchDatabase": "Changer de base de données",
|
||||
"tab.administration": "Administration",
|
||||
"tableCell.edit": "Modifier",
|
||||
"tableCell.filterColumns": "Filtrer les colonnes",
|
||||
"tableCell.hideNullValues": "Masquer les valeurs NULL",
|
||||
"tableCell.multipleValues": "Valeurs multiples",
|
||||
"tableCell.noDataSelected": "Aucune donnée sélectionnée",
|
||||
"tableData.errorWhenSaving": "Erreur lors de l'enregistrement",
|
||||
"tableData.refreshEvery": "Rafraîchir (toutes les {autoRefreshInterval}s)",
|
||||
"tableData.savedToDatabase": "Enregistré dans la base de données",
|
||||
|
||||
@@ -137,6 +137,8 @@
|
||||
"command.archiveFile": "File archivio",
|
||||
"command.archiveFile.save": "Salva",
|
||||
"command.archiveFile.saveAs": "Salva come",
|
||||
"command.chart": "Grafico",
|
||||
"command.chart.export": "Esporta grafico",
|
||||
"command.cloud": "Cloud",
|
||||
"command.cloud.logout": "Disconnetti",
|
||||
"command.collectionData": "Dati collezione",
|
||||
@@ -145,7 +147,21 @@
|
||||
"command.collectionData.save": "Salva",
|
||||
"command.commandPalette": "Palette dei comandi",
|
||||
"command.commandPalette.show": "Mostra",
|
||||
"command.compare": "Confronta modelli",
|
||||
"command.compare.deploy": "Deploy",
|
||||
"command.compare.refresh": "Aggiorna",
|
||||
"command.compare.refreshModels": "Aggiorna modelli",
|
||||
"command.compare.report": "Report",
|
||||
"command.compare.reportDiff": "Report diff",
|
||||
"command.compare.swap": "Scambia",
|
||||
"command.compare.swapSource": "Scambia sorgente e destinazione",
|
||||
"command.compareDatabase": "Confronto database",
|
||||
"command.copy": "Copia",
|
||||
"command.dataDeploy": "Data deployer",
|
||||
"command.dataDeploy.generateShell": "Genera shell",
|
||||
"command.dataDeploy.generateSql": "Genera SQL",
|
||||
"command.dataDeploy.kill": "Termina deploy",
|
||||
"command.dataDeploy.run": "Deploy nel DB",
|
||||
"command.dataForm": "Modulo dati",
|
||||
"command.dataForm.addToFilter": "Aggiungi a filtro",
|
||||
"command.dataForm.copyToClipboard": "Copia negli appunti",
|
||||
@@ -218,6 +234,9 @@
|
||||
"command.datagrid.stopAutoRefresh": "Ferma aggiornamento automatico",
|
||||
"command.datagrid.switchToJSON": "Passa a JSON",
|
||||
"command.datagrid.switchToform": "Passa a modulo",
|
||||
"command.datagrid.toggleCellDataView": "Attiva/Disattiva vista dati cella",
|
||||
"command.datagrid.toggleCellDataView.menu": "Mostra dati cella",
|
||||
"command.datagrid.toggleCellDataView.toolbar": "Dati cella",
|
||||
"command.datagrid.toggleLeftPanel": "Attiva/Disattiva pannello sinistro",
|
||||
"command.datagrid.undo": "Annulla",
|
||||
"command.datagrid.viewJsonDocument": "Visualizza riga come documento JSON",
|
||||
@@ -227,6 +246,7 @@
|
||||
"command.designer": "Designer",
|
||||
"command.designer.arrange": "Disponi",
|
||||
"command.designer.exportDiagram": "Esporta diagramma",
|
||||
"command.designer.openSql": "Apri SQL",
|
||||
"command.designer.remove": "Rimuovi",
|
||||
"command.designer.removeSelectedTables": "Rimuovi tabelle selezionate",
|
||||
"command.diagram": "Diagramma",
|
||||
@@ -256,6 +276,7 @@
|
||||
"command.internal": "Interno",
|
||||
"command.internal.loadCampaigns": "Carica elenco campagne",
|
||||
"command.internal.showCampaigns": "Mostra campagne",
|
||||
"command.jsonl": "Editor JSON Lines",
|
||||
"command.jsonl.closePreview": "Chiudi anteprima",
|
||||
"command.jsonl.preview": "Anteprima",
|
||||
"command.jsonl.previewNewTab": "Anteprima in nuova scheda",
|
||||
@@ -294,6 +315,13 @@
|
||||
"command.new.tableToolbar": "Nuova tabella",
|
||||
"command.openQuery": "Apri query",
|
||||
"command.paste": "Incolla",
|
||||
"command.perspective": "Prospettiva",
|
||||
"command.perspective.openJson": "Apri JSON",
|
||||
"command.perspective.refresh": "Aggiorna",
|
||||
"command.profiler": "Profiler",
|
||||
"command.profiler.save": "Salva",
|
||||
"command.profiler.start": "Avvia profiling",
|
||||
"command.profiler.stop": "Ferma profiling",
|
||||
"command.query": "Query",
|
||||
"command.query.AiAssistant": "Assistente AI",
|
||||
"command.query.autocommitOffSwitch": "Commit automatico: OFF",
|
||||
@@ -368,6 +396,7 @@
|
||||
"commandPalette.searchInDatabase": "Cerca nel database",
|
||||
"common.Remove": "Rimuovi",
|
||||
"common.addNew": "Aggiungi nuovo",
|
||||
"common.addProvider": "Aggiungi provider",
|
||||
"common.advanced": "Avanzate",
|
||||
"common.allFields": "Tutti {field}",
|
||||
"common.allFiles": "Tutti i file",
|
||||
@@ -395,6 +424,7 @@
|
||||
"common.done": "Fatto",
|
||||
"common.dontAskAgain": "Non chiedere di nuovo",
|
||||
"common.download": "Scarica",
|
||||
"common.edit": "Modifica",
|
||||
"common.erDiagram": "Diagramma ER",
|
||||
"common.error": "Errore",
|
||||
"common.execute": "Esegui",
|
||||
@@ -451,6 +481,57 @@
|
||||
"common.testingConnection": "Test connessione",
|
||||
"common.uncheckAll": "Deseleziona tutto",
|
||||
"common.zipFiles": "File ZIP",
|
||||
"compare.action": "Azione",
|
||||
"compare.added": "Aggiunto",
|
||||
"compare.allowDropColumns": "Consenti drop colonne",
|
||||
"compare.allowDropSqlObjects": "Consenti drop vista, procedura, ecc.",
|
||||
"compare.allowDropTables": "Consenti drop tabelle",
|
||||
"compare.allowTableRecreate": "Consenti ricreazione tabella",
|
||||
"compare.autoinc": "Autoinc",
|
||||
"compare.changed": "Modificato",
|
||||
"compare.columns": "Colonne",
|
||||
"compare.ddl": "DDL",
|
||||
"compare.deletedPrefix": "Prefisso eliminato",
|
||||
"compare.deployChanges": "Deploy modifiche",
|
||||
"compare.deployingDatabaseChanges": "Deploy modifiche database",
|
||||
"compare.dontDropColumns": "Non fare drop colonne",
|
||||
"compare.dontDropConstraints": "Non fare drop vincoli",
|
||||
"compare.dontDropSqlObjects": "Non fare drop oggetto",
|
||||
"compare.dontDropTables": "Non fare drop tabelle",
|
||||
"compare.dropColumnsIfMissing": "Drop colonne se mancanti",
|
||||
"compare.dropSqlObjectsIfMissing": "Drop oggetto se mancante",
|
||||
"compare.dropTablesIfMissing": "Drop tabelle se mancanti",
|
||||
"compare.equal": "Uguale",
|
||||
"compare.errorWhenSaving": "Errore durante il salvataggio",
|
||||
"compare.hideRowsWithoutOperations": "Nascondi righe senza operazioni",
|
||||
"compare.ignoreCase": "Ignora maiuscole/minuscole",
|
||||
"compare.ignoreConstraintNames": "Ignora nomi vincoli",
|
||||
"compare.ignoreDataTypes": "Ignora tipi dati",
|
||||
"compare.ignoreForeignKeyActions": "Ignora azioni chiavi esterne",
|
||||
"compare.ignoreNameRegex": "Ignora nomi che corrispondono a regex",
|
||||
"compare.ignoreSchema": "Ignora schema",
|
||||
"compare.loadingDatabaseStructure": "Caricamento struttura database",
|
||||
"compare.markColumnsAsDeleted": "Segna colonne come eliminate",
|
||||
"compare.markSqlObjectsAsDeleted": "Segna oggetto come eliminato",
|
||||
"compare.markTablesAsDeleted": "Segna tabelle come eliminate",
|
||||
"compare.name": "Nome",
|
||||
"compare.notNull": "Not null",
|
||||
"compare.operations": "Operazioni",
|
||||
"compare.removed": "Rimosso",
|
||||
"compare.sameSourceAndTargetDatabasesWarning": "I database sorgente e destinazione sono gli stessi, non verrà trovata alcuna differenza. Cambia il database sorgente o destinazione.",
|
||||
"compare.savedToDatabase": "Salvato nel database",
|
||||
"compare.schema": "Schema",
|
||||
"compare.searchTablesOrObjects": "Cerca tabelle o oggetti",
|
||||
"compare.settings": "Impostazioni",
|
||||
"compare.sourceDatabase": "Database sorgente",
|
||||
"compare.sourceDbModel": "Modello DB sorgente",
|
||||
"compare.sourceModelTransform": "Trasformazione modello sorgente",
|
||||
"compare.sourceServer": "Server sorgente",
|
||||
"compare.synchronizeScript": "Script di sincronizzazione",
|
||||
"compare.targetDatabase": "Database destinazione",
|
||||
"compare.targetSchema": "Schema destinazione",
|
||||
"compare.targetServer": "Server destinazione",
|
||||
"compare.type": "Tipo",
|
||||
"connection.accessKeyId": "Access Key ID",
|
||||
"connection.allowedDatabases": "Database consentiti, uno per riga",
|
||||
"connection.allowedDatabasesRegex": "Espressione regolare database consentiti",
|
||||
@@ -675,6 +756,7 @@
|
||||
"datagrid.searchMacros": "Cerca macro",
|
||||
"datagrid.setFormat": "Imposta formato: ",
|
||||
"datagrid.structure": "Struttura",
|
||||
"datagrid.useMacro": "Usa macro",
|
||||
"dbKeyAddItemModal.header": "Aggiungi elemento",
|
||||
"dbKeysTreeNode.deleteBranch": "Elimina ramo",
|
||||
"dbKeysTreeNode.deleteBranchConfirm": "Eliminare davvero il ramo {branch} con tutte le chiavi?",
|
||||
@@ -755,6 +837,22 @@
|
||||
"designerTable.newAlias": "Nuovo alias",
|
||||
"designerTable.removeTableAlias": "Rimuovi alias tabella",
|
||||
"designerTable.setTableAlias": "Imposta alias tabella",
|
||||
"diagram.all": "Tutto",
|
||||
"diagram.allKeys": "Tutte le chiavi",
|
||||
"diagram.columnFilter": "Filtro colonne",
|
||||
"diagram.exportWatermark": "Esporta watermark",
|
||||
"diagram.keysAndNotNull": "Chiavi e Not Null",
|
||||
"diagram.notNull": "Not Null",
|
||||
"diagram.omitExportWatermark": "Ometti watermark esportazione",
|
||||
"diagram.omitTablesFilter": "Ometti tabelle",
|
||||
"diagram.primaryKey": "Chiave primaria",
|
||||
"diagram.showColumns": "Mostra colonne",
|
||||
"diagram.showDataType": "Mostra tipo dato",
|
||||
"diagram.showNullability": "Mostra NULL/NOT NULL",
|
||||
"diagram.tableFilter": "Filtro tabelle",
|
||||
"diagram.tables": "Tabelle",
|
||||
"diagram.topTables": "Solo N tabelle più importanti",
|
||||
"diagram.zoom": "Zoom",
|
||||
"dictionaryLookupModal.customize": "Personalizza",
|
||||
"dictionaryLookupModal.description": "Descrizione",
|
||||
"dictionaryLookupModal.header": "Lookup da {pureName}",
|
||||
@@ -1032,6 +1130,16 @@
|
||||
"newObject.sqlGeneratorDisabled": "Il generatore SQL non è disponibile per il database corrente",
|
||||
"newObject.tableDescription": "Crea tabella nel database corrente",
|
||||
"newObject.tableDisabled": "La creazione tabella non è disponibile per il database corrente",
|
||||
"perspective.arrange": "Disponi",
|
||||
"perspective.arranged": "(Disposta)",
|
||||
"perspective.category": "Prospettiva",
|
||||
"perspective.chooseData": "Scegli dati",
|
||||
"perspective.customJoin": "Join personalizzata",
|
||||
"perspective.filters": "Filtri",
|
||||
"perspective.invalidFormat": "Formato prospettiva non valido, crea una nuova prospettiva",
|
||||
"perspective.noFiltersDefined": "Nessun filtro definito",
|
||||
"perspective.searchColumnOrTable": "Cerca colonna o tabella",
|
||||
"perspective.useContextMenuAddToFilter": "Usa il menu contestuale, comando \"Aggiungi a filtro\" nella tabella o nell'albero",
|
||||
"plugins.searchExtensionsOnWeb": "Cerca estensioni sul web",
|
||||
"privateCloudWidget.addExistingFolder": "Aggiungi cartella esistente (da link)",
|
||||
"privateCloudWidget.addExistingSharedFolder": "Aggiungi cartella condivisa esistente",
|
||||
@@ -1056,6 +1164,7 @@
|
||||
"publicCloudWidget.refreshFiles": "Aggiorna file",
|
||||
"publicCloudWidget.refreshList": "Aggiorna elenco",
|
||||
"publicCloudWidget.searchPublicFiles": "Cerca file pubblici",
|
||||
"query.AiAssistant": "Assistente AI",
|
||||
"query.Copy": "Copia",
|
||||
"query.Download": "Scarica",
|
||||
"query.Messages": "Messaggi",
|
||||
@@ -1064,17 +1173,34 @@
|
||||
"query.OutputFiles": "File di output",
|
||||
"query.Show": "Mostra",
|
||||
"query.Size": "Dimensione",
|
||||
"query.addCustomExpression": "Aggiungi espressione personalizzata",
|
||||
"query.addGroupOrCondition": "Aggiungi gruppo O condizione",
|
||||
"query.addOrCondition": "Aggiungi condizione OR",
|
||||
"query.aggregate": "Aggrega",
|
||||
"query.alias": "Alias",
|
||||
"query.columnExpression": "Colonna/Espressione",
|
||||
"query.download": "scarica",
|
||||
"query.filter": "Filtro",
|
||||
"query.groupBy": "Raggruppa per",
|
||||
"query.groupFilter": "Filtro gruppo",
|
||||
"query.limitRows": "Limita a {queryRowsLimit} righe",
|
||||
"query.named": ":variabile",
|
||||
"query.noParameters": "(nessun parametro)",
|
||||
"query.noRowsLimit": "(Nessun limite righe)",
|
||||
"query.orFilter": "Filtro OR {number}",
|
||||
"query.orGroupFilter": "Filtro gruppo OR {number}",
|
||||
"query.output": "Output",
|
||||
"query.positional": "? (posizionale)",
|
||||
"query.queryNumber": "Query #",
|
||||
"query.removeDuplicates": "Rimuovi duplicati: {status}",
|
||||
"query.removeGroupOrCondition": "Rimuovi gruppo O condizione",
|
||||
"query.removeOrCondition": "Rimuovi condizione OR",
|
||||
"query.returnOnlyNRows": "Restituisci solo N righe dalla query",
|
||||
"query.rowsLimit": "Limite righe",
|
||||
"query.save": "salva",
|
||||
"query.show": "mostra",
|
||||
"query.sortOrder": "Ordinamento",
|
||||
"query.table": "Tabella",
|
||||
"query.unlimitedRows": "Righe illimitate",
|
||||
"query.variable": "#variabile",
|
||||
"queryParameters.editQueryParameters": "Modifica parametri query",
|
||||
@@ -1106,6 +1232,35 @@
|
||||
"serverSummaryTab.processes": "Processi",
|
||||
"serverSummaryTab.variables": "Variabili",
|
||||
"settings.AI": "AI",
|
||||
"settings.aiChatDefaults.heading": "Impostazioni predefinite chat AI",
|
||||
"settings.aiExecuteMode": "Modalità esecuzione SQL",
|
||||
"settings.aiExecuteMode.ask": "Chiedi prima di eseguire",
|
||||
"settings.aiExecuteMode.auto": "Esegui automaticamente",
|
||||
"settings.aiExecuteMode.never": "Non eseguire mai SQL",
|
||||
"settings.aiProvider": "Provider AI",
|
||||
"settings.aiProvider.apiKey": "API Key",
|
||||
"settings.aiProvider.apiKeyPlaceholder": "La tua API key (lascia vuoto per provider locali)",
|
||||
"settings.aiProvider.baseUrl": "URL base",
|
||||
"settings.aiProvider.connectionTest.cancel": "Annulla test",
|
||||
"settings.aiProvider.connectionTest.retest": "Ritesta connessione",
|
||||
"settings.aiProvider.connectionTest.test": "Test connessione",
|
||||
"settings.aiProvider.connectionTestFailed": "Test connessione fallito:",
|
||||
"settings.aiProvider.defaultModel": "Modello predefinito",
|
||||
"settings.aiProvider.gateway": "DbGate AI Gateway",
|
||||
"settings.aiProvider.name": "Nome provider",
|
||||
"settings.aiProvider.newProviderName": "Provider {number}",
|
||||
"settings.aiProvider.noDefaultModel": "(Nessun modello predefinito)",
|
||||
"settings.aiProvider.noModelsAvailable": "(Nessun modello disponibile)",
|
||||
"settings.aiProvider.noUrlConfigured": "Nessun URL configurato",
|
||||
"settings.aiProvider.removeProviderConfirmation": "Sei sicuro di voler rimuovere il provider {provider}?",
|
||||
"settings.aiProvider.status.connectionFailed": "Connessione fallita:",
|
||||
"settings.aiProvider.status.error": "Errore",
|
||||
"settings.aiProvider.status.noModelsFound": "Nessun modello trovato",
|
||||
"settings.aiProvider.status.notConfigured": "Non configurato",
|
||||
"settings.aiProvider.status.testing": "Test in corso",
|
||||
"settings.aiProvider.status.testingConnection": "Test connessione...",
|
||||
"settings.aiProvider.status.untested": "Non testato",
|
||||
"settings.aiProvider.status.valid": "Valido",
|
||||
"settings.appearance": "Tema applicazione",
|
||||
"settings.appearance.afterInstalling": "Dopo aver installato un plugin tema (prova a cercare \"theme\" nelle estensioni disponibili) nuovi temi saranno disponibili qui.",
|
||||
"settings.appearance.customSize": "Dimensione personalizzata",
|
||||
@@ -1130,6 +1285,8 @@
|
||||
"settings.connection.autoRefreshInterval": "Intervallo tra ricaricamenti automatici struttura DB in secondi",
|
||||
"settings.connection.showOnlyTabsFromSelectedDatabase": "Mostra solo schede dal database selezionato",
|
||||
"settings.connection.sshBindHost": "Indirizzo host locale per connessioni SSH",
|
||||
"settings.customProviders.heading": "Provider personalizzati",
|
||||
"settings.customProviders.noProvidersConfigured": "Nessun provider personalizzato configurato. Clicca \"Aggiungi provider\" per iniziare.",
|
||||
"settings.dataGrid.alignNumbersRight": "Allinea numeri a destra",
|
||||
"settings.dataGrid.collectionPageSize": "Dimensione pagina collezione (per vista JSON MongoDB, deve essere tra 5 e 1000)",
|
||||
"settings.dataGrid.coloringMode": "Modalità colorazione righe",
|
||||
@@ -1142,6 +1299,12 @@
|
||||
"settings.dataGrid.showAllColumnsWhenSearch": "Mostra tutte le colonne durante la ricerca",
|
||||
"settings.dataGrid.showHintColumns": "Mostra suggerimenti chiavi esterne",
|
||||
"settings.dataGrid.thousandsSeparator": "Usa separatore migliaia per i numeri",
|
||||
"settings.dataGrid.thousandsSeparator.comma": "Virgola (,)",
|
||||
"settings.dataGrid.thousandsSeparator.dot": "Punto (.)",
|
||||
"settings.dataGrid.thousandsSeparator.narrowSpace": "Spazio stretto",
|
||||
"settings.dataGrid.thousandsSeparator.none": "Nessuno",
|
||||
"settings.dataGrid.thousandsSeparator.space": "Spazio",
|
||||
"settings.dataGrid.thousandsSeparator.system": "Sistema",
|
||||
"settings.dataGrid.title": "Griglia dati",
|
||||
"settings.defaultActions": "Azioni predefinite",
|
||||
"settings.defaultActions.collectionClick": "Clic collezione NoSQL",
|
||||
@@ -1198,6 +1361,9 @@
|
||||
"settings.sqlEditor.showTableAliasesInCodeCompletion": "Mostra alias tabelle nel completamento codice",
|
||||
"settings.sqlEditor.sqlCommandsCase": "Maiuscole/minuscole comandi SQL",
|
||||
"settings.sqlEditor.title": "Editor SQL",
|
||||
"settings.supportedProviders.description": "Qualsiasi servizio compatibile con il formato API OpenAI funzionerà, inclusi:",
|
||||
"settings.supportedProviders.heading": "Provider supportati",
|
||||
"settings.supportedProviders.useThisProvider": "Usa questo provider",
|
||||
"settings.tabGroup.showServerName": "Mostra nome server accanto al nome database nel titolo del gruppo schede",
|
||||
"settings.tabPreviewMode": "Modalità anteprima scheda",
|
||||
"settings.theme": "Temi",
|
||||
@@ -1267,6 +1433,11 @@
|
||||
"switchDatabase.server": "Server",
|
||||
"switchDatabase.switchDatabase": "Cambia database",
|
||||
"tab.administration": "Amministrazione",
|
||||
"tableCell.edit": "Modifica",
|
||||
"tableCell.filterColumns": "Filtra colonne",
|
||||
"tableCell.hideNullValues": "Nascondi valori NULL",
|
||||
"tableCell.multipleValues": "Valori multipli",
|
||||
"tableCell.noDataSelected": "Nessun dato selezionato",
|
||||
"tableData.errorWhenSaving": "Errore durante il salvataggio",
|
||||
"tableData.refreshEvery": "Aggiorna (ogni {autoRefreshInterval}s)",
|
||||
"tableData.savedToDatabase": "Salvato nel database",
|
||||
|
||||
@@ -137,6 +137,8 @@
|
||||
"command.archiveFile": "アーカイブファイル",
|
||||
"command.archiveFile.save": "保存",
|
||||
"command.archiveFile.saveAs": "名前を付けて保存",
|
||||
"command.chart": "チャート",
|
||||
"command.chart.export": "チャートをエクスポート",
|
||||
"command.cloud": "クラウド",
|
||||
"command.cloud.logout": "ログアウト",
|
||||
"command.collectionData": "コレクションデータ",
|
||||
@@ -145,7 +147,21 @@
|
||||
"command.collectionData.save": "保存",
|
||||
"command.commandPalette": "コマンドパレット",
|
||||
"command.commandPalette.show": "表示",
|
||||
"command.compare": "モデルを比較",
|
||||
"command.compare.deploy": "デプロイ",
|
||||
"command.compare.refresh": "更新",
|
||||
"command.compare.refreshModels": "モデルを更新",
|
||||
"command.compare.report": "レポート",
|
||||
"command.compare.reportDiff": "差分レポート",
|
||||
"command.compare.swap": "入れ替え",
|
||||
"command.compare.swapSource": "ソースとターゲットを入れ替え",
|
||||
"command.compareDatabase": "データベース比較",
|
||||
"command.copy": "コピー",
|
||||
"command.dataDeploy": "データデプロイヤー",
|
||||
"command.dataDeploy.generateShell": "シェルを生成",
|
||||
"command.dataDeploy.generateSql": "SQLを生成",
|
||||
"command.dataDeploy.kill": "デプロイを強制終了",
|
||||
"command.dataDeploy.run": "DBにデプロイ",
|
||||
"command.dataForm": "データフォーム",
|
||||
"command.dataForm.addToFilter": "フィルターに追加",
|
||||
"command.dataForm.copyToClipboard": "クリップボードにコピー",
|
||||
@@ -218,6 +234,9 @@
|
||||
"command.datagrid.stopAutoRefresh": "自動更新を停止",
|
||||
"command.datagrid.switchToJSON": "JSONに切り替え",
|
||||
"command.datagrid.switchToform": "フォームに切り替え",
|
||||
"command.datagrid.toggleCellDataView": "セルデータビューの切り替え",
|
||||
"command.datagrid.toggleCellDataView.menu": "セルデータを表示",
|
||||
"command.datagrid.toggleCellDataView.toolbar": "セルデータ",
|
||||
"command.datagrid.toggleLeftPanel": "左パネルの切り替え",
|
||||
"command.datagrid.undo": "元に戻す",
|
||||
"command.datagrid.viewJsonDocument": "行をJSONドキュメントとして表示",
|
||||
@@ -227,6 +246,7 @@
|
||||
"command.designer": "デザイナー",
|
||||
"command.designer.arrange": "配置",
|
||||
"command.designer.exportDiagram": "ダイアグラムをエクスポート",
|
||||
"command.designer.openSql": "SQLを開く",
|
||||
"command.designer.remove": "削除",
|
||||
"command.designer.removeSelectedTables": "選択したテーブルを削除",
|
||||
"command.diagram": "ダイアグラム",
|
||||
@@ -256,6 +276,7 @@
|
||||
"command.internal": "内部",
|
||||
"command.internal.loadCampaigns": "キャンペーンリストを読み込み",
|
||||
"command.internal.showCampaigns": "キャンペーンを表示",
|
||||
"command.jsonl": "JSON Linesエディター",
|
||||
"command.jsonl.closePreview": "プレビューを閉じる",
|
||||
"command.jsonl.preview": "プレビュー",
|
||||
"command.jsonl.previewNewTab": "新しいタブでプレビュー",
|
||||
@@ -294,6 +315,13 @@
|
||||
"command.new.tableToolbar": "新しいテーブル",
|
||||
"command.openQuery": "クエリを開く",
|
||||
"command.paste": "貼り付け",
|
||||
"command.perspective": "パースペクティブ",
|
||||
"command.perspective.openJson": "JSONを開く",
|
||||
"command.perspective.refresh": "更新",
|
||||
"command.profiler": "プロファイラー",
|
||||
"command.profiler.save": "保存",
|
||||
"command.profiler.start": "プロファイル開始",
|
||||
"command.profiler.stop": "プロファイル停止",
|
||||
"command.query": "クエリ",
|
||||
"command.query.AiAssistant": "AIアシスタント",
|
||||
"command.query.autocommitOffSwitch": "自動コミット: OFF",
|
||||
@@ -368,6 +396,7 @@
|
||||
"commandPalette.searchInDatabase": "データベース内を検索",
|
||||
"common.Remove": "削除",
|
||||
"common.addNew": "新規追加",
|
||||
"common.addProvider": "プロバイダーを追加",
|
||||
"common.advanced": "詳細設定",
|
||||
"common.allFields": "すべての{field}",
|
||||
"common.allFiles": "すべてのファイル",
|
||||
@@ -395,6 +424,7 @@
|
||||
"common.done": "完了",
|
||||
"common.dontAskAgain": "次回から表示しない",
|
||||
"common.download": "ダウンロード",
|
||||
"common.edit": "編集",
|
||||
"common.erDiagram": "ERダイアグラム",
|
||||
"common.error": "エラー",
|
||||
"common.execute": "実行",
|
||||
@@ -451,6 +481,57 @@
|
||||
"common.testingConnection": "接続テスト中",
|
||||
"common.uncheckAll": "すべてのチェックを外す",
|
||||
"common.zipFiles": "ZIPファイル",
|
||||
"compare.action": "アクション",
|
||||
"compare.added": "追加",
|
||||
"compare.allowDropColumns": "カラムの削除を許可",
|
||||
"compare.allowDropSqlObjects": "ビュー、プロシージャなどの削除を許可",
|
||||
"compare.allowDropTables": "テーブルの削除を許可",
|
||||
"compare.allowTableRecreate": "テーブルの再作成を許可",
|
||||
"compare.autoinc": "自動増分",
|
||||
"compare.changed": "変更",
|
||||
"compare.columns": "カラム",
|
||||
"compare.ddl": "DDL",
|
||||
"compare.deletedPrefix": "削除プレフィックス",
|
||||
"compare.deployChanges": "変更をデプロイ",
|
||||
"compare.deployingDatabaseChanges": "データベース変更をデプロイ中",
|
||||
"compare.dontDropColumns": "カラムを削除しない",
|
||||
"compare.dontDropConstraints": "制約を削除しない",
|
||||
"compare.dontDropSqlObjects": "オブジェクトを削除しない",
|
||||
"compare.dontDropTables": "テーブルを削除しない",
|
||||
"compare.dropColumnsIfMissing": "存在しないカラムを削除",
|
||||
"compare.dropSqlObjectsIfMissing": "存在しないオブジェクトを削除",
|
||||
"compare.dropTablesIfMissing": "存在しないテーブルを削除",
|
||||
"compare.equal": "同一",
|
||||
"compare.errorWhenSaving": "保存中にエラー",
|
||||
"compare.hideRowsWithoutOperations": "操作のない行を非表示",
|
||||
"compare.ignoreCase": "大文字小文字を無視",
|
||||
"compare.ignoreConstraintNames": "制約名を無視",
|
||||
"compare.ignoreDataTypes": "データ型を無視",
|
||||
"compare.ignoreForeignKeyActions": "外部キーアクションを無視",
|
||||
"compare.ignoreNameRegex": "正規表現に一致する名前を無視",
|
||||
"compare.ignoreSchema": "スキーマを無視",
|
||||
"compare.loadingDatabaseStructure": "データベース構造を読み込み中",
|
||||
"compare.markColumnsAsDeleted": "カラムを削除済みとしてマーク",
|
||||
"compare.markSqlObjectsAsDeleted": "オブジェクトを削除済みとしてマーク",
|
||||
"compare.markTablesAsDeleted": "テーブルを削除済みとしてマーク",
|
||||
"compare.name": "名前",
|
||||
"compare.notNull": "NOT NULL",
|
||||
"compare.operations": "操作",
|
||||
"compare.removed": "削除",
|
||||
"compare.sameSourceAndTargetDatabasesWarning": "ソースとターゲットのデータベースが同じです。差分は見つかりません。ソースまたはターゲットのデータベースを変更してください。",
|
||||
"compare.savedToDatabase": "データベースに保存しました",
|
||||
"compare.schema": "スキーマ",
|
||||
"compare.searchTablesOrObjects": "テーブルまたはオブジェクトを検索",
|
||||
"compare.settings": "設定",
|
||||
"compare.sourceDatabase": "ソースデータベース",
|
||||
"compare.sourceDbModel": "ソースDBモデル",
|
||||
"compare.sourceModelTransform": "ソースモデル変換",
|
||||
"compare.sourceServer": "ソースサーバー",
|
||||
"compare.synchronizeScript": "同期スクリプト",
|
||||
"compare.targetDatabase": "ターゲットデータベース",
|
||||
"compare.targetSchema": "ターゲットスキーマ",
|
||||
"compare.targetServer": "ターゲットサーバー",
|
||||
"compare.type": "タイプ",
|
||||
"connection.accessKeyId": "アクセスキーID",
|
||||
"connection.allowedDatabases": "許可されたデータベース、1行に1つ",
|
||||
"connection.allowedDatabasesRegex": "許可されたデータベースの正規表現",
|
||||
@@ -675,6 +756,7 @@
|
||||
"datagrid.searchMacros": "Search macros",
|
||||
"datagrid.setFormat": "Set format: ",
|
||||
"datagrid.structure": "Structure",
|
||||
"datagrid.useMacro": "マクロを使用",
|
||||
"dbKeyAddItemModal.header": "項目を追加",
|
||||
"dbKeysTreeNode.deleteBranch": "ブランチを削除",
|
||||
"dbKeysTreeNode.deleteBranchConfirm": "本当にブランチ {branch} とそのすべてのキーを削除しますか?",
|
||||
@@ -755,6 +837,22 @@
|
||||
"designerTable.newAlias": "新しいエイリアス",
|
||||
"designerTable.removeTableAlias": "テーブルエイリアスを削除",
|
||||
"designerTable.setTableAlias": "テーブルエイリアスを設定",
|
||||
"diagram.all": "すべて",
|
||||
"diagram.allKeys": "すべてのキー",
|
||||
"diagram.columnFilter": "カラムフィルター",
|
||||
"diagram.exportWatermark": "ウォーターマークをエクスポート",
|
||||
"diagram.keysAndNotNull": "キーとNOT NULL",
|
||||
"diagram.notNull": "NOT NULL",
|
||||
"diagram.omitExportWatermark": "ウォーターマークをエクスポートしない",
|
||||
"diagram.omitTablesFilter": "テーブルを除外",
|
||||
"diagram.primaryKey": "主キー",
|
||||
"diagram.showColumns": "カラムを表示",
|
||||
"diagram.showDataType": "データ型を表示",
|
||||
"diagram.showNullability": "NULL/NOT NULLを表示",
|
||||
"diagram.tableFilter": "テーブルフィルター",
|
||||
"diagram.tables": "テーブル",
|
||||
"diagram.topTables": "最重要テーブルN件のみ",
|
||||
"diagram.zoom": "ズーム",
|
||||
"dictionaryLookupModal.customize": "カスタマイズ",
|
||||
"dictionaryLookupModal.description": "説明",
|
||||
"dictionaryLookupModal.header": "{pureName} からルックアップ",
|
||||
@@ -1032,6 +1130,16 @@
|
||||
"newObject.sqlGeneratorDisabled": "現在のデータベースではSQLジェネレーターが利用できません",
|
||||
"newObject.tableDescription": "現在のデータベースにテーブルを作成",
|
||||
"newObject.tableDisabled": "現在のデータベースではテーブル作成が利用できません",
|
||||
"perspective.arrange": "配置",
|
||||
"perspective.arranged": "(配置済み)",
|
||||
"perspective.category": "パースペクティブ",
|
||||
"perspective.chooseData": "データを選択",
|
||||
"perspective.customJoin": "カスタムJOIN",
|
||||
"perspective.filters": "フィルター",
|
||||
"perspective.invalidFormat": "パースペクティブ形式が無効です。新しいパースペクティブを作成してください",
|
||||
"perspective.noFiltersDefined": "フィルターが定義されていません",
|
||||
"perspective.searchColumnOrTable": "カラムまたはテーブルを検索",
|
||||
"perspective.useContextMenuAddToFilter": "テーブルまたはツリーのコンテキストメニューで「フィルターに追加」を使用",
|
||||
"plugins.searchExtensionsOnWeb": "Webで拡張機能を検索",
|
||||
"privateCloudWidget.addExistingFolder": "既存フォルダーを追加(リンクから)",
|
||||
"privateCloudWidget.addExistingSharedFolder": "既存の共有フォルダーを追加",
|
||||
@@ -1056,6 +1164,7 @@
|
||||
"publicCloudWidget.refreshFiles": "ファイルを更新",
|
||||
"publicCloudWidget.refreshList": "リストを更新",
|
||||
"publicCloudWidget.searchPublicFiles": "公開ファイルを検索",
|
||||
"query.AiAssistant": "AIアシスタント",
|
||||
"query.Copy": "コピー",
|
||||
"query.Download": "ダウンロード",
|
||||
"query.Messages": "メッセージ",
|
||||
@@ -1064,17 +1173,34 @@
|
||||
"query.OutputFiles": "出力ファイル",
|
||||
"query.Show": "表示",
|
||||
"query.Size": "サイズ",
|
||||
"query.addCustomExpression": "カスタム式を追加",
|
||||
"query.addGroupOrCondition": "グループOR条件を追加",
|
||||
"query.addOrCondition": "OR条件を追加",
|
||||
"query.aggregate": "集計",
|
||||
"query.alias": "エイリアス",
|
||||
"query.columnExpression": "カラム/式",
|
||||
"query.download": "ダウンロード",
|
||||
"query.filter": "フィルター",
|
||||
"query.groupBy": "グループ化",
|
||||
"query.groupFilter": "グループフィルター",
|
||||
"query.limitRows": "{queryRowsLimit}行に制限",
|
||||
"query.named": ":variable",
|
||||
"query.noParameters": "(パラメーターなし)",
|
||||
"query.noRowsLimit": "(行数制限なし)",
|
||||
"query.orFilter": "ORフィルター {number}",
|
||||
"query.orGroupFilter": "ORグループフィルター {number}",
|
||||
"query.output": "出力",
|
||||
"query.positional": "? (位置指定)",
|
||||
"query.queryNumber": "クエリ #",
|
||||
"query.removeDuplicates": "重複を削除: {status}",
|
||||
"query.removeGroupOrCondition": "グループOR条件を削除",
|
||||
"query.removeOrCondition": "OR条件を削除",
|
||||
"query.returnOnlyNRows": "クエリからN行のみ返す",
|
||||
"query.rowsLimit": "行数制限",
|
||||
"query.save": "保存",
|
||||
"query.show": "表示",
|
||||
"query.sortOrder": "ソート順",
|
||||
"query.table": "テーブル",
|
||||
"query.unlimitedRows": "無制限",
|
||||
"query.variable": "#variable",
|
||||
"queryParameters.editQueryParameters": "クエリパラメーターを編集",
|
||||
@@ -1106,6 +1232,35 @@
|
||||
"serverSummaryTab.processes": "プロセス",
|
||||
"serverSummaryTab.variables": "変数",
|
||||
"settings.AI": "AI",
|
||||
"settings.aiChatDefaults.heading": "AIチャットのデフォルト",
|
||||
"settings.aiExecuteMode": "SQL実行モード",
|
||||
"settings.aiExecuteMode.ask": "実行前に確認",
|
||||
"settings.aiExecuteMode.auto": "自動的に実行",
|
||||
"settings.aiExecuteMode.never": "SQLを実行しない",
|
||||
"settings.aiProvider": "AIプロバイダー",
|
||||
"settings.aiProvider.apiKey": "APIキー",
|
||||
"settings.aiProvider.apiKeyPlaceholder": "APIキー(ローカルプロバイダーの場合は空のまま)",
|
||||
"settings.aiProvider.baseUrl": "ベースURL",
|
||||
"settings.aiProvider.connectionTest.cancel": "テストをキャンセル",
|
||||
"settings.aiProvider.connectionTest.retest": "再テスト",
|
||||
"settings.aiProvider.connectionTest.test": "接続テスト",
|
||||
"settings.aiProvider.connectionTestFailed": "接続テストに失敗しました:",
|
||||
"settings.aiProvider.defaultModel": "デフォルトモデル",
|
||||
"settings.aiProvider.gateway": "DbGate AIゲートウェイ",
|
||||
"settings.aiProvider.name": "プロバイダー名",
|
||||
"settings.aiProvider.newProviderName": "プロバイダー {number}",
|
||||
"settings.aiProvider.noDefaultModel": "(デフォルトモデルなし)",
|
||||
"settings.aiProvider.noModelsAvailable": "(利用可能なモデルなし)",
|
||||
"settings.aiProvider.noUrlConfigured": "URLが設定されていません",
|
||||
"settings.aiProvider.removeProviderConfirmation": "本当にプロバイダー {provider} を削除しますか?",
|
||||
"settings.aiProvider.status.connectionFailed": "接続に失敗しました:",
|
||||
"settings.aiProvider.status.error": "エラー",
|
||||
"settings.aiProvider.status.noModelsFound": "モデルが見つかりません",
|
||||
"settings.aiProvider.status.notConfigured": "未設定",
|
||||
"settings.aiProvider.status.testing": "テスト中",
|
||||
"settings.aiProvider.status.testingConnection": "接続をテスト中...",
|
||||
"settings.aiProvider.status.untested": "未テスト",
|
||||
"settings.aiProvider.status.valid": "有効",
|
||||
"settings.appearance": "アプリケーションテーマ",
|
||||
"settings.appearance.afterInstalling": "テーマプラグインをインストールすると(利用可能な拡張機能で\"theme\"を検索)、新しいテーマがここに表示されます。",
|
||||
"settings.appearance.customSize": "カスタムサイズ",
|
||||
@@ -1130,6 +1285,8 @@
|
||||
"settings.connection.autoRefreshInterval": "DB構造の自動再読み込み間隔(秒)",
|
||||
"settings.connection.showOnlyTabsFromSelectedDatabase": "選択されたデータベースのタブのみ表示",
|
||||
"settings.connection.sshBindHost": "SSH接続用のローカルホストアドレス",
|
||||
"settings.customProviders.heading": "カスタムプロバイダー",
|
||||
"settings.customProviders.noProvidersConfigured": "カスタムプロバイダーが設定されていません。「プロバイダーを追加」をクリックして開始してください。",
|
||||
"settings.dataGrid.alignNumbersRight": "数値を右揃え",
|
||||
"settings.dataGrid.collectionPageSize": "コレクションページサイズ(MongoDB JSONビュー用、5から1000の間)",
|
||||
"settings.dataGrid.coloringMode": "行の色分けモード",
|
||||
@@ -1142,6 +1299,12 @@
|
||||
"settings.dataGrid.showAllColumnsWhenSearch": "検索時にすべてのカラムを表示",
|
||||
"settings.dataGrid.showHintColumns": "外部キーヒントを表示",
|
||||
"settings.dataGrid.thousandsSeparator": "数値に桁区切りを使用",
|
||||
"settings.dataGrid.thousandsSeparator.comma": "カンマ (,)",
|
||||
"settings.dataGrid.thousandsSeparator.dot": "ドット (.)",
|
||||
"settings.dataGrid.thousandsSeparator.narrowSpace": "ナロースペース",
|
||||
"settings.dataGrid.thousandsSeparator.none": "なし",
|
||||
"settings.dataGrid.thousandsSeparator.space": "スペース",
|
||||
"settings.dataGrid.thousandsSeparator.system": "システム",
|
||||
"settings.dataGrid.title": "データグリッド",
|
||||
"settings.defaultActions": "デフォルト動作",
|
||||
"settings.defaultActions.collectionClick": "NoSQLコレクションクリック",
|
||||
@@ -1198,6 +1361,9 @@
|
||||
"settings.sqlEditor.showTableAliasesInCodeCompletion": "コード補完にテーブルエイリアスを表示",
|
||||
"settings.sqlEditor.sqlCommandsCase": "SQLコマンドの大文字小文字",
|
||||
"settings.sqlEditor.title": "SQLエディター",
|
||||
"settings.supportedProviders.description": "OpenAI API形式と互換性のあるサービスであれば、次のようなものを含めて利用できます:",
|
||||
"settings.supportedProviders.heading": "サポートされているプロバイダー",
|
||||
"settings.supportedProviders.useThisProvider": "このプロバイダーを使用",
|
||||
"settings.tabGroup.showServerName": "タブグループのタイトルにデータベース名と並んでサーバー名を表示",
|
||||
"settings.tabPreviewMode": "タブプレビューモード",
|
||||
"settings.theme": "テーマ",
|
||||
@@ -1267,6 +1433,11 @@
|
||||
"switchDatabase.server": "サーバー",
|
||||
"switchDatabase.switchDatabase": "データベースを切り替え",
|
||||
"tab.administration": "管理",
|
||||
"tableCell.edit": "編集",
|
||||
"tableCell.filterColumns": "カラムをフィルター",
|
||||
"tableCell.hideNullValues": "NULL値を非表示",
|
||||
"tableCell.multipleValues": "複数の値",
|
||||
"tableCell.noDataSelected": "データが選択されていません",
|
||||
"tableData.errorWhenSaving": "保存中にエラー",
|
||||
"tableData.refreshEvery": "更新({autoRefreshInterval}秒ごと)",
|
||||
"tableData.savedToDatabase": "データベースに保存しました",
|
||||
|
||||
@@ -137,6 +137,8 @@
|
||||
"command.archiveFile": "Arquivo compactado",
|
||||
"command.archiveFile.save": "Salvar",
|
||||
"command.archiveFile.saveAs": "Salvar como",
|
||||
"command.chart": "Gráfico",
|
||||
"command.chart.export": "Exportar gráfico",
|
||||
"command.cloud": "Nuvem",
|
||||
"command.cloud.logout": "Sair",
|
||||
"command.collectionData": "Dados da coleção",
|
||||
@@ -145,7 +147,21 @@
|
||||
"command.collectionData.save": "Salvar",
|
||||
"command.commandPalette": "Paleta de comandos",
|
||||
"command.commandPalette.show": "Mostrar",
|
||||
"command.compare": "Comparar modelos",
|
||||
"command.compare.deploy": "Implantar",
|
||||
"command.compare.refresh": "Atualizar",
|
||||
"command.compare.refreshModels": "Atualizar modelos",
|
||||
"command.compare.report": "Relatório",
|
||||
"command.compare.reportDiff": "Relatório de diferenças",
|
||||
"command.compare.swap": "Inverter",
|
||||
"command.compare.swapSource": "Inverter origem e destino",
|
||||
"command.compareDatabase": "Comparar banco de dados",
|
||||
"command.copy": "Copiar",
|
||||
"command.dataDeploy": "Implantador de dados",
|
||||
"command.dataDeploy.generateShell": "Gerar shell",
|
||||
"command.dataDeploy.generateSql": "Gerar SQL",
|
||||
"command.dataDeploy.kill": "Encerrar implantação",
|
||||
"command.dataDeploy.run": "Implantar no BD",
|
||||
"command.dataForm": "Formulário de dados",
|
||||
"command.dataForm.addToFilter": "Adicionar ao filtro",
|
||||
"command.dataForm.copyToClipboard": "Copiar para área de transferência",
|
||||
@@ -218,6 +234,9 @@
|
||||
"command.datagrid.stopAutoRefresh": "Parar atualização automática",
|
||||
"command.datagrid.switchToJSON": "Mudar para JSON",
|
||||
"command.datagrid.switchToform": "Mudar para formulário",
|
||||
"command.datagrid.toggleCellDataView": "Alternar visualização de dados da célula",
|
||||
"command.datagrid.toggleCellDataView.menu": "Mostrar dados da célula",
|
||||
"command.datagrid.toggleCellDataView.toolbar": "Dados da célula",
|
||||
"command.datagrid.toggleLeftPanel": "Alternar painel esquerdo",
|
||||
"command.datagrid.undo": "Desfazer",
|
||||
"command.datagrid.viewJsonDocument": "Ver linha como documento JSON",
|
||||
@@ -227,6 +246,7 @@
|
||||
"command.designer": "Designer",
|
||||
"command.designer.arrange": "Organizar",
|
||||
"command.designer.exportDiagram": "Exportar diagrama",
|
||||
"command.designer.openSql": "Abrir SQL",
|
||||
"command.designer.remove": "Remover",
|
||||
"command.designer.removeSelectedTables": "Remover tabelas selecionadas",
|
||||
"command.diagram": "Diagrama",
|
||||
@@ -256,6 +276,7 @@
|
||||
"command.internal": "Interno",
|
||||
"command.internal.loadCampaigns": "Carregar lista de campanhas",
|
||||
"command.internal.showCampaigns": "Mostrar campanhas",
|
||||
"command.jsonl": "Editor JSON Lines",
|
||||
"command.jsonl.closePreview": "Fechar visualização",
|
||||
"command.jsonl.preview": "Visualizar",
|
||||
"command.jsonl.previewNewTab": "Visualizar em nova aba",
|
||||
@@ -294,6 +315,13 @@
|
||||
"command.new.tableToolbar": "Nova tabela",
|
||||
"command.openQuery": "Abrir consulta",
|
||||
"command.paste": "Colar",
|
||||
"command.perspective": "Perspectiva",
|
||||
"command.perspective.openJson": "Abrir JSON",
|
||||
"command.perspective.refresh": "Atualizar",
|
||||
"command.profiler": "Profiler",
|
||||
"command.profiler.save": "Salvar",
|
||||
"command.profiler.start": "Iniciar profiling",
|
||||
"command.profiler.stop": "Parar profiling",
|
||||
"command.query": "Consulta",
|
||||
"command.query.AiAssistant": "Assistente de IA",
|
||||
"command.query.autocommitOffSwitch": "Auto commit: DESLIGADO",
|
||||
@@ -368,6 +396,7 @@
|
||||
"commandPalette.searchInDatabase": "Pesquisar no banco de dados",
|
||||
"common.Remove": "Remover",
|
||||
"common.addNew": "Adicionar novo",
|
||||
"common.addProvider": "Adicionar provedor",
|
||||
"common.advanced": "Avançado",
|
||||
"common.allFields": "Todos {field}",
|
||||
"common.allFiles": "Todos os arquivos",
|
||||
@@ -395,6 +424,7 @@
|
||||
"common.done": "Concluído",
|
||||
"common.dontAskAgain": "Não perguntar novamente",
|
||||
"common.download": "Baixar",
|
||||
"common.edit": "Editar",
|
||||
"common.erDiagram": "Diagrama ER",
|
||||
"common.error": "Erro",
|
||||
"common.execute": "Executar",
|
||||
@@ -451,6 +481,57 @@
|
||||
"common.testingConnection": "Testando conexão",
|
||||
"common.uncheckAll": "Desmarcar todos",
|
||||
"common.zipFiles": "Arquivos ZIP",
|
||||
"compare.action": "Ação",
|
||||
"compare.added": "Adicionado",
|
||||
"compare.allowDropColumns": "Permitir remover colunas",
|
||||
"compare.allowDropSqlObjects": "Permitir remover visão, procedimento, etc.",
|
||||
"compare.allowDropTables": "Permitir remover tabelas",
|
||||
"compare.allowTableRecreate": "Permitir recriar tabela",
|
||||
"compare.autoinc": "Autoinc",
|
||||
"compare.changed": "Alterado",
|
||||
"compare.columns": "Colunas",
|
||||
"compare.ddl": "DDL",
|
||||
"compare.deletedPrefix": "Prefixo de excluído",
|
||||
"compare.deployChanges": "Implantar alterações",
|
||||
"compare.deployingDatabaseChanges": "Implantando alterações no banco de dados",
|
||||
"compare.dontDropColumns": "Não remover colunas",
|
||||
"compare.dontDropConstraints": "Não remover restrições",
|
||||
"compare.dontDropSqlObjects": "Não remover objeto",
|
||||
"compare.dontDropTables": "Não remover tabelas",
|
||||
"compare.dropColumnsIfMissing": "Remover colunas se ausentes",
|
||||
"compare.dropSqlObjectsIfMissing": "Remover objeto se ausente",
|
||||
"compare.dropTablesIfMissing": "Remover tabelas se ausentes",
|
||||
"compare.equal": "Igual",
|
||||
"compare.errorWhenSaving": "Erro ao salvar",
|
||||
"compare.hideRowsWithoutOperations": "Ocultar linhas sem operações",
|
||||
"compare.ignoreCase": "Ignorar maiúsculas/minúsculas",
|
||||
"compare.ignoreConstraintNames": "Ignorar nomes de restrições",
|
||||
"compare.ignoreDataTypes": "Ignorar tipos de dados",
|
||||
"compare.ignoreForeignKeyActions": "Ignorar ações de chave estrangeira",
|
||||
"compare.ignoreNameRegex": "Ignorar nomes que correspondem à regex",
|
||||
"compare.ignoreSchema": "Ignorar schema",
|
||||
"compare.loadingDatabaseStructure": "Carregando estrutura do banco de dados",
|
||||
"compare.markColumnsAsDeleted": "Marcar colunas como excluídas",
|
||||
"compare.markSqlObjectsAsDeleted": "Marcar objeto como excluído",
|
||||
"compare.markTablesAsDeleted": "Marcar tabelas como excluídas",
|
||||
"compare.name": "Nome",
|
||||
"compare.notNull": "Not null",
|
||||
"compare.operations": "Operações",
|
||||
"compare.removed": "Removido",
|
||||
"compare.sameSourceAndTargetDatabasesWarning": "Os bancos de dados de origem e destino são os mesmos, nenhuma diferença será encontrada. Altere o banco de dados de origem ou de destino.",
|
||||
"compare.savedToDatabase": "Salvo no banco de dados",
|
||||
"compare.schema": "Schema",
|
||||
"compare.searchTablesOrObjects": "Pesquisar tabelas ou objetos",
|
||||
"compare.settings": "Configurações",
|
||||
"compare.sourceDatabase": "Banco de dados de origem",
|
||||
"compare.sourceDbModel": "Modelo de BD de origem",
|
||||
"compare.sourceModelTransform": "Transformação de modelo de origem",
|
||||
"compare.sourceServer": "Servidor de origem",
|
||||
"compare.synchronizeScript": "Sincronizar script",
|
||||
"compare.targetDatabase": "Banco de dados de destino",
|
||||
"compare.targetSchema": "Schema de destino",
|
||||
"compare.targetServer": "Servidor de destino",
|
||||
"compare.type": "Tipo",
|
||||
"connection.accessKeyId": "ID da Chave de Acesso",
|
||||
"connection.allowedDatabases": "Bancos de dados permitidos, um por linha",
|
||||
"connection.allowedDatabasesRegex": "Expressão regular de bancos de dados permitidos",
|
||||
@@ -675,6 +756,7 @@
|
||||
"datagrid.searchMacros": "Pesquisar macros",
|
||||
"datagrid.setFormat": "Definir formato: ",
|
||||
"datagrid.structure": "Estrutura",
|
||||
"datagrid.useMacro": "Usar macro",
|
||||
"dbKeyAddItemModal.header": "Adicionar item",
|
||||
"dbKeysTreeNode.deleteBranch": "Excluir ramo",
|
||||
"dbKeysTreeNode.deleteBranchConfirm": "Realmente excluir ramo {branch} com todas as chaves?",
|
||||
@@ -755,6 +837,22 @@
|
||||
"designerTable.newAlias": "Novo alias",
|
||||
"designerTable.removeTableAlias": "Remover alias da tabela",
|
||||
"designerTable.setTableAlias": "Definir alias da tabela",
|
||||
"diagram.all": "Todas",
|
||||
"diagram.allKeys": "Todas as Chaves",
|
||||
"diagram.columnFilter": "Filtro de coluna",
|
||||
"diagram.exportWatermark": "Exportar marca d'água",
|
||||
"diagram.keysAndNotNull": "Chaves e Not Null",
|
||||
"diagram.notNull": "Not Null",
|
||||
"diagram.omitExportWatermark": "Omitir marca d'água na exportação",
|
||||
"diagram.omitTablesFilter": "Omitir tabelas",
|
||||
"diagram.primaryKey": "Chave Primária",
|
||||
"diagram.showColumns": "Mostrar colunas",
|
||||
"diagram.showDataType": "Mostrar tipo de dados",
|
||||
"diagram.showNullability": "Mostrar NULL/NOT NULL",
|
||||
"diagram.tableFilter": "Filtro de tabela",
|
||||
"diagram.tables": "Tabelas",
|
||||
"diagram.topTables": "Apenas N tabelas mais importantes",
|
||||
"diagram.zoom": "Zoom",
|
||||
"dictionaryLookupModal.customize": "Personalizar",
|
||||
"dictionaryLookupModal.description": "Descrição",
|
||||
"dictionaryLookupModal.header": "Pesquisar em {pureName}",
|
||||
@@ -1032,6 +1130,16 @@
|
||||
"newObject.sqlGeneratorDisabled": "Gerador SQL não está disponível para o banco de dados atual",
|
||||
"newObject.tableDescription": "Criar tabela no banco de dados atual",
|
||||
"newObject.tableDisabled": "Criação de tabela não está disponível para o banco de dados atual",
|
||||
"perspective.arrange": "Organizar",
|
||||
"perspective.arranged": "(Organizado)",
|
||||
"perspective.category": "Perspectiva",
|
||||
"perspective.chooseData": "Escolher dados",
|
||||
"perspective.customJoin": "Join personalizado",
|
||||
"perspective.filters": "Filtros",
|
||||
"perspective.invalidFormat": "Formato de perspectiva inválido, crie uma nova perspectiva",
|
||||
"perspective.noFiltersDefined": "Nenhum Filtro definido",
|
||||
"perspective.searchColumnOrTable": "Pesquisar coluna ou tabela",
|
||||
"perspective.useContextMenuAddToFilter": "Use o menu de contexto, comando \"Adicionar ao filtro\" na tabela ou na árvore",
|
||||
"plugins.searchExtensionsOnWeb": "Pesquisar extensões na web",
|
||||
"privateCloudWidget.addExistingFolder": "Adicionar pasta existente (a partir de link)",
|
||||
"privateCloudWidget.addExistingSharedFolder": "Adicionar pasta compartilhada existente",
|
||||
@@ -1056,6 +1164,7 @@
|
||||
"publicCloudWidget.refreshFiles": "Atualizar arquivos",
|
||||
"publicCloudWidget.refreshList": "Atualizar lista",
|
||||
"publicCloudWidget.searchPublicFiles": "Pesquisar arquivos públicos",
|
||||
"query.AiAssistant": "Assistente de IA",
|
||||
"query.Copy": "Copiar",
|
||||
"query.Download": "Baixar",
|
||||
"query.Messages": "Mensagens",
|
||||
@@ -1064,17 +1173,34 @@
|
||||
"query.OutputFiles": "Arquivos de saída",
|
||||
"query.Show": "Mostrar",
|
||||
"query.Size": "Tamanho",
|
||||
"query.addCustomExpression": "Adicionar expressão personalizada",
|
||||
"query.addGroupOrCondition": "Adicionar grupo OU condição",
|
||||
"query.addOrCondition": "Adicionar condição OU",
|
||||
"query.aggregate": "Agregação",
|
||||
"query.alias": "Alias",
|
||||
"query.columnExpression": "Coluna/Expressão",
|
||||
"query.download": "baixar",
|
||||
"query.filter": "Filtro",
|
||||
"query.groupBy": "Agrupar por",
|
||||
"query.groupFilter": "Filtro de grupo",
|
||||
"query.limitRows": "Limitar a {queryRowsLimit} linhas",
|
||||
"query.named": ":variável",
|
||||
"query.noParameters": "(sem parâmetros)",
|
||||
"query.noRowsLimit": "(Sem limite de linhas)",
|
||||
"query.orFilter": "Filtro OU {number}",
|
||||
"query.orGroupFilter": "Filtro de grupo OU {number}",
|
||||
"query.output": "Saída",
|
||||
"query.positional": "? (posicional)",
|
||||
"query.queryNumber": "Consulta #",
|
||||
"query.removeDuplicates": "Remover duplicados: {status}",
|
||||
"query.removeGroupOrCondition": "Remover grupo OU condição",
|
||||
"query.removeOrCondition": "Remover condição OU",
|
||||
"query.returnOnlyNRows": "Retornar apenas N linhas da consulta",
|
||||
"query.rowsLimit": "Limite de linhas",
|
||||
"query.save": "salvar",
|
||||
"query.show": "mostrar",
|
||||
"query.sortOrder": "Ordem de classificação",
|
||||
"query.table": "Tabela",
|
||||
"query.unlimitedRows": "Linhas ilimitadas",
|
||||
"query.variable": "#variável",
|
||||
"queryParameters.editQueryParameters": "Editar parâmetros da consulta",
|
||||
@@ -1106,6 +1232,35 @@
|
||||
"serverSummaryTab.processes": "Processos",
|
||||
"serverSummaryTab.variables": "Variáveis",
|
||||
"settings.AI": "IA",
|
||||
"settings.aiChatDefaults.heading": "Padrões de Chat de IA",
|
||||
"settings.aiExecuteMode": "Modo de Execução SQL",
|
||||
"settings.aiExecuteMode.ask": "Perguntar antes de executar",
|
||||
"settings.aiExecuteMode.auto": "Executar automaticamente",
|
||||
"settings.aiExecuteMode.never": "Nunca executar SQL",
|
||||
"settings.aiProvider": "Provedor de IA",
|
||||
"settings.aiProvider.apiKey": "Chave de API",
|
||||
"settings.aiProvider.apiKeyPlaceholder": "Sua chave de API (deixe vazio para provedores locais)",
|
||||
"settings.aiProvider.baseUrl": "URL base",
|
||||
"settings.aiProvider.connectionTest.cancel": "Cancelar teste",
|
||||
"settings.aiProvider.connectionTest.retest": "Testar conexão novamente",
|
||||
"settings.aiProvider.connectionTest.test": "Testar conexão",
|
||||
"settings.aiProvider.connectionTestFailed": "Teste de conexão falhou:",
|
||||
"settings.aiProvider.defaultModel": "Modelo padrão",
|
||||
"settings.aiProvider.gateway": "DbGate AI Gateway",
|
||||
"settings.aiProvider.name": "Nome do provedor",
|
||||
"settings.aiProvider.newProviderName": "Provedor {number}",
|
||||
"settings.aiProvider.noDefaultModel": "(Nenhum modelo padrão)",
|
||||
"settings.aiProvider.noModelsAvailable": "(Nenhum modelo disponível)",
|
||||
"settings.aiProvider.noUrlConfigured": "Nenhuma URL configurada",
|
||||
"settings.aiProvider.removeProviderConfirmation": "Tem certeza que deseja remover o provedor {provider}?",
|
||||
"settings.aiProvider.status.connectionFailed": "Conexão falhou:",
|
||||
"settings.aiProvider.status.error": "Erro",
|
||||
"settings.aiProvider.status.noModelsFound": "Nenhum modelo encontrado",
|
||||
"settings.aiProvider.status.notConfigured": "Não configurado",
|
||||
"settings.aiProvider.status.testing": "Testando",
|
||||
"settings.aiProvider.status.testingConnection": "Testando conexão...",
|
||||
"settings.aiProvider.status.untested": "Não testado",
|
||||
"settings.aiProvider.status.valid": "Válido",
|
||||
"settings.appearance": "Tema da aplicação",
|
||||
"settings.appearance.afterInstalling": "Após instalar plugin de tema (tente pesquisar \"theme\" nas extensões disponíveis) novos temas estarão disponíveis aqui.",
|
||||
"settings.appearance.customSize": "Tamanho personalizado",
|
||||
@@ -1130,6 +1285,8 @@
|
||||
"settings.connection.autoRefreshInterval": "Intervalo entre recarregamentos automáticos da estrutura do BD em segundos",
|
||||
"settings.connection.showOnlyTabsFromSelectedDatabase": "Mostrar apenas abas do banco de dados selecionado",
|
||||
"settings.connection.sshBindHost": "Endereço de host local para conexões SSH",
|
||||
"settings.customProviders.heading": "Provedores Personalizados",
|
||||
"settings.customProviders.noProvidersConfigured": "Nenhum provedor personalizado configurado. Clique em \"Adicionar provedor\" para começar.",
|
||||
"settings.dataGrid.alignNumbersRight": "Alinhar números à direita",
|
||||
"settings.dataGrid.collectionPageSize": "Tamanho da página de coleção (para visão JSON do MongoDB, deve estar entre 5 e 1000)",
|
||||
"settings.dataGrid.coloringMode": "Modo de coloração de linhas",
|
||||
@@ -1142,6 +1299,12 @@
|
||||
"settings.dataGrid.showAllColumnsWhenSearch": "Mostrar todas as colunas ao pesquisar",
|
||||
"settings.dataGrid.showHintColumns": "Mostrar dicas de chave estrangeira",
|
||||
"settings.dataGrid.thousandsSeparator": "Usar separador de milhares para números",
|
||||
"settings.dataGrid.thousandsSeparator.comma": "Vírgula (,)",
|
||||
"settings.dataGrid.thousandsSeparator.dot": "Ponto (.)",
|
||||
"settings.dataGrid.thousandsSeparator.narrowSpace": "Espaço estreito",
|
||||
"settings.dataGrid.thousandsSeparator.none": "Nenhum",
|
||||
"settings.dataGrid.thousandsSeparator.space": "Espaço",
|
||||
"settings.dataGrid.thousandsSeparator.system": "Sistema",
|
||||
"settings.dataGrid.title": "Grade de dados",
|
||||
"settings.defaultActions": "Ações padrão",
|
||||
"settings.defaultActions.collectionClick": "Clique em coleção NoSQL",
|
||||
@@ -1198,6 +1361,9 @@
|
||||
"settings.sqlEditor.showTableAliasesInCodeCompletion": "Mostrar aliases de tabela no completar código",
|
||||
"settings.sqlEditor.sqlCommandsCase": "Maiúsculas/minúsculas de comandos SQL",
|
||||
"settings.sqlEditor.title": "Editor SQL",
|
||||
"settings.supportedProviders.description": "Qualquer serviço compatível com o formato da API OpenAI funcionará, incluindo:",
|
||||
"settings.supportedProviders.heading": "Provedores Suportados",
|
||||
"settings.supportedProviders.useThisProvider": "Usar este provedor",
|
||||
"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",
|
||||
@@ -1267,6 +1433,11 @@
|
||||
"switchDatabase.server": "Servidor",
|
||||
"switchDatabase.switchDatabase": "Trocar banco de dados",
|
||||
"tab.administration": "Administração",
|
||||
"tableCell.edit": "Editar",
|
||||
"tableCell.filterColumns": "Filtrar colunas",
|
||||
"tableCell.hideNullValues": "Ocultar valores NULL",
|
||||
"tableCell.multipleValues": "Múltiplos valores",
|
||||
"tableCell.noDataSelected": "Nenhum dado selecionado",
|
||||
"tableData.errorWhenSaving": "Erro ao salvar",
|
||||
"tableData.refreshEvery": "Atualizar (a cada {autoRefreshInterval}s)",
|
||||
"tableData.savedToDatabase": "Salvo no banco de dados",
|
||||
|
||||
@@ -137,6 +137,8 @@
|
||||
"command.archiveFile": "Archivný súbor",
|
||||
"command.archiveFile.save": "Uložiť",
|
||||
"command.archiveFile.saveAs": "Uložiť ako",
|
||||
"command.chart": "Graf",
|
||||
"command.chart.export": "Exportovať graf",
|
||||
"command.cloud": "Cloud",
|
||||
"command.cloud.logout": "Odhlásiť sa",
|
||||
"command.collectionData": "Údaje z kolekcie",
|
||||
@@ -145,7 +147,21 @@
|
||||
"command.collectionData.save": "Uložiť",
|
||||
"command.commandPalette": "Paleta príkazov",
|
||||
"command.commandPalette.show": "Zobraziť",
|
||||
"command.compare": "Porovnať modely",
|
||||
"command.compare.deploy": "Nasadiť",
|
||||
"command.compare.refresh": "Obnoviť",
|
||||
"command.compare.refreshModels": "Obnoviť modely",
|
||||
"command.compare.report": "Report",
|
||||
"command.compare.reportDiff": "Report rozdielov",
|
||||
"command.compare.swap": "Prehodiť",
|
||||
"command.compare.swapSource": "Prehodiť zdroj a cieľ",
|
||||
"command.compareDatabase": "Porovnanie databázy",
|
||||
"command.copy": "Kopírovať",
|
||||
"command.dataDeploy": "Data deployer",
|
||||
"command.dataDeploy.generateShell": "Generovať shell",
|
||||
"command.dataDeploy.generateSql": "Generovať SQL",
|
||||
"command.dataDeploy.kill": "Ukončiť nasadenie",
|
||||
"command.dataDeploy.run": "Nasadiť do DB",
|
||||
"command.dataForm": "Formulár dát",
|
||||
"command.dataForm.addToFilter": "Pridať do filtru",
|
||||
"command.dataForm.copyToClipboard": "Kopírovať do schránky",
|
||||
@@ -218,6 +234,9 @@
|
||||
"command.datagrid.stopAutoRefresh": "Zastaviť automatické obnovovanie",
|
||||
"command.datagrid.switchToJSON": "Prepnúť na JSON",
|
||||
"command.datagrid.switchToform": "Prepnúť na formulár",
|
||||
"command.datagrid.toggleCellDataView": "Prepnúť zobrazenie dát bunky",
|
||||
"command.datagrid.toggleCellDataView.menu": "Zobraziť dáta bunky",
|
||||
"command.datagrid.toggleCellDataView.toolbar": "Dáta bunky",
|
||||
"command.datagrid.toggleLeftPanel": "Prepnúť ľavý panel",
|
||||
"command.datagrid.undo": "Krok späť",
|
||||
"command.datagrid.viewJsonDocument": "Zobraziť riadok ako JSON dokument",
|
||||
@@ -227,6 +246,7 @@
|
||||
"command.designer": "Návrhár",
|
||||
"command.designer.arrange": "Usporiadať",
|
||||
"command.designer.exportDiagram": "Exportovať diagram",
|
||||
"command.designer.openSql": "Otvoriť SQL",
|
||||
"command.designer.remove": "Odstrániť",
|
||||
"command.designer.removeSelectedTables": "Odstrániť vybrané tabuľky",
|
||||
"command.diagram": "Diagram",
|
||||
@@ -256,6 +276,7 @@
|
||||
"command.internal": "Interné",
|
||||
"command.internal.loadCampaigns": "Načítať zoznam kampaní",
|
||||
"command.internal.showCampaigns": "Zobraziť kampane",
|
||||
"command.jsonl": "JSON Lines editor",
|
||||
"command.jsonl.closePreview": "Zavrieť náhľad",
|
||||
"command.jsonl.preview": "Náhľad",
|
||||
"command.jsonl.previewNewTab": "Náhľad na novej karte",
|
||||
@@ -294,6 +315,13 @@
|
||||
"command.new.tableToolbar": "Nová tabuľka",
|
||||
"command.openQuery": "Otvoriť dotaz",
|
||||
"command.paste": "Prilepiť",
|
||||
"command.perspective": "Perspektíva",
|
||||
"command.perspective.openJson": "Otvoriť JSON",
|
||||
"command.perspective.refresh": "Obnoviť",
|
||||
"command.profiler": "Profilovač",
|
||||
"command.profiler.save": "Uložiť",
|
||||
"command.profiler.start": "Spustiť profilovanie",
|
||||
"command.profiler.stop": "Zastaviť profilovanie",
|
||||
"command.query": "Dotaz",
|
||||
"command.query.AiAssistant": "AI Asistent",
|
||||
"command.query.autocommitOffSwitch": "Automatické potvrdenie: VYPNUTÉ",
|
||||
@@ -368,6 +396,7 @@
|
||||
"commandPalette.searchInDatabase": "Hľadať v databáze",
|
||||
"common.Remove": "Odstrániť",
|
||||
"common.addNew": "Pridať nový",
|
||||
"common.addProvider": "Pridať poskytovateľa",
|
||||
"common.advanced": "Pokročilé",
|
||||
"common.allFields": "Všetky {field}",
|
||||
"common.allFiles": "Všetky súbory",
|
||||
@@ -395,6 +424,7 @@
|
||||
"common.done": "Hotovo",
|
||||
"common.dontAskAgain": "Nabudúce sa nepýtať",
|
||||
"common.download": "Stiahnuť",
|
||||
"common.edit": "Upraviť",
|
||||
"common.erDiagram": "ER Diagram",
|
||||
"common.error": "Chyba",
|
||||
"common.execute": "Spustiť",
|
||||
@@ -451,6 +481,57 @@
|
||||
"common.testingConnection": "Testovanie pripojenia",
|
||||
"common.uncheckAll": "Zrušiť označenie všetkých",
|
||||
"common.zipFiles": "ZIP súbory",
|
||||
"compare.action": "Akcia",
|
||||
"compare.added": "Pridané",
|
||||
"compare.allowDropColumns": "Povoliť odstránenie stĺpcov",
|
||||
"compare.allowDropSqlObjects": "Povoliť odstránenie pohľadov, procedúr atď.",
|
||||
"compare.allowDropTables": "Povoliť odstránenie tabuliek",
|
||||
"compare.allowTableRecreate": "Povoliť znovuvytvorenie tabuľky",
|
||||
"compare.autoinc": "Autoinc",
|
||||
"compare.changed": "Zmenené",
|
||||
"compare.columns": "Stĺpce",
|
||||
"compare.ddl": "DDL",
|
||||
"compare.deletedPrefix": "Prefix pre odstránené",
|
||||
"compare.deployChanges": "Nasadiť zmeny",
|
||||
"compare.deployingDatabaseChanges": "Nasadzovanie zmien databázy",
|
||||
"compare.dontDropColumns": "Neodstraňovať stĺpce",
|
||||
"compare.dontDropConstraints": "Neodstraňovať obmedzenia",
|
||||
"compare.dontDropSqlObjects": "Neodstraňovať objekt",
|
||||
"compare.dontDropTables": "Neodstraňovať tabuľky",
|
||||
"compare.dropColumnsIfMissing": "Odstrániť chýbajúce stĺpce",
|
||||
"compare.dropSqlObjectsIfMissing": "Odstrániť chýbajúci objekt",
|
||||
"compare.dropTablesIfMissing": "Odstrániť chýbajúce tabuľky",
|
||||
"compare.equal": "Zhodné",
|
||||
"compare.errorWhenSaving": "Chyba pri ukladaní",
|
||||
"compare.hideRowsWithoutOperations": "Skryť riadky bez operácií",
|
||||
"compare.ignoreCase": "Ignorovať veľkosť písmen",
|
||||
"compare.ignoreConstraintNames": "Ignorovať názvy obmedzení",
|
||||
"compare.ignoreDataTypes": "Ignorovať dátové typy",
|
||||
"compare.ignoreForeignKeyActions": "Ignorovať akcie cudzích kľúčov",
|
||||
"compare.ignoreNameRegex": "Ignorovať názvy zodpovedajúce regexu",
|
||||
"compare.ignoreSchema": "Ignorovať schému",
|
||||
"compare.loadingDatabaseStructure": "Načítavanie štruktúry databázy",
|
||||
"compare.markColumnsAsDeleted": "Označiť stĺpce ako odstránené",
|
||||
"compare.markSqlObjectsAsDeleted": "Označiť objekt ako odstránený",
|
||||
"compare.markTablesAsDeleted": "Označiť tabuľky ako odstránené",
|
||||
"compare.name": "Názov",
|
||||
"compare.notNull": "Not null",
|
||||
"compare.operations": "Operácie",
|
||||
"compare.removed": "Odstránené",
|
||||
"compare.sameSourceAndTargetDatabasesWarning": "Zdrojová a cieľová databáza sú rovnaké, žiadne rozdiely nebudú nájdené. Zmeňte prosím zdrojovú alebo cieľovú databázu.",
|
||||
"compare.savedToDatabase": "Uložené do databázy",
|
||||
"compare.schema": "Schéma",
|
||||
"compare.searchTablesOrObjects": "Hľadať tabuľky alebo objekty",
|
||||
"compare.settings": "Nastavenia",
|
||||
"compare.sourceDatabase": "Zdrojová databáza",
|
||||
"compare.sourceDbModel": "Zdrojový DB model",
|
||||
"compare.sourceModelTransform": "Zdrojová transformácia modelu",
|
||||
"compare.sourceServer": "Zdrojový server",
|
||||
"compare.synchronizeScript": "Synchronizačný skript",
|
||||
"compare.targetDatabase": "Cieľová databáza",
|
||||
"compare.targetSchema": "Cieľová schéma",
|
||||
"compare.targetServer": "Cieľový server",
|
||||
"compare.type": "Typ",
|
||||
"connection.accessKeyId": "ID prístupového kľúča",
|
||||
"connection.allowedDatabases": "Povolené databázy, jedna na riadok",
|
||||
"connection.allowedDatabasesRegex": "Regulárny výraz pre povolené databázy",
|
||||
@@ -675,6 +756,7 @@
|
||||
"datagrid.searchMacros": "Vyhľadať makrá",
|
||||
"datagrid.setFormat": "Nastaviť formát: ",
|
||||
"datagrid.structure": "Štruktúra",
|
||||
"datagrid.useMacro": "Použiť makro",
|
||||
"dbKeyAddItemModal.header": "Pridať položku",
|
||||
"dbKeysTreeNode.deleteBranch": "Odstrániť vetvu",
|
||||
"dbKeysTreeNode.deleteBranchConfirm": "Naozaj odstrániť vetvu {branch} so všetkými kľúčmi?",
|
||||
@@ -755,6 +837,22 @@
|
||||
"designerTable.newAlias": "Nový alias",
|
||||
"designerTable.removeTableAlias": "Odstrániť alias tabuľky",
|
||||
"designerTable.setTableAlias": "Nastaviť alias tabuľky",
|
||||
"diagram.all": "Všetko",
|
||||
"diagram.allKeys": "Všetky kľúče",
|
||||
"diagram.columnFilter": "Filter stĺpcov",
|
||||
"diagram.exportWatermark": "Exportovať vodoznak",
|
||||
"diagram.keysAndNotNull": "Kľúče a Not Null",
|
||||
"diagram.notNull": "Not Null",
|
||||
"diagram.omitExportWatermark": "Vynechať export vodoznaku",
|
||||
"diagram.omitTablesFilter": "Vynechať tabuľky",
|
||||
"diagram.primaryKey": "Primárny kľúč",
|
||||
"diagram.showColumns": "Zobraziť stĺpce",
|
||||
"diagram.showDataType": "Zobraziť dátový typ",
|
||||
"diagram.showNullability": "Zobraziť NULL/NOT NULL",
|
||||
"diagram.tableFilter": "Filter tabuliek",
|
||||
"diagram.tables": "Tabuľky",
|
||||
"diagram.topTables": "Iba N najdôležitejších tabuliek",
|
||||
"diagram.zoom": "Priblíženie",
|
||||
"dictionaryLookupModal.customize": "Prispôsobiť",
|
||||
"dictionaryLookupModal.description": "Popis",
|
||||
"dictionaryLookupModal.header": "Vyhľadať z {pureName}",
|
||||
@@ -1032,6 +1130,16 @@
|
||||
"newObject.sqlGeneratorDisabled": "SQL Generátor nie je k dispozícii pre aktuálnu databázu",
|
||||
"newObject.tableDescription": "Vytvoriť tabuľku v aktuálnej databáze",
|
||||
"newObject.tableDisabled": "Vytvorenie tabuľky nie je k dispozícii pre aktuálnu databázu",
|
||||
"perspective.arrange": "Usporiadať",
|
||||
"perspective.arranged": "(Usporiadané)",
|
||||
"perspective.category": "Perspektíva",
|
||||
"perspective.chooseData": "Vybrať dáta",
|
||||
"perspective.customJoin": "Vlastný join",
|
||||
"perspective.filters": "Filtre",
|
||||
"perspective.invalidFormat": "Neplatný formát perspektívy, vytvorte prosím novú perspektívu",
|
||||
"perspective.noFiltersDefined": "Nie sú definované žiadne filtre",
|
||||
"perspective.searchColumnOrTable": "Hľadať stĺpec alebo tabuľku",
|
||||
"perspective.useContextMenuAddToFilter": "Použite kontextové menu, príkaz \"Pridať do filtru\" v tabuľke alebo v strome",
|
||||
"plugins.searchExtensionsOnWeb": "Hľadať rozšírenia na webe",
|
||||
"privateCloudWidget.addExistingFolder": "Pridať existujúci priečinok (z odkazu)",
|
||||
"privateCloudWidget.addExistingSharedFolder": "Pridať existujúci zdieľaný priečinok",
|
||||
@@ -1056,6 +1164,7 @@
|
||||
"publicCloudWidget.refreshFiles": "Obnoviť súbory",
|
||||
"publicCloudWidget.refreshList": "Obnoviť zoznam",
|
||||
"publicCloudWidget.searchPublicFiles": "Hľadať verejné súbory",
|
||||
"query.AiAssistant": "AI Asistent",
|
||||
"query.Copy": "Kopírovať",
|
||||
"query.Download": "Stiahnuť",
|
||||
"query.Messages": "Správy",
|
||||
@@ -1064,17 +1173,34 @@
|
||||
"query.OutputFiles": "Výstupné súbory",
|
||||
"query.Show": "Zobraziť",
|
||||
"query.Size": "Veľkosť",
|
||||
"query.addCustomExpression": "Pridať vlastný výraz",
|
||||
"query.addGroupOrCondition": "Pridať skupinu ALEBO podmienku",
|
||||
"query.addOrCondition": "Pridať ALEBO podmienku",
|
||||
"query.aggregate": "Agregácia",
|
||||
"query.alias": "Alias",
|
||||
"query.columnExpression": "Stĺpec/Výraz",
|
||||
"query.download": "stiahnuť",
|
||||
"query.filter": "Filter",
|
||||
"query.groupBy": "Zoskupiť podľa",
|
||||
"query.groupFilter": "Filter skupiny",
|
||||
"query.limitRows": "Obmedziť na {queryRowsLimit} riadkov",
|
||||
"query.named": ":premenná",
|
||||
"query.noParameters": "(žiadne parametre)",
|
||||
"query.noRowsLimit": "(bez limitu riadkov)",
|
||||
"query.orFilter": "OR filter {number}",
|
||||
"query.orGroupFilter": "OR filter skupiny {number}",
|
||||
"query.output": "Výstup",
|
||||
"query.positional": "? (pozíciový)",
|
||||
"query.queryNumber": "Dotaz #",
|
||||
"query.removeDuplicates": "Odstrániť duplicity: {status}",
|
||||
"query.removeGroupOrCondition": "Odstrániť skupinu ALEBO podmienku",
|
||||
"query.removeOrCondition": "Odstrániť ALEBO podmienku",
|
||||
"query.returnOnlyNRows": "Vrátiť iba N riadkov z dotazu",
|
||||
"query.rowsLimit": "Limit riadkov",
|
||||
"query.save": "uložiť",
|
||||
"query.show": "zobraziť",
|
||||
"query.sortOrder": "Poradie zoradenia",
|
||||
"query.table": "Tabuľka",
|
||||
"query.unlimitedRows": "Neobmedzené riadky",
|
||||
"query.variable": "#premenná",
|
||||
"queryParameters.editQueryParameters": "Upraviť parametre dotazu",
|
||||
@@ -1106,6 +1232,35 @@
|
||||
"serverSummaryTab.processes": "Procesy",
|
||||
"serverSummaryTab.variables": "Premenné",
|
||||
"settings.AI": "AI",
|
||||
"settings.aiChatDefaults.heading": "Predvolené nastavenia AI chatu",
|
||||
"settings.aiExecuteMode": "Režim vykonávania SQL",
|
||||
"settings.aiExecuteMode.ask": "Spýtať sa pred vykonaním",
|
||||
"settings.aiExecuteMode.auto": "Vykonať automaticky",
|
||||
"settings.aiExecuteMode.never": "Nikdy nevykonávať SQL",
|
||||
"settings.aiProvider": "AI poskytovateľ",
|
||||
"settings.aiProvider.apiKey": "API kľúč",
|
||||
"settings.aiProvider.apiKeyPlaceholder": "Váš API kľúč (pre lokálnych poskytovateľov nechajte prázdne)",
|
||||
"settings.aiProvider.baseUrl": "Základná URL",
|
||||
"settings.aiProvider.connectionTest.cancel": "Zrušiť test",
|
||||
"settings.aiProvider.connectionTest.retest": "Otestovať pripojenie znova",
|
||||
"settings.aiProvider.connectionTest.test": "Otestovať pripojenie",
|
||||
"settings.aiProvider.connectionTestFailed": "Test pripojenia zlyhal:",
|
||||
"settings.aiProvider.defaultModel": "Predvolený model",
|
||||
"settings.aiProvider.gateway": "DbGate AI Gateway",
|
||||
"settings.aiProvider.name": "Názov poskytovateľa",
|
||||
"settings.aiProvider.newProviderName": "Poskytovateľ {number}",
|
||||
"settings.aiProvider.noDefaultModel": "(Žiadny predvolený model)",
|
||||
"settings.aiProvider.noModelsAvailable": "(Žiadne modely nie sú k dispozícii)",
|
||||
"settings.aiProvider.noUrlConfigured": "Nie je nastavená URL",
|
||||
"settings.aiProvider.removeProviderConfirmation": "Naozaj chcete odstrániť poskytovateľa {provider}?",
|
||||
"settings.aiProvider.status.connectionFailed": "Pripojenie zlyhalo:",
|
||||
"settings.aiProvider.status.error": "Chyba",
|
||||
"settings.aiProvider.status.noModelsFound": "Nenašli sa žiadne modely",
|
||||
"settings.aiProvider.status.notConfigured": "Nenastavené",
|
||||
"settings.aiProvider.status.testing": "Testovanie",
|
||||
"settings.aiProvider.status.testingConnection": "Testovanie pripojenia...",
|
||||
"settings.aiProvider.status.untested": "Netestované",
|
||||
"settings.aiProvider.status.valid": "Platné",
|
||||
"settings.appearance": "Vzhľad aplikácie",
|
||||
"settings.appearance.afterInstalling": "Po nainštalovaní (skúste vyhľadať \"themes\" v dostupných rozšíreniach) budú nové témy k dispozícii tu.",
|
||||
"settings.appearance.customSize": "Vlastná veľkosť",
|
||||
@@ -1130,6 +1285,8 @@
|
||||
"settings.connection.autoRefreshInterval": "Interval medzi automatickým načítaním štruktúry DB (v sekundách)",
|
||||
"settings.connection.showOnlyTabsFromSelectedDatabase": "Zobraziť iba karty z vybranej databázy",
|
||||
"settings.connection.sshBindHost": "Adresa localhostu pre SSH pripojenia",
|
||||
"settings.customProviders.heading": "Vlastní poskytovatelia",
|
||||
"settings.customProviders.noProvidersConfigured": "Nie sú nakonfigurovaní žiadni vlastní poskytovatelia. Začnite kliknutím na \"Pridať poskytovateľa\".",
|
||||
"settings.dataGrid.alignNumbersRight": "Zarovnať čísla doprava",
|
||||
"settings.dataGrid.collectionPageSize": "Veľkosť stránky kolekcie (pre JSON zobrazenie MongoDB, musí byť medzi 5 a 1000)",
|
||||
"settings.dataGrid.coloringMode": "Režim farbenia riadkov",
|
||||
@@ -1142,6 +1299,12 @@
|
||||
"settings.dataGrid.showAllColumnsWhenSearch": "Zobraziť všetky stĺpce pri vyhľadávaní",
|
||||
"settings.dataGrid.showHintColumns": "Zobraziť nápovedy pre cudzie kľúče",
|
||||
"settings.dataGrid.thousandsSeparator": "Použiť oddeľovač tisícov pre čísla",
|
||||
"settings.dataGrid.thousandsSeparator.comma": "Čiarka (,)",
|
||||
"settings.dataGrid.thousandsSeparator.dot": "Bodka (.)",
|
||||
"settings.dataGrid.thousandsSeparator.narrowSpace": "Úzka medzera",
|
||||
"settings.dataGrid.thousandsSeparator.none": "Žiadne",
|
||||
"settings.dataGrid.thousandsSeparator.space": "Medzera",
|
||||
"settings.dataGrid.thousandsSeparator.system": "Systémové",
|
||||
"settings.dataGrid.title": "Mriežka údajov",
|
||||
"settings.defaultActions": "Predvolené akcie",
|
||||
"settings.defaultActions.collectionClick": "Kliknutie na kolekciu NoSQL",
|
||||
@@ -1198,6 +1361,9 @@
|
||||
"settings.sqlEditor.showTableAliasesInCodeCompletion": "Zobraziť aliasy tabuliek v automatickom doplňovaní",
|
||||
"settings.sqlEditor.sqlCommandsCase": "Veľkosť písmen",
|
||||
"settings.sqlEditor.title": "SQL editor",
|
||||
"settings.supportedProviders.description": "Bude fungovať akákoľvek služba kompatibilná s formátom OpenAI API, vrátane:",
|
||||
"settings.supportedProviders.heading": "Podporovaní poskytovatelia",
|
||||
"settings.supportedProviders.useThisProvider": "Použiť tohto poskytovateľa",
|
||||
"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",
|
||||
@@ -1267,6 +1433,11 @@
|
||||
"switchDatabase.server": "Server",
|
||||
"switchDatabase.switchDatabase": "Prepnúť databázu",
|
||||
"tab.administration": "Administrácia",
|
||||
"tableCell.edit": "Upraviť",
|
||||
"tableCell.filterColumns": "Filtrovať stĺpce",
|
||||
"tableCell.hideNullValues": "Skryť NULL hodnoty",
|
||||
"tableCell.multipleValues": "Viacero hodnôt",
|
||||
"tableCell.noDataSelected": "Nie sú vybrané žiadne dáta",
|
||||
"tableData.errorWhenSaving": "Chyba pri ukladaní",
|
||||
"tableData.refreshEvery": "Obnoviť (každých {autoRefreshInterval}s)",
|
||||
"tableData.savedToDatabase": "Uložené do databázy",
|
||||
|
||||
@@ -137,6 +137,8 @@
|
||||
"command.archiveFile": "归档文件",
|
||||
"command.archiveFile.save": "保存",
|
||||
"command.archiveFile.saveAs": "另存为",
|
||||
"command.chart": "图表",
|
||||
"command.chart.export": "导出图表",
|
||||
"command.cloud": "云",
|
||||
"command.cloud.logout": "登出",
|
||||
"command.collectionData": "集合数据",
|
||||
@@ -145,7 +147,21 @@
|
||||
"command.collectionData.save": "保存",
|
||||
"command.commandPalette": "命令面板",
|
||||
"command.commandPalette.show": "显示",
|
||||
"command.compare": "比较模型",
|
||||
"command.compare.deploy": "部署",
|
||||
"command.compare.refresh": "刷新",
|
||||
"command.compare.refreshModels": "刷新模型",
|
||||
"command.compare.report": "报告",
|
||||
"command.compare.reportDiff": "差异报告",
|
||||
"command.compare.swap": "交换",
|
||||
"command.compare.swapSource": "交换源和目标",
|
||||
"command.compareDatabase": "数据库比较",
|
||||
"command.copy": "复制",
|
||||
"command.dataDeploy": "数据部署器",
|
||||
"command.dataDeploy.generateShell": "生成命令行脚本",
|
||||
"command.dataDeploy.generateSql": "生成 SQL",
|
||||
"command.dataDeploy.kill": "终止部署",
|
||||
"command.dataDeploy.run": "部署到数据库",
|
||||
"command.dataForm": "数据表单",
|
||||
"command.dataForm.addToFilter": "添加到筛选",
|
||||
"command.dataForm.copyToClipboard": "复制到剪贴板",
|
||||
@@ -218,6 +234,9 @@
|
||||
"command.datagrid.stopAutoRefresh": "停止自动刷新",
|
||||
"command.datagrid.switchToJSON": "切换到 JSON",
|
||||
"command.datagrid.switchToform": "切换到表单",
|
||||
"command.datagrid.toggleCellDataView": "切换单元格数据视图",
|
||||
"command.datagrid.toggleCellDataView.menu": "显示单元格数据",
|
||||
"command.datagrid.toggleCellDataView.toolbar": "单元格数据",
|
||||
"command.datagrid.toggleLeftPanel": "切换左侧面板",
|
||||
"command.datagrid.undo": "撤销",
|
||||
"command.datagrid.viewJsonDocument": "将行查看为 JSON 文档",
|
||||
@@ -227,6 +246,7 @@
|
||||
"command.designer": "设计器",
|
||||
"command.designer.arrange": "排列",
|
||||
"command.designer.exportDiagram": "导出图表",
|
||||
"command.designer.openSql": "打开 SQL",
|
||||
"command.designer.remove": "删除",
|
||||
"command.designer.removeSelectedTables": "删除选中的表",
|
||||
"command.diagram": "图表",
|
||||
@@ -256,6 +276,7 @@
|
||||
"command.internal": "内部",
|
||||
"command.internal.loadCampaigns": "加载活动列表",
|
||||
"command.internal.showCampaigns": "显示活动",
|
||||
"command.jsonl": "JSON 行编辑器",
|
||||
"command.jsonl.closePreview": "关闭预览",
|
||||
"command.jsonl.preview": "预览",
|
||||
"command.jsonl.previewNewTab": "在新标签页中预览",
|
||||
@@ -294,6 +315,13 @@
|
||||
"command.new.tableToolbar": "新建表",
|
||||
"command.openQuery": "打开查询",
|
||||
"command.paste": "粘贴",
|
||||
"command.perspective": "视图",
|
||||
"command.perspective.openJson": "打开 JSON",
|
||||
"command.perspective.refresh": "刷新",
|
||||
"command.profiler": "分析器",
|
||||
"command.profiler.save": "保存",
|
||||
"command.profiler.start": "开始分析",
|
||||
"command.profiler.stop": "停止分析",
|
||||
"command.query": "查询",
|
||||
"command.query.AiAssistant": "AI 助手",
|
||||
"command.query.autocommitOffSwitch": "自动提交:关",
|
||||
@@ -368,6 +396,7 @@
|
||||
"commandPalette.searchInDatabase": "在数据库中搜索",
|
||||
"common.Remove": "移除",
|
||||
"common.addNew": "添加新项",
|
||||
"common.addProvider": "添加提供方",
|
||||
"common.advanced": "高级",
|
||||
"common.allFields": "所有 {field}",
|
||||
"common.allFiles": "所有文件",
|
||||
@@ -395,6 +424,7 @@
|
||||
"common.done": "完成",
|
||||
"common.dontAskAgain": "不再询问",
|
||||
"common.download": "下载",
|
||||
"common.edit": "编辑",
|
||||
"common.erDiagram": "ER 图",
|
||||
"common.error": "错误",
|
||||
"common.execute": "执行",
|
||||
@@ -451,6 +481,57 @@
|
||||
"common.testingConnection": "正在测试连接",
|
||||
"common.uncheckAll": "取消全选",
|
||||
"common.zipFiles": "ZIP 文件",
|
||||
"compare.action": "操作",
|
||||
"compare.added": "已添加",
|
||||
"compare.allowDropColumns": "允许删除列",
|
||||
"compare.allowDropSqlObjects": "允许删除视图、存储过程等对象",
|
||||
"compare.allowDropTables": "允许删除表",
|
||||
"compare.allowTableRecreate": "允许重新创建表",
|
||||
"compare.autoinc": "自增",
|
||||
"compare.changed": "已更改",
|
||||
"compare.columns": "列",
|
||||
"compare.ddl": "DDL",
|
||||
"compare.deletedPrefix": "删除前缀",
|
||||
"compare.deployChanges": "部署更改",
|
||||
"compare.deployingDatabaseChanges": "正在部署数据库更改",
|
||||
"compare.dontDropColumns": "不删除列",
|
||||
"compare.dontDropConstraints": "不删除约束",
|
||||
"compare.dontDropSqlObjects": "不删除对象",
|
||||
"compare.dontDropTables": "不删除表",
|
||||
"compare.dropColumnsIfMissing": "缺失时删除列",
|
||||
"compare.dropSqlObjectsIfMissing": "缺失时删除对象",
|
||||
"compare.dropTablesIfMissing": "缺失时删除表",
|
||||
"compare.equal": "相同",
|
||||
"compare.errorWhenSaving": "保存时出错",
|
||||
"compare.hideRowsWithoutOperations": "隐藏无操作的行",
|
||||
"compare.ignoreCase": "忽略大小写",
|
||||
"compare.ignoreConstraintNames": "忽略约束名称",
|
||||
"compare.ignoreDataTypes": "忽略数据类型",
|
||||
"compare.ignoreForeignKeyActions": "忽略外键操作",
|
||||
"compare.ignoreNameRegex": "忽略匹配正则表达式的名称",
|
||||
"compare.ignoreSchema": "忽略模式",
|
||||
"compare.loadingDatabaseStructure": "正在加载数据库结构",
|
||||
"compare.markColumnsAsDeleted": "将列标记为已删除",
|
||||
"compare.markSqlObjectsAsDeleted": "将对象标记为已删除",
|
||||
"compare.markTablesAsDeleted": "将表标记为已删除",
|
||||
"compare.name": "名称",
|
||||
"compare.notNull": "非空",
|
||||
"compare.operations": "操作",
|
||||
"compare.removed": "已删除",
|
||||
"compare.sameSourceAndTargetDatabasesWarning": "源数据库和目标数据库相同,将不会发现差异。请更改源或目标数据库。",
|
||||
"compare.savedToDatabase": "已保存到数据库",
|
||||
"compare.schema": "模式",
|
||||
"compare.searchTablesOrObjects": "搜索表或对象",
|
||||
"compare.settings": "设置",
|
||||
"compare.sourceDatabase": "源数据库",
|
||||
"compare.sourceDbModel": "源数据库模型",
|
||||
"compare.sourceModelTransform": "源模型转换",
|
||||
"compare.sourceServer": "源服务器",
|
||||
"compare.synchronizeScript": "同步脚本",
|
||||
"compare.targetDatabase": "目标数据库",
|
||||
"compare.targetSchema": "目标模式",
|
||||
"compare.targetServer": "目标服务器",
|
||||
"compare.type": "类型",
|
||||
"connection.accessKeyId": "访问密钥 ID",
|
||||
"connection.allowedDatabases": "允许的数据库,每行一个",
|
||||
"connection.allowedDatabasesRegex": "允许的数据库正则表达式",
|
||||
@@ -675,6 +756,7 @@
|
||||
"datagrid.searchMacros": "搜索宏",
|
||||
"datagrid.setFormat": "设置格式:",
|
||||
"datagrid.structure": "结构",
|
||||
"datagrid.useMacro": "使用宏",
|
||||
"dbKeyAddItemModal.header": "添加项",
|
||||
"dbKeysTreeNode.deleteBranch": "删除分支",
|
||||
"dbKeysTreeNode.deleteBranchConfirm": "确定删除分支 {branch} 及其所有键吗?",
|
||||
@@ -755,6 +837,22 @@
|
||||
"designerTable.newAlias": "新建别名",
|
||||
"designerTable.removeTableAlias": "移除表别名",
|
||||
"designerTable.setTableAlias": "设置表别名",
|
||||
"diagram.all": "全部",
|
||||
"diagram.allKeys": "所有键",
|
||||
"diagram.columnFilter": "列筛选",
|
||||
"diagram.exportWatermark": "导出水印",
|
||||
"diagram.keysAndNotNull": "键和非空",
|
||||
"diagram.notNull": "非空",
|
||||
"diagram.omitExportWatermark": "省略导出水印",
|
||||
"diagram.omitTablesFilter": "省略表",
|
||||
"diagram.primaryKey": "主键",
|
||||
"diagram.showColumns": "显示列",
|
||||
"diagram.showDataType": "显示数据类型",
|
||||
"diagram.showNullability": "显示 NULL/NOT NULL",
|
||||
"diagram.tableFilter": "表筛选",
|
||||
"diagram.tables": "表",
|
||||
"diagram.topTables": "仅显示最重要的 N 个表",
|
||||
"diagram.zoom": "缩放",
|
||||
"dictionaryLookupModal.customize": "自定义",
|
||||
"dictionaryLookupModal.description": "描述",
|
||||
"dictionaryLookupModal.header": "从 {pureName} 查找",
|
||||
@@ -1032,6 +1130,16 @@
|
||||
"newObject.sqlGeneratorDisabled": "当前数据库不支持SQL生成器",
|
||||
"newObject.tableDescription": "在当前数据库中创建表",
|
||||
"newObject.tableDisabled": "当前数据库不支持创建表",
|
||||
"perspective.arrange": "排列",
|
||||
"perspective.arranged": "(已排列)",
|
||||
"perspective.category": "视图",
|
||||
"perspective.chooseData": "选择数据",
|
||||
"perspective.customJoin": "自定义联接",
|
||||
"perspective.filters": "筛选",
|
||||
"perspective.invalidFormat": "视图格式无效,请创建新视图",
|
||||
"perspective.noFiltersDefined": "未定义筛选",
|
||||
"perspective.searchColumnOrTable": "搜索列或表",
|
||||
"perspective.useContextMenuAddToFilter": "在表或树中使用右键菜单命令“添加到筛选”",
|
||||
"plugins.searchExtensionsOnWeb": "在网页上搜索扩展",
|
||||
"privateCloudWidget.addExistingFolder": "添加现有文件夹(来自链接)",
|
||||
"privateCloudWidget.addExistingSharedFolder": "添加现有共享文件夹",
|
||||
@@ -1056,6 +1164,7 @@
|
||||
"publicCloudWidget.refreshFiles": "刷新文件",
|
||||
"publicCloudWidget.refreshList": "刷新列表",
|
||||
"publicCloudWidget.searchPublicFiles": "搜索公共文件",
|
||||
"query.AiAssistant": "AI 助手",
|
||||
"query.Copy": "复制",
|
||||
"query.Download": "下载",
|
||||
"query.Messages": "消息",
|
||||
@@ -1064,17 +1173,34 @@
|
||||
"query.OutputFiles": "输出文件",
|
||||
"query.Show": "显示",
|
||||
"query.Size": "大小",
|
||||
"query.addCustomExpression": "添加自定义表达式",
|
||||
"query.addGroupOrCondition": "添加分组或条件",
|
||||
"query.addOrCondition": "添加 OR 条件",
|
||||
"query.aggregate": "聚合",
|
||||
"query.alias": "别名",
|
||||
"query.columnExpression": "列/表达式",
|
||||
"query.download": "下载",
|
||||
"query.filter": "筛选",
|
||||
"query.groupBy": "分组依据",
|
||||
"query.groupFilter": "分组筛选",
|
||||
"query.limitRows": "限制 {queryRowsLimit} 行",
|
||||
"query.named": ":variable",
|
||||
"query.noParameters": "(无参数)",
|
||||
"query.noRowsLimit": "(无行数限制)",
|
||||
"query.orFilter": "OR 筛选 {number}",
|
||||
"query.orGroupFilter": "OR 分组筛选 {number}",
|
||||
"query.output": "输出",
|
||||
"query.positional": "? (位置)",
|
||||
"query.queryNumber": "查询 #",
|
||||
"query.removeDuplicates": "删除重复:{status}",
|
||||
"query.removeGroupOrCondition": "删除分组或条件",
|
||||
"query.removeOrCondition": "删除 OR 条件",
|
||||
"query.returnOnlyNRows": "仅从查询返回 N 行",
|
||||
"query.rowsLimit": "行数限制",
|
||||
"query.save": "保存",
|
||||
"query.show": "显示",
|
||||
"query.sortOrder": "排序顺序",
|
||||
"query.table": "表",
|
||||
"query.unlimitedRows": "不限行数",
|
||||
"query.variable": "#variable",
|
||||
"queryParameters.editQueryParameters": "编辑查询参数",
|
||||
@@ -1106,6 +1232,35 @@
|
||||
"serverSummaryTab.processes": "进程",
|
||||
"serverSummaryTab.variables": "变量",
|
||||
"settings.AI": "AI",
|
||||
"settings.aiChatDefaults.heading": "AI 聊天默认设置",
|
||||
"settings.aiExecuteMode": "SQL 执行模式",
|
||||
"settings.aiExecuteMode.ask": "执行前询问",
|
||||
"settings.aiExecuteMode.auto": "自动执行",
|
||||
"settings.aiExecuteMode.never": "从不执行 SQL",
|
||||
"settings.aiProvider": "AI 提供方",
|
||||
"settings.aiProvider.apiKey": "API 密钥",
|
||||
"settings.aiProvider.apiKeyPlaceholder": "您的 API 密钥(本地提供方可留空)",
|
||||
"settings.aiProvider.baseUrl": "基础 URL",
|
||||
"settings.aiProvider.connectionTest.cancel": "取消测试",
|
||||
"settings.aiProvider.connectionTest.retest": "重新测试连接",
|
||||
"settings.aiProvider.connectionTest.test": "测试连接",
|
||||
"settings.aiProvider.connectionTestFailed": "连接测试失败:",
|
||||
"settings.aiProvider.defaultModel": "默认模型",
|
||||
"settings.aiProvider.gateway": "DbGate AI 网关",
|
||||
"settings.aiProvider.name": "提供方名称",
|
||||
"settings.aiProvider.newProviderName": "提供方 {number}",
|
||||
"settings.aiProvider.noDefaultModel": "(无默认模型)",
|
||||
"settings.aiProvider.noModelsAvailable": "(无可用模型)",
|
||||
"settings.aiProvider.noUrlConfigured": "未配置 URL",
|
||||
"settings.aiProvider.removeProviderConfirmation": "确定要移除提供方 {provider} 吗?",
|
||||
"settings.aiProvider.status.connectionFailed": "连接失败:",
|
||||
"settings.aiProvider.status.error": "错误",
|
||||
"settings.aiProvider.status.noModelsFound": "未找到模型",
|
||||
"settings.aiProvider.status.notConfigured": "未配置",
|
||||
"settings.aiProvider.status.testing": "正在测试",
|
||||
"settings.aiProvider.status.testingConnection": "正在测试连接...",
|
||||
"settings.aiProvider.status.untested": "未测试",
|
||||
"settings.aiProvider.status.valid": "有效",
|
||||
"settings.appearance": "应用程序主题",
|
||||
"settings.appearance.afterInstalling": "安装主题插件后(尝试在可用扩展中搜索\"主题\"),新主题将在此处可用。",
|
||||
"settings.appearance.customSize": "自定义大小",
|
||||
@@ -1130,6 +1285,8 @@
|
||||
"settings.connection.autoRefreshInterval": "自动重新加载数据库结构的间隔(秒)",
|
||||
"settings.connection.showOnlyTabsFromSelectedDatabase": "仅显示来自选定数据库的标签页",
|
||||
"settings.connection.sshBindHost": "SSH连接的本地主机地址",
|
||||
"settings.customProviders.heading": "自定义提供方",
|
||||
"settings.customProviders.noProvidersConfigured": "尚未配置自定义提供方。点击“添加提供方”开始配置。",
|
||||
"settings.dataGrid.alignNumbersRight": "数字右对齐",
|
||||
"settings.dataGrid.collectionPageSize": "集合页面大小(用于MongoDB JSON视图,必须在5到1000之间)",
|
||||
"settings.dataGrid.coloringMode": "行颜色模式",
|
||||
@@ -1142,6 +1299,12 @@
|
||||
"settings.dataGrid.showAllColumnsWhenSearch": "搜索时显示所有列",
|
||||
"settings.dataGrid.showHintColumns": "显示外键提示",
|
||||
"settings.dataGrid.thousandsSeparator": "数字使用千位分隔符",
|
||||
"settings.dataGrid.thousandsSeparator.comma": "逗号 (,)",
|
||||
"settings.dataGrid.thousandsSeparator.dot": "点号 (.)",
|
||||
"settings.dataGrid.thousandsSeparator.narrowSpace": "窄空格",
|
||||
"settings.dataGrid.thousandsSeparator.none": "无",
|
||||
"settings.dataGrid.thousandsSeparator.space": "空格",
|
||||
"settings.dataGrid.thousandsSeparator.system": "系统",
|
||||
"settings.dataGrid.title": "数据网格",
|
||||
"settings.defaultActions": "默认操作",
|
||||
"settings.defaultActions.collectionClick": "NoSQL集合点击",
|
||||
@@ -1198,6 +1361,9 @@
|
||||
"settings.sqlEditor.showTableAliasesInCodeCompletion": "在代码完成中显示表别名",
|
||||
"settings.sqlEditor.sqlCommandsCase": "SQL命令大小写",
|
||||
"settings.sqlEditor.title": "SQL 编辑器",
|
||||
"settings.supportedProviders.description": "任何兼容 OpenAI API 格式的服务都可以使用,包括:",
|
||||
"settings.supportedProviders.heading": "支持的提供方",
|
||||
"settings.supportedProviders.useThisProvider": "使用此提供方",
|
||||
"settings.tabGroup.showServerName": "在标签页组标题中显示服务器名称和数据库名称",
|
||||
"settings.tabPreviewMode": "标签页预览模式",
|
||||
"settings.theme": "主题",
|
||||
@@ -1267,6 +1433,11 @@
|
||||
"switchDatabase.server": "服务器",
|
||||
"switchDatabase.switchDatabase": "切换数据库",
|
||||
"tab.administration": "管理",
|
||||
"tableCell.edit": "编辑",
|
||||
"tableCell.filterColumns": "筛选列",
|
||||
"tableCell.hideNullValues": "隐藏 NULL 值",
|
||||
"tableCell.multipleValues": "多个值",
|
||||
"tableCell.noDataSelected": "未选择数据",
|
||||
"tableData.errorWhenSaving": "保存时出错",
|
||||
"tableData.refreshEvery": "刷新(每 {autoRefreshInterval} 秒)",
|
||||
"tableData.savedToDatabase": "已保存到数据库",
|
||||
|
||||
@@ -3,11 +3,16 @@ name: Cypress tests with screenshots PREMIUM
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- stable
|
||||
- master
|
||||
- develop
|
||||
- 'feature/**'
|
||||
- hotfix/**
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
e2e-tests:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -63,7 +68,7 @@ jobs:
|
||||
path: screenshots
|
||||
|
||||
- name: Push E2E screenshots
|
||||
if: ${{ github.ref_name == 'master' }}
|
||||
if: ${{ github.ref_name == 'stable' }}
|
||||
run: |
|
||||
git config --global user.email "info@dbgate.info"
|
||||
git config --global user.name "GitHub Actions"
|
||||
|
||||
@@ -7,7 +7,7 @@ checkout-and-merge-pro:
|
||||
repository: dbgate/dbgate-pro
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: dbgate-pro
|
||||
ref: ae1fcf6e61c6f7dfbb21005daa259c68e899a80a
|
||||
ref: 2a71bec538f8e2cf6c1cd1322d89e64346a139fd
|
||||
- name: Merge dbgate/dbgate-pro
|
||||
run: |
|
||||
mkdir ../dbgate-pro
|
||||
|
||||
@@ -8,6 +8,10 @@ on:
|
||||
- 'feature/**'
|
||||
- hotfix/**
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
all-tests:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
Reference in New Issue
Block a user