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

Compare commits

...

83 Commits

Author SHA1 Message Date
275344eb8b chore(release): 0.7.19-beta.1 2023-10-26 01:07:15 +02:00
cf24adf99e Merge branch 'develop' of https://github.com/antares-sql/antares into beta 2023-10-26 01:06:54 +02:00
2eae580e18 chore: update electron 2023-10-22 19:04:31 +02:00
e4eb27d503 feat(MySQL): RLIKE and NOT RLIKE regular expression filters, closes #688 2023-10-18 18:08:01 +02:00
580973fd04 chore(release): 0.7.19-beta.0 2023-10-14 15:04:00 +02:00
215ab783ab chore: email change 2023-10-14 15:03:09 +02:00
72148e991c Merge branch 'master' of https://github.com/antares-sql/antares into develop 2023-10-13 09:23:41 +02:00
6e4c16741a chore: Update CODE_OF_CONDUCT.md 2023-10-13 09:22:04 +02:00
9f9c63bfcc feat: "now" and "random" options added in datetime related data in insert rows tool, closes #402 2023-10-10 18:36:35 +02:00
c0dcf30e73 fix: IN and NOT IN filters not working properly, fixes #687 2023-10-09 18:13:30 +02:00
ddd290c903 fix: timeout issue on long time sql import 2023-10-03 18:19:16 +02:00
267c017921 chore(release): 0.7.18 2023-10-03 09:31:58 +02:00
b3b698b3a2 fix: hotfix for Microsoft Store unauthorized process 2023-10-03 09:31:26 +02:00
71ac3a5164 chore(release): 0.7.17 2023-09-30 16:46:49 +02:00
6fc4418c02 chore(release): 0.7.17-beta.2 2023-09-28 18:11:10 +02:00
b37781df84 fix(UI): small icons in foreign key modal 2023-09-26 18:31:58 +02:00
9c66fd51cb feat: add NOT LIKE to table filters, closes #672 2023-09-25 18:16:07 +02:00
98c1f43a4d refactor: removed icon fonts in ace editor 2023-09-25 18:14:21 +02:00
12825c69d4 Merge branch 'beta' of https://github.com/antares-sql/antares into develop 2023-09-24 23:06:01 +02:00
198ff0103b fix: nsis updater not working 2023-09-24 23:04:35 +02:00
94ce615fc8 chore(release): 0.7.17-beta.1 2023-09-23 16:00:52 +02:00
354928e302 fix(UI): small icons in sidebar elements with long name 2023-09-21 11:18:00 +02:00
6dceaf09be fix(SQLite): table content not refresh after an update, fixes #665 2023-09-20 17:54:25 +02:00
b321e64b83 fix(SQLite): field length lost when editing a table, fixes #664 2023-09-19 18:12:49 +02:00
7e36260cdb fix: table filter not working when search string on integer field, #671 2023-09-19 18:10:27 +02:00
894087e196 Merge branch 'beta' of https://github.com/antares-sql/antares into develop 2023-09-18 15:13:03 +02:00
922f56f69b fix: flip not working on BaseIcon component 2023-09-18 08:56:26 +02:00
7d84b4e81f chore(release): 0.7.17-beta.0 2023-09-17 23:56:24 +02:00
495e48625c ci: manual creation of arm64 linux artifacts 2023-09-17 23:56:05 +02:00
5934d3a990 ci: update beta build node version 2023-09-17 19:59:13 +02:00
cb92ca99f6 refactor: minor refactor 2023-09-17 19:04:24 +02:00
e7bec0aaaf perf: migration from font icons to svg icons 2023-09-17 18:49:37 +02:00
9de5f67d18 perf: improved ipc validation on Linux 2023-09-13 16:30:08 +02:00
13592425af perf(core): improved app security, fixes #666 2023-09-13 14:21:31 +02:00
0de5ef8a98 fix: empty workspace deleting connections in some conditions 2023-09-11 18:02:19 +02:00
785bc40ad0 build(deps): update some dependencies (vue, pinia, electron) 2023-09-08 15:05:28 +02:00
940f64e6ab refactor: small cleanup 2023-09-08 09:20:13 +02:00
535dd21d69 Merge pull request #662 from 64knl/feat/update-dutch-translation
feat(translation): Update Dutch
2023-09-07 15:50:04 +02:00
Rene
b43c4000d5 feat(translation): Update Dutch 2023-09-07 10:44:38 +02:00
757a2b3cbf fix(SQLite): disconnecting a sqlite connection does not truly close it, fixes #661 2023-09-05 18:08:43 +02:00
c78258219a Merge branch 'master' of https://github.com/antares-sql/antares into develop 2023-09-05 17:45:47 +02:00
fe23d86694 Merge pull request #633 from digitalgopnik/feat/ssh-keep-alive-interval
feat: customize keep-alive-interval for ssh-tunnel
2023-09-04 17:12:39 +02:00
8d605ee287 feat: keep alive interval in seconds 2023-09-04 16:27:50 +02:00
fbe271af37 refactor: adaptation for changes to i18n 2023-09-04 15:27:56 +02:00
b838916937 Merge branch 'develop' of https://github.com/antares-sql/antares into pr/digitalgopnik/633 2023-09-04 14:59:21 +02:00
77ab561058 Merge pull request #660 from antares-sql/dependabot/npm_and_yarn/develop/ace-builds-1.24.1
build(deps): bump ace-builds from 1.14.0 to 1.24.1
2023-09-04 14:05:33 +02:00
dependabot[bot]
7bb03b4922 build(deps): bump ace-builds from 1.14.0 to 1.24.1
Bumps [ace-builds](https://github.com/ajaxorg/ace-builds) from 1.14.0 to 1.24.1.
- [Release notes](https://github.com/ajaxorg/ace-builds/releases)
- [Changelog](https://github.com/ajaxorg/ace-builds/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ajaxorg/ace-builds/compare/v1.14.0...v1.24.1)

---
updated-dependencies:
- dependency-name: ace-builds
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-04 11:53:17 +00:00
de607a6b06 Merge pull request #659 from antares-sql/dependabot/npm_and_yarn/develop/vueuse/core-10.4.1
build(deps): bump @vueuse/core from 8.7.5 to 10.4.1
2023-09-04 13:52:29 +02:00
c5f89f9fdd Merge pull request #640 from antares-sql/dependabot/npm_and_yarn/develop/mdi/font-7.2.96
build(deps): bump @mdi/font from 7.1.96 to 7.2.96
2023-09-04 13:48:41 +02:00
bf46b89988 Merge pull request #658 from antares-sql/dependabot/npm_and_yarn/develop/sql-formatter-13.0.0
build(deps): bump sql-formatter from 12.2.2 to 13.0.0
2023-09-04 13:38:33 +02:00
e6f45d71c7 fix(UI): update notification indicator moves settings icon 2023-09-02 16:09:19 +02:00
dependabot[bot]
8608c27f20 build(deps): bump @vueuse/core from 8.7.5 to 10.4.1
Bumps [@vueuse/core](https://github.com/vueuse/vueuse/tree/HEAD/packages/core) from 8.7.5 to 10.4.1.
- [Release notes](https://github.com/vueuse/vueuse/releases)
- [Commits](https://github.com/vueuse/vueuse/commits/v10.4.1/packages/core)

---
updated-dependencies:
- dependency-name: "@vueuse/core"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-01 19:14:14 +00:00
dependabot[bot]
e031c75e28 build(deps): bump sql-formatter from 12.2.2 to 13.0.0
Bumps [sql-formatter](https://github.com/sql-formatter-org/sql-formatter) from 12.2.2 to 13.0.0.
- [Release notes](https://github.com/sql-formatter-org/sql-formatter/releases)
- [Changelog](https://github.com/sql-formatter-org/sql-formatter/blob/master/.release-it.json)
- [Commits](https://github.com/sql-formatter-org/sql-formatter/compare/v12.2.2...v13.0.0)

---
updated-dependencies:
- dependency-name: sql-formatter
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-01 19:13:36 +00:00
c1891dd5de chore(release): 0.7.16 2023-08-26 15:21:02 +02:00
53fe986bcb Merge branch 'master' of https://github.com/antares-sql/antares into beta 2023-08-26 15:19:45 +02:00
661043b181 Merge branch 'master' of https://github.com/antares-sql/antares into develop 2023-08-26 15:14:10 +02:00
b74ec71b10 chore: mastodon social link 2023-08-18 16:05:04 +02:00
54df0e4aa8 style: implement eslint simple-import-sort 2023-08-18 15:57:31 +02:00
d702ce3fa9 chore(release): 0.7.16-beta.1 2023-08-18 12:22:56 +02:00
63544e95da Merge branch 'feat/export-connections' of https://github.com/antares-sql/antares into develop 2023-08-18 12:12:05 +02:00
6df214558f feat: ability to import connections 2023-08-18 12:11:08 +02:00
f5b86e59e7 feat: ability to export connections 2023-08-17 13:48:55 +02:00
28f14c9195 Merge pull request #653 from antares-sql/all-contributors/add-Lawondyss
docs: add Lawondyss as a contributor for translation
2023-08-14 12:17:38 +02:00
allcontributors[bot]
90922e6f96 docs: update .all-contributorsrc [skip ci] 2023-08-14 10:17:13 +00:00
allcontributors[bot]
4b414df7e4 docs: update README.md [skip ci] 2023-08-14 10:17:12 +00:00
27f0068415 Merge pull request #652 from Lawondyss/develop
Add CZ translation and titles for buttons
2023-08-14 12:16:44 +02:00
Ladislav Vondráček
52e42fa1b5 fix: add some missing titles of buttons 2023-08-14 11:50:38 +02:00
Ladislav Vondráček
5b9b539bc7 chore(i18n): add czech translation 2023-08-14 11:47:41 +02:00
832aa75ebe fix(SQLite): improved view body parsing 2023-08-14 10:44:36 +02:00
aba67f3872 refactor(translation): refactor ca-ES to new format 2023-08-14 09:16:40 +02:00
5a1644f023 Merge branches 'develop' and 'master' of https://github.com/antares-sql/antares into develop 2023-08-14 09:07:55 +02:00
e372712556 Merge pull request #651 from antares-sql/all-contributors/add-markusand
docs: add markusand as a contributor for translation
2023-08-14 09:06:55 +02:00
d4727a7d20 Merge pull request #649 from markusand/master
feat: Add support for catalan language
2023-08-14 09:06:42 +02:00
allcontributors[bot]
f2c2f33afa docs: update .all-contributorsrc [skip ci] 2023-08-14 07:06:40 +00:00
allcontributors[bot]
6dc4bdd0c0 docs: update README.md [skip ci] 2023-08-14 07:06:39 +00:00
Marc Vilella
9c6f1a9ea5 feat: Add catalan language 2023-08-13 19:20:26 +02:00
dd264f802e ci: update snapcraft.yaml 2023-08-11 18:12:38 +02:00
fed0e10702 Merge branch 'master' of https://github.com/antares-sql/antares into beta 2023-08-11 17:34:50 +02:00
e7ce4ef6ed Merge branch 'master' of https://github.com/antares-sql/antares 2023-08-11 17:34:30 +02:00
e03f2eef49 ci: update snapcraft.yaml 2023-08-11 17:34:27 +02:00
Christian Ratz
c0c33f8237 Merge branch 'develop' into feat/ssh-keep-alive-interval 2023-08-04 11:12:48 +02:00
Christian Ratz
b4731d67a5 feat: customize keep-alive-interval for ssh-tunnel 2023-08-04 11:06:35 +02:00
dependabot[bot]
de40414a0d build(deps): bump @mdi/font from 7.1.96 to 7.2.96
Bumps [@mdi/font](https://github.com/Templarian/MaterialDesign-Webfont) from 7.1.96 to 7.2.96.
- [Commits](https://github.com/Templarian/MaterialDesign-Webfont/compare/v7.1.96...v7.2.96)

---
updated-dependencies:
- dependency-name: "@mdi/font"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-31 08:55:49 +00:00
192 changed files with 5528 additions and 1477 deletions

View File

@@ -239,6 +239,24 @@
"contributions": [ "contributions": [
"platform" "platform"
] ]
},
{
"login": "markusand",
"name": "Marc Vilella",
"avatar_url": "https://avatars.githubusercontent.com/u/12972543?v=4",
"profile": "https://github.com/markusand",
"contributions": [
"translation"
]
},
{
"login": "Lawondyss",
"name": "Ladislav Vondráček",
"avatar_url": "https://avatars.githubusercontent.com/u/272130?v=4",
"profile": "https://github.com/Lawondyss",
"contributions": [
"translation"
]
} }
], ],
"contributorsPerLine": 7, "contributorsPerLine": 7,

View File

@@ -18,7 +18,8 @@
}, },
"plugins": [ "plugins": [
"vue", "vue",
"@typescript-eslint" "@typescript-eslint",
"simple-import-sort"
], ],
"rules": { "rules": {
"space-infix-ops": "off", "space-infix-ops": "off",
@@ -91,6 +92,8 @@
} }
} }
], ],
"@typescript-eslint/no-var-requires": "off" "@typescript-eslint/no-var-requires": "off",
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error"
} }
} }

View File

@@ -25,7 +25,7 @@ jobs:
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 16 node-version: 18
- name: Install dependencies - name: Install dependencies
run: npm i run: npm i

View File

@@ -9,11 +9,13 @@ jobs:
steps: steps:
- name: Check out Git repository - name: Check out Git repository
uses: actions/checkout@v3 uses: actions/checkout@v3
with:
ref: master
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 16 node-version: 18
- name: Install dependencies - name: Install dependencies
run: npm i run: npm i

View File

@@ -2,6 +2,99 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.7.19-beta.1](https://github.com/antares-sql/antares/compare/v0.7.19-beta.0...v0.7.19-beta.1) (2023-10-25)
### Features
* **MySQL:** RLIKE and NOT RLIKE regular expression filters, closes [#688](https://github.com/antares-sql/antares/issues/688) ([e4eb27d](https://github.com/antares-sql/antares/commit/e4eb27d503e8f912178359c01c62a9b523d17848))
### [0.7.19-beta.0](https://github.com/antares-sql/antares/compare/v0.7.18...v0.7.19-beta.0) (2023-10-14)
### Features
* "now" and "random" options added in datetime related data in insert rows tool, closes [#402](https://github.com/antares-sql/antares/issues/402) ([9f9c63b](https://github.com/antares-sql/antares/commit/9f9c63bfcc3423bfeef143cd835f48c62900a799))
### Bug Fixes
* IN and NOT IN filters not working properly, fixes [#687](https://github.com/antares-sql/antares/issues/687) ([c0dcf30](https://github.com/antares-sql/antares/commit/c0dcf30e73a69b25b01ba31d21b27c1983ed2db6))
* timeout issue on long time sql import ([ddd290c](https://github.com/antares-sql/antares/commit/ddd290c90344241eaa70cb528552e942fd7edec0))
### [0.7.18](https://github.com/antares-sql/antares/compare/v0.7.17...v0.7.18) (2023-10-03)
### Bug Fixes
* hotfix for Microsoft Store unauthorized process ([b3b698b](https://github.com/antares-sql/antares/commit/b3b698b3a23a3c848921ab40fc0fec5d8178ef0e))
### [0.7.17](https://github.com/antares-sql/antares/compare/v0.7.17-beta.2...v0.7.17) (2023-09-30)
### [0.7.17-beta.2](https://github.com/antares-sql/antares/compare/v0.7.17-beta.1...v0.7.17-beta.2) (2023-09-28)
### Features
* add NOT LIKE to table filters, closes [#672](https://github.com/antares-sql/antares/issues/672) ([9c66fd5](https://github.com/antares-sql/antares/commit/9c66fd51cbbe6f21a1fa6a34cc962496d3db7a98))
### Bug Fixes
* nsis updater not working ([198ff01](https://github.com/antares-sql/antares/commit/198ff0103bfa95e3491296d352c944165f31b87e))
* **UI:** small icons in foreign key modal ([b37781d](https://github.com/antares-sql/antares/commit/b37781df84cf7ee99a69ecaa54480d662d79c4aa))
### [0.7.17-beta.1](https://github.com/antares-sql/antares/compare/v0.7.17-beta.0...v0.7.17-beta.1) (2023-09-23)
### Bug Fixes
* flip not working on BaseIcon component ([922f56f](https://github.com/antares-sql/antares/commit/922f56f69b168302a9d1ff86565d3f09400d6a7c))
* **SQLite:** field length lost when editing a table, fixes [#664](https://github.com/antares-sql/antares/issues/664) ([b321e64](https://github.com/antares-sql/antares/commit/b321e64b835e0b39da116c4a77bac50247f240f3))
* **SQLite:** table content not refresh after an update, fixes [#665](https://github.com/antares-sql/antares/issues/665) ([6dceaf0](https://github.com/antares-sql/antares/commit/6dceaf09be7bd46f1915721abd03253ffc517256))
* table filter not working when search string on integer field, [#671](https://github.com/antares-sql/antares/issues/671) ([7e36260](https://github.com/antares-sql/antares/commit/7e36260cdb0438197152b5c6ac61db8ae8a9791a))
* **UI:** small icons in sidebar elements with long name ([354928e](https://github.com/antares-sql/antares/commit/354928e302437d608903d1434d99d68eb79aa6e9))
### [0.7.17-beta.0](https://github.com/antares-sql/antares/compare/v0.7.16...v0.7.17-beta.0) (2023-09-17)
### Features
* customize keep-alive-interval for ssh-tunnel ([b4731d6](https://github.com/antares-sql/antares/commit/b4731d67a5b819bf87c437eb626f30a7489477f9))
* keep alive interval in seconds ([8d605ee](https://github.com/antares-sql/antares/commit/8d605ee2872c20495f0ac4de84bf17d61c6455ae))
* **translation:** Update Dutch ([b43c400](https://github.com/antares-sql/antares/commit/b43c4000d5905838348c391f25b3228dc6a6b2ac))
### Bug Fixes
* empty workspace deleting connections in some conditions ([0de5ef8](https://github.com/antares-sql/antares/commit/0de5ef8a985cc8d9f1fa4479eeaf7dbb20f5fd7c))
* **SQLite:** disconnecting a sqlite connection does not truly close it, fixes [#661](https://github.com/antares-sql/antares/issues/661) ([757a2b3](https://github.com/antares-sql/antares/commit/757a2b3cbf0d7f4df37eb5d90faa2f9821794e5f))
* **UI:** update notification indicator moves settings icon ([e6f45d7](https://github.com/antares-sql/antares/commit/e6f45d71c75206187a7ae87e5f90a22d288a53ef))
### Improvements
* **core:** improved app security, fixes [#666](https://github.com/antares-sql/antares/issues/666) ([1359242](https://github.com/antares-sql/antares/commit/13592425afc643fe7188463fe4a2d02b6e27f87c))
* improved ipc validation on Linux ([9de5f67](https://github.com/antares-sql/antares/commit/9de5f67d189c9b56fff41b29e6df69a3909bfa26))
* migration from font icons to svg icons ([e7bec0a](https://github.com/antares-sql/antares/commit/e7bec0aaaf019fe0c3040d2d9443233e46a60188))
### [0.7.16](https://github.com/antares-sql/antares/compare/v0.7.16-beta.1...v0.7.16) (2023-08-26)
### [0.7.16-beta.1](https://github.com/antares-sql/antares/compare/v0.7.16-beta.0...v0.7.16-beta.1) (2023-08-18)
### Features
* ability to export connections ([f5b86e5](https://github.com/antares-sql/antares/commit/f5b86e59e7e41bbbe1555ec8a85ec1f849e8271d))
* ability to import connections ([6df2145](https://github.com/antares-sql/antares/commit/6df214558f8186dd5fbf101505465f4c07c8ad5f))
* Add catalan language ([9c6f1a9](https://github.com/antares-sql/antares/commit/9c6f1a9ea52b4791082bdbae91b764c486684c3b))
### Bug Fixes
* add some missing titles of buttons ([52e42fa](https://github.com/antares-sql/antares/commit/52e42fa1b529512154c0680124c5e425964a5b1a))
* **SQLite:** improved view body parsing ([832aa75](https://github.com/antares-sql/antares/commit/832aa75ebe46776b9c365dde2dd13db3746adcd5))
### [0.7.16-beta.0](https://github.com/antares-sql/antares/compare/v0.7.15...v0.7.16-beta.0) (2023-08-11) ### [0.7.16-beta.0](https://github.com/antares-sql/antares/compare/v0.7.15...v0.7.16-beta.0) (2023-08-11)

View File

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

View File

@@ -153,6 +153,8 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center" valign="top" width="14.28%"><a href="https://github.com/m1khal3v"><img src="https://avatars.githubusercontent.com/u/41085561?v=4?s=100" width="100px;" alt="Anton Mikhalev"/><br /><sub><b>Anton Mikhalev</b></sub></a><br /><a href="#translation-m1khal3v" title="Translation">🌍</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/m1khal3v"><img src="https://avatars.githubusercontent.com/u/41085561?v=4?s=100" width="100px;" alt="Anton Mikhalev"/><br /><sub><b>Anton Mikhalev</b></sub></a><br /><a href="#translation-m1khal3v" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://64k.nl/"><img src="https://avatars.githubusercontent.com/u/3864423?v=4?s=100" width="100px;" alt="René"/><br /><sub><b>René</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=64knl" title="Code">💻</a> <a href="#translation-64knl" title="Translation">🌍</a></td> <td align="center" valign="top" width="14.28%"><a href="https://64k.nl/"><img src="https://avatars.githubusercontent.com/u/3864423?v=4?s=100" width="100px;" alt="René"/><br /><sub><b>René</b></sub></a><br /><a href="https://github.com/antares-sql/antares/commits?author=64knl" title="Code">💻</a> <a href="#translation-64knl" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zxp19821005"><img src="https://avatars.githubusercontent.com/u/4915850?v=4?s=100" width="100px;" alt="Woodenman"/><br /><sub><b>Woodenman</b></sub></a><br /><a href="#platform-zxp19821005" title="Packaging/porting to new platform">📦</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/zxp19821005"><img src="https://avatars.githubusercontent.com/u/4915850?v=4?s=100" width="100px;" alt="Woodenman"/><br /><sub><b>Woodenman</b></sub></a><br /><a href="#platform-zxp19821005" title="Packaging/porting to new platform">📦</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/markusand"><img src="https://avatars.githubusercontent.com/u/12972543?v=4?s=100" width="100px;" alt="Marc Vilella"/><br /><sub><b>Marc Vilella</b></sub></a><br /><a href="#translation-markusand" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Lawondyss"><img src="https://avatars.githubusercontent.com/u/272130?v=4?s=100" width="100px;" alt="Ladislav Vondráček"/><br /><sub><b>Ladislav Vondráček</b></sub></a><br /><a href="#translation-Lawondyss" title="Translation">🌍</a></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

361
package-lock.json generated
View File

@@ -1,21 +1,22 @@
{ {
"name": "antares", "name": "antares",
"version": "0.7.16-beta.0", "version": "0.7.19-beta.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "antares", "name": "antares",
"version": "0.7.16-beta.0", "version": "0.7.19-beta.1",
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@electron/remote": "~2.0.1", "@electron/remote": "~2.0.1",
"@faker-js/faker": "~6.1.2", "@faker-js/faker": "~6.1.2",
"@mdi/font": "~7.1.96", "@jamescoyle/vue-icon": "~0.1.2",
"@mdi/js": "~7.2.96",
"@turf/helpers": "~6.5.0", "@turf/helpers": "~6.5.0",
"@vueuse/core": "~8.7.5", "@vueuse/core": "~10.4.1",
"ace-builds": "~1.14.0", "ace-builds": "~1.24.1",
"better-sqlite3": "~8.0.0", "better-sqlite3": "~8.0.0",
"electron-log": "~4.4.1", "electron-log": "~4.4.1",
"electron-store": "~8.1.0", "electron-store": "~8.1.0",
@@ -33,13 +34,13 @@
"pg-connection-string": "~2.5.0", "pg-connection-string": "~2.5.0",
"pg-query-stream": "~4.2.3", "pg-query-stream": "~4.2.3",
"pgsql-ast-parser": "~7.2.1", "pgsql-ast-parser": "~7.2.1",
"pinia": "~2.0.28", "pinia": "~2.1.6",
"source-map-support": "~0.5.20", "source-map-support": "~0.5.20",
"spectre.css": "~0.5.9", "spectre.css": "~0.5.9",
"sql-formatter": "~12.2.0", "sql-formatter": "~13.0.0",
"ssh2-promise": "~1.0.2", "ssh2-promise": "~1.0.2",
"v-mask": "~2.3.0", "v-mask": "~2.3.0",
"vue": "~3.2.45", "vue": "~3.3.4",
"vue-i18n": "~9.2.2", "vue-i18n": "~9.2.2",
"vuedraggable": "~4.1.0" "vuedraggable": "~4.1.0"
}, },
@@ -62,13 +63,14 @@
"chalk": "~4.1.2", "chalk": "~4.1.2",
"cross-env": "~7.0.2", "cross-env": "~7.0.2",
"css-loader": "~6.5.0", "css-loader": "~6.5.0",
"electron": "~22.0.3", "electron": "~22.3.27",
"electron-builder": "~22.10.3", "electron-builder": "~22.10.3",
"eslint": "~7.32.0", "eslint": "~7.32.0",
"eslint-config-standard": "~16.0.3", "eslint-config-standard": "~16.0.3",
"eslint-plugin-import": "~2.24.2", "eslint-plugin-import": "~2.24.2",
"eslint-plugin-node": "~11.1.0", "eslint-plugin-node": "~11.1.0",
"eslint-plugin-promise": "~5.2.0", "eslint-plugin-promise": "~5.2.0",
"eslint-plugin-simple-import-sort": "~10.0.0",
"eslint-plugin-vue": "~8.0.3", "eslint-plugin-vue": "~8.0.3",
"file-loader": "~6.2.0", "file-loader": "~6.2.0",
"html-webpack-plugin": "~5.5.0", "html-webpack-plugin": "~5.5.0",
@@ -2017,6 +2019,11 @@
"node": ">= 14" "node": ">= 14"
} }
}, },
"node_modules/@jamescoyle/vue-icon": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@jamescoyle/vue-icon/-/vue-icon-0.1.2.tgz",
"integrity": "sha512-KFrImXx5TKIi6iQXlnyLEBl4rNosNKbTeRnr70ucTdUaciVmd9qK9d/pZAaKt1Ob/8xNnX2GMp8LisyHdKtEgw=="
},
"node_modules/@jridgewell/gen-mapping": { "node_modules/@jridgewell/gen-mapping": {
"version": "0.3.3", "version": "0.3.3",
"dev": true, "dev": true,
@@ -2057,7 +2064,6 @@
}, },
"node_modules/@jridgewell/sourcemap-codec": { "node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15", "version": "1.4.15",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@jridgewell/trace-mapping": { "node_modules/@jridgewell/trace-mapping": {
@@ -2100,9 +2106,10 @@
"node": ">= 10" "node": ">= 10"
} }
}, },
"node_modules/@mdi/font": { "node_modules/@mdi/js": {
"version": "7.1.96", "version": "7.2.96",
"license": "Apache-2.0" "resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.2.96.tgz",
"integrity": "sha512-paR9M9ZT7rKbh2boksNUynuSZMHhqRYnEZOm/KrZTjQ4/FzyhjLHuvw/8XYzP+E7fS4+/Ms/82EN1pl/OFsiIA=="
}, },
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
@@ -2496,8 +2503,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/web-bluetooth": { "node_modules/@types/web-bluetooth": {
"version": "0.0.14", "version": "0.0.17",
"license": "MIT" "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz",
"integrity": "sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA=="
}, },
"node_modules/@types/ws": { "node_modules/@types/ws": {
"version": "8.5.4", "version": "8.5.4",
@@ -2777,6 +2785,7 @@
}, },
"node_modules/@vue/compiler-core": { "node_modules/@vue/compiler-core": {
"version": "3.2.47", "version": "3.2.47",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/parser": "^7.16.4", "@babel/parser": "^7.16.4",
@@ -2787,6 +2796,7 @@
}, },
"node_modules/@vue/compiler-dom": { "node_modules/@vue/compiler-dom": {
"version": "3.2.47", "version": "3.2.47",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vue/compiler-core": "3.2.47", "@vue/compiler-core": "3.2.47",
@@ -2795,6 +2805,7 @@
}, },
"node_modules/@vue/compiler-sfc": { "node_modules/@vue/compiler-sfc": {
"version": "3.2.47", "version": "3.2.47",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/parser": "^7.16.4", "@babel/parser": "^7.16.4",
@@ -2811,6 +2822,7 @@
}, },
"node_modules/@vue/compiler-ssr": { "node_modules/@vue/compiler-ssr": {
"version": "3.2.47", "version": "3.2.47",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vue/compiler-dom": "3.2.47", "@vue/compiler-dom": "3.2.47",
@@ -2822,14 +2834,16 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@vue/reactivity": { "node_modules/@vue/reactivity": {
"version": "3.2.47", "version": "3.3.4",
"license": "MIT", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz",
"integrity": "sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==",
"dependencies": { "dependencies": {
"@vue/shared": "3.2.47" "@vue/shared": "3.3.4"
} }
}, },
"node_modules/@vue/reactivity-transform": { "node_modules/@vue/reactivity-transform": {
"version": "3.2.47", "version": "3.2.47",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/parser": "^7.16.4", "@babel/parser": "^7.16.4",
@@ -2839,89 +2853,110 @@
"magic-string": "^0.25.7" "magic-string": "^0.25.7"
} }
}, },
"node_modules/@vue/reactivity/node_modules/@vue/shared": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ=="
},
"node_modules/@vue/runtime-core": { "node_modules/@vue/runtime-core": {
"version": "3.2.47", "version": "3.3.4",
"license": "MIT", "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.4.tgz",
"integrity": "sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==",
"dependencies": { "dependencies": {
"@vue/reactivity": "3.2.47", "@vue/reactivity": "3.3.4",
"@vue/shared": "3.2.47" "@vue/shared": "3.3.4"
} }
}, },
"node_modules/@vue/runtime-core/node_modules/@vue/shared": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ=="
},
"node_modules/@vue/runtime-dom": { "node_modules/@vue/runtime-dom": {
"version": "3.2.47", "version": "3.3.4",
"license": "MIT", "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz",
"integrity": "sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==",
"dependencies": { "dependencies": {
"@vue/runtime-core": "3.2.47", "@vue/runtime-core": "3.3.4",
"@vue/shared": "3.2.47", "@vue/shared": "3.3.4",
"csstype": "^2.6.8" "csstype": "^3.1.1"
} }
}, },
"node_modules/@vue/runtime-dom/node_modules/@vue/shared": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ=="
},
"node_modules/@vue/server-renderer": { "node_modules/@vue/server-renderer": {
"version": "3.2.47", "version": "3.3.4",
"license": "MIT", "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.4.tgz",
"integrity": "sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==",
"dependencies": { "dependencies": {
"@vue/compiler-ssr": "3.2.47", "@vue/compiler-ssr": "3.3.4",
"@vue/shared": "3.2.47" "@vue/shared": "3.3.4"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "3.2.47" "vue": "3.3.4"
} }
}, },
"node_modules/@vue/server-renderer/node_modules/@vue/compiler-core": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz",
"integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==",
"dependencies": {
"@babel/parser": "^7.21.3",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/server-renderer/node_modules/@vue/compiler-dom": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz",
"integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==",
"dependencies": {
"@vue/compiler-core": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/server-renderer/node_modules/@vue/compiler-ssr": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz",
"integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==",
"dependencies": {
"@vue/compiler-dom": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/server-renderer/node_modules/@vue/shared": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ=="
},
"node_modules/@vue/shared": { "node_modules/@vue/shared": {
"version": "3.2.47", "version": "3.2.47",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@vueuse/core": { "node_modules/@vueuse/core": {
"version": "8.7.5", "version": "10.4.1",
"license": "MIT", "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.4.1.tgz",
"integrity": "sha512-DkHIfMIoSIBjMgRRvdIvxsyboRZQmImofLyOHADqiVbQVilP8VVHDhBX2ZqoItOgu7dWa8oXiNnScOdPLhdEXg==",
"dependencies": { "dependencies": {
"@types/web-bluetooth": "^0.0.14", "@types/web-bluetooth": "^0.0.17",
"@vueuse/metadata": "8.7.5", "@vueuse/metadata": "10.4.1",
"@vueuse/shared": "8.7.5", "@vueuse/shared": "10.4.1",
"vue-demi": "*" "vue-demi": ">=0.14.5"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/antfu" "url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.1.0",
"vue": "^2.6.0 || ^3.2.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
},
"vue": {
"optional": true
}
}
},
"node_modules/@vueuse/core/node_modules/@vueuse/shared": {
"version": "8.7.5",
"license": "MIT",
"dependencies": {
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.1.0",
"vue": "^2.6.0 || ^3.2.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
},
"vue": {
"optional": true
}
} }
}, },
"node_modules/@vueuse/core/node_modules/vue-demi": { "node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.14.5", "version": "0.14.6",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT",
"bin": { "bin": {
"vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js" "vue-demi-switch": "bin/vue-demi-switch.js"
@@ -2943,12 +2978,49 @@
} }
}, },
"node_modules/@vueuse/metadata": { "node_modules/@vueuse/metadata": {
"version": "8.7.5", "version": "10.4.1",
"license": "MIT", "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.4.1.tgz",
"integrity": "sha512-2Sc8X+iVzeuMGHr6O2j4gv/zxvQGGOYETYXEc41h0iZXIRnRbJZGmY/QP8dvzqUelf8vg0p/yEA5VpCEu+WpZg==",
"funding": { "funding": {
"url": "https://github.com/sponsors/antfu" "url": "https://github.com/sponsors/antfu"
} }
}, },
"node_modules/@vueuse/shared": {
"version": "10.4.1",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.4.1.tgz",
"integrity": "sha512-vz5hbAM4qA0lDKmcr2y3pPdU+2EVw/yzfRsBdu+6+USGa4PxqSQRYIUC9/NcT06y+ZgaTsyURw2I9qOFaaXHAg==",
"dependencies": {
"vue-demi": ">=0.14.5"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.14.6",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@webassemblyjs/ast": { "node_modules/@webassemblyjs/ast": {
"version": "1.11.1", "version": "1.11.1",
"dev": true, "dev": true,
@@ -3141,8 +3213,9 @@
} }
}, },
"node_modules/ace-builds": { "node_modules/ace-builds": {
"version": "1.14.0", "version": "1.24.1",
"license": "BSD-3-Clause" "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.24.1.tgz",
"integrity": "sha512-TLcxMxiTRX5Eq9bBVSd/bTJlanCBULiv/IULLohJDDaCAfcpZKJBVSd4OWfN/j2c2jCLc+jhpNWGELiJZw3wPw=="
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "7.4.1", "version": "7.4.1",
@@ -5136,8 +5209,9 @@
} }
}, },
"node_modules/csstype": { "node_modules/csstype": {
"version": "2.6.21", "version": "3.1.2",
"license": "MIT" "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
}, },
"node_modules/dargs": { "node_modules/dargs": {
"version": "7.0.0", "version": "7.0.0",
@@ -5670,9 +5744,10 @@
} }
}, },
"node_modules/electron": { "node_modules/electron": {
"version": "22.0.3", "version": "22.3.27",
"resolved": "https://registry.npmjs.org/electron/-/electron-22.3.27.tgz",
"integrity": "sha512-7Rht21vHqj4ZFRnKuZdFqZFsvMBCmDqmjetiMqPtF+TmTBiGne1mnstVXOA/SRGhN2Qy5gY5bznJKpiqogjM8A==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@electron/get": "^2.0.0", "@electron/get": "^2.0.0",
"@types/node": "^16.11.26", "@types/node": "^16.11.26",
@@ -5958,8 +6033,9 @@
} }
}, },
"node_modules/electron/node_modules/@types/node": { "node_modules/electron/node_modules/@types/node": {
"version": "16.18.34", "version": "16.18.48",
"license": "MIT" "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.48.tgz",
"integrity": "sha512-mlaecDKQ7rIZrYD7iiKNdzFb6e/qD5I9U1rAhq+Fd+DWvYVs+G2kv74UFHmSOlg5+i/vF3XxuR522V4u8BqO+Q=="
}, },
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "8.0.0", "version": "8.0.0",
@@ -6460,6 +6536,15 @@
"eslint": "^7.0.0" "eslint": "^7.0.0"
} }
}, },
"node_modules/eslint-plugin-simple-import-sort": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-10.0.0.tgz",
"integrity": "sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==",
"dev": true,
"peerDependencies": {
"eslint": ">=5.0.0"
}
},
"node_modules/eslint-plugin-vue": { "node_modules/eslint-plugin-vue": {
"version": "8.0.3", "version": "8.0.3",
"dev": true, "dev": true,
@@ -7471,7 +7556,6 @@
}, },
"node_modules/get-stdin": { "node_modules/get-stdin": {
"version": "8.0.0", "version": "8.0.0",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10" "node": ">=10"
@@ -9228,6 +9312,7 @@
}, },
"node_modules/magic-string": { "node_modules/magic-string": {
"version": "0.25.9", "version": "0.25.9",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"sourcemap-codec": "^1.4.8" "sourcemap-codec": "^1.4.8"
@@ -10653,11 +10738,12 @@
} }
}, },
"node_modules/pinia": { "node_modules/pinia": {
"version": "2.0.36", "version": "2.1.6",
"license": "MIT", "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.6.tgz",
"integrity": "sha512-bIU6QuE5qZviMmct5XwCesXelb5VavdOWKWaB17ggk++NUwQWWbP5YnsONTk3b752QkW9sACiR81rorpeOMSvQ==",
"dependencies": { "dependencies": {
"@vue/devtools-api": "^6.5.0", "@vue/devtools-api": "^6.5.0",
"vue-demi": "*" "vue-demi": ">=0.14.5"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/posva" "url": "https://github.com/sponsors/posva"
@@ -10665,7 +10751,7 @@
"peerDependencies": { "peerDependencies": {
"@vue/composition-api": "^1.4.0", "@vue/composition-api": "^1.4.0",
"typescript": ">=4.4.4", "typescript": ">=4.4.4",
"vue": "^2.6.14 || ^3.2.0" "vue": "^2.6.14 || ^3.3.0"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"@vue/composition-api": { "@vue/composition-api": {
@@ -12387,6 +12473,7 @@
}, },
"node_modules/sourcemap-codec": { "node_modules/sourcemap-codec": {
"version": "1.4.8", "version": "1.4.8",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/spdx-correct": { "node_modules/spdx-correct": {
@@ -12472,11 +12559,12 @@
"license": "BSD-3-Clause" "license": "BSD-3-Clause"
}, },
"node_modules/sql-formatter": { "node_modules/sql-formatter": {
"version": "12.2.2", "version": "13.0.0",
"resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-12.2.2.tgz", "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-13.0.0.tgz",
"integrity": "sha512-UBChSI2X6hd4GhmO+c7BmSFtc792FwogVaVqc9Y22/OqybvVfgl2OeAShc9fjivWVshXbm4UEK8WTM3tt+2Mvw==", "integrity": "sha512-V21cVvge4rhn9Fa7K/fTKcmPM+x1yee6Vhq8ZwgaWh3VPBqApgsaoFB5kLAhiqRo5AmSaRyLU7LIdgnNwH01/w==",
"dependencies": { "dependencies": {
"argparse": "^2.0.1", "argparse": "^2.0.1",
"get-stdin": "=8.0.0",
"nearley": "^2.20.1" "nearley": "^2.20.1"
}, },
"bin": { "bin": {
@@ -14177,14 +14265,15 @@
} }
}, },
"node_modules/vue": { "node_modules/vue": {
"version": "3.2.47", "version": "3.3.4",
"license": "MIT", "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz",
"integrity": "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==",
"dependencies": { "dependencies": {
"@vue/compiler-dom": "3.2.47", "@vue/compiler-dom": "3.3.4",
"@vue/compiler-sfc": "3.2.47", "@vue/compiler-sfc": "3.3.4",
"@vue/runtime-dom": "3.2.47", "@vue/runtime-dom": "3.3.4",
"@vue/server-renderer": "3.2.47", "@vue/server-renderer": "3.3.4",
"@vue/shared": "3.2.47" "@vue/shared": "3.3.4"
} }
}, },
"node_modules/vue-eslint-parser": { "node_modules/vue-eslint-parser": {
@@ -14337,6 +14426,80 @@
"vue": "^3.0.0" "vue": "^3.0.0"
} }
}, },
"node_modules/vue/node_modules/@vue/compiler-core": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz",
"integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==",
"dependencies": {
"@babel/parser": "^7.21.3",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"source-map-js": "^1.0.2"
}
},
"node_modules/vue/node_modules/@vue/compiler-dom": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz",
"integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==",
"dependencies": {
"@vue/compiler-core": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/vue/node_modules/@vue/compiler-sfc": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz",
"integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==",
"dependencies": {
"@babel/parser": "^7.20.15",
"@vue/compiler-core": "3.3.4",
"@vue/compiler-dom": "3.3.4",
"@vue/compiler-ssr": "3.3.4",
"@vue/reactivity-transform": "3.3.4",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.0",
"postcss": "^8.1.10",
"source-map-js": "^1.0.2"
}
},
"node_modules/vue/node_modules/@vue/compiler-ssr": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz",
"integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==",
"dependencies": {
"@vue/compiler-dom": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/vue/node_modules/@vue/reactivity-transform": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz",
"integrity": "sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==",
"dependencies": {
"@babel/parser": "^7.20.15",
"@vue/compiler-core": "3.3.4",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.0"
}
},
"node_modules/vue/node_modules/@vue/shared": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ=="
},
"node_modules/vue/node_modules/magic-string": {
"version": "0.30.3",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.3.tgz",
"integrity": "sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
},
"engines": {
"node": ">=12"
}
},
"node_modules/vuedraggable": { "node_modules/vuedraggable": {
"version": "4.1.0", "version": "4.1.0",
"license": "MIT", "license": "MIT",

View File

@@ -1,7 +1,7 @@
{ {
"name": "antares", "name": "antares",
"productName": "Antares", "productName": "Antares",
"version": "0.7.16-beta.0", "version": "0.7.19-beta.1",
"description": "A modern, fast and productivity driven SQL client with a focus in UX.", "description": "A modern, fast and productivity driven SQL client with a focus in UX.",
"license": "MIT", "license": "MIT",
"repository": "https://github.com/antares-sql/antares.git", "repository": "https://github.com/antares-sql/antares.git",
@@ -27,7 +27,7 @@
"contributors:add": "all-contributors add", "contributors:add": "all-contributors add",
"contributors:generate": "all-contributors generate" "contributors:generate": "all-contributors generate"
}, },
"author": "Fabio Di Stasio <fabio286@gmail.com>", "author": "Fabio Di Stasio <info@fabiodistasio.it>",
"main": "./dist/main.js", "main": "./dist/main.js",
"antares": { "antares": {
"devtoolsId": "nhdogjmejiglipccpnnnanhbledajbpd" "devtoolsId": "nhdogjmejiglipccpnnnanhbledajbpd"
@@ -67,7 +67,6 @@
"target": "deb", "target": "deb",
"arch": [ "arch": [
"x64", "x64",
"arm64",
"armv7l" "armv7l"
] ]
}, },
@@ -75,7 +74,6 @@
"target": "AppImage", "target": "AppImage",
"arch": [ "arch": [
"x64", "x64",
"arm64",
"armv7l" "armv7l"
] ]
} }
@@ -122,10 +120,11 @@
"dependencies": { "dependencies": {
"@electron/remote": "~2.0.1", "@electron/remote": "~2.0.1",
"@faker-js/faker": "~6.1.2", "@faker-js/faker": "~6.1.2",
"@mdi/font": "~7.1.96", "@jamescoyle/vue-icon": "~0.1.2",
"@mdi/js": "~7.2.96",
"@turf/helpers": "~6.5.0", "@turf/helpers": "~6.5.0",
"@vueuse/core": "~8.7.5", "@vueuse/core": "~10.4.1",
"ace-builds": "~1.14.0", "ace-builds": "~1.24.1",
"better-sqlite3": "~8.0.0", "better-sqlite3": "~8.0.0",
"electron-log": "~4.4.1", "electron-log": "~4.4.1",
"electron-store": "~8.1.0", "electron-store": "~8.1.0",
@@ -143,13 +142,13 @@
"pg-connection-string": "~2.5.0", "pg-connection-string": "~2.5.0",
"pg-query-stream": "~4.2.3", "pg-query-stream": "~4.2.3",
"pgsql-ast-parser": "~7.2.1", "pgsql-ast-parser": "~7.2.1",
"pinia": "~2.0.28", "pinia": "~2.1.6",
"source-map-support": "~0.5.20", "source-map-support": "~0.5.20",
"spectre.css": "~0.5.9", "spectre.css": "~0.5.9",
"sql-formatter": "~12.2.0", "sql-formatter": "~13.0.0",
"ssh2-promise": "~1.0.2", "ssh2-promise": "~1.0.2",
"v-mask": "~2.3.0", "v-mask": "~2.3.0",
"vue": "~3.2.45", "vue": "~3.3.4",
"vue-i18n": "~9.2.2", "vue-i18n": "~9.2.2",
"vuedraggable": "~4.1.0" "vuedraggable": "~4.1.0"
}, },
@@ -172,13 +171,14 @@
"chalk": "~4.1.2", "chalk": "~4.1.2",
"cross-env": "~7.0.2", "cross-env": "~7.0.2",
"css-loader": "~6.5.0", "css-loader": "~6.5.0",
"electron": "~22.0.3", "electron": "~22.3.27",
"electron-builder": "~22.10.3", "electron-builder": "~22.10.3",
"eslint": "~7.32.0", "eslint": "~7.32.0",
"eslint-config-standard": "~16.0.3", "eslint-config-standard": "~16.0.3",
"eslint-plugin-import": "~2.24.2", "eslint-plugin-import": "~2.24.2",
"eslint-plugin-node": "~11.1.0", "eslint-plugin-node": "~11.1.0",
"eslint-plugin-promise": "~5.2.0", "eslint-plugin-promise": "~5.2.0",
"eslint-plugin-simple-import-sort": "~10.0.0",
"eslint-plugin-vue": "~8.0.3", "eslint-plugin-vue": "~8.0.3",
"file-loader": "~6.2.0", "file-loader": "~6.2.0",
"html-webpack-plugin": "~5.5.0", "html-webpack-plugin": "~5.5.0",

View File

@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable @typescript-eslint/ban-ts-comment */
import { localesNames } from '../src/renderer/i18n/supported-locales';
import { enUS } from '../src/renderer/i18n/en-US'; import { enUS } from '../src/renderer/i18n/en-US';
import { localesNames } from '../src/renderer/i18n/supported-locales';
const locale = process.argv[2]; const locale = process.argv[2];
let fullCount = 0; let fullCount = 0;
let checkCount = 0; let checkCount = 0;

View File

@@ -31,10 +31,10 @@ parts:
fi fi
# Get the latest releases json # Get the latest releases json
echo "Get GitHub releases..." echo "Get GitHub releases..."
wget --quiet https://api.github.com/repos/fabio286/antares/releases/latest -O releases.json wget --quiet https://api.github.com/repos/fabio286/antares/releases -O releases.json
# Get the version from the tag_name and the download URL. # Get the version from the tag_name and the download URL.
VERSION=$(jq . releases.json | grep tag_name | cut -d'"' -f4 | sed s'/release-//') VERSION=$(jq . releases.json | grep tag_name | head -1 | cut -d'"' -f4 | sed s'/release-//')
DEB_URL=$(cat releases.json | jq -r ".assets[] | select(.name | test(\"${FILTER}\")) | .browser_download_url") DEB_URL=$(cat releases.json | jq -r ".[0].assets[] | select(.name | test(\"${FILTER}\")) | .browser_download_url")
DEB=$(basename "${DEB_URL}") DEB=$(basename "${DEB_URL}")
echo "Downloading ${DEB_URL}..." echo "Downloading ${DEB_URL}..."
wget --quiet "${DEB_URL}" -O "${SNAPCRAFT_PART_INSTALL}/${DEB}" wget --quiet "${DEB_URL}" -O "${SNAPCRAFT_PART_INSTALL}/${DEB}"
@@ -79,7 +79,7 @@ parts:
- libdb5.3 - libdb5.3
- libdbus-1-3 - libdbus-1-3
- libexpat1 - libexpat1
- libffi7 - libffi8
- libgcc-s1 - libgcc-s1
- libgcrypt20 - libgcrypt20
- libglib2.0-0 - libglib2.0-0
@@ -87,9 +87,9 @@ parts:
- libgnutls30 - libgnutls30
- libgpg-error0 - libgpg-error0
- libgssapi-krb5-2 - libgssapi-krb5-2
- libhogweed5 - libhogweed6
- libidn2-0 - libidn2-0
- libjson-c4 - libjson-c5
- libk5crypto3 - libk5crypto3
- libkeyutils1 - libkeyutils1
- libkrb5-3 - libkrb5-3
@@ -97,12 +97,12 @@ parts:
- liblz4-1 - liblz4-1
- liblzma5 - liblzma5
- libmount1 - libmount1
- libnettle7 - libnettle8
- libp11-kit0 - libp11-kit0
- libpcre2-8-0 - libpcre2-8-0
- libselinux1 - libselinux1
- libsqlite3-0 - libsqlite3-0
- libssl1.1 - libssl3
- libstdc++6 - libstdc++6
- libsystemd0 - libsystemd0
- libtasn1-6 - libtasn1-6

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
import firebirdTypes from '../data-types/firebird';
import { Customizations } from '../interfaces/customizations'; import { Customizations } from '../interfaces/customizations';
import { defaults } from './defaults'; import { defaults } from './defaults';
import firebirdTypes from '../data-types/firebird';
export const customizations: Customizations = { export const customizations: Customizations = {
...defaults, ...defaults,

View File

@@ -1,7 +1,7 @@
import * as firebird from 'common/customizations/firebird';
import * as mysql from 'common/customizations/mysql'; import * as mysql from 'common/customizations/mysql';
import * as postgresql from 'common/customizations/postgresql'; import * as postgresql from 'common/customizations/postgresql';
import * as sqlite from 'common/customizations/sqlite'; import * as sqlite from 'common/customizations/sqlite';
import * as firebird from 'common/customizations/firebird';
import { Customizations } from 'common/interfaces/customizations'; import { Customizations } from 'common/interfaces/customizations';
export default { export default {

View File

@@ -1,6 +1,6 @@
import mysqlTypes from '../data-types/mysql';
import { Customizations } from '../interfaces/customizations'; import { Customizations } from '../interfaces/customizations';
import { defaults } from './defaults'; import { defaults } from './defaults';
import mysqlTypes from '../data-types/mysql';
export const customizations: Customizations = { export const customizations: Customizations = {
...defaults, ...defaults,
@@ -9,6 +9,7 @@ export const customizations: Customizations = {
defaultUser: 'root', defaultUser: 'root',
defaultDatabase: null, defaultDatabase: null,
dataTypes: mysqlTypes, dataTypes: mysqlTypes,
operators: ['=', '!=', '>', '<', '>=', '<=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'RLIKE', 'NOT RLIKE', 'BETWEEN', 'IS NULL', 'IS NOT NULL'],
indexTypes: [ indexTypes: [
'PRIMARY', 'PRIMARY',
'INDEX', 'INDEX',

View File

@@ -1,6 +1,6 @@
import postgresqlTypes from '../data-types/postgresql';
import { Customizations } from '../interfaces/customizations'; import { Customizations } from '../interfaces/customizations';
import { defaults } from './defaults'; import { defaults } from './defaults';
import postgresqlTypes from '../data-types/postgresql';
export const customizations: Customizations = { export const customizations: Customizations = {
...defaults, ...defaults,

View File

@@ -1,6 +1,6 @@
import sqliteTypes from '../data-types/sqlite';
import { Customizations } from '../interfaces/customizations'; import { Customizations } from '../interfaces/customizations';
import { defaults } from './defaults'; import { defaults } from './defaults';
import sqliteTypes from '../data-types/sqlite';
export const customizations: Customizations = { export const customizations: Customizations = {
...defaults, ...defaults,

View File

@@ -1,14 +1,15 @@
import * as mysql from 'mysql2/promise'; import * as mysql from 'mysql2/promise';
import * as pg from 'pg'; import * as pg from 'pg';
import { FirebirdSQLClient } from 'src/main/libs/clients/FirebirdSQLClient';
import MysqlExporter from 'src/main/libs/exporters/sql/MysqlExporter'; import MysqlExporter from 'src/main/libs/exporters/sql/MysqlExporter';
import PostgreSQLExporter from 'src/main/libs/exporters/sql/PostgreSQLExporter'; import PostgreSQLExporter from 'src/main/libs/exporters/sql/PostgreSQLExporter';
import MySQLImporter from 'src/main/libs/importers/sql/MySQLlImporter'; import MySQLImporter from 'src/main/libs/importers/sql/MySQLlImporter';
import PostgreSQLImporter from 'src/main/libs/importers/sql/PostgreSQLImporter'; import PostgreSQLImporter from 'src/main/libs/importers/sql/PostgreSQLImporter';
import SSHConfig from 'ssh2-promise/lib/sshConfig'; import SSHConfig from 'ssh2-promise/lib/sshConfig';
import { MySQLClient } from '../../main/libs/clients/MySQLClient'; import { MySQLClient } from '../../main/libs/clients/MySQLClient';
import { PostgreSQLClient } from '../../main/libs/clients/PostgreSQLClient'; import { PostgreSQLClient } from '../../main/libs/clients/PostgreSQLClient';
import { SQLiteClient } from '../../main/libs/clients/SQLiteClient'; import { SQLiteClient } from '../../main/libs/clients/SQLiteClient';
import { FirebirdSQLClient } from 'src/main/libs/clients/FirebirdSQLClient';
export type Client = MySQLClient | PostgreSQLClient | SQLiteClient | FirebirdSQLClient export type Client = MySQLClient | PostgreSQLClient | SQLiteClient | FirebirdSQLClient
export type ClientCode = 'mysql' | 'maria' | 'pg' | 'sqlite' | 'firebird' export type ClientCode = 'mysql' | 'maria' | 'pg' | 'sqlite' | 'firebird'
@@ -64,6 +65,7 @@ export interface ConnectionParams {
sshKey?: string; sshKey?: string;
sshPort?: number; sshPort?: number;
sshPassphrase?: string; sshPassphrase?: string;
sshKeepAliveInterval?: number;
} }
export interface TypeInformations { export interface TypeInformations {
@@ -361,8 +363,7 @@ export interface QueryBuilderObject {
offset: number; offset: number;
join: string[]; join: string[];
update: string[]; update: string[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any insert: {[key: string]: string | boolean | number }[];
insert: {[key: string]: any}[];
delete: boolean; delete: boolean;
} }

View File

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

View File

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

View File

@@ -0,0 +1,28 @@
import * as crypto from 'crypto';
const algorithm = 'aes-256-gcm';
function encrypt (text: string, password: string) {
const iv = crypto.randomBytes(16);
const key = crypto.scryptSync(password, 'antares', 32);
const cipher = crypto.createCipheriv(algorithm, key, iv);
const encrypted = Buffer.concat([cipher.update(text), cipher.final()]);
const authTag = cipher.getAuthTag();
return {
iv: iv.toString('hex'),
authTag: authTag.toString('hex'),
content: encrypted.toString('hex')
};
}
function decrypt (hash: { iv: string; content: string; authTag: string }, password: string) {
const key = crypto.scryptSync(password, 'antares', 32);
const decipher = crypto.createDecipheriv(algorithm, key, Buffer.from(hash.iv, 'hex'));
decipher.setAuthTag(Buffer.from(hash.authTag, 'hex'));
const decrpyted = decipher.update(hash.content, 'hex', 'utf8') + decipher.final('utf8');
return decrpyted;
}
export { decrypt, encrypt };

View File

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

View File

@@ -1,12 +1,13 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-useless-escape */ /* eslint-disable no-useless-escape */
import * as moment from 'moment';
import { lineString, point, polygon } from '@turf/helpers'; import { lineString, point, polygon } from '@turf/helpers';
import { BIT, BLOB, DATE, DATETIME, FLOAT, IS_MULTI_SPATIAL, NUMBER, SPATIAL, TEXT_SEARCH } from 'common/fieldTypes';
import * as moment from 'moment';
import customizations from '../customizations'; import customizations from '../customizations';
import { ClientCode } from '../interfaces/antares'; import { ClientCode } from '../interfaces/antares';
import { BLOB, BIT, DATE, DATETIME, FLOAT, SPATIAL, IS_MULTI_SPATIAL, NUMBER, TEXT_SEARCH } from 'common/fieldTypes';
import hexToBinary, { HexChar } from './hexToBinary';
import { getArrayDepth } from './getArrayDepth'; import { getArrayDepth } from './getArrayDepth';
import hexToBinary, { HexChar } from './hexToBinary';
/** /**
* Escapes a string fo SQL use * Escapes a string fo SQL use

View File

@@ -135,4 +135,4 @@ for (let i = 1; i <= 9; i++) {
}); });
} }
export { shortcuts, ShortcutRecord }; export { ShortcutRecord, shortcuts };

View File

@@ -1,35 +1,44 @@
import { app, ipcMain, dialog } from 'electron'; import { app, dialog, ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
import { ShortcutRegister } from '../libs/ShortcutRegister'; import { ShortcutRegister } from '../libs/ShortcutRegister';
export default () => { export default () => {
ipcMain.on('close-app', () => { ipcMain.on('close-app', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
app.exit(); app.exit();
}); });
ipcMain.handle('show-open-dialog', (event, options) => { ipcMain.handle('show-open-dialog', (event, options) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
return dialog.showOpenDialog(options); return dialog.showOpenDialog(options);
}); });
ipcMain.handle('get-download-dir-path', () => { ipcMain.handle('get-download-dir-path', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
return app.getPath('downloads'); return app.getPath('downloads');
}); });
ipcMain.handle('resotre-default-shortcuts', () => { ipcMain.handle('resotre-default-shortcuts', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
const shortCutRegister = ShortcutRegister.getInstance(); const shortCutRegister = ShortcutRegister.getInstance();
shortCutRegister.restoreDefaults(); shortCutRegister.restoreDefaults();
}); });
ipcMain.handle('reload-shortcuts', () => { ipcMain.handle('reload-shortcuts', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
const shortCutRegister = ShortcutRegister.getInstance(); const shortCutRegister = ShortcutRegister.getInstance();
shortCutRegister.reload(); shortCutRegister.reload();
}); });
ipcMain.handle('update-shortcuts', (event, shortcuts) => { ipcMain.handle('update-shortcuts', (event, shortcuts) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
const shortCutRegister = ShortcutRegister.getInstance(); const shortCutRegister = ShortcutRegister.getInstance();
shortCutRegister.updateShortcuts(shortcuts); shortCutRegister.updateShortcuts(shortcuts);
}); });
ipcMain.handle('unregister-shortcuts', () => { ipcMain.handle('unregister-shortcuts', (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
const shortCutRegister = ShortcutRegister.getInstance(); const shortCutRegister = ShortcutRegister.getInstance();
shortCutRegister.unregister(); shortCutRegister.unregister();
}); });

View File

@@ -1,11 +1,15 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import * as fs from 'fs';
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import { ClientsFactory } from '../libs/ClientsFactory'; import * as fs from 'fs';
import { SslOptions } from 'mysql2'; import { SslOptions } from 'mysql2';
import { ClientsFactory } from '../libs/ClientsFactory';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: {[key: string]: antares.Client}) => { export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('test-connection', async (event, conn: antares.ConnectionParams) => { ipcMain.handle('test-connection', async (event, conn: antares.ConnectionParams) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
const params = { const params = {
host: conn.host, host: conn.host,
port: +conn.port, port: +conn.port,
@@ -23,6 +27,7 @@ export default (connections: {[key: string]: antares.Client}) => {
port: number; port: number;
privateKey: string; privateKey: string;
passphrase: string; passphrase: string;
keepaliveInterval: number;
} }
}; };
@@ -49,7 +54,8 @@ export default (connections: {[key: string]: antares.Client}) => {
password: conn.sshPass, password: conn.sshPass,
port: conn.sshPort ? conn.sshPort : 22, port: conn.sshPort ? conn.sshPort : 22,
privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null, privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null,
passphrase: conn.sshPassphrase passphrase: conn.sshPassphrase,
keepaliveInterval: conn.sshKeepAliveInterval ?? conn.sshKeepAliveInterval*1000
}; };
} }
@@ -80,6 +86,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('connect', async (event, conn: antares.ConnectionParams) => { ipcMain.handle('connect', async (event, conn: antares.ConnectionParams) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
const params = { const params = {
host: conn.host, host: conn.host,
port: +conn.port, port: +conn.port,
@@ -98,6 +106,7 @@ export default (connections: {[key: string]: antares.Client}) => {
port: number; port: number;
privateKey: string; privateKey: string;
passphrase: string; passphrase: string;
keepaliveInterval: number;
} }
}; };
@@ -127,7 +136,8 @@ export default (connections: {[key: string]: antares.Client}) => {
password: conn.sshPass, password: conn.sshPass,
port: conn.sshPort ? conn.sshPort : 22, port: conn.sshPort ? conn.sshPort : 22,
privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null, privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null,
passphrase: conn.sshPassphrase passphrase: conn.sshPassphrase,
keepaliveInterval: conn.sshKeepAliveInterval ?? conn.sshKeepAliveInterval*1000
}; };
} }
@@ -153,6 +163,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('disconnect', (event, uid) => { ipcMain.handle('disconnect', (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
connections[uid].destroy(); connections[uid].destroy();
delete connections[uid]; delete connections[uid];
}); });

View File

@@ -1,8 +1,12 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: {[key: string]: antares.Client}) => { export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-databases', async (event, uid) => { ipcMain.handle('get-databases', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[uid].getDatabases(); const result = await connections[uid].getDatabases();
return { status: 'success', response: result }; return { status: 'success', response: result };

View File

@@ -1,8 +1,12 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: {[key: string]: antares.Client}) => { export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-function-informations', async (event, params) => { ipcMain.handle('get-function-informations', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[params.uid].getFunctionInformations(params); const result = await connections[params.uid].getFunctionInformations(params);
return { status: 'success', response: result }; return { status: 'success', response: result };
@@ -13,6 +17,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('drop-function', async (event, params) => { ipcMain.handle('drop-function', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].dropFunction(params); await connections[params.uid].dropFunction(params);
return { status: 'success' }; return { status: 'success' };
@@ -23,6 +29,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('alter-function', async (event, params) => { ipcMain.handle('alter-function', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].alterFunction(params); await connections[params.uid].alterFunction(params);
return { status: 'success' }; return { status: 'success' };
@@ -33,6 +41,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('alter-trigger-function', async (event, params) => { ipcMain.handle('alter-trigger-function', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].alterTriggerFunction(params); await connections[params.uid].alterTriggerFunction(params);
return { status: 'success' }; return { status: 'success' };
@@ -43,6 +53,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('create-function', async (event, params) => { ipcMain.handle('create-function', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].createFunction(params); await connections[params.uid].createFunction(params);
return { status: 'success' }; return { status: 'success' };
@@ -53,6 +65,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('create-trigger-function', async (event, params) => { ipcMain.handle('create-trigger-function', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].createTriggerFunction(params); await connections[params.uid].createTriggerFunction(params);
return { status: 'success' }; return { status: 'success' };

View File

@@ -1,17 +1,17 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import connection from './connection';
import tables from './tables';
import views from './views';
import triggers from './triggers';
import routines from './routines';
import functions from './functions';
import schedulers from './schedulers';
import updates from './updates';
import application from './application'; import application from './application';
import connection from './connection';
import database from './database'; import database from './database';
import functions from './functions';
import routines from './routines';
import schedulers from './schedulers';
import schema from './schema'; import schema from './schema';
import tables from './tables';
import triggers from './triggers';
import updates from './updates';
import users from './users'; import users from './users';
import views from './views';
const connections: {[key: string]: antares.Client} = {}; const connections: {[key: string]: antares.Client} = {};

View File

@@ -1,8 +1,12 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: {[key: string]: antares.Client}) => { export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-routine-informations', async (event, params) => { ipcMain.handle('get-routine-informations', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[params.uid].getRoutineInformations(params); const result = await connections[params.uid].getRoutineInformations(params);
return { status: 'success', response: result }; return { status: 'success', response: result };
@@ -13,6 +17,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('drop-routine', async (event, params) => { ipcMain.handle('drop-routine', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].dropRoutine(params); await connections[params.uid].dropRoutine(params);
return { status: 'success' }; return { status: 'success' };
@@ -23,6 +29,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('alter-routine', async (event, params) => { ipcMain.handle('alter-routine', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].alterRoutine(params); await connections[params.uid].alterRoutine(params);
return { status: 'success' }; return { status: 'success' };
@@ -33,6 +41,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('create-routine', async (event, params) => { ipcMain.handle('create-routine', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].createRoutine(params); await connections[params.uid].createRoutine(params);
return { status: 'success' }; return { status: 'success' };

View File

@@ -1,8 +1,12 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: {[key: string]: antares.Client}) => { export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-scheduler-informations', async (event, params) => { ipcMain.handle('get-scheduler-informations', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[params.uid].getEventInformations(params); const result = await connections[params.uid].getEventInformations(params);
return { status: 'success', response: result }; return { status: 'success', response: result };
@@ -13,6 +17,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('drop-scheduler', async (event, params) => { ipcMain.handle('drop-scheduler', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].dropEvent(params); await connections[params.uid].dropEvent(params);
return { status: 'success' }; return { status: 'success' };
@@ -23,6 +29,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('alter-scheduler', async (event, params) => { ipcMain.handle('alter-scheduler', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].alterEvent(params); await connections[params.uid].alterEvent(params);
return { status: 'success' }; return { status: 'success' };
@@ -33,6 +41,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('create-scheduler', async (event, params) => { ipcMain.handle('create-scheduler', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].createEvent(params); await connections[params.uid].createEvent(params);
return { status: 'success' }; return { status: 'success' };
@@ -43,6 +53,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('toggle-scheduler', async (event, params) => { ipcMain.handle('toggle-scheduler', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
if (!params.enabled) if (!params.enabled)
await connections[params.uid].enableEvent({ ...params }); await connections[params.uid].enableEvent({ ...params });

View File

@@ -1,9 +1,11 @@
import { ChildProcess, fork } from 'child_process';
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import * as workers from 'common/interfaces/workers'; import * as workers from 'common/interfaces/workers';
import { dialog, ipcMain } from 'electron';
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import { ChildProcess, fork } from 'child_process';
import { ipcMain, dialog } from 'electron'; import { validateSender } from '../libs/misc/validateSender';
const isDevelopment = process.env.NODE_ENV !== 'production'; const isDevelopment = process.env.NODE_ENV !== 'production';
@@ -12,6 +14,8 @@ export default (connections: {[key: string]: antares.Client}) => {
let importer: ChildProcess = null; let importer: ChildProcess = null;
ipcMain.handle('create-schema', async (event, params) => { ipcMain.handle('create-schema', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].createSchema(params); await connections[params.uid].createSchema(params);
@@ -23,6 +27,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('update-schema', async (event, params) => { ipcMain.handle('update-schema', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].alterSchema(params); await connections[params.uid].alterSchema(params);
@@ -34,6 +40,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('delete-schema', async (event, params) => { ipcMain.handle('delete-schema', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].dropSchema(params); await connections[params.uid].dropSchema(params);
@@ -45,6 +53,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-schema-collation', async (event, params) => { ipcMain.handle('get-schema-collation', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const collation = await connections[params.uid].getDatabaseCollation( const collation = await connections[params.uid].getDatabaseCollation(
params params
@@ -61,6 +71,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-structure', async (event, params) => { ipcMain.handle('get-structure', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const structure: unknown = await connections[params.uid].getStructure( const structure: unknown = await connections[params.uid].getStructure(
params.schemas params.schemas
@@ -74,6 +86,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-collations', async (event, uid) => { ipcMain.handle('get-collations', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[uid].getCollations(); const result = await connections[uid].getCollations();
@@ -85,6 +99,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-variables', async (event, uid) => { ipcMain.handle('get-variables', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[uid].getVariables(); const result = await connections[uid].getVariables();
@@ -96,6 +112,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-engines', async (event, uid) => { ipcMain.handle('get-engines', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result: unknown = await connections[uid].getEngines(); const result: unknown = await connections[uid].getEngines();
@@ -107,6 +125,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-version', async (event, uid) => { ipcMain.handle('get-version', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[uid].getVersion(); const result = await connections[uid].getVersion();
@@ -118,6 +138,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-processes', async (event, uid) => { ipcMain.handle('get-processes', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[uid].getProcesses(); const result = await connections[uid].getProcesses();
@@ -129,6 +151,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('kill-process', async (event, { uid, pid }) => { ipcMain.handle('kill-process', async (event, { uid, pid }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[uid].killProcess(pid); const result = await connections[uid].killProcess(pid);
@@ -140,6 +164,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('use-schema', async (event, { uid, schema }) => { ipcMain.handle('use-schema', async (event, { uid, schema }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (!schema) return; if (!schema) return;
try { try {
@@ -152,6 +178,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('raw-query', async (event, { uid, query, schema, tabUid, autocommit }) => { ipcMain.handle('raw-query', async (event, { uid, query, schema, tabUid, autocommit }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (!query) return; if (!query) return;
try { try {
@@ -171,6 +199,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('export', (event, { uid, type, tables, ...rest }) => { ipcMain.handle('export', (event, { uid, type, tables, ...rest }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (exporter !== null) { if (exporter !== null) {
exporter.kill(); exporter.kill();
return; return;
@@ -245,7 +275,9 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
}); });
ipcMain.handle('abort-export', async () => { ipcMain.handle('abort-export', async (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
let willAbort = false; let willAbort = false;
if (exporter) { if (exporter) {
@@ -267,6 +299,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('import-sql', async (event, options) => { ipcMain.handle('import-sql', async (event, options) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (importer !== null) { if (importer !== null) {
importer.kill(); importer.kill();
return; return;
@@ -318,7 +352,9 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
}); });
ipcMain.handle('abort-import-sql', async () => { ipcMain.handle('abort-import-sql', async (event) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
let willAbort = false; let willAbort = false;
if (importer) { if (importer) {
@@ -340,6 +376,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('kill-tab-query', async (event, { uid, tabUid }) => { ipcMain.handle('kill-tab-query', async (event, { uid, tabUid }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (!tabUid) return; if (!tabUid) return;
try { try {
@@ -352,6 +390,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('commit-tab', async (event, { uid, tabUid }) => { ipcMain.handle('commit-tab', async (event, { uid, tabUid }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (!tabUid) return; if (!tabUid) return;
try { try {
@@ -364,6 +404,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('rollback-tab', async (event, { uid, tabUid }) => { ipcMain.handle('rollback-tab', async (event, { uid, tabUid }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (!tabUid) return; if (!tabUid) return;
try { try {
@@ -376,6 +418,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('destroy-connection-to-commit', async (event, { uid, tabUid }) => { ipcMain.handle('destroy-connection-to-commit', async (event, { uid, tabUid }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (!tabUid) return; if (!tabUid) return;
try { try {

View File

@@ -1,15 +1,19 @@
import * as fs from 'fs'; import customizations from 'common/customizations';
import { ARRAY, BIT, BLOB, BOOLEAN, DATE, DATETIME, FLOAT, LONG_TEXT, NUMBER, TEXT, TEXT_SEARCH } from 'common/fieldTypes';
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { InsertRowsParams } from 'common/interfaces/tableApis'; import { InsertRowsParams } from 'common/interfaces/tableApis';
import { ipcMain } from 'electron'; import { fakerCustom } from 'common/libs/fakerCustom';
import { faker } from '@faker-js/faker';
import * as moment from 'moment';
import { sqlEscaper } from 'common/libs/sqlUtils'; import { sqlEscaper } from 'common/libs/sqlUtils';
import { TEXT, LONG_TEXT, ARRAY, TEXT_SEARCH, NUMBER, FLOAT, BLOB, BIT, DATE, DATETIME, BOOLEAN } from 'common/fieldTypes'; import { ipcMain } from 'electron';
import customizations from 'common/customizations'; import * as fs from 'fs';
import * as moment from 'moment';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: {[key: string]: antares.Client}) => { export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-table-columns', async (event, params) => { ipcMain.handle('get-table-columns', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[params.uid].getTableColumns(params); const result = await connections[params.uid].getTableColumns(params);
return { status: 'success', response: result }; return { status: 'success', response: result };
@@ -20,6 +24,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-table-data', async (event, { uid, schema, table, limit, page, sortParams, where }) => { ipcMain.handle('get-table-data', async (event, { uid, schema, table, limit, page, sortParams, where }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const offset = (page - 1) * limit; const offset = (page - 1) * limit;
const query = connections[uid] const query = connections[uid]
@@ -45,6 +51,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-table-count', async (event, params) => { ipcMain.handle('get-table-count', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[params.uid].getTableApproximateCount(params); const result = await connections[params.uid].getTableApproximateCount(params);
return { status: 'success', response: result }; return { status: 'success', response: result };
@@ -55,6 +63,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-table-options', async (event, params) => { ipcMain.handle('get-table-options', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[params.uid].getTableOptions(params); const result = await connections[params.uid].getTableOptions(params);
return { status: 'success', response: result }; return { status: 'success', response: result };
@@ -65,6 +75,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-table-indexes', async (event, params) => { ipcMain.handle('get-table-indexes', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[params.uid].getTableIndexes(params); const result = await connections[params.uid].getTableIndexes(params);
@@ -76,6 +88,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-table-ddl', async (event, params) => { ipcMain.handle('get-table-ddl', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[params.uid].getTableDll(params); const result = await connections[params.uid].getTableDll(params);
@@ -87,6 +101,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-key-usage', async (event, params) => { ipcMain.handle('get-key-usage', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[params.uid].getKeyUsage(params); const result = await connections[params.uid].getKeyUsage(params);
@@ -98,6 +114,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('update-table-cell', async (event, params) => { ipcMain.handle('update-table-cell', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
delete params.row._antares_id; delete params.row._antares_id;
const { stringsWrapper: sw } = customizations[connections[params.uid]._client]; const { stringsWrapper: sw } = customizations[connections[params.uid]._client];
@@ -227,6 +245,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('delete-table-rows', async (event, params) => { ipcMain.handle('delete-table-rows', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
if (params.primary) { if (params.primary) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const idString = params.rows.map((row: {[key: string]: any}) => { const idString = params.rows.map((row: {[key: string]: any}) => {
@@ -281,6 +301,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('insert-table-fake-rows', async (event, params: InsertRowsParams) => { ipcMain.handle('insert-table-fake-rows', async (event, params: InsertRowsParams) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { // TODO: move to client classes try { // TODO: move to client classes
const rows: {[key: string]: string | number | boolean | Date | Buffer}[] = []; const rows: {[key: string]: string | number | boolean | Date | Buffer}[] = [];
@@ -349,19 +371,19 @@ export default (connections: {[key: string]: antares.Client}) => {
let fakeValue; let fakeValue;
if (params.locale) if (params.locale)
faker.locale = params.locale; fakerCustom.locale = params.locale;
if (Object.keys(params.row[key].params).length) { if (Object.keys(params.row[key].params).length) {
Object.keys(params.row[key].params).forEach(param => { Object.keys(params.row[key].params).forEach(param => {
if (!isNaN(params.row[key].params[param])) if (!isNaN(params.row[key].params[param]))// Converts string numerics params to number
parsedParams[param] = +params.row[key].params[param]; parsedParams[param] = Number(params.row[key].params[param]);
}); });
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
fakeValue = (faker as any)[params.row[key].group][params.row[key].method](parsedParams); fakeValue = (fakerCustom as any)[params.row[key].group][params.row[key].method](parsedParams);
} }
else else
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
fakeValue = (faker as any)[params.row[key].group][params.row[key].method](); fakeValue = (fakerCustom as any)[params.row[key].group][params.row[key].method]();
if (typeof fakeValue === 'string') { if (typeof fakeValue === 'string') {
if (params.row[key].length) if (params.row[key].length)
@@ -403,6 +425,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('get-foreign-list', async (event, { uid, schema, table, column, description }) => { ipcMain.handle('get-foreign-list', async (event, { uid, schema, table, column, description }) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const query = connections[uid] const query = connections[uid]
.select(`${column} AS foreign_column`) .select(`${column} AS foreign_column`)
@@ -436,6 +460,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('create-table', async (event, params) => { ipcMain.handle('create-table', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].createTable(params); await connections[params.uid].createTable(params);
return { status: 'success' }; return { status: 'success' };
@@ -446,6 +472,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('alter-table', async (event, params) => { ipcMain.handle('alter-table', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].alterTable(params); await connections[params.uid].alterTable(params);
return { status: 'success' }; return { status: 'success' };
@@ -456,6 +484,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('duplicate-table', async (event, params) => { ipcMain.handle('duplicate-table', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].duplicateTable(params); await connections[params.uid].duplicateTable(params);
return { status: 'success' }; return { status: 'success' };
@@ -466,6 +496,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('truncate-table', async (event, params) => { ipcMain.handle('truncate-table', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].truncateTable(params); await connections[params.uid].truncateTable(params);
return { status: 'success' }; return { status: 'success' };
@@ -476,6 +508,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('drop-table', async (event, params) => { ipcMain.handle('drop-table', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].dropTable(params); await connections[params.uid].dropTable(params);
return { status: 'success' }; return { status: 'success' };

View File

@@ -1,8 +1,12 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: {[key: string]: antares.Client}) => { export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-trigger-informations', async (event, params) => { ipcMain.handle('get-trigger-informations', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[params.uid].getTriggerInformations(params); const result = await connections[params.uid].getTriggerInformations(params);
return { status: 'success', response: result }; return { status: 'success', response: result };
@@ -13,6 +17,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('drop-trigger', async (event, params) => { ipcMain.handle('drop-trigger', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].dropTrigger(params); await connections[params.uid].dropTrigger(params);
return { status: 'success' }; return { status: 'success' };
@@ -23,6 +29,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('alter-trigger', async (event, params) => { ipcMain.handle('alter-trigger', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].alterTrigger(params); await connections[params.uid].alterTrigger(params);
return { status: 'success' }; return { status: 'success' };
@@ -33,6 +41,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('create-trigger', async (event, params) => { ipcMain.handle('create-trigger', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].createTrigger(params); await connections[params.uid].createTrigger(params);
return { status: 'success' }; return { status: 'success' };
@@ -43,6 +53,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('toggle-trigger', async (event, params) => { ipcMain.handle('toggle-trigger', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
if (!params.enabled) if (!params.enabled)
await connections[params.uid].enableTrigger(params); await connections[params.uid].enableTrigger(params);

View File

@@ -1,6 +1,6 @@
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import { autoUpdater } from 'electron-updater';
import * as Store from 'electron-store'; import * as Store from 'electron-store';
import { autoUpdater } from 'electron-updater';
const persistentStore = new Store({ const persistentStore = new Store({
name: 'settings', name: 'settings',
@@ -51,8 +51,8 @@ export default () => {
mainWindow.reply('update-not-available'); mainWindow.reply('update-not-available');
}); });
autoUpdater.on('download-progress', data => { autoUpdater.on('download-progress', event => {
mainWindow.reply('download-progress', data); mainWindow.reply('download-progress', event);
}); });
autoUpdater.on('update-downloaded', () => { autoUpdater.on('update-downloaded', () => {

View File

@@ -1,8 +1,12 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: {[key: string]: antares.Client}) => { export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-users', async (event, uid) => { ipcMain.handle('get-users', async (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[uid].getUsers(); const result = await connections[uid].getUsers();
return { status: 'success', response: result }; return { status: 'success', response: result };

View File

@@ -1,8 +1,12 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import { validateSender } from '../libs/misc/validateSender';
export default (connections: {[key: string]: antares.Client}) => { export default (connections: {[key: string]: antares.Client}) => {
ipcMain.handle('get-view-informations', async (event, params) => { ipcMain.handle('get-view-informations', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
const result = await connections[params.uid].getViewInformations(params); const result = await connections[params.uid].getViewInformations(params);
return { status: 'success', response: result }; return { status: 'success', response: result };
@@ -13,6 +17,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('drop-view', async (event, params) => { ipcMain.handle('drop-view', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].dropView(params); await connections[params.uid].dropView(params);
return { status: 'success' }; return { status: 'success' };
@@ -23,6 +29,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('alter-view', async (event, params) => { ipcMain.handle('alter-view', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].alterView(params); await connections[params.uid].alterView(params);
return { status: 'success' }; return { status: 'success' };
@@ -33,6 +41,8 @@ export default (connections: {[key: string]: antares.Client}) => {
}); });
ipcMain.handle('create-view', async (event, params) => { ipcMain.handle('create-view', async (event, params) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
try { try {
await connections[params.uid].createView(params); await connections[params.uid].createView(params);
return { status: 'success' }; return { status: 'success' };

View File

@@ -1,8 +1,9 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { FirebirdSQLClient } from './clients/FirebirdSQLClient';
import { MySQLClient } from './clients/MySQLClient'; import { MySQLClient } from './clients/MySQLClient';
import { PostgreSQLClient } from './clients/PostgreSQLClient'; import { PostgreSQLClient } from './clients/PostgreSQLClient';
import { SQLiteClient } from './clients/SQLiteClient'; import { SQLiteClient } from './clients/SQLiteClient';
import { FirebirdSQLClient } from './clients/FirebirdSQLClient';
export class ClientsFactory { export class ClientsFactory {
static getClient (args: antares.ClientParams) { static getClient (args: antares.ClientParams) {

View File

@@ -1,6 +1,6 @@
import { ShortcutRecord, shortcuts } from 'common/shortcuts';
import { BrowserWindow, globalShortcut, Menu, MenuItem, MenuItemConstructorOptions } from 'electron'; import { BrowserWindow, globalShortcut, Menu, MenuItem, MenuItemConstructorOptions } from 'electron';
import * as Store from 'electron-store'; import * as Store from 'electron-store';
import { ShortcutRecord, shortcuts } from 'common/shortcuts';
const shortcutsStore = new Store({ name: 'shortcuts' }); const shortcutsStore = new Store({ name: 'shortcuts' });
const isDevelopment = process.env.NODE_ENV !== 'production'; const isDevelopment = process.env.NODE_ENV !== 'production';

View File

@@ -1,9 +1,10 @@
import * as path from 'path';
import * as antares from 'common/interfaces/antares';
import * as firebird from 'node-firebird';
import { AntaresCore } from '../AntaresCore';
import dataTypes from 'common/data-types/firebird'; import dataTypes from 'common/data-types/firebird';
import { FLOAT, NUMBER } from 'common/fieldTypes'; import { FLOAT, NUMBER } from 'common/fieldTypes';
import * as antares from 'common/interfaces/antares';
import * as firebird from 'node-firebird';
import * as path from 'path';
import { AntaresCore } from '../AntaresCore';
export class FirebirdSQLClient extends AntaresCore { export class FirebirdSQLClient extends AntaresCore {
private _schema?: string; private _schema?: string;

View File

@@ -1,7 +1,8 @@
import dataTypes from 'common/data-types/mysql';
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import * as mysql from 'mysql2/promise'; import * as mysql from 'mysql2/promise';
import { AntaresCore } from '../AntaresCore'; import { AntaresCore } from '../AntaresCore';
import dataTypes from 'common/data-types/mysql';
import SSH2Promise = require('ssh2-promise'); import SSH2Promise = require('ssh2-promise');
import SSHConfig from 'ssh2-promise/lib/sshConfig'; import SSHConfig from 'ssh2-promise/lib/sshConfig';
@@ -155,7 +156,6 @@ export class MySQLClient extends AntaresCore {
this._ssh = new SSH2Promise({ this._ssh = new SSH2Promise({
...this._params.ssh, ...this._params.ssh,
keepaliveInterval: 30*60*1000,
debug: process.env.NODE_ENV !== 'production' ? (s) => console.log(s) : null debug: process.env.NODE_ENV !== 'production' ? (s) => console.log(s) : null
}); });
@@ -256,9 +256,12 @@ export class MySQLClient extends AntaresCore {
} }
private async keepAlive () { private async keepAlive () {
const connection = await (this._connection as mysql.Pool).getConnection(); try {
await connection.ping(); const connection = await (this._connection as mysql.Pool).getConnection();
connection.release(); await connection.ping();
connection.release();
}
catch (_) {}
} }
use (schema: string) { use (schema: string) {

View File

@@ -1,8 +1,9 @@
import dataTypes from 'common/data-types/postgresql';
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import * as pg from 'pg'; import * as pg from 'pg';
import * as pgAst from 'pgsql-ast-parser'; import * as pgAst from 'pgsql-ast-parser';
import { AntaresCore } from '../AntaresCore'; import { AntaresCore } from '../AntaresCore';
import dataTypes from 'common/data-types/postgresql';
import SSH2Promise = require('ssh2-promise'); import SSH2Promise = require('ssh2-promise');
import SSHConfig from 'ssh2-promise/lib/sshConfig'; import SSHConfig from 'ssh2-promise/lib/sshConfig';
import { ConnectionOptions } from 'tls'; import { ConnectionOptions } from 'tls';
@@ -167,7 +168,6 @@ export class PostgreSQLClient extends AntaresCore {
try { try {
this._ssh = new SSH2Promise({ this._ssh = new SSH2Promise({
...this._params.ssh, ...this._params.ssh,
keepaliveInterval: 30*60*1000,
debug: process.env.NODE_ENV !== 'production' ? (s) => console.log(s) : null debug: process.env.NODE_ENV !== 'production' ? (s) => console.log(s) : null
}); });
@@ -240,9 +240,12 @@ export class PostgreSQLClient extends AntaresCore {
} }
private async keepAlive () { private async keepAlive () {
const connection = await this._connection.connect() as pg.PoolClient; try {
await connection.query('SELECT 1+1'); const connection = await this._connection.connect() as pg.PoolClient;
connection.release(); await connection.query('SELECT 1+1');
connection.release();
}
catch (_) {}
} }
use (schema: string, connection?: pg.Client | pg.PoolClient) { use (schema: string, connection?: pg.Client | pg.PoolClient) {

View File

@@ -1,8 +1,9 @@
import * as antares from 'common/interfaces/antares';
import * as sqlite from 'better-sqlite3'; import * as sqlite from 'better-sqlite3';
import { AntaresCore } from '../AntaresCore';
import dataTypes from 'common/data-types/sqlite'; import dataTypes from 'common/data-types/sqlite';
import { NUMBER, FLOAT, TIME, DATETIME } from 'common/fieldTypes'; import { DATETIME, FLOAT, NUMBER, TIME } from 'common/fieldTypes';
import * as antares from 'common/interfaces/antares';
import { AntaresCore } from '../AntaresCore';
export class SQLiteClient extends AntaresCore { export class SQLiteClient extends AntaresCore {
private _schema?: string; private _schema?: string;
@@ -34,8 +35,8 @@ export class SQLiteClient extends AntaresCore {
}); });
} }
destroy (): void { destroy () {
return null; this._connection.close();
} }
use (): void { use (): void {
@@ -295,7 +296,13 @@ export class SQLiteClient extends AntaresCore {
// ADD FIELDS // ADD FIELDS
fields.forEach(field => { fields.forEach(field => {
const typeInfo = this.getTypeInfo(field.type); const typeInfo = this.getTypeInfo(field.type);
const length = typeInfo?.length ? field.enumValues || field.numLength || field.charLength || field.datePrecision : false; const length = typeInfo?.length
? field.enumValues ||
field.numLength ||
field.numPrecision ||
field.charLength ||
field.datePrecision
: false;
newColumns.push(`"${field.name}" newColumns.push(`"${field.name}"
${field.type.toUpperCase()}${length ? `(${length})` : ''} ${field.type.toUpperCase()}${length ? `(${length})` : ''}
@@ -425,7 +432,7 @@ export class SQLiteClient extends AntaresCore {
return results.rows.map(row => { return results.rows.map(row => {
return { return {
sql: row.sql.match(/(?<=AS ).*?$/gs)[0], sql: row.sql.match(/(?<=(AS|as)( |\n)).*?$/gs)[0],
name: view name: view
}; };
})[0]; })[0];

View File

@@ -1,8 +1,8 @@
import * as exporter from 'common/interfaces/exporter'; import * as exporter from 'common/interfaces/exporter';
import * as fs from 'fs';
import { createGzip, Gzip } from 'zlib';
import * as path from 'path';
import * as EventEmitter from 'events'; import * as EventEmitter from 'events';
import * as fs from 'fs';
import * as path from 'path';
import { createGzip, Gzip } from 'zlib';
export class BaseExporter extends EventEmitter { export class BaseExporter extends EventEmitter {
protected _tables; protected _tables;

View File

@@ -1,8 +1,9 @@
import * as exporter from 'common/interfaces/exporter'; import * as exporter from 'common/interfaces/exporter';
import * as mysql from 'mysql2/promise';
import { SqlExporter } from './SqlExporter';
import { MySQLClient } from '../../clients/MySQLClient';
import { valueToSqlString } from 'common/libs/sqlUtils'; import { valueToSqlString } from 'common/libs/sqlUtils';
import * as mysql from 'mysql2/promise';
import { MySQLClient } from '../../clients/MySQLClient';
import { SqlExporter } from './SqlExporter';
export default class MysqlExporter extends SqlExporter { export default class MysqlExporter extends SqlExporter {
protected _client: MySQLClient; protected _client: MySQLClient;

View File

@@ -1,11 +1,12 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import * as exporter from 'common/interfaces/exporter'; import * as exporter from 'common/interfaces/exporter';
import { SqlExporter } from './SqlExporter'; import { valueToSqlString } from 'common/libs/sqlUtils';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
import * as QueryStream from 'pg-query-stream'; import * as QueryStream from 'pg-query-stream';
import { PostgreSQLClient } from '../../clients/PostgreSQLClient'; import { PostgreSQLClient } from '../../clients/PostgreSQLClient';
import { valueToSqlString } from 'common/libs/sqlUtils'; import { SqlExporter } from './SqlExporter';
export default class PostgreSQLExporter extends SqlExporter { export default class PostgreSQLExporter extends SqlExporter {
constructor (client: PostgreSQLClient, tables: exporter.TableParams[], options: exporter.ExportOptions) { constructor (client: PostgreSQLClient, tables: exporter.TableParams[], options: exporter.ExportOptions) {

View File

@@ -1,4 +1,5 @@
import * as moment from 'moment'; import * as moment from 'moment';
import { MySQLClient } from '../../clients/MySQLClient'; import { MySQLClient } from '../../clients/MySQLClient';
import { PostgreSQLClient } from '../../clients/PostgreSQLClient'; import { PostgreSQLClient } from '../../clients/PostgreSQLClient';
import { BaseExporter } from '../BaseExporter'; import { BaseExporter } from '../BaseExporter';

View File

@@ -1,6 +1,6 @@
import * as importer from 'common/interfaces/importer'; import * as importer from 'common/interfaces/importer';
import * as fs from 'fs';
import * as EventEmitter from 'events'; import * as EventEmitter from 'events';
import * as fs from 'fs';
export class BaseImporter extends EventEmitter { export class BaseImporter extends EventEmitter {
protected _options; protected _options;

View File

@@ -1,6 +1,7 @@
import * as mysql from 'mysql2';
import * as importer from 'common/interfaces/importer'; import * as importer from 'common/interfaces/importer';
import * as fs from 'fs/promises'; import * as fs from 'fs/promises';
import * as mysql from 'mysql2';
import MySQLParser from '../../parsers/MySQLParser'; import MySQLParser from '../../parsers/MySQLParser';
import { BaseImporter } from '../BaseImporter'; import { BaseImporter } from '../BaseImporter';

View File

@@ -1,6 +1,7 @@
import * as pg from 'pg';
import * as importer from 'common/interfaces/importer'; import * as importer from 'common/interfaces/importer';
import * as fs from 'fs/promises'; import * as fs from 'fs/promises';
import * as pg from 'pg';
import PostgreSQLParser from '../../parsers/PostgreSQLParser'; import PostgreSQLParser from '../../parsers/PostgreSQLParser';
import { BaseImporter } from '../BaseImporter'; import { BaseImporter } from '../BaseImporter';

View File

@@ -0,0 +1,16 @@
import { WebFrameMain } from 'electron';
import * as path from 'path';
const isDevelopment = process.env.NODE_ENV !== 'production';
const isWindows = process.platform === 'win32';
const indexPath = path.resolve(__dirname, 'index.html').split(path.sep).join('/');
export function validateSender (frame: WebFrameMain) {
if (process.windowsStore) return true; // TEMP HOTFIX
const frameUrl = new URL(frame.url);
const prefix = isWindows ? 'file:///' : 'file://';
const framePath = frameUrl.href.replace(prefix, '');
if ((isDevelopment && frameUrl.host === 'localhost:9080') || framePath === indexPath) return true;
return false;
}

View File

@@ -1,8 +1,8 @@
import { app, BrowserWindow, nativeImage, ipcMain } from 'electron'; import * as remoteMain from '@electron/remote/main';
import * as path from 'path'; import { app, BrowserWindow, ipcMain, nativeImage } from 'electron';
import * as Store from 'electron-store'; import * as Store from 'electron-store';
import * as windowStateKeeper from 'electron-window-state'; import * as windowStateKeeper from 'electron-window-state';
import * as remoteMain from '@electron/remote/main'; import * as path from 'path';
import ipcHandlers from './ipc-handlers'; import ipcHandlers from './ipc-handlers';
import { OsMenu, ShortcutRegister } from './libs/ShortcutRegister'; import { OsMenu, ShortcutRegister } from './libs/ShortcutRegister';
@@ -142,6 +142,14 @@ else {
const extensionPath = path.resolve(__dirname, `../../misc/${antares.devtoolsId}`); const extensionPath = path.resolve(__dirname, `../../misc/${antares.devtoolsId}`);
window.webContents.session.loadExtension(extensionPath, { allowFileAccess: true }).catch(console.error); window.webContents.session.loadExtension(extensionPath, { allowFileAccess: true }).catch(console.error);
} }
window.webContents.on('will-navigate', (e) => { // Prevent browser navigation
e.preventDefault();
});
window.webContents.on('did-create-window', (w) => { // Close new windows
w.close();
});
}); });
} }

View File

@@ -1,5 +1,6 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import * as fs from 'fs'; import * as fs from 'fs';
import { MySQLClient } from '../libs/clients/MySQLClient'; import { MySQLClient } from '../libs/clients/MySQLClient';
import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient'; import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient';
import { ClientsFactory } from '../libs/ClientsFactory'; import { ClientsFactory } from '../libs/ClientsFactory';

View File

@@ -1,13 +1,14 @@
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import * as pg from 'pg'; import { ImportOptions } from 'common/interfaces/importer';
import * as mysql from 'mysql2'; import * as mysql from 'mysql2';
import * as pg from 'pg';
import SSHConfig from 'ssh2-promise/lib/sshConfig';
import { MySQLClient } from '../libs/clients/MySQLClient'; import { MySQLClient } from '../libs/clients/MySQLClient';
import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient'; import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient';
import { ClientsFactory } from '../libs/ClientsFactory'; import { ClientsFactory } from '../libs/ClientsFactory';
import MySQLImporter from '../libs/importers/sql/MySQLlImporter'; import MySQLImporter from '../libs/importers/sql/MySQLlImporter';
import PostgreSQLImporter from '../libs/importers/sql/PostgreSQLImporter'; import PostgreSQLImporter from '../libs/importers/sql/PostgreSQLImporter';
import SSHConfig from 'ssh2-promise/lib/sshConfig';
import { ImportOptions } from 'common/interfaces/importer';
let importer: antares.Importer; let importer: antares.Importer;
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any

View File

@@ -34,18 +34,19 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineAsyncComponent, onMounted, Ref, ref } from 'vue'; import { getCurrentWindow, Menu } from '@electron/remote';
import { storeToRefs } from 'pinia';
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
import { storeToRefs } from 'pinia';
import { defineAsyncComponent, onMounted, Ref, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { Menu, getCurrentWindow } from '@electron/remote';
import ModalExportSchema from '@/components/ModalExportSchema.vue';
import TheSettingBar from '@/components/TheSettingBar.vue';
import { useApplicationStore } from '@/stores/application'; import { useApplicationStore } from '@/stores/application';
import { useConnectionsStore } from '@/stores/connections'; import { useConnectionsStore } from '@/stores/connections';
import { useSchemaExportStore } from '@/stores/schemaExport'; import { useSchemaExportStore } from '@/stores/schemaExport';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
import TheSettingBar from '@/components/TheSettingBar.vue';
import ModalExportSchema from '@/components/ModalExportSchema.vue';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -47,10 +47,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useFocusTrap } from '@/composables/useFocusTrap';
import { computed, onBeforeUnmount, PropType, useSlots } from 'vue'; import { computed, onBeforeUnmount, PropType, useSlots } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useFocusTrap } from '@/composables/useFocusTrap';
const { t } = useI18n(); const { t } = useI18n();
const props = defineProps({ const props = defineProps({

View File

@@ -0,0 +1,62 @@
<template>
<SvgIcon
:type="type"
:path="iconPath"
:size="size"
:rotate="rotate"
:class="iconFlip"
/>
</template>
<script setup lang="ts">
import SvgIcon from '@jamescoyle/vue-icon';
import * as Icons from '@mdi/js';
import { computed, PropType } from 'vue';
const props = defineProps({
iconName: {
type: String,
required: true
},
size: {
type: Number,
default: 48
},
type: {
type: String,
default: () => 'mdi'
},
flip: {
type: String as PropType<'horizontal' | 'vertical' | 'both'>,
default: () => null
},
rotate: {
type: Number,
default: () => null
}
});
const iconPath = computed(() => {
return (Icons as {[k:string]: string})[props.iconName];
});
const iconFlip = computed(() => {
if (['horizontal', 'vertical', 'both'].includes(props.flip))
return `flip-${props.flip}`;
else return '';
});
</script>
<style lang="scss" scoped>
.flip-horizontal {
transform: scaleX(-1);
}
.flip-vertical {
transform: scaleY(-1);
}
.flip-both {
transform: scale(-1, -1);
}
</style>

View File

@@ -3,15 +3,15 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, PropType, Ref, ref } from 'vue';
import * as L from 'leaflet';
import { import {
point,
lineString, lineString,
point,
polygon polygon
} from '@turf/helpers'; } from '@turf/helpers';
import { GeoJsonObject } from 'geojson';
import { getArrayDepth } from 'common/libs/getArrayDepth'; import { getArrayDepth } from 'common/libs/getArrayDepth';
import { GeoJsonObject } from 'geojson';
import * as L from 'leaflet';
import { onMounted, PropType, Ref, ref } from 'vue';
interface Coordinates { x: number; y: number } interface Coordinates { x: number; y: number }

View File

@@ -1,13 +1,18 @@
<template> <template>
<div class="toast mt-2" :class="notificationStatus.className"> <div class="toast mt-2" :class="notificationStatus.className">
<span class="p-vcentered text-left" :class="{'expanded': isExpanded}"> <span class="p-vcentered text-left" :class="{'expanded': isExpanded}">
<i class="mdi mdi-24px mr-2" :class="notificationStatus.iconName" /> <BaseIcon
:icon-name="notificationStatus.iconName"
class="mr-2"
:size="24"
/>
<span class="notification-message">{{ message }}</span> <span class="notification-message">{{ message }}</span>
</span> </span>
<i <BaseIcon
v-if="isExpandable" v-if="isExpandable"
class="mdi mdi-24px c-hand expand-btn" :icon-name="isExpanded ? 'mdiChevronUp' : 'mdiChevronDown'"
:class="isExpanded ? 'mdi-chevron-up' : 'mdi-chevron-down'" class=" c-hand expand-btn"
:size="24"
@click="toggleExpand" @click="toggleExpand"
/> />
<button class="btn btn-clear ml-2" @click="hideToast" /> <button class="btn btn-clear ml-2" @click="hideToast" />
@@ -17,6 +22,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import BaseIcon from '@/components/BaseIcon.vue';
const props = defineProps({ const props = defineProps({
message: { message: {
type: String, type: String,
@@ -36,19 +43,19 @@ const notificationStatus = computed(() => {
switch (props.status) { switch (props.status) {
case 'success': case 'success':
className = 'toast-success'; className = 'toast-success';
iconName = 'mdi-check'; iconName = 'mdiCheck';
break; break;
case 'error': case 'error':
className = 'toast-error'; className = 'toast-error';
iconName = 'mdi-alert-rhombus'; iconName = 'mdiAlertRhombus';
break; break;
case 'warning': case 'warning':
className = 'toast-warning'; className = 'toast-warning';
iconName = 'mdi-alert'; iconName = 'mdiAlert';
break; break;
case 'primary': case 'primary':
className = 'toast-primary'; className = 'toast-primary';
iconName = 'mdi-information-outline'; iconName = 'mdiInformationOutline';
break; break;
} }

View File

@@ -70,7 +70,7 @@
</template> </template>
<script> <script>
import { defineComponent, computed, ref, watch, nextTick, onMounted, onUnmounted } from 'vue'; import { computed, defineComponent, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
export default defineComponent({ export default defineComponent({
name: 'BaseSelect', name: 'BaseSelect',

View File

@@ -10,12 +10,16 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, watch } from 'vue'; /* eslint-disable simple-import-sort/imports */
import * as ace from 'ace-builds'; import * as ace from 'ace-builds';
import 'ace-builds/webpack-resolver'; import 'ace-builds/webpack-resolver';
import { storeToRefs } from 'pinia'; /* eslint-enable simple-import-sort/imports */
import { useSettingsStore } from '@/stores/settings';
import { uidGen } from 'common/libs/uidGen'; import { uidGen } from 'common/libs/uidGen';
import { storeToRefs } from 'pinia';
import { onMounted, watch } from 'vue';
import { useSettingsStore } from '@/stores/settings';
const props = defineProps({ const props = defineProps({
modelValue: String, modelValue: String,
@@ -132,9 +136,4 @@ onMounted(() => {
width: 100%; width: 100%;
} }
} }
.ace_.mdi {
display: inline-block;
width: 17px;
}
</style> </style>

View File

@@ -1,76 +0,0 @@
<template>
<div
:style="{display: isVisible ? 'flex' : 'none'}"
class="toast mt-2"
:class="toastStatus.className"
>
<span class="p-vcentered text-left"><i class="mdi mdi-24px mr-1" :class="toastStatus.iconName" /> {{ message }}</span>
<button class="btn btn-clear" @click="hideToast" />
</div>
</template>
<script setup lang="ts">
import { computed, ref, watch } from 'vue';
const props = defineProps({
message: {
type: String,
default: ''
},
status: {
type: String,
default: ''
}
});
const isVisible = ref(false);
const message = ref(props.message);
const emit = defineEmits(['close']);
const toastStatus = computed(() => {
let className = '';
let iconName = '';
switch (props.status) {
case 'success':
className = 'toast-success';
iconName = 'mdi-check';
break;
case 'error':
className = 'toast-error';
iconName = 'mdi-alert-rhombus';
break;
case 'warning':
className = 'toast-warning';
iconName = 'mdi-alert';
break;
case 'primary':
className = 'toast-primary';
iconName = 'mdi-information-outline';
break;
}
return { className, iconName };
});
watch(message, () => {
if (message.value)
isVisible.value = true;
else
isVisible.value = false;
});
const hideToast = () => {
isVisible.value = false;
emit('close');
};
</script>
<style scoped>
.toast {
display: flex;
justify-content: space-between;
user-select: text;
word-break: break-all;
}
</style>

View File

@@ -1,14 +1,20 @@
<template> <template>
<label :for="`id_${id}`" class="file-uploader"> <label :for="`id_${id}`" class="file-uploader">
<span class="file-uploader-message"> <span class="file-uploader-message">
<i class="mdi mdi-folder-open mr-1" />{{ message }} <BaseIcon
icon-name="mdiFolderOpen"
class="mr-1 mt-1"
:size="18"
/>{{ message }}
</span> </span>
<span class="text-ellipsis file-uploader-value"> <span class="text-ellipsis file-uploader-value">
{{ lastPart(modelValue, 19) }} {{ lastPart(modelValue, 19) }}
</span> </span>
<i <BaseIcon
v-if="modelValue" v-if="modelValue"
class="file-uploader-reset mdi mdi-close" class="file-upload-icon-clear"
icon-name="mdiClose"
:size="18"
@click.prevent="clear" @click.prevent="clear"
/> />
<form :ref="`form_${id}`"> <form :ref="`form_${id}`">
@@ -16,6 +22,7 @@
:id="`id_${id}`" :id="`id_${id}`"
class="file-uploader-input" class="file-uploader-input"
type="file" type="file"
:accept="accept"
@change="$emit('change', $event)" @change="$emit('change', $event)"
> >
</form> </form>
@@ -24,6 +31,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { uidGen } from 'common/libs/uidGen'; import { uidGen } from 'common/libs/uidGen';
import BaseIcon from '@/components/BaseIcon.vue';
import { useFilters } from '@/composables/useFilters'; import { useFilters } from '@/composables/useFilters';
const { lastPart } = useFilters(); const { lastPart } = useFilters();
@@ -33,6 +42,10 @@ defineProps({
default: 'Browse', default: 'Browse',
type: String type: String
}, },
accept: {
default: '',
type: String
},
modelValue: { modelValue: {
default: '', default: '',
type: String type: String
@@ -59,6 +72,12 @@ const clear = () => {
position: relative; position: relative;
flex: 1 1 auto; flex: 1 1 auto;
.file-upload-icon-clear {
position: absolute;
right: 4px;
top: 8px;
}
> span { > span {
padding: 0.25rem 0.4rem; padding: 0.25rem 0.4rem;
} }

View File

@@ -86,13 +86,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import FakerMethods from 'common/FakerMethods';
import { BIT, BLOB, DATE, DATETIME, FLOAT, IS_BIGINT, LONG_TEXT, NUMBER, TEXT, TIME, UUID } from 'common/fieldTypes';
import { computed, PropType, Ref, ref, watch } from 'vue'; import { computed, PropType, Ref, ref, watch } from 'vue';
import { TEXT, LONG_TEXT, NUMBER, FLOAT, DATE, TIME, DATETIME, BLOB, BIT, UUID, IS_BIGINT } from 'common/fieldTypes'; import { useI18n } from 'vue-i18n';
import BaseSelect from '@/components/BaseSelect.vue';
import BaseUploadInput from '@/components/BaseUploadInput.vue'; import BaseUploadInput from '@/components/BaseUploadInput.vue';
import ForeignKeySelect from '@/components/ForeignKeySelect.vue'; import ForeignKeySelect from '@/components/ForeignKeySelect.vue';
import FakerMethods from 'common/FakerMethods';
import BaseSelect from '@/components/BaseSelect.vue';
import { useI18n } from 'vue-i18n';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -13,15 +13,16 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, Ref, ref, watch } from 'vue'; import { LONG_TEXT, TEXT } from 'common/fieldTypes';
import { TableField } from 'common/interfaces/antares';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { computed, Ref, ref, watch } from 'vue';
import BaseSelect from '@/components/BaseSelect.vue';
import { useFilters } from '@/composables/useFilters';
import Tables from '@/ipc-api/Tables'; import Tables from '@/ipc-api/Tables';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
import { TEXT, LONG_TEXT } from 'common/fieldTypes';
import BaseSelect from '@/components/BaseSelect.vue';
import { TableField } from 'common/interfaces/antares';
import { useFilters } from '@/composables/useFilters';
const props = defineProps({ const props = defineProps({
modelValue: [String, Number], modelValue: [String, Number],

View File

@@ -9,12 +9,18 @@
@blur="isFocus = false" @blur="isFocus = false"
@keydown.prevent.stop="onKey" @keydown.prevent.stop="onKey"
> >
<i class="form-icon mdi mdi-keyboard-outline mdi-24px" /> <BaseIcon
icon-name="mdiKeyboardOutline"
class="form-icon"
:size="24"
/>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, PropType, Ref, ref, watch } from 'vue'; import { computed, PropType, Ref, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import Application from '@/ipc-api/Application'; import Application from '@/ipc-api/Application';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -6,7 +6,11 @@
<div class="modal-header pl-2"> <div class="modal-header pl-2">
<div class="modal-title h6"> <div class="modal-title h6">
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-apps mr-1" /> <BaseIcon
icon-name="mdiApps"
class="mr-1"
:size="24"
/>
<span class="cut-text">{{ t('connection.allConnections') }}</span> <span class="cut-text">{{ t('connection.allConnections') }}</span>
</div> </div>
</div> </div>
@@ -24,10 +28,17 @@
:placeholder="t('connection.searchForConnections')" :placeholder="t('connection.searchForConnections')"
@keypress.esc="searchTerm = ''" @keypress.esc="searchTerm = ''"
> >
<i v-if="!searchTerm" class="form-icon mdi mdi-magnify mdi-18px pr-4" /> <BaseIcon
<i v-if="!searchTerm"
icon-name="mdiMagnify"
class="form-icon pr-4"
:size="18"
/>
<BaseIcon
v-else v-else
class="form-icon c-hand mdi mdi-backspace mdi-18px pr-4" icon-name="mdiBackspace"
class="form-icon c-hand pr-4"
:size="18"
@click="searchTerm = ''" @click="searchTerm = ''"
/> />
</div> </div>
@@ -56,9 +67,11 @@
{{ clients.get(connection.client) || connection.client }} {{ clients.get(connection.client) || connection.client }}
</div> </div>
<div class="all-connections-buttons p-absolute d-flex" :style="'top: 0; right: 0;'"> <div class="all-connections-buttons p-absolute d-flex" :style="'top: 0; right: 0;'">
<i <BaseIcon
class="all-connections-delete mdi mdi-delete mdi-18px ml-2" icon-name="mdiDelete"
class="all-connections-delete ml-2"
:title="t('general.delete')" :title="t('general.delete')"
:size="18"
@click.stop="askToDelete(connection)" @click.stop="askToDelete(connection)"
/> />
</div> </div>
@@ -66,32 +79,57 @@
<div class="panel-body text-center"> <div class="panel-body text-center">
<div v-if="connection.databasePath"> <div v-if="connection.databasePath">
<div class="text-ellipsis" :title="connection.databasePath"> <div class="text-ellipsis" :title="connection.databasePath">
<i class="mdi mdi-database d-inline" /> <span class="text-bold">{{ <BaseIcon
icon-name="mdiDatabase"
class="p-relative"
:style="'top:3px'"
:size="18"
/> <span class="text-bold">{{
connection.databasePath connection.databasePath
}}</span> }}</span>
</div> </div>
</div> </div>
<div v-else> <div v-else>
<div class="text-ellipsis" :title="`${connection.host}:${connection.port}`"> <div class="text-ellipsis" :title="`${connection.host}:${connection.port}`">
<i class="mdi mdi-server d-inline" /> <span class="text-bold">{{ connection.host <BaseIcon
icon-name="mdiServer"
class="p-relative"
:style="'top:3px'"
:size="18"
/> <span class="text-bold">{{ connection.host
}}:{{ connection.port }}</span> }}:{{ connection.port }}</span>
</div> </div>
</div> </div>
<div v-if="connection.user"> <div v-if="connection.user">
<div class="text-ellipsis"> <div class="text-ellipsis">
<i class="mdi mdi-account d-inline" /> <span class="text-bold">{{ connection.user <BaseIcon
icon-name="mdiAccount"
class="p-relative"
:style="'top:3px'"
:size="18"
/> <span class="text-bold">{{ connection.user
}}</span> }}</span>
</div> </div>
</div> </div>
<div v-if="connection.schema"> <div v-if="connection.schema">
<div class="text-ellipsis"> <div class="text-ellipsis">
<i class="mdi mdi-database d-inline" /> <span class="text-bold">{{ connection.schema <BaseIcon
icon-name="mdiDatabase"
class="p-relative"
:style="'top:3px'"
:size="18"
/> <span class="text-bold">{{ connection.schema
}}</span> }}</span>
</div> </div>
</div> </div>
<div v-if="connection.database"> <div v-if="connection.database">
<div class="text-ellipsis"> <div class="text-ellipsis">
<i class="mdi mdi-database d-inline" /> <span class="text-bold">{{ <BaseIcon
icon-name="mdiDatabase"
class="p-relative"
:style="'top:3px'"
:size="18"
/> <span class="text-bold">{{
connection.database connection.database
}}</span> }}</span>
</div> </div>
@@ -99,11 +137,19 @@
</div> </div>
<div class="panel-footer text-center py-0"> <div class="panel-footer text-center py-0">
<div v-if="connection.ssl" class="chip bg-success mt-2"> <div v-if="connection.ssl" class="chip bg-success mt-2">
<i class="mdi mdi-shield-key mdi-18px mr-1" /> <BaseIcon
icon-name="mdiShieldKey"
class="mr-1"
:size="18"
/>
SSL SSL
</div> </div>
<div v-if="connection.ssh" class="chip bg-success mt-2"> <div v-if="connection.ssh" class="chip bg-success mt-2">
<i class="mdi mdi-console-network mdi-18px mr-1" /> <BaseIcon
icon-name="mdiConsoleNetwork"
class="mr-1"
:size="18"
/>
SSH SSH
</div> </div>
</div> </div>
@@ -130,7 +176,11 @@
> >
<template #header> <template #header>
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-server-remove mr-1" /> {{ t('connection.deleteConnection') }} <BaseIcon
icon-name="mdiServerRemove"
class="mr-1"
:size="24"
/> {{ t('connection.deleteConnection') }}
</div> </div>
</template> </template>
<template #body> <template #body>
@@ -143,14 +193,16 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onBeforeUnmount, Ref, ref } from 'vue'; import { ConnectionParams } from 'common/interfaces/antares';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import ConfirmModal from '@/components/BaseConfirmModal.vue';
import BaseIcon from '@/components/BaseIcon.vue';
import { useFocusTrap } from '@/composables/useFocusTrap'; import { useFocusTrap } from '@/composables/useFocusTrap';
import { useConnectionsStore } from '@/stores/connections'; import { useConnectionsStore } from '@/stores/connections';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
import ConfirmModal from '@/components/BaseConfirmModal.vue';
import { ConnectionParams } from 'common/interfaces/antares';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -6,7 +6,11 @@
<div class="modal-header pl-2"> <div class="modal-header pl-2">
<div class="modal-title h6"> <div class="modal-title h6">
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-key-variant mr-1" /> {{ t('connection.credentials') }} <BaseIcon
icon-name="mdiKeyVariant"
class="mr-1"
:size="24"
/> {{ t('connection.credentials') }}
</div> </div>
</div> </div>
<a class="btn btn-clear c-hand" @click.stop="closeModal" /> <a class="btn btn-clear c-hand" @click.stop="closeModal" />
@@ -57,9 +61,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { Ref, ref } from 'vue'; import { Ref, ref } from 'vue';
import { useFocusTrap } from '@/composables/useFocusTrap';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import { useFocusTrap } from '@/composables/useFocusTrap';
const { t } = useI18n(); const { t } = useI18n();
const { trapRef } = useFocusTrap(); const { trapRef } = useFocusTrap();

View File

@@ -8,7 +8,11 @@
> >
<template #header> <template #header>
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-play mr-1" /> <BaseIcon
icon-name="mdiPlay"
class="mr-1"
:size="24"
/>
<span class="cut-text">{{ t('database.parameters') }}: {{ localRoutine.name }}</span> <span class="cut-text">{{ t('database.parameters') }}: {{ localRoutine.name }}</span>
</div> </div>
</template> </template>
@@ -48,13 +52,15 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, PropType, Ref, ref } from 'vue'; import { FLOAT, NUMBER } from 'common/fieldTypes';
import { NUMBER, FLOAT } from 'common/fieldTypes';
import { FunctionInfos, RoutineInfos } from 'common/interfaces/antares'; import { FunctionInfos, RoutineInfos } from 'common/interfaces/antares';
import ConfirmModal from '@/components/BaseConfirmModal.vue'; import { computed, PropType, Ref, ref } from 'vue';
import { useFilters } from '@/composables/useFilters';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import ConfirmModal from '@/components/BaseConfirmModal.vue';
import BaseIcon from '@/components/BaseIcon.vue';
import { useFilters } from '@/composables/useFilters';
const { t } = useI18n(); const { t } = useI18n();
const { wrapNumber } = useFilters(); const { wrapNumber } = useFilters();

View File

@@ -6,8 +6,12 @@
<div class="modal-header pl-2"> <div class="modal-header pl-2">
<div class="modal-title h6"> <div class="modal-title h6">
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-brush-variant mr-1" /> <BaseIcon
<span class="cut-text">{{ t('connection.editConnectionAppearance') }}</span> icon-name="mdiBrushVariant"
class="mr-1"
:size="24"
/>
<span class="cut-text">{{ t('application.editConnectionAppearance') }}</span>
</div> </div>
</div> </div>
<a class="btn btn-clear c-hand" @click.stop="closeModal" /> <a class="btn btn-clear c-hand" @click.stop="closeModal" />
@@ -37,11 +41,24 @@
<div <div
v-for="icon in icons" v-for="icon in icons"
:key="icon.name" :key="icon.name"
class="icon-box" >
:title="icon.name" <BaseIcon
:class="[icon.code ? `mdi ${icon.code} mdi-36px` : `dbi dbi-${connection.client}`, {'selected': localConnection.icon === icon.code}]" v-if="icon.code"
@click="localConnection.icon = icon.code" :icon-name="camelize(icon.code)"
/> :size="36"
class="icon-box"
:title="icon.name"
:class="[{'selected': localConnection.icon === icon.code}]"
@click="localConnection.icon = icon.code"
/>
<div
v-else
class="icon-box"
:title="icon.name"
:class="[`dbi dbi-${connection.client}`, {'selected': localConnection.icon === icon.code}]"
@click="localConnection.icon = icon.code"
/>
</div>
</div> </div>
</div> </div>
</form> </form>
@@ -62,10 +79,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { onBeforeUnmount, PropType, Ref, ref } from 'vue'; import { onBeforeUnmount, PropType, Ref, ref } from 'vue';
import { useFocusTrap } from '@/composables/useFocusTrap';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { SidebarElement, useConnectionsStore } from '@/stores/connections';
import BaseIcon from '@/components/BaseIcon.vue';
import { useFocusTrap } from '@/composables/useFocusTrap';
import { unproxify } from '@/libs/unproxify'; import { unproxify } from '@/libs/unproxify';
import { SidebarElement, useConnectionsStore } from '@/stores/connections';
const connectionsStore = useConnectionsStore(); const connectionsStore = useConnectionsStore();
@@ -141,6 +160,16 @@ const editFolderAppearance = () => {
closeModal(); closeModal();
}; };
const camelize = (text: string) => {
const textArr = text.split('-');
for (let i = 0; i < textArr.length; i++) {
if (i === 0) continue;
textArr[i] = textArr[i].charAt(0).toUpperCase() + textArr[i].slice(1);
}
return textArr.join('');
};
const closeModal = () => emit('close'); const closeModal = () => emit('close');
const onKey =(e: KeyboardEvent) => { const onKey =(e: KeyboardEvent) => {

View File

@@ -7,7 +7,11 @@
> >
<template #header> <template #header>
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-content-save-alert mr-1" /> {{ t('application.unsavedChanges') }} <BaseIcon
icon-name="mdiContentSaveAlert"
class="mr-1"
:size="24"
/> {{ t('application.unsavedChanges') }}
</div> </div>
</template> </template>
<template #body> <template #body>
@@ -19,10 +23,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import ConfirmModal from '@/components/BaseConfirmModal.vue';
import { onBeforeUnmount } from 'vue'; import { onBeforeUnmount } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import ConfirmModal from '@/components/BaseConfirmModal.vue';
import BaseIcon from '@/components/BaseIcon.vue';
const { t } = useI18n(); const { t } = useI18n();
const emit = defineEmits(['confirm', 'close']); const emit = defineEmits(['confirm', 'close']);

View File

@@ -6,7 +6,11 @@
<div class="modal-header pl-2"> <div class="modal-header pl-2">
<div class="modal-title h6"> <div class="modal-title h6">
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-database-edit mr-1" /> <BaseIcon
icon-name="mdiDatabaseEdit"
class="mr-1"
:size="24"
/>
<span class="cut-text">{{ t('database.editSchema') }}</span> <span class="cut-text">{{ t('database.editSchema') }}</span>
</div> </div>
</div> </div>
@@ -64,14 +68,16 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useNotificationsStore } from '@/stores/notifications'; import { computed, onBeforeUnmount, Ref, ref } from 'vue';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import BaseSelect from '@/components/BaseSelect.vue';
import { useFocusTrap } from '@/composables/useFocusTrap'; import { useFocusTrap } from '@/composables/useFocusTrap';
import Schema from '@/ipc-api/Schema'; import Schema from '@/ipc-api/Schema';
import BaseSelect from '@/components/BaseSelect.vue'; import { useNotificationsStore } from '@/stores/notifications';
import { useI18n } from 'vue-i18n'; import { useWorkspacesStore } from '@/stores/workspaces';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -6,7 +6,11 @@
<div class="modal-header pl-2"> <div class="modal-header pl-2">
<div class="modal-title h6"> <div class="modal-title h6">
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-database-export mr-1" /> <BaseIcon
icon-name="mdiDatabaseExport"
class="mr-1"
:size="24"
/>
<span class="cut-text">{{ t('database.exportSchema') }}</span> <span class="cut-text">{{ t('database.exportSchema') }}</span>
</div> </div>
</div> </div>
@@ -26,7 +30,7 @@
type="text" type="text"
required required
readonly readonly
:placeholder="t('database.schemaName')" @click.prevent="openPathDialog"
> >
<button <button
type="button" type="button"
@@ -44,7 +48,11 @@
<div class="column col-8 left"> <div class="column col-8 left">
<div class="columns mb-2 mt-1 p-vcentered"> <div class="columns mb-2 mt-1 p-vcentered">
<div class="column col-auto input-group d-flex text-italic" :style="'flex-grow: 1'"> <div class="column col-auto input-group d-flex text-italic" :style="'flex-grow: 1'">
<i class="input-group-addon mdi mdi-file-document-outline" /> <BaseIcon
icon-name="mdiFileDocumentOutline"
class="input-group-addon"
:size="36"
/>
<input <input
v-model="chosenFilename" v-model="chosenFilename"
class="form-input" class="form-input"
@@ -56,27 +64,27 @@
<div class="column col-auto col-ml-auto "> <div class="column col-auto col-ml-auto ">
<button <button
class="btn btn-dark btn-sm" class="btn btn-dark btn-sm pt-1"
:title="t('general.refresh')" :title="t('general.refresh')"
@click="refresh" @click="refresh"
> >
<i class="mdi mdi-refresh" /> <BaseIcon icon-name="mdiRefresh" :size="15" />
</button> </button>
<button <button
class="btn btn-dark btn-sm mx-1" class="btn btn-dark btn-sm mx-1 pt-1"
:title="t('database.uncheckAllTables')" :title="t('database.uncheckAllTables')"
:disabled="isRefreshing" :disabled="isRefreshing"
@click="uncheckAllTables" @click="uncheckAllTables"
> >
<i class="mdi mdi-checkbox-blank-outline" /> <BaseIcon icon-name="mdiCheckboxBlankOutline" :size="15" />
</button> </button>
<button <button
class="btn btn-dark btn-sm" class="btn btn-dark btn-sm pt-1"
:title="t('database.checkAllTables')" :title="t('database.checkAllTables')"
:disabled="isRefreshing" :disabled="isRefreshing"
@click="checkAllTables" @click="checkAllTables"
> >
<i class="mdi mdi-checkbox-marked-outline" /> <BaseIcon icon-name="mdiCheckboxMarkedOutline" :size="15" />
</button> </button>
</div> </div>
</div> </div>
@@ -251,7 +259,7 @@
</div> </div>
</div> </div>
<div class="column col-auto px-0"> <div class="column col-auto px-0">
<button class="btn btn-link" @click.stop="closeModal"> <button class="btn btn-link mr-2" @click.stop="closeModal">
{{ t('general.close') }} {{ t('general.close') }}
</button> </button>
<button <button
@@ -271,21 +279,23 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
import * as moment from 'moment';
import { ipcRenderer } from 'electron';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { ClientCode, SchemaInfos } from 'common/interfaces/antares'; import { ClientCode, SchemaInfos } from 'common/interfaces/antares';
import { Customizations } from 'common/interfaces/customizations';
import { ExportOptions, ExportState } from 'common/interfaces/exporter'; import { ExportOptions, ExportState } from 'common/interfaces/exporter';
import { useNotificationsStore } from '@/stores/notifications'; import { ipcRenderer } from 'electron';
import { useSchemaExportStore } from '@/stores/schemaExport'; import * as moment from 'moment';
import { useWorkspacesStore } from '@/stores/workspaces'; import { storeToRefs } from 'pinia';
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import BaseSelect from '@/components/BaseSelect.vue';
import { useFocusTrap } from '@/composables/useFocusTrap'; import { useFocusTrap } from '@/composables/useFocusTrap';
import Application from '@/ipc-api/Application'; import Application from '@/ipc-api/Application';
import Schema from '@/ipc-api/Schema'; import Schema from '@/ipc-api/Schema';
import { Customizations } from 'common/interfaces/customizations'; import { useNotificationsStore } from '@/stores/notifications';
import BaseSelect from '@/components/BaseSelect.vue'; import { useSchemaExportStore } from '@/stores/schemaExport';
import { useWorkspacesStore } from '@/stores/workspaces';
const emit = defineEmits(['close']); const emit = defineEmits(['close']);
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -6,7 +6,11 @@
<div class="modal-header pl-2"> <div class="modal-header pl-2">
<div class="modal-title h6"> <div class="modal-title h6">
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-playlist-plus mr-1" /> <BaseIcon
icon-name="mdiPlaylistPlus"
:size="24"
class="mr-1"
/>
<span class="cut-text">{{ t('database.insertRow', 2) }}</span> <span class="cut-text">{{ t('database.insertRow', 2) }}</span>
</div> </div>
</div> </div>
@@ -64,7 +68,7 @@
:disabled="isInserting" :disabled="isInserting"
> >
<span class="input-group-addon"> <span class="input-group-addon">
<i class="mdi mdi-24px mdi-repeat" /> <BaseIcon icon-name="mdiRepeat" :size="24" />
</span> </span>
</div> </div>
<div <div
@@ -98,19 +102,21 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onBeforeMount, onMounted, Prop, Ref, ref, watch } from 'vue'; import { BIT, BLOB, DATE, DATETIME, FLOAT, LONG_TEXT, NUMBER, TEXT, TIME } from 'common/fieldTypes';
import * as moment from 'moment';
import { TableField, TableForeign } from 'common/interfaces/antares'; import { TableField, TableForeign } from 'common/interfaces/antares';
import * as moment from 'moment';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { TEXT, LONG_TEXT, NUMBER, FLOAT, DATE, TIME, DATETIME, BLOB, BIT } from 'common/fieldTypes'; import { computed, onBeforeMount, onMounted, Prop, Ref, ref, watch } from 'vue';
import { useNotificationsStore } from '@/stores/notifications'; import { useI18n } from 'vue-i18n';
import { useWorkspacesStore } from '@/stores/workspaces';
import BaseIcon from '@/components/BaseIcon.vue';
import BaseSelect from '@/components/BaseSelect.vue';
import FakerSelect from '@/components/FakerSelect.vue';
import { useFilters } from '@/composables/useFilters';
import { useFocusTrap } from '@/composables/useFocusTrap'; import { useFocusTrap } from '@/composables/useFocusTrap';
import Tables from '@/ipc-api/Tables'; import Tables from '@/ipc-api/Tables';
import FakerSelect from '@/components/FakerSelect.vue'; import { useNotificationsStore } from '@/stores/notifications';
import BaseSelect from '@/components/BaseSelect.vue'; import { useWorkspacesStore } from '@/stores/workspaces';
import { useFilters } from '@/composables/useFilters';
import { useI18n } from 'vue-i18n';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -6,7 +6,11 @@
<div class="modal-header pl-2"> <div class="modal-header pl-2">
<div class="modal-title h6"> <div class="modal-title h6">
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-folder-edit mr-1" /> <BaseIcon
icon-name="mdiFolderEdit"
class="mr-1"
:size="24"
/>
<span class="cut-text">{{ t('application.editFolder') }}</span> <span class="cut-text">{{ t('application.editFolder') }}</span>
</div> </div>
</div> </div>
@@ -43,7 +47,11 @@
:style="`background-color: ${color.hex}`" :style="`background-color: ${color.hex}`"
@click="localFolder.color = color.hex" @click="localFolder.color = color.hex"
> >
<i v-if="localFolder.color === color.hex" class="mdi mdi-check" /> <BaseIcon
v-if="localFolder.color === color.hex"
icon-name="mdiCheck"
:size="16"
/>
</div> </div>
</div> </div>
</div> </div>
@@ -65,10 +73,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { onBeforeUnmount, PropType, Ref, ref } from 'vue'; import { onBeforeUnmount, PropType, Ref, ref } from 'vue';
import { useFocusTrap } from '@/composables/useFocusTrap';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { SidebarElement, useConnectionsStore } from '@/stores/connections';
import BaseIcon from '@/components/BaseIcon.vue';
import { useFocusTrap } from '@/composables/useFocusTrap';
import { unproxify } from '@/libs/unproxify'; import { unproxify } from '@/libs/unproxify';
import { SidebarElement, useConnectionsStore } from '@/stores/connections';
const connectionsStore = useConnectionsStore(); const connectionsStore = useConnectionsStore();

View File

@@ -6,7 +6,11 @@
<div class="modal-header pl-2"> <div class="modal-header pl-2">
<div class="modal-title h6"> <div class="modal-title h6">
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-history mr-1" /> <BaseIcon
icon-name="mdiHistory"
class="mr-1"
:size="24"
/>
<span class="cut-text">{{ t('general.history') }}: {{ connectionName }}</span> <span class="cut-text">{{ t('general.history') }}: {{ connectionName }}</span>
</div> </div>
</div> </div>
@@ -24,17 +28,24 @@
type="text" type="text"
:placeholder="t('database.searchForQueries')" :placeholder="t('database.searchForQueries')"
> >
<i v-if="!searchTerm" class="form-icon mdi mdi-magnify mdi-18px pr-4" /> <BaseIcon
<i v-if="!searchTerm"
icon-name="mdiMagnify"
class="form-icon pr-2"
:size="18"
/>
<BaseIcon
v-else v-else
class="form-icon c-hand mdi mdi-backspace mdi-18px pr-4" icon-name="mdiBackspace"
class="form-icon c-hand pr-2"
:size="18"
@click="searchTerm = ''" @click="searchTerm = ''"
/> />
</div> </div>
<div <div
v-if="history.length" v-if="history.length"
ref="tableWrapper" ref="tableWrapper"
class="vscroll px-1 " class="vscroll px-1"
:style="{'height': resultsSize+'px'}" :style="{'height': resultsSize+'px'}"
> >
<div ref="table"> <div ref="table">
@@ -53,7 +64,11 @@
tabindex="0" tabindex="0"
> >
<div class="tile-icon"> <div class="tile-icon">
<i class="mdi mdi-code-tags pr-1" /> <BaseIcon
icon-name="mdiCodeTags"
class="pr-1"
:size="24"
/>
</div> </div>
<div class="tile-content"> <div class="tile-content">
<div class="tile-title"> <div class="tile-title">
@@ -67,13 +82,25 @@
<small class="tile-subtitle">{{ query.schema }} · {{ formatDate(query.date) }}</small> <small class="tile-subtitle">{{ query.schema }} · {{ formatDate(query.date) }}</small>
<div class="tile-history-buttons"> <div class="tile-history-buttons">
<button class="btn btn-link pl-1" @click.stop="$emit('select-query', query.sql)"> <button class="btn btn-link pl-1" @click.stop="$emit('select-query', query.sql)">
<i class="mdi mdi-open-in-app pr-1" /> {{ t('general.select') }} <BaseIcon
icon-name="mdiOpenInApp"
class="pr-1"
:size="22"
/> {{ t('general.select') }}
</button> </button>
<button class="btn btn-link pl-1" @click="copyQuery(query.sql)"> <button class="btn btn-link pl-1" @click="copyQuery(query.sql)">
<i class="mdi mdi-content-copy pr-1" /> {{ t('general.copy') }} <BaseIcon
icon-name="mdiContentCopy"
class="pr-1"
:size="22"
/> {{ t('general.copy') }}
</button> </button>
<button class="btn btn-link pl-1" @click="deleteQuery(query)"> <button class="btn btn-link pl-1" @click="deleteQuery(query)">
<i class="mdi mdi-delete-forever pr-1" /> {{ t('general.delete') }} <BaseIcon
icon-name="mdiDeleteForever"
class="pr-1"
:size="22"
/> {{ t('general.delete') }}
</button> </button>
</div> </div>
</div> </div>
@@ -85,7 +112,7 @@
</div> </div>
<div v-else class="empty"> <div v-else class="empty">
<div class="empty-icon"> <div class="empty-icon">
<i class="mdi mdi-history mdi-48px" /> <BaseIcon icon-name="mdiHistory" :size="48" />
</div> </div>
<p class="empty-title h5"> <p class="empty-title h5">
{{ t('database.thereIsNoQueriesYet') }} {{ t('database.thereIsNoQueriesYet') }}
@@ -98,14 +125,16 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ConnectionParams } from 'common/interfaces/antares';
import { Component, computed, ComputedRef, onBeforeUnmount, onMounted, onUpdated, Prop, Ref, ref, watch } from 'vue'; import { Component, computed, ComputedRef, onBeforeUnmount, onMounted, onUpdated, Prop, Ref, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { ConnectionParams } from 'common/interfaces/antares';
import { HistoryRecord, useHistoryStore } from '@/stores/history'; import BaseIcon from '@/components/BaseIcon.vue';
import { useConnectionsStore } from '@/stores/connections';
import { useFocusTrap } from '@/composables/useFocusTrap';
import { useFilters } from '@/composables/useFilters';
import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue'; import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue';
import { useFilters } from '@/composables/useFilters';
import { useFocusTrap } from '@/composables/useFocusTrap';
import { useConnectionsStore } from '@/stores/connections';
import { HistoryRecord, useHistoryStore } from '@/stores/history';
const { t } = useI18n(); const { t } = useI18n();
const { formatDate } = useFilters(); const { formatDate } = useFilters();

View File

@@ -6,7 +6,11 @@
<div class="modal-header pl-2"> <div class="modal-header pl-2">
<div class="modal-title h6"> <div class="modal-title h6">
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-database-import mr-1" /> <BaseIcon
icon-name="mdiDatabaseImport"
class="mr-1"
:size="24"
/>
<span class="cut-text">{{ t('database.importSchema') }}</span> <span class="cut-text">{{ t('database.importSchema') }}</span>
</div> </div>
</div> </div>
@@ -50,15 +54,17 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onBeforeUnmount, Ref, ref } from 'vue'; import { ImportState } from 'common/interfaces/importer';
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
import * as moment from 'moment'; import * as moment from 'moment';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import Schema from '@/ipc-api/Schema';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
import Schema from '@/ipc-api/Schema';
import { ImportState } from 'common/interfaces/importer';
import { useI18n } from 'vue-i18n';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -6,7 +6,11 @@
<div class="modal-header pl-2"> <div class="modal-header pl-2">
<div class="modal-title h6"> <div class="modal-title h6">
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-database-plus mr-1" /> <BaseIcon
icon-name="mdiDatabasePlus"
class="mr-1"
:size="24"
/>
<span class="cut-text">{{ t('database.createNewSchema') }}</span> <span class="cut-text">{{ t('database.createNewSchema') }}</span>
</div> </div>
</div> </div>
@@ -67,14 +71,16 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useNotificationsStore } from '@/stores/notifications'; import { computed, onBeforeUnmount, Ref, ref } from 'vue';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import BaseSelect from '@/components/BaseSelect.vue';
import { useFocusTrap } from '@/composables/useFocusTrap'; import { useFocusTrap } from '@/composables/useFocusTrap';
import Schema from '@/ipc-api/Schema'; import Schema from '@/ipc-api/Schema';
import BaseSelect from '@/components/BaseSelect.vue'; import { useNotificationsStore } from '@/stores/notifications';
import { useI18n } from 'vue-i18n'; import { useWorkspacesStore } from '@/stores/workspaces';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -16,7 +16,11 @@
<div class="modal-header pl-2"> <div class="modal-header pl-2">
<div class="modal-title h6"> <div class="modal-title h6">
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-memory mr-1" /> <BaseIcon
icon-name="mdiMemory"
class="mr-1"
:size="24"
/>
<span class="cut-text">{{ t('database.processesList') }}: {{ connectionName }}</span> <span class="cut-text">{{ t('database.processesList') }}: {{ connectionName }}</span>
</div> </div>
</div> </div>
@@ -32,11 +36,21 @@
:title="`${t('general.refresh')}`" :title="`${t('general.refresh')}`"
@click="getProcessesList" @click="getProcessesList"
> >
<i v-if="!+autorefreshTimer" class="mdi mdi-24px mdi-refresh mr-1" /> <BaseIcon
<i v-else class="mdi mdi-24px mdi-history mdi-flip-h mr-1" /> v-if="!+autorefreshTimer"
icon-name="mdiRefresh"
:size="24"
/>
<BaseIcon
v-else
icon-name="mdiHistory"
flip="horizontal"
class="mr-1"
:size="24"
/>
</button> </button>
<div class="btn btn-dark btn-sm dropdown-toggle pl-0 pr-0" tabindex="0"> <div class="btn btn-dark btn-sm dropdown-toggle pl-0 pr-0" tabindex="0">
<i class="mdi mdi-24px mdi-menu-down" /> <BaseIcon icon-name="mdiMenuDown" :size="24" />
</div> </div>
<div class="menu px-3"> <div class="menu px-3">
<span>{{ t('general.autoRefresh') }}: <b>{{ +autorefreshTimer ? `${autorefreshTimer}s` : 'OFF' }}</b></span> <span>{{ t('general.autoRefresh') }}: <b>{{ +autorefreshTimer ? `${autorefreshTimer}s` : 'OFF' }}</b></span>
@@ -58,9 +72,9 @@
class="btn btn-dark btn-sm dropdown-toggle d-flex mr-0 pr-0" class="btn btn-dark btn-sm dropdown-toggle d-flex mr-0 pr-0"
tabindex="0" tabindex="0"
> >
<i class="mdi mdi-24px mdi-file-export mr-1" /> <BaseIcon icon-name="mdiFileExport" :size="24" />
<span>{{ t('database.export') }}</span> <span>{{ t('database.export') }}</span>
<i class="mdi mdi-24px mdi-menu-down" /> <BaseIcon icon-name="mdiMenuDown" :size="24" />
</button> </button>
<ul class="menu text-left"> <ul class="menu text-left">
<li class="menu-item"> <li class="menu-item">
@@ -95,10 +109,12 @@
<div ref="columnResize" class="column-resizable"> <div ref="columnResize" class="column-resizable">
<div class="table-column-title" @click="sort(field)"> <div class="table-column-title" @click="sort(field)">
<span>{{ field.toUpperCase() }}</span> <span>{{ field.toUpperCase() }}</span>
<i
<BaseIcon
v-if="currentSort === field" v-if="currentSort === field"
class="mdi sort-icon" :icon-name="currentSortDir === 'asc' ? 'mdiSortAscending':'mdiSortDescending'"
:class="currentSortDir === 'asc' ? 'mdi-sort-ascending':'mdi-sort-descending'" :size="18"
class="ml-1"
/> />
</div> </div>
</div> </div>
@@ -134,18 +150,21 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Component, computed, onBeforeUnmount, onMounted, onUpdated, Prop, Ref, ref } from 'vue';
import { ipcRenderer } from 'electron';
import { ConnectionParams } from 'common/interfaces/antares'; import { ConnectionParams } from 'common/interfaces/antares';
import { exportRows } from '../libs/exportRows'; import { ipcRenderer } from 'electron';
import { useNotificationsStore } from '@/stores/notifications'; import { Component, computed, onBeforeUnmount, onMounted, onUpdated, Prop, Ref, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue';
import ModalProcessesListContext from '@/components/ModalProcessesListContext.vue';
import ModalProcessesListRow from '@/components/ModalProcessesListRow.vue';
import { useFocusTrap } from '@/composables/useFocusTrap'; import { useFocusTrap } from '@/composables/useFocusTrap';
import Schema from '@/ipc-api/Schema'; import Schema from '@/ipc-api/Schema';
import { useConnectionsStore } from '@/stores/connections'; import { useConnectionsStore } from '@/stores/connections';
import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue'; import { useNotificationsStore } from '@/stores/notifications';
import ModalProcessesListRow from '@/components/ModalProcessesListRow.vue';
import ModalProcessesListContext from '@/components/ModalProcessesListContext.vue'; import { exportRows } from '../libs/exportRows';
import { useI18n } from 'vue-i18n';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -4,8 +4,16 @@
@close-context="closeContext" @close-context="closeContext"
> >
<div v-if="props.selectedRow" class="context-element"> <div v-if="props.selectedRow" class="context-element">
<span class="d-flex"><i class="mdi mdi-18px mdi-content-copy text-light pr-1" /> {{ t('general.copy') }}</span> <span class="d-flex"><BaseIcon
<i class="mdi mdi-18px mdi-chevron-right text-light pl-1" /> icon-name="mdiContentCopy"
class="text-light mt-1 mr-1"
:size="18"
/> {{ t('general.copy') }}</span>
<BaseIcon
icon-name="mdiChevronRight"
class="text-light"
:size="18"
/>
<div class="context-submenu"> <div class="context-submenu">
<div <div
v-if="props.selectedRow" v-if="props.selectedRow"
@@ -13,7 +21,12 @@
@click="copyCell" @click="copyCell"
> >
<span class="d-flex"> <span class="d-flex">
<i class="mdi mdi-18px mdi-numeric-0 mdi-rotate-90 text-light pr-1" /> {{ t('database.cell', 1) }} <BaseIcon
icon-name="mdiNumeric0"
:rotate="90"
class="text-light mt-1 mr-1"
:size="18"
/> {{ t('database.cell', 1) }}
</span> </span>
</div> </div>
<div <div
@@ -22,7 +35,11 @@
@click="copyRow" @click="copyRow"
> >
<span class="d-flex"> <span class="d-flex">
<i class="mdi mdi-18px mdi-table-row text-light pr-1" /> {{ t('database.row', 1) }} <BaseIcon
icon-name="mdiTableRow"
class="text-light mt-1 mr-1"
:size="18"
/> {{ t('database.row', 1) }}
</span> </span>
</div> </div>
</div> </div>
@@ -33,16 +50,22 @@
@click="killProcess" @click="killProcess"
> >
<span class="d-flex"> <span class="d-flex">
<i class="mdi mdi-18px mdi-close-circle-outline text-light pr-1" /> {{ t('database.killProcess') }} <BaseIcon
icon-name="mdiCloseCircleOutline"
class="text-light mt-1 mr-1"
:size="18"
/> {{ t('database.killProcess') }}
</span> </span>
</div> </div>
</BaseContextMenu> </BaseContextMenu>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import BaseContextMenu from '@/components/BaseContextMenu.vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import BaseContextMenu from '@/components/BaseContextMenu.vue';
import BaseIcon from '@/components/BaseIcon.vue';
const { t } = useI18n(); const { t } = useI18n();
const props = defineProps({ const props = defineProps({

View File

@@ -24,7 +24,11 @@
> >
<template #header> <template #header>
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-information-outline mr-1" /> {{ t('database.processInfo') }} <BaseIcon
icon-name="mdiInformationOutline"
:size="24"
class="mr-1"
/> {{ t('database.processInfo') }}
</div> </div>
</template> </template>
<template #body> <template #body>
@@ -46,10 +50,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { Ref, ref } from 'vue'; import { Ref, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import ConfirmModal from '@/components/BaseConfirmModal.vue'; import ConfirmModal from '@/components/BaseConfirmModal.vue';
import BaseIcon from '@/components/BaseIcon.vue';
import TextEditor from '@/components/BaseTextEditor.vue'; import TextEditor from '@/components/BaseTextEditor.vue';
import { useFilters } from '@/composables/useFilters'; import { useFilters } from '@/composables/useFilters';
import { useI18n } from 'vue-i18n';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -6,7 +6,11 @@
<div class="modal-header pl-2"> <div class="modal-header pl-2">
<div class="modal-title h6"> <div class="modal-title h6">
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-cog mr-1" /> <BaseIcon
icon-name="mdiCog"
class="mr-1"
:size="24"
/>
<span class="cut-text">{{ t('application.settings') }}</span> <span class="cut-text">{{ t('application.settings') }}</span>
</div> </div>
</div> </div>
@@ -37,6 +41,13 @@
> >
<a class="tab-link">{{ t('application.shortcuts') }}</a> <a class="tab-link">{{ t('application.shortcuts') }}</a>
</li> </li>
<li
class="tab-item c-hand"
:class="{'active': selectedTab === 'data'}"
@click="selectTab('data')"
>
<a class="tab-link">{{ t('application.data') }}</a>
</li>
<li <li
v-if="updateStatus !== 'disabled'" v-if="updateStatus !== 'disabled'"
class="tab-item c-hand" class="tab-item c-hand"
@@ -71,7 +82,11 @@
<div class="form-group column col-12"> <div class="form-group column col-12">
<div class="col-5 col-sm-12"> <div class="col-5 col-sm-12">
<label class="form-label"> <label class="form-label">
<i class="mdi mdi-18px mdi-translate mr-1" /> <BaseIcon
icon-name="mdiTranslate"
class="mr-1"
:size="18"
/>
{{ t('application.language') }} {{ t('application.language') }}
</label> </label>
</div> </div>
@@ -267,7 +282,11 @@
> >
<img :src="darkPreview" class="img-responsive img-fit-cover s-rounded"> <img :src="darkPreview" class="img-responsive img-fit-cover s-rounded">
<div class="theme-name text-light"> <div class="theme-name text-light">
<i class="mdi mdi-moon-waning-crescent mdi-48px" /> <BaseIcon
icon-name="mdiMoonWaningCrescent"
class="mr-1"
:size="48"
/>
<div class="h6 mt-4"> <div class="h6 mt-4">
{{ t('application.dark') }} {{ t('application.dark') }}
</div> </div>
@@ -280,7 +299,11 @@
> >
<img :src="lightPreview" class="img-responsive img-fit-cover s-rounded"> <img :src="lightPreview" class="img-responsive img-fit-cover s-rounded">
<div class="theme-name text-dark"> <div class="theme-name text-dark">
<i class="mdi mdi-white-balance-sunny mdi-48px" /> <BaseIcon
icon-name="mdiWhiteBalanceSunny"
class="mr-1"
:size="48"
/>
<div class="h6 mt-4"> <div class="h6 mt-4">
{{ t('application.light') }} {{ t('application.light') }}
</div> </div>
@@ -366,6 +389,9 @@
<div v-show="selectedTab === 'shortcuts'" class="panel-body py-4"> <div v-show="selectedTab === 'shortcuts'" class="panel-body py-4">
<ModalSettingsShortcuts /> <ModalSettingsShortcuts />
</div> </div>
<div v-show="selectedTab === 'data'" class="panel-body py-4">
<ModalSettingsData />
</div>
<div v-show="selectedTab === 'update'" class="panel-body py-4"> <div v-show="selectedTab === 'update'" class="panel-body py-4">
<ModalSettingsUpdate /> <ModalSettingsUpdate />
</div> </div>
@@ -379,7 +405,39 @@
<h4>{{ appName }}</h4> <h4>{{ appName }}</h4>
<p class="mb-2"> <p class="mb-2">
{{ t('general.version') }} {{ appVersion }}<br> {{ t('general.version') }} {{ appVersion }}<br>
<a class="c-hand" @click="openOutside('https://github.com/antares-sql/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> <a
class="c-hand"
:style="'align-items: center; display: inline-flex;'"
@click="openOutside('https://github.com/antares-sql/antares')"
><BaseIcon
icon-name="mdiGithub"
class="d-inline mr-1"
:size="16"
/> GitHub</a> <a
class="c-hand"
:style="'align-items: center; display: inline-flex;'"
@click="openOutside('https://fosstodon.org/@AntaresSQL')"
><BaseIcon
icon-name="mdiMastodon"
class="d-inline mr-1"
:size="16"
/> Mastodon</a> <a
class="c-hand"
:style="'align-items: center; display: inline-flex;'"
@click="openOutside('https://twitter.com/AntaresSQL')"
><BaseIcon
icon-name="mdiTwitter"
class="d-inline mr-1"
:size="16"
/> Twitter</a> <a
class="c-hand"
:style="'align-items: center; display: inline-flex;'"
@click="openOutside('https://antares-sql.app/')"
><BaseIcon
icon-name="mdiWeb"
class="d-inline mr-1"
:size="16"
/> Website</a><br>
<small>{{ t('general.author') }} <a class="c-hand" @click="openOutside('https://github.com/Fabio286')">{{ appAuthor }}</a></small><br> <small>{{ t('general.author') }} <a class="c-hand" @click="openOutside('https://github.com/Fabio286')">{{ appAuthor }}</a></small><br>
</p> </p>
<div class="mb-2"> <div class="mb-2">
@@ -399,21 +457,24 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onBeforeUnmount, Ref, ref, computed } from 'vue';
import { shell } from 'electron'; import { shell } from 'electron';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import BaseSelect from '@/components/BaseSelect.vue';
import BaseTextEditor from '@/components/BaseTextEditor.vue';
import ModalSettingsChangelog from '@/components/ModalSettingsChangelog.vue';
import ModalSettingsData from '@/components/ModalSettingsData.vue';
import ModalSettingsShortcuts from '@/components/ModalSettingsShortcuts.vue';
import ModalSettingsUpdate from '@/components/ModalSettingsUpdate.vue';
import { useFocusTrap } from '@/composables/useFocusTrap';
import { AvailableLocale } from '@/i18n';
import { localesNames } from '@/i18n/supported-locales';
import { useApplicationStore } from '@/stores/application'; import { useApplicationStore } from '@/stores/application';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
import { useFocusTrap } from '@/composables/useFocusTrap';
import { localesNames } from '@/i18n/supported-locales';
import ModalSettingsUpdate from '@/components/ModalSettingsUpdate.vue';
import ModalSettingsChangelog from '@/components/ModalSettingsChangelog.vue';
import ModalSettingsShortcuts from '@/components/ModalSettingsShortcuts.vue';
import BaseTextEditor from '@/components/BaseTextEditor.vue';
import BaseSelect from '@/components/BaseSelect.vue';
import { AvailableLocale } from '@/i18n';
const { t } = useI18n(); const { t } = useI18n();
@@ -648,10 +709,14 @@ onBeforeUnmount(() => {
.modal-body { .modal-body {
overflow: hidden; overflow: hidden;
.tab-link { .tab-item {
overflow: hidden; max-width: 20%;
white-space: nowrap;
text-overflow: ellipsis; .tab-link {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
} }
.panel-body { .panel-body {

View File

@@ -8,17 +8,19 @@
/> />
<div v-if="isError" class="empty"> <div v-if="isError" class="empty">
<div class="empty-icon"> <div class="empty-icon">
<i class="mdi mdi-48px mdi-alert-outline" /> <BaseIcon icon-name="mdiAlertOutline" :size="48" />
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { shell } from 'electron';
import { marked } from 'marked'; import { marked } from 'marked';
import { ref } from 'vue';
import BaseIcon from '@/components/BaseIcon.vue';
import BaseLoader from '@/components/BaseLoader.vue'; import BaseLoader from '@/components/BaseLoader.vue';
import { useApplicationStore } from '@/stores/application'; import { useApplicationStore } from '@/stores/application';
import { ref } from 'vue';
import { shell } from 'electron';
const { appVersion } = useApplicationStore(); const { appVersion } = useApplicationStore();

View File

@@ -0,0 +1,69 @@
<template>
<div class="container">
<div class="columns">
<div class="column col-12 h6 text-uppercase mb-2">
{{ t('application.exportData') }}
</div>
<div class="column col-12">
{{ t('application.exportDataExplanation') }}
</div>
<div class="column col-12 text-right">
<button
class="btn btn-primary d-inline-flex"
@click="isExportModal=true"
>
<BaseIcon
icon-name="mdiTrayArrowUp"
class="mr-2"
:size="24"
/>
<span>{{ t('application.exportData') }}</span>
</button>
</div>
</div>
<div class="columns mt-4 mb-2">
<div class="column col-12 h6 text-uppercase mb-2 mt-4">
{{ t('application.importData') }}
</div>
<div class="column col-12">
{{ t('application.importDataExplanation') }}
</div>
<div class="column col-12 text-right">
<button
class="btn btn-dark d-inline-flex ml-auto"
@click="isImportModal=true"
>
<BaseIcon
icon-name="mdiTrayArrowDown"
class="mr-2"
:size="24"
/>
<span>{{ t('application.importData') }}</span>
</button>
</div>
</div>
<ModalSettingsDataExport
v-if="isExportModal"
@close="isExportModal = false"
/>
<ModalSettingsDataImport
v-if="isImportModal"
@close="isImportModal = false"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import ModalSettingsDataExport from '@/components/ModalSettingsDataExport.vue';
import ModalSettingsDataImport from '@/components/ModalSettingsDataImport.vue';
const { t } = useI18n();
const isExportModal = ref(false);
const isImportModal = ref(false);
</script>

View File

@@ -0,0 +1,347 @@
<template>
<Teleport to="#window-content">
<div class="modal active">
<a class="modal-overlay" @click.stop="closeModal" />
<div ref="trapRef" class="modal-container p-0">
<div class="modal-header pl-2">
<div class="modal-title h6">
<div class="d-flex">
<BaseIcon
icon-name="mdiTrayArrowUp"
class="mr-1"
:size="24"
/> {{ t('application.exportData') }}
</div>
</div>
<a class="btn btn-clear c-hand" @click.stop="closeModal" />
</div>
<div class="modal-body pb-0">
<div class="columns export-options">
<div class="column col-8 left">
<div class="workspace-query-results" :style="'min-height: 300px;'">
<div ref="table" class="table table-hover">
<div class="thead">
<div class="tr text-center">
<div class="th no-border" :style="'width:50%'" />
<div class="th no-border" />
<div class="th no-border">
<label
class="form-checkbox m-0 px-2 form-inline"
@click.prevent="toggleAllConnections()"
>
<input
type="checkbox"
:indeterminate="includeConnectionStatus === 2"
:checked="!!includeConnectionStatus"
>
<i class="form-icon" />
</label>
</div>
</div>
<div class="tr">
<div class="th">
<div class="table-column-title">
<span>{{ t('connection.connectionName') }}</span>
</div>
</div>
<div class="th">
<div class="table-column-title">
<span>{{ t('connection.client') }}</span>
</div>
</div>
<div class="th text-center">
<div class="table-column-title">
<span>{{ t('general.include') }}</span>
</div>
</div>
</div>
</div>
<div class="tbody">
<div
v-for="(item, i) in connections"
:key="i"
class="tr"
>
<div class="td">
{{ getConnectionName(item.uid) }}
</div>
<div class="td">
{{ item.client }}
</div>
<div class="td text-center">
<label class="form-checkbox m-0 px-2 form-inline">
<input v-model="connectionToggles[item.uid]" type="checkbox">
<i class="form-icon" />
</label>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="column col-4">
<h5 class="h5">
{{ t('general.options') }}
</h5>
<label class="form-checkbox">
<input v-model="options.includes.passwords" type="checkbox">
<i class="form-icon" />
{{ t(`application.includeConnectionPasswords`) }}
</label>
<label class="form-checkbox">
<input v-model="options.includes.folders" type="checkbox">
<i class="form-icon" />
{{ t(`application.includeFolders`) }}
</label>
<div class="h6 mt-4 mb-2">
{{ t('application.encryptionPassword') }}
</div>
<fieldset class="form-group" :class="{'has-error': isPasswordError}">
<div class="input-group">
<input
ref="passkey"
v-model="options.passkey"
:type="isPasswordVisible ? 'text' : 'password'"
class="form-input"
:placeholder="t('application.required')"
>
<button
type="button"
class="btn btn-link input-group-addon"
@click="isPasswordVisible = !isPasswordVisible"
>
<BaseIcon
v-if="isPasswordVisible"
icon-name="mdiEye"
class="mt-1 mx-1"
:size="16"
/>
<BaseIcon
v-else
icon-name="mdiEyeOff"
class="mt-1 mx-1"
:size="16"
/>
</button>
</div>
<span v-if="isPasswordError" class="form-input-hint">
{{ t('application.encryptionPasswordError') }}
</span>
</fieldset>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-link mr-2" @click.stop="closeModal">
{{ t('general.close') }}
</button>
<button
class="btn btn-primary mr-2"
autofocus
@click.prevent="exportData()"
>
{{ t('database.export') }}
</button>
</div>
</div>
</div>
</Teleport>
</template>
<script setup lang="ts">
import { ConnectionParams } from 'common/interfaces/antares';
import { encrypt } from 'common/libs/encrypter';
import { uidGen } from 'common/libs/uidGen';
import * as moment from 'moment';
import { storeToRefs } from 'pinia';
import { computed, onBeforeUnmount, Ref, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import { useFocusTrap } from '@/composables/useFocusTrap';
import { unproxify } from '@/libs/unproxify';
import { SidebarElement, useConnectionsStore } from '@/stores/connections';
const { t } = useI18n();
const emit = defineEmits(['close']);
const { trapRef } = useFocusTrap();
const { getConnectionName } = useConnectionsStore();
const { connectionsOrder, connections } = storeToRefs(useConnectionsStore());
const localConnections = unproxify<ConnectionParams[]>(connections.value);
const localConnectionsOrder = unproxify<SidebarElement[]>(connectionsOrder.value);
const isPasswordVisible = ref(false);
const isPasswordError = ref(false);
const connectionToggles: Ref<{[k:string]: boolean}> = ref({});
const options = ref({
passkey: '',
includes: {
passwords: true,
folders: true
}
});
const filename = computed(() => {
const date = moment().format('YYYY-MM-DD');
return `backup_${date}`;
});
const includeConnectionStatus = computed(() => {
if (Object.values(connectionToggles.value).every(item => item)) return 1;
else if (Object.values(connectionToggles.value).some(item => item)) return 2;
else return 0;
});
const exportData = () => {
if (options.value.passkey.length < 8)
isPasswordError.value = true;
else {
isPasswordError.value = false;
const connectionsToInclude: string[] = [];
const connectionsUidMap = new Map<string, string>();
for (const cUid in connectionToggles.value)
if (connectionToggles.value[cUid]) connectionsToInclude.push(cUid);
let filteredConnections = unproxify<typeof localConnections>(localConnections.filter(conn => connectionsToInclude.includes(conn.uid)));
filteredConnections = filteredConnections.map(c => {
const newUid = uidGen('C');
connectionsUidMap.set(c.uid, newUid);
c.uid = newUid;
return c;
});
if (!options.value.includes.passwords) { // Remove passwords and set ask:true
filteredConnections.map(c => {
if (c.password) {
c.password = '';
c.ask = true;
}
return c;
});
}
let filteredOrders = [];
for (const [oldVal, newVal] of connectionsUidMap) {
const connOrder = unproxify(localConnectionsOrder.find(c => c.uid === oldVal));
connOrder.uid = newVal;
filteredOrders.push(connOrder);
}
if (options.value.includes.folders) { // Includes folders
const oldConnUids = Array.from(connectionsUidMap.keys());
const newConnUids = Array.from(connectionsUidMap.values());
const foldersToInclude = unproxify(localConnectionsOrder).filter(f => (
f.isFolder && oldConnUids.some(uid => f.connections.includes(uid))
)).map(f => {
f.uid = uidGen('F');
f.connections = f.connections
.map(fc => connectionsUidMap.get(fc))
.filter(fc => newConnUids.includes(fc));
return f;
});
filteredOrders = [...filteredOrders, ...foldersToInclude];
}
const exportObj = encrypt(JSON.stringify({
connections: filteredConnections,
connectionsOrder: filteredOrders
}), options.value.passkey);
// console.log(exportObj, JSON.parse(decrypt(exportObj, options.value.passkey)));
const blobContent = Buffer.from(JSON.stringify(exportObj), 'utf-8').toString('hex');
const file = new Blob([blobContent], { type: 'application/octet-stream' });
const downloadLink = document.createElement('a');
downloadLink.download = `${filename.value}.antares`;
downloadLink.href = window.URL.createObjectURL(file);
downloadLink.style.display = 'none';
document.body.appendChild(downloadLink);
downloadLink.click();
downloadLink.remove();
closeModal();
}
};
const closeModal = () => {
emit('close');
};
const onKey = (e: KeyboardEvent) => {
e.stopPropagation();
if (e.key === 'Escape')
closeModal();
};
const toggleAllConnections = () => {
if (includeConnectionStatus.value !== 1) {
connectionToggles.value = localConnections.reduce((acc, curr) => {
acc[curr.uid] = true;
return acc;
}, {} as {[k:string]: boolean});
}
else {
connectionToggles.value = localConnections.reduce((acc, curr) => {
acc[curr.uid] = false;
return acc;
}, {} as {[k:string]: boolean});
}
};
connectionToggles.value = localConnections.reduce((acc, curr) => {
acc[curr.uid] = true;
return acc;
}, {} as {[k:string]: boolean});
window.addEventListener('keydown', onKey);
onBeforeUnmount(() => {
window.removeEventListener('keydown', onKey);
});
</script>
<style lang="scss" scoped>
.export-options {
flex: 1;
overflow: hidden;
.left {
display: flex;
flex-direction: column;
flex: 1;
}
}
.workspace-query-results {
flex: 1 0 1px;
.table {
width: 100% !important;
}
.form-checkbox {
min-height: 0.8rem;
padding: 0;
.form-icon {
top: 0.1rem;
}
}
}
.modal {
.modal-container {
max-width: 800px;
}
.modal-body {
max-height: 60vh;
display: flex;
flex-direction: column;
}
}
</style>

View File

@@ -0,0 +1,284 @@
<template>
<Teleport to="#window-content">
<div class="modal modal-sm active">
<a class="modal-overlay" @click.stop="closeModal" />
<div ref="trapRef" class="modal-container p-0">
<div class="modal-header pl-2">
<div class="modal-title h6">
<div class="d-flex">
<BaseIcon
icon-name="mdiTrayArrowDown"
class="mr-1"
:size="24"
/> {{ t('application.importData') }}
</div>
</div>
<a class="btn btn-clear c-hand" @click.stop="closeModal" />
</div>
<div class="modal-body pb-0">
<div class="mb-2">
<div class="h6 mb-2">
{{ t('application.choseFile') }}
</div>
<BaseUploadInput
:model-value="filePath"
:message="t('general.browse')"
accept=".antares"
@clear="clearPath"
@change="filesChange($event)"
/>
</div>
<div class="mb-2">
<div class="h6 mb-2">
{{ t('application.password') }}
</div>
<fieldset class="form-group" :class="{'has-error': isPasswordError}">
<div class="input-group">
<input
ref="passkey"
v-model="options.passkey"
:type="isPasswordVisible ? 'text' : 'password'"
class="form-input"
:placeholder="t('application.required')"
>
<button
type="button"
class="btn btn-link input-group-addon"
@click="isPasswordVisible = !isPasswordVisible"
>
<BaseIcon
v-if="isPasswordVisible"
icon-name="mdiEye"
class="mt-1 mx-1"
:size="16"
/>
<BaseIcon
v-else
icon-name="mdiEyeOff"
class="mt-1 mx-1"
:size="16"
/>
</button>
</div>
<span v-if="isPasswordError" class="form-input-hint">
{{ t('application.encryptionPasswordError') }}
</span>
</fieldset>
</div>
<div class="mb-2">
<label class="form-checkbox">
<input v-model="options.ignoreDuplicates" type="checkbox">
<i class="form-icon" />
{{ t(`application.ignoreDuplicates`) }}
</label>
</div>
</div>
<div class="modal-footer">
<button
class="btn btn-link mr-2"
@click.stop="closeModal"
>
{{ t('general.close') }}
</button>
<button
class="btn btn-primary mr-2"
:disabled="!filePath"
@click.prevent="importData()"
>
{{ t('database.import') }}
</button>
</div>
</div>
</div>
</Teleport>
</template>
<script setup lang="ts">
import { ConnectionParams } from 'common/interfaces/antares';
import { decrypt } from 'common/libs/encrypter';
import { storeToRefs } from 'pinia';
import { onBeforeUnmount, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import BaseUploadInput from '@/components/BaseUploadInput.vue';
import { unproxify } from '@/libs/unproxify';
import { SidebarElement, useConnectionsStore } from '@/stores/connections';
import { useNotificationsStore } from '@/stores/notifications';
const { t } = useI18n();
const emit = defineEmits(['close']);
const { addNotification } = useNotificationsStore();
const connectionsStore = useConnectionsStore();
const { importConnections } = connectionsStore;
const { connections } = storeToRefs(connectionsStore);
const filePath = ref('');
const fileContent = ref(null);
const isPasswordVisible = ref(false);
const isPasswordError = ref(false);
const options = ref({
passkey: '',
ignoreDuplicates: true
});
const closeModal = () => {
emit('close');
};
const filesChange = ({ target } : {target: HTMLInputElement }) => {
const { files } = target;
if (!files.length) return;
const reader = new FileReader();
reader.readAsText(files[0]);
reader.onload = () => {
fileContent.value = reader.result;
filePath.value = files[0].path;
};
};
const clearPath = () => {
filePath.value = '';
fileContent.value = null;
};
const importData = () => {
if (options.value.passkey.length < 8)
isPasswordError.value = true;
else {
try {
const hash = JSON.parse(Buffer.from(fileContent.value, 'hex').toString('utf-8'));
try {
const importObj: {
connections: ConnectionParams[];
connectionsOrder: SidebarElement[];
} = JSON.parse(decrypt(hash, options.value.passkey));
if (options.value.ignoreDuplicates) {
const actualConnections = unproxify(connections.value).map(c => {
delete c.uid;
delete c.name;
delete c.password;
delete c.ask;
delete c.key;
delete c.cert;
delete c.ca;
delete c.sshKey;
return JSON.stringify(c);
});
const incomingConnections = unproxify<ConnectionParams[]>(importObj.connections).map(c => {
const uid = c.uid;
delete c.uid;
delete c.name;
delete c.password;
delete c.ask;
delete c.key;
delete c.cert;
delete c.ca;
delete c.sshKey;
return { uid, jsonString: JSON.stringify(c) };
});
const newConnectionsUid = incomingConnections
.filter(c => !actualConnections.includes(c.jsonString))
.reduce((acc, cur) => {
acc.push(cur.uid);
return acc;
}, [] as string[]);
importObj.connections = importObj.connections.filter(c => newConnectionsUid.includes(c.uid));
importObj.connectionsOrder = importObj.connectionsOrder
.filter(c => newConnectionsUid
.includes(c.uid) ||
(c.isFolder && c.connections.every(c => newConnectionsUid.includes(c))));
}
importConnections(importObj);
addNotification({
status: 'success',
message: t('application.dataImportSuccess')
});
closeModal();
}
catch (error) {
addNotification({
status: 'error',
message: t('application.wrongImportPassword')
});
}
}
catch (error) {
addNotification({
status: 'error',
message: t('application.wrongFileFormat')
});
}
}
};
const onKey = (e: KeyboardEvent) => {
e.stopPropagation();
if (e.key === 'Escape')
closeModal();
};
window.addEventListener('keydown', onKey);
onBeforeUnmount(() => {
window.removeEventListener('keydown', onKey);
});
</script>
<style lang="scss" scoped>
.export-options {
flex: 1;
overflow: hidden;
.left {
display: flex;
flex-direction: column;
flex: 1;
}
}
.workspace-query-results {
flex: 1 0 1px;
.table {
width: 100% !important;
}
.form-checkbox {
min-height: 0.8rem;
padding: 0;
.form-icon {
top: 0.1rem;
}
}
}
.modal {
.modal-body {
max-height: 60vh;
display: flex;
flex-direction: column;
}
}
</style>

View File

@@ -2,10 +2,18 @@
<div class="p-relative"> <div class="p-relative">
<div class="shortcuts-tools pb-2 px-2"> <div class="shortcuts-tools pb-2 px-2">
<button class="btn btn-dark btn-sm d-flex ml-2" @click="showAddModal"> <button class="btn btn-dark btn-sm d-flex ml-2" @click="showAddModal">
<i class="mdi mdi-24px mdi-plus mr-1" /><span>{{ t('application.addShortcut') }}</span> <BaseIcon
icon-name="mdiPlus"
class="mr-1"
:size="24"
/><span>{{ t('application.addShortcut') }}</span>
</button> </button>
<button class="btn btn-dark btn-sm d-flex ml-2" @click="isConfirmRestoreModal = true"> <button class="btn btn-dark btn-sm d-flex ml-2" @click="isConfirmRestoreModal = true">
<i class="mdi mdi-24px mdi-undo mr-1" /><span>{{ t('application.restoreDefaults') }}</span> <BaseIcon
icon-name="mdiUndo"
class="mr-1"
:size="24"
/><span>{{ t('application.restoreDefaults') }}</span>
</button> </button>
</div> </div>
<div class="container workspace-query-results"> <div class="container workspace-query-results">
@@ -43,10 +51,20 @@
/> />
<div class="td py-1 pr-2"> <div class="td py-1 pr-2">
<button class="shortcut-button btn btn-link btn-sm d-flex p-0 px-1 mr-2" @click="showEditModal({...shortcut, index: i})"> <button class="shortcut-button btn btn-link btn-sm d-flex p-0 px-1 mr-2" @click="showEditModal({...shortcut, index: i})">
<span>{{ t('general.edit') }}</span><i class="mdi mdi-pencil ml-1" /> <span>{{ t('general.edit') }}</span>
<BaseIcon
icon-name="mdiPencil"
class="ml-1"
:size="16"
/>
</button> </button>
<button class="shortcut-button btn btn-link btn-sm d-flex p-0 px-1" @click="showDeleteModal(shortcut)"> <button class="shortcut-button btn btn-link btn-sm d-flex p-0 px-1" @click="showDeleteModal(shortcut)">
<span>{{ t('general.delete') }}</span><i class="mdi mdi-delete-outline ml-1" /> <span>{{ t('general.delete') }}</span>
<BaseIcon
icon-name="mdiDeleteOutline"
class="ml-1"
:size="16"
/>
</button> </button>
</div> </div>
</div> </div>
@@ -65,7 +83,11 @@
> >
<template #header> <template #header>
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-plus mr-1" /> {{ t('application.addShortcut') }} <BaseIcon
icon-name="mdiPlus"
class="mr-1"
:size="24"
/> {{ t('application.addShortcut') }}
</div> </div>
</template> </template>
<template #body> <template #body>
@@ -99,7 +121,11 @@
> >
<template #header> <template #header>
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-plus mr-1" /> {{ t('application.editShortcut') }} <BaseIcon
icon-name="mdiPencil"
class="mr-1"
:size="24"
/> {{ t('application.editShortcut') }}
</div> </div>
</template> </template>
<template #body> <template #body>
@@ -132,7 +158,11 @@
> >
<template #header> <template #header>
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-delete mr-1" /> {{ t('application.deleteShortcut') }} <BaseIcon
icon-name="mdiDelete"
class="mr-1"
:size="24"
/> {{ t('application.deleteShortcut') }}
</div> </div>
</template> </template>
<template #body> <template #body>
@@ -150,7 +180,11 @@
> >
<template #header> <template #header>
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-undo mr-1" /> {{ t('application.restoreDefaults') }} <BaseIcon
icon-name="mdiUndo"
class="mr-1"
:size="24"
/> {{ t('application.restoreDefaults') }}
</div> </div>
</template> </template>
<template #body> <template #body>
@@ -162,17 +196,20 @@
</Teleport> </Teleport>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Ref, ref, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { useSettingsStore } from '@/stores/settings';
import KeyPressDetector from './KeyPressDetector.vue';
import Application from '@/ipc-api/Application';
import { shortcutEvents, ShortcutRecord } from 'common/shortcuts';
import ConfirmModal from '@/components/BaseConfirmModal.vue';
import BaseSelect from '@/components/BaseSelect.vue';
import { computed } from '@vue/reactivity'; import { computed } from '@vue/reactivity';
import { shortcutEvents, ShortcutRecord } from 'common/shortcuts';
import { storeToRefs } from 'pinia';
import { Ref, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import ConfirmModal from '@/components/BaseConfirmModal.vue';
import BaseIcon from '@/components/BaseIcon.vue';
import BaseSelect from '@/components/BaseSelect.vue';
import { useFilters } from '@/composables/useFilters'; import { useFilters } from '@/composables/useFilters';
import Application from '@/ipc-api/Application';
import { useSettingsStore } from '@/stores/settings';
import KeyPressDetector from './KeyPressDetector.vue';
const { parseKeys } = useFilters(); const { parseKeys } = useFilters();

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="empty"> <div class="empty">
<div class="empty-icon"> <div class="empty-icon">
<i class="mdi mdi-48px mdi-cloud-download" /> <BaseIcon icon-name="mdiCloudDownload" :size="48" />
</div> </div>
<p class="empty-title h5"> <p class="empty-title h5">
{{ updateMessage }} {{ updateMessage }}
@@ -53,10 +53,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { ipcRenderer, shell } from 'electron'; import { ipcRenderer, shell } from 'electron';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import { useApplicationStore } from '@/stores/application'; import { useApplicationStore } from '@/stores/application';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';

View File

@@ -9,16 +9,20 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, Prop, Ref, ref, toRef, watch } from 'vue'; /* eslint-disable simple-import-sort/imports */
import * as ace from 'ace-builds'; import * as ace from 'ace-builds';
import 'ace-builds/webpack-resolver';
import '../libs/ext-language_tools'; import '../libs/ext-language_tools';
import { storeToRefs } from 'pinia'; import 'ace-builds/webpack-resolver';
/* eslint-enable simple-import-sort/imports */
import { uidGen } from 'common/libs/uidGen'; import { uidGen } from 'common/libs/uidGen';
import { storeToRefs } from 'pinia';
import { computed, onMounted, Prop, Ref, ref, toRef, watch } from 'vue';
import Tables from '@/ipc-api/Tables';
import { useApplicationStore } from '@/stores/application'; import { useApplicationStore } from '@/stores/application';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { Workspace } from '@/stores/workspaces'; import { Workspace } from '@/stores/workspaces';
import Tables from '@/ipc-api/Tables';
const editor: Ref<ace.Ace.Editor> = ref(null); const editor: Ref<ace.Ace.Editor> = ref(null);
const applicationStore = useApplicationStore(); const applicationStore = useApplicationStore();
@@ -399,11 +403,6 @@ defineExpose({ editor });
} }
} }
.ace_.mdi {
display: inline-block;
width: 17px;
}
.ace_gutter-cell.ace_breakpoint { .ace_gutter-cell.ace_breakpoint {
&::before { &::before {
content: '\F0403'; content: '\F0403';

View File

@@ -41,12 +41,28 @@
@dragleave="coveredElement = false" @dragleave="coveredElement = false"
@change="createFolder" @change="createFolder"
/> />
<i v-if="coveredElement === element.uid && draggedElement !== coveredElement" class="settingbar-element-icon mdi mdi-folder-plus mdi-36px" /> <BaseIcon
v-if="coveredElement === element.uid && draggedElement !== coveredElement"
class="settingbar-element-icon"
icon-name="mdiFolderPlus"
:size="36"
/>
<template v-else> <template v-else>
<div class="settingbar-element-icon-wrapper"> <div class="settingbar-element-icon-wrapper">
<i <div
v-if="element.icon"
class="settingbar-element-icon"
:class="[getStatusBadge(element.uid)]"
>
<BaseIcon
:icon-name="camelize(element.icon)"
:size="36"
/>
</div>
<div
v-else
class="settingbar-element-icon dbi" class="settingbar-element-icon dbi"
:class="[element.icon ? `mdi ${element.icon} mdi-36px`: `dbi-${element.client}`, getStatusBadge(element.uid)]" :class="[`dbi-${element.client}`, getStatusBadge(element.uid)]"
/> />
<small class="settingbar-element-name">{{ element.name || getConnectionName(element.uid) }}</small> <small class="settingbar-element-name">{{ element.name || getConnectionName(element.uid) }}</small>
</div> </div>
@@ -71,12 +87,14 @@
</Draggable> </Draggable>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, PropType, Ref, ref, watch } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { computed, PropType, Ref, ref, watch } from 'vue';
import * as Draggable from 'vuedraggable'; import * as Draggable from 'vuedraggable';
import BaseIcon from '@/components/BaseIcon.vue';
import SettingBarConnectionsFolder from '@/components/SettingBarConnectionsFolder.vue';
import { SidebarElement, useConnectionsStore } from '@/stores/connections'; import { SidebarElement, useConnectionsStore } from '@/stores/connections';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
import SettingBarConnectionsFolder from '@/components/SettingBarConnectionsFolder.vue';
const workspacesStore = useWorkspacesStore(); const workspacesStore = useWorkspacesStore();
const connectionsStore = useConnectionsStore(); const connectionsStore = useConnectionsStore();
@@ -147,6 +165,16 @@ const getStatusBadge = (uid: string) => {
} }
}; };
const camelize = (text: string) => {
const textArr = text.split('-');
for (let i = 0; i < textArr.length; i++) {
if (i === 0) continue;
textArr[i] = textArr[i].charAt(0).toUpperCase() + textArr[i].slice(1);
}
return textArr.join('');
};
watch(() => dummyNested.value.length, () => { watch(() => dummyNested.value.length, () => {
dummyNested.value = []; dummyNested.value = [];
}); });

View File

@@ -38,8 +38,16 @@
:style="`color: ${folder.color};`" :style="`color: ${folder.color};`"
@click="closeFolder" @click="closeFolder"
> >
<i class="folder-icon-open mdi mdi-folder-open mdi-36px" /> <BaseIcon
<i class="folder-icon-close mdi mdi-folder mdi-36px" /> class="folder-icon-open"
icon-name="mdiFolderOpen"
:size="36"
/>
<BaseIcon
class="folder-icon-close"
icon-name="mdiFolder"
:size="36"
/>
</div> </div>
</template> </template>
<template #item="{ element }"> <template #item="{ element }">
@@ -55,9 +63,20 @@
@click="emit('select-workspace', element)" @click="emit('select-workspace', element)"
@contextmenu.stop="emit('context', {event: $event, content: getConnectionOrderByUid(element)})" @contextmenu.stop="emit('context', {event: $event, content: getConnectionOrderByUid(element)})"
> >
<i <div
v-if="getConnectionOrderByUid(element).icon"
class="folder-element-icon"
:class="[getStatusBadge(element)]"
>
<BaseIcon
:icon-name="camelize(getConnectionOrderByUid(element).icon)"
:size="36"
/>
</div>
<div
v-else
class="folder-element-icon dbi" class="folder-element-icon dbi"
:class="[getConnectionOrderByUid(element)?.icon ? `mdi ${getConnectionOrderByUid(element).icon}`: `dbi-${getConnectionOrderByUid(element)?.client}`, getStatusBadge(element)]" :class="[`dbi-${getConnectionOrderByUid(element).client}`, getStatusBadge(element)]"
/> />
<small v-if="isOpen" class="folder-element-name">{{ getConnectionOrderByUid(element)?.name || getConnectionName(element) }}</small> <small v-if="isOpen" class="folder-element-name">{{ getConnectionOrderByUid(element)?.name || getConnectionName(element) }}</small>
</div> </div>
@@ -76,12 +95,14 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, PropType, ref, watch } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { computed, PropType, ref, watch } from 'vue';
import * as Draggable from 'vuedraggable'; import * as Draggable from 'vuedraggable';
import BaseIcon from '@/components/BaseIcon.vue';
import SettingBarConnections from '@/components/SettingBarConnections.vue';
import { SidebarElement, useConnectionsStore } from '@/stores/connections'; import { SidebarElement, useConnectionsStore } from '@/stores/connections';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
import SettingBarConnections from '@/components/SettingBarConnections.vue';
const workspacesStore = useWorkspacesStore(); const workspacesStore = useWorkspacesStore();
const connectionsStore = useConnectionsStore(); const connectionsStore = useConnectionsStore();
@@ -176,6 +197,16 @@ const dragStop = () => {
emit('folder-drag', false); emit('folder-drag', false);
}; };
const camelize = (text: string) => {
const textArr = text.split('-');
for (let i = 0; i < textArr.length; i++) {
if (i === 0) continue;
textArr[i] = textArr[i].charAt(0).toUpperCase() + textArr[i].slice(1);
}
return textArr.join('');
};
watch(() => dummyNested.value.length, () => { watch(() => dummyNested.value.length, () => {
dummyNested.value = []; dummyNested.value = [];
}); });
@@ -388,7 +419,8 @@ emit('folder-sort');// To apply changes on component key change
&:not(.opened){ &:not(.opened){
.folder-element { .folder-element {
.folder-element-icon { .folder-element-icon,
.folder-element-icon svg {
width: 21px; width: 21px;
height: 21px; height: 21px;
font-size: 16px; font-size: 16px;

View File

@@ -8,20 +8,40 @@
class="context-element" class="context-element"
@click="disconnect" @click="disconnect"
> >
<span class="d-flex"><i class="mdi mdi-18px mdi-power text-light pr-1" /> {{ t('connection.disconnect') }}</span> <span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiPower"
:size="18"
/> {{ t('connection.disconnect') }}</span>
</div> </div>
<div <div
v-if="!contextConnection.isFolder" v-if="!contextConnection.isFolder"
class="context-element" class="context-element"
@click="duplicateConnection" @click="duplicateConnection"
> >
<span class="d-flex"><i class="mdi mdi-18px mdi-content-duplicate text-light pr-1" /> {{ t('general.duplicate') }}</span> <span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiContentDuplicate"
:size="18"
/> {{ t('general.duplicate') }}</span>
</div> </div>
<div class="context-element" @click.stop="showAppearanceModal"> <div class="context-element" @click.stop="showAppearanceModal">
<span class="d-flex"><i class="mdi mdi-18px mdi-brush-variant text-light pr-1" /> {{ t('application.appearance') }}</span> <span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiBrushVariant"
:size="18"
/> {{ t('application.appearance') }}</span>
</div> </div>
<div class="context-element" @click="showConfirmModal"> <div class="context-element" @click="showConfirmModal">
<span class="d-flex"><i class="mdi mdi-18px mdi-delete text-light pr-1" /> {{ t('general.delete') }}</span> <span class="d-flex">
<BaseIcon
class="text-light mt-1 mr-1"
icon-name="mdiDelete"
:size="18"
/> {{ t('general.delete') }}</span>
</div> </div>
<ConfirmModal <ConfirmModal
@@ -31,7 +51,11 @@
> >
<template #header> <template #header>
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mr-1" :class="[contextConnection.isFolder ? 'mdi-folder-remove' : 'mdi-server-remove']" /> {{ t(contextConnection.isFolder ? 'application.deleteFolder' : 'connection.deleteConnection') }} <BaseIcon
class="text-light mr-1"
:icon-name="contextConnection.isFolder ? 'mdiFolderRemove' : 'mdiServerRemove'"
:size="24"
/> {{ t(contextConnection.isFolder ? 'application.deleteFolder' : 'connection.deleteConnection') }}
</div> </div>
</template> </template>
<template #body> <template #body>
@@ -54,16 +78,17 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, Prop, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { uidGen } from 'common/libs/uidGen'; import { uidGen } from 'common/libs/uidGen';
import { computed, Prop, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import ConfirmModal from '@/components/BaseConfirmModal.vue';
import BaseContextMenu from '@/components/BaseContextMenu.vue';
import BaseIcon from '@/components/BaseIcon.vue';
import ModalConnectionAppearance from '@/components/ModalConnectionAppearance.vue';
import ModalFolderAppearance from '@/components/ModalFolderAppearance.vue';
import { SidebarElement, useConnectionsStore } from '@/stores/connections'; import { SidebarElement, useConnectionsStore } from '@/stores/connections';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
import BaseContextMenu from '@/components/BaseContextMenu.vue';
import ConfirmModal from '@/components/BaseConfirmModal.vue';
import ModalFolderAppearance from '@/components/ModalFolderAppearance.vue';
import ModalConnectionAppearance from '@/components/ModalConnectionAppearance.vue';
const { t } = useI18n(); const { t } = useI18n();
@@ -77,10 +102,8 @@ const {
} = connectionsStore; } = connectionsStore;
const workspacesStore = useWorkspacesStore(); const workspacesStore = useWorkspacesStore();
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
const { const {
selectWorkspace,
removeConnected: disconnectWorkspace, removeConnected: disconnectWorkspace,
getWorkspace getWorkspace
} = workspacesStore; } = workspacesStore;
@@ -100,8 +123,8 @@ const connectionName = computed(() => props.contextConnection.name || getConnect
const isConnected = computed(() => getWorkspace(props.contextConnection.uid)?.connectionStatus === 'connected'); const isConnected = computed(() => getWorkspace(props.contextConnection.uid)?.connectionStatus === 'connected');
const confirmDeleteConnection = () => { const confirmDeleteConnection = () => {
if (selectedWorkspace.value === props.contextConnection.uid) if (isConnected.value)
selectWorkspace(null); disconnectWorkspace(props.contextConnection.uid);
deleteConnection(props.contextConnection); deleteConnection(props.contextConnection);
closeContext(); closeContext();
}; };

View File

@@ -7,19 +7,35 @@
<div class="footer-left-elements"> <div class="footer-left-elements">
<ul class="footer-elements"> <ul class="footer-elements">
<li class="footer-element"> <li class="footer-element">
<i class="mdi mdi-18px mdi-database mr-1" /> <BaseIcon
icon-name="mdiServer"
class="mr-1"
:size="18"
/>
<small>{{ versionString }}</small> <small>{{ versionString }}</small>
</li> </li>
<li v-if="connectionInfos && connectionInfos.readonly" class="footer-element"> <li v-if="connectionInfos && connectionInfos.readonly" class="footer-element">
<i class="mdi mdi-18px mdi-lock mr-1" /> <BaseIcon
icon-name="mdiLock"
class="mr-1"
:size="18"
/>
<small>{{ t('connection.readOnlyMode') }}</small> <small>{{ t('connection.readOnlyMode') }}</small>
</li> </li>
<li v-if="connectionInfos && connectionInfos.ssl" class="footer-element"> <li v-if="connectionInfos && connectionInfos.ssl" class="footer-element">
<i class="mdi mdi-18px mdi-shield-key mr-1" /> <BaseIcon
icon-name="mdiShieldKey"
class="mr-1"
:size="18"
/>
<small>SSL</small> <small>SSL</small>
</li> </li>
<li v-if="connectionInfos && connectionInfos.ssh" class="footer-element"> <li v-if="connectionInfos && connectionInfos.ssh" class="footer-element">
<i class="mdi mdi-18px mdi-console-network mr-1" /> <BaseIcon
icon-name="mdiConsoleNetwork"
class="mr-1"
:size="18"
/>
<small>SSH</small> <small>SSH</small>
</li> </li>
</ul> </ul>
@@ -32,11 +48,19 @@
class="footer-element footer-link" class="footer-element footer-link"
@click="toggleConsole()" @click="toggleConsole()"
> >
<i class="mdi mdi-18px mdi-console-line mr-1" /> <BaseIcon
icon-name="mdiConsoleLine"
class="mr-1"
:size="18"
/>
<small>{{ t('application.console') }}</small> <small>{{ t('application.console') }}</small>
</li> </li>
<li class="footer-element footer-link" @click="openOutside('https://www.paypal.com/paypalme/fabiodistasio')"> <li class="footer-element footer-link" @click="openOutside('https://www.paypal.com/paypalme/fabiodistasio')">
<i class="mdi mdi-18px mdi-coffee mr-1" /> <BaseIcon
icon-name="mdiCoffee"
class="mr-1"
:size="18"
/>
<small>{{ t('general.donate') }}</small> <small>{{ t('general.donate') }}</small>
</li> </li>
<li <li
@@ -44,14 +68,14 @@
:title="t('application.reportABug')" :title="t('application.reportABug')"
@click="openOutside('https://github.com/antares-sql/antares/issues')" @click="openOutside('https://github.com/antares-sql/antares/issues')"
> >
<i class="mdi mdi-18px mdi-bug" /> <BaseIcon icon-name="mdiBug" :size="18" />
</li> </li>
<li <li
class="footer-element footer-link" class="footer-element footer-link"
:title="t('application.about')" :title="t('application.about')"
@click="showSettingModal('about')" @click="showSettingModal('about')"
> >
<i class="mdi mdi-18px mdi-information-outline" /> <BaseIcon icon-name="mdiInformationOutline" :size="18" />
</li> </li>
</ul> </ul>
</div> </div>
@@ -61,12 +85,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { shell } from 'electron'; import { shell } from 'electron';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { useApplicationStore } from '@/stores/application';
import { useWorkspacesStore } from '@/stores/workspaces';
import { computed, ComputedRef } from 'vue'; import { computed, ComputedRef } from 'vue';
import { useConsoleStore } from '@/stores/console'; import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import { useApplicationStore } from '@/stores/application';
import { useConnectionsStore } from '@/stores/connections'; import { useConnectionsStore } from '@/stores/connections';
import { useConsoleStore } from '@/stores/console';
import { useWorkspacesStore } from '@/stores/workspaces';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -17,11 +17,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, Ref, ref, watch } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { computed, Ref, ref, watch } from 'vue';
import BaseNotification from '@/components/BaseNotification.vue';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import BaseNotification from '@/components/BaseNotification.vue';
const notificationsStore = useNotificationsStore(); const notificationsStore = useNotificationsStore();
const settingsStore = useSettingsStore(); const settingsStore = useSettingsStore();

View File

@@ -8,7 +8,11 @@
> >
<template #header> <template #header>
<div class="d-flex"> <div class="d-flex">
<i class="mdi mdi-24px mdi-notebook-edit-outline mr-1" /> {{ t('application.scratchpad') }} <BaseIcon
icon-name="mdiNotebookEditOutline"
class="mr-1"
:size="24"
/> {{ t('application.scratchpad') }}
</div> </div>
</template> </template>
<template #body> <template #body>
@@ -29,13 +33,15 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, Ref, watch } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { Ref, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import ConfirmModal from '@/components/BaseConfirmModal.vue';
import BaseIcon from '@/components/BaseIcon.vue';
import TextEditor from '@/components/BaseTextEditor.vue';
import { useApplicationStore } from '@/stores/application'; import { useApplicationStore } from '@/stores/application';
import { useScratchpadStore } from '@/stores/scratchpad'; import { useScratchpadStore } from '@/stores/scratchpad';
import ConfirmModal from '@/components/BaseConfirmModal.vue';
import TextEditor from '@/components/BaseTextEditor.vue';
import { useI18n } from 'vue-i18n';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -28,7 +28,11 @@
@click="emit('show-connections-modal')" @click="emit('show-connections-modal')"
> >
<div class="settingbar-element-icon-wrapper"> <div class="settingbar-element-icon-wrapper">
<i class="settingbar-element-icon mdi mdi-24px mdi-dots-horizontal text-light" /> <BaseIcon
icon-name="mdiDotsHorizontal"
class="settingbar-element-icon text-light"
:size="24"
/>
</div> </div>
</li> </li>
<li <li
@@ -42,7 +46,11 @@
@click="selectWorkspace('NEW')" @click="selectWorkspace('NEW')"
> >
<div class="settingbar-element-icon-wrapper"> <div class="settingbar-element-icon-wrapper">
<i class="settingbar-element-icon mdi mdi-24px mdi-plus text-light" /> <BaseIcon
icon-name="mdiPlus"
class="settingbar-element-icon text-light"
:size="24"
/>
</div> </div>
</li> </li>
</ul> </ul>
@@ -60,7 +68,11 @@
class="settingbar-element btn btn-link" class="settingbar-element btn btn-link"
@click="showScratchpad" @click="showScratchpad"
> >
<i class="settingbar-element-icon mdi mdi-24px mdi-notebook-edit-outline text-light" /> <BaseIcon
icon-name="mdiNotebookEditOutline"
class="settingbar-element-icon text-light"
:size="24"
/>
</li> </li>
<li <li
v-tooltip="{ v-tooltip="{
@@ -71,10 +83,14 @@
class="settingbar-element btn btn-link" class="settingbar-element btn btn-link"
@click="showSettingModal('general')" @click="showSettingModal('general')"
> >
<i <div class="settingbar-element-icon-wrapper">
class="settingbar-element-icon mdi mdi-24px mdi-cog text-light" <BaseIcon
:class="{ ' badge badge-update': hasUpdates }" icon-name="mdiCog"
/> class="settingbar-element-icon text-light"
:class="{ 'badge badge-update': hasUpdates }"
:size="24"
/>
</div>
</li> </li>
</ul> </ul>
</div> </div>
@@ -82,17 +98,19 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, Ref, computed, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { useApplicationStore } from '@/stores/application';
import { useConnectionsStore, SidebarElement } from '@/stores/connections';
import { useWorkspacesStore } from '@/stores/workspaces';
import { useSettingsStore } from '@/stores/settings';
import SettingBarContext from '@/components/SettingBarContext.vue';
import SettingBarConnections from '@/components/SettingBarConnections.vue';
import { useElementBounding } from '@vueuse/core'; import { useElementBounding } from '@vueuse/core';
import { storeToRefs } from 'pinia';
import { computed, Ref, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import SettingBarConnections from '@/components/SettingBarConnections.vue';
import SettingBarContext from '@/components/SettingBarContext.vue';
import { useApplicationStore } from '@/stores/application';
import { SidebarElement, useConnectionsStore } from '@/stores/connections';
import { useSettingsStore } from '@/stores/settings';
import { useWorkspacesStore } from '@/stores/workspaces';
const { t } = useI18n(); const { t } = useI18n();
localStorage.setItem('opened-folders', '[]'); localStorage.setItem('opened-folders', '[]');
@@ -238,7 +256,7 @@ if (!connectionsArr.value.length)
border-radius: $border-radius; border-radius: $border-radius;
} }
.settingbar-element-icon-wrapper{ .settingbar-element-icon-wrapper {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;

View File

@@ -21,14 +21,14 @@
class="titlebar-element" class="titlebar-element"
@click="openDevTools" @click="openDevTools"
> >
<i class="mdi mdi-24px mdi-code-tags" /> <BaseIcon icon-name="mdiCodeTags" :size="24" />
</div> </div>
<div <div
v-if="isDevelopment" v-if="isDevelopment"
class="titlebar-element" class="titlebar-element"
@click="reload" @click="reload"
> >
<i class="mdi mdi-24px mdi-refresh" /> <BaseIcon icon-name="mdiRefresh" :size="24" />
</div> </div>
<div v-if="isWindows" :style="'width: 140px;'" /> <div v-if="isWindows" :style="'width: 140px;'" />
</div> </div>
@@ -36,13 +36,15 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onUnmounted, ref, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { getCurrentWindow } from '@electron/remote'; import { getCurrentWindow } from '@electron/remote';
import { ipcRenderer } from 'electron';
import { storeToRefs } from 'pinia';
import { computed, onUnmounted, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import { useConnectionsStore } from '@/stores/connections'; import { useConnectionsStore } from '@/stores/connections';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
import { useI18n } from 'vue-i18n';
import { ipcRenderer } from 'electron';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -40,7 +40,11 @@
class="tab-link" class="tab-link"
:class="{'badge': element.isChanged}" :class="{'badge': element.isChanged}"
> >
<i class="mdi mdi-18px mdi-code-tags mr-1" /> <BaseIcon
class="mt-1 mr-1"
icon-name="mdiCodeTags"
:size="18"
/>
<span> <span>
<span>{{ cutText(element.content || 'Query', 20, true) }} #{{ element.index }}</span> <span>{{ cutText(element.content || 'Query', 20, true) }} #{{ element.index }}</span>
<span <span
@@ -57,7 +61,11 @@
class="tab-link" class="tab-link"
@dblclick="openAsPermanentTab(element)" @dblclick="openAsPermanentTab(element)"
> >
<i class="mdi mdi-18px mr-1" :class="element.elementType === 'view' ? 'mdi-table-eye' : 'mdi-table'" /> <BaseIcon
class="mt-1 mr-1"
:icon-name="element.elementType === 'view' ? 'mdiTableEye' : 'mdiTable'"
:size="18"
/>
<span :title="`${t('general.data').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('general.data').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
<span class=" text-italic">{{ cutText(element.elementName, 20, true) }}</span> <span class=" text-italic">{{ cutText(element.elementName, 20, true) }}</span>
<span <span
@@ -70,7 +78,11 @@
</a> </a>
<a v-else-if="element.type === 'data'" class="tab-link"> <a v-else-if="element.type === 'data'" class="tab-link">
<i class="mdi mdi-18px mr-1" :class="element.elementType === 'view' ? 'mdi-table-eye' : 'mdi-table'" /> <BaseIcon
class="mt-1 mr-1"
:icon-name="element.elementType === 'view' ? 'mdiTableEye' : 'mdiTable'"
:size="18"
/>
<span :title="`${t('general.data').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('general.data').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
{{ cutText(element.elementName, 20, true) }} {{ cutText(element.elementName, 20, true) }}
<span <span
@@ -87,7 +99,11 @@
class="tab-link" class="tab-link"
:class="{'badge': element.isChanged}" :class="{'badge': element.isChanged}"
> >
<i class="mdi mdi-shape-square-plus mdi-18px mr-1" /> <BaseIcon
class="mr-1"
icon-name="mdiShapeSquarePlus"
:size="18"
/>
<span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
{{ t('database.newTable') }} {{ t('database.newTable') }}
<span <span
@@ -104,7 +120,11 @@
class="tab-link" class="tab-link"
:class="{'badge': element.isChanged}" :class="{'badge': element.isChanged}"
> >
<i class="mdi mdi-wrench-cog mdi-18px mr-1" /> <BaseIcon
class="mr-1"
icon-name="mdiWrenchCog"
:size="18"
/>
<span :title="`${t('application.settings').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('application.settings').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
{{ cutText(element.elementName, 20, true) }} {{ cutText(element.elementName, 20, true) }}
<span <span
@@ -121,7 +141,11 @@
class="tab-link" class="tab-link"
:class="{'badge': element.isChanged}" :class="{'badge': element.isChanged}"
> >
<i class="mdi mdi-wrench-cog mdi-18px mr-1" /> <BaseIcon
class="mr-1"
icon-name="mdiWrenchCog"
:size="18"
/>
<span :title="`${t('application.settings').toUpperCase()}: ${t(`database.view`)}`"> <span :title="`${t('application.settings').toUpperCase()}: ${t(`database.view`)}`">
{{ cutText(element.elementName, 20, true) }} {{ cutText(element.elementName, 20, true) }}
<span <span
@@ -138,7 +162,11 @@
class="tab-link" class="tab-link"
:class="{'badge': element.isChanged}" :class="{'badge': element.isChanged}"
> >
<i class="mdi mdi-shape-square-plus mdi-18px mr-1" /> <BaseIcon
class="mr-1"
icon-name="mdiShapeSquarePlus"
:size="18"
/>
<span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
{{ t('database.newView') }} {{ t('database.newView') }}
<span <span
@@ -155,7 +183,11 @@
class="tab-link" class="tab-link"
:class="{'badge': element.isChanged}" :class="{'badge': element.isChanged}"
> >
<i class="mdi mdi-shape-square-plus mdi-18px mr-1" /> <BaseIcon
class="mr-1"
icon-name="mdiShapeSquarePlus"
:size="18"
/>
<span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
{{ t('database.newTrigger') }} {{ t('database.newTrigger') }}
<span <span
@@ -172,7 +204,11 @@
class="tab-link" class="tab-link"
:class="{'badge': element.isChanged}" :class="{'badge': element.isChanged}"
> >
<i class="mdi mdi-shape-square-plus mdi-18px mr-1" /> <BaseIcon
class="mr-1"
icon-name="mdiShapeSquarePlus"
:size="18"
/>
<span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
{{ t('database.newRoutine') }} {{ t('database.newRoutine') }}
<span <span
@@ -189,7 +225,11 @@
class="tab-link" class="tab-link"
:class="{'badge': element.isChanged}" :class="{'badge': element.isChanged}"
> >
<i class="mdi mdi-shape-square-plus mdi-18px mr-1" /> <BaseIcon
class="mr-1"
icon-name="mdiShapeSquarePlus"
:size="18"
/>
<span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
{{ t('database.newFunction') }} {{ t('database.newFunction') }}
<span <span
@@ -206,7 +246,11 @@
class="tab-link" class="tab-link"
:class="{'badge': element.isChanged}" :class="{'badge': element.isChanged}"
> >
<i class="mdi mdi-shape-square-plus mdi-18px mr-1" /> <BaseIcon
class="mr-1"
icon-name="mdiShapeSquarePlus"
:size="18"
/>
<span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
{{ t('database.newTriggerFunction') }} {{ t('database.newTriggerFunction') }}
<span <span
@@ -223,7 +267,11 @@
class="tab-link" class="tab-link"
:class="{'badge': element.isChanged}" :class="{'badge': element.isChanged}"
> >
<i class="mdi mdi-shape-square-plus mdi-18px mr-1" /> <BaseIcon
class="mr-1"
icon-name="mdiShapeSquarePlus"
:size="18"
/>
<span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('general.new').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
{{ t('database.newScheduler') }} {{ t('database.newScheduler') }}
<span <span
@@ -241,7 +289,11 @@
:class="{'badge': element.isChanged}" :class="{'badge': element.isChanged}"
@dblclick="openAsPermanentTab(element)" @dblclick="openAsPermanentTab(element)"
> >
<i class="mdi mdi-18px mdi-wrench-cog mr-1" /> <BaseIcon
class="mr-1"
icon-name="mdiWrenchCog"
:size="18"
/>
<span :title="`${t('application.settings').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('application.settings').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
<span class=" text-italic">{{ cutText(element.elementName, 20, true) }}</span> <span class=" text-italic">{{ cutText(element.elementName, 20, true) }}</span>
<span <span
@@ -258,7 +310,11 @@
class="tab-link" class="tab-link"
:class="{'badge': element.isChanged}" :class="{'badge': element.isChanged}"
> >
<i class="mdi mdi-18px mdi-wrench-cog mr-1" /> <BaseIcon
class="mr-1"
icon-name="mdiWrenchCog"
:size="18"
/>
<span :title="`${t('application.settings').toUpperCase()}: ${t(`database.${element.elementType}`)}`"> <span :title="`${t('application.settings').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
{{ cutText(element.elementName, 20, true) }} {{ cutText(element.elementName, 20, true) }}
<span <span
@@ -281,18 +337,26 @@
tabindex="0" tabindex="0"
:title="t('general.tools')" :title="t('general.tools')"
> >
<i class="mdi mdi-24px mdi-tools" /> <BaseIcon icon-name="mdiTools" :size="24" />
</a> </a>
<ul v-if="hasTools" class="menu text-left text-uppercase"> <ul v-if="hasTools" class="menu text-left text-uppercase">
<li class="menu-item"> <li class="menu-item">
<a class="c-hand p-vcentered" @click="showProcessesModal"> <a class="c-hand p-vcentered" @click="showProcessesModal">
<i class="mdi mdi-memory mr-1 tool-icon" /> <BaseIcon
icon-name="mdiMemory"
:size="18"
class="mr-1 tool-icon"
/>
<span>{{ t('database.processesList') }}</span> <span>{{ t('database.processesList') }}</span>
</a> </a>
</li> </li>
<li class="menu-item"> <li class="menu-item">
<a class="c-hand p-vcentered" @click="toggleConsole"> <a class="c-hand p-vcentered" @click="toggleConsole">
<i class="mdi mdi-console-line mr-1 tool-icon" /> <BaseIcon
icon-name="mdiConsoleLine"
:size="18"
class="mr-1 tool-icon"
/>
<span>{{ t('application.console') }}</span> <span>{{ t('application.console') }}</span>
</a> </a>
</li> </li>
@@ -302,7 +366,11 @@
title="Coming..." title="Coming..."
> >
<a class="c-hand p-vcentered disabled"> <a class="c-hand p-vcentered disabled">
<i class="mdi mdi-shape mr-1 tool-icon" /> <BaseIcon
icon-name="mdiShape"
:size="18"
class="mr-1 tool-icon"
/>
<span>{{ t('database.variables') }}</span> <span>{{ t('database.variables') }}</span>
</a> </a>
</li> </li>
@@ -312,7 +380,11 @@
title="Coming..." title="Coming..."
> >
<a class="c-hand p-vcentered disabled"> <a class="c-hand p-vcentered disabled">
<i class="mdi mdi-account-group mr-1 tool-icon" /> <BaseIcon
icon-name="mdiAccountGroup"
:size="18"
class="mr-1 tool-icon"
/>
<span>{{ t('database.manageUsers') }}</span> <span>{{ t('database.manageUsers') }}</span>
</a> </a>
</li> </li>
@@ -326,7 +398,7 @@
:title="t('application.openNewTab')" :title="t('application.openNewTab')"
@click="addQueryTab" @click="addQueryTab"
> >
<i class="mdi mdi-24px mdi-plus" /> <BaseIcon icon-name="mdiPlus" :size="24" />
</a> </a>
</li> </li>
</template> </template>
@@ -488,42 +560,41 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ipcRenderer } from 'electron';
import { computed, onMounted, Prop, ref, watch } from 'vue';
import { storeToRefs } from 'pinia';
import * as Draggable from 'vuedraggable';
import Connection from '@/ipc-api/Connection';
import { useWorkspacesStore, WorkspaceTab } from '@/stores/workspaces';
import { useConsoleStore } from '@/stores/console';
import { ConnectionParams } from 'common/interfaces/antares'; import { ConnectionParams } from 'common/interfaces/antares';
import { useFilters } from '@/composables/useFilters'; import { ipcRenderer } from 'electron';
import { storeToRefs } from 'pinia';
import { computed, onMounted, Prop, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import * as Draggable from 'vuedraggable';
import BaseIcon from '@/components/BaseIcon.vue';
import ModalDiscardChanges from '@/components/ModalDiscardChanges.vue';
import ModalProcessesList from '@/components/ModalProcessesList.vue';
import WorkspaceEditConnectionPanel from '@/components/WorkspaceEditConnectionPanel.vue';
import WorkspaceEmptyState from '@/components/WorkspaceEmptyState.vue'; import WorkspaceEmptyState from '@/components/WorkspaceEmptyState.vue';
import WorkspaceExploreBar from '@/components/WorkspaceExploreBar.vue'; import WorkspaceExploreBar from '@/components/WorkspaceExploreBar.vue';
import WorkspaceEditConnectionPanel from '@/components/WorkspaceEditConnectionPanel.vue';
import WorkspaceTabQuery from '@/components/WorkspaceTabQuery.vue';
import WorkspaceTabTable from '@/components/WorkspaceTabTable.vue';
import WorkspaceQueryConsole from '@/components/WorkspaceQueryConsole.vue'; import WorkspaceQueryConsole from '@/components/WorkspaceQueryConsole.vue';
import WorkspaceTabNewTable from '@/components/WorkspaceTabNewTable.vue';
import WorkspaceTabNewView from '@/components/WorkspaceTabNewView.vue';
import WorkspaceTabNewTrigger from '@/components/WorkspaceTabNewTrigger.vue';
import WorkspaceTabNewRoutine from '@/components/WorkspaceTabNewRoutine.vue';
import WorkspaceTabNewFunction from '@/components/WorkspaceTabNewFunction.vue'; import WorkspaceTabNewFunction from '@/components/WorkspaceTabNewFunction.vue';
import WorkspaceTabNewRoutine from '@/components/WorkspaceTabNewRoutine.vue';
import WorkspaceTabNewScheduler from '@/components/WorkspaceTabNewScheduler.vue'; import WorkspaceTabNewScheduler from '@/components/WorkspaceTabNewScheduler.vue';
import WorkspaceTabNewTable from '@/components/WorkspaceTabNewTable.vue';
import WorkspaceTabNewTrigger from '@/components/WorkspaceTabNewTrigger.vue';
import WorkspaceTabNewTriggerFunction from '@/components/WorkspaceTabNewTriggerFunction.vue'; import WorkspaceTabNewTriggerFunction from '@/components/WorkspaceTabNewTriggerFunction.vue';
import WorkspaceTabsContext from '@/components/WorkspaceTabsContext.vue'; import WorkspaceTabNewView from '@/components/WorkspaceTabNewView.vue';
import WorkspaceTabPropsFunction from '@/components/WorkspaceTabPropsFunction.vue';
import WorkspaceTabPropsRoutine from '@/components/WorkspaceTabPropsRoutine.vue';
import WorkspaceTabPropsScheduler from '@/components/WorkspaceTabPropsScheduler.vue';
import WorkspaceTabPropsTable from '@/components/WorkspaceTabPropsTable.vue'; import WorkspaceTabPropsTable from '@/components/WorkspaceTabPropsTable.vue';
import WorkspaceTabPropsView from '@/components/WorkspaceTabPropsView.vue';
import WorkspaceTabPropsTrigger from '@/components/WorkspaceTabPropsTrigger.vue'; import WorkspaceTabPropsTrigger from '@/components/WorkspaceTabPropsTrigger.vue';
import WorkspaceTabPropsTriggerFunction from '@/components/WorkspaceTabPropsTriggerFunction.vue'; import WorkspaceTabPropsTriggerFunction from '@/components/WorkspaceTabPropsTriggerFunction.vue';
import WorkspaceTabPropsRoutine from '@/components/WorkspaceTabPropsRoutine.vue'; import WorkspaceTabPropsView from '@/components/WorkspaceTabPropsView.vue';
import WorkspaceTabPropsFunction from '@/components/WorkspaceTabPropsFunction.vue'; import WorkspaceTabQuery from '@/components/WorkspaceTabQuery.vue';
import WorkspaceTabPropsScheduler from '@/components/WorkspaceTabPropsScheduler.vue'; import WorkspaceTabsContext from '@/components/WorkspaceTabsContext.vue';
import ModalProcessesList from '@/components/ModalProcessesList.vue'; import WorkspaceTabTable from '@/components/WorkspaceTabTable.vue';
import ModalDiscardChanges from '@/components/ModalDiscardChanges.vue'; import { useFilters } from '@/composables/useFilters';
import { useI18n } from 'vue-i18n'; import Connection from '@/ipc-api/Connection';
import { useConsoleStore } from '@/stores/console';
import { useWorkspacesStore, WorkspaceTab } from '@/stores/workspaces';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -33,10 +33,10 @@
<form class="form-horizontal"> <form class="form-horizontal">
<fieldset class="m-0" :disabled="isBusy"> <fieldset class="m-0" :disabled="isBusy">
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.connectionName') }}</label> <label class="form-label cut-text">{{ t('connection.connectionName') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
ref="firstInput" ref="firstInput"
v-model="connection.name" v-model="connection.name"
@@ -46,10 +46,10 @@
</div> </div>
</div> </div>
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.client') }}</label> <label class="form-label cut-text">{{ t('connection.client') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<BaseSelect <BaseSelect
v-model="connection.client" v-model="connection.client"
:options="clients" :options="clients"
@@ -60,10 +60,10 @@
</div> </div>
</div> </div>
<div v-if="connection.client === 'pg'" class="form-group columns"> <div v-if="connection.client === 'pg'" class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.connectionString') }}</label> <label class="form-label cut-text">{{ t('connection.connectionString') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
ref="pgString" ref="pgString"
v-model="connection.pgConnString" v-model="connection.pgConnString"
@@ -73,10 +73,10 @@
</div> </div>
</div> </div>
<div v-if="!clientCustomizations.fileConnection" class="form-group columns"> <div v-if="!clientCustomizations.fileConnection" class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.hostName') }}/IP</label> <label class="form-label cut-text">{{ t('connection.hostName') }}/IP</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
v-model="connection.host" v-model="connection.host"
class="form-input" class="form-input"
@@ -85,10 +85,10 @@
</div> </div>
</div> </div>
<div v-if="clientCustomizations.fileConnection" class="form-group columns"> <div v-if="clientCustomizations.fileConnection" class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('database.database') }}</label> <label class="form-label cut-text">{{ t('database.database') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<BaseUploadInput <BaseUploadInput
:model-value="connection.databasePath" :model-value="connection.databasePath"
:message="t('general.browse')" :message="t('general.browse')"
@@ -98,10 +98,10 @@
</div> </div>
</div> </div>
<div v-if="!clientCustomizations.fileConnection" class="form-group columns"> <div v-if="!clientCustomizations.fileConnection" class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.port') }}</label> <label class="form-label cut-text">{{ t('connection.port') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
v-model="connection.port" v-model="connection.port"
class="form-input" class="form-input"
@@ -112,10 +112,10 @@
</div> </div>
</div> </div>
<div v-if="clientCustomizations.database" class="form-group columns"> <div v-if="clientCustomizations.database" class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('database.database') }}</label> <label class="form-label cut-text">{{ t('database.database') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
v-model="connection.database" v-model="connection.database"
class="form-input" class="form-input"
@@ -125,10 +125,10 @@
</div> </div>
</div> </div>
<div v-if="!clientCustomizations.fileConnection" class="form-group columns"> <div v-if="!clientCustomizations.fileConnection" class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.user') }}</label> <label class="form-label cut-text">{{ t('connection.user') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
v-model="connection.user" v-model="connection.user"
class="form-input" class="form-input"
@@ -138,10 +138,10 @@
</div> </div>
</div> </div>
<div v-if="!clientCustomizations.fileConnection" class="form-group columns"> <div v-if="!clientCustomizations.fileConnection" class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.password') }}</label> <label class="form-label cut-text">{{ t('connection.password') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
v-model="connection.password" v-model="connection.password"
class="form-input" class="form-input"
@@ -151,10 +151,10 @@
</div> </div>
</div> </div>
<div v-if="clientCustomizations.connectionSchema" class="form-group columns"> <div v-if="clientCustomizations.connectionSchema" class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('database.schema') }}</label> <label class="form-label cut-text">{{ t('database.schema') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
v-model="connection.schema" v-model="connection.schema"
class="form-input" class="form-input"
@@ -164,16 +164,16 @@
</div> </div>
</div> </div>
<div v-if="clientCustomizations.readOnlyMode" class="form-group columns"> <div v-if="clientCustomizations.readOnlyMode" class="form-group columns">
<div class="column col-4 col-sm-12" /> <div class="column col-5 col-sm-12" />
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<label class="form-checkbox form-inline"> <label class="form-checkbox form-inline">
<input v-model="connection.readonly" type="checkbox"><i class="form-icon" /> {{ t('connection.readOnlyMode') }} <input v-model="connection.readonly" type="checkbox"><i class="form-icon" /> {{ t('connection.readOnlyMode') }}
</label> </label>
</div> </div>
</div> </div>
<div v-if="!clientCustomizations.fileConnection" class="form-group columns"> <div v-if="!clientCustomizations.fileConnection" class="form-group columns">
<div class="column col-4 col-sm-12" /> <div class="column col-5 col-sm-12" />
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<label class="form-checkbox form-inline"> <label class="form-checkbox form-inline">
<input v-model="connection.ask" type="checkbox"><i class="form-icon" /> {{ t('connection.askCredentials') }} <input v-model="connection.ask" type="checkbox"><i class="form-icon" /> {{ t('connection.askCredentials') }}
</label> </label>
@@ -187,12 +187,12 @@
<div> <div>
<form class="form-horizontal"> <form class="form-horizontal">
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text"> <label class="form-label cut-text">
{{ t('connection.enableSsl') }} {{ t('connection.enableSsl') }}
</label> </label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<label class="form-switch d-inline-block" @click.prevent="toggleSsl"> <label class="form-switch d-inline-block" @click.prevent="toggleSsl">
<input type="checkbox" :checked="connection.ssl"> <input type="checkbox" :checked="connection.ssl">
<i class="form-icon" /> <i class="form-icon" />
@@ -201,10 +201,10 @@
</div> </div>
<fieldset class="m-0" :disabled="isBusy || !connection.ssl"> <fieldset class="m-0" :disabled="isBusy || !connection.ssl">
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.privateKey') }}</label> <label class="form-label cut-text">{{ t('connection.privateKey') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<BaseUploadInput <BaseUploadInput
:model-value="connection.key" :model-value="connection.key"
:message="t('general.browse')" :message="t('general.browse')"
@@ -214,10 +214,10 @@
</div> </div>
</div> </div>
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.certificate') }}</label> <label class="form-label cut-text">{{ t('connection.certificate') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<BaseUploadInput <BaseUploadInput
:model-value="connection.cert" :model-value="connection.cert"
:message="t('general.browse')" :message="t('general.browse')"
@@ -227,10 +227,10 @@
</div> </div>
</div> </div>
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.caCertificate') }}</label> <label class="form-label cut-text">{{ t('connection.caCertificate') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<BaseUploadInput <BaseUploadInput
:model-value="connection.ca" :model-value="connection.ca"
:message="t('general.browse')" :message="t('general.browse')"
@@ -240,10 +240,10 @@
</div> </div>
</div> </div>
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.ciphers') }}</label> <label class="form-label cut-text">{{ t('connection.ciphers') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
ref="firstInput" ref="firstInput"
v-model="connection.ciphers" v-model="connection.ciphers"
@@ -253,8 +253,8 @@
</div> </div>
</div> </div>
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12" /> <div class="column col-5 col-sm-12" />
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<label class="form-checkbox form-inline"> <label class="form-checkbox form-inline">
<input v-model="connection.untrustedConnection" type="checkbox"><i class="form-icon" /> {{ t('connection.untrustedConnection') }} <input v-model="connection.untrustedConnection" type="checkbox"><i class="form-icon" /> {{ t('connection.untrustedConnection') }}
</label> </label>
@@ -268,12 +268,12 @@
<div> <div>
<form class="form-horizontal"> <form class="form-horizontal">
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text"> <label class="form-label cut-text">
{{ t('connection.enableSsh') }} {{ t('connection.enableSsh') }}
</label> </label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<label class="form-switch d-inline-block" @click.prevent="toggleSsh"> <label class="form-switch d-inline-block" @click.prevent="toggleSsh">
<input type="checkbox" :checked="connection.ssh"> <input type="checkbox" :checked="connection.ssh">
<i class="form-icon" /> <i class="form-icon" />
@@ -282,10 +282,10 @@
</div> </div>
<fieldset class="m-0" :disabled="isBusy || !connection.ssh"> <fieldset class="m-0" :disabled="isBusy || !connection.ssh">
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.hostName') }}/IP</label> <label class="form-label cut-text">{{ t('connection.hostName') }}/IP</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
v-model="connection.sshHost" v-model="connection.sshHost"
class="form-input" class="form-input"
@@ -294,10 +294,10 @@
</div> </div>
</div> </div>
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.user') }}</label> <label class="form-label cut-text">{{ t('connection.user') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
v-model="connection.sshUser" v-model="connection.sshUser"
class="form-input" class="form-input"
@@ -306,10 +306,10 @@
</div> </div>
</div> </div>
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.password') }}</label> <label class="form-label cut-text">{{ t('connection.password') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
v-model="connection.sshPass" v-model="connection.sshPass"
class="form-input" class="form-input"
@@ -318,10 +318,10 @@
</div> </div>
</div> </div>
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.port') }}</label> <label class="form-label cut-text">{{ t('connection.port') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
v-model="connection.sshPort" v-model="connection.sshPort"
class="form-input" class="form-input"
@@ -332,10 +332,10 @@
</div> </div>
</div> </div>
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.privateKey') }}</label> <label class="form-label cut-text">{{ t('connection.privateKey') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<BaseUploadInput <BaseUploadInput
:model-value="connection.sshKey" :model-value="connection.sshKey"
:message="t('general.browse')" :message="t('general.browse')"
@@ -345,10 +345,10 @@
</div> </div>
</div> </div>
<div class="form-group columns"> <div class="form-group columns">
<div class="column col-4 col-sm-12"> <div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.passphrase') }}</label> <label class="form-label cut-text">{{ t('connection.passphrase') }}</label>
</div> </div>
<div class="column col-8 col-sm-12"> <div class="column col-7 col-sm-12">
<input <input
v-model="connection.sshPassphrase" v-model="connection.sshPassphrase"
class="form-input" class="form-input"
@@ -356,6 +356,22 @@
> >
</div> </div>
</div> </div>
<div class="form-group columns">
<div class="column col-5 col-sm-12">
<label class="form-label cut-text">{{ t('connection.keepAliveInterval') }}</label>
</div>
<div class="column col-7 col-sm-12">
<div class="input-group">
<input
v-model="connection.sshKeepAliveInterval"
class="form-input"
type="number"
min="1"
>
<span class="input-group-addon">{{ t('general.seconds') }}</span>
</div>
</div>
</div>
</fieldset> </fieldset>
</form> </form>
</div> </div>
@@ -368,7 +384,11 @@
:disabled="isBusy" :disabled="isBusy"
@click="startTest" @click="startTest"
> >
<i class="mdi mdi-24px mdi-lightning-bolt mr-1" /> <BaseIcon
icon-name="mdiLightningBolt"
:size="24"
class="mr-1"
/>
{{ t('connection.testConnection') }} {{ t('connection.testConnection') }}
</button> </button>
<button <button
@@ -377,7 +397,11 @@
:disabled="isBusy" :disabled="isBusy"
@click="saveConnection" @click="saveConnection"
> >
<i class="mdi mdi-24px mdi-content-save mr-1" /> <BaseIcon
icon-name="mdiContentSave"
:size="24"
class="mr-1"
/>
{{ t('general.save') }} {{ t('general.save') }}
</button> </button>
</div> </div>
@@ -391,18 +415,20 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, Ref, ref, watch } from 'vue';
import customizations from 'common/customizations'; import customizations from 'common/customizations';
import Connection from '@/ipc-api/Connection'; import { ConnectionParams } from 'common/interfaces/antares';
import { uidGen } from 'common/libs/uidGen'; import { uidGen } from 'common/libs/uidGen';
import { computed, Ref, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import BaseIcon from '@/components/BaseIcon.vue';
import BaseSelect from '@/components/BaseSelect.vue';
import BaseUploadInput from '@/components/BaseUploadInput.vue';
import ModalAskCredentials from '@/components/ModalAskCredentials.vue';
import Connection from '@/ipc-api/Connection';
import { useConnectionsStore } from '@/stores/connections'; import { useConnectionsStore } from '@/stores/connections';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
import ModalAskCredentials from '@/components/ModalAskCredentials.vue';
import BaseUploadInput from '@/components/BaseUploadInput.vue';
import BaseSelect from '@/components/BaseSelect.vue';
import { ConnectionParams } from 'common/interfaces/antares';
import { useI18n } from 'vue-i18n';
const { t } = useI18n(); const { t } = useI18n();
@@ -442,8 +468,10 @@ const connection = ref({
sshHost: '', sshHost: '',
sshUser: '', sshUser: '',
sshPass: '', sshPass: '',
sshPassphrase: null,
sshKey: '', sshKey: '',
sshPort: 22, sshPort: 22,
sshKeepAliveInterval: 1800,
pgConnString: '' pgConnString: ''
}) as Ref<ConnectionParams & { pgConnString: string }>; }) as Ref<ConnectionParams & { pgConnString: string }>;

Some files were not shown because too many files have changed in this diff Show More