1
1
mirror of https://github.com/Fabio286/antares.git synced 2025-06-05 21:59:22 +02:00

Compare commits

...

59 Commits

Author SHA1 Message Date
4adbc575c2 chore(release): 0.7.34 2025-02-14 20:33:55 +01:00
eb706c3e51 fix: issue with some SSH connections, definitely 2025-02-14 20:30:47 +01:00
971df3a989 chore(release): 0.7.33 2025-02-14 18:03:57 +01:00
3129bf4baa fix: issue with some SSH connections, fixes #947 2025-02-14 17:58:49 +01:00
c6d67cef01 chore(release): 0.7.32 2025-02-14 09:12:05 +01:00
1d7053ce03 fix: black background with light theme, fixes #945 2025-02-14 09:08:45 +01:00
41e797f9e2 fix(PostgreSQL): error with materialized view tabs 2025-02-13 18:01:19 +01:00
704f70819b fix: improve error handling in SSH connection 2025-02-12 18:10:27 +01:00
49a3589536 fix: enhance SVG support in connection customization, fixes #939 2025-02-12 18:09:11 +01:00
49ada059bc chore(release): 0.7.31 2025-02-11 18:22:37 +01:00
8003d3eb1e chore(release): 0.7.31-beta.5 2025-02-09 10:19:09 +01:00
48cfa67889 perf: improve button styles of notes 2025-02-09 10:17:38 +01:00
9cda38e9d1 perf(MySQL): long loading in table settings when no checks present 2025-02-06 18:25:27 +01:00
72f8d4249f fix: improve BLOB primary fields management, fixes #938 2025-02-06 13:28:12 +01:00
0f93d70417 fix: unable to delete rows from context menu 2025-02-06 13:27:02 +01:00
580bef76ba fix: replace 'this.addNotification' with 'addNotification' in useResultTables.ts 2025-02-06 13:25:57 +01:00
7595e89223 fix(devtoolsInstaller): improve file path handling and increase chromium version 2025-02-06 12:50:45 +01:00
7af44d4a2c refactor: add ciaplu for pattern matching in language detection and MIME type resolution 2025-02-05 15:34:01 +01:00
0479e5307c fix(Linux): restored AppImage auto updates 2025-02-03 18:14:38 +01:00
d03c1b90ce chore(release): 0.7.31-beta.4 2025-01-31 18:06:58 +01:00
d34e56a517 fix(Linux): missing window management icons 2025-01-31 18:06:16 +01:00
0f35814ca0 chore(release): 0.7.31-beta.3 2025-01-31 17:54:25 +01:00
96ae09feca feat: implement a better query splitter for SQL queries, fixes #926 2025-01-31 17:28:58 +01:00
e3b30359bf refactor: disable auto opening dev tools in development mode 2025-01-31 13:33:42 +01:00
f3c3284fd1 ci: add GitHub Actions workflow for creating Windows APPX artifacts 2025-01-31 13:32:44 +01:00
27387f18a1 fix(MySQL): adjust utf8mb3 encoding to resolve compatibility issue, fixes #646 2025-01-31 13:32:06 +01:00
8e54f7b801 feat(Linux): update title bar for better Linux experience 2025-01-30 18:01:56 +01:00
70aae2f194 chore(release): 0.7.31-beta.2 2025-01-30 16:16:14 +01:00
592d7b3517 feat: add developer tools and refresh buttons to console in development mode 2025-01-23 18:10:37 +01:00
2b743a2c79 Merge pull request #925 from dyaskur/develop
fix: fail to fill cell to datetime column(Postgre) fixes #924
2025-01-23 09:17:40 +01:00
️Yaskur Dyas⚔⚔️⚔
e493db5112 fix: reorder condition when format the update data 2025-01-23 08:16:52 +07:00
️Yaskur Dyas⚔⚔️⚔
d3d7ab38c0 fix: fail to fill cell to datetime column(Postgre) fixes #924 2025-01-23 06:32:22 +07:00
7a66c11868 chore(release): 0.7.31-beta.1 2025-01-22 10:56:01 +01:00
8544bb5378 refactor: reorder import statements in sqlUtils.ts for consistency 2025-01-22 10:53:58 +01:00
6709a75298 Merge pull request #921 from curiouslad/develop
Zoom in/out and fullscreen shortcuts
2025-01-20 09:07:08 +01:00
f25f6659d5 refactor: enhancement of new shortcuts implementation 2025-01-17 13:45:46 +01:00
8d0ff4953e Merge pull request #922 from jimcat8/cn_trans
Update localization
2025-01-16 09:45:33 +01:00
tianci
fbe28f0ff0 Update localization 2025-01-16 12:22:07 +08:00
0d8bcf5cd6 Merge pull request #920 from dyaskur/develop
fix: Cannot update column value with composite primary key and JSON column #916
2025-01-15 09:12:26 +01:00
mladen
47ac729d2f feat: zoom in/out and fullscreen shortcuts 2025-01-14 05:24:33 +01:00
️Yaskur Dyas⚔⚔️⚔
450c4c47f3 refactor: improve update cell condition and move whereJson formatter to sqlUtils 2025-01-14 05:44:12 +07:00
️Yaskur Dyas⚔⚔️⚔
110dcd335a fix: cannot update on JSON column in MariaDB and PostgreSQL 2025-01-14 05:15:46 +07:00
️Yaskur Dyas⚔⚔️⚔
0029967619 fix: cannot update column value with composite primary key and JSON column, fixes #916 2025-01-14 04:44:29 +07:00
34848e8dc3 Merge branch 'develop' of https://github.com/antares-sql/antares into develop 2025-01-13 10:23:23 +01:00
c32add76e8 Merge pull request #919 from dyaskur/develop
fix: fail to duplicate JSON row
2025-01-13 10:23:17 +01:00
️Yaskur Dyas⚔⚔️⚔
507dc7d55b fix: fail to duplicate JSON row 2025-01-12 10:30:31 +07:00
4a2b5926f4 fix: saved connections lost opening a second window after first app run 2025-01-10 18:20:36 +01:00
ed90b12a7b Merge pull request #918 from antares-sql/all-contributors/add-JoseGonzalez84
docs: add JoseGonzalez84 as a contributor for translation
2025-01-10 08:46:59 +01:00
allcontributors[bot]
00ce76a12e docs: update .all-contributorsrc [skip ci] 2025-01-10 07:46:47 +00:00
allcontributors[bot]
77b3a8a354 docs: update README.md [skip ci] 2025-01-10 07:46:46 +00:00
d3ae45ec94 perf(translation): update spanish translation 2025-01-10 08:45:58 +01:00
ad4478a822 Merge pull request #917 from antares-sql/all-contributors/add-salvymc
docs: add salvymc as a contributor for code
2025-01-09 16:50:59 +01:00
allcontributors[bot]
ba5dd9ff15 docs: update .all-contributorsrc [skip ci] 2025-01-09 15:50:45 +00:00
allcontributors[bot]
5aab824fe9 docs: update README.md [skip ci] 2025-01-09 15:50:44 +00:00
87ab58c50f Merge pull request #912 from salvymc/patch-1
Update WorkspaceExploreBarSchema.vue - Changed search to not be case sensitive
2025-01-09 16:48:37 +01:00
Salvatore Forino
39a30e48dd Update WorkspaceExploreBarSchema.vue
Changed search to not be case sensitive
2025-01-03 13:09:15 +01:00
46165d2f4f Merge pull request #910 from antares-sql/all-contributors/add-r4f4dev
docs: add r4f4dev as a contributor for translation
2024-12-28 23:46:00 +01:00
allcontributors[bot]
d0e56e4eb6 docs: update .all-contributorsrc [skip ci] 2024-12-28 22:45:32 +00:00
allcontributors[bot]
c803c072d1 docs: update README.md [skip ci] 2024-12-28 22:45:31 +00:00
58 changed files with 1233 additions and 300 deletions

View File

@@ -338,6 +338,33 @@
"contributions": [ "contributions": [
"platform" "platform"
] ]
},
{
"login": "r4f4dev",
"name": "r4f4dev",
"avatar_url": "https://avatars.githubusercontent.com/u/65920592?v=4",
"profile": "https://github.com/r4f4dev",
"contributions": [
"translation"
]
},
{
"login": "salvymc",
"name": "Salvatore Forino",
"avatar_url": "https://avatars.githubusercontent.com/u/10051897?v=4",
"profile": "https://github.com/salvymc",
"contributions": [
"code"
]
},
{
"login": "JoseGonzalez84",
"name": "José González",
"avatar_url": "https://avatars.githubusercontent.com/u/16820141?v=4",
"profile": "https://gadev.com.es/",
"contributions": [
"translation"
]
} }
], ],
"contributorsPerLine": 7, "contributorsPerLine": 7,

View File

@@ -0,0 +1,32 @@
name: Create artifact [WINDOWS APPX]
on:
workflow_dispatch: {}
jobs:
build:
runs-on: windows-2022
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm i
- name: "Build"
run: npm run build:appx
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: windows-build
retention-days: 3
path: |
build
!build/*-unpacked
!build/.icon-ico

View File

@@ -2,6 +2,101 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.7.34](https://github.com/antares-sql/antares/compare/v0.7.33...v0.7.34) (2025-02-14)
### Bug Fixes
* issue with some SSH connections, definitely ([eb706c3](https://github.com/antares-sql/antares/commit/eb706c3e51e9cb7577febd291a33594c0650a34a))
### [0.7.33](https://github.com/antares-sql/antares/compare/v0.7.32...v0.7.33) (2025-02-14)
### Bug Fixes
* issue with some SSH connections, fixes [#947](https://github.com/antares-sql/antares/issues/947) ([3129bf4](https://github.com/antares-sql/antares/commit/3129bf4baa5e72b1d79df986605fd5fad1dce291))
### [0.7.32](https://github.com/antares-sql/antares/compare/v0.7.31...v0.7.32) (2025-02-14)
### Bug Fixes
* black background with light theme, fixes [#945](https://github.com/antares-sql/antares/issues/945) ([1d7053c](https://github.com/antares-sql/antares/commit/1d7053ce032efec8377d9500f2e24618f6381ab4))
* enhance SVG support in connection customization, fixes [#939](https://github.com/antares-sql/antares/issues/939) ([49a3589](https://github.com/antares-sql/antares/commit/49a3589536d2e75a14125be7b874e29b60fb56c4))
* improve error handling in SSH connection ([704f708](https://github.com/antares-sql/antares/commit/704f70819b21a42194d8f68cf9b58ba337f1ada7))
* **PostgreSQL:** error with materialized view tabs ([41e797f](https://github.com/antares-sql/antares/commit/41e797f9e27db66370d3ae7750c057f708af76f9))
### [0.7.31](https://github.com/antares-sql/antares/compare/v0.7.31-beta.5...v0.7.31) (2025-02-11)
### [0.7.31-beta.5](https://github.com/antares-sql/antares/compare/v0.7.31-beta.4...v0.7.31-beta.5) (2025-02-09)
### Bug Fixes
* **devtoolsInstaller:** improve file path handling and increase chromium version ([7595e89](https://github.com/antares-sql/antares/commit/7595e892238d2a93c454e9c1f236915fb458eed1))
* improve BLOB primary fields management, fixes [#938](https://github.com/antares-sql/antares/issues/938) ([72f8d42](https://github.com/antares-sql/antares/commit/72f8d4249f7f587d3e92b46cf7709ddab42107d4))
* **Linux:** restored AppImage auto updates ([0479e53](https://github.com/antares-sql/antares/commit/0479e5307c9a9d5f791e1c61fa772d331f6f7f1f))
* replace 'this.addNotification' with 'addNotification' in useResultTables.ts ([580bef7](https://github.com/antares-sql/antares/commit/580bef76ba390fc85df0892265f31392b80301bd))
* unable to delete rows from context menu ([0f93d70](https://github.com/antares-sql/antares/commit/0f93d70417871f02f9f64f203f6654fa1bf2004b))
### Improvements
* improve button styles of notes ([48cfa67](https://github.com/antares-sql/antares/commit/48cfa67889bd83228c109b7966c4acea4e542fc6))
* **MySQL:** long loading in table settings when no checks present ([9cda38e](https://github.com/antares-sql/antares/commit/9cda38e9d10e3000473863560d8be8f426a5ed17))
### [0.7.31-beta.4](https://github.com/antares-sql/antares/compare/v0.7.31-beta.3...v0.7.31-beta.4) (2025-01-31)
### Bug Fixes
* **Linux:** missing window management icons ([d34e56a](https://github.com/antares-sql/antares/commit/d34e56a517784dea16a7a53bc2249072a3b96596))
### [0.7.31-beta.3](https://github.com/antares-sql/antares/compare/v0.7.31-beta.2...v0.7.31-beta.3) (2025-01-31)
### Features
* implement a better query splitter for SQL queries, fixes [#926](https://github.com/antares-sql/antares/issues/926) ([96ae09f](https://github.com/antares-sql/antares/commit/96ae09fecad0c1fc8926d5dcf64cc779abe5ed49))
* **Linux:** update title bar for better Linux experience ([8e54f7b](https://github.com/antares-sql/antares/commit/8e54f7b80135768a33934bc9336239dee38401a5))
### Bug Fixes
* **MySQL:** adjust utf8mb3 encoding to resolve compatibility issue, fixes [#646](https://github.com/antares-sql/antares/issues/646) ([27387f1](https://github.com/antares-sql/antares/commit/27387f18a107fc6c09afec5f85134496ce764355))
### [0.7.31-beta.2](https://github.com/antares-sql/antares/compare/v0.7.31-beta.1...v0.7.31-beta.2) (2025-01-30)
### Features
* add developer tools and refresh buttons to console in development mode ([592d7b3](https://github.com/antares-sql/antares/commit/592d7b35170f8437ebc15221c97985e889fccb40))
### Bug Fixes
* fail to fill cell to datetime column(Postgre) fixes [#924](https://github.com/antares-sql/antares/issues/924) ([d3d7ab3](https://github.com/antares-sql/antares/commit/d3d7ab38c029fc5ec23767c6c86c49a96e4e329c))
* reorder condition when format the update data ([e493db5](https://github.com/antares-sql/antares/commit/e493db5112478ff121e4e77f69c21747c5d2e032))
### [0.7.31-beta.1](https://github.com/antares-sql/antares/compare/v0.7.31-beta.0...v0.7.31-beta.1) (2025-01-22)
### Features
* zoom in/out and fullscreen shortcuts ([47ac729](https://github.com/antares-sql/antares/commit/47ac729d2f5cced2c503358f7d45a1795f232a20))
### Bug Fixes
* cannot update column value with composite primary key and JSON column, fixes [#916](https://github.com/antares-sql/antares/issues/916) ([0029967](https://github.com/antares-sql/antares/commit/002996761997444ff689bf2384dae64ccb9ef8f7))
* fail to duplicate JSON row ([507dc7d](https://github.com/antares-sql/antares/commit/507dc7d55b342240bf18fd58e6bc71709e8e33a0))
* saved connections lost opening a second window after first app run ([4a2b592](https://github.com/antares-sql/antares/commit/4a2b5926f4783d0b9b1e28485e9293a25ddd31f3))
### Improvements
* **translation:** update spanish translation ([d3ae45e](https://github.com/antares-sql/antares/commit/d3ae45ec94b3538e84ac3013b285034caea695cf))
### [0.7.31-beta.0](https://github.com/antares-sql/antares/compare/v0.7.30...v0.7.31-beta.0) (2025-01-06) ### [0.7.31-beta.0](https://github.com/antares-sql/antares/compare/v0.7.30...v0.7.31-beta.0) (2025-01-06)

View File

@@ -159,6 +159,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
</tr> </tr>
<tr> <tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/carvalhods"><img src="https://avatars.githubusercontent.com/u/6569255?v=4?s=100" width="100px;" alt="David Carvalho"/><br /><sub><b>David Carvalho</b></sub></a><br /><a href="#platform-carvalhods" title="Packaging/porting to new platform">📦</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/carvalhods"><img src="https://avatars.githubusercontent.com/u/6569255?v=4?s=100" width="100px;" alt="David Carvalho"/><br /><sub><b>David Carvalho</b></sub></a><br /><a href="#platform-carvalhods" title="Packaging/porting to new platform">📦</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/r4f4dev"><img src="https://avatars.githubusercontent.com/u/65920592?v=4?s=100" width="100px;" alt="r4f4dev"/><br /><sub><b>r4f4dev</b></sub></a><br /><a href="#translation-r4f4dev" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/salvymc"><img src="https://avatars.githubusercontent.com/u/10051897?v=4?s=100" width="100px;" alt="Salvatore Forino"/><br /><sub><b>Salvatore Forino</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=salvymc" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://gadev.com.es/"><img src="https://avatars.githubusercontent.com/u/16820141?v=4?s=100" width="100px;" alt="José González"/><br /><sub><b>José González</b></sub></a><br /><a href="#translation-JoseGonzalez84" title="Translation">🌍</a></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

16
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "antares", "name": "antares",
"version": "0.7.31-beta.0", "version": "0.7.34",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "antares", "name": "antares",
"version": "0.7.31-beta.0", "version": "0.7.34",
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -22,6 +22,7 @@
"babel-loader": "~8.2.3", "babel-loader": "~8.2.3",
"better-sqlite3": "~10.0.0", "better-sqlite3": "~10.0.0",
"chalk": "~4.1.2", "chalk": "~4.1.2",
"ciaplu": "^2.2.0",
"cpu-features": "^0.0.10", "cpu-features": "^0.0.10",
"cross-env": "~7.0.2", "cross-env": "~7.0.2",
"css-loader": "~6.5.0", "css-loader": "~6.5.0",
@@ -5608,6 +5609,12 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/ciaplu": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/ciaplu/-/ciaplu-2.2.0.tgz",
"integrity": "sha512-7y8s0GMFpIKqX2kwiOEYbaX3P9tPIbX4x41uw8GZjkZ+y0QZrpY3PFjE2Ed6BOeFxcCWi7b85MYHeiRrVrlSOQ==",
"license": "MIT"
},
"node_modules/clean-css": { "node_modules/clean-css": {
"version": "5.3.2", "version": "5.3.2",
"license": "MIT", "license": "MIT",
@@ -20345,6 +20352,11 @@
"version": "3.9.0", "version": "3.9.0",
"dev": true "dev": true
}, },
"ciaplu": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/ciaplu/-/ciaplu-2.2.0.tgz",
"integrity": "sha512-7y8s0GMFpIKqX2kwiOEYbaX3P9tPIbX4x41uw8GZjkZ+y0QZrpY3PFjE2Ed6BOeFxcCWi7b85MYHeiRrVrlSOQ=="
},
"clean-css": { "clean-css": {
"version": "5.3.2", "version": "5.3.2",
"requires": { "requires": {

View File

@@ -1,7 +1,7 @@
{ {
"name": "antares", "name": "antares",
"productName": "Antares", "productName": "Antares",
"version": "0.7.31-beta.0", "version": "0.7.34",
"description": "A modern, fast and productivity driven SQL client with a focus in UX.", "description": "A modern, fast and productivity driven SQL client with a focus in UX.",
"license": "MIT", "license": "MIT",
"repository": "https://github.com/antares-sql/antares.git", "repository": "https://github.com/antares-sql/antares.git",
@@ -131,6 +131,7 @@
"babel-loader": "~8.2.3", "babel-loader": "~8.2.3",
"better-sqlite3": "~10.0.0", "better-sqlite3": "~10.0.0",
"chalk": "~4.1.2", "chalk": "~4.1.2",
"ciaplu": "^2.2.0",
"cpu-features": "^0.0.10", "cpu-features": "^0.0.10",
"cross-env": "~7.0.2", "cross-env": "~7.0.2",
"css-loader": "~6.5.0", "css-loader": "~6.5.0",

View File

@@ -1,5 +1,5 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck // @ts-check
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const https = require('https'); const https = require('https');
@@ -7,13 +7,18 @@ const unzip = require('unzip-crx-3');
const { antares } = require('../package.json'); const { antares } = require('../package.json');
const extensionID = antares.devtoolsId; const extensionID = antares.devtoolsId;
const chromiumVersion = '124';
const destFolder = path.resolve(__dirname, `../misc/${extensionID}`); const destFolder = path.resolve(__dirname, `../misc/${extensionID}`);
const filePath = path.resolve(__dirname, `${destFolder}${extensionID}.crx`); const filePath = path.resolve(__dirname, `${destFolder}/${extensionID}.crx`);
const fileUrl = `https://clients2.google.com/service/update2/crx?response=redirect&acceptformat=crx2,crx3&x=id%3D${extensionID}%26uc&prodversion=32`; const fileUrl = `https://clients2.google.com/service/update2/crx?response=redirect&acceptformat=crx2,crx3&x=id%3D${extensionID}%26uc&prodversion=${chromiumVersion}`;
if (!fs.existsSync(destFolder))
fs.mkdirSync(destFolder, { recursive: true });
const fileStream = fs.createWriteStream(filePath); const fileStream = fs.createWriteStream(filePath);
const downloadFile = url => { const downloadFile = url => {
return new Promise((resolve, reject) => { return /** @type {Promise<void>} */(new Promise((resolve, reject) => {
const request = https.get(url); const request = https.get(url);
request.on('response', response => { request.on('response', response => {
@@ -33,7 +38,7 @@ const downloadFile = url => {
}); });
request.on('error', reject); request.on('error', reject);
request.end(); request.end();
}); }));
}; };
(async () => { (async () => {

View File

@@ -34,6 +34,7 @@ export interface ClientParams {
| { databasePath: string; readonly: boolean }; | { databasePath: string; readonly: boolean };
poolSize?: number; poolSize?: number;
logger?: () => void; logger?: () => void;
querySplitter?: (sql: string, clieng?: string) => string[];
} }
/** /**

View File

@@ -1,3 +1,5 @@
import { match } from 'ciaplu';
function isJSON (str: string) { function isJSON (str: string) {
try { try {
if (!['{', '['].includes(str.trim()[0])) if (!['{', '['].includes(str.trim()[0]))
@@ -176,17 +178,13 @@ function isMD (str: string) {
} }
export function langDetector (str: string) { export function langDetector (str: string) {
if (!str || !str.trim().length) return match(str)
return 'text'; .when(() => !str || !str.trim().length, () => 'text')
if (isJSON(str)) .when(isJSON, () => 'json')
return 'json'; .when(isHTML, () => 'html')
if (isHTML(str)) .when(isSVG, () => 'svg')
return 'html'; .when(isXML, () => 'xml')
if (isSVG(str)) .when(isMD, () => 'markdown')
return 'svg'; .otherwise(() => 'text')
if (isXML(str)) .return();
return 'xml';
if (isMD(str))
return 'markdown';
return 'text';
} }

View File

@@ -1,45 +1,25 @@
import { match } from 'ciaplu';
export function mimeFromHex (hex: string) { export function mimeFromHex (hex: string) {
switch (hex.substring(0, 4)) { // 2 bytes return match(hex.substring(0, 4)) // 2 bytes
case '424D': .with('424D', () => ({ ext: 'bmp', mime: 'image/bmp' }))
return { ext: 'bmp', mime: 'image/bmp' }; .with('1F8B', () => ({ ext: 'tar.gz', mime: 'application/gzip' }))
case '1F8B': .with('0B77', () => ({ ext: 'ac3', mime: 'audio/vnd.dolby.dd-raw' }))
return { ext: 'tar.gz', mime: 'application/gzip' }; .with('7801', () => ({ ext: 'dmg', mime: 'application/x-apple-diskimage' }))
case '0B77': .with('4D5A', () => ({ ext: 'exe', mime: 'application/x-msdownload' }))
return { ext: 'ac3', mime: 'audio/vnd.dolby.dd-raw' }; .when((val) => ['1FA0', '1F9D'].includes(val), () => ({ ext: 'Z', mime: 'application/x-compress' }))
case '7801': .extracting(() => hex.substring(0, 6)) // 3 bytes
return { ext: 'dmg', mime: 'application/x-apple-diskimage' }; .with('FFD8FF', () => ({ ext: 'jpg', mime: 'image/jpeg' }))
case '4D5A': .with('4949BC', () => ({ ext: 'jxr', mime: 'image/vnd.ms-photo' }))
return { ext: 'exe', mime: 'application/x-msdownload' }; .with('425A68', () => ({ ext: 'bz2', mime: 'application/x-bzip2' }))
case '1FA0': .extracting(() => hex) // 4 bytes
case '1F9D': .with('89504E47', () => ({ ext: 'png', mime: 'image/png' }))
return { ext: 'Z', mime: 'application/x-compress' }; .with('47494638', () => ({ ext: 'gif', mime: 'image/gif' }))
default: .with('25504446', () => ({ ext: 'pdf', mime: 'application/pdf' }))
switch (hex.substring(0, 6)) { // 3 bytes .with('504B0304', () => ({ ext: 'zip', mime: 'application/zip' }))
case 'FFD8FF': .with('425047FB', () => ({ ext: 'bpg', mime: 'image/bpg' }))
return { ext: 'jpg', mime: 'image/jpeg' }; .with('4D4D002A', () => ({ ext: 'tif', mime: 'image/tiff' }))
case '4949BC': .with('00000100', () => ({ ext: 'ico', mime: 'image/x-icon' }))
return { ext: 'jxr', mime: 'image/vnd.ms-photo' }; .otherwise(() => ({ ext: '', mime: 'unknown ' + hex }))
case '425A68': .return();
return { ext: 'bz2', mime: 'application/x-bzip2' };
default:
switch (hex) { // 4 bites
case '89504E47':
return { ext: 'png', mime: 'image/png' };
case '47494638':
return { ext: 'gif', mime: 'image/gif' };
case '25504446':
return { ext: 'pdf', mime: 'application/pdf' };
case '504B0304':
return { ext: 'zip', mime: 'application/zip' };
case '425047FB':
return { ext: 'bpg', mime: 'image/bpg' };
case '4D4D002A':
return { ext: 'tif', mime: 'image/tiff' };
case '00000100':
return { ext: 'ico', mime: 'image/x-icon' };
default:
return { ext: '', mime: 'unknown ' + hex };
}
}
}
} }

View File

@@ -0,0 +1,86 @@
import { ClientCode } from 'common/interfaces/antares';
export const querySplitter =(sql: string, dbType: ClientCode): string[] => {
const queries: string[] = [];
let currentQuery = '';
let insideBlock = false;
let insideString = false;
let stringDelimiter: string | null = null;
let insideDollarTag = false;
let dollarTagDelimiter: string | null = null;
// Regex patterns for BEGIN-END blocks, dollar tags in PostgreSQL, and semicolons
const beginRegex = /\bBEGIN\b/i;
const endRegex = /\bEND\b;/i;
const dollarTagRegex = /\$(\w+)?\$/; // Matches $tag$ or $$
// Split on semicolons, keeping semicolons attached to the lines
const lines = sql.split(/(?<=;)/);
for (let line of lines) {
line = line.trim();
if (!line) continue;
for (let i = 0; i < line.length; i++) {
const char = line[i];
// Handle string boundaries
if ((char === '\'' || char === '"') && (!insideString || char === stringDelimiter)) {
if (!insideString) {
insideString = true;
stringDelimiter = char;
}
else {
insideString = false;
stringDelimiter = null;
}
}
currentQuery += char;
if (dbType === 'pg') {
// Handle dollar-quoted blocks in PostgreSQL
if (!insideString && line.slice(i).match(dollarTagRegex)) {
const match = line.slice(i).match(dollarTagRegex);
if (match) {
const tag = match[0];
if (!insideDollarTag) {
insideDollarTag = true;
dollarTagDelimiter = tag;
currentQuery += tag;
i += tag.length - 1;
}
else if (dollarTagDelimiter === tag) {
insideDollarTag = false;
dollarTagDelimiter = null;
currentQuery += tag;
i += tag.length - 1;
}
}
}
}
// Check BEGIN-END blocks
if (!insideString && !insideDollarTag) {
if (beginRegex.test(line))
insideBlock = true;
if (insideBlock && endRegex.test(line))
insideBlock = false;
}
}
// Append the query if we encounter a semicolon outside a BEGIN-END block, outside a string, and outside dollar tags
if (!insideBlock && !insideString && !insideDollarTag && /;\s*$/.test(line)) {
queries.push(currentQuery.trim());
currentQuery = '';
}
}
// Add any remaining query
if (currentQuery.trim())
queries.push(currentQuery.trim());
return queries;
};

View File

@@ -2,6 +2,7 @@
/* eslint-disable no-useless-escape */ /* eslint-disable no-useless-escape */
import { lineString, point, polygon } from '@turf/helpers'; import { lineString, point, polygon } from '@turf/helpers';
import { BIT, BLOB, DATE, DATETIME, FLOAT, IS_MULTI_SPATIAL, NUMBER, SPATIAL, TEXT_SEARCH } from 'common/fieldTypes'; import { BIT, BLOB, DATE, DATETIME, FLOAT, IS_MULTI_SPATIAL, NUMBER, SPATIAL, TEXT_SEARCH } from 'common/fieldTypes';
import * as antares from 'common/interfaces/antares';
import * as moment from 'moment'; import * as moment from 'moment';
import customizations from '../customizations'; import customizations from '../customizations';
@@ -209,3 +210,20 @@ export const jsonToSqlInsert = (args: {
return insertsString; return insertsString;
}; };
export const formatJsonForSqlWhere = (jsonValue: object, clientType: antares.ClientCode) => {
const formattedValue = JSON.stringify(jsonValue);
switch (clientType) {
case 'mysql':
return ` = CAST('${formattedValue}' AS JSON)`;
case 'maria':
return ` = '${formattedValue}'`;
case 'pg':
return `::text = '${formattedValue}'`;
case 'firebird':
case 'sqlite':
default:
return ` = '${formattedValue}'`;
}
};

View File

@@ -1,29 +1,34 @@
export const shortcutEvents: Record<string, { l18n: string; l18nParam?: string | number; context?: 'tab' }> = { export const shortcutEvents: Record<string, { i18n: string; i18nParam?: string | number; context?: 'tab' | 'main' }> = {
'run-or-reload': { l18n: 'application.runOrReload', context: 'tab' }, 'run-or-reload': { i18n: 'application.runOrReload', context: 'tab' },
'open-new-tab': { l18n: 'application.openNewTab', context: 'tab' }, 'open-new-tab': { i18n: 'application.openNewTab', context: 'tab' },
'close-tab': { l18n: 'application.closeTab', context: 'tab' }, 'close-tab': { i18n: 'application.closeTab', context: 'tab' },
'format-query': { l18n: 'database.formatQuery', context: 'tab' }, 'format-query': { i18n: 'database.formatQuery', context: 'tab' },
'kill-query': { l18n: 'database.killQuery', context: 'tab' }, 'kill-query': { i18n: 'database.killQuery', context: 'tab' },
'query-history': { l18n: 'database.queryHistory', context: 'tab' }, 'query-history': { i18n: 'database.queryHistory', context: 'tab' },
'clear-query': { l18n: 'database.clearQuery', context: 'tab' }, 'clear-query': { i18n: 'database.clearQuery', context: 'tab' },
// 'save-file': { l18n: 'application.saveFile', context: 'tab' }, // 'save-file': { i18n: 'application.saveFile', context: 'tab' },
'open-file': { l18n: 'application.openFile', context: 'tab' }, 'open-file': { i18n: 'application.openFile', context: 'tab' },
'save-file-as': { l18n: 'application.saveFileAs', context: 'tab' }, 'save-file-as': { i18n: 'application.saveFileAs', context: 'tab' },
'next-tab': { l18n: 'application.nextTab' }, 'next-tab': { i18n: 'application.nextTab' },
'prev-tab': { l18n: 'application.previousTab' }, 'prev-tab': { i18n: 'application.previousTab' },
'open-all-connections': { l18n: 'application.openAllConnections' }, 'open-all-connections': { i18n: 'application.openAllConnections' },
'open-filter': { l18n: 'application.openFilter' }, 'open-filter': { i18n: 'application.openFilter' },
'next-page': { l18n: 'application.nextResultsPage' }, 'next-page': { i18n: 'application.nextResultsPage' },
'prev-page': { l18n: 'application.previousResultsPage' }, 'prev-page': { i18n: 'application.previousResultsPage' },
'toggle-console': { l18n: 'application.toggleConsole' }, 'toggle-console': { i18n: 'application.toggleConsole' },
'save-content': { l18n: 'application.saveContent' }, 'save-content': { i18n: 'application.saveContent' },
'create-connection': { l18n: 'connection.createNewConnection' }, 'create-connection': { i18n: 'connection.createNewConnection' },
'open-settings': { l18n: 'application.openSettings' }, 'open-settings': { i18n: 'application.openSettings' },
'open-scratchpad': { l18n: 'application.openNotes' } 'open-scratchpad': { i18n: 'application.openNotes' },
setFullScreen: { i18n: 'application.fullScreen', context: 'main' },
setZoomIn: { i18n: 'application.zoomIn', context: 'main' },
setZoomOut: { i18n: 'application.zoomOut', context: 'main' },
setZoomReset: { i18n: 'application.zoomReset', context: 'main' }
}; };
interface ShortcutRecord { interface ShortcutRecord {
event: string; event: string;
isFunction?: boolean;
keys: Electron.Accelerator[] | string[]; keys: Electron.Accelerator[] | string[];
/** Needed for default shortcuts */ /** Needed for default shortcuts */
os: NodeJS.Platform[]; os: NodeJS.Platform[];
@@ -38,6 +43,30 @@ const shortcuts: ShortcutRecord[] = [
keys: ['F5'], keys: ['F5'],
os: ['darwin', 'linux', 'win32'] os: ['darwin', 'linux', 'win32']
}, },
{
event: 'setFullScreen',
isFunction: true,
keys: ['F11'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'setZoomIn',
isFunction: true,
keys: ['CommandOrControl+='],
os: ['darwin', 'linux', 'win32']
},
{
event: 'setZoomOut',
isFunction: true,
keys: ['CommandOrControl+-'],
os: ['darwin', 'linux', 'win32']
},
{
event: 'setZoomReset',
isFunction: true,
keys: ['CommandOrControl+0'],
os: ['darwin', 'linux', 'win32']
},
{ {
event: 'save-content', event: 'save-content',
keys: ['CommandOrControl+S'], keys: ['CommandOrControl+S'],
@@ -142,8 +171,8 @@ const shortcuts: ShortcutRecord[] = [
for (let i = 1; i <= 9; i++) { for (let i = 1; i <= 9; i++) {
shortcutEvents[`select-tab-${i}`] = { shortcutEvents[`select-tab-${i}`] = {
l18n: 'application.selectTabNumber', i18n: 'application.selectTabNumber',
l18nParam: i i18nParam: i
}; };
shortcuts.push({ shortcuts.push({

View File

@@ -64,9 +64,9 @@ export default (connections: Record<string, antares.Client>) => {
username: conn.sshUser, username: conn.sshUser,
password: conn.sshPass, password: conn.sshPass,
port: conn.sshPort ? conn.sshPort : 22, port: conn.sshPort ? conn.sshPort : 22,
privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null, privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : undefined,
passphrase: conn.sshPassphrase, passphrase: conn.sshPassphrase,
keepaliveInterval: conn.sshKeepAliveInterval ? conn.sshKeepAliveInterval*1000 : null keepaliveInterval: conn.sshKeepAliveInterval ? conn.sshKeepAliveInterval*1000 : undefined
}; };
} }
@@ -90,11 +90,12 @@ export default (connections: Record<string, antares.Client>) => {
return { status: 'success' }; return { status: 'success' };
} }
catch (err) { catch (error) {
clearInterval(abortChecker); clearInterval(abortChecker);
if (error instanceof AggregateError)
if (!isLocalAborted) throw new Error(error.errors.reduce((acc, curr) => acc +' | '+ curr.message, ''));
return { status: 'error', response: err.toString() }; else if (!isLocalAborted)
return { status: 'error', response: error.toString() };
else else
return { status: 'abort', response: 'Connection aborted' }; return { status: 'abort', response: 'Connection aborted' };
} }

View File

@@ -3,7 +3,7 @@ import { ARRAY, BIT, BLOB, BOOLEAN, DATE, DATETIME, FLOAT, LONG_TEXT, NUMBER, TE
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { InsertRowsParams } from 'common/interfaces/tableApis'; import { InsertRowsParams } from 'common/interfaces/tableApis';
import { fakerCustom } from 'common/libs/fakerCustom'; import { fakerCustom } from 'common/libs/fakerCustom';
import { sqlEscaper } from 'common/libs/sqlUtils'; import { formatJsonForSqlWhere, sqlEscaper } from 'common/libs/sqlUtils';
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import * as fs from 'fs'; import * as fs from 'fs';
import * as moment from 'moment'; import * as moment from 'moment';
@@ -233,9 +233,10 @@ export default (connections: Record<string, antares.Client>) => {
for (const key in orgRow) { for (const key in orgRow) {
if (typeof orgRow[key] === 'string') if (typeof orgRow[key] === 'string')
orgRow[key] = `'${orgRow[key]}'`; orgRow[key] = ` = '${orgRow[key]}'`;
else if (typeof orgRow[key] === 'object' && orgRow[key] !== null)
if (orgRow[key] === null) orgRow[key] = formatJsonForSqlWhere(orgRow[key], connections[params.uid]._client);
else if (orgRow[key] === null)
orgRow[key] = `IS ${orgRow[key]}`; orgRow[key] = `IS ${orgRow[key]}`;
else else
orgRow[key] = `= ${orgRow[key]}`; orgRow[key] = `= ${orgRow[key]}`;

View File

@@ -81,7 +81,15 @@ export class ShortcutRegister {
accelerator: key, accelerator: key,
visible: isMenuVisible, visible: isMenuVisible,
click: () => { click: () => {
this._mainWindow.webContents.send(shortcut.event); if (shortcut.isFunction) {
if (shortcut.event in this) {
type exporterMethods = 'setFullScreen' | 'setZoomIn' | 'setZoomOut' | 'setZoomReset';
this[shortcut.event as exporterMethods]();
}
}
else
this._mainWindow.webContents.send(shortcut.event);
if (isDevelopment) console.log('LOCAL EVENT:', shortcut); if (isDevelopment) console.log('LOCAL EVENT:', shortcut);
} }
}); });
@@ -121,6 +129,24 @@ export class ShortcutRegister {
} }
} }
setFullScreen () {
this._mainWindow.setFullScreen(!this._mainWindow.isFullScreen());
}
setZoomIn () {
const currentZoom = this._mainWindow.webContents.getZoomLevel();
this._mainWindow.webContents.setZoomLevel(currentZoom + 1);
}
setZoomOut () {
const currentZoom = this._mainWindow.webContents.getZoomLevel();
this._mainWindow.webContents.setZoomLevel(currentZoom - 1);
}
setZoomReset () {
this._mainWindow.webContents.setZoomLevel(0);
}
reload () { reload () {
this.unregister(); this.unregister();
this.init(); this.init();

View File

@@ -2,27 +2,9 @@ import * as antares from 'common/interfaces/antares';
import mysql from 'mysql2/promise'; import mysql from 'mysql2/promise';
import * as pg from 'pg'; import * as pg from 'pg';
import SSH2Promise = require('@fabio286/ssh2-promise'); import SSH2Promise = require('@fabio286/ssh2-promise');
import { querySplitter } from 'common/libs/querySplitter';
export type LoggerLevel = 'query' | 'error' import { ipcLogger, LoggerLevel } from '../misc/ipcLogger';
const ipcLogger = ({ content, cUid, level }: {content: string; cUid: string; level: LoggerLevel}) => {
if (level === 'error') {
if (process.type !== undefined) {
const mainWindow = require('electron').webContents.fromId(1);
mainWindow.send('non-blocking-exception', { cUid, message: content, date: new Date() });
}
if (process.env.NODE_ENV === 'development' && process.type === 'browser') console.log(content);
}
else if (level === 'query') {
// Remove comments, newlines and multiple spaces
const escapedSql = content.replace(/(\/\*(.|[\r\n])*?\*\/)|(--(.*|[\r\n]))/gm, '').replace(/\s\s+/g, ' ');
if (process.type !== undefined) {
const mainWindow = require('electron').webContents.fromId(1);
mainWindow.send('query-log', { cUid, sql: escapedSql, date: new Date() });
}
if (process.env.NODE_ENV === 'development' && process.type === 'browser') console.log(escapedSql);
}
};
/** /**
* As Simple As Possible Query Builder Core * As Simple As Possible Query Builder Core
@@ -34,6 +16,7 @@ export abstract class BaseClient {
protected _poolSize: number; protected _poolSize: number;
protected _ssh?: SSH2Promise; protected _ssh?: SSH2Promise;
protected _logger: (args: {content: string; cUid: string; level: LoggerLevel}) => void; protected _logger: (args: {content: string; cUid: string; level: LoggerLevel}) => void;
protected _querySplitter: (sql: string, client: antares.ClientCode) => string[];
protected _queryDefaults: antares.QueryBuilderObject; protected _queryDefaults: antares.QueryBuilderObject;
protected _query: antares.QueryBuilderObject; protected _query: antares.QueryBuilderObject;
@@ -43,6 +26,7 @@ export abstract class BaseClient {
this._params = args.params; this._params = args.params;
this._poolSize = args.poolSize || undefined; this._poolSize = args.poolSize || undefined;
this._logger = args.logger || ipcLogger; this._logger = args.logger || ipcLogger;
this._querySplitter = args.querySplitter || querySplitter;
this._queryDefaults = { this._queryDefaults = {
schema: '', schema: '',

View File

@@ -245,10 +245,10 @@ export class FirebirdSQLClient extends BaseClient {
name: db.name, name: db.name,
size: schemaSize, size: schemaSize,
tables: remappedTables, tables: remappedTables,
functions: [], functions: [] as null[],
procedures: remappedProcedures, procedures: remappedProcedures,
triggers: remappedTriggers, triggers: remappedTriggers,
schedulers: [] schedulers: [] as null[]
}; };
}); });
} }
@@ -337,7 +337,7 @@ export class FirebirdSQLClient extends BaseClient {
return { return {
name: field.FIELD_NAME.trim(), name: field.FIELD_NAME.trim(),
key: null, key: null as null,
type: fieldType, type: fieldType,
schema: schema, schema: schema,
table: table, table: table,
@@ -346,14 +346,14 @@ export class FirebirdSQLClient extends BaseClient {
datePrecision: field.FIELD_NAME.trim() === 'TIMESTAMP' ? 4 : null, datePrecision: field.FIELD_NAME.trim() === 'TIMESTAMP' ? 4 : null,
charLength: ![...NUMBER, ...FLOAT].includes(fieldType) ? field.FIELD_LENGTH : null, charLength: ![...NUMBER, ...FLOAT].includes(fieldType) ? field.FIELD_LENGTH : null,
nullable: !field.NOT_NULL, nullable: !field.NOT_NULL,
unsigned: null, unsigned: null as null,
zerofill: null, zerofill: null as null,
order: field.FIELD_POSITION+1, order: field.FIELD_POSITION+1,
default: defaultValue, default: defaultValue,
charset: field.CHARSET, charset: field.CHARSET,
collation: null, collation: null as null,
autoIncrement: false, autoIncrement: false,
onUpdate: null, onUpdate: null as null,
comment: field.DESCRIPTION?.trim() comment: field.DESCRIPTION?.trim()
}; };
}); });
@@ -457,7 +457,7 @@ export class FirebirdSQLClient extends BaseClient {
table: table, table: table,
field: field.FKCOLUMN_NAME.trim(), field: field.FKCOLUMN_NAME.trim(),
position: field.KEY_SEQ, position: field.KEY_SEQ,
constraintPosition: null, constraintPosition: null as null,
constraintName: field.FK_NAME.trim(), constraintName: field.FK_NAME.trim(),
refSchema: schema, refSchema: schema,
refTable: field.PKTABLE_NAME.trim(), refTable: field.PKTABLE_NAME.trim(),
@@ -1041,9 +1041,7 @@ export class FirebirdSQLClient extends BaseClient {
const resultsArr = []; const resultsArr = [];
let paramsArr = []; let paramsArr = [];
const queries = args.split const queries = args.split
? sql.split(/((?:[^;'"]*(?:"(?:\\.|[^"])*"|'(?:\\.|[^'])*')[^;'"]*)+)|;/gm) ? this._querySplitter(sql, 'firebird')
.filter(Boolean)
.map(q => q.trim())
: [sql]; : [sql];
let connection: firebird.Database | firebird.Transaction; let connection: firebird.Database | firebird.Transaction;

View File

@@ -4,7 +4,9 @@ import dataTypes from 'common/data-types/mysql';
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import * as mysql from 'mysql2/promise'; import * as mysql from 'mysql2/promise';
import * as EncodingToCharset from '../../../../node_modules/mysql2/lib/constants/encoding_charset.js';
import { BaseClient } from './BaseClient'; import { BaseClient } from './BaseClient';
EncodingToCharset.utf8mb3 = 192; // To fix https://github.com/sidorares/node-mysql2/issues/1398 until not included in mysql2
export class MySQLClient extends BaseClient { export class MySQLClient extends BaseClient {
private _schema?: string; private _schema?: string;
@@ -171,13 +173,13 @@ export class MySQLClient extends BaseClient {
remotePort: this._params.port remotePort: this._params.port
}); });
dbConfig.host = (this._ssh.config as SSHConfig[] & { host: string }).host; dbConfig.host = undefined;
dbConfig.port = tunnel.localPort; dbConfig.port = tunnel.localPort;
} }
catch (err) { catch (err) {
if (this._ssh) { if (this._ssh) {
this._ssh.close();
this._ssh.closeTunnel(); this._ssh.closeTunnel();
this._ssh.close();
} }
throw err; throw err;
} }
@@ -225,8 +227,8 @@ export class MySQLClient extends BaseClient {
clearInterval(this._keepaliveTimer); clearInterval(this._keepaliveTimer);
this._keepaliveTimer = undefined; this._keepaliveTimer = undefined;
if (this._ssh) { if (this._ssh) {
this._ssh.close();
this._ssh.closeTunnel(); this._ssh.closeTunnel();
this._ssh.close();
} }
} }
@@ -300,6 +302,8 @@ export class MySQLClient extends BaseClient {
await this.connect(); await this.connect();
return this.getConnection(args, true); return this.getConnection(args, true);
} }
else if (error instanceof AggregateError)
throw new Error(error.errors.reduce((acc, curr) => acc +' | '+ curr.message, ''));
else else
throw new Error(error.message); throw new Error(error.message);
} }
@@ -1753,9 +1757,7 @@ export class MySQLClient extends BaseClient {
const resultsArr: antares.QueryResult[] = []; const resultsArr: antares.QueryResult[] = [];
let paramsArr = []; let paramsArr = [];
const queries = args.split const queries = args.split
? sql.split(/((?:[^;'"]*(?:"(?:\\.|[^"])*"|'(?:\\.|[^'])*')[^;'"]*)+)|;/gm) ? this._querySplitter(sql, 'mysql')
.filter(Boolean)
.map(q => q.trim())
: [sql]; : [sql];
const connection = await this.getConnection(args); const connection = await this.getConnection(args);

View File

@@ -179,7 +179,7 @@ export class PostgreSQLClient extends BaseClient {
remotePort: this._params.port remotePort: this._params.port
}); });
dbConfig.host = (this._ssh.config as SSHConfig[] & { host: string }).host; dbConfig.host = undefined;
dbConfig.port = tunnel.localPort; dbConfig.port = tunnel.localPort;
} }
catch (err) { catch (err) {
@@ -348,7 +348,7 @@ export class PostgreSQLClient extends BaseClient {
matviewowner AS owner, matviewowner AS owner,
ispopulated AS is_populated, ispopulated AS is_populated,
definition, definition,
'materializedview' AS table_type 'materializedView' AS table_type
FROM pg_matviews FROM pg_matviews
WHERE schemaname = '${db.database}' WHERE schemaname = '${db.database}'
ORDER BY schema_name, ORDER BY schema_name,
@@ -408,8 +408,8 @@ export class PostgreSQLClient extends BaseClient {
name: table.table_name, name: table.table_name,
type: table.table_type === 'VIEW' type: table.table_type === 'VIEW'
? 'view' ? 'view'
: table.table_type === 'materializedview' : table.table_type === 'materializedView'
? 'materializedview' ? 'materializedView'
: 'table', : 'table',
rows: table.reltuples, rows: table.reltuples,
size: tableSize, size: tableSize,
@@ -466,7 +466,7 @@ export class PostgreSQLClient extends BaseClient {
procedures: remappedProcedures, procedures: remappedProcedures,
triggers: remappedTriggers, triggers: remappedTriggers,
triggerFunctions: remappedTriggerFunctions, triggerFunctions: remappedTriggerFunctions,
schedulers: [] schedulers: [] as null[]
}; };
} }
else { else {
@@ -532,7 +532,7 @@ export class PostgreSQLClient extends BaseClient {
return { return {
name: field.column_name, name: field.column_name,
key: null, key: null as null,
type: type.toUpperCase(), type: type.toUpperCase(),
isArray, isArray,
schema: field.table_schema, schema: field.table_schema,
@@ -542,14 +542,14 @@ export class PostgreSQLClient extends BaseClient {
datePrecision: field.datetime_precision, datePrecision: field.datetime_precision,
charLength: field.character_maximum_length, charLength: field.character_maximum_length,
nullable: field.is_nullable.includes('YES'), nullable: field.is_nullable.includes('YES'),
unsigned: null, unsigned: null as null,
zerofill: null, zerofill: null as null,
order: field.ordinal_position, order: field.ordinal_position,
default: field.column_default, default: field.column_default,
charset: field.character_set_name, charset: field.character_set_name,
collation: field.collation_name, collation: field.collation_name,
autoIncrement: false, autoIncrement: false,
onUpdate: null, onUpdate: null as null,
comment: field.column_comment comment: field.column_comment
}; };
}); });
@@ -1252,9 +1252,9 @@ export class PostgreSQLClient extends BaseClient {
return results.rows.map(async row => { return results.rows.map(async row => {
if (!row.pg_get_functiondef) { if (!row.pg_get_functiondef) {
return { return {
definer: null, definer: null as null,
sql: '', sql: '',
parameters: [], parameters: [] as null[],
name: routine, name: routine,
comment: '', comment: '',
security: 'DEFINER', security: 'DEFINER',
@@ -1303,8 +1303,8 @@ export class PostgreSQLClient extends BaseClient {
name: routine, name: routine,
comment: '', comment: '',
security: row.pg_get_functiondef.includes('SECURITY DEFINER') ? 'DEFINER' : 'INVOKER', security: row.pg_get_functiondef.includes('SECURITY DEFINER') ? 'DEFINER' : 'INVOKER',
deterministic: null, deterministic: null as null,
dataAccess: null, dataAccess: null as null,
language: row.pg_get_functiondef.match(/(?<=LANGUAGE )(.*)(?<=[\S+\n\r\s])/gm)[0] language: row.pg_get_functiondef.match(/(?<=LANGUAGE )(.*)(?<=[\S+\n\r\s])/gm)[0]
}; };
})[0]; })[0];
@@ -1368,9 +1368,9 @@ export class PostgreSQLClient extends BaseClient {
return results.rows.map(async row => { return results.rows.map(async row => {
if (!row.pg_get_functiondef) { if (!row.pg_get_functiondef) {
return { return {
definer: null, definer: null as null,
sql: '', sql: '',
parameters: [], parameters: [] as null[],
name: func, name: func,
comment: '', comment: '',
security: 'DEFINER', security: 'DEFINER',
@@ -1418,8 +1418,8 @@ export class PostgreSQLClient extends BaseClient {
name: func, name: func,
comment: '', comment: '',
security: row.pg_get_functiondef.includes('SECURITY DEFINER') ? 'DEFINER' : 'INVOKER', security: row.pg_get_functiondef.includes('SECURITY DEFINER') ? 'DEFINER' : 'INVOKER',
deterministic: null, deterministic: null as null,
dataAccess: null, dataAccess: null as null,
language: row.pg_get_functiondef.match(/(?<=LANGUAGE )(.*)(?<=[\S+\n\r\s])/gm)[0], language: row.pg_get_functiondef.match(/(?<=LANGUAGE )(.*)(?<=[\S+\n\r\s])/gm)[0],
returns: row.pg_get_functiondef.match(/(?<=RETURNS )(.*)(?<=[\S+\n\r\s])/gm)[0].replace('SETOF ', '').toUpperCase() returns: row.pg_get_functiondef.match(/(?<=RETURNS )(.*)(?<=[\S+\n\r\s])/gm)[0].replace('SETOF ', '').toUpperCase()
}; };
@@ -1665,9 +1665,7 @@ export class PostgreSQLClient extends BaseClient {
const resultsArr: antares.QueryResult[] = []; const resultsArr: antares.QueryResult[] = [];
let paramsArr = []; let paramsArr = [];
const queries = args.split const queries = args.split
? sql.split(/(?!\B'[^']*);(?![^']*'\B)/gm) ? this._querySplitter(sql, 'pg')
.filter(Boolean)
.map(q => q.trim())
: [sql]; : [sql];
let connection: pg.Client | pg.PoolClient; let connection: pg.Client | pg.PoolClient;

View File

@@ -124,10 +124,10 @@ export class SQLiteClient extends BaseClient {
name: db.name, name: db.name,
size: schemaSize, size: schemaSize,
tables: remappedTables, tables: remappedTables,
functions: [], functions: [] as null[],
procedures: [], procedures: [] as null[],
triggers: remappedTriggers, triggers: remappedTriggers,
schedulers: [] schedulers: [] as null[]
}; };
} }
else { else {
@@ -166,22 +166,22 @@ export class SQLiteClient extends BaseClient {
return { return {
name: field.name, name: field.name,
key: null, key: null as null,
type: type.trim(), type: type.trim(),
schema: schema, schema: schema,
table: table, table: table,
numLength: [...NUMBER, ...FLOAT].includes(type) ? length : null, numLength: [...NUMBER, ...FLOAT].includes(type) ? length : null,
datePrecision: null, datePrecision: null as null,
charLength: ![...NUMBER, ...FLOAT].includes(type) ? length : null, charLength: ![...NUMBER, ...FLOAT].includes(type) ? length : null,
nullable: !field.notnull, nullable: !field.notnull,
unsigned: null, unsigned: null as null,
zerofill: null, zerofill: null as null,
order: typeof field.cid === 'string' ? +field.cid + 1 : field.cid + 1, order: typeof field.cid === 'string' ? +field.cid + 1 : field.cid + 1,
default: field.dflt_value, default: field.dflt_value,
charset: null, charset: null as null,
collation: null, collation: null as null,
autoIncrement: false, autoIncrement: false,
onUpdate: null, onUpdate: null as null,
comment: '' comment: ''
}; };
}); });
@@ -267,7 +267,7 @@ export class SQLiteClient extends BaseClient {
table: table, table: table,
field: field.from, field: field.from,
position: field.id + 1, position: field.id + 1,
constraintPosition: null, constraintPosition: null as null,
constraintName: field.id, constraintName: field.id,
refSchema: schema, refSchema: schema,
refTable: field.table, refTable: field.table,
@@ -629,9 +629,7 @@ export class SQLiteClient extends BaseClient {
const resultsArr = []; const resultsArr = [];
let paramsArr = []; let paramsArr = [];
const queries = args.split const queries = args.split
? sql.split(/((?:[^;'"]*(?:"(?:\\.|[^"])*"|'(?:\\.|[^'])*')[^;'"]*)+)|;/gm) ? this._querySplitter(sql, 'sqlite')
.filter(Boolean)
.map(q => q.trim())
: [sql]; : [sql];
let connection: sqlite.Database; let connection: sqlite.Database;

View File

@@ -0,0 +1,20 @@
export type LoggerLevel = 'query' | 'error'
export const ipcLogger = ({ content, cUid, level }: {content: string; cUid: string; level: LoggerLevel}) => {
if (level === 'error') {
if (process.type !== undefined) {
const mainWindow = require('electron').webContents.fromId(1);
mainWindow.send('non-blocking-exception', { cUid, message: content, date: new Date() });
}
if (process.env.NODE_ENV === 'development' && process.type === 'browser') console.log(content);
}
else if (level === 'query') {
// Remove comments, newlines and multiple spaces
const escapedSql = content.replace(/(\/\*(.|[\r\n])*?\*\/)|(--(.*|[\r\n]))/gm, '').replace(/\s\s+/g, ' ');
if (process.type !== undefined) {
const mainWindow = require('electron').webContents.fromId(1);
mainWindow.send('query-log', { cUid, sql: escapedSql, date: new Date() });
}
if (process.env.NODE_ENV === 'development' && process.type === 'browser') console.log(escapedSql);
}
};

View File

@@ -43,7 +43,8 @@ async function createMainWindow () {
spellcheck: false spellcheck: false
}, },
autoHideMenuBar: true, autoHideMenuBar: true,
titleBarStyle: isLinux ? 'default' :'hidden', frame: !isLinux,
titleBarStyle: 'hidden',
titleBarOverlay: isWindows titleBarOverlay: isWindows
? { ? {
color: appTheme === 'dark' ? '#3f3f3f' : '#fff', color: appTheme === 'dark' ? '#3f3f3f' : '#fff',
@@ -127,15 +128,25 @@ app.on('ready', async () => {
if (isWindows) if (isWindows)
mainWindow.show(); mainWindow.show();
if (isDevelopment && !isWindows)// Because on Windows you can open devtools from title-bar // if (isDevelopment && !isWindows)
mainWindow.webContents.openDevTools(); // mainWindow.webContents.openDevTools();
process.on('uncaughtException', error => { process.on('uncaughtException', error => {
mainWindow.webContents.send('unhandled-exception', error); if (error instanceof AggregateError) {
for (const e of error.errors)
mainWindow.webContents.send('unhandled-exception', e);
}
else
mainWindow.webContents.send('unhandled-exception', error);
}); });
process.on('unhandledRejection', error => { process.on('unhandledRejection', error => {
mainWindow.webContents.send('unhandled-exception', error); if (error instanceof AggregateError) {
for (const e of error.errors)
mainWindow.webContents.send('unhandled-exception', e);
}
else
mainWindow.webContents.send('unhandled-exception', error);
}); });
}); });

View File

@@ -39,11 +39,11 @@ const props = defineProps({
default: () => 'mdi' default: () => 'mdi'
}, },
flip: { flip: {
type: String as PropType<'horizontal' | 'vertical' | 'both'>, type: String as PropType<'horizontal' | 'vertical' | 'both' | null>,
default: () => null default: () => null
}, },
rotate: { rotate: {
type: Number, type: Number as PropType<number | null>,
default: () => null default: () => null
} }
}); });
@@ -55,8 +55,7 @@ const iconPath = computed(() => {
const base64 = getIconByUid(props.iconName)?.base64; const base64 = getIconByUid(props.iconName)?.base64;
const svgString = Buffer const svgString = Buffer
.from(base64, 'base64') .from(base64, 'base64')
.toString('utf-8') .toString('utf-8');
.replaceAll(/width="[^"]*"|height="[^"]*"/g, '');
return svgString; return svgString;
} }

View File

@@ -21,7 +21,23 @@
<a class="tab-link" @click="selectedTab = 'debug'">{{ t('application.debugConsole') }}</a> <a class="tab-link" @click="selectedTab = 'debug'">{{ t('application.debugConsole') }}</a>
</li> </li>
</ul> </ul>
<button class="btn btn-clear mr-1" @click="resizeConsole(0)" /> <div class="d-flex">
<div
v-if="isDevelopment"
class="c-hand mr-2"
@click="openDevTools()"
>
<BaseIcon icon-name="mdiBugPlayOutline" :size="22" />
</div>
<div
v-if="isDevelopment"
class="c-hand mr-2"
@click="reload()"
>
<BaseIcon icon-name="mdiRefresh" :size="22" />
</div>
<button class="btn btn-clear mr-1" @click="resizeConsole(0)" />
</div>
</div> </div>
<div <div
v-show="selectedTab === 'query'" v-show="selectedTab === 'query'"
@@ -71,6 +87,7 @@
</BaseContextMenu> </BaseContextMenu>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { getCurrentWindow } from '@electron/remote';
import * as moment from 'moment'; import * as moment from 'moment';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { highlight } from 'sql-highlight'; import { highlight } from 'sql-highlight';
@@ -112,6 +129,8 @@ const isHover = ref(false);
const isContext = ref(false); const isContext = ref(false);
const contextContent: Ref<string> = ref(null); const contextContent: Ref<string> = ref(null);
const contextEvent: Ref<MouseEvent> = ref(null); const contextEvent: Ref<MouseEvent> = ref(null);
const w = ref(getCurrentWindow());
const isDevelopment = ref(process.env.NODE_ENV === 'development');
const resize = (e: MouseEvent) => { const resize = (e: MouseEvent) => {
const el = queryConsole.value; const el = queryConsole.value;
@@ -142,6 +161,14 @@ const copyLog = () => {
isContext.value = false; isContext.value = false;
}; };
const openDevTools = () => {
w.value.webContents.openDevTools();
};
const reload = () => {
w.value.reload();
};
watch(workspaceQueryLogs, async () => { watch(workspaceQueryLogs, async () => {
if (!isHover.value) { if (!isHover.value) {
await nextTick(); await nextTick();

View File

@@ -127,7 +127,7 @@ const fakerGroups = computed(() => {
localType.value = 'datetime'; localType.value = 'datetime';
else if (TIME.includes(props.type)) else if (TIME.includes(props.type))
localType.value = 'time'; localType.value = 'time';
else if (UUID.includes(props.type)) else if (UUID.includes(props.type) || (BLOB.includes(props.type) && props.field.key === 'pri'))
localType.value = 'uuid'; localType.value = 'uuid';
else else
localType.value = 'none'; localType.value = 'none';
@@ -177,7 +177,7 @@ const inputProps = () => {
return { type: 'text', mask: datetimeMask }; return { type: 'text', mask: datetimeMask };
} }
if (BLOB.includes(props.type)) if (BLOB.includes(props.type) && props.field.key !== 'pri')
return { type: 'file', mask: false }; return { type: 'file', mask: false };
if (BIT.includes(props.type)) if (BIT.includes(props.type))

View File

@@ -131,8 +131,10 @@ import Application from '@/ipc-api/Application';
import { camelize } from '@/libs/camelize'; import { camelize } from '@/libs/camelize';
import { unproxify } from '@/libs/unproxify'; import { unproxify } from '@/libs/unproxify';
import { SidebarElement, useConnectionsStore } from '@/stores/connections'; import { SidebarElement, useConnectionsStore } from '@/stores/connections';
import { useNotificationsStore } from '@/stores/notifications';
const connectionsStore = useConnectionsStore(); const connectionsStore = useConnectionsStore();
const { addNotification } = useNotificationsStore();
const { addIcon, removeIcon, updateConnectionOrder, getConnectionName } = connectionsStore; const { addIcon, removeIcon, updateConnectionOrder, getConnectionName } = connectionsStore;
const { customIcons } = storeToRefs(connectionsStore); const { customIcons } = storeToRefs(connectionsStore);
@@ -225,12 +227,56 @@ const removeIconHandler = () => {
isContext.value = false; isContext.value = false;
}; };
const adjustSVGContent = (svgContent: string) => {
try {
const parser = new DOMParser();
const doc = parser.parseFromString(svgContent, 'image/svg+xml');
const parseError = doc.querySelector('parsererror');
if (parseError) {
addNotification({ status: 'error', message: parseError.textContent });
return null;
}
const svg = doc.documentElement;
if (svg.tagName.toLowerCase() !== 'svg') {
addNotification({ status: 'error', message: t('application.invalidFIle') });
return null;
}
if (!svg.hasAttribute('viewBox')) {
const width = svg.getAttribute('width') || '36';
const height = svg.getAttribute('height') || '36';
svg.setAttribute('viewBox', `0 0 ${width} ${height}`);
}
svg.removeAttribute('width');
svg.removeAttribute('height');
const serializer = new XMLSerializer();
return serializer.serializeToString(svg);
}
catch (error) {
addNotification({ status: 'error', message: error.stack });
return null;
}
};
const openFile = async () => { const openFile = async () => {
const result = await Application.showOpenDialog({ properties: ['openFile'], filters: [{ name: '"SVG"', extensions: ['svg'] }] }); const result = await Application.showOpenDialog({
properties: ['openFile'],
filters: [{ name: '"SVG"', extensions: ['svg'] }]
});
if (result && !result.canceled) { if (result && !result.canceled) {
const file = result.filePaths[0]; const file = result.filePaths[0];
const content = await Application.readFile({ filePath: file, encoding: 'base64url' }); let content = await Application.readFile({ filePath: file, encoding: 'utf-8' });
addIcon(content);
content = adjustSVGContent(content);
const base64Content = Buffer.from(content).toString('base64');
addIcon(base64Content);
} }
}; };

View File

@@ -339,6 +339,8 @@ onMounted(() => {
for (const field of props.fields) { for (const field of props.fields) {
if (typeof props.rowToDuplicate[field.name] !== 'object') if (typeof props.rowToDuplicate[field.name] !== 'object')
rowObj[field.name] = { value: props.rowToDuplicate[field.name] }; rowObj[field.name] = { value: props.rowToDuplicate[field.name] };
else if (field.type === 'JSON')
rowObj[field.name] = { value: JSON.stringify(props.rowToDuplicate[field.name]) };
if (field.autoIncrement || !!field.onUpdate)// Disable by default auto increment or "on update" fields if (field.autoIncrement || !!field.onUpdate)// Disable by default auto increment or "on update" fields
fieldsToExclude.value = [...fieldsToExclude.value, field.name]; fieldsToExclude.value = [...fieldsToExclude.value, field.name];

View File

@@ -42,7 +42,7 @@
tabindex="0" tabindex="0"
> >
<div class="td py-1"> <div class="td py-1">
{{ t(shortcutEvents[shortcut.event].l18n, {param: shortcutEvents[shortcut.event].l18nParam}) }} {{ t(shortcutEvents[shortcut.event].i18n, {param: shortcutEvents[shortcut.event].i18nParam}) }}
</div> </div>
<div <div
class="td py-1" class="td py-1"
@@ -167,7 +167,7 @@
</template> </template>
<template #body> <template #body>
<div class="mb-2"> <div class="mb-2">
{{ t('general.deleteConfirm') }} <b>{{ t(shortcutEvents[shortcutToDelete.event].l18n, {param: shortcutEvents[shortcutToDelete.event].l18nParam}) }} (<span v-html="parseKeys(shortcutToDelete.keys)" />)</b>? {{ t('general.deleteConfirm') }} <b>{{ t(shortcutEvents[shortcutToDelete.event].i18n, {param: shortcutEvents[shortcutToDelete.event].i18nParam}) }} (<span v-html="parseKeys(shortcutToDelete.keys)" />)</b>?
</div> </div>
</template> </template>
</ConfirmModal> </ConfirmModal>
@@ -233,7 +233,7 @@ const { shortcuts } = storeToRefs(settingsStore);
const eventOptions = computed(() => { const eventOptions = computed(() => {
return Object.keys(shortcutEvents) return Object.keys(shortcutEvents)
.map(key => { .map(key => {
return { value: key, label: t(shortcutEvents[key].l18n, { param: shortcutEvents[key].l18nParam }) }; return { value: key, label: t(shortcutEvents[key].i18n, { param: shortcutEvents[key].i18nParam }) };
}) })
.sort((a, b) => { .sort((a, b) => {
if (a.label < b.label) return -1; if (a.label < b.label) return -1;

View File

@@ -47,65 +47,50 @@
<div class="tile-history-buttons"> <div class="tile-history-buttons">
<button <button
v-if="note.type === 'todo' && !note.isArchived" v-if="note.type === 'todo' && !note.isArchived"
class="btn btn-link pl-1" class="btn btn-dark tooltip tooltip-left"
:data-tooltip="t('general.archive')"
@click.stop="$emit('archive-note', note.uid)" @click.stop="$emit('archive-note', note.uid)"
> >
<BaseIcon <BaseIcon icon-name="mdiCheck" :size="22" />
icon-name="mdiCheck"
class="pr-1"
:size="22"
/> {{ t('general.archive') }}
</button> </button>
<button <button
v-if="note.type === 'todo' && note.isArchived" v-if="note.type === 'todo' && note.isArchived"
class="btn btn-link pl-1" class="btn btn-dark tooltip tooltip-left"
:data-tooltip="t('general.undo')"
@click.stop="$emit('restore-note', note.uid)" @click.stop="$emit('restore-note', note.uid)"
> >
<BaseIcon <BaseIcon icon-name="mdiRestore" :size="22" />
icon-name="mdiRestore"
class="pr-1"
:size="22"
/> {{ t('general.undo') }}
</button> </button>
<button <button
v-if="note.type === 'query'" v-if="note.type === 'query'"
class="btn btn-link pl-1" class="btn btn-dark tooltip tooltip-left"
:data-tooltip="t('general.select')"
@click.stop="$emit('select-query', note.note)" @click.stop="$emit('select-query', note.note)"
> >
<BaseIcon <BaseIcon icon-name="mdiOpenInApp" :size="22" />
icon-name="mdiOpenInApp"
class="pr-1"
:size="22"
/> {{ t('general.select') }}
</button> </button>
<button <button
v-if="note.type === 'query'" v-if="note.type === 'query'"
class="btn btn-link pl-1" class="btn btn-dark tooltip tooltip-left"
:data-tooltip="t('general.copy')"
@click.stop="copyText(note.note)" @click.stop="copyText(note.note)"
> >
<BaseIcon <BaseIcon icon-name="mdiContentCopy" :size="18" />
icon-name="mdiContentCopy"
class="pr-1"
:size="22"
/> {{ t('general.copy') }}
</button> </button>
<button <button
v-if=" !note.isArchived" v-if=" !note.isArchived"
class="btn btn-link pl-1" class="btn btn-dark tooltip tooltip-left"
:data-tooltip="t('general.edit')"
@click.stop="$emit('edit-note')" @click.stop="$emit('edit-note')"
> >
<BaseIcon <BaseIcon icon-name="mdiPencil" :size="22" />
icon-name="mdiPencil"
class="pr-1"
:size="22"
/> {{ t('general.edit') }}
</button> </button>
<button class="btn btn-link pl-1" @click.stop="$emit('delete-note', note.uid)"> <button
<BaseIcon class="btn btn-dark tooltip tooltip-left"
icon-name="mdiDeleteForever" :data-tooltip="t('general.delete')"
class="pr-1" @click.stop="$emit('delete-note', note.uid)"
:size="22" >
/> {{ t('general.delete') }} <BaseIcon icon-name="mdiDeleteForever" :size="22" />
</button> </button>
</div> </div>
</div> </div>
@@ -278,11 +263,14 @@ const highlightWord = (string: string) => {
button { button {
font-size: 0.7rem; font-size: 0.7rem;
height: 1rem;
line-height: 1rem; line-height: 1rem;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin: 0 5px;
padding: 0;
height: 24px;
width: 24px;
} }
} }
} }

View File

@@ -1,6 +1,5 @@
<template> <template>
<div <div
v-if="!isLinux"
id="titlebar" id="titlebar"
@dblclick="toggleFullScreen" @dblclick="toggleFullScreen"
> >
@@ -21,16 +20,27 @@
class="titlebar-element" class="titlebar-element"
@click="openDevTools" @click="openDevTools"
> >
<BaseIcon icon-name="mdiBugPlayOutline" :size="24" /> <BaseIcon icon-name="mdiBugPlayOutline" :size="18" />
</div> </div>
<div <div
v-if="isDevelopment" v-if="isDevelopment"
class="titlebar-element" class="titlebar-element"
@click="reload" @click="reload"
> >
<BaseIcon icon-name="mdiRefresh" :size="24" /> <BaseIcon icon-name="mdiRefresh" :size="18" />
</div> </div>
<div v-if="isWindows" :style="'width: 140px;'" /> <div v-if="isWindows" :style="'width: 140px;'" />
<div v-if="isLinux" class="d-flex">
<div class="titlebar-element" @click="minimize">
<BaseIcon icon-name="mdiWindowMinimize" :size="18" />
</div>
<div class="titlebar-element" @click="toggleFullScreen">
<BaseIcon :icon-name="isMaximized ? 'mdiWindowRestore' : 'mdiWindowMaximize'" :size="18" />
</div>
<div class="titlebar-element" @click="closeApp">
<BaseIcon icon-name="mdiClose" :size="18" />
</div>
</div>
</div> </div>
</div> </div>
</template> </template>
@@ -74,6 +84,18 @@ const windowTitle = computed(() => {
return [connectionName, ...breadcrumbs].join(' • '); return [connectionName, ...breadcrumbs].join(' • ');
}); });
const openDevTools = () => {
w.value.webContents.openDevTools();
};
const reload = () => {
w.value.reload();
};
const minimize = () => {
w.value.minimize();
};
const toggleFullScreen = () => { const toggleFullScreen = () => {
if (isMaximized.value) if (isMaximized.value)
w.value.unmaximize(); w.value.unmaximize();
@@ -81,12 +103,8 @@ const toggleFullScreen = () => {
w.value.maximize(); w.value.maximize();
}; };
const openDevTools = () => { const closeApp = () => {
w.value.webContents.openDevTools(); ipcRenderer.send('close-app');
};
const reload = () => {
w.value.reload();
}; };
const onResize = () => { const onResize = () => {

View File

@@ -64,7 +64,7 @@
> >
<BaseIcon <BaseIcon
class="mt-1 mr-1" class="mt-1 mr-1"
:icon-name="['view', 'materializedview'].includes(element.elementType) ? 'mdiTableEye' : 'mdiTable'" :icon-name="['view', 'materializedView'].includes(element.elementType) ? 'mdiTableEye' : 'mdiTable'"
:size="18" :size="18"
/> />
<span :title="`${t('general.data').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('general.data').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
@@ -81,7 +81,7 @@
<a v-else-if="element.type === 'data'" class="tab-link"> <a v-else-if="element.type === 'data'" class="tab-link">
<BaseIcon <BaseIcon
class="mt-1 mr-1" class="mt-1 mr-1"
:icon-name="['view', 'materializedview'].includes(element.elementType) ? 'mdiTableEye' : 'mdiTable'" :icon-name="['view', 'materializedView'].includes(element.elementType) ? 'mdiTableEye' : 'mdiTable'"
:size="18" :size="18"
/> />
<span :title="`${t('general.data').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('general.data').toUpperCase()}: ${t(`database.${element.elementType}`)}`">

View File

@@ -143,7 +143,7 @@
:selected-schema="selectedSchema" :selected-schema="selectedSchema"
:context-event="miscContextEvent" :context-event="miscContextEvent"
@open-create-view-tab="openCreateElementTab('view')" @open-create-view-tab="openCreateElementTab('view')"
@open-create-materializedview-tab="openCreateElementTab('materialized-view')" @open-create-materializedView-tab="openCreateElementTab('materialized-view')"
@open-create-trigger-tab="openCreateElementTab('trigger')" @open-create-trigger-tab="openCreateElementTab('trigger')"
@open-create-trigger-function-tab="openCreateElementTab('trigger-function')" @open-create-trigger-function-tab="openCreateElementTab('trigger-function')"
@open-create-routine-tab="openCreateElementTab('routine')" @open-create-routine-tab="openCreateElementTab('routine')"

View File

@@ -16,9 +16,9 @@
/> {{ t('database.createNewView') }}</span> /> {{ t('database.createNewView') }}</span>
</div> </div>
<div <div
v-if="props.selectedMisc === 'materializedview'" v-if="props.selectedMisc === 'materializedView'"
class="context-element" class="context-element"
@click="emit('open-create-materializedview-tab')" @click="emit('open-create-materializedView-tab')"
> >
<span class="d-flex"> <span class="d-flex">
<BaseIcon <BaseIcon
@@ -106,7 +106,7 @@ const props = defineProps({
const emit = defineEmits([ const emit = defineEmits([
'open-create-view-tab', 'open-create-view-tab',
'open-create-materializedview-tab', 'open-create-materializedView-tab',
'open-create-trigger-tab', 'open-create-trigger-tab',
'open-create-routine-tab', 'open-create-routine-tab',
'open-create-function-tab', 'open-create-function-tab',

View File

@@ -121,7 +121,7 @@
<summary <summary
class="accordion-header misc-name" class="accordion-header misc-name"
:class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.trigger}" :class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.trigger}"
@contextmenu.prevent="showMiscFolderContext($event, 'materializedview')" @contextmenu.prevent="showMiscFolderContext($event, 'materializedView')"
> >
<BaseIcon <BaseIcon
class="misc-icon mr-1" class="misc-icon mr-1"
@@ -133,7 +133,7 @@
icon-name="mdiFolderOpen" icon-name="mdiFolderOpen"
:size="18" :size="18"
/> />
{{ t('database.materializedview', 2) }} {{ t('database.materializedView', 2) }}
</summary> </summary>
<div class="accordion-body"> <div class="accordion-body">
<div> <div>
@@ -477,8 +477,12 @@ const searchTerm = computed(() => {
}); });
const filteredTables = computed(() => { const filteredTables = computed(() => {
if (props.searchMethod === 'elements') if (props.searchMethod === 'elements') {
return props.database.tables.filter(table => table.name.search(searchTerm.value) >= 0 && table.type === 'table'); const searchTermLower = searchTerm.value.toLowerCase();
return props.database.tables.filter(table =>
table.name.toLowerCase().includes(searchTermLower) && table.type === 'table'
);
}
else else
return props.database.tables; return props.database.tables;
}); });
@@ -492,9 +496,9 @@ const filteredViews = computed(() => {
const filteredMatViews = computed(() => { const filteredMatViews = computed(() => {
if (props.searchMethod === 'elements') if (props.searchMethod === 'elements')
return props.database.tables.filter(table => table.name.search(searchTerm.value) >= 0 && table.type === 'materializedview'); return props.database.tables.filter(table => table.name.search(searchTerm.value) >= 0 && table.type === 'materializedView');
else else
return props.database.tables.filter(table => table.type === 'materializedview'); return props.database.tables.filter(table => table.type === 'materializedView');
}); });
const filteredTriggers = computed(() => { const filteredTriggers = computed(() => {

View File

@@ -50,7 +50,7 @@
class="text-light mt-1 mr-1" class="text-light mt-1 mr-1"
icon-name="mdiTableEye" icon-name="mdiTableEye"
:size="18" :size="18"
/> {{ t('database.materializedview') }}</span> /> {{ t('database.materializedView') }}</span>
</div> </div>
<div <div
v-if="workspace.customizations.triggerAdd" v-if="workspace.customizations.triggerAdd"

View File

@@ -48,7 +48,7 @@
/> {{ t('application.settings') }}</span> /> {{ t('application.settings') }}</span>
</div> </div>
<div <div
v-if="selectedTable && selectedTable.type === 'materializedview' && customizations.materializedViewSettings" v-if="selectedTable && selectedTable.type === 'materializedView' && customizations.materializedViewSettings"
class="context-element" class="context-element"
@click="openMaterializedViewSettingTab" @click="openMaterializedViewSettingTab"
> >

View File

@@ -195,7 +195,7 @@ const saveChanges = async () => {
uid: props.connection.uid, uid: props.connection.uid,
schema: props.schema, schema: props.schema,
elementName: localView.value.name, elementName: localView.value.name,
elementType: 'materializedview', elementType: 'materializedView',
type: 'materialized-view-props' type: 'materialized-view-props'
}); });

View File

@@ -227,7 +227,7 @@ const saveChanges = async () => {
schema: props.schema, schema: props.schema,
elementName: oldName, elementName: oldName,
elementNewName: localView.value.name, elementNewName: localView.value.name,
elementType: 'materializedview' elementType: 'materializedView'
}); });
changeBreadcrumbs({ schema: props.schema, view: localView.value.name }); changeBreadcrumbs({ schema: props.schema, view: localView.value.name });

View File

@@ -458,6 +458,8 @@ const getFieldsData = async () => {
addNotification({ status: 'error', message: err.stack }); addNotification({ status: 'error', message: err.stack });
} }
isLoading.value = false;
if (workspace.value.customizations.tableCheck) { if (workspace.value.customizations.tableCheck) {
try { // Table checks try { // Table checks
const { status, response } = await Tables.getTableChecks(params); const { status, response } = await Tables.getTableChecks(params);
@@ -478,8 +480,6 @@ const getFieldsData = async () => {
addNotification({ status: 'error', message: err.stack }); addNotification({ status: 'error', message: err.stack });
} }
} }
isLoading.value = false;
}; };
const saveChanges = async () => { const saveChanges = async () => {

View File

@@ -7,7 +7,7 @@
:key="i" :key="i"
class="mb-4" class="mb-4"
> >
{{ t(shortcutEvents[shortcut.event].l18n, {param: shortcutEvents[shortcut.event].l18nParam}) }} {{ t(shortcutEvents[shortcut.event].i18n, {param: shortcutEvents[shortcut.event].i18nParam}) }}
</div> </div>
</div> </div>
<div class="column col-16"> <div class="column col-16">

View File

@@ -538,7 +538,7 @@ const closeContext = () => {
}; };
const showDeleteConfirmModal = (e: any) => { const showDeleteConfirmModal = (e: any) => {
if (e.code !== 'Delete') return; if (e && e.code !== 'Delete') return;
if (e && e.path && ['INPUT', 'TEXTAREA', 'SELECT'].includes(e.path[0].tagName)) if (e && e.path && ['INPUT', 'TEXTAREA', 'SELECT'].includes(e.path[0].tagName))
return; return;
if (selectedRows.value.length === 0) return; if (selectedRows.value.length === 0) return;
@@ -563,6 +563,7 @@ const deleteSelected = () => {
table: getTable(resultsetIndex.value), table: getTable(resultsetIndex.value),
rows rows
}; };
console.log(params);
emit('delete-selected', params); emit('delete-selected', params);
}; };
@@ -696,15 +697,15 @@ const fillCell = (event: { name: string; group: string; type: string }) => {
} }
fakeValue = (fakerCustom as any)[event.group][event.name](); fakeValue = (fakerCustom as any)[event.group][event.name]();
if (['string', 'number'].includes(typeof fakeValue)) { const isDateType = [...DATE, ...DATETIME].includes(selectedCell.value.type);
if (isDateType)
fakeValue = moment(fakeValue).format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
else if (['string', 'number'].includes(typeof fakeValue)) {
if (typeof fakeValue === 'number') if (typeof fakeValue === 'number')
fakeValue = String(fakeValue); fakeValue = String(fakeValue);
if (selectedCell.value.length) if (selectedCell.value.length)
fakeValue = fakeValue.substring(0, selectedCell.value.length < 1024 ? Number(selectedCell.value.length) : 1024); fakeValue = fakeValue.substring(0, selectedCell.value.length < 1024 ? Number(selectedCell.value.length) : 1024);
} }
else if ([...DATE, ...DATETIME].includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
else if (TIME.includes(selectedCell.value.type)) else if (TIME.includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`HH:mm:ss${datePrecision}`); fakeValue = moment(fakeValue).format(`HH:mm:ss${datePrecision}`);

View File

@@ -440,7 +440,7 @@ const editON = async (field: string) => {
return; return;
} }
if (BLOB.includes(type)) { if (BLOB.includes(type) && props.fields[field].key !== 'pri') {
isBlobEditor.value = true; isBlobEditor.value = true;
editingContent.value = content || ''; editingContent.value = content || '';
fileToUpload.value = null; fileToUpload.value = null;
@@ -458,9 +458,12 @@ const editON = async (field: string) => {
}; };
} }
} }
emit('start-editing', field); emit('start-editing', field);
return; return;
} }
else if (BLOB.includes(type) && props.fields[field].key === 'pri')// Disable edit on BLOB primary until we are sure it's not problematic
return;
// Inline editable fields // Inline editable fields
editingContent.value = originalContent.value; editingContent.value = originalContent.value;

View File

@@ -56,10 +56,10 @@ export function useResultTables (uid: string, reloadTable: () => void) {
if (status === 'success') if (status === 'success')
reloadTable(); reloadTable();
else else
this.addNotification({ status: 'error', message: response }); addNotification({ status: 'error', message: response });
} }
catch (err) { catch (err) {
this.addNotification({ status: 'error', message: err.stack }); addNotification({ status: 'error', message: err.stack });
isQuering.value = false; isQuering.value = false;
} }
} }

View File

@@ -141,7 +141,7 @@ export const csCZ = {
total: 'Celkem', total: 'Celkem',
table: 'Tabulka | Tabulky', table: 'Tabulka | Tabulky',
view: 'Pohled | Pohledy', view: 'Pohled | Pohledy',
materializedview: 'Materializovaný pohled', materializedView: 'Materializovaný pohled',
definer: 'Definér', definer: 'Definér',
algorithm: 'Algoritmus', algorithm: 'Algoritmus',
trigger: 'Trigger | Triggery', trigger: 'Trigger | Triggery',

View File

@@ -141,7 +141,7 @@ export const enUS = {
total: 'Total', total: 'Total',
table: 'Table | Tables', table: 'Table | Tables',
view: 'View | Views', view: 'View | Views',
materializedview: 'Materialized view | Materialized views', materializedView: 'Materialized view | Materialized views',
definer: 'Definer', definer: 'Definer',
algorithm: 'Algorithm', algorithm: 'Algorithm',
trigger: 'Trigger | Triggers', trigger: 'Trigger | Triggers',
@@ -401,6 +401,7 @@ export const enUS = {
ignoreDuplicates: 'Ignore duplicates', ignoreDuplicates: 'Ignore duplicates',
wrongImportPassword: 'Wrong import password', wrongImportPassword: 'Wrong import password',
wrongFileFormat: 'Wrong file format', wrongFileFormat: 'Wrong file format',
invalidFile: 'Invalid file',
dataImportSuccess: 'Data successfully imported', dataImportSuccess: 'Data successfully imported',
note: 'Note | Notes', note: 'Note | Notes',
thereAreNoNotesYet: 'There are no notes yet', thereAreNoNotesYet: 'There are no notes yet',
@@ -416,7 +417,11 @@ export const enUS = {
openNotes: 'Open notes', openNotes: 'Open notes',
debugConsole: 'Debug console', // <- console tab name debugConsole: 'Debug console', // <- console tab name
executedQueries: 'Executed queries', // <- console tab name executedQueries: 'Executed queries', // <- console tab name
sizeLimitError: 'Maximum size of {size} exceeded' sizeLimitError: 'Maximum size of {size} exceeded',
fullScreen: 'Full screen',
zoomIn: 'Zoom in',
zoomOut: 'Zoom out',
zoomReset: 'Reset zoom'
}, },
faker: { // Faker.js methods, used in random generated content faker: { // Faker.js methods, used in random generated content
address: 'Address', address: 'Address',

View File

@@ -1,5 +1,14 @@
/**
* [TRANSLATION UPDATE HELPER]
* - Open a terminal in antares folder and run `npm run translation:check short-code` replacing short-code with the one you are updating.
* - The command will output which terms are missing or not translated from english.
* - Open antares folder with your editor of choice.
* - Go to antares/src/renderer/i18n/ and open the locale file you want to translate.
* - Add and translate missing terms and consider whether to translate untranslated terms.
*/
export const esES = { export const esES = {
general: { general: { // General purpose terms
edit: 'Editar', edit: 'Editar',
save: 'Guardar', save: 'Guardar',
close: 'Cerrar', close: 'Cerrar',
@@ -8,6 +17,7 @@ export const esES = {
cancel: 'Cancelar', cancel: 'Cancelar',
send: 'Enviar', send: 'Enviar',
refresh: 'Refrescar', refresh: 'Refrescar',
autoRefresh: 'Auto refresco',
version: 'Versión', version: 'Versión',
donate: 'Donar', donate: 'Donar',
run: 'Ejecutar', run: 'Ejecutar',
@@ -18,12 +28,62 @@ export const esES = {
add: 'Añadir', add: 'Añadir',
data: 'Datos', data: 'Datos',
properties: 'Propiedades', properties: 'Propiedades',
name: 'Nombre',
clear: 'Limpiar',
options: 'Opciones',
insert: 'Insertar', insert: 'Insertar',
discard: 'Descartar',
stay: 'Mantener',
author: 'Autor',
upload: 'Subir',
browse: 'Navegar',
content: 'Contenido',
cut: 'Cortar',
copy: 'Copiar',
paste: 'Pegar',
duplicate: 'Duplicar',
tools: 'Herramientas',
seconds: 'Segundos', seconds: 'Segundos',
deleteConfirm: 'Confirmas la cancelación de', all: 'Todos',
uploadFile: 'Cargar fichero' new: 'Nuevo',
select: 'Seleccionar',
change: 'Cambiar',
include: 'Agregar',
includes: 'Agregados',
completed: 'Completado',
aborted: 'Cancelado',
disabled: 'Deshabilitado',
enable: 'Habilitar',
disable: 'Desabilitar',
contributors: 'Colaboradores',
pin: 'Fijar',
unpin: 'Desfijar',
folder: 'Carpeta | Carpetas',
none: 'Ninguno',
singleQuote: 'Comillas simples',
doubleQuote: 'Comillas dobles',
deleteConfirm: 'Confirmar la cancelación de',
uploadFile: 'Cargar fichero',
format: 'Formato', // Format code
history: 'Histórico',
filter: 'Filtro',
manualValue: 'Valor manual',
selectAll: 'Seleccionar todo',
pageNumber: 'Número de página',
directoryPath: 'Ruta de directorio',
actionSuccessful: '{action} exitoso',
outputFormat: 'Formato de salida',
singleFile: 'Fichero {ext} único',
zipCompressedFile: 'Fichero ZIP {ext} comprimido',
copyName: 'Copiar nombre',
search: 'Búsqueda',
title: 'Título',
archive: 'Archivo', // verb
undo: 'Deshacer',
moveTo: 'Mover a'
}, },
connection: { connection: { // Database connection
connection: 'Conexión',
connectionName: 'Nombre de la conexión', connectionName: 'Nombre de la conexión',
client: 'Cliente', client: 'Cliente',
hostName: 'Servidor', hostName: 'Servidor',
@@ -35,6 +95,17 @@ export const esES = {
connected: 'Conectado', connected: 'Conectado',
disconnect: 'Desconectar', disconnect: 'Desconectar',
disconnected: 'Desconectado', disconnected: 'Desconectado',
ssl: 'SSL',
enableSsl: 'Habilitar SSL',
privateKey: 'Clave privada',
certificate: 'Certificado',
caCertificate: 'Certificado CA',
ciphers: 'Cifrado',
untrustedConnection: 'Conexión no confiable',
passphrase: 'Frase de paso',
sshTunnel: 'Túnel SSH',
enableSsh: 'Habilitar SSH',
connectionString: 'Cadena de conexión',
addConnection: 'Añadir conexión', addConnection: 'Añadir conexión',
createConnection: 'Crear conexión', createConnection: 'Crear conexión',
createNewConnection: 'Crear nueva conexión', createNewConnection: 'Crear nueva conexión',
@@ -42,26 +113,216 @@ export const esES = {
testConnection: 'Comprobar conexión', testConnection: 'Comprobar conexión',
editConnection: 'Editar conexión', editConnection: 'Editar conexión',
deleteConnection: 'Eliminar conexión', deleteConnection: 'Eliminar conexión',
connectionSuccessfullyMade: 'Conexión realizada correctamente!' connectionSuccessfullyMade: 'Conexión realizada correctamente!',
readOnlyMode: 'Solo lectura',
allConnections: 'Todas las conexiones',
searchForConnections: 'Buscar por conexiones',
keepAliveInterval: 'Tiempo de mantenimiento de conexión',
singleConnection: 'Conexión única'
}, },
database: { database: { // Database related terms
schema: 'Esquema', schema: 'Esquema',
type: 'Tipo', type: 'Tipo',
unableEditFieldWithoutPrimary: 'No se puede editar una campo sin Llave Primaria en el registro', insert: 'Insertar',
editCell: 'Editar celda', indexes: 'Índices',
foreignKeys: 'Claves Foráneas',
tablaChecks: 'Validación de tabla',
length: 'Longitud',
unsigned: 'Sin signo',
default: 'Por defecto',
comment: 'Comentario',
key: 'Clave | Claves',
order: 'Orden',
expression: 'Expresión',
autoIncrement: 'Autoincremental',
engine: 'Motor',
field: 'Campo | Campos',
approximately: 'Aproximadamente',
total: 'Total',
table: 'Tabla | Tablas',
view: 'Vista | Vistas',
materializedView: 'Vista Materializada | Vistas Materializadas',
definer: 'Definidor',
algorithm: 'Algoritmo',
trigger: 'Disparador | Disparadores',
storedRoutine: 'Procedimiento almacenado | Procedimientos almacenados',
scheduler: 'Planificador | Planificadores',
event: 'Evento',
parameters: 'Parámetros',
function: 'Función | Funciones',
deterministic: 'Determinístico',
context: 'Contexto',
export: 'Exportar',
import: 'Importar',
returns: 'Retorno',
timing: 'Timing',
state: 'Estado',
execution: 'Ejecución',
starts: 'Inicio',
ends: 'Final',
variables: 'Variables',
processes: 'Procesos',
database: 'Base de Datos',
array: 'Tupla',
structure: 'Estructura',
row: 'Fila | Filas',
cell: 'Celda | Celdas',
triggerFunction: 'Función disparadora | Funciones disparadoras',
routine: 'Rutina | Rutinas',
drop: 'Abandonar',
commit: 'Commit',
rollback: 'Marcha atrás',
ddl: 'DDL',
collation: 'Colación',
resultsTable: 'Tabla de resultados',
unableEditFieldWithoutPrimary: 'No es posible modificar un campo sin una clave primaria en el set de resultados',
editCell: 'Modificar celda',
deleteRows: 'Eliminar fila | Eliminar {count} filas', deleteRows: 'Eliminar fila | Eliminar {count} filas',
confirmToDeleteRows: '¿Quiere realmente eliminar una fila? | ¿Quiere realmente eliminar {count} filas?', confirmToDeleteRows: '¿Quiere realmente eliminar una fila? | ¿Quiere realmente eliminar {count} filas?',
addNewRow: 'Añadir nueva fila', addNewRow: 'Añadir nueva fila',
numberOfInserts: 'Numero de inserciones', numberOfInserts: 'Número de inserciones',
affectedRows: 'Filas afectadas' affectedRows: 'Líneas afectadas',
createNewDatabase: 'Crear nueva Base de Datos',
databaseName: 'Nombre de Base de Datos',
serverDefault: 'Servidor por defecto',
deleteDatabase: 'Eliminar Base de Datos',
editDatabase: 'Modificar Base de Datos',
clearChanges: 'Deshacer cambios',
addNewField: 'Añadir nuevo campo',
manageIndexes: 'Administrar índices',
manageForeignKeys: 'Administrar claves foráneas',
manageTableChecks: 'Administrar validaciones de tabla',
allowNull: 'Permitir NULL',
zeroFill: 'Rellenar con ceros',
customValue: 'Valor predeterminado',
onUpdate: 'On UPDATE',
deleteField: 'Eliminar campo',
createNewIndex: 'Crear nuevo índice',
createNewCheck: 'Crear nueva verificación',
checkClause: 'Comprobar cláusula',
addToIndex: 'Añadir al índice',
createNewTable: 'Crear nueva tabla',
emptyTable: 'Tabla vacía',
duplicateTable: 'Duplicar tabla',
deleteTable: 'Eliminar tabla',
exportTable: 'Exportar tabla',
emptyConfirm: 'Confirmar vaciado',
thereAreNoIndexes: 'No hay índices',
thereAreNoForeign: 'No hay claves foráneas',
thereAreNoTableChecks: 'No hay validaciones de tabla',
createNewForeign: 'Crear nueva clave foránea',
referenceTable: 'Ref. tabla',
referenceField: 'Ref. campo',
foreignFields: 'Campos foráneos',
invalidDefault: 'Valor por defecto no válido',
onDelete: 'On DELETE',
selectStatement: 'Declaración SELECT',
triggerStatement: 'Declaración TRIGGER',
sqlSecurity: 'Seguridad SQL',
updateOption: 'Opción UPDATE',
deleteView: 'Eliminar vista',
createNewView: 'Crear nueva vista',
createNewMaterializedView: 'Crear nueva vista materializada',
deleteTrigger: 'Eliminar disparador',
createNewTrigger: 'Crear nuevo disparador',
currentUser: 'Usuario actual',
routineBody: 'Cuerpo de rutina',
dataAccess: 'Acceso a datos',
thereAreNoParameters: 'No hay parámetros',
createNewParameter: 'Crear nuevo parámetro',
createNewRoutine: 'Crear nuevo procedimiento almacenado',
deleteRoutine: 'Eliminar procedimiento almacenado',
functionBody: 'Cuerpo de función',
createNewFunction: 'Crear nueva función',
deleteFunction: 'Eliminar función',
schedulerBody: 'Cuerpo de planificador',
createNewScheduler: 'Crear nuevo planificador',
deleteScheduler: 'Eliminar planificador',
preserveOnCompletion: 'Mantener al finalizar',
tableFiller: 'Rellenador de tabla',
fakeDataLanguage: 'Lenguaje de datos dummy',
queryDuration: 'Duración de la consulta',
setNull: 'Establecer a NULL',
processesList: 'Lista de procesos',
processInfo: 'Información de proceso',
manageUsers: 'Administrar usuarios',
createNewSchema: 'Crear nuevo esquema',
schemaName: 'Nombre de esquema',
editSchema: 'Modificar esquema',
deleteSchema: 'Eliminar esquema',
noSchema: 'No hay esquemas',
runQuery: 'Ejecutar consulta',
thereAreNoTableFields: 'No hay campos en la tabla',
newTable: 'Nueva tabla',
newView: 'Nueva vista',
newMaterializedView: 'Nueva vista materializada',
newTrigger: 'Nuevo disparador',
newRoutine: 'Nueva rutina',
newFunction: 'Nueva función',
newScheduler: 'Nuevo planificador',
newTriggerFunction: 'Nueva función de disparador',
thereAreNoQueriesYet: 'No quedan mas consultas',
searchForQueries: 'Buscar consultas',
killProcess: 'Matar proceso',
exportSchema: 'Exportar esquema',
importSchema: 'Importar esquema',
newInsertStmtEvery: 'Nueva declaración INSERT',
processingTableExport: 'Procesando {table}',
fetchingTableExport: 'Obteniendo datos de {table}',
writingTableExport: 'Escribiendo datos de {table}',
checkAllTables: 'Verificar todas las tablas',
uncheckAllTables: 'Desmarcar todas las tablas',
killQuery: 'Matar consulta',
insertRow: 'Añadir fila | Añadir filas',
commitMode: 'Modo de Commit',
autoCommit: 'Automático',
manualCommit: 'Manual',
importQueryErrors: 'Atención: {n} de error encontrado | Atención: {n} errores encontrados',
executedQueries: '{n} consulta ejecutada | {n} consultas ejecutadas',
disableFKChecks: 'Deshabilitar comprobación de claves foráneas',
formatQuery: 'Formato de consulta',
queryHistory: 'Histórico de consultas',
clearQuery: 'Limpiar consulta',
fillCell: 'Rellenar celda',
executeSelectedQuery: 'Ejecutar consulta seleccionada',
noResultsPresent: 'No se obtuvieron resultados',
sqlExportOptions: 'Opciones de exportación de SQL',
targetTable: 'Tabla objetivo',
switchDatabase: 'Cambiar de Base de datos',
searchForElements: 'Buscar por elementos',
searchForSchemas: 'Buscar por esquemas',
savedQueries: 'Consultas almacenadas'
}, },
application: { application: {
settings: 'Configuración', settings: 'Configuración',
console: 'Consola',
general: 'General', general: 'General',
themes: 'Temas', themes: 'Temas',
update: 'Actualizar', update: 'Actualizar',
about: 'Sobre', about: 'Sobre',
language: 'Idioma', language: 'Idioma',
shortcuts: 'Atajos',
key: 'Tecla | Teclas', // Keyboard key
event: 'Evento',
light: 'Claro',
dark: 'Oscuro',
autoCompletion: 'Autocompletado',
application: 'Aplicación',
editor: 'Editor',
changelog: 'Histórico de cambios',
small: 'Pequeño',
medium: 'Mediano',
large: 'Grande',
appearance: 'Apariencia',
color: 'Color',
label: 'Etiqueta',
icon: 'Icono',
customIcon: 'Icono personalizado',
fileName: 'Nombre de fichero',
choseFile: 'Elegir fichero',
data: 'Datos',
password: 'Contraseña',
required: 'Requerido',
madeWithJS: 'Hecho con 💛 y JavaScript!', madeWithJS: 'Hecho con 💛 y JavaScript!',
checkForUpdates: 'Comprobar actualizaciones', checkForUpdates: 'Comprobar actualizaciones',
noUpdatesAvailable: 'No hay actualizaciones', noUpdatesAvailable: 'No hay actualizaciones',
@@ -71,7 +332,255 @@ export const esES = {
downloadingUpdate: 'Descargando actualización', downloadingUpdate: 'Descargando actualización',
updateDownloaded: 'Descargada actualización', updateDownloaded: 'Descargada actualización',
restartToInstall: 'Reiniciar Antares para instalar', restartToInstall: 'Reiniciar Antares para instalar',
includeBetaUpdates: 'Incluir actualizaciones en fase beta',
notificationsTimeout: 'Tiempo de espera', notificationsTimeout: 'Tiempo de espera',
openNewTab: 'Abrir nueva pestaña' openNewTab: 'Abrir nueva pestaña',
unsavedChanges: 'Cambios sin guardar',
discardUnsavedChanges: 'Tiene algunos cambios sin guardar. Al cerrar esta pestaña, serán descartados.',
applicationTheme: 'Tema de la Aplicación',
editorTheme: 'Editor de Tema',
wrapLongLines: 'Mantener lineas largas',
markdownSupported: 'Markdown soportado',
plantATree: 'Planta un arbol',
dataTabPageSize: 'Resultados por página',
noOpenTabs: 'No hay pestañas abiertas. Navega por la barra de la izquierda o:',
restorePreviousSession: 'Restablecer la sesión anterior',
closeTab: 'Cerrar pestaña',
goToDownloadPage: 'Ir a la página de descargas',
disableBlur: 'Deshabilitar opacidad',
missingOrIncompleteTranslation: '¿No hay traducción o hay algo incorrecto?',
findOutHowToContribute: 'Mira como puedes contribuir',
reportABug: 'Informar de un problema',
nextTab: 'Siguiente pestaña',
previousTab: 'Anterior pestaña',
selectTabNumber: 'Selecciona numero de pestaña {param}',
toggleConsole: 'Alternar vista de consola',
addShortcut: 'Añadir atajo',
editShortcut: 'Modificar atajo',
deleteShortcut: 'Eliminar atajo',
restoreDefaults: 'Restablecer valores por defecto',
restoreDefaultsQuestion: '¿Está seguro que quiere establecer los valores por defecto?',
registerAShortcut: 'Registrar un atajo',
invalidShortcutMessage: 'Combinación no válida, por favor intente otra',
shortcutAlreadyExists: 'El atajo ya existe',
saveContent: 'Guardar contenido',
openAllConnections: 'Abrir todas las conexiones',
openSettings: 'Abrir configuración',
runOrReload: 'Ejecutar o recargar',
openFilter: 'Abrir filtro',
nextResultsPage: 'Siguiente pagina de resultados',
previousResultsPage: 'Anterior página de resultados',
editFolder: 'Modificar carpeta',
folderName: 'Nombre de carpeta',
deleteFolder: 'Eliminar carpeta',
newFolder: 'Crear nueva carpeta',
outOfFolder: 'Fuera de la carpeta',
editConnectionAppearance: 'Modificar apariencia de conexión',
defaultCopyType: 'Default copy type',
showTableSize: 'Mostrar tamaño de tabla en la barra lateral',
showTableSizeDescription: 'Solo para MySQL/MariaDB. Habilitar esta opción puede afectar al rendimiento en esquemas con muchas tablas.',
switchSearchMethod: 'Switch search method',
phpArray: 'Array de PHP',
closeAllTabs: 'Cerrar todas las pestañas',
closeOtherTabs: 'Cerrar las otras pestañas',
closeTabsToLeft: 'Cerrar las pestañas a la izquierda',
closeTabsToRight: 'Cerrar las pestañas a la derecha',
csvFieldDelimiter: 'Delimitador de campos',
csvLinesTerminator: 'Terminador de líneas',
csvStringDelimiter: 'Delimitador de cadenas',
csvIncludeHeader: 'Incluir cabecera',
csvExportOptions: 'Opciones de exportación de CSV',
exportData: 'Exportar datos',
exportDataExplanation: 'Exportar conexiones guardadas en Antares. Se le preguntará por una contraseña para encriptar el fichero exportado.',
importData: 'Importar datos',
importDataExplanation: 'Importará un fichero con extensión .antares que contiene conexiones. Necesitará la contraseña con la que se encriptó el mismo.',
includeConnectionPasswords: 'Incluir contraseñas de conexión',
includeFolders: 'Incluir carpetas',
encryptionPassword: 'Encryption password',
encryptionPasswordError: 'The encryption password must be at least 8 characters long.',
ignoreDuplicates: 'Ignore duplicates',
wrongImportPassword: 'Wrong import password',
wrongFileFormat: 'Wrong file format',
dataImportSuccess: 'Data successfully imported',
note: 'Note | Notes',
thereAreNoNotesYet: 'There are no notes yet',
addNote: 'Add note',
editNote: 'Edit note',
saveAsNote: 'Save as note',
showArchivedNotes: 'Show archived notes',
hideArchivedNotes: 'Hide archived notes',
tag: 'Tag', // Note tag,
saveFile: 'Save file',
saveFileAs: 'Save file as',
openFile: 'Open file',
openNotes: 'Open notes',
debugConsole: 'Debug console', // <- console tab name
executedQueries: 'Executed queries', // <- console tab name
sizeLimitError: 'Maximum size of {size} exceeded'
},
faker: { // Faker.js methods, used in random generated content
address: 'Dirección',
commerce: 'Comercio',
company: 'Compañía',
database: 'Base de datos',
date: 'Fecha',
finance: 'Finanzas',
git: 'Git',
hacker: 'Hacker',
internet: 'Internet',
lorem: 'Lorem',
name: 'Nombre',
music: 'Música',
phone: 'Teléfono',
random: 'Aleatorio',
system: 'Sistema',
time: 'Hora',
vehicle: 'Vehículo',
zipCode: 'Código Postal',
zipCodeByState: 'Código Postal por Estado',
city: 'Ciudad',
cityPrefix: 'Prefijo de ciudad',
citySuffix: 'Sufijo de ciudad',
streetName: 'Nombre de calle',
streetAddress: 'Dirección',
streetSuffix: 'Sufijo de calle',
streetPrefix: 'Prefijo de calle',
secondaryAddress: 'Dirección secundaria',
county: 'Condado',
country: 'País',
countryCode: 'Código de país',
state: 'Estado',
stateAbbr: 'Abreviatura de Estado',
latitude: 'Latitud',
longitude: 'Longitud',
direction: 'Dirección',
cardinalDirection: 'Dirección cardinal',
ordinalDirection: 'Dirección ordinal',
nearbyGPSCoordinate: 'Coordenadas GPS',
timeZone: 'Zona horaria',
color: 'Color',
department: 'Departmento',
productName: 'Nombre de producto',
price: 'Precio',
productAdjective: 'Adjetivo de producto',
productMaterial: 'Material de producto',
product: 'Producto',
productDescription: 'Descripción de producto',
suffixes: 'Sufijos',
companyName: 'Nombre de compañía',
companySuffix: 'Sufijo de compañía',
catchPhrase: 'Catch phrase',
bs: 'BS',
catchPhraseAdjective: 'Catch phrase adjective',
catchPhraseDescriptor: 'Catch phrase descriptor',
catchPhraseNoun: 'Catch phrase noun',
bsAdjective: 'BS adjective',
bsBuzz: 'BS buzz',
bsNoun: 'BS noun',
column: 'Columna',
type: 'Tipo',
collation: 'Colación',
engine: 'Motor',
past: 'Pasado',
now: 'Ahora',
future: 'Futuro',
between: 'Entre',
recent: 'Reciente',
soon: 'Pronto',
month: 'Mes',
weekday: 'Día de la semana',
account: 'Cuenta',
accountName: 'Nombre de cuenta',
routingNumber: 'Número de enrutamiento',
mask: 'Máscara',
amount: 'Cantidad',
transactionType: 'Tipo de transacción',
currencyCode: 'Código de Moneda',
currencyName: 'Nombre de Moneda',
currencySymbol: 'Símbolo de Moneda',
bitcoinAddress: 'Dirección Bitcoin',
litecoinAddress: 'Dirección Litecoin',
creditCardNumber: 'Número de tarjeta',
creditCardCVV: 'CVV',
ethereumAddress: 'Dirección Ethereum',
iban: 'IBAN',
bic: 'BIC',
transactionDescription: 'Descripción de transacción',
branch: 'Rama',
commitEntry: 'Entrada de Commit',
commitMessage: 'Mensaje de Commit',
commitSha: 'SHA de Commit',
shortSha: 'SHA corto',
abbreviation: 'Abreviatura',
adjective: 'Adjetivo',
noun: 'Sustantivo',
verb: 'Verbo',
ingverb: 'Adverbio',
phrase: 'Frase',
avatar: 'Avatar',
email: 'Email',
exampleEmail: 'Email de ejemplo',
userName: 'Nombre de usuario',
protocol: 'Protocolo',
url: 'URL',
domainName: 'Dominio',
domainSuffix: 'Prefijo de dominio',
domainWord: 'Palabra de dominio',
ip: 'IP',
ipv6: 'IPv6',
userAgent: 'Agente de Usuario',
mac: 'MAC',
password: 'Contraseña',
word: 'Palabra',
words: 'Palabras',
sentence: 'Sentencia',
slug: 'Slug',
sentences: 'Sentencias',
paragraph: 'Frase',
paragraphs: 'Frases',
text: 'Texto',
lines: 'Lineas',
genre: 'Género',
firstName: 'Nombre',
lastName: 'Apellido',
middleName: 'Apellido',
findName: 'Nombre completo',
jobTitle: 'Ocupación',
gender: 'Género',
prefix: 'Prefijo',
suffix: 'Sufijo',
title: 'Título',
jobDescriptor: 'Descripción de trabajo',
jobArea: 'Area de trabajo',
jobType: 'Tipo de trabajo',
phoneNumber: 'Número de teléfono',
phoneNumberFormat: 'Formato de número de teléfono',
phoneFormats: 'Formatos de teléfono',
number: 'Número',
float: 'Decimal',
arrayElement: 'Elemento Array',
arrayElements: 'Elementos de Array',
objectElement: 'Elemento Objeto',
uuid: 'UUID',
boolean: 'Booleano',
image: 'Imagen',
locale: 'Conf. regional',
alpha: 'Alpha',
alphaNumeric: 'Alfanumérico',
hexaDecimal: 'Hexadecimal',
fileName: 'Nombre de fichero',
commonFileName: 'Common file name',
mimeType: 'Mime-Type',
commonFileType: 'Common file type',
commonFileExt: 'Common file extension',
fileType: 'Tipo de fichero',
fileExt: 'Extension de fichero',
directoryPath: 'Ruta de directorio',
filePath: 'Ruta de fichero',
semver: 'SemVer',
manufacturer: 'Fabricante',
model: 'Modelo',
fuel: 'Combustible',
vin: 'VIN'
} }
}; };

View File

@@ -140,7 +140,7 @@ export const heIL = {
total: 'סך הכל', total: 'סך הכל',
table: 'טבלה | טבלאות', table: 'טבלה | טבלאות',
view: 'תצוגה | תצוגות', view: 'תצוגה | תצוגות',
materializedview: 'תצוגה ממומשת | תצוגות ממומשות', materializedView: 'תצוגה ממומשת | תצוגות ממומשות',
definer: 'מגדיר', definer: 'מגדיר',
algorithm: 'אלגוריתם', algorithm: 'אלגוריתם',
trigger: 'טריגר | טריגרים', trigger: 'טריגר | טריגרים',

View File

@@ -275,7 +275,7 @@ export const nlNL = {
savedQueries: 'Opgeslagen queries', savedQueries: 'Opgeslagen queries',
searchForElements: 'Zoek naar elementen', searchForElements: 'Zoek naar elementen',
searchForSchemas: 'Zoek naar schema\'s', searchForSchemas: 'Zoek naar schema\'s',
materializedview: 'Materialized view | Materialized views', materializedView: 'Materialized view | Materialized views',
createNewMaterializedView: 'Materialized view maken', createNewMaterializedView: 'Materialized view maken',
newMaterializedView: 'Nieuwe materialized view' newMaterializedView: 'Nieuwe materialized view'
}, },

View File

@@ -270,7 +270,7 @@ export const ruRU = {
importQueryErrors: 'Внимание: {n} ошибка возникла | Внимание: {n} ошибок произошло', importQueryErrors: 'Внимание: {n} ошибка возникла | Внимание: {n} ошибок произошло',
executedQueries: '{n} запрос выполнен | {n} запросов выполнено', executedQueries: '{n} запрос выполнен | {n} запросов выполнено',
insert: 'Вставить', insert: 'Вставить',
materializedview: 'Материализованное представление | Материализованные представления', materializedView: 'Материализованное представление | Материализованные представления',
exportTable: 'Экспорт таблицы', exportTable: 'Экспорт таблицы',
createNewMaterializedView: 'Создать новое материализованное представление', createNewMaterializedView: 'Создать новое материализованное представление',
newMaterializedView: 'Новое материализованное представление', newMaterializedView: 'Новое материализованное представление',

View File

@@ -270,7 +270,7 @@ export const uzUZ = {
importQueryErrors: 'Diqqat: {n} xato yuz berdi | Diqqat: {n} xatolar yuz berdi', importQueryErrors: 'Diqqat: {n} xato yuz berdi | Diqqat: {n} xatolar yuz berdi',
executedQueries: '{n} soʻrov bajarildi | {n} soʻrovlar bajarildi', executedQueries: '{n} soʻrov bajarildi | {n} soʻrovlar bajarildi',
insert: 'Kiritish', insert: 'Kiritish',
materializedview: 'Materializatsiya qilingan korinish | Materializatsiya qilingan korinishlar', materializedView: 'Materializatsiya qilingan korinish | Materializatsiya qilingan korinishlar',
exportTable: 'Jadvalni eksport qilish', exportTable: 'Jadvalni eksport qilish',
createNewMaterializedView: 'Yangi materializatsiya qilingan korinish yaratish', createNewMaterializedView: 'Yangi materializatsiya qilingan korinish yaratish',
newMaterializedView: 'Yangi materializatsiya qilingan korinish', newMaterializedView: 'Yangi materializatsiya qilingan korinish',

View File

@@ -117,6 +117,7 @@ export const zhCN = {
insert: '插入', insert: '插入',
indexes: '索引', indexes: '索引',
foreignKeys: '外键', foreignKeys: '外键',
tableChecks: '表检查',
length: '长度', length: '长度',
unsigned: '无符号', unsigned: '无符号',
default: '默认', default: '默认',
@@ -131,6 +132,7 @@ export const zhCN = {
total: '总计', total: '总计',
table: '表 | 表', table: '表 | 表',
view: '视图 | 视图', view: '视图 | 视图',
materializedView: '实体化视图 | 实体化视图',
definer: '定义者', definer: '定义者',
algorithm: '算法', algorithm: '算法',
trigger: '触发器 | 触发器', trigger: '触发器 | 触发器',
@@ -180,12 +182,15 @@ export const zhCN = {
addNewField: '添加新字段', addNewField: '添加新字段',
manageIndexes: '管理索引', manageIndexes: '管理索引',
manageForeignKeys: '管理外键', manageForeignKeys: '管理外键',
manageTableChecks: '管理表 check 约束',
allowNull: '允许 NULL', allowNull: '允许 NULL',
zeroFill: '零填充', zeroFill: '零填充',
customValue: '自定义值', customValue: '自定义值',
onUpdate: '在更新', onUpdate: '在更新',
deleteField: '删除字段', deleteField: '删除字段',
createNewIndex: '创建新索引', createNewIndex: '创建新索引',
createNewCheck: '创建新 check 约束',
checkClause: 'Check 约束',
addToIndex: '添加到索引', addToIndex: '添加到索引',
createNewTable: '创建新表', createNewTable: '创建新表',
emptyTable: '清空表', emptyTable: '清空表',
@@ -195,6 +200,7 @@ export const zhCN = {
emptyConfirm: '您是否确认清空', emptyConfirm: '您是否确认清空',
thereAreNoIndexes: '没有索引', thereAreNoIndexes: '没有索引',
thereAreNoForeign: '没有外键', thereAreNoForeign: '没有外键',
thereAreNoTableChecks: '没有表 check 约束',
createNewForeign: '创建新外键', createNewForeign: '创建新外键',
referenceTable: '参考表', referenceTable: '参考表',
referenceField: '参考字段', referenceField: '参考字段',
@@ -207,6 +213,7 @@ export const zhCN = {
updateOption: '更新选项', updateOption: '更新选项',
deleteView: '删除视图', deleteView: '删除视图',
createNewView: '创建新视图', createNewView: '创建新视图',
createNewMaterializedView: '创建新实体化视图',
deleteTrigger: '删除触发器', deleteTrigger: '删除触发器',
createNewTrigger: '创建新触发器', createNewTrigger: '创建新触发器',
currentUser: '当前用户', currentUser: '当前用户',
@@ -239,6 +246,7 @@ export const zhCN = {
thereAreNoTableFields: '没有表的字段', thereAreNoTableFields: '没有表的字段',
newTable: '新表', newTable: '新表',
newView: '新视图', newView: '新视图',
newMaterializedView: '新实体化视图',
newTrigger: '新触发器', newTrigger: '新触发器',
newRoutine: '新例程', newRoutine: '新例程',
newFunction: '新函数', newFunction: '新函数',
@@ -300,6 +308,7 @@ export const zhCN = {
color: '颜色', color: '颜色',
label: '标签', label: '标签',
icon: '图标', icon: '图标',
customIcon: '定制图标',
fileName: '文件名称', fileName: '文件名称',
choseFile: '选择文件', choseFile: '选择文件',
data: '数据', data: '数据',
@@ -324,7 +333,7 @@ export const zhCN = {
wrapLongLines: '将长行换行显示', wrapLongLines: '将长行换行显示',
markdownSupported: '支持 Markdown', markdownSupported: '支持 Markdown',
plantATree: '种植一棵树', plantATree: '种植一棵树',
dataTabPageSize: '数据标签的页面大小', dataTabPageSize: '每页结果',
noOpenTabs: '没有打开的标签, 请在左侧栏上导航或:', noOpenTabs: '没有打开的标签, 请在左侧栏上导航或:',
restorePreviousSession: '恢复上一个会话', restorePreviousSession: '恢复上一个会话',
closeTab: '关闭标签', closeTab: '关闭标签',
@@ -348,7 +357,6 @@ export const zhCN = {
saveContent: '保存内容', saveContent: '保存内容',
openAllConnections: '打开所有连接', openAllConnections: '打开所有连接',
openSettings: '打开设置', openSettings: '打开设置',
openScratchpad: '打开草稿栏',
runOrReload: '运行或重新加载', runOrReload: '运行或重新加载',
openFilter: '打开过滤器', openFilter: '打开过滤器',
nextResultsPage: '下一个结果页', nextResultsPage: '下一个结果页',
@@ -356,6 +364,8 @@ export const zhCN = {
editFolder: '编辑文件夹', editFolder: '编辑文件夹',
folderName: '文件夹名称', folderName: '文件夹名称',
deleteFolder: '删除文件夹', deleteFolder: '删除文件夹',
newFolder: '新文件夹',
outOfFolder: '',
editConnectionAppearance: '编辑连接的外观', editConnectionAppearance: '编辑连接的外观',
defaultCopyType: '默认复制类型', defaultCopyType: '默认复制类型',
showTableSize: '在侧边栏显示表大小', showTableSize: '在侧边栏显示表大小',
@@ -394,7 +404,10 @@ export const zhCN = {
saveFile: '保存文件', saveFile: '保存文件',
saveFileAs: '将文件另存为', saveFileAs: '将文件另存为',
openFile: '打开文件', openFile: '打开文件',
openNotes: '打开笔记' openNotes: '打开笔记',
debugConsole: '调试控制台',
executedQueries: '执行的查询',
sizeLimitError: '超过 {size} 的最大大小'
}, },
faker: { // Faker.js 方法,用于随机生成的内容 faker: { // Faker.js 方法,用于随机生成的内容
address: '地址', address: '地址',

View File

@@ -29,13 +29,7 @@ $explorebar-width: 14rem;
$footer-height: 1.5rem; $footer-height: 1.5rem;
@function get-excluding-size() { @function get-excluding-size() {
@if $platform == linux { @return $footer-height + $titlebar-height;
@return $footer-height;
}
@else {
@return $footer-height + $titlebar-height;
}
} }
/* stylelint-disable-next-line function-no-unknown */ /* stylelint-disable-next-line function-no-unknown */

View File

@@ -20,6 +20,7 @@
body { body {
user-select: none; user-select: none;
background-color: #000;
} }
a { a {

View File

@@ -1,5 +1,7 @@
/* stylelint-disable function-no-unknown */ /* stylelint-disable function-no-unknown */
.theme-light { .theme-light {
background: $body-bg;
::-webkit-scrollbar-track { ::-webkit-scrollbar-track {
background: #fff; background: #fff;
} }

View File

@@ -25,12 +25,13 @@ export interface SidebarElement {
export interface CustomIcon {base64: string; uid: string} export interface CustomIcon {base64: string; uid: string}
if (!key) { // If no key in local storace if (!key) { // If no key in local storage
const storedKey = ipcRenderer.sendSync('get-key');// Ask for key stored on disk const storedKey = ipcRenderer.sendSync('get-key');// Ask for key stored on disk
if (!storedKey) { // Of nop stored key on disk if (!storedKey) { // If not stored key on disk
const newKey = crypto.randomBytes(16).toString('hex'); const newKey = crypto.randomBytes(16).toString('hex');
localStorage.setItem('key', newKey); localStorage.setItem('key', newKey);
ipcRenderer.send('set-key', newKey);
key = newKey; key = newKey;
} }
else { else {

View File

@@ -3,6 +3,7 @@
declare module '@/App.vue'; declare module '@/App.vue';
declare module 'v-mask'; declare module 'v-mask';
declare module 'json2php'; declare module 'json2php';
declare module '*/encoding_charset.js';
declare module 'vuedraggable' {// <- to export as default declare module 'vuedraggable' {// <- to export as default
const draggableComponent: import('vue').DefineComponent<{ const draggableComponent: import('vue').DefineComponent<{
list: { list: {

View File

@@ -1,8 +1,7 @@
const path = require('path'); const path = require('path');
const webpack = require('webpack');
const ProgressPlugin = require('progress-webpack-plugin'); const ProgressPlugin = require('progress-webpack-plugin');
const { dependencies, devDependencies, version } = require('./package.json'); const { dependencies, devDependencies } = require('./package.json');
const externals = Object.keys(dependencies).concat(Object.keys(devDependencies)); const externals = Object.keys(dependencies).concat(Object.keys(devDependencies));
const isDevMode = process.env.NODE_ENV === 'development'; const isDevMode = process.env.NODE_ENV === 'development';
@@ -48,13 +47,7 @@ module.exports = { // Main
} }
}, },
plugins: [ plugins: [
new ProgressPlugin(true), new ProgressPlugin(true)
new webpack.DefinePlugin({
'process.env': {
PACKAGE_VERSION: `"${version}"`,
DISTRIBUTION: `"${process.env.DISTRIBUTION || 'none'}"`
}
})
], ],
module: { module: {
rules: [ rules: [