mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
Compare commits
48 Commits
Author | SHA1 | Date | |
---|---|---|---|
420255cdd4 | |||
a8a47ed5f7 | |||
425f0663f9 | |||
e106d100b5 | |||
d7fdf53932 | |||
62f7e57d0c | |||
14577d14bb | |||
f5f2a697e8 | |||
a0105cf1c3 | |||
77c5d28032 | |||
d1d8592f79 | |||
1f828f69a0 | |||
adc5477673 | |||
1e543aa6b0 | |||
c41e059b0b | |||
e6ef5ffa56 | |||
d67d122270 | |||
b837e2fc68 | |||
a73a2f483e | |||
0a9983d30d | |||
58b91ebfe0 | |||
e78ca2417e | |||
e1855a262d | |||
6b725b1d40 | |||
f6faad98f8 | |||
320aa8ba04 | |||
9f0280b991 | |||
04fa320820 | |||
f7c3aa883d | |||
f7a74df009 | |||
003c02b1fb | |||
ef21ea7448 | |||
525c964c62 | |||
7845e3e501 | |||
0c29e0d566 | |||
d38097d056 | |||
c87b8dc738 | |||
ed6e7fa72d | |||
f0fa7c81b7 | |||
5bb4e496f2 | |||
01057332b0 | |||
ab382dfbcd | |||
88c4cdc8e2 | |||
15ff211a41 | |||
5c855a520a | |||
7488bc7a17 | |||
|
fd85cf43a2 | ||
a87079cd17 |
53
CHANGELOG.md
53
CHANGELOG.md
@@ -2,6 +2,59 @@
|
||||
|
||||
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.3.1](https://github.com/Fabio286/antares/compare/v0.3.0...v0.3.1) (2021-07-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **UI:** tabs or explorebar elements selected with mouse wheel or right button ([a8a47ed](https://github.com/Fabio286/antares/commit/a8a47ed5f7d5d8cbbdd6c33ef8307d9dce5b193b))
|
||||
|
||||
## [0.3.0](https://github.com/Fabio286/antares/compare/v0.2.1...v0.3.0) (2021-07-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* close tabs if element deleted ([320aa8b](https://github.com/Fabio286/antares/commit/320aa8ba04d464f628b938b812165cd1ec786492))
|
||||
* new data tabs ([ab382df](https://github.com/Fabio286/antares/commit/ab382dfbcd89f8ab38a8cbdb4d87e1705618fd0d))
|
||||
* new function, procedure and scheduler tabs ([0a9983d](https://github.com/Fabio286/antares/commit/0a9983d30d6aeb9aee1c68b31a31f8c605deea45))
|
||||
* new trigger function tabs ([58b91eb](https://github.com/Fabio286/antares/commit/58b91ebfe0ab200d76d4cfd442b9f2970ae97384))
|
||||
* new trigger setting tabs ([f6faad9](https://github.com/Fabio286/antares/commit/f6faad98f88222500dfb7265b74c1be914b894cd))
|
||||
* new unsaved change reminder ([f7a74df](https://github.com/Fabio286/antares/commit/f7a74df0097867a82a2a2d8b3c278a81897d7898))
|
||||
* new view setting tabs ([003c02b](https://github.com/Fabio286/antares/commit/003c02b1fbe5aba7f53f3faa5610b0c2f7706793))
|
||||
* option to restore session on startup ([adc5477](https://github.com/Fabio286/antares/commit/adc5477673603cd63fabf77a53db5397e3774e0e))
|
||||
* option to select schema in query tabs ([a73a2f4](https://github.com/Fabio286/antares/commit/a73a2f483ef6927def4ba635e306277c34ae4b53))
|
||||
* **UI:** empty workspace view ([e1855a2](https://github.com/Fabio286/antares/commit/e1855a262dc24363fc143a38a70154938308bd71))
|
||||
* rename tabs if element is renamed ([ef21ea7](https://github.com/Fabio286/antares/commit/ef21ea74481839ba67ca79d40d5f47e1c12aebc0))
|
||||
* **MySQL:** improved schema detection for queries ([5bb4e49](https://github.com/Fabio286/antares/commit/5bb4e496f289f3ae8a46f24d1a2fbb896d9da86e))
|
||||
* **UI:** close temp data tabs ([88c4cdc](https://github.com/Fabio286/antares/commit/88c4cdc8e2a60ffbe26b0f831184c3a6dd9a1637))
|
||||
* **UI:** display schema in data tabs ([0105733](https://github.com/Fabio286/antares/commit/01057332b090997c107bf395bb1fc3b9195e8218))
|
||||
* **UI:** new table settings tabs ([7845e3e](https://github.com/Fabio286/antares/commit/7845e3e501bb7f890d07b42d4f3eb5f9f4bc8586))
|
||||
* **UI:** sortable tabs ([d38097d](https://github.com/Fabio286/antares/commit/d38097d0567020b5265b5a0b347f5e1f38e0b1d4))
|
||||
* **UI:** temporary table data tabs ([a87079c](https://github.com/Fabio286/antares/commit/a87079cd179033cebb6fd228ad7f1b991f3b6c46))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* clear empty indexes and foreign keys on confirm respective modals ([04fa320](https://github.com/Fabio286/antares/commit/04fa320820df1f70a4ef05e4a6e4cbcd4081d047))
|
||||
* enabled copy context on non editable rows ([525c964](https://github.com/Fabio286/antares/commit/525c964c623e7574f6abe732a2b315b8805d5eee))
|
||||
* issues with trigger temp tabs ([6b725b1](https://github.com/Fabio286/antares/commit/6b725b1d40753ad89bfad6f1df57c6fb737e5262))
|
||||
* manual page input not disabled when only one page is available ([62f7e57](https://github.com/Fabio286/antares/commit/62f7e57d0ccf6041b5469bec6a1864aa5b045609))
|
||||
* new field default value unknown instead 'noval' ([77c5d28](https://github.com/Fabio286/antares/commit/77c5d280325792e20befc845f3a6834837131e39))
|
||||
* reload twice after element rename ([1e543aa](https://github.com/Fabio286/antares/commit/1e543aa6b0b63e9134bf544682a26bd98573b794))
|
||||
* solved a vulnerability in table names ([5c855a5](https://github.com/Fabio286/antares/commit/5c855a520a6bc66cc00b0b8afc6d2c03c75c0fab))
|
||||
* sort order of tables is lost switching pages ([14577d1](https://github.com/Fabio286/antares/commit/14577d14bb337898a1fd0fdee1c3760812b9d21f))
|
||||
* wrong editor height with some conditions ([d7fdf53](https://github.com/Fabio286/antares/commit/d7fdf53932a4d0609a88641c40d451c71b12c242))
|
||||
* **UI:** multiple trigger tabs open on single click on explore bar ([e78ca24](https://github.com/Fabio286/antares/commit/e78ca2417e8f996fa0507c5a5586a75393dfe8ee))
|
||||
* **UI:** not disabled buttons during save table setting tabs ([a0105cf](https://github.com/Fabio286/antares/commit/a0105cf1c37144ea27b212029d39275918f4f95e))
|
||||
* tab won't open after table or view creation ([f7c3aa8](https://github.com/Fabio286/antares/commit/f7c3aa883dfcad0a28222c53cf22ab49d381559c))
|
||||
* wrong loaded schema change ([c41e059](https://github.com/Fabio286/antares/commit/c41e059b0ba6d8c6d545c3b86a21a9a2abb6f537))
|
||||
* **UI:** table icon in view data tabs ([f0fa7c8](https://github.com/Fabio286/antares/commit/f0fa7c81b7aa2a05833ce0b243afed39db98d66b))
|
||||
|
||||
|
||||
### Improvements
|
||||
|
||||
* **UI:** improvements in setting bar connections sort ([0c29e0d](https://github.com/Fabio286/antares/commit/0c29e0d566c792ffd1b2b7045124e170b9c51985))
|
||||
|
||||
### [0.2.1](https://github.com/Fabio286/antares/compare/v0.2.0...v0.2.1) (2021-07-09)
|
||||
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "antares",
|
||||
"productName": "Antares",
|
||||
"version": "0.2.1",
|
||||
"version": "0.3.1",
|
||||
"description": "A cross-platform easy to use SQL client.",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/Fabio286/antares.git",
|
||||
@@ -102,7 +102,7 @@
|
||||
"source-map-support": "^0.5.16",
|
||||
"spectre.css": "^0.5.9",
|
||||
"sql-formatter": "^4.0.2",
|
||||
"ssh2-promise": "^0.1.7",
|
||||
"ssh2-promise": "^0.2.0",
|
||||
"v-mask": "^2.2.4",
|
||||
"vue-i18n": "^8.24.4",
|
||||
"vuedraggable": "^2.24.3",
|
||||
@@ -127,7 +127,7 @@
|
||||
"standard-version": "^9.3.0",
|
||||
"stylelint": "^13.13.1",
|
||||
"stylelint-config-standard": "^22.0.0",
|
||||
"stylelint-scss": "^3.19.0",
|
||||
"stylelint-scss": "^3.20.1",
|
||||
"vue": "^2.6.14",
|
||||
"vue-template-compiler": "^2.6.14",
|
||||
"webpack": "^4.46.0"
|
||||
|
@@ -4,9 +4,7 @@ summary: Open source SQL client made to be simple and complete.
|
||||
description: |
|
||||
Antares is an SQL client that aims to become an useful and complete tool, especially for developers.
|
||||
The target is to support as many databases as possible, and all major operating systems, including the ARM versions.
|
||||
At the moment this application is an alpha and supports only MySQL and x86 architecture.
|
||||
Most of its current features might be enough for MySQL management, so give it a chance and send us your feedback, we would really appreciate it.
|
||||
base: core18
|
||||
base: core20
|
||||
|
||||
grade: stable
|
||||
confinement: strict
|
||||
@@ -60,6 +58,7 @@ parts:
|
||||
- fcitx-frontend-gtk3
|
||||
- libappindicator3-1
|
||||
- libasound2
|
||||
- libcurl4
|
||||
- libgconf-2-4
|
||||
- libgtk-3-0
|
||||
- libnotify4
|
||||
@@ -71,13 +70,59 @@ parts:
|
||||
- libsecret-1-0
|
||||
- libxtst6
|
||||
- libxkbfile1
|
||||
- gcc-10-base
|
||||
- libapparmor1
|
||||
- libblkid1
|
||||
- libbsd0
|
||||
- libcom-err2
|
||||
- libcrypt1
|
||||
- libdb5.3
|
||||
- libdbus-1-3
|
||||
- libexpat1
|
||||
- libffi7
|
||||
- libgcc-s1
|
||||
- libgcrypt20
|
||||
- libglib2.0-0
|
||||
- libgmp10
|
||||
- libgnutls30
|
||||
- libgpg-error0
|
||||
- libgssapi-krb5-2
|
||||
- libhogweed5
|
||||
- libidn2-0
|
||||
- libjson-c4
|
||||
- libk5crypto3
|
||||
- libkeyutils1
|
||||
- libkrb5-3
|
||||
- libkrb5support0
|
||||
- liblz4-1
|
||||
- liblzma5
|
||||
- libmount1
|
||||
- libnettle7
|
||||
- libp11-kit0
|
||||
- libpcre2-8-0
|
||||
- libselinux1
|
||||
- libsqlite3-0
|
||||
- libssl1.1
|
||||
- libstdc++6
|
||||
- libsystemd0
|
||||
- libtasn1-6
|
||||
- libudev1
|
||||
- libunistring2
|
||||
- libuuid1
|
||||
- libwrap0
|
||||
- libzstd1
|
||||
- zlib1g
|
||||
- libx11-xcb1
|
||||
- libdrm2
|
||||
- libgbm1
|
||||
- libxcb-dri3-0
|
||||
cleanup:
|
||||
after: [antares]
|
||||
plugin: nil
|
||||
build-snaps: [gnome-3-28-1804]
|
||||
build-snaps: [gnome-3-38-2004]
|
||||
override-prime: |
|
||||
set -eux
|
||||
cd /snap/gnome-3-28-1804/current
|
||||
cd /snap/gnome-3-38-2004/current
|
||||
find . -type f,l -exec rm -f $SNAPCRAFT_PRIME/{} \;
|
||||
|
||||
mdns-lookup:
|
||||
@@ -91,7 +136,7 @@ parts:
|
||||
- libnss-mdns
|
||||
override-prime: |
|
||||
set -eux
|
||||
sed -Ee 's/^\s*hosts:(\s+)files/hosts:\1files mdns4_minimal \[NOTFOUND=return\]/' /snap/core18/current/etc/nsswitch.conf > $SNAPCRAFT_STAGE/etc/nsswitch.conf
|
||||
sed -Ee 's/^\s*hosts:(\s+)files/hosts:\1files mdns4_minimal \[NOTFOUND=return\]/' /snap/core20/current/etc/nsswitch.conf > $SNAPCRAFT_STAGE/etc/nsswitch.conf
|
||||
snapcraftctl prime
|
||||
prime:
|
||||
- lib/$SNAPCRAFT_ARCH_TRIPLET/libnss_mdns4_minimal*
|
||||
@@ -101,7 +146,7 @@ apps:
|
||||
antares:
|
||||
command: opt/Antares/antares --no-sandbox
|
||||
desktop: usr/share/applications/antares.desktop
|
||||
extensions: [gnome-3-28]
|
||||
extensions: [gnome-3-38]
|
||||
environment:
|
||||
# Fallback to XWayland if running in a Wayland session.
|
||||
DISABLE_WAYLAND: 1
|
||||
|
@@ -128,7 +128,12 @@ export default connections => {
|
||||
if (!query) return;
|
||||
|
||||
try {
|
||||
const result = await connections[uid].raw(query, { nest: true, details: true, schema });
|
||||
const result = await connections[uid].raw(query, {
|
||||
nest: true,
|
||||
details: true,
|
||||
schema,
|
||||
comments: false
|
||||
});
|
||||
|
||||
return { status: 'success', response: result };
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ export default (connections) => {
|
||||
if (sortParams && sortParams.field && sortParams.dir)
|
||||
query.orderBy({ [sortParams.field]: sortParams.dir.toUpperCase() });
|
||||
|
||||
const result = await query.run({ details: true });
|
||||
const result = await query.run({ details: true, schema });
|
||||
|
||||
return { status: 'success', response: result };
|
||||
}
|
||||
|
@@ -335,11 +335,11 @@ export class MySQLClient extends AntaresCore {
|
||||
.select('*')
|
||||
.schema('information_schema')
|
||||
.from('COLUMNS')
|
||||
.where({ TABLE_SCHEMA: `= '${this._schema || schema}'`, TABLE_NAME: `= '${table}'` })
|
||||
.where({ TABLE_SCHEMA: `= '${schema}'`, TABLE_NAME: `= '${table}'` })
|
||||
.orderBy({ ORDINAL_POSITION: 'ASC' })
|
||||
.run();
|
||||
|
||||
const { rows: fields } = await this.raw(`SHOW CREATE TABLE \`${this._schema || schema}\`.\`${table}\``);
|
||||
const { rows: fields } = await this.raw(`SHOW CREATE TABLE \`${schema}\`.\`${table}\``);
|
||||
|
||||
const remappedFields = fields.map(row => {
|
||||
if (!row['Create Table']) return false;
|
||||
@@ -363,15 +363,14 @@ export class MySQLClient extends AntaresCore {
|
||||
|
||||
const details = fieldArr.slice(2).join(' ');
|
||||
let defaultValue = null;
|
||||
if (details.includes('DEFAULT')) {
|
||||
if (details.includes('DEFAULT'))
|
||||
defaultValue = details.match(/(?<=DEFAULT ).*?$/gs)[0].split(' COMMENT')[0];
|
||||
const defaultValueArr = defaultValue.split('');
|
||||
if (defaultValueArr[0] === '\'') {
|
||||
defaultValueArr.shift();
|
||||
defaultValueArr.pop();
|
||||
defaultValue = defaultValueArr.join('');
|
||||
}
|
||||
}
|
||||
// const defaultValueArr = defaultValue.split('');
|
||||
// if (defaultValueArr[0] === '\'') {
|
||||
// defaultValueArr.shift();
|
||||
// defaultValueArr.pop();
|
||||
// defaultValue = defaultValueArr.join('');
|
||||
// }
|
||||
|
||||
const typeAndLength = nameAndType[1].replace(')', '').split('(');
|
||||
|
||||
@@ -574,7 +573,7 @@ export class MySQLClient extends AntaresCore {
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async dropView (params) {
|
||||
const sql = `DROP VIEW \`${this._schema}\`.\`${params.view}\``;
|
||||
const sql = `DROP VIEW \`${params.schema}\`.\`${params.view}\``;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -586,10 +585,10 @@ export class MySQLClient extends AntaresCore {
|
||||
*/
|
||||
async alterView (params) {
|
||||
const { view } = params;
|
||||
let sql = `ALTER ALGORITHM = ${view.algorithm}${view.definer ? ` DEFINER=${view.definer}` : ''} SQL SECURITY ${view.security} VIEW \`${this._schema}\`.\`${view.oldName}\` AS ${view.sql} ${view.updateOption ? `WITH ${view.updateOption} CHECK OPTION` : ''}`;
|
||||
let sql = `ALTER ALGORITHM = ${view.algorithm}${view.definer ? ` DEFINER=${view.definer}` : ''} SQL SECURITY ${view.security} VIEW \`${view.schema}\`.\`${view.oldName}\` AS ${view.sql} ${view.updateOption ? `WITH ${view.updateOption} CHECK OPTION` : ''}`;
|
||||
|
||||
if (view.name !== view.oldName)
|
||||
sql += `; RENAME TABLE \`${this._schema}\`.\`${view.oldName}\` TO \`${this._schema}\`.\`${view.name}\``;
|
||||
sql += `; RENAME TABLE \`${view.schema}\`.\`${view.oldName}\` TO \`${view.schema}\`.\`${view.name}\``;
|
||||
|
||||
return await this.raw(sql);
|
||||
}
|
||||
@@ -600,8 +599,8 @@ export class MySQLClient extends AntaresCore {
|
||||
* @returns {Array.<Object>} parameters
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async createView (view) {
|
||||
const sql = `CREATE ALGORITHM = ${view.algorithm} ${view.definer ? `DEFINER=${view.definer} ` : ''}SQL SECURITY ${view.security} VIEW \`${this._schema}\`.\`${view.name}\` AS ${view.sql} ${view.updateOption ? `WITH ${view.updateOption} CHECK OPTION` : ''}`;
|
||||
async createView (params) {
|
||||
const sql = `CREATE ALGORITHM = ${params.algorithm} ${params.definer ? `DEFINER=${params.definer} ` : ''}SQL SECURITY ${params.security} VIEW \`${params.schema}\`.\`${params.name}\` AS ${params.sql} ${params.updateOption ? `WITH ${params.updateOption} CHECK OPTION` : ''}`;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -634,7 +633,7 @@ export class MySQLClient extends AntaresCore {
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async dropTrigger (params) {
|
||||
const sql = `DROP TRIGGER \`${this._schema}\`.\`${params.trigger}\``;
|
||||
const sql = `DROP TRIGGER \`${params.schema}\`.\`${params.trigger}\``;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -651,8 +650,8 @@ export class MySQLClient extends AntaresCore {
|
||||
|
||||
try {
|
||||
await this.createTrigger(tempTrigger);
|
||||
await this.dropTrigger({ trigger: tempTrigger.name });
|
||||
await this.dropTrigger({ trigger: trigger.oldName });
|
||||
await this.dropTrigger({ schema: trigger.schema, trigger: tempTrigger.name });
|
||||
await this.dropTrigger({ schema: trigger.schema, trigger: trigger.oldName });
|
||||
await this.createTrigger(trigger);
|
||||
}
|
||||
catch (err) {
|
||||
@@ -666,8 +665,8 @@ export class MySQLClient extends AntaresCore {
|
||||
* @returns {Array.<Object>} parameters
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async createTrigger (trigger) {
|
||||
const sql = `CREATE ${trigger.definer ? `DEFINER=${trigger.definer} ` : ''}TRIGGER \`${this._schema}\`.\`${trigger.name}\` ${trigger.activation} ${trigger.event} ON \`${trigger.table}\` FOR EACH ROW ${trigger.sql}`;
|
||||
async createTrigger (params) {
|
||||
const sql = `CREATE ${params.definer ? `DEFINER=${params.definer} ` : ''}TRIGGER \`${params.schema}\`.\`${params.name}\` ${params.activation} ${params.event} ON \`${params.table}\` FOR EACH ROW ${params.sql}`;
|
||||
return await this.raw(sql, { split: false });
|
||||
}
|
||||
|
||||
@@ -741,7 +740,7 @@ export class MySQLClient extends AntaresCore {
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async dropRoutine (params) {
|
||||
const sql = `DROP PROCEDURE \`${this._schema}\`.\`${params.routine}\``;
|
||||
const sql = `DROP PROCEDURE \`${params.schema}\`.\`${params.routine}\``;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -758,8 +757,8 @@ export class MySQLClient extends AntaresCore {
|
||||
|
||||
try {
|
||||
await this.createRoutine(tempProcedure);
|
||||
await this.dropRoutine({ routine: tempProcedure.name });
|
||||
await this.dropRoutine({ routine: routine.oldName });
|
||||
await this.dropRoutine({ schema: routine.schema, routine: tempProcedure.name });
|
||||
await this.dropRoutine({ schema: routine.schema, routine: routine.oldName });
|
||||
await this.createRoutine(routine);
|
||||
}
|
||||
catch (err) {
|
||||
@@ -773,21 +772,21 @@ export class MySQLClient extends AntaresCore {
|
||||
* @returns {Array.<Object>} parameters
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async createRoutine (routine) {
|
||||
const parameters = 'parameters' in routine
|
||||
? routine.parameters.reduce((acc, curr) => {
|
||||
async createRoutine (params) {
|
||||
const parameters = 'parameters' in params
|
||||
? params.parameters.reduce((acc, curr) => {
|
||||
acc.push(`${curr.context} \`${curr.name}\` ${curr.type}${curr.length ? `(${curr.length})` : ''}`);
|
||||
return acc;
|
||||
}, []).join(',')
|
||||
: '';
|
||||
|
||||
const sql = `CREATE ${routine.definer ? `DEFINER=${routine.definer} ` : ''}PROCEDURE \`${this._schema}\`.\`${routine.name}\`(${parameters})
|
||||
const sql = `CREATE ${params.definer ? `DEFINER=${params.definer} ` : ''}PROCEDURE \`${params.schema}\`.\`${params.name}\`(${parameters})
|
||||
LANGUAGE SQL
|
||||
${routine.deterministic ? 'DETERMINISTIC' : 'NOT DETERMINISTIC'}
|
||||
${routine.dataAccess}
|
||||
SQL SECURITY ${routine.security}
|
||||
COMMENT '${routine.comment}'
|
||||
${routine.sql}`;
|
||||
${params.deterministic ? 'DETERMINISTIC' : 'NOT DETERMINISTIC'}
|
||||
${params.dataAccess}
|
||||
SQL SECURITY ${params.security}
|
||||
COMMENT '${params.comment}'
|
||||
${params.sql}`;
|
||||
|
||||
return await this.raw(sql, { split: false });
|
||||
}
|
||||
@@ -868,7 +867,7 @@ export class MySQLClient extends AntaresCore {
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async dropFunction (params) {
|
||||
const sql = `DROP FUNCTION \`${this._schema}\`.\`${params.func}\``;
|
||||
const sql = `DROP FUNCTION \`${params.schema}\`.\`${params.func}\``;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -885,8 +884,8 @@ export class MySQLClient extends AntaresCore {
|
||||
|
||||
try {
|
||||
await this.createFunction(tempProcedure);
|
||||
await this.dropFunction({ func: tempProcedure.name });
|
||||
await this.dropFunction({ func: func.oldName });
|
||||
await this.dropFunction({ schema: func.schema, func: tempProcedure.name });
|
||||
await this.dropFunction({ schema: func.schema, func: func.oldName });
|
||||
await this.createFunction(func);
|
||||
}
|
||||
catch (err) {
|
||||
@@ -900,20 +899,20 @@ export class MySQLClient extends AntaresCore {
|
||||
* @returns {Array.<Object>} parameters
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async createFunction (func) {
|
||||
const parameters = func.parameters.reduce((acc, curr) => {
|
||||
async createFunction (params) {
|
||||
const parameters = params.parameters.reduce((acc, curr) => {
|
||||
acc.push(`\`${curr.name}\` ${curr.type}${curr.length ? `(${curr.length})` : ''}`);
|
||||
return acc;
|
||||
}, []).join(',');
|
||||
|
||||
const body = func.returns ? func.sql : 'BEGIN\n RETURN 0;\nEND';
|
||||
const body = params.returns ? params.sql : 'BEGIN\n RETURN 0;\nEND';
|
||||
|
||||
const sql = `CREATE ${func.definer ? `DEFINER=${func.definer} ` : ''}FUNCTION \`${this._schema}\`.\`${func.name}\`(${parameters}) RETURNS ${func.returns || 'SMALLINT'}${func.returnsLength ? `(${func.returnsLength})` : ''}
|
||||
const sql = `CREATE ${params.definer ? `DEFINER=${params.definer} ` : ''}FUNCTION \`${params.schema}\`.\`${params.name}\`(${parameters}) RETURNS ${params.returns || 'SMALLINT'}${params.returnsLength ? `(${params.returnsLength})` : ''}
|
||||
LANGUAGE SQL
|
||||
${func.deterministic ? 'DETERMINISTIC' : 'NOT DETERMINISTIC'}
|
||||
${func.dataAccess}
|
||||
SQL SECURITY ${func.security}
|
||||
COMMENT '${func.comment}'
|
||||
${params.deterministic ? 'DETERMINISTIC' : 'NOT DETERMINISTIC'}
|
||||
${params.dataAccess}
|
||||
SQL SECURITY ${params.security}
|
||||
COMMENT '${params.comment}'
|
||||
${body}`;
|
||||
|
||||
return await this.raw(sql, { split: false });
|
||||
@@ -960,7 +959,7 @@ export class MySQLClient extends AntaresCore {
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async dropEvent (params) {
|
||||
const sql = `DROP EVENT \`${this._schema}\`.\`${params.scheduler}\``;
|
||||
const sql = `DROP EVENT \`${params.schema}\`.\`${params.scheduler}\``;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -976,13 +975,13 @@ export class MySQLClient extends AntaresCore {
|
||||
if (scheduler.execution === 'EVERY' && scheduler.every[0].includes('-'))
|
||||
scheduler.every[0] = `'${scheduler.every[0]}'`;
|
||||
|
||||
const sql = `ALTER ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${this._schema}\`.\`${scheduler.oldName}\`
|
||||
const sql = `ALTER ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${scheduler.schema}\`.\`${scheduler.oldName}\`
|
||||
ON SCHEDULE
|
||||
${scheduler.execution === 'EVERY'
|
||||
? `EVERY ${scheduler.every.join(' ')}${scheduler.starts ? ` STARTS '${scheduler.starts}'` : ''}${scheduler.ends ? ` ENDS '${scheduler.ends}'` : ''}`
|
||||
: `AT '${scheduler.at}'`}
|
||||
ON COMPLETION${!scheduler.preserve ? ' NOT' : ''} PRESERVE
|
||||
${scheduler.name !== scheduler.oldName ? `RENAME TO \`${this._schema}\`.\`${scheduler.name}\`` : ''}
|
||||
${scheduler.name !== scheduler.oldName ? `RENAME TO \`${scheduler.schema}\`.\`${scheduler.name}\`` : ''}
|
||||
${scheduler.state}
|
||||
COMMENT '${scheduler.comment}'
|
||||
DO ${scheduler.sql}`;
|
||||
@@ -996,16 +995,16 @@ export class MySQLClient extends AntaresCore {
|
||||
* @returns {Array.<Object>} parameters
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async createEvent (scheduler) {
|
||||
const sql = `CREATE ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${this._schema}\`.\`${scheduler.name}\`
|
||||
async createEvent (params) {
|
||||
const sql = `CREATE ${params.definer ? ` DEFINER=${params.definer}` : ''} EVENT \`${params.schema}\`.\`${params.name}\`
|
||||
ON SCHEDULE
|
||||
${scheduler.execution === 'EVERY'
|
||||
? `EVERY ${scheduler.every.join(' ')}${scheduler.starts ? ` STARTS '${scheduler.starts}'` : ''}${scheduler.ends ? ` ENDS '${scheduler.ends}'` : ''}`
|
||||
: `AT '${scheduler.at}'`}
|
||||
ON COMPLETION${!scheduler.preserve ? ' NOT' : ''} PRESERVE
|
||||
${scheduler.state}
|
||||
COMMENT '${scheduler.comment}'
|
||||
DO ${scheduler.sql}`;
|
||||
${params.execution === 'EVERY'
|
||||
? `EVERY ${params.every.join(' ')}${params.starts ? ` STARTS '${params.starts}'` : ''}${params.ends ? ` ENDS '${params.ends}'` : ''}`
|
||||
: `AT '${params.at}'`}
|
||||
ON COMPLETION${!params.preserve ? ' NOT' : ''} PRESERVE
|
||||
${params.state}
|
||||
COMMENT '${params.comment}'
|
||||
DO ${params.sql}`;
|
||||
|
||||
return await this.raw(sql, { split: false });
|
||||
}
|
||||
@@ -1127,14 +1126,7 @@ export class MySQLClient extends AntaresCore {
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async createTable (params) {
|
||||
const {
|
||||
name,
|
||||
collation,
|
||||
comment,
|
||||
engine
|
||||
} = params;
|
||||
|
||||
const sql = `CREATE TABLE \`${this._schema}\`.\`${name}\` (\`${name}_ID\` INT NULL) COMMENT='${comment}', COLLATE='${collation}', ENGINE=${engine}`;
|
||||
const sql = `CREATE TABLE \`${params.schema}\`.\`${params.name}\` (\`${params.name}_ID\` INT NULL) COMMENT='${params.comment}', COLLATE='${params.collation}', ENGINE=${params.engine}`;
|
||||
|
||||
return await this.raw(sql);
|
||||
}
|
||||
@@ -1148,6 +1140,7 @@ export class MySQLClient extends AntaresCore {
|
||||
async alterTable (params) {
|
||||
const {
|
||||
table,
|
||||
schema,
|
||||
additions,
|
||||
deletions,
|
||||
changes,
|
||||
@@ -1156,7 +1149,7 @@ export class MySQLClient extends AntaresCore {
|
||||
options
|
||||
} = params;
|
||||
|
||||
let sql = `ALTER TABLE \`${this._schema || params.options.schema}\`.\`${table}\` `;
|
||||
let sql = `ALTER TABLE \`${schema}\`.\`${table}\` `;
|
||||
const alterColumns = [];
|
||||
|
||||
// OPTIONS
|
||||
@@ -1268,7 +1261,7 @@ export class MySQLClient extends AntaresCore {
|
||||
sql += alterColumns.join(', ');
|
||||
|
||||
// RENAME
|
||||
if (options.name) sql += `; RENAME TABLE \`${this._schema}\`.\`${table}\` TO \`${this._schema}\`.\`${options.name}\``;
|
||||
if (options.name) sql += `; RENAME TABLE \`${schema}\`.\`${table}\` TO \`${schema}\`.\`${options.name}\``;
|
||||
|
||||
return await this.raw(sql);
|
||||
}
|
||||
@@ -1280,7 +1273,7 @@ export class MySQLClient extends AntaresCore {
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async duplicateTable (params) {
|
||||
const sql = `CREATE TABLE \`${this._schema}\`.\`${params.table}_copy\` LIKE \`${this._schema}\`.\`${params.table}\``;
|
||||
const sql = `CREATE TABLE \`${params.schema}\`.\`${params.table}_copy\` LIKE \`${params.schema}\`.\`${params.table}\``;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -1291,7 +1284,7 @@ export class MySQLClient extends AntaresCore {
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async truncateTable (params) {
|
||||
const sql = `TRUNCATE TABLE \`${this._schema}\`.\`${params.table}\``;
|
||||
const sql = `TRUNCATE TABLE \`${params.schema}\`.\`${params.table}\``;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -1302,7 +1295,7 @@ export class MySQLClient extends AntaresCore {
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async dropTable (params) {
|
||||
const sql = `DROP TABLE \`${this._schema}\`.\`${params.table}\``;
|
||||
const sql = `DROP TABLE \`${params.schema}\`.\`${params.table}\``;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -1373,16 +1366,19 @@ export class MySQLClient extends AntaresCore {
|
||||
* @memberof MySQLClient
|
||||
*/
|
||||
async raw (sql, args) {
|
||||
sql = sql.replace(/(\/\*(.|[\r\n])*?\*\/)|(--(.*|[\r\n]))/gm, '');
|
||||
if (process.env.NODE_ENV === 'development') this._logger(sql);// TODO: replace BLOB content with a placeholder
|
||||
|
||||
args = {
|
||||
nest: false,
|
||||
details: false,
|
||||
split: true,
|
||||
comments: true,
|
||||
...args
|
||||
};
|
||||
|
||||
if (!args.comments)
|
||||
sql = sql.replace(/(\/\*(.|[\r\n])*?\*\/)|(--(.*|[\r\n]))/gm, '');// Remove comments
|
||||
|
||||
const nestTables = args.nest ? '.' : false;
|
||||
const resultsArr = [];
|
||||
let paramsArr = [];
|
||||
@@ -1419,7 +1415,7 @@ export class MySQLClient extends AntaresCore {
|
||||
name: field.orgName,
|
||||
alias: field.name,
|
||||
orgName: field.orgName,
|
||||
schema: field.schema,
|
||||
schema: args.schema || field.schema,
|
||||
table: field.table,
|
||||
tableAlias: field.table,
|
||||
orgTable: field.orgTable,
|
||||
|
@@ -483,7 +483,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
* @memberof PostgreSQLClient
|
||||
*/
|
||||
async dropView (params) {
|
||||
const sql = `DROP VIEW ${this._schema}.${params.view}`;
|
||||
const sql = `DROP VIEW ${params.schema}.${params.view}`;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -495,10 +495,10 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
*/
|
||||
async alterView (params) {
|
||||
const { view } = params;
|
||||
let sql = `CREATE OR REPLACE VIEW ${this._schema}.${view.oldName} AS ${view.sql}`;
|
||||
let sql = `CREATE OR REPLACE VIEW ${view.schema}.${view.oldName} AS ${view.sql}`;
|
||||
|
||||
if (view.name !== view.oldName)
|
||||
sql += `; ALTER VIEW ${this._schema}.${view.oldName} RENAME TO ${view.name}`;
|
||||
sql += `; ALTER VIEW ${view.schema}.${view.oldName} RENAME TO ${view.name}`;
|
||||
|
||||
return await this.raw(sql);
|
||||
}
|
||||
@@ -509,8 +509,8 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
* @returns {Array.<Object>} parameters
|
||||
* @memberof PostgreSQLClient
|
||||
*/
|
||||
async createView (view) {
|
||||
const sql = `CREATE VIEW ${this._schema}.${view.name} AS ${view.sql}`;
|
||||
async createView (params) {
|
||||
const sql = `CREATE VIEW ${params.schema}.${params.name} AS ${params.sql}`;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -560,7 +560,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
*/
|
||||
async dropTrigger (params) {
|
||||
const triggerParts = params.trigger.split('.');
|
||||
const sql = `DROP TRIGGER "${triggerParts[1]}" ON "${triggerParts[0]}"`;
|
||||
const sql = `DROP TRIGGER "${triggerParts[1]}" ON "${params.schema}"."${triggerParts[0]}"`;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -577,8 +577,8 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
|
||||
try {
|
||||
await this.createTrigger(tempTrigger);
|
||||
await this.dropTrigger({ trigger: `${tempTrigger.table}.${tempTrigger.name}` });
|
||||
await this.dropTrigger({ trigger: `${trigger.table}.${trigger.oldName}` });
|
||||
await this.dropTrigger({ schema: trigger.schema, trigger: `${tempTrigger.table}.${tempTrigger.name}` });
|
||||
await this.dropTrigger({ schema: trigger.schema, trigger: `${trigger.table}.${trigger.oldName}` });
|
||||
await this.createTrigger(trigger);
|
||||
}
|
||||
catch (err) {
|
||||
@@ -592,9 +592,9 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
* @returns {Array.<Object>} parameters
|
||||
* @memberof PostgreSQLClient
|
||||
*/
|
||||
async createTrigger (trigger) {
|
||||
const eventsString = Array.isArray(trigger.event) ? trigger.event.join(' OR ') : trigger.event;
|
||||
const sql = `CREATE TRIGGER "${trigger.name}" ${trigger.activation} ${eventsString} ON "${trigger.table}" FOR EACH ROW ${trigger.sql}`;
|
||||
async createTrigger (params) {
|
||||
const eventsString = Array.isArray(params.event) ? params.event.join(' OR ') : params.event;
|
||||
const sql = `CREATE TRIGGER "${params.name}" ${params.activation} ${eventsString} ON "${params.schema}"."${params.table}" FOR EACH ROW ${params.sql}`;
|
||||
return await this.raw(sql, { split: false });
|
||||
}
|
||||
|
||||
@@ -637,6 +637,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
AND proc.routine_type = 'PROCEDURE'
|
||||
AND proc.routine_name = '${routine}'
|
||||
AND proc.specific_schema = '${schema}'
|
||||
AND args.data_type != NULL
|
||||
ORDER BY procedure_schema,
|
||||
specific_name,
|
||||
procedure_name,
|
||||
@@ -675,7 +676,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
* @memberof PostgreSQLClient
|
||||
*/
|
||||
async dropRoutine (params) {
|
||||
const sql = `DROP PROCEDURE ${this._schema}.${params.routine}`;
|
||||
const sql = `DROP PROCEDURE "${params.schema}"."${params.routine}"`;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -692,8 +693,8 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
|
||||
try {
|
||||
await this.createRoutine(tempProcedure);
|
||||
await this.dropRoutine({ routine: tempProcedure.name });
|
||||
await this.dropRoutine({ routine: routine.oldName });
|
||||
await this.dropRoutine({ schema: routine.schema, routine: tempProcedure.name });
|
||||
await this.dropRoutine({ schema: routine.schema, routine: routine.oldName });
|
||||
await this.createRoutine(routine);
|
||||
}
|
||||
catch (err) {
|
||||
@@ -715,10 +716,10 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
}, []).join(',')
|
||||
: '';
|
||||
|
||||
if (this._schema !== 'public')
|
||||
await this.use(this._schema);
|
||||
if (routine.schema !== 'public')
|
||||
await this.use(routine.schema);
|
||||
|
||||
const sql = `CREATE PROCEDURE ${this._schema}.${routine.name}(${parameters})
|
||||
const sql = `CREATE PROCEDURE "${routine.schema}"."${routine.name}"(${parameters})
|
||||
LANGUAGE ${routine.language}
|
||||
SECURITY ${routine.security}
|
||||
AS ${routine.sql}`;
|
||||
@@ -804,7 +805,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
* @memberof PostgreSQLClient
|
||||
*/
|
||||
async dropFunction (params) {
|
||||
const sql = `DROP FUNCTION ${this._schema}.${params.func}`;
|
||||
const sql = `DROP FUNCTION "${params.schema}"."${params.func}"`;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -821,8 +822,8 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
|
||||
try {
|
||||
await this.createFunction(tempProcedure);
|
||||
await this.dropFunction({ func: tempProcedure.name });
|
||||
await this.dropFunction({ func: func.oldName });
|
||||
await this.dropFunction({ schema: func.schema, func: tempProcedure.name });
|
||||
await this.dropFunction({ schema: func.schema, func: func.oldName });
|
||||
await this.createFunction(func);
|
||||
}
|
||||
catch (err) {
|
||||
@@ -839,17 +840,17 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
async createFunction (func) {
|
||||
const parameters = 'parameters' in func
|
||||
? func.parameters.reduce((acc, curr) => {
|
||||
acc.push(`${curr.context} ${curr.name} ${curr.type}${curr.length ? `(${curr.length})` : ''}`);
|
||||
acc.push(`${curr.context} ${curr.name || ''} ${curr.type}${curr.length ? `(${curr.length})` : ''}`);
|
||||
return acc;
|
||||
}, []).join(',')
|
||||
: '';
|
||||
|
||||
if (this._schema !== 'public')
|
||||
await this.use(this._schema);
|
||||
if (func.schema !== 'public')
|
||||
await this.use(func.schema);
|
||||
|
||||
const body = func.returns ? func.sql : '$function$\n$function$';
|
||||
|
||||
const sql = `CREATE FUNCTION ${this._schema}.${func.name}(${parameters})
|
||||
const sql = `CREATE FUNCTION "${func.schema}"."${func.name}" (${parameters})
|
||||
RETURNS ${func.returns || 'void'}
|
||||
LANGUAGE ${func.language}
|
||||
SECURITY ${func.security}
|
||||
@@ -867,12 +868,12 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
async alterTriggerFunction (params) {
|
||||
const { func } = params;
|
||||
|
||||
if (this._schema !== 'public')
|
||||
await this.use(this._schema);
|
||||
if (func.schema !== 'public')
|
||||
await this.use(func.schema);
|
||||
|
||||
const body = func.returns ? func.sql : '$function$\n$function$';
|
||||
|
||||
const sql = `CREATE OR REPLACE FUNCTION ${this._schema}.${func.name}()
|
||||
const sql = `CREATE OR REPLACE FUNCTION "${func.schema}"."${func.name}" ()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE ${func.language}
|
||||
AS ${body}`;
|
||||
@@ -887,12 +888,12 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
* @memberof PostgreSQLClient
|
||||
*/
|
||||
async createTriggerFunction (func) {
|
||||
if (this._schema !== 'public')
|
||||
await this.use(this._schema);
|
||||
if (func.schema !== 'public')
|
||||
await this.use(func.schema);
|
||||
|
||||
const body = func.returns ? func.sql : '$function$\r\nBEGIN\r\n\r\nEND\r\n$function$';
|
||||
|
||||
const sql = `CREATE FUNCTION ${this._schema}.${func.name}()
|
||||
const sql = `CREATE FUNCTION "${func.schema}"."${func.name}" ()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE ${func.language}
|
||||
AS ${body}`;
|
||||
@@ -988,11 +989,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
* @memberof PostgreSQLClient
|
||||
*/
|
||||
async createTable (params) {
|
||||
const {
|
||||
name
|
||||
} = params;
|
||||
|
||||
const sql = `CREATE TABLE ${this._schema}.${name} (${name}_id INTEGER NULL); ALTER TABLE ${this._schema}.${name} DROP COLUMN ${name}_id`;
|
||||
const sql = `CREATE TABLE "${params.schema}"."${params.name}" (${params.name}_id INTEGER NULL); ALTER TABLE "${params.schema}"."${params.name}" DROP COLUMN ${params.name}_id`;
|
||||
|
||||
return await this.raw(sql);
|
||||
}
|
||||
@@ -1006,6 +1003,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
async alterTable (params) {
|
||||
const {
|
||||
table,
|
||||
schema,
|
||||
additions,
|
||||
deletions,
|
||||
changes,
|
||||
@@ -1014,8 +1012,8 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
options
|
||||
} = params;
|
||||
|
||||
if (this._schema !== 'public')
|
||||
await this.use(this._schema);
|
||||
if (schema !== 'public')
|
||||
await this.use(schema);
|
||||
|
||||
let sql = '';
|
||||
const alterColumns = [];
|
||||
@@ -1056,7 +1054,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
else if (type === 'UNIQUE')
|
||||
alterColumns.push(`ADD CONSTRAINT ${addition.name} UNIQUE (${fields})`);
|
||||
else
|
||||
manageIndexes.push(`CREATE INDEX ${addition.name} ON ${this._schema}.${table}(${fields})`);
|
||||
manageIndexes.push(`CREATE INDEX ${addition.name} ON "${schema}"."${table}" (${fields})`);
|
||||
});
|
||||
|
||||
// ADD FOREIGN KEYS
|
||||
@@ -1094,7 +1092,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
}
|
||||
|
||||
if (change.orgName !== change.name)
|
||||
renameColumns.push(`ALTER TABLE "${this._schema}"."${table}" RENAME COLUMN "${change.orgName}" TO "${change.name}"`);
|
||||
renameColumns.push(`ALTER TABLE "${schema}"."${table}" RENAME COLUMN "${change.orgName}" TO "${change.name}"`);
|
||||
});
|
||||
|
||||
// CHANGE INDEX
|
||||
@@ -1112,7 +1110,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
else if (type === 'UNIQUE')
|
||||
alterColumns.push(`ADD CONSTRAINT ${change.name} UNIQUE (${fields})`);
|
||||
else
|
||||
manageIndexes.push(`CREATE INDEX ${change.name} ON ${this._schema}.${table}(${fields})`);
|
||||
manageIndexes.push(`CREATE INDEX ${change.name} ON "${schema}"."${table}" (${fields})`);
|
||||
});
|
||||
|
||||
// CHANGE FOREIGN KEYS
|
||||
@@ -1139,10 +1137,10 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
alterColumns.push(`DROP CONSTRAINT ${deletion.constraintName}`);
|
||||
});
|
||||
|
||||
if (alterColumns.length) sql += `ALTER TABLE "${this._schema}"."${table}" ${alterColumns.join(', ')}; `;
|
||||
if (alterColumns.length) sql += `ALTER TABLE "${schema}"."${table}" ${alterColumns.join(', ')}; `;
|
||||
if (createSequences.length) sql = `${createSequences.join(';')}; ${sql}`;
|
||||
if (manageIndexes.length) sql = `${manageIndexes.join(';')}; ${sql}`;
|
||||
if (options.name) sql += `ALTER TABLE "${this._schema}"."${table}" RENAME TO "${options.name}"; `;
|
||||
if (options.name) sql += `ALTER TABLE "${schema}"."${table}" RENAME TO "${options.name}"; `;
|
||||
|
||||
// RENAME
|
||||
if (renameColumns.length) sql = `${renameColumns.join(';')}; ${sql}`;
|
||||
@@ -1157,7 +1155,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
* @memberof PostgreSQLClient
|
||||
*/
|
||||
async duplicateTable (params) {
|
||||
const sql = `CREATE TABLE ${this._schema}.${params.table}_copy (LIKE ${this._schema}.${params.table} INCLUDING ALL)`;
|
||||
const sql = `CREATE TABLE ${params.schema}.${params.table}_copy (LIKE ${params.schema}.${params.table} INCLUDING ALL)`;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -1168,7 +1166,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
* @memberof PostgreSQLClient
|
||||
*/
|
||||
async truncateTable (params) {
|
||||
const sql = `TRUNCATE TABLE ${this._schema}.${params.table}`;
|
||||
const sql = `TRUNCATE TABLE ${params.schema}.${params.table}`;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -1179,7 +1177,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
* @memberof PostgreSQLClient
|
||||
*/
|
||||
async dropTable (params) {
|
||||
const sql = `DROP TABLE ${this._schema}.${params.table}`;
|
||||
const sql = `DROP TABLE ${params.schema}.${params.table}`;
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
||||
@@ -1250,18 +1248,20 @@ export class PostgreSQLClient extends AntaresCore {
|
||||
* @memberof PostgreSQLClient
|
||||
*/
|
||||
async raw (sql, args) {
|
||||
sql = sql.replace(/(\/\*(.|[\r\n])*?\*\/)|(--(.*|[\r\n]))/gm, '');
|
||||
|
||||
args = {
|
||||
nest: false,
|
||||
details: false,
|
||||
split: true,
|
||||
comments: true,
|
||||
...args
|
||||
};
|
||||
|
||||
if (args.schema && args.schema !== 'public')
|
||||
await this.use(args.schema);
|
||||
|
||||
if (!args.comments)
|
||||
sql = sql.replace(/(\/\*(.|[\r\n])*?\*\/)|(--(.*|[\r\n]))/gm, '');// Remove comments
|
||||
|
||||
const resultsArr = [];
|
||||
let paramsArr = [];
|
||||
const queries = args.split
|
||||
|
@@ -16,7 +16,6 @@
|
||||
<TheNotificationsBoard />
|
||||
<TheScratchpad v-if="isScratchpad" />
|
||||
<ModalSettings v-if="isSettingModal" />
|
||||
<ModalDiscardChanges v-if="isUnsavedDiscardModal" />
|
||||
<BaseTextEditor class="d-none" value="" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -39,7 +38,6 @@ export default {
|
||||
WorkspaceAddConnectionPanel: () => import(/* webpackChunkName: "WorkspaceAddConnectionPanel" */'@/components/WorkspaceAddConnectionPanel'),
|
||||
ModalSettings: () => import(/* webpackChunkName: "ModalSettings" */'@/components/ModalSettings'),
|
||||
TheScratchpad: () => import(/* webpackChunkName: "TheScratchpad" */'@/components/TheScratchpad'),
|
||||
ModalDiscardChanges: () => import(/* webpackChunkName: "ModalDiscardChanges" */'@/components/ModalDiscardChanges'),
|
||||
BaseTextEditor: () => import(/* webpackChunkName: "BaseTextEditor" */'@/components/BaseTextEditor')
|
||||
},
|
||||
data () {
|
||||
|
@@ -41,7 +41,7 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer text-light">
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary mr-2" @click.stop="sendCredentials">
|
||||
{{ $t('word.send') }}
|
||||
</button>
|
||||
|
@@ -2,8 +2,8 @@
|
||||
<ConfirmModal
|
||||
:confirm-text="$t('word.discard')"
|
||||
:cancel-text="$t('word.stay')"
|
||||
@confirm="discardUnsavedChanges"
|
||||
@hide="closeUnsavedChangesModal"
|
||||
@confirm="$emit('confirm')"
|
||||
@hide="$emit('close')"
|
||||
>
|
||||
<template slot="header">
|
||||
<div class="d-flex">
|
||||
@@ -19,7 +19,6 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex';
|
||||
import ConfirmModal from '@/components/BaseConfirmModal';
|
||||
|
||||
export default {
|
||||
@@ -34,13 +33,6 @@ export default {
|
||||
window.removeEventListener('keydown', this.onKey);
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
discardUnsavedChanges: 'workspaces/discardUnsavedChanges',
|
||||
closeUnsavedChangesModal: 'workspaces/closeUnsavedChangesModal'
|
||||
}),
|
||||
closeModal () {
|
||||
this.$emit('close');
|
||||
},
|
||||
onKey (e) {
|
||||
e.stopPropagation();
|
||||
if (e.key === 'Escape')
|
||||
|
@@ -53,7 +53,7 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer text-light">
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary mr-2" @click.stop="updateSchema">
|
||||
{{ $t('word.update') }}
|
||||
</button>
|
||||
@@ -72,7 +72,7 @@ import Schema from '@/ipc-api/Schema';
|
||||
export default {
|
||||
name: 'ModalEditSchema',
|
||||
props: {
|
||||
selectedDatabase: String
|
||||
selectedSchema: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -99,7 +99,7 @@ export default {
|
||||
async created () {
|
||||
let actualCollation;
|
||||
try {
|
||||
const { status, response } = await Schema.getDatabaseCollation({ uid: this.selectedWorkspace, database: this.selectedDatabase });
|
||||
const { status, response } = await Schema.getDatabaseCollation({ uid: this.selectedWorkspace, database: this.selectedSchema });
|
||||
|
||||
if (status === 'success')
|
||||
actualCollation = response;
|
||||
@@ -112,8 +112,8 @@ export default {
|
||||
}
|
||||
|
||||
this.database = {
|
||||
name: this.selectedDatabase,
|
||||
prevName: this.selectedDatabase,
|
||||
name: this.selectedSchema,
|
||||
prevName: this.selectedSchema,
|
||||
collation: actualCollation || this.defaultCollation,
|
||||
prevCollation: actualCollation || this.defaultCollation
|
||||
};
|
||||
|
@@ -52,7 +52,7 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer text-light columns">
|
||||
<div class="modal-footer columns">
|
||||
<div class="column d-flex" :class="hasFakes ? 'col-4' : 'col-2'">
|
||||
<div class="input-group tooltip tooltip-right" :data-tooltip="$t('message.numberOfInserts')">
|
||||
<input
|
||||
|
@@ -49,7 +49,7 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer text-light">
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
class="btn btn-primary mr-2"
|
||||
:class="{'loading': isLoading}"
|
||||
|
@@ -86,7 +86,7 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer text-light">
|
||||
<div class="modal-footer">
|
||||
<div class="input-group col-3 tooltip tooltip-right" :data-tooltip="$t('message.numberOfInserts')">
|
||||
<input
|
||||
v-model="nInserts"
|
||||
|
@@ -104,6 +104,19 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-6 col-sm-12">
|
||||
<label class="form-label">
|
||||
{{ $t('message.restorePreviourSession') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-6 col-sm-12">
|
||||
<label class="form-switch d-inline-block" @click.prevent="toggleRestoreSession">
|
||||
<input type="checkbox" :checked="restoreTabs">
|
||||
<i class="form-icon" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-6 col-sm-12">
|
||||
<label class="form-label">
|
||||
@@ -369,6 +382,7 @@ export default {
|
||||
selectedAutoComplete: 'settings/getAutoComplete',
|
||||
selectedLineWrap: 'settings/getLineWrap',
|
||||
notificationsTimeout: 'settings/getNotificationsTimeout',
|
||||
restoreTabs: 'settings/getRestoreTabs',
|
||||
applicationTheme: 'settings/getApplicationTheme',
|
||||
editorTheme: 'settings/getEditorTheme',
|
||||
editorFontSize: 'settings/getEditorFontSize',
|
||||
@@ -423,6 +437,7 @@ ORDER BY
|
||||
closeModal: 'application/hideSettingModal',
|
||||
changeLocale: 'settings/changeLocale',
|
||||
changePageSize: 'settings/changePageSize',
|
||||
changeRestoreTabs: 'settings/changeRestoreTabs',
|
||||
changeAutoComplete: 'settings/changeAutoComplete',
|
||||
changeLineWrap: 'settings/changeLineWrap',
|
||||
changeApplicationTheme: 'settings/changeApplicationTheme',
|
||||
@@ -447,6 +462,9 @@ ORDER BY
|
||||
if (e.key === 'Escape')
|
||||
this.closeModal();
|
||||
},
|
||||
toggleRestoreSession () {
|
||||
this.changeRestoreTabs(!this.restoreTabs);
|
||||
},
|
||||
toggleAutoComplete () {
|
||||
this.changeAutoComplete(!this.selectedAutoComplete);
|
||||
},
|
||||
|
@@ -8,21 +8,25 @@
|
||||
@close-context="isContext = false"
|
||||
/>
|
||||
<ul class="settingbar-elements">
|
||||
<draggable v-model="connections">
|
||||
<Draggable
|
||||
v-model="connections"
|
||||
@start="isDragging = true"
|
||||
@end="dragStop"
|
||||
>
|
||||
<li
|
||||
v-for="connection in connections"
|
||||
:key="connection.uid"
|
||||
draggable="true"
|
||||
class="settingbar-element btn btn-link ex-tooltip"
|
||||
:class="{'selected': connection.uid === selectedWorkspace}"
|
||||
@click="selectWorkspace(connection.uid)"
|
||||
@click.stop="selectWorkspace(connection.uid)"
|
||||
@contextmenu.prevent="contextMenu($event, connection)"
|
||||
@mouseover.self="tooltipPosition"
|
||||
>
|
||||
<i class="settingbar-element-icon dbi" :class="`dbi-${connection.client} ${getStatusBadge(connection.uid)}`" />
|
||||
<span class="ex-tooltip-content">{{ getConnectionName(connection.uid) }}</span>
|
||||
<span v-if="!isDragging" class="ex-tooltip-content">{{ getConnectionName(connection.uid) }}</span>
|
||||
</li>
|
||||
</draggable>
|
||||
</Draggable>
|
||||
<li
|
||||
class="settingbar-element btn btn-link ex-tooltip"
|
||||
:class="{'selected': 'NEW' === selectedWorkspace}"
|
||||
@@ -52,19 +56,20 @@
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex';
|
||||
import draggable from 'vuedraggable';
|
||||
import Draggable from 'vuedraggable';
|
||||
import SettingBarContext from '@/components/SettingBarContext';
|
||||
|
||||
export default {
|
||||
name: 'TheSettingBar',
|
||||
components: {
|
||||
draggable,
|
||||
Draggable,
|
||||
SettingBarContext
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
dragElement: null,
|
||||
isContext: false,
|
||||
isDragging: false,
|
||||
contextEvent: null,
|
||||
contextConnection: {},
|
||||
scale: 0
|
||||
@@ -106,7 +111,7 @@ export default {
|
||||
return connection.ask ? '' : `${connection.user + '@'}${connection.host}:${connection.port}`;
|
||||
},
|
||||
tooltipPosition (e) {
|
||||
const el = e.target;
|
||||
const el = e.target ? e.target : e;
|
||||
const fromTop = window.pageYOffset + el.getBoundingClientRect().top - (el.offsetHeight / 4);
|
||||
el.querySelector('.ex-tooltip-content').style.top = `${fromTop}px`;
|
||||
},
|
||||
@@ -125,6 +130,13 @@ export default {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
},
|
||||
dragStop (e) {
|
||||
this.isDragging = false;
|
||||
|
||||
setTimeout(() => {
|
||||
this.tooltipPosition(e.originalEvent.target.parentNode);
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -235,7 +247,13 @@ export default {
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
&:hover .ex-tooltip-content {
|
||||
&.sortable-chosen {
|
||||
.ex-tooltip-content {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover:not(.selected) .ex-tooltip-content {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
@@ -6,12 +6,163 @@
|
||||
:is-selected="isSelected"
|
||||
/>
|
||||
<div v-if="workspace.connection_status === 'connected'" class="workspace-tabs column columns col-gapless">
|
||||
<ul
|
||||
id="tabWrap"
|
||||
<Draggable
|
||||
ref="tabWrap"
|
||||
v-model="draggableTabs"
|
||||
tag="ul"
|
||||
group="tabs"
|
||||
class="tab tab-block column col-12"
|
||||
draggable=".tab-draggable"
|
||||
@mouseover.native="addWheelEvent"
|
||||
>
|
||||
<li class="tab-item dropdown tools-dropdown">
|
||||
<li
|
||||
v-for="(tab, i) of draggableTabs"
|
||||
:key="i"
|
||||
class="tab-item tab-draggable"
|
||||
draggable="true"
|
||||
:class="{'active': selectedTab === tab.uid}"
|
||||
@mousedown.left="selectTab({uid: workspace.uid, tab: tab.uid})"
|
||||
@mouseup.middle="closeTab(tab)"
|
||||
>
|
||||
<a v-if="tab.type === 'query'" class="tab-link">
|
||||
<i class="mdi mdi-18px mdi-code-tags mr-1" />
|
||||
<span>
|
||||
Query #{{ tab.index }}
|
||||
<span
|
||||
class="btn btn-clear"
|
||||
:title="$t('word.close')"
|
||||
@click.stop="closeTab(tab)"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
v-else-if="tab.type === 'temp-data'"
|
||||
class="tab-link"
|
||||
@dblclick="openAsPermanentTab(tab)"
|
||||
>
|
||||
<i class="mdi mdi-18px mr-1" :class="tab.elementType === 'view' ? 'mdi-table-eye' : 'mdi-table'" />
|
||||
<span :title="`${$t('word.data').toUpperCase()}: ${tab.elementType}`">
|
||||
<span class=" text-italic">{{ tab.elementName }}</span>
|
||||
<span
|
||||
class="btn btn-clear"
|
||||
:title="$t('word.close')"
|
||||
@click.stop="closeTab(tab)"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a v-else-if="tab.type === 'data'" class="tab-link">
|
||||
<i class="mdi mdi-18px mr-1" :class="tab.elementType === 'view' ? 'mdi-table-eye' : 'mdi-table'" />
|
||||
<span :title="`${$t('word.data').toUpperCase()}: ${tab.elementType}`">
|
||||
{{ tab.elementName }}
|
||||
<span
|
||||
class="btn btn-clear"
|
||||
:title="$t('word.close')"
|
||||
@click.stop="closeTab(tab)"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
v-else-if="tab.type === 'table-props'"
|
||||
class="tab-link"
|
||||
:class="{'badge': tab.isChanged}"
|
||||
>
|
||||
<i class="mdi mdi-tune-vertical-variant mdi-18px mr-1" />
|
||||
<span :title="`${$t('word.settings').toUpperCase()}: ${tab.elementType}`">
|
||||
{{ tab.elementName }}
|
||||
<span
|
||||
class="btn btn-clear"
|
||||
:title="$t('word.close')"
|
||||
@click.stop="closeTab(tab)"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
v-else-if="tab.type === 'view-props'"
|
||||
class="tab-link"
|
||||
:class="{'badge': tab.isChanged}"
|
||||
>
|
||||
<i class="mdi mdi-tune-vertical-variant mdi-18px mr-1" />
|
||||
<span :title="`${$t('word.settings').toUpperCase()}: ${tab.elementType}`">
|
||||
{{ tab.elementName }}
|
||||
<span
|
||||
class="btn btn-clear"
|
||||
:title="$t('word.close')"
|
||||
@click.stop="closeTab(tab)"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
v-else-if="tab.type.includes('temp-')"
|
||||
class="tab-link"
|
||||
:class="{'badge': tab.isChanged}"
|
||||
@dblclick="openAsPermanentTab(tab)"
|
||||
>
|
||||
<i class="mdi mdi-18px mdi-tune-vertical-variant mr-1" />
|
||||
<span :title="`${$t('word.settings').toUpperCase()}: ${tab.elementType}`">
|
||||
<span class=" text-italic">{{ tab.elementName }}</span>
|
||||
<span
|
||||
class="btn btn-clear"
|
||||
:title="$t('word.close')"
|
||||
@click.stop="closeTab(tab)"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
v-else
|
||||
class="tab-link"
|
||||
:class="{'badge': tab.isChanged}"
|
||||
>
|
||||
<i class="mdi mdi-18px mdi-tune-vertical-variant mr-1" />
|
||||
<span :title="`${$t('word.settings').toUpperCase()}: ${tab.elementType}`">
|
||||
{{ tab.elementName }}
|
||||
<span
|
||||
class="btn btn-clear"
|
||||
:title="$t('word.close')"
|
||||
@click.stop="closeTab(tab)"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<!-- <a
|
||||
v-else-if="tab.type === 'temp-trigger-function-props'"
|
||||
class="tab-link"
|
||||
:class="{'badge': tab.isChanged}"
|
||||
@dblclick="openAsPermanentTab(tab)"
|
||||
>
|
||||
<i class="mdi mdi-18px mdi-tune-vertical-variant mr-1" />
|
||||
<span :title="`${$t('word.settings').toUpperCase()}: ${tab.elementType}`">
|
||||
<span class=" text-italic">{{ tab.elementName }}</span>
|
||||
<span
|
||||
class="btn btn-clear"
|
||||
:title="$t('word.close')"
|
||||
@click.stop="closeTab(tab)"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
v-else-if="tab.type === 'trigger-function-props'"
|
||||
class="tab-link"
|
||||
:class="{'badge': tab.isChanged}"
|
||||
>
|
||||
<i class="mdi mdi-18px mdi-tune-vertical-variant mr-1" />
|
||||
<span :title="`${$t('word.settings').toUpperCase()}: ${tab.elementType}`">
|
||||
{{ tab.elementName }}
|
||||
<span
|
||||
class="btn btn-clear"
|
||||
:title="$t('word.close')"
|
||||
@click.stop="closeTab(tab)"
|
||||
/>
|
||||
</span>
|
||||
</a> -->
|
||||
</li>
|
||||
<li slot="header" class="tab-item dropdown tools-dropdown">
|
||||
<a
|
||||
class="tab-link workspace-tools-link dropdown-toggle"
|
||||
tabindex="0"
|
||||
@@ -48,113 +199,97 @@
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li
|
||||
v-if="schemaChild && isSettingSupported"
|
||||
class="tab-item"
|
||||
:class="{'active': selectedTab === 'prop'}"
|
||||
@click="selectTab({uid: workspace.uid, tab: 'prop'})"
|
||||
>
|
||||
<a class="tab-link">
|
||||
<i class="mdi mdi-18px mdi-tune-vertical-variant mr-1" />
|
||||
<span :title="schemaChild">{{ $t('word.settings').toUpperCase() }}: {{ schemaChild }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
v-if="workspace.breadcrumbs.table || workspace.breadcrumbs.view"
|
||||
class="tab-item"
|
||||
:class="{'active': selectedTab === 'data'}"
|
||||
@click="selectTab({uid: workspace.uid, tab: 'data'})"
|
||||
>
|
||||
<a class="tab-link">
|
||||
<i class="mdi mdi-18px mr-1" :class="workspace.breadcrumbs.table ? 'mdi-table' : 'mdi-table-eye'" />
|
||||
<span :title="schemaChild">{{ $t('word.data').toUpperCase() }}: {{ schemaChild }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
v-for="tab of queryTabs"
|
||||
:key="tab.uid"
|
||||
class="tab-item"
|
||||
:class="{'active': selectedTab === tab.uid}"
|
||||
@click="selectTab({uid: workspace.uid, tab: tab.uid})"
|
||||
@mouseup.middle="closeTab(tab.uid)"
|
||||
>
|
||||
<a class="tab-link">
|
||||
<i class="mdi mdi-18px mdi-code-tags mr-1" />
|
||||
<span>
|
||||
Query #{{ tab.index }}
|
||||
<span
|
||||
v-if="queryTabs.length > 1"
|
||||
class="btn btn-clear"
|
||||
:title="$t('word.close')"
|
||||
@click.stop="closeTab(tab.uid)"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="tab-item">
|
||||
<li slot="footer" class="tab-item">
|
||||
<a
|
||||
class="tab-add"
|
||||
:title="$t('message.openNewTab')"
|
||||
@click="addTab"
|
||||
@click="addQueryTab"
|
||||
>
|
||||
<i class="mdi mdi-24px mdi-plus" />
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<WorkspacePropsTab
|
||||
v-show="selectedTab === 'prop' && workspace.breadcrumbs.table"
|
||||
:is-selected="selectedTab === 'prop'"
|
||||
:connection="connection"
|
||||
:table="workspace.breadcrumbs.table"
|
||||
/>
|
||||
<WorkspacePropsTabView
|
||||
v-show="selectedTab === 'prop' && workspace.breadcrumbs.view"
|
||||
:is-selected="selectedTab === 'prop'"
|
||||
:connection="connection"
|
||||
:view="workspace.breadcrumbs.view"
|
||||
/>
|
||||
<WorkspacePropsTabTrigger
|
||||
v-show="selectedTab === 'prop' && workspace.breadcrumbs.trigger"
|
||||
:is-selected="selectedTab === 'prop'"
|
||||
:connection="connection"
|
||||
:trigger="workspace.breadcrumbs.trigger"
|
||||
/>
|
||||
<WorkspacePropsTabRoutine
|
||||
v-show="selectedTab === 'prop' && workspace.breadcrumbs.procedure"
|
||||
:is-selected="selectedTab === 'prop'"
|
||||
:connection="connection"
|
||||
:routine="workspace.breadcrumbs.procedure"
|
||||
/>
|
||||
<WorkspacePropsTabFunction
|
||||
v-show="selectedTab === 'prop' && workspace.breadcrumbs.function"
|
||||
:is-selected="selectedTab === 'prop'"
|
||||
:connection="connection"
|
||||
:function="workspace.breadcrumbs.function"
|
||||
/>
|
||||
<WorkspacePropsTabTriggerFunction
|
||||
v-show="selectedTab === 'prop' && workspace.breadcrumbs.triggerFunction"
|
||||
:is-selected="selectedTab === 'prop'"
|
||||
:connection="connection"
|
||||
:function="workspace.breadcrumbs.triggerFunction"
|
||||
/>
|
||||
<WorkspacePropsTabScheduler
|
||||
</Draggable>
|
||||
<!--<WorkspacePropsTabScheduler
|
||||
v-show="selectedTab === 'prop' && workspace.breadcrumbs.scheduler"
|
||||
:is-selected="selectedTab === 'prop'"
|
||||
:connection="connection"
|
||||
:scheduler="workspace.breadcrumbs.scheduler"
|
||||
/>
|
||||
<WorkspaceTableTab
|
||||
v-show="selectedTab === 'data'"
|
||||
:connection="connection"
|
||||
:table="workspace.breadcrumbs.table || workspace.breadcrumbs.view"
|
||||
/>
|
||||
<WorkspaceQueryTab
|
||||
v-for="tab of queryTabs"
|
||||
:key="tab.uid"
|
||||
:tab="tab"
|
||||
:is-selected="selectedTab === tab.uid"
|
||||
:connection="connection"
|
||||
/>
|
||||
/> -->
|
||||
<WorkspaceEmptyState v-if="!workspace.tabs.length" @new-tab="addQueryTab" />
|
||||
<template v-for="tab of workspace.tabs">
|
||||
<WorkspaceQueryTab
|
||||
v-if="tab.type==='query'"
|
||||
:key="tab.uid"
|
||||
:tab="tab"
|
||||
:is-selected="selectedTab === tab.uid"
|
||||
:connection="connection"
|
||||
/>
|
||||
<WorkspaceTableTab
|
||||
v-else-if="['temp-data', 'data'].includes(tab.type)"
|
||||
:key="tab.uid"
|
||||
:connection="connection"
|
||||
:is-selected="selectedTab === tab.uid"
|
||||
:table="tab.elementName"
|
||||
:schema="tab.schema"
|
||||
:element-type="tab.elementType"
|
||||
/>
|
||||
<WorkspacePropsTab
|
||||
v-else-if="tab.type === 'table-props'"
|
||||
:key="tab.uid"
|
||||
:connection="connection"
|
||||
:is-selected="selectedTab === tab.uid"
|
||||
:table="tab.elementName"
|
||||
:schema="tab.schema"
|
||||
/>
|
||||
<WorkspacePropsTabView
|
||||
v-else-if="tab.type === 'view-props'"
|
||||
:key="tab.uid"
|
||||
:is-selected="selectedTab === tab.uid"
|
||||
:connection="connection"
|
||||
:view="tab.elementName"
|
||||
:schema="tab.schema"
|
||||
/>
|
||||
<WorkspacePropsTabTrigger
|
||||
v-else-if="['temp-trigger-props', 'trigger-props'].includes(tab.type)"
|
||||
:key="tab.uid"
|
||||
:connection="connection"
|
||||
:is-selected="selectedTab === tab.uid"
|
||||
:trigger="tab.elementName"
|
||||
:schema="tab.schema"
|
||||
/>
|
||||
<WorkspacePropsTabTriggerFunction
|
||||
v-else-if="['temp-trigger-function-props', 'trigger-function-props'].includes(tab.type)"
|
||||
:key="tab.uid"
|
||||
:connection="connection"
|
||||
:is-selected="selectedTab === tab.uid"
|
||||
:function="tab.elementName"
|
||||
:schema="tab.schema"
|
||||
/>
|
||||
<WorkspacePropsTabRoutine
|
||||
v-else-if="['temp-routine-props', 'routine-props'].includes(tab.type)"
|
||||
:key="tab.uid"
|
||||
:connection="connection"
|
||||
:is-selected="selectedTab === tab.uid"
|
||||
:routine="tab.elementName"
|
||||
:schema="tab.schema"
|
||||
/>
|
||||
<WorkspacePropsTabFunction
|
||||
v-else-if="['temp-function-props', 'function-props'].includes(tab.type)"
|
||||
:key="tab.uid"
|
||||
:connection="connection"
|
||||
:is-selected="selectedTab === tab.uid"
|
||||
:function="tab.elementName"
|
||||
:schema="tab.schema"
|
||||
/>
|
||||
<WorkspacePropsTabScheduler
|
||||
v-else-if="['temp-scheduler-props', 'scheduler-props'].includes(tab.type)"
|
||||
:key="tab.uid"
|
||||
:connection="connection"
|
||||
:is-selected="selectedTab === tab.uid"
|
||||
:scheduler="tab.elementName"
|
||||
:schema="tab.schema"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
<WorkspaceEditConnectionPanel v-else :connection="connection" />
|
||||
<ModalProcessesList
|
||||
@@ -162,12 +297,20 @@
|
||||
:connection="connection"
|
||||
@close="hideProcessesModal"
|
||||
/>
|
||||
|
||||
<ModalDiscardChanges
|
||||
v-if="unsavedTab"
|
||||
@confirm="closeTab(unsavedTab, true)"
|
||||
@close="unsavedTab = null"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex';
|
||||
import Draggable from 'vuedraggable';
|
||||
import Connection from '@/ipc-api/Connection';
|
||||
import WorkspaceEmptyState from '@/components/WorkspaceEmptyState';
|
||||
import WorkspaceExploreBar from '@/components/WorkspaceExploreBar';
|
||||
import WorkspaceEditConnectionPanel from '@/components/WorkspaceEditConnectionPanel';
|
||||
import WorkspaceQueryTab from '@/components/WorkspaceQueryTab';
|
||||
@@ -175,15 +318,18 @@ import WorkspaceTableTab from '@/components/WorkspaceTableTab';
|
||||
import WorkspacePropsTab from '@/components/WorkspacePropsTab';
|
||||
import WorkspacePropsTabView from '@/components/WorkspacePropsTabView';
|
||||
import WorkspacePropsTabTrigger from '@/components/WorkspacePropsTabTrigger';
|
||||
import WorkspacePropsTabTriggerFunction from '@/components/WorkspacePropsTabTriggerFunction';
|
||||
import WorkspacePropsTabRoutine from '@/components/WorkspacePropsTabRoutine';
|
||||
import WorkspacePropsTabFunction from '@/components/WorkspacePropsTabFunction';
|
||||
import WorkspacePropsTabTriggerFunction from '@/components/WorkspacePropsTabTriggerFunction';
|
||||
import WorkspacePropsTabScheduler from '@/components/WorkspacePropsTabScheduler';
|
||||
import ModalProcessesList from '@/components/ModalProcessesList';
|
||||
import ModalDiscardChanges from '@/components/ModalDiscardChanges';
|
||||
|
||||
export default {
|
||||
name: 'Workspace',
|
||||
components: {
|
||||
Draggable,
|
||||
WorkspaceEmptyState,
|
||||
WorkspaceExploreBar,
|
||||
WorkspaceEditConnectionPanel,
|
||||
WorkspaceQueryTab,
|
||||
@@ -191,11 +337,12 @@ export default {
|
||||
WorkspacePropsTab,
|
||||
WorkspacePropsTabView,
|
||||
WorkspacePropsTabTrigger,
|
||||
WorkspacePropsTabTriggerFunction,
|
||||
WorkspacePropsTabRoutine,
|
||||
WorkspacePropsTabFunction,
|
||||
WorkspacePropsTabTriggerFunction,
|
||||
WorkspacePropsTabScheduler,
|
||||
ModalProcessesList
|
||||
ModalProcessesList,
|
||||
ModalDiscardChanges
|
||||
},
|
||||
props: {
|
||||
connection: Object
|
||||
@@ -203,7 +350,8 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
hasWheelEvent: false,
|
||||
isProcessesModal: false
|
||||
isProcessesModal: false,
|
||||
unsavedTab: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -214,6 +362,14 @@ export default {
|
||||
workspace () {
|
||||
return this.getWorkspace(this.connection.uid);
|
||||
},
|
||||
draggableTabs: {
|
||||
get () {
|
||||
return this.workspace.tabs;
|
||||
},
|
||||
set (val) {
|
||||
this.updateTabs({ uid: this.connection.uid, tabs: val });
|
||||
}
|
||||
},
|
||||
isSelected () {
|
||||
return this.selectedWorkspace === this.connection.uid;
|
||||
},
|
||||
@@ -228,29 +384,7 @@ export default {
|
||||
return false;
|
||||
},
|
||||
selectedTab () {
|
||||
if (
|
||||
(
|
||||
this.workspace.breadcrumbs.table === null &&
|
||||
this.workspace.breadcrumbs.view === null &&
|
||||
this.workspace.breadcrumbs.trigger === null &&
|
||||
this.workspace.breadcrumbs.procedure === null &&
|
||||
this.workspace.breadcrumbs.function === null &&
|
||||
this.workspace.breadcrumbs.triggerFunction === null &&
|
||||
this.workspace.breadcrumbs.scheduler === null &&
|
||||
['data', 'prop'].includes(this.workspace.selected_tab)
|
||||
) ||
|
||||
(
|
||||
this.workspace.breadcrumbs.table === null &&
|
||||
this.workspace.breadcrumbs.view === null &&
|
||||
this.workspace.selected_tab === 'data'
|
||||
)
|
||||
)
|
||||
return this.queryTabs[0].uid;
|
||||
|
||||
return this.queryTabs.find(tab => tab.uid === this.workspace.selected_tab) ||
|
||||
['data', 'prop'].includes(this.workspace.selected_tab)
|
||||
? this.workspace.selected_tab
|
||||
: this.queryTabs[0].uid;
|
||||
return this.workspace.selected_tab;
|
||||
},
|
||||
queryTabs () {
|
||||
return this.workspace.tabs.filter(tab => tab.type === 'query');
|
||||
@@ -269,14 +403,6 @@ export default {
|
||||
if (isInitiated)
|
||||
this.connectWorkspace(this.connection);
|
||||
},
|
||||
mounted () {
|
||||
if (this.$refs.tabWrap) {
|
||||
this.$refs.tabWrap.addEventListener('wheel', e => {
|
||||
if (e.deltaY > 0) this.$refs.tabWrap.scrollLeft += 50;
|
||||
else this.$refs.tabWrap.scrollLeft -= 50;
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
addWorkspace: 'workspaces/addWorkspace',
|
||||
@@ -284,28 +410,55 @@ export default {
|
||||
removeConnected: 'workspaces/removeConnected',
|
||||
selectTab: 'workspaces/selectTab',
|
||||
newTab: 'workspaces/newTab',
|
||||
removeTab: 'workspaces/removeTab'
|
||||
removeTab: 'workspaces/removeTab',
|
||||
updateTabs: 'workspaces/updateTabs'
|
||||
}),
|
||||
addTab () {
|
||||
this.newTab({ uid: this.connection.uid });
|
||||
|
||||
if (!this.hasWheelEvent) {
|
||||
this.$refs.tabWrap.addEventListener('wheel', e => {
|
||||
if (e.deltaY > 0) this.$refs.tabWrap.scrollLeft += 50;
|
||||
else this.$refs.tabWrap.scrollLeft -= 50;
|
||||
});
|
||||
this.hasWheelEvent = true;
|
||||
}
|
||||
addQueryTab () {
|
||||
this.newTab({ uid: this.connection.uid, type: 'query' });
|
||||
},
|
||||
closeTab (tUid) {
|
||||
if (this.queryTabs.length === 1) return;
|
||||
this.removeTab({ uid: this.connection.uid, tab: tUid });
|
||||
openAsPermanentTab (tab) {
|
||||
const permanentTabs = {
|
||||
table: 'data',
|
||||
view: 'data',
|
||||
trigger: 'trigger-props',
|
||||
triggerFunction: 'trigger-function-props',
|
||||
function: 'function-props',
|
||||
routine: 'routine-props',
|
||||
scheduler: 'scheduler-props'
|
||||
};
|
||||
|
||||
this.newTab({
|
||||
uid: this.connection.uid,
|
||||
schema: tab.schema,
|
||||
elementName: tab.elementName,
|
||||
type: permanentTabs[tab.elementType],
|
||||
elementType: tab.elementType
|
||||
});
|
||||
},
|
||||
closeTab (tab, force) {
|
||||
this.unsavedTab = null;
|
||||
// if (tab.type === 'query' && this.queryTabs.length === 1) return;
|
||||
if (!force && tab.isChanged) {
|
||||
this.unsavedTab = tab;
|
||||
return;
|
||||
}
|
||||
|
||||
this.removeTab({ uid: this.connection.uid, tab: tab.uid });
|
||||
},
|
||||
showProcessesModal () {
|
||||
this.isProcessesModal = true;
|
||||
},
|
||||
hideProcessesModal () {
|
||||
this.isProcessesModal = false;
|
||||
},
|
||||
addWheelEvent () {
|
||||
if (!this.hasWheelEvent) {
|
||||
this.$refs.tabWrap.$el.addEventListener('wheel', e => {
|
||||
if (e.deltaY > 0) this.$refs.tabWrap.$el.scrollLeft += 50;
|
||||
else this.$refs.tabWrap.$el.scrollLeft -= 50;
|
||||
});
|
||||
this.hasWheelEvent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -334,20 +487,35 @@ export default {
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
max-width: 12rem;
|
||||
width: fit-content;
|
||||
flex: initial;
|
||||
|
||||
> a {
|
||||
padding: 0.2rem 0.8rem;
|
||||
padding: 0.2rem 0.6rem;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
opacity: 0.7;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
&.badge::after {
|
||||
position: absolute;
|
||||
right: 35px;
|
||||
top: 25px;
|
||||
}
|
||||
|
||||
.btn-clear {
|
||||
margin-left: 0.5rem;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
|
||||
.btn-clear {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.tab-add {
|
||||
@@ -366,9 +534,15 @@ export default {
|
||||
|
||||
&.active a {
|
||||
opacity: 1;
|
||||
|
||||
.btn-clear {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.tools-dropdown {
|
||||
height: 34px;
|
||||
|
||||
.tab-link:focus {
|
||||
opacity: 1;
|
||||
outline: 0;
|
||||
|
55
src/renderer/components/WorkspaceEmptyState.vue
Normal file
55
src/renderer/components/WorkspaceEmptyState.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<div class="column col-12 empty">
|
||||
<div class="empty-icon">
|
||||
<img :src="require(`@/images/logo-${applicationTheme}.svg`).default" width="200">
|
||||
</div>
|
||||
<p class="h6 empty-subtitle">
|
||||
{{ $t('message.noOpenTabs') }}
|
||||
</p>
|
||||
<div class="empty-action">
|
||||
<button class="btn btn-gray d-flex" @click="$emit('new-tab')">
|
||||
<i class="mdi mdi-24px mdi-tab-plus mr-2" />
|
||||
{{ $t('message.openNewTab') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex';
|
||||
export default {
|
||||
name: 'WorkspaceEmptyState',
|
||||
computed: {
|
||||
...mapGetters({
|
||||
applicationTheme: 'settings/getApplicationTheme',
|
||||
getWorkspace: 'workspaces/getWorkspace',
|
||||
selectedWorkspace: 'workspaces/getSelected'
|
||||
}),
|
||||
workspace () {
|
||||
return this.getWorkspace(this.selectedWorkspace);
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.changeBreadcrumbs({ schema: this.workspace.breadcrumbs.schema });
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs'
|
||||
})
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.empty {
|
||||
height: 100%;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
</style>
|
@@ -21,7 +21,7 @@
|
||||
@click="refresh"
|
||||
/>
|
||||
<i
|
||||
class="mdi mdi-18px mdi-power-plug-off c-hand"
|
||||
class="mdi mdi-18px mdi-power c-hand"
|
||||
:title="$t('word.disconnect')"
|
||||
@click="disconnectWorkspace(connection.uid)"
|
||||
/>
|
||||
@@ -100,7 +100,7 @@
|
||||
/>
|
||||
<DatabaseContext
|
||||
v-if="isDatabaseContext"
|
||||
:selected-database="selectedDatabase"
|
||||
:selected-schema="selectedSchema"
|
||||
:context-event="databaseContextEvent"
|
||||
@close-context="closeDatabaseContext"
|
||||
@show-create-table-modal="showCreateTableModal"
|
||||
@@ -114,6 +114,7 @@
|
||||
/>
|
||||
<TableContext
|
||||
v-if="isTableContext"
|
||||
:selected-schema="selectedSchema"
|
||||
:selected-table="selectedTable"
|
||||
:context-event="tableContextEvent"
|
||||
@close-context="closeTableContext"
|
||||
@@ -122,6 +123,7 @@
|
||||
<MiscContext
|
||||
v-if="isMiscContext"
|
||||
:selected-misc="selectedMisc"
|
||||
:selected-schema="selectedSchema"
|
||||
:context-event="miscContextEvent"
|
||||
@close-context="closeMiscContext"
|
||||
@reload="refresh"
|
||||
@@ -129,6 +131,7 @@
|
||||
<MiscFolderContext
|
||||
v-if="isMiscFolderContext"
|
||||
:selected-misc="selectedMisc"
|
||||
:selected-schema="selectedSchema"
|
||||
:context-event="miscContextEvent"
|
||||
@show-create-trigger-modal="showCreateTriggerModal"
|
||||
@show-create-routine-modal="showCreateRoutineModal"
|
||||
@@ -211,7 +214,7 @@ export default {
|
||||
tableContextEvent: null,
|
||||
miscContextEvent: null,
|
||||
|
||||
selectedDatabase: '',
|
||||
selectedSchema: '',
|
||||
selectedTable: null,
|
||||
selectedMisc: null,
|
||||
searchTerm: ''
|
||||
@@ -271,6 +274,7 @@ export default {
|
||||
refreshStructure: 'workspaces/refreshStructure',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
|
||||
selectTab: 'workspaces/selectTab',
|
||||
newTab: 'workspaces/newTab',
|
||||
setSearchTerm: 'workspaces/setSearchTerm',
|
||||
addNotification: 'notifications/addNotification',
|
||||
changeExplorebarSize: 'settings/changeExplorebarSize'
|
||||
@@ -308,6 +312,7 @@ export default {
|
||||
async openCreateTableEditor (payload) {
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.selectedSchema,
|
||||
...payload
|
||||
};
|
||||
|
||||
@@ -315,14 +320,19 @@ export default {
|
||||
|
||||
if (status === 'success') {
|
||||
await this.refresh();
|
||||
this.changeBreadcrumbs({ schema: this.selectedDatabase, table: payload.name });
|
||||
this.selectTab({ uid: this.workspace.uid, tab: 'prop' });
|
||||
this.newTab({
|
||||
uid: this.workspace.uid,
|
||||
schema: this.selectedSchema,
|
||||
elementName: payload.name,
|
||||
elementType: 'table',
|
||||
type: 'table-props'
|
||||
});
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
},
|
||||
openSchemaContext (payload) {
|
||||
this.selectedDatabase = payload.schema;
|
||||
this.selectedSchema = payload.schema;
|
||||
this.databaseContextEvent = payload.event;
|
||||
this.isDatabaseContext = true;
|
||||
},
|
||||
@@ -331,6 +341,7 @@ export default {
|
||||
},
|
||||
openTableContext (payload) {
|
||||
this.selectedTable = payload.table;
|
||||
this.selectedSchema = payload.schema;
|
||||
this.tableContextEvent = payload.event;
|
||||
this.isTableContext = true;
|
||||
},
|
||||
@@ -339,11 +350,13 @@ export default {
|
||||
},
|
||||
openMiscContext (payload) {
|
||||
this.selectedMisc = payload.misc;
|
||||
this.selectedSchema = payload.schema;
|
||||
this.miscContextEvent = payload.event;
|
||||
this.isMiscContext = true;
|
||||
},
|
||||
openMiscFolderContext (payload) {
|
||||
this.selectedMisc = payload.type;
|
||||
this.selectedSchema = payload.schema;
|
||||
this.miscContextEvent = payload.event;
|
||||
this.isMiscFolderContext = true;
|
||||
},
|
||||
@@ -364,6 +377,7 @@ export default {
|
||||
async openCreateViewEditor (payload) {
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.selectedSchema,
|
||||
...payload
|
||||
};
|
||||
|
||||
@@ -371,8 +385,15 @@ export default {
|
||||
|
||||
if (status === 'success') {
|
||||
await this.refresh();
|
||||
this.changeBreadcrumbs({ schema: this.selectedDatabase, view: payload.name });
|
||||
this.selectTab({ uid: this.workspace.uid, tab: 'prop' });
|
||||
this.changeBreadcrumbs({ schema: this.selectedSchema, view: payload.name });
|
||||
|
||||
this.newTab({
|
||||
uid: this.workspace.uid,
|
||||
schema: this.selectedSchema,
|
||||
elementName: payload.name,
|
||||
elementType: 'view',
|
||||
type: 'view-props'
|
||||
});
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
@@ -388,6 +409,7 @@ export default {
|
||||
async openCreateTriggerEditor (payload) {
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.selectedSchema,
|
||||
...payload
|
||||
};
|
||||
|
||||
@@ -396,8 +418,15 @@ export default {
|
||||
if (status === 'success') {
|
||||
await this.refresh();
|
||||
const triggerName = this.customizations.triggerTableInName ? `${payload.table}.${payload.name}` : payload.name;
|
||||
this.changeBreadcrumbs({ schema: this.selectedDatabase, trigger: triggerName });
|
||||
this.selectTab({ uid: this.workspace.uid, tab: 'prop' });
|
||||
this.changeBreadcrumbs({ schema: this.selectedSchema, trigger: triggerName });
|
||||
|
||||
this.newTab({
|
||||
uid: this.workspace.uid,
|
||||
schema: this.selectedSchema,
|
||||
elementName: triggerName,
|
||||
elementType: 'trigger',
|
||||
type: 'trigger-props'
|
||||
});
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
@@ -413,6 +442,7 @@ export default {
|
||||
async openCreateRoutineEditor (payload) {
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.selectedSchema,
|
||||
...payload
|
||||
};
|
||||
|
||||
@@ -420,8 +450,15 @@ export default {
|
||||
|
||||
if (status === 'success') {
|
||||
await this.refresh();
|
||||
this.changeBreadcrumbs({ schema: this.selectedDatabase, procedure: payload.name });
|
||||
this.selectTab({ uid: this.workspace.uid, tab: 'prop' });
|
||||
this.changeBreadcrumbs({ schema: this.selectedSchema, routine: payload.name });
|
||||
|
||||
this.newTab({
|
||||
uid: this.workspace.uid,
|
||||
schema: this.selectedSchema,
|
||||
elementName: payload.name,
|
||||
elementType: 'routine',
|
||||
type: 'routine-props'
|
||||
});
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
@@ -453,6 +490,7 @@ export default {
|
||||
async openCreateFunctionEditor (payload) {
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.selectedSchema,
|
||||
...payload
|
||||
};
|
||||
|
||||
@@ -460,8 +498,15 @@ export default {
|
||||
|
||||
if (status === 'success') {
|
||||
await this.refresh();
|
||||
this.changeBreadcrumbs({ schema: this.selectedDatabase, function: payload.name });
|
||||
this.selectTab({ uid: this.workspace.uid, tab: 'prop' });
|
||||
this.changeBreadcrumbs({ schema: this.selectedSchema, function: payload.name });
|
||||
|
||||
this.newTab({
|
||||
uid: this.workspace.uid,
|
||||
schema: this.selectedSchema,
|
||||
elementName: payload.name,
|
||||
elementType: 'function',
|
||||
type: 'function-props'
|
||||
});
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
@@ -469,6 +514,7 @@ export default {
|
||||
async openCreateTriggerFunctionEditor (payload) {
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.selectedSchema,
|
||||
...payload
|
||||
};
|
||||
|
||||
@@ -476,8 +522,15 @@ export default {
|
||||
|
||||
if (status === 'success') {
|
||||
await this.refresh();
|
||||
this.changeBreadcrumbs({ schema: this.selectedDatabase, triggerFunction: payload.name });
|
||||
this.selectTab({ uid: this.workspace.uid, tab: 'prop' });
|
||||
this.changeBreadcrumbs({ schema: this.selectedSchema, triggerFunction: payload.name });
|
||||
|
||||
this.newTab({
|
||||
uid: this.workspace.uid,
|
||||
schema: this.selectedSchema,
|
||||
elementName: payload.name,
|
||||
elementType: 'triggerFunction',
|
||||
type: 'trigger-function-props'
|
||||
});
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
@@ -485,6 +538,7 @@ export default {
|
||||
async openCreateSchedulerEditor (payload) {
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.selectedSchema,
|
||||
...payload
|
||||
};
|
||||
|
||||
@@ -492,8 +546,15 @@ export default {
|
||||
|
||||
if (status === 'success') {
|
||||
await this.refresh();
|
||||
this.changeBreadcrumbs({ schema: this.selectedDatabase, scheduler: payload.name });
|
||||
this.selectTab({ uid: this.workspace.uid, tab: 'prop' });
|
||||
this.changeBreadcrumbs({ schema: this.selectedSchema, scheduler: payload.name });
|
||||
|
||||
this.newTab({
|
||||
uid: this.workspace.uid,
|
||||
schema: this.selectedSchema,
|
||||
elementName: payload.name,
|
||||
elementType: 'scheduler',
|
||||
type: 'scheduler-props'
|
||||
});
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
|
@@ -59,7 +59,8 @@ export default {
|
||||
},
|
||||
props: {
|
||||
contextEvent: MouseEvent,
|
||||
selectedMisc: Object
|
||||
selectedMisc: Object,
|
||||
selectedSchema: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -97,6 +98,7 @@ export default {
|
||||
...mapActions({
|
||||
addNotification: 'notifications/addNotification',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
|
||||
removeTabs: 'workspaces/removeTabs',
|
||||
newTab: 'workspaces/newTab'
|
||||
}),
|
||||
showCreateTableModal () {
|
||||
@@ -126,12 +128,14 @@ export default {
|
||||
case 'trigger':
|
||||
res = await Triggers.dropTrigger({
|
||||
uid: this.selectedWorkspace,
|
||||
schema: this.selectedSchema,
|
||||
trigger: this.selectedMisc.name
|
||||
});
|
||||
break;
|
||||
case 'procedure':
|
||||
res = await Routines.dropRoutine({
|
||||
uid: this.selectedWorkspace,
|
||||
schema: this.selectedSchema,
|
||||
routine: this.selectedMisc.name
|
||||
});
|
||||
break;
|
||||
@@ -139,12 +143,14 @@ export default {
|
||||
case 'triggerFunction':
|
||||
res = await Functions.dropFunction({
|
||||
uid: this.selectedWorkspace,
|
||||
schema: this.selectedSchema,
|
||||
func: this.selectedMisc.name
|
||||
});
|
||||
break;
|
||||
case 'scheduler':
|
||||
res = await Schedulers.dropScheduler({
|
||||
uid: this.selectedWorkspace,
|
||||
schema: this.selectedSchema,
|
||||
scheduler: this.selectedMisc.name
|
||||
});
|
||||
break;
|
||||
@@ -153,7 +159,12 @@ export default {
|
||||
const { status, response } = res;
|
||||
|
||||
if (status === 'success') {
|
||||
this.changeBreadcrumbs({ [this.selectedMisc.type]: null });
|
||||
this.removeTabs({
|
||||
uid: this.selectedWorkspace,
|
||||
elementName: this.selectedMisc.name,
|
||||
elementType: this.selectedMisc.type,
|
||||
schema: this.selectedSchema
|
||||
});
|
||||
|
||||
this.closeContext();
|
||||
this.$emit('reload');
|
||||
@@ -180,8 +191,8 @@ export default {
|
||||
async runRoutineCheck () {
|
||||
const params = {
|
||||
uid: this.selectedWorkspace,
|
||||
schema: this.workspace.breadcrumbs.schema,
|
||||
routine: this.workspace.breadcrumbs.procedure
|
||||
schema: this.selectedSchema,
|
||||
routine: this.selectedMisc.name
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -218,14 +229,14 @@ export default {
|
||||
sql = `CALL \`${this.localElement.name}\`(${params.join(',')})`;
|
||||
}
|
||||
|
||||
this.newTab({ uid: this.workspace.uid, content: sql, autorun: true });
|
||||
this.newTab({ uid: this.workspace.uid, content: sql, type: 'query', autorun: true });
|
||||
this.closeContext();
|
||||
},
|
||||
async runFunctionCheck () {
|
||||
const params = {
|
||||
uid: this.selectedWorkspace,
|
||||
schema: this.workspace.breadcrumbs.schema,
|
||||
func: this.workspace.breadcrumbs.function
|
||||
schema: this.selectedSchema,
|
||||
func: this.selectedMisc.name
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -263,7 +274,7 @@ export default {
|
||||
sql = `SELECT \`${this.localElement.name}\` (${params.join(',')})`;
|
||||
}
|
||||
|
||||
this.newTab({ uid: this.workspace.uid, content: sql, autorun: true });
|
||||
this.newTab({ uid: this.workspace.uid, content: sql, type: 'query', autorun: true });
|
||||
this.closeContext();
|
||||
}
|
||||
}
|
||||
|
@@ -52,7 +52,8 @@ export default {
|
||||
},
|
||||
props: {
|
||||
contextEvent: MouseEvent,
|
||||
selectedMisc: String
|
||||
selectedMisc: String,
|
||||
selectedSchema: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
@@ -19,7 +19,8 @@
|
||||
:key="table.name"
|
||||
class="menu-item"
|
||||
:class="{'text-bold': breadcrumbs.schema === database.name && [breadcrumbs.table, breadcrumbs.view].includes(table.name)}"
|
||||
@click="setBreadcrumbs({schema: database.name, [table.type]: table.name})"
|
||||
@mousedown.left="selectTable({schema: database.name, table})"
|
||||
@dblclick="openDataTab({schema: database.name, table})"
|
||||
@contextmenu.prevent="showTableContext($event, table)"
|
||||
>
|
||||
<a class="table-name">
|
||||
@@ -55,7 +56,8 @@
|
||||
:key="trigger.name"
|
||||
class="menu-item"
|
||||
:class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.trigger === trigger.name}"
|
||||
@click="setBreadcrumbs({schema: database.name, trigger: trigger.name})"
|
||||
@mousedown="selectMisc({schema: database.name, misc: trigger, type: 'trigger'})"
|
||||
@dblclick="openMiscPermanentTab({schema: database.name, misc: trigger, type: 'trigger'})"
|
||||
@contextmenu.prevent="showMiscContext($event, {...trigger, type: 'trigger'})"
|
||||
>
|
||||
<a class="table-name">
|
||||
@@ -73,7 +75,7 @@
|
||||
<details class="accordion">
|
||||
<summary
|
||||
class="accordion-header misc-name"
|
||||
:class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.procedure}"
|
||||
:class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.routine}"
|
||||
@contextmenu.prevent="showMiscFolderContext($event, 'procedure')"
|
||||
>
|
||||
<i class="misc-icon mdi mdi-18px mdi-folder-sync mr-1" />
|
||||
@@ -86,8 +88,9 @@
|
||||
v-for="(procedure, i) of filteredProcedures"
|
||||
:key="`${procedure.name}-${i}`"
|
||||
class="menu-item"
|
||||
:class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.procedure === procedure.name}"
|
||||
@click="setBreadcrumbs({schema: database.name, procedure: procedure.name})"
|
||||
:class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.routine === procedure.name}"
|
||||
@mousedown="selectMisc({schema: database.name, misc: procedure, type: 'routine'})"
|
||||
@dblclick="openMiscPermanentTab({schema: database.name, misc: procedure, type: 'routine'})"
|
||||
@contextmenu.prevent="showMiscContext($event, {...procedure, type: 'procedure'})"
|
||||
>
|
||||
<a class="table-name">
|
||||
@@ -119,7 +122,8 @@
|
||||
:key="`${func.name}-${i}`"
|
||||
class="menu-item"
|
||||
:class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.triggerFunction === func.name}"
|
||||
@click="setBreadcrumbs({schema: database.name, triggerFunction: func.name})"
|
||||
@mousedown="selectMisc({schema: database.name, misc: func, type: 'triggerFunction'})"
|
||||
@dblclick="openMiscPermanentTab({schema: database.name, misc: func, type: 'triggerFunction'})"
|
||||
@contextmenu.prevent="showMiscContext($event, {...func, type: 'triggerFunction'})"
|
||||
>
|
||||
<a class="table-name">
|
||||
@@ -151,7 +155,8 @@
|
||||
:key="`${func.name}-${i}`"
|
||||
class="menu-item"
|
||||
:class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.function === func.name}"
|
||||
@click="setBreadcrumbs({schema: database.name, function: func.name})"
|
||||
@mousedown="selectMisc({schema: database.name, misc: func, type: 'function'})"
|
||||
@dblclick="openMiscPermanentTab({schema: database.name, misc: func, type: 'function'})"
|
||||
@contextmenu.prevent="showMiscContext($event, {...func, type: 'function'})"
|
||||
>
|
||||
<a class="table-name">
|
||||
@@ -183,7 +188,8 @@
|
||||
:key="scheduler.name"
|
||||
class="menu-item"
|
||||
:class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.scheduler === scheduler.name}"
|
||||
@click="setBreadcrumbs({schema: database.name, scheduler: scheduler.name})"
|
||||
@mousedown="selectMisc({schema: database.name, misc: scheduler, type: 'scheduler'})"
|
||||
@dblclick="openMiscPermanentTab({schema: database.name, misc: scheduler, type: 'scheduler'})"
|
||||
@contextmenu.prevent="showMiscContext($event, {...scheduler, type: 'scheduler'})"
|
||||
>
|
||||
<a class="table-name">
|
||||
@@ -267,6 +273,8 @@ export default {
|
||||
methods: {
|
||||
...mapActions({
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
|
||||
addLoadedSchema: 'workspaces/addLoadedSchema',
|
||||
newTab: 'workspaces/newTab',
|
||||
refreshSchema: 'workspaces/refreshSchema'
|
||||
}),
|
||||
formatBytes,
|
||||
@@ -274,27 +282,68 @@ export default {
|
||||
if (!this.loadedSchemas.has(schema) && !this.isLoading) {
|
||||
this.isLoading = true;
|
||||
await this.refreshSchema({ uid: this.connection.uid, schema });
|
||||
this.addLoadedSchema(schema);
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
this.changeBreadcrumbs({ schema, table: null });
|
||||
},
|
||||
selectTable ({ schema, table }) {
|
||||
this.newTab({ uid: this.connection.uid, elementName: table.name, schema: this.database.name, type: 'temp-data', elementType: table.type });
|
||||
this.setBreadcrumbs({ schema, [table.type]: table.name });
|
||||
},
|
||||
selectMisc ({ schema, misc, type }) {
|
||||
const miscTempTabs = {
|
||||
trigger: 'temp-trigger-props',
|
||||
triggerFunction: 'temp-trigger-function-props',
|
||||
function: 'temp-function-props',
|
||||
routine: 'temp-routine-props',
|
||||
scheduler: 'temp-scheduler-props'
|
||||
};
|
||||
|
||||
this.newTab({
|
||||
uid: this.connection.uid,
|
||||
elementName: misc.name,
|
||||
schema: this.database.name,
|
||||
type: miscTempTabs[type],
|
||||
elementType: type
|
||||
});
|
||||
|
||||
this.setBreadcrumbs({ schema, [type]: misc.name });
|
||||
},
|
||||
openDataTab ({ schema, table }) {
|
||||
this.newTab({ uid: this.connection.uid, elementName: table.name, schema: this.database.name, type: 'data', elementType: table.type });
|
||||
this.setBreadcrumbs({ schema, [table.type]: table.name });
|
||||
},
|
||||
openMiscPermanentTab ({ schema, misc, type }) {
|
||||
const miscTabs = {
|
||||
trigger: 'trigger-props',
|
||||
triggerFunction: 'trigger-function-props',
|
||||
function: 'function-props',
|
||||
routine: 'routine-props',
|
||||
scheduler: 'scheduler-props'
|
||||
};
|
||||
|
||||
this.newTab({
|
||||
uid: this.connection.uid,
|
||||
elementName: misc.name,
|
||||
schema: this.database.name,
|
||||
type: miscTabs[type],
|
||||
elementType: type
|
||||
});
|
||||
this.setBreadcrumbs({ schema, [type]: misc.name });
|
||||
},
|
||||
showSchemaContext (event, schema) {
|
||||
this.selectSchema(schema);
|
||||
this.$emit('show-schema-context', { event, schema });
|
||||
},
|
||||
showTableContext (event, table) {
|
||||
this.setBreadcrumbs({ schema: this.database.name, [table.type]: table.name });
|
||||
this.$emit('show-table-context', { event, table });
|
||||
this.$emit('show-table-context', { event, schema: this.database.name, table });
|
||||
},
|
||||
showMiscContext (event, misc) {
|
||||
this.setBreadcrumbs({ schema: this.database.name, [misc.type]: misc.name });
|
||||
this.$emit('show-misc-context', { event, misc });
|
||||
this.$emit('show-misc-context', { event, schema: this.database.name, misc });
|
||||
},
|
||||
showMiscFolderContext (event, type) {
|
||||
this.selectSchema(this.database.name);
|
||||
this.setBreadcrumbs({ schema: this.database.name, type });
|
||||
this.$emit('show-misc-folder-context', { event, type });
|
||||
this.$emit('show-misc-folder-context', { event, schema: this.database.name, type });
|
||||
},
|
||||
piePercentage (val) {
|
||||
const perc = val / this.maxSize * 100;
|
||||
@@ -308,6 +357,8 @@ export default {
|
||||
this.changeBreadcrumbs(payload);
|
||||
},
|
||||
highlightWord (string) {
|
||||
string = string.replaceAll('<', '<').replaceAll('>', '>');
|
||||
|
||||
if (this.searchTerm) {
|
||||
const regexp = new RegExp(`(${this.searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
|
||||
return string.replace(regexp, '<span class="text-primary">$1</span>');
|
||||
|
@@ -82,13 +82,13 @@
|
||||
</template>
|
||||
<div slot="body">
|
||||
<div class="mb-2">
|
||||
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedDatabase }}</b>"?
|
||||
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedSchema }}</b>"?
|
||||
</div>
|
||||
</div>
|
||||
</ConfirmModal>
|
||||
<ModalEditSchema
|
||||
v-if="isEditModal"
|
||||
:selected-database="selectedDatabase"
|
||||
:selected-schema="selectedSchema"
|
||||
@close="hideEditModal"
|
||||
/>
|
||||
</BaseContextMenu>
|
||||
@@ -110,7 +110,7 @@ export default {
|
||||
},
|
||||
props: {
|
||||
contextEvent: MouseEvent,
|
||||
selectedDatabase: String
|
||||
selectedSchema: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -173,11 +173,11 @@ export default {
|
||||
try {
|
||||
const { status, response } = await Schema.deleteSchema({
|
||||
uid: this.selectedWorkspace,
|
||||
database: this.selectedDatabase
|
||||
database: this.selectedSchema
|
||||
});
|
||||
|
||||
if (status === 'success') {
|
||||
if (this.selectedDatabase === this.workspace.breadcrumbs.schema)
|
||||
if (this.selectedSchema === this.workspace.breadcrumbs.schema)
|
||||
this.changeBreadcrumbs({ schema: null });
|
||||
|
||||
this.closeContext();
|
||||
|
@@ -3,6 +3,20 @@
|
||||
:context-event="contextEvent"
|
||||
@close-context="closeContext"
|
||||
>
|
||||
<div
|
||||
v-if="selectedTable.type === 'table' && workspace.customizations.tableSettings"
|
||||
class="context-element"
|
||||
@click="openTableSettingTab"
|
||||
>
|
||||
<span class="d-flex"><i class="mdi mdi-18px mdi-tune-vertical-variant text-light pr-1" /> {{ $t('word.settings') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedTable.type === 'view' && workspace.customizations.viewSettings"
|
||||
class="context-element"
|
||||
@click="openViewSettingTab"
|
||||
>
|
||||
<span class="d-flex"><i class="mdi mdi-18px mdi-tune-vertical-variant text-light pr-1" /> {{ $t('word.settings') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedTable.type === 'table'"
|
||||
class="context-element"
|
||||
@@ -72,7 +86,8 @@ export default {
|
||||
},
|
||||
props: {
|
||||
contextEvent: MouseEvent,
|
||||
selectedTable: Object
|
||||
selectedTable: Object,
|
||||
selectedSchema: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -92,6 +107,8 @@ export default {
|
||||
methods: {
|
||||
...mapActions({
|
||||
addNotification: 'notifications/addNotification',
|
||||
newTab: 'workspaces/newTab',
|
||||
removeTabs: 'workspaces/removeTabs',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs'
|
||||
}),
|
||||
showCreateTableModal () {
|
||||
@@ -112,11 +129,44 @@ export default {
|
||||
closeContext () {
|
||||
this.$emit('close-context');
|
||||
},
|
||||
openTableSettingTab () {
|
||||
this.newTab({
|
||||
uid: this.selectedWorkspace,
|
||||
elementName: this.selectedTable.name,
|
||||
schema: this.selectedSchema,
|
||||
type: 'table-props',
|
||||
elementType: 'table'
|
||||
});
|
||||
|
||||
this.changeBreadcrumbs({
|
||||
schema: this.selectedSchema,
|
||||
table: this.selectedTable.name
|
||||
});
|
||||
|
||||
this.closeContext();
|
||||
},
|
||||
openViewSettingTab () {
|
||||
this.newTab({
|
||||
uid: this.selectedWorkspace,
|
||||
elementType: 'table',
|
||||
elementName: this.selectedTable.name,
|
||||
schema: this.selectedSchema,
|
||||
type: 'view-props'
|
||||
});
|
||||
|
||||
this.changeBreadcrumbs({
|
||||
schema: this.selectedSchema,
|
||||
view: this.selectedTable.name
|
||||
});
|
||||
|
||||
this.closeContext();
|
||||
},
|
||||
async duplicateTable () {
|
||||
try {
|
||||
const { status, response } = await Tables.duplicateTable({
|
||||
uid: this.selectedWorkspace,
|
||||
table: this.selectedTable.name
|
||||
table: this.selectedTable.name,
|
||||
schema: this.selectedSchema
|
||||
});
|
||||
|
||||
if (status === 'success') {
|
||||
@@ -134,13 +184,11 @@ export default {
|
||||
try {
|
||||
const { status, response } = await Tables.truncateTable({
|
||||
uid: this.selectedWorkspace,
|
||||
table: this.selectedTable.name
|
||||
table: this.selectedTable.name,
|
||||
schema: this.selectedSchema
|
||||
});
|
||||
|
||||
if (status === 'success') {
|
||||
if (this.selectedTable.name === this.workspace.breadcrumbs.table)
|
||||
this.changeBreadcrumbs({ table: null });
|
||||
|
||||
this.closeContext();
|
||||
this.$emit('reload');
|
||||
}
|
||||
@@ -158,21 +206,27 @@ export default {
|
||||
if (this.selectedTable.type === 'table') {
|
||||
res = await Tables.dropTable({
|
||||
uid: this.selectedWorkspace,
|
||||
table: this.selectedTable.name
|
||||
table: this.selectedTable.name,
|
||||
schema: this.selectedSchema
|
||||
});
|
||||
}
|
||||
else if (this.selectedTable.type === 'view') {
|
||||
res = await Views.dropView({
|
||||
uid: this.selectedWorkspace,
|
||||
view: this.selectedTable.name
|
||||
view: this.selectedTable.name,
|
||||
schema: this.selectedSchema
|
||||
});
|
||||
}
|
||||
|
||||
const { status, response } = res;
|
||||
|
||||
if (status === 'success') {
|
||||
if (this.selectedTable.name === this.workspace.breadcrumbs.table || this.selectedTable.name === this.workspace.breadcrumbs.view)
|
||||
this.changeBreadcrumbs({ table: null, view: null });
|
||||
this.removeTabs({
|
||||
uid: this.selectedWorkspace,
|
||||
elementName: this.selectedTable.name,
|
||||
elementType: this.selectedTable.type,
|
||||
schema: this.selectedSchema
|
||||
});
|
||||
|
||||
this.closeContext();
|
||||
this.$emit('reload');
|
||||
|
@@ -267,6 +267,12 @@ export default {
|
||||
addNotification: 'notifications/addNotification'
|
||||
}),
|
||||
confirmForeignsChange () {
|
||||
this.foreignProxy = this.foreignProxy.filter(foreign =>
|
||||
foreign.field &&
|
||||
foreign.refField &&
|
||||
foreign.table &&
|
||||
foreign.refTable
|
||||
);
|
||||
this.$emit('foreigns-update', this.foreignProxy);
|
||||
},
|
||||
selectForeign (event, id) {
|
||||
@@ -331,6 +337,8 @@ export default {
|
||||
this.selectedForeignID = this.foreignProxy.length ? this.foreignProxy[0]._id : '';
|
||||
},
|
||||
async getRefFields () {
|
||||
if (!this.selectedForeignObj.refTable) return;
|
||||
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.selectedForeignObj.refSchema,
|
||||
|
@@ -186,6 +186,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
confirmIndexesChange () {
|
||||
this.indexesProxy = this.indexesProxy.filter(index => index.fields.length);
|
||||
this.$emit('indexes-update', this.indexesProxy);
|
||||
},
|
||||
selectIndex (event, id) {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div v-show="isSelected" class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div class="workspace-query-runner column col-12">
|
||||
<div class="workspace-query-runner-footer">
|
||||
<div class="workspace-query-buttons">
|
||||
@@ -14,7 +14,7 @@
|
||||
<span>{{ $t('word.save') }}</span>
|
||||
</button>
|
||||
<button
|
||||
:disabled="!isChanged"
|
||||
:disabled="!isChanged || isSaving"
|
||||
class="btn btn-link btn-sm mr-0"
|
||||
:title="$t('message.clearChanges')"
|
||||
@click="clearChanges"
|
||||
@@ -26,6 +26,7 @@
|
||||
<div class="divider-vert py-3" />
|
||||
|
||||
<button
|
||||
:disabled="isSaving"
|
||||
class="btn btn-dark btn-sm"
|
||||
:title="$t('message.addNewField')"
|
||||
@click="addField"
|
||||
@@ -34,6 +35,7 @@
|
||||
<span>{{ $t('word.add') }}</span>
|
||||
</button>
|
||||
<button
|
||||
:disabled="isSaving"
|
||||
class="btn btn-dark btn-sm"
|
||||
:title="$t('message.manageIndexes')"
|
||||
@click="showIntdexesModal"
|
||||
@@ -41,15 +43,28 @@
|
||||
<i class="mdi mdi-24px mdi-key mdi-rotate-45 mr-1" />
|
||||
<span>{{ $t('word.indexes') }}</span>
|
||||
</button>
|
||||
<button class="btn btn-dark btn-sm" @click="showForeignModal">
|
||||
<button
|
||||
class="btn btn-dark btn-sm"
|
||||
:disabled="isSaving"
|
||||
@click="showForeignModal"
|
||||
>
|
||||
<i class="mdi mdi-24px mdi-key-link mr-1" />
|
||||
<span>{{ $t('word.foreignKeys') }}</span>
|
||||
</button>
|
||||
<button class="btn btn-dark btn-sm" @click="showOptionsModal">
|
||||
<button
|
||||
class="btn btn-dark btn-sm"
|
||||
:disabled="isSaving"
|
||||
@click="showOptionsModal"
|
||||
>
|
||||
<i class="mdi mdi-24px mdi-cogs mr-1" />
|
||||
<span>{{ $t('word.options') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="workspace-query-info">
|
||||
<div class="d-flex" :title="$t('word.schema')">
|
||||
<i class="mdi mdi-18px mdi-database mr-1" /><b>{{ schema }}</b>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="workspace-query-results column col-12 p-relative">
|
||||
@@ -126,11 +141,12 @@ export default {
|
||||
},
|
||||
props: {
|
||||
connection: Object,
|
||||
table: String
|
||||
isSelected: Boolean,
|
||||
table: String,
|
||||
schema: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tabUid: 'prop',
|
||||
isLoading: false,
|
||||
isSaving: false,
|
||||
isOptionsModal: false,
|
||||
@@ -157,6 +173,9 @@ export default {
|
||||
workspace () {
|
||||
return this.getWorkspace(this.connection.uid);
|
||||
},
|
||||
tabUid () {
|
||||
return this.$vnode.key;
|
||||
},
|
||||
tableOptions () {
|
||||
const db = this.workspace.structure.find(db => db.name === this.schema);
|
||||
return db && this.table ? db.tables.find(table => table.name === this.table) : {};
|
||||
@@ -164,12 +183,6 @@ export default {
|
||||
defaultEngine () {
|
||||
return this.getDatabaseVariable(this.connection.uid, 'default_storage_engine').value || '';
|
||||
},
|
||||
isSelected () {
|
||||
return this.workspace.selected_tab === 'prop' && this.selectedWorkspace === this.workspace.uid && this.table;
|
||||
},
|
||||
schema () {
|
||||
return this.workspace.breadcrumbs.schema;
|
||||
},
|
||||
schemaTables () {
|
||||
const schemaTables = this.workspace.structure
|
||||
.filter(schema => schema.name === this.schema)
|
||||
@@ -185,6 +198,12 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
schema () {
|
||||
if (this.isSelected) {
|
||||
this.getFieldsData();
|
||||
this.lastTable = this.table;
|
||||
}
|
||||
},
|
||||
table () {
|
||||
if (this.isSelected) {
|
||||
this.getFieldsData();
|
||||
@@ -192,17 +211,19 @@ export default {
|
||||
}
|
||||
},
|
||||
isSelected (val) {
|
||||
if (val && this.lastTable !== this.table) {
|
||||
this.getFieldsData();
|
||||
this.lastTable = this.table;
|
||||
if (val) {
|
||||
this.changeBreadcrumbs({ schema: this.schema, table: this.table });
|
||||
|
||||
if (this.lastTable !== this.table)
|
||||
this.getFieldsData();
|
||||
}
|
||||
},
|
||||
isChanged (val) {
|
||||
if (this.isSelected && this.lastTable === this.table && this.table !== null)
|
||||
this.setUnsavedChanges(val);
|
||||
this.setUnsavedChanges({ uid: this.connection.uid, tUid: this.tabUid, isChanged: val });
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getFieldsData();
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
beforeDestroy () {
|
||||
@@ -213,20 +234,25 @@ export default {
|
||||
addNotification: 'notifications/addNotification',
|
||||
refreshStructure: 'workspaces/refreshStructure',
|
||||
setUnsavedChanges: 'workspaces/setUnsavedChanges',
|
||||
renameTabs: 'workspaces/renameTabs',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs'
|
||||
}),
|
||||
async getFieldsData () {
|
||||
if (!this.table) return;
|
||||
|
||||
this.localFields = [];
|
||||
this.lastTable = this.table;
|
||||
this.newFieldsCounter = 0;
|
||||
this.isLoading = true;
|
||||
this.localOptions = JSON.parse(JSON.stringify(this.tableOptions));
|
||||
try {
|
||||
this.localOptions = JSON.parse(JSON.stringify(this.tableOptions));
|
||||
}
|
||||
catch (err) {}
|
||||
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
table: this.workspace.breadcrumbs.table
|
||||
table: this.table
|
||||
};
|
||||
|
||||
try { // Columns data
|
||||
@@ -410,7 +436,7 @@ export default {
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
table: this.workspace.breadcrumbs.table,
|
||||
table: this.table,
|
||||
additions,
|
||||
changes,
|
||||
deletions,
|
||||
@@ -428,11 +454,18 @@ export default {
|
||||
await this.refreshStructure(this.connection.uid);
|
||||
|
||||
if (oldName !== this.localOptions.name) {
|
||||
this.setUnsavedChanges(false);
|
||||
this.renameTabs({
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
elementName: oldName,
|
||||
elementNewName: this.localOptions.name,
|
||||
elementType: 'table'
|
||||
});
|
||||
|
||||
this.changeBreadcrumbs({ schema: this.schema, table: this.localOptions.name });
|
||||
}
|
||||
|
||||
this.getFieldsData();
|
||||
else
|
||||
this.getFieldsData();
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div v-show="isSelected" class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div class="workspace-query-runner column col-12">
|
||||
<div class="workspace-query-runner-footer">
|
||||
<div class="workspace-query-buttons">
|
||||
@@ -42,6 +42,11 @@
|
||||
<span>{{ $t('word.options') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="workspace-query-info">
|
||||
<div class="d-flex" :title="$t('word.schema')">
|
||||
<i class="mdi mdi-18px mdi-database mr-1" /><b>{{ schema }}</b>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="workspace-query-results column col-12 mt-2 p-relative">
|
||||
@@ -102,11 +107,12 @@ export default {
|
||||
},
|
||||
props: {
|
||||
connection: Object,
|
||||
function: String
|
||||
function: String,
|
||||
isSelected: Boolean,
|
||||
schema: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tabUid: 'prop',
|
||||
isLoading: false,
|
||||
isSaving: false,
|
||||
isOptionsModal: false,
|
||||
@@ -127,11 +133,8 @@ export default {
|
||||
workspace () {
|
||||
return this.getWorkspace(this.connection.uid);
|
||||
},
|
||||
isSelected () {
|
||||
return this.workspace.selected_tab === 'prop' && this.selectedWorkspace === this.workspace.uid && this.function;
|
||||
},
|
||||
schema () {
|
||||
return this.workspace.breadcrumbs.schema;
|
||||
tabUid () {
|
||||
return this.$vnode.key;
|
||||
},
|
||||
isChanged () {
|
||||
return JSON.stringify(this.originalFunction) !== JSON.stringify(this.localFunction);
|
||||
@@ -150,6 +153,13 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
async schema () {
|
||||
if (this.isSelected) {
|
||||
await this.getFunctionData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localFunction.sql);
|
||||
this.lastFunction = this.function;
|
||||
}
|
||||
},
|
||||
async function () {
|
||||
if (this.isSelected) {
|
||||
await this.getFunctionData();
|
||||
@@ -158,26 +168,32 @@ export default {
|
||||
}
|
||||
},
|
||||
async isSelected (val) {
|
||||
if (val && this.lastFunction !== this.function) {
|
||||
await this.getFunctionData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localFunction.sql);
|
||||
this.lastFunction = this.function;
|
||||
if (val) {
|
||||
this.changeBreadcrumbs({ schema: this.schema, function: this.function });
|
||||
|
||||
setTimeout(() => {
|
||||
this.resizeQueryEditor();
|
||||
}, 200);
|
||||
|
||||
if (this.lastFunction !== this.function)
|
||||
this.getRoutineData();
|
||||
}
|
||||
},
|
||||
isChanged (val) {
|
||||
if (this.isSelected && this.lastFunction === this.function && this.function !== null)
|
||||
this.setUnsavedChanges(val);
|
||||
this.setUnsavedChanges({ uid: this.connection.uid, tUid: this.tabUid, isChanged: val });
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
await this.getFunctionData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localFunction.sql);
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
mounted () {
|
||||
window.addEventListener('resize', this.resizeQueryEditor);
|
||||
},
|
||||
destroyed () {
|
||||
window.removeEventListener('resize', this.resizeQueryEditor);
|
||||
},
|
||||
created () {
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('keydown', this.onKey);
|
||||
},
|
||||
@@ -185,20 +201,22 @@ export default {
|
||||
...mapActions({
|
||||
addNotification: 'notifications/addNotification',
|
||||
refreshStructure: 'workspaces/refreshStructure',
|
||||
setUnsavedChanges: 'workspaces/setUnsavedChanges',
|
||||
renameTabs: 'workspaces/renameTabs',
|
||||
newTab: 'workspaces/newTab',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
|
||||
newTab: 'workspaces/newTab'
|
||||
setUnsavedChanges: 'workspaces/setUnsavedChanges'
|
||||
}),
|
||||
async getFunctionData () {
|
||||
if (!this.function) return;
|
||||
|
||||
this.isLoading = true;
|
||||
this.localFunction = { sql: '' };
|
||||
this.lastFunction = this.function;
|
||||
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
func: this.workspace.breadcrumbs.function
|
||||
func: this.function
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -229,9 +247,9 @@ export default {
|
||||
this.isSaving = true;
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
func: {
|
||||
...this.localFunction,
|
||||
schema: this.schema,
|
||||
oldName: this.originalFunction.name
|
||||
}
|
||||
};
|
||||
@@ -245,11 +263,18 @@ export default {
|
||||
await this.refreshStructure(this.connection.uid);
|
||||
|
||||
if (oldName !== this.localFunction.name) {
|
||||
this.setUnsavedChanges(false);
|
||||
this.renameTabs({
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
elementName: oldName,
|
||||
elementNewName: this.localFunction.name,
|
||||
elementType: 'function'
|
||||
});
|
||||
|
||||
this.changeBreadcrumbs({ schema: this.schema, function: this.localFunction.name });
|
||||
}
|
||||
|
||||
this.getFunctionData();
|
||||
else
|
||||
this.getFunctionData();
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
@@ -303,7 +328,7 @@ export default {
|
||||
sql = `SELECT \`${this.originalFunction.name}\` (${params.join(',')})`;
|
||||
}
|
||||
|
||||
this.newTab({ uid: this.connection.uid, content: sql, autorun: true });
|
||||
this.newTab({ uid: this.connection.uid, content: sql, type: 'query', autorun: true });
|
||||
},
|
||||
showOptionsModal () {
|
||||
this.isOptionsModal = true;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div v-show="isSelected" class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div class="workspace-query-runner column col-12">
|
||||
<div class="workspace-query-runner-footer">
|
||||
<div class="workspace-query-buttons">
|
||||
@@ -42,6 +42,11 @@
|
||||
<span>{{ $t('word.options') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="workspace-query-info">
|
||||
<div class="d-flex" :title="$t('word.schema')">
|
||||
<i class="mdi mdi-18px mdi-database mr-1" /><b>{{ schema }}</b>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="workspace-query-results column col-12 mt-2 p-relative">
|
||||
@@ -103,11 +108,12 @@ export default {
|
||||
},
|
||||
props: {
|
||||
connection: Object,
|
||||
routine: String
|
||||
routine: String,
|
||||
isSelected: Boolean,
|
||||
schema: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tabUid: 'prop',
|
||||
isLoading: false,
|
||||
isSaving: false,
|
||||
isOptionsModal: false,
|
||||
@@ -128,11 +134,8 @@ export default {
|
||||
workspace () {
|
||||
return this.getWorkspace(this.connection.uid);
|
||||
},
|
||||
isSelected () {
|
||||
return this.workspace.selected_tab === 'prop' && this.selectedWorkspace === this.workspace.uid && this.routine;
|
||||
},
|
||||
schema () {
|
||||
return this.workspace.breadcrumbs.schema;
|
||||
tabUid () {
|
||||
return this.$vnode.key;
|
||||
},
|
||||
isChanged () {
|
||||
return JSON.stringify(this.originalRoutine) !== JSON.stringify(this.localRoutine);
|
||||
@@ -149,6 +152,13 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
async schema () {
|
||||
if (this.isSelected) {
|
||||
await this.getRoutineData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localRoutine.sql);
|
||||
this.lastRoutine = this.routine;
|
||||
}
|
||||
},
|
||||
async routine () {
|
||||
if (this.isSelected) {
|
||||
await this.getRoutineData();
|
||||
@@ -157,26 +167,32 @@ export default {
|
||||
}
|
||||
},
|
||||
async isSelected (val) {
|
||||
if (val && this.lastRoutine !== this.routine) {
|
||||
await this.getRoutineData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localRoutine.sql);
|
||||
this.lastRoutine = this.routine;
|
||||
if (val) {
|
||||
this.changeBreadcrumbs({ schema: this.schema, routine: this.routine });
|
||||
|
||||
setTimeout(() => {
|
||||
this.resizeQueryEditor();
|
||||
}, 200);
|
||||
|
||||
if (this.lastRoutine !== this.routine)
|
||||
this.getRoutineData();
|
||||
}
|
||||
},
|
||||
isChanged (val) {
|
||||
if (this.isSelected && this.lastRoutine === this.routine && this.routine !== null)
|
||||
this.setUnsavedChanges(val);
|
||||
this.setUnsavedChanges({ uid: this.connection.uid, tUid: this.tabUid, isChanged: val });
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
await this.getRoutineData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localRoutine.sql);
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
mounted () {
|
||||
window.addEventListener('resize', this.resizeQueryEditor);
|
||||
},
|
||||
destroyed () {
|
||||
window.removeEventListener('resize', this.resizeQueryEditor);
|
||||
},
|
||||
created () {
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('keydown', this.onKey);
|
||||
},
|
||||
@@ -184,19 +200,22 @@ export default {
|
||||
...mapActions({
|
||||
addNotification: 'notifications/addNotification',
|
||||
refreshStructure: 'workspaces/refreshStructure',
|
||||
setUnsavedChanges: 'workspaces/setUnsavedChanges',
|
||||
renameTabs: 'workspaces/renameTabs',
|
||||
newTab: 'workspaces/newTab',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
|
||||
newTab: 'workspaces/newTab'
|
||||
setUnsavedChanges: 'workspaces/setUnsavedChanges'
|
||||
}),
|
||||
async getRoutineData () {
|
||||
if (!this.routine) return;
|
||||
|
||||
this.localRoutine = { sql: '' };
|
||||
this.isLoading = true;
|
||||
this.lastRoutine = this.routine;
|
||||
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
routine: this.workspace.breadcrumbs.procedure
|
||||
routine: this.routine
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -227,9 +246,9 @@ export default {
|
||||
this.isSaving = true;
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
routine: {
|
||||
...this.localRoutine,
|
||||
schema: this.schema,
|
||||
oldName: this.originalRoutine.name
|
||||
}
|
||||
};
|
||||
@@ -243,11 +262,18 @@ export default {
|
||||
await this.refreshStructure(this.connection.uid);
|
||||
|
||||
if (oldName !== this.localRoutine.name) {
|
||||
this.setUnsavedChanges(false);
|
||||
this.renameTabs({
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
elementName: oldName,
|
||||
elementNewName: this.localRoutine.name,
|
||||
elementType: 'procedure'
|
||||
});
|
||||
|
||||
this.changeBreadcrumbs({ schema: this.schema, procedure: this.localRoutine.name });
|
||||
}
|
||||
|
||||
this.getRoutineData();
|
||||
else
|
||||
this.getRoutineData();
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
@@ -299,7 +325,7 @@ export default {
|
||||
sql = `CALL \`${this.originalRoutine.name}\`(${params.join(',')})`;
|
||||
}
|
||||
|
||||
this.newTab({ uid: this.connection.uid, content: sql, autorun: true });
|
||||
this.newTab({ uid: this.connection.uid, content: sql, type: 'query', autorun: true });
|
||||
},
|
||||
showOptionsModal () {
|
||||
this.isOptionsModal = true;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div v-show="isSelected" class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div class="workspace-query-runner column col-12">
|
||||
<div class="workspace-query-runner-footer">
|
||||
<div class="workspace-query-buttons">
|
||||
@@ -29,6 +29,11 @@
|
||||
<span>{{ $t('word.timing') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="workspace-query-info">
|
||||
<div class="d-flex" :title="$t('word.schema')">
|
||||
<i class="mdi mdi-18px mdi-database mr-1" /><b>{{ schema }}</b>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
@@ -153,11 +158,12 @@ export default {
|
||||
},
|
||||
props: {
|
||||
connection: Object,
|
||||
scheduler: String
|
||||
scheduler: String,
|
||||
isSelected: Boolean,
|
||||
schema: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tabUid: 'prop',
|
||||
isLoading: false,
|
||||
isSaving: false,
|
||||
isTimingModal: false,
|
||||
@@ -176,11 +182,8 @@ export default {
|
||||
workspace () {
|
||||
return this.getWorkspace(this.connection.uid);
|
||||
},
|
||||
isSelected () {
|
||||
return this.workspace.selected_tab === 'prop' && this.selectedWorkspace === this.workspace.uid && this.scheduler;
|
||||
},
|
||||
schema () {
|
||||
return this.workspace.breadcrumbs.schema;
|
||||
tabUid () {
|
||||
return this.$vnode.key;
|
||||
},
|
||||
isChanged () {
|
||||
return JSON.stringify(this.originalScheduler) !== JSON.stringify(this.localScheduler);
|
||||
@@ -197,6 +200,13 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
async schema () {
|
||||
if (this.isSelected) {
|
||||
await this.getSchedulerData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localScheduler.sql);
|
||||
this.lastScheduler = this.scheduler;
|
||||
}
|
||||
},
|
||||
async scheduler () {
|
||||
if (this.isSelected) {
|
||||
await this.getSchedulerData();
|
||||
@@ -205,26 +215,32 @@ export default {
|
||||
}
|
||||
},
|
||||
async isSelected (val) {
|
||||
if (val && this.lastScheduler !== this.scheduler) {
|
||||
await this.getSchedulerData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localScheduler.sql);
|
||||
this.lastScheduler = this.scheduler;
|
||||
if (val) {
|
||||
this.changeBreadcrumbs({ schema: this.schema, scheduler: this.scheduler });
|
||||
|
||||
setTimeout(() => {
|
||||
this.resizeQueryEditor();
|
||||
}, 200);
|
||||
|
||||
if (this.lastScheduler !== this.scheduler)
|
||||
this.getSchedulerData();
|
||||
}
|
||||
},
|
||||
isChanged (val) {
|
||||
if (this.isSelected && this.lastScheduler === this.scheduler && this.scheduler !== null)
|
||||
this.setUnsavedChanges(val);
|
||||
this.setUnsavedChanges({ uid: this.connection.uid, tUid: this.tabUid, isChanged: val });
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
await this.getSchedulerData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localScheduler.sql);
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
mounted () {
|
||||
window.addEventListener('resize', this.resizeQueryEditor);
|
||||
},
|
||||
destroyed () {
|
||||
window.removeEventListener('resize', this.resizeQueryEditor);
|
||||
},
|
||||
created () {
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('keydown', this.onKey);
|
||||
},
|
||||
@@ -232,17 +248,21 @@ export default {
|
||||
...mapActions({
|
||||
addNotification: 'notifications/addNotification',
|
||||
refreshStructure: 'workspaces/refreshStructure',
|
||||
setUnsavedChanges: 'workspaces/setUnsavedChanges',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs'
|
||||
renameTabs: 'workspaces/renameTabs',
|
||||
newTab: 'workspaces/newTab',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
|
||||
setUnsavedChanges: 'workspaces/setUnsavedChanges'
|
||||
}),
|
||||
async getSchedulerData () {
|
||||
if (!this.scheduler) return;
|
||||
|
||||
this.isLoading = true;
|
||||
this.lastScheduler = this.scheduler;
|
||||
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
scheduler: this.workspace.breadcrumbs.scheduler
|
||||
scheduler: this.scheduler
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -267,9 +287,9 @@ export default {
|
||||
this.isSaving = true;
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
scheduler: {
|
||||
...this.localScheduler,
|
||||
schema: this.schema,
|
||||
oldName: this.originalScheduler.name
|
||||
}
|
||||
};
|
||||
@@ -283,11 +303,18 @@ export default {
|
||||
await this.refreshStructure(this.connection.uid);
|
||||
|
||||
if (oldName !== this.localScheduler.name) {
|
||||
this.setUnsavedChanges(false);
|
||||
this.renameTabs({
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
elementName: oldName,
|
||||
elementNewName: this.localScheduler.name,
|
||||
elementType: 'scheduler'
|
||||
});
|
||||
|
||||
this.changeBreadcrumbs({ schema: this.schema, scheduler: this.localScheduler.name });
|
||||
}
|
||||
|
||||
this.getSchedulerData();
|
||||
else
|
||||
this.getSchedulerData();
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div v-show="isSelected" class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div class="workspace-query-runner column col-12">
|
||||
<div class="workspace-query-runner-footer">
|
||||
<div class="workspace-query-buttons">
|
||||
@@ -23,6 +23,11 @@
|
||||
<span>{{ $t('word.clear') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="workspace-query-info">
|
||||
<div class="d-flex" :title="$t('word.schema')">
|
||||
<i class="mdi mdi-18px mdi-database mr-1" /><b>{{ schema }}</b>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
@@ -139,11 +144,12 @@ export default {
|
||||
},
|
||||
props: {
|
||||
connection: Object,
|
||||
trigger: String
|
||||
trigger: String,
|
||||
isSelected: Boolean,
|
||||
schema: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tabUid: 'prop',
|
||||
isLoading: false,
|
||||
isSaving: false,
|
||||
originalTrigger: null,
|
||||
@@ -162,15 +168,12 @@ export default {
|
||||
workspace () {
|
||||
return this.getWorkspace(this.connection.uid);
|
||||
},
|
||||
tabUid () {
|
||||
return this.$vnode.key;
|
||||
},
|
||||
customizations () {
|
||||
return this.workspace.customizations;
|
||||
},
|
||||
isSelected () {
|
||||
return this.workspace.selected_tab === 'prop' && this.selectedWorkspace === this.workspace.uid && this.trigger;
|
||||
},
|
||||
schema () {
|
||||
return this.workspace.breadcrumbs.schema;
|
||||
},
|
||||
isChanged () {
|
||||
return JSON.stringify(this.originalTrigger) !== JSON.stringify(this.localTrigger);
|
||||
},
|
||||
@@ -186,6 +189,13 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
async schema () {
|
||||
if (this.isSelected) {
|
||||
await this.getTriggerData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localTrigger.sql);
|
||||
this.lastTrigger = this.trigger;
|
||||
}
|
||||
},
|
||||
async trigger () {
|
||||
if (this.isSelected) {
|
||||
await this.getTriggerData();
|
||||
@@ -194,26 +204,32 @@ export default {
|
||||
}
|
||||
},
|
||||
async isSelected (val) {
|
||||
if (val && this.lastTrigger !== this.trigger) {
|
||||
await this.getTriggerData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localTrigger.sql);
|
||||
this.lastTrigger = this.trigger;
|
||||
if (val) {
|
||||
this.changeBreadcrumbs({ schema: this.schema, trigger: this.trigger });
|
||||
|
||||
setTimeout(() => {
|
||||
this.resizeQueryEditor();
|
||||
}, 200);
|
||||
|
||||
if (this.lastTrigger !== this.trigger)
|
||||
this.getTriggerData();
|
||||
}
|
||||
},
|
||||
isChanged (val) {
|
||||
if (this.isSelected && this.lastTrigger === this.trigger && this.trigger !== null)
|
||||
this.setUnsavedChanges(val);
|
||||
this.setUnsavedChanges({ uid: this.connection.uid, tUid: this.tabUid, isChanged: val });
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
await this.getTriggerData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localTrigger.sql);
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
mounted () {
|
||||
window.addEventListener('resize', this.resizeQueryEditor);
|
||||
},
|
||||
destroyed () {
|
||||
window.removeEventListener('resize', this.resizeQueryEditor);
|
||||
},
|
||||
created () {
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('keydown', this.onKey);
|
||||
},
|
||||
@@ -221,8 +237,10 @@ export default {
|
||||
...mapActions({
|
||||
addNotification: 'notifications/addNotification',
|
||||
refreshStructure: 'workspaces/refreshStructure',
|
||||
setUnsavedChanges: 'workspaces/setUnsavedChanges',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs'
|
||||
renameTabs: 'workspaces/renameTabs',
|
||||
newTab: 'workspaces/newTab',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
|
||||
setUnsavedChanges: 'workspaces/setUnsavedChanges'
|
||||
}),
|
||||
async getTriggerData () {
|
||||
if (!this.trigger) return;
|
||||
@@ -233,11 +251,12 @@ export default {
|
||||
|
||||
this.localTrigger = { sql: '' };
|
||||
this.isLoading = true;
|
||||
this.lastTrigger = this.trigger;
|
||||
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
trigger: this.workspace.breadcrumbs.trigger
|
||||
trigger: this.trigger
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -278,9 +297,9 @@ export default {
|
||||
this.isSaving = true;
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
trigger: {
|
||||
...this.localTrigger,
|
||||
schema: this.schema,
|
||||
oldName: this.originalTrigger.name
|
||||
}
|
||||
};
|
||||
@@ -289,17 +308,24 @@ export default {
|
||||
const { status, response } = await Triggers.alterTrigger(params);
|
||||
|
||||
if (status === 'success') {
|
||||
const oldName = this.originalTrigger.name;
|
||||
|
||||
await this.refreshStructure(this.connection.uid);
|
||||
|
||||
if (oldName !== this.localTrigger.name) {
|
||||
this.setUnsavedChanges(false);
|
||||
if (this.originalTrigger.name !== this.localTrigger.name) {
|
||||
const triggerName = this.customizations.triggerTableInName ? `${this.localTrigger.table}.${this.localTrigger.name}` : this.localTrigger.name;
|
||||
const triggerOldName = this.customizations.triggerTableInName ? `${this.originalTrigger.table}.${this.originalTrigger.name}` : this.originalTrigger.name;
|
||||
|
||||
this.renameTabs({
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
elementName: triggerOldName,
|
||||
elementNewName: triggerName,
|
||||
elementType: 'trigger'
|
||||
});
|
||||
|
||||
this.changeBreadcrumbs({ schema: this.schema, trigger: triggerName });
|
||||
}
|
||||
|
||||
this.getTriggerData();
|
||||
else
|
||||
this.getTriggerData();
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div v-show="isSelected" class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div class="workspace-query-runner column col-12">
|
||||
<div class="workspace-query-runner-footer">
|
||||
<div class="workspace-query-buttons">
|
||||
@@ -80,11 +80,12 @@ export default {
|
||||
},
|
||||
props: {
|
||||
connection: Object,
|
||||
function: String
|
||||
function: String,
|
||||
isSelected: Boolean,
|
||||
schema: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tabUid: 'prop',
|
||||
isLoading: false,
|
||||
isSaving: false,
|
||||
isOptionsModal: false,
|
||||
@@ -105,11 +106,8 @@ export default {
|
||||
workspace () {
|
||||
return this.getWorkspace(this.connection.uid);
|
||||
},
|
||||
isSelected () {
|
||||
return this.workspace.selected_tab === 'prop' && this.selectedWorkspace === this.workspace.uid && this.function;
|
||||
},
|
||||
schema () {
|
||||
return this.workspace.breadcrumbs.schema;
|
||||
tabUid () {
|
||||
return this.$vnode.key;
|
||||
},
|
||||
isChanged () {
|
||||
return JSON.stringify(this.originalFunction) !== JSON.stringify(this.localFunction);
|
||||
@@ -128,6 +126,13 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
async schema () {
|
||||
if (this.isSelected) {
|
||||
await this.getFunctionData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localFunction.sql);
|
||||
this.lastFunction = this.function;
|
||||
}
|
||||
},
|
||||
async function () {
|
||||
if (this.isSelected) {
|
||||
await this.getFunctionData();
|
||||
@@ -136,26 +141,32 @@ export default {
|
||||
}
|
||||
},
|
||||
async isSelected (val) {
|
||||
if (val && this.lastFunction !== this.function) {
|
||||
await this.getFunctionData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localFunction.sql);
|
||||
this.lastFunction = this.function;
|
||||
if (val) {
|
||||
this.changeBreadcrumbs({ schema: this.schema, triggerFunction: this.function });
|
||||
|
||||
setTimeout(() => {
|
||||
this.resizeQueryEditor();
|
||||
}, 200);
|
||||
|
||||
if (this.lastFunction !== this.function)
|
||||
await this.getFunctionData();
|
||||
}
|
||||
},
|
||||
isChanged (val) {
|
||||
if (this.isSelected && this.lastFunction === this.function && this.function !== null)
|
||||
this.setUnsavedChanges(val);
|
||||
this.setUnsavedChanges({ uid: this.connection.uid, tUid: this.tabUid, isChanged: val });
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
await this.getFunctionData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localFunction.sql);
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
mounted () {
|
||||
window.addEventListener('resize', this.resizeQueryEditor);
|
||||
},
|
||||
destroyed () {
|
||||
window.removeEventListener('resize', this.resizeQueryEditor);
|
||||
},
|
||||
created () {
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('keydown', this.onKey);
|
||||
},
|
||||
@@ -163,20 +174,22 @@ export default {
|
||||
...mapActions({
|
||||
addNotification: 'notifications/addNotification',
|
||||
refreshStructure: 'workspaces/refreshStructure',
|
||||
setUnsavedChanges: 'workspaces/setUnsavedChanges',
|
||||
renameTabs: 'workspaces/renameTabs',
|
||||
newTab: 'workspaces/newTab',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
|
||||
newTab: 'workspaces/newTab'
|
||||
setUnsavedChanges: 'workspaces/setUnsavedChanges'
|
||||
}),
|
||||
async getFunctionData () {
|
||||
if (!this.function) return;
|
||||
|
||||
this.isLoading = true;
|
||||
this.localFunction = { sql: '' };
|
||||
this.lastFunction = this.function;
|
||||
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
func: this.workspace.breadcrumbs.triggerFunction
|
||||
func: this.function
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -207,9 +220,9 @@ export default {
|
||||
this.isSaving = true;
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
func: {
|
||||
...this.localFunction,
|
||||
schema: this.schema,
|
||||
oldName: this.originalFunction.name
|
||||
}
|
||||
};
|
||||
@@ -223,11 +236,18 @@ export default {
|
||||
await this.refreshStructure(this.connection.uid);
|
||||
|
||||
if (oldName !== this.localFunction.name) {
|
||||
this.setUnsavedChanges(false);
|
||||
this.changeBreadcrumbs({ schema: this.schema, function: this.localFunction.name });
|
||||
}
|
||||
this.renameTabs({
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
elementName: oldName,
|
||||
elementNewName: this.localFunction.name,
|
||||
elementType: 'triggerFunction'
|
||||
});
|
||||
|
||||
this.getFunctionData();
|
||||
this.changeBreadcrumbs({ schema: this.schema, triggerFunction: this.localFunction.name });
|
||||
}
|
||||
else
|
||||
this.getFunctionData();
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
@@ -281,7 +301,7 @@ export default {
|
||||
sql = `SELECT \`${this.originalFunction.name}\` (${params.join(',')})`;
|
||||
}
|
||||
|
||||
this.newTab({ uid: this.connection.uid, content: sql, autorun: true });
|
||||
this.newTab({ uid: this.connection.uid, content: sql, type: 'query', autorun: true });
|
||||
},
|
||||
showOptionsModal () {
|
||||
this.isOptionsModal = true;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div v-show="isSelected" class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div class="workspace-query-runner column col-12">
|
||||
<div class="workspace-query-runner-footer">
|
||||
<div class="workspace-query-buttons">
|
||||
@@ -23,6 +23,11 @@
|
||||
<span>{{ $t('word.clear') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="workspace-query-info">
|
||||
<div class="d-flex" :title="$t('word.schema')">
|
||||
<i class="mdi mdi-18px mdi-database mr-1" /><b>{{ schema }}</b>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
@@ -161,7 +166,7 @@
|
||||
<BaseLoader v-if="isLoading" />
|
||||
<label class="form-label ml-2">{{ $t('message.selectStatement') }}</label>
|
||||
<QueryEditor
|
||||
v-if="isSelected"
|
||||
v-show="isSelected"
|
||||
ref="queryEditor"
|
||||
:value.sync="localView.sql"
|
||||
:workspace="workspace"
|
||||
@@ -186,11 +191,12 @@ export default {
|
||||
},
|
||||
props: {
|
||||
connection: Object,
|
||||
isSelected: Boolean,
|
||||
schema: String,
|
||||
view: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tabUid: 'prop',
|
||||
isLoading: false,
|
||||
isSaving: false,
|
||||
originalView: null,
|
||||
@@ -208,11 +214,8 @@ export default {
|
||||
workspace () {
|
||||
return this.getWorkspace(this.connection.uid);
|
||||
},
|
||||
isSelected () {
|
||||
return this.workspace.selected_tab === 'prop' && this.selectedWorkspace === this.workspace.uid && this.view;
|
||||
},
|
||||
schema () {
|
||||
return this.workspace.breadcrumbs.schema;
|
||||
tabUid () {
|
||||
return this.$vnode.key;
|
||||
},
|
||||
isChanged () {
|
||||
return JSON.stringify(this.originalView) !== JSON.stringify(this.localView);
|
||||
@@ -222,6 +225,13 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
async schema () {
|
||||
if (this.isSelected) {
|
||||
await this.getViewData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localView.sql);
|
||||
this.lastView = this.view;
|
||||
}
|
||||
},
|
||||
async view () {
|
||||
if (this.isSelected) {
|
||||
await this.getViewData();
|
||||
@@ -229,27 +239,33 @@ export default {
|
||||
this.lastView = this.view;
|
||||
}
|
||||
},
|
||||
async isSelected (val) {
|
||||
if (val && this.lastView !== this.view) {
|
||||
await this.getViewData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localView.sql);
|
||||
this.lastView = this.view;
|
||||
isSelected (val) {
|
||||
if (val) {
|
||||
this.changeBreadcrumbs({ schema: this.schema, view: this.view });
|
||||
|
||||
setTimeout(() => {
|
||||
this.resizeQueryEditor();
|
||||
}, 200);
|
||||
|
||||
if (this.lastView !== this.view)
|
||||
this.getViewData();
|
||||
}
|
||||
},
|
||||
isChanged (val) {
|
||||
if (this.isSelected && this.lastView === this.view && this.view !== null)
|
||||
this.setUnsavedChanges(val);
|
||||
this.setUnsavedChanges({ uid: this.connection.uid, tUid: this.tabUid, isChanged: val });
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
await this.getViewData();
|
||||
this.$refs.queryEditor.editor.session.setValue(this.localView.sql);
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
mounted () {
|
||||
window.addEventListener('resize', this.resizeQueryEditor);
|
||||
},
|
||||
destroyed () {
|
||||
window.removeEventListener('resize', this.resizeQueryEditor);
|
||||
},
|
||||
created () {
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('keydown', this.onKey);
|
||||
},
|
||||
@@ -258,17 +274,19 @@ export default {
|
||||
addNotification: 'notifications/addNotification',
|
||||
refreshStructure: 'workspaces/refreshStructure',
|
||||
setUnsavedChanges: 'workspaces/setUnsavedChanges',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs'
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
|
||||
renameTabs: 'workspaces/renameTabs'
|
||||
}),
|
||||
async getViewData () {
|
||||
if (!this.view) return;
|
||||
this.isLoading = true;
|
||||
this.localView = { sql: '' };
|
||||
this.lastView = this.view;
|
||||
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
view: this.workspace.breadcrumbs.view
|
||||
view: this.view
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -293,9 +311,9 @@ export default {
|
||||
this.isSaving = true;
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
view: {
|
||||
...this.localView,
|
||||
schema: this.schema,
|
||||
oldName: this.originalView.name
|
||||
}
|
||||
};
|
||||
@@ -309,11 +327,18 @@ export default {
|
||||
await this.refreshStructure(this.connection.uid);
|
||||
|
||||
if (oldName !== this.localView.name) {
|
||||
this.setUnsavedChanges(false);
|
||||
this.renameTabs({
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
elementName: oldName,
|
||||
elementNewName: this.localView.name,
|
||||
elementType: 'view'
|
||||
});
|
||||
|
||||
this.changeBreadcrumbs({ schema: this.schema, view: this.localView.name });
|
||||
}
|
||||
|
||||
this.getViewData();
|
||||
else
|
||||
this.getViewData();
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
|
@@ -100,7 +100,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<draggable
|
||||
<Draggable
|
||||
ref="resultTable"
|
||||
:list="fields"
|
||||
class="tbody"
|
||||
@@ -117,14 +117,14 @@
|
||||
@contextmenu="contextMenu"
|
||||
@rename-field="$emit('rename-field', $event)"
|
||||
/>
|
||||
</draggable>
|
||||
</Draggable>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex';
|
||||
import draggable from 'vuedraggable';
|
||||
import Draggable from 'vuedraggable';
|
||||
import TableRow from '@/components/WorkspacePropsTableRow';
|
||||
import TableContext from '@/components/WorkspacePropsTableContext';
|
||||
|
||||
@@ -133,7 +133,7 @@ export default {
|
||||
components: {
|
||||
TableRow,
|
||||
TableContext,
|
||||
draggable
|
||||
Draggable
|
||||
},
|
||||
props: {
|
||||
fields: Array,
|
||||
|
@@ -450,7 +450,7 @@ export default {
|
||||
});
|
||||
|
||||
this.defaultValue.onUpdate = this.localRow.onUpdate;
|
||||
this.defaultValue.type = this.localRow.defaultType;
|
||||
this.defaultValue.type = this.localRow.defaultType || 'noval';
|
||||
if (this.defaultValue.type === 'custom') {
|
||||
this.defaultValue.custom = this.localRow.default
|
||||
? this.localRow.default.includes('\'')
|
||||
@@ -458,8 +458,13 @@ export default {
|
||||
: this.localRow.default
|
||||
: '';
|
||||
}
|
||||
if (this.defaultValue.type === 'expression')
|
||||
this.defaultValue.expression = this.localRow.default;
|
||||
else if (this.defaultValue.type === 'expression') {
|
||||
console.log(this.localRow.default);
|
||||
if (this.localRow.default.toUpperCase().includes('ON UPDATE'))
|
||||
this.defaultValue.expression = this.localRow.default.replace(/ on update.*$/i, '');
|
||||
else
|
||||
this.defaultValue.expression = this.localRow.default;
|
||||
}
|
||||
},
|
||||
editON (event, content, field) {
|
||||
if (field === 'length') {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
v-show="isSelected"
|
||||
class="workspace-query-tab column col-12 columns col-gapless no-outline"
|
||||
class="workspace-query-tab column col-12 columns col-gapless no-outline p-0"
|
||||
tabindex="0"
|
||||
@keydown.116="runQuery(query)"
|
||||
@keydown.ctrl.87="clear"
|
||||
@@ -14,7 +14,7 @@
|
||||
:auto-focus="true"
|
||||
:value.sync="query"
|
||||
:workspace="workspace"
|
||||
:schema="schema"
|
||||
:schema="breadcrumbsSchema"
|
||||
:is-selected="isSelected"
|
||||
:height="editorHeight"
|
||||
/>
|
||||
@@ -86,12 +86,16 @@
|
||||
<div v-if="affectedCount">
|
||||
{{ $t('message.affectedRows') }}: <b>{{ affectedCount }}</b>
|
||||
</div>
|
||||
<div
|
||||
v-if="workspace.breadcrumbs.schema"
|
||||
class="d-flex"
|
||||
:title="$t('word.schema')"
|
||||
>
|
||||
<i class="mdi mdi-18px mdi-database mr-1" /><b>{{ workspace.breadcrumbs.schema }}</b>
|
||||
<div class="input-group" :title="$t('word.schema')">
|
||||
<i class="input-group-addon addon-sm mdi mdi-24px mdi-database" />
|
||||
<select v-model="selectedSchema" class="form-select select-sm text-bold">
|
||||
<option :value="null">
|
||||
{{ $t('message.noSchema') }}
|
||||
</option>
|
||||
<option v-for="schemaName in databaseSchemas" :key="schemaName">
|
||||
{{ schemaName }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -142,6 +146,7 @@ export default {
|
||||
lastQuery: '',
|
||||
isQuering: false,
|
||||
results: [],
|
||||
selectedSchema: null,
|
||||
resultsCount: 0,
|
||||
durationsCount: 0,
|
||||
affectedCount: 0,
|
||||
@@ -156,12 +161,32 @@ export default {
|
||||
workspace () {
|
||||
return this.getWorkspace(this.connection.uid);
|
||||
},
|
||||
breadcrumbsSchema () {
|
||||
return this.workspace.breadcrumbs.schema || null;
|
||||
},
|
||||
databaseSchemas () {
|
||||
return this.workspace.structure.reduce((acc, curr) => {
|
||||
acc.push(curr.name);
|
||||
return acc;
|
||||
}, []);
|
||||
},
|
||||
isWorkspaceSelected () {
|
||||
return this.workspace.uid === this.selectedWorkspace;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isSelected (val) {
|
||||
if (val)
|
||||
this.changeBreadcrumbs({ schema: this.selectedSchema, query: `Query #${this.tab.index}` });
|
||||
},
|
||||
selectedSchema () {
|
||||
this.changeBreadcrumbs({ schema: this.selectedSchema, query: `Query #${this.tab.index}` });
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.query = this.tab.content;
|
||||
this.selectedSchema = this.tab.schema || this.breadcrumbsSchema;
|
||||
// this.changeBreadcrumbs({ schema: this.selectedSchema, query: `Query #${this.tab.index}` });
|
||||
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
},
|
||||
@@ -183,7 +208,9 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
addNotification: 'notifications/addNotification'
|
||||
addNotification: 'notifications/addNotification',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
|
||||
updateTabContent: 'workspaces/updateTabContent'
|
||||
}),
|
||||
async runQuery (query) {
|
||||
if (!query || this.isQuering) return;
|
||||
@@ -194,7 +221,7 @@ export default {
|
||||
try { // Query Data
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
schema: this.selectedSchema,
|
||||
query
|
||||
};
|
||||
|
||||
@@ -205,6 +232,8 @@ export default {
|
||||
this.resultsCount += this.results.reduce((acc, curr) => acc + (curr.rows ? curr.rows.length : 0), 0);
|
||||
this.durationsCount += this.results.reduce((acc, curr) => acc + curr.duration, 0);
|
||||
this.affectedCount += this.results.reduce((acc, curr) => acc + (curr.report ? curr.report.affectedRows : 0), 0);
|
||||
|
||||
this.updateTabContent({ uid: this.connection.uid, tab: this.tab.uid, type: 'query', schema: this.selectedSchema, content: query });
|
||||
}
|
||||
else
|
||||
this.addNotification({ status: 'error', message: response });
|
||||
@@ -303,8 +332,10 @@ export default {
|
||||
align-items: center;
|
||||
height: 42px;
|
||||
|
||||
.workspace-query-buttons {
|
||||
.workspace-query-buttons,
|
||||
.workspace-query-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.btn {
|
||||
display: flex;
|
||||
@@ -314,7 +345,7 @@ export default {
|
||||
}
|
||||
|
||||
.workspace-query-info {
|
||||
display: flex;
|
||||
overflow: visible;
|
||||
|
||||
> div + div {
|
||||
padding-left: 0.6rem;
|
||||
|
@@ -10,6 +10,7 @@
|
||||
v-if="isContext"
|
||||
:context-event="contextEvent"
|
||||
:selected-rows="selectedRows"
|
||||
:selected-cell="selectedCell"
|
||||
@show-delete-modal="showDeleteConfirmModal"
|
||||
@set-null="setNull"
|
||||
@copy-cell="copyCell"
|
||||
@@ -71,6 +72,7 @@
|
||||
:row="row"
|
||||
:fields="fieldsObj"
|
||||
:key-usage="keyUsage"
|
||||
:element-type="elementType"
|
||||
:class="{'selected': selectedRows.includes(row._id)}"
|
||||
@select-row="selectRow($event, row._id)"
|
||||
@update-field="updateField($event, row)"
|
||||
@@ -123,7 +125,8 @@ export default {
|
||||
results: Array,
|
||||
connUid: String,
|
||||
mode: String,
|
||||
isSelected: Boolean
|
||||
isSelected: Boolean,
|
||||
elementType: { type: String, default: 'table' }
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -226,6 +229,9 @@ export default {
|
||||
},
|
||||
resultsetIndex () {
|
||||
this.setLocalResults();
|
||||
},
|
||||
isSelected (val) {
|
||||
if (val) this.refreshScroller();
|
||||
}
|
||||
},
|
||||
updated () {
|
||||
|
@@ -28,7 +28,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedRows.length === 1"
|
||||
v-if="selectedRows.length === 1 && selectedCell.isEditable"
|
||||
class="context-element"
|
||||
@click="setNull"
|
||||
>
|
||||
@@ -36,7 +36,11 @@
|
||||
<i class="mdi mdi-18px mdi-null text-light pr-1" /> {{ $t('message.setNull') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="context-element" @click="showConfirmModal">
|
||||
<div
|
||||
v-if="selectedCell.isEditable"
|
||||
class="context-element"
|
||||
@click="showConfirmModal"
|
||||
>
|
||||
<span class="d-flex">
|
||||
<i class="mdi mdi-18px mdi-delete text-light pr-1" /> {{ $tc('message.deleteRows', selectedRows.length) }}
|
||||
</span>
|
||||
@@ -54,7 +58,8 @@ export default {
|
||||
},
|
||||
props: {
|
||||
contextEvent: MouseEvent,
|
||||
selectedRows: Array
|
||||
selectedRows: Array,
|
||||
selectedCell: Object
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
|
@@ -260,7 +260,8 @@ export default {
|
||||
props: {
|
||||
row: Object,
|
||||
fields: Object,
|
||||
keyUsage: Array
|
||||
keyUsage: Array,
|
||||
elementType: { type: String, default: 'table' }
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -334,6 +335,8 @@ export default {
|
||||
return this.keyUsage.map(key => key.field);
|
||||
},
|
||||
isEditable () {
|
||||
if (this.elementType === 'view') return false;
|
||||
|
||||
if (this.fields) {
|
||||
const nElements = Object.keys(this.fields).reduce((acc, curr) => {
|
||||
acc.add(this.fields[curr].table);
|
||||
@@ -503,10 +506,9 @@ export default {
|
||||
return this.keyUsage.find(key => key.field === keyName);
|
||||
},
|
||||
openContext (event, payload) {
|
||||
if (this.isEditable) {
|
||||
payload.field = this.fields[payload.field].name;// Ensures field name only
|
||||
this.$emit('contextmenu', event, payload);
|
||||
}
|
||||
payload.field = this.fields[payload.field].name;// Ensures field name only
|
||||
payload.isEditable = this.isEditable;
|
||||
this.$emit('contextmenu', event, payload);
|
||||
},
|
||||
onKey (e) {
|
||||
e.stopPropagation();
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div v-show="isSelected" class="workspace-query-tab column col-12 columns col-gapless">
|
||||
<div v-show="isSelected" class="workspace-query-tab column col-12 columns col-gapless no-outline p-0">
|
||||
<div class="workspace-query-runner column col-12">
|
||||
<div class="workspace-query-runner-footer">
|
||||
<div class="workspace-query-buttons">
|
||||
@@ -115,8 +115,8 @@
|
||||
<div v-if="hasApproximately || (page > 1 && tableInfo.rows)">
|
||||
{{ $t('word.total') }}: <b>{{ tableInfo.rows | localeString }}</b> <small>({{ $t('word.approximately') }})</small>
|
||||
</div>
|
||||
<div v-if="workspace.breadcrumbs.database">
|
||||
{{ $t('word.schema') }}: <b>{{ workspace.breadcrumbs.database }}</b>
|
||||
<div class="d-flex" :title="$t('word.schema')">
|
||||
<i class="mdi mdi-18px mdi-database mr-1" /><b>{{ schema }}</b>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -131,6 +131,7 @@
|
||||
:conn-uid="connection.uid"
|
||||
:is-selected="isSelected"
|
||||
mode="table"
|
||||
:element-type="elementType"
|
||||
@update-field="updateField"
|
||||
@delete-selected="deleteSelected"
|
||||
@hard-sort="hardSort"
|
||||
@@ -181,11 +182,14 @@ export default {
|
||||
mixins: [tableTabs],
|
||||
props: {
|
||||
connection: Object,
|
||||
table: String
|
||||
isSelected: Boolean,
|
||||
table: String,
|
||||
schema: String,
|
||||
elementType: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tabUid: 'data',
|
||||
tabUid: 'data', // ???
|
||||
isQuering: false,
|
||||
isPageMenu: false,
|
||||
results: [],
|
||||
@@ -208,9 +212,6 @@ export default {
|
||||
workspace () {
|
||||
return this.getWorkspace(this.connection.uid);
|
||||
},
|
||||
isSelected () {
|
||||
return this.workspace.selected_tab === 'data' && this.workspace.uid === this.selectedWorkspace;
|
||||
},
|
||||
isTable () {
|
||||
return !!this.workspace.breadcrumbs.table;
|
||||
},
|
||||
@@ -237,6 +238,15 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
schema () {
|
||||
if (this.isSelected) {
|
||||
this.page = 1;
|
||||
this.sortParams = {};
|
||||
this.getTableData();
|
||||
this.lastTable = this.table;
|
||||
this.$refs.queryTable.resetSort();
|
||||
}
|
||||
},
|
||||
table () {
|
||||
if (this.isSelected) {
|
||||
this.page = 1;
|
||||
@@ -253,9 +263,11 @@ export default {
|
||||
}
|
||||
},
|
||||
isSelected (val) {
|
||||
if (val && this.lastTable !== this.table) {
|
||||
this.getTableData();
|
||||
this.lastTable = this.table;
|
||||
if (val) {
|
||||
this.changeBreadcrumbs({ schema: this.schema, [this.elementType]: this.table });
|
||||
|
||||
if (this.lastTable !== this.table)
|
||||
this.getTableData();
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -269,9 +281,10 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
addNotification: 'notifications/addNotification'
|
||||
addNotification: 'notifications/addNotification',
|
||||
changeBreadcrumbs: 'workspaces/changeBreadcrumbs'
|
||||
}),
|
||||
async getTableData (sortParams) {
|
||||
async getTableData () {
|
||||
if (!this.table) return;
|
||||
this.isQuering = true;
|
||||
|
||||
@@ -279,13 +292,15 @@ export default {
|
||||
if (this.lastTable !== this.table)
|
||||
this.results = [];
|
||||
|
||||
this.lastTable = this.table;
|
||||
|
||||
const params = {
|
||||
uid: this.connection.uid,
|
||||
schema: this.schema,
|
||||
table: this.workspace.breadcrumbs.table || this.workspace.breadcrumbs.view,
|
||||
table: this.table,
|
||||
limit: this.limit,
|
||||
page: this.page,
|
||||
sortParams
|
||||
sortParams: this.sortParams
|
||||
};
|
||||
|
||||
try { // Table data
|
||||
@@ -306,14 +321,14 @@ export default {
|
||||
return this.table;
|
||||
},
|
||||
reloadTable () {
|
||||
this.getTableData(this.sortParams);
|
||||
this.getTableData();
|
||||
},
|
||||
hardSort (sortParams) {
|
||||
this.sortParams = sortParams;
|
||||
this.getTableData(sortParams);
|
||||
this.getTableData();
|
||||
},
|
||||
openPageMenu () {
|
||||
if (this.isQuering) return;
|
||||
if (this.isQuering || (this.results.length && this.results[0].rows.length < this.limit && this.page === 1)) return;
|
||||
|
||||
this.isPageMenu = true;
|
||||
if (this.isPageMenu)
|
||||
|
@@ -1,489 +0,0 @@
|
||||
<template>
|
||||
<div class="modal active">
|
||||
<a class="modal-overlay c-hand" @click="closeModal" />
|
||||
<div class="modal-container">
|
||||
<div class="modal-header pl-2">
|
||||
<div class="modal-title h6">
|
||||
<div class="d-flex">
|
||||
<i class="mdi mdi-24px mdi-server mr-1" /> {{ $t('message.editConnection') }}
|
||||
</div>
|
||||
</div>
|
||||
<a class="btn btn-clear c-hand" @click="closeModal" />
|
||||
</div>
|
||||
<div class="modal-body p-0">
|
||||
<div class="panel">
|
||||
<div class="panel-nav">
|
||||
<ul class="tab tab-block">
|
||||
<li
|
||||
class="tab-item c-hand"
|
||||
:class="{'active': selectedTab === 'general'}"
|
||||
@click="selectTab('general')"
|
||||
>
|
||||
<a class="tab-link">{{ $t('word.general') }}</a>
|
||||
</li>
|
||||
<li
|
||||
class="tab-item c-hand"
|
||||
:class="{'active': selectedTab === 'ssl'}"
|
||||
@click="selectTab('ssl')"
|
||||
>
|
||||
<a class="tab-link">{{ $t('word.ssl') }}</a>
|
||||
</li>
|
||||
<li
|
||||
class="tab-item"
|
||||
:class="{'active': selectedTab === 'ssh'}"
|
||||
@click="selectTab('ssh')"
|
||||
>
|
||||
<a class="c-hand">{{ $t('word.sshTunnel') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-if="selectedTab === 'general'" class="panel-body py-0">
|
||||
<div class="container">
|
||||
<form class="form-horizontal">
|
||||
<fieldset class="m-0" :disabled="isTesting">
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.connectionName') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
ref="firstInput"
|
||||
v-model="localConnection.name"
|
||||
class="form-input"
|
||||
type="text"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.client') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<select v-model="localConnection.client" class="form-select">
|
||||
<option value="mysql">
|
||||
MySQL
|
||||
</option>
|
||||
<option value="maria">
|
||||
MariaDB
|
||||
</option>
|
||||
<option value="pg">
|
||||
PostgreSQL
|
||||
</option>
|
||||
<!-- <option value="mssql">
|
||||
Microsoft SQL
|
||||
</option>
|
||||
<option value="oracledb">
|
||||
Oracle DB
|
||||
</option> -->
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.hostName') }}/IP</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="localConnection.host"
|
||||
class="form-input"
|
||||
type="text"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.port') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="localConnection.port"
|
||||
class="form-input"
|
||||
type="number"
|
||||
min="1"
|
||||
max="65535"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="customizations.database" class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.database') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="localConnection.database"
|
||||
class="form-input"
|
||||
type="text"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.user') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="localConnection.user"
|
||||
class="form-input"
|
||||
type="text"
|
||||
:disabled="localConnection.ask"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.password') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="localConnection.password"
|
||||
class="form-input"
|
||||
type="password"
|
||||
:disabled="localConnection.ask"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12" />
|
||||
<div class="col-8 col-sm-12">
|
||||
<label class="form-checkbox form-inline">
|
||||
<input v-model="localConnection.ask" type="checkbox"><i class="form-icon" /> {{ $t('message.askCredentials') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<BaseToast
|
||||
class="mb-2"
|
||||
:message="toast.message"
|
||||
:status="toast.status"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="selectedTab === 'ssl'" class="panel-body py-0">
|
||||
<div class="container">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">
|
||||
{{ $t('message.enableSsl') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<label class="form-switch d-inline-block" @click.prevent="toggleSsl">
|
||||
<input type="checkbox" :checked="localConnection.ssl">
|
||||
<i class="form-icon" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="m-0" :disabled="isTesting || !localConnection.ssl">
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.privateKey') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<BaseUploadInput
|
||||
:value="localConnection.key"
|
||||
:message="$t('word.browse')"
|
||||
@clear="pathClear('key')"
|
||||
@change="pathSelection($event, 'key')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.certificate') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<BaseUploadInput
|
||||
:value="localConnection.cert"
|
||||
:message="$t('word.browse')"
|
||||
@clear="pathClear('cert')"
|
||||
@change="pathSelection($event, 'cert')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.caCertificate') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<BaseUploadInput
|
||||
:value="localConnection.ca"
|
||||
:message="$t('word.browse')"
|
||||
@clear="pathClear('ca')"
|
||||
@change="pathSelection($event, 'ca')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.ciphers') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
ref="firstInput"
|
||||
v-model="localConnection.ciphers"
|
||||
class="form-input"
|
||||
type="text"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<BaseToast
|
||||
class="mb-2"
|
||||
:message="toast.message"
|
||||
:status="toast.status"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="selectedTab === 'ssh'" class="panel-body py-0">
|
||||
<div class="container">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">
|
||||
{{ $t('message.enableSsh') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<label class="form-switch d-inline-block" @click.prevent="toggleSsh">
|
||||
<input type="checkbox" :checked="localConnection.ssh">
|
||||
<i class="form-icon" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="m-0" :disabled="isTesting || !localConnection.ssh">
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.hostName') }}/IP</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="localConnection.sshHost"
|
||||
class="form-input"
|
||||
type="text"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.user') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="localConnection.sshUser"
|
||||
class="form-input"
|
||||
type="text"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.password') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="localConnection.sshPass"
|
||||
class="form-input"
|
||||
type="password"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.port') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="localConnection.sshPort"
|
||||
class="form-input"
|
||||
type="number"
|
||||
min="1"
|
||||
max="65535"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.privateKey') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<BaseUploadInput
|
||||
:value="localConnection.sshKey"
|
||||
:message="$t('word.browse')"
|
||||
@clear="pathClear('sshKey')"
|
||||
@change="pathSelection($event, 'sshKey')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<BaseToast
|
||||
class="mb-2"
|
||||
:message="toast.message"
|
||||
:status="toast.status"
|
||||
/>
|
||||
</div>
|
||||
<div class="modal-footer text-light">
|
||||
<button
|
||||
class="btn btn-gray mr-2"
|
||||
:class="{'loading': isTesting}"
|
||||
@click="startTest"
|
||||
>
|
||||
{{ $t('message.testConnection') }}
|
||||
</button>
|
||||
<button class="btn btn-primary mr-2" @click="saveEditConnection">
|
||||
{{ $t('word.save') }}
|
||||
</button>
|
||||
<button class="btn btn-link" @click="closeModal">
|
||||
{{ $t('word.close') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<ModalAskCredentials
|
||||
v-if="isAsking"
|
||||
@close-asking="closeAsking"
|
||||
@credentials="continueTest"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex';
|
||||
import customizations from 'common/customizations';
|
||||
import Connection from '@/ipc-api/Connection';
|
||||
import ModalAskCredentials from '@/components/ModalAskCredentials';
|
||||
import BaseToast from '@/components/BaseToast';
|
||||
import BaseUploadInput from '@/components/BaseUploadInput';
|
||||
|
||||
export default {
|
||||
name: 'ModalEditConnection',
|
||||
components: {
|
||||
ModalAskCredentials,
|
||||
BaseToast,
|
||||
BaseUploadInput
|
||||
},
|
||||
props: {
|
||||
connection: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
toast: {
|
||||
status: '',
|
||||
message: ''
|
||||
},
|
||||
isTesting: false,
|
||||
isAsking: false,
|
||||
localConnection: null,
|
||||
selectedTab: 'general'
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
customizations () {
|
||||
return customizations[this.connection.client];
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.localConnection = Object.assign({}, this.connection);
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
|
||||
setTimeout(() => {
|
||||
this.$refs.firstInput.focus();
|
||||
}, 20);
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('keydown', this.onKey);
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
editConnection: 'connections/editConnection'
|
||||
}),
|
||||
async startTest () {
|
||||
this.isTesting = true;
|
||||
this.toast = {
|
||||
status: '',
|
||||
message: ''
|
||||
};
|
||||
|
||||
if (this.localConnection.ask)
|
||||
this.isAsking = true;
|
||||
else {
|
||||
try {
|
||||
const res = await Connection.makeTest(this.localConnection);
|
||||
if (res.status === 'error')
|
||||
this.toast = { status: 'error', message: res.response.message };
|
||||
else
|
||||
this.toast = { status: 'success', message: this.$t('message.connectionSuccessfullyMade') };
|
||||
}
|
||||
catch (err) {
|
||||
this.toast = { status: 'error', message: err.stack };
|
||||
}
|
||||
|
||||
this.isTesting = false;
|
||||
}
|
||||
},
|
||||
async continueTest (credentials) { // if "Ask for credentials" is true
|
||||
this.isAsking = false;
|
||||
const params = Object.assign({}, this.localConnection, credentials);
|
||||
try {
|
||||
const res = await Connection.makeTest(params);
|
||||
if (res.status === 'error')
|
||||
this.toast = { status: 'error', message: res.response.message };
|
||||
else
|
||||
this.toast = { status: 'success', message: this.$t('message.connectionSuccessfullyMade') };
|
||||
}
|
||||
catch (err) {
|
||||
this.toast = { status: 'error', message: err.stack };
|
||||
}
|
||||
|
||||
this.isTesting = false;
|
||||
},
|
||||
saveEditConnection () {
|
||||
this.editConnection(this.localConnection);
|
||||
this.closeModal();
|
||||
},
|
||||
closeAsking () {
|
||||
this.isTesting = false;
|
||||
this.isAsking = false;
|
||||
},
|
||||
closeModal () {
|
||||
this.$emit('close');
|
||||
},
|
||||
onKey (e) {
|
||||
e.stopPropagation();
|
||||
if (e.key === 'Escape')
|
||||
this.closeModal();
|
||||
},
|
||||
selectTab (tab) {
|
||||
this.selectedTab = tab;
|
||||
},
|
||||
toggleSsl () {
|
||||
this.localConnection.ssl = !this.localConnection.ssl;
|
||||
},
|
||||
toggleSsh () {
|
||||
this.localConnection.ssh = !this.localConnection.ssh;
|
||||
},
|
||||
pathSelection (event, name) {
|
||||
const { files } = event.target;
|
||||
if (!files.length) return;
|
||||
|
||||
this.localConnection[name] = files[0].path;
|
||||
},
|
||||
pathClear (name) {
|
||||
this.localConnection[name] = '';
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.modal-container {
|
||||
position: absolute;
|
||||
max-width: 450px;
|
||||
top: 17.5vh;
|
||||
}
|
||||
</style>
|
@@ -1,518 +0,0 @@
|
||||
<template>
|
||||
<div class="modal active">
|
||||
<a class="modal-overlay c-hand" @click="closeModal" />
|
||||
<div class="modal-container">
|
||||
<div class="modal-header pl-2">
|
||||
<div class="modal-title h6">
|
||||
<div class="d-flex">
|
||||
<i class="mdi mdi-24px mdi-server-plus mr-1" />
|
||||
<span class="cut-text">{{ $t('message.createNewConnection') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<a class="btn btn-clear c-hand" @click="closeModal" />
|
||||
</div>
|
||||
<div class="modal-body p-0">
|
||||
<div class="panel">
|
||||
<div class="panel-nav">
|
||||
<ul class="tab tab-block">
|
||||
<li
|
||||
class="tab-item c-hand"
|
||||
:class="{'active': selectedTab === 'general'}"
|
||||
@click="selectTab('general')"
|
||||
>
|
||||
<a class="tab-link">{{ $t('word.general') }}</a>
|
||||
</li>
|
||||
<li
|
||||
class="tab-item c-hand"
|
||||
:class="{'active': selectedTab === 'ssl'}"
|
||||
@click="selectTab('ssl')"
|
||||
>
|
||||
<a class="tab-link">{{ $t('word.ssl') }}</a>
|
||||
</li>
|
||||
<li
|
||||
class="tab-item"
|
||||
:class="{'active': selectedTab === 'ssh'}"
|
||||
@click="selectTab('ssh')"
|
||||
>
|
||||
<a class="c-hand">{{ $t('word.sshTunnel') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-if="selectedTab === 'general'" class="panel-body py-0">
|
||||
<div class="container">
|
||||
<form class="form-horizontal">
|
||||
<fieldset class="m-0" :disabled="isTesting">
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.connectionName') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
ref="firstInput"
|
||||
v-model="connection.name"
|
||||
class="form-input"
|
||||
type="text"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.client') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<select
|
||||
v-model="connection.client"
|
||||
class="form-select"
|
||||
@change="setDefaults"
|
||||
>
|
||||
<option value="mysql">
|
||||
MySQL
|
||||
</option>
|
||||
<option value="maria">
|
||||
MariaDB
|
||||
</option>
|
||||
<option value="pg">
|
||||
PostgreSQL
|
||||
</option>
|
||||
<!-- <option value="mssql">
|
||||
Microsoft SQL
|
||||
</option>
|
||||
<option value="oracledb">
|
||||
Oracle DB
|
||||
</option> -->
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.hostName') }}/IP</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="connection.host"
|
||||
class="form-input"
|
||||
type="text"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.port') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="connection.port"
|
||||
class="form-input"
|
||||
type="number"
|
||||
min="1"
|
||||
max="65535"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="customizations.database" class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.database') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="connection.database"
|
||||
class="form-input"
|
||||
type="text"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.user') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="connection.user"
|
||||
class="form-input"
|
||||
type="text"
|
||||
:disabled="connection.ask"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.password') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="connection.password"
|
||||
class="form-input"
|
||||
type="password"
|
||||
:disabled="connection.ask"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12" />
|
||||
<div class="col-8 col-sm-12">
|
||||
<label class="form-checkbox form-inline">
|
||||
<input v-model="connection.ask" type="checkbox"><i class="form-icon" /> {{ $t('message.askCredentials') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<BaseToast
|
||||
class="mb-2"
|
||||
:message="toast.message"
|
||||
:status="toast.status"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="selectedTab === 'ssl'" class="panel-body py-0">
|
||||
<div class="container">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">
|
||||
{{ $t('message.enableSsl') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<label class="form-switch d-inline-block" @click.prevent="toggleSsl">
|
||||
<input type="checkbox" :checked="connection.ssl">
|
||||
<i class="form-icon" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="m-0" :disabled="isTesting || !connection.ssl">
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.privateKey') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<BaseUploadInput
|
||||
:value="connection.key"
|
||||
:message="$t('word.browse')"
|
||||
@clear="pathClear('key')"
|
||||
@change="pathSelection($event, 'key')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.certificate') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<BaseUploadInput
|
||||
:value="connection.cert"
|
||||
:message="$t('word.browse')"
|
||||
@clear="pathClear('cert')"
|
||||
@change="pathSelection($event, 'cert')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.caCertificate') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<BaseUploadInput
|
||||
:value="connection.ca"
|
||||
:message="$t('word.browse')"
|
||||
@clear="pathClear('ca')"
|
||||
@change="pathSelection($event, 'ca')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.ciphers') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
ref="firstInput"
|
||||
v-model="connection.ciphers"
|
||||
class="form-input"
|
||||
type="text"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<BaseToast
|
||||
class="mb-2"
|
||||
:message="toast.message"
|
||||
:status="toast.status"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="selectedTab === 'ssh'" class="panel-body py-0">
|
||||
<div class="container">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">
|
||||
{{ $t('message.enableSsh') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<label class="form-switch d-inline-block" @click.prevent="toggleSsh">
|
||||
<input type="checkbox" :checked="connection.ssh">
|
||||
<i class="form-icon" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="m-0" :disabled="isTesting || !connection.ssh">
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.hostName') }}/IP</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="connection.sshHost"
|
||||
class="form-input"
|
||||
type="text"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.user') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="connection.sshUser"
|
||||
class="form-input"
|
||||
type="text"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.password') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="connection.sshPass"
|
||||
class="form-input"
|
||||
type="password"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.port') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<input
|
||||
v-model="connection.sshPort"
|
||||
class="form-input"
|
||||
type="number"
|
||||
min="1"
|
||||
max="65535"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-4 col-sm-12">
|
||||
<label class="form-label">{{ $t('word.privateKey') }}</label>
|
||||
</div>
|
||||
<div class="col-8 col-sm-12">
|
||||
<BaseUploadInput
|
||||
:value="connection.sshKey"
|
||||
:message="$t('word.browse')"
|
||||
@clear="pathClear('sshKey')"
|
||||
@change="pathSelection($event, 'sshKey')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<BaseToast
|
||||
class="mb-2"
|
||||
:message="toast.message"
|
||||
:status="toast.status"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer text-light">
|
||||
<button
|
||||
class="btn btn-gray mr-2"
|
||||
:class="{'loading': isTesting}"
|
||||
@click="startTest"
|
||||
>
|
||||
{{ $t('message.testConnection') }}
|
||||
</button>
|
||||
<button class="btn btn-primary mr-2" @click="saveNewConnection">
|
||||
{{ $t('word.save') }}
|
||||
</button>
|
||||
<button class="btn btn-link" @click="closeModal">
|
||||
{{ $t('word.close') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<ModalAskCredentials
|
||||
v-if="isAsking"
|
||||
@close-asking="closeAsking"
|
||||
@credentials="continueTest"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex';
|
||||
import customizations from 'common/customizations';
|
||||
import Connection from '@/ipc-api/Connection';
|
||||
import { uidGen } from 'common/libs/uidGen';
|
||||
import ModalAskCredentials from '@/components/ModalAskCredentials';
|
||||
import BaseToast from '@/components/BaseToast';
|
||||
import BaseUploadInput from '@/components/BaseUploadInput';
|
||||
|
||||
export default {
|
||||
name: 'ModalNewConnection',
|
||||
components: {
|
||||
ModalAskCredentials,
|
||||
BaseToast,
|
||||
BaseUploadInput
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
connection: {
|
||||
name: '',
|
||||
client: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
database: null,
|
||||
port: null,
|
||||
user: null,
|
||||
password: '',
|
||||
ask: false,
|
||||
uid: uidGen('C'),
|
||||
ssl: false,
|
||||
cert: '',
|
||||
key: '',
|
||||
ca: '',
|
||||
ciphers: '',
|
||||
ssh: false,
|
||||
sshHost: '',
|
||||
sshUser: '',
|
||||
sshPass: '',
|
||||
sshKey: '',
|
||||
sshPort: 22
|
||||
},
|
||||
toast: {
|
||||
status: '',
|
||||
message: ''
|
||||
},
|
||||
isTesting: false,
|
||||
isAsking: false,
|
||||
selectedTab: 'general'
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
customizations () {
|
||||
return customizations[this.connection.client];
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.setDefaults();
|
||||
window.addEventListener('keydown', this.onKey);
|
||||
|
||||
setTimeout(() => {
|
||||
this.$refs.firstInput.focus();
|
||||
}, 20);
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('keydown', this.onKey);
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
closeModal: 'application/hideNewConnModal',
|
||||
addConnection: 'connections/addConnection'
|
||||
}),
|
||||
setDefaults () {
|
||||
this.connection.user = this.customizations.defaultUser;
|
||||
this.connection.port = this.customizations.defaultPort;
|
||||
this.connection.database = this.customizations.defaultDatabase;
|
||||
},
|
||||
async startTest () {
|
||||
this.isTesting = true;
|
||||
this.toast = {
|
||||
status: '',
|
||||
message: ''
|
||||
};
|
||||
|
||||
if (this.connection.ask)
|
||||
this.isAsking = true;
|
||||
else {
|
||||
try {
|
||||
const res = await Connection.makeTest(this.connection);
|
||||
console.log(res.response);
|
||||
if (res.status === 'error')
|
||||
this.toast = { status: 'error', message: res.response.message };
|
||||
else
|
||||
this.toast = { status: 'success', message: this.$t('message.connectionSuccessfullyMade') };
|
||||
}
|
||||
catch (err) {
|
||||
this.toast = { status: 'error', message: err.stack };
|
||||
}
|
||||
|
||||
this.isTesting = false;
|
||||
}
|
||||
},
|
||||
async continueTest (credentials) { // if "Ask for credentials" is true
|
||||
this.isAsking = false;
|
||||
const params = Object.assign({}, this.connection, credentials);
|
||||
|
||||
try {
|
||||
const res = await Connection.makeTest(params);
|
||||
if (res.status === 'error')
|
||||
this.toast = { status: 'error', message: res.response.message };
|
||||
else
|
||||
this.toast = { status: 'success', message: this.$t('message.connectionSuccessfullyMade') };
|
||||
}
|
||||
catch (err) {
|
||||
this.toast = { status: 'error', message: err.stack };
|
||||
}
|
||||
|
||||
this.isTesting = false;
|
||||
},
|
||||
saveNewConnection () {
|
||||
this.addConnection(this.connection);
|
||||
this.closeModal();
|
||||
},
|
||||
closeAsking () {
|
||||
this.isAsking = false;
|
||||
this.isTesting = false;
|
||||
},
|
||||
onKey (e) {
|
||||
e.stopPropagation();
|
||||
if (e.key === 'Escape')
|
||||
this.closeModal();
|
||||
},
|
||||
selectTab (tab) {
|
||||
this.selectedTab = tab;
|
||||
},
|
||||
toggleSsl () {
|
||||
this.connection.ssl = !this.connection.ssl;
|
||||
},
|
||||
toggleSsh () {
|
||||
this.connection.ssh = !this.connection.ssh;
|
||||
},
|
||||
pathSelection (event, name) {
|
||||
const { files } = event.target;
|
||||
if (!files.length) return;
|
||||
|
||||
this.connection[name] = files[0].path;
|
||||
},
|
||||
pathClear (name) {
|
||||
this.connection[name] = '';
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.modal-container {
|
||||
position: absolute;
|
||||
max-width: 450px;
|
||||
top: 17.5vh;
|
||||
}
|
||||
</style>
|
@@ -1,37 +0,0 @@
|
||||
<template>
|
||||
<div class="columns">
|
||||
<div class="column col-12 empty text-light">
|
||||
<div class="empty-icon">
|
||||
<i class="mdi mdi-48px mdi-emoticon" />
|
||||
</div>
|
||||
<p class="empty-title h5">
|
||||
{{ $t('message.appWelcome') }}
|
||||
</p>
|
||||
<p class="empty-subtitle">
|
||||
{{ $t('message.appFirstStep') }}
|
||||
</p>
|
||||
<div class="empty-action">
|
||||
<button class="btn btn-primary" @click="$emit('new-conn')">
|
||||
{{ $t('message.createConnection') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'TheAppWelcome'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.empty {
|
||||
height: 100%;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
@@ -1,82 +0,0 @@
|
||||
<template>
|
||||
<div class="columns">
|
||||
<div class="column col-12 empty">
|
||||
<div class="empty-icon">
|
||||
<i class="mdi mdi-48px mdi-power-plug-off" />
|
||||
</div>
|
||||
<p class="empty-title h5">
|
||||
{{ isConnecting ? $t('word.connecting') : $t('word.disconnected') }}
|
||||
</p>
|
||||
<div class="empty-action">
|
||||
<button
|
||||
class="btn btn-success"
|
||||
:class="{'loading': isConnecting}"
|
||||
@click="startConnection"
|
||||
>
|
||||
{{ $t('word.connect') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<ModalAskCredentials
|
||||
v-if="isAsking"
|
||||
@close-asking="closeAsking"
|
||||
@credentials="continueTest"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex';
|
||||
import ModalAskCredentials from '@/components/ModalAskCredentials';
|
||||
|
||||
export default {
|
||||
name: 'WorkspaceConnectPanel',
|
||||
components: {
|
||||
ModalAskCredentials
|
||||
},
|
||||
props: {
|
||||
connection: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isConnecting: false,
|
||||
isAsking: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
connectWorkspace: 'workspaces/connectWorkspace'
|
||||
}),
|
||||
async startConnection () {
|
||||
this.isConnecting = true;
|
||||
|
||||
if (this.connection.ask)
|
||||
this.isAsking = true;
|
||||
else {
|
||||
await this.connectWorkspace(this.connection);
|
||||
this.isConnecting = false;
|
||||
}
|
||||
},
|
||||
async continueTest (credentials) { // if "Ask for credentials" is true
|
||||
this.isAsking = false;
|
||||
const params = Object.assign({}, this.connection, credentials);
|
||||
await this.connectWorkspace(params);
|
||||
this.isConnecting = false;
|
||||
},
|
||||
closeAsking () {
|
||||
this.isAsking = false;
|
||||
this.isConnecting = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.empty {
|
||||
height: 100%;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
@@ -169,7 +169,7 @@ module.exports = {
|
||||
deleteTable: 'Delete table',
|
||||
emptyCorfirm: 'Do you confirm to empty',
|
||||
unsavedChanges: 'Unsaved changes',
|
||||
discardUnsavedChanges: 'You have some unsaved changes. By leaving this tab these changes will be discarded.',
|
||||
discardUnsavedChanges: 'You have some unsaved changes. Closing this tab these changes will be discarded.',
|
||||
thereAreNoIndexes: 'There are no indexes',
|
||||
thereAreNoForeign: 'There are no foreign keys',
|
||||
createNewForeign: 'Create new foreign key',
|
||||
@@ -224,7 +224,10 @@ module.exports = {
|
||||
dataTabPageSize: 'DATA tab page size',
|
||||
enableSsh: 'Enable SSH',
|
||||
pageNumber: 'Page number',
|
||||
duplicateTable: 'Duplicate table'
|
||||
duplicateTable: 'Duplicate table',
|
||||
noOpenTabs: 'There are no open tabs, navigate on the left bar or:',
|
||||
noSchema: 'No schema',
|
||||
restorePreviourSession: 'Restore previous session'
|
||||
},
|
||||
faker: {
|
||||
address: 'Address',
|
||||
|
301
src/renderer/images/logo-dark.svg
Normal file
301
src/renderer/images/logo-dark.svg
Normal file
@@ -0,0 +1,301 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 1024 1024"
|
||||
style="enable-background:new 0 0 1024 1024;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="Antares-shape-2.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs80" /><sodipodi:namedview
|
||||
id="namedview78"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.66015625"
|
||||
inkscape:cx="210.55621"
|
||||
inkscape:cy="511.2426"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1009"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g75" />
|
||||
<style
|
||||
type="text/css"
|
||||
id="style2">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
.st1{fill:url(#XMLID_15_);}
|
||||
.st2{opacity:0.5;fill:#FFBC00;}
|
||||
.st3{fill:#FFBC00;}
|
||||
.st4{fill:url(#XMLID_16_);}
|
||||
.st5{fill:url(#XMLID_17_);}
|
||||
.st6{fill:url(#XMLID_18_);}
|
||||
.st7{fill:url(#XMLID_19_);}
|
||||
.st8{fill:url(#XMLID_20_);}
|
||||
.st9{fill:url(#XMLID_21_);}
|
||||
.st10{opacity:0.46;}
|
||||
.st11{fill:url(#XMLID_23_);}
|
||||
.st12{fill:url(#XMLID_24_);}
|
||||
.st13{fill:url(#XMLID_25_);}
|
||||
.st14{fill:url(#XMLID_27_);}
|
||||
.st15{fill:url(#XMLID_28_);}
|
||||
.st16{fill:url(#XMLID_29_);}
|
||||
.st17{fill:url(#XMLID_30_);}
|
||||
.st18{opacity:0.75;}
|
||||
.st19{opacity:0.44;clip-path:url(#XMLID_31_);}
|
||||
.st20{fill:url(#XMLID_32_);}
|
||||
.st21{fill:url(#XMLID_33_);}
|
||||
.st22{fill:url(#XMLID_34_);}
|
||||
.st23{fill:url(#XMLID_35_);}
|
||||
.st24{fill:url(#XMLID_37_);}
|
||||
.st25{fill:url(#XMLID_38_);}
|
||||
.st26{opacity:0.43;fill:#FFBC00;}
|
||||
.st27{opacity:0.58;fill:#FFBC00;}
|
||||
.st28{fill:#FFBE06;}
|
||||
.st29{fill:none;}
|
||||
.st30{fill:url(#XMLID_42_);}
|
||||
.st31{fill:url(#XMLID_43_);}
|
||||
.st32{fill:url(#XMLID_44_);}
|
||||
.st33{fill:url(#XMLID_45_);}
|
||||
.st34{fill:url(#XMLID_46_);}
|
||||
.st35{fill:url(#SVGID_4_);}
|
||||
.st36{fill:url(#SVGID_5_);}
|
||||
.st37{fill:url(#SVGID_6_);}
|
||||
.st38{fill:url(#SVGID_7_);}
|
||||
.st39{fill:url(#SVGID_8_);}
|
||||
.st40{fill:url(#SVGID_11_);}
|
||||
.st41{fill:url(#SVGID_12_);}
|
||||
.st42{fill:url(#SVGID_13_);}
|
||||
.st43{fill:url(#SVGID_14_);}
|
||||
.st44{fill:#C68D00;}
|
||||
.st45{fill:#CE000F;}
|
||||
</style>
|
||||
<g
|
||||
id="g75">
|
||||
<radialGradient
|
||||
id="XMLID_15_"
|
||||
cx="358.2692"
|
||||
cy="227.2655"
|
||||
r="830.0055"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#F6971E"
|
||||
id="stop4" />
|
||||
<stop
|
||||
offset="0.6338"
|
||||
style="stop-color:#F4592D"
|
||||
id="stop6" />
|
||||
<stop
|
||||
offset="0.7025"
|
||||
style="stop-color:#EF4F29"
|
||||
id="stop8" />
|
||||
<stop
|
||||
offset="0.8178"
|
||||
style="stop-color:#E1351D"
|
||||
id="stop10" />
|
||||
<stop
|
||||
offset="0.9647"
|
||||
style="stop-color:#CA0B0B"
|
||||
id="stop12" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#C40006"
|
||||
id="stop14" />
|
||||
</radialGradient>
|
||||
<path
|
||||
id="XMLID_124_"
|
||||
style="fill:#ffffff;fill-opacity:0.15000001"
|
||||
class="st1"
|
||||
d="M 510.30078 9.0996094 A 502.79999 502.79999 0 0 0 7.5 511.90039 A 502.79999 502.79999 0 0 0 510.30078 1014.6992 A 502.79999 502.79999 0 0 0 1013.0996 511.90039 A 502.79999 502.79999 0 0 0 510.30078 9.0996094 z M 326.17578 78.685547 C 349.74023 78.648438 372.16211 83.875 393.09961 95 C 420.19961 112.9 439.6 136.99922 455 172.69922 C 465.4 205.69922 469.30078 238.79961 465.80078 281.59961 C 457.70078 373.59961 411.09922 469.09961 341.19922 531.59961 C 312.29922 557.49961 284.4 573.59961 256.5 589.59961 L 256.69922 593.19922 C 279.39922 594.99922 301.39922 586.10078 326.19922 571.80078 C 415.89922 516.50078 483.49922 397.69922 504.69922 285.19922 C 495.49922 338.79922 478.19922 391.4 449.69922 445 C 423.79922 489.6 397.30039 527.1 359.40039 562 C 300.00039 612.9 238.89961 638.80078 183.09961 626.30078 C 122.39961 611.00078 90.399609 545.8 92.599609 461 C 92.399609 457.4 92.1 453.89961 89 455.59961 C 87.6 458.29961 84.700781 463.60078 83.300781 466.30078 C 69.000781 517.30078 77.1 562.79922 91 601.19922 C 116.5 666.39922 177.79922 688.69922 244.69922 676.19922 C 204.99922 685.99922 167.69922 683.3 134.19922 665.5 C 107.09922 647.6 84.599609 625.30039 70.599609 586.90039 C 55.899609 537.80039 50.700391 486.89922 70.400391 421.69922 C 95.300391 338.69922 139.50078 255.59922 207.30078 209.19922 C 227.30078 195.79922 245.99922 185.09961 267.69922 172.59961 C 270.79922 170.79961 270.60039 167.20039 268.90039 166.40039 C 159.40039 170.00039 46.500391 333.30039 20.900391 474.40039 C 36.400391 372.60039 87.500391 272.6 167.90039 198.5 C 213.50039 157.4 258.79922 136.89922 305.19922 130.69922 C 386.89922 122.69922 437.10078 194.1 434.80078 299.5 C 435.00078 303.1 436.70039 304.00039 438.40039 304.90039 C 446.50039 281.70039 451.39961 260.29922 451.59961 239.69922 C 451.50293 126.5894 381.21362 66.112098 291.87891 82.363281 C 288.79216 82.977349 285.71662 83.531343 282.59961 84.300781 C 285.71508 83.559319 288.80642 82.922208 291.87891 82.363281 C 303.5351 80.044429 314.99734 78.703151 326.17578 78.685547 z M 858.04883 508.3457 C 873.78027 508.64453 888.6875 512.44922 902.5 520.19922 C 920.3 532.49922 935.10078 547.69961 943.80078 573.59961 C 952.90078 606.59961 955.59961 640.70039 941.59961 683.90039 C 923.79961 739.00039 893.09961 793.80039 847.09961 823.90039 C 833.49961 832.60039 820.89922 839.4 806.19922 847.5 C 804.09922 848.6 804.20078 850.99922 805.30078 851.69922 C 878.70078 851.09922 956.39961 743.59922 975.59961 649.69922 C 963.79961 717.49922 928.2 783.50078 873.5 831.80078 C 842.5 858.60078 811.90078 871.59961 780.80078 875.09961 C 726.10078 879.29961 693.59922 830.9 696.69922 760.5 C 696.59922 758.1 695.50039 757.50039 694.40039 756.90039 C 688.70039 772.30039 685.09961 786.49922 684.59961 800.19922 C 683.15311 870.80636 723.40104 911.63389 777.53906 908.77344 C 757.57984 910.46578 738.70856 907.29881 721.59961 897.69922 C 703.79961 885.39922 691.10039 869.00039 681.40039 844.90039 C 674.90039 822.70039 672.79922 800.6 675.69922 772 C 682.39922 710.7 714.9 647.60078 762.5 606.80078 C 782.1 589.90078 801.00039 579.60078 819.90039 569.30078 L 819.80078 566.90039 C 804.70078 565.40039 789.89961 570.99922 773.09961 580.19922 C 712.39961 615.89922 665.50078 694.2 649.80078 769 C 656.70078 733.4 669.00078 698.39961 688.80078 663.09961 C 706.80078 633.69961 725.00078 609.00078 750.80078 586.30078 C 791.20078 553.20078 832.40039 536.80039 869.40039 545.90039 C 909.80039 556.90039 930.2 600.9 927.5 657.5 C 927.6 659.9 927.70078 662.29961 929.80078 661.09961 C 930.80078 659.29961 932.80078 655.8 933.80078 654 C 944.00078 620.2 939.3 589.70078 930.5 563.80078 C 914.4 519.90078 873.80039 504.1 828.90039 511.5 C 838.87539 509.25 848.60996 508.16641 858.04883 508.3457 z " />
|
||||
<linearGradient
|
||||
id="XMLID_16_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="505.4734"
|
||||
y1="-52.674"
|
||||
x2="505.4734"
|
||||
y2="155.1105">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF;stop-opacity:0.4"
|
||||
id="stop18" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#FFFFFF;stop-opacity:0"
|
||||
id="stop20" />
|
||||
</linearGradient>
|
||||
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_17_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="503.3253"
|
||||
y1="-583.7885"
|
||||
x2="503.3253"
|
||||
y2="-376.4571"
|
||||
gradientTransform="matrix(-1 0 0 -1 1017 456.5313)">
|
||||
<stop
|
||||
offset="5.263158e-03"
|
||||
style="stop-color:#9E3A1D;stop-opacity:0.4"
|
||||
id="stop24" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#9E3A1D;stop-opacity:0"
|
||||
id="stop26" />
|
||||
</linearGradient>
|
||||
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_18_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="506.1886"
|
||||
y1="-38.7551"
|
||||
x2="506.1886"
|
||||
y2="169.0294"
|
||||
gradientTransform="matrix(4.489700e-11 1 -1 4.489700e-11 1026.6101 -2.3899)">
|
||||
<stop
|
||||
offset="5.263158e-03"
|
||||
style="stop-color:#9E3A1D;stop-opacity:0.4"
|
||||
id="stop30" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#9E3A1D;stop-opacity:0"
|
||||
id="stop32" />
|
||||
</linearGradient>
|
||||
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_19_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="502.6101"
|
||||
y1="-660.7308"
|
||||
x2="502.6101"
|
||||
y2="-450.373"
|
||||
gradientTransform="matrix(-4.489700e-11 -1 1 -4.489700e-11 570.0789 1014.6101)">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF;stop-opacity:0.4"
|
||||
id="stop36" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#FFFFFF;stop-opacity:0"
|
||||
id="stop38" />
|
||||
</linearGradient>
|
||||
|
||||
<g
|
||||
id="XMLID_39_"
|
||||
class="st10">
|
||||
<defs
|
||||
id="defs43">
|
||||
|
||||
<ellipse
|
||||
id="XMLID_36_"
|
||||
transform="matrix(0.8019 -0.5974 0.5974 0.8019 -204.724 406.2339)"
|
||||
class="st10"
|
||||
cx="510.3"
|
||||
cy="511.9"
|
||||
ry="502.8"
|
||||
rx="502.8" />
|
||||
</defs>
|
||||
<clipPath
|
||||
id="XMLID_20_">
|
||||
<use
|
||||
xlink:href="#XMLID_36_"
|
||||
style="overflow:visible;"
|
||||
id="use45" />
|
||||
</clipPath>
|
||||
</g>
|
||||
<g
|
||||
id="XMLID_41_">
|
||||
<linearGradient
|
||||
id="XMLID_21_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="64.4989"
|
||||
y1="234.8705"
|
||||
x2="401.1502"
|
||||
y2="480.7042">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#F4592D"
|
||||
id="stop49" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#FFD900"
|
||||
id="stop51" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_22_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="438.1351"
|
||||
y1="490.0881"
|
||||
x2="196.6566"
|
||||
y2="356.1772">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#F64626"
|
||||
id="stop55" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#FFD900"
|
||||
id="stop57" />
|
||||
</linearGradient>
|
||||
|
||||
</g>
|
||||
<g
|
||||
id="XMLID_11_">
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_23_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-316.9261"
|
||||
y1="9.5862"
|
||||
x2="-92.0354"
|
||||
y2="173.8087"
|
||||
gradientTransform="matrix(-0.9998 -2.148304e-02 2.148304e-02 -0.9998 625.9278 811.8477)">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#F4592D"
|
||||
id="stop62" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#FFD900"
|
||||
id="stop64" />
|
||||
</linearGradient>
|
||||
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_24_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-52.9013"
|
||||
y1="188.0779"
|
||||
x2="-214.2144"
|
||||
y2="98.6225"
|
||||
gradientTransform="matrix(-0.9998 -2.148304e-02 2.148304e-02 -0.9998 625.9278 811.8477)">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#F42C2D"
|
||||
id="stop68" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#FFD900"
|
||||
id="stop70" />
|
||||
</linearGradient>
|
||||
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 10 KiB |
301
src/renderer/images/logo-light.svg
Normal file
301
src/renderer/images/logo-light.svg
Normal file
@@ -0,0 +1,301 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 1024 1024"
|
||||
style="enable-background:new 0 0 1024 1024;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="Antares-shape-1.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs80" /><sodipodi:namedview
|
||||
id="namedview78"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.66015625"
|
||||
inkscape:cx="512"
|
||||
inkscape:cy="511.2426"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1009"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g75" />
|
||||
<style
|
||||
type="text/css"
|
||||
id="style2">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
.st1{fill:url(#XMLID_15_);}
|
||||
.st2{opacity:0.5;fill:#FFBC00;}
|
||||
.st3{fill:#FFBC00;}
|
||||
.st4{fill:url(#XMLID_16_);}
|
||||
.st5{fill:url(#XMLID_17_);}
|
||||
.st6{fill:url(#XMLID_18_);}
|
||||
.st7{fill:url(#XMLID_19_);}
|
||||
.st8{fill:url(#XMLID_20_);}
|
||||
.st9{fill:url(#XMLID_21_);}
|
||||
.st10{opacity:0.46;}
|
||||
.st11{fill:url(#XMLID_23_);}
|
||||
.st12{fill:url(#XMLID_24_);}
|
||||
.st13{fill:url(#XMLID_25_);}
|
||||
.st14{fill:url(#XMLID_27_);}
|
||||
.st15{fill:url(#XMLID_28_);}
|
||||
.st16{fill:url(#XMLID_29_);}
|
||||
.st17{fill:url(#XMLID_30_);}
|
||||
.st18{opacity:0.75;}
|
||||
.st19{opacity:0.44;clip-path:url(#XMLID_31_);}
|
||||
.st20{fill:url(#XMLID_32_);}
|
||||
.st21{fill:url(#XMLID_33_);}
|
||||
.st22{fill:url(#XMLID_34_);}
|
||||
.st23{fill:url(#XMLID_35_);}
|
||||
.st24{fill:url(#XMLID_37_);}
|
||||
.st25{fill:url(#XMLID_38_);}
|
||||
.st26{opacity:0.43;fill:#FFBC00;}
|
||||
.st27{opacity:0.58;fill:#FFBC00;}
|
||||
.st28{fill:#FFBE06;}
|
||||
.st29{fill:none;}
|
||||
.st30{fill:url(#XMLID_42_);}
|
||||
.st31{fill:url(#XMLID_43_);}
|
||||
.st32{fill:url(#XMLID_44_);}
|
||||
.st33{fill:url(#XMLID_45_);}
|
||||
.st34{fill:url(#XMLID_46_);}
|
||||
.st35{fill:url(#SVGID_4_);}
|
||||
.st36{fill:url(#SVGID_5_);}
|
||||
.st37{fill:url(#SVGID_6_);}
|
||||
.st38{fill:url(#SVGID_7_);}
|
||||
.st39{fill:url(#SVGID_8_);}
|
||||
.st40{fill:url(#SVGID_11_);}
|
||||
.st41{fill:url(#SVGID_12_);}
|
||||
.st42{fill:url(#SVGID_13_);}
|
||||
.st43{fill:url(#SVGID_14_);}
|
||||
.st44{fill:#C68D00;}
|
||||
.st45{fill:#CE000F;}
|
||||
</style>
|
||||
<g
|
||||
id="g75">
|
||||
<radialGradient
|
||||
id="XMLID_15_"
|
||||
cx="358.2692"
|
||||
cy="227.2655"
|
||||
r="830.0055"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#F6971E"
|
||||
id="stop4" />
|
||||
<stop
|
||||
offset="0.6338"
|
||||
style="stop-color:#F4592D"
|
||||
id="stop6" />
|
||||
<stop
|
||||
offset="0.7025"
|
||||
style="stop-color:#EF4F29"
|
||||
id="stop8" />
|
||||
<stop
|
||||
offset="0.8178"
|
||||
style="stop-color:#E1351D"
|
||||
id="stop10" />
|
||||
<stop
|
||||
offset="0.9647"
|
||||
style="stop-color:#CA0B0B"
|
||||
id="stop12" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#C40006"
|
||||
id="stop14" />
|
||||
</radialGradient>
|
||||
<path
|
||||
id="XMLID_124_"
|
||||
style="fill:#000000;fill-opacity:0.5"
|
||||
class="st1"
|
||||
d="M 510.30078 9.0996094 A 502.79999 502.79999 0 0 0 7.5 511.90039 A 502.79999 502.79999 0 0 0 510.30078 1014.6992 A 502.79999 502.79999 0 0 0 1013.0996 511.90039 A 502.79999 502.79999 0 0 0 510.30078 9.0996094 z M 326.17578 78.685547 C 349.74023 78.648438 372.16211 83.875 393.09961 95 C 420.19961 112.9 439.6 136.99922 455 172.69922 C 465.4 205.69922 469.30078 238.79961 465.80078 281.59961 C 457.70078 373.59961 411.09922 469.09961 341.19922 531.59961 C 312.29922 557.49961 284.4 573.59961 256.5 589.59961 L 256.69922 593.19922 C 279.39922 594.99922 301.39922 586.10078 326.19922 571.80078 C 415.89922 516.50078 483.49922 397.69922 504.69922 285.19922 C 495.49922 338.79922 478.19922 391.4 449.69922 445 C 423.79922 489.6 397.30039 527.1 359.40039 562 C 300.00039 612.9 238.89961 638.80078 183.09961 626.30078 C 122.39961 611.00078 90.399609 545.8 92.599609 461 C 92.399609 457.4 92.1 453.89961 89 455.59961 C 87.6 458.29961 84.700781 463.60078 83.300781 466.30078 C 69.000781 517.30078 77.1 562.79922 91 601.19922 C 116.5 666.39922 177.79922 688.69922 244.69922 676.19922 C 204.99922 685.99922 167.69922 683.3 134.19922 665.5 C 107.09922 647.6 84.599609 625.30039 70.599609 586.90039 C 55.899609 537.80039 50.700391 486.89922 70.400391 421.69922 C 95.300391 338.69922 139.50078 255.59922 207.30078 209.19922 C 227.30078 195.79922 245.99922 185.09961 267.69922 172.59961 C 270.79922 170.79961 270.60039 167.20039 268.90039 166.40039 C 159.40039 170.00039 46.500391 333.30039 20.900391 474.40039 C 36.400391 372.60039 87.500391 272.6 167.90039 198.5 C 213.50039 157.4 258.79922 136.89922 305.19922 130.69922 C 386.89922 122.69922 437.10078 194.1 434.80078 299.5 C 435.00078 303.1 436.70039 304.00039 438.40039 304.90039 C 446.50039 281.70039 451.39961 260.29922 451.59961 239.69922 C 451.50293 126.5894 381.21362 66.112098 291.87891 82.363281 C 288.79216 82.977349 285.71662 83.531343 282.59961 84.300781 C 285.71508 83.559319 288.80642 82.922208 291.87891 82.363281 C 303.5351 80.044429 314.99734 78.703151 326.17578 78.685547 z M 858.04883 508.3457 C 873.78027 508.64453 888.6875 512.44922 902.5 520.19922 C 920.3 532.49922 935.10078 547.69961 943.80078 573.59961 C 952.90078 606.59961 955.59961 640.70039 941.59961 683.90039 C 923.79961 739.00039 893.09961 793.80039 847.09961 823.90039 C 833.49961 832.60039 820.89922 839.4 806.19922 847.5 C 804.09922 848.6 804.20078 850.99922 805.30078 851.69922 C 878.70078 851.09922 956.39961 743.59922 975.59961 649.69922 C 963.79961 717.49922 928.2 783.50078 873.5 831.80078 C 842.5 858.60078 811.90078 871.59961 780.80078 875.09961 C 726.10078 879.29961 693.59922 830.9 696.69922 760.5 C 696.59922 758.1 695.50039 757.50039 694.40039 756.90039 C 688.70039 772.30039 685.09961 786.49922 684.59961 800.19922 C 683.15311 870.80636 723.40104 911.63389 777.53906 908.77344 C 757.57984 910.46578 738.70856 907.29881 721.59961 897.69922 C 703.79961 885.39922 691.10039 869.00039 681.40039 844.90039 C 674.90039 822.70039 672.79922 800.6 675.69922 772 C 682.39922 710.7 714.9 647.60078 762.5 606.80078 C 782.1 589.90078 801.00039 579.60078 819.90039 569.30078 L 819.80078 566.90039 C 804.70078 565.40039 789.89961 570.99922 773.09961 580.19922 C 712.39961 615.89922 665.50078 694.2 649.80078 769 C 656.70078 733.4 669.00078 698.39961 688.80078 663.09961 C 706.80078 633.69961 725.00078 609.00078 750.80078 586.30078 C 791.20078 553.20078 832.40039 536.80039 869.40039 545.90039 C 909.80039 556.90039 930.2 600.9 927.5 657.5 C 927.6 659.9 927.70078 662.29961 929.80078 661.09961 C 930.80078 659.29961 932.80078 655.8 933.80078 654 C 944.00078 620.2 939.3 589.70078 930.5 563.80078 C 914.4 519.90078 873.80039 504.1 828.90039 511.5 C 838.87539 509.25 848.60996 508.16641 858.04883 508.3457 z " />
|
||||
<linearGradient
|
||||
id="XMLID_16_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="505.4734"
|
||||
y1="-52.674"
|
||||
x2="505.4734"
|
||||
y2="155.1105">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF;stop-opacity:0.4"
|
||||
id="stop18" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#FFFFFF;stop-opacity:0"
|
||||
id="stop20" />
|
||||
</linearGradient>
|
||||
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_17_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="503.3253"
|
||||
y1="-583.7885"
|
||||
x2="503.3253"
|
||||
y2="-376.4571"
|
||||
gradientTransform="matrix(-1 0 0 -1 1017 456.5313)">
|
||||
<stop
|
||||
offset="5.263158e-03"
|
||||
style="stop-color:#9E3A1D;stop-opacity:0.4"
|
||||
id="stop24" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#9E3A1D;stop-opacity:0"
|
||||
id="stop26" />
|
||||
</linearGradient>
|
||||
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_18_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="506.1886"
|
||||
y1="-38.7551"
|
||||
x2="506.1886"
|
||||
y2="169.0294"
|
||||
gradientTransform="matrix(4.489700e-11 1 -1 4.489700e-11 1026.6101 -2.3899)">
|
||||
<stop
|
||||
offset="5.263158e-03"
|
||||
style="stop-color:#9E3A1D;stop-opacity:0.4"
|
||||
id="stop30" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#9E3A1D;stop-opacity:0"
|
||||
id="stop32" />
|
||||
</linearGradient>
|
||||
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_19_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="502.6101"
|
||||
y1="-660.7308"
|
||||
x2="502.6101"
|
||||
y2="-450.373"
|
||||
gradientTransform="matrix(-4.489700e-11 -1 1 -4.489700e-11 570.0789 1014.6101)">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF;stop-opacity:0.4"
|
||||
id="stop36" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#FFFFFF;stop-opacity:0"
|
||||
id="stop38" />
|
||||
</linearGradient>
|
||||
|
||||
<g
|
||||
id="XMLID_39_"
|
||||
class="st10">
|
||||
<defs
|
||||
id="defs43">
|
||||
|
||||
<ellipse
|
||||
id="XMLID_36_"
|
||||
transform="matrix(0.8019 -0.5974 0.5974 0.8019 -204.724 406.2339)"
|
||||
class="st10"
|
||||
cx="510.3"
|
||||
cy="511.9"
|
||||
ry="502.8"
|
||||
rx="502.8" />
|
||||
</defs>
|
||||
<clipPath
|
||||
id="XMLID_20_">
|
||||
<use
|
||||
xlink:href="#XMLID_36_"
|
||||
style="overflow:visible;"
|
||||
id="use45" />
|
||||
</clipPath>
|
||||
</g>
|
||||
<g
|
||||
id="XMLID_41_">
|
||||
<linearGradient
|
||||
id="XMLID_21_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="64.4989"
|
||||
y1="234.8705"
|
||||
x2="401.1502"
|
||||
y2="480.7042">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#F4592D"
|
||||
id="stop49" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#FFD900"
|
||||
id="stop51" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_22_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="438.1351"
|
||||
y1="490.0881"
|
||||
x2="196.6566"
|
||||
y2="356.1772">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#F64626"
|
||||
id="stop55" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#FFD900"
|
||||
id="stop57" />
|
||||
</linearGradient>
|
||||
|
||||
</g>
|
||||
<g
|
||||
id="XMLID_11_">
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_23_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-316.9261"
|
||||
y1="9.5862"
|
||||
x2="-92.0354"
|
||||
y2="173.8087"
|
||||
gradientTransform="matrix(-0.9998 -2.148304e-02 2.148304e-02 -0.9998 625.9278 811.8477)">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#F4592D"
|
||||
id="stop62" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#FFD900"
|
||||
id="stop64" />
|
||||
</linearGradient>
|
||||
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_24_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-52.9013"
|
||||
y1="188.0779"
|
||||
x2="-214.2144"
|
||||
y2="98.6225"
|
||||
gradientTransform="matrix(-0.9998 -2.148304e-02 2.148304e-02 -0.9998 625.9278 811.8477)">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#F42C2D"
|
||||
id="stop68" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#FFD900"
|
||||
id="stop70" />
|
||||
</linearGradient>
|
||||
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 10 KiB |
@@ -1,11 +1,6 @@
|
||||
import Tables from '@/ipc-api/Tables';
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
schema () {
|
||||
return this.workspace.breadcrumbs.schema;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async updateField (payload) {
|
||||
this.isQuering = true;
|
||||
|
@@ -63,6 +63,12 @@
|
||||
background-color: $primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-clear {
|
||||
&:hover {
|
||||
background: rgba($light-color, 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal {
|
||||
@@ -191,19 +197,8 @@
|
||||
color: $body-font-color-dark;
|
||||
}
|
||||
|
||||
& &.tools-dropdown {
|
||||
.tab-link:focus {
|
||||
color: $primary-color;
|
||||
}
|
||||
|
||||
.menu {
|
||||
.menu-item a {
|
||||
&:hover {
|
||||
color: $primary-color;
|
||||
background: $bg-color-gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.tools-dropdown {
|
||||
background-color: $bg-color-light-dark;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,11 +387,6 @@
|
||||
background: rgba(48, 55, 66, 0.95);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&:hover .ex-tooltip-content {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
#footer {
|
||||
|
@@ -168,11 +168,6 @@
|
||||
background: rgba(48, 55, 66, 0.95);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&:hover .ex-tooltip-content {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.workspace {
|
||||
@@ -191,6 +186,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
.workspace-tabs {
|
||||
.tab-block {
|
||||
.tab-item {
|
||||
&.tools-dropdown {
|
||||
background-color: $body-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.workspace-query-results {
|
||||
.table {
|
||||
.th {
|
||||
|
@@ -16,7 +16,8 @@ export default {
|
||||
line_wrap: persistentStore.get('line_wrap', true),
|
||||
application_theme: persistentStore.get('application_theme', 'dark'),
|
||||
editor_theme: persistentStore.get('editor_theme', 'twilight'),
|
||||
editor_font_size: persistentStore.get('editor_font_size', 'medium')
|
||||
editor_font_size: persistentStore.get('editor_font_size', 'medium'),
|
||||
restore_tabs: persistentStore.get('restore_tabs', true)
|
||||
},
|
||||
getters: {
|
||||
getLocale: state => state.locale,
|
||||
@@ -28,7 +29,8 @@ export default {
|
||||
getLineWrap: state => state.line_wrap,
|
||||
getApplicationTheme: state => state.application_theme,
|
||||
getEditorTheme: state => state.editor_theme,
|
||||
getEditorFontSize: state => state.editor_font_size
|
||||
getEditorFontSize: state => state.editor_font_size,
|
||||
getRestoreTabs: state => state.restore_tabs
|
||||
},
|
||||
mutations: {
|
||||
SET_LOCALE (state, locale) {
|
||||
@@ -71,6 +73,10 @@ export default {
|
||||
SET_EDITOR_FONT_SIZE (state, size) {
|
||||
state.editor_font_size = size;
|
||||
persistentStore.set('editor_font_size', state.editor_font_size);
|
||||
},
|
||||
SET_RESTORE_TABS (state, val) {
|
||||
state.restore_tabs = val;
|
||||
persistentStore.set('restore_tabs', state.restore_tabs);
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
@@ -103,6 +109,9 @@ export default {
|
||||
},
|
||||
changeEditorFontSize ({ commit }, size) {
|
||||
commit('SET_EDITOR_FONT_SIZE', size);
|
||||
},
|
||||
changeRestoreTabs ({ commit }, size) {
|
||||
commit('SET_RESTORE_TABS', size);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -1,20 +1,18 @@
|
||||
'use strict';
|
||||
import Store from 'electron-store';
|
||||
import Connection from '@/ipc-api/Connection';
|
||||
import Schema from '@/ipc-api/Schema';
|
||||
import Users from '@/ipc-api/Users';
|
||||
import { uidGen } from 'common/libs/uidGen';
|
||||
const persistentStore = new Store({ name: 'tabs' });
|
||||
const tabIndex = [];
|
||||
let lastBreadcrumbs = {};
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
strict: true,
|
||||
state: {
|
||||
workspaces: [],
|
||||
selected_workspace: null,
|
||||
has_unsaved_changes: false,
|
||||
is_unsaved_discard_modal: false,
|
||||
pending_breadcrumbs: {}
|
||||
selected_workspace: null
|
||||
},
|
||||
getters: {
|
||||
getSelected: state => {
|
||||
@@ -45,9 +43,6 @@ export default {
|
||||
},
|
||||
getSearchTerm: state => uid => {
|
||||
return state.workspaces.find(workspace => workspace.uid === uid).search_term;
|
||||
},
|
||||
isUnsavedDiscardModal: state => {
|
||||
return state.is_unsaved_discard_modal;
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
@@ -60,6 +55,15 @@ export default {
|
||||
SET_CONNECTED (state, payload) {
|
||||
const { uid, client, dataTypes, indexTypes, customizations, structure, version } = payload;
|
||||
|
||||
const cachedTabs = payload.restoreTabs ? persistentStore.get(uid, []) : [];
|
||||
|
||||
if (cachedTabs.length) {
|
||||
tabIndex[uid] = cachedTabs.reduce((acc, curr) => {
|
||||
if (curr.index > acc) acc = curr.index;
|
||||
return acc;
|
||||
}, null);
|
||||
}
|
||||
|
||||
state.workspaces = state.workspaces.map(workspace => workspace.uid === uid
|
||||
? {
|
||||
...workspace,
|
||||
@@ -69,6 +73,8 @@ export default {
|
||||
customizations,
|
||||
structure,
|
||||
connection_status: 'connected',
|
||||
tabs: cachedTabs,
|
||||
selected_tab: cachedTabs.length ? cachedTabs[0].uid : null,
|
||||
version
|
||||
}
|
||||
: workspace);
|
||||
@@ -178,18 +184,24 @@ export default {
|
||||
}
|
||||
: workspace);
|
||||
},
|
||||
NEW_TAB (state, { uid, tab, content, autorun }) {
|
||||
tabIndex[uid] = tabIndex[uid] ? ++tabIndex[uid] : 1;
|
||||
NEW_TAB (state, { uid, tab, content, type, autorun, schema, elementName, elementType }) {
|
||||
if (type === 'query')
|
||||
tabIndex[uid] = tabIndex[uid] ? ++tabIndex[uid] : 1;
|
||||
|
||||
const newTab = {
|
||||
uid: tab,
|
||||
index: tabIndex[uid],
|
||||
index: type === 'query' ? tabIndex[uid] : null,
|
||||
selected: false,
|
||||
type: 'query',
|
||||
type,
|
||||
schema,
|
||||
elementName,
|
||||
elementType,
|
||||
fields: [],
|
||||
keyUsage: [],
|
||||
content: content || '',
|
||||
autorun: !!autorun
|
||||
};
|
||||
|
||||
state.workspaces = state.workspaces.map(workspace => {
|
||||
if (workspace.uid === uid) {
|
||||
return {
|
||||
@@ -200,6 +212,8 @@ export default {
|
||||
else
|
||||
return workspace;
|
||||
});
|
||||
|
||||
persistentStore.set(uid, state.workspaces.find(workspace => workspace.uid === uid).tabs);
|
||||
},
|
||||
REMOVE_TAB (state, { uid, tab: tUid }) {
|
||||
state.workspaces = state.workspaces.map(workspace => {
|
||||
@@ -212,10 +226,78 @@ export default {
|
||||
else
|
||||
return workspace;
|
||||
});
|
||||
|
||||
persistentStore.set(uid, state.workspaces.find(workspace => workspace.uid === uid).tabs);
|
||||
},
|
||||
REMOVE_TABS (state, { uid, schema, elementName, elementType }) { // Multiple tabs based on schema and element name
|
||||
if (elementType === 'procedure') elementType = 'routine'; // TODO: pass directly "routine"
|
||||
|
||||
state.workspaces = state.workspaces.map(workspace => {
|
||||
if (workspace.uid === uid) {
|
||||
return {
|
||||
...workspace,
|
||||
tabs: workspace.tabs.filter(tab =>
|
||||
tab.schema !== schema ||
|
||||
tab.elementName !== elementName ||
|
||||
tab.elementType !== elementType
|
||||
)
|
||||
};
|
||||
}
|
||||
else
|
||||
return workspace;
|
||||
});
|
||||
|
||||
persistentStore.set(uid, state.workspaces.find(workspace => workspace.uid === uid).tabs);
|
||||
},
|
||||
REPLACE_TAB (state, { uid, tab: tUid, type, schema, content, elementName, elementType }) {
|
||||
state.workspaces = state.workspaces.map(workspace => {
|
||||
if (workspace.uid === uid) {
|
||||
return {
|
||||
...workspace,
|
||||
tabs: workspace.tabs.map(tab => {
|
||||
if (tab.uid === tUid)
|
||||
return { ...tab, type, schema, content, elementName, elementType };
|
||||
|
||||
return tab;
|
||||
})
|
||||
};
|
||||
}
|
||||
else
|
||||
return workspace;
|
||||
});
|
||||
|
||||
persistentStore.set(uid, state.workspaces.find(workspace => workspace.uid === uid).tabs);
|
||||
},
|
||||
RENAME_TABS (state, { uid, schema, elementName, elementType, elementNewName }) {
|
||||
state.workspaces = state.workspaces.map(workspace => {
|
||||
if (workspace.uid === uid) {
|
||||
return {
|
||||
...workspace,
|
||||
tabs: workspace.tabs.map(tab => {
|
||||
if (tab.elementName === elementName && tab.schema === schema) {
|
||||
return {
|
||||
...tab,
|
||||
elementName: elementNewName
|
||||
};
|
||||
}
|
||||
|
||||
return tab;
|
||||
})
|
||||
};
|
||||
}
|
||||
else
|
||||
return workspace;
|
||||
});
|
||||
|
||||
persistentStore.set(uid, state.workspaces.find(workspace => workspace.uid === uid).tabs);
|
||||
},
|
||||
SELECT_TAB (state, { uid, tab }) {
|
||||
state.workspaces = state.workspaces.map(workspace => workspace.uid === uid ? { ...workspace, selected_tab: tab } : workspace);
|
||||
},
|
||||
UPDATE_TABS (state, { uid, tabs }) {
|
||||
state.workspaces = state.workspaces.map(workspace => workspace.uid === uid ? { ...workspace, tabs } : workspace);
|
||||
persistentStore.set(uid, state.workspaces.find(workspace => workspace.uid === uid).tabs);
|
||||
},
|
||||
SET_TAB_FIELDS (state, { cUid, tUid, fields }) {
|
||||
state.workspaces = state.workspaces.map(workspace => {
|
||||
if (workspace.uid === cUid) {
|
||||
@@ -232,6 +314,8 @@ export default {
|
||||
else
|
||||
return workspace;
|
||||
});
|
||||
|
||||
persistentStore.set(uid, state.workspaces.find(workspace => workspace.uid === uid).tabs);
|
||||
},
|
||||
SET_TAB_KEY_USAGE (state, { cUid, tUid, keyUsage }) {
|
||||
state.workspaces = state.workspaces.map(workspace => {
|
||||
@@ -249,15 +333,25 @@ export default {
|
||||
else
|
||||
return workspace;
|
||||
});
|
||||
|
||||
persistentStore.set(uid, state.workspaces.find(workspace => workspace.uid === uid).tabs);
|
||||
},
|
||||
SET_UNSAVED_CHANGES (state, val) {
|
||||
state.has_unsaved_changes = !!val;
|
||||
},
|
||||
SET_UNSAVED_DISCARD_MODAL (state, val) {
|
||||
state.is_unsaved_discard_modal = !!val;
|
||||
},
|
||||
SET_PENDING_BREADCRUMBS (state, payload) {
|
||||
state.pending_breadcrumbs = payload;
|
||||
SET_UNSAVED_CHANGES (state, { uid, tUid, isChanged }) {
|
||||
state.workspaces = state.workspaces.map(workspace => {
|
||||
if (workspace.uid === uid) {
|
||||
return {
|
||||
...workspace,
|
||||
tabs: workspace.tabs.map(tab => {
|
||||
if (tab.uid === tUid)
|
||||
return { ...tab, isChanged };
|
||||
|
||||
return tab;
|
||||
})
|
||||
};
|
||||
}
|
||||
else
|
||||
return workspace;
|
||||
});
|
||||
},
|
||||
ADD_LOADED_SCHEMA (state, payload) {
|
||||
state.workspaces = state.workspaces.map(workspace => {
|
||||
@@ -271,7 +365,7 @@ export default {
|
||||
selectWorkspace ({ commit }, uid) {
|
||||
commit('SELECT_WORKSPACE', uid);
|
||||
},
|
||||
async connectWorkspace ({ dispatch, commit }, connection) {
|
||||
async connectWorkspace ({ dispatch, commit, getters, rootGetters }, connection) {
|
||||
commit('SET_CONNECTING', connection.uid);
|
||||
|
||||
try {
|
||||
@@ -304,6 +398,7 @@ export default {
|
||||
if (status === 'error')
|
||||
dispatch('notifications/addNotification', { status, message: version }, { root: true });
|
||||
|
||||
// Check if Maria or MySQL
|
||||
const isMySQL = version.name.includes('MySQL');
|
||||
|
||||
if (isMySQL && connection.client !== 'mysql') {
|
||||
@@ -324,7 +419,8 @@ export default {
|
||||
indexTypes,
|
||||
customizations,
|
||||
structure: response,
|
||||
version
|
||||
version,
|
||||
restoreTabs: rootGetters['settings/getRestoreTabs']
|
||||
});
|
||||
dispatch('refreshCollations', connection.uid);
|
||||
dispatch('refreshVariables', connection.uid);
|
||||
@@ -414,7 +510,7 @@ export default {
|
||||
commit('SET_DISCONNECTED', uid);
|
||||
commit('SELECT_TAB', { uid, tab: 0 });
|
||||
},
|
||||
addWorkspace ({ commit, dispatch, getters }, uid) {
|
||||
addWorkspace ({ commit }, uid) {
|
||||
const workspace = {
|
||||
uid,
|
||||
connection_status: 'disconnected',
|
||||
@@ -430,75 +526,211 @@ export default {
|
||||
};
|
||||
|
||||
commit('ADD_WORKSPACE', workspace);
|
||||
|
||||
if (getters.getWorkspace(uid).tabs.length < 3)
|
||||
dispatch('newTab', { uid });
|
||||
|
||||
dispatch('setUnsavedChanges', false);
|
||||
},
|
||||
changeBreadcrumbs ({ state, commit, getters }, payload) {
|
||||
if (state.has_unsaved_changes) {
|
||||
commit('SET_UNSAVED_DISCARD_MODAL', true);
|
||||
commit('SET_PENDING_BREADCRUMBS', payload);
|
||||
return;
|
||||
}
|
||||
|
||||
changeBreadcrumbs ({ commit, getters }, payload) {
|
||||
const breadcrumbsObj = {
|
||||
schema: null,
|
||||
table: null,
|
||||
trigger: null,
|
||||
triggerFunction: null,
|
||||
procedure: null,
|
||||
function: null,
|
||||
scheduler: null,
|
||||
view: null
|
||||
view: null,
|
||||
query: null
|
||||
};
|
||||
|
||||
const hasLastChildren = Object.keys(lastBreadcrumbs).filter(b => b !== 'schema').some(b => lastBreadcrumbs[b]);
|
||||
const hasChildren = Object.keys(payload).filter(b => b !== 'schema').some(b => payload[b]);
|
||||
|
||||
if (lastBreadcrumbs.schema === payload.schema && hasLastChildren && !hasChildren) return;
|
||||
|
||||
if (lastBreadcrumbs.schema !== payload.schema)
|
||||
Schema.useSchema({ uid: getters.getSelected, schema: payload.schema });
|
||||
|
||||
commit('CHANGE_BREADCRUMBS', { uid: getters.getSelected, breadcrumbs: { ...breadcrumbsObj, ...payload } });
|
||||
lastBreadcrumbs = { ...breadcrumbsObj, ...payload };
|
||||
|
||||
if (payload.schema)
|
||||
commit('ADD_LOADED_SCHEMA', { uid: getters.getSelected, schema: payload.schema });
|
||||
},
|
||||
addLoadedSchema ({ commit, getters }, schema) {
|
||||
commit('ADD_LOADED_SCHEMA', { uid: getters.getSelected, schema });
|
||||
},
|
||||
setSearchTerm ({ commit, getters }, term) {
|
||||
commit('SET_SEARCH_TERM', { uid: getters.getSelected, term });
|
||||
},
|
||||
newTab ({ commit }, { uid, content, autorun }) {
|
||||
const tab = uidGen('T');
|
||||
newTab ({ state, commit }, { uid, content, type, autorun, schema, elementName, elementType }) {
|
||||
let tabUid;
|
||||
const workspaceTabs = state.workspaces.find(workspace => workspace.uid === uid);
|
||||
|
||||
commit('NEW_TAB', { uid, tab, content, autorun });
|
||||
commit('SELECT_TAB', { uid, tab });
|
||||
switch (type) {
|
||||
case 'temp-data': {
|
||||
const existentTab = workspaceTabs
|
||||
? workspaceTabs.tabs.find(tab =>
|
||||
tab.schema === schema &&
|
||||
tab.elementName === elementName &&
|
||||
tab.elementType === elementType &&
|
||||
['temp-data', 'data'].includes(tab.type))
|
||||
: false;
|
||||
|
||||
if (existentTab) { // if data tab exists
|
||||
tabUid = existentTab.uid;
|
||||
}
|
||||
else {
|
||||
const tempTabs = workspaceTabs ? workspaceTabs.tabs.filter(tab => tab.type === 'temp-data') : false;
|
||||
if (tempTabs && tempTabs.length) { // if temp table already opened
|
||||
for (const tab of tempTabs) {
|
||||
commit('REPLACE_TAB', { uid, tab: tab.uid, type, schema, elementName, elementType });
|
||||
tabUid = tab.uid;
|
||||
}
|
||||
}
|
||||
else {
|
||||
tabUid = uidGen('T');
|
||||
commit('NEW_TAB', { uid, tab: tabUid, content, type, autorun, schema, elementName, elementType });
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'data': {
|
||||
const existentTab = workspaceTabs
|
||||
? workspaceTabs.tabs.find(tab =>
|
||||
tab.schema === schema &&
|
||||
tab.elementName === elementName &&
|
||||
tab.elementType === elementType &&
|
||||
['temp-data', 'data'].includes(tab.type))
|
||||
: false;
|
||||
|
||||
if (existentTab) {
|
||||
commit('REPLACE_TAB', { uid, tab: existentTab.uid, type, schema, elementName, elementType });
|
||||
tabUid = existentTab.uid;
|
||||
}
|
||||
else {
|
||||
tabUid = uidGen('T');
|
||||
commit('NEW_TAB', { uid, tab: tabUid, content, type, autorun, schema, elementName, elementType });
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'table-props': {
|
||||
const existentTab = workspaceTabs
|
||||
? workspaceTabs.tabs.find(tab =>
|
||||
tab.elementName === elementName &&
|
||||
tab.elementType === elementType &&
|
||||
tab.type === type)
|
||||
: false;
|
||||
|
||||
if (existentTab) {
|
||||
commit('REPLACE_TAB', { uid, tab: existentTab.uid, type, schema, elementName, elementType });
|
||||
tabUid = existentTab.uid;
|
||||
}
|
||||
else {
|
||||
tabUid = uidGen('T');
|
||||
commit('NEW_TAB', { uid, tab: tabUid, content, type, autorun, schema, elementName, elementType });
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'temp-trigger-props':
|
||||
case 'temp-trigger-function-props':
|
||||
case 'temp-function-props':
|
||||
case 'temp-routine-props':
|
||||
case 'temp-scheduler-props': {
|
||||
const existentTab = workspaceTabs
|
||||
? workspaceTabs.tabs.find(tab =>
|
||||
tab.schema === schema &&
|
||||
tab.elementName === elementName &&
|
||||
tab.elementType === elementType &&
|
||||
[type, type.replace('temp-', '')].includes(tab.type))
|
||||
: false;
|
||||
|
||||
if (existentTab) { // if tab exists
|
||||
tabUid = existentTab.uid;
|
||||
}
|
||||
else {
|
||||
const tempTabs = workspaceTabs ? workspaceTabs.tabs.filter(tab => tab.type.includes('temp-')) : false;
|
||||
if (tempTabs && tempTabs.length) { // if temp tab already opened
|
||||
for (const tab of tempTabs) {
|
||||
if (tab.isChanged) {
|
||||
commit('REPLACE_TAB', { // make permanent a temp table with unsaved changes
|
||||
uid,
|
||||
tab: tab.uid,
|
||||
type: tab.type.replace('temp-', ''),
|
||||
schema: tab.schema,
|
||||
elementName: tab.elementName,
|
||||
elementType: tab.elementType
|
||||
});
|
||||
|
||||
tabUid = uidGen('T');
|
||||
commit('NEW_TAB', { uid, tab: tabUid, content, type, autorun, schema, elementName, elementType });
|
||||
}
|
||||
else {
|
||||
commit('REPLACE_TAB', { uid, tab: tab.uid, type, schema, elementName, elementType });
|
||||
tabUid = tab.uid;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
tabUid = uidGen('T');
|
||||
commit('NEW_TAB', { uid, tab: tabUid, content, type, autorun, schema, elementName, elementType });
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'trigger-props':
|
||||
case 'trigger-function-props':
|
||||
case 'function-props':
|
||||
case 'routine-props':
|
||||
case 'scheduler-props': {
|
||||
const existentTab = workspaceTabs
|
||||
? workspaceTabs.tabs.find(tab =>
|
||||
tab.schema === schema &&
|
||||
tab.elementName === elementName &&
|
||||
tab.elementType === elementType &&
|
||||
[`temp-${type}`, type].includes(tab.type))
|
||||
: false;
|
||||
|
||||
if (existentTab) {
|
||||
commit('REPLACE_TAB', { uid, tab: existentTab.uid, type, schema, elementName, elementType });
|
||||
tabUid = existentTab.uid;
|
||||
}
|
||||
else {
|
||||
tabUid = uidGen('T');
|
||||
commit('NEW_TAB', { uid, tab: tabUid, content, type, autorun, schema, elementName, elementType });
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
tabUid = uidGen('T');
|
||||
commit('NEW_TAB', { uid, tab: tabUid, content, type, autorun, schema, elementName, elementType });
|
||||
break;
|
||||
}
|
||||
|
||||
commit('SELECT_TAB', { uid, tab: tabUid });
|
||||
},
|
||||
removeTab ({ commit }, payload) {
|
||||
checkSelectedTabExists ({ state, commit }, uid) {
|
||||
const workspace = state.workspaces.find(workspace => workspace.uid === uid);
|
||||
const isSelectedExistent = workspace
|
||||
? workspace.tabs.some(tab => tab.uid === workspace.selected_tab)
|
||||
: false;
|
||||
|
||||
if (!isSelectedExistent && workspace.tabs.length)
|
||||
commit('SELECT_TAB', { uid, tab: workspace.tabs[workspace.tabs.length - 1].uid });
|
||||
},
|
||||
updateTabContent ({ commit }, { uid, tab, type, schema, content }) {
|
||||
commit('REPLACE_TAB', { uid, tab, type, schema, content });
|
||||
},
|
||||
renameTabs ({ commit }, payload) {
|
||||
commit('RENAME_TABS', payload);
|
||||
},
|
||||
removeTab ({ commit, dispatch }, payload) {
|
||||
commit('REMOVE_TAB', payload);
|
||||
dispatch('checkSelectedTabExists', payload.uid);
|
||||
},
|
||||
removeTabs ({ commit, dispatch }, payload) {
|
||||
commit('REMOVE_TABS', payload);
|
||||
dispatch('checkSelectedTabExists', payload.uid);
|
||||
},
|
||||
selectTab ({ commit }, payload) {
|
||||
commit('SELECT_TAB', payload);
|
||||
},
|
||||
updateTabs ({ commit }, payload) {
|
||||
commit('UPDATE_TABS', payload);
|
||||
},
|
||||
setTabFields ({ commit }, payload) {
|
||||
commit('SET_TAB_FIELDS', payload);
|
||||
},
|
||||
setTabKeyUsage ({ commit }, payload) {
|
||||
commit('SET_TAB_KEY_USAGE', payload);
|
||||
},
|
||||
setUnsavedChanges ({ commit }, val) {
|
||||
commit('SET_UNSAVED_CHANGES', val);
|
||||
},
|
||||
discardUnsavedChanges ({ state, commit, dispatch }) {
|
||||
dispatch('setUnsavedChanges', false);
|
||||
dispatch('changeBreadcrumbs', state.pending_breadcrumbs);
|
||||
commit('SET_UNSAVED_DISCARD_MODAL', false);
|
||||
commit('SET_PENDING_BREADCRUMBS', {});
|
||||
},
|
||||
closeUnsavedChangesModal ({ commit }) {
|
||||
commit('SET_UNSAVED_DISCARD_MODAL', false);
|
||||
setUnsavedChanges ({ commit }, payload) {
|
||||
commit('SET_UNSAVED_CHANGES', payload);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user