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

Compare commits

...

99 Commits

Author SHA1 Message Date
71910ca5c8 chore(release): 0.1.12 2021-06-09 09:03:18 +02:00
cce5adbac7 feat(PostgreSQL): trigger rename and delete 2021-06-08 09:12:43 +02:00
e6d67fcb0c Update README.md 2021-06-07 23:03:08 +02:00
e83b80afc9 chore: update README.md 2021-06-05 12:27:20 +02:00
8742fa10f0 fix: internal exceptions 2021-06-05 10:15:44 +02:00
ab54eb086f chore: update dependencies 2021-06-05 10:15:08 +02:00
308f69f12e chore: update README.md 2021-06-04 14:01:46 +02:00
2f30bafa33 Merge pull request #74 from digitalgopnik/master
feat: added translation for de-DE
2021-06-04 10:39:22 +02:00
Christian
1716077182 added translation for de-DE 2021-06-04 09:37:02 +02:00
5562e73e75 fix: page offset not reset when selected table changes 2021-06-03 11:02:24 +02:00
8a7cc2a14f fix(UI): unable to browse view's result pages 2021-06-03 10:57:57 +02:00
9ca059d979 fix(MySQL): view's data tab doesn't work with some views, closes #71 2021-06-03 10:54:59 +02:00
c9ccf786cd chore(release): 0.1.11 2021-06-02 15:47:12 +02:00
5e9c88a7fd fix(UI): prevent canc key to trigger delete modal when editing a row 2021-06-02 12:32:12 +02:00
e0e6483d1f build: update dependencies 2021-06-02 12:13:43 +02:00
66227569f4 fix: table row loses internal id after cell update 2021-06-02 11:58:34 +02:00
faa799c8ea fix(MySQL): missing schema altering tables in some conditions 2021-05-31 17:07:48 +02:00
acc1eeb094 fix: empty offset in cell update queries 2021-05-31 14:27:02 +02:00
865dad80df chore: update README.md 2021-05-30 10:54:58 +02:00
f502620779 chore(release): 0.1.10 2021-05-29 11:41:48 +02:00
f61d7eeaf4 feat: key shortcuts to change DATA tab page 2021-05-29 11:26:23 +02:00
e71c7568c0 feat: option to set DATA tab page size 2021-05-29 11:04:02 +02:00
79f033e524 feat: prev/next buttons to browse the results pages of data tab 2021-05-27 22:13:59 +02:00
310cfaa3c2 fix(MySQL): wrong schema in view data tab select, closes #71 2021-05-26 17:44:33 +02:00
6f93e1f9ab chore: AUR badge on README.md 2021-05-26 13:19:48 +02:00
04bdd085a5 fix: wrong detection of field default expressions in some cases 2021-05-25 16:54:13 +02:00
c568acae14 build: update dependencies 2021-05-25 10:09:09 +02:00
7a46a119d8 chore(release): 0.1.9 2021-05-23 11:35:54 +02:00
f1636f1528 fix(MySQL): can't access tables having UNIQUE KEY, closes #69 2021-05-23 11:12:09 +02:00
f839d5cd3c chore: Twitter link in about tab 2021-05-23 10:19:56 +02:00
8f4f1d393c chore: update README.md 2021-05-22 17:33:03 +02:00
ab17c6d4bf chore: update README.md 2021-05-22 17:26:32 +02:00
b4b2f3d0cf chore(release): 0.1.8 2021-05-22 16:25:52 +02:00
7a766f04e6 perf: improved the way how field default value are handled 2021-05-22 16:24:19 +02:00
f6b77d1243 build: update dependencies 2021-05-22 16:12:08 +02:00
840241c3cc refactor: better description in foreign key value select 2021-05-20 15:07:51 +02:00
0f10c9e824 fix: internal id not removed before row update 2021-05-20 12:45:49 +02:00
1e37f2a96f fix: unable to add new ENUM fields 2021-05-20 12:38:05 +02:00
0d6137195d fix: unable to delete table rows 2021-05-19 16:55:38 +02:00
d26f168250 build: update build script 2021-05-17 19:08:36 +02:00
5efcad4d3f chore(release): 0.1.7 2021-05-16 21:08:52 +02:00
0a872e7023 build: separate build configurations 2021-05-16 21:03:04 +02:00
0e425a9c6d build: removed linux arm64 build from build process 2021-05-16 19:50:06 +02:00
434711a360 perf(MySQL): improved connections pool handling 2021-05-15 21:47:30 +02:00
854472c7a3 fix: row loses internal id after cell update 2021-05-15 19:33:31 +02:00
9a7cd90d5c build: arm mac (apple silicon) build configuration 2021-05-14 22:24:50 +02:00
026400d242 build: arm linux build configuration 2021-05-14 18:59:58 +02:00
4bd8cbbf6c build: moved to sass from node-sass 2021-05-14 17:27:56 +02:00
1382bc9300 Merge pull request #64 from Fabio286/dependabot/npm_and_yarn/pgsql-ast-parser-8.1.1
build(deps): bump pgsql-ast-parser from 7.2.1 to 8.1.1
2021-05-14 17:21:10 +02:00
ae103e5477 perf(core): increased connection pool size to improve performance 2021-05-14 17:17:37 +02:00
6b0b8b19d7 fix(MySQL): connection loses schema in some conditions 2021-05-14 17:02:27 +02:00
475397ca34 fix: issue with ENUM and SET fields on table filler modal 2021-05-13 20:46:44 +02:00
7a62131cc7 fix: issue with ENUM and SET length when creating a new field 2021-05-13 15:45:54 +02:00
c7663be338 fix: multiple row select on sorted tables not work properly 2021-05-11 18:32:11 +02:00
496490b14a build: update dependencies and build config 2021-05-11 12:00:22 +02:00
dependabot[bot]
672573d8c2 build(deps): bump pgsql-ast-parser from 7.2.1 to 8.1.1
Bumps [pgsql-ast-parser](https://github.com/oguimbal/pgsql-ast-parser) from 7.2.1 to 8.1.1.
- [Release notes](https://github.com/oguimbal/pgsql-ast-parser/releases)
- [Changelog](https://github.com/oguimbal/pgsql-ast-parser/blob/master/changelog.md)
- [Commits](https://github.com/oguimbal/pgsql-ast-parser/compare/7.2.1...8.1.1)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-10 06:16:49 +00:00
d923453919 chore(release): 0.1.6 2021-05-08 17:33:25 +02:00
0435279604 build: temporarily disabled Windows builds due issues with dependencies 2021-05-08 17:22:45 +02:00
79cef61fea build: revert to electron-builder@22.9.1 due Windows build issues 2021-05-08 17:13:24 +02:00
dec334737f chore: update dependencies 2021-05-08 16:41:18 +02:00
84c3692e95 chore: icons for appx build 2021-05-08 16:04:37 +02:00
5dc0b0bea4 perf: italian translation updated 2021-05-07 12:11:55 +02:00
19d16e46bb build: update dependencies 2021-05-06 22:55:10 +02:00
3baf6fa173 fix: better detection and handling of field default type 2021-05-06 22:21:42 +02:00
29e2d92b5b fix: no quotes around strings in field default custom value 2021-05-05 17:13:12 +02:00
bebba64d06 feat(MySQL): ENUM and SET fields support, closes #61 2021-05-04 21:50:41 +02:00
9dfe7cca22 fix(UI): data type figure twice on type select 2021-05-03 22:55:39 +02:00
35ef070725 fix: support to mDNS/zeroconf in snap build, closes #58 2021-05-01 12:16:57 +02:00
370ad6a536 chore(release): 0.1.5 2021-04-30 17:37:04 +02:00
5822b3df43 perf(UI): new application icon 2021-04-30 14:14:01 +02:00
5208ec171b fix(MySQL): multiple queries non properly split in some cases 2021-04-29 21:03:32 +02:00
6e332da425 chore: update issue template 2021-04-28 16:56:04 +02:00
bf3367b41d build: minor changes to build and dependencies 2021-04-28 12:11:39 +02:00
ecfb732c26 fix: % character not properly escaped, closes #60 2021-04-28 12:10:43 +02:00
fd4f032a6f build: mssql temporarily removed from dependencies 2021-04-28 11:55:29 +02:00
1b09909126 fix: semicolon inside strings breaks queries, closes #59 2021-04-28 11:50:07 +02:00
04cd806954 chore: update README.md 2021-04-26 10:16:55 +02:00
773cb36ca1 Merge pull request #57 from Fabio286/dependabot/npm_and_yarn/electron-store-8.0.0
build(deps): bump electron-store from 7.0.3 to 8.0.0
2021-04-26 10:12:32 +02:00
ccacd3e2c3 Merge pull request #56 from Fabio286/dependabot/npm_and_yarn/electron-12.0.5
build(deps-dev): bump electron from 11.4.3 to 12.0.5
2021-04-26 10:08:32 +02:00
15948b30c9 refactor: modifications for electron 12 support 2021-04-26 10:07:47 +02:00
3dcb5d4f14 Merge pull request #55 from Fabio286/dependabot/npm_and_yarn/stylelint-config-standard-22.0.0
build(deps-dev): bump stylelint-config-standard from 21.0.0 to 22.0.0
2021-04-26 08:59:35 +02:00
dependabot[bot]
64d93d7c40 build(deps): bump electron-store from 7.0.3 to 8.0.0
Bumps [electron-store](https://github.com/sindresorhus/electron-store) from 7.0.3 to 8.0.0.
- [Release notes](https://github.com/sindresorhus/electron-store/releases)
- [Commits](https://github.com/sindresorhus/electron-store/compare/v7.0.3...v8.0.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-26 06:26:31 +00:00
dependabot[bot]
2d85295093 build(deps-dev): bump electron from 11.4.3 to 12.0.5
Bumps [electron](https://github.com/electron/electron) from 11.4.3 to 12.0.5.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v11.4.3...v12.0.5)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-26 06:25:55 +00:00
dependabot[bot]
cd58e2d8ca build(deps-dev): bump stylelint-config-standard from 21.0.0 to 22.0.0
Bumps [stylelint-config-standard](https://github.com/stylelint/stylelint-config-standard) from 21.0.0 to 22.0.0.
- [Release notes](https://github.com/stylelint/stylelint-config-standard/releases)
- [Changelog](https://github.com/stylelint/stylelint-config-standard/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stylelint/stylelint-config-standard/compare/21.0.0...22.0.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-26 06:25:16 +00:00
d87495822e Merge pull request #54 from daeleduardo/master
feat: portugues (Brasil) translation
2021-04-25 11:44:55 +02:00
Daniel Aguiar
8720bcdad6 New Translation: Portugues (Brasil) 2021-04-25 03:53:21 -03:00
1df57dc705 chore(release): 0.1.4 2021-04-22 15:18:07 +02:00
86240fb53c refactor(PostgreSQL): preparing code to support triggers 2021-04-22 15:15:08 +02:00
1d363f755e feat: query results export 2021-04-22 15:08:22 +02:00
0d77aee3eb refactor: Improved pulse animation code 2021-04-22 14:24:34 +02:00
a41cf1ab56 fix: wrong changelog in some cases 2021-04-22 11:35:59 +02:00
5ceddb8e00 perf(UI): improved connection status indicator 2021-04-21 16:41:42 +02:00
16e17b39b6 feat(UI): ctrl+s shortcut to save changes 2021-04-20 17:39:15 +02:00
20cba6ee9b feat(UI): canc press to delete selected rows 2021-04-20 16:30:10 +02:00
9ffd443a66 feat(UI): format and clear queries 2021-04-19 19:15:06 +02:00
f82dbd24dc fix: launch from shortcut of procedures or functions with parameters without name dont works 2021-04-19 15:40:25 +02:00
6eb2977568 fix(UI): data type not listed in selection if not present in global types 2021-04-19 11:07:29 +02:00
cafb65560a chore: update README.md 2021-04-17 12:28:55 +02:00
532d963019 chore: update README.md 2021-04-17 11:28:02 +02:00
75 changed files with 2558 additions and 578 deletions

View File

@@ -9,22 +9,25 @@
"plugin:vue/recommended"
],
"parserOptions": {
"parser": "babel-eslint",
"parser": "@babel/eslint-parser",
"ecmaVersion": 9,
"sourceType": "module"
"sourceType": "module",
"requireConfigFile": false
},
"rules": {
"indent": [
"error",
3,
{ "SwitchCase": 1 }
{
"SwitchCase": 1
}
],
"linebreak-style": [
"error",
"unix"
],
"brace-style": [
"error",
"error",
"stroustrup"
],
"quotes": [
@@ -36,7 +39,7 @@
"always"
],
"curly": [
"error",
"error",
"multi-or-nest"
],
"no-console": "off",
@@ -44,18 +47,25 @@
"vue/no-side-effects-in-computed-properties": "off",
"vue/require-default-prop": "off",
"vue/no-v-html": "off",
"vue/html-indent": ["error", 3, {
"attribute": 1,
"baseIndent": 1,
"closeBracket": 0,
"ignores": []
}],
"vue/max-attributes-per-line": ["error", {
"singleline": 2,
"multiline": {
"max": 1,
"allowFirstLine": false
"vue/html-indent": [
"error",
3,
{
"attribute": 1,
"baseIndent": 1,
"closeBracket": 0,
"ignores": []
}
}]
],
"vue/max-attributes-per-line": [
"error",
{
"singleline": 2,
"multiline": {
"max": 1,
"allowFirstLine": false
}
}
]
}
}

View File

@@ -12,6 +12,7 @@ A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
@@ -23,9 +24,15 @@ A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Application (please complete the following information):**
- Version [e.g. 0.14.0]
- Distribution: [e.g. exe, Linux Store, AppImage, dmg]
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Version [e.g. 22]
- OS: [e.g. iOS]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@@ -1,4 +1,4 @@
name: Build/release
name: Build/release [linux]
on: push
@@ -8,7 +8,7 @@ jobs:
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
os: [ubuntu-latest]
steps:
- name: Check out Git repository
@@ -17,10 +17,10 @@ jobs:
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 10
node-version: 12
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1
with:
github_token: ${{ secrets.github_token }}
release: ${{ startsWith(github.ref, 'refs/tags/v') }}
release: ${{ startsWith(github.ref, 'refs/tags/v') }}

26
.github/workflows/build-mac.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: Build/release [mac]
on: push
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v1
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 12
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1
with:
github_token: ${{ secrets.github_token }}
release: ${{ startsWith(github.ref, 'refs/tags/v') }}

26
.github/workflows/build-win.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: Build/release [windows]
on: push
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v1
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 12
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1
with:
github_token: ${{ secrets.github_token }}
release: ${{ startsWith(github.ref, 'refs/tags/v') }}

View File

@@ -1,52 +0,0 @@
language: node_js
node_js: 12
cache:
directories:
- node_modules
- app/node_modules
- $HOME/.cache/electron
- $HOME/.cache/electron-builder
- $HOME/.npm/_prebuilds
env:
global:
- ELECTRON_CACHE=$HOME/.cache/electron
- ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder
jobs:
include:
- stage: Test
before_install:
- sudo apt-get install libsecret-1-dev
- npm install
script:
- npm test
- stage: Deploy Linux & Windows
if: tag IS present
os: linux
services: docker
before_install:
- sudo apt-get install libsecret-1-dev
- npm install
script:
- docker run --rm --env-file <(env | grep -iE 'DEBUG|NODE_|ELECTRON_|NPM_|CI|CIRCLE|TRAVIS|APPVEYOR_|CSC_|_TOKEN|_KEY|AWS_|STRIP|BUILD_') -v ${PWD}:/project -v ~/.cache/electron:/root/.cache/electron -v ~/.cache/electron-builder:/root/.cache/electron-builder electronuserland/builder:wine /bin/bash -c "npm run build -- --linux --win -p always"
before_cache:
- rm -rf $HOME/.cache/electron-builder/wine
- stage: Deploy Mac
if: tag IS present
os: osx
before_install:
- npm install
osx_image: xcode10.2
script:
- npm run build -- -p always
# - stage: Deploy ARM Linux
# if: tag IS present
# os: linux
# arch: arm64
# script:
# - npm run build -- --linux AppImage -p always

View File

@@ -2,6 +2,140 @@
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.1.12](https://github.com/Fabio286/antares/compare/v0.1.11...v0.1.12) (2021-06-09)
### Features
* **PostgreSQL:** trigger rename and delete ([cce5adb](https://github.com/Fabio286/antares/commit/cce5adbac75170186956211b54f4db5be25aba07))
### Bug Fixes
* internal exceptions ([8742fa1](https://github.com/Fabio286/antares/commit/8742fa10f08c92a98325df50be9a7df8e36b0f2c))
* page offset not reset when selected table changes ([5562e73](https://github.com/Fabio286/antares/commit/5562e73e75c659051a49d61041d1eee9d66ff6e2))
* **MySQL:** view's data tab doesn't work with some views, closes [#71](https://github.com/Fabio286/antares/issues/71) ([9ca059d](https://github.com/Fabio286/antares/commit/9ca059d979161c0132f64db372b4ed7ecc844b2d))
* **UI:** unable to browse view's result pages ([8a7cc2a](https://github.com/Fabio286/antares/commit/8a7cc2a14fa289c2f3d9e9eb1a5435ffbbaab006))
### [0.1.11](https://github.com/Fabio286/antares/compare/v0.1.10...v0.1.11) (2021-06-02)
### Bug Fixes
* **UI:** prevent canc key to trigger delete modal when editing a row ([5e9c88a](https://github.com/Fabio286/antares/commit/5e9c88a7fd656dd69b92ba4384ca81f4e8cdd422))
* table row loses internal id after cell update ([6622756](https://github.com/Fabio286/antares/commit/66227569f4c032298e20d44c253d30109ffde0b2))
* **MySQL:** missing schema altering tables in some conditions ([faa799c](https://github.com/Fabio286/antares/commit/faa799c8ea2329e7ca1b54c9414a060bc8a2a840))
* empty offset in cell update queries ([acc1eeb](https://github.com/Fabio286/antares/commit/acc1eeb0948db35f2c9a4d85d70fb654b41b15e5))
### [0.1.10](https://github.com/Fabio286/antares/compare/v0.1.9...v0.1.10) (2021-05-29)
### Features
* key shortcuts to change DATA tab page ([f61d7ee](https://github.com/Fabio286/antares/commit/f61d7eeaf42406eb88b3285ac4606794f56e88d3))
* option to set DATA tab page size ([e71c756](https://github.com/Fabio286/antares/commit/e71c7568c09bf8ad184753d3d0f14046f1e386d0))
* prev/next buttons to browse the results pages of data tab ([79f033e](https://github.com/Fabio286/antares/commit/79f033e5245e0e744c35540d25a30b1eadc4d603))
### Bug Fixes
* **MySQL:** wrong schema in view data tab select, closes [#71](https://github.com/Fabio286/antares/issues/71) ([310cfaa](https://github.com/Fabio286/antares/commit/310cfaa3c2324b1159a46be566b6af2555dc9732))
* wrong detection of field default expressions in some cases ([04bdd08](https://github.com/Fabio286/antares/commit/04bdd085a56240273133586d23196e52341d5f27))
### [0.1.9](https://github.com/Fabio286/antares/compare/v0.1.8...v0.1.9) (2021-05-23)
### Bug Fixes
* **MySQL:** can't access tables having UNIQUE KEY, closes [#69](https://github.com/Fabio286/antares/issues/69) ([f1636f1](https://github.com/Fabio286/antares/commit/f1636f1528b5765423535f84027fdc853c58ce80))
### [0.1.8](https://github.com/Fabio286/antares/compare/v0.1.7...v0.1.8) (2021-05-22)
### Bug Fixes
* internal id not removed before row update ([0f10c9e](https://github.com/Fabio286/antares/commit/0f10c9e824b679cfebd8a31085236da3d38a7953))
* unable to add new ENUM fields ([1e37f2a](https://github.com/Fabio286/antares/commit/1e37f2a96f660a36f2739fea57ca298059e9c31a))
* unable to delete table rows ([0d61371](https://github.com/Fabio286/antares/commit/0d6137195da9e0e9afe68f6d3ebcd50e913a888e))
### Improvements
* improved the way how field default value are handled ([7a766f0](https://github.com/Fabio286/antares/commit/7a766f04e668868e8844aac1d7d445bc2da21558))
### [0.1.7](https://github.com/Fabio286/antares/compare/v0.1.6...v0.1.7) (2021-05-16)
### Bug Fixes
* row loses internal id after cell update ([854472c](https://github.com/Fabio286/antares/commit/854472c7a3d8442b1eede12f978cad5aa684094e))
* **MySQL:** connection loses schema in some conditions ([6b0b8b1](https://github.com/Fabio286/antares/commit/6b0b8b19d7176ef8647d6f401a33315f8732fdf3))
* issue with ENUM and SET fields on table filler modal ([475397c](https://github.com/Fabio286/antares/commit/475397ca34c5b7d8925e2d97d32216d5b80d8211))
* issue with ENUM and SET length when creating a new field ([7a62131](https://github.com/Fabio286/antares/commit/7a62131cc707aa1c98bb12513de76229472b7c38))
* multiple row select on sorted tables not work properly ([c7663be](https://github.com/Fabio286/antares/commit/c7663be338ccb5ff31e241e824593531ad95bd32))
### Improvements
* **core:** increased connection pool size to improve performance ([ae103e5](https://github.com/Fabio286/antares/commit/ae103e5477ad190c541d0f29e277c41de6947063))
* **MySQL:** improved connections pool handling ([434711a](https://github.com/Fabio286/antares/commit/434711a360bd7539d2ec3adec92e7ccc96fa828e))
### [0.1.6](https://github.com/Fabio286/antares/compare/v0.1.5...v0.1.6) (2021-05-08)
### Features
* **MySQL:** ENUM and SET fields support, closes [#61](https://github.com/Fabio286/antares/issues/61) ([bebba64](https://github.com/Fabio286/antares/commit/bebba64d06532990405763284e27cb768dc050f7))
### Bug Fixes
* better detection and handling of field default type ([3baf6fa](https://github.com/Fabio286/antares/commit/3baf6fa1736a405c95fb02d17c11514861ca9e04))
* no quotes around strings in field default custom value ([29e2d92](https://github.com/Fabio286/antares/commit/29e2d92b5bf66ff9e80bb1fee1274967c4418601))
* **UI:** data type figure twice on type select ([9dfe7cc](https://github.com/Fabio286/antares/commit/9dfe7cca2234ce6de512bb4c21205c2217e7f765))
* support to mDNS/zeroconf in snap build, closes [#58](https://github.com/Fabio286/antares/issues/58) ([35ef070](https://github.com/Fabio286/antares/commit/35ef070725f5779923bf3ad428b44accddf22dbe))
### Improvements
* italian translation updated ([5dc0b0b](https://github.com/Fabio286/antares/commit/5dc0b0bea40f9d5a5944af2f1c5dc6ff3e60c396))
### [0.1.5](https://github.com/Fabio286/antares/compare/v0.1.4...v0.1.5) (2021-04-30)
### Bug Fixes
* **MySQL:** multiple queries non properly split in some cases ([5208ec1](https://github.com/Fabio286/antares/commit/5208ec171b44da0e6bfa93f15bfedd03ef2aa868))
* % character not properly escaped, closes [#60](https://github.com/Fabio286/antares/issues/60) ([ecfb732](https://github.com/Fabio286/antares/commit/ecfb732c265a5485e131e75f3d20ff07d9409753))
* semicolon inside strings breaks queries, closes [#59](https://github.com/Fabio286/antares/issues/59) ([1b09909](https://github.com/Fabio286/antares/commit/1b0990912627a3a4a4e8d62b4593f8a7aa3a7fe5))
### Improvements
* **UI:** new application icon ([5822b3d](https://github.com/Fabio286/antares/commit/5822b3df432e0a2b305d0ff37a20dc466c3a3992))
### [0.1.4](https://github.com/Fabio286/antares/compare/v0.1.3...v0.1.4) (2021-04-22)
### Features
* query results export ([1d363f7](https://github.com/Fabio286/antares/commit/1d363f755e025d0fc6fec61cbd47ff87a8f25728))
* **UI:** canc press to delete selected rows ([20cba6e](https://github.com/Fabio286/antares/commit/20cba6ee9bc1daa902b04d6e2ddcb31d04fbf805))
* **UI:** ctrl+s shortcut to save changes ([16e17b3](https://github.com/Fabio286/antares/commit/16e17b39b6c8b561cc018d02afee2276190ce304))
* **UI:** format and clear queries ([9ffd443](https://github.com/Fabio286/antares/commit/9ffd443a66303f88fc4529896f6d1d7917454f7a))
### Bug Fixes
* launch from shortcut of procedures or functions with parameters without name dont works ([f82dbd2](https://github.com/Fabio286/antares/commit/f82dbd24dcef7b4d8d127a604e256b3f79a6c617))
* wrong changelog in some cases ([a41cf1a](https://github.com/Fabio286/antares/commit/a41cf1ab5662f5f5fdedff4a9e1c626c23071377))
* **UI:** data type not listed in selection if not present in global types ([6eb2977](https://github.com/Fabio286/antares/commit/6eb2977568987b9440b62ae7dbd7183338bfcc9b))
### Improvements
* **UI:** improved connection status indicator ([5ceddb8](https://github.com/Fabio286/antares/commit/5ceddb8e00f3bc1984b8e47de270dc39b367903f))
### [0.1.3](https://github.com/Fabio286/antares/compare/v0.1.2...v0.1.3) (2021-04-17)

View File

@@ -4,7 +4,7 @@
# Antares SQL Client
![GitHub package.json version](https://img.shields.io/github/package-json/v/fabio286/antares) [![Build Status](https://travis-ci.com/Fabio286/antares.svg?branch=master)](https://travis-ci.com/Fabio286/antares) ![GitHub All Releases](https://img.shields.io/github/downloads/fabio286/antares/total) ![GitHub](https://img.shields.io/github/license/fabio286/antares) [![antares](https://snapcraft.io/antares/badge.svg)](https://snapcraft.io/antares) [![antares](https://snapcraft.io/antares/trending.svg?name=0)](https://snapcraft.io/antares)
![GitHub package.json version](https://img.shields.io/github/package-json/v/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) ![GitHub All Releases](https://img.shields.io/github/downloads/fabio286/antares/total) ![GitHub](https://img.shields.io/github/license/fabio286/antares) [![antares](https://snapcraft.io/antares/badge.svg)](https://snapcraft.io/antares) [![antares](https://snapcraft.io/antares/trending.svg?name=0)](https://snapcraft.io/antares) [![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.
My target is to support as many databases as possible, and all major operating systems, including the ARM versions.
@@ -14,7 +14,7 @@ Many of its current features are enough to have a pleasant user experience with
I'm actively working on it, hoping to provide cool features and fixes as soon as possible.
🔗 If you are curious to try Antares you can download and install the [latest release](https://github.com/Fabio286/antares/releases/latest).
👁 To stay tuned for new releases watch this repo on **Release only** channel.
👁 To stay tuned for new releases [follow Antares SQL](https://twitter.com/AntaresSQL) on Twitter.
🌟 Don't forget to **leave a star** if you appreciate this project.
## Philosophy
@@ -25,12 +25,14 @@ A modern application created with minimalism and semplicity in mind, with featur
## 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 Microsoft Store](https://raw.githubusercontent.com/Fabio286/antares/gh-pages/src/assets/ms-store.png)](https://www.microsoft.com/p/antares-sql-client/9nhtb9sq51r1?cid=storebadge&ocid=badge&rtc=1&activetab=pivot:overviewtab)
[![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/) [![Get it from Microsoft Store](https://raw.githubusercontent.com/Fabio286/antares/gh-pages/src/assets/ms-store.png)](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)**
## How to contribute
- [Translate Antares](https://github.com/Fabio286/antares/wiki/Translate-Antares)
- 🌍 [Translate Antares](https://github.com/Fabio286/antares/wiki/Translate-Antares)
- 📖 [Contributors Guide](https://github.com/Fabio286/antares/wiki/Contributors-Guide)
- 🚧 [Project Board](https://github.com/users/Fabio286/projects/1)
## Current main features
@@ -45,7 +47,6 @@ A modern application created with minimalism and semplicity in mind, with featur
- Scratchpad.
- Multi language.
- Secure password storage.
- Auto updates.
## Coming soon
@@ -62,17 +63,6 @@ This is a roadmap with major features will come in near future.
- Query logs console.
- Import/export and migration.
## Troubleshooting
### **Linux**
With KDE may need necessary installation of the additional `gnome-keyring` package.
Depending on your distribution, you will need to run the following command:
- Debian/Ubuntu: `sudo apt-get install gnome-keyring`
- Red Hat-based: `sudo yum install gnome-keyring`
- Arch Linux: `sudo pacman -S gnome-keyring`
## Currently supported
### Databases
@@ -95,15 +85,17 @@ Depending on your distribution, you will need to run the following command:
#### • ARM
- [ ] Windows
- [ ] Linux
- [x] Linux
- [ ] MacOS
## Translations
**Italian Translation** (46%) / [Giuseppe Gigliotti](https://github.com/ReverbOD) [[#20](https://github.com/Fabio286/antares/pull/20)]
**Arabic Translation** (45%) / [Mohd-PH](https://github.com/Mohd-PH) [[#29](https://github.com/Fabio286/antares/pull/29)]
**Spanish Translation** (46%) / [hongkfui](https://github.com/hongkfui) [[#32](https://github.com/Fabio286/antares/pull/32)]
**French Translation** (100%) / [MrAnyx](https://github.com/MrAnyx) [[#44](https://github.com/Fabio286/antares/pull/44)]
**Italian Translation** / [Giuseppe Gigliotti](https://github.com/ReverbOD) [[#20](https://github.com/Fabio286/antares/pull/20)]
**Arabic Translation** / [Mohd-PH](https://github.com/Mohd-PH) [[#29](https://github.com/Fabio286/antares/pull/29)]
**Spanish Translation** / [hongkfui](https://github.com/hongkfui) [[#32](https://github.com/Fabio286/antares/pull/32)]
**French Translation** / [MrAnyx](https://github.com/MrAnyx) [[#44](https://github.com/Fabio286/antares/pull/44)]
**Portugues (Brasil)** / [Daniel Eduardo](https://github.com/daeleduardo) [[#54](https://github.com/Fabio286/antares/pull/54)]
**Deutsch (Deutschland)** / [Christian Ratz](https://github.com/digitalgopnik) [[#74](https://github.com/Fabio286/antares/pull/74)]
## Reviews

BIN
build/appx/LargeTile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
build/appx/SmallTile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 50 KiB

77
docs/aur-badge.svg Normal file
View File

@@ -0,0 +1,77 @@
<?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">
<defs>
<clipPath id="_clipPath_tR1uglJ1Zei76xP861DY1TsjAiQWS9qF">
<rect width="182" height="56" />
</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>
<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>
</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>
<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>
</defs>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 172 KiB

View File

@@ -1,20 +1,22 @@
{
"name": "antares",
"productName": "Antares",
"version": "0.1.3",
"version": "0.1.12",
"description": "A cross-platform easy to use SQL client.",
"license": "MIT",
"repository": "https://github.com/Fabio286/antares.git",
"scripts": {
"dev": "cross-env NODE_ENV=development electron-webpack dev",
"compile": "electron-webpack",
"build": "cross-env NODE_ENV=production npm run compile && electron-builder",
"build:appx": "npm run build -- --win appx",
"build": "cross-env NODE_ENV=production npm run compile",
"build:local": "npm run build && electron-builder",
"build:appx": "npm run build:local -- --win appx",
"release": "standard-version",
"release:pre": "npm run release -- --prerelease alpha",
"test": "npm run lint",
"lint": "eslint . --ext .js,.vue && stylelint \"./src/**/*.{css,scss,sass,vue}\"",
"lint:fix": "eslint . --ext .js,.vue --fix && stylelint \"./src/**/*.{css,scss,sass,vue}\" --fix"
"lint:fix": "eslint . --ext .js,.vue --fix && stylelint \"./src/**/*.{css,scss,sass,vue}\" --fix",
"postinstall": "electron-builder install-app-deps"
},
"author": "Fabio Di Stasio <fabio286@gmail.com>",
"build": {
@@ -26,24 +28,28 @@
"portable"
]
},
"dmg": {
"contents": [
{
"x": 130,
"y": 220
},
{
"x": 410,
"y": 220,
"type": "link",
"path": "/Applications"
}
]
"mac": {
"target": {
"target": "default",
"arch": [
"x64"
]
}
},
"linux": {
"target": [
"deb",
"AppImage"
{
"target": "deb",
"arch": "x64"
},
{
"target": "AppImage",
"arch": [
"x64",
"armv7l",
"arm64"
]
}
],
"category": "Development"
},
@@ -59,6 +65,20 @@
"identityName": "62514FabioDiStasio.AntaresSQLClient",
"publisher": "CN=1A2729ED-865C-41D2-9038-39AE2A63AA52",
"applicationId": "FabioDiStasio.AntaresSQLClient"
},
"dmg": {
"contents": [
{
"x": 130,
"y": 220
},
{
"x": 410,
"y": 220,
"type": "link",
"path": "/Applications"
}
]
}
},
"electronWebpack": {
@@ -67,49 +87,48 @@
}
},
"dependencies": {
"@electron/remote": "^1.1.0",
"@mdi/font": "^5.9.55",
"ace-builds": "^1.4.12",
"electron-log": "^4.3.0",
"electron-store": "^7.0.0",
"electron-updater": "^4.3.5",
"faker": "^5.3.1",
"keytar": "^7.3.0",
"marked": "^2.0.2",
"electron-log": "^4.3.5",
"electron-store": "^8.0.0",
"electron-updater": "^4.3.9",
"faker": "^5.5.3",
"marked": "^2.0.7",
"moment": "^2.29.1",
"mssql": "^6.2.3",
"mysql2": "^2.2.5",
"node-sql-parser": "^3.1.0",
"pg": "^8.5.1",
"pgsql-ast-parser": "^7.0.2",
"pgsql-ast-parser": "^7.2.1",
"source-map-support": "^0.5.16",
"spectre.css": "^0.5.9",
"sql-formatter": "^4.0.2",
"v-mask": "^2.2.4",
"vue-i18n": "^8.22.4",
"vue-i18n": "^8.24.4",
"vuedraggable": "^2.24.3",
"vuex": "^3.6.0"
"vuex": "^3.6.2"
},
"devDependencies": {
"babel-eslint": "^10.1.0",
"@babel/eslint-parser": "^7.14.4",
"cross-env": "^7.0.2",
"electron": "^11.4.3",
"electron-builder": "^22.9.1",
"electron-devtools-installer": "^3.1.1",
"electron": "^13.1.1",
"electron-builder": "22.10.5",
"electron-devtools-installer": "^3.2.0",
"electron-webpack": "^2.8.2",
"electron-webpack-vue": "^2.4.0",
"eslint": "^7.24.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.22.1",
"eslint": "^7.28.0",
"eslint-config-standard": "^16.0.3",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-vue": "^7.9.0",
"node-sass": "^5.0.0",
"sass-loader": "^10.1.1",
"standard-version": "^9.2.0",
"stylelint": "^13.9.0",
"stylelint-config-standard": "^21.0.0",
"eslint-plugin-vue": "^7.10.0",
"sass": "^1.34.1",
"sass-loader": "^10.2.0",
"standard-version": "^9.3.0",
"stylelint": "^13.13.1",
"stylelint-config-standard": "^22.0.0",
"stylelint-scss": "^3.19.0",
"vue": "^2.6.12",
"vue-template-compiler": "^2.6.12",
"vue": "^2.6.14",
"vue-template-compiler": "^2.6.14",
"webpack": "^4.46.0"
}
}

View File

@@ -14,6 +14,9 @@ confinement: strict
architectures:
- build-on: amd64
compression: lzo
layout:
/etc/nsswitch.conf:
bind-file: $SNAP/etc/nsswitch.conf
parts:
antares:
@@ -71,11 +74,28 @@ parts:
cleanup:
after: [antares]
plugin: nil
build-snaps: [ gnome-3-28-1804 ]
build-snaps: [gnome-3-28-1804]
override-prime: |
set -eux
cd /snap/gnome-3-28-1804/current
find . -type f,l -exec rm -f $SNAPCRAFT_PRIME/{} \;
set -eux
cd /snap/gnome-3-28-1804/current
find . -type f,l -exec rm -f $SNAPCRAFT_PRIME/{} \;
mdns-lookup:
# Make resolution of ".local" host names (Zero-Conf/mDNS/DNS-SD)
# working: Take the original nsswitch.conf file from the base
# Snap and add "mdns4_minimal [NOTFOUND=return]" to its "hosts:" line
# Also install corresponding mdns4_minimal plug-in
# See: https://forum.snapcraft.io/t/no-mdns-support-in-snaps-should-core-have-a-modified-nsswitch-conf/
plugin: nil
stage-packages:
- libnss-mdns
override-prime: |
set -eux
sed -Ee 's/^\s*hosts:(\s+)files/hosts:\1files mdns4_minimal \[NOTFOUND=return\]/' /snap/core18/current/etc/nsswitch.conf > $SNAPCRAFT_STAGE/etc/nsswitch.conf
snapcraftctl prime
prime:
- lib/$SNAPCRAFT_ARCH_TRIPLET/libnss_mdns4_minimal*
- etc/nsswitch.conf
apps:
antares:
@@ -93,4 +113,4 @@ apps:
- opengl
- pulseaudio
- removable-media
- unity7
- unity7

View File

@@ -16,6 +16,7 @@ module.exports = {
tables: false,
views: false,
triggers: false,
triggerFunctions: false,
routines: false,
functions: false,
schedulers: false,
@@ -23,6 +24,7 @@ module.exports = {
tableAdd: false,
viewAdd: false,
triggerAdd: false,
triggerFunctionAdd: false,
routineAdd: false,
functionAdd: false,
schedulerAdd: false,
@@ -31,6 +33,7 @@ module.exports = {
tableSettings: false,
viewSettings: false,
triggerSettings: false,
triggerFunctionSettings: false,
routineSettings: false,
functionSettings: false,
schedulerSettings: false,
@@ -59,6 +62,10 @@ module.exports = {
functionSql: false,
functionContext: false,
functionLanguage: false,
triggerMiltipleEvents: false,
triggerTableInName: false,
triggerUpdateColumns: false,
triggerOnlyRename: false,
parametersLength: false,
languages: false
};

View File

@@ -13,7 +13,7 @@ module.exports = {
// Structure
tables: true,
views: true,
triggers: false,
triggers: true,
routines: true,
functions: true,
// Settings
@@ -25,7 +25,7 @@ module.exports = {
databaseEdit: false,
tableSettings: true,
viewSettings: true,
triggerSettings: false,
triggerSettings: true,
routineSettings: true,
functionSettings: true,
indexes: true,
@@ -38,5 +38,8 @@ module.exports = {
functionSql: '$BODY$\r\n\r\n$BODY$',
functionContext: true,
functionLanguage: true,
triggerMultipleEvents: true,
triggerTableInName: true,
triggerOnlyRename: true,
languages: ['sql', 'plpgsql', 'c', 'internal']
};

View File

@@ -277,13 +277,6 @@ module.exports = [
{
group: 'other',
types: [
{
name: 'UNKNOWN',
length: false,
collation: false,
unsigned: false,
zerofill: false
},
{
name: 'ENUM',
length: true,
@@ -299,5 +292,17 @@ module.exports = [
zerofill: false
}
]
},
{
group: 'unknown',
types: [
{
name: 'UNKNOWN',
length: false,
collation: false,
unsigned: false,
zerofill: false
}
]
}
];

View File

@@ -12,7 +12,7 @@ const regex = new RegExp(pattern);
function sqlEscaper (string) {
return string.replace(regex, char => {
const m = ['\\0', '\\x08', '\\x09', '\\x1a', '\\n', '\\r', '\'', '\"', '\\', '\\\\', '%'];
const r = ['\\\\0', '\\\\b', '\\\\t', '\\\\z', '\\\\n', '\\\\r', '\\\'', '\\\"', '\\\\', '\\\\\\\\', '\\%'];
const r = ['\\\\0', '\\\\b', '\\\\t', '\\\\z', '\\\\n', '\\\\r', '\\\'', '\\\"', '\\\\', '\\\\\\\\', '\%'];
return r[m.indexOf(char)] || char;
});
}

View File

@@ -2,9 +2,7 @@
import { app, BrowserWindow, nativeImage } from 'electron';
import * as path from 'path';
import crypto from 'crypto';
import { format as formatUrl } from 'url';
import keytar from 'keytar';
import Store from 'electron-store';
import ipcHandlers from './ipc-handlers';
@@ -31,6 +29,7 @@ async function createMainWindow () {
icon: nativeImage.createFromDataURL(icon.default),
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
'web-security': false,
enableRemoteModule: true,
spellcheck: false
@@ -39,26 +38,25 @@ async function createMainWindow () {
backgroundColor: '#1d1d1d'
});
if (isDevelopment) {
await window.loadURL(`http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}`);
try {
if (isDevelopment) {
await window.loadURL(`http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}`);
const { default: installExtension, VUEJS_DEVTOOLS } = require('electron-devtools-installer');
window.webContents.openDevTools();
const { default: installExtension, VUEJS_DEVTOOLS } = require('electron-devtools-installer');
installExtension(VUEJS_DEVTOOLS)
.then(name => {
console.log(name, 'installed');
})
.catch(err => {
console.log(err);
});
const toolName = await installExtension(VUEJS_DEVTOOLS);
console.log(toolName, 'installed');
}
else {
await window.loadURL(formatUrl({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file',
slashes: true
}));
}
}
else {
await window.loadURL(formatUrl({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file',
slashes: true
}));
catch (err) {
console.log(err);
}
window.on('closed', () => {
@@ -78,6 +76,8 @@ async function createMainWindow () {
if (!gotTheLock)
app.quit();
else {
require('@electron/remote/main').initialize();
// Initialize ipcHandlers
ipcHandlers();
@@ -88,26 +88,19 @@ else {
app.quit();
});
app.on('activate', () => {
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 = createMainWindow();
if (mainWindow === null) {
mainWindow = await createMainWindow();
if (isDevelopment)
mainWindow.webContents.openDevTools();
}
});
// create main BrowserWindow when electron is ready
app.on('ready', async () => {
try {
let key = await keytar.getPassword('antares', 'user');
if (!key) {
key = crypto.randomBytes(16).toString('hex');
keytar.setPassword('antares', 'user', key);
}
}
catch (err) {
console.log(err);
}
mainWindow = createMainWindow();
mainWindow = await createMainWindow();
if (isDevelopment)
mainWindow.webContents.openDevTools();
});
}

View File

@@ -1,4 +1,3 @@
import keytar from 'keytar';
import { app, ipcMain } from 'electron';
export default () => {
@@ -7,14 +6,7 @@ export default () => {
});
ipcMain.on('get-key', async event => {
let key = false;
try {
key = await keytar.getPassword('antares', 'user');
}
catch (err) {
console.log(err);
}
const key = false;
event.returnValue = key;
});
};

View File

@@ -71,7 +71,7 @@ export default connections => {
const connection = ClientsFactory.getConnection({
client: conn.client,
params,
poolSize: 1
poolSize: 5
});
await connection.connect();

View File

@@ -128,7 +128,7 @@ export default connections => {
if (!query) return;
try {
const result = await connections[uid].raw(query, { nest: true, details: true });
const result = await connections[uid].raw(query, { nest: true, details: true, schema });
return { status: 'success', response: result };
}

View File

@@ -16,13 +16,15 @@ export default (connections) => {
}
});
ipcMain.handle('get-table-data', async (event, { uid, schema, table, sortParams }) => {
ipcMain.handle('get-table-data', async (event, { uid, schema, table, limit, page, sortParams }) => {
try {
const offset = (page - 1) * limit;
const query = connections[uid]
.select('*')
.schema(schema)
.from(table)
.limit(1000);
.limit(limit)
.offset(offset);
if (sortParams && sortParams.field && sortParams.dir)
query.orderBy({ [sortParams.field]: sortParams.dir.toUpperCase() });
@@ -59,6 +61,8 @@ export default (connections) => {
});
ipcMain.handle('update-table-cell', async (event, params) => {
delete params.row._id;
try { // TODO: move to client classes
let escapedParam;
let reload = false;

View File

@@ -26,6 +26,7 @@ export class AntaresCore {
groupBy: [],
orderBy: [],
limit: [],
offset: [],
join: [],
update: [],
insert: [],
@@ -109,6 +110,11 @@ export class AntaresCore {
return this;
}
offset (...args) {
this._query.offset = args;
return this;
}
/**
* @param {String | Array} args field = value
* @returns
@@ -134,7 +140,7 @@ export class AntaresCore {
* @returns {Promise}
* @memberof AntaresCore
*/
async run (args) {
run (args) {
const rawQuery = this.getSQL();
this._resetQuery();
return this.raw(rawQuery, args);

View File

@@ -1,5 +1,5 @@
'use strict';
import mysql from 'mysql2';
import mysql from 'mysql2/promise';
import { AntaresCore } from '../AntaresCore';
import dataTypes from 'common/data-types/mysql';
@@ -102,8 +102,10 @@ export class MySQLClient extends AntaresCore {
* @memberof MySQLClient
*/
async connect () {
delete this._params.application_name;
if (!this._poolSize)
this._connection = mysql.createConnection(this._params);
this._connection = await mysql.createConnection(this._params);
else {
this._connection = mysql.createPool({
...this._params,
@@ -303,29 +305,80 @@ export class MySQLClient extends AntaresCore {
.select('*')
.schema('information_schema')
.from('COLUMNS')
.where({ TABLE_SCHEMA: `= '${schema}'`, TABLE_NAME: `= '${table}'` })
.where({ TABLE_SCHEMA: `= '${this._schema || schema}'`, TABLE_NAME: `= '${table}'` })
.orderBy({ ORDINAL_POSITION: 'ASC' })
.run();
const { rows: fields } = await this.raw(`SHOW CREATE TABLE \`${this._schema || schema}\`.\`${table}\``);
const remappedFields = fields.map(row => {
if (!row['Create Table']) return false;
let n = 0;
return row['Create Table']
.split('')
.reduce((acc, curr) => {
if (curr === ')') n--;
if (n !== 0) acc += curr;
if (curr === '(') n++;
return acc;
}, '')
.replaceAll('\n', '')
.split(',')
.map(f => {
try {
const fieldArr = f.trim().split(' ');
const nameAndType = fieldArr.slice(0, 2);
if (nameAndType[0].charAt(0) !== '`') return false;
const details = fieldArr.slice(2).join(' ');
let defaultValue = null;
if (details.includes('DEFAULT'))
defaultValue = details.match(/(?<=DEFAULT ).*?$/gs)[0].split(' COMMENT')[0];
const typeAndLength = nameAndType[1].replace(')', '').split('(');
return {
name: nameAndType[0].replaceAll('`', ''),
type: typeAndLength[0].toUpperCase(),
length: typeAndLength[1] ? typeAndLength[1] : null,
default: defaultValue
};
}
catch (err) {
return false;
}
})
.filter(Boolean)
.reduce((acc, curr) => {
acc[curr.name] = curr;
return acc;
}, {});
})[0];
return rows.map(field => {
let numLength = field.COLUMN_TYPE.match(/int\(([^)]+)\)/);
numLength = numLength ? +numLength.pop() : null;
const enumValues = /(enum|set)/.test(field.COLUMN_TYPE)
? field.COLUMN_TYPE.match(/\(([^)]+)\)/)[0].slice(1, -1)
: null;
return {
name: field.COLUMN_NAME,
key: field.COLUMN_KEY.toLowerCase(),
type: field.DATA_TYPE.toUpperCase(),
type: remappedFields ? remappedFields[field.COLUMN_NAME].type : field.DATA_TYPE,
schema: field.TABLE_SCHEMA,
table: field.TABLE_NAME,
numPrecision: field.NUMERIC_PRECISION,
numLength,
enumValues,
datePrecision: field.DATETIME_PRECISION,
charLength: field.CHARACTER_MAXIMUM_LENGTH,
nullable: field.IS_NULLABLE.includes('YES'),
unsigned: field.COLUMN_TYPE.includes('unsigned'),
zerofill: field.COLUMN_TYPE.includes('zerofill'),
order: field.ORDINAL_POSITION,
default: field.COLUMN_DEFAULT,
default: remappedFields ? remappedFields[field.COLUMN_NAME].default : field.COLUMN_DEFAULT,
charset: field.CHARACTER_SET_NAME,
collation: field.COLLATION_NAME,
autoIncrement: field.EXTRA.includes('auto_increment'),
@@ -484,7 +537,7 @@ export class MySQLClient extends AntaresCore {
* @memberof MySQLClient
*/
async dropView (params) {
const sql = `DROP VIEW \`${params.view}\``;
const sql = `DROP VIEW \`${this._schema}\`.\`${params.view}\``;
return await this.raw(sql);
}
@@ -496,10 +549,10 @@ export class MySQLClient extends AntaresCore {
*/
async alterView (params) {
const { view } = params;
let sql = `ALTER ALGORITHM = ${view.algorithm}${view.definer ? ` DEFINER=${view.definer}` : ''} SQL SECURITY ${view.security} VIEW \`${view.oldName}\` AS ${view.sql} ${view.updateOption ? `WITH ${view.updateOption} CHECK OPTION` : ''}`;
let sql = `ALTER ALGORITHM = ${view.algorithm}${view.definer ? ` DEFINER=${view.definer}` : ''} SQL SECURITY ${view.security} VIEW \`${this._schema}\`.\`${view.oldName}\` AS ${view.sql} ${view.updateOption ? `WITH ${view.updateOption} CHECK OPTION` : ''}`;
if (view.name !== view.oldName)
sql += `; RENAME TABLE \`${view.oldName}\` TO \`${view.name}\``;
sql += `; RENAME TABLE \`${this._schema}\`.\`${view.oldName}\` TO \`${this._schema}\`.\`${view.name}\``;
return await this.raw(sql);
}
@@ -511,7 +564,7 @@ export class MySQLClient extends AntaresCore {
* @memberof MySQLClient
*/
async createView (view) {
const sql = `CREATE ALGORITHM = ${view.algorithm} ${view.definer ? `DEFINER=${view.definer} ` : ''}SQL SECURITY ${view.security} VIEW \`${view.name}\` AS ${view.sql} ${view.updateOption ? `WITH ${view.updateOption} CHECK OPTION` : ''}`;
const sql = `CREATE ALGORITHM = ${view.algorithm} ${view.definer ? `DEFINER=${view.definer} ` : ''}SQL SECURITY ${view.security} VIEW \`${this._schema}\`.\`${view.name}\` AS ${view.sql} ${view.updateOption ? `WITH ${view.updateOption} CHECK OPTION` : ''}`;
return await this.raw(sql);
}
@@ -531,8 +584,8 @@ export class MySQLClient extends AntaresCore {
sql: row['SQL Original Statement'].match(/(BEGIN|begin)(.*)(END|end)/gs)[0],
name: row.Trigger,
table: row['SQL Original Statement'].match(/(?<=ON `).*?(?=`)/gs)[0],
event1: row['SQL Original Statement'].match(/(BEFORE|AFTER)/gs)[0],
event2: row['SQL Original Statement'].match(/(INSERT|UPDATE|DELETE)/gs)[0]
activation: row['SQL Original Statement'].match(/(BEFORE|AFTER)/gs)[0],
event: row['SQL Original Statement'].match(/(INSERT|UPDATE|DELETE)/gs)[0]
};
})[0];
}
@@ -544,7 +597,7 @@ export class MySQLClient extends AntaresCore {
* @memberof MySQLClient
*/
async dropTrigger (params) {
const sql = `DROP TRIGGER \`${params.trigger}\``;
const sql = `DROP TRIGGER \`${this._schema}\`.\`${params.trigger}\``;
return await this.raw(sql);
}
@@ -577,7 +630,7 @@ export class MySQLClient extends AntaresCore {
* @memberof MySQLClient
*/
async createTrigger (trigger) {
const sql = `CREATE ${trigger.definer ? `DEFINER=${trigger.definer} ` : ''}TRIGGER \`${trigger.name}\` ${trigger.event1} ${trigger.event2} ON \`${trigger.table}\` FOR EACH ROW ${trigger.sql}`;
const sql = `CREATE ${trigger.definer ? `DEFINER=${trigger.definer} ` : ''}TRIGGER \`${this._schema}\`.\`${trigger.name}\` ${trigger.activation} ${trigger.event} ON \`${trigger.table}\` FOR EACH ROW ${trigger.sql}`;
return await this.raw(sql, { split: false });
}
@@ -651,7 +704,7 @@ export class MySQLClient extends AntaresCore {
* @memberof MySQLClient
*/
async dropRoutine (params) {
const sql = `DROP PROCEDURE \`${params.routine}\``;
const sql = `DROP PROCEDURE \`${this._schema}\`.\`${params.routine}\``;
return await this.raw(sql);
}
@@ -691,7 +744,7 @@ export class MySQLClient extends AntaresCore {
}, []).join(',')
: '';
const sql = `CREATE ${routine.definer ? `DEFINER=${routine.definer} ` : ''}PROCEDURE \`${routine.name}\`(${parameters})
const sql = `CREATE ${routine.definer ? `DEFINER=${routine.definer} ` : ''}PROCEDURE \`${this._schema}\`.\`${routine.name}\`(${parameters})
LANGUAGE SQL
${routine.deterministic ? 'DETERMINISTIC' : 'NOT DETERMINISTIC'}
${routine.dataAccess}
@@ -778,7 +831,7 @@ export class MySQLClient extends AntaresCore {
* @memberof MySQLClient
*/
async dropFunction (params) {
const sql = `DROP FUNCTION \`${params.func}\``;
const sql = `DROP FUNCTION \`${this._schema}\`.\`${params.func}\``;
return await this.raw(sql);
}
@@ -818,7 +871,7 @@ export class MySQLClient extends AntaresCore {
const body = func.returns ? func.sql : 'BEGIN\n RETURN 0;\nEND';
const sql = `CREATE ${func.definer ? `DEFINER=${func.definer} ` : ''}FUNCTION \`${func.name}\`(${parameters}) RETURNS ${func.returns || 'SMALLINT'}${func.returnsLength ? `(${func.returnsLength})` : ''}
const sql = `CREATE ${func.definer ? `DEFINER=${func.definer} ` : ''}FUNCTION \`${this._schema}\`.\`${func.name}\`(${parameters}) RETURNS ${func.returns || 'SMALLINT'}${func.returnsLength ? `(${func.returnsLength})` : ''}
LANGUAGE SQL
${func.deterministic ? 'DETERMINISTIC' : 'NOT DETERMINISTIC'}
${func.dataAccess}
@@ -870,7 +923,7 @@ export class MySQLClient extends AntaresCore {
* @memberof MySQLClient
*/
async dropEvent (params) {
const sql = `DROP EVENT \`${params.scheduler}\``;
const sql = `DROP EVENT \`${this._schema}\`.\`${params.scheduler}\``;
return await this.raw(sql);
}
@@ -886,13 +939,13 @@ export class MySQLClient extends AntaresCore {
if (scheduler.execution === 'EVERY' && scheduler.every[0].includes('-'))
scheduler.every[0] = `'${scheduler.every[0]}'`;
const sql = `ALTER ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${scheduler.oldName}\`
const sql = `ALTER ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${this._schema}\`.\`${scheduler.oldName}\`
ON SCHEDULE
${scheduler.execution === 'EVERY'
? `EVERY ${scheduler.every.join(' ')}${scheduler.starts ? ` STARTS '${scheduler.starts}'` : ''}${scheduler.ends ? ` ENDS '${scheduler.ends}'` : ''}`
: `AT '${scheduler.at}'`}
ON COMPLETION${!scheduler.preserve ? ' NOT' : ''} PRESERVE
${scheduler.name !== scheduler.oldName ? `RENAME TO \`${scheduler.name}\`` : ''}
${scheduler.name !== scheduler.oldName ? `RENAME TO \`${this._schema}\`.\`${scheduler.name}\`` : ''}
${scheduler.state}
COMMENT '${scheduler.comment}'
DO ${scheduler.sql}`;
@@ -907,7 +960,7 @@ export class MySQLClient extends AntaresCore {
* @memberof MySQLClient
*/
async createEvent (scheduler) {
const sql = `CREATE ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${scheduler.name}\`
const sql = `CREATE ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${this._schema}\`.\`${scheduler.name}\`
ON SCHEDULE
${scheduler.execution === 'EVERY'
? `EVERY ${scheduler.every.join(' ')}${scheduler.starts ? ` STARTS '${scheduler.starts}'` : ''}${scheduler.ends ? ` ENDS '${scheduler.ends}'` : ''}`
@@ -1044,7 +1097,7 @@ export class MySQLClient extends AntaresCore {
engine
} = params;
const sql = `CREATE TABLE \`${name}\` (\`${name}_ID\` INT NULL) COMMENT='${comment}', COLLATE='${collation}', ENGINE=${engine}`;
const sql = `CREATE TABLE \`${this._schema}\`.\`${name}\` (\`${name}_ID\` INT NULL) COMMENT='${comment}', COLLATE='${collation}', ENGINE=${engine}`;
return await this.raw(sql);
}
@@ -1066,7 +1119,7 @@ export class MySQLClient extends AntaresCore {
options
} = params;
let sql = `ALTER TABLE \`${this._schema}\`.\`${table}\` `;
let sql = `ALTER TABLE \`${this._schema || params.options.schema}\`.\`${table}\` `;
const alterColumns = [];
// OPTIONS
@@ -1078,7 +1131,7 @@ export class MySQLClient extends AntaresCore {
// ADD FIELDS
additions.forEach(addition => {
const typeInfo = this._getTypeInfo(addition.type);
const length = typeInfo.length ? addition.numLength || addition.charLength || addition.datePrecision : false;
const length = typeInfo.length ? addition.enumValues || addition.numLength || addition.charLength || addition.datePrecision : false;
alterColumns.push(`ADD COLUMN \`${addition.name}\`
${addition.type.toUpperCase()}${length ? `(${length})` : ''}
@@ -1116,7 +1169,7 @@ export class MySQLClient extends AntaresCore {
// CHANGE FIELDS
changes.forEach(change => {
const typeInfo = this._getTypeInfo(change.type);
const length = typeInfo.length ? change.numLength || change.charLength || change.datePrecision : false;
const length = typeInfo.length ? change.enumValues || change.numLength || change.charLength || change.datePrecision : false;
alterColumns.push(`CHANGE COLUMN \`${change.orgName}\` \`${change.name}\`
${change.type.toUpperCase()}${length ? `(${length})` : ''}
@@ -1178,7 +1231,7 @@ export class MySQLClient extends AntaresCore {
sql += alterColumns.join(', ');
// RENAME
if (options.name) sql += `; RENAME TABLE \`${table}\` TO \`${options.name}\``;
if (options.name) sql += `; RENAME TABLE \`${this._schema}\`.\`${table}\` TO \`${this._schema}\`.\`${options.name}\``;
return await this.raw(sql);
}
@@ -1190,7 +1243,7 @@ export class MySQLClient extends AntaresCore {
* @memberof MySQLClient
*/
async truncateTable (params) {
const sql = `TRUNCATE TABLE \`${params.table}\``;
const sql = `TRUNCATE TABLE \`${this._schema}\`.\`${params.table}\``;
return await this.raw(sql);
}
@@ -1201,7 +1254,7 @@ export class MySQLClient extends AntaresCore {
* @memberof MySQLClient
*/
async dropTable (params) {
const sql = `DROP TABLE \`${params.table}\``;
const sql = `DROP TABLE \`${this._schema}\`.\`${params.table}\``;
return await this.raw(sql);
}
@@ -1256,7 +1309,10 @@ export class MySQLClient extends AntaresCore {
// LIMIT
const limitRaw = this._query.limit.length ? `LIMIT ${this._query.limit.join(', ')} ` : '';
return `${selectRaw}${updateRaw ? 'UPDATE' : ''}${insertRaw ? 'INSERT ' : ''}${this._query.delete ? 'DELETE ' : ''}${fromRaw}${updateRaw}${whereRaw}${groupByRaw}${orderByRaw}${limitRaw}${insertRaw}`;
// OFFSET
const offsetRaw = this._query.offset.length ? `OFFSET ${this._query.offset.join(', ')} ` : '';
return `${selectRaw}${updateRaw ? 'UPDATE' : ''}${insertRaw ? 'INSERT ' : ''}${this._query.delete ? 'DELETE ' : ''}${fromRaw}${updateRaw}${whereRaw}${groupByRaw}${orderByRaw}${limitRaw}${offsetRaw}${insertRaw}`;
}
/**
@@ -1269,18 +1325,24 @@ export class MySQLClient extends AntaresCore {
* @memberof MySQLClient
*/
async raw (sql, args) {
if (process.env.NODE_ENV === 'development') this._logger(sql);// TODO: replace BLOB content with a placeholder
args = {
nest: false,
details: false,
split: true,
...args
};
const nestTables = args.nest ? '.' : false;
const resultsArr = [];
let paramsArr = [];
const queries = args.split ? sql.split(';') : [sql];
const queries = args.split ? sql.split(/((?:[^;'"]*(?:"(?:\\.|[^"])*"|'(?:\\.|[^'])*')[^;'"]*)+)|;/gm) : [sql];
const isPool = typeof this._connection.getConnection === 'function';
const connection = isPool ? await this._connection.getConnection() : this._connection;
if (process.env.NODE_ENV === 'development') this._logger(sql);// TODO: replace BLOB content with a placeholder
if (args.schema)
await connection.query(`USE \`${args.schema}\``);
for (const query of queries) {
if (!query) continue;
@@ -1289,87 +1351,87 @@ export class MySQLClient extends AntaresCore {
let keysArr = [];
const { rows, report, fields, keys, duration } = await new Promise((resolve, reject) => {
this._connection.query({ sql: query, nestTables }, async (err, response, fields) => {
connection.query({ sql: query, nestTables }).then(async ([response, fields]) => {
timeStop = new Date();
const queryResult = response;
if (err)
reject(err);
else {
let remappedFields = fields
? fields.map(field => {
if (!field || Array.isArray(field))
return false;
let remappedFields = fields
? fields.map(field => {
if (!field || Array.isArray(field))
return false;
const type = this._getType(field);
const type = this._getType(field);
return {
name: field.orgName,
alias: field.name,
orgName: field.orgName,
schema: field.schema,
table: field.table,
tableAlias: field.table,
orgTable: field.orgTable,
type: type.name,
length: type.length
};
}).filter(Boolean)
: [];
if (args.details) {
let cachedTable;
if (remappedFields.length) {
paramsArr = remappedFields.map(field => {
if (field.orgTable) cachedTable = field.orgTable;// Needed for some queries on information_schema
return {
name: field.orgName,
alias: field.name,
orgName: field.orgName,
schema: field.schema,
table: field.table,
tableAlias: field.table,
orgTable: field.orgTable,
type: type.name,
length: type.length
table: field.orgTable || cachedTable,
schema: field.schema || 'INFORMATION_SCHEMA'
};
}).filter(Boolean)
: [];
}).filter((val, i, arr) => arr.findIndex(el => el.schema === val.schema && el.table === val.table) === i);
if (args.details) {
let cachedTable;
for (const paramObj of paramsArr) {
if (!paramObj.table || !paramObj.schema) continue;
if (remappedFields.length) {
paramsArr = remappedFields.map(field => {
if (field.orgTable) cachedTable = field.orgTable;// Needed for some queries on information_schema
return {
table: field.orgTable || cachedTable,
schema: field.schema || 'INFORMATION_SCHEMA'
};
}).filter((val, i, arr) => arr.findIndex(el => el.schema === val.schema && el.table === val.table) === i);
try { // Column details
const response = await this.getTableColumns(paramObj);
remappedFields = remappedFields.map(field => {
const detailedField = response.find(f => f.name === field.name);
if (detailedField && field.orgTable === paramObj.table && field.schema === paramObj.schema)
field = { ...field, ...detailedField };
return field;
});
}
catch (err) {
if (isPool) connection.release();
reject(err);
}
for (const paramObj of paramsArr) {
if (!paramObj.table || !paramObj.schema) continue;
try { // Column details
const response = await this.getTableColumns(paramObj);
remappedFields = remappedFields.map(field => {
const detailedField = response.find(f => f.name === field.name);
if (detailedField && field.orgTable === paramObj.table && field.schema === paramObj.schema)
field = { ...detailedField, ...field };
return field;
});
}
catch (err) {
reject(err);
}
try { // Key usage (foreign keys)
const response = await this.getKeyUsage(paramObj);
keysArr = keysArr ? [...keysArr, ...response] : response;
}
catch (err) {
reject(err);
}
try { // Key usage (foreign keys)
const response = await this.getKeyUsage(paramObj);
keysArr = keysArr ? [...keysArr, ...response] : response;
}
catch (err) {
if (isPool) connection.release();
reject(err);
}
}
}
resolve({
duration: timeStop - timeStart,
rows: Array.isArray(queryResult) ? queryResult.some(el => Array.isArray(el)) ? [] : queryResult : false,
report: !Array.isArray(queryResult) ? queryResult : false,
fields: remappedFields,
keys: keysArr
});
}
});
resolve({
duration: timeStop - timeStart,
rows: Array.isArray(queryResult) ? queryResult.some(el => Array.isArray(el)) ? [] : queryResult : false,
report: !Array.isArray(queryResult) ? queryResult : false,
fields: remappedFields,
keys: keysArr
});
}).catch(reject);
});
resultsArr.push({ rows, report, fields, keys, duration });
}
if (isPool) connection.release();
return resultsArr.length === 1 ? resultsArr[0] : resultsArr;
}
}

View File

@@ -77,7 +77,8 @@ export class PostgreSQLClient extends AntaresCore {
*/
use (schema) {
this._schema = schema;
return this.raw(`SET search_path TO ${schema}`);
if (schema)
return this.raw(`SET search_path TO ${schema}`);
}
/**
@@ -186,12 +187,14 @@ export class PostgreSQLClient extends AntaresCore {
// TRIGGERS
const remappedTriggers = triggersArr.filter(trigger => trigger.Db === db.database).map(trigger => {
return {
name: trigger.trigger_name,
name: `${trigger.table_name}.${trigger.trigger_name}`,
orgName: trigger.trigger_name,
timing: trigger.activation,
definer: trigger.definition, // ???
definer: '',
definition: trigger.definition,
event: trigger.event,
table: trigger.table_trigger,
sqlMode: trigger.sql_mode
table: trigger.table_name,
sqlMode: ''
};
});
@@ -274,7 +277,7 @@ export class PostgreSQLClient extends AntaresCore {
*/
async getTableIndexes ({ schema, table }) {
if (schema !== 'public')
this.use(schema);
await this.use(schema);
const { rows } = await this.raw(`WITH ndx_list AS (
SELECT pg_index.indexrelid, pg_class.oid
@@ -493,17 +496,33 @@ export class PostgreSQLClient extends AntaresCore {
* @memberof PostgreSQLClient
*/
async getTriggerInformations ({ schema, trigger }) {
const sql = `SHOW CREATE TRIGGER \`${schema}\`.\`${trigger}\``;
const results = await this.raw(sql);
const [table, triggerName] = trigger.split('.');
const results = await this.raw(`
SELECT event_object_schema AS table_schema,
event_object_table AS table_name,
trigger_schema,
trigger_name,
string_agg(event_manipulation, ',') AS event,
action_timing AS activation,
action_condition AS condition,
action_statement AS definition
FROM information_schema.triggers
WHERE trigger_schema = '${schema}'
AND trigger_name = '${triggerName}'
AND event_object_table = '${table}'
GROUP BY 1,2,3,4,6,7,8
ORDER BY table_schema,
table_name
`);
return results.rows.map(row => {
return {
definer: row['SQL Original Statement'].match(/(?<=DEFINER=).*?(?=\s)/gs)[0],
sql: row['SQL Original Statement'].match(/(BEGIN|begin)(.*)(END|end)/gs)[0],
name: row.Trigger,
table: row['SQL Original Statement'].match(/(?<=ON `).*?(?=`)/gs)[0],
event1: row['SQL Original Statement'].match(/(BEFORE|AFTER)/gs)[0],
event2: row['SQL Original Statement'].match(/(INSERT|UPDATE|DELETE)/gs)[0]
sql: row.definition,
name: row.trigger_name,
table: row.table_name,
event: row.event.split(','),
activation: row.activation
};
})[0];
}
@@ -515,7 +534,8 @@ export class PostgreSQLClient extends AntaresCore {
* @memberof PostgreSQLClient
*/
async dropTrigger (params) {
const sql = `DROP TRIGGER \`${params.trigger}\``;
const triggerParts = params.trigger.split('.');
const sql = `DROP TRIGGER ${triggerParts[1]} ON ${triggerParts[0]}`;
return await this.raw(sql);
}
@@ -527,18 +547,21 @@ export class PostgreSQLClient extends AntaresCore {
*/
async alterTrigger (params) {
const { trigger } = params;
const tempTrigger = Object.assign({}, trigger);
tempTrigger.name = `Antares_${tempTrigger.name}_tmp`;
// const tempTrigger = Object.assign({}, trigger);
// tempTrigger.name = `Antares_${tempTrigger.name}_tmp`;
try {
await this.createTrigger(tempTrigger);
await this.dropTrigger({ trigger: tempTrigger.name });
await this.dropTrigger({ trigger: trigger.oldName });
await this.createTrigger(trigger);
}
catch (err) {
return Promise.reject(err);
}
// try {
// await this.createTrigger(tempTrigger);
// await this.dropTrigger({ trigger: tempTrigger.name });
// await this.dropTrigger({ trigger: trigger.oldName });
// await this.createTrigger(trigger);
// }
// catch (err) {
// return Promise.reject(err);
// }
const sql = `ALTER TRIGGER ${trigger.oldName} ON ${trigger.table} RENAME TO ${trigger.name}`;
return await this.raw(sql);
}
/**
@@ -548,7 +571,7 @@ export class PostgreSQLClient extends AntaresCore {
* @memberof PostgreSQLClient
*/
async createTrigger (trigger) {
const sql = `CREATE ${trigger.definer ? `DEFINER=${trigger.definer} ` : ''}TRIGGER \`${trigger.name}\` ${trigger.event1} ${trigger.event2} ON \`${trigger.table}\` FOR EACH ROW ${trigger.sql}`;
const sql = `CREATE ${trigger.definer ? `DEFINER=${trigger.definer} ` : ''}TRIGGER \`${trigger.name}\` ${trigger.event} ${trigger.activation} ON \`${trigger.table}\` FOR EACH ROW ${trigger.sql}`;
return await this.raw(sql, { split: false });
}
@@ -670,7 +693,7 @@ export class PostgreSQLClient extends AntaresCore {
: '';
if (this._schema !== 'public')
this.use(this._schema);
await this.use(this._schema);
const sql = `CREATE PROCEDURE ${this._schema}.${routine.name}(${parameters})
LANGUAGE ${routine.language}
@@ -799,7 +822,7 @@ export class PostgreSQLClient extends AntaresCore {
: '';
if (this._schema !== 'public')
this.use(this._schema);
await this.use(this._schema);
const body = func.returns ? func.sql : '$BODY$\n$BODY$';
@@ -812,97 +835,6 @@ export class PostgreSQLClient extends AntaresCore {
return await this.raw(sql, { split: false });
}
/**
* SHOW CREATE EVENT
*
* @returns {Array.<Object>} view informations
* @memberof PostgreSQLClient
*/
// async getEventInformations ({ schema, scheduler }) {
// const sql = `SHOW CREATE EVENT \`${schema}\`.\`${scheduler}\``;
// const results = await this.raw(sql);
// return results.rows.map(row => {
// const schedule = row['Create Event'];
// const execution = schedule.includes('EVERY') ? 'EVERY' : 'ONCE';
// const every = execution === 'EVERY' ? row['Create Event'].match(/(?<=EVERY )(\s*([^\s]+)){0,2}/gs)[0].replaceAll('\'', '').split(' ') : [];
// const starts = execution === 'EVERY' && schedule.includes('STARTS') ? schedule.match(/(?<=STARTS ').*?(?='\s)/gs)[0] : '';
// const ends = execution === 'EVERY' && schedule.includes('ENDS') ? schedule.match(/(?<=ENDS ').*?(?='\s)/gs)[0] : '';
// const at = execution === 'ONCE' && schedule.includes('AT') ? schedule.match(/(?<=AT ').*?(?='\s)/gs)[0] : '';
// return {
// definer: row['Create Event'].match(/(?<=DEFINER=).*?(?=\s)/gs)[0],
// sql: row['Create Event'].match(/(?<=DO )(.*)/gs)[0],
// name: row.Event,
// comment: row['Create Event'].match(/(?<=COMMENT ').*?(?=')/gs) ? row['Create Event'].match(/(?<=COMMENT ').*?(?=')/gs)[0] : '',
// state: row['Create Event'].includes('ENABLE') ? 'ENABLE' : row['Create Event'].includes('DISABLE ON SLAVE') ? 'DISABLE ON SLAVE' : 'DISABLE',
// preserve: row['Create Event'].includes('ON COMPLETION PRESERVE'),
// execution,
// every,
// starts,
// ends,
// at
// };
// })[0];
// }
/**
* DROP EVENT
*
* @returns {Array.<Object>} parameters
* @memberof PostgreSQLClient
*/
// async dropEvent (params) {
// const sql = `DROP EVENT \`${params.scheduler}\``;
// return await this.raw(sql);
// }
/**
* ALTER EVENT
*
* @returns {Array.<Object>} parameters
* @memberof PostgreSQLClient
*/
// async alterEvent (params) {
// const { scheduler } = params;
// if (scheduler.execution === 'EVERY' && scheduler.every[0].includes('-'))
// scheduler.every[0] = `'${scheduler.every[0]}'`;
// const sql = `ALTER ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${scheduler.oldName}\`
// ON SCHEDULE
// ${scheduler.execution === 'EVERY'
// ? `EVERY ${scheduler.every.join(' ')}${scheduler.starts ? ` STARTS '${scheduler.starts}'` : ''}${scheduler.ends ? ` ENDS '${scheduler.ends}'` : ''}`
// : `AT '${scheduler.at}'`}
// ON COMPLETION${!scheduler.preserve ? ' NOT' : ''} PRESERVE
// ${scheduler.name !== scheduler.oldName ? `RENAME TO \`${scheduler.name}\`` : ''}
// ${scheduler.state}
// COMMENT '${scheduler.comment}'
// DO ${scheduler.sql}`;
// return await this.raw(sql, { split: false });
// }
/**
* CREATE EVENT
*
* @returns {Array.<Object>} parameters
* @memberof PostgreSQLClient
*/
// async createEvent (scheduler) {
// const sql = `CREATE ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${scheduler.name}\`
// ON SCHEDULE
// ${scheduler.execution === 'EVERY'
// ? `EVERY ${scheduler.every.join(' ')}${scheduler.starts ? ` STARTS '${scheduler.starts}'` : ''}${scheduler.ends ? ` ENDS '${scheduler.ends}'` : ''}`
// : `AT '${scheduler.at}'`}
// ON COMPLETION${!scheduler.preserve ? ' NOT' : ''} PRESERVE
// ${scheduler.state}
// COMMENT '${scheduler.comment}'
// DO ${scheduler.sql}`;
// return await this.raw(sql, { split: false });
// }
/**
* SELECT * FROM pg_collation
*
@@ -1018,7 +950,7 @@ export class PostgreSQLClient extends AntaresCore {
} = params;
if (this._schema !== 'public')
this.use(this._schema);
await this.use(this._schema);
let sql = '';
const alterColumns = [];
@@ -1226,7 +1158,10 @@ export class PostgreSQLClient extends AntaresCore {
// LIMIT
const limitRaw = selectArray.length && this._query.limit.length ? `LIMIT ${this._query.limit.join(', ')} ` : '';
return `${selectRaw}${updateRaw ? 'UPDATE' : ''}${insertRaw ? 'INSERT ' : ''}${this._query.delete ? 'DELETE ' : ''}${fromRaw}${updateRaw}${whereRaw}${groupByRaw}${orderByRaw}${limitRaw}${insertRaw}`;
// OFFSET
const offsetRaw = selectArray.length && this._query.offset.length ? `OFFSET ${this._query.offset.join(', ')} ` : '';
return `${selectRaw}${updateRaw ? 'UPDATE' : ''}${insertRaw ? 'INSERT ' : ''}${this._query.delete ? 'DELETE ' : ''}${fromRaw}${updateRaw}${whereRaw}${groupByRaw}${orderByRaw}${limitRaw}${offsetRaw}${insertRaw}`;
}
/**
@@ -1246,12 +1181,12 @@ export class PostgreSQLClient extends AntaresCore {
...args
};
if (args.nest && this._schema !== 'public')
this.use(this._schema);
if (args.schema && args.schema !== 'public')
await this.use(args.schema);
const resultsArr = [];
let paramsArr = [];
const queries = args.split ? sql.split(';') : [sql];
const queries = args.split ? sql.split(/(?!\B'[^']*);(?![^']*'\B)/gm) : [sql];
if (process.env.NODE_ENV === 'development') this._logger(sql);// TODO: replace BLOB content with a placeholder

View File

@@ -25,7 +25,8 @@
<script>
import { mapActions, mapGetters } from 'vuex';
import { ipcRenderer, remote } from 'electron';
import { ipcRenderer } from 'electron';
import { Menu, getCurrentWindow } from '@electron/remote';
export default {
name: 'App',
@@ -60,8 +61,6 @@ export default {
ipcRenderer.send('check-for-updates');
this.checkVersionUpdate();
const Menu = remote.Menu;
const InputMenu = Menu.buildFromTemplate([
{
label: this.$t('word.cut'),
@@ -92,7 +91,7 @@ export default {
while (node) {
if (node.nodeName.match(/^(input|textarea)$/i) || node.isContentEditable) {
InputMenu.popup(remote.getCurrentWindow());
InputMenu.popup(getCurrentWindow());
break;
}
node = node.parentNode;

View File

@@ -66,6 +66,21 @@
:type="inputProps().type"
:disabled="!isChecked"
>
<select
v-else-if="enumArray"
v-model="selectedValue"
class="form-select"
:disabled="!isChecked"
@change="onChange"
>
<option
v-for="val in enumArray"
:key="val"
:value="val"
>
{{ val }}
</option>
</select>
<input
v-else
ref="formInput"
@@ -121,7 +136,8 @@ export default {
selectedMethod: '',
selectedValue: '',
debounceTimeout: null,
methodParams: {}
methodParams: {},
enumArray: null
};
},
computed: {
@@ -150,8 +166,14 @@ export default {
},
watch: {
fieldObj () {
if (this.fieldObj)
this.selectedValue = this.fieldObj.value;
if (this.fieldObj) {
if (Array.isArray(this.fieldObj.value)) {
this.enumArray = this.fieldObj.value;
this.selectedValue = this.fieldObj.value[0];
}
else
this.selectedValue = this.fieldObj.value;
}
},
selectedGroup () {
if (this.fakerMethods.length)

View File

@@ -51,7 +51,8 @@ export default {
}),
isValidDefault () {
if (!this.foreignList.length) return true;
return this.value === null || this.foreignList.some(foreign => foreign.foreign_column.toString() === this.value.toString());
if (this.value === null) return false;
return this.foreignList.some(foreign => foreign.foreign_column.toString() === this.value.toString());
}
},
async created () {
@@ -65,7 +66,7 @@ export default {
try { // Field data
const { status, response } = await Tables.getTableColumns(params);
if (status === 'success') {
const textField = response.find(field => [...TEXT, ...LONG_TEXT].includes(field.type));
const textField = response.find(field => [...TEXT, ...LONG_TEXT].includes(field.type) && field.name !== this.keyUsage.refField);
foreignDesc = textField ? textField.name : false;
}
else

View File

@@ -26,7 +26,7 @@
<div class="input-group">
<input
:ref="i === 0 ? 'firstInput' : ''"
v-model="values[parameter.name]"
v-model="values[`${i}-${parameter.name}`]"
class="form-input"
type="text"
>
@@ -88,7 +88,7 @@ export default {
return '';
},
runRoutine () {
const valArr = Object.keys(this.values).reduce((acc, curr) => {
const valArr = Object.keys(this.values).reduce((acc, curr, i) => {
let qc;
switch (this.client) {
case 'maria':
@@ -102,7 +102,7 @@ export default {
qc = '"';
}
const param = this.localRoutine.parameters.find(param => param.name === curr);
const param = this.localRoutine.parameters.find(param => `${i}-${param.name}` === curr);
const value = [...NUMBER, ...FLOAT].includes(param.type) ? this.values[curr] : `${qc}${this.values[curr]}${qc}`;
acc.push(value);

View File

@@ -250,10 +250,15 @@ export default {
if (field.default === 'NULL') fieldDefault = null;
else {
if ([...NUMBER, ...FLOAT].includes(field.type))
fieldDefault = +field.default;
fieldDefault = Number.isNaN(+field.default) ? null : +field.default;
if ([...TEXT, ...LONG_TEXT].includes(field.type))
fieldDefault = field.default ? field.default.substring(1, field.default.length - 1) : '';
if ([...TEXT, ...LONG_TEXT].includes(field.type)) {
fieldDefault = field.default
? field.default.includes('\'')
? field.default.split('\'')[1]
: field.default
: '';
}
if ([...TIME, ...DATE].includes(field.type))
fieldDefault = field.default;
@@ -269,6 +274,9 @@ export default {
fieldDefault = moment().format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
}
}
if (field.enumValues)
fieldDefault = field.enumValues.replaceAll('\'', '').split(',');
}
rowObj[field.name] = { value: fieldDefault };

View File

@@ -71,11 +71,11 @@
</label>
<div class="column">
<div class="input-group">
<select v-model="localTrigger.event1" class="form-select">
<select v-model="localTrigger.activation" class="form-select">
<option>BEFORE</option>
<option>AFTER</option>
</select>
<select v-model="localTrigger.event2" class="form-select">
<select v-model="localTrigger.event" class="form-select">
<option>INSERT</option>
<option>UPDATE</option>
<option>DELETE</option>
@@ -106,8 +106,8 @@ export default {
sql: 'BEGIN\r\n\r\nEND',
name: '',
table: '',
event1: 'BEFORE',
event2: 'INSERT'
activation: 'BEFORE',
event: 'INSERT'
},
isOptionsChanging: false
};

View File

@@ -83,6 +83,27 @@
</select>
</div>
</div>
<div class="form-group">
<div class="col-6 col-sm-12">
<label class="form-label">
{{ $t('message.dataTabPageSize') }}
</label>
</div>
<div class="col-6 col-sm-12">
<select
v-model="localPageSize"
class="form-select"
@change="changePageSize(+localPageSize)"
>
<option
v-for="size in pageSizes"
:key="size"
>
{{ size }}
</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-6 col-sm-12">
<label class="form-label">
@@ -227,7 +248,7 @@
<h4>{{ appName }}</h4>
<p>
{{ $t('word.version') }} {{ appVersion }}<br>
<a class="c-hand" @click="openOutside('https://github.com/Fabio286/antares')">GitHub</a> | <a class="c-hand" @click="openOutside('https://antares-sql.app/')">Website</a><br>
<a class="c-hand" @click="openOutside('https://github.com/Fabio286/antares')"><i class="mdi mdi-github d-inline" /> GitHub</a> <a class="c-hand" @click="openOutside('https://twitter.com/AntaresSQL')"><i class="mdi mdi-twitter d-inline" /> Twitter</a> <a class="c-hand" @click="openOutside('https://antares-sql.app/')"><i class="mdi mdi-web d-inline" /> Website</a><br>
<small>{{ $t('word.author') }} <a class="c-hand" @click="openOutside('https://github.com/Fabio286')">Fabio Di Stasio</a></small><br>
<small>{{ $t('message.madeWithJS') }}</small>
</p>
@@ -257,9 +278,11 @@ export default {
data () {
return {
localLocale: null,
localPageSize: null,
localTimeout: null,
localEditorTheme: null,
selectedTab: 'general',
pageSizes: [40, 100, 250, 500, 1000],
editorThemes: [
{
group: this.$t('word.light'),
@@ -317,6 +340,7 @@ export default {
appVersion: 'application/appVersion',
selectedSettingTab: 'application/selectedSettingTab',
selectedLocale: 'settings/getLocale',
pageSize: 'settings/getDataTabLimit',
selectedAutoComplete: 'settings/getAutoComplete',
selectedLineWrap: 'settings/getLineWrap',
notificationsTimeout: 'settings/getNotificationsTimeout',
@@ -359,6 +383,7 @@ ORDER BY
},
created () {
this.localLocale = this.selectedLocale;
this.localPageSize = this.pageSize;
this.localTimeout = this.notificationsTimeout;
this.localEditorTheme = this.editorTheme;
this.selectedTab = this.selectedSettingTab;
@@ -371,6 +396,7 @@ ORDER BY
...mapActions({
closeModal: 'application/hideSettingModal',
changeLocale: 'settings/changeLocale',
changePageSize: 'settings/changePageSize',
changeAutoComplete: 'settings/changeAutoComplete',
changeLineWrap: 'settings/changeLineWrap',
changeApplicationTheme: 'settings/changeApplicationTheme',

View File

@@ -15,6 +15,7 @@
</template>
<script>
import { mapGetters } from 'vuex';
import marked from 'marked';
import BaseLoader from '@/components/BaseLoader';
@@ -31,13 +32,16 @@ export default {
isError: false
};
},
computed: {
...mapGetters({ appVersion: 'application/appVersion' })
},
created () {
this.getChangelog();
},
methods: {
async getChangelog () {
try {
const apiRes = await fetch('https://api.github.com/repos/Fabio286/antares/releases/latest', {
const apiRes = await fetch(`https://api.github.com/repos/Fabio286/antares/releases/tags/v${this.appVersion}`, {
method: 'GET'
});

View File

@@ -19,7 +19,7 @@
@contextmenu.prevent="contextMenu($event, connection)"
@mouseover.self="tooltipPosition"
>
<i class="settingbar-element-icon dbi" :class="`dbi-${connection.client} ${connected.includes(connection.uid) ? 'badge' : ''}`" />
<i class="settingbar-element-icon dbi" :class="`dbi-${connection.client} ${getStatusBadge(connection.uid)}`" />
<span class="ex-tooltip-content">{{ getConnectionName(connection.uid) }}</span>
</li>
</draggable>
@@ -73,7 +73,7 @@ export default {
...mapGetters({
getConnections: 'connections/getConnections',
getConnectionName: 'connections/getConnectionName',
connected: 'workspaces/getConnected',
getWorkspace: 'workspaces/getWorkspace',
selectedWorkspace: 'workspaces/getSelected',
updateStatus: 'application/getUpdateStatus'
}),
@@ -109,6 +109,22 @@ export default {
const el = e.target;
const fromTop = window.pageYOffset + el.getBoundingClientRect().top - (el.offsetHeight / 4);
el.querySelector('.ex-tooltip-content').style.top = `${fromTop}px`;
},
getStatusBadge (uid) {
if (this.getWorkspace(uid)) {
const status = this.getWorkspace(uid).connection_status;
switch (status) {
case 'connected':
return 'badge badge-connected';
case 'connecting':
return 'badge badge-connecting';
case 'failed':
return 'badge badge-failed';
default:
return '';
}
}
}
}
};

View File

@@ -37,15 +37,16 @@
</template>
<script>
import { remote, ipcRenderer } from 'electron';
import { ipcRenderer } from 'electron';
import { getCurrentWindow } from '@electron/remote';
import { mapGetters } from 'vuex';
export default {
name: 'TheTitleBar',
data () {
return {
w: remote.getCurrentWindow(),
isMaximized: remote.getCurrentWindow().isMaximized(),
w: getCurrentWindow(),
isMaximized: getCurrentWindow().isMaximized(),
isDevelopment: process.env.NODE_ENV === 'development'
};
},
@@ -132,7 +133,7 @@ export default {
.titlebar-logo {
height: $titlebar-height;
padding: 0 0.4rem;
padding: 0.3rem 0.4rem;
}
.titlebar-element {

View File

@@ -1,7 +1,7 @@
<template>
<div v-show="isSelected" class="workspace column columns col-gapless">
<WorkspaceExploreBar :connection="connection" :is-selected="isSelected" />
<div v-if="workspace.connected" class="workspace-tabs column columns col-gapless">
<div v-if="workspace.connection_status === 'connected'" class="workspace-tabs column columns col-gapless">
<ul
id="tabWrap"
ref="tabWrap"

View File

@@ -8,7 +8,7 @@
>
<div class="workspace-explorebar-header">
<span class="workspace-explorebar-title">{{ connectionName }}</span>
<span v-if="workspace.connected" class="workspace-explorebar-tools">
<span v-if="workspace.connection_status === 'connected'" class="workspace-explorebar-tools">
<i
class="mdi mdi-18px mdi-database-plus c-hand mr-2"
:title="$t('message.createNewSchema')"
@@ -28,7 +28,7 @@
</span>
</div>
<div class="workspace-explorebar-search">
<div v-if="workspace.connected" class="has-icon-right">
<div v-if="workspace.connection_status === 'connected'" class="has-icon-right">
<input
v-model="searchTerm"
class="form-input input-sm"
@@ -39,7 +39,7 @@
</div>
</div>
<WorkspaceConnectPanel
v-if="!workspace.connected"
v-if="workspace.connection_status !== 'connected'"
class="workspace-explorebar-body"
:connection="connection"
/>

View File

@@ -80,6 +80,9 @@
<option v-if="localOptions.returns === 'VOID'">
VOID
</option>
<option v-if="!isInDataTypes">
{{ localOptions.returns }}
</option>
<optgroup
v-for="group in workspace.dataTypes"
:key="group.group"
@@ -178,6 +181,16 @@ export default {
},
customizations () {
return this.workspace.customizations;
},
isInDataTypes () {
let typeNames = [];
for (const group of this.workspace.dataTypes) {
typeNames = group.types.reduce((acc, curr) => {
acc.push(curr.name);
return acc;
}, []);
}
return typeNames.includes(this.localOptions.returns);
}
},
created () {

View File

@@ -7,6 +7,7 @@
class="btn btn-primary btn-sm"
:disabled="!isChanged"
:class="{'loading':isSaving}"
title="CTRL+S"
@click="saveChanges"
>
<span>{{ $t('word.save') }}</span>
@@ -150,6 +151,7 @@ export default {
computed: {
...mapGetters({
getWorkspace: 'workspaces/getWorkspace',
selectedWorkspace: 'workspaces/getSelected',
getDatabaseVariable: 'workspaces/getDatabaseVariable'
}),
workspace () {
@@ -163,7 +165,7 @@ export default {
return this.getDatabaseVariable(this.connection.uid, 'default_storage_engine').value || '';
},
isSelected () {
return this.workspace.selected_tab === 'prop';
return this.workspace.selected_tab === 'prop' && this.selectedWorkspace === this.workspace.uid && this.table;
},
schema () {
return this.workspace.breadcrumbs.schema;
@@ -200,6 +202,12 @@ export default {
this.setUnsavedChanges(val);
}
},
created () {
window.addEventListener('keydown', this.onKey);
},
beforeDestroy () {
window.removeEventListener('keydown', this.onKey);
},
methods: {
...mapActions({
addNotification: 'notifications/addNotification',
@@ -225,6 +233,20 @@ export default {
const { status, response } = await Tables.getTableColumns(params);
if (status === 'success') {
this.originalFields = response.map(field => {
if (field.autoIncrement)
field.defaultType = 'autoincrement';
else if (field.default === null)
field.defaultType = 'noval';
else if (field.default === 'NULL')
field.defaultType = 'null';
else if (isNaN(+field.default) && field.default.charAt(0) !== '\'')
field.defaultType = 'expression';
else {
field.defaultType = 'custom';
if (isNaN(+field.default) && !field.default.includes('\''))
field.default = `'${field.default}'`;
}
return { ...field, _id: uidGen() };
});
this.localFields = JSON.parse(JSON.stringify(this.originalFields));
@@ -519,6 +541,15 @@ export default {
},
foreignsUpdate (foreigns) {
this.localKeyUsage = foreigns;
},
onKey (e) {
if (this.isSelected) {
e.stopPropagation();
if (e.ctrlKey && e.keyCode === 83) { // CTRL + S
if (this.isChanged)
this.saveChanges();
}
}
}
}
};

View File

@@ -7,6 +7,7 @@
class="btn btn-primary btn-sm"
:disabled="!isChanged"
:class="{'loading':isSaving}"
title="CTRL+S"
@click="saveChanges"
>
<span>{{ $t('word.save') }}</span>
@@ -120,13 +121,14 @@ export default {
},
computed: {
...mapGetters({
selectedWorkspace: 'workspaces/getSelected',
getWorkspace: 'workspaces/getWorkspace'
}),
workspace () {
return this.getWorkspace(this.connection.uid);
},
isSelected () {
return this.workspace.selected_tab === 'prop';
return this.workspace.selected_tab === 'prop' && this.selectedWorkspace === this.workspace.uid && this.function;
},
schema () {
return this.workspace.breadcrumbs.schema;
@@ -171,6 +173,12 @@ export default {
destroyed () {
window.removeEventListener('resize', this.resizeQueryEditor);
},
created () {
window.addEventListener('keydown', this.onKey);
},
beforeDestroy () {
window.removeEventListener('keydown', this.onKey);
},
methods: {
...mapActions({
addNotification: 'notifications/addNotification',
@@ -312,6 +320,15 @@ export default {
},
hideAskParamsModal () {
this.isAskingParameters = false;
},
onKey (e) {
if (this.isSelected) {
e.stopPropagation();
if (e.ctrlKey && e.keyCode === 83) { // CTRL + S
if (this.isChanged)
this.saveChanges();
}
}
}
}
};

View File

@@ -7,6 +7,7 @@
class="btn btn-primary btn-sm"
:disabled="!isChanged"
:class="{'loading':isSaving}"
title="CTRL+S"
@click="saveChanges"
>
<span>{{ $t('word.save') }}</span>
@@ -121,13 +122,14 @@ export default {
},
computed: {
...mapGetters({
selectedWorkspace: 'workspaces/getSelected',
getWorkspace: 'workspaces/getWorkspace'
}),
workspace () {
return this.getWorkspace(this.connection.uid);
},
isSelected () {
return this.workspace.selected_tab === 'prop';
return this.workspace.selected_tab === 'prop' && this.selectedWorkspace === this.workspace.uid && this.routine;
},
schema () {
return this.workspace.breadcrumbs.schema;
@@ -172,6 +174,12 @@ export default {
destroyed () {
window.removeEventListener('resize', this.resizeQueryEditor);
},
created () {
window.addEventListener('keydown', this.onKey);
},
beforeDestroy () {
window.removeEventListener('keydown', this.onKey);
},
methods: {
...mapActions({
addNotification: 'notifications/addNotification',
@@ -310,6 +318,15 @@ export default {
},
hideAskParamsModal () {
this.isAskingParameters = false;
},
onKey (e) {
if (this.isSelected) {
e.stopPropagation();
if (e.ctrlKey && e.keyCode === 83) { // CTRL + S
if (this.isChanged)
this.saveChanges();
}
}
}
}
};

View File

@@ -7,6 +7,7 @@
class="btn btn-primary btn-sm"
:disabled="!isChanged"
:class="{'loading':isSaving}"
title="CTRL+S"
@click="saveChanges"
>
<span>{{ $t('word.save') }}</span>
@@ -169,13 +170,14 @@ export default {
},
computed: {
...mapGetters({
selectedWorkspace: 'workspaces/getSelected',
getWorkspace: 'workspaces/getWorkspace'
}),
workspace () {
return this.getWorkspace(this.connection.uid);
},
isSelected () {
return this.workspace.selected_tab === 'prop';
return this.workspace.selected_tab === 'prop' && this.selectedWorkspace === this.workspace.uid && this.scheduler;
},
schema () {
return this.workspace.breadcrumbs.schema;
@@ -220,6 +222,12 @@ export default {
destroyed () {
window.removeEventListener('resize', this.resizeQueryEditor);
},
created () {
window.addEventListener('keydown', this.onKey);
},
beforeDestroy () {
window.removeEventListener('keydown', this.onKey);
},
methods: {
...mapActions({
addNotification: 'notifications/addNotification',
@@ -310,6 +318,15 @@ export default {
},
timingUpdate (options) {
this.localScheduler = options;
},
onKey (e) {
if (this.isSelected) {
e.stopPropagation();
if (e.ctrlKey && e.keyCode === 83) { // CTRL + S
if (this.isChanged)
this.saveChanges();
}
}
}
}
};

View File

@@ -7,6 +7,7 @@
class="btn btn-primary btn-sm"
:disabled="!isChanged"
:class="{'loading':isSaving}"
title="CTRL+S"
@click="saveChanges"
>
<span>{{ $t('word.save') }}</span>
@@ -36,7 +37,7 @@
>
</div>
</div>
<div class="column col-auto">
<div v-if="customizations.definer" class="column col-auto">
<div class="form-group">
<label class="form-label">{{ $t('word.definer') }}</label>
<select
@@ -66,7 +67,7 @@
</div>
</div>
</div>
<div class="columns">
<fieldset class="columns" :disabled="customizations.triggerOnlyRename">
<div class="column col-auto">
<div class="form-group">
<label class="form-label">{{ $t('word.table') }}</label>
@@ -81,19 +82,33 @@
<div class="form-group">
<label class="form-label">{{ $t('word.event') }}</label>
<div class="input-group">
<select v-model="localTrigger.event1" class="form-select">
<select v-model="localTrigger.activation" class="form-select">
<option>BEFORE</option>
<option>AFTER</option>
</select>
<select v-model="localTrigger.event2" class="form-select">
<option>INSERT</option>
<option>UPDATE</option>
<option>DELETE</option>
<select
v-if="!customizations.triggerMultipleEvents"
v-model="localTrigger.event"
class="form-select"
>
<option v-for="event in Object.keys(localEvents)" :key="event">
{{ event }}
</option>
</select>
<div v-if="customizations.triggerMultipleEvents" class="px-4">
<label
v-for="event in Object.keys(localEvents)"
:key="event"
class="form-checkbox form-inline"
@change.prevent="changeEvents(event)"
>
<input :checked="localEvents[event]" type="checkbox"><i class="form-icon" /> {{ event }}
</label>
</div>
</div>
</div>
</div>
</div>
</fieldset>
</div>
<div class="workspace-query-results column col-12 mt-2 p-relative">
<BaseLoader v-if="isLoading" />
@@ -135,18 +150,23 @@ export default {
localTrigger: { sql: '' },
lastTrigger: null,
sqlProxy: '',
editorHeight: 300
editorHeight: 300,
localEvents: { INSERT: false, UPDATE: false, DELETE: false }
};
},
computed: {
...mapGetters({
selectedWorkspace: 'workspaces/getSelected',
getWorkspace: 'workspaces/getWorkspace'
}),
workspace () {
return this.getWorkspace(this.connection.uid);
},
customizations () {
return this.workspace.customizations;
},
isSelected () {
return this.workspace.selected_tab === 'prop';
return this.workspace.selected_tab === 'prop' && this.selectedWorkspace === this.workspace.uid && this.trigger;
},
schema () {
return this.workspace.breadcrumbs.schema;
@@ -191,6 +211,12 @@ export default {
destroyed () {
window.removeEventListener('resize', this.resizeQueryEditor);
},
created () {
window.addEventListener('keydown', this.onKey);
},
beforeDestroy () {
window.removeEventListener('keydown', this.onKey);
},
methods: {
...mapActions({
addNotification: 'notifications/addNotification',
@@ -201,6 +227,10 @@ export default {
async getTriggerData () {
if (!this.trigger) return;
Object.keys(this.localEvents).forEach(event => {
this.localEvents[event] = false;
});
this.localTrigger = { sql: '' };
this.isLoading = true;
@@ -216,6 +246,12 @@ export default {
this.originalTrigger = response;
this.localTrigger = JSON.parse(JSON.stringify(this.originalTrigger));
this.sqlProxy = this.localTrigger.sql;
if (this.customizations.triggerMultipleEvents) {
this.originalTrigger.event.forEach(e => {
this.localEvents[e] = true;
});
}
}
else
this.addNotification({ status: 'error', message: response });
@@ -227,6 +263,16 @@ export default {
this.resizeQueryEditor();
this.isLoading = false;
},
changeEvents (event) {
if (this.customizations.triggerMultipleEvents) {
this.localEvents[event] = !this.localEvents[event];
this.localTrigger.event = [];
for (const key in this.localEvents) {
if (this.localEvents[key])
this.localTrigger.event.push(key);
}
}
},
async saveChanges () {
if (this.isSaving) return;
this.isSaving = true;
@@ -249,7 +295,8 @@ export default {
if (oldName !== this.localTrigger.name) {
this.setUnsavedChanges(false);
this.changeBreadcrumbs({ schema: this.schema, trigger: this.localTrigger.name });
const triggerName = this.customizations.triggerTableInName ? `${this.localTrigger.table}.${this.localTrigger.name}` : this.localTrigger.name;
this.changeBreadcrumbs({ schema: this.schema, trigger: triggerName });
}
this.getTriggerData();
@@ -266,6 +313,16 @@ export default {
clearChanges () {
this.localTrigger = JSON.parse(JSON.stringify(this.originalTrigger));
this.$refs.queryEditor.editor.session.setValue(this.localTrigger.sql);
Object.keys(this.localEvents).forEach(event => {
this.localEvents[event] = false;
});
if (this.customizations.triggerMultipleEvents) {
this.originalTrigger.event.forEach(e => {
this.localEvents[e] = true;
});
}
},
resizeQueryEditor () {
if (this.$refs.queryEditor) {
@@ -274,6 +331,15 @@ export default {
this.editorHeight = size;
this.$refs.queryEditor.editor.resize();
}
},
onKey (e) {
if (this.isSelected) {
e.stopPropagation();
if (e.ctrlKey && e.keyCode === 83) { // CTRL + S
if (this.isChanged)
this.saveChanges();
}
}
}
}
};

View File

@@ -7,6 +7,7 @@
class="btn btn-primary btn-sm"
:disabled="!isChanged"
:class="{'loading':isSaving}"
title="CTRL+S"
@click="saveChanges"
>
<span>{{ $t('word.save') }}</span>
@@ -201,13 +202,14 @@ export default {
},
computed: {
...mapGetters({
selectedWorkspace: 'workspaces/getSelected',
getWorkspace: 'workspaces/getWorkspace'
}),
workspace () {
return this.getWorkspace(this.connection.uid);
},
isSelected () {
return this.workspace.selected_tab === 'prop';
return this.workspace.selected_tab === 'prop' && this.selectedWorkspace === this.workspace.uid && this.view;
},
schema () {
return this.workspace.breadcrumbs.schema;
@@ -245,6 +247,12 @@ export default {
destroyed () {
window.removeEventListener('resize', this.resizeQueryEditor);
},
created () {
window.addEventListener('keydown', this.onKey);
},
beforeDestroy () {
window.removeEventListener('keydown', this.onKey);
},
methods: {
...mapActions({
addNotification: 'notifications/addNotification',
@@ -327,6 +335,15 @@ export default {
this.editorHeight = size;
this.$refs.queryEditor.editor.resize();
}
},
onKey (e) {
if (this.isSelected) {
e.stopPropagation();
if (e.ctrlKey && e.keyCode === 83) { // CTRL + S
if (this.isChanged)
this.saveChanges();
}
}
}
}
};

View File

@@ -60,6 +60,9 @@
class="form-select editable-field small-select text-uppercase"
@blur="editOFF"
>
<option v-if="!isInDataTypes">
{{ row.type }}
</option>
<optgroup
v-for="group in dataTypes"
:key="group.group"
@@ -68,7 +71,7 @@
<option
v-for="type in group.types"
:key="type.name"
:selected="localRow.type.toUpperCase() === type.name"
:selected="localRow.type === type.name"
:value="type.name"
>
{{ type.name }}
@@ -93,8 +96,22 @@
class="cell-content"
@dblclick="editON($event, localLength, 'length')"
>
{{ localLength }}
<span v-if="localRow.enumValues">
{{ localRow.enumValues }}
</span>
<span v-else>
{{ localLength }}
</span>
</span>
<input
v-else-if="localRow.enumValues"
ref="editField"
v-model="editingContent"
type="text"
autofocus
class="editable-field px-2"
@blur="editOFF"
>
<input
v-else
ref="editField"
@@ -374,6 +391,18 @@ export default {
},
isNullable () {
return !this.indexes.some(index => ['PRIMARY'].includes(index.type));
},
isInDataTypes () {
let typeNames = [];
for (const group of this.dataTypes) {
const groupTypeNames = group.types.reduce((acc, curr) => {
acc.push(curr.name);
return acc;
}, []);
typeNames = [...groupTypeNames, ...typeNames];
}
return typeNames.includes(this.row.type);
}
},
watch: {
@@ -420,37 +449,35 @@ export default {
});
this.defaultValue.onUpdate = this.localRow.onUpdate;
if (this.localRow.autoIncrement)
this.defaultValue.type = 'autoincrement';
else if (this.localRow.default === null)
this.defaultValue.type = 'noval';
else if (this.localRow.default === 'NULL')
this.defaultValue.type = 'null';
else if (this.localRow.default.match(/^'.*'$/g)) {
this.defaultValue.type = 'custom';
this.defaultValue.custom = this.localRow.default.replace(/(^')|('$)/g, '');
this.defaultValue.type = this.localRow.defaultType;
if (this.defaultValue.type === 'custom') {
this.defaultValue.custom = this.localRow.default
? this.localRow.default.includes('\'')
? this.localRow.default.split('\'')[1]
: this.localRow.default
: '';
}
else if (!isNaN(this.localRow.default.replace(/[:.-\s]/g, ''))) {
this.defaultValue.type = 'custom';
this.defaultValue.custom = this.localRow.default;
}
else {
this.defaultValue.type = 'expression';
if (this.defaultValue.type === 'expression')
this.defaultValue.expression = this.localRow.default;
}
},
editON (event, content, field) {
if (field === 'length') {
if (['integer', 'float', 'binary', 'spatial'].includes(this.fieldType.group)) this.editingField = 'numLength';
if (['string', 'other'].includes(this.fieldType.group)) this.editingField = 'charLength';
if (['time'].includes(this.fieldType.group)) this.editingField = 'datePrecision';
else if (['string', 'unknown'].includes(this.fieldType.group)) this.editingField = 'charLength';
else if (['other'].includes(this.fieldType.group)) this.editingField = 'enumValues';
else if (['time'].includes(this.fieldType.group)) this.editingField = 'datePrecision';
}
else
this.editingField = field;
this.editingContent = content;
this.originalContent = content;
if (this.localRow.enumValues && field === 'length') {
this.editingContent = this.localRow.enumValues;
this.originalContent = this.localRow.enumValues;
}
else {
this.editingContent = content;
this.originalContent = content;
}
const obj = { [field]: true };
this.isInlineEditor = { ...this.isInlineEditor, ...obj };
@@ -475,11 +502,13 @@ export default {
this.localRow.numLength = null;
this.localRow.charLength = null;
this.localRow.datePrecision = null;
this.localRow.enumValues = '';
if (this.fieldType.length) {
if (['integer', 'float', 'binary', 'spatial'].includes(this.fieldType.group)) this.localRow.numLength = 11;
if (['string', 'other'].includes(this.fieldType.group)) this.localRow.charLength = 15;
if (['string'].includes(this.fieldType.group)) this.localRow.charLength = 15;
if (['time'].includes(this.fieldType.group)) this.localRow.datePrecision = 0;
if (['other'].includes(this.fieldType.group)) this.localRow.enumValues = '\'valA\',\'valB\'';
}
if (!this.fieldType.collation)
@@ -506,7 +535,7 @@ export default {
break;
case 'custom':
this.localRow.autoIncrement = false;
this.localRow.default = `'${this.defaultValue.custom}'`;
this.localRow.default = Number.isNaN(+this.defaultValue.custom) ? `'${this.defaultValue.custom}'` : this.defaultValue.custom;
break;
case 'expression':
this.localRow.autoIncrement = false;

View File

@@ -1,5 +1,12 @@
<template>
<div v-show="isSelected" class="workspace-query-tab column col-12 columns col-gapless">
<div
v-show="isSelected"
class="workspace-query-tab column col-12 columns col-gapless no-outline"
tabindex="0"
@keydown.116="runQuery(query)"
@keydown.ctrl.87="clear"
@keydown.ctrl.119="beautify"
>
<div class="workspace-query-runner column col-12">
<QueryEditor
v-show="isSelected"
@@ -24,6 +31,43 @@
<span>{{ $t('word.run') }}</span>
<i class="mdi mdi-24px mdi-play" />
</button>
<div class="dropdown export-dropdown pr-2">
<button
:disabled="!results.length || isQuering"
class="btn btn-dark btn-sm dropdown-toggle mr-0 pr-0"
tabindex="0"
>
<span>{{ $t('word.export') }}</span>
<i class="mdi mdi-24px mdi-file-export ml-1" />
<i class="mdi mdi-24px mdi-menu-down" />
</button>
<ul class="menu text-left">
<li class="menu-item">
<a class="c-hand" @click="downloadTable('json')">JSON</a>
</li>
<li class="menu-item">
<a class="c-hand" @click="downloadTable('csv')">CSV</a>
</li>
</ul>
</div>
<button
class="btn btn-dark btn-sm"
:disabled="!query || isQuering"
title="CTRL+F8"
@click="beautify()"
>
<span>{{ $t('word.format') }}</span>
<i class="mdi mdi-24px mdi-brush pl-1" />
</button>
<button
class="btn btn-link btn-sm"
:disabled="!query || isQuering"
title="CTRL+W"
@click="clear()"
>
<span>{{ $t('word.clear') }}</span>
<i class="mdi mdi-24px mdi-delete-sweep pl-1" />
</button>
</div>
<div class="workspace-query-info">
<div
@@ -68,6 +112,7 @@
</template>
<script>
import { format } from 'sql-formatter';
import Schema from '@/ipc-api/Schema';
import QueryEditor from '@/components/QueryEditor';
import BaseLoader from '@/components/BaseLoader';
@@ -192,12 +237,36 @@ export default {
if (this.$refs.queryEditor)
this.$refs.queryEditor.editor.resize();
},
onKey (e) {
if (this.isSelected && this.isWorkspaceSelected) {
e.stopPropagation();
if (e.key === 'F5')
this.runQuery(this.query);
beautify () {
if (this.$refs.queryEditor) {
let language = 'sql';
switch (this.workspace.client) {
case 'mysql':
language = 'mysql';
break;
case 'maria':
language = 'mariadb';
break;
case 'pg':
language = 'postgresql';
break;
}
const formattedQuery = format(this.query, {
language,
uppercase: true
});
this.$refs.queryEditor.editor.session.setValue(formattedQuery);
}
},
clear () {
if (this.$refs.queryEditor)
this.$refs.queryEditor.editor.session.setValue('');
this.clearTabData();
},
downloadTable (format) {
this.$refs.queryTable.downloadTable(format, `${this.tab.type}-${this.tab.index}`);
}
}
};
@@ -251,4 +320,9 @@ export default {
}
}
.export-dropdown {
.menu {
min-width: 100%;
}
}
</style>

View File

@@ -1,16 +1,18 @@
<template>
<div
ref="tableWrapper"
class="vscroll"
class="vscroll no-outline"
tabindex="0"
:style="{'height': resultsSize+'px'}"
@keyup.46="showDeleteConfirmModal"
>
<TableContext
v-if="isContext"
:context-event="contextEvent"
:selected-rows="selectedRows"
@delete-selected="deleteSelected"
@show-delete-modal="showDeleteConfirmModal"
@set-null="setNull"
@close-context="isContext = false"
@close-context="closeContext"
/>
<ul v-if="resultsWithRows.length > 1" class="tab tab-block result-tabs">
<li
@@ -75,6 +77,23 @@
</template>
</BaseVirtualScroll>
</div>
<ConfirmModal
v-if="isDeleteConfirmModal"
@confirm="deleteSelected"
@hide="hideDeleteConfirmModal"
>
<template :slot="'header'">
<div class="d-flex">
<i class="mdi mdi-24px mdi-delete mr-1" /> {{ $tc('message.deleteRows', selectedRows.length) }}
</div>
</template>
<div :slot="'body'">
<div class="mb-2">
{{ $tc('message.confirmToDeleteRows', selectedRows.length) }}
</div>
</div>
</ConfirmModal>
</div>
</template>
@@ -85,6 +104,7 @@ import { TEXT, LONG_TEXT, BLOB } from 'common/fieldTypes';
import BaseVirtualScroll from '@/components/BaseVirtualScroll';
import WorkspaceQueryTableRow from '@/components/WorkspaceQueryTableRow';
import TableContext from '@/components/WorkspaceQueryTableContext';
import ConfirmModal from '@/components/BaseConfirmModal';
import { mapActions, mapGetters } from 'vuex';
import moment from 'moment';
@@ -93,7 +113,8 @@ export default {
components: {
BaseVirtualScroll,
WorkspaceQueryTableRow,
TableContext
TableContext,
ConfirmModal
},
props: {
results: Array,
@@ -106,6 +127,7 @@ export default {
resultsSize: 1000,
localResults: [],
isContext: false,
isDeleteConfirmModal: false,
contextEvent: null,
selectedCell: null,
selectedRows: [],
@@ -117,7 +139,8 @@ export default {
},
computed: {
...mapGetters({
getWorkspace: 'workspaces/getWorkspace'
getWorkspace: 'workspaces/getWorkspace',
pageSize: 'settings/getDataTabLimit'
}),
workspaceSchema () {
return this.getWorkspace(this.connUid).breadcrumbs.schema;
@@ -135,7 +158,7 @@ export default {
return this.fields.every(field => field.name);
},
isHardSort () {
return this.mode === 'table' && this.localResults.length === 1000;
return this.mode === 'table' && this.localResults.length === this.pageSize;
},
sortedResults () {
if (this.currentSort && !this.isHardSort) {
@@ -297,8 +320,6 @@ export default {
},
updateField (payload, row) {
const orgRow = this.localResults.find(lr => lr._id === row._id);
delete row._id;
delete orgRow._id;
Object.keys(orgRow).forEach(key => { // remap the row
if (orgRow[key] instanceof Date && moment(orgRow[key]).isValid()) { // if datetime
@@ -322,7 +343,19 @@ export default {
};
this.$emit('update-field', params);
},
closeContext () {
this.isContext = false;
},
showDeleteConfirmModal (e) {
if (e && e.path && ['INPUT', 'TEXTAREA', 'SELECT'].includes(e.path[0].tagName))
return;
this.isDeleteConfirmModal = true;
},
hideDeleteConfirmModal () {
this.isDeleteConfirmModal = false;
},
deleteSelected () {
this.closeContext();
const rows = this.localResults.filter(row => this.selectedRows.includes(row._id)).map(row => {
delete row._id;
return row;
@@ -338,7 +371,6 @@ export default {
},
setNull () {
const row = this.localResults.find(row => this.selectedRows.includes(row._id));
delete row._id;
const params = {
primary: this.primaryField.name,
@@ -376,15 +408,15 @@ export default {
this.selectedRows.push(row);
else {
const lastID = this.selectedRows.slice(-1)[0];
const lastIndex = this.localResults.findIndex(el => el._id === lastID);
const clickedIndex = this.localResults.findIndex(el => el._id === row);
const lastIndex = this.sortedResults.findIndex(el => el._id === lastID);
const clickedIndex = this.sortedResults.findIndex(el => el._id === row);
if (lastIndex > clickedIndex) {
for (let i = clickedIndex; i < lastIndex; i++)
this.selectedRows.push(this.localResults[i]._id);
this.selectedRows.push(this.sortedResults[i]._id);
}
else if (lastIndex < clickedIndex) {
for (let i = clickedIndex; i > lastIndex; i--)
this.selectedRows.push(this.localResults[i]._id);
this.selectedRows.push(this.sortedResults[i]._id);
}
}
}
@@ -403,6 +435,8 @@ export default {
sort (field) {
if (!this.isSortable) return;
this.selectedRows = [];
if (this.mode === 'query')
field = `${this.getTable(this.resultsetIndex)}.${field}`;

View File

@@ -17,61 +17,30 @@
<i class="mdi mdi-18px mdi-delete text-light pr-1" /> {{ $tc('message.deleteRows', selectedRows.length) }}
</span>
</div>
<ConfirmModal
v-if="isConfirmModal"
@confirm="deleteRows"
@hide="hideConfirmModal"
>
<template :slot="'header'">
<div class="d-flex">
<i class="mdi mdi-24px mdi-delete mr-1" /> {{ $tc('message.deleteRows', selectedRows.length) }}
</div>
</template>
<div :slot="'body'">
<div class="mb-2">
{{ $tc('message.confirmToDeleteRows', selectedRows.length) }}
</div>
</div>
</ConfirmModal>
</BaseContextMenu>
</template>
<script>
import BaseContextMenu from '@/components/BaseContextMenu';
import ConfirmModal from '@/components/BaseConfirmModal';
export default {
name: 'WorkspaceQueryTableContext',
components: {
BaseContextMenu,
ConfirmModal
BaseContextMenu
},
props: {
contextEvent: MouseEvent,
selectedRows: Array
},
data () {
return {
isConfirmModal: false
};
},
computed: {
},
methods: {
showConfirmModal () {
this.isConfirmModal = true;
},
hideConfirmModal () {
this.isConfirmModal = false;
this.$emit('show-delete-modal');
},
closeContext () {
this.$emit('close-context');
},
deleteRows () {
this.$emit('delete-selected');
this.closeContext();
},
setNull () {
this.$emit('set-null');
this.closeContext();

View File

@@ -10,7 +10,7 @@
>
<template v-if="cKey !== '_id'">
<span
v-if="!isInlineEditor[cKey]"
v-if="!isInlineEditor[cKey] && fields[cKey]"
class="cell-content px-2"
:class="`${isNull(col)} ${typeClass(fields[cKey].type)}`"
@dblclick="editON($event, col, cKey)"
@@ -43,6 +43,16 @@
<option>true</option>
<option>false</option>
</select>
<select
v-else-if="enumArray"
v-model="editingContent"
class="form-select small-select editable-field"
@blur="editOFF"
>
<option v-for="value in enumArray" :key="value">
{{ value }}
</option>
</select>
<input
v-else
ref="editField"
@@ -336,6 +346,11 @@ export default {
}
return false;
},
enumArray () {
if (this.fields[this.editingField] && this.fields[this.editingField].enumValues)
return this.fields[this.editingField].enumValues.replaceAll('\'', '').split(',');
return false;
}
},
watch: {

View File

@@ -32,6 +32,29 @@
</div>
</div>
</div>
<div class="btn-group">
<button
class="btn btn-dark btn-sm mr-0"
:disabled="isQuering || page === 1"
title="CTRL+ᐊ"
@click="pageChange('prev')"
>
<i class="mdi mdi-24px mdi-skip-previous" />
</button>
<div class="btn btn-dark btn-sm mr-0 text-bold c-auto px-2">
{{ page }}
</div>
<button
class="btn btn-dark btn-sm mr-0"
:disabled="isQuering || (results.length && results[0].rows.length < limit)"
title="CTRL+ᐅ"
@click="pageChange('next')"
>
<i class="mdi mdi-24px mdi-skip-next" />
</button>
</div>
<div class="divider-vert py-3" />
<button
v-if="isTable"
@@ -72,10 +95,10 @@
<i class="mdi mdi-timer-sand mdi-rotate-180 pr-1" /> <b>{{ results[0].duration / 1000 }}s</b>
</div>
<div v-if="results.length && results[0].rows">
{{ $t('word.results') }}: <b>{{ results[0].rows.length.toLocaleString() }}</b>
{{ $t('word.results') }}: <b>{{ results[0].rows.length | localeString }}</b>
</div>
<div v-if="hasApproximately">
{{ $t('word.total') }}: <b>{{ tableInfo.rows.toLocaleString() }}</b> <small>({{ $t('word.approximately') }})</small>
<div v-if="hasApproximately || (page > 1 && tableInfo.rows)">
{{ $t('word.total') }}: <b>{{ tableInfo.rows | localeString }}</b> <small>({{ $t('word.approximately') }})</small>
</div>
<div v-if="workspace.breadcrumbs.database">
{{ $t('word.schema') }}: <b>{{ workspace.breadcrumbs.database }}</b>
@@ -134,6 +157,12 @@ export default {
ModalNewTableRow,
ModalFakerRows
},
filters: {
localeString (val) {
if (val)
return val.toLocaleString();
}
},
mixins: [tableTabs],
props: {
connection: Object,
@@ -149,13 +178,15 @@ export default {
isFakerModal: false,
autorefreshTimer: 0,
refreshInterval: null,
sortParams: {}
sortParams: {},
page: 1
};
},
computed: {
...mapGetters({
getWorkspace: 'workspaces/getWorkspace',
selectedWorkspace: 'workspaces/getSelected'
selectedWorkspace: 'workspaces/getSelected',
limit: 'settings/getDataTabLimit'
}),
workspace () {
return this.getWorkspace(this.connection.uid);
@@ -184,19 +215,23 @@ export default {
return this.results.length &&
this.results[0].rows &&
this.tableInfo &&
this.results[0].rows.length === 1000 &&
this.results[0].rows.length === this.limit &&
this.results[0].rows.length < this.tableInfo.rows;
}
},
watch: {
table () {
if (this.isSelected) {
this.page = 1;
this.sortParams = {};
this.getTableData();
this.lastTable = this.table;
this.$refs.queryTable.resetSort();
}
},
page () {
this.getTableData();
},
isSelected (val) {
if (val && this.lastTable !== this.table) {
this.getTableData();
@@ -228,6 +263,8 @@ export default {
uid: this.connection.uid,
schema: this.schema,
table: this.workspace.breadcrumbs.table || this.workspace.breadcrumbs.view,
limit: this.limit,
page: this.page,
sortParams
};
@@ -255,6 +292,14 @@ export default {
this.sortParams = sortParams;
this.getTableData(sortParams);
},
pageChange (direction) {
if (this.isQuering) return;
if (direction === 'next' && (this.results.length && this.results[0].rows.length === this.limit))
this.page++;
else if (direction === 'prev' && this.page > 1)
this.page--;
},
showAddModal () {
this.isAddModal = true;
},
@@ -273,6 +318,13 @@ export default {
e.stopPropagation();
if (e.key === 'F5')
this.reloadTable();
if (e.ctrlKey) {
if (e.key === 'ArrowRight')
this.pageChange('next');
if (e.key === 'ArrowLeft')
this.pageChange('prev');
}
}
},
setRefreshInterval () {

379
src/renderer/i18n/de-DE.js Normal file
View File

@@ -0,0 +1,379 @@
module.exports = {
word: {
edit: 'Bearbeiten',
save: 'Speichern',
close: 'Schließen',
delete: 'Löschen',
confirm: 'Bestätigen',
cancel: 'Abbrechen',
send: 'Senden',
connectionName: 'Verbindungsname',
client: 'Client',
hostName: 'Hostname',
port: 'Port',
user: 'Nutzer',
password: 'Kennwort',
credentials: 'Zugangsdaten',
connect: 'Verbinden',
connected: 'Verbunden',
disconnect: 'Trennen',
disconnected: 'Getrennt',
refresh: 'Aktualisieren',
settings: 'Einstellungen',
general: 'Allgemein',
themes: 'Designs',
update: 'Aktualisierung',
about: 'Über',
language: 'Sprache',
version: 'Version',
donate: 'Spenden',
run: 'Ausführen',
schema: 'Schema',
results: 'Ergebnisse',
size: 'Größe',
seconds: 'Sekunden',
type: 'Typ',
mimeType: 'Mime-Type',
download: 'Herunterladen',
add: 'Hinzufügen',
data: 'Daten',
properties: 'Eigenschaften',
insert: 'Einfügen',
connecting: 'Verbinden',
name: 'Name',
collation: 'Kollation',
clear: 'Leeren',
options: 'Optionen',
autoRefresh: 'Auto-Aktualisierung',
indexes: 'Indizes',
foreignKeys: 'Fremdschlüssel',
length: 'Länge',
unsigned: 'Unsigniert',
default: 'Standard',
comment: 'Kommentar',
key: 'Schlüssel',
order: 'Sortierung',
expression: 'Ausdruck',
autoIncrement: 'Auto Inkrement',
engine: 'Engine',
field: 'Feld | Felder',
approximately: 'Ungefähr',
total: 'Gesamt',
table: 'Tabelle',
discard: 'Verwerfen',
stay: 'Warten',
author: 'Autor',
light: 'Hell',
dark: 'Dunkel',
autoCompletion: 'Auto-Vervollständigung',
application: 'Anwendung',
editor: 'Editor',
view: 'Ansicht',
definer: 'Bestimmer',
algorithm: 'Algorithmus',
trigger: 'Auslöser',
storedRoutine: 'Gespeicherte Routine | Gespeicherte Routinen',
scheduler: 'Zeitplaner',
event: 'Ereignis',
parameters: 'Parameter',
function: 'Funktion | Funktionen',
deterministic: 'Deterministisch',
context: 'Kontext',
export: 'Export',
returns: 'Rückgabe',
timing: 'Dauer',
state: 'Stand',
execution: 'Ausführung',
starts: 'Startet',
ends: 'Endet',
ssl: 'SSL',
privateKey: 'Privater Schlüssel',
certificate: 'Zertifikat',
caCertificate: 'CA Zertifikat',
ciphers: 'Chiffren',
upload: 'Hochladen',
browse: 'Suchen',
faker: 'Faker',
content: 'Inhalt',
cut: 'Ausschneiden',
copy: 'Kopieren',
paste: 'Einfügen',
tools: 'Tools',
variables: 'Variablen',
processes: 'Prozesse',
database: 'Datenbank',
scratchpad: 'Scratchpad',
array: 'Array',
format: 'Formatierung'
},
message: {
appWelcome: 'Willkommen im Antares SQL Client!',
appFirstStep: 'Dein erster Schritt: Erstelle eine neue Datenbankverbindung.',
addConnection: 'Verbindung hinzufügen',
createConnection: 'Verbindung erstellen',
createNewConnection: 'Neue Verbindung erstellen',
askCredentials: 'Frage nach Zugangsdaten',
testConnection: 'Verbindung testen',
editConnection: 'Verbindung bearbeiten',
deleteConnection: 'Verbindung löschen',
deleteCorfirm: 'Bestätige den Abbruch von',
connectionSuccessfullyMade: 'Verbindung erfolgreich erstellt!',
madeWithJS: 'Mit 💛 und JavaScript gemacht!',
checkForUpdates: 'Suche nach Aktualisierungen',
noUpdatesAvailable: 'Keine Aktualisierungen verfügbar',
checkingForUpdate: 'Suche nach Aktualisierungen',
checkFailure: 'Suche fehlgeschlagen, bitte versuche es später noch einmal',
updateAvailable: 'Aktualisierung verfügbar',
downloadingUpdate: 'Aktualisierung wird heruntergeladen',
updateDownloaded: 'Aktualisierung heruntergeladen',
restartToInstall: 'Starte Antares neu für die Installation',
unableEditFieldWithoutPrimary: 'Feld kann ohne Primärschlüssel in Ergebnisliste nicht bearbeitet werden',
editCell: 'Zelle bearbeiten',
deleteRows: 'Zeile löschen | Lösche {count} Zeilen',
confirmToDeleteRows: 'Eine Zeile wirklich löschen? | {count} Zeilen wirklich löschen?',
notificationsTimeout: 'Timeout für Benachrichtigungen',
uploadFile: 'Datei hochladen',
addNewRow: 'Neue Zeile hinzufügen',
numberOfInserts: 'Anzahl der eingefügten Zeilen',
openNewTab: 'Öffne einen neuen Tab',
affectedRows: 'Betroffene Zeilen',
createNewDatabase: 'Erstelle ein neue Datenbank',
databaseName: 'Datenbankname',
serverDefault: 'Server default',
deleteDatabase: 'Datenbank löschen',
editDatabase: 'Datenbank bearbeiten',
clearChanges: 'Änderungen leeren',
addNewField: 'Neues Feld hinzufügen',
manageIndexes: 'Indizes verwalten',
manageForeignKeys: 'Fremdschlüssel verwalten',
allowNull: 'Erlaube NULL',
zeroFill: 'Nullauffüllung',
customValue: 'Spezifischer Wert',
onUpdate: 'Bei Aktualisierung',
deleteField: 'Feld löschen',
createNewIndex: 'Neuen Index erstellen',
addToIndex: 'Zum Index hinzufügen',
createNewTable: 'Neue Tabelle erstellen',
emptyTable: 'Tabelle leeren',
deleteTable: 'Tabelle löschen',
emptyCorfirm: 'Wirklich leeren?',
unsavedChanges: 'Ungespeicherte Änderungen',
discardUnsavedChanges: 'Du hast ungespeicherte Änderungen. Wenn du den Tab verlässt, werden diese Änderungen verworfen.',
thereAreNoIndexes: 'Es gibt keine Indizes',
thereAreNoForeign: 'Es gibt keine Fremdschlüssel',
createNewForeign: 'Neuen Fremdschlüssel erstellen',
referenceTable: 'Referenztabelle',
referenceField: 'Referenzfeld',
foreignFields: 'Fremdfelder',
invalidDefault: 'Ungültiger Standard',
onDelete: 'Bei Löschung',
applicationTheme: 'Anwendungsdesign',
editorTheme: 'Editordesign',
wrapLongLines: 'Lange Zeilen umbrechen',
selectStatement: 'Select-Anweisung',
triggerStatement: 'Trigger-Anweisung',
sqlSecurity: 'SQL-Sicherheit',
updateOption: 'Aktualisierungsoption',
deleteView: 'View löschen',
createNewView: 'Neue View erstellen',
deleteTrigger: 'Trigger löschen',
createNewTrigger: 'Neuen Trigger erstellen',
currentUser: 'Aktueller Nutzer',
routineBody: 'Routineninhalt',
dataAccess: 'Datenzugriff',
thereAreNoParameters: 'Es gibt keine Parameter',
createNewParameter: 'Neue Parameter erstellen',
createNewRoutine: 'Neue Routine erstellen',
deleteRoutine: 'Routine löschen',
functionBody: 'Funktionsinhalt',
createNewFunction: 'Neue Funktion erstellen',
deleteFunction: 'Funktion löschen',
schedulerBody: 'Zeitplaner-Inhalt',
createNewScheduler: 'Neuen Zeitplaner erstellen',
deleteScheduler: 'Zeitplaner löschen',
preserveOnCompletion: 'Bei Vervollständigung erhalten',
enableSsl: 'Aktiviere SSL',
manualValue: 'Manueller Wert',
tableFiller: 'Tabellenfüller',
fakeDataLanguage: 'Fingierte Datensprache',
searchForElements: 'Suche nach Elemente',
selectAll: 'Alle auswählen',
queryDuration: 'Dauer der Abfrage',
includeBetaUpdates: 'Beta-Aktualisierungen berücksichtigen',
setNull: 'Setze NULL',
processesList: 'Prozessliste',
processInfo: 'Prozessinformationen',
manageUsers: 'Benutzer verwalten',
createNewSchema: 'Neues Schema erstellen',
schemaName: 'Schemaname',
editSchema: 'Schema bearbeiten',
deleteSchema: 'Schema löschen',
markdownSupported: 'Unterstützt Markdown',
plantATree: 'Pflanze einen Baum',
dataTabPageSize: 'Einträge pro Tab / Seite'
},
faker: {
address: 'Adresse',
commerce: 'Handel',
company: 'Firma',
database: 'Datenbank',
date: 'Datum',
finance: 'Finanzen',
git: 'Git',
hacker: 'Hacker',
internet: 'Internet',
lorem: 'Lorem',
name: 'Name',
music: 'Musik',
phone: 'Telefon',
random: 'Zufällig',
system: 'System',
time: 'Zeit',
vehicle: 'Fahrzeug',
zipCode: 'Postleitzahl',
zipCodeByState: 'Postleitzahl nach Stadt',
city: 'Stadt',
cityPrefix: 'Stadtpräfix',
citySuffix: 'Stadtzusatz',
streetName: 'Straßenname',
streetAddress: 'Anschrift',
streetSuffix: 'Straßenzusatz',
streetPrefix: 'Straßenpräfix',
secondaryAddress: 'Zweite Anschrift',
county: 'Landkreis',
country: 'Land',
countryCode: 'Ländercode',
state: 'Bundesland',
stateAbbr: 'Bundeslandkürzel',
latitude: 'Breitengrad',
longitude: 'Längengrad',
direction: 'Richtung',
cardinalDirection: 'Himmelsrichtung',
ordinalDirection: 'Nebenhimmelsrichtung',
nearbyGPSCoordinate: 'Nächste GPS-Koordinate',
timeZone: 'Zeitzone',
color: 'Farbe',
department: 'Abteilung',
productName: 'Produktname',
price: 'Preis',
productAdjective: 'Produkteigenschaft',
productMaterial: 'Produktmaterial',
product: 'Produkt',
productDescription: 'Produktbeschreibung',
suffixes: 'Zusätze',
companyName: 'Firmenname',
companySuffix: 'Firmenzusatz',
catchPhrase: 'Slogan',
bs: 'BS',
catchPhraseAdjective: 'Sloganeigenschaft',
catchPhraseDescriptor: 'Sloganbeschreibung',
catchPhraseNoun: 'Slogannomen',
bsAdjective: 'BS-Eigenschaft',
bsBuzz: 'BS-Klatsch',
bsNoun: 'BS-Nomen',
column: 'Spalte',
type: 'Typ',
collation: 'Kollation',
engine: 'Engine',
past: 'Vergangenheit',
future: 'Zukunft',
between: 'Zwischen',
recent: 'Kürzlich',
soon: 'Bald',
month: 'Monat',
weekday: 'Wochentag',
account: 'Konto',
accountName: 'Kontoname',
routingNumber: 'Bankleitzahl',
mask: 'Maske',
amount: 'Wert',
transactionType: 'Vorgangstyp',
currencyCode: 'Währungscode',
currencyName: 'Währungsname',
currencySymbol: 'Währungssymbol',
bitcoinAddress: 'Bitcoin-Adresse',
litecoinAddress: 'Litecoin-Adresse',
creditCardNumber: 'Kreditkartennummer',
creditCardCVV: 'Kartenprüfnummer',
ethereumAddress: 'Ethereum-Adresse',
iban: 'IBAN',
bic: 'BIC',
transactionDescription: 'Vorgangsbeschreibung',
branch: 'Zweig',
commitEntry: 'Commit-Eintrag',
commitMessage: 'Commit-Nachricht',
commitSha: 'Commit-SHA',
shortSha: 'Kurzer SHA',
abbreviation: 'Kürzel',
adjective: 'Adjektiv',
noun: 'Nomen',
verb: 'Verb',
ingverb: 'Ingverb',
phrase: 'Phrase',
avatar: 'Avatar',
email: 'E-Mail',
exampleEmail: 'Beispiel-E-Mail',
userName: 'Benutzername',
protocol: 'Protokoll',
url: 'Url',
domainName: 'Domainname',
domainSuffix: 'Domainzusatz',
domainWord: 'Domainwort',
ip: 'IP',
ipv6: 'IPv6',
userAgent: 'Browserkennung',
mac: 'Mac',
password: 'Kennwort',
word: 'Wort',
words: 'Wörter',
sentence: 'Satz',
slug: 'Slug',
sentences: 'Sätze',
paragraph: 'Paragraph',
paragraphs: 'Paragraphen',
text: 'Text',
lines: 'Zeilen',
genre: 'Genre',
firstName: 'Vorname',
lastName: 'Nachname',
middleName: 'Zweitname',
findName: 'Vollständiger Name',
jobTitle: 'Berufsbezeichnung',
gender: 'Geschlecht',
prefix: 'Präfix',
suffix: 'Zusatz',
title: 'Titel',
jobDescriptor: 'Berufsbeschreibung',
jobArea: 'Berufsfeld',
jobType: 'Anstellungsart',
phoneNumber: 'Telefonnummer',
phoneNumberFormat: 'Telefonnummerformat',
phoneFormats: 'Telefonnummerformate',
number: 'Nummer',
float: 'Gleitkommazahl',
arrayElement: 'Array-Element',
arrayElements: 'Array-Elemente',
objectElement: 'Object-Element',
uuid: 'Uuid',
boolean: 'Boolean',
image: 'Grafik',
locale: 'Sprachumgebung',
alpha: 'Alpha',
alphaNumeric: 'Alphanumerisch',
hexaDecimal: 'Hexadezimal',
fileName: 'Dateiname',
commonFileName: 'Allgemeiner Dateiname',
mimeType: 'Mimetype',
commonFileType: 'Allgemeiner Dateityp',
commonFileExt: 'Allgemeine Dateiendung',
fileType: 'Dateityp',
fileExt: 'Dateiendung',
directoryPath: 'Verzeichnispfad',
filePath: 'Dateipfad',
semver: 'Semver',
manufacturer: 'Hersteller',
model: 'Modell',
fuel: 'Treibstoff',
vin: 'Wein'
}
};

View File

@@ -104,7 +104,8 @@ module.exports = {
database: 'Database',
scratchpad: 'Scratchpad',
array: 'Array',
changelog: 'Changelog'
changelog: 'Changelog',
format: 'Format'
},
message: {
appWelcome: 'Welcome to Antares SQL Client!',
@@ -209,7 +210,8 @@ module.exports = {
editSchema: 'Edit schema',
deleteSchema: 'Delete schema',
markdownSupported: 'Markdown supported',
plantATree: 'Plant a Tree'
plantATree: 'Plant a Tree',
dataTabPageSize: 'DATA tab page size'
},
faker: {
address: 'Address',

View File

@@ -9,7 +9,9 @@ const i18n = new VueI18n({
'it-IT': require('./it-IT'),
'ar-SA': require('./ar-SA'),
'es-ES': require('./es-ES'),
'fr-FR': require('./fr-FR')
'fr-FR': require('./fr-FR'),
'pt-BR': require('./pt-BR'),
'de-DE': require('./de-DE')
}
});
export default i18n;

View File

@@ -39,7 +39,73 @@ module.exports = {
data: 'Dati',
properties: 'Proprietà',
insert: 'Inserisci',
connecting: 'Connessione in corso'
connecting: 'Connessione in corso',
name: 'Nome',
collation: 'Confronto',
clear: 'Scarta',
options: 'Opzioni',
autoRefresh: 'Auto-aggiorna',
indexes: 'Indici',
foreignKeys: 'Chiavi esterne',
length: 'Lunghezza',
unsigned: 'Senza segno',
default: 'Default',
comment: 'Commento',
key: 'Chiave | Chiavi',
order: 'Ordine',
expression: 'Espressione',
autoIncrement: 'Auto Incremento',
engine: 'Motore',
field: 'Campo | Campi',
approximately: 'Approssimativamente',
total: 'Totali',
table: 'Tabella',
discard: 'Scarta',
stay: 'Resta',
author: 'Autore',
light: 'Chiaro',
dark: 'Scuro',
autoCompletion: 'Auto Completamento',
application: 'Applicazione',
editor: 'Editor',
view: 'Vista',
definer: 'Definer',
algorithm: 'Algoritmo',
trigger: 'Trigger | Triggers',
storedRoutine: 'Stored routine | Stored routines',
scheduler: 'Scheduler | Schedulers',
event: 'Evento',
parameters: 'Parametri',
function: 'Funzione | Funzioni',
deterministic: 'Deterministico',
context: 'Contesto',
export: 'Esporta',
returns: 'Ritorna',
timing: 'Temporizzazione',
state: 'Stato',
execution: 'Esecuzione',
starts: 'Inizia',
ends: 'Finisce',
ssl: 'SSL',
privateKey: 'Chiave privata',
certificate: 'Certificato',
caCertificate: 'Certificato CA',
ciphers: 'Ciphers',
upload: 'Carica',
browse: 'Sfoglia',
faker: 'Faker',
content: 'Contenuto',
cut: 'Taglia',
copy: 'Copia',
paste: 'Incolla',
tools: 'Strumenti',
variables: 'Variabili',
processes: 'Processi',
database: 'Database',
scratchpad: 'Blocco appunti',
array: 'Array',
changelog: 'Changelog',
format: 'Formatta'
},
message: {
appWelcome: 'Benvenuto in Antares SQL Client!',
@@ -71,6 +137,243 @@ module.exports = {
addNewRow: 'Aggiungi nuova riga',
numberOfInserts: 'Numero di insert',
openNewTab: 'Apri nuova scheda',
affectedRows: 'Righe interessate'
affectedRows: 'Righe interessate',
createNewDatabase: 'Crea nuovo database',
databaseName: 'Nome database',
serverDefault: 'Default del server',
deleteDatabase: 'Cancella database',
editDatabase: 'Modifica database',
clearChanges: 'Scarta modifiche',
addNewField: 'Aggiungi nuovo campo',
manageIndexes: 'Gestisci indici',
manageForeignKeys: 'Gestisci chiavi esterne',
allowNull: 'Permetti NULL',
zeroFill: 'Riempimento con zero',
customValue: 'Varore personalizzato',
onUpdate: 'All\'aggiornamento',
deleteField: 'Cancella campo',
createNewIndex: 'Crea nuovo indice',
addToIndex: 'Aggiungi a indice',
createNewTable: 'Crea nuova tabella',
emptyTable: 'Svuota tabella',
deleteTable: 'Cancella tabella',
emptyCorfirm: 'Confermi di voler svuotare',
unsavedChanges: 'Modifiche non salvate',
discardUnsavedChanges: 'Hai modifiche non salvate. Lasciando questa scheda le modifiche saranno scartate.',
thereAreNoIndexes: 'Non ci sono indici',
thereAreNoForeign: 'Non ci sono chiavi esterne',
createNewForeign: 'Crea nuova chiave esterna',
referenceTable: 'Tabella di rif.',
referenceField: 'Campo di rif.',
foreignFields: 'Campi esterni',
invalidDefault: 'Default non valido',
onDelete: 'All\'eliminazione',
applicationTheme: 'Tema applicazione',
editorTheme: 'Tema editor',
wrapLongLines: 'A capo righe lunghe',
selectStatement: 'Dichiarazione select',
triggerStatement: 'Dichiarazione trigger',
sqlSecurity: 'Sicurezza SQL',
updateOption: 'Update option',
deleteView: 'Elimina vista',
createNewView: 'Crea nuova vista',
deleteTrigger: 'Elimina trigger',
createNewTrigger: 'Crea nuovo trigger',
currentUser: 'Utente attuale',
routineBody: 'Corpo della routine',
dataAccess: 'Accesso dati',
thereAreNoParameters: 'Non ci sono parametri',
createNewParameter: 'Crea nuovo parametro',
createNewRoutine: 'Crea nuova stored routine',
deleteRoutine: 'Elimina stored routine',
functionBody: 'Corpo della funzione',
createNewFunction: 'Crea nuova funzione',
deleteFunction: 'Elimina funzione',
schedulerBody: 'Corpo dello scheduler',
createNewScheduler: 'Crea nuovo scheduler',
deleteScheduler: 'Elimina scheduler',
preserveOnCompletion: 'Preserva al completamento',
enableSsl: 'Abilita SSL',
manualValue: 'Valore manuale',
tableFiller: 'Riempitore Tabella',
fakeDataLanguage: 'Lingua dati falsi',
searchForElements: 'Cerca elementi',
selectAll: 'Seleziona tutto',
queryDuration: 'Durata query',
includeBetaUpdates: 'Includi aggiornamenti beta',
setNull: 'Imposta NULL',
processesList: 'Lista processi',
processInfo: 'Info processo',
manageUsers: 'Gestisci utenti',
createNewSchema: 'Crea nuovo schema',
schemaName: 'Nome schema',
editSchema: 'Modifica schema',
deleteSchema: 'Elimina schema',
markdownSupported: 'Markdown supportato',
plantATree: 'Pianta un albero'
},
faker: {
address: 'Indirizzo',
commerce: 'Commercio',
company: 'Compagnia',
database: 'Database',
date: 'Data',
finance: 'Finanza',
git: 'Git',
hacker: 'Hacker',
internet: 'Internet',
lorem: 'Lorem',
name: 'Nome',
music: 'Musica',
phone: 'Telefono',
random: 'Casuale',
system: 'Sistema',
time: 'Tempo',
vehicle: 'Veicolo',
zipCode: 'Codice zip',
zipCodeByState: 'Codice zip per stato',
city: 'Città',
cityPrefix: 'Prefisso città',
citySuffix: 'Suffisso città',
streetName: 'Nome strada',
streetAddress: 'Indirizzo strada',
streetSuffix: 'Suffisso strada',
streetPrefix: 'Prefisso strada',
secondaryAddress: 'Indirizzo secondario',
county: 'Contea',
country: 'Nazione',
countryCode: 'Codice nazione',
state: 'Stato',
stateAbbr: 'Abbreviazione stato',
latitude: 'Latitudine',
longitude: 'Longitudine',
direction: 'Direzione',
cardinalDirection: 'Direzione cardinale',
ordinalDirection: 'Direzione ordinale',
nearbyGPSCoordinate: 'Coordinate GPS vicine',
timeZone: 'Time zone',
color: 'Colore',
department: 'Dipartimento',
productName: 'Nome prodotto',
price: 'Prezzo',
productAdjective: 'Aggettivo prodotto',
productMaterial: 'Materiale prodotto',
product: 'Prodotto',
productDescription: 'Descrizione prodotto',
suffixes: 'Suffissi',
companyName: 'Nome compagnia',
companySuffix: 'Suffisso compagnia',
catchPhrase: 'Slogan',
bs: 'BS',
catchPhraseAdjective: 'Aggettivo slogan',
catchPhraseDescriptor: 'Descrittore slogan',
catchPhraseNoun: 'Sostantivo slogan',
bsAdjective: 'Aggettivo BS',
bsBuzz: 'Buzz BS',
bsNoun: 'Sostantivo BS',
column: 'Colonna',
type: 'Tipo',
collation: 'Confronto',
engine: 'Motore',
past: 'Passato',
future: 'Futuro',
between: 'Tra',
recent: 'Recente',
soon: 'Presto',
month: 'Mese',
weekday: 'Giorno della settimana',
account: 'Account',
accountName: 'Nome account',
routingNumber: 'Numero di instradamento',
mask: 'Maschera',
amount: 'Ammontare',
transactionType: 'Tipo transazione',
currencyCode: 'Codice valuta',
currencyName: 'Nome valuta',
currencySymbol: 'Simbolo valuta',
bitcoinAddress: 'Indirizzo Bitcoin',
litecoinAddress: 'Indirizzo Litecoin',
creditCardNumber: 'Numero carta di credito',
creditCardCVV: 'CVV carta di credito',
ethereumAddress: 'Indirizzo Ethereum',
iban: 'Iban',
bic: 'Bic',
transactionDescription: 'Descrizione transazione',
branch: 'Ramo',
commitEntry: 'Commit entry',
commitMessage: 'Messaggio di commit',
commitSha: 'SHA del commit',
shortSha: 'SHA breve',
abbreviation: 'Abbreviazione',
adjective: 'Aggettivo',
noun: 'Sostantivo',
verb: 'Verbo',
ingverb: 'Ingverb',
phrase: 'Frase',
avatar: 'Avatar',
email: 'Email',
exampleEmail: 'Email di esempio',
userName: 'Username',
protocol: 'Protocollo',
url: 'Url',
domainName: 'Nome dominio',
domainSuffix: 'Suffisso dominio',
domainWord: 'Parola dominio',
ip: 'Ip',
ipv6: 'Ipv6',
userAgent: 'User agent',
mac: 'Mac',
password: 'Password',
word: 'Parola',
words: 'Parole',
sentence: 'Sentenza',
slug: 'Slug',
sentences: 'Sentenze',
paragraph: 'Paragrafo',
paragraphs: 'Paragrafi',
text: 'Testo',
lines: 'Righe',
genre: 'Genere',
firstName: 'Nome',
lastName: 'Cognome',
middleName: 'Secondo nome',
findName: 'Nome completo',
jobTitle: 'Titolo di lavoro',
gender: 'Genere',
prefix: 'Prefisso',
suffix: 'Suffisso',
title: 'Titolo',
jobDescriptor: 'Descrittore del lavoro',
jobArea: 'Area di lavoro',
jobType: 'Tipo di lavoro',
phoneNumber: 'Numero di telefono',
phoneNumberFormat: 'Formato numeri di telefono',
phoneFormats: 'Formati di telefono',
number: 'Numero',
float: 'Float',
arrayElement: 'Elemento array',
arrayElements: 'Elementi array',
objectElement: 'Elemento object',
uuid: 'Uuid',
boolean: 'Booleano',
image: 'Immagine',
locale: 'Localizzazione',
alpha: 'Alfabetico',
alphaNumeric: 'Alfanumerico',
hexaDecimal: 'Esadecimale',
fileName: 'Nome file',
commonFileName: 'Nome file comune',
mimeType: 'Mime type',
commonFileType: 'Tipo file comune',
commonFileExt: 'Estensione file comune',
fileType: 'Tipo file',
fileExt: 'Estensione file',
directoryPath: 'Percorso directory',
filePath: 'Percorso file',
semver: 'Semver',
manufacturer: 'Produttore',
model: 'Modello',
fuel: 'Carburante',
vin: 'Vin'
}
};

379
src/renderer/i18n/pt-BR.js Normal file
View File

@@ -0,0 +1,379 @@
module.exports = {
word: {
edit: 'Editar',
save: 'Salvar',
close: 'Fechar',
delete: 'Apagar',
confirm: 'Confirmar',
cancel: 'Cancelar',
send: 'Enviar',
connectionName: 'Nome da Conexão',
client: 'Cliente',
hostName: 'Nome do Host',
port: 'Porta',
user: 'Usuário',
password: 'Senha',
credentials: 'Credenciais',
connect: 'Conectar',
connected: 'Conectado',
disconnect: 'Desconectar',
disconnected: 'Desconectado',
refresh: 'Atualizar',
settings: 'Opções',
general: 'Geral',
themes: 'Temas',
update: 'Atualizar',
about: 'Sobre',
language: 'Linguagem',
version: 'Versão',
donate: 'Doação',
run: 'Executar',
schema: 'Schema',
results: 'Resultados',
size: 'Tamanho',
seconds: 'Segundos',
type: 'Tipo',
mimeType: 'Mime-Type',
download: 'Download',
add: 'Adicionar',
data: 'Data',
properties: 'Propriedades',
insert: 'Inserção',
connecting: 'Connectando',
name: 'Nome',
collation: 'Collation',
clear: 'Limpar',
options: 'Opções',
autoRefresh: 'Atualização Automática',
indexes: 'Indices',
foreignKeys: 'Chaves Estrangeiras',
length: 'Tamanho',
unsigned: 'Sem sinal (Unsigned)',
default: 'Padrão',
comment: 'Comente',
key: 'Chave | Chaves',
order: 'Ordem',
expression: 'Expressão',
autoIncrement: 'Auto Incremental',
engine: 'Engine',
field: 'Campo | Campos',
approximately: 'Aproximadamente',
total: 'Total',
table: 'Tabela',
discard: 'Descartar',
stay: 'Stay',
author: 'Autor',
light: 'Claro',
dark: 'Escuro',
autoCompletion: 'Auto Complemento',
application: 'Aplicação',
editor: 'Editor',
view: 'Visão',
definer: 'Definidor',
algorithm: 'Algoritmo',
trigger: 'Trigger | Triggers',
storedRoutine: 'Stored routine | Stored routines',
scheduler: 'Scheduler | Schedulers',
event: 'Event',
parameters: 'Parametros',
function: 'Função | Funções',
deterministic: 'Deterministico',
context: 'Contexto',
export: 'Exportar',
returns: 'Retornos',
timing: 'Tempo',
state: 'Estado',
execution: 'Execução',
starts: 'Começa',
ends: 'Termina',
ssl: 'SSL',
privateKey: 'Chave Privada',
certificate: 'Certificado',
caCertificate: 'Certificado CA',
ciphers: 'Cifras (ciphers)',
upload: 'Upload',
browse: 'Navegar',
faker: 'Faker',
content: 'Conteúdo',
cut: 'Cortar',
copy: 'Copiar',
paste: 'Colar',
tools: 'Ferramentas',
variables: 'Variaveis',
processes: 'Processos',
database: 'Banco de Dados',
scratchpad: 'Rascunho',
array: 'Array',
changelog: 'Logs de alteração',
format: 'Formato'
},
message: {
appWelcome: 'Bem vindo ao Antares SQL Client!',
appFirstStep: 'Seu primeiro passo: criar uma nova conexão de banco de dados.',
addConnection: 'Adicionar Conexão',
createConnection: 'Criar Conexão',
createNewConnection: 'Criar Nova Conexão',
askCredentials: 'Pedir Credenciais',
testConnection: 'Testar Conexão',
editConnection: 'Editar Conexão',
deleteConnection: 'Apagar Conexão',
deleteCorfirm: 'Você confirma o cancelamento de',
connectionSuccessfullyMade: 'Conexão feita com sucesso!',
madeWithJS: 'Feito com 💛 e JavaScript!',
checkForUpdates: 'Verificar se há novas atualizações',
noUpdatesAvailable: 'Sem atualizações disponíveis',
checkingForUpdate: 'Verificando se há novas atualizações',
checkFailure: 'Erro na verificação, por favor, tente mais tarde',
updateAvailable: 'Atualização disponível',
downloadingUpdate: 'Baixando a atualização',
updateDownloaded: 'Atualização baixada',
restartToInstall: 'Reinicie o Antares para instalar',
unableEditFieldWithoutPrimary: 'Indisponível a edição de um campo sem a chave primária na tabela de resultados',
editCell: 'Editar celula',
deleteRows: 'Apgar linha | Apagar {count} linhas',
confirmToDeleteRows: 'Você confirma a exclusão de uma linha? | Você confirma a exclusão de {count} linhas?',
notificationsTimeout: 'Notificações de timeout',
uploadFile: 'Upload de arquivo',
addNewRow: 'Adicionar nova linha',
numberOfInserts: 'Número de inserções',
openNewTab: 'Abrir nova aba',
affectedRows: 'Linhas afetadas',
createNewDatabase: 'Criar novo banco de dados',
databaseName: 'Nome do banco de dados',
serverDefault: 'Servidor padrão',
deleteDatabase: 'Apagar banco de dados',
editDatabase: 'Editar banco de dados',
clearChanges: 'Limpar alterações',
addNewField: 'Adicionar novo campo',
manageIndexes: 'Gerenciar índices',
manageForeignKeys: 'Gerenciar chaes estrangeiras',
allowNull: 'Permitir NULL',
zeroFill: 'Preenchimento zero',
customValue: 'Valor personalizado',
onUpdate: 'Quando atualizar',
deleteField: 'Apagar campo',
createNewIndex: 'Criar novo índice',
addToIndex: 'Adicionar ao índice',
createNewTable: 'Criar nova tabela',
emptyTable: 'Tabela vazia',
deleteTable: 'Apagar tabela',
emptyCorfirm: 'Você confirma o esvaziamento',
unsavedChanges: 'Alterações não salvas',
discardUnsavedChanges: 'Você tem algumas alterações não salvas. Ao sair desta guia, essas alterações serão descartadas.',
thereAreNoIndexes: 'Não há índices',
thereAreNoForeign: 'Não há chaves estrangeiras',
createNewForeign: 'Criar nova chave estrangeira',
referenceTable: 'Ref. tabela',
referenceField: 'Ref. campo',
foreignFields: 'Campos estrangeiros',
invalidDefault: 'Padrão inválido',
onDelete: 'Quando apagar',
applicationTheme: 'Tema da aplicação',
editorTheme: 'Editor de tema',
wrapLongLines: 'Quebrar linhas longas',
selectStatement: 'Select statement',
triggerStatement: 'Trigger statement',
sqlSecurity: 'Segurança SQL',
updateOption: 'Opção de atualização',
deleteView: 'Apagar view',
createNewView: 'Criar nova view',
deleteTrigger: 'Apgar trigger',
createNewTrigger: 'Criar nova trigger',
currentUser: 'Usuário atual',
routineBody: 'Corpo da rotina',
dataAccess: 'Acesso de dados',
thereAreNoParameters: 'Não há parametros',
createNewParameter: 'Criar novo parametro',
createNewRoutine: 'Criar nova stored routine',
deleteRoutine: 'Apgar stored routine',
functionBody: 'Corpo da função',
createNewFunction: 'Criar nova função',
deleteFunction: 'Apagar função',
schedulerBody: 'Corpo do agendador',
createNewScheduler: 'Criar novo agendador',
deleteScheduler: 'Apagar agendador',
preserveOnCompletion: 'Preservar na conclusão',
enableSsl: 'Habilitar SSL',
manualValue: 'Valor manual',
tableFiller: 'Preenchedor de tabela',
fakeDataLanguage: 'Linguagem de dados fake',
searchForElements: 'Buscar por elementos',
selectAll: 'Selecionar todos',
queryDuration: 'Tempo de Consulta',
includeBetaUpdates: 'Incluir atualizações beta',
setNull: 'Setar NULL',
processesList: 'Lista de processos',
processInfo: 'Informação de processos',
manageUsers: 'Gerenciar usuários',
createNewSchema: 'Criar novo schema',
schemaName: 'Nome schema',
editSchema: 'Editar schema',
deleteSchema: 'Apagar schema',
markdownSupported: 'Markdown suportado',
plantATree: 'Plante uma árvore'
},
faker: {
address: 'Endereço',
commerce: 'Comércio',
company: 'Empresa',
database: 'Banco de dados',
date: 'Data',
finance: 'Finança',
git: 'Git',
hacker: 'Hacker',
internet: 'Internet',
lorem: 'Lorem',
name: 'Nome',
music: 'Música',
phone: 'Telefone',
random: 'Randomico',
system: 'Sistema',
time: 'Tempo',
vehicle: 'Veículo',
zipCode: 'Código postal',
zipCodeByState: 'Código postal por estado',
city: 'Cidade',
cityPrefix: 'Cidade prefixo',
citySuffix: 'Cidade sufixo',
streetName: 'Nome da rua',
streetAddress: 'Endereço rua',
streetSuffix: 'Rua sufixo',
streetPrefix: 'Rua prefixo',
secondaryAddress: 'Endereço secundário',
county: 'Município',
country: 'País',
countryCode: 'Código do País',
state: 'Estado',
stateAbbr: 'Sigla estado',
latitude: 'Latitude',
longitude: 'Longitude',
direction: 'Direção',
cardinalDirection: 'Direção cardinal',
ordinalDirection: 'Direção Ordinal',
nearbyGPSCoordinate: 'Coordenadas de GPS próximas',
timeZone: 'Fuso Horário',
color: 'Cor',
department: 'Departamento',
productName: 'Nome produto',
price: 'Preço',
productAdjective: 'Adjetivo produto',
productMaterial: 'Material de produto',
product: 'Produto',
productDescription: 'Descrição do produto',
suffixes: 'Sufixos',
companyName: 'Nome da empresa',
companySuffix: 'Sufixo empresa',
catchPhrase: 'Frase de efeito',
bs: 'BS',
catchPhraseAdjective: 'Adjetivo frase de efeito',
catchPhraseDescriptor: 'Descritor de frase de efeito',
catchPhraseNoun: 'Frase de efeito sinônimo',
bsAdjective: 'BS adjetivo',
bsBuzz: 'Rumor BS',
bsNoun: 'Sinônimo BS',
column: 'Coluna',
type: 'Tipo',
collation: 'Colação',
engine: 'Engine',
past: 'Passado',
future: 'Futuro',
between: 'Entre',
recent: 'Recente',
soon: 'Em breve',
month: 'Mês',
weekday: 'Semana',
account: 'Conta',
accountName: 'Nome conta',
routingNumber: 'Número de roteamento',
mask: 'Máscara',
amount: 'Soma',
transactionType: 'Tipo transição',
currencyCode: 'Código moeda',
currencyName: 'Código nome',
currencySymbol: 'Código simbolo',
bitcoinAddress: 'Endereço Bitcoin',
litecoinAddress: 'Endereço Litecoin',
creditCardNumber: 'Número cartão de crédito',
creditCardCVV: 'CVV cartão de crédito',
ethereumAddress: 'Endereço Ethereum',
iban: 'Iban',
bic: 'Bic',
transactionDescription: 'Descrição transação',
branch: 'Branch',
commitEntry: 'Inserção commit',
commitMessage: 'Mensagem commit',
commitSha: 'SHA Commit',
shortSha: 'SHA Curto',
abbreviation: 'Abreviação',
adjective: 'Adjetivo',
noun: 'Sinônimo',
verb: 'Verbo',
ingverb: 'Ingverb',
phrase: 'Frase',
avatar: 'Avatar',
email: 'Email',
exampleEmail: 'Exemplo email',
userName: 'Nome de usuário',
protocol: 'Protocolo',
url: 'Url',
domainName: 'Nome domínio',
domainSuffix: 'Sufixo domíno',
domainWord: 'Palavra de domínio',
ip: 'Ip',
ipv6: 'Ipv6',
userAgent: 'Agente usuário',
mac: 'Mac',
password: 'Senha',
word: 'Palavra',
words: 'Palavras',
sentence: 'Sentença',
slug: 'Slug',
sentences: 'Sentenças',
paragraph: 'Paragrafo',
paragraphs: 'Paragrafos',
text: 'Texto',
lines: 'Linhas',
genre: 'Genero',
firstName: 'Primeiro nome',
lastName: 'Ultimo nome',
middleName: 'Nome do meio',
findName: 'Nome completo',
jobTitle: 'Cargo',
gender: 'Genero',
prefix: 'Prefixo',
suffix: 'Sufixo',
title: 'Titulo',
jobDescriptor: 'Descrição cargo',
jobArea: 'Area de trabalho',
jobType: 'Tipo de trabalho',
phoneNumber: 'Número telefone',
phoneNumberFormat: 'Formato número de telefone',
phoneFormats: 'Formatos de telefone',
number: 'Número',
float: 'Flutuante',
arrayElement: 'Elemento array',
arrayElements: 'Elementos Array',
objectElement: 'Elemento object',
uuid: 'Uuid',
boolean: 'Booleano',
image: 'Imagem',
locale: 'Localidade',
alpha: 'Alpha',
alphaNumeric: 'Alphanumerico',
hexaDecimal: 'Hexadecimal',
fileName: 'Nome arquivo',
commonFileName: 'Nome de arquivo comum',
mimeType: 'Mime type',
commonFileType: 'Tipo de arquivo comum',
commonFileExt: 'Extensão de arquivo comum',
fileType: 'Tipo de arquivo',
fileExt: 'Extensão de arquivo',
directoryPath: 'Caminho do diretório',
filePath: 'Caminho do arquivo',
semver: 'Semver',
manufacturer: 'Fabricante',
model: 'Modelo',
fuel: 'Combusível',
vin: 'Vin'
}
};

View File

@@ -3,5 +3,7 @@ export default {
'it-IT': 'Italiano',
'ar-SA': 'العربية',
'es-ES': 'Español',
'fr-FR': 'Français'
'fr-FR': 'Français',
'pt-BR': 'Português (Brasil)',
'de-DE': 'Deutsch (Deutschland)'
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 172 KiB

View File

@@ -1,6 +1,154 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 210 210">
<defs/>
<path fill="#e36929" d="M180.088 107.51a72.967 69.474 0 01-72.858 69.473 72.967 69.474 0 01-73.075-69.266 72.967 69.474 0 0172.639-69.68 72.967 69.474 0 0173.292 69.056"/>
<path fill="#f8d163" d="M82.985 102.48a17.02 21.735 21.455 01-23.767 14.012 17.02 21.735 21.455 01-7.938-26.403 17.02 21.735 21.455 0123.744-14.091 17.02 21.735 21.455 018.009 26.36m74.797 16.204a17.472 11.51-52.488 01-1.695 20.917 17.472 11.51-52.488 01-19.742 6.678 17.472 11.51-52.488 011.635-20.897 17.472 11.51-52.488 0119.747-6.74"/>
<path fill="#fbfcf7" d="M72.979 98.717a9.143 10.562 0 01-9.13 10.562 9.143 10.562 0 01-9.156-10.53 9.143 10.562 0 019.102-10.594 9.143 10.562 0 019.184 10.499m82.68 32.078a6.21 6.986 0 01-6.2 6.987 6.21 6.986 0 01-6.22-6.966 6.21 6.986 0 016.182-7.007 6.21 6.986 0 016.238 6.945"/>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
<style type="text/css">
.st0{fill:url(#SVGID_1_);}
.st1{fill:url(#XMLID_15_);}
.st2{opacity:0.5;fill:#FFBC00;}
.st3{fill:#FFBC00;}
.st4{fill:url(#XMLID_16_);}
.st5{fill:url(#XMLID_17_);}
.st6{fill:url(#XMLID_18_);}
.st7{fill:url(#XMLID_19_);}
.st8{fill:url(#XMLID_20_);}
.st9{fill:url(#XMLID_21_);}
.st10{opacity:0.46;}
.st11{fill:url(#XMLID_23_);}
.st12{fill:url(#XMLID_24_);}
.st13{fill:url(#XMLID_25_);}
.st14{fill:url(#XMLID_27_);}
.st15{fill:url(#XMLID_28_);}
.st16{fill:url(#XMLID_29_);}
.st17{fill:url(#XMLID_30_);}
.st18{opacity:0.75;}
.st19{opacity:0.44;clip-path:url(#XMLID_31_);}
.st20{fill:url(#XMLID_32_);}
.st21{fill:url(#XMLID_33_);}
.st22{fill:url(#XMLID_34_);}
.st23{fill:url(#XMLID_35_);}
.st24{fill:url(#XMLID_37_);}
.st25{fill:url(#XMLID_38_);}
.st26{opacity:0.43;fill:#FFBC00;}
.st27{opacity:0.58;fill:#FFBC00;}
.st28{fill:#FFBE06;}
.st29{fill:none;}
.st30{fill:url(#XMLID_42_);}
.st31{fill:url(#XMLID_43_);}
.st32{fill:url(#XMLID_44_);}
.st33{fill:url(#XMLID_45_);}
.st34{fill:url(#XMLID_46_);}
.st35{fill:url(#SVGID_4_);}
.st36{fill:url(#SVGID_5_);}
.st37{fill:url(#SVGID_6_);}
.st38{fill:url(#SVGID_7_);}
.st39{fill:url(#SVGID_8_);}
.st40{fill:url(#SVGID_11_);}
.st41{fill:url(#SVGID_12_);}
.st42{fill:url(#SVGID_13_);}
.st43{fill:url(#SVGID_14_);}
.st44{fill:#C68D00;}
.st45{fill:#CE000F;}
</style>
<g>
<radialGradient id="XMLID_15_" cx="358.2692" cy="227.2655" r="830.0055" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#F6971E"/>
<stop offset="0.6338" style="stop-color:#F4592D"/>
<stop offset="0.7025" style="stop-color:#EF4F29"/>
<stop offset="0.8178" style="stop-color:#E1351D"/>
<stop offset="0.9647" style="stop-color:#CA0B0B"/>
<stop offset="1" style="stop-color:#C40006"/>
</radialGradient>
<circle id="XMLID_124_" class="st1" cx="510.3" cy="511.9" r="502.8"/>
<linearGradient id="XMLID_16_" gradientUnits="userSpaceOnUse" x1="505.4734" y1="-52.674" x2="505.4734" y2="155.1105">
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.4"/>
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0"/>
</linearGradient>
<path id="XMLID_59_" class="st4" d="M861.5,198.8c0,87.2-170.7-23.4-344.5-23.4S149.4,294.2,149.4,207S336.5,9,510.3,9
S861.5,111.7,861.5,198.8z"/>
<linearGradient id="XMLID_17_" gradientUnits="userSpaceOnUse" x1="503.3253" y1="-583.7885" x2="503.3253" y2="-376.4571" gradientTransform="matrix(-1 0 0 -1 1017 456.5313)">
<stop offset="5.263158e-03" style="stop-color:#9E3A1D;stop-opacity:0.4"/>
<stop offset="1" style="stop-color:#9E3A1D;stop-opacity:0"/>
</linearGradient>
<path id="XMLID_61_" class="st5" d="M149.4,825.2c0-87.2,170.7,23.4,344.5,23.4s384.1-118.2,384.1-31S674.4,1015,500.7,1015
S149.4,912.3,149.4,825.2z"/>
<linearGradient id="XMLID_18_" gradientUnits="userSpaceOnUse" x1="506.1886" y1="-38.7551" x2="506.1886" y2="169.0294" gradientTransform="matrix(4.489700e-11 1 -1 4.489700e-11 1026.6101 -2.3899)">
<stop offset="5.263158e-03" style="stop-color:#9E3A1D;stop-opacity:0.4"/>
<stop offset="1" style="stop-color:#9E3A1D;stop-opacity:0"/>
</linearGradient>
<path id="XMLID_63_" class="st6" d="M826.8,859.9c-87.2,0,23.4-170.7,23.4-344.5s-118.8-367.7-31.6-367.7s198,187.1,198,360.9
S914,859.9,826.8,859.9z"/>
<linearGradient id="XMLID_19_" gradientUnits="userSpaceOnUse" x1="502.6101" y1="-660.7308" x2="502.6101" y2="-450.373" gradientTransform="matrix(-4.489700e-11 -1 1 -4.489700e-11 570.0789 1014.6101)">
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.4"/>
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0"/>
</linearGradient>
<path id="XMLID_62_" class="st7" d="M200.5,147.7c87.2,0-23.4,170.7-23.4,344.5s118.2,384.1,31,384.1S11.3,701,7.4,512
C3.9,338.3,113.3,147.7,200.5,147.7z"/>
<g id="XMLID_39_" class="st10">
<defs>
<ellipse id="XMLID_36_" transform="matrix(0.8019 -0.5974 0.5974 0.8019 -204.724 406.2339)" class="st10" cx="510.3" cy="511.9" rx="502.8" ry="502.8"/>
</defs>
<clipPath id="XMLID_20_">
<use xlink:href="#XMLID_36_" style="overflow:visible;"/>
</clipPath>
</g>
<g id="XMLID_41_">
<linearGradient id="XMLID_21_" gradientUnits="userSpaceOnUse" x1="64.4989" y1="234.8705" x2="401.1502" y2="480.7042">
<stop offset="0" style="stop-color:#F4592D"/>
<stop offset="1" style="stop-color:#FFD900"/>
</linearGradient>
<path id="XMLID_7_" class="st9" d="M20.9,474.4c15.5-101.8,66.6-201.8,147-275.9c45.6-41.1,90.9-61.6,137.3-67.8
c81.7-8,131.9,63.4,129.6,168.8c0.2,3.6,1.9,4.5,3.6,5.4c8.1-23.2,13-44.6,13.2-65.2c-0.1-117-75.3-177.7-169-155.4
c39.7-9.8,77-7.1,110.5,10.7c27.1,17.9,46.5,42,61.9,77.7c10.4,33,14.3,66.1,10.8,108.9c-8.1,92-54.7,187.5-124.6,250
c-28.9,25.9-56.8,42-84.7,58l0.2,3.6c22.7,1.8,44.7-7.1,69.5-21.4c89.7-55.3,157.3-174.1,178.5-286.6
c-9.2,53.6-26.5,106.2-55,159.8c-25.9,44.6-52.4,82.1-90.3,117c-59.4,50.9-120.5,76.8-176.3,64.3C122.4,611,90.4,545.8,92.6,461
c-0.2-3.6-0.5-7.1-3.6-5.4c-1.4,2.7-4.3,8-5.7,10.7C69,517.3,77.1,562.8,91,601.2c25.5,65.2,86.8,87.5,153.7,75
c-39.7,9.8-77,7.1-110.5-10.7c-27.1-17.9-49.6-40.2-63.6-78.6c-14.7-49.1-19.9-100-0.2-165.2c24.9-83,69.1-166.1,136.9-212.5
c20-13.4,38.7-24.1,60.4-36.6c3.1-1.8,2.9-5.4,1.2-6.2C159.4,170,46.5,333.3,20.9,474.4L20.9,474.4z"/>
<linearGradient id="XMLID_22_" gradientUnits="userSpaceOnUse" x1="438.1351" y1="490.0881" x2="196.6566" y2="356.1772">
<stop offset="0" style="stop-color:#F64626"/>
<stop offset="1" style="stop-color:#FFD900"/>
</linearGradient>
<path id="XMLID_40_" style="fill:url(#XMLID_22_);" d="M86.7,460.9C98,387.2,135,314.8,193.2,261.1c33-29.7,65.9-44.6,99.4-49.1
c59.2-5.8,95.5,45.9,93.8,122.2c0.2,2.6,1.4,3.2,2.6,3.9c5.8-16.8,9.4-32.3,9.6-47.2c-0.1-84.7-54.6-128.7-122.4-112.5
c28.7-7.1,55.7-5.2,80,7.8c19.6,12.9,33.7,30.4,44.8,56.3c7.5,23.9,10.3,47.9,7.8,78.9c-5.9,66.6-39.6,135.8-90.2,181.1
c-20.9,18.8-41.1,30.4-61.4,42l0.2,2.6c16.5,1.3,32.4-5.2,50.3-15.5c65-40.1,113.9-126.1,129.3-207.6
c-6.6,38.8-19.2,77-39.9,115.8c-18.8,32.3-37.9,59.5-65.4,84.7c-43,36.9-87.3,55.6-127.7,46.6c-44-11-67.2-58.2-65.6-119.6
c-0.2-2.6-0.4-5.2-2.6-3.9c-1,1.9-3.1,5.8-4.1,7.8c-10.3,36.9-4.5,69.8,5.6,97.7c18.5,47.2,62.9,63.4,111.3,54.3
c-28.7,7.1-55.7,5.2-80-7.8c-19.6-12.9-35.9-29.1-46-56.9c-10.7-35.6-14.4-72.4-0.2-119.6c18-60.1,50.1-120.3,99.1-153.9
c14.5-9.7,28-17.5,43.7-26.5c2.2-1.3,2.1-3.9,0.9-4.5C187.1,240.4,105.3,358.8,86.7,460.9L86.7,460.9z"/>
</g>
<g id="XMLID_11_">
<linearGradient id="XMLID_23_" gradientUnits="userSpaceOnUse" x1="-316.9261" y1="9.5862" x2="-92.0354" y2="173.8087" gradientTransform="matrix(-0.9998 -2.148304e-02 2.148304e-02 -0.9998 625.9278 811.8477)">
<stop offset="0" style="stop-color:#F4592D"/>
<stop offset="1" style="stop-color:#FFD900"/>
</linearGradient>
<path id="XMLID_13_" class="st11" d="M975.6,649.7c-11.8,67.8-47.4,133.8-102.1,182.1c-31,26.8-61.6,39.8-92.7,43.3
c-54.7,4.2-87.2-44.2-84.1-114.6c-0.1-2.4-1.2-3-2.3-3.6c-5.7,15.4-9.3,29.6-9.8,43.3c-1.6,78.1,47.8,119.8,110.6,106.2
c-26.6,6-51.5,3.7-73.6-8.7c-17.8-12.3-30.5-28.7-40.2-52.8c-6.5-22.2-8.6-44.3-5.7-72.9c6.7-61.3,39.2-124.4,86.8-165.2
c19.6-16.9,38.5-27.2,57.4-37.5l-0.1-2.4c-15.1-1.5-29.9,4.1-46.7,13.3c-60.7,35.7-107.6,114-123.3,188.8
c6.9-35.6,19.2-70.6,39-105.9c18-29.4,36.2-54.1,62-76.8c40.4-33.1,81.6-49.5,118.6-40.4c40.4,11,60.8,55,58.1,111.6
c0.1,2.4,0.2,4.8,2.3,3.6c1-1.8,3-5.3,4-7.1c10.2-33.8,5.5-64.3-3.3-90.2c-16.1-43.9-56.7-59.7-101.6-52.3
c26.6-6,51.5-3.7,73.6,8.7c17.8,12.3,32.6,27.5,41.3,53.4c9.1,33,11.8,67.1-2.2,110.3c-17.8,55.1-48.5,109.9-94.5,140
c-13.6,8.7-26.2,15.5-40.9,23.6c-2.1,1.1-2,3.5-0.9,4.2C878.7,851.1,956.4,743.6,975.6,649.7L975.6,649.7z"/>
<linearGradient id="XMLID_24_" gradientUnits="userSpaceOnUse" x1="-52.9013" y1="188.0779" x2="-214.2144" y2="98.6225" gradientTransform="matrix(-0.9998 -2.148304e-02 2.148304e-02 -0.9998 625.9278 811.8477)">
<stop offset="0" style="stop-color:#F42C2D"/>
<stop offset="1" style="stop-color:#FFD900"/>
</linearGradient>
<path id="XMLID_12_" class="st12" d="M931.4,657.8c-8.6,49.1-34.3,96.9-74,131.9c-22.5,19.4-44.6,28.9-67.1,31.4
c-39.6,3-63.2-32-60.9-83c-0.1-1.7-0.9-2.2-1.7-2.6c-4.1,11.1-6.8,21.5-7.1,31.4c-1.2,56.6,34.6,86.7,80.1,76.9
c-19.3,4.3-37.3,2.7-53.3-6.3c-12.9-8.9-22.1-20.8-29.1-38.2c-4.7-16.1-6.2-32.1-4.1-52.8c4.9-44.4,28.4-90.1,62.9-119.6
c14.2-12.2,27.9-19.7,41.6-27.2l-0.1-1.7c-11-1.1-21.7,3-33.8,9.6c-44,25.8-77.9,82.6-89.3,136.8c5-25.8,13.9-51.1,28.3-76.7
c13-21.3,26.2-39.2,44.9-55.6c29.3-24,59.1-35.9,85.9-29.3c29.2,8,44,39.8,42.1,80.8c0.1,1.7,0.2,3.5,1.7,2.6
c0.7-1.3,2.2-3.8,2.9-5.1c7.4-24.5,4-46.6-2.4-65.3c-11.7-31.8-41.1-43.2-73.6-37.9c19.3-4.3,37.3-2.7,53.3,6.3
c12.9,8.9,23.6,20,29.9,38.7c6.6,23.9,8.6,48.6-1.6,79.9c-12.9,39.9-35.2,79.6-68.4,101.4c-9.8,6.3-19,11.3-29.6,17.1
c-1.5,0.8-1.4,2.6-0.6,3C861.2,803.6,917.5,725.7,931.4,657.8L931.4,657.8z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 880 B

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

@@ -30,6 +30,12 @@
animation: jump-down-in 0.2s reverse;
}
.pulse {
animation-name: pulse;
animation-duration: 2s;
animation-iteration-count: infinite;
}
@keyframes jump-down-in {
0% {
transform: scale(0);
@@ -39,3 +45,17 @@
transform: scale(1);
}
}
@keyframes pulse {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}

View File

@@ -30,6 +30,10 @@ body {
cursor: help;
}
.no-outline {
outline: none !important;
}
.no-border {
outline: none !important;
border: none !important;
@@ -132,6 +136,21 @@ body {
box-shadow: none;
}
}
&.badge-connected::after {
background: $success-color;
}
&.badge-connecting::after {
background: $warning-color;
animation-name: pulse;
animation-duration: 2s;
animation-iteration-count: infinite;
}
&.badge-failed::after {
background: $error-color;
}
}
.form-select {

View File

@@ -386,7 +386,6 @@
bottom: -10px;
right: 0;
position: absolute;
background: $success-color;
}
&.badge-update::after {

View File

@@ -168,7 +168,6 @@
bottom: -10px;
right: 0;
position: absolute;
background: $success-color;
}
&.badge-update::after {

View File

@@ -1,8 +1,7 @@
'use strict';
import Store from 'electron-store';
import crypto from 'crypto';
import Application from '../../ipc-api/Application';
const key = Application.getKey() || localStorage.getItem('key');
const key = localStorage.getItem('key');
if (!key)
localStorage.setItem('key', crypto.randomBytes(16).toString('hex'));

View File

@@ -11,6 +11,7 @@ export default {
allow_prerelease: persistentStore.get('allow_prerelease', true),
explorebar_size: persistentStore.get('explorebar_size', null),
notifications_timeout: persistentStore.get('notifications_timeout', 5),
data_tab_limit: persistentStore.get('data_tab_limit', 1000),
auto_complete: persistentStore.get('auto_complete', true),
line_wrap: persistentStore.get('line_wrap', true),
application_theme: persistentStore.get('application_theme', 'dark'),
@@ -18,6 +19,7 @@ export default {
},
getters: {
getLocale: state => state.locale,
getDataTabLimit: state => state.data_tab_limit,
getAllowPrerelease: state => state.allow_prerelease,
getExplorebarSize: state => state.explorebar_size,
getNotificationsTimeout: state => state.notifications_timeout,
@@ -32,6 +34,10 @@ export default {
i18n.locale = locale;
persistentStore.set('locale', state.locale);
},
SET_DATA_TAB_LIMIT (state, limit) {
state.data_tab_limit = limit;
persistentStore.set('data_tab_limit', state.data_tab_limit);
},
SET_ALLOW_PRERELEASE (state, allow) {
state.allow_prerelease = allow;
persistentStore.set('allow_prerelease', state.allow_prerelease);
@@ -65,6 +71,9 @@ export default {
changeLocale ({ commit }, locale) {
commit('SET_LOCALE', locale);
},
changePageSize ({ commit }, limit) {
commit('SET_DATA_TAB_LIMIT', limit);
},
changeAllowPrerelease ({ commit }, allow) {
commit('SET_ALLOW_PRERELEASE', allow);
},

View File

@@ -37,7 +37,7 @@ export default {
},
getConnected: state => {
return state.workspaces
.filter(workspace => workspace.connected)
.filter(workspace => workspace.connection_status === 'connected')
.map(workspace => workspace.uid);
},
getLoadedSchemas: state => uid => {
@@ -54,7 +54,7 @@ export default {
SELECT_WORKSPACE (state, uid) {
state.selected_workspace = uid;
},
ADD_CONNECTED (state, payload) {
SET_CONNECTED (state, payload) {
const { uid, client, dataTypes, indexTypes, customizations, structure, version } = payload;
state.workspaces = state.workspaces.map(workspace => workspace.uid === uid
@@ -65,19 +65,41 @@ export default {
indexTypes,
customizations,
structure,
connected: true,
connection_status: 'connected',
version
}
: workspace);
},
REMOVE_CONNECTED (state, uid) {
SET_CONNECTING (state, uid) {
state.workspaces = state.workspaces.map(workspace => workspace.uid === uid
? {
...workspace,
structure: {},
breadcrumbs: {},
loaded_schemas: new Set(),
connected: false
connection_status: 'connecting'
}
: workspace);
},
SET_FAILED (state, uid) {
state.workspaces = state.workspaces.map(workspace => workspace.uid === uid
? {
...workspace,
structure: {},
breadcrumbs: {},
loaded_schemas: new Set(),
connection_status: 'failed'
}
: workspace);
},
SET_DISCONNECTED (state, uid) {
state.workspaces = state.workspaces.map(workspace => workspace.uid === uid
? {
...workspace,
structure: {},
breadcrumbs: {},
loaded_schemas: new Set(),
connection_status: 'disconnected'
}
: workspace);
},
@@ -247,10 +269,14 @@ export default {
commit('SELECT_WORKSPACE', uid);
},
async connectWorkspace ({ dispatch, commit }, connection) {
commit('SET_CONNECTING', connection.uid);
try {
const { status, response } = await Connection.connect(connection);
if (status === 'error')
if (status === 'error') {
dispatch('notifications/addNotification', { status, message: response }, { root: true });
commit('SET_FAILED', connection.uid);
}
else {
let dataTypes = [];
let indexTypes = [];
@@ -288,7 +314,7 @@ export default {
dispatch('connections/editConnection', connProxy, { root: true });
}
commit('ADD_CONNECTED', {
commit('SET_CONNECTED', {
uid: connection.uid,
client: connection.client,
dataTypes,
@@ -382,13 +408,13 @@ export default {
},
removeConnected ({ commit }, uid) {
Connection.disconnect(uid);
commit('REMOVE_CONNECTED', uid);
commit('SET_DISCONNECTED', uid);
commit('SELECT_TAB', { uid, tab: 0 });
},
addWorkspace ({ commit, dispatch, getters }, uid) {
const workspace = {
uid,
connected: false,
connection_status: 'disconnected',
selected_tab: 0,
search_term: '',
tabs: [],