Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
76dc66c14d |
@@ -120,24 +120,6 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"code"
|
"code"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"login": "wenj91",
|
|
||||||
"name": "文杰",
|
|
||||||
"avatar_url": "https://avatars.githubusercontent.com/u/12549338?v=4",
|
|
||||||
"profile": "https://github.com/wenj91",
|
|
||||||
"contributions": [
|
|
||||||
"code"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"login": "goYou",
|
|
||||||
"name": "goYou",
|
|
||||||
"avatar_url": "https://avatars.githubusercontent.com/u/62732795?v=4",
|
|
||||||
"profile": "https://github.com/goYou",
|
|
||||||
"contributions": [
|
|
||||||
"translation"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"contributorsPerLine": 7,
|
"contributorsPerLine": 7,
|
||||||
|
8
.github/workflows/build-linux.yml
vendored
@@ -12,18 +12,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out Git repository
|
- name: Check out Git repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v1
|
||||||
|
|
||||||
- name: Install Node.js, NPM and Yarn
|
- name: Install Node.js, NPM and Yarn
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 14
|
node-version: 14
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm i
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: npm run test
|
|
||||||
|
|
||||||
- name: Build/release Electron app
|
- name: Build/release Electron app
|
||||||
uses: samuelmeuli/action-electron-builder@v1
|
uses: samuelmeuli/action-electron-builder@v1
|
||||||
|
8
.github/workflows/build-mac.yml
vendored
@@ -12,18 +12,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out Git repository
|
- name: Check out Git repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v1
|
||||||
|
|
||||||
- name: Install Node.js, NPM and Yarn
|
- name: Install Node.js, NPM and Yarn
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 14
|
node-version: 14
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm i
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: npm run test
|
|
||||||
|
|
||||||
- name: Build/release Electron app
|
- name: Build/release Electron app
|
||||||
uses: samuelmeuli/action-electron-builder@v1
|
uses: samuelmeuli/action-electron-builder@v1
|
||||||
|
8
.github/workflows/build-win.yml
vendored
@@ -12,19 +12,13 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out Git repository
|
- name: Check out Git repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v1
|
||||||
|
|
||||||
- name: Install Node.js, NPM and Yarn
|
- name: Install Node.js, NPM and Yarn
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 14
|
node-version: 14
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm i
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: npm run test
|
|
||||||
|
|
||||||
- name: Build/release Electron app
|
- name: Build/release Electron app
|
||||||
uses: samuelmeuli/action-electron-builder@v1
|
uses: samuelmeuli/action-electron-builder@v1
|
||||||
with:
|
with:
|
||||||
|
3
.vscode/settings.json
vendored
@@ -4,8 +4,7 @@
|
|||||||
"core",
|
"core",
|
||||||
"MySQL",
|
"MySQL",
|
||||||
"PostgreSQL",
|
"PostgreSQL",
|
||||||
"SQLite",
|
"SQLite"
|
||||||
"Windows"
|
|
||||||
],
|
],
|
||||||
"svg.preview.background": "transparent"
|
"svg.preview.background": "transparent"
|
||||||
}
|
}
|
68
CHANGELOG.md
@@ -2,73 +2,7 @@
|
|||||||
|
|
||||||
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.3](https://github.com/Fabio286/antares/compare/v0.4.2...v0.4.3) (2022-01-30)
|
### [0.3.10](https://github.com/Fabio286/antares/compare/v0.3.9...v0.3.10) (2021-11-24)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* add Simplified Chinese translation ([6ef565c](https://github.com/Fabio286/antares/commit/6ef565cf078cb3f5b7bcdc226894cddeb6239db9))
|
|
||||||
* **MySQL:** spatial fields support ([#165](https://github.com/Fabio286/antares/issues/165)) ([48ebf23](https://github.com/Fabio286/antares/commit/48ebf23bd1574408f429f2e1200ce878352007f6))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* cell copy returns "undefined" in some conditions, closes [#170](https://github.com/Fabio286/antares/issues/170) ([8fb1f08](https://github.com/Fabio286/antares/commit/8fb1f0803efd9df0b66521e73bb6e1a229cf9691))
|
|
||||||
* indexes and foreign keys not cleared after deletion of related field, closes [#182](https://github.com/Fabio286/antares/issues/182) ([9f033fb](https://github.com/Fabio286/antares/commit/9f033fb994916b4fb165e81e55e86127ca817791))
|
|
||||||
* **PostgreSQL:** schema different than public not automatically selected, closes [#172](https://github.com/Fabio286/antares/issues/172) ([46b45c8](https://github.com/Fabio286/antares/commit/46b45c8ab64fb6837a532c4f8342167e4fd794bb))
|
|
||||||
* scale on numeric fields that doesn't support it ([0cfd793](https://github.com/Fabio286/antares/commit/0cfd7938ee7d607dbad66ae452d0200223a6bab2))
|
|
||||||
* **Windows:** temporary fix to Windows 7 style frame on app startup, closes [#169](https://github.com/Fabio286/antares/issues/169) ([1356011](https://github.com/Fabio286/antares/commit/1356011ba3b7dd72e12cb252a8787ce48a364fd4))
|
|
||||||
|
|
||||||
|
|
||||||
### Improvements
|
|
||||||
|
|
||||||
* support of scale in field's length setting ([eef7c1d](https://github.com/Fabio286/antares/commit/eef7c1dcecc6593ab0e69ed678187a57fe0a4fb6))
|
|
||||||
|
|
||||||
### [0.4.2](https://github.com/Fabio286/antares/compare/v0.4.1...v0.4.2) (2022-01-10)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **MySQL:** ability to cancel queries ([a59f77f](https://github.com/Fabio286/antares/commit/a59f77f618aea6156fc80fb832d3efcb9848411f))
|
|
||||||
* **PostgreSQL:** ability to cancel queries ([0c00291](https://github.com/Fabio286/antares/commit/0c002918eb0226f6b3f21ed62117495f86396fb1))
|
|
||||||
* save window state ([8f9385d](https://github.com/Fabio286/antares/commit/8f9385d50815635d091758ecd5d00884e3297ca0))
|
|
||||||
* **UI:** textarea autofocus selecting a query tab, closes [#166](https://github.com/Fabio286/antares/issues/166) ([b4545b1](https://github.com/Fabio286/antares/commit/b4545b178f795712c781a3f4fc35eec31b5ad902))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **SQLite:** exception with some fields ([e7a1858](https://github.com/Fabio286/antares/commit/e7a18580915e7739bfa97948c6a0c4fc90a7e78a))
|
|
||||||
|
|
||||||
|
|
||||||
### Improvements
|
|
||||||
|
|
||||||
* hash for foreign key default names ([48c3e6a](https://github.com/Fabio286/antares/commit/48c3e6afc43c51f70a16703f1a71194f43da7a3e))
|
|
||||||
* **MySQL:** support to ANSI_QUOTES sql_mode, closes [#158](https://github.com/Fabio286/antares/issues/158) ([d9a3eab](https://github.com/Fabio286/antares/commit/d9a3eab015302e9f23112f659658073ab3242191))
|
|
||||||
|
|
||||||
### [0.4.1](https://github.com/Fabio286/antares/compare/v0.4.0...v0.4.1) (2021-12-11)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* language format detection for text fields ([a5fdcc1](https://github.com/Fabio286/antares/commit/a5fdcc1a85aa188ff1b9a15b1a768aced026f360))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* cell disappear on edit in one column tables ([aaa5549](https://github.com/Fabio286/antares/commit/aaa5549609664665bd4513632d621cb249b379c1))
|
|
||||||
* false positive with Windows Defender ([992a033](https://github.com/Fabio286/antares/commit/992a033cb2bede3d1eb52e19482d810f6692de1e))
|
|
||||||
* **MySQL:** wrong datetime fields default in table filler in some cases ([8da0224](https://github.com/Fabio286/antares/commit/8da022487650039b7f34a9c86a7bd9045eba65e2))
|
|
||||||
* **MySQL:** wrong value for fields "on update" in some conditions ([359e14a](https://github.com/Fabio286/antares/commit/359e14a9ebd48f86069ba7762fe00a7056f52d47))
|
|
||||||
* select all rows with ctrl+a when editing a cell ([35cb7e1](https://github.com/Fabio286/antares/commit/35cb7e1dc48d3a74e9d106cb1a37f454c1b4a4d1))
|
|
||||||
* **SQLite:** update rows with a text primary key ([d7f1aa9](https://github.com/Fabio286/antares/commit/d7f1aa97af32a4c51fc7022498bd47e15fa08430))
|
|
||||||
|
|
||||||
|
|
||||||
### Improvements
|
|
||||||
|
|
||||||
* **UI:** avoid columns size change when editing cells or scrolling results ([813aa32](https://github.com/Fabio286/antares/commit/813aa320d9ab799efea38a7110b7c0bdf7549123))
|
|
||||||
* **UI:** disable save button in table creation when no fields are added ([e8af2d2](https://github.com/Fabio286/antares/commit/e8af2d24a869f7667c069936648808952d2062ab))
|
|
||||||
|
|
||||||
## [0.4.0](https://github.com/Fabio286/antares/compare/v0.3.9...v0.4.0) (2021-11-24)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
@@ -130,8 +130,6 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|||||||
<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="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="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>
|
<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>
|
||||||
<td align="center"><a href="https://github.com/wenj91"><img src="https://avatars.githubusercontent.com/u/12549338?v=4?s=100" width="100px;" alt=""/><br /><sub><b>文杰</b></sub></a><br /><a href="https://github.com/Fabio286/antares/commits?author=wenj91" title="Code">💻</a></td>
|
|
||||||
<td align="center"><a href="https://github.com/goYou"><img src="https://avatars.githubusercontent.com/u/62732795?v=4?s=100" width="100px;" alt=""/><br /><sub><b>goYou</b></sub></a><br /><a href="#translation-goYou" title="Translation">🌍</a></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
BIN
assets/appx/LargeTile.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
assets/appx/SmallTile.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 17 KiB |
23
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "antares",
|
"name": "antares",
|
||||||
"productName": "Antares",
|
"productName": "Antares",
|
||||||
"version": "0.4.3",
|
"version": "0.3.10",
|
||||||
"description": "A modern, fast and productivity driven SQL client with a focus in UX.",
|
"description": "A modern, fast and productivity driven SQL client with a focus in UX.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/Fabio286/antares.git",
|
"repository": "https://github.com/Fabio286/antares.git",
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
"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",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"test": "npm run compile && node tests/app.spec.js",
|
"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",
|
||||||
"contributors:add": "all-contributors add",
|
"contributors:add": "all-contributors add",
|
||||||
@@ -51,8 +51,7 @@
|
|||||||
"target": {
|
"target": {
|
||||||
"target": "default",
|
"target": "default",
|
||||||
"arch": [
|
"arch": [
|
||||||
"x64",
|
"x64"
|
||||||
"arm64"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -83,7 +82,6 @@
|
|||||||
"appx": {
|
"appx": {
|
||||||
"displayName": "Antares SQL",
|
"displayName": "Antares SQL",
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"showNameOnTiles": true,
|
|
||||||
"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"
|
||||||
@@ -106,16 +104,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron/remote": "^2.0.1",
|
"@electron/remote": "^2.0.1",
|
||||||
"@mdi/font": "^6.1.95",
|
"@mdi/font": "^6.1.95",
|
||||||
"@turf/helpers": "^6.5.0",
|
|
||||||
"@vscode/vscode-languagedetection": "^1.0.21",
|
|
||||||
"ace-builds": "^1.4.13",
|
"ace-builds": "^1.4.13",
|
||||||
"better-sqlite3": "^7.4.4",
|
"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.6.1",
|
"electron-updater": "^4.3.9",
|
||||||
"electron-window-state": "^5.0.3",
|
|
||||||
"faker": "^5.5.3",
|
"faker": "^5.5.3",
|
||||||
"leaflet": "^1.7.1",
|
|
||||||
"marked": "^4.0.0",
|
"marked": "^4.0.0",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"mysql2": "^2.3.2",
|
"mysql2": "^2.3.2",
|
||||||
@@ -139,20 +133,19 @@
|
|||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"cross-env": "^7.0.2",
|
"cross-env": "^7.0.2",
|
||||||
"css-loader": "^6.5.0",
|
"css-loader": "^6.5.0",
|
||||||
"electron": "^16.0.8",
|
"electron": "^16.0.1",
|
||||||
"electron-builder": "^22.14.11",
|
"electron-builder": "^22.13.1",
|
||||||
"electron-devtools-installer": "^3.2.0",
|
"electron-devtools-installer": "^3.2.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.2.0",
|
"eslint-plugin-promise": "^5.1.0",
|
||||||
"eslint-plugin-vue": "^8.0.3",
|
"eslint-plugin-vue": "^8.0.3",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"mini-css-extract-plugin": "~2.4.5",
|
"mini-css-extract-plugin": "^2.4.3",
|
||||||
"node-loader": "^2.0.0",
|
"node-loader": "^2.0.0",
|
||||||
"playwright": "^1.18.1",
|
|
||||||
"progress-webpack-plugin": "^1.0.12",
|
"progress-webpack-plugin": "^1.0.12",
|
||||||
"sass": "^1.42.1",
|
"sass": "^1.42.1",
|
||||||
"sass-loader": "^12.3.0",
|
"sass-loader": "^12.3.0",
|
||||||
|
@@ -11,7 +11,6 @@ module.exports = {
|
|||||||
sslConnection: false,
|
sslConnection: false,
|
||||||
sshConnection: false,
|
sshConnection: false,
|
||||||
fileConnection: false,
|
fileConnection: false,
|
||||||
cancelQueries: false,
|
|
||||||
// Tools
|
// Tools
|
||||||
processesList: false,
|
processesList: false,
|
||||||
usersManagement: false,
|
usersManagement: false,
|
||||||
|
@@ -12,7 +12,6 @@ module.exports = {
|
|||||||
engines: true,
|
engines: true,
|
||||||
sslConnection: true,
|
sslConnection: true,
|
||||||
sshConnection: true,
|
sshConnection: true,
|
||||||
cancelQueries: true,
|
|
||||||
// Tools
|
// Tools
|
||||||
processesList: true,
|
processesList: true,
|
||||||
// Structure
|
// Structure
|
||||||
|
@@ -10,7 +10,6 @@ module.exports = {
|
|||||||
database: true,
|
database: true,
|
||||||
sslConnection: true,
|
sslConnection: true,
|
||||||
sshConnection: true,
|
sshConnection: true,
|
||||||
cancelQueries: true,
|
|
||||||
// Tools
|
// Tools
|
||||||
processesList: true,
|
processesList: true,
|
||||||
// Structure
|
// Structure
|
||||||
|
@@ -7,8 +7,8 @@ module.exports = {
|
|||||||
views: true,
|
views: true,
|
||||||
triggers: true,
|
triggers: true,
|
||||||
// Settings
|
// Settings
|
||||||
elementsWrapper: '"',
|
elementsWrapper: '',
|
||||||
stringsWrapper: '\'',
|
stringsWrapper: '"',
|
||||||
tableAdd: true,
|
tableAdd: true,
|
||||||
viewAdd: true,
|
viewAdd: true,
|
||||||
triggerAdd: true,
|
triggerAdd: true,
|
||||||
|
@@ -66,7 +66,6 @@ module.exports = [
|
|||||||
{
|
{
|
||||||
name: 'DECIMAL',
|
name: 'DECIMAL',
|
||||||
length: true,
|
length: true,
|
||||||
scale: true,
|
|
||||||
collation: false,
|
collation: false,
|
||||||
unsigned: false,
|
unsigned: false,
|
||||||
zerofill: false
|
zerofill: false
|
||||||
@@ -219,56 +218,56 @@ module.exports = [
|
|||||||
types: [
|
types: [
|
||||||
{
|
{
|
||||||
name: 'POINT',
|
name: 'POINT',
|
||||||
length: false,
|
length: true,
|
||||||
collation: false,
|
collation: false,
|
||||||
unsigned: false,
|
unsigned: false,
|
||||||
zerofill: false
|
zerofill: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'LINESTRING',
|
name: 'LINESTRING',
|
||||||
length: false,
|
length: true,
|
||||||
collation: false,
|
collation: false,
|
||||||
unsigned: false,
|
unsigned: false,
|
||||||
zerofill: false
|
zerofill: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'POLYGON',
|
name: 'POLYGON',
|
||||||
length: false,
|
length: true,
|
||||||
collation: false,
|
collation: false,
|
||||||
unsigned: false,
|
unsigned: false,
|
||||||
zerofill: false
|
zerofill: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'GEOMETRY',
|
name: 'GEOMETRY',
|
||||||
length: false,
|
length: true,
|
||||||
collation: false,
|
collation: false,
|
||||||
unsigned: false,
|
unsigned: false,
|
||||||
zerofill: false
|
zerofill: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'MULTIPOINT',
|
name: 'MULTIPOINT',
|
||||||
length: false,
|
length: true,
|
||||||
collation: false,
|
collation: false,
|
||||||
unsigned: false,
|
unsigned: false,
|
||||||
zerofill: false
|
zerofill: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'MULTILINESTRING',
|
name: 'MULTILINESTRING',
|
||||||
length: false,
|
length: true,
|
||||||
collation: false,
|
collation: false,
|
||||||
unsigned: false,
|
unsigned: false,
|
||||||
zerofill: false
|
zerofill: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'MULTIPOLYGON',
|
name: 'MULTIPOLYGON',
|
||||||
length: false,
|
length: true,
|
||||||
collation: false,
|
collation: false,
|
||||||
unsigned: false,
|
unsigned: false,
|
||||||
zerofill: false
|
zerofill: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'GEOMCOLLECTION',
|
name: 'GEOMETRYCOLLECTION',
|
||||||
length: false,
|
length: true,
|
||||||
collation: false,
|
collation: false,
|
||||||
unsigned: false,
|
unsigned: false,
|
||||||
zerofill: false
|
zerofill: false
|
||||||
|
@@ -22,6 +22,11 @@ module.exports = [
|
|||||||
length: false,
|
length: false,
|
||||||
unsigned: true
|
unsigned: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'NUMERIC',
|
||||||
|
length: true,
|
||||||
|
unsigned: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'SMALLSERIAL',
|
name: 'SMALLSERIAL',
|
||||||
length: false,
|
length: false,
|
||||||
@@ -47,12 +52,6 @@ module.exports = [
|
|||||||
length: false,
|
length: false,
|
||||||
unsigned: true
|
unsigned: true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'NUMERIC',
|
|
||||||
length: true,
|
|
||||||
unsigned: true,
|
|
||||||
scale: true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'DOUBLE PRECISION',
|
name: 'DOUBLE PRECISION',
|
||||||
length: false,
|
length: false,
|
||||||
|
@@ -8,9 +8,7 @@ export const TEXT = [
|
|||||||
export const LONG_TEXT = [
|
export const LONG_TEXT = [
|
||||||
'TEXT',
|
'TEXT',
|
||||||
'MEDIUMTEXT',
|
'MEDIUMTEXT',
|
||||||
'LONGTEXT',
|
'LONGTEXT'
|
||||||
'JSON',
|
|
||||||
'VARBINARY'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export const ARRAY = [
|
export const ARRAY = [
|
||||||
@@ -84,24 +82,3 @@ export const BIT = [
|
|||||||
'BIT',
|
'BIT',
|
||||||
'BIT VARYING'
|
'BIT VARYING'
|
||||||
];
|
];
|
||||||
|
|
||||||
export const SPATIAL = [
|
|
||||||
'POINT',
|
|
||||||
'LINESTRING',
|
|
||||||
'POLYGON',
|
|
||||||
'GEOMETRY',
|
|
||||||
'MULTIPOINT',
|
|
||||||
'MULTILINESTRING',
|
|
||||||
'MULTIPOLYGON',
|
|
||||||
'GEOMCOLLECTION',
|
|
||||||
'GEOMETRYCOLLECTION'
|
|
||||||
];
|
|
||||||
|
|
||||||
// Used to check multi spatial fields only
|
|
||||||
export const IS_MULTI_SPATIAL = [
|
|
||||||
'MULTIPOINT',
|
|
||||||
'MULTILINESTRING',
|
|
||||||
'MULTIPOLYGON',
|
|
||||||
'GEOMCOLLECTION',
|
|
||||||
'GEOMETRYCOLLECTION'
|
|
||||||
];
|
|
||||||
|
@@ -1,10 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* @param {any[]} array
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
export function getArrayDepth (array) {
|
|
||||||
return Array.isArray(array)
|
|
||||||
? 1 + Math.max(0, ...array.map(getArrayDepth))
|
|
||||||
: 0;
|
|
||||||
}
|
|
@@ -52,7 +52,7 @@ export default connections => {
|
|||||||
return { status: 'success' };
|
return { status: 'success' };
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
return { status: 'error', response: err.toString() };
|
return { status: 'error', response: err };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -135,7 +135,7 @@ export default connections => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('raw-query', async (event, { uid, query, schema, tabUid }) => {
|
ipcMain.handle('raw-query', async (event, { uid, query, schema }) => {
|
||||||
if (!query) return;
|
if (!query) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -143,7 +143,6 @@ export default connections => {
|
|||||||
nest: true,
|
nest: true,
|
||||||
details: true,
|
details: true,
|
||||||
schema,
|
schema,
|
||||||
tabUid,
|
|
||||||
comments: false
|
comments: false
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -153,16 +152,4 @@ export default connections => {
|
|||||||
return { status: 'error', response: err.toString() };
|
return { status: 'error', response: err.toString() };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('kill-tab-query', async (event, { uid, tabUid }) => {
|
|
||||||
if (!tabUid) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await connections[uid].killTabQuery(tabUid);
|
|
||||||
return { status: 'success' };
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
return { status: 'error', response: err.toString() };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
@@ -3,7 +3,6 @@ import faker from 'faker';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { sqlEscaper } from 'common/libs/sqlEscaper';
|
import { sqlEscaper } from 'common/libs/sqlEscaper';
|
||||||
import { TEXT, LONG_TEXT, ARRAY, TEXT_SEARCH, NUMBER, FLOAT, BLOB, BIT, DATE, DATETIME } from 'common/fieldTypes';
|
import { TEXT, LONG_TEXT, ARRAY, TEXT_SEARCH, NUMBER, FLOAT, BLOB, BIT, DATE, DATETIME } from 'common/fieldTypes';
|
||||||
import * as customizations from 'common/customizations';
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|
||||||
export default (connections) => {
|
export default (connections) => {
|
||||||
@@ -86,12 +85,11 @@ export default (connections) => {
|
|||||||
|
|
||||||
ipcMain.handle('update-table-cell', async (event, params) => {
|
ipcMain.handle('update-table-cell', async (event, params) => {
|
||||||
delete params.row._antares_id;
|
delete params.row._antares_id;
|
||||||
const { stringsWrapper: sw } = customizations[connections[params.uid]._client];
|
|
||||||
|
|
||||||
try { // TODO: move to client classes
|
try { // TODO: move to client classes
|
||||||
let escapedParam;
|
let escapedParam;
|
||||||
let reload = false;
|
let reload = false;
|
||||||
const id = typeof params.id === 'number' ? params.id : `${sw}${params.id}${sw}`;
|
const id = typeof params.id === 'number' ? params.id : `"${params.id}"`;
|
||||||
|
|
||||||
if ([...NUMBER, ...FLOAT].includes(params.type))
|
if ([...NUMBER, ...FLOAT].includes(params.type))
|
||||||
escapedParam = params.content;
|
escapedParam = params.content;
|
||||||
|
@@ -9,7 +9,6 @@ export class MySQLClient extends AntaresCore {
|
|||||||
super(args);
|
super(args);
|
||||||
|
|
||||||
this._schema = null;
|
this._schema = null;
|
||||||
this._runningConnections = new Map();
|
|
||||||
|
|
||||||
this.types = {
|
this.types = {
|
||||||
0: 'DECIMAL',
|
0: 'DECIMAL',
|
||||||
@@ -137,16 +136,8 @@ export class MySQLClient extends AntaresCore {
|
|||||||
if (!this._poolSize) {
|
if (!this._poolSize) {
|
||||||
this._connection = await mysql.createConnection(dbConfig);
|
this._connection = await mysql.createConnection(dbConfig);
|
||||||
|
|
||||||
// ANSI_QUOTES check
|
|
||||||
const res = await this.getVariable('sql_mode', 'global');
|
|
||||||
const sqlMode = res?.value.split(',');
|
|
||||||
const hasAnsiQuotes = sqlMode.includes('ANSI_QUOTES');
|
|
||||||
|
|
||||||
if (this._params.readonly)
|
if (this._params.readonly)
|
||||||
await this.raw('SET SESSION TRANSACTION READ ONLY');
|
await this.raw('SET SESSION TRANSACTION READ ONLY');
|
||||||
|
|
||||||
if (hasAnsiQuotes)
|
|
||||||
await this.raw(`SET SESSION sql_mode = "${sqlMode.filter(m => m !== 'ANSI_QUOTES').join(',')}"`);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this._connection = mysql.createPool({
|
this._connection = mysql.createPool({
|
||||||
@@ -160,21 +151,11 @@ export class MySQLClient extends AntaresCore {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ANSI_QUOTES check
|
if (this._params.readonly) {
|
||||||
const res = await this.getVariable('sql_mode', 'global');
|
this._connection.on('connection', connection => {
|
||||||
const sqlMode = res?.value.split(',');
|
|
||||||
const hasAnsiQuotes = sqlMode.includes('ANSI_QUOTES');
|
|
||||||
|
|
||||||
if (hasAnsiQuotes)
|
|
||||||
await this._connection.query(`SET SESSION sql_mode = "${sqlMode.filter(m => m !== 'ANSI_QUOTES').join(',')}"`);
|
|
||||||
|
|
||||||
this._connection.on('connection', connection => {
|
|
||||||
if (this._params.readonly)
|
|
||||||
connection.query('SET SESSION TRANSACTION READ ONLY');
|
connection.query('SET SESSION TRANSACTION READ ONLY');
|
||||||
|
});
|
||||||
if (hasAnsiQuotes)
|
}
|
||||||
connection.query(`SET SESSION sql_mode = "${sqlMode.filter(m => m !== 'ANSI_QUOTES').join(',')}"`);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,7 +416,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
|
|
||||||
return rows.map(field => {
|
return rows.map(field => {
|
||||||
let numLength = field.COLUMN_TYPE.match(/int\(([^)]+)\)/);
|
let numLength = field.COLUMN_TYPE.match(/int\(([^)]+)\)/);
|
||||||
numLength = numLength ? +numLength.pop() : field.NUMERIC_PRECISION || null;
|
numLength = numLength ? +numLength.pop() : null;
|
||||||
const enumValues = /(enum|set)/.test(field.COLUMN_TYPE)
|
const enumValues = /(enum|set)/.test(field.COLUMN_TYPE)
|
||||||
? field.COLUMN_TYPE.match(/\(([^)]+)\)/)[0].slice(1, -1)
|
? field.COLUMN_TYPE.match(/\(([^)]+)\)/)[0].slice(1, -1)
|
||||||
: null;
|
: null;
|
||||||
@@ -443,13 +424,10 @@ export class MySQLClient extends AntaresCore {
|
|||||||
return {
|
return {
|
||||||
name: field.COLUMN_NAME,
|
name: field.COLUMN_NAME,
|
||||||
key: field.COLUMN_KEY.toLowerCase(),
|
key: field.COLUMN_KEY.toLowerCase(),
|
||||||
type: (remappedFields && remappedFields[field.COLUMN_NAME])
|
type: remappedFields ? remappedFields[field.COLUMN_NAME].type : field.DATA_TYPE,
|
||||||
? remappedFields[field.COLUMN_NAME].type
|
|
||||||
: field.DATA_TYPE.toUpperCase(),
|
|
||||||
schema: field.TABLE_SCHEMA,
|
schema: field.TABLE_SCHEMA,
|
||||||
table: field.TABLE_NAME,
|
table: field.TABLE_NAME,
|
||||||
numPrecision: field.NUMERIC_PRECISION,
|
numPrecision: field.NUMERIC_PRECISION,
|
||||||
numScale: field.NUMERIC_SCALE,
|
|
||||||
numLength,
|
numLength,
|
||||||
enumValues,
|
enumValues,
|
||||||
datePrecision: field.DATETIME_PRECISION,
|
datePrecision: field.DATETIME_PRECISION,
|
||||||
@@ -458,13 +436,11 @@ export class MySQLClient extends AntaresCore {
|
|||||||
unsigned: field.COLUMN_TYPE.includes('unsigned'),
|
unsigned: field.COLUMN_TYPE.includes('unsigned'),
|
||||||
zerofill: field.COLUMN_TYPE.includes('zerofill'),
|
zerofill: field.COLUMN_TYPE.includes('zerofill'),
|
||||||
order: field.ORDINAL_POSITION,
|
order: field.ORDINAL_POSITION,
|
||||||
default: (remappedFields && remappedFields[field.COLUMN_NAME]) ? remappedFields[field.COLUMN_NAME].default : field.COLUMN_DEFAULT,
|
default: remappedFields ? remappedFields[field.COLUMN_NAME].default : field.COLUMN_DEFAULT,
|
||||||
charset: field.CHARACTER_SET_NAME,
|
charset: field.CHARACTER_SET_NAME,
|
||||||
collation: field.COLLATION_NAME,
|
collation: field.COLLATION_NAME,
|
||||||
autoIncrement: field.EXTRA.includes('auto_increment'),
|
autoIncrement: field.EXTRA.includes('auto_increment'),
|
||||||
onUpdate: field.EXTRA.toLowerCase().includes('on update')
|
onUpdate: field.EXTRA.toLowerCase().includes('on update') ? field.EXTRA.replace('on update', '') : '',
|
||||||
? field.EXTRA.substr(field.EXTRA.indexOf('on update') + 9, field.EXTRA.length).trim()
|
|
||||||
: '',
|
|
||||||
comment: field.COLUMN_COMMENT
|
comment: field.COLUMN_COMMENT
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -1161,26 +1137,6 @@ export class MySQLClient extends AntaresCore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* SHOW VARIABLES LIKE %variable%
|
|
||||||
*
|
|
||||||
* @param {String} variable
|
|
||||||
* @param {'global'|'session'|null} level
|
|
||||||
* @returns {Object} variable
|
|
||||||
* @memberof MySQLClient
|
|
||||||
*/
|
|
||||||
async getVariable (variable, level) {
|
|
||||||
const sql = `SHOW${level ? ' ' + level.toUpperCase() : ''} VARIABLES LIKE '%${variable}%'`;
|
|
||||||
const results = await this.raw(sql);
|
|
||||||
|
|
||||||
if (results.rows.length) {
|
|
||||||
return {
|
|
||||||
name: results.rows[0].Variable_name,
|
|
||||||
value: results.rows[0].Value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SHOW ENGINES
|
* SHOW ENGINES
|
||||||
*
|
*
|
||||||
@@ -1252,26 +1208,10 @@ export class MySQLClient extends AntaresCore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {number} id
|
|
||||||
* @returns {Promise<null>}
|
|
||||||
*/
|
|
||||||
async killProcess (id) {
|
async killProcess (id) {
|
||||||
return await this.raw(`KILL ${id}`);
|
return await this.raw(`KILL ${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {string} tabUid
|
|
||||||
* @returns {Promise<null>}
|
|
||||||
*/
|
|
||||||
async killTabQuery (tabUid) {
|
|
||||||
const id = this._runningConnections.get(tabUid);
|
|
||||||
if (id)
|
|
||||||
return await this.killProcess(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CREATE TABLE
|
* CREATE TABLE
|
||||||
*
|
*
|
||||||
@@ -1298,7 +1238,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
const length = typeInfo.length ? field.enumValues || field.numLength || field.charLength || field.datePrecision : false;
|
const length = typeInfo.length ? field.enumValues || field.numLength || field.charLength || field.datePrecision : false;
|
||||||
|
|
||||||
newColumns.push(`\`${field.name}\`
|
newColumns.push(`\`${field.name}\`
|
||||||
${field.type.toUpperCase()}${length ? `(${length}${field.numScale ? `,${field.numScale}` : ''})` : ''}
|
${field.type.toUpperCase()}${length ? `(${length})` : ''}
|
||||||
${field.unsigned ? 'UNSIGNED' : ''}
|
${field.unsigned ? 'UNSIGNED' : ''}
|
||||||
${field.zerofill ? 'ZEROFILL' : ''}
|
${field.zerofill ? 'ZEROFILL' : ''}
|
||||||
${field.nullable ? 'NULL' : 'NOT NULL'}
|
${field.nullable ? 'NULL' : 'NOT NULL'}
|
||||||
@@ -1367,7 +1307,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
const length = typeInfo.length ? addition.enumValues || addition.numLength || addition.charLength || addition.datePrecision : false;
|
const length = typeInfo.length ? addition.enumValues || addition.numLength || addition.charLength || addition.datePrecision : false;
|
||||||
|
|
||||||
alterColumns.push(`ADD COLUMN \`${addition.name}\`
|
alterColumns.push(`ADD COLUMN \`${addition.name}\`
|
||||||
${addition.type.toUpperCase()}${length ? `(${length}${addition.numScale ? `,${addition.numScale}` : ''})` : ''}
|
${addition.type.toUpperCase()}${length ? `(${length})` : ''}
|
||||||
${addition.unsigned ? 'UNSIGNED' : ''}
|
${addition.unsigned ? 'UNSIGNED' : ''}
|
||||||
${addition.zerofill ? 'ZEROFILL' : ''}
|
${addition.zerofill ? 'ZEROFILL' : ''}
|
||||||
${addition.nullable ? 'NULL' : 'NOT NULL'}
|
${addition.nullable ? 'NULL' : 'NOT NULL'}
|
||||||
@@ -1405,7 +1345,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
const length = typeInfo.length ? change.enumValues || change.numLength || change.charLength || change.datePrecision : false;
|
const length = typeInfo.length ? change.enumValues || change.numLength || change.charLength || change.datePrecision : false;
|
||||||
|
|
||||||
alterColumns.push(`CHANGE COLUMN \`${change.orgName}\` \`${change.name}\`
|
alterColumns.push(`CHANGE COLUMN \`${change.orgName}\` \`${change.name}\`
|
||||||
${change.type.toUpperCase()}${length ? `(${length}${change.numScale ? `,${change.numScale}` : ''})` : ''}
|
${change.type.toUpperCase()}${length ? `(${length})` : ''}
|
||||||
${change.unsigned ? 'UNSIGNED' : ''}
|
${change.unsigned ? 'UNSIGNED' : ''}
|
||||||
${change.zerofill ? 'ZEROFILL' : ''}
|
${change.zerofill ? 'ZEROFILL' : ''}
|
||||||
${change.nullable ? 'NULL' : 'NOT NULL'}
|
${change.nullable ? 'NULL' : 'NOT NULL'}
|
||||||
@@ -1593,9 +1533,6 @@ export class MySQLClient extends AntaresCore {
|
|||||||
const isPool = typeof this._connection.getConnection === 'function';
|
const isPool = typeof this._connection.getConnection === 'function';
|
||||||
const connection = isPool ? await this._connection.getConnection() : this._connection;
|
const connection = isPool ? await this._connection.getConnection() : this._connection;
|
||||||
|
|
||||||
if (args.tabUid && isPool)
|
|
||||||
this._runningConnections.set(args.tabUid, connection.connection.connectionId);
|
|
||||||
|
|
||||||
if (args.schema)
|
if (args.schema)
|
||||||
await connection.query(`USE \`${args.schema}\``);
|
await connection.query(`USE \`${args.schema}\``);
|
||||||
|
|
||||||
@@ -1656,10 +1593,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
if (isPool) {
|
if (isPool) connection.release();
|
||||||
connection.release();
|
|
||||||
this._runningConnections.delete(args.tabUid);
|
|
||||||
}
|
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1668,10 +1602,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
keysArr = keysArr ? [...keysArr, ...response] : response;
|
keysArr = keysArr ? [...keysArr, ...response] : response;
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
if (isPool) {
|
if (isPool) connection.release();
|
||||||
connection.release();
|
|
||||||
this._runningConnections.delete(args.tabUid);
|
|
||||||
}
|
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1686,10 +1617,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
keys: keysArr
|
keys: keysArr
|
||||||
});
|
});
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
if (isPool) {
|
if (isPool) connection.release();
|
||||||
connection.release();
|
|
||||||
this._runningConnections.delete(args.tabUid);
|
|
||||||
}
|
|
||||||
reject(err);
|
reject(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1697,10 +1625,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
resultsArr.push({ rows, report, fields, keys, duration });
|
resultsArr.push({ rows, report, fields, keys, duration });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPool) {
|
if (isPool) connection.release();
|
||||||
connection.release();
|
|
||||||
this._runningConnections.delete(args.tabUid);
|
|
||||||
}
|
|
||||||
|
|
||||||
return resultsArr.length === 1 ? resultsArr[0] : resultsArr;
|
return resultsArr.length === 1 ? resultsArr[0] : resultsArr;
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,6 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
super(args);
|
super(args);
|
||||||
|
|
||||||
this._schema = null;
|
this._schema = null;
|
||||||
this._runningConnections = new Map();
|
|
||||||
|
|
||||||
this.types = {};
|
this.types = {};
|
||||||
for (const key in types.builtins)
|
for (const key in types.builtins)
|
||||||
@@ -131,23 +130,15 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes an 'SET search_path TO "${schema}"' query
|
* Executes an "USE" query
|
||||||
*
|
*
|
||||||
* @param {String} schema
|
* @param {String} schema
|
||||||
* @param {Object?} connection optional
|
|
||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
use (schema, connection) {
|
use (schema) {
|
||||||
this._schema = schema;
|
this._schema = schema;
|
||||||
|
if (schema)
|
||||||
if (schema) {
|
return this.raw(`SET search_path TO "${schema}"`);
|
||||||
const sql = `SET search_path TO "${schema}"`;
|
|
||||||
|
|
||||||
if (connection === undefined)
|
|
||||||
return this.raw(sql);
|
|
||||||
else
|
|
||||||
return connection.query(sql);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -326,7 +317,6 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
isArray,
|
isArray,
|
||||||
schema: field.table_schema,
|
schema: field.table_schema,
|
||||||
table: field.table_name,
|
table: field.table_name,
|
||||||
numScale: field.numeric_scale,
|
|
||||||
numPrecision: field.numeric_precision,
|
numPrecision: field.numeric_precision,
|
||||||
datePrecision: field.datetime_precision,
|
datePrecision: field.datetime_precision,
|
||||||
charLength: field.character_maximum_length,
|
charLength: field.character_maximum_length,
|
||||||
@@ -1098,26 +1088,10 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {number} id
|
|
||||||
* @returns {Promise<null>}
|
|
||||||
*/
|
|
||||||
async killProcess (id) {
|
async killProcess (id) {
|
||||||
return await this.raw(`SELECT pg_terminate_backend(${id})`);
|
return await this.raw(`SELECT pg_terminate_backend(${id})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {string} tabUid
|
|
||||||
* @returns {Promise<null>}
|
|
||||||
*/
|
|
||||||
async killTabQuery (tabUid) {
|
|
||||||
const id = this._runningConnections.get(tabUid);
|
|
||||||
if (id)
|
|
||||||
return await this.raw(`SELECT pg_cancel_backend(${id})`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CREATE TABLE
|
* CREATE TABLE
|
||||||
*
|
*
|
||||||
@@ -1145,7 +1119,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
const length = typeInfo.length ? field.enumValues || field.numLength || field.charLength || field.datePrecision : false;
|
const length = typeInfo.length ? field.enumValues || field.numLength || field.charLength || field.datePrecision : false;
|
||||||
|
|
||||||
newColumns.push(`"${field.name}"
|
newColumns.push(`"${field.name}"
|
||||||
${field.type.toUpperCase()}${length ? `(${length}${field.numScale !== null ? `,${field.numScale}` : ''})` : ''}
|
${field.type.toUpperCase()}${length ? `(${length})` : ''}
|
||||||
${field.unsigned ? 'UNSIGNED' : ''}
|
${field.unsigned ? 'UNSIGNED' : ''}
|
||||||
${field.zerofill ? 'ZEROFILL' : ''}
|
${field.zerofill ? 'ZEROFILL' : ''}
|
||||||
${field.nullable ? 'NULL' : 'NOT NULL'}
|
${field.nullable ? 'NULL' : 'NOT NULL'}
|
||||||
@@ -1209,7 +1183,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
const length = typeInfo.length ? addition.numLength || addition.charLength || addition.datePrecision : false;
|
const length = typeInfo.length ? addition.numLength || addition.charLength || addition.datePrecision : false;
|
||||||
|
|
||||||
alterColumns.push(`ADD COLUMN "${addition.name}"
|
alterColumns.push(`ADD COLUMN "${addition.name}"
|
||||||
${addition.type.toUpperCase()}${length ? `(${length}${addition.numScale !== null ? `,${addition.numScale}` : ''})` : ''}${addition.isArray ? '[]' : ''}
|
${addition.type.toUpperCase()}${length ? `(${length})` : ''}${addition.isArray ? '[]' : ''}
|
||||||
${addition.unsigned ? 'UNSIGNED' : ''}
|
${addition.unsigned ? 'UNSIGNED' : ''}
|
||||||
${addition.zerofill ? 'ZEROFILL' : ''}
|
${addition.zerofill ? 'ZEROFILL' : ''}
|
||||||
${addition.nullable ? 'NULL' : 'NOT NULL'}
|
${addition.nullable ? 'NULL' : 'NOT NULL'}
|
||||||
@@ -1255,7 +1229,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
localType = change.type.toLowerCase();
|
localType = change.type.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
alterColumns.push(`ALTER COLUMN "${change.name}" TYPE ${localType}${length ? `(${length}${change.numScale ? `,${change.numScale}` : ''})` : ''}${change.isArray ? '[]' : ''} USING "${change.name}"::${localType}`);
|
alterColumns.push(`ALTER COLUMN "${change.name}" TYPE ${localType}${length ? `(${length})` : ''}${change.isArray ? '[]' : ''} USING "${change.name}"::${localType}`);
|
||||||
alterColumns.push(`ALTER COLUMN "${change.name}" ${change.nullable ? 'DROP NOT NULL' : 'SET NOT NULL'}`);
|
alterColumns.push(`ALTER COLUMN "${change.name}" ${change.nullable ? 'DROP NOT NULL' : 'SET NOT NULL'}`);
|
||||||
alterColumns.push(`ALTER COLUMN "${change.name}" ${change.default ? `SET DEFAULT ${change.default}` : 'DROP DEFAULT'}`);
|
alterColumns.push(`ALTER COLUMN "${change.name}" ${change.default ? `SET DEFAULT ${change.default}` : 'DROP DEFAULT'}`);
|
||||||
|
|
||||||
@@ -1422,8 +1396,6 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
async raw (sql, args) {
|
async raw (sql, args) {
|
||||||
if (process.env.NODE_ENV === 'development') this._logger(sql);// TODO: replace BLOB content with a placeholder
|
|
||||||
|
|
||||||
args = {
|
args = {
|
||||||
nest: false,
|
nest: false,
|
||||||
details: false,
|
details: false,
|
||||||
@@ -1432,6 +1404,9 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
...args
|
...args
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (args.schema && args.schema !== 'public')
|
||||||
|
await this.use(args.schema);
|
||||||
|
|
||||||
if (!args.comments)
|
if (!args.comments)
|
||||||
sql = sql.replace(/(\/\*(.|[\r\n])*?\*\/)|(--(.*|[\r\n]))/gm, '');// Remove comments
|
sql = sql.replace(/(\/\*(.|[\r\n])*?\*\/)|(--(.*|[\r\n]))/gm, '');// Remove comments
|
||||||
|
|
||||||
@@ -1443,14 +1418,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
.map(q => q.trim())
|
.map(q => q.trim())
|
||||||
: [sql];
|
: [sql];
|
||||||
|
|
||||||
const isPool = this._connection instanceof Pool;
|
if (process.env.NODE_ENV === 'development') this._logger(sql);// TODO: replace BLOB content with a placeholder
|
||||||
const connection = isPool ? await this._connection.connect() : this._connection;
|
|
||||||
|
|
||||||
if (args.tabUid && isPool)
|
|
||||||
this._runningConnections.set(args.tabUid, connection.processID);
|
|
||||||
|
|
||||||
if (args.schema && args.schema !== 'public')
|
|
||||||
await this.use(args.schema, connection);
|
|
||||||
|
|
||||||
for (const query of queries) {
|
for (const query of queries) {
|
||||||
if (!query) continue;
|
if (!query) continue;
|
||||||
@@ -1460,12 +1428,15 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
let keysArr = [];
|
let keysArr = [];
|
||||||
|
|
||||||
const { rows, report, fields, keys, duration } = await new Promise((resolve, reject) => {
|
const { rows, report, fields, keys, duration } = await new Promise((resolve, reject) => {
|
||||||
(async () => {
|
this._connection.query({
|
||||||
try {
|
rowMode: args.nest ? 'array' : null,
|
||||||
const res = await connection.query({ rowMode: args.nest ? 'array' : null, text: query });
|
text: query
|
||||||
|
}, async (err, res) => {
|
||||||
timeStop = new Date();
|
timeStop = new Date();
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
reject(err);
|
||||||
|
else {
|
||||||
let ast;
|
let ast;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1554,10 +1525,6 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
if (isPool) {
|
|
||||||
connection.release();
|
|
||||||
this._runningConnections.delete(args.tabUid);
|
|
||||||
}
|
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1566,10 +1533,6 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
keysArr = keysArr ? [...keysArr, ...response] : response;
|
keysArr = keysArr ? [...keysArr, ...response] : response;
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
if (isPool) {
|
|
||||||
connection.release();
|
|
||||||
this._runningConnections.delete(args.tabUid);
|
|
||||||
}
|
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1584,24 +1547,12 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
keys: keysArr
|
keys: keysArr
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (err) {
|
});
|
||||||
if (isPool) {
|
|
||||||
connection.release();
|
|
||||||
this._runningConnections.delete(args.tabUid);
|
|
||||||
}
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
resultsArr.push({ rows, report, fields, keys, duration });
|
resultsArr.push({ rows, report, fields, keys, duration });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPool) {
|
|
||||||
connection.release();
|
|
||||||
this._runningConnections.delete(args.tabUid);
|
|
||||||
}
|
|
||||||
|
|
||||||
return resultsArr.length === 1 ? resultsArr[0] : resultsArr;
|
return resultsArr.length === 1 ? resultsArr[0] : resultsArr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import sqlite from 'better-sqlite3';
|
import sqlite from 'better-sqlite3';
|
||||||
import { AntaresCore } from '../AntaresCore';
|
import { AntaresCore } from '../AntaresCore';
|
||||||
import dataTypes from 'common/data-types/sqlite';
|
import dataTypes from 'common/data-types/mysql';
|
||||||
import { NUMBER, FLOAT, TIME, DATETIME } from 'common/fieldTypes';
|
import { NUMBER, FLOAT, TIME, DATETIME } from 'common/fieldTypes';
|
||||||
|
|
||||||
export class SQLiteClient extends AntaresCore {
|
export class SQLiteClient extends AntaresCore {
|
||||||
@@ -732,7 +732,7 @@ export class SQLiteClient extends AntaresCore {
|
|||||||
|
|
||||||
if ([...TIME, ...DATETIME].includes(parsedType)) {
|
if ([...TIME, ...DATETIME].includes(parsedType)) {
|
||||||
const firstNotNull = queryResult.find(res => res[field.name] !== null);
|
const firstNotNull = queryResult.find(res => res[field.name] !== null);
|
||||||
if (firstNotNull && firstNotNull[field.name].includes('.'))
|
if (firstNotNull[field.name].includes('.'))
|
||||||
length = firstNotNull[field.name].split('.').pop().length;
|
length = firstNotNull[field.name].split('.').pop().length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,6 @@
|
|||||||
import { app, BrowserWindow, /* session, */ nativeImage, Menu } from 'electron';
|
import { app, BrowserWindow, /* session, */ nativeImage, Menu } from 'electron';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import Store from 'electron-store';
|
import Store from 'electron-store';
|
||||||
import * as windowStateKeeper from 'electron-window-state';
|
|
||||||
import * as remoteMain from '@electron/remote/main';
|
import * as remoteMain from '@electron/remote/main';
|
||||||
|
|
||||||
import ipcHandlers from './ipc-handlers';
|
import ipcHandlers from './ipc-handlers';
|
||||||
@@ -13,27 +12,22 @@ Store.initRenderer();
|
|||||||
|
|
||||||
const isDevelopment = process.env.NODE_ENV !== 'production';
|
const isDevelopment = process.env.NODE_ENV !== 'production';
|
||||||
const isMacOS = process.platform === 'darwin';
|
const isMacOS = process.platform === 'darwin';
|
||||||
const isWindows = process.platform === 'win32';
|
|
||||||
const gotTheLock = app.requestSingleInstanceLock();
|
const gotTheLock = app.requestSingleInstanceLock();
|
||||||
|
|
||||||
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true';
|
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true';
|
||||||
|
|
||||||
// global reference to mainWindow (necessary to prevent window from being garbage collected)
|
// global reference to mainWindow (necessary to prevent window from being garbage collected)
|
||||||
let mainWindow;
|
let mainWindow;
|
||||||
let mainWindowState;
|
|
||||||
|
|
||||||
async function createMainWindow () {
|
async function createMainWindow () {
|
||||||
const icon = require('../renderer/images/logo-32.png');
|
const icon = require('../renderer/images/logo-32.png');
|
||||||
const window = new BrowserWindow({
|
const window = new BrowserWindow({
|
||||||
width: mainWindowState.width,
|
width: 1024,
|
||||||
height: mainWindowState.height,
|
height: 800,
|
||||||
x: mainWindowState.x,
|
|
||||||
y: mainWindowState.y,
|
|
||||||
minWidth: 900,
|
minWidth: 900,
|
||||||
minHeight: 550,
|
minHeight: 550,
|
||||||
title: 'Antares SQL',
|
title: 'Antares SQL',
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
show: !isWindows, // Temporary workaround to https://github.com/electron/electron/issues/30024
|
|
||||||
icon: nativeImage.createFromDataURL(icon.default),
|
icon: nativeImage.createFromDataURL(icon.default),
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
@@ -47,9 +41,6 @@ async function createMainWindow () {
|
|||||||
backgroundColor: '#1d1d1d'
|
backgroundColor: '#1d1d1d'
|
||||||
});
|
});
|
||||||
|
|
||||||
mainWindowState.manage(window);
|
|
||||||
window.on('moved', saveWindowState);
|
|
||||||
|
|
||||||
remoteMain.enable(window.webContents);
|
remoteMain.enable(window.webContents);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -79,10 +70,16 @@ async function createMainWindow () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
window.on('closed', () => {
|
window.on('closed', () => {
|
||||||
window.removeListener('moved', saveWindowState);
|
|
||||||
mainWindow = null;
|
mainWindow = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window.webContents.on('devtools-opened', () => {
|
||||||
|
window.focus();
|
||||||
|
setImmediate(() => {
|
||||||
|
window.focus();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,17 +104,9 @@ else {
|
|||||||
|
|
||||||
// create main BrowserWindow when electron is ready
|
// create main BrowserWindow when electron is ready
|
||||||
app.on('ready', async () => {
|
app.on('ready', async () => {
|
||||||
mainWindowState = windowStateKeeper({
|
|
||||||
defaultWidth: 1024,
|
|
||||||
defaultHeight: 800
|
|
||||||
});
|
|
||||||
|
|
||||||
mainWindow = await createMainWindow();
|
mainWindow = await createMainWindow();
|
||||||
createAppMenu();
|
createAppMenu();
|
||||||
|
|
||||||
if (isWindows) // Temporary workaround to https://github.com/electron/electron/issues/30024
|
|
||||||
mainWindow.show();
|
|
||||||
|
|
||||||
// if (isDevelopment)
|
// if (isDevelopment)
|
||||||
// mainWindow.webContents.openDevTools();
|
// mainWindow.webContents.openDevTools();
|
||||||
|
|
||||||
@@ -171,7 +160,3 @@ function createAppMenu () {
|
|||||||
|
|
||||||
Menu.setApplicationMenu(menu);
|
Menu.setApplicationMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveWindowState () {
|
|
||||||
mainWindowState.saveState(mainWindow);
|
|
||||||
}
|
|
||||||
|
@@ -1,108 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="map" class="map" />
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import L from 'leaflet';
|
|
||||||
import {
|
|
||||||
point,
|
|
||||||
lineString,
|
|
||||||
polygon
|
|
||||||
} from '@turf/helpers';
|
|
||||||
import { getArrayDepth } from 'common/libs/getArrayDepth';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'BaseMap',
|
|
||||||
props: {
|
|
||||||
points: [Object, Array],
|
|
||||||
isMultiSpatial: Boolean
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
map: null,
|
|
||||||
markers: [],
|
|
||||||
center: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
if (this.isMultiSpatial) {
|
|
||||||
for (const element of this.points)
|
|
||||||
this.markers.push(this.getMarkers(element));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.markers = this.getMarkers(this.points);
|
|
||||||
|
|
||||||
if (!Array.isArray(this.points))
|
|
||||||
this.center = [this.points.y, this.points.x];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.map = L.map('map', {
|
|
||||||
center: this.center || [0, 0],
|
|
||||||
zoom: 15,
|
|
||||||
minZoom: 1,
|
|
||||||
attributionControl: false
|
|
||||||
});
|
|
||||||
|
|
||||||
L.control.attribution({ prefix: '<b>Leaflet</b>' }).addTo(this.map);
|
|
||||||
|
|
||||||
const geoJsonObj = L.geoJSON(this.markers, {
|
|
||||||
style: function () {
|
|
||||||
return {
|
|
||||||
weight: 2,
|
|
||||||
fillColor: '#ff7800',
|
|
||||||
color: '#ff7800',
|
|
||||||
opacity: 0.8,
|
|
||||||
fillOpacity: 0.4
|
|
||||||
};
|
|
||||||
},
|
|
||||||
pointToLayer: function (feature, latlng) {
|
|
||||||
return L.circleMarker(latlng, {
|
|
||||||
radius: 7,
|
|
||||||
weight: 2,
|
|
||||||
fillColor: '#ff7800',
|
|
||||||
color: '#ff7800',
|
|
||||||
opacity: 0.8,
|
|
||||||
fillOpacity: 0.4
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).addTo(this.map);
|
|
||||||
|
|
||||||
const southWest = L.latLng(-90, -180);
|
|
||||||
const northEast = L.latLng(90, 180);
|
|
||||||
const bounds = L.latLngBounds(southWest, northEast);
|
|
||||||
this.map.setMaxBounds(bounds);
|
|
||||||
|
|
||||||
if (!this.center) this.map.fitBounds(geoJsonObj.getBounds());
|
|
||||||
|
|
||||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
||||||
attribution: '© <b>OpenStreetMap</b>'
|
|
||||||
}).addTo(this.map);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getMarkers (points) {
|
|
||||||
if (Array.isArray(points)) {
|
|
||||||
if (getArrayDepth(points) === 1)
|
|
||||||
return lineString(points.reduce((acc, curr) => [...acc, [curr.x, curr.y]], []));
|
|
||||||
else
|
|
||||||
return polygon(points.map(arr => arr.reduce((acc, curr) => [...acc, [curr.x, curr.y]], [])));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return point([points.x, points.y]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.map{
|
|
||||||
height: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.marker-icon{
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
background: $primary-color;
|
|
||||||
border-radius: 50%;
|
|
||||||
box-shadow: 0 0 5px 1px darken($body-font-color-dark, 40%);
|
|
||||||
}
|
|
||||||
</style>
|
|
@@ -6,13 +6,13 @@
|
|||||||
@confirm="runRoutine"
|
@confirm="runRoutine"
|
||||||
@hide="closeModal"
|
@hide="closeModal"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template slot="header">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-play mr-1" />
|
<i class="mdi mdi-24px mdi-play mr-1" />
|
||||||
<span class="cut-text">{{ $t('word.parameters') }}: {{ localRoutine.name }}</span>
|
<span class="cut-text">{{ $t('word.parameters') }}: {{ localRoutine.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div slot="body">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<form class="form-horizontal">
|
<form class="form-horizontal">
|
||||||
<div
|
<div
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@@ -5,16 +5,16 @@
|
|||||||
@confirm="$emit('confirm')"
|
@confirm="$emit('confirm')"
|
||||||
@hide="$emit('close')"
|
@hide="$emit('close')"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template slot="header">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-content-save-alert mr-1" /> {{ $t('message.unsavedChanges') }}
|
<i class="mdi mdi-24px mdi-content-save-alert mr-1" /> {{ $t('message.unsavedChanges') }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div slot="body">
|
||||||
<div>
|
<div>
|
||||||
{{ $t('message.discardUnsavedChanges') }}
|
{{ $t('message.discardUnsavedChanges') }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@@ -41,7 +41,7 @@
|
|||||||
<label class="form-checkbox ml-3" :title="$t('word.insert')">
|
<label class="form-checkbox ml-3" :title="$t('word.insert')">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
:checked="!fieldsToExclude.includes(field.name)"
|
:checked="!field.autoIncrement"
|
||||||
@change.prevent="toggleFields($event, field)"
|
@change.prevent="toggleFields($event, field)"
|
||||||
><i class="form-icon" />
|
><i class="form-icon" />
|
||||||
</label>
|
</label>
|
||||||
@@ -264,7 +264,7 @@ export default {
|
|||||||
else if (BIT.includes(field.type))
|
else if (BIT.includes(field.type))
|
||||||
fieldDefault = field.default.replaceAll('\'', '').replaceAll('b', '');
|
fieldDefault = field.default.replaceAll('\'', '').replaceAll('b', '');
|
||||||
else if (DATETIME.includes(field.type)) {
|
else if (DATETIME.includes(field.type)) {
|
||||||
if (field.default && ['current_timestamp', 'now()'].some(term => field.default.toLowerCase().includes(term))) {
|
if (field.default && ['current_timestamp', 'now()'].includes(field.default.toLowerCase())) {
|
||||||
let datePrecision = '';
|
let datePrecision = '';
|
||||||
for (let i = 0; i < field.datePrecision; i++)
|
for (let i = 0; i < field.datePrecision; i++)
|
||||||
datePrecision += i === 0 ? '.S' : 'S';
|
datePrecision += i === 0 ? '.S' : 'S';
|
||||||
@@ -281,7 +281,7 @@ export default {
|
|||||||
|
|
||||||
rowObj[field.name] = { value: fieldDefault };
|
rowObj[field.name] = { value: fieldDefault };
|
||||||
|
|
||||||
if (field.autoIncrement || !!field.onUpdate)// Disable by default auto increment or "on update" fields
|
if (field.autoIncrement)// Disable by default auto increment fields
|
||||||
this.fieldsToExclude = [...this.fieldsToExclude, field.name];
|
this.fieldsToExclude = [...this.fieldsToExclude, field.name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,12 +22,12 @@
|
|||||||
:hide-footer="true"
|
:hide-footer="true"
|
||||||
@hide="hideInfoModal"
|
@hide="hideInfoModal"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template :slot="'header'">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-information-outline mr-1" /> {{ $t('message.processInfo') }}
|
<i class="mdi mdi-24px mdi-information-outline mr-1" /> {{ $t('message.processInfo') }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div :slot="'body'">
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<TextEditor
|
<TextEditor
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@@ -15,16 +15,16 @@
|
|||||||
@confirm="confirmDeleteConnection"
|
@confirm="confirmDeleteConnection"
|
||||||
@hide="hideConfirmModal"
|
@hide="hideConfirmModal"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template :slot="'header'">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-server-remove mr-1" /> {{ $t('message.deleteConnection') }}
|
<i class="mdi mdi-24px mdi-server-remove mr-1" /> {{ $t('message.deleteConnection') }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div :slot="'body'">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
{{ $t('message.deleteCorfirm') }} <b>{{ connectionName }}</b>?
|
{{ $t('message.deleteCorfirm') }} <b>{{ connectionName }}</b>?
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</BaseContextMenu>
|
</BaseContextMenu>
|
||||||
</template>
|
</template>
|
||||||
|
@@ -6,12 +6,12 @@
|
|||||||
:hide-footer="true"
|
:hide-footer="true"
|
||||||
@hide="hideScratchpad"
|
@hide="hideScratchpad"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template :slot="'header'">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-notebook-edit-outline mr-1" /> {{ $t('word.scratchpad') }}
|
<i class="mdi mdi-24px mdi-notebook-edit-outline mr-1" /> {{ $t('word.scratchpad') }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div :slot="'body'">
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<TextEditor
|
<TextEditor
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<small class="text-gray">{{ $t('message.markdownSupported') }}</small>
|
<small class="text-gray">{{ $t('message.markdownSupported') }}</small>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@@ -200,7 +200,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: "";
|
content: '';
|
||||||
height: 0;
|
height: 0;
|
||||||
width: 3px;
|
width: 3px;
|
||||||
transition: height 0.2s;
|
transition: height 0.2s;
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
<li
|
<li
|
||||||
v-for="(tab, i) of draggableTabs"
|
v-for="(tab, i) of draggableTabs"
|
||||||
:key="i"
|
:key="i"
|
||||||
|
:ref="selectedTab === tab.uid ? 'tab-selected' : ''"
|
||||||
class="tab-item tab-draggable"
|
class="tab-item tab-draggable"
|
||||||
draggable="true"
|
draggable="true"
|
||||||
:class="{'active': selectedTab === tab.uid}"
|
:class="{'active': selectedTab === tab.uid}"
|
||||||
@@ -255,59 +256,56 @@
|
|||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<template #header>
|
<li
|
||||||
<li
|
v-if="workspace.customizations.processesList"
|
||||||
v-if="workspace.customizations.processesList"
|
slot="header"
|
||||||
class="tab-item dropdown tools-dropdown"
|
class="tab-item dropdown tools-dropdown"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
class="tab-link workspace-tools-link dropdown-toggle"
|
||||||
|
tabindex="0"
|
||||||
|
:title="$t('word.tools')"
|
||||||
>
|
>
|
||||||
<a
|
<i class="mdi mdi-24px mdi-tools" />
|
||||||
class="tab-link workspace-tools-link dropdown-toggle"
|
</a>
|
||||||
tabindex="0"
|
<ul v-if="hasTools" class="menu text-left text-uppercase">
|
||||||
:title="$t('word.tools')"
|
<li class="menu-item">
|
||||||
|
<a class="c-hand p-vcentered" @click="showProcessesModal">
|
||||||
|
<i class="mdi mdi-memory mr-1 tool-icon" />
|
||||||
|
<span>{{ $t('message.processesList') }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
v-if="workspace.customizations.variables"
|
||||||
|
class="menu-item"
|
||||||
|
title="Coming..."
|
||||||
>
|
>
|
||||||
<i class="mdi mdi-24px mdi-tools" />
|
<a class="c-hand p-vcentered disabled">
|
||||||
</a>
|
<i class="mdi mdi-shape mr-1 tool-icon" />
|
||||||
<ul v-if="hasTools" class="menu text-left text-uppercase">
|
<span>{{ $t('word.variables') }}</span>
|
||||||
<li class="menu-item">
|
</a>
|
||||||
<a class="c-hand p-vcentered" @click="showProcessesModal">
|
</li>
|
||||||
<i class="mdi mdi-memory mr-1 tool-icon" />
|
<li
|
||||||
<span>{{ $t('message.processesList') }}</span>
|
v-if="workspace.customizations.usersManagement"
|
||||||
</a>
|
class="menu-item"
|
||||||
</li>
|
title="Coming..."
|
||||||
<li
|
|
||||||
v-if="workspace.customizations.variables"
|
|
||||||
class="menu-item"
|
|
||||||
title="Coming..."
|
|
||||||
>
|
|
||||||
<a class="c-hand p-vcentered disabled">
|
|
||||||
<i class="mdi mdi-shape mr-1 tool-icon" />
|
|
||||||
<span>{{ $t('word.variables') }}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
v-if="workspace.customizations.usersManagement"
|
|
||||||
class="menu-item"
|
|
||||||
title="Coming..."
|
|
||||||
>
|
|
||||||
<a class="c-hand p-vcentered disabled">
|
|
||||||
<i class="mdi mdi-account-group mr-1 tool-icon" />
|
|
||||||
<span>{{ $t('message.manageUsers') }}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</template>
|
|
||||||
<template #footer>
|
|
||||||
<li class="tab-item">
|
|
||||||
<a
|
|
||||||
class="tab-add"
|
|
||||||
:title="$t('message.openNewTab')"
|
|
||||||
@click="addQueryTab"
|
|
||||||
>
|
>
|
||||||
<i class="mdi mdi-24px mdi-plus" />
|
<a class="c-hand p-vcentered disabled">
|
||||||
</a>
|
<i class="mdi mdi-account-group mr-1 tool-icon" />
|
||||||
</li>
|
<span>{{ $t('message.manageUsers') }}</span>
|
||||||
</template>
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li slot="footer" class="tab-item">
|
||||||
|
<a
|
||||||
|
class="tab-add"
|
||||||
|
:title="$t('message.openNewTab')"
|
||||||
|
@click="addQueryTab"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-24px mdi-plus" />
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</Draggable>
|
</Draggable>
|
||||||
<WorkspaceEmptyState v-if="!workspace.tabs.length" @new-tab="addQueryTab" />
|
<WorkspaceEmptyState v-if="!workspace.tabs.length" @new-tab="addQueryTab" />
|
||||||
<template v-for="tab of workspace.tabs">
|
<template v-for="tab of workspace.tabs">
|
||||||
@@ -567,7 +565,7 @@ export default {
|
|||||||
return this.workspace ? this.workspace.selectedTab : null;
|
return this.workspace ? this.workspace.selectedTab : null;
|
||||||
},
|
},
|
||||||
queryTabs () {
|
queryTabs () {
|
||||||
return this.workspace ? this.workspace.tabs.filter(tab => tab.type === 'query') : [];
|
return this.workspace.tabs.filter(tab => tab.type === 'query');
|
||||||
},
|
},
|
||||||
schemaChild () {
|
schemaChild () {
|
||||||
for (const key in this.workspace.breadcrumbs) {
|
for (const key in this.workspace.breadcrumbs) {
|
||||||
@@ -583,12 +581,16 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
queryTabs: function (newVal, oldVal) {
|
selectedTab (newVal, oldVal) {
|
||||||
if (newVal.length > oldVal.length) {
|
if (newVal !== oldVal) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const scroller = this.$refs.tabWrap;
|
const element = this.$refs['tab-selected'] ? this.$refs['tab-selected'][0] : null;
|
||||||
if (scroller) scroller.$el.scrollLeft = scroller.$el.scrollWidth;
|
if (element) {
|
||||||
}, 0);
|
element.setAttribute('tabindex', '-1');
|
||||||
|
element.focus();
|
||||||
|
element.removeAttribute('tabindex');
|
||||||
|
}
|
||||||
|
}, 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@@ -42,17 +42,17 @@
|
|||||||
@confirm="deleteMisc"
|
@confirm="deleteMisc"
|
||||||
@hide="hideDeleteModal"
|
@hide="hideDeleteModal"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template slot="header">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-delete mr-1" />
|
<i class="mdi mdi-24px mdi-delete mr-1" />
|
||||||
<span class="cut-text">{{ deleteMessage }}</span>
|
<span class="cut-text">{{ deleteMessage }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div slot="body">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedMisc.name }}</b>"?
|
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedMisc.name }}</b>"?
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
<ModalAskParameters
|
<ModalAskParameters
|
||||||
v-if="isAskingParameters"
|
v-if="isAskingParameters"
|
||||||
|
@@ -452,9 +452,9 @@ export default {
|
|||||||
top: 0;
|
top: 0;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
|
||||||
.schema-size {
|
.schema-size{
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
width: 22.5px;
|
width: 22.5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,8 +502,8 @@ export default {
|
|||||||
&:hover {
|
&:hover {
|
||||||
border-radius: $border-radius;
|
border-radius: $border-radius;
|
||||||
|
|
||||||
.schema-size {
|
.schema-size{
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -78,17 +78,17 @@
|
|||||||
@confirm="deleteSchema"
|
@confirm="deleteSchema"
|
||||||
@hide="hideDeleteModal"
|
@hide="hideDeleteModal"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template slot="header">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-database-remove mr-1" />
|
<i class="mdi mdi-24px mdi-database-remove mr-1" />
|
||||||
<span class="cut-text">{{ $t('message.deleteSchema') }}</span>
|
<span class="cut-text">{{ $t('message.deleteSchema') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div slot="body">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedSchema }}</b>"?
|
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedSchema }}</b>"?
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
<ModalEditSchema
|
<ModalEditSchema
|
||||||
v-if="isEditModal"
|
v-if="isEditModal"
|
||||||
|
@@ -40,33 +40,33 @@
|
|||||||
@confirm="emptyTable"
|
@confirm="emptyTable"
|
||||||
@hide="hideEmptyModal"
|
@hide="hideEmptyModal"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template slot="header">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-table-off mr-1" /> <span class="cut-text">{{ $t('message.emptyTable') }}</span>
|
<i class="mdi mdi-24px mdi-table-off mr-1" /> <span class="cut-text">{{ $t('message.emptyTable') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div slot="body">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
{{ $t('message.emptyCorfirm') }} "<b>{{ selectedTable.name }}</b>"?
|
{{ $t('message.emptyCorfirm') }} "<b>{{ selectedTable.name }}</b>"?
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
v-if="isDeleteModal"
|
v-if="isDeleteModal"
|
||||||
@confirm="deleteTable"
|
@confirm="deleteTable"
|
||||||
@hide="hideDeleteModal"
|
@hide="hideDeleteModal"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template slot="header">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-table-remove mr-1" />
|
<i class="mdi mdi-24px mdi-table-remove mr-1" />
|
||||||
<span class="cut-text">{{ selectedTable.type === 'table' ? $t('message.deleteTable') : $t('message.deleteView') }}</span>
|
<span class="cut-text">{{ selectedTable.type === 'table' ? $t('message.deleteTable') : $t('message.deleteView') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div slot="body">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedTable.name }}</b>"?
|
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedTable.name }}</b>"?
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</BaseContextMenu>
|
</BaseContextMenu>
|
||||||
</template>
|
</template>
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
<div class="workspace-query-buttons">
|
<div class="workspace-query-buttons">
|
||||||
<button
|
<button
|
||||||
class="btn btn-primary btn-sm"
|
class="btn btn-primary btn-sm"
|
||||||
:disabled="!isChanged || !isValid"
|
:disabled="!isChanged"
|
||||||
:class="{'loading':isSaving}"
|
:class="{'loading':isSaving}"
|
||||||
title="CTRL+S"
|
title="CTRL+S"
|
||||||
@click="saveChanges"
|
@click="saveChanges"
|
||||||
@@ -242,9 +242,6 @@ export default {
|
|||||||
JSON.stringify(this.originalKeyUsage) !== JSON.stringify(this.localKeyUsage) ||
|
JSON.stringify(this.originalKeyUsage) !== JSON.stringify(this.localKeyUsage) ||
|
||||||
JSON.stringify(this.originalIndexes) !== JSON.stringify(this.localIndexes) ||
|
JSON.stringify(this.originalIndexes) !== JSON.stringify(this.localIndexes) ||
|
||||||
JSON.stringify(this.tableOptions) !== JSON.stringify(this.localOptions);
|
JSON.stringify(this.tableOptions) !== JSON.stringify(this.localOptions);
|
||||||
},
|
|
||||||
isValid () {
|
|
||||||
return !!this.localFields.length && !!this.localOptions.name.trim().length;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -290,7 +287,7 @@ export default {
|
|||||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs'
|
changeBreadcrumbs: 'workspaces/changeBreadcrumbs'
|
||||||
}),
|
}),
|
||||||
async saveChanges () {
|
async saveChanges () {
|
||||||
if (this.isSaving || !this.isValid) return;
|
if (this.isSaving) return;
|
||||||
this.isSaving = true;
|
this.isSaving = true;
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
|
@@ -6,13 +6,13 @@
|
|||||||
@confirm="confirmParametersChange"
|
@confirm="confirmParametersChange"
|
||||||
@hide="$emit('hide')"
|
@hide="$emit('hide')"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template :slot="'header'">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-dots-horizontal mr-1" />
|
<i class="mdi mdi-24px mdi-dots-horizontal mr-1" />
|
||||||
<span class="cut-text">{{ $t('word.parameters') }} "{{ func }}"</span>
|
<span class="cut-text">{{ $t('word.parameters') }} "{{ func }}"</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div :slot="'body'">
|
||||||
<div class="columns col-gapless">
|
<div class="columns col-gapless">
|
||||||
<div class="column col-5">
|
<div class="column col-5">
|
||||||
<div class="panel" :style="{ height: modalInnerHeight + 'px'}">
|
<div class="panel" :style="{ height: modalInnerHeight + 'px'}">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@@ -6,13 +6,13 @@
|
|||||||
@confirm="confirmParametersChange"
|
@confirm="confirmParametersChange"
|
||||||
@hide="$emit('hide')"
|
@hide="$emit('hide')"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template :slot="'header'">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-dots-horizontal mr-1" />
|
<i class="mdi mdi-24px mdi-dots-horizontal mr-1" />
|
||||||
<span class="cut-text">{{ $t('word.parameters') }} "{{ routine }}"</span>
|
<span class="cut-text">{{ $t('word.parameters') }} "{{ routine }}"</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div :slot="'body'">
|
||||||
<div class="columns col-gapless">
|
<div class="columns col-gapless">
|
||||||
<div class="column col-5">
|
<div class="column col-5">
|
||||||
<div class="panel" :style="{ height: modalInnerHeight + 'px'}">
|
<div class="panel" :style="{ height: modalInnerHeight + 'px'}">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@@ -5,13 +5,13 @@
|
|||||||
@confirm="confirmOptionsChange"
|
@confirm="confirmOptionsChange"
|
||||||
@hide="$emit('hide')"
|
@hide="$emit('hide')"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template :slot="'header'">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-timer mr-1" />
|
<i class="mdi mdi-24px mdi-timer mr-1" />
|
||||||
<span class="cut-text">{{ $t('word.timing') }} "{{ localOptions.name }}"</span>
|
<span class="cut-text">{{ $t('word.timing') }} "{{ localOptions.name }}"</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div :slot="'body'">
|
||||||
<form class="form-horizontal">
|
<form class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label col-4">
|
<label class="form-label col-4">
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@@ -616,14 +616,6 @@ export default {
|
|||||||
},
|
},
|
||||||
removeField (uid) {
|
removeField (uid) {
|
||||||
this.localFields = this.localFields.filter(field => field._antares_id !== uid);
|
this.localFields = this.localFields.filter(field => field._antares_id !== uid);
|
||||||
this.localKeyUsage = this.localKeyUsage.filter(fk =>// Clear foreign keys
|
|
||||||
this.localFields.some(field => field.name === fk.field)
|
|
||||||
);
|
|
||||||
this.localIndexes = this.localIndexes.filter(index =>// Clear indexes
|
|
||||||
this.localFields.some(field =>
|
|
||||||
index.fields.includes(field.name)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
addNewIndex (payload) {
|
addNewIndex (payload) {
|
||||||
this.localIndexes = [...this.localIndexes, {
|
this.localIndexes = [...this.localIndexes, {
|
||||||
|
@@ -6,13 +6,13 @@
|
|||||||
@confirm="confirmForeignsChange"
|
@confirm="confirmForeignsChange"
|
||||||
@hide="$emit('hide')"
|
@hide="$emit('hide')"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template :slot="'header'">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-key-link mr-1" />
|
<i class="mdi mdi-24px mdi-key-link mr-1" />
|
||||||
<span class="cut-text">{{ $t('word.foreignKeys') }} "{{ table }}"</span>
|
<span class="cut-text">{{ $t('word.foreignKeys') }} "{{ table }}"</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div :slot="'body'">
|
||||||
<div class="columns col-gapless">
|
<div class="columns col-gapless">
|
||||||
<div class="column col-5">
|
<div class="column col-5">
|
||||||
<div class="panel" :style="{ height: modalInnerHeight + 'px'}">
|
<div class="panel" :style="{ height: modalInnerHeight + 'px'}">
|
||||||
@@ -197,7 +197,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -289,7 +289,7 @@ export default {
|
|||||||
addForeign () {
|
addForeign () {
|
||||||
this.foreignProxy = [...this.foreignProxy, {
|
this.foreignProxy = [...this.foreignProxy, {
|
||||||
_antares_id: uidGen(),
|
_antares_id: uidGen(),
|
||||||
constraintName: `FK_${uidGen()}`,
|
constraintName: `FK_${this.foreignProxy.length + 1}`,
|
||||||
refSchema: this.schema,
|
refSchema: this.schema,
|
||||||
table: this.table,
|
table: this.table,
|
||||||
refTable: '',
|
refTable: '',
|
||||||
|
@@ -6,13 +6,13 @@
|
|||||||
@confirm="confirmIndexesChange"
|
@confirm="confirmIndexesChange"
|
||||||
@hide="$emit('hide')"
|
@hide="$emit('hide')"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template :slot="'header'">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-key mdi-rotate-45 mr-1" />
|
<i class="mdi mdi-24px mdi-key mdi-rotate-45 mr-1" />
|
||||||
<span class="cut-text">{{ $t('word.indexes') }} "{{ table }}"</span>
|
<span class="cut-text">{{ $t('word.indexes') }} "{{ table }}"</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div :slot="'body'">
|
||||||
<div class="columns col-gapless">
|
<div class="columns col-gapless">
|
||||||
<div class="column col-5">
|
<div class="column col-5">
|
||||||
<div class="panel" :style="{ height: modalInnerHeight + 'px'}">
|
<div class="panel" :style="{ height: modalInnerHeight + 'px'}">
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@@ -99,9 +99,6 @@
|
|||||||
<span v-if="localRow.enumValues">
|
<span v-if="localRow.enumValues">
|
||||||
{{ localRow.enumValues }}
|
{{ localRow.enumValues }}
|
||||||
</span>
|
</span>
|
||||||
<span v-else-if="localRow.numScale">
|
|
||||||
{{ localLength }}, {{ localRow.numScale }}
|
|
||||||
</span>
|
|
||||||
<span v-else>
|
<span v-else>
|
||||||
{{ localLength }}
|
{{ localLength }}
|
||||||
</span>
|
</span>
|
||||||
@@ -115,16 +112,6 @@
|
|||||||
class="editable-field form-input input-sm px-1"
|
class="editable-field form-input input-sm px-1"
|
||||||
@blur="editOFF"
|
@blur="editOFF"
|
||||||
>
|
>
|
||||||
<input
|
|
||||||
v-else-if="fieldType.scale"
|
|
||||||
ref="editField"
|
|
||||||
v-model="editingContent"
|
|
||||||
type="text"
|
|
||||||
autofocus
|
|
||||||
class="editable-field form-input input-sm px-1"
|
|
||||||
@keypress="checkLengthScale"
|
|
||||||
@blur="editOFF"
|
|
||||||
>
|
|
||||||
<input
|
<input
|
||||||
v-else
|
v-else
|
||||||
ref="editField"
|
ref="editField"
|
||||||
@@ -243,13 +230,13 @@
|
|||||||
@confirm="editOFF"
|
@confirm="editOFF"
|
||||||
@hide="hideDefaultModal"
|
@hide="hideDefaultModal"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template :slot="'header'">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-playlist-edit mr-1" />
|
<i class="mdi mdi-24px mdi-playlist-edit mr-1" />
|
||||||
<span class="cut-text">{{ $t('word.default') }} "{{ row.name }}"</span>
|
<span class="cut-text">{{ $t('word.default') }} "{{ row.name }}"</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div :slot="'body'">
|
||||||
<form class="form-horizontal">
|
<form class="form-horizontal">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<label class="form-radio form-inline">
|
<label class="form-radio form-inline">
|
||||||
@@ -337,7 +324,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -493,11 +480,6 @@ export default {
|
|||||||
this.editingContent = this.localRow.enumValues;
|
this.editingContent = this.localRow.enumValues;
|
||||||
this.originalContent = this.localRow.enumValues;
|
this.originalContent = this.localRow.enumValues;
|
||||||
}
|
}
|
||||||
else if (this.fieldType.scale && field === 'length') {
|
|
||||||
const scale = this.localRow.numScale !== null ? this.localRow.numScale : 0;
|
|
||||||
this.editingContent = `${content}, ${scale}`;
|
|
||||||
this.originalContent = `${content}, ${scale}`;
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
this.editingContent = content;
|
this.editingContent = content;
|
||||||
this.originalContent = content;
|
this.originalContent = content;
|
||||||
@@ -520,17 +502,10 @@ export default {
|
|||||||
if (this.editingField === 'name')
|
if (this.editingField === 'name')
|
||||||
this.$emit('rename-field', { old: this.localRow[this.editingField], new: this.editingContent });
|
this.$emit('rename-field', { old: this.localRow[this.editingField], new: this.editingContent });
|
||||||
|
|
||||||
if (this.editingField === 'numLength' && this.fieldType.scale) {
|
this.localRow[this.editingField] = this.editingContent;
|
||||||
const [length, scale] = this.editingContent.split(',');
|
|
||||||
this.localRow.numLength = +length;
|
|
||||||
this.localRow.numScale = scale ? +scale : null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
this.localRow[this.editingField] = this.editingContent;
|
|
||||||
|
|
||||||
if (this.editingField === 'type' && this.editingContent !== this.originalContent) {
|
if (this.editingField === 'type' && this.editingContent !== this.originalContent) {
|
||||||
this.localRow.numLength = null;
|
this.localRow.numLength = null;
|
||||||
this.localRow.numScale = null;
|
|
||||||
this.localRow.charLength = null;
|
this.localRow.charLength = null;
|
||||||
this.localRow.datePrecision = null;
|
this.localRow.datePrecision = null;
|
||||||
this.localRow.enumValues = '';
|
this.localRow.enumValues = '';
|
||||||
@@ -585,15 +560,6 @@ export default {
|
|||||||
this.originalContent = null;
|
this.originalContent = null;
|
||||||
this.editingField = null;
|
this.editingField = null;
|
||||||
},
|
},
|
||||||
checkLengthScale (e) {
|
|
||||||
e = (e) || window.event;
|
|
||||||
const charCode = (e.which) ? e.which : e.keyCode;
|
|
||||||
|
|
||||||
if (((charCode > 31 && (charCode < 48 || charCode > 57)) && charCode !== 44) || (charCode === 44 && e.target.value.includes(',')))
|
|
||||||
e.preventDefault();
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
hideDefaultModal () {
|
hideDefaultModal () {
|
||||||
this.isDefaultModal = false;
|
this.isDefaultModal = false;
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,6 @@
|
|||||||
class="workspace-query-tab column col-12 columns col-gapless no-outline p-0"
|
class="workspace-query-tab column col-12 columns col-gapless no-outline p-0"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@keydown.116="runQuery(query)"
|
@keydown.116="runQuery(query)"
|
||||||
@keydown.75="killTabQuery"
|
|
||||||
@keydown.ctrl.alt.87="clear"
|
@keydown.ctrl.alt.87="clear"
|
||||||
@keydown.ctrl.66="beautify"
|
@keydown.ctrl.66="beautify"
|
||||||
@keydown.ctrl.71="openHistoryModal"
|
@keydown.ctrl.71="openHistoryModal"
|
||||||
@@ -23,29 +22,16 @@
|
|||||||
<div ref="resizer" class="query-area-resizer" />
|
<div ref="resizer" class="query-area-resizer" />
|
||||||
<div class="workspace-query-runner-footer">
|
<div class="workspace-query-runner-footer">
|
||||||
<div class="workspace-query-buttons">
|
<div class="workspace-query-buttons">
|
||||||
<div @mouseenter="setCancelButtonVisibility(true)" @mouseleave="setCancelButtonVisibility(false)">
|
<button
|
||||||
<button
|
class="btn btn-primary btn-sm"
|
||||||
v-if="showCancel && isQuering"
|
:class="{'loading':isQuering}"
|
||||||
class="btn btn-primary btn-sm cancellable"
|
:disabled="!query"
|
||||||
:disabled="!query"
|
title="F5"
|
||||||
:title="$t('word.cancel')"
|
@click="runQuery(query)"
|
||||||
@click="killTabQuery()"
|
>
|
||||||
>
|
<i class="mdi mdi-24px mdi-play pr-1" />
|
||||||
<i class="mdi mdi-24px mdi-window-close" />
|
<span>{{ $t('word.run') }}</span>
|
||||||
<span class="d-invisible pr-1">{{ $t('word.run') }}</span>
|
</button>
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
v-else
|
|
||||||
class="btn btn-primary btn-sm"
|
|
||||||
:class="{'loading':isQuering}"
|
|
||||||
:disabled="!query"
|
|
||||||
title="F5"
|
|
||||||
@click="runQuery(query)"
|
|
||||||
>
|
|
||||||
<i class="mdi mdi-24px mdi-play pr-1" />
|
|
||||||
<span>{{ $t('word.run') }}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<button
|
<button
|
||||||
class="btn btn-link btn-sm mr-0"
|
class="btn btn-link btn-sm mr-0"
|
||||||
:disabled="!query || isQuering"
|
:disabled="!query || isQuering"
|
||||||
@@ -124,7 +110,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<WorkspaceTabQueryEmptyState v-if="!results.length && !isQuering" :customizations="workspace.customizations" />
|
<WorkspaceTabQueryEmptyState v-if="!results.length && !isQuering" />
|
||||||
<div class="workspace-query-results p-relative column col-12">
|
<div class="workspace-query-results p-relative column col-12">
|
||||||
<BaseLoader v-if="isQuering" />
|
<BaseLoader v-if="isQuering" />
|
||||||
<WorkspaceTabQueryTable
|
<WorkspaceTabQueryTable
|
||||||
@@ -180,8 +166,6 @@ export default {
|
|||||||
query: '',
|
query: '',
|
||||||
lastQuery: '',
|
lastQuery: '',
|
||||||
isQuering: false,
|
isQuering: false,
|
||||||
isCancelling: false,
|
|
||||||
showCancel: false,
|
|
||||||
results: [],
|
results: [],
|
||||||
selectedSchema: null,
|
selectedSchema: null,
|
||||||
resultsCount: 0,
|
resultsCount: 0,
|
||||||
@@ -218,13 +202,8 @@ export default {
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
isSelected (val) {
|
isSelected (val) {
|
||||||
if (val) {
|
if (val)
|
||||||
this.changeBreadcrumbs({ schema: this.selectedSchema, query: `Query #${this.tab.index}` });
|
this.changeBreadcrumbs({ schema: this.selectedSchema, query: `Query #${this.tab.index}` });
|
||||||
setTimeout(() => {
|
|
||||||
if (this.$refs.queryEditor)
|
|
||||||
this.$refs.queryEditor.editor.focus();
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
selectedSchema () {
|
selectedSchema () {
|
||||||
this.changeBreadcrumbs({ schema: this.selectedSchema, query: `Query #${this.tab.index}` });
|
this.changeBreadcrumbs({ schema: this.selectedSchema, query: `Query #${this.tab.index}` });
|
||||||
@@ -269,7 +248,6 @@ export default {
|
|||||||
const params = {
|
const params = {
|
||||||
uid: this.connection.uid,
|
uid: this.connection.uid,
|
||||||
schema: this.selectedSchema,
|
schema: this.selectedSchema,
|
||||||
tabUid: this.tab.uid,
|
|
||||||
query
|
query
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -305,29 +283,6 @@ export default {
|
|||||||
this.isQuering = false;
|
this.isQuering = false;
|
||||||
this.lastQuery = query;
|
this.lastQuery = query;
|
||||||
},
|
},
|
||||||
async killTabQuery () {
|
|
||||||
if (this.isCancelling) return;
|
|
||||||
|
|
||||||
this.isCancelling = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const params = {
|
|
||||||
uid: this.connection.uid,
|
|
||||||
tabUid: this.tab.uid
|
|
||||||
};
|
|
||||||
|
|
||||||
await Schema.killTabQuery(params);
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
this.addNotification({ status: 'error', message: err.stack });
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isCancelling = false;
|
|
||||||
},
|
|
||||||
setCancelButtonVisibility (val) {
|
|
||||||
if (this.workspace.customizations.cancelQueries)
|
|
||||||
this.showCancel = val;
|
|
||||||
},
|
|
||||||
reloadTable () {
|
reloadTable () {
|
||||||
this.runQuery(this.lastQuery);
|
this.runQuery(this.lastQuery);
|
||||||
},
|
},
|
||||||
|
@@ -5,9 +5,6 @@
|
|||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
{{ $t('message.runQuery') }}
|
{{ $t('message.runQuery') }}
|
||||||
</div>
|
</div>
|
||||||
<div v-if="customizations.cancelQueries" class="mb-4">
|
|
||||||
{{ $t('message.killQuery') }}
|
|
||||||
</div>
|
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
{{ $t('word.format') }}
|
{{ $t('word.format') }}
|
||||||
</div>
|
</div>
|
||||||
@@ -28,9 +25,6 @@
|
|||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<code>F5</code>
|
<code>F5</code>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="customizations.cancelQueries" class="mb-4">
|
|
||||||
<code>CTRL</code> + <code>K</code>
|
|
||||||
</div>
|
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<code>CTRL</code> + <code>B</code>
|
<code>CTRL</code> + <code>B</code>
|
||||||
</div>
|
</div>
|
||||||
@@ -53,10 +47,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'WorkspaceTabQueryEmptyState',
|
name: 'WorkspaceTabQueryEmptyState'
|
||||||
props: {
|
|
||||||
customizations: Object
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
tabindex="0"
|
tabindex="0"
|
||||||
:style="{'height': resultsSize+'px'}"
|
:style="{'height': resultsSize+'px'}"
|
||||||
@keyup.46="showDeleteConfirmModal"
|
@keyup.46="showDeleteConfirmModal"
|
||||||
@keydown.ctrl.65="selectAllRows($event)"
|
@keydown.ctrl.65="selectAllRows"
|
||||||
@keydown.esc="deselectRows"
|
@keydown.esc="deselectRows"
|
||||||
>
|
>
|
||||||
<TableContext
|
<TableContext
|
||||||
@@ -53,7 +53,6 @@
|
|||||||
class="mdi sort-icon"
|
class="mdi sort-icon"
|
||||||
:class="currentSortDir === 'asc' ? 'mdi-sort-ascending':'mdi-sort-descending'"
|
:class="currentSortDir === 'asc' ? 'mdi-sort-ascending':'mdi-sort-descending'"
|
||||||
/>
|
/>
|
||||||
<i v-else class="mdi sort-icon mdi-minus d-invisible" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -63,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="rowHeight"
|
:item-height="23"
|
||||||
class="tbody"
|
class="tbody"
|
||||||
:visible-height="resultsSize"
|
:visible-height="resultsSize"
|
||||||
:scroll-element="scrollElement"
|
:scroll-element="scrollElement"
|
||||||
@@ -72,7 +71,6 @@
|
|||||||
<WorkspaceTabQueryTableRow
|
<WorkspaceTabQueryTableRow
|
||||||
v-for="row in items"
|
v-for="row in items"
|
||||||
:key="row._antares_id"
|
:key="row._antares_id"
|
||||||
:item-height="rowHeight"
|
|
||||||
:row="row"
|
:row="row"
|
||||||
:fields="fieldsObj"
|
:fields="fieldsObj"
|
||||||
:key-usage="keyUsage"
|
:key-usage="keyUsage"
|
||||||
@@ -91,17 +89,17 @@
|
|||||||
@confirm="deleteSelected"
|
@confirm="deleteSelected"
|
||||||
@hide="hideDeleteConfirmModal"
|
@hide="hideDeleteConfirmModal"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template :slot="'header'">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-delete mr-1" />
|
<i class="mdi mdi-24px mdi-delete mr-1" />
|
||||||
<span class="cut-text">{{ $tc('message.deleteRows', selectedRows.length) }}</span>
|
<span class="cut-text">{{ $tc('message.deleteRows', selectedRows.length) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div :slot="'body'">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
{{ $tc('message.confirmToDeleteRows', selectedRows.length) }}
|
{{ $tc('message.confirmToDeleteRows', selectedRows.length) }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -144,8 +142,7 @@ export default {
|
|||||||
currentSort: '',
|
currentSort: '',
|
||||||
currentSortDir: 'asc',
|
currentSortDir: 'asc',
|
||||||
resultsetIndex: 0,
|
resultsetIndex: 0,
|
||||||
scrollElement: null,
|
scrollElement: null
|
||||||
rowHeight: 23
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -245,11 +242,6 @@ export default {
|
|||||||
|
|
||||||
if (this.$refs.tableWrapper)
|
if (this.$refs.tableWrapper)
|
||||||
this.scrollElement = this.$refs.tableWrapper;
|
this.scrollElement = this.$refs.tableWrapper;
|
||||||
|
|
||||||
document.querySelectorAll('.column-resizable').forEach(element => {
|
|
||||||
if (element.clientWidth !== 0)
|
|
||||||
element.style.width = element.clientWidth + 'px';
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
window.addEventListener('resize', this.resizeResults);
|
window.addEventListener('resize', this.resizeResults);
|
||||||
@@ -280,7 +272,6 @@ export default {
|
|||||||
fieldLength (field) {
|
fieldLength (field) {
|
||||||
if ([...BLOB, ...LONG_TEXT].includes(field.type)) return null;
|
if ([...BLOB, ...LONG_TEXT].includes(field.type)) return null;
|
||||||
else if (TEXT.includes(field.type)) return field.charLength;
|
else if (TEXT.includes(field.type)) return field.charLength;
|
||||||
else if (field.numScale) return `${field.numPrecision}, ${field.numScale}`;
|
|
||||||
return field.length;
|
return field.length;
|
||||||
},
|
},
|
||||||
keyName (key) {
|
keyName (key) {
|
||||||
@@ -408,13 +399,10 @@ export default {
|
|||||||
const row = this.localResults.find(row => this.selectedRows.includes(row._antares_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.selectedCell.orgField,
|
|
||||||
`${this.fields[0].table}.${this.selectedCell.field}`,
|
`${this.fields[0].table}.${this.selectedCell.field}`,
|
||||||
`${this.fields[0].tableAlias}.${this.selectedCell.field}`
|
`${this.fields[0].tableAlias}.${this.selectedCell.field}`
|
||||||
].includes(prop));
|
].includes(prop));
|
||||||
let valueToCopy = row[cellName];
|
const valueToCopy = row[cellName];
|
||||||
if (typeof valueToCopy === 'object')
|
|
||||||
valueToCopy = JSON.stringify(valueToCopy);
|
|
||||||
navigator.clipboard.writeText(valueToCopy);
|
navigator.clipboard.writeText(valueToCopy);
|
||||||
},
|
},
|
||||||
copyRow () {
|
copyRow () {
|
||||||
@@ -462,9 +450,7 @@ export default {
|
|||||||
else
|
else
|
||||||
this.selectedRows = [row];
|
this.selectedRows = [row];
|
||||||
},
|
},
|
||||||
selectAllRows (e) {
|
selectAllRows () {
|
||||||
if (e.target.classList.contains('editable-field')) return;
|
|
||||||
|
|
||||||
this.selectedRows = this.localResults.reduce((acc, curr) => {
|
this.selectedRows = this.localResults.reduce((acc, curr) => {
|
||||||
acc.push(curr._antares_id);
|
acc.push(curr._antares_id);
|
||||||
return acc;
|
return acc;
|
||||||
|
@@ -61,6 +61,8 @@ export default {
|
|||||||
selectedRows: Array,
|
selectedRows: Array,
|
||||||
selectedCell: Object
|
selectedCell: Object
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
showConfirmModal () {
|
showConfirmModal () {
|
||||||
this.$emit('show-delete-modal');
|
this.$emit('show-delete-modal');
|
||||||
|
@@ -1,16 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div class="tr" @click="selectRow($event, row._antares_id)">
|
||||||
class="tr"
|
|
||||||
:style="{height: itemHeight+'px'}"
|
|
||||||
@click="selectRow($event, row._antares_id)"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
v-for="(col, cKey) in row"
|
v-for="(col, cKey) in row"
|
||||||
v-show="cKey !== '_antares_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._antares_id, orgField: cKey })"
|
@contextmenu.prevent="openContext($event, { id: row._antares_id, field: cKey })"
|
||||||
>
|
>
|
||||||
<template v-if="cKey !== '_antares_id'">
|
<template v-if="cKey !== '_antares_id'">
|
||||||
<span
|
<span
|
||||||
@@ -76,12 +72,12 @@
|
|||||||
@confirm="editOFF"
|
@confirm="editOFF"
|
||||||
@hide="hideEditorModal"
|
@hide="hideEditorModal"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template :slot="'header'">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-playlist-edit mr-1" /> <span class="cut-text">{{ $t('word.edit') }} "{{ editingField }}"</span>
|
<i class="mdi mdi-24px mdi-playlist-edit mr-1" /> <span class="cut-text">{{ $t('word.edit') }} "{{ editingField }}"</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div :slot="'body'">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<div>
|
<div>
|
||||||
<TextEditor
|
<TextEditor
|
||||||
@@ -100,12 +96,23 @@
|
|||||||
v-model="editorMode"
|
v-model="editorMode"
|
||||||
class="form-select select-sm"
|
class="form-select select-sm"
|
||||||
>
|
>
|
||||||
<option
|
<option value="text">
|
||||||
v-for="language in availableLanguages"
|
TEXT
|
||||||
:key="language.slug"
|
</option>
|
||||||
:value="language.slug"
|
<option value="html">
|
||||||
>
|
HTML
|
||||||
{{ language.name }}
|
</option>
|
||||||
|
<option value="xml">
|
||||||
|
XML
|
||||||
|
</option>
|
||||||
|
<option value="json">
|
||||||
|
JSON
|
||||||
|
</option>
|
||||||
|
<option value="svg">
|
||||||
|
SVG
|
||||||
|
</option>
|
||||||
|
<option value="yaml">
|
||||||
|
YAML
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@@ -121,22 +128,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
|
||||||
<ConfirmModal
|
|
||||||
v-if="isMapModal"
|
|
||||||
:hide-footer="true"
|
|
||||||
size="medium"
|
|
||||||
@hide="hideEditorModal"
|
|
||||||
>
|
|
||||||
<template #header>
|
|
||||||
<div class="d-flex">
|
|
||||||
<i class="mdi mdi-24px mdi-map mr-1" /> <span class="cut-text">"{{ editingField }}"</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #body>
|
|
||||||
<BaseMap :points="editingContent" :is-multi-spatial="isMultiSpatial" />
|
|
||||||
</template>
|
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
v-if="isBlobEditor"
|
v-if="isBlobEditor"
|
||||||
@@ -144,13 +136,13 @@
|
|||||||
@confirm="editOFF"
|
@confirm="editOFF"
|
||||||
@hide="hideEditorModal"
|
@hide="hideEditorModal"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template :slot="'header'">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-playlist-edit mr-1" />
|
<i class="mdi mdi-24px mdi-playlist-edit mr-1" />
|
||||||
<span class="cut-text">{{ $t('word.edit') }} "{{ editingField }}"</span>
|
<span class="cut-text">{{ $t('word.edit') }} "{{ editingField }}"</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<div :slot="'body'">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<transition name="jump-down">
|
<transition name="jump-down">
|
||||||
<div v-if="contentInfo.size">
|
<div v-if="contentInfo.size">
|
||||||
@@ -190,39 +182,21 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { ModelOperations } from '@vscode/vscode-languagedetection';
|
|
||||||
import { mimeFromHex } from 'common/libs/mimeFromHex';
|
import { mimeFromHex } from 'common/libs/mimeFromHex';
|
||||||
import { formatBytes } from 'common/libs/formatBytes';
|
import { formatBytes } from 'common/libs/formatBytes';
|
||||||
import { bufferToBase64 } from 'common/libs/bufferToBase64';
|
import { bufferToBase64 } from 'common/libs/bufferToBase64';
|
||||||
import hexToBinary from 'common/libs/hexToBinary';
|
import hexToBinary from 'common/libs/hexToBinary';
|
||||||
import {
|
import { TEXT, LONG_TEXT, ARRAY, TEXT_SEARCH, NUMBER, FLOAT, BOOLEAN, DATE, TIME, DATETIME, BLOB, BIT, HAS_TIMEZONE } from 'common/fieldTypes';
|
||||||
TEXT,
|
|
||||||
LONG_TEXT,
|
|
||||||
ARRAY,
|
|
||||||
TEXT_SEARCH,
|
|
||||||
NUMBER,
|
|
||||||
FLOAT,
|
|
||||||
BOOLEAN,
|
|
||||||
DATE,
|
|
||||||
TIME,
|
|
||||||
DATETIME,
|
|
||||||
BLOB,
|
|
||||||
BIT,
|
|
||||||
HAS_TIMEZONE,
|
|
||||||
SPATIAL,
|
|
||||||
IS_MULTI_SPATIAL
|
|
||||||
} from 'common/fieldTypes';
|
|
||||||
import { VueMaskDirective } from 'v-mask';
|
import { VueMaskDirective } from 'v-mask';
|
||||||
import ConfirmModal from '@/components/BaseConfirmModal';
|
import ConfirmModal from '@/components/BaseConfirmModal';
|
||||||
import TextEditor from '@/components/BaseTextEditor';
|
import TextEditor from '@/components/BaseTextEditor';
|
||||||
import BaseMap from '@/components/BaseMap';
|
|
||||||
import ForeignKeySelect from '@/components/ForeignKeySelect';
|
import ForeignKeySelect from '@/components/ForeignKeySelect';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -230,8 +204,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
ConfirmModal,
|
ConfirmModal,
|
||||||
TextEditor,
|
TextEditor,
|
||||||
ForeignKeySelect,
|
ForeignKeySelect
|
||||||
BaseMap
|
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
mask: VueMaskDirective
|
mask: VueMaskDirective
|
||||||
@@ -281,17 +254,13 @@ export default {
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SPATIAL.includes(type))
|
return val;
|
||||||
return val;
|
|
||||||
|
|
||||||
return typeof val === 'object' ? JSON.stringify(val) : val;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
row: Object,
|
row: Object,
|
||||||
fields: Object,
|
fields: Object,
|
||||||
keyUsage: Array,
|
keyUsage: Array,
|
||||||
itemHeight: Number,
|
|
||||||
elementType: { type: String, default: 'table' }
|
elementType: { type: String, default: 'table' }
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
@@ -299,8 +268,6 @@ export default {
|
|||||||
isInlineEditor: {},
|
isInlineEditor: {},
|
||||||
isTextareaEditor: false,
|
isTextareaEditor: false,
|
||||||
isBlobEditor: false,
|
isBlobEditor: false,
|
||||||
isMapModal: false,
|
|
||||||
isMultiSpatial: false,
|
|
||||||
willBeDeleted: false,
|
willBeDeleted: false,
|
||||||
originalContent: null,
|
originalContent: null,
|
||||||
editingContent: null,
|
editingContent: null,
|
||||||
@@ -313,17 +280,7 @@ export default {
|
|||||||
mime: '',
|
mime: '',
|
||||||
size: null
|
size: null
|
||||||
},
|
},
|
||||||
fileToUpload: null,
|
fileToUpload: null
|
||||||
availableLanguages: [
|
|
||||||
{ name: 'TEXT', slug: 'text', id: 'text' },
|
|
||||||
{ name: 'HTML', slug: 'html', id: 'html' },
|
|
||||||
{ name: 'XML', slug: 'xml', id: 'xml' },
|
|
||||||
{ name: 'JSON', slug: 'json', id: 'json' },
|
|
||||||
{ name: 'SVG', slug: 'svg', id: 'svg' },
|
|
||||||
{ name: 'INI', slug: 'ini', id: 'ini' },
|
|
||||||
{ name: 'MARKDOWN', slug: 'markdown', id: 'md' },
|
|
||||||
{ name: 'YAML', slug: 'yaml', id: 'yaml' }
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -369,9 +326,6 @@ export default {
|
|||||||
if (BOOLEAN.includes(this.editingType))
|
if (BOOLEAN.includes(this.editingType))
|
||||||
return { type: 'boolean', mask: false };
|
return { type: 'boolean', mask: false };
|
||||||
|
|
||||||
if (SPATIAL.includes(this.editingType))
|
|
||||||
return { type: 'map', mask: false };
|
|
||||||
|
|
||||||
return { type: 'text', mask: false };
|
return { type: 'text', mask: false };
|
||||||
},
|
},
|
||||||
isImage () {
|
isImage () {
|
||||||
@@ -408,21 +362,6 @@ export default {
|
|||||||
Object.keys(this.fields).forEach(field => {
|
Object.keys(this.fields).forEach(field => {
|
||||||
this.isInlineEditor[field.name] = false;
|
this.isInlineEditor[field.name] = false;
|
||||||
});
|
});
|
||||||
},
|
|
||||||
isTextareaEditor (val) {
|
|
||||||
if (val) {
|
|
||||||
const modelOperations = new ModelOperations();
|
|
||||||
(async () => {
|
|
||||||
const detected = await modelOperations.runModel(this.editingContent);
|
|
||||||
const filteredLanguages = detected.filter(dLang =>
|
|
||||||
this.availableLanguages.some(aLang => aLang.id === dLang.languageId) &&
|
|
||||||
dLang.confidence > 0.1
|
|
||||||
);
|
|
||||||
|
|
||||||
if (filteredLanguages.length)
|
|
||||||
this.editorMode = this.availableLanguages.find(lang => lang.id === filteredLanguages[0].languageId).slug;
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -444,7 +383,7 @@ export default {
|
|||||||
return bufferToBase64(val);
|
return bufferToBase64(val);
|
||||||
},
|
},
|
||||||
editON (event, content, field) {
|
editON (event, content, field) {
|
||||||
if (!this.isEditable || this.editingType === 'none') return;
|
if (!this.isEditable) return;
|
||||||
|
|
||||||
window.addEventListener('keydown', this.onKey);
|
window.addEventListener('keydown', this.onKey);
|
||||||
|
|
||||||
@@ -460,15 +399,6 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SPATIAL.includes(type)) {
|
|
||||||
if (content) {
|
|
||||||
this.isMultiSpatial = IS_MULTI_SPATIAL.includes(type);
|
|
||||||
this.isMapModal = true;
|
|
||||||
this.editingContent = this.$options.filters.typeFormat(content, type);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BLOB.includes(type)) {
|
if (BLOB.includes(type)) {
|
||||||
this.isBlobEditor = true;
|
this.isBlobEditor = true;
|
||||||
this.editingContent = content || '';
|
this.editingContent = content || '';
|
||||||
@@ -540,8 +470,6 @@ export default {
|
|||||||
hideEditorModal () {
|
hideEditorModal () {
|
||||||
this.isTextareaEditor = false;
|
this.isTextareaEditor = false;
|
||||||
this.isBlobEditor = false;
|
this.isBlobEditor = false;
|
||||||
this.isMapModal = false;
|
|
||||||
this.isMultiSpatial = false;
|
|
||||||
},
|
},
|
||||||
downloadFile () {
|
downloadFile () {
|
||||||
const downloadLink = document.createElement('a');
|
const downloadLink = document.createElement('a');
|
||||||
@@ -578,7 +506,7 @@ export default {
|
|||||||
return this.keyUsage.find(key => key.field === keyName);
|
return this.keyUsage.find(key => key.field === keyName);
|
||||||
},
|
},
|
||||||
openContext (event, payload) {
|
openContext (event, payload) {
|
||||||
payload.field = this.fields[payload.orgField].name;// Ensures field name only
|
payload.field = this.fields[payload.field].name;// Ensures field name only
|
||||||
payload.isEditable = this.isEditable;
|
payload.isEditable = this.isEditable;
|
||||||
this.$emit('contextmenu', event, payload);
|
this.$emit('contextmenu', event, payload);
|
||||||
},
|
},
|
||||||
|
@@ -251,8 +251,7 @@ module.exports = {
|
|||||||
killProcess: 'Kill process',
|
killProcess: 'Kill process',
|
||||||
closeTab: 'Close tab',
|
closeTab: 'Close tab',
|
||||||
goToDownloadPage: 'Go to download page',
|
goToDownloadPage: 'Go to download page',
|
||||||
readOnlyMode: 'Read-only mode',
|
readOnlyMode: 'Read-only mode'
|
||||||
killQuery: 'Kill query'
|
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Address',
|
address: 'Address',
|
||||||
|
@@ -13,8 +13,7 @@ const i18n = new VueI18n({
|
|||||||
'pt-BR': require('./pt-BR'),
|
'pt-BR': require('./pt-BR'),
|
||||||
'de-DE': require('./de-DE'),
|
'de-DE': require('./de-DE'),
|
||||||
'vi-VN': require('./vi-VN'),
|
'vi-VN': require('./vi-VN'),
|
||||||
'ja-JP': require('./ja-JP'),
|
'ja-JP': require('./ja-JP')
|
||||||
'zh-CN': require('./zh-CN')
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
export default i18n;
|
export default i18n;
|
||||||
|
@@ -7,6 +7,5 @@ export default {
|
|||||||
'pt-BR': 'Português (Brasil)',
|
'pt-BR': 'Português (Brasil)',
|
||||||
'de-DE': 'Deutsch (Deutschland)',
|
'de-DE': 'Deutsch (Deutschland)',
|
||||||
'vi-VN': 'Tiếng Việt',
|
'vi-VN': 'Tiếng Việt',
|
||||||
'ja-JP': '日本語',
|
'ja-JP': '日本語'
|
||||||
'zh-CN': '简体中文'
|
|
||||||
};
|
};
|
||||||
|
@@ -120,11 +120,7 @@ module.exports = {
|
|||||||
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'
|
||||||
filter: 'Bộ lọc',
|
|
||||||
disabled: 'Đã tắt',
|
|
||||||
enable: 'Bật',
|
|
||||||
disable: 'Tắt'
|
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
appWelcome: 'Chào bạn đến với Antares SQL Client!',
|
appWelcome: 'Chào bạn đến với Antares SQL Client!',
|
||||||
@@ -248,10 +244,7 @@ module.exports = {
|
|||||||
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'
|
||||||
closeTab: 'Đóng tab',
|
|
||||||
goToDownloadPage: 'Tới trang tải về',
|
|
||||||
readOnlyMode: 'Chế độ chỉ đọc'
|
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Địa chỉ',
|
address: 'Địa chỉ',
|
||||||
|
@@ -1,421 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
word: {
|
|
||||||
edit: '编辑',
|
|
||||||
save: '保存',
|
|
||||||
close: '关闭',
|
|
||||||
delete: '删除',
|
|
||||||
confirm: '确定',
|
|
||||||
cancel: '取消',
|
|
||||||
send: '发送',
|
|
||||||
connectionName: '连接名称',
|
|
||||||
client: 'Client',
|
|
||||||
hostName: '主机名',
|
|
||||||
port: '端口',
|
|
||||||
user: '用户',
|
|
||||||
password: '密码',
|
|
||||||
credentials: '凭据',
|
|
||||||
connect: '连接',
|
|
||||||
connected: '已连接',
|
|
||||||
disconnect: '断开连接',
|
|
||||||
disconnected: '已断开',
|
|
||||||
refresh: '刷新',
|
|
||||||
settings: '设置',
|
|
||||||
general: '一般',
|
|
||||||
themes: '主题',
|
|
||||||
update: '更新',
|
|
||||||
about: '关于',
|
|
||||||
language: '语言',
|
|
||||||
version: '版本',
|
|
||||||
donate: '捐赠',
|
|
||||||
run: '运行',
|
|
||||||
schema: 'schema',
|
|
||||||
results: '结果',
|
|
||||||
size: '尺寸',
|
|
||||||
seconds: '秒',
|
|
||||||
type: '类型',
|
|
||||||
mimeType: 'MIME类型',
|
|
||||||
download: '下载',
|
|
||||||
add: '新增',
|
|
||||||
data: '数据',
|
|
||||||
properties: '属性',
|
|
||||||
insert: '插入',
|
|
||||||
connecting: '连接中',
|
|
||||||
name: '名称',
|
|
||||||
collation: '排序规则',
|
|
||||||
clear: '清除',
|
|
||||||
options: '选项',
|
|
||||||
autoRefresh: '自动刷新',
|
|
||||||
indexes: '索引',
|
|
||||||
foreignKeys: '外键',
|
|
||||||
length: '长度',
|
|
||||||
unsigned: '无符号',
|
|
||||||
default: '默认',
|
|
||||||
comment: '注释',
|
|
||||||
key: '键',
|
|
||||||
order: 'Order',
|
|
||||||
expression: '表达式',
|
|
||||||
autoIncrement: '自动增量',
|
|
||||||
engine: 'Engine',
|
|
||||||
field: '字段',
|
|
||||||
approximately: '大约',
|
|
||||||
total: '总计',
|
|
||||||
table: '表',
|
|
||||||
discard: '弃置',
|
|
||||||
stay: '等待',
|
|
||||||
author: '作者',
|
|
||||||
light: 'Light',
|
|
||||||
dark: 'Dark',
|
|
||||||
autoCompletion: '自动完成',
|
|
||||||
application: '应用程序',
|
|
||||||
editor: '编辑器',
|
|
||||||
view: '视图',
|
|
||||||
definer: '定义者',
|
|
||||||
algorithm: 'Algorithm',
|
|
||||||
trigger: '触发器',
|
|
||||||
storedRoutine: '存储例程',
|
|
||||||
scheduler: '调度器',
|
|
||||||
event: '事件',
|
|
||||||
parameters: '参数',
|
|
||||||
function: '函数',
|
|
||||||
deterministic: 'Deterministic',
|
|
||||||
context: '上下文',
|
|
||||||
export: '导出',
|
|
||||||
returns: '返回',
|
|
||||||
timing: '定时器',
|
|
||||||
state: '状态',
|
|
||||||
execution: '执行',
|
|
||||||
starts: '开始',
|
|
||||||
ends: '结束',
|
|
||||||
ssl: 'SSL',
|
|
||||||
privateKey: '私钥',
|
|
||||||
certificate: '证书',
|
|
||||||
caCertificate: 'CA 证书',
|
|
||||||
ciphers: 'Ciphers',
|
|
||||||
upload: '上传',
|
|
||||||
browse: '浏览',
|
|
||||||
faker: 'Faker',
|
|
||||||
content: '内容',
|
|
||||||
cut: '剪切',
|
|
||||||
copy: '复制',
|
|
||||||
paste: '粘贴',
|
|
||||||
tools: '工具',
|
|
||||||
variables: '变量',
|
|
||||||
processes: '进程',
|
|
||||||
database: '数据库',
|
|
||||||
scratchpad: 'Scratchpad',
|
|
||||||
array: '数组',
|
|
||||||
changelog: '更改日志',
|
|
||||||
format: '格式',
|
|
||||||
sshTunnel: 'SSH 隧道',
|
|
||||||
structure: '结构',
|
|
||||||
small: '小',
|
|
||||||
medium: '中',
|
|
||||||
large: '大',
|
|
||||||
row: '行',
|
|
||||||
cell: '单元格',
|
|
||||||
triggerFunction: '触发函数',
|
|
||||||
all: '全部',
|
|
||||||
duplicate: '重复',
|
|
||||||
routine: '例程',
|
|
||||||
new: 'New',
|
|
||||||
history: '历史记录',
|
|
||||||
select: '选择',
|
|
||||||
passphrase: '密码',
|
|
||||||
filter: '过滤器',
|
|
||||||
disabled: '禁用',
|
|
||||||
enable: '启用',
|
|
||||||
disable: '是否禁用'
|
|
||||||
},
|
|
||||||
message: {
|
|
||||||
appWelcome: '欢迎来到Antares SQL Client!',
|
|
||||||
appFirstStep: '你的第一步: 创建一个新的数据库连接.',
|
|
||||||
addConnection: '添加连接',
|
|
||||||
createConnection: '创建连接',
|
|
||||||
createNewConnection: '创建新的连接',
|
|
||||||
askCredentials: '询问凭证',
|
|
||||||
testConnection: '测试连接',
|
|
||||||
editConnection: '编辑连接',
|
|
||||||
deleteConnection: '删除连接',
|
|
||||||
deleteCorfirm: '您是否确认取消',
|
|
||||||
connectionSuccessfullyMade: '连接成功建立!',
|
|
||||||
madeWithJS: '用💛和JavaScript制造!',
|
|
||||||
checkForUpdates: '检查更新',
|
|
||||||
noUpdatesAvailable: '没有可用的更新',
|
|
||||||
checkingForUpdate: '正在检查更新',
|
|
||||||
checkFailure: '检查失败,请稍后再试',
|
|
||||||
updateAvailable: '可用的更新',
|
|
||||||
downloadingUpdate: '正在下载更新',
|
|
||||||
updateDownloaded: '更新已下载',
|
|
||||||
restartToInstall: '重启Antares完成更新',
|
|
||||||
unableEditFieldWithoutPrimary: '无法编辑一个在结果集中没有主键的字段',
|
|
||||||
editCell: '编辑单元格',
|
|
||||||
deleteRows: '删除行 | 删除{count}行',
|
|
||||||
confirmToDeleteRows: '你是否确认要删除一行? | 您是否确认要删除{count}行?',
|
|
||||||
notificationsTimeout: '通知超时',
|
|
||||||
uploadFile: '上传文件',
|
|
||||||
addNewRow: '添加新行',
|
|
||||||
numberOfInserts: '插入的数量',
|
|
||||||
openNewTab: '打开一个新标签',
|
|
||||||
affectedRows: '受影响的行',
|
|
||||||
createNewDatabase: '创建新的数据库',
|
|
||||||
databaseName: '数据库名称',
|
|
||||||
serverDefault: '默认服务器',
|
|
||||||
deleteDatabase: '删除数据库',
|
|
||||||
editDatabase: '编辑数据库',
|
|
||||||
clearChanges: '清除变化',
|
|
||||||
addNewField: '添加新字段',
|
|
||||||
manageIndexes: '管理索引',
|
|
||||||
manageForeignKeys: '管理外键',
|
|
||||||
allowNull: '允许NULL',
|
|
||||||
zeroFill: '填充零',
|
|
||||||
customValue: '自定义值',
|
|
||||||
onUpdate: '在更新时',
|
|
||||||
deleteField: '删除字段',
|
|
||||||
createNewIndex: '创建新的索引',
|
|
||||||
addToIndex: '添加到索引',
|
|
||||||
createNewTable: '创建新表',
|
|
||||||
emptyTable: '清空表',
|
|
||||||
deleteTable: '删除表',
|
|
||||||
emptyCorfirm: '你是否确认清空',
|
|
||||||
unsavedChanges: '未保存的更改',
|
|
||||||
discardUnsavedChanges: '你有一些未保存的修改。关闭这个标签,这些变化将被丢弃.',
|
|
||||||
thereAreNoIndexes: '没有索引',
|
|
||||||
thereAreNoForeign: '没有外键',
|
|
||||||
createNewForeign: '创建新的外键',
|
|
||||||
referenceTable: '参考表',
|
|
||||||
referenceField: '参考字段',
|
|
||||||
foreignFields: '外键字段',
|
|
||||||
invalidDefault: '无效的默认值',
|
|
||||||
onDelete: '在删除时',
|
|
||||||
applicationTheme: '应用主题',
|
|
||||||
editorTheme: '编辑器主题',
|
|
||||||
wrapLongLines: '超出换行显示',
|
|
||||||
selectStatement: '选择语句',
|
|
||||||
triggerStatement: '触发器语句',
|
|
||||||
sqlSecurity: 'SQL安全',
|
|
||||||
updateOption: '更新选项',
|
|
||||||
deleteView: '删除视图',
|
|
||||||
createNewView: '创建新视图',
|
|
||||||
deleteTrigger: '删除触发器',
|
|
||||||
createNewTrigger: '创建新的触发器',
|
|
||||||
currentUser: '当前用户',
|
|
||||||
routineBody: '例程主体',
|
|
||||||
dataAccess: '数据访问',
|
|
||||||
thereAreNoParameters: '没有参数',
|
|
||||||
createNewParameter: '创建新参数',
|
|
||||||
createNewRoutine: '创建新的例程',
|
|
||||||
deleteRoutine: '删除例程',
|
|
||||||
functionBody: '函数体',
|
|
||||||
createNewFunction: '创建新函数',
|
|
||||||
deleteFunction: '删除函数',
|
|
||||||
schedulerBody: '调度器主体',
|
|
||||||
createNewScheduler: '创建新的调度器',
|
|
||||||
deleteScheduler: '删除调度器',
|
|
||||||
preserveOnCompletion: '完成时保存',
|
|
||||||
enableSsl: '启用SSL',
|
|
||||||
manualValue: '手动值',
|
|
||||||
tableFiller: '表填充器',
|
|
||||||
fakeDataLanguage: '伪造的数据语言',
|
|
||||||
searchForElements: '搜索元素',
|
|
||||||
selectAll: '选择所有',
|
|
||||||
queryDuration: '查询时间',
|
|
||||||
includeBetaUpdates: '包括测试版更新',
|
|
||||||
setNull: '设置NULL',
|
|
||||||
processesList: '进程列表',
|
|
||||||
processInfo: '进程信息',
|
|
||||||
manageUsers: '管理用户',
|
|
||||||
createNewSchema: '创建新模式',
|
|
||||||
schemaName: '模式名称',
|
|
||||||
editSchema: '编辑模式',
|
|
||||||
deleteSchema: '删除模式',
|
|
||||||
markdownSupported: '支持Markdown',
|
|
||||||
plantATree: '种植一棵树',
|
|
||||||
dataTabPageSize: '数据标签的页面大小',
|
|
||||||
enableSsh: '启用SSH',
|
|
||||||
pageNumber: '页数',
|
|
||||||
duplicateTable: '重复的表格',
|
|
||||||
noOpenTabs: '没有打开的标签,在左栏导航或:',
|
|
||||||
noSchema: '没有模式',
|
|
||||||
restorePreviourSession: '恢复以前的会话',
|
|
||||||
runQuery: '运行查询',
|
|
||||||
thereAreNoTableFields: '没有表的字段',
|
|
||||||
newTable: '新表',
|
|
||||||
newView: '新视图',
|
|
||||||
newTrigger: '新触发器',
|
|
||||||
newRoutine: '新例程',
|
|
||||||
newFunction: '新函数',
|
|
||||||
newScheduler: '新调度器',
|
|
||||||
newTriggerFunction: '新触发函数',
|
|
||||||
thereIsNoQueriesYet: '还没有查询',
|
|
||||||
searchForQueries: '搜索查询',
|
|
||||||
killProcess: '杀死进程',
|
|
||||||
closeTab: '关闭标签',
|
|
||||||
goToDownloadPage: '跳转到下载页面',
|
|
||||||
readOnlyMode: '只读模式',
|
|
||||||
killQuery: '停止查询'
|
|
||||||
},
|
|
||||||
faker: {
|
|
||||||
address: '地址',
|
|
||||||
commerce: '商业',
|
|
||||||
company: '公司',
|
|
||||||
database: '数据库',
|
|
||||||
date: '日期',
|
|
||||||
finance: '财务',
|
|
||||||
git: 'Git',
|
|
||||||
hacker: '黑客',
|
|
||||||
internet: '互联网',
|
|
||||||
lorem: 'Lorem',
|
|
||||||
name: '姓名',
|
|
||||||
music: '音乐',
|
|
||||||
phone: '电话',
|
|
||||||
random: '随机',
|
|
||||||
system: '系统',
|
|
||||||
time: '时间',
|
|
||||||
vehicle: '车辆',
|
|
||||||
zipCode: '邮政编码',
|
|
||||||
zipCodeByState: '按州的邮编',
|
|
||||||
city: '城市',
|
|
||||||
cityPrefix: '城市前缀',
|
|
||||||
citySuffix: '城市后缀',
|
|
||||||
streetName: '街道名称',
|
|
||||||
streetAddress: '街道地址',
|
|
||||||
streetSuffix: '街道前缀',
|
|
||||||
streetPrefix: '街道后缀',
|
|
||||||
secondaryAddress: '次要地址',
|
|
||||||
county: '县',
|
|
||||||
country: '国家',
|
|
||||||
countryCode: '国家代码',
|
|
||||||
state: '州',
|
|
||||||
stateAbbr: '州的缩写',
|
|
||||||
latitude: '纬度',
|
|
||||||
longitude: '经度',
|
|
||||||
direction: '方向',
|
|
||||||
cardinalDirection: 'Cardinal direction',
|
|
||||||
ordinalDirection: 'Ordinal direction',
|
|
||||||
nearbyGPSCoordinate: '附近的GPS坐标',
|
|
||||||
timeZone: '时区',
|
|
||||||
color: '颜色',
|
|
||||||
department: '部门',
|
|
||||||
productName: '产品名称',
|
|
||||||
price: '价格',
|
|
||||||
productAdjective: '产品形容词',
|
|
||||||
productMaterial: '产品材料',
|
|
||||||
product: '产品',
|
|
||||||
productDescription: '产品描述',
|
|
||||||
suffixes: '后缀',
|
|
||||||
companyName: '公司名称',
|
|
||||||
companySuffix: '公司后缀',
|
|
||||||
catchPhrase: 'Catch phrase',
|
|
||||||
bs: 'BS',
|
|
||||||
catchPhraseAdjective: 'Catch phrase adjective',
|
|
||||||
catchPhraseDescriptor: 'Catch phrase descriptor',
|
|
||||||
catchPhraseNoun: 'Catch phrase noun',
|
|
||||||
bsAdjective: 'BS adjective',
|
|
||||||
bsBuzz: 'BS buzz',
|
|
||||||
bsNoun: 'BS noun',
|
|
||||||
column: '列',
|
|
||||||
type: '类型',
|
|
||||||
collation: '校对',
|
|
||||||
engine: 'Engine',
|
|
||||||
past: '过去',
|
|
||||||
future: '未来',
|
|
||||||
between: '之间',
|
|
||||||
recent: '最近',
|
|
||||||
soon: '很快',
|
|
||||||
month: '月',
|
|
||||||
weekday: '工作日',
|
|
||||||
account: '账户',
|
|
||||||
accountName: '账户名称',
|
|
||||||
routingNumber: '路由号码',
|
|
||||||
mask: '掩码',
|
|
||||||
amount: '金额',
|
|
||||||
transactionType: '交易类型',
|
|
||||||
currencyCode: '货币代码',
|
|
||||||
currencyName: '货币名称',
|
|
||||||
currencySymbol: '货币符号',
|
|
||||||
bitcoinAddress: '比特币地址',
|
|
||||||
litecoinAddress: '莱特币地址',
|
|
||||||
creditCardNumber: '信用卡号码',
|
|
||||||
creditCardCVV: '信用卡CVV',
|
|
||||||
ethereumAddress: '以太坊地址',
|
|
||||||
iban: 'Iban',
|
|
||||||
bic: 'Bic',
|
|
||||||
transactionDescription: '交易描述',
|
|
||||||
branch: '分支',
|
|
||||||
commitEntry: '提交条目',
|
|
||||||
commitMessage: '提交信息',
|
|
||||||
commitSha: '提交 SHA',
|
|
||||||
shortSha: 'Short SHA',
|
|
||||||
abbreviation: '缩写',
|
|
||||||
adjective: '形容词',
|
|
||||||
noun: '名词',
|
|
||||||
verb: '动词',
|
|
||||||
ingverb: 'Ingverb',
|
|
||||||
phrase: '短语',
|
|
||||||
avatar: '头像',
|
|
||||||
email: '电子邮箱',
|
|
||||||
exampleEmail: '电子邮件例子',
|
|
||||||
userName: '用户名',
|
|
||||||
protocol: '协议',
|
|
||||||
url: 'Url',
|
|
||||||
domainName: 'Domin name',
|
|
||||||
domainSuffix: '域名后缀',
|
|
||||||
domainWord: 'Domain word',
|
|
||||||
ip: 'Ip',
|
|
||||||
ipv6: 'Ipv6',
|
|
||||||
userAgent: 'User agent',
|
|
||||||
mac: 'Mac',
|
|
||||||
password: '密码',
|
|
||||||
word: 'Word',
|
|
||||||
words: 'Words',
|
|
||||||
sentence: '句子',
|
|
||||||
slug: 'Slug',
|
|
||||||
sentences: '句子',
|
|
||||||
paragraph: '段落',
|
|
||||||
paragraphs: '段落',
|
|
||||||
text: '文本',
|
|
||||||
lines: '行',
|
|
||||||
genre: 'Genre',
|
|
||||||
firstName: '名',
|
|
||||||
lastName: '姓氏',
|
|
||||||
middleName: '中间名',
|
|
||||||
findName: '全名',
|
|
||||||
jobTitle: '职位名称',
|
|
||||||
gender: '性别',
|
|
||||||
prefix: '前缀',
|
|
||||||
suffix: '后缀',
|
|
||||||
title: '标题',
|
|
||||||
jobDescriptor: '工作描述',
|
|
||||||
jobArea: '工作领域',
|
|
||||||
jobType: '工作类型',
|
|
||||||
phoneNumber: '电话号码',
|
|
||||||
phoneNumberFormat: '电话号码格式',
|
|
||||||
phoneFormats: '电话格式',
|
|
||||||
number: 'Number',
|
|
||||||
float: 'Float',
|
|
||||||
arrayElement: '数组元素',
|
|
||||||
arrayElements: '数组元素',
|
|
||||||
objectElement: '对象元素',
|
|
||||||
uuid: 'Uuid',
|
|
||||||
boolean: 'Boolean',
|
|
||||||
image: 'Image',
|
|
||||||
locale: 'Locale',
|
|
||||||
alpha: 'Alpha',
|
|
||||||
alphaNumeric: 'Alphanumeric',
|
|
||||||
hexaDecimal: 'Hexadecimal',
|
|
||||||
fileName: '文件名',
|
|
||||||
commonFileName: '普通文件名',
|
|
||||||
mimeType: 'MIME类型',
|
|
||||||
commonFileType: '常见的文件类型',
|
|
||||||
commonFileExt: '常见的文件扩展名',
|
|
||||||
fileType: '文件类型',
|
|
||||||
fileExt: '文件扩展名',
|
|
||||||
directoryPath: '目录路径',
|
|
||||||
filePath: '文件路径',
|
|
||||||
semver: 'Semver',
|
|
||||||
manufacturer: '制造商',
|
|
||||||
model: '型号',
|
|
||||||
fuel: 'Fuel',
|
|
||||||
vin: 'Vin'
|
|
||||||
}
|
|
||||||
};
|
|
@@ -3,7 +3,6 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
import '@mdi/font/css/materialdesignicons.css';
|
import '@mdi/font/css/materialdesignicons.css';
|
||||||
import 'leaflet/dist/leaflet.css';
|
|
||||||
import '@/scss/main.scss';
|
import '@/scss/main.scss';
|
||||||
|
|
||||||
import App from '@/App.vue';
|
import App from '@/App.vue';
|
||||||
|
@@ -46,10 +46,6 @@ export default class {
|
|||||||
return ipcRenderer.invoke('kill-process', params);
|
return ipcRenderer.invoke('kill-process', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
static killTabQuery (params) {
|
|
||||||
return ipcRenderer.invoke('kill-tab-query', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
static useSchema (params) {
|
static useSchema (params) {
|
||||||
return ipcRenderer.invoke('use-schema', params);
|
return ipcRenderer.invoke('use-schema', params);
|
||||||
}
|
}
|
||||||
|
@@ -81,15 +81,6 @@
|
|||||||
"tsvector": $array-color,
|
"tsvector": $array-color,
|
||||||
"tsquery": $array-color,
|
"tsquery": $array-color,
|
||||||
"pg_node_tree": $array-color,
|
"pg_node_tree": $array-color,
|
||||||
"point": $array-color,
|
|
||||||
"linestring": $array-color,
|
|
||||||
"polygon": $array-color,
|
|
||||||
"geometry": $array-color,
|
|
||||||
"multipoint": $array-color,
|
|
||||||
"multilinestring": $array-color,
|
|
||||||
"multipolygon": $array-color,
|
|
||||||
"geomcollection": $array-color,
|
|
||||||
"geometrycollection": $array-color,
|
|
||||||
"aclitem": $array-color,
|
"aclitem": $array-color,
|
||||||
"unknown": $unknown-color,
|
"unknown": $unknown-color,
|
||||||
)
|
)
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
background-image: url("../images/svg/pg.svg");
|
background-image: url("../images/svg/pg.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.dbi-sqlite {
|
&.dbi-sqlite {
|
||||||
background-image: url("../images/svg/sqlite.svg");
|
background-image: url("../images/svg/sqlite.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -59,34 +59,6 @@ option:checked {
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cancellable {
|
|
||||||
color: transparent !important;
|
|
||||||
min-height: 0.8rem;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
> .mdi,
|
|
||||||
> .span {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: "\2715";
|
|
||||||
color: $light-color;
|
|
||||||
font-weight: 700;
|
|
||||||
top: 36%;
|
|
||||||
display: block;
|
|
||||||
height: 0.8rem;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -0.4rem;
|
|
||||||
margin-top: -0.4rem;
|
|
||||||
opacity: 1;
|
|
||||||
padding: 0;
|
|
||||||
position: absolute;
|
|
||||||
width: 0.8rem;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace-tabs {
|
.workspace-tabs {
|
||||||
align-content: baseline;
|
align-content: baseline;
|
||||||
|
|
||||||
|
@@ -1,63 +0,0 @@
|
|||||||
const { _electron: electron } = require('playwright');
|
|
||||||
const { strict: assert } = require('assert');
|
|
||||||
|
|
||||||
const isWindows = process.platform === 'win32';
|
|
||||||
async function wait (ms) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
setTimeout(resolve, ms);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
if (isWindows) {
|
|
||||||
console.log('Termporary skipping tests on Windows');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Starting tests');
|
|
||||||
// Launch Electron app.
|
|
||||||
const electronApp = await electron.launch({ args: ['dist/main.js'] });
|
|
||||||
|
|
||||||
if (isWindows) await wait(5000);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* App main window state
|
|
||||||
* @type {{isVisible: boolean; isDevToolsOpened: boolean; isCrashed: boolean}}
|
|
||||||
*/
|
|
||||||
const windowState = await electronApp.evaluate(({ BrowserWindow }) => {
|
|
||||||
const mainWindow = BrowserWindow.getAllWindows()[0];
|
|
||||||
const getState = () => ({
|
|
||||||
isVisible: mainWindow.isVisible(),
|
|
||||||
isDevToolsOpened: mainWindow.webContents.isDevToolsOpened()
|
|
||||||
});
|
|
||||||
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
if (mainWindow.isVisible())
|
|
||||||
resolve(getState());
|
|
||||||
else
|
|
||||||
mainWindow.once('ready-to-show', () => setTimeout(() => resolve(getState()), 0));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check main window state
|
|
||||||
assert.ok(windowState.isVisible, 'Main window not visible');
|
|
||||||
assert.ok(!windowState.isDevToolsOpened, 'DevTools opened');
|
|
||||||
assert.ok(!windowState.isCrashed, 'Window crashed');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rendered Main window web-page
|
|
||||||
* @type {Page}
|
|
||||||
*/
|
|
||||||
const page = await electronApp.firstWindow();
|
|
||||||
console.log(await page.title());
|
|
||||||
|
|
||||||
// Check web-page content
|
|
||||||
const element = await page.$('#wrapper', { strict: true });
|
|
||||||
|
|
||||||
assert.notStrictEqual(element, null, 'Can\'t find root element');
|
|
||||||
assert.notStrictEqual((await element.innerHTML()).trim(), '', 'Window content is empty');
|
|
||||||
|
|
||||||
// Close app
|
|
||||||
await electronApp.close();
|
|
||||||
console.log('Tests finished');
|
|
||||||
})();
|
|