Compare commits

...

111 Commits

Author SHA1 Message Date
Jan Prochazka efaa4893bf v6.8.2 2025-12-29 14:08:42 +01:00
Jan Prochazka be8580cc4b v6.8.2-premium-beta.1 2025-12-29 11:20:21 +01:00
Jan Prochazka e43bb3123b fixed connections scaffold for postgres 2025-12-29 11:19:58 +01:00
SPRINX0\prochazka 0dba4ba653 changelog 2025-12-22 11:52:23 +01:00
SPRINX0\prochazka 758d8689ab v6.8.1 2025-12-22 11:51:25 +01:00
SPRINX0\prochazka 2c14530e3c fixded data grid column click scroll #1303 2025-12-22 08:20:23 +01:00
SPRINX0\prochazka 1f19d1925a screenshots only from stable branch 2025-12-19 13:23:02 +01:00
SPRINX0\prochazka dedfe1f421 SYNC: filter by expanded column 2025-12-18 15:57:53 +00:00
SPRINX0\prochazka 1cf583d197 SYNC: fix 2025-12-18 15:34:37 +00:00
SPRINX0\prochazka 63693f908d SYNC: group by screenshot 2025-12-18 15:12:29 +00:00
CI workflows 4489a54e82 chore: auto-update github workflows 2025-12-18 14:17:05 +00:00
CI workflows 6d48915945 Update pro ref 2025-12-18 14:16:46 +00:00
SPRINX0\prochazka 00f3a7f4db SYNC: translations 2025-12-18 11:48:40 +00:00
SPRINX0\prochazka c5ebc01978 v6.8.0 2025-12-17 15:38:39 +01:00
SPRINX0\prochazka f29b468fc1 changelog 2025-12-17 15:33:41 +01:00
SPRINX0\prochazka e796fbb990 save export jobs only in proapp 2025-12-17 14:58:12 +01:00
CI workflows 37a122c981 chore: auto-update github workflows 2025-12-17 13:42:41 +00:00
CI workflows 4f426a73f6 Update pro ref 2025-12-17 13:42:25 +00:00
Jan Prochazka 1bcb74cd85 SYNC: Merge pull request #20 from dbgate/feature/sfill2 2025-12-17 13:42:13 +00:00
SPRINX0\prochazka cd88c8de78 v6.7.4-premium-beta.2 2025-12-17 12:28:27 +01:00
CI workflows eee288b45b chore: auto-update github workflows 2025-12-17 11:27:35 +00:00
CI workflows 797cb7615d Update pro ref 2025-12-17 11:27:20 +00:00
Jan Prochazka ca4667ff1e SYNC: Merge pull request #19 from dbgate/feature/sfill 2025-12-17 11:27:08 +00:00
Jan Prochazka 66d1143ca0 replicator - support for skip update columns 2025-12-16 14:43:44 +01:00
SPRINX0\prochazka f310916c76 SYNC: fix 2025-12-16 09:30:38 +00:00
SPRINX0\prochazka 5d3d8ab932 v6.7.4-beta.1 2025-12-16 09:02:17 +01:00
SPRINX0\prochazka fd91c18460 SYNC: fixed e2e tests + new form cell view test 2025-12-15 15:03:43 +00:00
Jan Prochazka 2a12c04518 Merge pull request #1299 from dbgate/feature/wordwrap-editor
Feature/wordwrap editor
2025-12-15 13:26:54 +01:00
CI workflows d08cae6fa3 chore: auto-update github workflows 2025-12-15 12:23:33 +00:00
SPRINX0\prochazka d7f9de1881 concurrency settings for workflows 2025-12-15 13:23:10 +01:00
SPRINX0\prochazka 962190cc57 SYNC: code cleanup 2025-12-15 12:08:07 +00:00
SPRINX0\prochazka 4527866276 SYNC: form cell view - show JSON 2025-12-15 12:08:05 +00:00
SPRINX0\prochazka 088dfcd4dc SYNC: renamed table cell view => form cell view 2025-12-15 12:08:03 +00:00
SPRINX0\prochazka 6c317b6e64 SYNC: table cell view - single click 2025-12-15 12:08:01 +00:00
SPRINX0\prochazka 6b66c273b4 SYNC: fixed display numbers 2025-12-15 12:07:59 +00:00
SPRINX0\prochazka 60f31008c0 SYNC: table cell view UX 2025-12-15 12:07:58 +00:00
SPRINX0\prochazka 078f74db97 SYNC: cell data - allow to edit 2025-12-15 12:07:56 +00:00
SPRINX0\prochazka a0b025cf59 SYNC: Run macro context menu 2025-12-15 12:07:54 +00:00
SPRINX0\prochazka bc695f5af9 SYNC: run macro WIP 2025-12-15 12:07:52 +00:00
SPRINX0\prochazka 9685e63b09 SYNC: table cell view refactor 2025-12-15 12:07:50 +00:00
SPRINX0\prochazka 142791360c SYNC: working widget resizing 2025-12-15 12:07:48 +00:00
SPRINX0\prochazka e004ed2f4b SYNC: widget bar fix 2025-12-15 12:07:47 +00:00
SPRINX0\prochazka 23ed487252 SYNC: fix 2025-12-15 12:07:45 +00:00
SPRINX0\prochazka efefec3c20 SYNC: widgetbar refactor 2025-12-15 12:07:43 +00:00
SPRINX0\prochazka 3d2ad1cb9b SYNC: resize WIP 2025-12-15 12:07:41 +00:00
SPRINX0\prochazka 90d3016938 SYNC: resize heights 2025-12-15 12:07:39 +00:00
SPRINX0\prochazka 438f9fc94d SYNC: better widget panel height processing 2025-12-15 12:07:37 +00:00
SPRINX0\prochazka 82ec88cc2f SYNC: recompute WIP 2025-12-15 12:07:36 +00:00
SPRINX0\prochazka 149611041e SYNC: widget configuration saved to storage 2025-12-15 12:07:33 +00:00
SPRINX0\prochazka b12c79462e SYNC: widget column bar update 2025-12-15 12:07:31 +00:00
SPRINX0\prochazka fbf34fb730 SYNC: widgetcolumnbar refactor 2025-12-15 12:07:29 +00:00
SPRINX0\prochazka e1fe3eb710 SYNC: widgetcolumnbar props 2025-12-15 12:07:27 +00:00
SPRINX0\prochazka 76ae2e0e5a SYNC: improved data grid navigation 2025-12-15 12:07:25 +00:00
SPRINX0\prochazka a57063adf7 SYNC: refactor 2025-12-15 12:07:24 +00:00
SPRINX0\prochazka ff0157e624 SYNC: autodetect data grid cell 2025-12-15 12:07:22 +00:00
SPRINX0\prochazka af9701feb8 SYNC: cell data view 2025-12-15 12:07:20 +00:00
SPRINX0\prochazka 93c1f31588 SYNC: removed selectedCellsCallback 2025-12-15 12:07:17 +00:00
SPRINX0\prochazka 1964e54476 SYNC: cell data widget moved 2025-12-15 12:07:15 +00:00
Stela Augustinova 4682255d5f Refactor SQL editor settings layout and update word wrap field type 2025-12-15 13:02:11 +01:00
Stela Augustinova a503898b21 Refactor SQL editor to integrate word wrap settings and remove redundant options in QueryTab 2025-12-15 12:44:04 +01:00
Stela Augustinova 21352dae07 Revert "Implement word wrap feature in SQL editor and settings"
This reverts commit 28aa86f0aa.
2025-12-15 12:37:15 +01:00
Jan Prochazka 8470c7ac6b Merge pull request #1297 from dbgate/feature/redis-number-of-db
Retrieve the number of databases from Redis configuration
2025-12-15 10:50:53 +01:00
Stela Augustinova 28aa86f0aa Implement word wrap feature in SQL editor and settings 2025-12-14 17:26:25 +01:00
Stela Augustinova 3ed214269a Retrieve the number of databases from Redis configuration 2025-12-12 11:15:26 +01:00
SPRINX0\prochazka a71129df4b SYNC: AI assistant 2025-12-10 07:13:16 +00:00
SPRINX0\prochazka de6acfa1ce Revert "Revert "MPR archive""
This reverts commit ccf075dc65.
2025-12-10 07:48:30 +01:00
SPRINX0\prochazka ccf075dc65 Revert "MPR archive"
This reverts commit 391d04b45c.
2025-12-10 07:36:03 +01:00
SPRINX0\prochazka 1d8ac3cf86 Revert "MPR advanced exports"
This reverts commit 864797fc99.
2025-12-10 07:36:03 +01:00
Jan Prochazka 7a8ff89c5c Merge pull request #1293 from dbgate/feature/FK-test
Feature/fk test
2025-12-09 16:22:29 +01:00
CI workflows eda70def2a chore: auto-update github workflows 2025-12-09 15:02:50 +00:00
CI workflows 08fd75edc7 Update pro ref 2025-12-09 15:02:30 +00:00
Jan Prochazka 15ea53864f SYNC: Merge pull request #18 from dbgate/feature/translation5 2025-12-09 15:02:19 +00:00
Jan Prochazka 377cd64556 Revert "try to comment out earlier patch"
This reverts commit 955ca99cf3.
2025-12-09 12:56:47 +01:00
Stela Augustinova b37744d574 Merge pull request #1296 from dbgate/feature/map-autodetect-lat-lon
Feature/map autodetect lat lon
2025-12-09 11:01:49 +01:00
Stela Augustinova a7f21fe0c6 Merge pull request #1292 from dbgate/feature/table-cell-data-view
Feature/table cell data view
2025-12-09 11:00:19 +01:00
Jan Prochazka 955ca99cf3 try to comment out earlier patch 2025-12-09 10:46:25 +01:00
Jan Prochazka 98f5bb4124 sanitize constraints 2025-12-09 10:45:38 +01:00
Jan Prochazka b3943f005d alter table fixed 2025-12-08 17:35:29 +01:00
Jan Prochazka 8d4178b984 grouped table recreates 2025-12-08 16:57:09 +01:00
Stela Augustinova 2a88ed38c4 Added translation tags to TableCellView component, updated decimal handling 2025-12-08 16:45:18 +01:00
Jan Prochazka 52dce7dfd3 disabled grouping recreate table OPs 2025-12-08 16:41:55 +01:00
Stela Augustinova 6ebee92542 Merge branch 'master' into feature/table-cell-data-view 2025-12-08 16:07:55 +01:00
Jan Prochazka 1b5646f526 Revert "fix: correct reference from wholeNewDb to wholeOldDb in AlterPlan class"
This reverts commit 12e6afbaad.
2025-12-08 16:05:50 +01:00
Jan Prochazka 7024e4b40d Merge pull request #1289 from dbgate/feature/postgresql-decimal
Postgresql decimal
2025-12-08 15:42:19 +01:00
Jan Prochazka bc2e27d7da Merge pull request #1290 from david-pivonka/feature/table-cell-data-view
Add Table format to Cell data view sidebar
2025-12-08 15:35:35 +01:00
Jan Prochazka 189da2bfe2 Merge pull request #1291 from david-pivonka/fix/map-autodetect-lat-lon
Improve Map view lat/lon field autodetection
2025-12-08 15:33:58 +01:00
Stela Augustinova 12e6afbaad fix: correct reference from wholeNewDb to wholeOldDb in AlterPlan class 2025-12-08 15:27:45 +01:00
David Pivoňka 142ebe3d27 Fix scrolling in Table - Row view
Use absolute positioning pattern for proper scrolling behavior
when many columns are displayed.
2025-12-08 15:23:59 +01:00
Stela Augustinova 7579f6e42a fix: comment out incremental analysis in testTableDiff and correct clickhouse image reference 2025-12-08 15:19:27 +01:00
David Pivoňka 38c25cae74 Add multi-row selection support with bulk editing
- Show "(Multiple values)" when selected rows have different values
- Allow bulk editing: changes apply to all selected rows
- Rename format to "Table - Row" for clarity
2025-12-08 15:01:02 +01:00
David Pivoňka 408496eb7c Improve Map view lat/lon field autodetection
Prioritize field names that are more likely to be actual latitude/longitude
fields instead of randomly selecting the first numeric field containing
"lat" or "lon" in its name.
2025-12-08 14:42:56 +01:00
Jan Prochazka 4d61c74a8b fixed tes on CI 2025-12-08 14:34:45 +01:00
David Pivoňka 190c610466 Add column filter/search to Table cell data view
Adds a search input at the top of the Table view that filters columns
by name with regex support.
2025-12-08 14:31:38 +01:00
Jan Prochazka 85b7e3ebe3 fixed sqlite test folder 2025-12-08 14:18:28 +01:00
David Pivoňka d220525ac7 Use braces for isChangedRef.get() blocks to match codebase style 2025-12-08 13:47:35 +01:00
David Pivoňka 5e4a631ff2 Remove comments and apply early return pattern 2025-12-08 13:43:41 +01:00
David Pivoňka 9099ce42b9 Add Table format to Cell data view sidebar
Adds a new "Table" format option to the Cell data view widget that
displays the selected row as a vertical list with column names above
values, inspired by TablePlus.

Features:
- Shows all columns from the selected row in grid display order
- Inline editing support for regular values (double-click to edit)
- JSON values open Edit Cell modal on double-click
- Open-in-new button for JSON values to view in JSON tab
2025-12-08 13:37:55 +01:00
Jan Prochazka df226fea22 import test - greater timeout 2025-12-08 13:12:08 +01:00
Jan Prochazka 851d2e9151 fixed double drop constraint 2025-12-08 13:05:38 +01:00
SPRINX0\prochazka 89121a2608 handled UTF-8 BOM in CSV input 2025-12-04 16:44:08 +01:00
SPRINX0\prochazka 23cf264d4d fix 2025-12-04 16:29:06 +01:00
Stela Augustinova b3130225b5 Filter out primary key columns in nullability change tests 2025-12-04 14:53:08 +01:00
Stela Augustinova 65512defed Merge branch 'master' into feature/FK-test 2025-12-04 14:36:14 +01:00
Stela Augustinova 3b1c8748f1 Add createForeignKeyFore method to handle foreign key creation (Oracle) 2025-12-04 14:34:26 +01:00
Stela Augustinova aba660eddb Fix nullability filter in alter table tests 2025-12-04 14:08:22 +01:00
Stela Augustinova 137eac7dbf Add dropColumnDependencies property to dialect configuration 2025-12-04 14:07:55 +01:00
Stela Augustinova fdbd08f511 Added FK constraint type for sqlite 2025-12-04 13:00:06 +01:00
Stela Augustinova ace1cec1f6 Delete FK from drop column 2025-12-04 10:00:48 +01:00
Stela Augustinova fa5fda0c3b Incremental analysis 2025-12-03 15:31:05 +01:00
Stela Augustinova 251609e274 Update foreign key references when dropping or renaming columns in alter table tests 2025-12-03 15:21:12 +01:00
Stela Augustinova c0287e49d8 FK test 2025-12-03 14:28:58 +01:00
100 changed files with 4462 additions and 589 deletions
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+4 -1
View File
@@ -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
+3
View File
@@ -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
View File
@@ -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
+41 -6
View File
@@ -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');
});
});
+4 -4
View File
@@ -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');
});
});
+32 -10
View File
@@ -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');
})
);
});
+1 -1
View File
@@ -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
+3 -1
View File
@@ -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
View File
@@ -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",
+46
View File
@@ -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
+1
View File
@@ -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",
+11 -49
View File
@@ -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,
+2 -2
View File
@@ -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;
}
}
+1
View File
@@ -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
+171 -2
View File
@@ -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": {
+454
View File
@@ -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,
};
+7 -1
View File
@@ -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;
+75 -9
View File
@@ -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
View File
@@ -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>
+11 -1
View File
@@ -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'])}
/>
+1 -1
View File
@@ -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);
// }
+72 -25
View File
@@ -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}
+135 -37
View File
@@ -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>
+18
View File
@@ -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)));
+19 -11
View File
@@ -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>
+9 -5
View File
@@ -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 -2
View File
@@ -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">
+2 -2
View File
@@ -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>
+4 -1
View File
@@ -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>
-1
View File
@@ -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,
+5 -1
View File
@@ -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>
+8 -2
View File
@@ -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>
+1 -2
View File
@@ -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 }));
}}
+36 -21
View File
@@ -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(),
+50 -32
View File
@@ -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={() =>
+33 -7
View File
@@ -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>
+1
View File
@@ -129,6 +129,7 @@
<ToolStripCommandButton command="dataGrid.refresh" />
<ToolStripExportButton {quickExportHandlerRef} />
<ToolStripCommandButton command="dataGrid.toggleCellDataView" hideDisabled />
</svelte:fragment>
</ToolStripContainer>
{/if}
+2 -2
View File
@@ -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,
},
+3
View File
@@ -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>
+31 -13
View File
@@ -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>&nbsp;</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>
+3 -3
View File
@@ -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>
+64 -25
View File
@@ -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;
});
+171
View File
@@ -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",
+171
View File
@@ -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
View File
@@ -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"
}
+171
View File
@@ -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",
+171
View File
@@ -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",
+171
View File
@@ -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",
+171
View File
@@ -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": "データベースに保存しました",
+171
View File
@@ -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",
+171
View File
@@ -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",
+171
View File
@@ -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": "已保存到数据库",
+6 -1
View File
@@ -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"
+1 -1
View File
@@ -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
+4
View File
@@ -8,6 +8,10 @@ on:
- 'feature/**'
- hotfix/**
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
all-tests:
runs-on: ubuntu-latest