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

Compare commits

...

84 Commits

Author SHA1 Message Date
ba6063e636 chore(release): 0.7.20 2023-12-08 13:08:29 +01:00
b055350726 fix: missing update indicator on setting icon 2023-12-08 13:02:15 +01:00
b5b35be45c chore(release): 0.7.20-beta.2 2023-12-06 08:52:48 +01:00
6a72f6b4ae fix: communication with worker thread not working 2023-12-06 08:51:48 +01:00
861b704344 chore(release): 0.7.20-beta.1 2023-12-02 14:22:32 +01:00
9ce53165e8 chore: post merge cleanup 2023-12-02 14:21:34 +01:00
62614dceb9 Merge pull request #727 from antares-sql/flatpak-experiments
Flatpak experiments
2023-12-02 14:12:51 +01:00
8774dd44e6 Merge branch 'develop' into flatpak-experiments 2023-12-02 14:12:18 +01:00
f0ae01ca5e Merge branch 'develop' of https://github.com/antares-sql/antares into develop 2023-12-02 12:11:35 +01:00
03be777c2a refactor: worker threads to import sql dump instead of process 2023-12-02 11:35:20 +01:00
45a695ac0a refactor: improvements in worker implementation 2023-12-02 11:21:48 +01:00
c176841b75 refactor: worker threads to export sql dump instead of process 2023-12-02 09:31:54 +01:00
329246e2d8 refactor: minor refactor 2023-12-01 20:05:30 +01:00
e26809f260 fix(Flatpak): import/export schema not working 2023-12-01 14:18:40 +01:00
f13d4e6dce feat: copy element names on sidebar from context menu, closes #718 2023-11-29 18:15:22 +01:00
879de91516 refactor: minor refactor 2023-11-27 18:35:56 +01:00
38b32bfb28 build: process.exit on devtoolsInstaller 2023-11-27 13:37:24 +01:00
315d9d84c2 feat: logging errors on log file 2023-11-27 13:36:56 +01:00
c3d96cb35b refactor(Flatpak): temporarily disable import/export feature 2023-11-26 17:49:12 +01:00
05bd7672e1 chore: update package-lock.json 2023-11-26 17:28:45 +01:00
390bf88bb8 refactor: inport/export change for flatpak 2023-11-26 16:42:30 +01:00
984aa893d3 refactor: temporary disable windows process validation 2023-11-24 10:18:44 +01:00
1ac816eaa9 Merge branch 'master' of https://github.com/antares-sql/antares into develop 2023-11-16 18:30:05 +01:00
6f25fcbc05 ci: update workflow files 2023-11-16 18:16:41 +01:00
bc44465132 Merge branch 'master' of https://github.com/antares-sql/antares into develop 2023-11-16 18:09:51 +01:00
634a442213 ci: update workflow files 2023-11-16 18:01:40 +01:00
93fe28d07d chore(release): 0.7.20-beta.0 2023-11-15 21:36:27 +01:00
77a78078b2 chore(deps): update electron-builder 2023-11-14 15:14:59 +01:00
0da31254a9 Merge branch 'master' of https://github.com/antares-sql/antares into beta 2023-11-14 14:36:50 +01:00
b1aeabf2b6 ci: update gh actions scripts 2023-11-14 14:36:31 +01:00
f1c857fca9 chore(deps): update better-sqlite3 2023-11-14 10:38:26 +01:00
169f610b2e fix: error with multiple sessions in non-dev environment 2023-11-13 18:08:29 +01:00
075f542dc8 feat: ability to open multiple app sessions 2023-11-12 18:05:11 +01:00
664b2181be Merge pull request #712 from 64knl/feat/update-nl-translation
feat: Update Dutch translation
2023-11-12 15:43:15 +01:00
1bc95b0c2c fix: missing open folder icon for trigger, function and other database elements on sidebar 2023-11-10 18:12:07 +01:00
Rene
8628711374 feat: nl string updates 2023-11-10 15:21:22 +01:00
186fc18363 fix(Firebird SQL): error "Cannot read properties of null" connecting to some databases, fixes #708 2023-11-09 18:49:56 +01:00
e14302bdc0 feat(translation): add Ukrainian language, thanks to #707 2023-11-06 18:01:19 +01:00
13afc8bffd Merge pull request #710 from antares-sql/all-contributors/add-zvlad
docs: add zvlad as a contributor for translation
2023-11-06 09:15:12 +01:00
allcontributors[bot]
811be75c73 docs: update .all-contributorsrc [skip ci] 2023-11-06 08:14:38 +00:00
allcontributors[bot]
bddec52b40 docs: update README.md [skip ci] 2023-11-06 08:14:37 +00:00
e34af5bfa4 chore: update README.md 2023-11-03 18:26:58 +01:00
3322a06fed Merge pull request #703 from jimcat8/cn_main
Updated zh-CN.ts file
2023-11-03 13:17:19 +01:00
tianci
74040cee44 update 2023-11-02 17:52:13 +08:00
tianci
27c904e7f4 Updated zh-CN.ts file 2023-11-02 16:51:13 +08:00
6876dd6063 chore: add flathub badge in README.md 2023-11-02 09:25:13 +01:00
4d676a41cd chode: add flatpak assets 2023-11-01 12:12:14 +01:00
19d9f56f08 chore(release): 0.7.19 2023-11-01 09:43:50 +01:00
4c89578188 Merge branch 'develop' of https://github.com/antares-sql/antares into beta 2023-11-01 09:42:59 +01:00
f6fb266771 fix: table field changes not saved on text fields if pressing enter on textarea modal 2023-10-31 17:57:58 +01:00
3e739bcaa2 chore(release): 0.7.19-beta.2 2023-10-29 11:47:08 +01:00
debc1da289 fix: ssh tunnel keep-alive not working properly 2023-10-28 19:09:19 +02:00
3c2e2be40f chore: regenerate package-lock.json 2023-10-28 18:47:06 +02:00
581ec6a25d Merge branch 'develop' of https://github.com/antares-sql/antares into develop 2023-10-28 18:25:03 +02:00
d30a978cd6 refactor: replace ssh2-promise with @fabio286/ssh2-promise 2023-10-28 18:25:01 +02:00
0015f2e860 Merge branch 'master' of https://github.com/antares-sql/antares into develop 2023-10-28 11:58:06 +02:00
389e6624d8 chore: update stylelint dependencies 2023-10-28 11:55:18 +02:00
275344eb8b chore(release): 0.7.19-beta.1 2023-10-26 01:07:15 +02:00
cf24adf99e Merge branch 'develop' of https://github.com/antares-sql/antares into beta 2023-10-26 01:06:54 +02:00
2eae580e18 chore: update electron 2023-10-22 19:04:31 +02:00
e4eb27d503 feat(MySQL): RLIKE and NOT RLIKE regular expression filters, closes #688 2023-10-18 18:08:01 +02:00
580973fd04 chore(release): 0.7.19-beta.0 2023-10-14 15:04:00 +02:00
215ab783ab chore: email change 2023-10-14 15:03:09 +02:00
72148e991c Merge branch 'master' of https://github.com/antares-sql/antares into develop 2023-10-13 09:23:41 +02:00
6e4c16741a chore: Update CODE_OF_CONDUCT.md 2023-10-13 09:22:04 +02:00
9f9c63bfcc feat: "now" and "random" options added in datetime related data in insert rows tool, closes #402 2023-10-10 18:36:35 +02:00
c0dcf30e73 fix: IN and NOT IN filters not working properly, fixes #687 2023-10-09 18:13:30 +02:00
ddd290c903 fix: timeout issue on long time sql import 2023-10-03 18:19:16 +02:00
267c017921 chore(release): 0.7.18 2023-10-03 09:31:58 +02:00
b3b698b3a2 fix: hotfix for Microsoft Store unauthorized process 2023-10-03 09:31:26 +02:00
71ac3a5164 chore(release): 0.7.17 2023-09-30 16:46:49 +02:00
6fc4418c02 chore(release): 0.7.17-beta.2 2023-09-28 18:11:10 +02:00
b37781df84 fix(UI): small icons in foreign key modal 2023-09-26 18:31:58 +02:00
9c66fd51cb feat: add NOT LIKE to table filters, closes #672 2023-09-25 18:16:07 +02:00
98c1f43a4d refactor: removed icon fonts in ace editor 2023-09-25 18:14:21 +02:00
12825c69d4 Merge branch 'beta' of https://github.com/antares-sql/antares into develop 2023-09-24 23:06:01 +02:00
198ff0103b fix: nsis updater not working 2023-09-24 23:04:35 +02:00
94ce615fc8 chore(release): 0.7.17-beta.1 2023-09-23 16:00:52 +02:00
354928e302 fix(UI): small icons in sidebar elements with long name 2023-09-21 11:18:00 +02:00
6dceaf09be fix(SQLite): table content not refresh after an update, fixes #665 2023-09-20 17:54:25 +02:00
b321e64b83 fix(SQLite): field length lost when editing a table, fixes #664 2023-09-19 18:12:49 +02:00
7e36260cdb fix: table filter not working when search string on integer field, #671 2023-09-19 18:10:27 +02:00
894087e196 Merge branch 'beta' of https://github.com/antares-sql/antares into develop 2023-09-18 15:13:03 +02:00
922f56f69b fix: flip not working on BaseIcon component 2023-09-18 08:56:26 +02:00
92 changed files with 19901 additions and 3922 deletions

View File

@@ -257,6 +257,15 @@
"contributions": [
"translation"
]
},
{
"login": "zvlad",
"name": "Vladyslav",
"avatar_url": "https://avatars.githubusercontent.com/u/9055134?v=4",
"profile": "https://github.com/zvlad",
"contributions": [
"translation"
]
}
],
"contributorsPerLine": 7,

View File

@@ -13,8 +13,9 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-11, ubuntu-latest, windows-latest]
os: [macos-latest, ubuntu-latest, windows-latest]
steps:
- name: Check out Git repository
@@ -25,7 +26,7 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18
node-version: 20
- name: Install dependencies
run: npm i

View File

@@ -13,8 +13,9 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-11, ubuntu-latest, windows-latest]
os: [macos-latest, ubuntu-latest, windows-latest]
steps:
- name: Exit if not on master branch
@@ -31,7 +32,7 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 20
- name: Install dependencies
run: npm i

View File

@@ -5,7 +5,7 @@ on:
jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v3
@@ -13,7 +13,7 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 20
- name: Install dependencies
run: npm i

View File

@@ -13,7 +13,7 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 20
- name: npm install & build
run: |
@@ -29,3 +29,30 @@ jobs:
build
!build/*-unpacked
!build/.icon-ico
build-beta:
runs-on: macos-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v3
with:
ref: beta
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 20
- name: npm install & build
run: |
npm install
npm run build
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: macos-build-beta
retention-days: 3
path: |
build
!build/*-unpacked
!build/.icon-ico

33
.github/workflows/test-builds.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Test build [DEVELOP]
on:
workflow_dispatch: {}
env:
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v3
with:
ref: develop
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 20
- name: Install dependencies
run: npm i
- name: "Build"
run: npm run build

BIN
.nvmrc Normal file

Binary file not shown.

View File

@@ -10,7 +10,8 @@
"translation",
"Linux",
"MacOS",
"deps"
"deps",
"Flatpak"
],
"svg.preview.background": "transparent"
}

View File

@@ -2,6 +2,116 @@
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.20](https://github.com/antares-sql/antares/compare/v0.7.20-beta.2...v0.7.20) (2023-12-08)
### Bug Fixes
* missing update indicator on setting icon ([b055350](https://github.com/antares-sql/antares/commit/b055350726774e05a4e04ea6d890c46f64f2112e))
### [0.7.20-beta.2](https://github.com/antares-sql/antares/compare/v0.7.20-beta.1...v0.7.20-beta.2) (2023-12-06)
### Bug Fixes
* communication with worker thread not working ([6a72f6b](https://github.com/antares-sql/antares/commit/6a72f6b4ae3f4c1d6c42ca7a817d2f2c135696a7))
### [0.7.20-beta.1](https://github.com/antares-sql/antares/compare/v0.7.20-beta.0...v0.7.20-beta.1) (2023-12-02)
### Features
* copy element names on sidebar from context menu, closes [#718](https://github.com/antares-sql/antares/issues/718) ([f13d4e6](https://github.com/antares-sql/antares/commit/f13d4e6dceb70b0c7cb8d56ddfb5f00e938571cc))
* logging errors on log file ([315d9d8](https://github.com/antares-sql/antares/commit/315d9d84c2caa29852d68bd189750b2a4028d953))
### Bug Fixes
* **Flatpak:** import/export schema not working ([e26809f](https://github.com/antares-sql/antares/commit/e26809f260099ba194bf5d00671cae14d438197b))
### [0.7.20-beta.0](https://github.com/antares-sql/antares/compare/v0.7.19...v0.7.20-beta.0) (2023-11-15)
### Features
* ability to open multiple app sessions ([075f542](https://github.com/antares-sql/antares/commit/075f542dc8f4a48bef07b86b78c40d03fcdccc56))
* nl string updates ([8628711](https://github.com/antares-sql/antares/commit/8628711374269c29c4b1e6722fe66b0d8179477e))
* **translation:** add Ukrainian language, thanks to [#707](https://github.com/antares-sql/antares/issues/707) ([e14302b](https://github.com/antares-sql/antares/commit/e14302bdc0038b84a1a06089753205149cd1a92b))
### Bug Fixes
* error with multiple sessions in non-dev environment ([169f610](https://github.com/antares-sql/antares/commit/169f610b2ee4857661ec3da7f04b628fec21f1f0))
* **Firebird SQL:** error "Cannot read properties of null" connecting to some databases, fixes [#708](https://github.com/antares-sql/antares/issues/708) ([186fc18](https://github.com/antares-sql/antares/commit/186fc18363b6f14678465a8e38d85b1319e47b50))
* missing open folder icon for trigger, function and other database elements on sidebar ([1bc95b0](https://github.com/antares-sql/antares/commit/1bc95b0c2cd91bbf0410a23266e23bbbf2a71995))
### [0.7.19](https://github.com/antares-sql/antares/compare/v0.7.19-beta.2...v0.7.19) (2023-11-01)
### Bug Fixes
* table field changes not saved on text fields if pressing enter on textarea modal ([f6fb266](https://github.com/antares-sql/antares/commit/f6fb266771f2d798c8ae42b997c1e33520cf21c3))
### [0.7.19-beta.2](https://github.com/antares-sql/antares/compare/v0.7.19-beta.1...v0.7.19-beta.2) (2023-10-29)
### Bug Fixes
* ssh tunnel keep-alive not working properly ([debc1da](https://github.com/antares-sql/antares/commit/debc1da289d5e35d59adf69d094b329cf93af536))
### [0.7.19-beta.1](https://github.com/antares-sql/antares/compare/v0.7.19-beta.0...v0.7.19-beta.1) (2023-10-25)
### Features
* **MySQL:** RLIKE and NOT RLIKE regular expression filters, closes [#688](https://github.com/antares-sql/antares/issues/688) ([e4eb27d](https://github.com/antares-sql/antares/commit/e4eb27d503e8f912178359c01c62a9b523d17848))
### [0.7.19-beta.0](https://github.com/antares-sql/antares/compare/v0.7.18...v0.7.19-beta.0) (2023-10-14)
### Features
* "now" and "random" options added in datetime related data in insert rows tool, closes [#402](https://github.com/antares-sql/antares/issues/402) ([9f9c63b](https://github.com/antares-sql/antares/commit/9f9c63bfcc3423bfeef143cd835f48c62900a799))
### Bug Fixes
* IN and NOT IN filters not working properly, fixes [#687](https://github.com/antares-sql/antares/issues/687) ([c0dcf30](https://github.com/antares-sql/antares/commit/c0dcf30e73a69b25b01ba31d21b27c1983ed2db6))
* timeout issue on long time sql import ([ddd290c](https://github.com/antares-sql/antares/commit/ddd290c90344241eaa70cb528552e942fd7edec0))
### [0.7.18](https://github.com/antares-sql/antares/compare/v0.7.17...v0.7.18) (2023-10-03)
### Bug Fixes
* hotfix for Microsoft Store unauthorized process ([b3b698b](https://github.com/antares-sql/antares/commit/b3b698b3a23a3c848921ab40fc0fec5d8178ef0e))
### [0.7.17](https://github.com/antares-sql/antares/compare/v0.7.17-beta.2...v0.7.17) (2023-09-30)
### [0.7.17-beta.2](https://github.com/antares-sql/antares/compare/v0.7.17-beta.1...v0.7.17-beta.2) (2023-09-28)
### Features
* add NOT LIKE to table filters, closes [#672](https://github.com/antares-sql/antares/issues/672) ([9c66fd5](https://github.com/antares-sql/antares/commit/9c66fd51cbbe6f21a1fa6a34cc962496d3db7a98))
### Bug Fixes
* nsis updater not working ([198ff01](https://github.com/antares-sql/antares/commit/198ff0103bfa95e3491296d352c944165f31b87e))
* **UI:** small icons in foreign key modal ([b37781d](https://github.com/antares-sql/antares/commit/b37781df84cf7ee99a69ecaa54480d662d79c4aa))
### [0.7.17-beta.1](https://github.com/antares-sql/antares/compare/v0.7.17-beta.0...v0.7.17-beta.1) (2023-09-23)
### Bug Fixes
* flip not working on BaseIcon component ([922f56f](https://github.com/antares-sql/antares/commit/922f56f69b168302a9d1ff86565d3f09400d6a7c))
* **SQLite:** field length lost when editing a table, fixes [#664](https://github.com/antares-sql/antares/issues/664) ([b321e64](https://github.com/antares-sql/antares/commit/b321e64b835e0b39da116c4a77bac50247f240f3))
* **SQLite:** table content not refresh after an update, fixes [#665](https://github.com/antares-sql/antares/issues/665) ([6dceaf0](https://github.com/antares-sql/antares/commit/6dceaf09be7bd46f1915721abd03253ffc517256))
* table filter not working when search string on integer field, [#671](https://github.com/antares-sql/antares/issues/671) ([7e36260](https://github.com/antares-sql/antares/commit/7e36260cdb0438197152b5c6ac61db8ae8a9791a))
* **UI:** small icons in sidebar elements with long name ([354928e](https://github.com/antares-sql/antares/commit/354928e302437d608903d1434d99d68eb79aa6e9))
### [0.7.17-beta.0](https://github.com/antares-sql/antares/compare/v0.7.16...v0.7.17-beta.0) (2023-09-17)

View File

@@ -61,7 +61,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
fabio286@gmail.com.
info@fabiodistasio.it.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the

View File

@@ -7,8 +7,7 @@
# Antares SQL Client
![GitHub package.json version](https://img.shields.io/github/package-json/v/fabio286/antares) ![GitHub](https://img.shields.io/github/license/fabio286/antares) [![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Ffabio286%2Fantares%2Fbadge&style=flat)](https://actions-badge.atrox.dev/fabio286/antares/goto) [![antares](https://snapcraft.io/antares/badge.svg)](https://snapcraft.io/antares) [![antares](https://snapcraft.io/antares/trending.svg?name=0)](https://snapcraft.io/antares)
![Mastodon Follow](https://img.shields.io/mastodon/follow/%20110860460902482117?domain=https%3A%2F%2Ffosstodon.org&style=social) [![Twitter Follow](https://img.shields.io/twitter/follow/AntaresSQL?style=social)](https://twitter.com/AntaresSQL) [![Plant a Tree](https://raw.githubusercontent.com/Fabio286/treedom-badge/master/svg/plant-a-tree.svg)](https://www.treedom.net/en/user/fabio-di-stasio/event/antares-for-the-planet)
![GitHub package.json version](https://img.shields.io/github/package-json/v/fabio286/antares) ![GitHub](https://img.shields.io/github/license/fabio286/antares) [![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Ffabio286%2Fantares%2Fbadge&style=flat)](https://actions-badge.atrox.dev/fabio286/antares/goto) ![Mastodon Follow](https://img.shields.io/mastodon/follow/%20110860460902482117?domain=https%3A%2F%2Ffosstodon.org&style=social) [![Twitter Follow](https://img.shields.io/twitter/follow/AntaresSQL?style=social)](https://twitter.com/AntaresSQL) [![Plant a Tree](https://raw.githubusercontent.com/Fabio286/treedom-badge/master/svg/plant-a-tree.svg)](https://www.treedom.net/en/user/fabio-di-stasio/event/antares-for-the-planet)
Antares is an SQL client based on [Electron.js](https://github.com/electron/electron) and [Vue.js](https://github.com/vuejs/vue) that aims to become a useful tool, especially for developers.
Our target is to support as many databases as possible, and all major operating systems, including the ARM versions.
@@ -21,7 +20,8 @@ We are actively working on it, hoping to provide new cool features, improvements
👁 To stay tuned for new releases follow Antares SQL on [Mastodon](https://fosstodon.org/@AntaresSQL) or [Twitter](https://twitter.com/AntaresSQL).
🌟 Don't forget to **leave a star** if you appreciate this project.
🗳️ Polls:
🗳️ Polls:
- **[Which is the main OS you use Antares on?](https://github.com/antares-sql/antares/discussions/379)**
- **[Which database do you use the most?](https://github.com/antares-sql/antares/discussions/594)**
@@ -55,7 +55,7 @@ Since Antares SQL is a free software we don't have a budget to spend on annual l
### Linux
On Linux you can simply download and run the `.AppImage` distribution, install from Snap Store, from AUR or from our [PPA repository](https://github.com/antares-sql/antares-ppa).
On Linux you can simply download and run the `.AppImage` distribution, install from FlatHub, Snap Store, AUR or from our [PPA repository](https://github.com/antares-sql/antares-ppa).
### Windows
@@ -67,8 +67,8 @@ On macOS you can run `.dmg` distribution following [this guide](https://support.
## Download
[![Get it from the Snap Store](https://snapcraft.io/static/images/badges/en/snap-store-black.svg)](https://snapcraft.io/antares) [![Get it from AUR](https://raw.githubusercontent.com/Fabio286/antares/3e00c4bae6e036300c752c1a40c5a038fea9c169/docs/aur-badge.svg)](https://aur.archlinux.org/packages/antares-sql-bin) [<img src="https://developer.microsoft.com/store/badges/images/English_get-it-from-MS.png" style="height: 56px">](https://www.microsoft.com/p/antares-sql-client/9nhtb9sq51r1?cid=storebadge&ocid=badge&rtc=1&activetab=pivot:overviewtab)
🚀 **[Other Downloads](https://github.com/Fabio286/antares/releases/latest)**
[<img height='56' alt='Download on Flathub' src='https://dl.flathub.org/assets/badges/flathub-badge-en.svg'/>](https://flathub.org/apps/it.fabiodistasio.AntaresSQL) [![Get it from the Snap Store](https://snapcraft.io/static/images/badges/en/snap-store-black.svg)](https://snapcraft.io/antares) [![Get it from AUR](https://raw.githubusercontent.com/antares-sql/antares/master/docs/aur-badge.svg)](https://aur.archlinux.org/packages/antares-sql-bin) [<img src="https://developer.microsoft.com/store/badges/images/English_get-it-from-MS.png" style="height: 56px">](https://www.microsoft.com/p/antares-sql-client/9nhtb9sq51r1?cid=storebadge&ocid=badge&rtc=1&activetab=pivot:overviewtab)
🚀 **[Other Downloads](https://github.com/antares-sql/antares/releases/latest)**
## Coming soon
@@ -155,6 +155,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zxp19821005"><img src="https://avatars.githubusercontent.com/u/4915850?v=4?s=100" width="100px;" alt="Woodenman"/><br /><sub><b>Woodenman</b></sub></a><br /><a href="#platform-zxp19821005" title="Packaging/porting to new platform">📦</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/markusand"><img src="https://avatars.githubusercontent.com/u/12972543?v=4?s=100" width="100px;" alt="Marc Vilella"/><br /><sub><b>Marc Vilella</b></sub></a><br /><a href="#translation-markusand" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Lawondyss"><img src="https://avatars.githubusercontent.com/u/272130?v=4?s=100" width="100px;" alt="Ladislav Vondráček"/><br /><sub><b>Ladislav Vondráček</b></sub></a><br /><a href="#translation-Lawondyss" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zvlad"><img src="https://avatars.githubusercontent.com/u/9055134?v=4?s=100" width="100px;" alt="Vladyslav"/><br /><sub><b>Vladyslav</b></sub></a><br /><a href="#translation-zvlad" title="Translation">🌍</a></td>
</tr>
</tbody>
</table>

View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Name=Antares SQL
Exec=startantares
Terminal=false
Type=Application
Icon=it.fabiodistasio.AntaresSQL
StartupWMClass=antares
Comment=A modern, fast and productivity driven SQL client with a focus in UX
Categories=Development;

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>it.fabiodistasio.AntaresSQL</id>
<name>Antares SQL</name>
<metadata_license>CC0-1.0</metadata_license>
<project_license>MIT</project_license>
<developer_name>Fabio Di Stasio</developer_name>
<summary>A modern, fast and productivity driven SQL client with a focus in UX</summary>
<url type="homepage">https://antares-sql.app/</url>
<url type="bugtracker">https://github.com/antares-sql/antares/issues</url>
<url type="help">https://github.com/antares-sql/antares/discussions</url>
<url type="donation">https://paypal.me/fabiodistasio</url>
<description>
<p>Antares is an SQL client that aims to become an useful and complete tool, especially for developers. </p>
<p>The main goal is to develop a totally free, full featured, cross platform and open source alternative.
A modern application created with minimalism and semplicity in mind, with features in the right places, not hundreds of tiny buttons, nested tabs or submenu; productivity comes first.</p>
<p>Supported database: </p>
<ul>
<li>MySQL/MariaDB</li>
<li>PostgreSQL</li>
<li>SQLite</li>
<li>Firebird SQL</li>
</ul>
</description>
<screenshots>
<screenshot type="default">
<image type="source">https://lh3.googleusercontent.com/drive-viewer/AK7aPaC00fbmJIUcfwSPv-hjoxEmHS8NapR8qyOqOpopMIdcDFqYKNDs5mdIK08hnhZdHMrozTfR4Hx3Yj6bQ0zgfStEEFhxWg=s1600</image>
</screenshot>
</screenshots>
<content_rating type="oars-1.1" />
<releases>
<release version="v0.7.19" date="2023-11-01"/>
</releases>
</component>

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -1,76 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Gravit.io --><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
style="isolation:isolate" viewBox="0 0 182 56" width="182px" height="56px">
<svg xmlns="http://www.w3.org/2000/svg" style="isolation:isolate" width="182" height="56">
<defs>
<clipPath id="_clipPath_tR1uglJ1Zei76xP861DY1TsjAiQWS9qF">
<rect width="182" height="56" />
<clipPath id="prefix__a">
<path d="M0 0h182v56H0z" />
</clipPath>
</defs>
<g clip-path="url(#_clipPath_tR1uglJ1Zei76xP861DY1TsjAiQWS9qF)">
<path
d="M 2.5 0.5 L 180.5 0.5 C 181.604 0.5 182.5 1.396 182.5 2.5 L 182.5 54.5 C 182.5 55.604 181.604 56.5 180.5 56.5 L 2.5 56.5 C 1.396 56.5 0.5 55.604 0.5 54.5 L 0.5 2.5 C 0.5 1.396 1.396 0.5 2.5 0.5 Z"
style="stroke:none;fill:#252525;stroke-miterlimit:10;" />
<path
d="M 2.5 0.5 L 180.5 0.5 C 181.604 0.5 182.5 1.396 182.5 2.5 L 182.5 54.5 C 182.5 55.604 181.604 56.5 180.5 56.5 L 2.5 56.5 C 1.396 56.5 0.5 55.604 0.5 54.5 L 0.5 2.5 C 0.5 1.396 1.396 0.5 2.5 0.5 Z"
style="fill:none;stroke:#CDCDCD;stroke-width:1;stroke-miterlimit:2;" />
<g>
<g>
<path
d=" M 60.898 13.777 C 58.555 13.774 56.61 14.254 55.858 14.516 L 55.083 18.697 C 55.081 18.712 58.937 17.669 60.635 17.73 C 63.447 17.831 63.706 18.805 63.656 20.119 C 63.704 20.196 62.931 18.931 60.498 18.889 C 57.43 18.836 53.098 19.976 53.104 24.608 C 53.022 29.818 56.997 31.351 59.704 31.379 C 62.138 31.335 63.279 30.458 63.904 29.988 C 64.726 29.129 65.665 28.265 66.561 27.229 C 65.714 28.77 64.978 29.835 64.213 30.651 L 64.213 31.339 L 67.913 30.716 L 67.938 20.66 C 67.901 19.237 68.754 13.791 60.898 13.777 Z M 60.367 22.533 C 61.9 22.554 63.659 23.31 63.662 25.129 C 63.669 26.784 61.589 27.674 60.235 27.66 C 58.881 27.646 57.085 26.596 57.077 24.982 C 57.103 23.54 58.771 22.496 60.367 22.533 Z "
fill-rule="evenodd" fill="rgb(255,255,255)" />
<path
d=" M 70.378 14.707 L 70.352 31.36 L 74.662 30.529 L 74.67 21.087 C 74.671 19.681 76.679 18.039 79.198 18.065 C 79.733 17.097 80.738 14.625 80.983 14.062 C 75.354 14.049 75.282 15.68 74.303 16.483 C 74.293 14.952 74.3 14.033 74.3 14.033 L 70.378 14.707 L 70.378 14.707 Z "
fill-rule="evenodd" fill="rgb(255,255,255)" />
<path
d=" M 94.632 16.893 C 94.591 16.873 92.385 14.312 87.949 14.292 C 83.795 14.223 79.135 15.834 79.061 22.8 C 79.097 28.925 83.537 31.318 87.973 31.365 C 92.72 31.414 94.609 28.396 94.722 28.322 C 94.156 27.83 92.034 25.728 92.034 25.728 C 92.034 25.728 90.709 27.615 88.138 27.639 C 85.566 27.664 83.331 25.651 83.299 22.844 C 83.266 20.036 85.354 18.515 88.157 18.392 C 90.584 18.392 91.984 19.959 91.984 19.959 L 94.632 16.893 L 94.632 16.893 Z "
fill-rule="evenodd" fill="rgb(255,255,255)" />
<path
d=" M 100.065 8.879 L 95.996 9.835 L 96.026 31.526 L 100.034 30.802 L 100.08 20.595 C 100.089 19.524 101.628 17.88 104.2 17.933 C 106.658 17.958 107.207 19.571 107.201 19.775 L 107.272 31.592 L 111.224 30.894 L 111.239 18.363 C 111.265 17.157 108.598 14.61 104.311 14.592 C 102.273 14.596 101.145 15.057 100.571 15.397 C 99.588 16.156 98.466 16.883 97.362 17.811 C 98.382 16.501 99.239 15.595 100.075 14.921 L 100.065 8.879 L 100.065 8.879 Z "
fill-rule="evenodd" fill="rgb(255,255,255)" />
</g>
<g>
<path
d=" M 114.673 9.441 L 116.508 8.982 L 116.595 30.85 L 114.73 31.168 L 114.673 9.441 L 114.673 9.441 Z "
fill-rule="evenodd" fill="rgb(23,147,209)" />
<path
d=" M 119.663 15.968 L 121.271 15.252 L 121.285 30.932 L 119.731 31.253 L 119.663 15.968 L 119.663 15.968 Z M 119.28 10.314 L 120.577 9.255 L 121.655 10.454 L 120.357 11.54 L 119.28 10.314 L 119.28 10.314 Z "
fill-rule="evenodd" fill="rgb(23,147,209)" />
<path
d=" M 124.296 15.682 L 126.131 15.308 L 126.14 18.586 C 126.14 18.727 127.148 14.924 132.008 15.009 C 136.727 15.035 137.499 18.688 137.473 19.507 L 137.531 31.034 L 135.922 31.384 L 135.913 19.998 C 135.932 19.665 135.178 16.853 131.843 16.843 C 128.509 16.833 126.199 19.265 126.203 20.818 L 126.229 30.848 L 124.365 31.335 L 124.296 15.682 L 124.296 15.682 Z "
fill-rule="evenodd" fill="rgb(23,147,209)" />
<path
d=" M 153.547 31.117 L 151.711 31.492 L 151.703 28.214 C 151.703 28.073 150.694 31.876 145.835 31.791 C 141.116 31.765 140.344 28.112 140.37 27.293 L 140.311 15.765 L 142.261 15.372 L 142.292 26.758 C 142.292 27.069 142.665 29.947 145.999 29.957 C 149.334 29.967 151.669 27.949 151.686 24.911 L 151.662 15.928 L 153.477 15.464 L 153.547 31.117 L 153.547 31.117 Z "
fill-rule="evenodd" fill="rgb(23,147,209)" />
<path
d=" M 157.144 15.553 L 155.857 16.56 L 160.792 23.018 L 155.529 30.478 L 156.894 31.492 L 161.841 24.563 L 166.948 31.656 L 168.211 30.649 L 162.738 23.065 L 167.104 16.933 L 165.762 15.797 L 161.785 21.472 L 157.144 15.553 L 157.144 15.553 Z "
fill-rule="evenodd" fill="rgb(23,147,209)" />
</g>
<g clip-path="url(#prefix__a)">
<!-- <path d="M2.5.5h178a2 2 0 012 2v52a2 2 0 01-2 2H2.5a2 2 0" fill="#252525" stroke="#FFF" stroke-width="2"/> -->
<rect x="0" y="0" width="182" height="56" fill="#252525" stroke="#FFF" stroke-width="1" rx="0" />
<g fill-rule="evenodd" fill="#FFF">
<path
d=" M 33.112 3.879 C 30.965 9.143 29.67 12.587 27.279 17.695 C 28.745 19.248 30.544 21.058 33.466 23.101 C 30.325 21.809 28.182 20.511 26.581 19.164 C 23.521 25.549 18.728 34.643 9 52.121 C 16.645 47.707 22.572 44.986 28.095 43.948 C 27.858 42.928 27.723 41.824 27.733 40.673 L 27.742 40.428 C 27.863 35.53 30.411 31.763 33.43 32.019 C 36.448 32.274 38.794 36.455 38.673 41.353 C 38.65 42.275 38.546 43.162 38.364 43.984 C 43.828 45.053 49.691 47.767 57.233 52.121 C 55.746 49.383 54.419 46.915 53.151 44.565 C 51.154 43.017 49.072 41.003 44.823 38.822 C 47.743 39.581 49.834 40.456 51.464 41.435 C 38.575 17.439 37.532 14.251 33.112 3.879 Z "
fill-rule="evenodd" fill="rgb(23,147,209)" />
<g>
<path
d=" M 170.614 30.156 L 170.614 28.802 L 170.109 28.802 L 170.109 28.621 L 171.325 28.621 L 171.325 28.802 L 170.817 28.802 L 170.817 30.156 L 170.614 30.156 Z "
fill="rgb(23,147,209)" />
<path
d=" M 171.536 30.156 L 171.536 28.621 L 171.842 28.621 L 172.205 29.708 C 172.238 29.809 172.263 29.884 172.278 29.935 C 172.295 29.879 172.323 29.797 172.36 29.689 L 172.727 28.621 L 173 28.621 L 173 30.156 L 172.804 30.156 L 172.804 28.871 L 172.358 30.156 L 172.175 30.156 L 171.732 28.849 L 171.732 30.156 L 171.536 30.156 Z "
fill="rgb(23,147,209)" />
</g>
<g>
<path
d=" M 57.471 47.815 L 57.471 46.493 L 56.977 46.493 L 56.977 46.316 L 58.166 46.316 L 58.166 46.493 L 57.67 46.493 L 57.67 47.815 L 57.471 47.815 Z "
fill="rgb(23,147,209)" />
<path
d=" M 58.372 47.815 L 58.372 46.316 L 58.671 46.316 L 59.026 47.377 C 59.059 47.476 59.083 47.55 59.098 47.599 C 59.115 47.545 59.141 47.465 59.177 47.359 L 59.536 46.316 L 59.803 46.316 L 59.803 47.815 L 59.612 47.815 L 59.612 46.56 L 59.176 47.815 L 58.997 47.815 L 58.564 46.539 L 58.564 47.815 L 58.372 47.815"
fill="rgb(23,147,209)" />
</g>
d="M60.898 13.777c-2.343-.003-4.288.477-5.04.739l-.775 4.181c-.002.015 3.854-1.028 5.552-.967 2.812.101 3.071 1.075 3.021 2.389.048.077-.725-1.188-3.158-1.23-3.068-.053-7.4 1.087-7.394 5.719-.082 5.21 3.893 6.743 6.6 6.771 2.434-.044 3.575-.921 4.2-1.391.822-.859 1.761-1.723 2.657-2.759-.847 1.541-1.583 2.606-2.348 3.422v.688l3.7-.623.025-10.056c-.037-1.423.816-6.869-7.04-6.883zm-.531 8.756c1.533.021 3.292.777 3.295 2.596.007 1.655-2.073 2.545-3.427 2.531-1.354-.014-3.15-1.064-3.158-2.678.026-1.442 1.694-2.486 3.29-2.449zM70.378 14.707l-.026 16.653 4.31-.831.008-9.442c.001-1.406 2.009-3.048 4.528-3.022.535-.968 1.54-3.44 1.785-4.003-5.629-.013-5.701 1.618-6.68 2.421-.01-1.531-.003-2.45-.003-2.45l-3.922.674zM94.632 16.893c-.041-.02-2.247-2.581-6.683-2.601-4.154-.069-8.814 1.542-8.888 8.508.036 6.125 4.476 8.518 8.912 8.565 4.747.049 6.636-2.969 6.749-3.043-.566-.492-2.688-2.594-2.688-2.594s-1.325 1.887-3.896 1.911c-2.572.025-4.807-1.988-4.839-4.795-.033-2.808 2.055-4.329 4.858-4.452 2.427 0 3.827 1.567 3.827 1.567l2.648-3.066zM100.065 8.879l-4.069.956.03 21.691 4.008-.724.046-10.207c.009-1.071 1.548-2.715 4.12-2.662 2.458.025 3.007 1.638 3.001 1.842l.071 11.817 3.952-.698.015-12.531c.026-1.206-2.641-3.753-6.928-3.771-2.038.004-3.166.465-3.74.805-.983.759-2.105 1.486-3.209 2.414 1.02-1.31 1.877-2.216 2.713-2.89l-.01-6.042z" />
</g>
<g clip-path="url(#_clipPath_NvFIpNfWUS6M4fZAtfyVzggsKR3URDoi)"><text transform="matrix(1,0,0,1,87.023,43.899)"
style="font-family:'Open Sans';font-weight:700;font-size:11px;font-style:normal;fill:#ffffff;stroke:none;">user
repository</text></g>
<g fill-rule="evenodd" fill="#1793D1">
<path
d="M114.673 9.441l1.835-.459.087 21.868-1.865.318-.057-21.727zM119.663 15.968l1.608-.716.014 15.68-1.554.321-.068-15.285zm-.383-5.654l1.297-1.059 1.078 1.199-1.298 1.086-1.077-1.226zM124.296 15.682l1.835-.374.009 3.278c0 .141 1.008-3.662 5.868-3.577 4.719.026 5.491 3.679 5.465 4.498l.058 11.527-1.609.35-.009-11.386c.019-.333-.735-3.145-4.07-3.155-3.334-.01-5.644 2.422-5.64 3.975l.026 10.03-1.864.487-.069-15.653zM153.547 31.117l-1.836.375-.008-3.278c0-.141-1.009 3.662-5.868 3.577-4.719-.026-5.491-3.679-5.465-4.498l-.059-11.528 1.95-.393.031 11.386c0 .311.373 3.189 3.707 3.199 3.335.01 5.67-2.008 5.687-5.046l-.024-8.983 1.815-.464.07 15.653zM157.144 15.553l-1.287 1.007 4.935 6.458-5.263 7.46 1.365 1.014 4.947-6.929 5.107 7.093 1.263-1.007-5.473-7.584 4.366-6.132-1.342-1.136-3.977 5.675-4.641-5.919z" />
</g>
<path
d="M33.112 3.879c-2.147 5.264-3.442 8.708-5.833 13.816 1.466 1.553 3.265 3.363 6.187 5.406-3.141-1.292-5.284-2.59-6.885-3.937C23.521 25.549 18.728 34.643 9 52.121c7.645-4.414 13.572-7.135 19.095-8.173a13.965 13.965 0 01-.362-3.275l.009-.245c.121-4.898 2.669-8.665 5.688-8.409 3.018.255 5.364 4.436 5.243 9.334a13.819 13.819 0 01-.309 2.631c5.464 1.069 11.327 3.783 18.869 8.137-1.487-2.738-2.814-5.206-4.082-7.556-1.997-1.548-4.079-3.562-8.328-5.743 2.92.759 5.011 1.634 6.641 2.613C38.575 17.439 37.532 14.251 33.112 3.879z"
fill-rule="evenodd" fill="#1793D1" />
<g fill="#1793D1">
<path
d="M170.614 30.156v-1.354h-.505v-.181h1.216v.181h-.508v1.354h-.203zM171.536 30.156v-1.535h.306l.363 1.087c.033.101.058.176.073.227a8.63 8.63 0 01.082-.246l.367-1.068H173v1.535h-.196v-1.285l-.446 1.285h-.183l-.443-1.307v1.307h-.196z" />
</g>
<g fill="#1793D1">
<path
d="M57.471 47.815v-1.322h-.494v-.177h1.189v.177h-.496v1.322h-.199zM58.372 47.815v-1.499h.299l.355 1.061.072.222c.017-.054.043-.134.079-.24l.359-1.043h.267v1.499h-.191V46.56l-.436 1.255h-.179l-.433-1.276v1.276h-.192" />
</g>
<g clip-path="url(#prefix__b)"><text transform="translate(95.023 43.899)" font-family="sans-serif"
font-weight="700" font-size="10" fill="#fff">user repository</text></g>
<defs>
<clipPath id="_clipPath_NvFIpNfWUS6M4fZAtfyVzggsKR3URDoi">
<rect x="0" y="0" width="86" height="14.98" transform="matrix(1,0,0,1,87,32.142)" />
<clipPath id="prefix__b">
<path transform="translate(87 32.142)" d="M0 0h86v14.98H0z" />
</clipPath>
</defs>
</g>

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

21282
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "antares",
"productName": "Antares",
"version": "0.7.17-beta.0",
"version": "0.7.20",
"description": "A modern, fast and productivity driven SQL client with a focus in UX.",
"license": "MIT",
"repository": "https://github.com/antares-sql/antares.git",
@@ -27,7 +27,7 @@
"contributors:add": "all-contributors add",
"contributors:generate": "all-contributors generate"
},
"author": "Fabio Di Stasio <fabio286@gmail.com>",
"author": "Fabio Di Stasio <info@fabiodistasio.it>",
"main": "./dist/main.js",
"antares": {
"devtoolsId": "nhdogjmejiglipccpnnnanhbledajbpd"
@@ -119,15 +119,15 @@
},
"dependencies": {
"@electron/remote": "~2.0.1",
"@fabio286/ssh2-promise": "~1.0.4-b",
"@faker-js/faker": "~6.1.2",
"@jamescoyle/vue-icon": "~0.1.2",
"@mdi/font": "~7.2.96",
"@mdi/js": "~7.2.96",
"@turf/helpers": "~6.5.0",
"@vueuse/core": "~10.4.1",
"ace-builds": "~1.24.1",
"better-sqlite3": "~8.0.0",
"electron-log": "~4.4.1",
"better-sqlite3": "~9.1.1",
"electron-log": "~5.0.1",
"electron-store": "~8.1.0",
"electron-updater": "~4.6.5",
"electron-window-state": "~5.0.3",
@@ -147,7 +147,6 @@
"source-map-support": "~0.5.20",
"spectre.css": "~0.5.9",
"sql-formatter": "~13.0.0",
"ssh2-promise": "~1.0.2",
"v-mask": "~2.3.0",
"vue": "~3.3.4",
"vue-i18n": "~9.2.2",
@@ -172,8 +171,8 @@
"chalk": "~4.1.2",
"cross-env": "~7.0.2",
"css-loader": "~6.5.0",
"electron": "~22.3.23",
"electron-builder": "~22.10.3",
"electron": "~22.3.27",
"electron-builder": "~24.6.4",
"eslint": "~7.32.0",
"eslint-config-standard": "~16.0.3",
"eslint-plugin-import": "~2.24.2",
@@ -194,10 +193,10 @@
"sass-loader": "~12.3.0",
"standard-version": "~9.3.1",
"style-loader": "~3.3.1",
"stylelint": "~14.9.1",
"stylelint-config-recommended-vue": "~1.4.0",
"stylelint-config-standard": "~26.0.0",
"stylelint-scss": "~4.3.0",
"stylelint": "^15.11.0",
"stylelint-config-recommended-vue": "~1.5.0",
"stylelint-config-standard": "~34.0.0",
"stylelint-scss": "~5.3.0",
"tree-kill": "~1.2.2",
"ts-loader": "~9.2.8",
"ts-node": "~10.9.1",
@@ -209,10 +208,5 @@
"webpack-cli": "~4.9.1",
"webpack-dev-server": "~4.11.1",
"xvfb-maybe": "~0.2.1"
},
"overrides": {
"ssh2-promise": {
"ssh2": "github:Fabio286/ssh2"
}
}
}

View File

@@ -63,43 +63,39 @@ async function restartElectron () {
if (!manualRestart) process.exit(0);
});
}
function startWorkers () {
const compiler = webpack(workersConfig);
const { name } = compiler;
function startMain () {
const webpackSetup = webpack([mainConfig, workersConfig]);
webpackSetup.compilers.forEach((compiler) => {
const { name } = compiler;
switch (name) {
case 'workers':
compiler.hooks.afterEmit.tap('afterEmit', async () => {
console.log(chalk.gray(`\nCompiled ${name} script!`));
console.log(
chalk.gray(`\nWatching file changes for ${name} script...`)
);
});
break;
case 'main':
default:
compiler.hooks.afterEmit.tap('afterEmit', async () => {
console.log(chalk.gray(`\nCompiled ${name} script!`));
manualRestart = true;
await restartElectron();
setTimeout(() => {
manualRestart = false;
}, 2500);
console.log(
chalk.gray(`\nWatching file changes for ${name} script...`)
);
});
break;
}
compiler.hooks.afterEmit.tap('afterEmit', () => {
console.log(chalk.gray(`\nCompiled ${name} script!`));
console.log(chalk.gray(`\nWatching file changes for ${name} script...`));
});
webpackSetup.watch({ aggregateTimeout: 500 }, err => {
compiler.watch({ aggregateTimeout: 500 }, err => {
if (err) console.error(chalk.red(err));
});
}
function startMain () {
const compiler = webpack(mainConfig);
const { name } = compiler;
compiler.hooks.afterEmit.tap('afterEmit', async () => {
console.log(chalk.gray(`\nCompiled ${name} script!`));
manualRestart = true;
await restartElectron();
startWorkers();
setTimeout(() => {
manualRestart = false;
}, 2500);
console.log(chalk.gray(`\nWatching file changes for ${name} script...`));
});
compiler.watch({ aggregateTimeout: 500 }, err => {
if (err) console.error(chalk.red(err));
});
}

View File

@@ -42,6 +42,7 @@ const downloadFile = url => {
await unzip(filePath, destFolder);
fs.unlinkSync(filePath);
fs.unlinkSync(`${destFolder}/package.json`);// <- Avoid to display annoyng npm script in vscode
process.exit();
}
catch (error) {
console.log(error);

View File

@@ -51,6 +51,7 @@ export default class {
{ name: 'collation', group: 'database', types: ['string'] },
{ name: 'engine', group: 'database', types: ['string'] },
{ name: 'now', group: 'date', types: ['string', 'datetime'] },
{ name: 'past', group: 'date', types: ['string', 'datetime'] },
{ name: 'future', group: 'date', types: ['string', 'datetime'] },
// { name: 'between', group: 'date', types: ['string'] },
@@ -161,7 +162,9 @@ export default class {
{ name: 'filePath', group: 'system', types: ['string'] },
{ name: 'semver', group: 'system', types: ['string'] },
{ name: 'now', group: 'time', types: ['string', 'time'] },
{ name: 'recent', group: 'time', types: ['string', 'time'] },
{ name: 'random', group: 'time', types: ['string', 'time'] },
{ name: 'vehicle', group: 'vehicle', types: ['string'] },
{ name: 'manufacturer', group: 'vehicle', types: ['string'] },

View File

@@ -9,6 +9,7 @@ export const defaults: Customizations = {
dataTypes: [],
indexTypes: [],
foreignActions: [],
operators: ['=', '!=', '>', '<', '>=', '<=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'BETWEEN', 'IS NULL', 'IS NOT NULL'],
// Core
database: false,
collations: false,

View File

@@ -9,6 +9,7 @@ export const customizations: Customizations = {
defaultUser: 'root',
defaultDatabase: null,
dataTypes: mysqlTypes,
operators: ['=', '!=', '>', '<', '>=', '<=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'RLIKE', 'NOT RLIKE', 'BETWEEN', 'IS NULL', 'IS NOT NULL'],
indexTypes: [
'PRIMARY',
'INDEX',

View File

@@ -1,3 +1,4 @@
import SSHConfig from '@fabio286/ssh2-promise/lib/sshConfig';
import * as mysql from 'mysql2/promise';
import * as pg from 'pg';
import { FirebirdSQLClient } from 'src/main/libs/clients/FirebirdSQLClient';
@@ -5,7 +6,6 @@ import MysqlExporter from 'src/main/libs/exporters/sql/MysqlExporter';
import PostgreSQLExporter from 'src/main/libs/exporters/sql/PostgreSQLExporter';
import MySQLImporter from 'src/main/libs/importers/sql/MySQLlImporter';
import PostgreSQLImporter from 'src/main/libs/importers/sql/PostgreSQLImporter';
import SSHConfig from 'ssh2-promise/lib/sshConfig';
import { MySQLClient } from '../../main/libs/clients/MySQLClient';
import { PostgreSQLClient } from '../../main/libs/clients/PostgreSQLClient';
@@ -363,8 +363,7 @@ export interface QueryBuilderObject {
offset: number;
join: string[];
update: string[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
insert: {[key: string]: any}[];
insert: {[key: string]: string | boolean | number }[];
delete: boolean;
}

View File

@@ -1,4 +1,5 @@
import { TypesGroup } from './antares';
import { TableFilterOperator } from './tableApis';
export interface Customizations {
// Defaults
@@ -8,6 +9,7 @@ export interface Customizations {
dataTypes?: TypesGroup[];
indexTypes?: string[];
foreignActions?: string[];
operators?: TableFilterOperator[];
// Core
database?: boolean;
collations?: boolean;

View File

@@ -21,10 +21,12 @@ export interface TableDeleteParams {
rows: {[key: string]: any};
}
export type TableFilterOperator = '=' | '!=' | '>' | '<' | '>=' | '<=' | 'IN' | 'NOT IN' | 'LIKE' | 'NOT LIKE' | 'RLIKE' | 'NOT RLIKE' | 'BETWEEN' | 'IS NULL' | 'IS NOT NULL'
export interface TableFilterClausole {
active: boolean;
field: string;
op: '=' | '!=' | '>' | '<' | '>=' | '<=' | 'IN' | 'NOT IN' | 'LIKE' | 'BETWEEN' | 'IS NULL' | 'IS NOT NULL';
op:TableFilterOperator;
value: '';
value2: '';
}

View File

@@ -0,0 +1,17 @@
import { faker } from '@faker-js/faker';
import * as moment from 'moment';
export const fakerCustom = {
seed: faker.seed,
setLocale: faker.setLocale,
...faker,
date: {
now: () => moment().format('YYYY-MM-DD HH:mm:ss'),
...faker.date
},
time: {
now: () => moment().format('HH:mm:ss'),
random: () => moment(faker.date.recent()).format('HH:mm:ss'),
...faker.time
}
};

View File

@@ -1,14 +1,46 @@
import { app, dialog, ipcMain } from 'electron';
import { app, dialog, ipcMain, safeStorage } from 'electron';
import * as Store from 'electron-store';
import { validateSender } from '../libs/misc/validateSender';
import { ShortcutRegister } from '../libs/ShortcutRegister';
export default () => {
ipcMain.on('close-app', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (!validateSender(event.senderFrame)) {
return {
status: 'error',
response: 'Unauthorized process'
};
}
app.exit();
});
ipcMain.on('set-key', (event, key) => {
if (safeStorage.isEncryptionAvailable()) {
const sessionStore = new Store({
name: 'session',
fileExtension: ''
});
const encrypted = safeStorage.encryptString(key);
sessionStore.set('key', encrypted);
event.returnValue = true;
}
});
ipcMain.on('get-key', (event) => {
if (!safeStorage.isEncryptionAvailable()) {
event.returnValue = false;
return;
}
const sessionStore = new Store({
name: 'session',
fileExtension: ''
});
const encrypted = sessionStore.get('key') as string;
const key = safeStorage.decryptString(Buffer.from(encrypted, 'utf-8'));
event.returnValue = key;
});
ipcMain.handle('show-open-dialog', (event, options) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
return dialog.showOpenDialog(options);

View File

@@ -55,7 +55,7 @@ export default (connections: {[key: string]: antares.Client}) => {
port: conn.sshPort ? conn.sshPort : 22,
privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null,
passphrase: conn.sshPassphrase,
keepaliveInterval: conn.sshKeepAliveInterval ?? conn.sshKeepAliveInterval*1000
keepaliveInterval: conn.sshKeepAliveInterval ? conn.sshKeepAliveInterval*1000 : null
};
}
@@ -137,7 +137,7 @@ export default (connections: {[key: string]: antares.Client}) => {
port: conn.sshPort ? conn.sshPort : 22,
privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null,
passphrase: conn.sshPassphrase,
keepaliveInterval: conn.sshKeepAliveInterval ?? conn.sshKeepAliveInterval*1000
keepaliveInterval: conn.sshKeepAliveInterval ? conn.sshKeepAliveInterval*1000 : null
};
}

View File

@@ -1,17 +1,14 @@
import { ChildProcess, fork } from 'child_process';
import * as antares from 'common/interfaces/antares';
import * as workers from 'common/interfaces/workers';
import { dialog, ipcMain } from 'electron';
import * as fs from 'fs';
import * as path from 'path';
import { Worker } from 'worker_threads';
import { validateSender } from '../libs/misc/validateSender';
const isDevelopment = process.env.NODE_ENV !== 'production';
export default (connections: {[key: string]: antares.Client}) => {
let exporter: ChildProcess = null;
let importer: ChildProcess = null;
let exporter: Worker = null;
let importer: Worker = null;
ipcMain.handle('create-schema', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
@@ -202,7 +199,7 @@ export default (connections: {[key: string]: antares.Client}) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (exporter !== null) {
exporter.kill();
exporter.terminate();
return;
}
@@ -227,11 +224,12 @@ export default (connections: {[key: string]: antares.Client}) => {
}
}
// Init exporter process
exporter = fork(isDevelopment ? './dist/exporter.js' : path.resolve(__dirname, './exporter.js'), [], {
execArgv: isDevelopment ? ['--inspect=9224'] : undefined
});
exporter.send({
// Init exporter thread
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
exporter = new Worker(new URL('../workers/exporter', import.meta.url));
exporter.postMessage({
type: 'init',
client: {
name: type,
@@ -242,32 +240,34 @@ export default (connections: {[key: string]: antares.Client}) => {
});
// Exporter message listener
exporter.on('message', ({ type, payload }: workers.WorkerIpcMessage) => {
exporter.on('message', (message: workers.WorkerIpcMessage) => {
const { type, payload } = message;
switch (type) {
case 'export-progress':
event.sender.send('export-progress', payload);
break;
case 'end':
setTimeout(() => { // Ensures that writing process has finished
exporter.kill();
setTimeout(() => { // Ensures that writing thread has finished
exporter?.terminate();
exporter = null;
}, 2000);
resolve({ status: 'success', response: payload });
break;
case 'cancel':
exporter.kill();
exporter?.terminate();
exporter = null;
resolve({ status: 'error', response: 'Operation cancelled' });
break;
case 'error':
exporter.kill();
exporter?.terminate();
exporter = null;
resolve({ status: 'error', response: payload });
break;
}
});
exporter.on('exit', code => {
exporter.on('close', code => {
exporter = null;
resolve({ status: 'error', response: `Operation ended with code: ${code}` });
});
@@ -291,7 +291,7 @@ export default (connections: {[key: string]: antares.Client}) => {
if (result.response === 1) {
willAbort = true;
exporter.send({ type: 'cancel' });
exporter.postMessage({ type: 'cancel' });
}
}
@@ -302,7 +302,7 @@ export default (connections: {[key: string]: antares.Client}) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (importer !== null) {
importer.kill();
importer.terminate();
return;
}
@@ -310,18 +310,21 @@ export default (connections: {[key: string]: antares.Client}) => {
(async () => {
const dbConfig = await connections[options.uid].getDbConfig();
// Init importer process
importer = fork(isDevelopment ? './dist/importer.js' : path.resolve(__dirname, './importer.js'), [], {
execArgv: isDevelopment ? ['--inspect=9224'] : undefined
});
importer.send({
// Init importer thread
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
importer = new Worker(new URL('../workers/importer', import.meta.url));
importer.postMessage({
type: 'init',
dbConfig,
options
});
// Importer message listener
importer.on('message', ({ type, payload }: workers.WorkerIpcMessage) => {
importer.on('message', (message: workers.WorkerIpcMessage) => {
const { type, payload } = message;
switch (type) {
case 'import-progress':
event.sender.send('import-progress', payload);
@@ -331,23 +334,28 @@ export default (connections: {[key: string]: antares.Client}) => {
break;
case 'end':
setTimeout(() => { // Ensures that writing process has finished
importer?.kill();
importer?.terminate();
importer = null;
}, 2000);
resolve({ status: 'success', response: payload });
break;
case 'cancel':
importer.kill();
importer.terminate();
importer = null;
resolve({ status: 'error', response: 'Operation cancelled' });
break;
case 'error':
importer.kill();
importer.terminate();
importer = null;
resolve({ status: 'error', response: payload });
break;
}
});
importer.on('close', code => {
importer = null;
resolve({ status: 'error', response: `Operation ended with code: ${code}` });
});
})();
});
});
@@ -368,7 +376,7 @@ export default (connections: {[key: string]: antares.Client}) => {
if (result.response === 1) {
willAbort = true;
importer.send({ type: 'cancel' });
importer.postMessage({ type: 'cancel' });
}
}

View File

@@ -1,8 +1,8 @@
import { faker } from '@faker-js/faker';
import customizations from 'common/customizations';
import { ARRAY, BIT, BLOB, BOOLEAN, DATE, DATETIME, FLOAT, LONG_TEXT, NUMBER, TEXT, TEXT_SEARCH } from 'common/fieldTypes';
import * as antares from 'common/interfaces/antares';
import { InsertRowsParams } from 'common/interfaces/tableApis';
import { fakerCustom } from 'common/libs/fakerCustom';
import { sqlEscaper } from 'common/libs/sqlUtils';
import { ipcMain } from 'electron';
import * as fs from 'fs';
@@ -371,19 +371,19 @@ export default (connections: {[key: string]: antares.Client}) => {
let fakeValue;
if (params.locale)
faker.locale = params.locale;
fakerCustom.locale = params.locale;
if (Object.keys(params.row[key].params).length) {
Object.keys(params.row[key].params).forEach(param => {
if (!isNaN(params.row[key].params[param]))
parsedParams[param] = +params.row[key].params[param];
if (!isNaN(params.row[key].params[param]))// Converts string numerics params to number
parsedParams[param] = Number(params.row[key].params[param]);
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fakeValue = (faker as any)[params.row[key].group][params.row[key].method](parsedParams);
fakeValue = (fakerCustom as any)[params.row[key].group][params.row[key].method](parsedParams);
}
else
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fakeValue = (faker as any)[params.row[key].group][params.row[key].method]();
fakeValue = (fakerCustom as any)[params.row[key].group][params.row[key].method]();
if (typeof fakeValue === 'string') {
if (params.row[key].length)

View File

@@ -1,9 +1,8 @@
import { ipcMain } from 'electron';
import * as log from 'electron-log/main';
import * as Store from 'electron-store';
import { autoUpdater } from 'electron-updater';
import { validateSender } from '../libs/misc/validateSender';
const persistentStore = new Store({
name: 'settings',
clearInvalidConfig: true,
@@ -20,8 +19,6 @@ autoUpdater.allowPrerelease = persistentStore.get('allow_prerelease', false) as
export default () => {
ipcMain.on('check-for-updates', event => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
mainWindow = event;
if (process.windowsStore || (process.platform === 'linux' && !process.env.APPIMAGE))
mainWindow.reply('no-auto-update');
@@ -35,42 +32,35 @@ export default () => {
}
});
ipcMain.on('restart-to-update', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
ipcMain.on('restart-to-update', () => {
autoUpdater.quitAndInstall();
});
// auto-updater events
autoUpdater.on('checking-for-update', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
autoUpdater.on('checking-for-update', () => {
mainWindow.reply('checking-for-update');
});
autoUpdater.on('update-available', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
autoUpdater.on('update-available', () => {
if (isMacOS)
mainWindow.reply('link-to-download');
else
mainWindow.reply('update-available');
});
autoUpdater.on('update-not-available', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
autoUpdater.on('update-not-available', () => {
mainWindow.reply('update-not-available');
});
autoUpdater.on('download-progress', event => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
mainWindow.reply('download-progress', event);
});
autoUpdater.on('update-downloaded', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
autoUpdater.on('update-downloaded', () => {
mainWindow.reply('update-downloaded');
});
// autoUpdater.logger = require('electron-log');
// autoUpdater.logger.transports.console.format = '{h}:{i}:{s} {text}';
// autoUpdater.logger.transports.file.level = 'info';
log.transports.file.level = 'info';
// log.transports.console.format = '{h}:{i}:{s} {text}';
autoUpdater.logger = log;
};

View File

@@ -1,7 +1,7 @@
import * as antares from 'common/interfaces/antares';
import mysql from 'mysql2/promise';
import * as pg from 'pg';
import SSH2Promise from 'ssh2-promise';
import SSH2Promise = require('@fabio286/ssh2-promise');
const queryLogger = ({ sql, cUid }: {sql: string; cUid: string}) => {
// Remove comments, newlines and multiple spaces
@@ -10,13 +10,13 @@ const queryLogger = ({ sql, cUid }: {sql: string; cUid: string}) => {
const mainWindow = require('electron').webContents.fromId(1);
mainWindow.send('query-log', { cUid, sql: escapedSql, date: new Date() });
}
if (process.env.NODE_ENV === 'development') console.log(escapedSql);
if (process.env.NODE_ENV === 'development' && process.type === 'browser') console.log(escapedSql);
};
/**
* As Simple As Possible Query Builder Core
*/
export abstract class AntaresCore {
export abstract class BaseClient {
_client: antares.ClientCode;
protected _cUid: string
protected _params: mysql.ConnectionOptions | pg.ClientConfig | { databasePath: string; readonly: boolean};

View File

@@ -4,9 +4,9 @@ import * as antares from 'common/interfaces/antares';
import * as firebird from 'node-firebird';
import * as path from 'path';
import { AntaresCore } from '../AntaresCore';
import { BaseClient } from './BaseClient';
export class FirebirdSQLClient extends AntaresCore {
export class FirebirdSQLClient extends BaseClient {
private _schema?: string;
private _runningConnections: Map<string, number>;
private _connectionsToCommit: Map<string, firebird.Transaction>;
@@ -118,6 +118,10 @@ export class FirebirdSQLClient extends AntaresCore {
return null;
}
getDatabases (): null[] {
return [];
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async getStructure (_schemas: Set<string>) {
interface TableResult {
@@ -157,10 +161,10 @@ export class FirebirdSQLClient extends AntaresCore {
const { rows: tables } = await this.raw<antares.QueryResult<TableResult>>(`
SELECT
rdb$relation_name AS name,
rdb$format AS format,
rdb$description AS description,
'table' AS type
rdb$relation_name AS NAME,
rdb$format AS FORMAT,
rdb$description AS DESCRIPTION,
'table' AS TYPE
FROM RDB$RELATIONS a
WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0
AND RDB$RELATION_TYPE = 0
@@ -168,8 +172,8 @@ export class FirebirdSQLClient extends AntaresCore {
const { rows: views } = await this.raw<antares.QueryResult<TableResult>>(`
SELECT
DISTINCT RDB$VIEW_NAME AS name,
'view' AS type
DISTINCT RDB$VIEW_NAME AS NAME,
'view' AS TYPE
FROM RDB$VIEW_RELATIONS
`);
@@ -177,9 +181,9 @@ export class FirebirdSQLClient extends AntaresCore {
const { rows: triggers } = await this.raw<antares.QueryResult<TriggersResult>>(`
SELECT
RDB$TRIGGER_NAME as name,
RDB$RELATION_NAME as relation,
RDB$TRIGGER_SOURCE as source
RDB$TRIGGER_NAME as NAME,
RDB$RELATION_NAME as RELATION,
RDB$TRIGGER_SOURCE as SOURCE
FROM RDB$TRIGGERS
WHERE RDB$SYSTEM_FLAG=0
ORDER BY RDB$TRIGGER_NAME;
@@ -208,8 +212,8 @@ export class FirebirdSQLClient extends AntaresCore {
schemaSize += tableSize;
return {
name: table.NAME.trim(),
type: table.TYPE.trim(),
name: table.NAME?.trim(),
type: table.TYPE?.trim(),
rows: false,
size: false
};
@@ -218,8 +222,8 @@ export class FirebirdSQLClient extends AntaresCore {
// TRIGGERS
const remappedTriggers = triggersArr.map(trigger => {
return {
name: trigger.NAME.trim(),
table: trigger.RELATION.trim(),
name: trigger.NAME?.trim(),
table: trigger.RELATION?.trim(),
statement: trigger.SOURCE
};
});
@@ -227,7 +231,7 @@ export class FirebirdSQLClient extends AntaresCore {
// PROCEDURES
const remappedProcedures = proceduresArr.map(procedure => {
return {
name: procedure.NAME.trim(),
name: procedure.NAME?.trim(),
definer: procedure.DEFINER,
comment: procedure.COMMENT?.trim()
};

View File

@@ -1,12 +1,12 @@
import SSH2Promise = require('@fabio286/ssh2-promise');
import SSHConfig from '@fabio286/ssh2-promise/lib/sshConfig';
import dataTypes from 'common/data-types/mysql';
import * as antares from 'common/interfaces/antares';
import * as mysql from 'mysql2/promise';
import { AntaresCore } from '../AntaresCore';
import SSH2Promise = require('ssh2-promise');
import SSHConfig from 'ssh2-promise/lib/sshConfig';
import { BaseClient } from './BaseClient';
export class MySQLClient extends AntaresCore {
export class MySQLClient extends BaseClient {
private _schema?: string;
private _runningConnections: Map<string, number>;
private _connectionsToCommit: Map<string, mysql.Connection | mysql.PoolConnection>;
@@ -168,7 +168,10 @@ export class MySQLClient extends AntaresCore {
dbConfig.port = tunnel.localPort;
}
catch (err) {
if (this._ssh) this._ssh.close();
if (this._ssh) {
this._ssh.close();
this._ssh.closeTunnel();
}
throw err;
}
}
@@ -187,7 +190,10 @@ export class MySQLClient extends AntaresCore {
this._connection.end();
clearInterval(this._keepaliveTimer);
this._keepaliveTimer = undefined;
if (this._ssh) this._ssh.close();
if (this._ssh) {
this._ssh.close();
this._ssh.closeTunnel();
}
}
async getConnection () {
@@ -256,9 +262,12 @@ export class MySQLClient extends AntaresCore {
}
private async keepAlive () {
const connection = await (this._connection as mysql.Pool).getConnection();
await connection.ping();
connection.release();
try {
const connection = await (this._connection as mysql.Pool).getConnection();
await connection.ping();
connection.release();
}
catch (_) {}
}
use (schema: string) {

View File

@@ -1,13 +1,13 @@
import SSH2Promise = require('@fabio286/ssh2-promise');
import SSHConfig from '@fabio286/ssh2-promise/lib/sshConfig';
import dataTypes from 'common/data-types/postgresql';
import * as antares from 'common/interfaces/antares';
import * as pg from 'pg';
import * as pgAst from 'pgsql-ast-parser';
import { AntaresCore } from '../AntaresCore';
import SSH2Promise = require('ssh2-promise');
import SSHConfig from 'ssh2-promise/lib/sshConfig';
import { ConnectionOptions } from 'tls';
import { BaseClient } from './BaseClient';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function pgToString (value: any) {
return value.toString();
@@ -81,7 +81,7 @@ type builtinsTypes =
'JSONB' |
'REGNAMESPACE' |
'REGROLE';
export class PostgreSQLClient extends AntaresCore {
export class PostgreSQLClient extends BaseClient {
private _schema?: string;
private _runningConnections: Map<string, number>;
private _connectionsToCommit: Map<string, pg.Client | pg.PoolClient>;
@@ -180,7 +180,10 @@ export class PostgreSQLClient extends AntaresCore {
dbConfig.port = tunnel.localPort;
}
catch (err) {
if (this._ssh) this._ssh.close();
if (this._ssh) {
this._ssh.close();
this._ssh.closeTunnel();
}
throw err;
}
}
@@ -236,13 +239,19 @@ export class PostgreSQLClient extends AntaresCore {
this._connection.end();
clearInterval(this._keepaliveTimer);
this._keepaliveTimer = undefined;
if (this._ssh) this._ssh.close();
if (this._ssh) {
this._ssh.close();
this._ssh.closeTunnel();
}
}
private async keepAlive () {
const connection = await this._connection.connect() as pg.PoolClient;
await connection.query('SELECT 1+1');
connection.release();
try {
const connection = await this._connection.connect() as pg.PoolClient;
await connection.query('SELECT 1+1');
connection.release();
}
catch (_) {}
}
use (schema: string, connection?: pg.Client | pg.PoolClient) {

View File

@@ -3,9 +3,9 @@ import dataTypes from 'common/data-types/sqlite';
import { DATETIME, FLOAT, NUMBER, TIME } from 'common/fieldTypes';
import * as antares from 'common/interfaces/antares';
import { AntaresCore } from '../AntaresCore';
import { BaseClient } from './BaseClient';
export class SQLiteClient extends AntaresCore {
export class SQLiteClient extends BaseClient {
private _schema?: string;
private _connectionsToCommit: Map<string, sqlite.Database>;
protected _connection?: sqlite.Database;
@@ -296,7 +296,13 @@ export class SQLiteClient extends AntaresCore {
// ADD FIELDS
fields.forEach(field => {
const typeInfo = this.getTypeInfo(field.type);
const length = typeInfo?.length ? field.enumValues || field.numLength || field.charLength || field.datePrecision : false;
const length = typeInfo?.length
? field.enumValues ||
field.numLength ||
field.numPrecision ||
field.charLength ||
field.datePrecision
: false;
newColumns.push(`"${field.name}"
${field.type.toUpperCase()}${length ? `(${length})` : ''}

View File

@@ -1,6 +1,5 @@
import * as exporter from 'common/interfaces/exporter';
import { valueToSqlString } from 'common/libs/sqlUtils';
import * as mysql from 'mysql2/promise';
import { MySQLClient } from '../../clients/MySQLClient';
import { SqlExporter } from './SqlExporter';
@@ -334,12 +333,10 @@ CREATE TABLE \`${view.Name}\`(
}
async _queryStream (sql: string) {
if (process.env.NODE_ENV === 'development') console.log('EXPORTER:', sql);
const isPool = 'getConnection' in this._client._connection;
const connection = isPool ? await (this._client._connection as mysql.Pool).getConnection() : this._client._connection;
const connection = await this._client.getConnection();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const stream = (connection as any).connection.query(sql).stream();
const dispose = () => (connection as mysql.PoolConnection).release();
const dispose = () => connection.end();
stream.on('end', dispose);
stream.on('error', dispose);

View File

@@ -425,7 +425,6 @@ SET row_security = off;\n\n\n`;
}
async _queryStream (sql: string) {
if (process.env.NODE_ENV === 'development') console.log('EXPORTER:', sql);
const connection = await this._client.getConnection();
const query = new QueryStream(sql, null);
// eslint-disable-next-line @typescript-eslint/no-explicit-any

View File

@@ -33,8 +33,8 @@ export default class MySQLImporter extends BaseImporter {
parser.on('error', reject);
parser.on('close', async () => {
console.log('TOTAL QUERIES', queryCount);
console.log('import end');
// console.log('TOTAL QUERIES', queryCount);
// console.log('import end');
resolve();
});

View File

@@ -33,8 +33,8 @@ export default class PostgreSQLImporter extends BaseImporter {
parser.on('error', reject);
parser.on('close', async () => {
console.log('TOTAL QUERIES', queryCount);
console.log('import end');
// console.log('TOTAL QUERIES', queryCount);
// console.log('import end');
resolve();
});

View File

@@ -6,6 +6,7 @@ const isWindows = process.platform === 'win32';
const indexPath = path.resolve(__dirname, 'index.html').split(path.sep).join('/');
export function validateSender (frame: WebFrameMain) {
if (isWindows) return true; // TEMP HOTFIX
const frameUrl = new URL(frame.url);
const prefix = isWindows ? 'file:///' : 'file://';
const framePath = frameUrl.href.replace(prefix, '');

View File

@@ -1,5 +1,6 @@
import * as remoteMain from '@electron/remote/main';
import { app, BrowserWindow, ipcMain, nativeImage } from 'electron';
import { app, BrowserWindow, ipcMain, nativeImage, safeStorage } from 'electron';
import * as log from 'electron-log/main';
import * as Store from 'electron-store';
import * as windowStateKeeper from 'electron-window-state';
import * as path from 'path';
@@ -8,6 +9,7 @@ import ipcHandlers from './ipc-handlers';
import { OsMenu, ShortcutRegister } from './libs/ShortcutRegister';
Store.initRenderer();
log.errorHandler.startCatching();
const settingsStore = new Store({ name: 'settings' });
const appTheme = settingsStore.get('application_theme');
const isDevelopment = process.env.NODE_ENV !== 'production';
@@ -78,80 +80,80 @@ async function createMainWindow () {
return window;
}
if (!gotTheLock) app.quit();
else {
require('@electron/remote/main').initialize();
require('@electron/remote/main').initialize();
// Initialize ipcHandlers
ipcHandlers();
// Initialize ipcHandlers
ipcHandlers();
ipcMain.on('refresh-theme-settings', () => {
const appTheme = settingsStore.get('application_theme');
if (isWindows && mainWindow) {
mainWindow.setTitleBarOverlay({
color: appTheme === 'dark' ? '#3f3f3f' : '#fff',
symbolColor: appTheme === 'dark' ? '#fff' : '#000'
});
}
});
ipcMain.on('change-window-title', (_, title: string) => {
if (mainWindow) mainWindow.setTitle(title);
});
// quit application when all windows are closed
app.on('window-all-closed', () => {
// on macOS it is common for applications to stay open until the user explicitly quits
if (!isMacOS) app.quit();
});
app.on('activate', async () => {
// on macOS it is common to re-create a window even after all windows have been closed
if (mainWindow === null)
mainWindow = await createMainWindow();
});
// create main BrowserWindow when electron is ready
app.on('ready', async () => {
mainWindowState = windowStateKeeper({
defaultWidth: 1024,
defaultHeight: 800
ipcMain.on('refresh-theme-settings', () => {
const appTheme = settingsStore.get('application_theme');
if (isWindows && mainWindow) {
mainWindow.setTitleBarOverlay({
color: appTheme === 'dark' ? '#3f3f3f' : '#fff',
symbolColor: appTheme === 'dark' ? '#fff' : '#000'
});
}
});
ipcMain.on('change-window-title', (_, title: string) => {
if (mainWindow) mainWindow.setTitle(title);
});
// quit application when all windows are closed
app.on('window-all-closed', () => {
// on macOS it is common for applications to stay open until the user explicitly quits
if (!isMacOS) app.quit();
});
app.on('activate', async () => {
// on macOS it is common to re-create a window even after all windows have been closed
if (mainWindow === null)
mainWindow = await createMainWindow();
createAppMenu();
});
if (isWindows)
mainWindow.show();
// create main BrowserWindow when electron is ready
app.on('ready', async () => {
if (!gotTheLock && !safeStorage.isEncryptionAvailable()) // Disable multiple instances if is not possible to share session keys
app.quit();
// if (isDevelopment)
// mainWindow.webContents.openDevTools();
process.on('uncaughtException', error => {
mainWindow.webContents.send('unhandled-exception', error);
});
process.on('unhandledRejection', error => {
mainWindow.webContents.send('unhandled-exception', error);
});
mainWindowState = windowStateKeeper({
defaultWidth: 1024,
defaultHeight: 800
});
app.on('browser-window-created', (event, window) => {
if (isDevelopment) {
const { antares } = require('../../package.json');
const extensionPath = path.resolve(__dirname, `../../misc/${antares.devtoolsId}`);
window.webContents.session.loadExtension(extensionPath, { allowFileAccess: true }).catch(console.error);
}
mainWindow = await createMainWindow();
createAppMenu();
window.webContents.on('will-navigate', (e) => { // Prevent browser navigation
e.preventDefault();
});
if (isWindows)
mainWindow.show();
window.webContents.on('did-create-window', (w) => { // Close new windows
w.close();
});
// if (isDevelopment)
// mainWindow.webContents.openDevTools();
process.on('uncaughtException', error => {
mainWindow.webContents.send('unhandled-exception', error);
});
}
process.on('unhandledRejection', error => {
mainWindow.webContents.send('unhandled-exception', error);
});
});
app.on('browser-window-created', (event, window) => {
if (isDevelopment) {
const { antares } = require('../../package.json');
const extensionPath = path.resolve(__dirname, `../../misc/${antares.devtoolsId}`);
window.webContents.session.loadExtension(extensionPath, { allowFileAccess: true }).catch(console.error);
}
window.webContents.on('will-navigate', (e) => { // Prevent browser navigation
e.preventDefault();
});
window.webContents.on('did-create-window', (w) => { // Close new windows
w.close();
});
});
function createAppMenu () {
const menuTemplate: OsMenu = {

View File

@@ -1,5 +1,7 @@
import * as antares from 'common/interfaces/antares';
import * as log from 'electron-log/main';
import * as fs from 'fs';
import { parentPort } from 'worker_threads';
import { MySQLClient } from '../libs/clients/MySQLClient';
import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient';
@@ -8,63 +10,78 @@ import MysqlExporter from '../libs/exporters/sql/MysqlExporter';
import PostgreSQLExporter from '../libs/exporters/sql/PostgreSQLExporter';
let exporter: antares.Exporter;
process.on('message', async ({ type, client, tables, options }: any) => {
log.transports.file.fileName = 'workers.log';
log.transports.console = null;
log.errorHandler.startCatching();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const exportHandler = async (data: any) => {
const { type, client, tables, options } = data;
if (type === 'init') {
const connection = await ClientsFactory.getClient({
client: client.name,
params: client.config,
poolSize: 5
}) as MySQLClient | PostgreSQLClient;
await connection.connect();
try {
const connection = await ClientsFactory.getClient({
client: client.name,
params: client.config,
poolSize: 5
}) as MySQLClient | PostgreSQLClient;
await connection.connect();
switch (client.name) {
case 'mysql':
case 'maria':
exporter = new MysqlExporter(connection as MySQLClient, tables, options);
break;
case 'pg':
exporter = new PostgreSQLExporter(connection as PostgreSQLClient, tables, options);
break;
default:
process.send({
switch (client.name) {
case 'mysql':
case 'maria':
exporter = new MysqlExporter(connection as MySQLClient, tables, options);
break;
case 'pg':
exporter = new PostgreSQLExporter(connection as PostgreSQLClient, tables, options);
break;
default:
parentPort.postMessage({
type: 'error',
payload: `"${client.name}" exporter not aviable`
});
return;
}
exporter.once('error', err => {
log.error(err.toString());
parentPort.postMessage({
type: 'error',
payload: `"${client.name}" exporter not aviable`
payload: err.toString()
});
return;
}
});
exporter.once('error', err => {
console.error(err);
process.send({
exporter.once('end', () => {
parentPort.postMessage({
type: 'end',
payload: { cancelled: exporter.isCancelled }
});
});
exporter.once('cancel', () => {
fs.unlinkSync(exporter.outputFile);
parentPort.postMessage({ type: 'cancel' });
});
exporter.on('progress', state => {
parentPort.postMessage({
type: 'export-progress',
payload: state
});
});
exporter.run();
}
catch (err) {
log.error(err.toString());
parentPort.postMessage({
type: 'error',
payload: err.toString()
});
});
exporter.once('end', () => {
process.send({
type: 'end',
payload: { cancelled: exporter.isCancelled }
});
connection.destroy();
});
exporter.once('cancel', () => {
fs.unlinkSync(exporter.outputFile);
process.send({ type: 'cancel' });
});
exporter.on('progress', state => {
process.send({
type: 'export-progress',
payload: state
});
});
exporter.run();
}
}
else if (type === 'cancel')
exporter.cancel();
});
};
process.on('beforeExit', console.log);
parentPort.on('message', exportHandler);

View File

@@ -1,8 +1,10 @@
import SSHConfig from '@fabio286/ssh2-promise/lib/sshConfig';
import * as antares from 'common/interfaces/antares';
import { ImportOptions } from 'common/interfaces/importer';
import * as log from 'electron-log/main';
import * as mysql from 'mysql2';
import * as pg from 'pg';
import SSHConfig from 'ssh2-promise/lib/sshConfig';
import { parentPort } from 'worker_threads';
import { MySQLClient } from '../libs/clients/MySQLClient';
import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient';
@@ -11,14 +13,18 @@ import MySQLImporter from '../libs/importers/sql/MySQLlImporter';
import PostgreSQLImporter from '../libs/importers/sql/PostgreSQLImporter';
let importer: antares.Importer;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
process.on('message', async ({ type, dbConfig, options }: {
log.transports.file.fileName = 'workers.log';
log.transports.console = null;
log.errorHandler.startCatching();
const importHandler = async (data: {
type: string;
dbConfig: mysql.ConnectionOptions & { schema: string; ssl?: mysql.SslOptions; ssh?: SSHConfig; readonly: boolean }
| pg.ClientConfig & { schema: string; ssl?: mysql.SslOptions; ssh?: SSHConfig; readonly: boolean }
| { databasePath: string; readonly: boolean };
options: ImportOptions;
}) => {
const { type, dbConfig, options } = data;
if (type === 'init') {
try {
const connection = await ClientsFactory.getClient({
@@ -41,7 +47,7 @@ process.on('message', async ({ type, dbConfig, options }: {
importer = new PostgreSQLImporter(pool as unknown as pg.PoolClient, options);
break;
default:
process.send({
parentPort.postMessage({
type: 'error',
payload: `"${options.type}" importer not aviable`
});
@@ -49,33 +55,33 @@ process.on('message', async ({ type, dbConfig, options }: {
}
importer.once('error', err => {
console.error(err);
process.send({
log.error(err.toString());
parentPort.postMessage({
type: 'error',
payload: err.toString()
});
});
importer.once('end', () => {
process.send({
parentPort.postMessage({
type: 'end',
payload: { cancelled: importer.isCancelled }
});
});
importer.once('cancel', () => {
process.send({ type: 'cancel' });
parentPort.postMessage({ type: 'cancel' });
});
importer.on('progress', state => {
process.send({
parentPort.postMessage({
type: 'import-progress',
payload: state
});
});
importer.on('query-error', state => {
process.send({
parentPort.postMessage({
type: 'query-error',
payload: state
});
@@ -84,8 +90,8 @@ process.on('message', async ({ type, dbConfig, options }: {
importer.run();
}
catch (err) {
console.error(err);
process.send({
log.error(err.toString());
parentPort.postMessage({
type: 'error',
payload: err.toString()
});
@@ -93,20 +99,6 @@ process.on('message', async ({ type, dbConfig, options }: {
}
else if (type === 'cancel')
importer.cancel();
});
};
process.on('uncaughtException', (err) => {
console.error(err);
process.send({
type: 'error',
payload: err.toString()
});
});
process.on('unhandledRejection', (err) => {
console.error(err);
process.send({
type: 'error',
payload: err.toString()
});
});
parentPort.on('message', importHandler);

View File

@@ -3,8 +3,8 @@
:type="type"
:path="iconPath"
:size="size"
:flip="flip"
:rotate="rotate"
:class="iconFlip"
/>
</template>
@@ -39,4 +39,24 @@ const props = defineProps({
const iconPath = computed(() => {
return (Icons as {[k:string]: string})[props.iconName];
});
const iconFlip = computed(() => {
if (['horizontal', 'vertical', 'both'].includes(props.flip))
return `flip-${props.flip}`;
else return '';
});
</script>
<style lang="scss" scoped>
.flip-horizontal {
transform: scaleX(-1);
}
.flip-vertical {
transform: scaleY(-1);
}
.flip-both {
transform: scale(-1, -1);
}
</style>

View File

@@ -136,9 +136,4 @@ onMounted(() => {
width: 100%;
}
}
.ace_.mdi {
display: inline-block;
width: 17px;
}
</style>

View File

@@ -133,6 +133,7 @@ import BaseIcon from '@/components/BaseIcon.vue';
import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue';
import { useFilters } from '@/composables/useFilters';
import { useFocusTrap } from '@/composables/useFocusTrap';
import { copyText } from '@/libs/copyText';
import { useConnectionsStore } from '@/stores/connections';
import { HistoryRecord, useHistoryStore } from '@/stores/history';
@@ -173,7 +174,7 @@ watch(searchTerm, () => {
});
const copyQuery = (sql: string) => {
navigator.clipboard.writeText(sql);
copyText(sql);
};
const deleteQuery = (query: HistoryRecord[]) => {

View File

@@ -161,6 +161,7 @@ import ModalProcessesListContext from '@/components/ModalProcessesListContext.vu
import ModalProcessesListRow from '@/components/ModalProcessesListRow.vue';
import { useFocusTrap } from '@/composables/useFocusTrap';
import Schema from '@/ipc-api/Schema';
import { copyText } from '@/libs/copyText';
import { useConnectionsStore } from '@/stores/connections';
import { useNotificationsStore } from '@/stores/notifications';
@@ -322,13 +323,13 @@ const closeContext = () => {
const copyCell = () => {
const row = results.value.find(row => Number(row.id) === selectedRow.value);
const valueToCopy = row[selectedCell.value.field];
navigator.clipboard.writeText(valueToCopy);
copyText(valueToCopy);
};
const copyRow = () => {
const row = results.value.find(row => Number(row.id) === selectedRow.value);
const rowToCopy = JSON.parse(JSON.stringify(row));
navigator.clipboard.writeText(JSON.stringify(rowToCopy));
copyText(JSON.stringify(rowToCopy));
};
const closeModal = () => emit('close');

View File

@@ -403,11 +403,6 @@ defineExpose({ editor });
}
}
.ace_.mdi {
display: inline-block;
width: 17px;
}
.ace_gutter-cell.ace_breakpoint {
&::before {
content: '\F0403';

View File

@@ -15,6 +15,14 @@
:size="18"
/> {{ t('connection.disconnect') }}</span>
</div>
<div class="context-element" @click.stop="showAppearanceModal">
<span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiBrushVariant"
:size="18"
/> {{ t('application.appearance') }}</span>
</div>
<div
v-if="!contextConnection.isFolder"
class="context-element"
@@ -27,14 +35,6 @@
:size="18"
/> {{ t('general.duplicate') }}</span>
</div>
<div class="context-element" @click.stop="showAppearanceModal">
<span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiBrushVariant"
:size="18"
/> {{ t('application.appearance') }}</span>
</div>
<div class="context-element" @click="showConfirmModal">
<span class="d-flex">
<BaseIcon

View File

@@ -84,12 +84,15 @@
@click="showSettingModal('general')"
>
<div class="settingbar-element-icon-wrapper">
<BaseIcon
icon-name="mdiCog"
<div
class="settingbar-element-icon text-light"
:class="{ 'badge badge-update': hasUpdates }"
:size="24"
/>
>
<BaseIcon
icon-name="mdiCog"
:size="24"
/>
</div>
</div>
</li>
</ul>
@@ -266,7 +269,7 @@ if (!connectionsArr.value.length)
.settingbar-element-icon {
&.badge::after {
top: 10px;
right: -6px;
right: -3px;
position: absolute;
}

View File

@@ -11,7 +11,7 @@
>
<div class="workspace-explorebar-header">
<div
v-if="customizations.database"
v-if="customizations.database && databases.length"
class="workspace-explorebar-database-switch"
:title="t('database.switchDatabase')"
>

View File

@@ -55,6 +55,14 @@
/> {{ t('general.disable') }}
</span>
</div>
<div class="context-element" @click="copyName(selectedMisc.name)">
<span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiContentCopy"
:size="18"
/> {{ t('general.copyName') }}</span>
</div>
<div class="context-element" @click="showDeleteModal">
<span class="d-flex">
<BaseIcon
@@ -108,6 +116,7 @@ import Functions from '@/ipc-api/Functions';
import Routines from '@/ipc-api/Routines';
import Schedulers from '@/ipc-api/Schedulers';
import Triggers from '@/ipc-api/Triggers';
import { copyText } from '@/libs/copyText';
import { useNotificationsStore } from '@/stores/notifications';
import { useWorkspacesStore } from '@/stores/workspaces';
@@ -163,6 +172,11 @@ const deleteMessage = computed(() => {
}
});
const copyName = (name: string) => {
copyText(name);
closeContext();
};
const showDeleteModal = () => {
isDeleteModal.value = true;
};

View File

@@ -52,6 +52,7 @@
class="table-icon mr-1"
:icon-name="table.type === 'view' ? 'mdiTableEye' : 'mdiTable'"
:size="18"
:style="`min-width: 18px`"
/>
<span v-html="highlightWord(table.name)" />
</a>
@@ -78,6 +79,11 @@
icon-name="mdiFolderCog"
:size="18"
/>
<BaseIcon
class="misc-icon open-folder mr-1"
icon-name="mdiFolderOpen"
:size="18"
/>
{{ t('database.trigger', 2) }}
</summary>
<div class="accordion-body">
@@ -99,6 +105,7 @@
class="table-icon mr-1"
icon-name="mdiTableCog"
:size="18"
:style="`min-width: 18px`"
/>
<span v-html="highlightWord(trigger.name)" />
</a>
@@ -132,6 +139,11 @@
icon-name="mdiFolderSync"
:size="18"
/>
<BaseIcon
class="misc-icon open-folder mr-1"
icon-name="mdiFolderOpen"
:size="18"
/>
{{ t('database.storedRoutine', 2) }}
</summary>
<div class="accordion-body">
@@ -151,6 +163,7 @@
class="table-icon mr-1"
icon-name="mdiSyncCircle"
:size="18"
:style="`min-width: 18px`"
/>
<span v-html="highlightWord(routine.name)" />
</a>
@@ -172,6 +185,12 @@
class="misc-icon mr-1"
icon-name="mdiFolderRefresh"
:size="18"
:style="`min-width: 18px`"
/>
<BaseIcon
class="misc-icon open-folder mr-1"
icon-name="mdiFolderOpen"
:size="18"
/>
{{ t('database.triggerFunction', 2) }}
</summary>
@@ -214,6 +233,11 @@
icon-name="mdiFolderMove"
:size="18"
/>
<BaseIcon
class="misc-icon open-folder mr-1"
icon-name="mdiFolderOpen"
:size="18"
/>
{{ t('database.function', 2) }}
</summary>
<div class="accordion-body">
@@ -233,6 +257,7 @@
class="misc-icon mr-1"
icon-name="mdiArrowRightBoldBox"
:size="18"
:style="`min-width: 18px`"
/>
<span v-html="highlightWord(func.name)" />
</a>
@@ -255,6 +280,11 @@
icon-name="mdiFolderClock"
:size="18"
/>
<BaseIcon
class="misc-icon open-folder mr-1"
icon-name="mdiFolderOpen"
:size="18"
/>
{{ t('database.scheduler', 2) }}
</summary>
<div class="accordion-body">
@@ -275,6 +305,7 @@
class="misc-icon mr-1"
icon-name="mdiCalendarClock"
:size="18"
:style="`min-width: 18px`"
/>
<span v-html="highlightWord(scheduler.name)" />
</a>
@@ -639,10 +670,19 @@ defineExpose({ selectSchema, schemaAccordion });
.database-misc {
margin-left: 1.6rem;
.accordion[open] .accordion-header > .misc-icon:first-child::before {
content: "\F0770";
.open-folder {
display: none;
}
.accordion[open] .accordion-header {
> .misc-icon {
display: none;
&.open-folder {
display: initial;
}
}
}
.accordion-body {
margin-bottom: 0.2rem;
}

View File

@@ -102,6 +102,14 @@
</div>
</div>
</div>
<div class="context-element" @click="copyName(selectedSchema)">
<span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiContentCopy"
:size="18"
/> {{ t('general.copyName') }}</span>
</div>
<div
v-if="workspace.customizations.schemaExport"
class="context-element"
@@ -198,6 +206,7 @@ import ModalEditSchema from '@/components/ModalEditSchema.vue';
import ModalImportSchema from '@/components/ModalImportSchema.vue';
import Application from '@/ipc-api/Application';
import Schema from '@/ipc-api/Schema';
import { copyText } from '@/libs/copyText';
import { useNotificationsStore } from '@/stores/notifications';
import { useSchemaExportStore } from '@/stores/schemaExport';
import { useWorkspacesStore } from '@/stores/workspaces';
@@ -268,6 +277,11 @@ const openCreateSchedulerTab = () => {
emit('open-create-scheduler-tab');
};
const copyName = (name: string) => {
copyText(name);
closeContext();
};
const showDeleteModal = () => {
isDeleteModal.value = true;
};

View File

@@ -15,6 +15,14 @@
:size="18"
/> {{ t('application.settings') }}</span>
</div>
<div class="context-element" @click="copyName(selectedTable.name)">
<span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiContentCopy"
:size="18"
/> {{ t('general.copyName') }}</span>
</div>
<div
v-if="selectedTable && selectedTable.type === 'table' && customizations.schemaExport"
class="context-element"
@@ -130,6 +138,7 @@ import ConfirmModal from '@/components/BaseConfirmModal.vue';
import BaseContextMenu from '@/components/BaseContextMenu.vue';
import BaseIcon from '@/components/BaseIcon.vue';
import Tables from '@/ipc-api/Tables';
import { copyText } from '@/libs/copyText';
import { useNotificationsStore } from '@/stores/notifications';
import { useSchemaExportStore } from '@/stores/schemaExport';
import { useWorkspacesStore } from '@/stores/workspaces';
@@ -170,6 +179,11 @@ const showTableExportModal = () => {
closeContext();
};
const copyName = (name: string) => {
copyText(name);
closeContext();
};
const showDeleteModal = () => {
isDeleteModal.value = true;
};

View File

@@ -52,6 +52,7 @@ import { useI18n } from 'vue-i18n';
import BaseContextMenu from '@/components/BaseContextMenu.vue';
import BaseIcon from '@/components/BaseIcon.vue';
import { copyText } from '@/libs/copyText';
import { useConsoleStore } from '@/stores/console';
const { t } = useI18n();
@@ -100,7 +101,7 @@ const contextMenu = (event: MouseEvent, wLog: {date: Date; sql: string}) => {
};
const copyQuery = () => {
navigator.clipboard.writeText(contextQuery.value);
copyText(contextQuery.value);
isContext.value = false;
};

View File

@@ -56,7 +56,7 @@
<div class="tile-icon">
<div>
<BaseIcon
class="mr-1"
class="mr-1 mt-1"
icon-name="mdiKeyLink"
:size="24"
/>
@@ -78,6 +78,7 @@
class="mr-1"
icon-name="mdiTable"
:size="14"
:style="'min-width:14px'"
/>
<span>{{ foreign.table }}.{{ foreign.field }}</span>
</span>
@@ -86,6 +87,7 @@
class="mr-1"
icon-name="mdiTable"
:size="14"
:style="'min-width:14px'"
/>
<span>{{ foreign.refTable }}.{{ foreign.refField }}</span>
</span>

View File

@@ -27,11 +27,7 @@
:title="t('general.cancel')"
@click="killTabQuery()"
>
<BaseIcon
class="mr-1"
icon-name="mdiWindowCLose"
:size="24"
/>
<BaseIcon icon-name="mdiWindowClose" :size="24" />
<span class="d-invisible pr-1">{{ t('general.run') }}</span>
</button>
<button

View File

@@ -3,7 +3,7 @@
ref="tableWrapper"
class="vscroll no-outline"
tabindex="0"
:style="{'height': resultsSize+'px'}"
:style="{ 'height': resultsSize + 'px' }"
@blur="deselectRows"
@focus="hasFocus = true"
@keyup.delete="showDeleteConfirmModal"
@@ -28,7 +28,7 @@
v-for="(result, index) in resultsWithRows"
:key="index"
class="tab-item"
:class="{'active': resultsetIndex === index}"
:class="{ 'active': resultsetIndex === index }"
@click="selectResultset(index)"
>
<a>{{ result.fields ? result.fields[0]?.table : '' }} ({{ result.rows.length }})</a>
@@ -57,7 +57,7 @@
<span>{{ field.alias || field.name }}</span>
<BaseIcon
v-if="isSortable && currentSort === field.name || currentSort === `${field.table}.${field.name}`"
:icon-name="currentSortDir === 'asc' ? 'mdiSortAscending':'mdiSortDescending'"
:icon-name="currentSortDir === 'asc' ? 'mdiSortAscending' : 'mdiSortDescending'"
:size="18"
class="sort-icon ml-1"
/>
@@ -90,7 +90,7 @@
:fields="fieldsObj"
:key-usage="keyUsage"
:element-type="elementType"
:class="{'selected': selectedRows.includes(row._antares_id)}"
:class="{ 'selected': selectedRows.includes(row._antares_id) }"
:selected="selectedRows.includes(row._antares_id)"
:selected-cell="selectedRows.length === 1 && selectedRows.includes(row._antares_id) ? selectedField : null"
@start-editing="isEditingRow = true"
@@ -163,7 +163,7 @@
<BaseSelect
v-model="sqlExportOptions.sqlInsertDivider"
class="form-select"
:options="[{value: 'bytes', label: 'KiB'}, {value: 'rows', label: t('database.row', 2)}]"
:options="[{ value: 'bytes', label: 'KiB' }, { value: 'rows', label: t('database.row', 2) }]"
/>
</div>
</div>
@@ -208,9 +208,9 @@
v-model="csvExportOptions.stringDelimiter"
class="form-select"
:options="[
{value: '', label: t('general.none')},
{value: 'single', label: t('general.singleQuote')},
{value: 'double', label: t('general.doubleQuote')}
{ value: '', label: t('general.none') },
{ value: 'single', label: t('general.singleQuote') },
{ value: 'double', label: t('general.doubleQuote') }
]"
/>
</div>
@@ -235,7 +235,10 @@
</label>
</div>
<div class="column col-7">
<label class="form-switch d-inline-block" @click.prevent="csvExportOptions.header = !csvExportOptions.header">
<label
class="form-switch d-inline-block"
@click.prevent="csvExportOptions.header = !csvExportOptions.header"
>
<input type="checkbox" :checked="csvExportOptions.header">
<i class="form-icon" />
</label>
@@ -249,10 +252,10 @@
<script setup lang="ts">
/* eslint-disable @typescript-eslint/no-explicit-any */
import faker from '@faker-js/faker';
import { BLOB, DATE, DATETIME, LONG_TEXT, TEXT, TIME } from 'common/fieldTypes';
import { QueryResult, TableField } from 'common/interfaces/antares';
import { TableUpdateParams } from 'common/interfaces/tableApis';
import { fakerCustom } from 'common/libs/fakerCustom';
import { jsonToSqlInsert } from 'common/libs/sqlUtils';
import { uidGen } from 'common/libs/uidGen';
import * as json2php from 'json2php';
@@ -267,6 +270,7 @@ import BaseSelect from '@/components/BaseSelect.vue';
import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue';
import TableContext from '@/components/WorkspaceTabQueryTableContext.vue';
import WorkspaceTabQueryTableRow from '@/components/WorkspaceTabQueryTableRow.vue';
import { copyText } from '@/libs/copyText';
import { unproxify } from '@/libs/unproxify';
import { useConsoleStore } from '@/stores/console';
import { useSettingsStore } from '@/stores/settings';
@@ -299,7 +303,7 @@ const emit = defineEmits([
'duplicate-row'
]);
const resultTable: Ref<Component & {updateWindow: () => void}> = ref(null);
const resultTable: Ref<Component & { updateWindow: () => void }> = ref(null);
const tableWrapper: Ref<HTMLDivElement> = ref(null);
const table: Ref<HTMLDivElement> = ref(null);
const resultsSize = ref(0);
@@ -377,7 +381,7 @@ const keyUsage = computed(() => resultsWithRows.value.length ? resultsWithRows.v
const fieldsObj = computed(() => {
if (sortedResults.value.length) {
const fieldsObj: {[key: string]: TableField} = {};
const fieldsObj: { [key: string]: TableField } = {};
for (const key in sortedResults.value[0]) {
if (key === '_antares_id') continue;
@@ -483,7 +487,7 @@ const resizeResults = () => {
const refreshScroller = () => resizeResults();
const updateField = (payload: { field: string; type: string; content: any }, row: {[key: string]: any}) => {
const updateField = (payload: { field: string; type: string; content: any }, row: { [key: string]: any }) => {
const orgRow: any = localResults.value.find((lr: any) => lr._antares_id === row._antares_id);
Object.keys(orgRow).forEach(key => { // remap the row
@@ -568,7 +572,7 @@ const copyCell = () => {
let valueToCopy = row[cellName];
if (typeof valueToCopy === 'object')
valueToCopy = JSON.stringify(valueToCopy);
navigator.clipboard.writeText(valueToCopy);
copyText(valueToCopy);
};
const copyRow = (format: string) => {
@@ -590,7 +594,7 @@ const copyRow = (format: string) => {
}
if (format === 'json')
navigator.clipboard.writeText(JSON.stringify(contentToCopy));
copyText(JSON.stringify(contentToCopy));
else if (format === 'sql') {
if (!Array.isArray(contentToCopy)) contentToCopy = [contentToCopy];
@@ -598,11 +602,11 @@ const copyRow = (format: string) => {
json: contentToCopy,
client: workspaceClient.value,
fields: fieldsObj.value as {
[key: string]: {type: string; datePrecision: number};
[key: string]: { type: string; datePrecision: number };
},
table: getTable(resultsetIndex.value)
});
navigator.clipboard.writeText(sqlInserts);
copyText(sqlInserts);
}
else if (format === 'csv') {
const csv = [];
@@ -614,7 +618,7 @@ const copyRow = (format: string) => {
for (const row of contentToCopy)
csv.push(Object.values(row).map(col => typeof col === 'string' ? `"${col}"` : col).join(';'));
navigator.clipboard.writeText(csv.join('\n'));
copyText(csv.join('\n'));
}
else if (format === 'html') {
const arrayContent = new Array<string[]>();
@@ -637,7 +641,7 @@ const copyRow = (format: string) => {
if (!Array.isArray(contentToCopy)) contentToCopy = [contentToCopy];
const printer = json2php.make({ linebreak: '\n', indent: '\t', shortArraySyntax: true });
const phpString = printer(contentToCopy);
navigator.clipboard.writeText(phpString);
copyText(phpString);
}
};
@@ -670,28 +674,18 @@ const fillCell = (event: { name: string; group: string; type: string }) => {
datePrecision += i === 0 ? '.S' : 'S';
}
if (event.group === 'custom') {
if (event.type === 'time' && event.name === 'now')
fakeValue = moment().format(`HH:mm:ss${datePrecision}`);
else if (event.type === 'time' && event.name === 'random')
fakeValue = moment(faker.date.recent()).format(`HH:mm:ss${datePrecision}`);
else if (event.type === 'datetime' && event.name === 'now')
fakeValue = moment().format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
}
else {
fakeValue = (faker as any)[event.group][event.name]();
if (['string', 'number'].includes(typeof fakeValue)) {
if (typeof fakeValue === 'number')
fakeValue = String(fakeValue);
fakeValue = (fakerCustom as any)[event.group][event.name]();
if (['string', 'number'].includes(typeof fakeValue)) {
if (typeof fakeValue === 'number')
fakeValue = String(fakeValue);
if (selectedCell.value.length)
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))
fakeValue = moment(fakeValue).format(`HH:mm:ss${datePrecision}`);
if (selectedCell.value.length)
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))
fakeValue = moment(fakeValue).format(`HH:mm:ss${datePrecision}`);
const params = {
primary: primaryField.value?.name,
@@ -859,12 +853,12 @@ const downloadTable = (format: 'csv' | 'json' | 'sql' | 'php', table: string, po
type: format,
content: rows,
fields: JSON.parse(JSON.stringify(fieldsObj.value)) as {
[key: string]: {type: string; datePrecision: number};
[key: string]: { type: string; datePrecision: number };
},
client: workspaceClient.value,
table,
sqlOptions: popup ? { ...sqlExportOptions.value }: null,
csvOptions: popup ? { ...csvExportOptions.value }: null
sqlOptions: popup ? { ...sqlExportOptions.value } : null,
csvOptions: popup ? { ...csvExportOptions.value } : null
});
};
@@ -885,7 +879,7 @@ const onKey = async (e: KeyboardEvent) => {
const copyType = defaultCopyType.value;
if (selectedRows.value.length >= 1) {
if (selectedRows.value.length === 1 && copyType === 'cell')
await navigator.clipboard.writeText(scrollElement.value.querySelector('.td.selected').innerText);
await copyText(scrollElement.value.querySelector('.td.selected').innerText);
else if (selectedRows.value.length > 1 && copyType === 'cell')
copyRow('html');
else
@@ -897,7 +891,7 @@ const onKey = async (e: KeyboardEvent) => {
if (!(e.ctrlKey || e.metaKey) && (e.code.includes('Arrow') || e.code === 'Tab') && sortedResults.value.length > 0 && !e.altKey) {
e.preventDefault();
const aviableFields= Object.keys(sortedResults.value[0]).slice(0, -1); // removes _antares_id
const aviableFields = Object.keys(sortedResults.value[0]).slice(0, -1); // removes _antares_id
if (!selectedField.value)
selectedField.value = aviableFields[0];
@@ -914,8 +908,8 @@ const onKey = async (e: KeyboardEvent) => {
nextIndex = selectedIndex + 1;
nextFieldIndex = selectedFieldIndex;
if (nextIndex > sortedResults.value.length -1)
nextIndex = sortedResults.value.length -1;
if (nextIndex > sortedResults.value.length - 1)
nextIndex = sortedResults.value.length - 1;
break;
case 'ArrowUp':
@@ -931,7 +925,7 @@ const onKey = async (e: KeyboardEvent) => {
nextIndex = selectedIndex;
nextFieldIndex = selectedFieldIndex + 1;
if (nextFieldIndex > aviableFields.length -1)
if (nextFieldIndex > aviableFields.length - 1)
nextFieldIndex = 0;
break;
@@ -941,7 +935,7 @@ const onKey = async (e: KeyboardEvent) => {
nextFieldIndex = selectedFieldIndex - 1;
if (nextFieldIndex < 0)
nextFieldIndex = aviableFields.length -1;
nextFieldIndex = aviableFields.length - 1;
break;
@@ -950,11 +944,11 @@ const onKey = async (e: KeyboardEvent) => {
if (e.shiftKey) {
nextFieldIndex = selectedFieldIndex - 1;
if (nextFieldIndex < 0)
nextFieldIndex = aviableFields.length -1;
nextFieldIndex = aviableFields.length - 1;
}
else {
nextFieldIndex = selectedFieldIndex + 1;
if (nextFieldIndex > aviableFields.length -1)
if (nextFieldIndex > aviableFields.length - 1)
nextFieldIndex = 0;
}
}
@@ -1049,32 +1043,33 @@ onUnmounted(() => {
<style lang="scss" scoped>
.vscroll {
height: 1000px;
overflow: auto;
overflow-anchor: none;
height: 1000px;
overflow: auto;
overflow-anchor: none;
}
.column-resizable {
&:hover,
&:active {
resize: horizontal;
overflow: hidden;
}
&:hover,
&:active {
resize: horizontal;
overflow: hidden;
}
}
.table-column-title {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
.sort-icon {
font-size: 0.7rem;
line-height: 1;
margin-left: 0.2rem;
font-size: 0.7rem;
line-height: 1;
margin-left: 0.2rem;
}
.result-tabs {
background: transparent !important;
margin: 0;
background: transparent !important;
margin: 0;
}
</style>

View File

@@ -197,13 +197,13 @@ const fakerMethods = {
{ name: 'amount', group: 'finance' }
],
datetime: [
{ name: 'now', group: 'custom' },
{ name: 'now', group: 'date' },
{ name: 'past', group: 'date' },
{ name: 'future', group: 'date' }
],
time: [
{ name: 'now', group: 'custom' },
{ name: 'random', group: 'custom' }
{ name: 'now', group: 'time' },
{ name: 'random', group: 'time' }
],
uuid: [
{ name: 'uuid', group: 'random' }

View File

@@ -580,7 +580,7 @@ const onKey = (e: KeyboardEvent) => {
if (!editingField.value && e.key === 'Enter')
return editON(props.selectedCell);
if (editingField.value && e.key === 'Enter' && !isBaseSelectField.value)
if (editingField.value && e.key === 'Enter' && !isBaseSelectField.value && !isTextareaEditor.value)
return editOFF();
if (editingField.value && e.key === 'Escape') {

View File

@@ -183,6 +183,7 @@
<WorkspaceTabTableFilters
v-if="isSearch"
:fields="fields"
:is-quering="isQuering"
:conn-client="connection.client"
@filter="updateFilters"
@filter-change="onFilterChange"
@@ -231,7 +232,7 @@ import { ConnectionParams } from 'common/interfaces/antares';
import { TableFilterClausole } from 'common/interfaces/tableApis';
import { ipcRenderer } from 'electron';
import { storeToRefs } from 'pinia';
import { computed, onBeforeUnmount, Prop, Ref, ref, watch } from 'vue';
import { computed, nextTick, onBeforeUnmount, Prop, Ref, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
@@ -258,7 +259,10 @@ const props = defineProps({
elementType: String
});
const reloadTable = () => getTableData();
const reloadTable = async () => {
await nextTick();
getTableData();
};
const {
queryTable,

View File

@@ -9,6 +9,7 @@
<input
v-model="row.active"
type="checkbox"
:disabled="isQuering"
@change="doFilter"
><i class="form-icon" />
</label>
@@ -18,11 +19,13 @@
:options="fields"
option-track-by="name"
option-label="name"
:disabled="isQuering"
/>
<BaseSelect
v-model="row.op"
class="form-select ml-2 col-auto select-sm"
:options="operators"
:disabled="isQuering"
/>
<div class="workspace-table-filters-row-value ml-2">
<input
@@ -30,12 +33,14 @@
v-model="row.value"
type="text"
class="form-input input-sm"
:disabled="isQuering"
>
<input
v-if="row.op === 'BETWEEN'"
v-model="row.value2"
type="text"
class="form-input ml-2 input-sm"
:disabled="isQuering"
>
</div>
<button
@@ -76,7 +81,7 @@
import customizations from 'common/customizations';
import { FLOAT, NUMBER } from 'common/fieldTypes';
import { ClientCode, TableField } from 'common/interfaces/antares';
import { TableFilterClausole } from 'common/interfaces/tableApis';
import { TableFilterClausole, TableFilterOperator } from 'common/interfaces/tableApis';
import { computed, Prop, ref } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -87,15 +92,14 @@ const { t } = useI18n();
const props = defineProps({
fields: Array as Prop<TableField[]>,
connClient: String as Prop<ClientCode>
connClient: String as Prop<ClientCode>,
isQuering: Boolean
});
const emit = defineEmits(['filter-change', 'filter']);
const rows = ref([]);
const operators = ref([
'=', '!=', '>', '<', '>=', '<=', 'IN', 'NOT IN', 'LIKE', 'BETWEEN', 'IS NULL', 'IS NOT NULL'
]);
const operators: TableFilterOperator[] = customizations[props.connClient].operators;
const clientCustomizations = computed(() => customizations[props.connClient]);
@@ -122,6 +126,13 @@ const createClausole = (filter: TableFilterClausole) => {
const { elementsWrapper: ew, stringsWrapper: sw } = clientCustomizations.value;
let value;
if (isNumeric && !['IN', 'NOT IN', 'RLIKE', 'NOT RLIKE'].includes(filter.op)) {
if (isNaN(Number(filter.value)))
filter.value = '';
if (isNaN(Number(filter.value2)))
filter.value2 = '';
}
switch (filter.op) {
case '=':
case '!=':
@@ -138,13 +149,14 @@ const createClausole = (filter: TableFilterClausole) => {
val = val.trim();
return isNumeric ? val : `${sw}${val}${sw}`;
}).join(',');
value = `(${filter.value})`;
value = `(${value})`;
break;
case 'IS NULL':
case 'IS NOT NULL':
value = '';
break;
case 'LIKE':
case 'NOT LIKE':
value = `${sw}%${filter.value}%${sw}`;
break;
default:

View File

@@ -65,7 +65,8 @@ export const enUS = {
actionSuccessful: '{action} successful',
outputFormat: 'Output format',
singleFile: 'Single {ext} file',
zipCompressedFile: 'ZIP compressed {ext} file'
zipCompressedFile: 'ZIP compressed {ext} file',
copyName: 'Copy name'
},
connection: { // Database connection
connectionName: 'Connection name',

View File

@@ -14,6 +14,7 @@ import { koKR } from './ko-KR';
import { nlNL } from './nl-NL';
import { ptBR } from './pt-BR';
import { ruRU } from './ru-RU';
import { ukUA } from './uk-UA';
import { viVN } from './vi-VN';
import { zhCN } from './zh-CN';
const messages = {
@@ -32,7 +33,8 @@ const messages = {
'ko-KR': koKR,
'nl-NL': nlNL,
'ca-ES': caES,
'cs-CZ': csCZ
'cs-CZ': csCZ,
'uk-UA': ukUA
};
type NestedPartial<T> = {

View File

@@ -24,17 +24,17 @@ export const nlNL = {
clear: 'Wis',
seconds: 'Seconden',
options: 'Opties',
discard: 'Discard',
discard: 'Verwerp',
stay: 'Stay',
author: 'Auteur',
upload: 'Upload',
browse: 'Blader',
content: 'Content',
cut: 'Cut',
cut: 'Knip',
copy: 'Kopieer',
paste: 'Plak',
tools: 'Gereedschap',
format: 'Format',
format: 'Formatteer',
all: 'Alle',
duplicate: 'Dupliceer',
new: 'Nieuw',
@@ -48,7 +48,7 @@ export const nlNL = {
disabled: 'Uitgeschakeld',
enable: 'Inschakelen',
disable: 'Uitschakelen',
contributors: 'Contributors',
contributors: 'Bijdragers',
pin: 'Vastzetten',
unpin: 'Losmaken',
folder: 'Folder | Folders',
@@ -129,7 +129,7 @@ export const nlNL = {
scheduler: 'Scheduler | Schedulers',
event: 'Event',
parameters: 'Parameters',
function: 'Functiw | Functies',
function: 'Functie | Functies',
deterministic: 'Deterministic',
context: 'Context',
export: 'Export',
@@ -138,10 +138,10 @@ export const nlNL = {
timing: 'Timing',
state: 'State',
execution: 'Execution',
starts: 'Starts',
ends: 'Ends',
starts: 'Start',
ends: 'Eindigt',
variables: 'Variabelen',
processes: 'Processes',
processes: 'Processen',
database: 'Database',
array: 'Array',
structure: 'Structuur',
@@ -254,9 +254,9 @@ export const nlNL = {
queryHistory: 'Query geschiedenis',
clearQuery: 'Wis query',
fillCell: 'Vul cel',
executeSelectedQuery: 'Execute selected query',
executeSelectedQuery: 'Voer geselecteerde query uit',
noResultsPresent: 'Geen resultaten beschikbaar',
sqlExportOptions: 'SQL export options',
sqlExportOptions: 'SQL export opties',
targetTable: 'Doeltabel',
switchDatabase: 'Wissel van database',
importQueryErrors: 'Waarschuwing: {n} fout is opgetreden | Waarschuwing: {n} fouten opgetreden',
@@ -275,7 +275,7 @@ export const nlNL = {
application: 'Applicatie',
editor: 'Editor',
scratchpad: 'Kladblok',
changelog: 'Changelog',
changelog: 'Wijzigingslogboek',
small: 'Klein',
medium: 'Medium',
large: 'Groot',
@@ -296,11 +296,11 @@ export const nlNL = {
restartToInstall: 'Herstart Antares om te installeren',
notificationsTimeout: 'Notifications timeout',
openNewTab: 'Open een nieuw tabblad',
unsavedChanges: 'Onopgeslagen wijzigingen',
discardUnsavedChanges: 'Je hebt onopgeslagen wijzigingen. Closing this tab these changes will be discarded.',
applicationTheme: 'Applicatie thema',
editorTheme: 'Editor Theme',
wrapLongLines: 'Wrap long lines',
unsavedChanges: 'Niet opgeslagen wijzigingen',
discardUnsavedChanges: 'Je hebt niet opgeslagen wijzigingen. Closing this tab these changes will be discarded.',
applicationTheme: 'Applicatiethema',
editorTheme: 'Editor Thema',
wrapLongLines: 'Lange regels afbreken',
includeBetaUpdates: 'Include beta updates',
markdownSupported: 'Markdown wordt ondersteund',
plantATree: 'Plant een boom',
@@ -310,7 +310,7 @@ export const nlNL = {
closeTab: 'Sluit tabblad',
goToDownloadPage: 'Ga naar de downloadpagina',
disableBlur: 'Vervagen uitschakelen',
missingOrIncompleteTranslation: 'Missing or incomplete translation?',
missingOrIncompleteTranslation: 'Onvolledige of ontbrekende vertaling?',
findOutHowToContribute: 'Ontdek hoe je kunt bijdragen',
disableScratchpad: 'Kladblok uitschakelen',
reportABug: 'Bug melden',
@@ -338,9 +338,9 @@ export const nlNL = {
folderName: 'Foldernaam',
deleteFolder: 'Verwijder folder',
editConnectionAppearance: 'Edit connection appearance',
defaultCopyType: 'Default copy type',
showTableSize: 'Show table size in sidebar',
showTableSizeDescription: 'MySQL/MariaDB only. Enable this option may affects performance on schema with many tables.',
defaultCopyType: 'Kopieer standaard',
showTableSize: 'Toon tabelgrootte in de sidebar',
showTableSizeDescription: 'Alleen voor MySQL/MariaDB. Bij schema\'s met veel tabellen kan dit de snelheid beïnvloeden.',
searchForSchemas: 'Zoek naar schemas',
searchForElements: 'Zoek naar elementen',
switchSearchMethod: 'Switch search method',
@@ -370,36 +370,36 @@ export const nlNL = {
password: 'Wachtwoord'
},
faker: {
address: 'Address',
address: 'Adres',
commerce: 'Commerce',
company: 'Company',
database: 'Database',
date: 'Date',
date: 'Datum',
finance: 'Finance',
git: 'Git',
hacker: 'Hacker',
internet: 'Internet',
lorem: 'Lorem',
name: 'Name',
music: 'Music',
phone: 'Phone',
name: 'Naam',
music: 'Muziek',
phone: 'Telefoon',
random: 'Random',
system: 'System',
time: 'Time',
vehicle: 'Vehicle',
zipCode: 'Zip code',
time: 'Tijd',
vehicle: 'Voertuig',
zipCode: 'Postcode',
zipCodeByState: 'Zip code by state',
city: 'City',
city: 'Woonplaats',
cityPrefix: 'City prefix',
citySuffix: 'City suffix',
streetName: 'Street name',
streetName: 'Straatnaam',
streetAddress: 'Street address',
streetSuffix: 'Street suffix',
streetPrefix: 'Street prefix',
secondaryAddress: 'Secondary address',
county: 'County',
country: 'Country',
countryCode: 'Country code',
country: 'Land',
countryCode: 'Landcode',
state: 'State',
stateAbbr: 'State abbreviation',
latitude: 'Latitude',
@@ -408,11 +408,11 @@ export const nlNL = {
cardinalDirection: 'Cardinal direction',
ordinalDirection: 'Ordinal direction',
nearbyGPSCoordinate: 'Nearby GPS coordinate',
timeZone: 'Time zone',
color: 'Color',
department: 'Department',
productName: 'Product name',
price: 'Price',
timeZone: 'Tijdzone',
color: 'Kleur',
department: 'Afdeling',
productName: 'Productnaam',
price: 'Prijs',
productAdjective: 'Product adjective',
productMaterial: 'Product material',
product: 'Product',
@@ -453,7 +453,7 @@ export const nlNL = {
litecoinAddress: 'Litecoin address',
creditCardNumber: 'Credit card number',
creditCardCVV: 'Credit card CVV',
ethereumAddress: 'Ethereum address',
ethereumAddress: 'Ethereum adres',
iban: 'IBAN',
bic: 'BIC',
transactionDescription: 'Transaction description',
@@ -464,14 +464,14 @@ export const nlNL = {
shortSha: 'Short SHA',
abbreviation: 'Abbreviation',
adjective: 'Adjective',
noun: 'Noun',
verb: 'Verb',
noun: 'Zelfstandig naamwoord',
verb: 'Werkwoord',
ingverb: 'Ingverb',
phrase: 'Phrase',
phrase: 'Zin',
avatar: 'Avatar',
email: 'Email',
email: 'E-mailadres',
exampleEmail: 'Voorbeeld email',
userName: 'Gebuikersnaam',
userName: 'Gebruikersnaam',
protocol: 'Protocol',
url: 'Url',
domainName: 'Domeinnaam',
@@ -482,8 +482,8 @@ export const nlNL = {
userAgent: 'User agent',
mac: 'Mac',
password: 'Wachtwoord',
word: 'Word',
words: 'Words',
word: 'Woord',
words: 'Woorden',
sentence: 'Zin',
slug: 'Slug',
sentences: 'Zinnen',

View File

@@ -14,5 +14,6 @@ export const localesNames: {[key: string]: string} = {
'ko-KR': '한국어',
'nl-NL': 'Nederlands',
'ca-ES': 'Català',
'cs-CZ': 'Čeština'
'cs-CZ': 'Čeština',
'uk-UA': 'Українська'
};

550
src/renderer/i18n/uk-UA.ts Normal file
View File

@@ -0,0 +1,550 @@
export const ukUA = {
general: { // Загальні терміни для загальних цілей
edit: 'Редагувати',
save: 'Зберегти',
close: 'Закрити',
delete: 'Видалити',
confirm: 'Підтвердити',
cancel: 'Скасувати',
send: 'Надіслати',
refresh: 'Оновити',
autoRefresh: 'Автоматичне оновлення',
version: 'Версія',
donate: 'Пожертвувати',
run: 'Запустити',
results: 'Результати',
size: 'Розмір',
mimeType: 'Тип MIME',
download: 'Завантажити',
add: 'Додати',
data: 'Дані',
properties: 'Властивості',
name: 'Назва',
clear: 'Очистити',
options: 'Параметри',
insert: 'Вставити',
discard: 'Відкинути',
stay: 'Залишити',
author: 'Автор',
upload: 'Завантажити',
browse: 'Переглянути',
content: 'Вміст',
cut: 'Вирізати',
copy: 'Копіювати',
paste: 'Вставити',
duplicate: 'Дублювати',
tools: 'Інструменти',
seconds: 'Секунди',
all: 'Усі',
new: 'Новий',
select: 'Вибрати',
change: 'Змінити',
include: 'Включити',
includes: 'Включає',
completed: 'Завершено',
aborted: 'Перервано',
disabled: 'Вимкнено',
enable: 'Увімкнути',
disable: 'Вимкнути',
contributors: 'Учасники',
pin: 'Закріпити',
unpin: 'Відкріпити',
folder: 'Папка | Папки',
none: 'Нічого',
singleQuote: 'Одинарна лапка',
doubleQuote: 'Подвійна лапка',
deleteConfirm: 'Ви підтверджуєте скасування',
uploadFile: 'Завантажити файл',
format: 'Формат', // Форматування коду
history: 'Історія',
filter: 'Фільтр',
manualValue: 'Власне значення',
selectAll: 'Вибрати все',
pageNumber: 'Номер сторінки',
directoryPath: 'Шлях до каталогу',
actionSuccessful: '{action} успішно виконано',
outputFormat: 'Формат виводу',
singleFile: 'Один файл {ext}',
zipCompressedFile: 'ZIP-стиснутий файл {ext}'
},
connection: { // Підключення до бази даних
connectionName: 'Назва підключення',
hostName: 'Ім"я хоста',
client: 'Клієнт',
port: 'Порт',
user: 'Користувач',
password: 'Пароль',
credentials: 'Облікові дані',
connect: 'Підключити',
connected: 'Підключено',
disconnect: 'Відключити',
disconnected: 'Відключено',
ssl: 'SSL',
enableSsl: 'Увімкнути SSL',
privateKey: 'Приватний ключ',
certificate: 'Сертифікат',
caCertificate: 'CA-сертифікат',
ciphers: 'Шифри',
untrustedConnection: 'Ненадійне підключення',
passphrase: 'Пароль до ключа',
sshTunnel: 'SSH-тунель',
enableSsh: 'Увімкнути SSH',
connectionString: 'Рядок підключення',
addConnection: 'Додати підключення',
createConnection: 'Створити підключення',
createNewConnection: 'Створити нове підключення',
askCredentials: 'Запитати облікові дані',
testConnection: 'Перевірити підключення',
editConnection: 'Редагувати підключення',
deleteConnection: 'Видалити підключення',
connectionSuccessfullyMade: 'Підключення успішно виконано!',
readOnlyMode: 'Режим тільки для читання',
allConnections: 'Усі підключення',
searchForConnections: 'Пошук підключень',
keepAliveInterval: 'Інтервал утримання зв"язку'
},
database: { // Терміни, пов'язані з базою даних
schema: 'Схема',
type: 'Тип',
insert: 'Вставити',
indexes: 'Індекси',
foreignKeys: 'Зовнішні ключі',
length: 'Довжина',
unsigned: 'Беззнаковий',
default: 'За замовчуванням',
comment: 'Коментар',
key: 'Ключ | Ключі',
order: 'Порядок',
expression: 'Вираз',
autoIncrement: 'Авто-інкремент',
engine: 'Двигун',
field: 'Поле | Поля',
approximately: 'Приблизно',
total: 'Загально',
table: 'Таблиця | Таблиці',
view: 'Вид | Види',
definer: 'Визначник',
algorithm: 'Алгоритм',
trigger: 'Тригер | Тригери',
storedRoutine: 'Збережена процедура | Збережені процедури',
scheduler: 'Планувальник | Планувальники',
event: 'Подія',
parameters: 'Параметри',
function: 'Функція | Функції',
deterministic: 'Детермінована',
context: 'Контекст',
export: 'Експорт',
import: 'Імпорт',
returns: 'Повертає',
timing: 'Часування',
state: 'Стан',
execution: 'Виконання',
starts: 'Починається',
ends: 'Закінчується',
variables: 'Змінні',
processes: 'Процеси',
database: 'База даних',
array: 'Масив',
structure: 'Структура',
row: 'Рядок | Рядки',
cell: 'Комірка | Комірки',
triggerFunction: 'Функція тригера | Функції тригера',
routine: 'Процедура | Процедури',
drop: 'Видалити',
commit: 'Закріпити',
rollback: 'Скасувати',
ddl: 'DDL',
collation: 'Колація',
resultsTable: 'Таблиця результатів',
unableEditFieldWithoutPrimary: 'Неможливо редагувати поле без первинного ключа в наборі результатів',
editCell: 'Редагувати комірку',
deleteRows: 'Видалити рядок | Видалити {count} рядків',
confirmToDeleteRows: 'Ви підтверджуєте видалення одного рядка? | Ви підтверджуєте видалення {count} рядків?',
addNewRow: 'Додати новий рядок',
numberOfInserts: 'Кількість вставок',
affectedRows: 'Підпадають під дію рядки',
createNewDatabase: 'Створити нову базу даних',
databaseName: 'Назва бази даних',
serverDefault: 'За замовчуванням на сервері',
deleteDatabase: 'Видалити базу даних',
editDatabase: 'Редагувати базу даних',
clearChanges: 'Скасувати зміни',
addNewField: 'Додати нове поле',
manageIndexes: 'Управління індексами',
manageForeignKeys: 'Управління зовнішніми ключами',
allowNull: 'Допускати NULL',
zeroFill: 'Заповнювати нулями',
customValue: 'Власне значення',
onUpdate: 'При оновленні',
deleteField: 'Видалити поле',
createNewIndex: 'Створити новий індекс',
addToIndex: 'Додати до індексу',
createNewTable: 'Створити нову таблицю',
emptyTable: 'Очистити таблицю',
duplicateTable: 'Дублювати таблицю',
deleteTable: 'Видалити таблицю',
exportTable: 'Експорт таблиці',
emptyConfirm: 'Ви підтверджуєте очищення',
thereAreNoIndexes: 'Немає індексів',
thereAreNoForeign: 'Немає зовнішніх ключів',
createNewForeign: 'Створити новий зовнішній ключ',
referenceTable: 'Таблиця посилання',
referenceField: 'Поле посилання',
foreignFields: 'Зовнішні поля',
invalidDefault: 'Недійсне значення за замовчуванням',
onDelete: 'При видаленні',
selectStatement: 'Оператор SELECT',
triggerStatement: 'Оператор тригера',
sqlSecurity: 'Безпека SQL',
updateOption: 'Опція оновлення',
deleteView: 'Видалити вид',
createNewView: 'Створити новий вид',
deleteTrigger: 'Видалити тригер',
createNewTrigger: 'Створити новий тригер',
currentUser: 'Поточний користувач',
routineBody: 'Тіло процедури',
dataAccess: 'Доступ до даних',
thereAreNoParameters: 'Немає параметрів',
createNewParameter: 'Створити новий параметр',
createNewRoutine: 'Створити нову збережену процедуру',
deleteRoutine: 'Видалити збережену процедуру',
functionBody: 'Тіло функції',
createNewFunction: 'Створити нову функцію',
deleteFunction: 'Видалити функцію',
schedulerBody: 'Тіло планувальника',
createNewScheduler: 'Створити новий планувальник',
deleteScheduler: 'Видалити планувальник',
preserveOnCompletion: 'Зберегти при завершенні',
tableFiller: 'Заповнювач таблиць',
fakeDataLanguage: 'Мова вигаданих даних',
queryDuration: 'Тривалість запиту',
setNull: 'Встановити NULL',
processesList: 'Список процесів',
processInfo: 'Інформація про процес',
manageUsers: 'Управління користувачами',
createNewSchema: 'Створити нову схему',
schemaName: 'Назва схеми',
editSchema: 'Редагувати схему',
deleteSchema: 'Видалити схему',
noSchema: 'Немає схеми',
runQuery: 'Виконати запит',
thereAreNoTableFields: 'Немає полів таблиці',
newTable: 'Нова таблиця',
newView: 'Новий вид',
newTrigger: 'Новий тригер',
newRoutine: 'Нова збережена процедура',
newFunction: 'Нова функція',
newScheduler: 'Новий планувальник',
newTriggerFunction: 'Нова функція тригера',
thereIsNoQueriesYet: 'Поки що немає запитів',
searchForQueries: 'Пошук запитів',
killProcess: 'Завершити процес',
exportSchema: 'Експорт схеми',
importSchema: 'Імпорт схеми',
newInsertStmtEvery: 'Новий оператор INSERT кожні',
processingTableExport: 'Обробка {table}',
fetchingTableExport: 'Отримання даних {table}',
writingTableExport: 'Запис даних {table}',
checkAllTables: 'Позначити всі таблиці',
uncheckAllTables: 'Зняти позначку з усіх таблиць',
killQuery: 'Завершити запит',
insertRow: 'Вставити рядок | Вставити рядки',
commitMode: 'Режим закріплення',
autoCommit: 'Автоматичне закріплення',
manualCommit: 'Ручне закріплення',
importQueryErrors: 'Попередження: сталася помилка: {n} помилка | Попередження: сталася помилка: {n} помилки',
executedQueries: '{n} виконаний запит | {n} виконаних запитів',
disableFKChecks: 'Вимкнути перевірку зовнішніх ключів',
formatQuery: 'Форматування запиту',
queryHistory: 'Історія запитів',
clearQuery: 'Очистити запит',
fillCell: 'Заповнити комірку',
executeSelectedQuery: 'Виконати вибраний запит',
noResultsPresent: 'Відсутні результати',
sqlExportOptions: 'Опції експорту SQL',
targetTable: 'Цільова таблиця',
switchDatabase: 'Перемкнути базу даних',
searchForElements: 'Пошук елементів',
searchForSchemas: 'Пошук схем'
},
application: { // Терміни, пов'язані з додатком
settings: 'Налаштування',
scratchpad: 'Блокнот',
disableScratchpad: 'Вимкнути блокнот',
console: 'Консоль',
general: 'Загальне',
themes: 'Теми',
update: 'Оновлення',
about: 'Про програму',
language: 'Мова',
shortcuts: 'Скорочення',
key: 'Клавіша | Клавіші', // Клавіша клавіатури
event: 'Подія',
light: 'Світлий',
dark: 'Темний',
autoCompletion: 'Автодоповнення',
application: 'Додаток',
editor: 'Редактор',
changelog: 'Журнал змін',
small: 'Маленький',
medium: 'Середній',
large: 'Великий',
appearance: 'Вигляд',
color: 'Колір',
label: 'Мітка',
icon: 'Іконка',
fileName: 'Ім"я файлу',
choseFile: 'Обрати файл',
data: 'Дані',
password: 'Пароль',
required: 'Обов"язково',
madeWithJS: 'Створено з 💛 і JavaScript!',
checkForUpdates: 'Перевірити оновлення',
noUpdatesAvailable: 'Оновлень немає',
checkingForUpdate: 'Перевірка оновлення',
checkFailure: 'Перевірка не вдалася, спробуйте пізніше',
updateAvailable: 'Доступно оновлення',
downloadingUpdate: 'Завантаження оновлення',
updateDownloaded: 'Оновлення завантажено',
restartToInstall: 'Перезапустіть Antares, щоб встановити',
includeBetaUpdates: 'Включити бета-оновлення',
notificationsTimeout: 'Таймаут сповіщень',
openNewTab: 'Відкрити нову вкладку',
unsavedChanges: 'Незбережені зміни',
discardUnsavedChanges: 'У вас є незбережені зміни. Закривши цю вкладку, ці зміни будуть скасовані.',
applicationTheme: 'Тема додатка',
editorTheme: 'Тема редактора',
wrapLongLines: 'Переносити довгі рядки',
markdownSupported: 'Підтримка Markdown',
plantATree: 'Посадити дерево',
dataTabPageSize: 'Розмір сторінки вкладки DATA',
noOpenTabs: 'Немає відкритих вкладок, перейдіть на панель зліва або:',
restorePreviousSession: 'Відновити попередню сесію',
closeTab: 'Закрити вкладку',
goToDownloadPage: 'Перейти на сторінку завантаження',
disableBlur: 'Вимкнути розмиття',
missingOrIncompleteTranslation: 'Відсутній або неповний переклад?',
findOutHowToContribute: 'Дізнайтеся, як внести свій внесок',
reportABug: 'Повідомити про помилку',
nextTab: 'Наступна вкладка',
previousTab: 'Попередня вкладка',
selectTabNumber: 'Вибрати вкладку номер {param}',
toggleConsole: 'Перемкнути консоль',
addShortcut: 'Додати скорочення',
editShortcut: 'Редагувати скорочення',
deleteShortcut: 'Видалити скорочення',
restoreDefaults: 'Відновити значення за замовчуванням',
restoreDefaultsQuestion: 'Ви підтверджуєте відновлення значень за замовчуванням?',
registerAShortcut: 'Зареєструвати скорочення',
invalidShortcutMessage: 'Недійсна комбінація, продовжте введення',
shortcutAlreadyExists: 'Скорочення вже існує',
saveContent: 'Зберегти вміст',
openAllConnections: 'Відкрити всі підключення',
openSettings: 'Відкрити налаштування',
openScratchpad: 'Відкрити блокнот',
runOrReload: 'Запустити або перезавантажити',
openFilter: 'Відкрити фільтр',
nextResultsPage: 'Наступна сторінка результатів',
previousResultsPage: 'Попередня сторінка результатів',
editFolder: 'Редагувати теку',
folderName: 'Назва теки',
deleteFolder: 'Видалити теку',
editConnectionAppearance: 'Редагувати вигляд підключення',
defaultCopyType: 'Тип копіювання за замовчуванням',
showTableSize: 'Показувати розмір таблиці в бічній панелі',
showTableSizeDescription: 'Тільки для MySQL/MariaDB. Увімкнення цієї опції може вплинути на продуктивність в схемах з багатьма таблицями.',
switchSearchMethod: 'Перемкнути метод пошуку',
phpArray: 'Масив PHP',
closeAllTabs: 'Закрити всі вкладки',
closeOtherTabs: 'Закрити інші вкладки',
closeTabsToLeft: 'Закрити вкладки ліворуч',
closeTabsToRight: 'Закрити вкладки праворуч',
csvFieldDelimiter: 'Роздільник полів для CSV',
csvLinesTerminator: 'Роздільник рядків для CSV',
csvStringDelimiter: 'Роздільник рядків для CSV',
csvIncludeHeader: 'Включити заголовок для CSV',
csvExportOptions: 'Опції експорту CSV',
exportData: 'Експорт даних',
exportDataExplanation: 'Експорт збережених підключень до Antares. Вам буде запропоновано ввести пароль для шифрування експортованого файлу.',
importData: 'Імпорт даних',
importDataExplanation: 'Імпорт файлу .antares, який містить підключення. Вам потрібно буде ввести пароль, встановлений під час експорту.',
includeConnectionPasswords: 'Включити паролі підключень',
includeFolders: 'Включити теки',
encryptionPassword: 'Пароль для шифрування',
encryptionPasswordError: 'Пароль для шифрування повинен містити щонайменше 8 символів.',
ignoreDuplicates: 'Ігнорувати дублікати',
wrongImportPassword: 'Неправильний пароль для імпорту',
wrongFileFormat: 'Неправильний формат файлу',
dataImportSuccess: 'Дані успішно імпортовано'
},
faker: { // Методи Faker.js, використовувані в випадково згенерованому вмісті
address: 'Адреса',
commerce: 'Комерція',
company: 'Компанія',
database: 'База даних',
date: 'Дата',
finance: 'Фінанси',
git: 'Git',
hacker: 'Хакер',
internet: 'Інтернет',
lorem: 'Lorem',
name: 'Ім"я',
music: 'Музика',
phone: 'Телефон',
random: 'Випадково',
system: 'Система',
time: 'Час',
vehicle: 'Транспортний засіб',
zipCode: 'Поштовий індекс',
zipCodeByState: 'Поштовий індекс за станом',
city: 'Місто',
cityPrefix: 'Префікс міста',
citySuffix: 'Суфікс міста',
streetName: 'Назва вулиці',
streetAddress: 'Адреса вулиці',
streetSuffix: 'Суфікс вулиці',
streetPrefix: 'Префікс вулиці',
secondaryAddress: 'Додаткова адреса',
county: 'Округ',
country: 'Країна',
countryCode: 'Код країни',
state: 'Штат',
stateAbbr: 'Скорочення назви штату',
latitude: 'Широта',
longitude: 'Довгота',
direction: 'Напрям',
cardinalDirection: 'Кардинальний напрям',
ordinalDirection: 'Ординальний напрям',
nearbyGPSCoordinate: 'Ближча координата GPS',
timeZone: 'Часовий пояс',
color: 'Колір',
department: 'Відділ',
productName: 'Назва продукту',
price: 'Ціна',
productAdjective: 'Прикметник продукту',
productMaterial: 'Матеріал продукту',
product: 'Продукт',
productDescription: 'Опис продукту',
suffixes: 'Суфікси',
companyName: 'Назва компанії',
companySuffix: 'Суфікс компанії',
catchPhrase: 'Захоплива фраза',
bs: 'БС',
catchPhraseAdjective: 'Прикметник захопливої фрази',
catchPhraseDescriptor: 'Опис захопливої фрази',
catchPhraseNoun: 'Іменник захопливої фрази',
bsAdjective: 'Прикметник БС',
bsBuzz: 'БС буз',
bsNoun: 'Іменник БС',
column: 'Стовпець',
type: 'Тип',
collation: 'Спільність',
engine: 'Двигун',
past: 'Минуле',
now: 'Зараз',
future: 'Майбутнє',
between: 'Між',
recent: 'Останнє',
soon: 'Незабаром',
month: 'Місяць',
weekday: 'День тижня',
account: 'Рахунок',
accountName: 'Назва рахунку',
routingNumber: 'Номер маршрутизації',
mask: 'Маска',
amount: 'Сума',
transactionType: 'Тип транзакції',
currencyCode: 'Код валюти',
currencyName: 'Назва валюти',
currencySymbol: 'Символ валюти',
bitcoinAddress: 'Адреса Bitcoin',
litecoinAddress: 'Адреса Litecoin',
creditCardNumber: 'Номер кредитної картки',
creditCardCVV: 'CVV кредитної картки',
ethereumAddress: 'Адреса Ethereum',
iban: 'IBAN',
bic: 'BIC',
transactionDescription: 'Опис транзакції',
branch: 'Відділення',
commitEntry: 'Запис коміту',
commitMessage: 'Повідомлення коміту',
commitSha: 'SHA коміту',
shortSha: 'Короткий SHA',
abbreviation: 'Абревіатура',
adjective: 'Прикметник',
noun: 'Іменник',
verb: 'Дієслово',
ingverb: 'Дієприкметник',
phrase: 'Фраза',
avatar: 'Аватар',
email: 'Електронна пошта',
exampleEmail: 'Приклад електронної пошти',
userName: 'Ім"я користувача',
protocol: 'Протокол',
url: 'URL',
domainName: 'Ім"я домену',
domainSuffix: 'Суфікс домену',
domainWord: 'Слово домену',
ip: 'IP-адреса',
ipv6: 'IPv6',
userAgent: 'User-Agent',
mac: 'MAC-адреса',
password: 'Пароль',
word: 'Слово',
words: 'Слова',
sentence: 'Речення',
slug: 'URL-посилання',
sentences: 'Речення',
paragraph: 'Абзац',
paragraphs: 'Абзаци',
text: 'Текст',
lines: 'Рядки',
genre: 'Жанр',
firstName: 'Ім"я',
lastName: 'Прізвище',
middleName: 'По батькові',
findName: 'Повне ім\'я',
jobTitle: 'Посада',
gender: 'Стать',
prefix: 'Префікс',
suffix: 'Суфікс',
title: 'Заголовок',
jobDescriptor: 'Опис посади',
jobArea: 'Сфера діяльності',
jobType: 'Тип посади',
phoneNumber: 'Номер телефону',
phoneNumberFormat: 'Формат номеру телефону',
phoneFormats: 'Формати номерів телефону',
number: 'Число',
float: 'Дійсне число',
arrayElement: 'Елемент масиву',
arrayElements: 'Елементи масиву',
objectElement: 'Елемент об"єкта',
uuid: 'UUID',
boolean: 'Логічний тип',
image: 'Зображення',
locale: 'Локаль',
alpha: 'Літера',
alphaNumeric: 'Літера або число',
hexaDecimal: 'Шістнадцяткове число',
fileName: 'Назва файлу',
commonFileName: 'Загальна назва файлу',
mimeType: 'MIME-тип',
commonFileType: 'Загальний тип файлу',
commonFileExt: 'Загальний розширення файлу',
fileType: 'Тип файлу',
fileExt: 'Розширення файлу',
directoryPath: 'Шлях до каталогу',
filePath: 'Шлях до файлу',
semver: 'Семантичний номер версії',
manufacturer: 'Виробник',
model: 'Модель',
fuel: 'Паливо',
vin: 'VIN'
}
};

View File

@@ -1,5 +1,5 @@
export const zhCN = {
general: {
general: { // 通用术语
edit: '编辑',
save: '保存',
close: '关闭',
@@ -13,17 +13,16 @@ export const zhCN = {
donate: '捐赠',
run: '运行',
results: '结果',
size: '尺寸',
size: '大小',
mimeType: 'MIME类型',
download: '下载',
add: '新增',
data: '数据',
properties: '属性',
insert: '插入',
name: '名称',
clear: '清除',
seconds: '秒',
options: '选项',
insert: '插入',
discard: '丢弃',
stay: '等待',
author: '作者',
@@ -33,27 +32,32 @@ export const zhCN = {
cut: '剪切',
copy: '复制',
paste: '粘贴',
tools: '工具',
format: '格式',
all: '全部',
duplicate: '重复',
tools: '工具',
seconds: '秒',
all: '全部',
new: '新',
history: '历史',
select: '选择',
filter: '过滤器',
change: '变更',
include: '包含',
includes: '包含',
completed: '已完成',
aborted: '中止',
disabled: '禁用',
enable: '启',
enable: '启',
disable: '禁用',
contributors: '贡献者',
pin: '固定',
unpin: '取消固定',
folder: '文件夹 | 文件夹',
none: '无',
singleQuote: '单引号',
doubleQuote: '双引号',
deleteConfirm: '您是否确认取消',
uploadFile: '上传文件',
format: '格式码', // 格式码
history: '历史',
filter: '过滤器',
manualValue: '手动值',
selectAll: '选择全部',
pageNumber: '页数',
@@ -63,10 +67,10 @@ export const zhCN = {
singleFile: '单个 {ext} 文件',
zipCompressedFile: 'ZIP 压缩 {ext} 文件'
},
connection: {
connection: { // 数据库连接
connectionName: '连接名称',
client: '数据库类型',
hostName: '主机名',
client: '数据库类型',
port: '端口',
user: '用户',
password: '密码',
@@ -76,12 +80,15 @@ export const zhCN = {
disconnect: '断开连接',
disconnected: '断开连接',
ssl: 'SSL',
enableSsl: '启用 SSL',
privateKey: '私钥',
certificate: '证书',
caCertificate: 'CA 证书',
ciphers: '密码',
sshTunnel: 'SSH 隧道',
untrustedConnection: '不受信任的连接',
passphrase: '密码短语',
sshTunnel: 'SSH 隧道',
enableSsh: '启用 SSH',
connectionString: '连接字符串',
addConnection: '添加连接',
createConnection: '创建连接',
@@ -91,23 +98,22 @@ export const zhCN = {
editConnection: '编辑连接',
deleteConnection: '删除连接',
connectionSuccessfullyMade: '连接成功了!',
enableSsl: '启用 SSL',
enableSsh: '启用 SSH',
readOnlyMode: '只读模式',
untrustedConnection: '不受信任的连接',
allConnections: '所有连接',
searchForConnections: '搜索连接'
searchForConnections: '搜索连接',
keepAliveInterval: '保持活跃间隔'
},
database: {
database: { // 数据库相关术语
schema: '模式(schema)',
type: '类型',
insert: '插入',
indexes: '索引',
foreignKeys: '外键',
length: '长度',
unsigned: '无符号',
default: '默认',
comment: '注释',
collation: '排序规则',
key: '键位 | 键位',
key: '键 | 键',
order: '排序',
expression: '表达式',
autoIncrement: '自动增量',
@@ -115,9 +121,8 @@ export const zhCN = {
field: '字段 | 字段',
approximately: '大约',
total: '总计',
table: '表',
view: '视图',
indexes: '索引',
table: '表 | 表',
view: '视图 | 视图',
definer: '定义者',
algorithm: '算法',
trigger: '触发器 | 触发器',
@@ -139,16 +144,18 @@ export const zhCN = {
variables: '变量',
processes: '进程',
database: '数据库',
array: '数',
array: '数',
structure: '结构',
row: '行 | 行',
cell: '单元格 | 单元格',
triggerFunction: '触发函数 | 触发函数',
routine: '例程',
triggerFunction: '触发函数 | 触发函数',
routine: '例程 | 例程',
drop: '丢弃',
commit: '提交',
rollback: '回滚',
ddl: '数据定义语言',
collation: '排序规则',
resultsTable: '结果表',
drop: '下降',
unableEditFieldWithoutPrimary: '无法编辑结果集中一个没有主键的字段',
editCell: '编辑单元格',
deleteRows: '删除行 | 删除 {count} 行',
@@ -161,7 +168,7 @@ export const zhCN = {
serverDefault: '默认服务器',
deleteDatabase: '删除数据库',
editDatabase: '编辑数据库',
clearChanges: '清除更',
clearChanges: '清除更',
addNewField: '添加新字段',
manageIndexes: '管理索引',
manageForeignKeys: '管理外键',
@@ -174,7 +181,9 @@ export const zhCN = {
addToIndex: '添加到索引',
createNewTable: '创建新表',
emptyTable: '清空表',
duplicateTable: '重复表',
deleteTable: '删除表',
exportTable: '导出表',
emptyConfirm: '您是否确认清空',
thereAreNoIndexes: '没有索引',
thereAreNoForeign: '没有外键',
@@ -182,7 +191,7 @@ export const zhCN = {
referenceTable: '参考表',
referenceField: '参考字段',
foreignFields: '外键字段',
invalidDefault: '无效默认值',
invalidDefault: '无效默认值',
onDelete: '在删除',
selectStatement: '选择语句',
triggerStatement: '触发器语句',
@@ -205,10 +214,10 @@ export const zhCN = {
schedulerBody: '调度器主体',
createNewScheduler: '创建新调度器',
deleteScheduler: '删除调度器',
preserveOnCompletion: '完成时保',
preserveOnCompletion: '完成时保',
tableFiller: '表填充器',
fakeDataLanguage: '伪造的数据语言',
queryDuration: '查询时间',
queryDuration: '查询持续时间',
setNull: '设置 NULL',
processesList: '进程列表',
processInfo: '进程信息',
@@ -217,7 +226,6 @@ export const zhCN = {
schemaName: '模式名称',
editSchema: '编辑模式',
deleteSchema: '删除模式',
duplicateTable: '重复的表',
noSchema: '没有模式',
runQuery: '运行查询',
thereAreNoTableFields: '没有表的字段',
@@ -227,7 +235,7 @@ export const zhCN = {
newRoutine: '新例程',
newFunction: '新函数',
newScheduler: '新调度器',
newTriggerFunction: '新触发函数',
newTriggerFunction: '新触发函数',
thereIsNoQueriesYet: '目前还没有任何查询',
searchForQueries: '搜索查询',
killProcess: '终止进程',
@@ -237,45 +245,59 @@ export const zhCN = {
processingTableExport: '处理 {table}',
fetchingTableExport: '正在获取 {table} 数据',
writingTableExport: '正在写入 {table} 数据',
checkAllTables: '勾选所有表',
uncheckAllTables: '不勾选所有表',
killQuery: '取消查询',
insertRow: '插入行 | 插入多行',
checkAllTables: '检查所有表',
uncheckAllTables: '不检查所有表',
killQuery: '终止查询',
insertRow: '插入行 | 插入多行',
commitMode: '提交模式',
autoCommit: '自动提交',
manualCommit: '手动提交',
importQueryErrors: '警告: 发生了 {n} 个错误 | 警告: 发生了 {n} 个错误',
executedQueries: '{n} 个查询已执行 | {n} 个查询已执行',
disableFKChecks: '禁用外键检查',
formatQuery: '格式查询',
queryHistory: '查询历史',
clearQuery: '清除查询',
fillCell: '填充单元格',
executeSelectedQuery: '执行所选查询',
importQueryErrors: '警告: 发生了 {n} 个错误 | 警告: 发生了 {n} 个错误',
executedQueries: '{n} 个查询已执行 | {n} 个查询已执行'
noResultsPresent: '没有结果',
sqlExportOptions: 'SQL 导出选项',
targetTable: '目标表',
switchDatabase: '切换数据库',
searchForElements: '搜索元素',
searchForSchemas: '搜索模式(schema)'
},
application: {
application: { // 应用程序相关术语
settings: '设置',
scratchpad: '草稿栏',
disableScratchpad: '禁用草稿栏',
console: '控制台',
general: '常规',
themes: '主题',
update: '更新',
about: '关于',
language: '语言',
shortcuts: '快捷方式',
key: '按键 | 按键', // 键盘按键
event: '事件',
light: '明亮',
dark: '暗黑',
autoCompletion: '自动完成',
application: '应用程序',
editor: '编辑器',
scratchpad: '草稿栏',
changelog: '变更日志',
small: '小',
medium: '中',
large: '大',
console: '控制台',
shortcuts: '快捷键',
appearance: '外观',
color: '颜色',
label: '标签',
icon: '图标',
fileName: '文件名称',
choseFile: '选择文件',
data: '数据',
password: '密码',
required: '依赖',
madeWithJS: '使用 💛 和 JavaScript 制作!',
checkForUpdates: '检查更新',
noUpdatesAvailable: '无可用更新',
@@ -285,14 +307,14 @@ export const zhCN = {
downloadingUpdate: '正在下载更新',
updateDownloaded: '已下载更新',
restartToInstall: '重启 Antares 以进行安装',
includeBetaUpdates: '包含测试版更新',
notificationsTimeout: '通知超时',
openNewTab: '打开一个新标签',
unsavedChanges: '未保存的更',
discardUnsavedChanges: '您有一些未保存的更, 关闭此标签将放弃这些更.',
unsavedChanges: '未保存的更',
discardUnsavedChanges: '您有一些未保存的更, 关闭此标签将放弃这些更.',
applicationTheme: '应用程序主题',
editorTheme: '编辑器主题',
wrapLongLines: '将长行换行显示',
includeBetaUpdates: '包含测试版的更新',
markdownSupported: '支持 Markdown',
plantATree: '种植一棵树',
dataTabPageSize: '数据标签的页面大小',
@@ -303,22 +325,21 @@ export const zhCN = {
disableBlur: '禁用模糊',
missingOrIncompleteTranslation: '有缺失或不完整的翻译?',
findOutHowToContribute: '了解如何做出贡献',
disableScratchpad: '禁用草稿栏',
reportABug: '报告错误',
nextTab: '下一个标签',
previousTab: '上一个标签',
selectTabNumber: '选择标签编号 {param}',
toggleConsole: '切换控制台',
addShortcut: '添加快捷',
editShortcut: '编辑快捷',
deleteShortcut: '删除快捷',
restoreDefaults: '恢复默认',
addShortcut: '添加快捷方式',
editShortcut: '编辑快捷方式',
deleteShortcut: '删除快捷方式',
restoreDefaults: '恢复默认',
restoreDefaultsQuestion: '是否确认恢复默认值?',
registerAShortcut: '注册快捷',
invalidShortcutMessage: '无效组合,请继续入',
shortcutAlreadyExists: '快捷键已经存在',
registerAShortcut: '注册快捷方式',
invalidShortcutMessage: '无效组合,请继续入',
shortcutAlreadyExists: '快捷方式已存在',
saveContent: '保存内容',
openAllConnections: '打开全部连接',
openAllConnections: '打开所有连接',
openSettings: '打开设置',
openScratchpad: '打开草稿栏',
runOrReload: '运行或重新加载',
@@ -332,9 +353,31 @@ export const zhCN = {
defaultCopyType: '默认复制类型',
showTableSize: '在侧边栏显示表大小',
showTableSizeDescription: '仅限 MySQL/MariaDB. 启用此选项可能会影响许多表的模式(schema)的性能.',
searchForElements: '搜索元素'
switchSearchMethod: '切换搜索方法',
phpArray: 'PHP 数组',
closeAllTabs: '关闭所有标签',
closeOtherTabs: '关闭其他标签',
closeTabsToLeft: '关闭左侧的标签',
closeTabsToRight: '关闭右侧的标签',
csvFieldDelimiter: '字段分隔符',
csvLinesTerminator: '行终止符',
csvStringDelimiter: '字符串分隔符',
csvIncludeHeader: '包含页眉',
csvExportOptions: 'CSV 导出选项',
exportData: '导出数据',
exportDataExplanation: '将保存的连接导出到 Antares. 系统将要求您输入密码以加密导出的文件.',
importData: '导入数据',
importDataExplanation: '导入包含连接的 .antares 文件. 您需要输入在导出过程中定义的密码.',
includeConnectionPasswords: '包含连接密码',
includeFolders: '包含文件夹',
encryptionPassword: '加密密码',
encryptionPasswordError: '加密密码的长度必须至少为 8 个字符.',
ignoreDuplicates: '忽略重复',
wrongImportPassword: '错误的导入密码',
wrongFileFormat: '错误的文件格式',
dataImportSuccess: '数据已成功导入'
},
faker: {
faker: { // Faker.js 方法,用于随机生成的内容
address: '地址',
commerce: '商业',
company: '公司',

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 7A2 2 0 0 0 1 9V17H3V13H5V17H7V9A2 2 0 0 0 5 7H3M3 9H5V11H3M15 10.5V9A2 2 0 0 0 13 7H9V17H13A2 2 0 0 0 15 15V13.5A1.54 1.54 0 0 0 13.5 12A1.54 1.54 0 0 0 15 10.5M13 15H11V13H13V15M13 11H11V9H13M19 7A2 2 0 0 0 17 9V15A2 2 0 0 0 19 17H21A2 2 0 0 0 23 15V14H21V15H19V9H21V10H23V9A2 2 0 0 0 21 7Z" /></svg>

After

Width:  |  Height:  |  Size: 374 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3,19V5A2,2 0 0,1 5,3H19A2,2 0 0,1 21,5V19A2,2 0 0,1 19,21H5A2,2 0 0,1 3,19M17,12L12,7V10H8V14H12V17L17,12Z" /></svg>

After

Width:  |  Height:  |  Size: 186 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15,13H16.5V15.82L18.94,17.23L18.19,18.53L15,16.69V13M19,8H5V19H9.67C9.24,18.09 9,17.07 9,16A7,7 0 0,1 16,9C17.07,9 18.09,9.24 19,9.67V8M5,21C3.89,21 3,20.1 3,19V5C3,3.89 3.89,3 5,3H6V1H8V3H16V1H18V3H19A2,2 0 0,1 21,5V11.1C22.24,12.36 23,14.09 23,16A7,7 0 0,1 16,23C14.09,23 12.36,22.24 11.1,21H5M16,11.15A4.85,4.85 0 0,0 11.15,16C11.15,18.68 13.32,20.85 16,20.85A4.85,4.85 0 0,0 20.85,16C20.85,13.32 18.68,11.15 16,11.15Z" /></svg>

After

Width:  |  Height:  |  Size: 501 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" /></svg>

After

Width:  |  Height:  |  Size: 155 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z" /></svg>

After

Width:  |  Height:  |  Size: 339 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L6.04,7.5L12,10.85L17.96,7.5L12,4.15Z" /></svg>

After

Width:  |  Height:  |  Size: 412 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2C11.5 2 11 2.19 10.59 2.59L2.59 10.59C1.8 11.37 1.8 12.63 2.59 13.41L10.59 21.41C11.37 22.2 12.63 22.2 13.41 21.41L21.41 13.41C22.2 12.63 22.2 11.37 21.41 10.59L13.41 2.59C13 2.19 12.5 2 12 2M12 4L15.29 7.29L12 10.59L8.71 7.29L12 4M7.29 8.71L10.59 12L7.29 15.29L4 12L7.29 8.71M16.71 8.71L20 12L16.71 15.29L13.41 12L16.71 8.71M12 13.41L15.29 16.71L12 20L8.71 16.71L12 13.41Z" /></svg>

After

Width:  |  Height:  |  Size: 457 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M2 12A10 10 0 1 0 12 2A10 10 0 0 0 2 12M15.6 13.72A4 4 0 0 0 16 12A4 4 0 0 0 12 8V10L8.88 7L12 4V6A6 6 0 0 1 18 12A5.9 5.9 0 0 1 17.07 15.19M6 12A5.9 5.9 0 0 1 6.93 8.81L8.4 10.28A4 4 0 0 0 8 12A4 4 0 0 0 12 16V14L15 17L12 20V18A6 6 0 0 1 6 12Z" /></svg>

After

Width:  |  Height:  |  Size: 323 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 3H17C18.11 3 19 3.9 19 5V12.08C17.45 11.82 15.92 12.18 14.68 13H11V17H12.08C11.97 17.68 11.97 18.35 12.08 19H3C1.9 19 1 18.11 1 17V5C1 3.9 1.9 3 3 3M3 7V11H9V7H3M11 7V11H17V7H11M3 13V17H9V13H3M22.78 19.32L21.71 18.5C21.73 18.33 21.75 18.17 21.75 18S21.74 17.67 21.71 17.5L22.77 16.68C22.86 16.6 22.89 16.47 22.83 16.36L21.83 14.63C21.77 14.5 21.64 14.5 21.5 14.5L20.28 15C20 14.82 19.74 14.65 19.43 14.53L19.24 13.21C19.23 13.09 19.12 13 19 13H17C16.88 13 16.77 13.09 16.75 13.21L16.56 14.53C16.26 14.66 15.97 14.82 15.71 15L14.47 14.5C14.36 14.5 14.23 14.5 14.16 14.63L13.16 16.36C13.1 16.47 13.12 16.6 13.22 16.68L14.28 17.5C14.26 17.67 14.25 17.83 14.25 18S14.26 18.33 14.28 18.5L13.22 19.32C13.13 19.4 13.1 19.53 13.16 19.64L14.16 21.37C14.22 21.5 14.35 21.5 14.47 21.5L15.71 21C15.97 21.18 16.25 21.35 16.56 21.47L16.75 22.79C16.77 22.91 16.87 23 17 23H19C19.12 23 19.23 22.91 19.25 22.79L19.44 21.47C19.74 21.34 20 21.18 20.28 21L21.5 21.5C21.64 21.5 21.77 21.5 21.84 21.37L22.84 19.64C22.9 19.53 22.87 19.4 22.78 19.32M18 19.5C17.17 19.5 16.5 18.83 16.5 18S17.18 16.5 18 16.5 19.5 17.17 19.5 18 18.84 19.5 18 19.5Z" /></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 16.88C17.56 16.88 18 17.32 18 17.88S17.56 18.88 17 18.88 16 18.43 16 17.88 16.44 16.88 17 16.88M17 13.88C19.73 13.88 22.06 15.54 23 17.88C22.06 20.22 19.73 21.88 17 21.88S11.94 20.22 11 17.88C11.94 15.54 14.27 13.88 17 13.88M17 15.38C15.62 15.38 14.5 16.5 14.5 17.88S15.62 20.38 17 20.38 19.5 19.26 19.5 17.88 18.38 15.38 17 15.38M18 3H4C2.9 3 2 3.9 2 5V17C2 18.1 2.9 19 4 19H9.42C9.26 18.68 9.12 18.34 9 18C9.12 17.66 9.26 17.32 9.42 17H4V13H10V15.97C10.55 15.11 11.23 14.37 12 13.76V13H13.15C14.31 12.36 15.62 12 17 12C18.06 12 19.07 12.21 20 12.59V5C20 3.9 19.1 3 18 3M10 11H4V7H10V11M18 11H12V7H18V11Z" /></svg>

After

Width:  |  Height:  |  Size: 688 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5,4H19A2,2 0 0,1 21,6V18A2,2 0 0,1 19,20H5A2,2 0 0,1 3,18V6A2,2 0 0,1 5,4M5,8V12H11V8H5M13,8V12H19V8H13M5,14V18H11V14H5M13,14V18H19V14H13Z" /></svg>

After

Width:  |  Height:  |  Size: 218 B

View File

@@ -1,5 +1,4 @@
'use strict';
import '@mdi/font/css/materialdesignicons.css';
import 'floating-vue/dist/style.css';
import 'leaflet/dist/leaflet.css';
import '@/scss/main.scss';

View File

@@ -0,0 +1,7 @@
/**
* Copy a string on clipboard
* @param text
*/
export const copyText = (text: string) => {
navigator.clipboard.writeText(text);
};

View File

@@ -1227,42 +1227,42 @@ ace.define('ace/autocomplete/popup', ['require', 'exports', 'module', 'ace/virtu
switch (meta) {
case 'table':
iconClass = 'mdi-table';
iconClass = 'editor-icon-table';
break;
case 'column':
iconClass = 'mdi-rhombus-split-outline';
iconClass = 'editor-icon-rhombus-split-outline';
break;
case 'view':
iconClass = 'mdi-table-eye';
iconClass = 'editor-icon-table-eye';
break;
case 'trigger':
iconClass = 'mdi-table-cog';
iconClass = 'editor-icon-table-cog';
break;
case 'routine':
iconClass = 'mdi-sync-circle';
iconClass = 'editor-icon-sync-circle';
break;
case 'function':
iconClass = 'mdi-arrow-right-bold-box';
iconClass = 'editor-icon-arrow-right-bold-box';
break;
case 'scheduler':
iconClass = 'mdi-calendar-clock';
iconClass = 'editor-icon-calendar-clock';
break;
case 'keyword':
iconClass = 'mdi-cube';
iconClass = 'editor-icon-cube';
break;
case 'snippet':
iconClass = 'mdi-code-braces';
iconClass = 'editor-icon-code-braces';
break;
case 'local':
iconClass = 'mdi-alphabetical-variant';
iconClass = 'editor-icon-alphabetical-variant';
break;
default:
iconClass = 'mdi-circle';
iconClass = 'editor-icon-circle';
break;
}
iconClass && tokens.push({
type: ` mdi ${iconClass}`,
type: ` editor-icon ${iconClass}`,
value: ' '
});
}

View File

@@ -0,0 +1,67 @@
/* stylelint-disable selector-class-pattern */
/* Only used in ext-language_tools.js */
.editor-icon {
display: inline-block;
width: 17px;
height: 17px;
background-size: cover;
position: relative;
top: 2px;
margin-right: 1px;
opacity: 0.7;
&.editor-icon-table {
background-image: url("../images/svg/table.svg");
}
&.editor-icon-rhombus-split-outline {
background-image: url("../images/svg/rhombus-split-outline.svg");
}
&.editor-icon-table-eye {
background-image: url("../images/svg/table-eye.svg");
}
&.editor-icon-table-cog {
background-image: url("../images/svg/table-cog.svg");
}
&.editor-icon-sync-circle {
background-image: url("../images/svg/sync-circle.svg");
}
&.editor-icon-arrow-right-bold-box {
background-image: url("../images/svg/arrow-right-bold-box.svg");
}
&.editor-icon-calendar-clock {
background-image: url("../images/svg/calendar-clock.svg");
}
&.editor-icon-cube {
background-image: url("../images/svg/cube.svg");
}
&.editor-icon-code-braces {
background-image: url("../images/svg/code-braces.svg");
}
&.editor-icon-alphabetical-variant {
background-image: url("../images/svg/alphabetical-variant.svg");
}
&.editor-icon-circle {
background-image: url("../images/svg/circle.svg");
}
&::before {
line-height: 1;
}
}
.ace_dark {
.editor-icon {
filter: invert(100%);
}
}

View File

@@ -1,9 +0,0 @@
.mdi {
display: flex;
align-items: center;
justify-content: center;
&::before {
line-height: 1;
}
}

View File

@@ -5,7 +5,7 @@
@import "data-types";
@import "table-keys";
@import "fake-tables";
@import "mdi-additions";
@import "editor-icons";
@import "db-icons";
@import "themes/dark-theme";
@import "themes/light-theme";

View File

@@ -1,11 +1,12 @@
import { ConnectionParams } from 'common/interfaces/antares';
import { uidGen } from 'common/libs/uidGen';
import * as crypto from 'crypto';
import { ipcRenderer } from 'electron';
import * as Store from 'electron-store';
import { defineStore } from 'pinia';
import { useWorkspacesStore } from '@/stores/workspaces';
const key = localStorage.getItem('key');
let key = localStorage.getItem('key');
export interface SidebarElement {
isFolder: boolean;
@@ -17,10 +18,21 @@ export interface SidebarElement {
icon?: null | string;
}
if (!key)
localStorage.setItem('key', crypto.randomBytes(16).toString('hex'));
if (!key) { // If no key in local storace
const storedKey = ipcRenderer.sendSync('get-key');// Ask for key stored on disk
if (!storedKey) { // Of nop stored key on disk
const newKey = crypto.randomBytes(16).toString('hex');
localStorage.setItem('key', newKey);
key = newKey;
}
else {
localStorage.setItem('key', storedKey);
key = storedKey;
}
}
else
localStorage.setItem('key', key);
ipcRenderer.send('set-key', key);
const persistentStore = new Store({
name: 'connections',

View File

@@ -2,9 +2,18 @@ import * as Store from 'electron-store';
import { defineStore } from 'pinia';
const persistentStore = new Store({ name: 'notes' });
export interface ConnectionNote {
uid: string;
note: string;
date: Date;
}
export const useScratchpadStore = defineStore('scratchpad', {
state: () => ({
notes: persistentStore.get('notes', '# HOW TO SUPPORT ANTARES\n\n- [ ] Leave a star to Antares [GitHub repo](https://github.com/antares-sql/antares)\n- [ ] Send feedbacks and advices\n- [ ] Report for bugs\n- [ ] If you enjoy, share Antares with friends\n\n# ABOUT SCRATCHPAD\n\nThis is a scratchpad where you can save your **personal notes**. It supports `markdown` format, but you are free to use plain text.\nThis content is just a placeholder, feel free to clear it to make space for your notes.\n') as string
/** Global notes */
notes: persistentStore.get('notes', '# HOW TO SUPPORT ANTARES\n\n- [ ] Leave a star to Antares [GitHub repo](https://github.com/antares-sql/antares)\n- [ ] Send feedbacks and advices\n- [ ] Report for bugs\n- [ ] If you enjoy, share Antares with friends\n\n# ABOUT SCRATCHPAD\n\nThis is a scratchpad where you can save your **personal notes**. It supports `markdown` format, but you are free to use plain text.\nThis content is just a placeholder, feel free to clear it to make space for your notes.\n') as string,
/** Connection specific notes */
connectionNotes: persistentStore.get('connectionNotes', {}) as {[k: string]: ConnectionNote}
}),
actions: {
changeNotes (notes: string) {

View File

@@ -4,109 +4,109 @@ declare module '@/App.vue';
declare module 'v-mask';
declare module 'json2php';
declare module 'vuedraggable' {// <- to export as default
const draggableComponent: import('vue').DefineComponent<{
list: {
type: ArrayConstructor;
required: boolean;
default: any;
};
modelValue: {
type: ArrayConstructor;
required: boolean;
default: any;
};
itemKey: {
type: (FunctionConstructor | StringConstructor)[];
required: boolean;
};
clone: {
type: FunctionConstructor;
default: (original: any) => any;
};
tag: {
type: StringConstructor;
default: string;
};
move: {
type: FunctionConstructor;
default: any;
};
componentData: {
type: ObjectConstructor;
required: boolean;
default: any;
};
const draggableComponent: import('vue').DefineComponent<{
list: {
type: ArrayConstructor;
required: boolean;
default: any;
};
modelValue: {
type: ArrayConstructor;
required: boolean;
default: any;
};
itemKey: {
type: (FunctionConstructor | StringConstructor)[];
required: boolean;
};
clone: {
type: FunctionConstructor;
default: (original: any) => any;
};
tag: {
type: StringConstructor;
default: string;
};
move: {
type: FunctionConstructor;
default: any;
};
componentData: {
type: ObjectConstructor;
required: boolean;
default: any;
};
}, unknown, {
error: boolean;
error: boolean;
}, {
realList(): any;
getKey(): any;
realList(): any;
getKey(): any;
}, {
getUnderlyingVm(domElement: any): any;
getUnderlyingPotencialDraggableComponent(htmElement: any): any;
emitChanges(evt: any): void;
alterList(onList: any): void;
spliceList(): void;
updatePosition(oldIndex: any, newIndex: any): void;
getRelatedContextFromMoveEvent({ to, related }: {
to: any;
related: any;
}): any;
getVmIndexFromDomIndex(domIndex: any): any;
onDragStart(evt: any): void;
onDragAdd(evt: any): void;
onDragRemove(evt: any): void;
onDragUpdate(evt: any): void;
computeFutureIndex(relatedContext: any, evt: any): any;
onDragMove(evt: any, originalEvent: any): any;
onDragEnd(): void;
getUnderlyingVm(domElement: any): any;
getUnderlyingPotencialDraggableComponent(htmElement: any): any;
emitChanges(evt: any): void;
alterList(onList: any): void;
spliceList(): void;
updatePosition(oldIndex: any, newIndex: any): void;
getRelatedContextFromMoveEvent({ to, related }: {
to: any;
related: any;
}): any;
getVmIndexFromDomIndex(domIndex: any): any;
onDragStart(evt: any): void;
onDragAdd(evt: any): void;
onDragRemove(evt: any): void;
onDragUpdate(evt: any): void;
computeFutureIndex(relatedContext: any, evt: any): any;
onDragMove(evt: any, originalEvent: any): any;
onDragEnd(): void;
}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, any[], any, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<{
move: Function;
tag: string;
clone: Function;
list: unknown[];
modelValue: unknown[];
componentData: Record<string, any>;
move: Function;
tag: string;
clone: Function;
list: unknown[];
modelValue: unknown[];
componentData: Record<string, any>;
} & {
itemKey?: string | Function;
itemKey?: string | Function;
}>, {
move: Function;
tag: string;
clone: Function;
list: unknown[];
modelValue: unknown[];
componentData: Record<string, any>;
move: Function;
tag: string;
clone: Function;
list: unknown[];
modelValue: unknown[];
componentData: Record<string, any>;
}>;
export = draggableComponent;
export = draggableComponent;
}
declare const SvgIcon: import('vue').DefineComponent<{
type: {
type: StringConstructor;
default: string;
};
path: {
type: StringConstructor;
default: string;
};
size: {
type: NumberConstructor;
optional: boolean;
};
viewbox: {
type: StringConstructor;
optional: boolean;
};
flip: {
type: StringConstructor;
optional: boolean;
};
rotate: {
type: NumberConstructor;
optional: boolean;
};
}>;
type: {
type: StringConstructor;
default: string;
};
path: {
type: StringConstructor;
default: string;
};
size: {
type: NumberConstructor;
optional: boolean;
};
viewbox: {
type: StringConstructor;
optional: boolean;
};
flip: {
type: StringConstructor;
optional: boolean;
};
rotate: {
type: NumberConstructor;
optional: boolean;
};
}>;
declare module '@jamescoyle/vue-icon' {
export default SvgIcon;
}
declare module '@jamescoyle/vue-icon' {
export default SvgIcon;
}

View File

@@ -19,7 +19,15 @@ module.exports = { // Main
output: {
libraryTarget: 'commonjs2',
path: path.join(__dirname, 'dist'),
filename: '[name].js'
filename: '[name].js',
assetModuleFilename: (pathData) => {
const { filename } = pathData;
if (filename.endsWith('.ts'))
return '[name].js';
else
return '[name][ext]';
}
},
node: {
global: true,
@@ -43,7 +51,8 @@ module.exports = { // Main
new ProgressPlugin(true),
new webpack.DefinePlugin({
'process.env': {
PACKAGE_VERSION: `"${version}"`
PACKAGE_VERSION: `"${version}"`,
DISTRIBUTION: `"${process.env.DISTRIBUTION || 'none'}"`
}
})
],

View File

@@ -62,7 +62,8 @@ const config = {
new ProgressPlugin(true),
new webpack.DefinePlugin({
'process.env': {
PACKAGE_VERSION: `"${version}"`
PACKAGE_VERSION: `"${version}"`,
DISTRIBUTION: `"${process.env.DISTRIBUTION || 'none'}"`
}
})
]