Compare commits
59 Commits
Author | SHA1 | Date | |
---|---|---|---|
c46224635a | |||
cc99491fe4 | |||
fe8435531e | |||
5d48fe08c7 | |||
4437d44486 | |||
9fe3680bbb | |||
da1947e4ef | |||
37a848df9d | |||
|
9816965e18 | ||
98165cacaa | |||
7ad3096b4e | |||
7d345cf795 | |||
f40e9c592e | |||
7671c585f5 | |||
93b4a7063b | |||
3efeb45c46 | |||
3fc227d2de | |||
604b371920 | |||
fd321beece | |||
9fe4e6b9e3 | |||
|
57bf90481b | ||
|
6062a32c1c | ||
94c899eb82 | |||
44a4ca75bd | |||
|
c8e1605b08 | ||
60e5556a3e | |||
f2fcc98839 | |||
c54438d6d3 | |||
b3f10220b3 | |||
d19f475fc2 | |||
795db96319 | |||
b5fee79e90 | |||
|
5532ddbda9 | ||
3369d3dc2d | |||
fd25f881f9 | |||
5ca3a22dc5 | |||
5c668249cf | |||
39b9a59143 | |||
534659f9ae | |||
c00fd1381f | |||
17c6686163 | |||
bc0c5a76ba | |||
2b16c0ece4 | |||
|
ba1416dce2 | ||
13adf0a767 | |||
cacab55f55 | |||
|
3189d625e3 | ||
|
f71ed39b88 | ||
729aa9781a | |||
cd1ebacf89 | |||
a08074b446 | |||
0cd182546b | |||
89fdd210ca | |||
|
e2cf6e8c21 | ||
|
430490ad93 | ||
|
a35566f273 | ||
3679121c25 | |||
|
7657d05edf | ||
|
1ddf8f0dbe |
127
.all-contributorsrc
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
{
|
||||||
|
"projectName": "antares",
|
||||||
|
"projectOwner": "Fabio286",
|
||||||
|
"repoType": "github",
|
||||||
|
"repoHost": "https://github.com",
|
||||||
|
"files": [
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"imageSize": 100,
|
||||||
|
"commit": false,
|
||||||
|
"commitConvention": "angular",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"login": "Fabio286",
|
||||||
|
"name": "Fabio Di Stasio",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/31471771?v=4",
|
||||||
|
"profile": "https://fabiodistasio.it/",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"translation",
|
||||||
|
"doc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "toriphes",
|
||||||
|
"name": "Giulio Ganci",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/4192159?v=4",
|
||||||
|
"profile": "https://www.linkedin.com/in/giulioganci/",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "digitalgopnik",
|
||||||
|
"name": "Christian Ratz",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/2630316?v=4",
|
||||||
|
"profile": "https://christianratz.de/",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "reverb6821",
|
||||||
|
"name": "Giuseppe Gigliotti",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/55198803?v=4",
|
||||||
|
"profile": "https://reverb6821.github.io/",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Mohd-PH",
|
||||||
|
"name": "Mohd-PH",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/9362157?v=4",
|
||||||
|
"profile": "https://github.com/Mohd-PH",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "hongkfui",
|
||||||
|
"name": "hongkfui",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/37477191?v=4",
|
||||||
|
"profile": "https://github.com/hongkfui",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "MrAnyx",
|
||||||
|
"name": "Robin",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/44176707?v=4",
|
||||||
|
"profile": "https://github.com/MrAnyx",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "daeleduardo",
|
||||||
|
"name": "Daniel Eduardo",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/8599078?v=4",
|
||||||
|
"profile": "https://github.com/daeleduardo",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "datlechin",
|
||||||
|
"name": "Ngô Quốc Đạt",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/56961917?v=4",
|
||||||
|
"profile": "https://ngoquocdat.com/",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "IsamuSugi",
|
||||||
|
"name": "Isamu Sugiura",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/7746658?v=4",
|
||||||
|
"profile": "https://github.com/IsamuSugi",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Occhioverde",
|
||||||
|
"name": "Riccardo Sacchetto",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/18429412?v=4",
|
||||||
|
"profile": "http://rsacchetto.nexxontech.it/",
|
||||||
|
"contributions": [
|
||||||
|
"platform"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "kilianstallz",
|
||||||
|
"name": "Kilian Stallinger",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/5290318?v=4",
|
||||||
|
"profile": "https://kilianstallinger.com",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contributorsPerLine": 7,
|
||||||
|
"skipCi": true
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
/node_modules
|
node_modules
|
||||||
/assets/vendor
|
assets
|
||||||
/out
|
out
|
||||||
/dist
|
dist
|
@@ -45,7 +45,9 @@
|
|||||||
"no-console": "off",
|
"no-console": "off",
|
||||||
"no-undef": "off",
|
"no-undef": "off",
|
||||||
"vue/no-side-effects-in-computed-properties": "off",
|
"vue/no-side-effects-in-computed-properties": "off",
|
||||||
|
"vue/multi-word-component-names": "off",
|
||||||
"vue/require-default-prop": "off",
|
"vue/require-default-prop": "off",
|
||||||
|
"vue/comment-directive": "off",
|
||||||
"vue/no-v-html": "off",
|
"vue/no-v-html": "off",
|
||||||
"vue/html-indent": [
|
"vue/html-indent": [
|
||||||
"error",
|
"error",
|
||||||
@@ -60,10 +62,11 @@
|
|||||||
"vue/max-attributes-per-line": [
|
"vue/max-attributes-per-line": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
"singleline": 2,
|
"singleline": {
|
||||||
|
"max": 2
|
||||||
|
},
|
||||||
"multiline": {
|
"multiline": {
|
||||||
"max": 1,
|
"max": 1
|
||||||
"allowFirstLine": false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
7
.gitignore
vendored
@@ -1,9 +1,8 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
dist/
|
dist
|
||||||
node_modules/
|
build
|
||||||
|
node_modules
|
||||||
thumbs.db
|
thumbs.db
|
||||||
.idea/
|
|
||||||
.vscode
|
|
||||||
NOTES.md
|
NOTES.md
|
||||||
*.txt
|
*.txt
|
||||||
package-lock.json
|
package-lock.json
|
29
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"name": "Electron: Main",
|
||||||
|
"port": 9222,
|
||||||
|
"protocol": "inspector",
|
||||||
|
"request": "attach",
|
||||||
|
"sourceMaps": true,
|
||||||
|
"type": "node",
|
||||||
|
"timeout": 1000000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Electron: Renderer",
|
||||||
|
"port": 9223,
|
||||||
|
"request": "attach",
|
||||||
|
"sourceMaps": true,
|
||||||
|
"type": "chrome",
|
||||||
|
"webRoot": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compounds": [
|
||||||
|
{
|
||||||
|
"name": "Electron: All",
|
||||||
|
"configurations": ["Electron: Main", "Electron: Renderer"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
10
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"conventionalCommits.scopes": [
|
||||||
|
"UI",
|
||||||
|
"core",
|
||||||
|
"MySQL",
|
||||||
|
"PostgreSQL",
|
||||||
|
"SQLite"
|
||||||
|
],
|
||||||
|
"svg.preview.background": "transparent"
|
||||||
|
}
|
56
CHANGELOG.md
@@ -2,6 +2,62 @@
|
|||||||
|
|
||||||
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.4.0](https://github.com/Fabio286/antares/compare/v0.3.9...v0.4.0) (2021-11-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **MySQL:** read-only mode ([4437d44](https://github.com/Fabio286/antares/commit/4437d44486c4f20b0bec4bf89d56016b08e36e79))
|
||||||
|
* **PostgreSQL:** read-only mode ([5d48fe0](https://github.com/Fabio286/antares/commit/5d48fe08c77755ed18b3f7a9ea834268e317e7ef))
|
||||||
|
* **SQLite:** cell update in data tabs ([604b371](https://github.com/Fabio286/antares/commit/604b3719204f7473ce4846624f08f8be9eec8b8f))
|
||||||
|
* **SQLite:** connection add/edit masks ([c54438d](https://github.com/Fabio286/antares/commit/c54438d6d3bad38bc76dfcd61f58929fe30279cb))
|
||||||
|
* **SQLite:** keys support ([fd321be](https://github.com/Fabio286/antares/commit/fd321beece075d3ad23fdd8541f9beb5727045a5))
|
||||||
|
* **SQLite:** readonly mode ([3fc227d](https://github.com/Fabio286/antares/commit/3fc227d2de53aae115226ad3c965bfb6e9f3eca6))
|
||||||
|
* **SQLite:** table data visualization ([f2fcc98](https://github.com/Fabio286/antares/commit/f2fcc9883972402eab4d51ef2a9796638dde2d3d))
|
||||||
|
* **SQLite:** tables management ([3efeb45](https://github.com/Fabio286/antares/commit/3efeb45c460f178b794de72367f8d542fd8ddd56))
|
||||||
|
* **SQLite:** triggers management ([f40e9c5](https://github.com/Fabio286/antares/commit/f40e9c592eeffd204aba21a0a0767a0c523fca49))
|
||||||
|
* **SQLite:** views management ([7671c58](https://github.com/Fabio286/antares/commit/7671c585f5f8049bd863db190d4fc60d8f0c6c66))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **SQLite:** hide schema creation ([98165ca](https://github.com/Fabio286/antares/commit/98165cacaa158c85ead0490d3caf579e2a17319f))
|
||||||
|
* **UI:** hide tools menu if no tools available ([da1947e](https://github.com/Fabio286/antares/commit/da1947e4efa7f0a26d6a231fadf750be055fbdd5))
|
||||||
|
* **UI:** notifications timeout anomalies ([cc99491](https://github.com/Fabio286/antares/commit/cc99491fe4a15812368f6c928b8c7801d7b255aa))
|
||||||
|
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
|
||||||
|
* **SQLite:** improvements in data visualization ([94c899e](https://github.com/Fabio286/antares/commit/94c899eb8288b41a5962ac3d24365227e1f9f485))
|
||||||
|
* **SQLite:** improvements in field length detection ([93b4a70](https://github.com/Fabio286/antares/commit/93b4a7063beeb5a7001cb06a74f05b23105212f5))
|
||||||
|
* update italian traslation ([9fe3680](https://github.com/Fabio286/antares/commit/9fe3680bbb17c192cffa85348e68794ab49beb81))
|
||||||
|
|
||||||
|
### [0.3.9](https://github.com/Fabio286/antares/compare/v0.3.8...v0.3.9) (2021-11-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* added macos basic shortcusts and menu ([430490a](https://github.com/Fabio286/antares/commit/430490ad93f3148962ced1f13a5330c79cd86b3b))
|
||||||
|
* **MySQL:** enable/disable schedulers from contextual menu ([5ca3a22](https://github.com/Fabio286/antares/commit/5ca3a22dc538b27a4bf6402f1288c4b9f5bc5a90))
|
||||||
|
* **MySQL:** scheduler status indicator in explore bar ([5c66824](https://github.com/Fabio286/antares/commit/5c668249cf102cd9d601f9f7b4943c7155775217))
|
||||||
|
* **PostgreSQL:** enable/disable triggers from contextual menu ([534659f](https://github.com/Fabio286/antares/commit/534659f9aee12eb5ac477f91bfe5d764387dc17e))
|
||||||
|
* schema size in explore bar ([fd25f88](https://github.com/Fabio286/antares/commit/fd25f881f95779709156cbad93a41d6b391f1a45))
|
||||||
|
* **UI:** double click on the title bar will toggle window fullscreen size ([a35566f](https://github.com/Fabio286/antares/commit/a35566f273322602abe434b8bd30817ba8885900))
|
||||||
|
* **UI:** improved topbar look&feel on MacOS ([7657d05](https://github.com/Fabio286/antares/commit/7657d05edfbeaed6a14eb337fc562da5126e6ba0))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* copy&paste and basic usability on macOS ([1ddf8f0](https://github.com/Fabio286/antares/commit/1ddf8f0dbe22f94d6bffddf70636706d2d142ecf))
|
||||||
|
* **PostgreSQL:** bigint fetched as string instead of number, closes [#134](https://github.com/Fabio286/antares/issues/134) ([39b9a59](https://github.com/Fabio286/antares/commit/39b9a59143b457a96f0711a3b8588c92dd80e28d))
|
||||||
|
* row selection problems after a deletion fail, closes [#128](https://github.com/Fabio286/antares/issues/128) ([89fdd21](https://github.com/Fabio286/antares/commit/89fdd210ca48fc9ae399b195ea796c8523619627))
|
||||||
|
* temporary solution on MacOS for unsigned app updates ([c00fd13](https://github.com/Fabio286/antares/commit/c00fd1381f451ba7aace7047b28b904ddcaf18f0))
|
||||||
|
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
|
||||||
|
* **UI:** improved function and routine parameters modals ([d19f475](https://github.com/Fabio286/antares/commit/d19f475fc28c0367ada569cb634769fa618b48b4))
|
||||||
|
|
||||||
### [0.3.8](https://github.com/Fabio286/antares/compare/v0.3.7...v0.3.8) (2021-10-23)
|
### [0.3.8](https://github.com/Fabio286/antares/compare/v0.3.7...v0.3.8) (2021-10-23)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -57,8 +57,8 @@ The command to build Antares SQL locally is `npm run build:local`.
|
|||||||
|
|
||||||
- **PascalCase** for file names (with .vue extension) and including components inside others (`<MyComponent/>`).
|
- **PascalCase** for file names (with .vue extension) and including components inside others (`<MyComponent/>`).
|
||||||
- "**Base**" prefix for [base component names](https://vuejs.org/v2/style-guide/#Base-component-names-strongly-recommended).
|
- "**Base**" prefix for [base component names](https://vuejs.org/v2/style-guide/#Base-component-names-strongly-recommended).
|
||||||
- "**The**" prefix for [single-instance component names](https://vuejs.org/v2/style-guide/#Single-instance-component-names-strongly-recommended).
|
- "**The**" prefix for [single-instance component names](https://vuejs.org/v2/style-guide/#Single-instance-component-names-strongly-recommended).
|
||||||
- [Tightly coupled component names ](https://vuejs.org/v2/style-guide/#Tightly-coupled-component-names-strongly-recommended).
|
- [Tightly coupled component names](https://vuejs.org/v2/style-guide/#Tightly-coupled-component-names-strongly-recommended).
|
||||||
- [Order of words in component names](https://vuejs.org/v2/style-guide/#Order-of-words-in-component-names-strongly-recommended).
|
- [Order of words in component names](https://vuejs.org/v2/style-guide/#Order-of-words-in-component-names-strongly-recommended).
|
||||||
- **kebab-case** in templates for property and event names.
|
- **kebab-case** in templates for property and event names.
|
||||||
|
|
||||||
@@ -74,15 +74,21 @@ The project includes [ESlint](https://eslint.org/) and [StyleLint](https://style
|
|||||||
Alternatively you can launch following commands to lint the project.
|
Alternatively you can launch following commands to lint the project.
|
||||||
|
|
||||||
Check if all the style rules have been followed:
|
Check if all the style rules have been followed:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
npm run lint
|
npm run lint
|
||||||
```
|
```
|
||||||
|
|
||||||
Apply style rules globally if possible:
|
Apply style rules globally if possible:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
npm run lint:fix
|
npm run lint:fix
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Other recommendations
|
||||||
|
|
||||||
|
Please, use if possible **template literals** to compose strings and **avoid unnecessary dependencies**.
|
||||||
|
|
||||||
### Commits
|
### Commits
|
||||||
|
|
||||||
The commit style adopted for this project is [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
|
The commit style adopted for this project is [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
|
||||||
@@ -91,30 +97,11 @@ For Visual Studio Code users may be useful [Conventional Commits](https://market
|
|||||||
|
|
||||||
## Debug
|
## Debug
|
||||||
|
|
||||||
**Dev mode**:
|
**Debug mode**:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
npm run dev
|
npm run debug
|
||||||
```
|
```
|
||||||
|
|
||||||
**Visual Studio Code:**
|
After running the debug mode Antares will listen on port 9222 (main process) for a debugger.
|
||||||
|
On **Visual Studio Code** just launch "*Electron: Main*" configurations after running Antares in debug mode.
|
||||||
``` json
|
|
||||||
{
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"type": "node",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "Launch Electron in debugger",
|
|
||||||
"autoAttachChildProcesses": true,
|
|
||||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-webpack",
|
|
||||||
"runtimeArgs": [
|
|
||||||
"dev"
|
|
||||||
],
|
|
||||||
"env": {},
|
|
||||||
"console": "integratedTerminal",
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
49
README.md
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
|
<!-- markdownlint-disable -->
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img width="800" src="https://raw.githubusercontent.com/Fabio286/antares/master/docs/gh-logo.png">
|
<img width="800" src="https://raw.githubusercontent.com/Fabio286/antares/master/docs/gh-logo.png">
|
||||||
</p>
|
</p>
|
||||||
|
<!-- markdownlint-restore -->
|
||||||
|
|
||||||
# Antares SQL Client
|
# Antares SQL Client
|
||||||
|
|
||||||
@@ -9,7 +12,7 @@
|
|||||||
Antares is an SQL client based on [Electron.js](https://github.com/electron/electron) and [Vue.js](https://github.com/vuejs/vue) that aims to become a useful tool, especially for developers.
|
Antares is an SQL client based on [Electron.js](https://github.com/electron/electron) and [Vue.js](https://github.com/vuejs/vue) that aims to become a useful tool, especially for developers.
|
||||||
Our target is to support as many databases as possible, and all major operating systems, including the ARM versions.
|
Our target is to support as many databases as possible, and all major operating systems, including the ARM versions.
|
||||||
|
|
||||||
**At the moment this application is in development state, many features will come in future updates**, and supports only MySQL/MariaDB and PostgreSQL.
|
**At the moment this application is in development state, many features will come in future updates**, and supports only MySQL/MariaDB, PostgreSQL and SQLite.
|
||||||
At the moment, however, there are all the features necessary to have a pleasant database management experience, so give it a chance and send us your feedback, we would really appreciate it.
|
At the moment, however, there are all the features necessary to have a pleasant database management experience, so give it a chance and send us your feedback, we would really appreciate it.
|
||||||
We are actively working on it, hoping to provide new cool features, improvements and fixes as soon as possible.
|
We are actively working on it, hoping to provide new cool features, improvements and fixes as soon as possible.
|
||||||
|
|
||||||
@@ -65,12 +68,12 @@ On macOS you can run `.dmg` distribution following [this guide](https://support.
|
|||||||
|
|
||||||
This is a roadmap with major features will come in near future.
|
This is a roadmap with major features will come in near future.
|
||||||
|
|
||||||
- Support for other databases.
|
|
||||||
- Database tools.
|
- Database tools.
|
||||||
- Users management (add/edit/delete).
|
- Users management (add/edit/delete).
|
||||||
- More context menu shortcuts.
|
- More context menu shortcuts.
|
||||||
- More keyboard shortcuts.
|
- More keyboard shortcuts.
|
||||||
- Import/export and migration.
|
- Import/export and migration.
|
||||||
|
- Support for other databases.
|
||||||
- Apple Silicon distribution
|
- Apple Silicon distribution
|
||||||
|
|
||||||
## Currently supported
|
## Currently supported
|
||||||
@@ -79,7 +82,7 @@ This is a roadmap with major features will come in near future.
|
|||||||
|
|
||||||
- [x] MySQL/MariaDB
|
- [x] MySQL/MariaDB
|
||||||
- [x] PostgreSQL
|
- [x] PostgreSQL
|
||||||
- [ ] SQLite
|
- [x] SQLite
|
||||||
- [ ] MSSQL
|
- [ ] MSSQL
|
||||||
- [ ] OracleDB
|
- [ ] OracleDB
|
||||||
- [ ] More...
|
- [ ] More...
|
||||||
@@ -104,13 +107,35 @@ This is a roadmap with major features will come in near future.
|
|||||||
- 📖 [Contributors Guide](https://github.com/Fabio286/antares/wiki/Contributors-Guide)
|
- 📖 [Contributors Guide](https://github.com/Fabio286/antares/wiki/Contributors-Guide)
|
||||||
- 🚧 [Project Board](https://github.com/users/Fabio286/projects/1)
|
- 🚧 [Project Board](https://github.com/users/Fabio286/projects/1)
|
||||||
|
|
||||||
## Translations
|
## Contributors ✨
|
||||||
|
|
||||||
**Italian** / [Giuseppe Gigliotti](https://github.com/ReverbOD) [[#20](https://github.com/Fabio286/antares/pull/20)]
|
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||||
**Arabic** (needs updates) / [Mohd-PH](https://github.com/Mohd-PH) [[#29](https://github.com/Fabio286/antares/pull/29)]
|
|
||||||
**Spanish** (needs updates) / [hongkfui](https://github.com/hongkfui) [[#32](https://github.com/Fabio286/antares/pull/32)]
|
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||||
**French** (needs updates) / [MrAnyx](https://github.com/MrAnyx) [[#44](https://github.com/Fabio286/antares/pull/44)]
|
<!-- prettier-ignore-start -->
|
||||||
**Portugues (Brasil)** / [Daniel Eduardo](https://github.com/daeleduardo) [[#54](https://github.com/Fabio286/antares/pull/54)]
|
<!-- markdownlint-disable -->
|
||||||
**Deutsch (Deutschland)** / [Christian Ratz](https://github.com/digitalgopnik) [[#74](https://github.com/Fabio286/antares/pull/74)]
|
<table>
|
||||||
**Vietnamese** / [Ngô Quốc Đạt](https://github.com/datlechin) [[#111](https://github.com/Fabio286/antares/pull/111)]
|
<tr>
|
||||||
**Japanese** / [Isamu Sugiura](https://github.com/IsamuSugi) [[#115](https://github.com/Fabio286/antares/pull/115)]
|
<td align="center"><a href="https://fabiodistasio.it/"><img src="https://avatars.githubusercontent.com/u/31471771?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fabio Di Stasio</b></sub></a><br /><a href="https://github.com/Fabio286/antares/commits?author=Fabio286" title="Code">💻</a> <a href="#translation-Fabio286" title="Translation">🌍</a> <a href="https://github.com/Fabio286/antares/commits?author=Fabio286" title="Documentation">📖</a></td>
|
||||||
|
<td align="center"><a href="https://www.linkedin.com/in/giulioganci/"><img src="https://avatars.githubusercontent.com/u/4192159?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Giulio Ganci</b></sub></a><br /><a href="https://github.com/Fabio286/antares/commits?author=toriphes" title="Code">💻</a></td>
|
||||||
|
<td align="center"><a href="https://christianratz.de/"><img src="https://avatars.githubusercontent.com/u/2630316?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Christian Ratz</b></sub></a><br /><a href="https://github.com/Fabio286/antares/commits?author=digitalgopnik" title="Code">💻</a> <a href="#translation-digitalgopnik" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://reverb6821.github.io/"><img src="https://avatars.githubusercontent.com/u/55198803?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Giuseppe Gigliotti</b></sub></a><br /><a href="#translation-reverb6821" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/Mohd-PH"><img src="https://avatars.githubusercontent.com/u/9362157?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mohd-PH</b></sub></a><br /><a href="#translation-Mohd-PH" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/hongkfui"><img src="https://avatars.githubusercontent.com/u/37477191?v=4?s=100" width="100px;" alt=""/><br /><sub><b>hongkfui</b></sub></a><br /><a href="#translation-hongkfui" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/MrAnyx"><img src="https://avatars.githubusercontent.com/u/44176707?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Robin</b></sub></a><br /><a href="#translation-MrAnyx" title="Translation">🌍</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><a href="https://github.com/daeleduardo"><img src="https://avatars.githubusercontent.com/u/8599078?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Eduardo</b></sub></a><br /><a href="#translation-daeleduardo" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://ngoquocdat.com/"><img src="https://avatars.githubusercontent.com/u/56961917?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ngô Quốc Đạt</b></sub></a><br /><a href="#translation-datlechin" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/IsamuSugi"><img src="https://avatars.githubusercontent.com/u/7746658?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Isamu Sugiura</b></sub></a><br /><a href="#translation-IsamuSugi" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="http://rsacchetto.nexxontech.it/"><img src="https://avatars.githubusercontent.com/u/18429412?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Riccardo Sacchetto</b></sub></a><br /><a href="#platform-Occhioverde" title="Packaging/porting to new platform">📦</a></td>
|
||||||
|
<td align="center"><a href="https://kilianstallinger.com"><img src="https://avatars.githubusercontent.com/u/5290318?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kilian Stallinger</b></sub></a><br /><a href="https://github.com/Fabio286/antares/commits?author=kilianstallz" title="Code">💻</a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- markdownlint-restore -->
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
|
|
||||||
|
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||||
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"include": [
|
|
||||||
"./src/renderer/**/*"
|
|
||||||
]
|
|
||||||
}
|
|
64
package.json
@@ -1,27 +1,46 @@
|
|||||||
{
|
{
|
||||||
"name": "antares",
|
"name": "antares",
|
||||||
"productName": "Antares",
|
"productName": "Antares",
|
||||||
"version": "0.3.8",
|
"version": "0.4.0",
|
||||||
"description": "A cross-platform easy to use SQL client.",
|
"description": "A modern, fast and productivity driven SQL client with a focus in UX.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/Fabio286/antares.git",
|
"repository": "https://github.com/Fabio286/antares.git",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "cross-env NODE_ENV=development electron-webpack dev",
|
"debug": "npm run rebuild:electron && npm run debug-runner",
|
||||||
"compile": "electron-webpack",
|
"debug-runner": "node scripts/devRunner.js --remote-debug",
|
||||||
|
"compile": "npm run compile:main && npm run compile:renderer",
|
||||||
|
"compile:main": "webpack --mode=production --config webpack.main.config.js",
|
||||||
|
"compile:renderer": "webpack --mode=production --config webpack.renderer.config.js",
|
||||||
"build": "cross-env NODE_ENV=production npm run compile",
|
"build": "cross-env NODE_ENV=production npm run compile",
|
||||||
"build:local": "npm run build && electron-builder",
|
"build:local": "npm run build && electron-builder",
|
||||||
"build:appx": "npm run build:local -- --win appx",
|
"build:appx": "npm run build:local -- --win appx",
|
||||||
|
"rebuild:electron": "npm run postinstall",
|
||||||
"release": "standard-version",
|
"release": "standard-version",
|
||||||
"release:pre": "npm run release -- --prerelease alpha",
|
"release:pre": "npm run release -- --prerelease alpha",
|
||||||
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"test": "npm run lint",
|
"test": "npm run lint",
|
||||||
"lint": "eslint . --ext .js,.vue && stylelint \"./src/**/*.{css,scss,sass,vue}\"",
|
"lint": "eslint . --ext .js,.vue && stylelint \"./src/**/*.{css,scss,sass,vue}\"",
|
||||||
"lint:fix": "eslint . --ext .js,.vue --fix && stylelint \"./src/**/*.{css,scss,sass,vue}\" --fix",
|
"lint:fix": "eslint . --ext .js,.vue --fix && stylelint \"./src/**/*.{css,scss,sass,vue}\" --fix",
|
||||||
"postinstall": "electron-builder install-app-deps"
|
"contributors:add": "all-contributors add",
|
||||||
|
"contributors:generate": "all-contributors generate"
|
||||||
},
|
},
|
||||||
"author": "Fabio Di Stasio <fabio286@gmail.com>",
|
"author": "Fabio Di Stasio <fabio286@gmail.com>",
|
||||||
|
"main": "./dist/main.js",
|
||||||
"build": {
|
"build": {
|
||||||
"appId": "com.fabio286.antares",
|
"appId": "com.fabio286.antares",
|
||||||
"artifactName": "${productName}-${version}-${os}_${arch}.${ext}",
|
"artifactName": "${productName}-${version}-${os}_${arch}.${ext}",
|
||||||
|
"asar": true,
|
||||||
|
"buildDependenciesFromSource": true,
|
||||||
|
"directories": {
|
||||||
|
"output": "build",
|
||||||
|
"buildResources": "assets"
|
||||||
|
},
|
||||||
|
"asarUnpack": "**\\*.{node,dll}",
|
||||||
|
"files": [
|
||||||
|
"dist/**/*",
|
||||||
|
"node_modules",
|
||||||
|
"package.json"
|
||||||
|
],
|
||||||
"win": {
|
"win": {
|
||||||
"target": [
|
"target": [
|
||||||
"nsis",
|
"nsis",
|
||||||
@@ -61,7 +80,8 @@
|
|||||||
"artifactName": "${productName}-${version}-portable.exe"
|
"artifactName": "${productName}-${version}-portable.exe"
|
||||||
},
|
},
|
||||||
"appx": {
|
"appx": {
|
||||||
"displayName": "Antares SQL Client",
|
"displayName": "Antares SQL",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
"identityName": "62514FabioDiStasio.AntaresSQLClient",
|
"identityName": "62514FabioDiStasio.AntaresSQLClient",
|
||||||
"publisher": "CN=1A2729ED-865C-41D2-9038-39AE2A63AA52",
|
"publisher": "CN=1A2729ED-865C-41D2-9038-39AE2A63AA52",
|
||||||
"applicationId": "FabioDiStasio.AntaresSQLClient"
|
"applicationId": "FabioDiStasio.AntaresSQLClient"
|
||||||
@@ -81,20 +101,16 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"electronWebpack": {
|
|
||||||
"renderer": {
|
|
||||||
"webpackConfig": "webpack.config.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron/remote": "^2.0.1",
|
"@electron/remote": "^2.0.1",
|
||||||
"@mdi/font": "^6.1.95",
|
"@mdi/font": "^6.1.95",
|
||||||
"ace-builds": "^1.4.13",
|
"ace-builds": "^1.4.13",
|
||||||
|
"better-sqlite3": "^7.4.4",
|
||||||
"electron-log": "^4.4.1",
|
"electron-log": "^4.4.1",
|
||||||
"electron-store": "^8.0.1",
|
"electron-store": "^8.0.1",
|
||||||
"electron-updater": "^4.3.9",
|
"electron-updater": "^4.3.9",
|
||||||
"faker": "^5.5.3",
|
"faker": "^5.5.3",
|
||||||
"marked": "^3.0.4",
|
"marked": "^4.0.0",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"mysql2": "^2.3.2",
|
"mysql2": "^2.3.2",
|
||||||
"pg": "^8.7.1",
|
"pg": "^8.7.1",
|
||||||
@@ -110,28 +126,40 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/eslint-parser": "^7.15.7",
|
"@babel/eslint-parser": "^7.15.7",
|
||||||
|
"@babel/preset-env": "^7.15.8",
|
||||||
|
"all-contributors-cli": "^6.20.0",
|
||||||
"babel-loader": "^8.2.3",
|
"babel-loader": "^8.2.3",
|
||||||
|
"chalk": "^4.1.2",
|
||||||
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"cross-env": "^7.0.2",
|
"cross-env": "^7.0.2",
|
||||||
"electron": "^15.3.0",
|
"css-loader": "^6.5.0",
|
||||||
|
"electron": "^16.0.1",
|
||||||
"electron-builder": "^22.13.1",
|
"electron-builder": "^22.13.1",
|
||||||
"electron-devtools-installer": "^3.2.0",
|
"electron-devtools-installer": "^3.2.0",
|
||||||
"electron-webpack": "^2.8.2",
|
|
||||||
"electron-webpack-vue": "^2.4.0",
|
|
||||||
"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.1.0",
|
"eslint-plugin-promise": "^5.1.0",
|
||||||
"eslint-plugin-vue": "^7.18.0",
|
"eslint-plugin-vue": "^8.0.3",
|
||||||
|
"file-loader": "^6.2.0",
|
||||||
|
"html-webpack-plugin": "^5.5.0",
|
||||||
|
"mini-css-extract-plugin": "^2.4.3",
|
||||||
|
"node-loader": "^2.0.0",
|
||||||
|
"progress-webpack-plugin": "^1.0.12",
|
||||||
"sass": "^1.42.1",
|
"sass": "^1.42.1",
|
||||||
"sass-loader": "^10.2.0",
|
"sass-loader": "^12.3.0",
|
||||||
"standard-version": "^9.3.1",
|
"standard-version": "^9.3.1",
|
||||||
|
"style-loader": "^3.3.1",
|
||||||
"stylelint": "^13.13.1",
|
"stylelint": "^13.13.1",
|
||||||
"stylelint-config-standard": "^22.0.0",
|
"stylelint-config-standard": "^22.0.0",
|
||||||
"stylelint-scss": "^3.21.0",
|
"stylelint-scss": "^3.21.0",
|
||||||
|
"tree-kill": "^1.2.2",
|
||||||
"vue": "^2.6.14",
|
"vue": "^2.6.14",
|
||||||
"vue-loader": "^15.9.8",
|
"vue-loader": "^15.9.8",
|
||||||
"vue-template-compiler": "^2.6.14",
|
"vue-template-compiler": "^2.6.14",
|
||||||
"webpack": "^4.46.0"
|
"webpack": "^5.60.0",
|
||||||
|
"webpack-cli": "^4.9.1",
|
||||||
|
"webpack-dev-server": "^4.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
131
scripts/devRunner.js
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
process.env.NODE_ENV = 'development';
|
||||||
|
// process.env.ELECTRON_ENABLE_LOGGING = true
|
||||||
|
|
||||||
|
const chalk = require('chalk');
|
||||||
|
const electron = require('electron');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const WebpackDevServer = require('webpack-dev-server');
|
||||||
|
const kill = require('tree-kill');
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const { spawn } = require('child_process');
|
||||||
|
|
||||||
|
const mainConfig = require('../webpack.main.config');
|
||||||
|
const rendererConfig = require('../webpack.renderer.config');
|
||||||
|
// const workersConfig = require('../webpack.workers.config');
|
||||||
|
|
||||||
|
let electronProcess = null;
|
||||||
|
let manualRestart = null;
|
||||||
|
const remoteDebugging = process.argv.includes('--remote-debug');
|
||||||
|
|
||||||
|
if (remoteDebugging) {
|
||||||
|
// disable dvtools open in electron
|
||||||
|
process.env.RENDERER_REMOTE_DEBUGGING = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function killElectron (pid) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (pid) {
|
||||||
|
kill(pid, 'SIGKILL', err => {
|
||||||
|
if (err) reject(err);
|
||||||
|
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function restartElectron () {
|
||||||
|
console.log(chalk.gray('\nStarting electron...'));
|
||||||
|
|
||||||
|
const { pid } = electronProcess || {};
|
||||||
|
await killElectron(pid);
|
||||||
|
|
||||||
|
electronProcess = spawn(electron, [
|
||||||
|
path.join(__dirname, '../dist/main.js'),
|
||||||
|
// '--enable-logging', // Enable to show logs from all electron processes
|
||||||
|
remoteDebugging ? '--inspect=9222' : '',
|
||||||
|
remoteDebugging ? '--remote-debugging-port=9223' : ''
|
||||||
|
]);
|
||||||
|
|
||||||
|
electronProcess.stdout.on('data', data => {
|
||||||
|
console.log(chalk.white(data.toString()));
|
||||||
|
});
|
||||||
|
|
||||||
|
electronProcess.stderr.on('data', data => {
|
||||||
|
console.error(chalk.red(data.toString()));
|
||||||
|
});
|
||||||
|
|
||||||
|
electronProcess.on('exit', (code, signal) => {
|
||||||
|
if (!manualRestart) process.exit(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function startMain () {
|
||||||
|
const webpackSetup = webpack(mainConfig);
|
||||||
|
|
||||||
|
webpackSetup.compilers.forEach((compiler) => {
|
||||||
|
const { name } = compiler;
|
||||||
|
|
||||||
|
switch (name) {
|
||||||
|
case 'workers':
|
||||||
|
compiler.hooks.afterEmit.tap('afterEmit', async () => {
|
||||||
|
console.log(chalk.gray(`\nCompiled ${name} script!`));
|
||||||
|
console.log(
|
||||||
|
chalk.gray(`\nWatching file changes for ${name} script...`)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'main':
|
||||||
|
default:
|
||||||
|
compiler.hooks.afterEmit.tap('afterEmit', async () => {
|
||||||
|
console.log(chalk.gray(`\nCompiled ${name} script!`));
|
||||||
|
|
||||||
|
manualRestart = true;
|
||||||
|
await restartElectron();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
manualRestart = false;
|
||||||
|
}, 2500);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
chalk.gray(`\nWatching file changes for ${name} script...`)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
webpackSetup.watch({ aggregateTimeout: 500 }, err => {
|
||||||
|
if (err) console.error(chalk.red(err));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function startRenderer (callback) {
|
||||||
|
const compiler = webpack(rendererConfig);
|
||||||
|
const { name } = compiler;
|
||||||
|
|
||||||
|
compiler.hooks.afterEmit.tap('afterEmit', () => {
|
||||||
|
console.log(chalk.gray(`\nCompiled ${name} script!`));
|
||||||
|
console.log(chalk.gray(`\nWatching file changes for ${name} script...`));
|
||||||
|
});
|
||||||
|
|
||||||
|
const server = new WebpackDevServer(compiler, {
|
||||||
|
hot: true,
|
||||||
|
port: 9080,
|
||||||
|
client: {
|
||||||
|
overlay: true,
|
||||||
|
logging: 'warn'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.startCallback(err => {
|
||||||
|
if (err) console.error(chalk.red(err));
|
||||||
|
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
startRenderer(startMain);
|
@@ -8,6 +8,9 @@ module.exports = {
|
|||||||
collations: false,
|
collations: false,
|
||||||
engines: false,
|
engines: false,
|
||||||
connectionSchema: false,
|
connectionSchema: false,
|
||||||
|
sslConnection: false,
|
||||||
|
sshConnection: false,
|
||||||
|
fileConnection: false,
|
||||||
// Tools
|
// Tools
|
||||||
processesList: false,
|
processesList: false,
|
||||||
usersManagement: false,
|
usersManagement: false,
|
||||||
@@ -33,7 +36,11 @@ module.exports = {
|
|||||||
schedulerAdd: false,
|
schedulerAdd: false,
|
||||||
databaseEdit: false,
|
databaseEdit: false,
|
||||||
schemaEdit: false,
|
schemaEdit: false,
|
||||||
|
schemaDrop: false,
|
||||||
tableSettings: false,
|
tableSettings: false,
|
||||||
|
tableOptions: false,
|
||||||
|
tableArray: false,
|
||||||
|
tableRealCount: false,
|
||||||
viewSettings: false,
|
viewSettings: false,
|
||||||
triggerSettings: false,
|
triggerSettings: false,
|
||||||
triggerFunctionSettings: false,
|
triggerFunctionSettings: false,
|
||||||
@@ -45,14 +52,13 @@ module.exports = {
|
|||||||
sortableFields: false,
|
sortableFields: false,
|
||||||
unsigned: false,
|
unsigned: false,
|
||||||
nullable: false,
|
nullable: false,
|
||||||
|
nullablePrimary: false,
|
||||||
zerofill: false,
|
zerofill: false,
|
||||||
tableOptions: false,
|
|
||||||
autoIncrement: false,
|
autoIncrement: false,
|
||||||
comment: false,
|
comment: false,
|
||||||
collation: false,
|
collation: false,
|
||||||
definer: false,
|
definer: false,
|
||||||
onUpdate: false,
|
onUpdate: false,
|
||||||
tableArray: false,
|
|
||||||
viewAlgorithm: false,
|
viewAlgorithm: false,
|
||||||
viewSqlSecurity: false,
|
viewSqlSecurity: false,
|
||||||
viewUpdateOption: false,
|
viewUpdateOption: false,
|
||||||
@@ -72,8 +78,10 @@ module.exports = {
|
|||||||
triggerTableInName: false,
|
triggerTableInName: false,
|
||||||
triggerUpdateColumns: false,
|
triggerUpdateColumns: false,
|
||||||
triggerOnlyRename: false,
|
triggerOnlyRename: false,
|
||||||
|
triggerEnableDisable: false,
|
||||||
triggerFunctionSql: false,
|
triggerFunctionSql: false,
|
||||||
triggerFunctionlanguages: false,
|
triggerFunctionlanguages: false,
|
||||||
parametersLength: false,
|
parametersLength: false,
|
||||||
languages: false
|
languages: false,
|
||||||
|
readOnlyMode: false
|
||||||
};
|
};
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
maria: require('./mysql'),
|
maria: require('./mysql'),
|
||||||
mysql: require('./mysql'),
|
mysql: require('./mysql'),
|
||||||
pg: require('./postgresql')
|
pg: require('./postgresql'),
|
||||||
|
sqlite: require('./sqlite')
|
||||||
};
|
};
|
||||||
|
@@ -10,6 +10,8 @@ module.exports = {
|
|||||||
connectionSchema: true,
|
connectionSchema: true,
|
||||||
collations: true,
|
collations: true,
|
||||||
engines: true,
|
engines: true,
|
||||||
|
sslConnection: true,
|
||||||
|
sshConnection: true,
|
||||||
// Tools
|
// Tools
|
||||||
processesList: true,
|
processesList: true,
|
||||||
// Structure
|
// Structure
|
||||||
@@ -30,6 +32,7 @@ module.exports = {
|
|||||||
functionAdd: true,
|
functionAdd: true,
|
||||||
schedulerAdd: true,
|
schedulerAdd: true,
|
||||||
schemaEdit: true,
|
schemaEdit: true,
|
||||||
|
schemaDrop: true,
|
||||||
tableSettings: true,
|
tableSettings: true,
|
||||||
viewSettings: true,
|
viewSettings: true,
|
||||||
triggerSettings: true,
|
triggerSettings: true,
|
||||||
@@ -59,5 +62,6 @@ module.exports = {
|
|||||||
functionDeterministic: true,
|
functionDeterministic: true,
|
||||||
functionDataAccess: true,
|
functionDataAccess: true,
|
||||||
functionSql: 'BEGIN\r\n\r\nEND',
|
functionSql: 'BEGIN\r\n\r\nEND',
|
||||||
parametersLength: true
|
parametersLength: true,
|
||||||
|
readOnlyMode: true
|
||||||
};
|
};
|
||||||
|
@@ -8,9 +8,12 @@ module.exports = {
|
|||||||
defaultDatabase: 'postgres',
|
defaultDatabase: 'postgres',
|
||||||
// Core
|
// Core
|
||||||
database: true,
|
database: true,
|
||||||
|
sslConnection: true,
|
||||||
|
sshConnection: true,
|
||||||
// Tools
|
// Tools
|
||||||
processesList: true,
|
processesList: true,
|
||||||
// Structure
|
// Structure
|
||||||
|
schemas: true,
|
||||||
tables: true,
|
tables: true,
|
||||||
views: true,
|
views: true,
|
||||||
triggers: true,
|
triggers: true,
|
||||||
@@ -26,6 +29,7 @@ module.exports = {
|
|||||||
triggerFunctionAdd: true,
|
triggerFunctionAdd: true,
|
||||||
routineAdd: true,
|
routineAdd: true,
|
||||||
functionAdd: true,
|
functionAdd: true,
|
||||||
|
schemaDrop: true,
|
||||||
databaseEdit: false,
|
databaseEdit: false,
|
||||||
tableSettings: true,
|
tableSettings: true,
|
||||||
viewSettings: true,
|
viewSettings: true,
|
||||||
@@ -50,5 +54,7 @@ module.exports = {
|
|||||||
triggerMultipleEvents: true,
|
triggerMultipleEvents: true,
|
||||||
triggerTableInName: true,
|
triggerTableInName: true,
|
||||||
triggerOnlyRename: false,
|
triggerOnlyRename: false,
|
||||||
languages: ['sql', 'plpgsql', 'c', 'internal']
|
triggerEnableDisable: true,
|
||||||
|
languages: ['sql', 'plpgsql', 'c', 'internal'],
|
||||||
|
readOnlyMode: true
|
||||||
};
|
};
|
||||||
|
27
src/common/customizations/sqlite.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
module.exports = {
|
||||||
|
// Core
|
||||||
|
fileConnection: true,
|
||||||
|
// Structure
|
||||||
|
schemas: false,
|
||||||
|
tables: true,
|
||||||
|
views: true,
|
||||||
|
triggers: true,
|
||||||
|
// Settings
|
||||||
|
elementsWrapper: '',
|
||||||
|
stringsWrapper: '"',
|
||||||
|
tableAdd: true,
|
||||||
|
viewAdd: true,
|
||||||
|
triggerAdd: true,
|
||||||
|
schemaEdit: false,
|
||||||
|
tableSettings: true,
|
||||||
|
tableRealCount: true,
|
||||||
|
viewSettings: true,
|
||||||
|
triggerSettings: true,
|
||||||
|
indexes: true,
|
||||||
|
foreigns: true,
|
||||||
|
sortableFields: true,
|
||||||
|
nullable: true,
|
||||||
|
nullablePrimary: true,
|
||||||
|
triggerSql: 'BEGIN\r\n\r\nEND',
|
||||||
|
readOnlyMode: true
|
||||||
|
};
|
137
src/common/data-types/sqlite.js
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
group: 'integer',
|
||||||
|
types: [
|
||||||
|
{
|
||||||
|
name: 'INT',
|
||||||
|
length: true,
|
||||||
|
collation: false,
|
||||||
|
unsigned: true,
|
||||||
|
zerofill: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'INTEGER',
|
||||||
|
length: true,
|
||||||
|
collation: false,
|
||||||
|
unsigned: true,
|
||||||
|
zerofill: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'BIGINT',
|
||||||
|
length: true,
|
||||||
|
collation: false,
|
||||||
|
unsigned: true,
|
||||||
|
zerofill: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'NUMERIC',
|
||||||
|
length: true,
|
||||||
|
collation: false,
|
||||||
|
unsigned: true,
|
||||||
|
zerofill: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'BOOLEAN',
|
||||||
|
length: false,
|
||||||
|
collation: false,
|
||||||
|
unsigned: true,
|
||||||
|
zerofill: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: 'float',
|
||||||
|
types: [
|
||||||
|
{
|
||||||
|
name: 'FLOAT',
|
||||||
|
length: true,
|
||||||
|
collation: false,
|
||||||
|
unsigned: false,
|
||||||
|
zerofill: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'REAL',
|
||||||
|
length: true,
|
||||||
|
collation: false,
|
||||||
|
unsigned: false,
|
||||||
|
zerofill: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: 'string',
|
||||||
|
types: [
|
||||||
|
{
|
||||||
|
name: 'CHAR',
|
||||||
|
length: true,
|
||||||
|
collation: true,
|
||||||
|
unsigned: false,
|
||||||
|
zerofill: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'VARCHAR',
|
||||||
|
length: true,
|
||||||
|
collation: true,
|
||||||
|
unsigned: false,
|
||||||
|
zerofill: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TEXT',
|
||||||
|
length: true,
|
||||||
|
collation: true,
|
||||||
|
unsigned: false,
|
||||||
|
zerofill: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: 'binary',
|
||||||
|
types: [
|
||||||
|
{
|
||||||
|
name: 'BLOB',
|
||||||
|
length: true,
|
||||||
|
collation: false,
|
||||||
|
unsigned: false,
|
||||||
|
zerofill: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: 'time',
|
||||||
|
types: [
|
||||||
|
{
|
||||||
|
name: 'DATE',
|
||||||
|
length: false,
|
||||||
|
collation: false,
|
||||||
|
unsigned: false,
|
||||||
|
zerofill: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TIME',
|
||||||
|
length: true,
|
||||||
|
collation: false,
|
||||||
|
unsigned: false,
|
||||||
|
zerofill: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'DATETIME',
|
||||||
|
length: true,
|
||||||
|
collation: false,
|
||||||
|
unsigned: false,
|
||||||
|
zerofill: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: 'other',
|
||||||
|
types: [
|
||||||
|
{
|
||||||
|
name: 'NONE',
|
||||||
|
length: false,
|
||||||
|
collation: false,
|
||||||
|
unsigned: false,
|
||||||
|
zerofill: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
5
src/common/index-types/sqlite.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = [
|
||||||
|
'PRIMARY',
|
||||||
|
'INDEX',
|
||||||
|
'UNIQUE'
|
||||||
|
];
|
@@ -9,12 +9,16 @@ export default connections => {
|
|||||||
port: +conn.port,
|
port: +conn.port,
|
||||||
user: conn.user,
|
user: conn.user,
|
||||||
password: conn.password,
|
password: conn.password,
|
||||||
application_name: 'Antares SQL'
|
application_name: 'Antares SQL',
|
||||||
|
readonly: conn.readonly
|
||||||
};
|
};
|
||||||
|
|
||||||
if (conn.database)
|
if (conn.database)
|
||||||
params.database = conn.database;
|
params.database = conn.database;
|
||||||
|
|
||||||
|
if (conn.databasePath)
|
||||||
|
params.databasePath = conn.databasePath;
|
||||||
|
|
||||||
if (conn.ssl) {
|
if (conn.ssl) {
|
||||||
params.ssl = {
|
params.ssl = {
|
||||||
key: conn.key ? fs.readFileSync(conn.key) : null,
|
key: conn.key ? fs.readFileSync(conn.key) : null,
|
||||||
@@ -62,12 +66,16 @@ export default connections => {
|
|||||||
port: +conn.port,
|
port: +conn.port,
|
||||||
user: conn.user,
|
user: conn.user,
|
||||||
password: conn.password,
|
password: conn.password,
|
||||||
application_name: 'Antares SQL'
|
application_name: 'Antares SQL',
|
||||||
|
readonly: conn.readonly
|
||||||
};
|
};
|
||||||
|
|
||||||
if (conn.database)
|
if (conn.database)
|
||||||
params.database = conn.database;
|
params.database = conn.database;
|
||||||
|
|
||||||
|
if (conn.databasePath)
|
||||||
|
params.databasePath = conn.databasePath;
|
||||||
|
|
||||||
if (conn.schema)
|
if (conn.schema)
|
||||||
params.schema = conn.schema;
|
params.schema = conn.schema;
|
||||||
|
|
||||||
|
@@ -40,4 +40,17 @@ export default (connections) => {
|
|||||||
return { status: 'error', response: err.toString() };
|
return { status: 'error', response: err.toString() };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('toggle-scheduler', async (event, params) => {
|
||||||
|
try {
|
||||||
|
if (!params.enabled)
|
||||||
|
await connections[params.uid].enableEvent({ ...params });
|
||||||
|
else
|
||||||
|
await connections[params.uid].disableEvent({ ...params });
|
||||||
|
return { status: 'success' };
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return { status: 'error', response: err.toString() };
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
@@ -84,7 +84,7 @@ export default (connections) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('update-table-cell', async (event, params) => {
|
ipcMain.handle('update-table-cell', async (event, params) => {
|
||||||
delete params.row._id;
|
delete params.row._antares_id;
|
||||||
|
|
||||||
try { // TODO: move to client classes
|
try { // TODO: move to client classes
|
||||||
let escapedParam;
|
let escapedParam;
|
||||||
@@ -102,6 +102,9 @@ export default (connections) => {
|
|||||||
case 'pg':
|
case 'pg':
|
||||||
escapedParam = `'${params.content.replaceAll('\'', '\'\'')}'`;
|
escapedParam = `'${params.content.replaceAll('\'', '\'\'')}'`;
|
||||||
break;
|
break;
|
||||||
|
case 'sqlite':
|
||||||
|
escapedParam = `'${params.content.replaceAll('\'', '\'\'')}'`;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ARRAY.includes(params.type))
|
else if (ARRAY.includes(params.type))
|
||||||
@@ -122,6 +125,10 @@ export default (connections) => {
|
|||||||
fileBlob = fs.readFileSync(params.content);
|
fileBlob = fs.readFileSync(params.content);
|
||||||
escapedParam = `decode('${fileBlob.toString('hex')}', 'hex')`;
|
escapedParam = `decode('${fileBlob.toString('hex')}', 'hex')`;
|
||||||
break;
|
break;
|
||||||
|
case 'sqlite':
|
||||||
|
fileBlob = fs.readFileSync(params.content);
|
||||||
|
escapedParam = `X'${fileBlob.toString('hex')}'`;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
reload = true;
|
reload = true;
|
||||||
}
|
}
|
||||||
@@ -134,6 +141,9 @@ export default (connections) => {
|
|||||||
case 'pg':
|
case 'pg':
|
||||||
escapedParam = 'decode(\'\', \'hex\')';
|
escapedParam = 'decode(\'\', \'hex\')';
|
||||||
break;
|
break;
|
||||||
|
case 'sqlite':
|
||||||
|
escapedParam = 'X\'\'';
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,7 +198,7 @@ export default (connections) => {
|
|||||||
const fieldName = Object.keys(row)[0].includes('.') ? `${params.table}.${params.primary}` : params.primary;
|
const fieldName = Object.keys(row)[0].includes('.') ? `${params.table}.${params.primary}` : params.primary;
|
||||||
|
|
||||||
return typeof row[fieldName] === 'string'
|
return typeof row[fieldName] === 'string'
|
||||||
? `"${row[fieldName]}"`
|
? `'${row[fieldName]}'`
|
||||||
: row[fieldName];
|
: row[fieldName];
|
||||||
}).join(',');
|
}).join(',');
|
||||||
|
|
||||||
|
@@ -40,4 +40,17 @@ export default (connections) => {
|
|||||||
return { status: 'error', response: err.toString() };
|
return { status: 'error', response: err.toString() };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('toggle-trigger', async (event, params) => {
|
||||||
|
try {
|
||||||
|
if (!params.enabled)
|
||||||
|
await connections[params.uid].enableTrigger(params);
|
||||||
|
else
|
||||||
|
await connections[params.uid].disableTrigger(params);
|
||||||
|
return { status: 'success' };
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return { status: 'error', response: err.toString() };
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
@@ -2,6 +2,7 @@ import { ipcMain } from 'electron';
|
|||||||
import { autoUpdater } from 'electron-updater';
|
import { autoUpdater } from 'electron-updater';
|
||||||
import Store from 'electron-store';
|
import Store from 'electron-store';
|
||||||
const persistentStore = new Store({ name: 'settings' });
|
const persistentStore = new Store({ name: 'settings' });
|
||||||
|
const isMacOS = process.platform === 'darwin';
|
||||||
|
|
||||||
let mainWindow;
|
let mainWindow;
|
||||||
autoUpdater.allowPrerelease = persistentStore.get('allow_prerelease', true);
|
autoUpdater.allowPrerelease = persistentStore.get('allow_prerelease', true);
|
||||||
@@ -11,6 +12,9 @@ export default () => {
|
|||||||
mainWindow = event;
|
mainWindow = event;
|
||||||
if (process.windowsStore || (process.platform === 'linux' && !process.env.APPIMAGE))
|
if (process.windowsStore || (process.platform === 'linux' && !process.env.APPIMAGE))
|
||||||
mainWindow.reply('no-auto-update');
|
mainWindow.reply('no-auto-update');
|
||||||
|
else if (isMacOS) { // Temporary solution on MacOS for unsigned app updates
|
||||||
|
autoUpdater.autoDownload = false;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
autoUpdater.checkForUpdatesAndNotify().catch(() => {
|
autoUpdater.checkForUpdatesAndNotify().catch(() => {
|
||||||
mainWindow.reply('check-failed');
|
mainWindow.reply('check-failed');
|
||||||
@@ -28,7 +32,10 @@ export default () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
autoUpdater.on('update-available', () => {
|
autoUpdater.on('update-available', () => {
|
||||||
mainWindow.reply('update-available');
|
if (isMacOS)
|
||||||
|
mainWindow.reply('link-to-download');
|
||||||
|
else
|
||||||
|
mainWindow.reply('update-available');
|
||||||
});
|
});
|
||||||
|
|
||||||
autoUpdater.on('update-not-available', () => {
|
autoUpdater.on('update-not-available', () => {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
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';
|
||||||
|
|
||||||
const queryLogger = sql => {
|
const queryLogger = sql => {
|
||||||
// Remove comments, newlines and multiple spaces
|
// Remove comments, newlines and multiple spaces
|
||||||
@@ -37,6 +38,8 @@ export class ClientsFactory {
|
|||||||
return new MySQLClient(args);
|
return new MySQLClient(args);
|
||||||
case 'pg':
|
case 'pg':
|
||||||
return new PostgreSQLClient(args);
|
return new PostgreSQLClient(args);
|
||||||
|
case 'sqlite':
|
||||||
|
return new SQLiteClient(args);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unknown database client: ${args.client}`);
|
throw new Error(`Unknown database client: ${args.client}`);
|
||||||
}
|
}
|
||||||
|
@@ -133,8 +133,12 @@ export class MySQLClient extends AntaresCore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._poolSize)
|
if (!this._poolSize) {
|
||||||
this._connection = await mysql.createConnection(dbConfig);
|
this._connection = await mysql.createConnection(dbConfig);
|
||||||
|
|
||||||
|
if (this._params.readonly)
|
||||||
|
await this.raw('SET SESSION TRANSACTION READ ONLY');
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
this._connection = mysql.createPool({
|
this._connection = mysql.createPool({
|
||||||
...dbConfig,
|
...dbConfig,
|
||||||
@@ -146,6 +150,12 @@ export class MySQLClient extends AntaresCore {
|
|||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (this._params.readonly) {
|
||||||
|
this._connection.on('connection', connection => {
|
||||||
|
connection.query('SET SESSION TRANSACTION READ ONLY');
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +197,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
|
|
||||||
const tablesArr = [];
|
const tablesArr = [];
|
||||||
const triggersArr = [];
|
const triggersArr = [];
|
||||||
|
let schemaSize = 0;
|
||||||
|
|
||||||
for (const db of filteredDatabases) {
|
for (const db of filteredDatabases) {
|
||||||
if (!schemas.has(db.Database)) continue;
|
if (!schemas.has(db.Database)) continue;
|
||||||
@@ -224,6 +235,9 @@ export class MySQLClient extends AntaresCore {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tableSize = table.Data_length + table.Index_length;
|
||||||
|
schemaSize += tableSize;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: table.Name,
|
name: table.Name,
|
||||||
type: tableType,
|
type: tableType,
|
||||||
@@ -232,7 +246,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
updated: table.Update_time,
|
updated: table.Update_time,
|
||||||
engine: table.Engine,
|
engine: table.Engine,
|
||||||
comment: table.Comment,
|
comment: table.Comment,
|
||||||
size: table.Data_length + table.Index_length,
|
size: tableSize,
|
||||||
autoIncrement: table.Auto_increment,
|
autoIncrement: table.Auto_increment,
|
||||||
collation: table.Collation
|
collation: table.Collation
|
||||||
};
|
};
|
||||||
@@ -276,7 +290,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
body: scheduler.EVENT_BODY,
|
body: scheduler.EVENT_BODY,
|
||||||
starts: scheduler.STARTS,
|
starts: scheduler.STARTS,
|
||||||
ends: scheduler.ENDS,
|
ends: scheduler.ENDS,
|
||||||
status: scheduler.STATUS,
|
enabled: scheduler.STATUS === 'ENABLED',
|
||||||
executeAt: scheduler.EXECUTE_AT,
|
executeAt: scheduler.EXECUTE_AT,
|
||||||
intervalField: scheduler.INTERVAL_FIELD,
|
intervalField: scheduler.INTERVAL_FIELD,
|
||||||
intervalValue: scheduler.INTERVAL_VALUE,
|
intervalValue: scheduler.INTERVAL_VALUE,
|
||||||
@@ -309,6 +323,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
name: db.Database,
|
name: db.Database,
|
||||||
|
size: schemaSize,
|
||||||
tables: remappedTables,
|
tables: remappedTables,
|
||||||
functions: remappedFunctions,
|
functions: remappedFunctions,
|
||||||
procedures: remappedProcedures,
|
procedures: remappedProcedures,
|
||||||
@@ -319,6 +334,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
else {
|
else {
|
||||||
return {
|
return {
|
||||||
name: db.Database,
|
name: db.Database,
|
||||||
|
size: 0,
|
||||||
tables: [],
|
tables: [],
|
||||||
functions: [],
|
functions: [],
|
||||||
procedures: [],
|
procedures: [],
|
||||||
@@ -565,7 +581,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* CREATE DATABASE
|
* CREATE DATABASE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async createSchema (params) {
|
async createSchema (params) {
|
||||||
@@ -575,7 +591,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* ALTER DATABASE
|
* ALTER DATABASE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async alterSchema (params) {
|
async alterSchema (params) {
|
||||||
@@ -585,7 +601,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* DROP DATABASE
|
* DROP DATABASE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async dropSchema (params) {
|
async dropSchema (params) {
|
||||||
@@ -625,7 +641,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* DROP VIEW
|
* DROP VIEW
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async dropView (params) {
|
async dropView (params) {
|
||||||
@@ -636,7 +652,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* ALTER VIEW
|
* ALTER VIEW
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async alterView (params) {
|
async alterView (params) {
|
||||||
@@ -657,7 +673,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* CREATE VIEW
|
* CREATE VIEW
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async createView (params) {
|
async createView (params) {
|
||||||
@@ -690,7 +706,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* DROP TRIGGER
|
* DROP TRIGGER
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async dropTrigger (params) {
|
async dropTrigger (params) {
|
||||||
@@ -701,7 +717,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* ALTER TRIGGER
|
* ALTER TRIGGER
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async alterTrigger (params) {
|
async alterTrigger (params) {
|
||||||
@@ -723,7 +739,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* CREATE TRIGGER
|
* CREATE TRIGGER
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async createTrigger (params) {
|
async createTrigger (params) {
|
||||||
@@ -797,7 +813,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* DROP PROCEDURE
|
* DROP PROCEDURE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async dropRoutine (params) {
|
async dropRoutine (params) {
|
||||||
@@ -808,7 +824,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* ALTER PROCEDURE
|
* ALTER PROCEDURE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async alterRoutine (params) {
|
async alterRoutine (params) {
|
||||||
@@ -830,7 +846,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* CREATE PROCEDURE
|
* CREATE PROCEDURE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async createRoutine (params) {
|
async createRoutine (params) {
|
||||||
@@ -924,7 +940,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* DROP FUNCTION
|
* DROP FUNCTION
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async dropFunction (params) {
|
async dropFunction (params) {
|
||||||
@@ -935,7 +951,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* ALTER FUNCTION
|
* ALTER FUNCTION
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async alterFunction (params) {
|
async alterFunction (params) {
|
||||||
@@ -957,7 +973,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* CREATE FUNCTION
|
* CREATE FUNCTION
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async createFunction (params) {
|
async createFunction (params) {
|
||||||
@@ -1018,7 +1034,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* DROP EVENT
|
* DROP EVENT
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async dropEvent (params) {
|
async dropEvent (params) {
|
||||||
@@ -1029,7 +1045,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* ALTER EVENT
|
* ALTER EVENT
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async alterEvent (params) {
|
async alterEvent (params) {
|
||||||
@@ -1055,7 +1071,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* CREATE EVENT
|
* CREATE EVENT
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async createEvent (params) {
|
async createEvent (params) {
|
||||||
@@ -1072,6 +1088,16 @@ export class MySQLClient extends AntaresCore {
|
|||||||
return await this.raw(sql, { split: false });
|
return await this.raw(sql, { split: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async enableEvent ({ schema, scheduler }) {
|
||||||
|
const sql = `ALTER EVENT \`${schema}\`.\`${scheduler}\` ENABLE`;
|
||||||
|
return await this.raw(sql, { split: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
async disableEvent ({ schema, scheduler }) {
|
||||||
|
const sql = `ALTER EVENT \`${schema}\`.\`${scheduler}\` DISABLE`;
|
||||||
|
return await this.raw(sql, { split: false });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SHOW COLLATION
|
* SHOW COLLATION
|
||||||
*
|
*
|
||||||
@@ -1189,7 +1215,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* CREATE TABLE
|
* CREATE TABLE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async createTable (params) {
|
async createTable (params) {
|
||||||
@@ -1251,7 +1277,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* ALTER TABLE
|
* ALTER TABLE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async alterTable (params) {
|
async alterTable (params) {
|
||||||
@@ -1386,7 +1412,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* DUPLICATE TABLE
|
* DUPLICATE TABLE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async duplicateTable (params) {
|
async duplicateTable (params) {
|
||||||
@@ -1397,7 +1423,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* TRUNCATE TABLE
|
* TRUNCATE TABLE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async truncateTable (params) {
|
async truncateTable (params) {
|
||||||
@@ -1408,7 +1434,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* DROP TABLE
|
* DROP TABLE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async dropTable (params) {
|
async dropTable (params) {
|
||||||
|
@@ -9,6 +9,7 @@ function pgToString (value) {
|
|||||||
return value.toString();
|
return value.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
types.setTypeParser(20, a => parseInt(a));// bigint string to number
|
||||||
types.setTypeParser(1082, pgToString); // date
|
types.setTypeParser(1082, pgToString); // date
|
||||||
types.setTypeParser(1083, pgToString); // time
|
types.setTypeParser(1083, pgToString); // time
|
||||||
types.setTypeParser(1114, pgToString); // timestamp
|
types.setTypeParser(1114, pgToString); // timestamp
|
||||||
@@ -104,10 +105,19 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
const client = new Client(dbConfig);
|
const client = new Client(dbConfig);
|
||||||
await client.connect();
|
await client.connect();
|
||||||
this._connection = client;
|
this._connection = client;
|
||||||
|
|
||||||
|
if (this._params.readonly)
|
||||||
|
await this.raw('SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const pool = new Pool({ ...dbConfig, max: this._poolSize });
|
const pool = new Pool({ ...dbConfig, max: this._poolSize });
|
||||||
this._connection = pool;
|
this._connection = pool;
|
||||||
|
|
||||||
|
if (this._params.readonly) {
|
||||||
|
this._connection.on('connect', connection => {
|
||||||
|
connection.query('SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY');
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +153,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
|
|
||||||
const tablesArr = [];
|
const tablesArr = [];
|
||||||
const triggersArr = [];
|
const triggersArr = [];
|
||||||
|
let schemaSize = 0;
|
||||||
|
|
||||||
for (const db of databases) {
|
for (const db of databases) {
|
||||||
if (!schemas.has(db.database)) continue;
|
if (!schemas.has(db.database)) continue;
|
||||||
@@ -168,19 +179,20 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let { rows: triggers } = await this.raw(`
|
let { rows: triggers } = await this.raw(`
|
||||||
SELECT event_object_schema AS table_schema,
|
SELECT
|
||||||
event_object_table AS table_name,
|
pg_class.relname AS table_name,
|
||||||
trigger_schema,
|
pg_trigger.tgname AS trigger_name,
|
||||||
trigger_name,
|
pg_namespace.nspname AS trigger_schema,
|
||||||
string_agg(event_manipulation, ',') AS event,
|
(pg_trigger.tgenabled != 'D')::bool AS enabled
|
||||||
action_timing AS activation,
|
FROM pg_trigger
|
||||||
action_condition AS condition,
|
JOIN pg_class ON pg_trigger.tgrelid = pg_class.oid
|
||||||
action_statement AS definition
|
JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
|
||||||
FROM information_schema.triggers
|
JOIN information_schema.triggers ON information_schema.triggers.trigger_schema = pg_namespace.nspname
|
||||||
|
AND information_schema.triggers.event_object_table = pg_class.relname
|
||||||
|
AND information_schema.triggers.trigger_name = pg_trigger.tgname
|
||||||
WHERE trigger_schema = '${db.database}'
|
WHERE trigger_schema = '${db.database}'
|
||||||
GROUP BY 1,2,3,4,6,7,8
|
GROUP BY 1, 2, 3, 4
|
||||||
ORDER BY table_schema,
|
ORDER BY table_name
|
||||||
table_name
|
|
||||||
`);
|
`);
|
||||||
|
|
||||||
if (triggers.length) {
|
if (triggers.length) {
|
||||||
@@ -196,11 +208,14 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
if (schemas.has(db.database)) {
|
if (schemas.has(db.database)) {
|
||||||
// TABLES
|
// TABLES
|
||||||
const remappedTables = tablesArr.filter(table => table.Db === db.database).map(table => {
|
const remappedTables = tablesArr.filter(table => table.Db === db.database).map(table => {
|
||||||
|
const tableSize = +table.data_length + table.index_length;
|
||||||
|
schemaSize += tableSize;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: table.table_name,
|
name: table.table_name,
|
||||||
type: table.table_type === 'VIEW' ? 'view' : 'table',
|
type: table.table_type === 'VIEW' ? 'view' : 'table',
|
||||||
rows: table.reltuples,
|
rows: table.reltuples,
|
||||||
size: +table.data_length + +table.index_length,
|
size: tableSize,
|
||||||
collation: table.Collation,
|
collation: table.Collation,
|
||||||
comment: table.comment,
|
comment: table.comment,
|
||||||
engine: ''
|
engine: ''
|
||||||
@@ -239,17 +254,16 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
return {
|
return {
|
||||||
name: `${trigger.table_name}.${trigger.trigger_name}`,
|
name: `${trigger.table_name}.${trigger.trigger_name}`,
|
||||||
orgName: trigger.trigger_name,
|
orgName: trigger.trigger_name,
|
||||||
timing: trigger.activation,
|
|
||||||
definer: '',
|
definer: '',
|
||||||
definition: trigger.definition,
|
|
||||||
event: trigger.event,
|
|
||||||
table: trigger.table_name,
|
table: trigger.table_name,
|
||||||
sqlMode: ''
|
sqlMode: '',
|
||||||
|
enabled: trigger.enabled
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: db.database,
|
name: db.database,
|
||||||
|
size: schemaSize,
|
||||||
tables: remappedTables,
|
tables: remappedTables,
|
||||||
functions: remappedFunctions,
|
functions: remappedFunctions,
|
||||||
procedures: remappedProcedures,
|
procedures: remappedProcedures,
|
||||||
@@ -261,6 +275,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
else {
|
else {
|
||||||
return {
|
return {
|
||||||
name: db.database,
|
name: db.database,
|
||||||
|
size: 0,
|
||||||
tables: [],
|
tables: [],
|
||||||
functions: [],
|
functions: [],
|
||||||
procedures: [],
|
procedures: [],
|
||||||
@@ -500,7 +515,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* CREATE SCHEMA
|
* CREATE SCHEMA
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async createSchema (params) {
|
async createSchema (params) {
|
||||||
@@ -510,7 +525,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* ALTER DATABASE
|
* ALTER DATABASE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async alterSchema (params) {
|
async alterSchema (params) {
|
||||||
@@ -520,7 +535,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* DROP DATABASE
|
* DROP DATABASE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof MySQLClient
|
* @memberof MySQLClient
|
||||||
*/
|
*/
|
||||||
async dropSchema (params) {
|
async dropSchema (params) {
|
||||||
@@ -552,7 +567,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* DROP VIEW
|
* DROP VIEW
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
async dropView (params) {
|
async dropView (params) {
|
||||||
@@ -563,7 +578,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* ALTER VIEW
|
* ALTER VIEW
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
async alterView (params) {
|
async alterView (params) {
|
||||||
@@ -579,7 +594,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* CREATE VIEW
|
* CREATE VIEW
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
async createView (params) {
|
async createView (params) {
|
||||||
@@ -597,19 +612,25 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
const [table, triggerName] = trigger.split('.');
|
const [table, triggerName] = trigger.split('.');
|
||||||
|
|
||||||
const results = await this.raw(`
|
const results = await this.raw(`
|
||||||
SELECT event_object_schema AS table_schema,
|
SELECT
|
||||||
event_object_table AS table_name,
|
information_schema.triggers.event_object_schema AS table_schema,
|
||||||
trigger_schema,
|
information_schema.triggers.event_object_table AS table_name,
|
||||||
trigger_name,
|
information_schema.triggers.trigger_schema,
|
||||||
string_agg(event_manipulation, ',') AS event,
|
information_schema.triggers.trigger_name,
|
||||||
|
string_agg(event_manipulation, ',') AS EVENT,
|
||||||
action_timing AS activation,
|
action_timing AS activation,
|
||||||
action_condition AS condition,
|
action_condition AS condition,
|
||||||
action_statement AS definition
|
action_statement AS definition,
|
||||||
FROM information_schema.triggers
|
(pg_trigger.tgenabled != 'D')::bool AS enabled
|
||||||
|
FROM pg_trigger
|
||||||
|
JOIN pg_class ON pg_trigger.tgrelid = pg_class.oid
|
||||||
|
JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
|
||||||
|
JOIN information_schema.triggers ON pg_namespace.nspname = information_schema.triggers.trigger_schema
|
||||||
|
AND pg_class.relname = information_schema.triggers.event_object_table
|
||||||
WHERE trigger_schema = '${schema}'
|
WHERE trigger_schema = '${schema}'
|
||||||
AND trigger_name = '${triggerName}'
|
AND trigger_name = '${triggerName}'
|
||||||
AND event_object_table = '${table}'
|
AND event_object_table = '${table}'
|
||||||
GROUP BY 1,2,3,4,6,7,8
|
GROUP BY 1,2,3,4,6,7,8,9
|
||||||
ORDER BY table_schema,
|
ORDER BY table_schema,
|
||||||
table_name
|
table_name
|
||||||
`);
|
`);
|
||||||
@@ -619,7 +640,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
sql: row.definition,
|
sql: row.definition,
|
||||||
name: row.trigger_name,
|
name: row.trigger_name,
|
||||||
table: row.table_name,
|
table: row.table_name,
|
||||||
event: row.event.split(','),
|
event: [...new Set(row.event.split(','))],
|
||||||
activation: row.activation
|
activation: row.activation
|
||||||
};
|
};
|
||||||
})[0];
|
})[0];
|
||||||
@@ -628,7 +649,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* DROP TRIGGER
|
* DROP TRIGGER
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
async dropTrigger (params) {
|
async dropTrigger (params) {
|
||||||
@@ -640,7 +661,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* ALTER TRIGGER
|
* ALTER TRIGGER
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
async alterTrigger (params) {
|
async alterTrigger (params) {
|
||||||
@@ -662,7 +683,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* CREATE TRIGGER
|
* CREATE TRIGGER
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
async createTrigger (params) {
|
async createTrigger (params) {
|
||||||
@@ -671,6 +692,18 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
return await this.raw(sql, { split: false });
|
return await this.raw(sql, { split: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async enableTrigger ({ schema, trigger }) {
|
||||||
|
const [table, triggerName] = trigger.split('.');
|
||||||
|
const sql = `ALTER TABLE "${schema}"."${table}" ENABLE TRIGGER "${triggerName}"`;
|
||||||
|
return await this.raw(sql, { split: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
async disableTrigger ({ schema, trigger }) {
|
||||||
|
const [table, triggerName] = trigger.split('.');
|
||||||
|
const sql = `ALTER TABLE "${schema}"."${table}" DISABLE TRIGGER "${triggerName}"`;
|
||||||
|
return await this.raw(sql, { split: false });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SHOW CREATE PROCEDURE
|
* SHOW CREATE PROCEDURE
|
||||||
*
|
*
|
||||||
@@ -1062,7 +1095,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* CREATE TABLE
|
* CREATE TABLE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
async createTable (params) {
|
async createTable (params) {
|
||||||
@@ -1120,7 +1153,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* ALTER TABLE
|
* ALTER TABLE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
async alterTable (params) {
|
async alterTable (params) {
|
||||||
@@ -1266,7 +1299,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* DUPLICATE TABLE
|
* DUPLICATE TABLE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
async duplicateTable (params) {
|
async duplicateTable (params) {
|
||||||
@@ -1277,7 +1310,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* TRUNCATE TABLE
|
* TRUNCATE TABLE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
async truncateTable (params) {
|
async truncateTable (params) {
|
||||||
@@ -1288,7 +1321,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
/**
|
/**
|
||||||
* DROP TABLE
|
* DROP TABLE
|
||||||
*
|
*
|
||||||
* @returns {Array.<Object>} parameters
|
* @returns {Promise<null>}
|
||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
async dropTable (params) {
|
async dropTable (params) {
|
||||||
|
806
src/main/libs/clients/SQLiteClient.js
Normal file
@@ -0,0 +1,806 @@
|
|||||||
|
'use strict';
|
||||||
|
import sqlite from 'better-sqlite3';
|
||||||
|
import { AntaresCore } from '../AntaresCore';
|
||||||
|
import dataTypes from 'common/data-types/mysql';
|
||||||
|
import { NUMBER, FLOAT, TIME, DATETIME } from 'common/fieldTypes';
|
||||||
|
|
||||||
|
export class SQLiteClient extends AntaresCore {
|
||||||
|
constructor (args) {
|
||||||
|
super(args);
|
||||||
|
|
||||||
|
this._schema = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_getTypeInfo (type) {
|
||||||
|
return dataTypes
|
||||||
|
.reduce((acc, group) => [...acc, ...group.types], [])
|
||||||
|
.filter(_type => _type.name === type.toUpperCase())[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async connect () {
|
||||||
|
this._connection = sqlite(this._params.databasePath, {
|
||||||
|
fileMustExist: true,
|
||||||
|
readonly: this._params.readonly
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
destroy () {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes an USE query
|
||||||
|
*
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
use () {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array} schemas list
|
||||||
|
* @returns {Array.<Object>} databases scructure
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async getStructure (schemas) {
|
||||||
|
const { rows: databases } = await this.raw('SELECT * FROM pragma_database_list');
|
||||||
|
|
||||||
|
const filteredDatabases = databases;
|
||||||
|
|
||||||
|
const tablesArr = [];
|
||||||
|
const triggersArr = [];
|
||||||
|
let schemaSize = 0;
|
||||||
|
|
||||||
|
for (const db of filteredDatabases) {
|
||||||
|
if (!schemas.has(db.name)) continue;
|
||||||
|
|
||||||
|
let { rows: tables } = await this.raw(`
|
||||||
|
SELECT *
|
||||||
|
FROM "${db.name}".sqlite_master
|
||||||
|
WHERE type IN ('table', 'view')
|
||||||
|
AND name NOT LIKE 'sqlite_%'
|
||||||
|
ORDER BY name
|
||||||
|
`);
|
||||||
|
if (tables.length) {
|
||||||
|
tables = tables.map(table => {
|
||||||
|
table.Db = db.name;
|
||||||
|
return table;
|
||||||
|
});
|
||||||
|
tablesArr.push(...tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
let { rows: triggers } = await this.raw(`SELECT * FROM "${db.name}".sqlite_master WHERE type='trigger'`);
|
||||||
|
if (triggers.length) {
|
||||||
|
triggers = triggers.map(trigger => {
|
||||||
|
trigger.Db = db.name;
|
||||||
|
return trigger;
|
||||||
|
});
|
||||||
|
triggersArr.push(...triggers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredDatabases.map(db => {
|
||||||
|
if (schemas.has(db.name)) {
|
||||||
|
// TABLES
|
||||||
|
const remappedTables = tablesArr.filter(table => table.Db === db.name).map(table => {
|
||||||
|
const tableSize = 0;
|
||||||
|
schemaSize += tableSize;
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: table.name,
|
||||||
|
type: table.type,
|
||||||
|
rows: false,
|
||||||
|
size: false
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// TRIGGERS
|
||||||
|
const remappedTriggers = triggersArr.filter(trigger => trigger.Db === db.name).map(trigger => {
|
||||||
|
return {
|
||||||
|
name: trigger.name,
|
||||||
|
table: trigger.tbl_name
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: db.name,
|
||||||
|
size: schemaSize,
|
||||||
|
tables: remappedTables,
|
||||||
|
functions: [],
|
||||||
|
procedures: [],
|
||||||
|
triggers: remappedTriggers,
|
||||||
|
schedulers: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return {
|
||||||
|
name: db.name,
|
||||||
|
size: 0,
|
||||||
|
tables: [],
|
||||||
|
functions: [],
|
||||||
|
procedures: [],
|
||||||
|
triggers: [],
|
||||||
|
schedulers: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} params
|
||||||
|
* @param {String} params.schema
|
||||||
|
* @param {String} params.table
|
||||||
|
* @returns {Object} table scructure
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async getTableColumns ({ schema, table }) {
|
||||||
|
const { rows: fields } = await this.raw(`SELECT * FROM "${schema}".pragma_table_info('${table}')`);
|
||||||
|
|
||||||
|
return fields.map(field => {
|
||||||
|
const [type, length] = field.type.includes('(')
|
||||||
|
? field.type.replace(')', '').split('(').map(el => {
|
||||||
|
if (!isNaN(el)) el = +el;
|
||||||
|
return el;
|
||||||
|
})
|
||||||
|
: [field.type, null];
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: field.name,
|
||||||
|
key: null,
|
||||||
|
type: type.trim(),
|
||||||
|
schema: schema,
|
||||||
|
table: table,
|
||||||
|
numPrecision: [...NUMBER, ...FLOAT].includes(type) ? length : null,
|
||||||
|
datePrecision: null,
|
||||||
|
charLength: ![...NUMBER, ...FLOAT].includes(type) ? length : null,
|
||||||
|
nullable: !field.notnull,
|
||||||
|
unsigned: null,
|
||||||
|
zerofill: null,
|
||||||
|
order: field.cid + 1,
|
||||||
|
default: field.dflt_value,
|
||||||
|
charset: null,
|
||||||
|
collation: null,
|
||||||
|
autoIncrement: false,
|
||||||
|
onUpdate: null,
|
||||||
|
comment: ''
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} params
|
||||||
|
* @param {String} params.schema
|
||||||
|
* @param {String} params.table
|
||||||
|
* @returns {Object} table row count
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async getTableApproximateCount ({ schema, table }) {
|
||||||
|
const { rows } = await this.raw(`SELECT COUNT(*) AS count FROM "${schema}"."${table}"`);
|
||||||
|
|
||||||
|
return rows.length ? rows[0].count : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} params
|
||||||
|
* @param {String} params.schema
|
||||||
|
* @param {String} params.table
|
||||||
|
* @returns {Object} table options
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async getTableOptions ({ schema, table }) {
|
||||||
|
return { name: table };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} params
|
||||||
|
* @param {String} params.schema
|
||||||
|
* @param {String} params.table
|
||||||
|
* @returns {Object} table indexes
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async getTableIndexes ({ schema, table }) {
|
||||||
|
const remappedIndexes = [];
|
||||||
|
const { rows: primaryKeys } = await this.raw(`SELECT * FROM "${schema}".pragma_table_info('${table}') WHERE pk != 0`);
|
||||||
|
|
||||||
|
for (const key of primaryKeys) {
|
||||||
|
remappedIndexes.push({
|
||||||
|
name: 'PRIMARY',
|
||||||
|
column: key.name,
|
||||||
|
indexType: null,
|
||||||
|
type: 'PRIMARY',
|
||||||
|
cardinality: null,
|
||||||
|
comment: '',
|
||||||
|
indexComment: ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { rows: indexes } = await this.raw(`SELECT * FROM "${schema}".pragma_index_list('${table}');`);
|
||||||
|
|
||||||
|
for (const index of indexes) {
|
||||||
|
const { rows: details } = await this.raw(`SELECT * FROM "${schema}".pragma_index_info('${index.name}');`);
|
||||||
|
|
||||||
|
for (const detail of details) {
|
||||||
|
remappedIndexes.push({
|
||||||
|
name: index.name,
|
||||||
|
column: detail.name,
|
||||||
|
indexType: null,
|
||||||
|
type: index.unique === 1 ? 'UNIQUE' : 'INDEX',
|
||||||
|
cardinality: null,
|
||||||
|
comment: '',
|
||||||
|
indexComment: ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return remappedIndexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} params
|
||||||
|
* @param {String} params.schema
|
||||||
|
* @param {String} params.table
|
||||||
|
* @returns {Object} table key usage
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async getKeyUsage ({ schema, table }) {
|
||||||
|
const { rows } = await this.raw(`SELECT * FROM "${schema}".pragma_foreign_key_list('${table}');`);
|
||||||
|
|
||||||
|
return rows.map(field => {
|
||||||
|
return {
|
||||||
|
schema: schema,
|
||||||
|
table: table,
|
||||||
|
field: field.from,
|
||||||
|
position: field.id + 1,
|
||||||
|
constraintPosition: null,
|
||||||
|
constraintName: field.id,
|
||||||
|
refSchema: schema,
|
||||||
|
refTable: field.table,
|
||||||
|
refField: field.to,
|
||||||
|
onUpdate: field.on_update,
|
||||||
|
onDelete: field.on_delete
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getUsers () {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SHOW CREATE VIEW
|
||||||
|
*
|
||||||
|
* @returns {Array.<Object>} view informations
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async getViewInformations ({ schema, view }) {
|
||||||
|
const sql = `SELECT "sql" FROM "${schema}".sqlite_master WHERE "type"='view' AND name='${view}'`;
|
||||||
|
const results = await this.raw(sql);
|
||||||
|
|
||||||
|
return results.rows.map(row => {
|
||||||
|
return {
|
||||||
|
sql: row.sql.match(/(?<=AS ).*?$/gs)[0],
|
||||||
|
name: view
|
||||||
|
};
|
||||||
|
})[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DROP VIEW
|
||||||
|
*
|
||||||
|
* @returns {Array.<Object>} parameters
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async dropView (params) {
|
||||||
|
const sql = `DROP VIEW "${params.schema}"."${params.view}"`;
|
||||||
|
return await this.raw(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ALTER VIEW
|
||||||
|
*
|
||||||
|
* @returns {Array.<Object>} parameters
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async alterView (params) {
|
||||||
|
const { view } = params;
|
||||||
|
try {
|
||||||
|
await this.dropView({ schema: view.schema, view: view.oldName });
|
||||||
|
await this.createView(view);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return Promise.reject(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CREATE VIEW
|
||||||
|
*
|
||||||
|
* @returns {Array.<Object>} parameters
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async createView (params) {
|
||||||
|
const sql = `CREATE VIEW "${params.schema}"."${params.name}" AS ${params.sql}`;
|
||||||
|
return await this.raw(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SHOW CREATE TRIGGER
|
||||||
|
*
|
||||||
|
* @returns {Array.<Object>} view informations
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async getTriggerInformations ({ schema, trigger }) {
|
||||||
|
const sql = `SELECT "sql" FROM "${schema}".sqlite_master WHERE "type"='trigger' AND name='${trigger}'`;
|
||||||
|
const results = await this.raw(sql);
|
||||||
|
|
||||||
|
return results.rows.map(row => {
|
||||||
|
return {
|
||||||
|
sql: row.sql.match(/(BEGIN|begin)(.*)(END|end)/gs)[0],
|
||||||
|
name: trigger,
|
||||||
|
table: row.sql.match(/(?<=ON `).*?(?=`)/gs)[0],
|
||||||
|
activation: row.sql.match(/(BEFORE|AFTER)/gs)[0],
|
||||||
|
event: row.sql.match(/(INSERT|UPDATE|DELETE)/gs)[0]
|
||||||
|
};
|
||||||
|
})[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DROP TRIGGER
|
||||||
|
*
|
||||||
|
* @returns {Array.<Object>} parameters
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async dropTrigger (params) {
|
||||||
|
const sql = `DROP TRIGGER \`${params.schema}\`.\`${params.trigger}\``;
|
||||||
|
return await this.raw(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ALTER TRIGGER
|
||||||
|
*
|
||||||
|
* @returns {Array.<Object>} parameters
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async alterTrigger (params) {
|
||||||
|
const { trigger } = params;
|
||||||
|
const tempTrigger = Object.assign({}, trigger);
|
||||||
|
tempTrigger.name = `Antares_${tempTrigger.name}_tmp`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.createTrigger(tempTrigger);
|
||||||
|
await this.dropTrigger({ schema: trigger.schema, trigger: tempTrigger.name });
|
||||||
|
await this.dropTrigger({ schema: trigger.schema, trigger: trigger.oldName });
|
||||||
|
await this.createTrigger(trigger);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return Promise.reject(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CREATE TRIGGER
|
||||||
|
*
|
||||||
|
* @returns {Array.<Object>} parameters
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async createTrigger (params) {
|
||||||
|
const sql = `CREATE ${params.definer ? `DEFINER=${params.definer} ` : ''}TRIGGER \`${params.schema}\`.\`${params.name}\` ${params.activation} ${params.event} ON \`${params.table}\` FOR EACH ROW ${params.sql}`;
|
||||||
|
return await this.raw(sql, { split: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SHOW COLLATION
|
||||||
|
*
|
||||||
|
* @returns {Array.<Object>} collations list
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async getCollations () {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SHOW VARIABLES
|
||||||
|
*
|
||||||
|
* @returns {Array.<Object>} variables list
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async getVariables () {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SHOW ENGINES
|
||||||
|
*
|
||||||
|
* @returns {Array.<Object>} engines list
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async getEngines () {
|
||||||
|
return {
|
||||||
|
name: 'SQLite',
|
||||||
|
support: 'YES',
|
||||||
|
comment: '',
|
||||||
|
isDefault: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SHOW VARIABLES LIKE '%vers%'
|
||||||
|
*
|
||||||
|
* @returns {Array.<Object>} version parameters
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async getVersion () {
|
||||||
|
const os = require('os');
|
||||||
|
const sql = 'SELECT sqlite_version() AS version';
|
||||||
|
const { rows } = await this.raw(sql);
|
||||||
|
|
||||||
|
return {
|
||||||
|
number: rows[0].version,
|
||||||
|
name: 'SQLite',
|
||||||
|
arch: process.arch,
|
||||||
|
os: `${os.type()} ${os.release()}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async getProcesses () {}
|
||||||
|
|
||||||
|
async killProcess () {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CREATE TABLE
|
||||||
|
*
|
||||||
|
* @returns {Promise<null>}
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async createTable (params) {
|
||||||
|
const {
|
||||||
|
schema,
|
||||||
|
fields,
|
||||||
|
foreigns,
|
||||||
|
indexes,
|
||||||
|
options
|
||||||
|
} = params;
|
||||||
|
const newColumns = [];
|
||||||
|
const newIndexes = [];
|
||||||
|
const manageIndexes = [];
|
||||||
|
const newForeigns = [];
|
||||||
|
|
||||||
|
let sql = `CREATE TABLE "${schema}"."${options.name}"`;
|
||||||
|
|
||||||
|
// ADD FIELDS
|
||||||
|
fields.forEach(field => {
|
||||||
|
const typeInfo = this._getTypeInfo(field.type);
|
||||||
|
const length = typeInfo?.length ? field.enumValues || field.numLength || field.charLength || field.datePrecision : false;
|
||||||
|
|
||||||
|
newColumns.push(`"${field.name}"
|
||||||
|
${field.type.toUpperCase()}${length && length !== true ? `(${length})` : ''}
|
||||||
|
${field.unsigned ? 'UNSIGNED' : ''}
|
||||||
|
${field.nullable ? 'NULL' : 'NOT NULL'}
|
||||||
|
${field.autoIncrement ? 'AUTO_INCREMENT' : ''}
|
||||||
|
${field.default ? `DEFAULT ${field.default}` : ''}
|
||||||
|
${field.onUpdate ? `ON UPDATE ${field.onUpdate}` : ''}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// ADD INDEX
|
||||||
|
indexes.forEach(index => {
|
||||||
|
const fields = index.fields.map(field => `"${field}"`).join(',');
|
||||||
|
const type = index.type;
|
||||||
|
|
||||||
|
if (type === 'PRIMARY')
|
||||||
|
newIndexes.push(`PRIMARY KEY (${fields})`);
|
||||||
|
else
|
||||||
|
manageIndexes.push(`CREATE ${type === 'UNIQUE' ? type : ''} INDEX "${index.name}" ON "${options.name}" (${fields})`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// ADD FOREIGN KEYS
|
||||||
|
foreigns.forEach(foreign => {
|
||||||
|
newForeigns.push(`CONSTRAINT "${foreign.constraintName}" FOREIGN KEY ("${foreign.field}") REFERENCES "${foreign.refTable}" ("${foreign.refField}") ON UPDATE ${foreign.onUpdate} ON DELETE ${foreign.onDelete}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
sql = `${sql} (${[...newColumns, ...newIndexes, ...newForeigns].join(', ')})`;
|
||||||
|
if (manageIndexes.length) sql = `${sql}; ${manageIndexes.join(';')}`;
|
||||||
|
|
||||||
|
return await this.raw(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ALTER TABLE
|
||||||
|
*
|
||||||
|
* @returns {Promise<null>}
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async alterTable (params) {
|
||||||
|
try {
|
||||||
|
await this.raw('BEGIN TRANSACTION');
|
||||||
|
await this.raw('PRAGMA foreign_keys = 0');
|
||||||
|
|
||||||
|
const tmpName = `Antares_${params.table}_tmp`;
|
||||||
|
await this.raw(`CREATE TABLE "${tmpName}" AS SELECT * FROM "${params.table}"`);
|
||||||
|
await this.dropTable(params);
|
||||||
|
|
||||||
|
const createTableParams = {
|
||||||
|
schema: params.schema,
|
||||||
|
fields: params.tableStructure.fields,
|
||||||
|
foreigns: params.tableStructure.foreigns,
|
||||||
|
indexes: params.tableStructure.indexes.filter(index => !index.name.includes('sqlite_autoindex')),
|
||||||
|
options: { name: params.tableStructure.name }
|
||||||
|
};
|
||||||
|
await this.createTable(createTableParams);
|
||||||
|
const insertFields = createTableParams.fields
|
||||||
|
.filter(field => {
|
||||||
|
return (
|
||||||
|
params.additions.every(add => add.name !== field.name) &&
|
||||||
|
params.deletions.every(del => del.name !== field.name)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.reduce((acc, curr) => {
|
||||||
|
acc.push(`"${curr.name}"`);
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const selectFields = insertFields.map(field => {
|
||||||
|
const renamedField = params.changes.find(change => `"${change.name}"` === field);
|
||||||
|
if (renamedField)
|
||||||
|
return `"${renamedField.orgName}"`;
|
||||||
|
return field;
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.raw(`INSERT INTO "${createTableParams.options.name}" (${insertFields.join(',')}) SELECT ${selectFields.join(',')} FROM "${tmpName}"`);
|
||||||
|
|
||||||
|
await this.dropTable({ schema: params.schema, table: tmpName });
|
||||||
|
await this.raw('PRAGMA foreign_keys = 1');
|
||||||
|
await this.raw('COMMIT');
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
await this.raw('ROLLBACK');
|
||||||
|
return Promise.reject(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DUPLICATE TABLE
|
||||||
|
*
|
||||||
|
* @returns {Promise<null>}
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async duplicateTable (params) { // TODO: retrive table informations and create a copy
|
||||||
|
const sql = `CREATE TABLE "${params.schema}"."${params.table}_copy" AS SELECT * FROM "${params.schema}"."${params.table}"`;
|
||||||
|
return await this.raw(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TRUNCATE TABLE
|
||||||
|
*
|
||||||
|
* @returns {Promise<null>}
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async truncateTable (params) {
|
||||||
|
const sql = `DELETE FROM "${params.schema}"."${params.table}"`;
|
||||||
|
return await this.raw(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DROP TABLE
|
||||||
|
*
|
||||||
|
* @returns {Promise<null>}
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async dropTable (params) {
|
||||||
|
const sql = `DROP TABLE "${params.schema}"."${params.table}"`;
|
||||||
|
return await this.raw(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {String} SQL string
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
getSQL () {
|
||||||
|
// SELECT
|
||||||
|
const selectArray = this._query.select.reduce(this._reducer, []);
|
||||||
|
let selectRaw = '';
|
||||||
|
|
||||||
|
if (selectArray.length)
|
||||||
|
selectRaw = selectArray.length ? `SELECT ${selectArray.join(', ')} ` : 'SELECT * ';
|
||||||
|
|
||||||
|
// FROM
|
||||||
|
let fromRaw = '';
|
||||||
|
|
||||||
|
if (!this._query.update.length && !Object.keys(this._query.insert).length && !!this._query.from)
|
||||||
|
fromRaw = 'FROM';
|
||||||
|
else if (Object.keys(this._query.insert).length)
|
||||||
|
fromRaw = 'INTO';
|
||||||
|
|
||||||
|
fromRaw += this._query.from ? ` ${this._query.schema ? `"${this._query.schema}".` : ''}"${this._query.from}" ` : '';
|
||||||
|
|
||||||
|
// WHERE
|
||||||
|
const whereArray = this._query.where
|
||||||
|
.reduce(this._reducer, [])
|
||||||
|
?.map(clausole => clausole.replace('= null', 'IS NULL'));
|
||||||
|
const whereRaw = whereArray.length ? `WHERE ${whereArray.join(' AND ')} ` : '';
|
||||||
|
|
||||||
|
// UPDATE
|
||||||
|
const updateArray = this._query.update.reduce(this._reducer, []);
|
||||||
|
const updateRaw = updateArray.length ? `SET ${updateArray.join(', ')} ` : '';
|
||||||
|
|
||||||
|
// INSERT
|
||||||
|
let insertRaw = '';
|
||||||
|
|
||||||
|
if (this._query.insert.length) {
|
||||||
|
const fieldsList = Object.keys(this._query.insert[0]);
|
||||||
|
const rowsList = this._query.insert.map(el => `(${Object.values(el).join(', ')})`);
|
||||||
|
|
||||||
|
insertRaw = `(${fieldsList.join(', ')}) VALUES ${rowsList.join(', ')} `;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GROUP BY
|
||||||
|
const groupByArray = this._query.groupBy.reduce(this._reducer, []);
|
||||||
|
const groupByRaw = groupByArray.length ? `GROUP BY ${groupByArray.join(', ')} ` : '';
|
||||||
|
|
||||||
|
// ORDER BY
|
||||||
|
const orderByArray = this._query.orderBy.reduce(this._reducer, []);
|
||||||
|
const orderByRaw = orderByArray.length ? `ORDER BY ${orderByArray.join(', ')} ` : '';
|
||||||
|
|
||||||
|
// LIMIT
|
||||||
|
const limitRaw = this._query.limit.length ? `LIMIT ${this._query.limit.join(', ')} ` : '';
|
||||||
|
|
||||||
|
// OFFSET
|
||||||
|
const offsetRaw = this._query.offset.length ? `OFFSET ${this._query.offset.join(', ')} ` : '';
|
||||||
|
|
||||||
|
return `${selectRaw}${updateRaw ? 'UPDATE' : ''}${insertRaw ? 'INSERT ' : ''}${this._query.delete ? 'DELETE ' : ''}${fromRaw}${updateRaw}${whereRaw}${groupByRaw}${orderByRaw}${limitRaw}${offsetRaw}${insertRaw}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} sql raw SQL query
|
||||||
|
* @param {object} args
|
||||||
|
* @param {boolean} args.nest
|
||||||
|
* @param {boolean} args.details
|
||||||
|
* @param {boolean} args.split
|
||||||
|
* @returns {Promise}
|
||||||
|
* @memberof SQLiteClient
|
||||||
|
*/
|
||||||
|
async raw (sql, args) {
|
||||||
|
if (process.env.NODE_ENV === 'development') this._logger(sql);// TODO: replace BLOB content with a placeholder
|
||||||
|
|
||||||
|
args = {
|
||||||
|
nest: false,
|
||||||
|
details: false,
|
||||||
|
split: true,
|
||||||
|
comments: true,
|
||||||
|
...args
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!args.comments)
|
||||||
|
sql = sql.replace(/(\/\*(.|[\r\n])*?\*\/)|(--(.*|[\r\n]))/gm, '');// Remove comments
|
||||||
|
|
||||||
|
const resultsArr = [];
|
||||||
|
let paramsArr = [];
|
||||||
|
const queries = args.split
|
||||||
|
? sql.split(/((?:[^;'"]*(?:"(?:\\.|[^"])*"|'(?:\\.|[^'])*')[^;'"]*)+)|;/gm)
|
||||||
|
.filter(Boolean)
|
||||||
|
.map(q => q.trim())
|
||||||
|
: [sql];
|
||||||
|
const connection = this._connection;
|
||||||
|
|
||||||
|
for (const query of queries) {
|
||||||
|
if (!query) continue;
|
||||||
|
const timeStart = new Date();
|
||||||
|
let timeStop;
|
||||||
|
const keysArr = [];
|
||||||
|
|
||||||
|
const { rows, report, fields, keys, duration } = await new Promise((resolve, reject) => {
|
||||||
|
(async () => {
|
||||||
|
let queryResult;
|
||||||
|
let affectedRows;
|
||||||
|
let fields;
|
||||||
|
const detectedTypes = {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const stmt = connection.prepare(query);
|
||||||
|
|
||||||
|
if (stmt.reader) {
|
||||||
|
queryResult = stmt.all();
|
||||||
|
fields = stmt.columns();
|
||||||
|
|
||||||
|
if (queryResult.length) {
|
||||||
|
fields.forEach(field => {
|
||||||
|
detectedTypes[field.name] = typeof queryResult[0][field.name];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const info = queryResult = stmt.run();
|
||||||
|
affectedRows = info.changes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
timeStop = new Date();
|
||||||
|
|
||||||
|
let remappedFields = fields
|
||||||
|
? fields.map(field => {
|
||||||
|
let [parsedType, length] = field.type?.includes('(')
|
||||||
|
? field.type.replace(')', '').split('(').map(el => {
|
||||||
|
if (!isNaN(el))
|
||||||
|
el = +el;
|
||||||
|
else
|
||||||
|
el = el.trim();
|
||||||
|
return el;
|
||||||
|
})
|
||||||
|
: [field.type, null];
|
||||||
|
|
||||||
|
if ([...TIME, ...DATETIME].includes(parsedType)) {
|
||||||
|
const firstNotNull = queryResult.find(res => res[field.name] !== null);
|
||||||
|
if (firstNotNull[field.name].includes('.'))
|
||||||
|
length = firstNotNull[field.name].split('.').pop().length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: field.name,
|
||||||
|
alias: field.name,
|
||||||
|
orgName: field.column,
|
||||||
|
schema: field.database,
|
||||||
|
table: field.table,
|
||||||
|
tableAlias: field.table,
|
||||||
|
orgTable: field.table,
|
||||||
|
type: field.type !== null ? parsedType : detectedTypes[field.name],
|
||||||
|
length
|
||||||
|
};
|
||||||
|
}).filter(Boolean)
|
||||||
|
: [];
|
||||||
|
|
||||||
|
if (args.details) {
|
||||||
|
paramsArr = remappedFields.map(field => {
|
||||||
|
return {
|
||||||
|
table: field.table,
|
||||||
|
schema: field.schema
|
||||||
|
};
|
||||||
|
}).filter((val, i, arr) => arr.findIndex(el => el.schema === val.schema && el.table === val.table) === i);
|
||||||
|
|
||||||
|
for (const paramObj of paramsArr) {
|
||||||
|
if (!paramObj.table || !paramObj.schema) continue;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const indexes = await this.getTableIndexes(paramObj);
|
||||||
|
|
||||||
|
remappedFields = remappedFields.map(field => {
|
||||||
|
// const detailedField = columns.find(f => f.name === field.name);
|
||||||
|
const fieldIndex = indexes.find(i => i.column === field.name);
|
||||||
|
if (field.table === paramObj.table && field.schema === paramObj.schema) {
|
||||||
|
// if (detailedField) {
|
||||||
|
// const length = detailedField.numPrecision || detailedField.charLength || detailedField.datePrecision || null;
|
||||||
|
// field = { ...field, ...detailedField, length };
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (fieldIndex) {
|
||||||
|
const key = fieldIndex.type === 'PRIMARY' ? 'pri' : fieldIndex.type === 'UNIQUE' ? 'uni' : 'mul';
|
||||||
|
field = { ...field, key };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return field;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
duration: timeStop - timeStart,
|
||||||
|
rows: Array.isArray(queryResult) ? queryResult.some(el => Array.isArray(el)) ? [] : queryResult : false,
|
||||||
|
report: affectedRows !== undefined ? { affectedRows } : null,
|
||||||
|
fields: remappedFields,
|
||||||
|
keys: keysArr
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
});
|
||||||
|
|
||||||
|
resultsArr.push({ rows, report, fields, keys, duration });
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultsArr.length === 1 ? resultsArr[0] : resultsArr;
|
||||||
|
}
|
||||||
|
}
|
@@ -11,6 +11,7 @@ import ipcHandlers from './ipc-handlers';
|
|||||||
Store.initRenderer();
|
Store.initRenderer();
|
||||||
|
|
||||||
const isDevelopment = process.env.NODE_ENV !== 'production';
|
const isDevelopment = process.env.NODE_ENV !== 'production';
|
||||||
|
const isMacOS = process.platform === 'darwin';
|
||||||
const gotTheLock = app.requestSingleInstanceLock();
|
const gotTheLock = app.requestSingleInstanceLock();
|
||||||
|
|
||||||
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true';
|
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true';
|
||||||
@@ -25,7 +26,7 @@ async function createMainWindow () {
|
|||||||
height: 800,
|
height: 800,
|
||||||
minWidth: 900,
|
minWidth: 900,
|
||||||
minHeight: 550,
|
minHeight: 550,
|
||||||
title: 'Antares',
|
title: 'Antares SQL',
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
icon: nativeImage.createFromDataURL(icon.default),
|
icon: nativeImage.createFromDataURL(icon.default),
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
@@ -35,23 +36,34 @@ async function createMainWindow () {
|
|||||||
spellcheck: false
|
spellcheck: false
|
||||||
},
|
},
|
||||||
frame: false,
|
frame: false,
|
||||||
|
titleBarStyle: isMacOS ? 'hidden' : 'default',
|
||||||
|
trafficLightPosition: isMacOS ? { x: 10, y: 8 } : undefined,
|
||||||
backgroundColor: '#1d1d1d'
|
backgroundColor: '#1d1d1d'
|
||||||
});
|
});
|
||||||
|
|
||||||
remoteMain.enable(window.webContents);
|
remoteMain.enable(window.webContents);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isDevelopment) { //
|
if (isDevelopment) {
|
||||||
await window.loadURL(`http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}`);
|
const { default: installExtension, VUEJS3_DEVTOOLS } = require('electron-devtools-installer');
|
||||||
|
const options = {
|
||||||
|
loadExtensionOptions: { allowFileAccess: true }
|
||||||
|
};
|
||||||
|
|
||||||
// const { default: installExtension, VUEJS3_DEVTOOLS } = require('electron-devtools-installer');
|
try {
|
||||||
|
const name = await installExtension(VUEJS3_DEVTOOLS, options);
|
||||||
|
console.log(`Added Extension: ${name}`);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.log('An error occurred: ', err);
|
||||||
|
}
|
||||||
|
|
||||||
// const oldDevToolsID = session.defaultSession.getAllExtensions().find(ext => ext.name === 'Vue.js devtools').id;
|
await window.loadURL('http://localhost:9080');
|
||||||
// session.defaultSession.removeExtension(oldDevToolsID);
|
}
|
||||||
// const toolName = await installExtension(VUEJS3_DEVTOOLS);
|
else {
|
||||||
// console.log(toolName, 'installed');
|
const indexPath = path.resolve(__dirname, 'index.html');
|
||||||
|
await window.loadFile(indexPath);
|
||||||
}
|
}
|
||||||
else await window.loadURL(new URL(`file:///${path.join(__dirname, 'index.html')}`).href);
|
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
@@ -81,15 +93,13 @@ else {
|
|||||||
// quit application when all windows are closed
|
// quit application when all windows are closed
|
||||||
app.on('window-all-closed', () => {
|
app.on('window-all-closed', () => {
|
||||||
// on macOS it is common for applications to stay open until the user explicitly quits
|
// on macOS it is common for applications to stay open until the user explicitly quits
|
||||||
if (process.platform !== 'darwin') app.quit();
|
if (isMacOS) app.quit();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on('activate', async () => {
|
app.on('activate', async () => {
|
||||||
// on macOS it is common to re-create a window even after all windows have been closed
|
// on macOS it is common to re-create a window even after all windows have been closed
|
||||||
if (mainWindow === null) {
|
if (mainWindow === null)
|
||||||
mainWindow = await createMainWindow();
|
mainWindow = await createMainWindow();
|
||||||
if (isDevelopment) mainWindow.webContents.openDevTools();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// create main BrowserWindow when electron is ready
|
// create main BrowserWindow when electron is ready
|
||||||
@@ -97,13 +107,14 @@ else {
|
|||||||
mainWindow = await createMainWindow();
|
mainWindow = await createMainWindow();
|
||||||
createAppMenu();
|
createAppMenu();
|
||||||
|
|
||||||
if (isDevelopment) mainWindow.webContents.openDevTools();
|
// if (isDevelopment)
|
||||||
|
// mainWindow.webContents.openDevTools();
|
||||||
|
|
||||||
process.on('uncaughtException', (error) => {
|
process.on('uncaughtException', error => {
|
||||||
mainWindow.webContents.send('unhandled-exception', error);
|
mainWindow.webContents.send('unhandled-exception', error);
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('unhandledRejection', (error) => {
|
process.on('unhandledRejection', error => {
|
||||||
mainWindow.webContents.send('unhandled-exception', error);
|
mainWindow.webContents.send('unhandled-exception', error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -112,19 +123,37 @@ else {
|
|||||||
function createAppMenu () {
|
function createAppMenu () {
|
||||||
let menu = null;
|
let menu = null;
|
||||||
|
|
||||||
if (process.platform === 'darwin') {
|
if (isMacOS) {
|
||||||
menu = Menu.buildFromTemplate([
|
menu = Menu.buildFromTemplate([
|
||||||
{
|
{
|
||||||
label: app.name,
|
label: app.name,
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{ role: 'about' },
|
||||||
role: 'about'
|
|
||||||
},
|
|
||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
{
|
{
|
||||||
role: 'quit'
|
label: 'Check for Updates...',
|
||||||
}
|
click: (_menuItem, win) => win.webContents.send('open-updates-preferences')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Preferences',
|
||||||
|
click: (_menuItem, win) => win.webContents.send('toggle-preferences'),
|
||||||
|
accelerator: 'CmdOrCtrl+,'
|
||||||
|
},
|
||||||
|
{ type: 'separator' },
|
||||||
|
{ role: 'hide' },
|
||||||
|
{ role: 'hideOthers' },
|
||||||
|
{ type: 'separator' },
|
||||||
|
{ role: 'quit' }
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'editMenu'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'viewMenu'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'windowMenu'
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
@@ -89,7 +89,7 @@
|
|||||||
:type="inputProps().type"
|
:type="inputProps().type"
|
||||||
:disabled="!isChecked"
|
:disabled="!isChecked"
|
||||||
>
|
>
|
||||||
<template v-if="methodData && 'params' in methodData" class="columns">
|
<template v-if="methodData && 'params' in methodData">
|
||||||
<input
|
<input
|
||||||
v-for="(option, key) in methodData.params"
|
v-for="(option, key) in methodData.params"
|
||||||
:key="key"
|
:key="key"
|
||||||
|
@@ -17,7 +17,7 @@
|
|||||||
<form class="form-horizontal">
|
<form class="form-horizontal">
|
||||||
<div
|
<div
|
||||||
v-for="(parameter, i) in inParameters"
|
v-for="(parameter, i) in inParameters"
|
||||||
:key="parameter._id"
|
:key="parameter._antares_id"
|
||||||
class="form-group"
|
class="form-group"
|
||||||
>
|
>
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
|
@@ -253,6 +253,7 @@ export default {
|
|||||||
font-size: 100%;
|
font-size: 100%;
|
||||||
// color: $primary-color;
|
// color: $primary-color;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tile-subtitle {
|
.tile-subtitle {
|
||||||
|
@@ -184,7 +184,7 @@
|
|||||||
:class="{'selected': applicationTheme === 'dark'}"
|
:class="{'selected': applicationTheme === 'dark'}"
|
||||||
@click="changeApplicationTheme('dark')"
|
@click="changeApplicationTheme('dark')"
|
||||||
>
|
>
|
||||||
<img :src="require('@/images/dark.png').default" class="img-responsive img-fit-cover s-rounded">
|
<img src="../images/dark.png" 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" />
|
<i class="mdi mdi-moon-waning-crescent mdi-48px" />
|
||||||
<div class="h6 mt-4">
|
<div class="h6 mt-4">
|
||||||
@@ -197,7 +197,7 @@
|
|||||||
:class="{'selected': applicationTheme === 'light'}"
|
:class="{'selected': applicationTheme === 'light'}"
|
||||||
@click="changeApplicationTheme('light')"
|
@click="changeApplicationTheme('light')"
|
||||||
>
|
>
|
||||||
<img :src="require('@/images/light.png').default" class="img-responsive img-fit-cover s-rounded">
|
<img src="../images/light.png" 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" />
|
<i class="mdi mdi-white-balance-sunny mdi-48px" />
|
||||||
<div class="h6 mt-4">
|
<div class="h6 mt-4">
|
||||||
@@ -280,7 +280,7 @@
|
|||||||
|
|
||||||
<div v-show="selectedTab === 'about'" class="panel-body py-4">
|
<div v-show="selectedTab === 'about'" class="panel-body py-4">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<img :src="require('@/images/logo.svg').default" width="128">
|
<img src="../images/logo.svg" width="128">
|
||||||
<h4>{{ appName }}</h4>
|
<h4>{{ appName }}</h4>
|
||||||
<p>
|
<p>
|
||||||
{{ $t('word.version') }} {{ appVersion }}<br>
|
{{ $t('word.version') }} {{ appVersion }}<br>
|
||||||
@@ -396,7 +396,7 @@ export default {
|
|||||||
return locales;
|
return locales;
|
||||||
},
|
},
|
||||||
hasUpdates () {
|
hasUpdates () {
|
||||||
return ['available', 'downloading', 'downloaded'].includes(this.updateStatus);
|
return ['available', 'downloading', 'downloaded', 'link'].includes(this.updateStatus);
|
||||||
},
|
},
|
||||||
workspace () {
|
workspace () {
|
||||||
return this.getWorkspace(this.selectedWorkspace);
|
return this.getWorkspace(this.selectedWorkspace);
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import marked from 'marked';
|
import { marked } from 'marked';
|
||||||
import BaseLoader from '@/components/BaseLoader';
|
import BaseLoader from '@/components/BaseLoader';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@@ -29,12 +29,19 @@
|
|||||||
{{ $t('message.checkForUpdates') }}
|
{{ $t('message.checkForUpdates') }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="updateStatus === 'downloaded'"
|
v-else-if="updateStatus === 'downloaded'"
|
||||||
class="btn btn-primary"
|
class="btn btn-primary"
|
||||||
@click="restartToUpdate"
|
@click="restartToUpdate"
|
||||||
>
|
>
|
||||||
{{ $t('message.restartToInstall') }}
|
{{ $t('message.restartToInstall') }}
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
v-else-if="updateStatus === 'link'"
|
||||||
|
class="btn btn-primary"
|
||||||
|
@click="openOutside('https://antares-sql.app/download.html')"
|
||||||
|
>
|
||||||
|
{{ $t('message.goToDownloadPage') }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group mt-4">
|
<div class="form-group mt-4">
|
||||||
<label class="form-switch d-inline-block disabled" @click.prevent="toggleAllowPrerelease">
|
<label class="form-switch d-inline-block disabled" @click.prevent="toggleAllowPrerelease">
|
||||||
@@ -47,7 +54,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters, mapActions } from 'vuex';
|
import { mapGetters, mapActions } from 'vuex';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer, shell } from 'electron';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalSettingsUpdate',
|
name: 'ModalSettingsUpdate',
|
||||||
@@ -71,6 +78,8 @@ export default {
|
|||||||
return this.$t('message.downloadingUpdate');
|
return this.$t('message.downloadingUpdate');
|
||||||
case 'downloaded':
|
case 'downloaded':
|
||||||
return this.$t('message.updateDownloaded');
|
return this.$t('message.updateDownloaded');
|
||||||
|
case 'link':
|
||||||
|
return this.$t('message.updateAvailable');
|
||||||
default:
|
default:
|
||||||
return this.updateStatus;
|
return this.updateStatus;
|
||||||
}
|
}
|
||||||
@@ -80,6 +89,9 @@ export default {
|
|||||||
...mapActions({
|
...mapActions({
|
||||||
changeAllowPrerelease: 'settings/changeAllowPrerelease'
|
changeAllowPrerelease: 'settings/changeAllowPrerelease'
|
||||||
}),
|
}),
|
||||||
|
openOutside (link) {
|
||||||
|
shell.openExternal(link);
|
||||||
|
},
|
||||||
checkForUpdates () {
|
checkForUpdates () {
|
||||||
ipcRenderer.send('check-for-updates');
|
ipcRenderer.send('check-for-updates');
|
||||||
},
|
},
|
||||||
|
@@ -40,15 +40,13 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
notifications: {
|
'notifications.length': function (val) {
|
||||||
deep: true,
|
if (val > 0) {
|
||||||
handler: function (notification) {
|
const nUid = this.notifications[0].uid;
|
||||||
if (notification.length) {
|
this.timeouts[nUid] = setTimeout(() => {
|
||||||
this.timeouts[notification[0].uid] = setTimeout(() => {
|
this.removeNotification(nUid);
|
||||||
this.removeNotification(notification[0].uid);
|
delete this.timeouts[nUid];
|
||||||
delete this.timeouts[notification.uid];
|
}, this.notificationsTimeout * 1000);
|
||||||
}, this.notificationsTimeout * 1000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -63,11 +61,14 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
rearmTimeouts () {
|
rearmTimeouts () {
|
||||||
|
const delay = 50;
|
||||||
|
let i = this.notifications.length * delay;
|
||||||
for (const notification of this.notifications) {
|
for (const notification of this.notifications) {
|
||||||
this.timeouts[notification.uid] = setTimeout(() => {
|
this.timeouts[notification.uid] = setTimeout(() => {
|
||||||
this.removeNotification(notification.uid);
|
this.removeNotification(notification.uid);
|
||||||
delete this.timeouts[notification.uid];
|
delete this.timeouts[notification.uid];
|
||||||
}, this.notificationsTimeout * 1000);
|
}, (this.notificationsTimeout * 1000) + i);
|
||||||
|
i = i > delay ? i - delay : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -92,7 +92,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
hasUpdates () {
|
hasUpdates () {
|
||||||
return ['available', 'downloading', 'downloaded'].includes(this.updateStatus);
|
return ['available', 'downloading', 'downloaded', 'link'].includes(this.updateStatus);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@@ -1,8 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="titlebar">
|
<div id="titlebar" @dblclick="toggleFullScreen">
|
||||||
<div class="titlebar-resizer" />
|
<div class="titlebar-resizer" />
|
||||||
<div class="titlebar-elements">
|
<div class="titlebar-elements">
|
||||||
<img class="titlebar-logo" :src="require('@/images/logo.svg').default">
|
<img
|
||||||
|
v-if="!isMacOS"
|
||||||
|
class="titlebar-logo"
|
||||||
|
src="@/images/logo.svg"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="titlebar-elements titlebar-title">
|
<div class="titlebar-elements titlebar-title">
|
||||||
{{ windowTitle }}
|
{{ windowTitle }}
|
||||||
@@ -22,14 +26,26 @@
|
|||||||
>
|
>
|
||||||
<i class="mdi mdi-24px mdi-refresh" />
|
<i class="mdi mdi-24px mdi-refresh" />
|
||||||
</div>
|
</div>
|
||||||
<div class="titlebar-element" @click="minimizeApp">
|
<div
|
||||||
|
v-if="!isMacOS"
|
||||||
|
class="titlebar-element"
|
||||||
|
@click="minimizeApp"
|
||||||
|
>
|
||||||
<i class="mdi mdi-24px mdi-minus" />
|
<i class="mdi mdi-24px mdi-minus" />
|
||||||
</div>
|
</div>
|
||||||
<div class="titlebar-element" @click="toggleFullScreen">
|
<div
|
||||||
|
v-if="!isMacOS"
|
||||||
|
class="titlebar-element"
|
||||||
|
@click="toggleFullScreen"
|
||||||
|
>
|
||||||
<i v-if="isMaximized" class="mdi mdi-24px mdi-fullscreen-exit" />
|
<i v-if="isMaximized" class="mdi mdi-24px mdi-fullscreen-exit" />
|
||||||
<i v-else class="mdi mdi-24px mdi-fullscreen" />
|
<i v-else class="mdi mdi-24px mdi-fullscreen" />
|
||||||
</div>
|
</div>
|
||||||
<div class="titlebar-element close-button" @click="closeApp">
|
<div
|
||||||
|
v-if="!isMacOS"
|
||||||
|
class="titlebar-element close-button"
|
||||||
|
@click="closeApp"
|
||||||
|
>
|
||||||
<i class="mdi mdi-24px mdi-close" />
|
<i class="mdi mdi-24px mdi-close" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -47,7 +63,8 @@ export default {
|
|||||||
return {
|
return {
|
||||||
w: getCurrentWindow(),
|
w: getCurrentWindow(),
|
||||||
isMaximized: getCurrentWindow().isMaximized(),
|
isMaximized: getCurrentWindow().isMaximized(),
|
||||||
isDevelopment: process.env.NODE_ENV === 'development'
|
isDevelopment: process.env.NODE_ENV === 'development',
|
||||||
|
isMacOS: process.platform === 'darwin'
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@@ -256,7 +256,11 @@
|
|||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li slot="header" class="tab-item dropdown tools-dropdown">
|
<li
|
||||||
|
v-if="workspace.customizations.processesList"
|
||||||
|
slot="header"
|
||||||
|
class="tab-item dropdown tools-dropdown"
|
||||||
|
>
|
||||||
<a
|
<a
|
||||||
class="tab-link workspace-tools-link dropdown-toggle"
|
class="tab-link workspace-tools-link dropdown-toggle"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@@ -264,8 +268,8 @@
|
|||||||
>
|
>
|
||||||
<i class="mdi mdi-24px mdi-tools" />
|
<i class="mdi mdi-24px mdi-tools" />
|
||||||
</a>
|
</a>
|
||||||
<ul class="menu text-left text-uppercase">
|
<ul v-if="hasTools" class="menu text-left text-uppercase">
|
||||||
<li v-if="workspace.customizations.processesList" 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" />
|
<i class="mdi mdi-memory mr-1 tool-icon" />
|
||||||
<span>{{ $t('message.processesList') }}</span>
|
<span>{{ $t('message.processesList') }}</span>
|
||||||
@@ -569,6 +573,11 @@ export default {
|
|||||||
if (this.workspace.breadcrumbs[key]) return this.workspace.breadcrumbs[key];
|
if (this.workspace.breadcrumbs[key]) return this.workspace.breadcrumbs[key];
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
},
|
||||||
|
hasTools () {
|
||||||
|
return this.workspace.customizations.processesList ||
|
||||||
|
this.workspace.customizations.usersManagement ||
|
||||||
|
this.workspace.customizations.variables;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
<a class="tab-link">{{ $t('word.general') }}</a>
|
<a class="tab-link">{{ $t('word.general') }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
|
v-if="customizations.sslConnection"
|
||||||
class="tab-item c-hand"
|
class="tab-item c-hand"
|
||||||
:class="{'active': selectedTab === 'ssl'}"
|
:class="{'active': selectedTab === 'ssl'}"
|
||||||
@click="selectTab('ssl')"
|
@click="selectTab('ssl')"
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
<a class="tab-link">{{ $t('word.ssl') }}</a>
|
<a class="tab-link">{{ $t('word.ssl') }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
|
v-if="customizations.sshConnection"
|
||||||
class="tab-item c-hand"
|
class="tab-item c-hand"
|
||||||
:class="{'active': selectedTab === 'ssh'}"
|
:class="{'active': selectedTab === 'ssh'}"
|
||||||
@click="selectTab('ssh')"
|
@click="selectTab('ssh')"
|
||||||
@@ -49,25 +51,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="column col-8 col-sm-12">
|
<div class="column col-8 col-sm-12">
|
||||||
<select v-model="connection.client" class="form-select">
|
<select v-model="connection.client" class="form-select">
|
||||||
<option value="mysql">
|
<option
|
||||||
MySQL
|
v-for="client in clients"
|
||||||
|
:key="client.slug"
|
||||||
|
:value="client.slug"
|
||||||
|
>
|
||||||
|
{{ client.name }}
|
||||||
</option>
|
</option>
|
||||||
<option value="maria">
|
|
||||||
MariaDB
|
|
||||||
</option>
|
|
||||||
<option value="pg">
|
|
||||||
PostgreSQL
|
|
||||||
</option>
|
|
||||||
<!-- <option value="mssql">
|
|
||||||
Microsoft SQL
|
|
||||||
</option>
|
|
||||||
<option value="oracledb">
|
|
||||||
Oracle DB
|
|
||||||
</option> -->
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group columns">
|
<div v-if="!customizations.fileConnection" class="form-group columns">
|
||||||
<div class="column col-4 col-sm-12">
|
<div class="column col-4 col-sm-12">
|
||||||
<label class="form-label">{{ $t('word.hostName') }}/IP</label>
|
<label class="form-label">{{ $t('word.hostName') }}/IP</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -79,7 +73,20 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group columns">
|
<div v-if="customizations.fileConnection" class="form-group columns">
|
||||||
|
<div class="column col-4 col-sm-12">
|
||||||
|
<label class="form-label">{{ $t('word.database') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="column col-8 col-sm-12">
|
||||||
|
<BaseUploadInput
|
||||||
|
:value="connection.databasePath"
|
||||||
|
:message="$t('word.browse')"
|
||||||
|
@clear="pathClear('databasePath')"
|
||||||
|
@change="pathSelection($event, 'databasePath')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="!customizations.fileConnection" class="form-group columns">
|
||||||
<div class="column col-4 col-sm-12">
|
<div class="column col-4 col-sm-12">
|
||||||
<label class="form-label">{{ $t('word.port') }}</label>
|
<label class="form-label">{{ $t('word.port') }}</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -105,7 +112,7 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group columns">
|
<div v-if="!customizations.fileConnection" class="form-group columns">
|
||||||
<div class="column col-4 col-sm-12">
|
<div class="column col-4 col-sm-12">
|
||||||
<label class="form-label">{{ $t('word.user') }}</label>
|
<label class="form-label">{{ $t('word.user') }}</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -118,7 +125,7 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group columns">
|
<div v-if="!customizations.fileConnection" class="form-group columns">
|
||||||
<div class="column col-4 col-sm-12">
|
<div class="column col-4 col-sm-12">
|
||||||
<label class="form-label">{{ $t('word.password') }}</label>
|
<label class="form-label">{{ $t('word.password') }}</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -144,7 +151,15 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group columns">
|
<div v-if="customizations.readOnlyMode" class="form-group columns">
|
||||||
|
<div class="column col-4 col-sm-12" />
|
||||||
|
<div class="column col-8 col-sm-12">
|
||||||
|
<label class="form-checkbox form-inline">
|
||||||
|
<input v-model="connection.readonly" type="checkbox"><i class="form-icon" /> {{ $t('message.readOnlyMode') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="!customizations.fileConnection" class="form-group columns">
|
||||||
<div class="column col-4 col-sm-12" />
|
<div class="column col-4 col-sm-12" />
|
||||||
<div class="column col-8 col-sm-12">
|
<div class="column col-8 col-sm-12">
|
||||||
<label class="form-checkbox form-inline">
|
<label class="form-checkbox form-inline">
|
||||||
@@ -369,15 +384,23 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
clients: [
|
||||||
|
{ name: 'MySQL', slug: 'mysql' },
|
||||||
|
{ name: 'MariaDB', slug: 'maria' },
|
||||||
|
{ name: 'PostgreSQL', slug: 'pg' },
|
||||||
|
{ name: 'SQLite', slug: 'sqlite' }
|
||||||
|
],
|
||||||
connection: {
|
connection: {
|
||||||
name: '',
|
name: '',
|
||||||
client: 'mysql',
|
client: 'mysql',
|
||||||
host: '127.0.0.1',
|
host: '127.0.0.1',
|
||||||
database: null,
|
database: null,
|
||||||
|
databasePath: '',
|
||||||
port: null,
|
port: null,
|
||||||
user: null,
|
user: null,
|
||||||
password: '',
|
password: '',
|
||||||
ask: false,
|
ask: false,
|
||||||
|
readonly: false,
|
||||||
uid: uidGen('C'),
|
uid: uidGen('C'),
|
||||||
ssl: false,
|
ssl: false,
|
||||||
cert: '',
|
cert: '',
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
<a class="tab-link">{{ $t('word.general') }}</a>
|
<a class="tab-link">{{ $t('word.general') }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
|
v-if="customizations.sslConnection"
|
||||||
class="tab-item c-hand"
|
class="tab-item c-hand"
|
||||||
:class="{'active': selectedTab === 'ssl'}"
|
:class="{'active': selectedTab === 'ssl'}"
|
||||||
@click="selectTab('ssl')"
|
@click="selectTab('ssl')"
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
<a class="tab-link">{{ $t('word.ssl') }}</a>
|
<a class="tab-link">{{ $t('word.ssl') }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
|
v-if="customizations.sshConnection"
|
||||||
class="tab-item c-hand"
|
class="tab-item c-hand"
|
||||||
:class="{'active': selectedTab === 'ssh'}"
|
:class="{'active': selectedTab === 'ssh'}"
|
||||||
@click="selectTab('ssh')"
|
@click="selectTab('ssh')"
|
||||||
@@ -49,19 +51,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="column col-8 col-sm-12">
|
<div class="column col-8 col-sm-12">
|
||||||
<select v-model="localConnection.client" class="form-select">
|
<select v-model="localConnection.client" class="form-select">
|
||||||
<option value="mysql">
|
<option
|
||||||
MySQL
|
v-for="client in clients"
|
||||||
</option>
|
:key="client.slug"
|
||||||
<option value="maria">
|
:value="client.slug"
|
||||||
MariaDB
|
>
|
||||||
</option>
|
{{ client.name }}
|
||||||
<option value="pg">
|
|
||||||
PostgreSQL
|
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group columns">
|
<div v-if="!customizations.fileConnection" class="form-group columns">
|
||||||
<div class="column col-4 col-sm-12">
|
<div class="column col-4 col-sm-12">
|
||||||
<label class="form-label">{{ $t('word.hostName') }}/IP</label>
|
<label class="form-label">{{ $t('word.hostName') }}/IP</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -73,7 +73,20 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group columns">
|
<div v-if="customizations.fileConnection" class="form-group columns">
|
||||||
|
<div class="column col-4 col-sm-12">
|
||||||
|
<label class="form-label">{{ $t('word.database') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="column col-8 col-sm-12">
|
||||||
|
<BaseUploadInput
|
||||||
|
:value="localConnection.databasePath"
|
||||||
|
:message="$t('word.browse')"
|
||||||
|
@clear="pathClear('databasePath')"
|
||||||
|
@change="pathSelection($event, 'databasePath')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="!customizations.fileConnection" class="form-group columns">
|
||||||
<div class="column col-4 col-sm-12">
|
<div class="column col-4 col-sm-12">
|
||||||
<label class="form-label">{{ $t('word.port') }}</label>
|
<label class="form-label">{{ $t('word.port') }}</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -99,7 +112,7 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group columns">
|
<div v-if="!customizations.fileConnection" class="form-group columns">
|
||||||
<div class="column col-4 col-sm-12">
|
<div class="column col-4 col-sm-12">
|
||||||
<label class="form-label">{{ $t('word.user') }}</label>
|
<label class="form-label">{{ $t('word.user') }}</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -112,7 +125,7 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group columns">
|
<div v-if="!customizations.fileConnection" class="form-group columns">
|
||||||
<div class="column col-4 col-sm-12">
|
<div class="column col-4 col-sm-12">
|
||||||
<label class="form-label">{{ $t('word.password') }}</label>
|
<label class="form-label">{{ $t('word.password') }}</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -138,7 +151,15 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group columns">
|
<div v-if="customizations.readOnlyMode" class="form-group columns">
|
||||||
|
<div class="column col-4 col-sm-12" />
|
||||||
|
<div class="column col-8 col-sm-12">
|
||||||
|
<label class="form-checkbox form-inline">
|
||||||
|
<input v-model="localConnection.readonly" type="checkbox"><i class="form-icon" /> {{ $t('message.readOnlyMode') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="!customizations.fileConnection" class="form-group columns">
|
||||||
<div class="column col-4 col-sm-12" />
|
<div class="column col-4 col-sm-12" />
|
||||||
<div class="column col-8 col-sm-12">
|
<div class="column col-8 col-sm-12">
|
||||||
<label class="form-checkbox form-inline">
|
<label class="form-checkbox form-inline">
|
||||||
@@ -374,6 +395,12 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
clients: [
|
||||||
|
{ name: 'MySQL', slug: 'mysql' },
|
||||||
|
{ name: 'MariaDB', slug: 'maria' },
|
||||||
|
{ name: 'PostgreSQL', slug: 'pg' },
|
||||||
|
{ name: 'SQLite', slug: 'sqlite' }
|
||||||
|
],
|
||||||
isConnecting: false,
|
isConnecting: false,
|
||||||
isTesting: false,
|
isTesting: false,
|
||||||
isAsking: false,
|
isAsking: false,
|
||||||
@@ -383,7 +410,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
customizations () {
|
customizations () {
|
||||||
return customizations[this.connection.client];
|
return customizations[this.localConnection.client];
|
||||||
},
|
},
|
||||||
isBusy () {
|
isBusy () {
|
||||||
return this.isConnecting || this.isTesting;
|
return this.isConnecting || this.isTesting;
|
||||||
|
@@ -1,7 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="column col-12 empty">
|
<div class="column col-12 empty">
|
||||||
<div class="empty-icon">
|
<div class="empty-icon">
|
||||||
<img :src="require(`@/images/logo-${applicationTheme}.svg`).default" width="200">
|
<img
|
||||||
|
v-if="applicationTheme === 'dark'"
|
||||||
|
src="../images/logo-dark.svg"
|
||||||
|
width="200"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-if="applicationTheme === 'light'"
|
||||||
|
src="../images/logo-light.svg"
|
||||||
|
width="200"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<p class="h6 empty-subtitle">
|
<p class="h6 empty-subtitle">
|
||||||
{{ $t('message.noOpenTabs') }}
|
{{ $t('message.noOpenTabs') }}
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
<span class="workspace-explorebar-title">{{ connectionName }}</span>
|
<span class="workspace-explorebar-title">{{ connectionName }}</span>
|
||||||
<span v-if="workspace.connectionStatus === 'connected'" class="workspace-explorebar-tools">
|
<span v-if="workspace.connectionStatus === 'connected'" class="workspace-explorebar-tools">
|
||||||
<i
|
<i
|
||||||
|
v-if="customizations.schemas"
|
||||||
class="mdi mdi-18px mdi-database-plus c-hand mr-2"
|
class="mdi mdi-18px mdi-database-plus c-hand mr-2"
|
||||||
:title="$t('message.createNewSchema')"
|
:title="$t('message.createNewSchema')"
|
||||||
@click="showNewDBModal"
|
@click="showNewDBModal"
|
||||||
|
@@ -10,6 +10,30 @@
|
|||||||
>
|
>
|
||||||
<span class="d-flex"><i class="mdi mdi-18px mdi-play text-light pr-1" /> {{ $t('word.run') }}</span>
|
<span class="d-flex"><i class="mdi mdi-18px mdi-play text-light pr-1" /> {{ $t('word.run') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="selectedMisc.type === 'trigger' && customizations.triggerEnableDisable"
|
||||||
|
class="context-element"
|
||||||
|
@click="toggleTrigger"
|
||||||
|
>
|
||||||
|
<span v-if="!selectedMisc.enabled" class="d-flex">
|
||||||
|
<i class="mdi mdi-18px mdi-play text-light pr-1" /> {{ $t('word.enable') }}
|
||||||
|
</span>
|
||||||
|
<span v-else class="d-flex">
|
||||||
|
<i class="mdi mdi-18px mdi-pause text-light pr-1" /> {{ $t('word.disable') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="selectedMisc.type === 'scheduler'"
|
||||||
|
class="context-element"
|
||||||
|
@click="toggleScheduler"
|
||||||
|
>
|
||||||
|
<span v-if="!selectedMisc.enabled" class="d-flex">
|
||||||
|
<i class="mdi mdi-18px mdi-play text-light pr-1" /> {{ $t('word.enable') }}
|
||||||
|
</span>
|
||||||
|
<span v-else class="d-flex">
|
||||||
|
<i class="mdi mdi-18px mdi-pause text-light pr-1" /> {{ $t('word.disable') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<div class="context-element" @click="showDeleteModal">
|
<div class="context-element" @click="showDeleteModal">
|
||||||
<span class="d-flex"><i class="mdi mdi-18px mdi-table-remove text-light pr-1" /> {{ $t('word.delete') }}</span>
|
<span class="d-flex"><i class="mdi mdi-18px mdi-table-remove text-light pr-1" /> {{ $t('word.delete') }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -78,6 +102,9 @@ export default {
|
|||||||
workspace () {
|
workspace () {
|
||||||
return this.getWorkspace(this.selectedWorkspace);
|
return this.getWorkspace(this.selectedWorkspace);
|
||||||
},
|
},
|
||||||
|
customizations () {
|
||||||
|
return this.getWorkspace(this.selectedWorkspace).customizations;
|
||||||
|
},
|
||||||
deleteMessage () {
|
deleteMessage () {
|
||||||
switch (this.selectedMisc.type) {
|
switch (this.selectedMisc.type) {
|
||||||
case 'trigger':
|
case 'trigger':
|
||||||
@@ -98,6 +125,8 @@ export default {
|
|||||||
...mapActions({
|
...mapActions({
|
||||||
addNotification: 'notifications/addNotification',
|
addNotification: 'notifications/addNotification',
|
||||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
|
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
|
||||||
|
addLoadingElement: 'workspaces/addLoadingElement',
|
||||||
|
removeLoadingElement: 'workspaces/removeLoadingElement',
|
||||||
removeTabs: 'workspaces/removeTabs',
|
removeTabs: 'workspaces/removeTabs',
|
||||||
newTab: 'workspaces/newTab'
|
newTab: 'workspaces/newTab'
|
||||||
}),
|
}),
|
||||||
@@ -273,6 +302,68 @@ export default {
|
|||||||
|
|
||||||
this.newTab({ uid: this.workspace.uid, content: sql, type: 'query', autorun: true });
|
this.newTab({ uid: this.workspace.uid, content: sql, type: 'query', autorun: true });
|
||||||
this.closeContext();
|
this.closeContext();
|
||||||
|
},
|
||||||
|
async toggleTrigger () {
|
||||||
|
this.addLoadingElement({
|
||||||
|
name: this.selectedMisc.name,
|
||||||
|
schema: this.selectedSchema,
|
||||||
|
type: 'trigger'
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { status, response } = await Triggers.toggleTrigger({
|
||||||
|
uid: this.selectedWorkspace,
|
||||||
|
schema: this.selectedSchema,
|
||||||
|
trigger: this.selectedMisc.name,
|
||||||
|
enabled: this.selectedMisc.enabled
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status !== 'success')
|
||||||
|
this.addNotification({ status: 'error', message: response });
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.addNotification({ status: 'error', message: err.stack });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.removeLoadingElement({
|
||||||
|
name: this.selectedMisc.name,
|
||||||
|
schema: this.selectedSchema,
|
||||||
|
type: 'trigger'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.closeContext();
|
||||||
|
this.$emit('reload');
|
||||||
|
},
|
||||||
|
async toggleScheduler () {
|
||||||
|
this.addLoadingElement({
|
||||||
|
name: this.selectedMisc.name,
|
||||||
|
schema: this.selectedSchema,
|
||||||
|
type: 'scheduler'
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { status, response } = await Schedulers.toggleScheduler({
|
||||||
|
uid: this.selectedWorkspace,
|
||||||
|
schema: this.selectedSchema,
|
||||||
|
scheduler: this.selectedMisc.name,
|
||||||
|
enabled: this.selectedMisc.enabled
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status !== 'success')
|
||||||
|
this.addNotification({ status: 'error', message: response });
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.addNotification({ status: 'error', message: err.stack });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.removeLoadingElement({
|
||||||
|
name: this.selectedMisc.name,
|
||||||
|
schema: this.selectedSchema,
|
||||||
|
type: 'scheduler'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.closeContext();
|
||||||
|
this.$emit('reload');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -9,7 +9,16 @@
|
|||||||
<div v-if="isLoading" class="icon loading" />
|
<div v-if="isLoading" class="icon loading" />
|
||||||
<i v-else class="icon mdi mdi-18px mdi-chevron-right" />
|
<i v-else class="icon mdi mdi-18px mdi-chevron-right" />
|
||||||
<i class="database-icon mdi mdi-18px mdi-database mr-1" />
|
<i class="database-icon mdi mdi-18px mdi-database mr-1" />
|
||||||
<span>{{ database.name }}</span>
|
<div class="">
|
||||||
|
<span>{{ database.name }}</span>
|
||||||
|
<div
|
||||||
|
v-if="database.size"
|
||||||
|
class="schema-size tooltip tooltip-left mr-1"
|
||||||
|
:data-tooltip="formatBytes(database.size)"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-information-outline pr-2" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</summary>
|
</summary>
|
||||||
<div class="accordion-body">
|
<div class="accordion-body">
|
||||||
<div class="database-tables">
|
<div class="database-tables">
|
||||||
@@ -34,7 +43,7 @@
|
|||||||
<span v-html="highlightWord(table.name)" />
|
<span v-html="highlightWord(table.name)" />
|
||||||
</a>
|
</a>
|
||||||
<div
|
<div
|
||||||
v-if="table.type === 'table'"
|
v-if="table.type === 'table' && table.size !== false"
|
||||||
class="table-size tooltip tooltip-left mr-1"
|
class="table-size tooltip tooltip-left mr-1"
|
||||||
:data-tooltip="formatBytes(table.size)"
|
:data-tooltip="formatBytes(table.size)"
|
||||||
>
|
>
|
||||||
@@ -68,9 +77,17 @@
|
|||||||
@contextmenu.prevent="showMiscContext($event, {...trigger, type: 'trigger'})"
|
@contextmenu.prevent="showMiscContext($event, {...trigger, type: 'trigger'})"
|
||||||
>
|
>
|
||||||
<a class="table-name">
|
<a class="table-name">
|
||||||
<i class="table-icon mdi mdi-table-cog mdi-18px mr-1" />
|
<div v-if="checkLoadingStatus(trigger.name, 'trigger')" class="icon loading mr-1" />
|
||||||
|
<i v-else class="table-icon mdi mdi-table-cog mdi-18px mr-1" />
|
||||||
<span v-html="highlightWord(trigger.name)" />
|
<span v-html="highlightWord(trigger.name)" />
|
||||||
</a>
|
</a>
|
||||||
|
<div
|
||||||
|
v-if="trigger.enabled === false"
|
||||||
|
class="tooltip tooltip-left disabled-indicator"
|
||||||
|
:data-tooltip="$t('word.disabled')"
|
||||||
|
>
|
||||||
|
<i class="table-icon mdi mdi-pause mdi-18px mr-1" />
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -204,9 +221,17 @@
|
|||||||
@contextmenu.prevent="showMiscContext($event, {...scheduler, type: 'scheduler'})"
|
@contextmenu.prevent="showMiscContext($event, {...scheduler, type: 'scheduler'})"
|
||||||
>
|
>
|
||||||
<a class="table-name">
|
<a class="table-name">
|
||||||
<i class="table-icon mdi mdi-calendar-clock mdi-18px mr-1" />
|
<div v-if="checkLoadingStatus(scheduler.name, 'scheduler')" class="icon loading mr-1" />
|
||||||
|
<i v-else class="table-icon mdi mdi-calendar-clock mdi-18px mr-1" />
|
||||||
<span v-html="highlightWord(scheduler.name)" />
|
<span v-html="highlightWord(scheduler.name)" />
|
||||||
</a>
|
</a>
|
||||||
|
<div
|
||||||
|
v-if="scheduler.enabled === false"
|
||||||
|
class="tooltip tooltip-left disabled-indicator"
|
||||||
|
:data-tooltip="$t('word.disabled')"
|
||||||
|
>
|
||||||
|
<i class="table-icon mdi mdi-pause mdi-18px mr-1" />
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -426,6 +451,11 @@ export default {
|
|||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
|
||||||
|
.schema-size{
|
||||||
|
visibility: hidden;
|
||||||
|
width: 22.5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.database-name,
|
.database-name,
|
||||||
@@ -471,6 +501,10 @@ export default {
|
|||||||
.misc-name {
|
.misc-name {
|
||||||
&:hover {
|
&:hover {
|
||||||
border-radius: $border-radius;
|
border-radius: $border-radius;
|
||||||
|
|
||||||
|
.schema-size{
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,7 +534,9 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-size {
|
.schema-size,
|
||||||
|
.table-size,
|
||||||
|
.disabled-indicator {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@@ -65,7 +65,11 @@
|
|||||||
>
|
>
|
||||||
<span class="d-flex"><i class="mdi mdi-18px mdi-database-edit text-light pr-1" /> {{ $t('word.edit') }}</span>
|
<span class="d-flex"><i class="mdi mdi-18px mdi-database-edit text-light pr-1" /> {{ $t('word.edit') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="context-element" @click="showDeleteModal">
|
<div
|
||||||
|
v-if="workspace.customizations.schemaDrop"
|
||||||
|
class="context-element"
|
||||||
|
@click="showDeleteModal"
|
||||||
|
>
|
||||||
<span class="d-flex"><i class="mdi mdi-18px mdi-database-remove text-light pr-1" /> {{ $t('word.delete') }}</span>
|
<span class="d-flex"><i class="mdi mdi-18px mdi-database-remove text-light pr-1" /> {{ $t('word.delete') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -344,7 +344,7 @@ export default {
|
|||||||
},
|
},
|
||||||
addField () {
|
addField () {
|
||||||
this.localFields.push({
|
this.localFields.push({
|
||||||
_id: uidGen(),
|
_antares_id: uidGen(),
|
||||||
name: `${this.$tc('word.field', 1)}_${++this.newFieldsCounter}`,
|
name: `${this.$tc('word.field', 1)}_${++this.newFieldsCounter}`,
|
||||||
key: '',
|
key: '',
|
||||||
type: this.workspace.dataTypes[0].types[0].name,
|
type: this.workspace.dataTypes[0].types[0].name,
|
||||||
@@ -385,8 +385,8 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
duplicateField (uid) {
|
duplicateField (uid) {
|
||||||
const fieldToClone = Object.assign({}, this.localFields.find(field => field._id === uid));
|
const fieldToClone = Object.assign({}, this.localFields.find(field => field._antares_id === uid));
|
||||||
fieldToClone._id = uidGen();
|
fieldToClone._antares_id = uidGen();
|
||||||
fieldToClone.name = `${fieldToClone.name}_copy`;
|
fieldToClone.name = `${fieldToClone.name}_copy`;
|
||||||
fieldToClone.order = this.localFields.length + 1;
|
fieldToClone.order = this.localFields.length + 1;
|
||||||
this.localFields = [...this.localFields, fieldToClone];
|
this.localFields = [...this.localFields, fieldToClone];
|
||||||
@@ -397,11 +397,11 @@ export default {
|
|||||||
}, 20);
|
}, 20);
|
||||||
},
|
},
|
||||||
removeField (uid) {
|
removeField (uid) {
|
||||||
this.localFields = this.localFields.filter(field => field._id !== uid);
|
this.localFields = this.localFields.filter(field => field._antares_id !== uid);
|
||||||
},
|
},
|
||||||
addNewIndex (payload) {
|
addNewIndex (payload) {
|
||||||
this.localIndexes = [...this.localIndexes, {
|
this.localIndexes = [...this.localIndexes, {
|
||||||
_id: uidGen(),
|
_antares_id: uidGen(),
|
||||||
name: payload.index === 'PRIMARY' ? 'PRIMARY' : payload.field,
|
name: payload.index === 'PRIMARY' ? 'PRIMARY' : payload.field,
|
||||||
fields: [payload.field],
|
fields: [payload.field],
|
||||||
type: payload.index,
|
type: payload.index,
|
||||||
@@ -413,7 +413,7 @@ export default {
|
|||||||
},
|
},
|
||||||
addToIndex (payload) {
|
addToIndex (payload) {
|
||||||
this.localIndexes = this.localIndexes.map(index => {
|
this.localIndexes = this.localIndexes.map(index => {
|
||||||
if (index._id === payload.index) index.fields.push(payload.field);
|
if (index._antares_id === payload.index) index.fields.push(payload.field);
|
||||||
return index;
|
return index;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@@ -373,7 +373,7 @@ export default {
|
|||||||
this.originalFunction = response;
|
this.originalFunction = response;
|
||||||
|
|
||||||
this.originalFunction.parameters = [...this.originalFunction.parameters.map(param => {
|
this.originalFunction.parameters = [...this.originalFunction.parameters.map(param => {
|
||||||
param._id = uidGen();
|
param._antares_id = uidGen();
|
||||||
return param;
|
return param;
|
||||||
})];
|
})];
|
||||||
|
|
||||||
|
@@ -36,10 +36,10 @@
|
|||||||
<div ref="parametersPanel" class="panel-body p-0 pr-1">
|
<div ref="parametersPanel" class="panel-body p-0 pr-1">
|
||||||
<div
|
<div
|
||||||
v-for="param in parametersProxy"
|
v-for="param in parametersProxy"
|
||||||
:key="param._id"
|
:key="param._antares_id"
|
||||||
class="tile tile-centered c-hand mb-1 p-1"
|
class="tile tile-centered c-hand mb-1 p-1"
|
||||||
:class="{'selected-element': selectedParam === param._id}"
|
:class="{'selected-element': selectedParam === param._antares_id}"
|
||||||
@click="selectParameter($event, param._id)"
|
@click="selectParameter($event, param._antares_id)"
|
||||||
>
|
>
|
||||||
<div class="tile-icon">
|
<div class="tile-icon">
|
||||||
<div>
|
<div>
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<button
|
<button
|
||||||
class="btn btn-link remove-field p-0 mr-2"
|
class="btn btn-link remove-field p-0 mr-2"
|
||||||
:title="$t('word.delete')"
|
:title="$t('word.delete')"
|
||||||
@click.prevent="removeParameter(param._id)"
|
@click.prevent="removeParameter(param._antares_id)"
|
||||||
>
|
>
|
||||||
<i class="mdi mdi-close" />
|
<i class="mdi mdi-close" />
|
||||||
</button>
|
</button>
|
||||||
@@ -196,7 +196,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
selectedParamObj () {
|
selectedParamObj () {
|
||||||
return this.parametersProxy.find(param => param._id === this.selectedParam);
|
return this.parametersProxy.find(param => param._antares_id === this.selectedParam);
|
||||||
},
|
},
|
||||||
isChanged () {
|
isChanged () {
|
||||||
return JSON.stringify(this.localParameters) !== JSON.stringify(this.parametersProxy);
|
return JSON.stringify(this.localParameters) !== JSON.stringify(this.parametersProxy);
|
||||||
@@ -237,10 +237,11 @@ export default {
|
|||||||
this.modalInnerHeight = modalBody.clientHeight - (parseFloat(getComputedStyle(modalBody).paddingTop) + parseFloat(getComputedStyle(modalBody).paddingBottom));
|
this.modalInnerHeight = modalBody.clientHeight - (parseFloat(getComputedStyle(modalBody).paddingTop) + parseFloat(getComputedStyle(modalBody).paddingBottom));
|
||||||
},
|
},
|
||||||
addParameter () {
|
addParameter () {
|
||||||
|
const newUid = uidGen();
|
||||||
this.parametersProxy = [...this.parametersProxy, {
|
this.parametersProxy = [...this.parametersProxy, {
|
||||||
_id: uidGen(),
|
_antares_id: newUid,
|
||||||
name: `Param${this.i++}`,
|
name: `param${this.i++}`,
|
||||||
type: 'INT',
|
type: this.workspace.dataTypes[0].types[0].name,
|
||||||
context: 'IN',
|
context: 'IN',
|
||||||
length: ''
|
length: ''
|
||||||
}];
|
}];
|
||||||
@@ -250,12 +251,13 @@ export default {
|
|||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$refs.parametersPanel.scrollTop = this.$refs.parametersPanel.scrollHeight + 60;
|
this.$refs.parametersPanel.scrollTop = this.$refs.parametersPanel.scrollHeight + 60;
|
||||||
|
this.selectedParam = newUid;
|
||||||
}, 20);
|
}, 20);
|
||||||
},
|
},
|
||||||
removeParameter (uid) {
|
removeParameter (uid) {
|
||||||
this.parametersProxy = this.parametersProxy.filter(param => param._id !== uid);
|
this.parametersProxy = this.parametersProxy.filter(param => param._antares_id !== uid);
|
||||||
|
|
||||||
if (this.selectedParam === name && this.parametersProxy.length)
|
if (this.parametersProxy.length && this.selectedParam === uid)
|
||||||
this.resetSelectedID();
|
this.resetSelectedID();
|
||||||
},
|
},
|
||||||
clearChanges () {
|
clearChanges () {
|
||||||
@@ -266,7 +268,7 @@ export default {
|
|||||||
this.resetSelectedID();
|
this.resetSelectedID();
|
||||||
},
|
},
|
||||||
resetSelectedID () {
|
resetSelectedID () {
|
||||||
this.selectedParam = this.parametersProxy.length ? this.parametersProxy[0]._id : '';
|
this.selectedParam = this.parametersProxy.length ? this.parametersProxy[0]._antares_id : '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -318,7 +318,7 @@ export default {
|
|||||||
this.originalRoutine = response;
|
this.originalRoutine = response;
|
||||||
|
|
||||||
this.originalRoutine.parameters = [...this.originalRoutine.parameters.map(param => {
|
this.originalRoutine.parameters = [...this.originalRoutine.parameters.map(param => {
|
||||||
param._id = uidGen();
|
param._antares_id = uidGen();
|
||||||
return param;
|
return param;
|
||||||
})];
|
})];
|
||||||
|
|
||||||
|
@@ -36,10 +36,10 @@
|
|||||||
<div ref="parametersPanel" class="panel-body p-0 pr-1">
|
<div ref="parametersPanel" class="panel-body p-0 pr-1">
|
||||||
<div
|
<div
|
||||||
v-for="param in parametersProxy"
|
v-for="param in parametersProxy"
|
||||||
:key="param._id"
|
:key="param._antares_id"
|
||||||
class="tile tile-centered c-hand mb-1 p-1"
|
class="tile tile-centered c-hand mb-1 p-1"
|
||||||
:class="{'selected-element': selectedParam === param._id}"
|
:class="{'selected-element': selectedParam === param._antares_id}"
|
||||||
@click="selectParameter($event, param._id)"
|
@click="selectParameter($event, param._antares_id)"
|
||||||
>
|
>
|
||||||
<div class="tile-icon">
|
<div class="tile-icon">
|
||||||
<div>
|
<div>
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<button
|
<button
|
||||||
class="btn btn-link remove-field p-0 mr-2"
|
class="btn btn-link remove-field p-0 mr-2"
|
||||||
:title="$t('word.delete')"
|
:title="$t('word.delete')"
|
||||||
@click.prevent="removeParameter(param._id)"
|
@click.prevent="removeParameter(param._antares_id)"
|
||||||
>
|
>
|
||||||
<i class="mdi mdi-close" />
|
<i class="mdi mdi-close" />
|
||||||
</button>
|
</button>
|
||||||
@@ -196,7 +196,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
selectedParamObj () {
|
selectedParamObj () {
|
||||||
return this.parametersProxy.find(param => param._id === this.selectedParam);
|
return this.parametersProxy.find(param => param._antares_id === this.selectedParam);
|
||||||
},
|
},
|
||||||
isChanged () {
|
isChanged () {
|
||||||
return JSON.stringify(this.localParameters) !== JSON.stringify(this.parametersProxy);
|
return JSON.stringify(this.localParameters) !== JSON.stringify(this.parametersProxy);
|
||||||
@@ -237,8 +237,9 @@ export default {
|
|||||||
this.modalInnerHeight = modalBody.clientHeight - (parseFloat(getComputedStyle(modalBody).paddingTop) + parseFloat(getComputedStyle(modalBody).paddingBottom));
|
this.modalInnerHeight = modalBody.clientHeight - (parseFloat(getComputedStyle(modalBody).paddingTop) + parseFloat(getComputedStyle(modalBody).paddingBottom));
|
||||||
},
|
},
|
||||||
addParameter () {
|
addParameter () {
|
||||||
|
const newUid = uidGen();
|
||||||
this.parametersProxy = [...this.parametersProxy, {
|
this.parametersProxy = [...this.parametersProxy, {
|
||||||
_id: uidGen(),
|
_antares_id: newUid,
|
||||||
name: `param${this.i++}`,
|
name: `param${this.i++}`,
|
||||||
type: this.workspace.dataTypes[0].types[0].name,
|
type: this.workspace.dataTypes[0].types[0].name,
|
||||||
context: 'IN',
|
context: 'IN',
|
||||||
@@ -250,12 +251,13 @@ export default {
|
|||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$refs.parametersPanel.scrollTop = this.$refs.parametersPanel.scrollHeight + 60;
|
this.$refs.parametersPanel.scrollTop = this.$refs.parametersPanel.scrollHeight + 60;
|
||||||
|
this.selectedParam = newUid;
|
||||||
}, 20);
|
}, 20);
|
||||||
},
|
},
|
||||||
removeParameter (uid) {
|
removeParameter (uid) {
|
||||||
this.parametersProxy = this.parametersProxy.filter(param => param._id !== uid);
|
this.parametersProxy = this.parametersProxy.filter(param => param._antares_id !== uid);
|
||||||
|
|
||||||
if (this.selectedParam === name && this.parametersProxy.length)
|
if (this.parametersProxy.length && this.selectedParam === uid)
|
||||||
this.resetSelectedID();
|
this.resetSelectedID();
|
||||||
},
|
},
|
||||||
clearChanges () {
|
clearChanges () {
|
||||||
@@ -266,7 +268,7 @@ export default {
|
|||||||
this.resetSelectedID();
|
this.resetSelectedID();
|
||||||
},
|
},
|
||||||
resetSelectedID () {
|
resetSelectedID () {
|
||||||
this.selectedParam = this.parametersProxy.length ? this.parametersProxy[0]._id : '';
|
this.selectedParam = this.parametersProxy.length ? this.parametersProxy[0]._antares_id : '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -342,7 +342,7 @@ export default {
|
|||||||
field.default = `'${field.default}'`;
|
field.default = `'${field.default}'`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { ...field, _id: uidGen() };
|
return { ...field, _antares_id: uidGen() };
|
||||||
});
|
});
|
||||||
this.localFields = JSON.parse(JSON.stringify(this.originalFields));
|
this.localFields = JSON.parse(JSON.stringify(this.originalFields));
|
||||||
}
|
}
|
||||||
@@ -365,7 +365,7 @@ export default {
|
|||||||
|
|
||||||
this.originalIndexes = Object.keys(indexesObj).map(index => {
|
this.originalIndexes = Object.keys(indexesObj).map(index => {
|
||||||
return {
|
return {
|
||||||
_id: uidGen(),
|
_antares_id: uidGen(),
|
||||||
name: index,
|
name: index,
|
||||||
fields: indexesObj[index].map(field => field.column),
|
fields: indexesObj[index].map(field => field.column),
|
||||||
type: indexesObj[index][0].type,
|
type: indexesObj[index][0].type,
|
||||||
@@ -391,7 +391,7 @@ export default {
|
|||||||
if (status === 'success') {
|
if (status === 'success') {
|
||||||
this.originalKeyUsage = response.map(foreign => {
|
this.originalKeyUsage = response.map(foreign => {
|
||||||
return {
|
return {
|
||||||
_id: uidGen(),
|
_antares_id: uidGen(),
|
||||||
...foreign
|
...foreign
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -411,25 +411,25 @@ export default {
|
|||||||
this.isSaving = true;
|
this.isSaving = true;
|
||||||
|
|
||||||
// FIELDS
|
// FIELDS
|
||||||
const originalIDs = this.originalFields.reduce((acc, curr) => [...acc, curr._id], []);
|
const originalIDs = this.originalFields.reduce((acc, curr) => [...acc, curr._antares_id], []);
|
||||||
const localIDs = this.localFields.reduce((acc, curr) => [...acc, curr._id], []);
|
const localIDs = this.localFields.reduce((acc, curr) => [...acc, curr._antares_id], []);
|
||||||
|
|
||||||
// Fields Additions
|
// Fields Additions
|
||||||
const additions = this.localFields.filter((field, i) => !originalIDs.includes(field._id)).map(field => {
|
const additions = this.localFields.filter((field, i) => !originalIDs.includes(field._antares_id)).map(field => {
|
||||||
const lI = this.localFields.findIndex(localField => localField._id === field._id);
|
const lI = this.localFields.findIndex(localField => localField._antares_id === field._antares_id);
|
||||||
const after = lI > 0 ? this.localFields[lI - 1].name : false;
|
const after = lI > 0 ? this.localFields[lI - 1].name : false;
|
||||||
return { ...field, after };
|
return { ...field, after };
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fields Deletions
|
// Fields Deletions
|
||||||
const deletions = this.originalFields.filter(field => !localIDs.includes(field._id));
|
const deletions = this.originalFields.filter(field => !localIDs.includes(field._antares_id));
|
||||||
|
|
||||||
// Fields Changes
|
// Fields Changes
|
||||||
const changes = [];
|
const changes = [];
|
||||||
this.originalFields.forEach((originalField, oI) => {
|
this.originalFields.forEach((originalField, oI) => {
|
||||||
const lI = this.localFields.findIndex(localField => localField._id === originalField._id);
|
const lI = this.localFields.findIndex(localField => localField._antares_id === originalField._antares_id);
|
||||||
const originalSibling = oI > 0 ? this.originalFields[oI - 1]._id : false;
|
const originalSibling = oI > 0 ? this.originalFields[oI - 1]._antares_id : false;
|
||||||
const localSibling = lI > 0 ? this.localFields[lI - 1]._id : false;
|
const localSibling = lI > 0 ? this.localFields[lI - 1]._antares_id : false;
|
||||||
const after = lI > 0 ? this.localFields[lI - 1].name : false;
|
const after = lI > 0 ? this.localFields[lI - 1].name : false;
|
||||||
const orgName = originalField.name;
|
const orgName = originalField.name;
|
||||||
|
|
||||||
@@ -450,15 +450,15 @@ export default {
|
|||||||
changes: [],
|
changes: [],
|
||||||
deletions: []
|
deletions: []
|
||||||
};
|
};
|
||||||
const originalIndexIDs = this.originalIndexes.reduce((acc, curr) => [...acc, curr._id], []);
|
const originalIndexIDs = this.originalIndexes.reduce((acc, curr) => [...acc, curr._antares_id], []);
|
||||||
const localIndexIDs = this.localIndexes.reduce((acc, curr) => [...acc, curr._id], []);
|
const localIndexIDs = this.localIndexes.reduce((acc, curr) => [...acc, curr._antares_id], []);
|
||||||
|
|
||||||
// Index Additions
|
// Index Additions
|
||||||
indexChanges.additions = this.localIndexes.filter(index => !originalIndexIDs.includes(index._id));
|
indexChanges.additions = this.localIndexes.filter(index => !originalIndexIDs.includes(index._antares_id));
|
||||||
|
|
||||||
// Index Changes
|
// Index Changes
|
||||||
this.originalIndexes.forEach(originalIndex => {
|
this.originalIndexes.forEach(originalIndex => {
|
||||||
const lI = this.localIndexes.findIndex(localIndex => localIndex._id === originalIndex._id);
|
const lI = this.localIndexes.findIndex(localIndex => localIndex._antares_id === originalIndex._antares_id);
|
||||||
if (JSON.stringify(originalIndex) !== JSON.stringify(this.localIndexes[lI])) {
|
if (JSON.stringify(originalIndex) !== JSON.stringify(this.localIndexes[lI])) {
|
||||||
if (this.localIndexes[lI]) {
|
if (this.localIndexes[lI]) {
|
||||||
indexChanges.changes.push({
|
indexChanges.changes.push({
|
||||||
@@ -471,7 +471,7 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Index Deletions
|
// Index Deletions
|
||||||
indexChanges.deletions = this.originalIndexes.filter(index => !localIndexIDs.includes(index._id));
|
indexChanges.deletions = this.originalIndexes.filter(index => !localIndexIDs.includes(index._antares_id));
|
||||||
|
|
||||||
// FOREIGN KEYS
|
// FOREIGN KEYS
|
||||||
const foreignChanges = {
|
const foreignChanges = {
|
||||||
@@ -479,15 +479,15 @@ export default {
|
|||||||
changes: [],
|
changes: [],
|
||||||
deletions: []
|
deletions: []
|
||||||
};
|
};
|
||||||
const originalForeignIDs = this.originalKeyUsage.reduce((acc, curr) => [...acc, curr._id], []);
|
const originalForeignIDs = this.originalKeyUsage.reduce((acc, curr) => [...acc, curr._antares_id], []);
|
||||||
const localForeignIDs = this.localKeyUsage.reduce((acc, curr) => [...acc, curr._id], []);
|
const localForeignIDs = this.localKeyUsage.reduce((acc, curr) => [...acc, curr._antares_id], []);
|
||||||
|
|
||||||
// Foreigns Additions
|
// Foreigns Additions
|
||||||
foreignChanges.additions = this.localKeyUsage.filter(foreign => !originalForeignIDs.includes(foreign._id));
|
foreignChanges.additions = this.localKeyUsage.filter(foreign => !originalForeignIDs.includes(foreign._antares_id));
|
||||||
|
|
||||||
// Foreigns Changes
|
// Foreigns Changes
|
||||||
this.originalKeyUsage.forEach(originalForeign => {
|
this.originalKeyUsage.forEach(originalForeign => {
|
||||||
const lI = this.localKeyUsage.findIndex(localForeign => localForeign._id === originalForeign._id);
|
const lI = this.localKeyUsage.findIndex(localForeign => localForeign._antares_id === originalForeign._antares_id);
|
||||||
if (JSON.stringify(originalForeign) !== JSON.stringify(this.localKeyUsage[lI])) {
|
if (JSON.stringify(originalForeign) !== JSON.stringify(this.localKeyUsage[lI])) {
|
||||||
if (this.localKeyUsage[lI]) {
|
if (this.localKeyUsage[lI]) {
|
||||||
foreignChanges.changes.push({
|
foreignChanges.changes.push({
|
||||||
@@ -499,13 +499,19 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Foreigns Deletions
|
// Foreigns Deletions
|
||||||
foreignChanges.deletions = this.originalKeyUsage.filter(foreign => !localForeignIDs.includes(foreign._id));
|
foreignChanges.deletions = this.originalKeyUsage.filter(foreign => !localForeignIDs.includes(foreign._antares_id));
|
||||||
|
|
||||||
// ALTER
|
// ALTER
|
||||||
const params = {
|
const params = {
|
||||||
uid: this.connection.uid,
|
uid: this.connection.uid,
|
||||||
schema: this.schema,
|
schema: this.schema,
|
||||||
table: this.table,
|
table: this.table,
|
||||||
|
tableStructure: {
|
||||||
|
name: this.localOptions.name,
|
||||||
|
fields: this.localFields,
|
||||||
|
foreigns: this.localKeyUsage,
|
||||||
|
indexes: this.localIndexes
|
||||||
|
},
|
||||||
additions,
|
additions,
|
||||||
changes,
|
changes,
|
||||||
deletions,
|
deletions,
|
||||||
@@ -555,7 +561,7 @@ export default {
|
|||||||
},
|
},
|
||||||
addField () {
|
addField () {
|
||||||
this.localFields.push({
|
this.localFields.push({
|
||||||
_id: uidGen(),
|
_antares_id: uidGen(),
|
||||||
name: `${this.$tc('word.field', 1)}_${++this.newFieldsCounter}`,
|
name: `${this.$tc('word.field', 1)}_${++this.newFieldsCounter}`,
|
||||||
key: '',
|
key: '',
|
||||||
type: this.workspace.dataTypes[0].types[0].name,
|
type: this.workspace.dataTypes[0].types[0].name,
|
||||||
@@ -597,8 +603,8 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
duplicateField (uid) {
|
duplicateField (uid) {
|
||||||
const fieldToClone = Object.assign({}, this.localFields.find(field => field._id === uid));
|
const fieldToClone = Object.assign({}, this.localFields.find(field => field._antares_id === uid));
|
||||||
fieldToClone._id = uidGen();
|
fieldToClone._antares_id = uidGen();
|
||||||
fieldToClone.name = `${fieldToClone.name}_copy`;
|
fieldToClone.name = `${fieldToClone.name}_copy`;
|
||||||
fieldToClone.order = this.localFields.length + 1;
|
fieldToClone.order = this.localFields.length + 1;
|
||||||
this.localFields = [...this.localFields, fieldToClone];
|
this.localFields = [...this.localFields, fieldToClone];
|
||||||
@@ -609,11 +615,11 @@ export default {
|
|||||||
}, 20);
|
}, 20);
|
||||||
},
|
},
|
||||||
removeField (uid) {
|
removeField (uid) {
|
||||||
this.localFields = this.localFields.filter(field => field._id !== uid);
|
this.localFields = this.localFields.filter(field => field._antares_id !== uid);
|
||||||
},
|
},
|
||||||
addNewIndex (payload) {
|
addNewIndex (payload) {
|
||||||
this.localIndexes = [...this.localIndexes, {
|
this.localIndexes = [...this.localIndexes, {
|
||||||
_id: uidGen(),
|
_antares_id: uidGen(),
|
||||||
name: payload.index === 'PRIMARY' ? 'PRIMARY' : payload.field,
|
name: payload.index === 'PRIMARY' ? 'PRIMARY' : payload.field,
|
||||||
fields: [payload.field],
|
fields: [payload.field],
|
||||||
type: payload.index,
|
type: payload.index,
|
||||||
@@ -625,7 +631,7 @@ export default {
|
|||||||
},
|
},
|
||||||
addToIndex (payload) {
|
addToIndex (payload) {
|
||||||
this.localIndexes = this.localIndexes.map(index => {
|
this.localIndexes = this.localIndexes.map(index => {
|
||||||
if (index._id === payload.index) index.fields.push(payload.field);
|
if (index._antares_id === payload.index) index.fields.push(payload.field);
|
||||||
return index;
|
return index;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
:key="index.name"
|
:key="index.name"
|
||||||
class="context-element"
|
class="context-element"
|
||||||
:class="{'disabled': index.fields.includes(selectedField.name)}"
|
:class="{'disabled': index.fields.includes(selectedField.name)}"
|
||||||
@click="addToIndex(index._id)"
|
@click="addToIndex(index._antares_id)"
|
||||||
>
|
>
|
||||||
<span class="d-flex"><i class="mdi mdi-18px mdi-key column-key pr-1" :class="`key-${index.type}`" /> {{ index.name }}</span>
|
<span class="d-flex"><i class="mdi mdi-18px mdi-key column-key pr-1" :class="`key-${index.type}`" /> {{ index.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -109,7 +109,7 @@
|
|||||||
>
|
>
|
||||||
<TableRow
|
<TableRow
|
||||||
v-for="row in fields"
|
v-for="row in fields"
|
||||||
:key="row._id"
|
:key="row._antares_id"
|
||||||
:row="row"
|
:row="row"
|
||||||
:indexes="getIndexes(row.name)"
|
:indexes="getIndexes(row.name)"
|
||||||
:foreigns="getForeigns(row.name)"
|
:foreigns="getForeigns(row.name)"
|
||||||
@@ -217,15 +217,15 @@ export default {
|
|||||||
this.resizeResults();
|
this.resizeResults();
|
||||||
},
|
},
|
||||||
contextMenu (event, uid) {
|
contextMenu (event, uid) {
|
||||||
this.selectedField = this.fields.find(field => field._id === uid);
|
this.selectedField = this.fields.find(field => field._antares_id === uid);
|
||||||
this.contextEvent = event;
|
this.contextEvent = event;
|
||||||
this.isContext = true;
|
this.isContext = true;
|
||||||
},
|
},
|
||||||
duplicateField () {
|
duplicateField () {
|
||||||
this.$emit('duplicate-field', this.selectedField._id);
|
this.$emit('duplicate-field', this.selectedField._antares_id);
|
||||||
},
|
},
|
||||||
removeField () {
|
removeField () {
|
||||||
this.$emit('remove-field', this.selectedField._id);
|
this.$emit('remove-field', this.selectedField._antares_id);
|
||||||
},
|
},
|
||||||
getIndexes (field) {
|
getIndexes (field) {
|
||||||
return this.indexes.reduce((acc, curr) => {
|
return this.indexes.reduce((acc, curr) => {
|
||||||
|
@@ -36,10 +36,10 @@
|
|||||||
<div ref="indexesPanel" class="panel-body p-0 pr-1">
|
<div ref="indexesPanel" class="panel-body p-0 pr-1">
|
||||||
<div
|
<div
|
||||||
v-for="foreign in foreignProxy"
|
v-for="foreign in foreignProxy"
|
||||||
:key="foreign._id"
|
:key="foreign._antares_id"
|
||||||
class="tile tile-centered c-hand mb-1 p-1"
|
class="tile tile-centered c-hand mb-1 p-1"
|
||||||
:class="{'selected-element': selectedForeignID === foreign._id}"
|
:class="{'selected-element': selectedForeignID === foreign._antares_id}"
|
||||||
@click="selectForeign($event, foreign._id)"
|
@click="selectForeign($event, foreign._antares_id)"
|
||||||
>
|
>
|
||||||
<div class="tile-icon">
|
<div class="tile-icon">
|
||||||
<div>
|
<div>
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
<button
|
<button
|
||||||
class="btn btn-link remove-field p-0 mr-2"
|
class="btn btn-link remove-field p-0 mr-2"
|
||||||
:title="$t('word.delete')"
|
:title="$t('word.delete')"
|
||||||
@click.prevent="removeIndex(foreign._id)"
|
@click.prevent="removeIndex(foreign._antares_id)"
|
||||||
>
|
>
|
||||||
<i class="mdi mdi-close" />
|
<i class="mdi mdi-close" />
|
||||||
</button>
|
</button>
|
||||||
@@ -238,7 +238,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
selectedForeignObj () {
|
selectedForeignObj () {
|
||||||
return this.foreignProxy.find(foreign => foreign._id === this.selectedForeignID);
|
return this.foreignProxy.find(foreign => foreign._antares_id === this.selectedForeignID);
|
||||||
},
|
},
|
||||||
isChanged () {
|
isChanged () {
|
||||||
return JSON.stringify(this.localKeyUsage) !== JSON.stringify(this.foreignProxy);
|
return JSON.stringify(this.localKeyUsage) !== JSON.stringify(this.foreignProxy);
|
||||||
@@ -288,7 +288,7 @@ export default {
|
|||||||
},
|
},
|
||||||
addForeign () {
|
addForeign () {
|
||||||
this.foreignProxy = [...this.foreignProxy, {
|
this.foreignProxy = [...this.foreignProxy, {
|
||||||
_id: uidGen(),
|
_antares_id: uidGen(),
|
||||||
constraintName: `FK_${this.foreignProxy.length + 1}`,
|
constraintName: `FK_${this.foreignProxy.length + 1}`,
|
||||||
refSchema: this.schema,
|
refSchema: this.schema,
|
||||||
table: this.table,
|
table: this.table,
|
||||||
@@ -307,19 +307,19 @@ export default {
|
|||||||
}, 20);
|
}, 20);
|
||||||
},
|
},
|
||||||
removeIndex (id) {
|
removeIndex (id) {
|
||||||
this.foreignProxy = this.foreignProxy.filter(foreign => foreign._id !== id);
|
this.foreignProxy = this.foreignProxy.filter(foreign => foreign._antares_id !== id);
|
||||||
|
|
||||||
if (this.selectedForeignID === id && this.foreignProxy.length)
|
if (this.selectedForeignID === id && this.foreignProxy.length)
|
||||||
this.resetSelectedID();
|
this.resetSelectedID();
|
||||||
},
|
},
|
||||||
clearChanges () {
|
clearChanges () {
|
||||||
this.foreignProxy = JSON.parse(JSON.stringify(this.localKeyUsage));
|
this.foreignProxy = JSON.parse(JSON.stringify(this.localKeyUsage));
|
||||||
if (!this.foreignProxy.some(foreign => foreign._id === this.selectedForeignID))
|
if (!this.foreignProxy.some(foreign => foreign._antares_id === this.selectedForeignID))
|
||||||
this.resetSelectedID();
|
this.resetSelectedID();
|
||||||
},
|
},
|
||||||
toggleField (field) {
|
toggleField (field) {
|
||||||
this.foreignProxy = this.foreignProxy.map(foreign => {
|
this.foreignProxy = this.foreignProxy.map(foreign => {
|
||||||
if (foreign._id === this.selectedForeignID)
|
if (foreign._antares_id === this.selectedForeignID)
|
||||||
foreign.field = field;
|
foreign.field = field;
|
||||||
|
|
||||||
return foreign;
|
return foreign;
|
||||||
@@ -327,14 +327,14 @@ export default {
|
|||||||
},
|
},
|
||||||
toggleRefField (field) {
|
toggleRefField (field) {
|
||||||
this.foreignProxy = this.foreignProxy.map(foreign => {
|
this.foreignProxy = this.foreignProxy.map(foreign => {
|
||||||
if (foreign._id === this.selectedForeignID)
|
if (foreign._antares_id === this.selectedForeignID)
|
||||||
foreign.refField = field;
|
foreign.refField = field;
|
||||||
|
|
||||||
return foreign;
|
return foreign;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
resetSelectedID () {
|
resetSelectedID () {
|
||||||
this.selectedForeignID = this.foreignProxy.length ? this.foreignProxy[0]._id : '';
|
this.selectedForeignID = this.foreignProxy.length ? this.foreignProxy[0]._antares_id : '';
|
||||||
},
|
},
|
||||||
async getRefFields () {
|
async getRefFields () {
|
||||||
if (!this.selectedForeignObj.refTable) return;
|
if (!this.selectedForeignObj.refTable) return;
|
||||||
|
@@ -36,10 +36,10 @@
|
|||||||
<div ref="indexesPanel" class="panel-body p-0 pr-1">
|
<div ref="indexesPanel" class="panel-body p-0 pr-1">
|
||||||
<div
|
<div
|
||||||
v-for="index in indexesProxy"
|
v-for="index in indexesProxy"
|
||||||
:key="index._id"
|
:key="index._antares_id"
|
||||||
class="tile tile-centered c-hand mb-1 p-1"
|
class="tile tile-centered c-hand mb-1 p-1"
|
||||||
:class="{'selected-element': selectedIndexID === index._id}"
|
:class="{'selected-element': selectedIndexID === index._antares_id}"
|
||||||
@click="selectIndex($event, index._id)"
|
@click="selectIndex($event, index._antares_id)"
|
||||||
>
|
>
|
||||||
<div class="tile-icon">
|
<div class="tile-icon">
|
||||||
<div>
|
<div>
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<button
|
<button
|
||||||
class="btn btn-link remove-field p-0 mr-2"
|
class="btn btn-link remove-field p-0 mr-2"
|
||||||
:title="$t('word.delete')"
|
:title="$t('word.delete')"
|
||||||
@click.prevent="removeIndex(index._id)"
|
@click.prevent="removeIndex(index._antares_id)"
|
||||||
>
|
>
|
||||||
<i class="mdi mdi-close" />
|
<i class="mdi mdi-close" />
|
||||||
</button>
|
</button>
|
||||||
@@ -163,7 +163,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
selectedIndexObj () {
|
selectedIndexObj () {
|
||||||
return this.indexesProxy.find(index => index._id === this.selectedIndexID);
|
return this.indexesProxy.find(index => index._antares_id === this.selectedIndexID);
|
||||||
},
|
},
|
||||||
isChanged () {
|
isChanged () {
|
||||||
return JSON.stringify(this.localIndexes) !== JSON.stringify(this.indexesProxy);
|
return JSON.stringify(this.localIndexes) !== JSON.stringify(this.indexesProxy);
|
||||||
@@ -200,7 +200,7 @@ export default {
|
|||||||
},
|
},
|
||||||
addIndex () {
|
addIndex () {
|
||||||
this.indexesProxy = [...this.indexesProxy, {
|
this.indexesProxy = [...this.indexesProxy, {
|
||||||
_id: uidGen(),
|
_antares_id: uidGen(),
|
||||||
name: 'NEW_INDEX',
|
name: 'NEW_INDEX',
|
||||||
fields: [],
|
fields: [],
|
||||||
type: 'INDEX',
|
type: 'INDEX',
|
||||||
@@ -218,19 +218,19 @@ export default {
|
|||||||
}, 20);
|
}, 20);
|
||||||
},
|
},
|
||||||
removeIndex (id) {
|
removeIndex (id) {
|
||||||
this.indexesProxy = this.indexesProxy.filter(index => index._id !== id);
|
this.indexesProxy = this.indexesProxy.filter(index => index._antares_id !== id);
|
||||||
|
|
||||||
if (this.selectedIndexID === id && this.indexesProxy.length)
|
if (this.selectedIndexID === id && this.indexesProxy.length)
|
||||||
this.resetSelectedID();
|
this.resetSelectedID();
|
||||||
},
|
},
|
||||||
clearChanges () {
|
clearChanges () {
|
||||||
this.indexesProxy = JSON.parse(JSON.stringify(this.localIndexes));
|
this.indexesProxy = JSON.parse(JSON.stringify(this.localIndexes));
|
||||||
if (!this.indexesProxy.some(index => index._id === this.selectedIndexID))
|
if (!this.indexesProxy.some(index => index._antares_id === this.selectedIndexID))
|
||||||
this.resetSelectedID();
|
this.resetSelectedID();
|
||||||
},
|
},
|
||||||
toggleField (field) {
|
toggleField (field) {
|
||||||
this.indexesProxy = this.indexesProxy.map(index => {
|
this.indexesProxy = this.indexesProxy.map(index => {
|
||||||
if (index._id === this.selectedIndexID) {
|
if (index._antares_id === this.selectedIndexID) {
|
||||||
if (index.fields.includes(field))
|
if (index.fields.includes(field))
|
||||||
index.fields = index.fields.filter(f => f !== field);
|
index.fields = index.fields.filter(f => f !== field);
|
||||||
else
|
else
|
||||||
@@ -240,7 +240,7 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
resetSelectedID () {
|
resetSelectedID () {
|
||||||
this.selectedIndexID = this.indexesProxy.length ? this.indexesProxy[0]._id : '';
|
this.selectedIndexID = this.indexesProxy.length ? this.indexesProxy[0]._antares_id : '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tr" @contextmenu.prevent="$emit('contextmenu', $event, localRow._id)">
|
<div class="tr" @contextmenu.prevent="$emit('contextmenu', $event, localRow._antares_id)">
|
||||||
<div class="td p-0" tabindex="0">
|
<div class="td p-0" tabindex="0">
|
||||||
<div :class="customizations.sortableFields ? 'row-draggable' : 'text-center'">
|
<div :class="customizations.sortableFields ? 'row-draggable' : 'text-center'">
|
||||||
<i v-if="customizations.sortableFields" class="mdi mdi-drag-horizontal row-draggable-icon" />
|
<i v-if="customizations.sortableFields" class="mdi mdi-drag-horizontal row-draggable-icon" />
|
||||||
@@ -367,7 +367,8 @@ export default {
|
|||||||
getWorkspace: 'workspaces/getWorkspace'
|
getWorkspace: 'workspaces/getWorkspace'
|
||||||
}),
|
}),
|
||||||
localLength () {
|
localLength () {
|
||||||
return this.localRow.numLength || this.localRow.charLength || this.localRow.datePrecision || this.localRow.numPrecision || 0;
|
const localLength = this.localRow.numLength || this.localRow.charLength || this.localRow.datePrecision || this.localRow.numPrecision || 0;
|
||||||
|
return localLength === true ? null : localLength;
|
||||||
},
|
},
|
||||||
fieldType () {
|
fieldType () {
|
||||||
const fieldType = this.dataTypes.reduce((acc, group) => [...acc, ...group.types], []).filter(type =>
|
const fieldType = this.dataTypes.reduce((acc, group) => [...acc, ...group.types], []).filter(type =>
|
||||||
@@ -391,7 +392,7 @@ export default {
|
|||||||
return this.indexes.some(index => ['PRIMARY', 'UNIQUE'].includes(index.type));
|
return this.indexes.some(index => ['PRIMARY', 'UNIQUE'].includes(index.type));
|
||||||
},
|
},
|
||||||
isNullable () {
|
isNullable () {
|
||||||
return !this.indexes.some(index => ['PRIMARY'].includes(index.type));
|
return this.customizations.nullablePrimary || !this.indexes.some(index => ['PRIMARY'].includes(index.type));
|
||||||
},
|
},
|
||||||
isInDataTypes () {
|
isInDataTypes () {
|
||||||
let typeNames = [];
|
let typeNames = [];
|
||||||
|
@@ -238,7 +238,7 @@ export default {
|
|||||||
this.originalFunction = response;
|
this.originalFunction = response;
|
||||||
|
|
||||||
this.originalFunction.parameters = [...this.originalFunction.parameters.map(param => {
|
this.originalFunction.parameters = [...this.originalFunction.parameters.map(param => {
|
||||||
param._id = uidGen();
|
param._antares_id = uidGen();
|
||||||
return param;
|
return param;
|
||||||
})];
|
})];
|
||||||
|
|
||||||
|
@@ -93,7 +93,7 @@
|
|||||||
<div v-if="resultsCount">
|
<div v-if="resultsCount">
|
||||||
{{ $t('word.results') }}: <b>{{ resultsCount.toLocaleString() }}</b>
|
{{ $t('word.results') }}: <b>{{ resultsCount.toLocaleString() }}</b>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="affectedCount">
|
<div v-if="affectedCount !== null">
|
||||||
{{ $t('message.affectedRows') }}: <b>{{ affectedCount }}</b>
|
{{ $t('message.affectedRows') }}: <b>{{ affectedCount }}</b>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group" :title="$t('word.schema')">
|
<div class="input-group" :title="$t('word.schema')">
|
||||||
@@ -170,7 +170,7 @@ export default {
|
|||||||
selectedSchema: null,
|
selectedSchema: null,
|
||||||
resultsCount: 0,
|
resultsCount: 0,
|
||||||
durationsCount: 0,
|
durationsCount: 0,
|
||||||
affectedCount: 0,
|
affectedCount: null,
|
||||||
editorHeight: 200,
|
editorHeight: 200,
|
||||||
isHistoryOpen: false
|
isHistoryOpen: false
|
||||||
};
|
};
|
||||||
@@ -255,9 +255,14 @@ export default {
|
|||||||
|
|
||||||
if (status === 'success') {
|
if (status === 'success') {
|
||||||
this.results = Array.isArray(response) ? response : [response];
|
this.results = Array.isArray(response) ? response : [response];
|
||||||
this.resultsCount += this.results.reduce((acc, curr) => acc + (curr.rows ? curr.rows.length : 0), 0);
|
this.resultsCount = this.results.reduce((acc, curr) => acc + (curr.rows ? curr.rows.length : 0), 0);
|
||||||
this.durationsCount += this.results.reduce((acc, curr) => acc + curr.duration, 0);
|
this.durationsCount = this.results.reduce((acc, curr) => acc + curr.duration, 0);
|
||||||
this.affectedCount += this.results.reduce((acc, curr) => acc + (curr.report ? curr.report.affectedRows : 0), 0);
|
this.affectedCount = this.results
|
||||||
|
.filter(result => result.report !== null)
|
||||||
|
.reduce((acc, curr) => {
|
||||||
|
if (acc === null) acc = 0;
|
||||||
|
return acc + (curr.report ? curr.report.affectedRows : 0);
|
||||||
|
}, null);
|
||||||
|
|
||||||
this.updateTabContent({
|
this.updateTabContent({
|
||||||
uid: this.connection.uid,
|
uid: this.connection.uid,
|
||||||
@@ -285,7 +290,7 @@ export default {
|
|||||||
this.results = [];
|
this.results = [];
|
||||||
this.resultsCount = 0;
|
this.resultsCount = 0;
|
||||||
this.durationsCount = 0;
|
this.durationsCount = 0;
|
||||||
this.affectedCount = 0;
|
this.affectedCount = null;
|
||||||
},
|
},
|
||||||
resize (e) {
|
resize (e) {
|
||||||
const el = this.$refs.queryEditor.$el;
|
const el = this.$refs.queryEditor.$el;
|
||||||
|
@@ -62,7 +62,7 @@
|
|||||||
v-if="resultsWithRows[resultsetIndex] && resultsWithRows[resultsetIndex].rows"
|
v-if="resultsWithRows[resultsetIndex] && resultsWithRows[resultsetIndex].rows"
|
||||||
ref="resultTable"
|
ref="resultTable"
|
||||||
:items="sortedResults"
|
:items="sortedResults"
|
||||||
:item-height="22"
|
:item-height="23"
|
||||||
class="tbody"
|
class="tbody"
|
||||||
:visible-height="resultsSize"
|
:visible-height="resultsSize"
|
||||||
:scroll-element="scrollElement"
|
:scroll-element="scrollElement"
|
||||||
@@ -70,13 +70,13 @@
|
|||||||
<template slot-scope="{ items }">
|
<template slot-scope="{ items }">
|
||||||
<WorkspaceTabQueryTableRow
|
<WorkspaceTabQueryTableRow
|
||||||
v-for="row in items"
|
v-for="row in items"
|
||||||
:key="row._id"
|
:key="row._antares_id"
|
||||||
:row="row"
|
:row="row"
|
||||||
:fields="fieldsObj"
|
:fields="fieldsObj"
|
||||||
:key-usage="keyUsage"
|
:key-usage="keyUsage"
|
||||||
:element-type="elementType"
|
:element-type="elementType"
|
||||||
:class="{'selected': selectedRows.includes(row._id)}"
|
:class="{'selected': selectedRows.includes(row._antares_id)}"
|
||||||
@select-row="selectRow($event, row._id)"
|
@select-row="selectRow($event, row._antares_id)"
|
||||||
@update-field="updateField($event, row)"
|
@update-field="updateField($event, row)"
|
||||||
@contextmenu="contextMenu"
|
@contextmenu="contextMenu"
|
||||||
/>
|
/>
|
||||||
@@ -196,7 +196,7 @@ export default {
|
|||||||
if (this.sortedResults.length) {
|
if (this.sortedResults.length) {
|
||||||
const fieldsObj = {};
|
const fieldsObj = {};
|
||||||
for (const key in this.sortedResults[0]) {
|
for (const key in this.sortedResults[0]) {
|
||||||
if (key === '_id') continue;
|
if (key === '_antares_id') continue;
|
||||||
|
|
||||||
const fieldObj = this.fields.find(field => {
|
const fieldObj = this.fields.find(field => {
|
||||||
let fieldNames = [
|
let fieldNames = [
|
||||||
@@ -310,7 +310,7 @@ export default {
|
|||||||
setLocalResults () {
|
setLocalResults () {
|
||||||
this.localResults = this.resultsWithRows[this.resultsetIndex] && this.resultsWithRows[this.resultsetIndex].rows
|
this.localResults = this.resultsWithRows[this.resultsetIndex] && this.resultsWithRows[this.resultsetIndex].rows
|
||||||
? this.resultsWithRows[this.resultsetIndex].rows.map(item => {
|
? this.resultsWithRows[this.resultsetIndex].rows.map(item => {
|
||||||
return { ...item, _id: uidGen() };
|
return { ...item, _antares_id: uidGen() };
|
||||||
})
|
})
|
||||||
: [];
|
: [];
|
||||||
},
|
},
|
||||||
@@ -330,7 +330,7 @@ export default {
|
|||||||
this.resizeResults();
|
this.resizeResults();
|
||||||
},
|
},
|
||||||
updateField (payload, row) {
|
updateField (payload, row) {
|
||||||
const orgRow = this.localResults.find(lr => lr._id === row._id);
|
const orgRow = this.localResults.find(lr => lr._antares_id === row._antares_id);
|
||||||
|
|
||||||
Object.keys(orgRow).forEach(key => { // remap the row
|
Object.keys(orgRow).forEach(key => { // remap the row
|
||||||
if (orgRow[key] instanceof Date && moment(orgRow[key]).isValid()) { // if datetime
|
if (orgRow[key] instanceof Date && moment(orgRow[key]).isValid()) { // if datetime
|
||||||
@@ -367,8 +367,8 @@ export default {
|
|||||||
},
|
},
|
||||||
deleteSelected () {
|
deleteSelected () {
|
||||||
this.closeContext();
|
this.closeContext();
|
||||||
const rows = this.localResults.filter(row => this.selectedRows.includes(row._id)).map(row => {
|
const rows = JSON.parse(JSON.stringify(this.localResults)).filter(row => this.selectedRows.includes(row._antares_id)).map(row => {
|
||||||
delete row._id;
|
delete row._antares_id;
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -381,7 +381,7 @@ export default {
|
|||||||
this.$emit('delete-selected', params);
|
this.$emit('delete-selected', params);
|
||||||
},
|
},
|
||||||
setNull () {
|
setNull () {
|
||||||
const row = this.localResults.find(row => this.selectedRows.includes(row._id));
|
const row = this.localResults.find(row => this.selectedRows.includes(row._antares_id));
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
primary: this.primaryField.name,
|
primary: this.primaryField.name,
|
||||||
@@ -396,7 +396,7 @@ export default {
|
|||||||
this.$emit('update-field', params);
|
this.$emit('update-field', params);
|
||||||
},
|
},
|
||||||
copyCell () {
|
copyCell () {
|
||||||
const row = this.localResults.find(row => this.selectedRows.includes(row._id));
|
const row = this.localResults.find(row => this.selectedRows.includes(row._antares_id));
|
||||||
const cellName = Object.keys(row).find(prop => [
|
const cellName = Object.keys(row).find(prop => [
|
||||||
this.selectedCell.field,
|
this.selectedCell.field,
|
||||||
`${this.fields[0].table}.${this.selectedCell.field}`,
|
`${this.fields[0].table}.${this.selectedCell.field}`,
|
||||||
@@ -406,9 +406,9 @@ export default {
|
|||||||
navigator.clipboard.writeText(valueToCopy);
|
navigator.clipboard.writeText(valueToCopy);
|
||||||
},
|
},
|
||||||
copyRow () {
|
copyRow () {
|
||||||
const row = this.localResults.find(row => this.selectedRows.includes(row._id));
|
const row = this.localResults.find(row => this.selectedRows.includes(row._antares_id));
|
||||||
const rowToCopy = JSON.parse(JSON.stringify(row));
|
const rowToCopy = JSON.parse(JSON.stringify(row));
|
||||||
delete rowToCopy._id;
|
delete rowToCopy._antares_id;
|
||||||
navigator.clipboard.writeText(JSON.stringify(rowToCopy));
|
navigator.clipboard.writeText(JSON.stringify(rowToCopy));
|
||||||
},
|
},
|
||||||
applyUpdate (params) {
|
applyUpdate (params) {
|
||||||
@@ -435,15 +435,15 @@ export default {
|
|||||||
this.selectedRows.push(row);
|
this.selectedRows.push(row);
|
||||||
else {
|
else {
|
||||||
const lastID = this.selectedRows.slice(-1)[0];
|
const lastID = this.selectedRows.slice(-1)[0];
|
||||||
const lastIndex = this.sortedResults.findIndex(el => el._id === lastID);
|
const lastIndex = this.sortedResults.findIndex(el => el._antares_id === lastID);
|
||||||
const clickedIndex = this.sortedResults.findIndex(el => el._id === row);
|
const clickedIndex = this.sortedResults.findIndex(el => el._antares_id === row);
|
||||||
if (lastIndex > clickedIndex) {
|
if (lastIndex > clickedIndex) {
|
||||||
for (let i = clickedIndex; i < lastIndex; i++)
|
for (let i = clickedIndex; i < lastIndex; i++)
|
||||||
this.selectedRows.push(this.sortedResults[i]._id);
|
this.selectedRows.push(this.sortedResults[i]._antares_id);
|
||||||
}
|
}
|
||||||
else if (lastIndex < clickedIndex) {
|
else if (lastIndex < clickedIndex) {
|
||||||
for (let i = clickedIndex; i > lastIndex; i--)
|
for (let i = clickedIndex; i > lastIndex; i--)
|
||||||
this.selectedRows.push(this.sortedResults[i]._id);
|
this.selectedRows.push(this.sortedResults[i]._antares_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -452,7 +452,7 @@ export default {
|
|||||||
},
|
},
|
||||||
selectAllRows () {
|
selectAllRows () {
|
||||||
this.selectedRows = this.localResults.reduce((acc, curr) => {
|
this.selectedRows = this.localResults.reduce((acc, curr) => {
|
||||||
acc.push(curr._id);
|
acc.push(curr._antares_id);
|
||||||
return acc;
|
return acc;
|
||||||
}, []);
|
}, []);
|
||||||
},
|
},
|
||||||
@@ -501,7 +501,7 @@ export default {
|
|||||||
if (!this.sortedResults) return;
|
if (!this.sortedResults) return;
|
||||||
|
|
||||||
const rows = JSON.parse(JSON.stringify(this.sortedResults)).map(row => {
|
const rows = JSON.parse(JSON.stringify(this.sortedResults)).map(row => {
|
||||||
delete row._id;
|
delete row._antares_id;
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,14 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tr" @click="selectRow($event, row._id)">
|
<div class="tr" @click="selectRow($event, row._antares_id)">
|
||||||
<div
|
<div
|
||||||
v-for="(col, cKey) in row"
|
v-for="(col, cKey) in row"
|
||||||
v-show="cKey !== '_id'"
|
v-show="cKey !== '_antares_id'"
|
||||||
:key="cKey"
|
:key="cKey"
|
||||||
class="td p-0"
|
class="td p-0"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@contextmenu.prevent="openContext($event, { id: row._id, field: cKey })"
|
@contextmenu.prevent="openContext($event, { id: row._antares_id, field: cKey })"
|
||||||
>
|
>
|
||||||
<template v-if="cKey !== '_id'">
|
<template v-if="cKey !== '_antares_id'">
|
||||||
<span
|
<span
|
||||||
v-if="!isInlineEditor[cKey] && fields[cKey]"
|
v-if="!isInlineEditor[cKey] && fields[cKey]"
|
||||||
class="cell-content"
|
class="cell-content"
|
||||||
|
@@ -120,7 +120,12 @@
|
|||||||
{{ $t('word.results') }}: <b>{{ results[0].rows.length | localeString }}</b>
|
{{ $t('word.results') }}: <b>{{ results[0].rows.length | localeString }}</b>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="hasApproximately || (page > 1 && approximateCount)">
|
<div v-if="hasApproximately || (page > 1 && approximateCount)">
|
||||||
{{ $t('word.total') }}: <b :title="$t('word.approximately')">≈ {{ approximateCount | localeString }}</b>
|
{{ $t('word.total') }}: <b
|
||||||
|
:title="!customizations.tableRealCount ? $t('word.approximately') : ''"
|
||||||
|
>
|
||||||
|
<span v-if="!customizations.tableRealCount">≈</span>
|
||||||
|
{{ approximateCount | localeString }}
|
||||||
|
</b>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex" :title="$t('word.schema')">
|
<div class="d-flex" :title="$t('word.schema')">
|
||||||
<i class="mdi mdi-18px mdi-database mr-1" /><b>{{ schema }}</b>
|
<i class="mdi mdi-18px mdi-database mr-1" /><b>{{ schema }}</b>
|
||||||
@@ -231,6 +236,9 @@ export default {
|
|||||||
workspace () {
|
workspace () {
|
||||||
return this.getWorkspace(this.connection.uid);
|
return this.getWorkspace(this.connection.uid);
|
||||||
},
|
},
|
||||||
|
customizations () {
|
||||||
|
return this.workspace.customizations;
|
||||||
|
},
|
||||||
isTable () {
|
isTable () {
|
||||||
return !!this.workspace.breadcrumbs.table;
|
return !!this.workspace.breadcrumbs.table;
|
||||||
},
|
},
|
||||||
|
@@ -121,7 +121,10 @@ module.exports = {
|
|||||||
history: 'History',
|
history: 'History',
|
||||||
select: 'Select',
|
select: 'Select',
|
||||||
passphrase: 'Passphrase',
|
passphrase: 'Passphrase',
|
||||||
filter: 'Filter'
|
filter: 'Filter',
|
||||||
|
disabled: 'Disabled',
|
||||||
|
enable: 'Enable',
|
||||||
|
disable: 'Disable'
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
appWelcome: 'Welcome to Antares SQL Client!',
|
appWelcome: 'Welcome to Antares SQL Client!',
|
||||||
@@ -246,7 +249,9 @@ module.exports = {
|
|||||||
thereIsNoQueriesYet: 'There is no queries yet',
|
thereIsNoQueriesYet: 'There is no queries yet',
|
||||||
searchForQueries: 'Search for queries',
|
searchForQueries: 'Search for queries',
|
||||||
killProcess: 'Kill process',
|
killProcess: 'Kill process',
|
||||||
closeTab: 'Close tab'
|
closeTab: 'Close tab',
|
||||||
|
goToDownloadPage: 'Go to download page',
|
||||||
|
readOnlyMode: 'Read-only mode'
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Address',
|
address: 'Address',
|
||||||
|
@@ -121,7 +121,10 @@ module.exports = {
|
|||||||
history: 'Cronologia',
|
history: 'Cronologia',
|
||||||
select: 'Seleziona',
|
select: 'Seleziona',
|
||||||
passphrase: 'Passphrase',
|
passphrase: 'Passphrase',
|
||||||
filter: 'Filtra'
|
filter: 'Filtra',
|
||||||
|
disabled: 'Disabilitato',
|
||||||
|
enable: 'Abilita',
|
||||||
|
disable: 'Disabilita'
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
appWelcome: 'Benvenuto in Antares SQL Client!',
|
appWelcome: 'Benvenuto in Antares SQL Client!',
|
||||||
@@ -233,7 +236,22 @@ module.exports = {
|
|||||||
duplicateTable: 'Duplica tabella',
|
duplicateTable: 'Duplica tabella',
|
||||||
noOpenTabs: 'Non ci sono tab aperte, naviga nella barra sinistra o:',
|
noOpenTabs: 'Non ci sono tab aperte, naviga nella barra sinistra o:',
|
||||||
noSchema: 'Nessuno schema',
|
noSchema: 'Nessuno schema',
|
||||||
restorePreviourSession: 'Ripristina sessione precedente'
|
restorePreviourSession: 'Ripristina sessione precedente',
|
||||||
|
runQuery: 'Esegui query',
|
||||||
|
thereAreNoTableFields: 'Non ci sono campi della tabella',
|
||||||
|
newTable: 'Nuova tabella',
|
||||||
|
newView: 'Nuova vista',
|
||||||
|
newTrigger: 'Nuovo trigger',
|
||||||
|
newRoutine: 'Nuova routine',
|
||||||
|
newFunction: 'Nuova funzione',
|
||||||
|
newScheduler: 'Nuovo scheduler',
|
||||||
|
newTriggerFunction: 'Nuova funzione di trigger',
|
||||||
|
thereIsNoQueriesYet: 'Non ci sono ancora query',
|
||||||
|
searchForQueries: 'Cerca query',
|
||||||
|
killProcess: 'Uccidi processo',
|
||||||
|
closeTab: 'Chiudi tab',
|
||||||
|
goToDownloadPage: 'Vai alla pagina di download',
|
||||||
|
readOnlyMode: 'Modalità sola lettura'
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Indirizzo',
|
address: 'Indirizzo',
|
||||||
|
@@ -1,413 +1,413 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
word: {
|
word: {
|
||||||
edit: 'Chỉnh sửa',
|
edit: 'Chỉnh sửa',
|
||||||
save: 'Lưu',
|
save: 'Lưu',
|
||||||
close: 'Đóng',
|
close: 'Đóng',
|
||||||
delete: 'Xoá',
|
delete: 'Xoá',
|
||||||
confirm: 'Xác nhận',
|
confirm: 'Xác nhận',
|
||||||
cancel: 'Huỷ',
|
cancel: 'Huỷ',
|
||||||
send: 'Gửi',
|
send: 'Gửi',
|
||||||
connectionName: 'Tên kết nối',
|
connectionName: 'Tên kết nối',
|
||||||
client: 'Client',
|
client: 'Client',
|
||||||
hostName: 'Tên máy chủ',
|
hostName: 'Tên máy chủ',
|
||||||
port: 'Cổng',
|
port: 'Cổng',
|
||||||
user: 'Người dùng',
|
user: 'Người dùng',
|
||||||
password: 'Mật khẩu',
|
password: 'Mật khẩu',
|
||||||
credentials: 'Thông tin xác thực',
|
credentials: 'Thông tin xác thực',
|
||||||
connect: 'Kết nối',
|
connect: 'Kết nối',
|
||||||
connected: 'Đã kết nối',
|
connected: 'Đã kết nối',
|
||||||
disconnect: 'Ngắt kết nối',
|
disconnect: 'Ngắt kết nối',
|
||||||
disconnected: 'Đã ngắt kết nối',
|
disconnected: 'Đã ngắt kết nối',
|
||||||
refresh: 'Làm mới',
|
refresh: 'Làm mới',
|
||||||
settings: 'Cài đặt',
|
settings: 'Cài đặt',
|
||||||
general: 'Chung',
|
general: 'Chung',
|
||||||
themes: 'Giao diện',
|
themes: 'Giao diện',
|
||||||
update: 'Cập nhật',
|
update: 'Cập nhật',
|
||||||
about: 'Giới thiệu',
|
about: 'Giới thiệu',
|
||||||
language: 'Ngôn ngữ',
|
language: 'Ngôn ngữ',
|
||||||
version: 'Phiên bản',
|
version: 'Phiên bản',
|
||||||
donate: 'Ủng hộ',
|
donate: 'Ủng hộ',
|
||||||
run: 'Chạy',
|
run: 'Chạy',
|
||||||
schema: 'Schema',
|
schema: 'Schema',
|
||||||
results: 'Kết quả',
|
results: 'Kết quả',
|
||||||
size: 'Kích thước',
|
size: 'Kích thước',
|
||||||
seconds: 'Giây',
|
seconds: 'Giây',
|
||||||
type: 'Kiểu',
|
type: 'Kiểu',
|
||||||
mimeType: 'Mime-Type',
|
mimeType: 'Mime-Type',
|
||||||
download: 'Tải xuống',
|
download: 'Tải xuống',
|
||||||
add: 'Thêm',
|
add: 'Thêm',
|
||||||
data: 'Dữ liệu',
|
data: 'Dữ liệu',
|
||||||
properties: 'Thuộc tính',
|
properties: 'Thuộc tính',
|
||||||
insert: 'Nhập',
|
insert: 'Nhập',
|
||||||
connecting: 'Đang kết nối',
|
connecting: 'Đang kết nối',
|
||||||
name: 'Tên',
|
name: 'Tên',
|
||||||
collation: 'Đối chiếu',
|
collation: 'Đối chiếu',
|
||||||
clear: 'Xoá',
|
clear: 'Xoá',
|
||||||
options: 'Tuỳ chọn',
|
options: 'Tuỳ chọn',
|
||||||
autoRefresh: 'Tự động làm mới',
|
autoRefresh: 'Tự động làm mới',
|
||||||
indexes: 'Index',
|
indexes: 'Index',
|
||||||
foreignKeys: 'Khoá ngoại',
|
foreignKeys: 'Khoá ngoại',
|
||||||
length: 'Độ dài',
|
length: 'Độ dài',
|
||||||
unsigned: 'Unsigned',
|
unsigned: 'Unsigned',
|
||||||
default: 'Mặc định',
|
default: 'Mặc định',
|
||||||
comment: 'Nhận xét',
|
comment: 'Nhận xét',
|
||||||
key: 'Khoá | Khoá',
|
key: 'Khoá | Khoá',
|
||||||
order: 'Sắp xếp',
|
order: 'Sắp xếp',
|
||||||
expression: 'Biểu hiện',
|
expression: 'Biểu hiện',
|
||||||
autoIncrement: 'Tự động tăng',
|
autoIncrement: 'Tự động tăng',
|
||||||
engine: 'Engine',
|
engine: 'Engine',
|
||||||
field: 'Trường | Trường',
|
field: 'Trường | Trường',
|
||||||
approximately: 'Khoảng',
|
approximately: 'Khoảng',
|
||||||
total: 'Toàn bộ',
|
total: 'Toàn bộ',
|
||||||
table: 'Bảng',
|
table: 'Bảng',
|
||||||
discard: 'Bỏ',
|
discard: 'Bỏ',
|
||||||
stay: 'Ở lại',
|
stay: 'Ở lại',
|
||||||
author: 'Tác giả',
|
author: 'Tác giả',
|
||||||
light: 'Sáng',
|
light: 'Sáng',
|
||||||
dark: 'Tối',
|
dark: 'Tối',
|
||||||
autoCompletion: 'Tự động hoàn thành',
|
autoCompletion: 'Tự động hoàn thành',
|
||||||
application: 'Ứng dụng',
|
application: 'Ứng dụng',
|
||||||
editor: 'Người chỉnh sửa',
|
editor: 'Người chỉnh sửa',
|
||||||
view: 'Xem',
|
view: 'Xem',
|
||||||
definer: 'Định nghĩa',
|
definer: 'Định nghĩa',
|
||||||
algorithm: 'Thuật toán',
|
algorithm: 'Thuật toán',
|
||||||
trigger: 'Kích hoạt | Kích hoạt',
|
trigger: 'Kích hoạt | Kích hoạt',
|
||||||
storedRoutine: 'Quy trình đã lưu | Quy trình đã lưu',
|
storedRoutine: 'Quy trình đã lưu | Quy trình đã lưu',
|
||||||
scheduler: 'Lập lịch trình | Lập lịch trình',
|
scheduler: 'Lập lịch trình | Lập lịch trình',
|
||||||
event: 'Sự kiện',
|
event: 'Sự kiện',
|
||||||
parameters: 'Tham số',
|
parameters: 'Tham số',
|
||||||
function: 'Chức năng | Chức năng',
|
function: 'Chức năng | Chức năng',
|
||||||
deterministic: 'Xác định',
|
deterministic: 'Xác định',
|
||||||
context: 'Context',
|
context: 'Context',
|
||||||
export: 'Xuất',
|
export: 'Xuất',
|
||||||
returns: 'Returns',
|
returns: 'Returns',
|
||||||
timing: 'Thời gian',
|
timing: 'Thời gian',
|
||||||
state: 'Trạng thái',
|
state: 'Trạng thái',
|
||||||
execution: 'Thực thi',
|
execution: 'Thực thi',
|
||||||
starts: 'Bắt đầu',
|
starts: 'Bắt đầu',
|
||||||
ends: 'Kết thúc',
|
ends: 'Kết thúc',
|
||||||
ssl: 'SSL',
|
ssl: 'SSL',
|
||||||
privateKey: 'Mã khoá riêng tư',
|
privateKey: 'Mã khoá riêng tư',
|
||||||
certificate: 'Chứng chỉ',
|
certificate: 'Chứng chỉ',
|
||||||
caCertificate: 'Chứng chỉ CA',
|
caCertificate: 'Chứng chỉ CA',
|
||||||
ciphers: 'Ciphers',
|
ciphers: 'Ciphers',
|
||||||
upload: 'Tải lên',
|
upload: 'Tải lên',
|
||||||
browse: 'Duyệt',
|
browse: 'Duyệt',
|
||||||
faker: 'Faker',
|
faker: 'Faker',
|
||||||
content: 'Nội dung',
|
content: 'Nội dung',
|
||||||
cut: 'Cắt',
|
cut: 'Cắt',
|
||||||
copy: 'Sao chép',
|
copy: 'Sao chép',
|
||||||
paste: 'Dán',
|
paste: 'Dán',
|
||||||
tools: 'Công cụ',
|
tools: 'Công cụ',
|
||||||
variables: 'Biến',
|
variables: 'Biến',
|
||||||
processes: 'Quá trình',
|
processes: 'Quá trình',
|
||||||
database: 'Cơ sở dữ liệu',
|
database: 'Cơ sở dữ liệu',
|
||||||
scratchpad: 'Scratchpad',
|
scratchpad: 'Scratchpad',
|
||||||
array: 'Mảng',
|
array: 'Mảng',
|
||||||
changelog: 'Nhật ký thay đổi',
|
changelog: 'Nhật ký thay đổi',
|
||||||
format: 'Định dạng',
|
format: 'Định dạng',
|
||||||
sshTunnel: 'SSH tunnel',
|
sshTunnel: 'SSH tunnel',
|
||||||
structure: 'Structure',
|
structure: 'Structure',
|
||||||
small: 'Nhỏ',
|
small: 'Nhỏ',
|
||||||
medium: 'Vừa',
|
medium: 'Vừa',
|
||||||
large: 'Lớn',
|
large: 'Lớn',
|
||||||
row: 'Hàng | Hàng',
|
row: 'Hàng | Hàng',
|
||||||
cell: 'Ô | Ô',
|
cell: 'Ô | Ô',
|
||||||
triggerFunction: 'Trigger function | Trigger functions',
|
triggerFunction: 'Trigger function | Trigger functions',
|
||||||
all: 'Tất cả',
|
all: 'Tất cả',
|
||||||
duplicate: 'Bản sao',
|
duplicate: 'Bản sao',
|
||||||
routine: 'Routine',
|
routine: 'Routine',
|
||||||
new: 'Mới',
|
new: 'Mới',
|
||||||
history: 'Lịch sử',
|
history: 'Lịch sử',
|
||||||
select: 'Chọn',
|
select: 'Chọn',
|
||||||
passphrase: 'Cụm mật khẩu'
|
passphrase: 'Cụm mật khẩu'
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
appWelcome: 'Chào bạn đến với Antares SQL Client!',
|
appWelcome: 'Chào bạn đến với Antares SQL Client!',
|
||||||
appFirstStep: 'Bước đầu tiên: tạo một kết nối tới cơ sở dữ liệu.',
|
appFirstStep: 'Bước đầu tiên: tạo một kết nối tới cơ sở dữ liệu.',
|
||||||
addConnection: 'Thêm kết nối',
|
addConnection: 'Thêm kết nối',
|
||||||
createConnection: 'Tạo kết nối',
|
createConnection: 'Tạo kết nối',
|
||||||
createNewConnection: 'Tạo kết nối mới',
|
createNewConnection: 'Tạo kết nối mới',
|
||||||
askCredentials: 'Yêu cầu thông tin đăng nhập',
|
askCredentials: 'Yêu cầu thông tin đăng nhập',
|
||||||
testConnection: 'Chạy thử kết nối',
|
testConnection: 'Chạy thử kết nối',
|
||||||
editConnection: 'Sửa kết nối',
|
editConnection: 'Sửa kết nối',
|
||||||
deleteConnection: 'Xoá kết nối',
|
deleteConnection: 'Xoá kết nối',
|
||||||
deleteCorfirm: 'Bạn có xác nhận việc hủy bỏ',
|
deleteCorfirm: 'Bạn có xác nhận việc hủy bỏ',
|
||||||
connectionSuccessfullyMade: 'Kết nối được thực hiện thành công!',
|
connectionSuccessfullyMade: 'Kết nối được thực hiện thành công!',
|
||||||
madeWithJS: 'Được tạo bằng 💛 và JavaScript!',
|
madeWithJS: 'Được tạo bằng 💛 và JavaScript!',
|
||||||
checkForUpdates: 'Kiểm tra cập nhật',
|
checkForUpdates: 'Kiểm tra cập nhật',
|
||||||
noUpdatesAvailable: 'Không có bản cập nhật nào',
|
noUpdatesAvailable: 'Không có bản cập nhật nào',
|
||||||
checkingForUpdate: 'Đang kiểm tra cập nhật',
|
checkingForUpdate: 'Đang kiểm tra cập nhật',
|
||||||
checkFailure: 'Kiểm tra thất bại, vui lòng thử lại sau',
|
checkFailure: 'Kiểm tra thất bại, vui lòng thử lại sau',
|
||||||
updateAvailable: 'Cập nhật có sẵn',
|
updateAvailable: 'Cập nhật có sẵn',
|
||||||
downloadingUpdate: 'Đang tải bản cập nhật',
|
downloadingUpdate: 'Đang tải bản cập nhật',
|
||||||
updateDownloaded: 'Đã tải bản cập nhạt',
|
updateDownloaded: 'Đã tải bản cập nhạt',
|
||||||
restartToInstall: 'Khởi động lại Antares để cài đặt',
|
restartToInstall: 'Khởi động lại Antares để cài đặt',
|
||||||
unableEditFieldWithoutPrimary: 'Không thể chỉnh sửa trường mà không có khóa chính trong kết quả',
|
unableEditFieldWithoutPrimary: 'Không thể chỉnh sửa trường mà không có khóa chính trong kết quả',
|
||||||
editCell: 'Sửa ô',
|
editCell: 'Sửa ô',
|
||||||
deleteRows: 'Xoá hàng | Xoá {count} hàng',
|
deleteRows: 'Xoá hàng | Xoá {count} hàng',
|
||||||
confirmToDeleteRows: 'Bạn có xác nhận xóa một hàng không? | Bạn có xác nhận xóa {count} hàng không?',
|
confirmToDeleteRows: 'Bạn có xác nhận xóa một hàng không? | Bạn có xác nhận xóa {count} hàng không?',
|
||||||
notificationsTimeout: 'Thông báo hết giờ',
|
notificationsTimeout: 'Thông báo hết giờ',
|
||||||
uploadFile: 'Tải lên tệp',
|
uploadFile: 'Tải lên tệp',
|
||||||
addNewRow: 'Thêm hàng mới',
|
addNewRow: 'Thêm hàng mới',
|
||||||
numberOfInserts: 'Số lần nhập',
|
numberOfInserts: 'Số lần nhập',
|
||||||
openNewTab: 'Mở trong tab mới',
|
openNewTab: 'Mở trong tab mới',
|
||||||
affectedRows: 'Các hàng bị ảnh hưởng',
|
affectedRows: 'Các hàng bị ảnh hưởng',
|
||||||
createNewDatabase: 'Tạo Cơ sở dữ liệu mới',
|
createNewDatabase: 'Tạo Cơ sở dữ liệu mới',
|
||||||
databaseName: 'Tên cơ sở dữ liệu',
|
databaseName: 'Tên cơ sở dữ liệu',
|
||||||
serverDefault: 'Máy chủ mặc định',
|
serverDefault: 'Máy chủ mặc định',
|
||||||
deleteDatabase: 'Xoá cơ sở dữ liệu',
|
deleteDatabase: 'Xoá cơ sở dữ liệu',
|
||||||
editDatabase: 'Sửa cơ sở dữ liệu',
|
editDatabase: 'Sửa cơ sở dữ liệu',
|
||||||
clearChanges: 'Xóa các thay đổi',
|
clearChanges: 'Xóa các thay đổi',
|
||||||
addNewField: 'Thêm trường mới',
|
addNewField: 'Thêm trường mới',
|
||||||
manageIndexes: 'Quản lý index',
|
manageIndexes: 'Quản lý index',
|
||||||
manageForeignKeys: 'Quản lý khoá ngoại',
|
manageForeignKeys: 'Quản lý khoá ngoại',
|
||||||
allowNull: 'Cho phép NULL',
|
allowNull: 'Cho phép NULL',
|
||||||
zeroFill: 'Không điền',
|
zeroFill: 'Không điền',
|
||||||
customValue: 'Tuỳ chỉnh giá trị',
|
customValue: 'Tuỳ chỉnh giá trị',
|
||||||
onUpdate: 'Đang cập nhật',
|
onUpdate: 'Đang cập nhật',
|
||||||
deleteField: 'Xoá trường',
|
deleteField: 'Xoá trường',
|
||||||
createNewIndex: 'Tạo index mới',
|
createNewIndex: 'Tạo index mới',
|
||||||
addToIndex: 'Thêm vào index',
|
addToIndex: 'Thêm vào index',
|
||||||
createNewTable: 'Tạo bảng mới',
|
createNewTable: 'Tạo bảng mới',
|
||||||
emptyTable: 'Bảng trống',
|
emptyTable: 'Bảng trống',
|
||||||
deleteTable: 'Xoá bảng',
|
deleteTable: 'Xoá bảng',
|
||||||
emptyCorfirm: 'Bạn có xác nhận để làm trống không',
|
emptyCorfirm: 'Bạn có xác nhận để làm trống không',
|
||||||
unsavedChanges: 'Chưa lưu lại thay đổi',
|
unsavedChanges: 'Chưa lưu lại thay đổi',
|
||||||
discardUnsavedChanges: 'Bạn có một số thay đổi chưa được lưu. Đóng tab này, những thay đổi này sẽ bị huỷ bỏ.',
|
discardUnsavedChanges: 'Bạn có một số thay đổi chưa được lưu. Đóng tab này, những thay đổi này sẽ bị huỷ bỏ.',
|
||||||
thereAreNoIndexes: 'Không có index',
|
thereAreNoIndexes: 'Không có index',
|
||||||
thereAreNoForeign: 'Không có khoá ngoại',
|
thereAreNoForeign: 'Không có khoá ngoại',
|
||||||
createNewForeign: 'Tạo khoá ngoại mới',
|
createNewForeign: 'Tạo khoá ngoại mới',
|
||||||
referenceTable: 'Tham khảo bảng',
|
referenceTable: 'Tham khảo bảng',
|
||||||
referenceField: 'Tham khảo trường',
|
referenceField: 'Tham khảo trường',
|
||||||
foreignFields: 'Trường ngoại',
|
foreignFields: 'Trường ngoại',
|
||||||
invalidDefault: 'Mặc định không hợp lệ',
|
invalidDefault: 'Mặc định không hợp lệ',
|
||||||
onDelete: 'Đang xoá',
|
onDelete: 'Đang xoá',
|
||||||
applicationTheme: 'Chủ đề ứng dụng',
|
applicationTheme: 'Chủ đề ứng dụng',
|
||||||
editorTheme: 'Trình chỉnh sửa chủ đề',
|
editorTheme: 'Trình chỉnh sửa chủ đề',
|
||||||
wrapLongLines: 'Wrap long lines',
|
wrapLongLines: 'Wrap long lines',
|
||||||
selectStatement: 'Chọn câu lệnh',
|
selectStatement: 'Chọn câu lệnh',
|
||||||
triggerStatement: 'Kích hoạt câu lệnh',
|
triggerStatement: 'Kích hoạt câu lệnh',
|
||||||
sqlSecurity: 'Bảo mật SQL',
|
sqlSecurity: 'Bảo mật SQL',
|
||||||
updateOption: 'Cập nhật tuỳ chọn',
|
updateOption: 'Cập nhật tuỳ chọn',
|
||||||
deleteView: 'Xóa chế độ xem',
|
deleteView: 'Xóa chế độ xem',
|
||||||
createNewView: 'Tạo chế độ xem mới',
|
createNewView: 'Tạo chế độ xem mới',
|
||||||
deleteTrigger: 'Xóa trình kích hoạt',
|
deleteTrigger: 'Xóa trình kích hoạt',
|
||||||
createNewTrigger: 'Tạo trình kích hoạt mới',
|
createNewTrigger: 'Tạo trình kích hoạt mới',
|
||||||
currentUser: 'Người dùng hiện tại',
|
currentUser: 'Người dùng hiện tại',
|
||||||
routineBody: 'Body quy trình',
|
routineBody: 'Body quy trình',
|
||||||
dataAccess: 'Truy cập dữ liệu',
|
dataAccess: 'Truy cập dữ liệu',
|
||||||
thereAreNoParameters: 'Không có tham số',
|
thereAreNoParameters: 'Không có tham số',
|
||||||
createNewParameter: 'Tạo tham số mới',
|
createNewParameter: 'Tạo tham số mới',
|
||||||
createNewRoutine: 'Tạo quy trình lưu trữ mới',
|
createNewRoutine: 'Tạo quy trình lưu trữ mới',
|
||||||
deleteRoutine: 'Xoá quy trình lưu trữ',
|
deleteRoutine: 'Xoá quy trình lưu trữ',
|
||||||
functionBody: 'Body chức năng',
|
functionBody: 'Body chức năng',
|
||||||
createNewFunction: 'Tạo chức năng mới',
|
createNewFunction: 'Tạo chức năng mới',
|
||||||
deleteFunction: 'Xoá chức năng',
|
deleteFunction: 'Xoá chức năng',
|
||||||
schedulerBody: 'Body trình lập lịch',
|
schedulerBody: 'Body trình lập lịch',
|
||||||
createNewScheduler: 'Tạo lịch trình mới',
|
createNewScheduler: 'Tạo lịch trình mới',
|
||||||
deleteScheduler: 'Xóa trình lên lịch',
|
deleteScheduler: 'Xóa trình lên lịch',
|
||||||
preserveOnCompletion: 'Bảo tồn khi hoàn thành',
|
preserveOnCompletion: 'Bảo tồn khi hoàn thành',
|
||||||
enableSsl: 'Bật SSL',
|
enableSsl: 'Bật SSL',
|
||||||
manualValue: 'Giá trị thủ công',
|
manualValue: 'Giá trị thủ công',
|
||||||
tableFiller: 'Bộ lọc bảng',
|
tableFiller: 'Bộ lọc bảng',
|
||||||
fakeDataLanguage: 'Ngôn ngữ dữ liệu giả mạo',
|
fakeDataLanguage: 'Ngôn ngữ dữ liệu giả mạo',
|
||||||
searchForElements: 'Tìm kiếm yếu tố',
|
searchForElements: 'Tìm kiếm yếu tố',
|
||||||
selectAll: 'Chọn tất cả',
|
selectAll: 'Chọn tất cả',
|
||||||
queryDuration: 'Thời lượng truy vấn',
|
queryDuration: 'Thời lượng truy vấn',
|
||||||
includeBetaUpdates: 'Bao gồm các bản cập nhật beta',
|
includeBetaUpdates: 'Bao gồm các bản cập nhật beta',
|
||||||
setNull: 'Đặt NULL',
|
setNull: 'Đặt NULL',
|
||||||
processesList: 'Danh sách quy trình',
|
processesList: 'Danh sách quy trình',
|
||||||
processInfo: 'Thông tin quá trình',
|
processInfo: 'Thông tin quá trình',
|
||||||
manageUsers: 'Quản lý người dùng',
|
manageUsers: 'Quản lý người dùng',
|
||||||
createNewSchema: 'Tạo schema mới',
|
createNewSchema: 'Tạo schema mới',
|
||||||
schemaName: 'Tên schema',
|
schemaName: 'Tên schema',
|
||||||
editSchema: 'Sửa schema',
|
editSchema: 'Sửa schema',
|
||||||
deleteSchema: 'Xoá schema',
|
deleteSchema: 'Xoá schema',
|
||||||
markdownSupported: 'Hỗ trợ Markdown',
|
markdownSupported: 'Hỗ trợ Markdown',
|
||||||
plantATree: 'Trồng cây',
|
plantATree: 'Trồng cây',
|
||||||
dataTabPageSize: 'Kích thước trang tab DATA',
|
dataTabPageSize: 'Kích thước trang tab DATA',
|
||||||
enableSsh: 'Bật SSH',
|
enableSsh: 'Bật SSH',
|
||||||
pageNumber: 'Số trang',
|
pageNumber: 'Số trang',
|
||||||
duplicateTable: 'Sao chép bản',
|
duplicateTable: 'Sao chép bản',
|
||||||
noOpenTabs: 'Không có tab nào đang mở, điều hướng trên thanh bên trái hoặc:',
|
noOpenTabs: 'Không có tab nào đang mở, điều hướng trên thanh bên trái hoặc:',
|
||||||
noSchema: 'Không có schema',
|
noSchema: 'Không có schema',
|
||||||
restorePreviourSession: 'Khôi phục phiên trước',
|
restorePreviourSession: 'Khôi phục phiên trước',
|
||||||
runQuery: 'Chạy truy vấn',
|
runQuery: 'Chạy truy vấn',
|
||||||
thereAreNoTableFields: 'Không có trường bảng',
|
thereAreNoTableFields: 'Không có trường bảng',
|
||||||
newTable: 'Bảng mới',
|
newTable: 'Bảng mới',
|
||||||
newView: 'Chế độ xem mới',
|
newView: 'Chế độ xem mới',
|
||||||
newTrigger: 'Trình kích hoạt mới',
|
newTrigger: 'Trình kích hoạt mới',
|
||||||
newRoutine: 'Quy trình mới',
|
newRoutine: 'Quy trình mới',
|
||||||
newFunction: 'Chức năng mới',
|
newFunction: 'Chức năng mới',
|
||||||
newScheduler: 'Bộ lập lịch mới',
|
newScheduler: 'Bộ lập lịch mới',
|
||||||
newTriggerFunction: 'Chức năng kích hoạt mới',
|
newTriggerFunction: 'Chức năng kích hoạt mới',
|
||||||
thereIsNoQueriesYet: 'Không có truy vấn nào',
|
thereIsNoQueriesYet: 'Không có truy vấn nào',
|
||||||
searchForQueries: 'Tìm kiếm truy vấn',
|
searchForQueries: 'Tìm kiếm truy vấn',
|
||||||
killProcess: 'Huỷ quá trình'
|
killProcess: 'Huỷ quá trình'
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Địa chỉ',
|
address: 'Địa chỉ',
|
||||||
commerce: 'Thương mại',
|
commerce: 'Thương mại',
|
||||||
company: 'Công ty',
|
company: 'Công ty',
|
||||||
database: 'Cơ sở dữ liệu',
|
database: 'Cơ sở dữ liệu',
|
||||||
date: 'Ngày',
|
date: 'Ngày',
|
||||||
finance: 'Tài chánh',
|
finance: 'Tài chánh',
|
||||||
git: 'Git',
|
git: 'Git',
|
||||||
hacker: 'Tin tặc',
|
hacker: 'Tin tặc',
|
||||||
internet: 'Mạng Internet',
|
internet: 'Mạng Internet',
|
||||||
lorem: 'Lorem',
|
lorem: 'Lorem',
|
||||||
name: 'Tên',
|
name: 'Tên',
|
||||||
music: 'Âm nhạc',
|
music: 'Âm nhạc',
|
||||||
phone: 'Số điện thoại',
|
phone: 'Số điện thoại',
|
||||||
random: 'Ngẫu nhiên',
|
random: 'Ngẫu nhiên',
|
||||||
system: 'Hệ thống',
|
system: 'Hệ thống',
|
||||||
time: 'Thời gian',
|
time: 'Thời gian',
|
||||||
vehicle: 'Phương tiện giao thông',
|
vehicle: 'Phương tiện giao thông',
|
||||||
zipCode: 'Mã Bưu Chính',
|
zipCode: 'Mã Bưu Chính',
|
||||||
zipCodeByState: 'Mã Bưu Chính theo tiểu bang',
|
zipCodeByState: 'Mã Bưu Chính theo tiểu bang',
|
||||||
city: 'Thành phố',
|
city: 'Thành phố',
|
||||||
cityPrefix: 'Tiền tố thành phố',
|
cityPrefix: 'Tiền tố thành phố',
|
||||||
citySuffix: 'Hậu tố thành phố',
|
citySuffix: 'Hậu tố thành phố',
|
||||||
streetName: 'Tên đường',
|
streetName: 'Tên đường',
|
||||||
streetAddress: 'Địa chỉ đường',
|
streetAddress: 'Địa chỉ đường',
|
||||||
streetSuffix: 'Hậu tố đường',
|
streetSuffix: 'Hậu tố đường',
|
||||||
streetPrefix: 'Tiền tố đường',
|
streetPrefix: 'Tiền tố đường',
|
||||||
secondaryAddress: 'Địa chỉ phụ',
|
secondaryAddress: 'Địa chỉ phụ',
|
||||||
county: 'Quận',
|
county: 'Quận',
|
||||||
country: 'Quốc gia',
|
country: 'Quốc gia',
|
||||||
countryCode: 'Mã quốc gia',
|
countryCode: 'Mã quốc gia',
|
||||||
state: 'Tiểu bang',
|
state: 'Tiểu bang',
|
||||||
stateAbbr: 'Viết tắt của tiểu bang',
|
stateAbbr: 'Viết tắt của tiểu bang',
|
||||||
latitude: 'Vĩ độ',
|
latitude: 'Vĩ độ',
|
||||||
longitude: 'Kinh độ',
|
longitude: 'Kinh độ',
|
||||||
direction: 'Hướng',
|
direction: 'Hướng',
|
||||||
cardinalDirection: 'Hướng cốt yếu',
|
cardinalDirection: 'Hướng cốt yếu',
|
||||||
ordinalDirection: 'Hướng thứ tự',
|
ordinalDirection: 'Hướng thứ tự',
|
||||||
nearbyGPSCoordinate: 'Tọa độ GPS lân cận',
|
nearbyGPSCoordinate: 'Tọa độ GPS lân cận',
|
||||||
timeZone: 'Múi giờ',
|
timeZone: 'Múi giờ',
|
||||||
color: 'Màu',
|
color: 'Màu',
|
||||||
department: 'Phòng',
|
department: 'Phòng',
|
||||||
productName: 'Tên sản phẩm',
|
productName: 'Tên sản phẩm',
|
||||||
price: 'Giá',
|
price: 'Giá',
|
||||||
productAdjective: 'Tính từ sản phẩm',
|
productAdjective: 'Tính từ sản phẩm',
|
||||||
productMaterial: 'Chất liệu sản phẩm',
|
productMaterial: 'Chất liệu sản phẩm',
|
||||||
product: 'Sản phẩm',
|
product: 'Sản phẩm',
|
||||||
productDescription: 'Mô tả sản phẩm',
|
productDescription: 'Mô tả sản phẩm',
|
||||||
suffixes: 'Hậu tố',
|
suffixes: 'Hậu tố',
|
||||||
companyName: 'Tên công ty',
|
companyName: 'Tên công ty',
|
||||||
companySuffix: 'Hậu tố công ty',
|
companySuffix: 'Hậu tố công ty',
|
||||||
catchPhrase: 'Khẩu hiệu',
|
catchPhrase: 'Khẩu hiệu',
|
||||||
bs: 'BS',
|
bs: 'BS',
|
||||||
catchPhraseAdjective: 'Bắt cụm từ tính từ',
|
catchPhraseAdjective: 'Bắt cụm từ tính từ',
|
||||||
catchPhraseDescriptor: 'Bắt bộ mô tả cụm từ',
|
catchPhraseDescriptor: 'Bắt bộ mô tả cụm từ',
|
||||||
catchPhraseNoun: 'Bắt cụm từ danh từ',
|
catchPhraseNoun: 'Bắt cụm từ danh từ',
|
||||||
bsAdjective: 'BS tính từ',
|
bsAdjective: 'BS tính từ',
|
||||||
bsBuzz: 'BS buzz',
|
bsBuzz: 'BS buzz',
|
||||||
bsNoun: 'BS danh từ',
|
bsNoun: 'BS danh từ',
|
||||||
column: 'Cột',
|
column: 'Cột',
|
||||||
type: 'Loại',
|
type: 'Loại',
|
||||||
collation: 'Đối chiếu',
|
collation: 'Đối chiếu',
|
||||||
engine: 'Engine',
|
engine: 'Engine',
|
||||||
past: 'Quá khứ',
|
past: 'Quá khứ',
|
||||||
future: 'Tương lai',
|
future: 'Tương lai',
|
||||||
between: 'Giữa',
|
between: 'Giữa',
|
||||||
recent: 'Gần đây',
|
recent: 'Gần đây',
|
||||||
soon: 'Sớm',
|
soon: 'Sớm',
|
||||||
month: 'Tháng',
|
month: 'Tháng',
|
||||||
weekday: 'Ngày trong tuần',
|
weekday: 'Ngày trong tuần',
|
||||||
account: 'Tài khoản',
|
account: 'Tài khoản',
|
||||||
accountName: 'Tên tài khoản',
|
accountName: 'Tên tài khoản',
|
||||||
routingNumber: 'Số định tuyến',
|
routingNumber: 'Số định tuyến',
|
||||||
mask: 'Mặt nạ',
|
mask: 'Mặt nạ',
|
||||||
amount: 'Số tiền',
|
amount: 'Số tiền',
|
||||||
transactionType: 'Loại giao dịch',
|
transactionType: 'Loại giao dịch',
|
||||||
currencyCode: 'Mã tiền tệ',
|
currencyCode: 'Mã tiền tệ',
|
||||||
currencyName: 'Tên tiền tệ',
|
currencyName: 'Tên tiền tệ',
|
||||||
currencySymbol: 'Ký hiệu tiền tệ',
|
currencySymbol: 'Ký hiệu tiền tệ',
|
||||||
bitcoinAddress: 'Địa chỉ Bitcoin',
|
bitcoinAddress: 'Địa chỉ Bitcoin',
|
||||||
litecoinAddress: 'Địa chỉ Litecoin',
|
litecoinAddress: 'Địa chỉ Litecoin',
|
||||||
creditCardNumber: 'Số thẻ tín dụng',
|
creditCardNumber: 'Số thẻ tín dụng',
|
||||||
creditCardCVV: 'CVV thẻ tín dụng',
|
creditCardCVV: 'CVV thẻ tín dụng',
|
||||||
ethereumAddress: 'Địa chỉ Ethereum',
|
ethereumAddress: 'Địa chỉ Ethereum',
|
||||||
iban: 'Iban',
|
iban: 'Iban',
|
||||||
bic: 'Bic',
|
bic: 'Bic',
|
||||||
transactionDescription: 'Mô tả giao dịch',
|
transactionDescription: 'Mô tả giao dịch',
|
||||||
branch: 'Nhánh',
|
branch: 'Nhánh',
|
||||||
commitEntry: 'Nhập cam kết',
|
commitEntry: 'Nhập cam kết',
|
||||||
commitMessage: 'Thông báo cam kết',
|
commitMessage: 'Thông báo cam kết',
|
||||||
commitSha: 'Cam kết SHA',
|
commitSha: 'Cam kết SHA',
|
||||||
shortSha: 'SHA ngắn',
|
shortSha: 'SHA ngắn',
|
||||||
abbreviation: 'Viết tắt',
|
abbreviation: 'Viết tắt',
|
||||||
adjective: 'Tính từ',
|
adjective: 'Tính từ',
|
||||||
noun: 'Danh từ',
|
noun: 'Danh từ',
|
||||||
verb: 'Động từ',
|
verb: 'Động từ',
|
||||||
ingverb: 'Động từ ing',
|
ingverb: 'Động từ ing',
|
||||||
phrase: 'Cụm từ',
|
phrase: 'Cụm từ',
|
||||||
avatar: 'Ảnh đại diện',
|
avatar: 'Ảnh đại diện',
|
||||||
email: 'Email',
|
email: 'Email',
|
||||||
exampleEmail: 'Email ví dụ',
|
exampleEmail: 'Email ví dụ',
|
||||||
userName: 'Tên người dùng',
|
userName: 'Tên người dùng',
|
||||||
protocol: 'Giao thức',
|
protocol: 'Giao thức',
|
||||||
url: 'Url',
|
url: 'Url',
|
||||||
domainName: 'Tên miền',
|
domainName: 'Tên miền',
|
||||||
domainSuffix: 'Hậu tố miền',
|
domainSuffix: 'Hậu tố miền',
|
||||||
domainWord: 'Từ miền',
|
domainWord: 'Từ miền',
|
||||||
ip: 'Ip',
|
ip: 'Ip',
|
||||||
ipv6: 'Ipv6',
|
ipv6: 'Ipv6',
|
||||||
userAgent: 'User agent',
|
userAgent: 'User agent',
|
||||||
mac: 'Mac',
|
mac: 'Mac',
|
||||||
password: 'Mật khẩu',
|
password: 'Mật khẩu',
|
||||||
word: 'Từ',
|
word: 'Từ',
|
||||||
words: 'Từ',
|
words: 'Từ',
|
||||||
sentence: 'Câu',
|
sentence: 'Câu',
|
||||||
slug: 'Slug',
|
slug: 'Slug',
|
||||||
sentences: 'Câu',
|
sentences: 'Câu',
|
||||||
paragraph: 'Đoạn văn',
|
paragraph: 'Đoạn văn',
|
||||||
paragraphs: 'Đoạn văn',
|
paragraphs: 'Đoạn văn',
|
||||||
text: 'Văn bản',
|
text: 'Văn bản',
|
||||||
lines: 'Dòng',
|
lines: 'Dòng',
|
||||||
genre: 'Thể loại',
|
genre: 'Thể loại',
|
||||||
firstName: 'Tên',
|
firstName: 'Tên',
|
||||||
lastName: 'Họ',
|
lastName: 'Họ',
|
||||||
middleName: 'Tên đệm',
|
middleName: 'Tên đệm',
|
||||||
findName: 'Tên đầy đủ',
|
findName: 'Tên đầy đủ',
|
||||||
jobTitle: 'Chức vụ',
|
jobTitle: 'Chức vụ',
|
||||||
gender: 'Giới tính',
|
gender: 'Giới tính',
|
||||||
prefix: 'Tiền tố',
|
prefix: 'Tiền tố',
|
||||||
suffix: 'Hậu tố',
|
suffix: 'Hậu tố',
|
||||||
title: 'Tiêu đề',
|
title: 'Tiêu đề',
|
||||||
jobDescriptor: 'Mô tả công việc',
|
jobDescriptor: 'Mô tả công việc',
|
||||||
jobArea: 'Lĩnh vực việc làm',
|
jobArea: 'Lĩnh vực việc làm',
|
||||||
jobType: 'Loại công việc',
|
jobType: 'Loại công việc',
|
||||||
phoneNumber: 'Số điện thoại',
|
phoneNumber: 'Số điện thoại',
|
||||||
phoneNumberFormat: 'Định dạng số điện thoại',
|
phoneNumberFormat: 'Định dạng số điện thoại',
|
||||||
phoneFormats: 'Định dạng điện thoại',
|
phoneFormats: 'Định dạng điện thoại',
|
||||||
number: 'Số',
|
number: 'Số',
|
||||||
float: 'Float',
|
float: 'Float',
|
||||||
arrayElement: 'Phân tử array',
|
arrayElement: 'Phân tử array',
|
||||||
arrayElements: 'Phân tử array',
|
arrayElements: 'Phân tử array',
|
||||||
objectElement: 'Phần tử object',
|
objectElement: 'Phần tử object',
|
||||||
uuid: 'Uuid',
|
uuid: 'Uuid',
|
||||||
boolean: 'Boolean',
|
boolean: 'Boolean',
|
||||||
image: 'Hình ảnh',
|
image: 'Hình ảnh',
|
||||||
locale: 'Ngôn ngữ',
|
locale: 'Ngôn ngữ',
|
||||||
alpha: 'Alpha',
|
alpha: 'Alpha',
|
||||||
alphaNumeric: 'Chữ và số',
|
alphaNumeric: 'Chữ và số',
|
||||||
hexaDecimal: 'Hệ thập lục phân',
|
hexaDecimal: 'Hệ thập lục phân',
|
||||||
fileName: 'File name',
|
fileName: 'File name',
|
||||||
commonFileName: 'Tên tệp chung',
|
commonFileName: 'Tên tệp chung',
|
||||||
mimeType: 'Kiểu mine',
|
mimeType: 'Kiểu mine',
|
||||||
commonFileType: 'Loại tệp chung',
|
commonFileType: 'Loại tệp chung',
|
||||||
commonFileExt: 'Phần mở rộng tệp chung',
|
commonFileExt: 'Phần mở rộng tệp chung',
|
||||||
fileType: 'Loại tệp',
|
fileType: 'Loại tệp',
|
||||||
fileExt: 'Phần mở rộng tệp',
|
fileExt: 'Phần mở rộng tệp',
|
||||||
directoryPath: 'Đường dẫn thư mục',
|
directoryPath: 'Đường dẫn thư mục',
|
||||||
filePath: 'Đường dẫn tệp',
|
filePath: 'Đường dẫn tệp',
|
||||||
semver: 'Semver',
|
semver: 'Semver',
|
||||||
manufacturer: 'Manufacturer',
|
manufacturer: 'Manufacturer',
|
||||||
model: 'Model',
|
model: 'Model',
|
||||||
fuel: 'Fuel',
|
fuel: 'Fuel',
|
||||||
vin: 'Vin'
|
vin: 'Vin'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Before Width: | Height: | Size: 1004 B After Width: | Height: | Size: 1004 B |
22
src/renderer/index.ejs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title></title>
|
||||||
|
<script>
|
||||||
|
global = globalThis
|
||||||
|
</script>
|
||||||
|
<% if (htmlWebpackPlugin.options.nodeModules) { %>
|
||||||
|
<script>
|
||||||
|
require('module').globalPaths.push(
|
||||||
|
`<%= htmlWebpackPlugin.options.nodeModules.replace(/\\/g, '\\\\') %>`
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
<% } %>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<!-- webpack builds are automatically injected -->
|
||||||
|
</body>
|
||||||
|
</html>
|
@@ -17,4 +17,8 @@ export default class {
|
|||||||
static createScheduler (params) {
|
static createScheduler (params) {
|
||||||
return ipcRenderer.invoke('create-scheduler', params);
|
return ipcRenderer.invoke('create-scheduler', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static toggleScheduler (params) {
|
||||||
|
return ipcRenderer.invoke('toggle-scheduler', params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,4 +17,8 @@ export default class {
|
|||||||
static createTrigger (params) {
|
static createTrigger (params) {
|
||||||
return ipcRenderer.invoke('create-trigger', params);
|
return ipcRenderer.invoke('create-trigger', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static toggleTrigger (params) {
|
||||||
|
return ipcRenderer.invoke('toggle-trigger', params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,10 +17,12 @@
|
|||||||
(
|
(
|
||||||
"char": $string-color,
|
"char": $string-color,
|
||||||
"varchar": $string-color,
|
"varchar": $string-color,
|
||||||
|
"longvarchar": $string-color,
|
||||||
"text": $string-color,
|
"text": $string-color,
|
||||||
"tinytext": $string-color,
|
"tinytext": $string-color,
|
||||||
"mediumtext": $string-color,
|
"mediumtext": $string-color,
|
||||||
"longtext": $string-color,
|
"longtext": $string-color,
|
||||||
|
"string": $string-color,
|
||||||
"json": $string-color,
|
"json": $string-color,
|
||||||
"name": $string-color,
|
"name": $string-color,
|
||||||
"character": $string-color,
|
"character": $string-color,
|
||||||
@@ -50,6 +52,7 @@
|
|||||||
"oid": $number-color,
|
"oid": $number-color,
|
||||||
"xid": $number-color,
|
"xid": $number-color,
|
||||||
"money": $number-color,
|
"money": $number-color,
|
||||||
|
"number": $number-color,
|
||||||
"datetime": $date-color,
|
"datetime": $date-color,
|
||||||
"date": $date-color,
|
"date": $date-color,
|
||||||
"time": $date-color,
|
"time": $date-color,
|
||||||
@@ -70,6 +73,7 @@
|
|||||||
"bytea": $blob-color,
|
"bytea": $blob-color,
|
||||||
"enum": $enum-color,
|
"enum": $enum-color,
|
||||||
"set": $enum-color,
|
"set": $enum-color,
|
||||||
|
"bool": $enum-color,
|
||||||
"boolean": $enum-color,
|
"boolean": $enum-color,
|
||||||
"interval": $array-color,
|
"interval": $array-color,
|
||||||
"array": $array-color,
|
"array": $array-color,
|
||||||
|
@@ -20,6 +20,10 @@
|
|||||||
background-image: url("../images/svg/pg.svg");
|
background-image: url("../images/svg/pg.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.dbi-sqlite {
|
||||||
|
background-image: url("../images/svg/sqlite.svg");
|
||||||
|
}
|
||||||
|
|
||||||
&.dbi-oracledb {
|
&.dbi-oracledb {
|
||||||
background-image: url("../images/svg/oracledb.svg");
|
background-image: url("../images/svg/oracledb.svg");
|
||||||
}
|
}
|
||||||
|
@@ -142,7 +142,7 @@
|
|||||||
|
|
||||||
code {
|
code {
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
color: $body-font-color-dark;
|
color: rgba($body-font-color-dark, 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Antares
|
// Antares
|
||||||
|
@@ -13,6 +13,7 @@ import notifications from './modules/notifications.store';
|
|||||||
|
|
||||||
import ipcUpdates from './plugins/ipcUpdates';
|
import ipcUpdates from './plugins/ipcUpdates';
|
||||||
import ipcExceptions from './plugins/ipcExceptions';
|
import ipcExceptions from './plugins/ipcExceptions';
|
||||||
|
import ipcShortcuts from './plugins/ipcShortcuts';
|
||||||
|
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ export default new Vuex.Store({
|
|||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
ipcUpdates,
|
ipcUpdates,
|
||||||
ipcExceptions
|
ipcExceptions,
|
||||||
|
ipcShortcuts
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
@@ -24,12 +24,24 @@ export default {
|
|||||||
getConnections: state => state.connections,
|
getConnections: state => state.connections,
|
||||||
getConnectionName: state => uid => {
|
getConnectionName: state => uid => {
|
||||||
const connection = state.connections.filter(connection => connection.uid === uid)[0];
|
const connection = state.connections.filter(connection => connection.uid === uid)[0];
|
||||||
if (!connection) return '';
|
let connectionName = '';
|
||||||
return connection.name
|
|
||||||
? connection.name
|
if (connection.name)
|
||||||
: connection.ask
|
connectionName = connection.name;
|
||||||
? `${connection.host}:${connection.port}`
|
else if (connection.ask)
|
||||||
: `${connection.user + '@'}${connection.host}:${connection.port}`;
|
connectionName = `${connection.host}:${connection.port}`;
|
||||||
|
else if (connection.databasePath) {
|
||||||
|
let string = connection.databasePath.split(/[/\\]+/).pop();
|
||||||
|
|
||||||
|
if (string.length >= 30)
|
||||||
|
string = `...${string.slice(-30)}`;
|
||||||
|
|
||||||
|
connectionName = string;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
connectionName = `${connection.user + '@'}${connection.host}:${connection.port}`;
|
||||||
|
|
||||||
|
return connectionName;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
|
@@ -412,6 +412,11 @@ export default {
|
|||||||
indexTypes = require('common/index-types/postgresql');
|
indexTypes = require('common/index-types/postgresql');
|
||||||
customizations = require('common/customizations/postgresql');
|
customizations = require('common/customizations/postgresql');
|
||||||
break;
|
break;
|
||||||
|
case 'sqlite':
|
||||||
|
dataTypes = require('common/data-types/sqlite');
|
||||||
|
indexTypes = require('common/index-types/sqlite');
|
||||||
|
customizations = require('common/customizations/sqlite');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { status, response: version } = await Schema.getVersion(connection.uid);
|
const { status, response: version } = await Schema.getVersion(connection.uid);
|
||||||
|
12
src/renderer/store/plugins/ipcShortcuts.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { ipcRenderer } from 'electron';
|
||||||
|
|
||||||
|
export default store => {
|
||||||
|
ipcRenderer.on('toggle-preferences', (event, error) => {
|
||||||
|
store.dispatch('application/showSettingModal', 'general');
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcRenderer.on('open-updates-preferences', (event, error) => {
|
||||||
|
store.dispatch('application/showSettingModal', 'update');
|
||||||
|
ipcRenderer.send('check-for-updates');
|
||||||
|
});
|
||||||
|
};
|
@@ -4,23 +4,33 @@ export default store => {
|
|||||||
ipcRenderer.on('checking-for-update', () => {
|
ipcRenderer.on('checking-for-update', () => {
|
||||||
store.commit('application/CHANGE_UPDATE_STATUS', 'checking');
|
store.commit('application/CHANGE_UPDATE_STATUS', 'checking');
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('update-available', () => {
|
ipcRenderer.on('update-available', () => {
|
||||||
store.commit('application/CHANGE_UPDATE_STATUS', 'available');
|
store.commit('application/CHANGE_UPDATE_STATUS', 'available');
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('update-not-available', () => {
|
ipcRenderer.on('update-not-available', () => {
|
||||||
store.commit('application/CHANGE_UPDATE_STATUS', 'noupdate');
|
store.commit('application/CHANGE_UPDATE_STATUS', 'noupdate');
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('check-failed', () => {
|
ipcRenderer.on('check-failed', () => {
|
||||||
store.commit('application/CHANGE_UPDATE_STATUS', 'nocheck');
|
store.commit('application/CHANGE_UPDATE_STATUS', 'nocheck');
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('no-auto-update', () => {
|
ipcRenderer.on('no-auto-update', () => {
|
||||||
store.commit('application/CHANGE_UPDATE_STATUS', 'disabled');
|
store.commit('application/CHANGE_UPDATE_STATUS', 'disabled');
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('download-progress', (event, data) => {
|
ipcRenderer.on('download-progress', (event, data) => {
|
||||||
store.commit('application/CHANGE_UPDATE_STATUS', 'downloading');
|
store.commit('application/CHANGE_UPDATE_STATUS', 'downloading');
|
||||||
store.commit('application/CHANGE_PROGRESS_PERCENTAGE', data.percent);
|
store.commit('application/CHANGE_PROGRESS_PERCENTAGE', data.percent);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('update-downloaded', () => {
|
ipcRenderer.on('update-downloaded', () => {
|
||||||
store.commit('application/CHANGE_UPDATE_STATUS', 'downloaded');
|
store.commit('application/CHANGE_UPDATE_STATUS', 'downloaded');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcRenderer.on('link-to-download', () => {
|
||||||
|
store.commit('application/CHANGE_UPDATE_STATUS', 'link');
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
@@ -1,27 +0,0 @@
|
|||||||
const webpack = require('webpack');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
stats: 'errors-warnings',
|
|
||||||
plugins: [
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env': {
|
|
||||||
PACKAGE_VERSION: JSON.stringify(require('./package.json').version)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
],
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.scss$/,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: 'sass-loader',
|
|
||||||
options: {
|
|
||||||
additionalData: '@import "@/scss/_variables.scss";'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
|
70
webpack.main.config.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||||
|
const ProgressPlugin = require('progress-webpack-plugin');
|
||||||
|
|
||||||
|
const { dependencies, devDependencies } = require('./package.json');
|
||||||
|
|
||||||
|
const externals = Object.keys(dependencies).concat(Object.keys(devDependencies));
|
||||||
|
const isDevMode = process.env.NODE_ENV === 'development';
|
||||||
|
const whiteListedModules = [];
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{ // Main
|
||||||
|
name: 'main',
|
||||||
|
mode: process.env.NODE_ENV,
|
||||||
|
devtool: isDevMode ? 'eval-source-map' : false,
|
||||||
|
entry: {
|
||||||
|
main: path.join(__dirname, './src/main/main.js')
|
||||||
|
},
|
||||||
|
target: 'electron-main',
|
||||||
|
output: {
|
||||||
|
libraryTarget: 'commonjs2',
|
||||||
|
path: path.join(__dirname, 'dist'),
|
||||||
|
filename: '[name].js'
|
||||||
|
},
|
||||||
|
node: {
|
||||||
|
global: true,
|
||||||
|
__dirname: isDevMode,
|
||||||
|
__filename: isDevMode
|
||||||
|
},
|
||||||
|
externals: externals.filter((d) => !whiteListedModules.includes(d)),
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.json'],
|
||||||
|
alias: {
|
||||||
|
src: path.join(__dirname, 'src/'),
|
||||||
|
common: path.resolve(__dirname, 'src/common')
|
||||||
|
},
|
||||||
|
fallback: {
|
||||||
|
'pg-native': false,
|
||||||
|
'cpu-features': false,
|
||||||
|
cardinal: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new ProgressPlugin(true),
|
||||||
|
new CleanWebpackPlugin({ root: path.join(__dirname, 'dist') })
|
||||||
|
],
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.node$/,
|
||||||
|
loader: 'node-loader',
|
||||||
|
options: {
|
||||||
|
name: '[path][name].[ext]'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
loader: 'babel-loader'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(png|jpg|gif)$/,
|
||||||
|
use: [{
|
||||||
|
loader: 'file-loader'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
147
webpack.renderer.config.js
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
|
const { VueLoaderPlugin } = require('vue-loader');
|
||||||
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
|
const ProgressPlugin = require('progress-webpack-plugin');
|
||||||
|
|
||||||
|
const { dependencies, devDependencies, version } = require('./package.json');
|
||||||
|
|
||||||
|
const externals = Object.keys(dependencies).concat(Object.keys(devDependencies));
|
||||||
|
const isDevMode = process.env.NODE_ENV === 'development';
|
||||||
|
const whiteListedModules = ['vue'];
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
name: 'renderer',
|
||||||
|
mode: process.env.NODE_ENV,
|
||||||
|
devtool: isDevMode ? 'eval-source-map' : false,
|
||||||
|
entry: {
|
||||||
|
renderer: path.join(__dirname, './src/renderer/index.js')
|
||||||
|
},
|
||||||
|
target: 'electron-renderer',
|
||||||
|
output: {
|
||||||
|
libraryTarget: 'commonjs2',
|
||||||
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
filename: '[name].js',
|
||||||
|
publicPath: ''
|
||||||
|
},
|
||||||
|
node: {
|
||||||
|
global: true,
|
||||||
|
__dirname: isDevMode,
|
||||||
|
__filename: isDevMode
|
||||||
|
},
|
||||||
|
externals: externals.filter((d) => !whiteListedModules.includes(d)),
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
vue$: 'vue/dist/vue.common.js',
|
||||||
|
common: path.resolve(__dirname, 'src/common'),
|
||||||
|
'@': path.resolve(__dirname, 'src/renderer')
|
||||||
|
},
|
||||||
|
extensions: ['', '.js', '.vue', '.json'],
|
||||||
|
fallback: {
|
||||||
|
fs: false,
|
||||||
|
path: false,
|
||||||
|
util: false,
|
||||||
|
crypto: false,
|
||||||
|
assert: false,
|
||||||
|
os: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new ProgressPlugin(true),
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
excludeChunks: ['processTaskWorker'],
|
||||||
|
filename: 'index.html',
|
||||||
|
template: path.resolve(__dirname, 'src/renderer/index.ejs'),
|
||||||
|
nodeModules: isDevMode
|
||||||
|
? path.resolve(__dirname, '../node_modules')
|
||||||
|
: false
|
||||||
|
}),
|
||||||
|
new MiniCssExtractPlugin({
|
||||||
|
filename: '[name].css',
|
||||||
|
chunkFilename: '[id].css'
|
||||||
|
}),
|
||||||
|
new VueLoaderPlugin(),
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.env': {
|
||||||
|
PACKAGE_VERSION: `"${version}"`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
use: 'babel-loader',
|
||||||
|
exclude: /node_modules/
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.node$/,
|
||||||
|
use: 'node-loader'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.vue$/,
|
||||||
|
loader: 'vue-loader'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.s(c|a)ss$/,
|
||||||
|
use: [
|
||||||
|
{ loader: MiniCssExtractPlugin.loader },
|
||||||
|
{ loader: 'css-loader' },
|
||||||
|
{
|
||||||
|
loader: 'sass-loader',
|
||||||
|
options: {
|
||||||
|
additionalData: '@import "@/scss/_variables.scss";',
|
||||||
|
sassOptions: { quietDeps: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: MiniCssExtractPlugin.loader,
|
||||||
|
options: {
|
||||||
|
publicPath: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
loader: 'css-loader',
|
||||||
|
options: {
|
||||||
|
url: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(png|jpe?g|gif|tif?f|bmp|webp|svg)(\?.*)?$/,
|
||||||
|
type: 'asset/resource',
|
||||||
|
generator: {
|
||||||
|
filename: 'images/[hash][ext][query]'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(woff|woff2|ttf|eot)$/,
|
||||||
|
type: 'asset',
|
||||||
|
parser: {
|
||||||
|
dataUrlCondition: {
|
||||||
|
maxSize: 8 * 1024
|
||||||
|
}
|
||||||
|
},
|
||||||
|
generator: {
|
||||||
|
filename: 'fonts/[hash][ext][query]'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isDevMode) {
|
||||||
|
// any dev only config
|
||||||
|
config.plugins.push(
|
||||||
|
new webpack.HotModuleReplacementPlugin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = config;
|