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

Compare commits

..

19 Commits

Author SHA1 Message Date
010147b553 chore(release): 0.7.29-beta.0 2024-09-23 09:12:15 +02:00
da8cc39157 fix: mismatch between table field columns and results with duplicate fields, fixes #848 2024-09-20 18:08:11 +02:00
37d44c95ee perf(UI): hide edit/delete functions in readonly mode 2024-09-18 16:42:21 +02:00
4df4c6197d Merge pull request #858 from Lawondyss/lawondyss
feat: update czech translation
2024-08-30 16:25:29 +02:00
Ladislav Vondráček
0506b653d7 feat: update czech translation 2024-08-30 15:22:19 +02:00
5fd9fe48a2 Merge pull request #853 from hatch01/master
build(deps): update various dependencies
2024-08-30 09:07:42 +02:00
b6a7124f33 feat: cancel button when waiting to connect database, closes #830 2024-08-28 18:05:04 +02:00
eymeric
5855ab0921 build(deps): update various dependencies 2024-08-26 22:15:47 +02:00
c2b602785a chore(release): 0.7.28 2024-08-20 17:48:59 +02:00
97279742e9 chore(release): 0.7.28-beta.0 2024-08-06 18:45:16 +02:00
6cb21ff792 fix: html tags searching in history or saved queries, fixes #847 2024-08-05 18:03:10 +02:00
72bacdeabf fix: disabled column sort during loadings 2024-08-05 18:02:24 +02:00
c434855879 fix(PostgreSQL): issue exporting tables with primary keys 2024-07-30 16:52:20 +02:00
ba0ffcc6f5 fix: wrong password message importing app data 2024-07-19 18:00:52 +02:00
8e7965a0f9 fix(PostgreSQL): wrong export formato of JSON fields 2024-07-19 18:00:13 +02:00
4aab84fbd5 Merge pull request #839 from 64knl/feat-update-dutch-string
feat: add missing Dutch strings
2024-07-18 09:15:00 +02:00
Rene
74e97e660d feat(translation): Add more faker translations 2024-07-16 14:56:15 +02:00
Rene
f5d236b521 fix(translation): Spelling error 2024-07-16 14:49:21 +02:00
Rene
e794d207ad feat: add missing Dutch strings 2024-07-16 14:36:35 +02:00
30 changed files with 11115 additions and 397 deletions

View File

@@ -2,6 +2,44 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.7.29-beta.0](https://github.com/antares-sql/antares/compare/v0.7.28...v0.7.29-beta.0) (2024-09-23)
### Features
* cancel button when waiting to connect database, closes [#830](https://github.com/antares-sql/antares/issues/830) ([b6a7124](https://github.com/antares-sql/antares/commit/b6a7124f33397a2ae7da654b5867f6982ac5810e))
* update czech translation ([0506b65](https://github.com/antares-sql/antares/commit/0506b653d74d8cd5e848bc2ec4d29d4b0247c880))
### Bug Fixes
* mismatch between table field columns and results with duplicate fields, fixes [#848](https://github.com/antares-sql/antares/issues/848) ([da8cc39](https://github.com/antares-sql/antares/commit/da8cc39157a4b507d3d377ee1e888b8f8a52b7c5))
### Improvements
* **UI:** hide edit/delete functions in readonly mode ([37d44c9](https://github.com/antares-sql/antares/commit/37d44c95ee559f3ee1345e91fca5e2c1e86c5fbf))
### [0.7.28](https://github.com/antares-sql/antares/compare/v0.7.28-beta.0...v0.7.28) (2024-08-20)
### [0.7.28-beta.0](https://github.com/antares-sql/antares/compare/v0.7.27...v0.7.28-beta.0) (2024-08-06)
### Features
* add missing Dutch strings ([e794d20](https://github.com/antares-sql/antares/commit/e794d207ad75e0f5380f57df579912893e5edb6a))
* **translation:** Add more faker translations ([74e97e6](https://github.com/antares-sql/antares/commit/74e97e660df089ed8273565942118e112f6b3220))
### Bug Fixes
* disabled column sort during loadings ([72bacde](https://github.com/antares-sql/antares/commit/72bacdeabf833880482a839c4735505573d33bdc))
* html tags searching in history or saved queries, fixes [#847](https://github.com/antares-sql/antares/issues/847) ([6cb21ff](https://github.com/antares-sql/antares/commit/6cb21ff7926c74469b421c47b434612b3894b4c2))
* **PostgreSQL:** issue exporting tables with primary keys ([c434855](https://github.com/antares-sql/antares/commit/c434855879de16f83e17784e38e931decdd94873))
* **PostgreSQL:** wrong export formato of JSON fields ([8e7965a](https://github.com/antares-sql/antares/commit/8e7965a0f94a17ed73d5c8913f66e4e9cf0b11c7))
* **translation:** Spelling error ([f5d236b](https://github.com/antares-sql/antares/commit/f5d236b521a3534754de0b1031513f8eb83b3cc0))
* wrong password message importing app data ([ba0ffcc](https://github.com/antares-sql/antares/commit/ba0ffcc6f56c5506c1768c05d43bb07f7b090a68))
### [0.7.27](https://github.com/antares-sql/antares/compare/v0.7.26...v0.7.27) (2024-07-16) ### [0.7.27](https://github.com/antares-sql/antares/compare/v0.7.26...v0.7.27) (2024-07-16)

10499
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{ {
"name": "antares", "name": "antares",
"productName": "Antares", "productName": "Antares",
"version": "0.7.27", "version": "0.7.29-beta.0",
"description": "A modern, fast and productivity driven SQL client with a focus in UX.", "description": "A modern, fast and productivity driven SQL client with a focus in UX.",
"license": "MIT", "license": "MIT",
"repository": "https://github.com/antares-sql/antares.git", "repository": "https://github.com/antares-sql/antares.git",

View File

@@ -18,7 +18,7 @@ export type Importer = MySQLImporter | PostgreSQLImporter
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
export interface IpcResponse<T = any> { export interface IpcResponse<T = any> {
status: 'success' | 'error'; status: 'success' | 'error' | 'abort';
response?: T; response?: T;
} }

View File

@@ -40,7 +40,7 @@ export const objectToGeoJSON = (val: any) => {
export const escapeAndQuote = (val: string, client: ClientCode) => { export const escapeAndQuote = (val: string, client: ClientCode) => {
const { stringsWrapper: sw } = customizations[client]; const { stringsWrapper: sw } = customizations[client];
// eslint-disable-next-line no-control-regex // eslint-disable-next-line no-control-regex
const CHARS_TO_ESCAPE = /[\0\b\t\n\r\x1a"'\\]/g; const CHARS_TO_ESCAPE = sw === '"' ? /[\0\b\t\n\r\x1a"'\\]/g : /[\0\b\t\n\r\x1a'\\]/g;
const CHARS_ESCAPE_MAP: Record<string, string> = { const CHARS_ESCAPE_MAP: Record<string, string> = {
'\0': '\\0', '\0': '\\0',
'\b': '\\b', '\b': '\\b',
@@ -48,10 +48,13 @@ export const escapeAndQuote = (val: string, client: ClientCode) => {
'\n': '\\n', '\n': '\\n',
'\r': '\\r', '\r': '\\r',
'\x1a': '\\Z', '\x1a': '\\Z',
'"': '\\"',
'\'': '\\\'', '\'': '\\\'',
'\\': '\\\\' '\\': '\\\\'
}; };
if (sw === '"')
CHARS_ESCAPE_MAP['"'] = '\\"';
let chunkIndex = CHARS_TO_ESCAPE.lastIndex = 0; let chunkIndex = CHARS_TO_ESCAPE.lastIndex = 0;
let escapedVal = ''; let escapedVal = '';
let match; let match;
@@ -97,10 +100,19 @@ export const valueToSqlString = (args: {
} }
else if ('isArray' in field && field.isArray) { else if ('isArray' in field && field.isArray) {
let localVal; let localVal;
if (Array.isArray(val)) if (Array.isArray(val)) {
localVal = JSON.stringify(val).replaceAll('[', '{').replaceAll(']', '}'); localVal = JSON
else .stringify(val)
localVal = typeof val === 'string' ? val.replaceAll('[', '{').replaceAll(']', '}') : ''; .replaceAll('[', '{')
.replaceAll(']', '}');
}
else {
localVal = typeof val === 'string'
? val
.replaceAll('[', '{')
.replaceAll(']', '}')
: '';
}
parsedValue = `'${localVal}'`; parsedValue = `'${localVal}'`;
} }
else if (TEXT_SEARCH.includes(field.type)) else if (TEXT_SEARCH.includes(field.type))

View File

@@ -5,11 +5,21 @@ import { SslOptions } from 'mysql2';
import { ClientsFactory } from '../libs/ClientsFactory'; import { ClientsFactory } from '../libs/ClientsFactory';
import { validateSender } from '../libs/misc/validateSender'; import { validateSender } from '../libs/misc/validateSender';
const isAborting: Record<string, boolean> = {};
export default (connections: Record<string, antares.Client>) => { export default (connections: Record<string, antares.Client>) => {
ipcMain.handle('test-connection', async (event, conn: antares.ConnectionParams) => { ipcMain.handle('test-connection', async (event, conn: antares.ConnectionParams) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' }; if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
let isLocalAborted = false;
const abortChecker = setInterval(() => { // Intercepts abort request
if (isAborting[conn.uid]) {
isAborting[conn.uid] = false;
isLocalAborted = true;
clearInterval(abortChecker);
}
}, 50);
const params = { const params = {
host: conn.host, host: conn.host,
port: +conn.port, port: +conn.port,
@@ -65,19 +75,27 @@ export default (connections: Record<string, antares.Client>) => {
client: conn.client, client: conn.client,
params params
}); });
await connection.connect();
if (conn.client === 'firebird') await connection.connect();
connection.raw('SELECT rdb$get_context(\'SYSTEM\', \'DB_NAME\') FROM rdb$database'); if (isLocalAborted) {
else connection.destroy();
await connection.select('1+1').run(); return;
}
await connection.ping();
connection.destroy(); connection.destroy();
clearInterval(abortChecker);
return { status: 'success' }; return { status: 'success' };
} }
catch (err) { catch (err) {
clearInterval(abortChecker);
if (!isLocalAborted)
return { status: 'error', response: err.toString() }; return { status: 'error', response: err.toString() };
else
return { status: 'abort', response: 'Connection aborted' };
} }
}); });
@@ -88,6 +106,15 @@ export default (connections: Record<string, antares.Client>) => {
ipcMain.handle('connect', async (event, conn: antares.ConnectionParams) => { ipcMain.handle('connect', async (event, conn: antares.ConnectionParams) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' }; if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };
let isLocalAborted = false;
const abortChecker = setInterval(() => { // Intercepts abort request
if (isAborting[conn.uid]) {
isAborting[conn.uid] = false;
isLocalAborted = true;
clearInterval(abortChecker);
}
}, 50);
const params = { const params = {
host: conn.host, host: conn.host,
port: +conn.port, port: +conn.port,
@@ -150,18 +177,36 @@ export default (connections: Record<string, antares.Client>) => {
}); });
await connection.connect(); await connection.connect();
if (isLocalAborted) {
connection.destroy();
return { status: 'abort', response: 'Connection aborted' };
}
const structure = await connection.getStructure(new Set()); const structure = await connection.getStructure(new Set());
if (isLocalAborted) {
connection.destroy();
return { status: 'abort', response: 'Connection aborted' };
}
connections[conn.uid] = connection; connections[conn.uid] = connection;
clearInterval(abortChecker);
return { status: 'success', response: structure }; return { status: 'success', response: structure };
} }
catch (err) { catch (err) {
clearInterval(abortChecker);
if (!isLocalAborted)
return { status: 'error', response: err.toString() }; return { status: 'error', response: err.toString() };
else
return { status: 'abort', response: 'Connection aborted' };
} }
}); });
ipcMain.on('abort-connection', (event, uid) => {
isAborting[uid] = true;
});
ipcMain.handle('disconnect', (event, uid) => { ipcMain.handle('disconnect', (event, uid) => {
if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' }; if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' };

View File

@@ -251,7 +251,7 @@ export default (connections: Record<string, antares.Client>) => {
setTimeout(() => { // Ensures that writing thread has finished setTimeout(() => { // Ensures that writing thread has finished
exporter?.terminate(); exporter?.terminate();
exporter = null; exporter = null;
}, 2000); }, 500);
resolve({ status: 'success', response: payload }); resolve({ status: 'success', response: payload });
break; break;
case 'cancel': case 'cancel':

View File

@@ -109,6 +109,10 @@ export class FirebirdSQLClient extends BaseClient {
return firebird.pool(this._poolSize, { ...this._params, blobAsText: true }); return firebird.pool(this._poolSize, { ...this._params, blobAsText: true });
} }
ping () {
return this.raw('SELECT rdb$get_context(\'SYSTEM\', \'DB_NAME\') FROM rdb$database');
}
destroy () { destroy () {
if (this._poolSize) if (this._poolSize)
return (this._connection as firebird.ConnectionPool).destroy(); return (this._connection as firebird.ConnectionPool).destroy();

View File

@@ -214,6 +214,10 @@ export class MySQLClient extends BaseClient {
} }
} }
ping () {
return this.select('1+1').run();
}
destroy () { destroy () {
this._connection.end(); this._connection.end();
clearInterval(this._keepaliveTimer); clearInterval(this._keepaliveTimer);

View File

@@ -243,6 +243,10 @@ export class PostgreSQLClient extends BaseClient {
return connection; return connection;
} }
ping () {
return this.select('1+1').run();
}
destroy () { destroy () {
this._connection.end(); this._connection.end();
clearInterval(this._keepaliveTimer); clearInterval(this._keepaliveTimer);
@@ -591,7 +595,7 @@ export class PostgreSQLClient extends BaseClient {
} }
/* eslint-enable camelcase */ /* eslint-enable camelcase */
if (schema !== 'public') // if (schema !== 'public')
await this.use(schema); await this.use(schema);
const { rows } = await this.raw<antares.QueryResult<ShowIntexesResult>>(`WITH ndx_list AS ( const { rows } = await this.raw<antares.QueryResult<ShowIntexesResult>>(`WITH ndx_list AS (
@@ -636,35 +640,7 @@ export class PostgreSQLClient extends BaseClient {
}, {} as {table: string; schema: string}[]); }, {} as {table: string; schema: string}[]);
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async getTableDll ({ schema, table }: { schema: string; table: string }) { async getTableDll ({ schema, table }: { schema: string; table: string }) {
// const { rows } = await this.raw<antares.QueryResult<{'ddl'?: string}>>(`
// SELECT
// 'CREATE TABLE ' || relname || E'\n(\n' ||
// array_to_string(
// array_agg(' ' || column_name || ' ' || type || ' '|| not_null)
// , E',\n'
// ) || E'\n);\n' AS ddl
// FROM (
// SELECT
// a.attname AS column_name
// , pg_catalog.format_type(a.atttypid, a.atttypmod) AS type
// , CASE WHEN a.attnotnull THEN 'NOT NULL' ELSE 'NULL' END AS not_null
// , c.relname
// FROM pg_attribute a, pg_class c, pg_type t
// WHERE a.attnum > 0
// AND a.attrelid = c.oid
// AND a.atttypid = t.oid
// AND c.relname = '${table}'
// ORDER BY a.attnum
// ) AS tabledefinition
// GROUP BY relname
// `);
// if (rows.length)
// return rows[0].ddl;
// else return '';
/* eslint-disable camelcase */ /* eslint-disable camelcase */
interface SequenceRecord { interface SequenceRecord {
sequence_catalog: string; sequence_catalog: string;
@@ -706,6 +682,34 @@ export class PostgreSQLClient extends BaseClient {
if (!rows.length) return ''; if (!rows.length) return '';
const indexes = await this.getTableIndexes({ schema, table });
const primaryKey = indexes
.filter(i => i.type === 'PRIMARY')
.reduce((acc, cur) => {
if (!Object.keys(acc).length) {
cur.column = `"${cur.column}"`;
acc = cur;
}
else
acc.column += `, "${cur.column}"`;
return acc;
}, {} as { name: string; column: string; type: string});
const remappedIndexes = indexes
.filter(i => i.type !== 'PRIMARY')
.reduce((acc, cur) => {
const existingIndex = acc.findIndex(i => i.name === cur.name);
if (existingIndex >= 0)
acc[existingIndex].column += `, "${cur.column}"`;
else {
cur.column = `"${cur.column}"`;
acc.push(cur);
}
return acc;
}, [] as { name: string; column: string; type: string}[]);
for (const column of rows) { for (const column of rows) {
let fieldType = column.data_type; let fieldType = column.data_type;
if (fieldType === 'USER-DEFINED') fieldType = `"${schema}".${column.udt_name}`; if (fieldType === 'USER-DEFINED') fieldType = `"${schema}".${column.udt_name}`;
@@ -733,6 +737,9 @@ export class PostgreSQLClient extends BaseClient {
columnsSql.push(columnArr.join(' ')); columnsSql.push(columnArr.join(' '));
} }
if (primaryKey)
columnsSql.push(`CONSTRAINT "${primaryKey.name}" PRIMARY KEY (${primaryKey.column})`);
// Table sequences // Table sequences
for (let sequence of sequences) { for (let sequence of sequences) {
if (sequence.includes('.')) sequence = sequence.split('.')[1]; if (sequence.includes('.')) sequence = sequence.split('.')[1];
@@ -749,25 +756,22 @@ export class PostgreSQLClient extends BaseClient {
INCREMENT BY ${rows[0].increment} INCREMENT BY ${rows[0].increment}
MINVALUE ${rows[0].minimum_value} MINVALUE ${rows[0].minimum_value}
MAXVALUE ${rows[0].maximum_value} MAXVALUE ${rows[0].maximum_value}
CACHE 1;\n`; CACHE 1;\n\n`;
} }
} }
// Table create // Table create
createSql += `\nCREATE TABLE "${schema}"."${table}"( createSql += `CREATE TABLE "${schema}"."${table}"(
${columnsSql.join(',\n ')} ${columnsSql.join(',\n ')}
);\n`; );\n`;
// Table indexes // Table indexes
createSql += '\n'; createSql += '\n';
const { rows: indexes } = await this.select('*')
.schema('pg_catalog')
.from('pg_indexes')
.where({ schemaname: `= '${schema}'`, tablename: `= '${table}'` })
.run<{indexdef: string}>();
for (const index of indexes) for (const index of remappedIndexes) {
createSql += `${index.indexdef};\n`; if (index.type !== 'PRIMARY')
createSql += `CREATE ${index.type}${index.type === 'UNIQUE' ? ' INDEX' : ''} "${index.name}" ON "${schema}"."${table}" (${index.column});\n`;
}
return createSql; return createSql;
} }

View File

@@ -35,6 +35,10 @@ export class SQLiteClient extends BaseClient {
}); });
} }
ping () {
return this.select('1+1').run();
}
destroy () { destroy () {
this._connection.close(); this._connection.close();
} }

View File

@@ -336,7 +336,8 @@ CREATE TABLE \`${view.Name}\`(
const connection = await this._client.getConnection(); const connection = await this._client.getConnection();
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const stream = (connection as any).connection.query(sql).stream(); const stream = (connection as any).connection.query(sql).stream();
const dispose = () => connection.end(); // eslint-disable-next-line @typescript-eslint/no-explicit-any
const dispose = () => (connection as any).release();
stream.on('end', dispose); stream.on('end', dispose);
stream.on('error', dispose); stream.on('error', dispose);

View File

@@ -39,115 +39,7 @@ SET row_security = off;\n\n\n`;
} }
async getCreateTable (tableName: string) { async getCreateTable (tableName: string) {
/* eslint-disable camelcase */ const createSql = await this._client.getTableDll({ schema: this.schemaName, table: tableName });
interface SequenceRecord {
sequence_catalog: string;
sequence_schema: string;
sequence_name: string;
data_type: string;
numeric_precision: number;
numeric_precision_radix: number;
numeric_scale: number;
start_value: string;
minimum_value: string;
maximum_value: string;
increment: string;
cycle_option: string;
}
/* eslint-enable camelcase */
let createSql = '';
const sequences = [];
const columnsSql = [];
const arrayTypes: Record<string, string> = {
_int2: 'smallint',
_int4: 'integer',
_int8: 'bigint',
_float4: 'real',
_float8: 'double precision',
_char: '"char"',
_varchar: 'character varying'
};
// Table columns
const { rows } = await this._client.raw(`
SELECT *
FROM "information_schema"."columns"
WHERE "table_schema" = '${this.schemaName}'
AND "table_name" = '${tableName}'
ORDER BY "ordinal_position" ASC
`, { schema: 'information_schema' });
if (!rows.length) return '';
for (const column of rows) {
let fieldType = column.data_type;
if (fieldType === 'USER-DEFINED') fieldType = `"${this.schemaName}".${column.udt_name}`;
else if (fieldType === 'ARRAY') {
if (Object.keys(arrayTypes).includes(fieldType))
fieldType = arrayTypes[column.udt_name] + '[]';
else
fieldType = column.udt_name.replaceAll('_', '') + '[]';
}
const columnArr = [
`"${column.column_name}"`,
`${fieldType}${column.character_maximum_length ? `(${column.character_maximum_length})` : ''}`
];
if (column.column_default) {
columnArr.push(`DEFAULT ${column.column_default}`);
if (column.column_default.includes('nextval')) {
const sequenceName = column.column_default.split('\'')[1];
sequences.push(sequenceName);
}
}
if (column.is_nullable === 'NO') columnArr.push('NOT NULL');
columnsSql.push(columnArr.join(' '));
}
// Table sequences
for (let sequence of sequences) {
if (sequence.includes('.')) sequence = sequence.split('.')[1];
const { rows } = await this._client
.select('*')
.schema('information_schema')
.from('sequences')
.where({ sequence_schema: `= '${this.schemaName}'`, sequence_name: `= '${sequence}'` })
.run<SequenceRecord>();
if (rows.length) {
createSql += `CREATE SEQUENCE "${this.schemaName}"."${sequence}"
START WITH ${rows[0].start_value}
INCREMENT BY ${rows[0].increment}
MINVALUE ${rows[0].minimum_value}
MAXVALUE ${rows[0].maximum_value}
CACHE 1;\n`;
// createSql += `\nALTER TABLE "${sequence}" OWNER TO ${this._client._params.user};\n\n`;
}
}
// Table create
createSql += `\nCREATE TABLE "${this.schemaName}"."${tableName}"(
${columnsSql.join(',\n ')}
);\n`;
// createSql += `\nALTER TABLE "${tableName}" OWNER TO ${this._client._params.user};\n\n`;
// Table indexes
createSql += '\n';
const { rows: indexes } = await this._client
.select('*')
.schema('pg_catalog')
.from('pg_indexes')
.where({ schemaname: `= '${this.schemaName}'`, tablename: `= '${tableName}'` })
.run<{indexdef: string}>();
for (const index of indexes)
createSql += `${index.indexdef};\n`;
// Table foreigns // Table foreigns
const { rows: foreigns } = await this._client.raw(` const { rows: foreigns } = await this._client.raw(`

View File

@@ -380,6 +380,7 @@ const startExport = async () => {
try { try {
const { status, response } = await Schema.export(params); const { status, response } = await Schema.export(params);
if (status === 'success') if (status === 'success')
progressStatus.value = response.cancelled ? t('general.aborted') : t('general.completed'); progressStatus.value = response.cancelled ? t('general.aborted') : t('general.completed');
else { else {

View File

@@ -75,7 +75,7 @@
<code <code
class="cut-text" class="cut-text"
:title="query.sql" :title="query.sql"
v-html="highlight(highlightWord(query.sql), {html: true})" v-html="highlight(query.sql, {html: true})"
/> />
</div> </div>
<div class="tile-bottom-content"> <div class="tile-bottom-content">
@@ -210,17 +210,6 @@ const resizeResults = () => {
const refreshScroller = () => resizeResults(); const refreshScroller = () => resizeResults();
const closeModal = () => emit('close'); const closeModal = () => emit('close');
const highlightWord = (string: string) => {
string = string.replaceAll('<', '&lt;').replaceAll('>', '&gt;');
if (searchTerm.value) {
const regexp = new RegExp(`(${searchTerm.value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
return string.replace(regexp, '<span class="text-primary text-bold">$1</span>');
}
else
return string;
};
const onKey = (e: KeyboardEvent) => { const onKey = (e: KeyboardEvent) => {
e.stopPropagation(); e.stopPropagation();
if (e.key === 'Escape') if (e.key === 'Escape')

View File

@@ -247,7 +247,7 @@ const exportData = () => {
const exportObj = encrypt(JSON.stringify({ const exportObj = encrypt(JSON.stringify({
connections: filteredConnections, connections: filteredConnections,
connectionsOrder: filteredOrders, connectionsOrder: filteredOrders,
customIcons customIcons: customIcons.value
}), options.value.passkey); }), options.value.passkey);
// console.log(exportObj, JSON.parse(decrypt(exportObj, options.value.passkey))); // console.log(exportObj, JSON.parse(decrypt(exportObj, options.value.passkey)));

View File

@@ -206,7 +206,6 @@ const importData = () => {
.includes(c.uid) || .includes(c.uid) ||
(c.isFolder && c.connections.every(c => newConnectionsUid.includes(c)))); (c.isFolder && c.connections.every(c => newConnectionsUid.includes(c))));
} }
importConnections(importObj); importConnections(importObj);
addNotification({ addNotification({
@@ -216,6 +215,7 @@ const importData = () => {
closeModal(); closeModal();
} }
catch (error) { catch (error) {
console.error(error);
addNotification({ addNotification({
status: 'error', status: 'error',
message: t('application.wrongImportPassword') message: t('application.wrongImportPassword')
@@ -223,6 +223,7 @@ const importData = () => {
} }
} }
catch (error) { catch (error) {
console.error(error);
addNotification({ addNotification({
status: 'error', status: 'error',
message: t('application.wrongFileFormat') message: t('application.wrongFileFormat')

View File

@@ -32,7 +32,7 @@
v-if="note.type === 'query'" v-if="note.type === 'query'"
ref="noteParagraph" ref="noteParagraph"
class="tile-paragraph sql" class="tile-paragraph sql"
v-html="highlight(highlightWord(note.note), {html: true})" v-html="highlight(note.note, {html: true})"
/> />
<div <div
v-else v-else

View File

@@ -386,7 +386,21 @@
</div> </div>
</div> </div>
<div class="panel-footer"> <div class="panel-footer">
<div
@mouseenter="setCancelTestButtonVisibility(true)"
@mouseleave="setCancelTestButtonVisibility(false)"
>
<button <button
v-if="showTestCancel && isTesting"
class="btn btn-gray mr-2 cancellable"
:title="t('general.cancel')"
@click="abortConnection()"
>
<BaseIcon icon-name="mdiWindowClose" :size="24" />
<span class="d-invisible pr-1">{{ t('connection.testConnection') }}</span>
</button>
<button
v-else
id="connection-test" id="connection-test"
class="btn btn-gray mr-2 d-flex" class="btn btn-gray mr-2 d-flex"
:class="{'loading': isTesting}" :class="{'loading': isTesting}"
@@ -400,6 +414,7 @@
/> />
{{ t('connection.testConnection') }} {{ t('connection.testConnection') }}
</button> </button>
</div>
<button <button
id="connection-save" id="connection-save"
class="btn btn-primary mr-2 d-flex" class="btn btn-primary mr-2 d-flex"
@@ -494,6 +509,8 @@ const firstInput: Ref<HTMLInputElement> = ref(null);
const isConnecting = ref(false); const isConnecting = ref(false);
const isTesting = ref(false); const isTesting = ref(false);
const isAsking = ref(false); const isAsking = ref(false);
const showTestCancel = ref(false);
const abortController: Ref<AbortController> = ref(new AbortController());
const selectedTab = ref('general'); const selectedTab = ref('general');
const clientCustomizations = computed(() => { const clientCustomizations = computed(() => {
@@ -516,6 +533,10 @@ const setDefaults = () => {
connection.value.database = clientCustomizations.value.defaultDatabase; connection.value.database = clientCustomizations.value.defaultDatabase;
}; };
const setCancelTestButtonVisibility = (val: boolean) => {
showTestCancel.value = val;
};
const startTest = async () => { const startTest = async () => {
isTesting.value = true; isTesting.value = true;
@@ -526,7 +547,7 @@ const startTest = async () => {
const res = await Connection.makeTest(connection.value); const res = await Connection.makeTest(connection.value);
if (res.status === 'error') if (res.status === 'error')
addNotification({ status: 'error', message: res.response.message || res.response.toString() }); addNotification({ status: 'error', message: res.response.message || res.response.toString() });
else else if (res.status === 'success')
addNotification({ status: 'success', message: t('connection.connectionSuccessfullyMade') }); addNotification({ status: 'success', message: t('connection.connectionSuccessfullyMade') });
} }
catch (err) { catch (err) {
@@ -537,13 +558,21 @@ const startTest = async () => {
} }
}; };
const abortConnection = (): void => {
abortController.value.abort();
Connection.abortConnection(connection.value.uid);
isTesting.value = false;
isConnecting.value = false;
abortController.value = new AbortController();
};
const continueTest = async (credentials: { user: string; password: string }) => { // if "Ask for credentials" is true const continueTest = async (credentials: { user: string; password: string }) => { // if "Ask for credentials" is true
isAsking.value = false; isAsking.value = false;
const params = Object.assign({}, connection.value, credentials); const params = Object.assign({}, connection.value, credentials);
try { try {
if (isConnecting.value) { if (isConnecting.value) {
await connectWorkspace(params); await connectWorkspace(params, { signal: abortController.value.signal }).catch(() => undefined);
isConnecting.value = false; isConnecting.value = false;
} }
else { else {

View File

@@ -387,7 +387,21 @@
</div> </div>
</div> </div>
<div class="panel-footer"> <div class="panel-footer">
<div
@mouseenter="setCancelTestButtonVisibility(true)"
@mouseleave="setCancelTestButtonVisibility(false)"
>
<button <button
v-if="showTestCancel && isTesting"
class="btn btn-gray mr-2 cancellable"
:title="t('general.cancel')"
@click="abortConnection()"
>
<BaseIcon icon-name="mdiWindowClose" :size="24" />
<span class="d-invisible pr-1">{{ t('connection.testConnection') }}</span>
</button>
<button
v-else
id="connection-test" id="connection-test"
class="btn btn-gray mr-2 d-flex" class="btn btn-gray mr-2 d-flex"
:class="{'loading': isTesting}" :class="{'loading': isTesting}"
@@ -401,6 +415,7 @@
/> />
{{ t('connection.testConnection') }} {{ t('connection.testConnection') }}
</button> </button>
</div>
<button <button
id="connection-save" id="connection-save"
class="btn btn-primary mr-2 d-flex" class="btn btn-primary mr-2 d-flex"
@@ -414,7 +429,21 @@
/> />
{{ t('general.save') }} {{ t('general.save') }}
</button> </button>
<div
@mouseenter="setCancelConnectButtonVisibility(true)"
@mouseleave="setCancelConnectButtonVisibility(false)"
>
<button <button
v-if="showConnectCancel && isConnecting"
class="btn btn-success cancellable"
:title="t('general.cancel')"
@click="abortConnection()"
>
<BaseIcon icon-name="mdiWindowClose" :size="24" />
<span class="d-invisible pr-1">{{ t('connection.connect') }}</span>
</button>
<button
v-else
id="connection-connect" id="connection-connect"
class="btn btn-success d-flex" class="btn btn-success d-flex"
:class="{'loading': isConnecting}" :class="{'loading': isConnecting}"
@@ -430,6 +459,7 @@
</button> </button>
</div> </div>
</div> </div>
</div>
<ModalAskCredentials <ModalAskCredentials
v-if="isAsking" v-if="isAsking"
@close-asking="closeAsking" @close-asking="closeAsking"
@@ -476,6 +506,9 @@ const localConnection: Ref<ConnectionParams & { pgConnString: string }> = ref(nu
const isConnecting = ref(false); const isConnecting = ref(false);
const isTesting = ref(false); const isTesting = ref(false);
const isAsking = ref(false); const isAsking = ref(false);
const showTestCancel = ref(false);
const showConnectCancel = ref(false);
const abortController: Ref<AbortController> = ref(new AbortController());
const selectedTab = ref('general'); const selectedTab = ref('general');
const clientCustomizations = computed(() => { const clientCustomizations = computed(() => {
@@ -501,7 +534,7 @@ const startConnection = async () => {
if (localConnection.value.ask) if (localConnection.value.ask)
isAsking.value = true; isAsking.value = true;
else { else {
await connectWorkspace(localConnection.value); await connectWorkspace(localConnection.value, { signal: abortController.value.signal }).catch(() => undefined);
isConnecting.value = false; isConnecting.value = false;
} }
}; };
@@ -516,7 +549,7 @@ const startTest = async () => {
const res = await Connection.makeTest(localConnection.value); const res = await Connection.makeTest(localConnection.value);
if (res.status === 'error') if (res.status === 'error')
addNotification({ status: 'error', message: res.response.message || res.response.toString() }); addNotification({ status: 'error', message: res.response.message || res.response.toString() });
else else if (res.status === 'success')
addNotification({ status: 'success', message: t('connection.connectionSuccessfullyMade') }); addNotification({ status: 'success', message: t('connection.connectionSuccessfullyMade') });
} }
catch (err) { catch (err) {
@@ -527,20 +560,36 @@ const startTest = async () => {
} }
}; };
const setCancelTestButtonVisibility = (val: boolean) => {
showTestCancel.value = val;
};
const setCancelConnectButtonVisibility = (val: boolean) => {
showConnectCancel.value = val;
};
const abortConnection = (): void => {
abortController.value.abort();
Connection.abortConnection(localConnection.value.uid);
isTesting.value = false;
isConnecting.value = false;
abortController.value = new AbortController();
};
const continueTest = async (credentials: {user: string; password: string }) => { // if "Ask for credentials" is true const continueTest = async (credentials: {user: string; password: string }) => { // if "Ask for credentials" is true
isAsking.value = false; isAsking.value = false;
const params = Object.assign({}, localConnection.value, credentials); const params = Object.assign({}, localConnection.value, credentials);
try { try {
if (isConnecting.value) { if (isConnecting.value) {
const params = Object.assign({}, props.connection, credentials); const params = Object.assign({}, props.connection, credentials);
await connectWorkspace(params); await connectWorkspace(params, { signal: abortController.value.signal }).catch(() => undefined);
isConnecting.value = false; isConnecting.value = false;
} }
else { else {
const res = await Connection.makeTest(params); const res = await Connection.makeTest(params);
if (res.status === 'error') if (res.status === 'error')
addNotification({ status: 'error', message: res.response.message || res.response.toString() }); addNotification({ status: 'error', message: res.response.message || res.response.toString() });
else else if (res.status === 'success')
addNotification({ status: 'success', message: t('connection.connectionSuccessfullyMade') }); addNotification({ status: 'success', message: t('connection.connectionSuccessfullyMade') });
} }
} }

View File

@@ -16,7 +16,7 @@
/> {{ t('general.run') }}</span> /> {{ t('general.run') }}</span>
</div> </div>
<div <div
v-if="selectedMisc.type === 'trigger' && customizations.triggerEnableDisable" v-if="selectedMisc.type === 'trigger' && customizations.triggerEnableDisable && !connection.readonly"
class="context-element" class="context-element"
@click="toggleTrigger" @click="toggleTrigger"
> >
@@ -36,7 +36,7 @@
</span> </span>
</div> </div>
<div <div
v-if="selectedMisc.type === 'scheduler'" v-if="selectedMisc.type === 'scheduler' && !connection.readonly"
class="context-element" class="context-element"
@click="toggleScheduler" @click="toggleScheduler"
> >
@@ -63,7 +63,11 @@
:size="18" :size="18"
/> {{ t('general.copyName') }}</span> /> {{ t('general.copyName') }}</span>
</div> </div>
<div class="context-element" @click="showDeleteModal"> <div
v-if="!connection.readonly"
class="context-element"
@click="showDeleteModal"
>
<span class="d-flex"> <span class="d-flex">
<BaseIcon <BaseIcon
class="text-light mt-1 mr-1" class="text-light mt-1 mr-1"
@@ -117,6 +121,7 @@ import Routines from '@/ipc-api/Routines';
import Schedulers from '@/ipc-api/Schedulers'; import Schedulers from '@/ipc-api/Schedulers';
import Triggers from '@/ipc-api/Triggers'; import Triggers from '@/ipc-api/Triggers';
import { copyText } from '@/libs/copyText'; import { copyText } from '@/libs/copyText';
import { useConnectionsStore } from '@/stores/connections';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
@@ -132,6 +137,7 @@ const emit = defineEmits(['close-context', 'reload']);
const { addNotification } = useNotificationsStore(); const { addNotification } = useNotificationsStore();
const workspacesStore = useWorkspacesStore(); const workspacesStore = useWorkspacesStore();
const { getConnectionByUid } = useConnectionsStore();
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore); const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
@@ -154,6 +160,7 @@ const workspace = computed(() => {
const customizations = computed(() => { const customizations = computed(() => {
return getWorkspace(selectedWorkspace.value).customizations; return getWorkspace(selectedWorkspace.value).customizations;
}); });
const connection = computed(() => getConnectionByUid(selectedWorkspace.value));
const deleteMessage = computed(() => { const deleteMessage = computed(() => {
switch (props.selectedMisc.type) { switch (props.selectedMisc.type) {

View File

@@ -3,7 +3,7 @@
:context-event="contextEvent" :context-event="contextEvent"
@close-context="closeContext" @close-context="closeContext"
> >
<div class="context-element"> <div v-if="!connection.readonly" class="context-element">
<span class="d-flex"> <span class="d-flex">
<BaseIcon <BaseIcon
class="text-light mt-1 mr-1" class="text-light mt-1 mr-1"
@@ -135,7 +135,7 @@
/> {{ t('database.export') }}</span> /> {{ t('database.export') }}</span>
</div> </div>
<div <div
v-if="workspace.customizations.schemaImport" v-if="workspace.customizations.schemaImport && !connection.readonly"
class="context-element" class="context-element"
@click="initImport" @click="initImport"
> >
@@ -147,7 +147,7 @@
/> {{ t('database.import') }}</span> /> {{ t('database.import') }}</span>
</div> </div>
<div <div
v-if="workspace.customizations.schemaEdit" v-if="workspace.customizations.schemaEdit && !connection.readonly"
class="context-element" class="context-element"
@click="showEditModal" @click="showEditModal"
> >
@@ -159,7 +159,7 @@
/> {{ t('database.editSchema') }}</span> /> {{ t('database.editSchema') }}</span>
</div> </div>
<div <div
v-if="workspace.customizations.schemaDrop" v-if="workspace.customizations.schemaDrop && !connection.readonly"
class="context-element" class="context-element"
@click="showDeleteModal" @click="showDeleteModal"
> >
@@ -219,6 +219,7 @@ import ModalImportSchema from '@/components/ModalImportSchema.vue';
import Application from '@/ipc-api/Application'; import Application from '@/ipc-api/Application';
import Schema from '@/ipc-api/Schema'; import Schema from '@/ipc-api/Schema';
import { copyText } from '@/libs/copyText'; import { copyText } from '@/libs/copyText';
import { useConnectionsStore } from '@/stores/connections';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useSchemaExportStore } from '@/stores/schemaExport'; import { useSchemaExportStore } from '@/stores/schemaExport';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
@@ -248,7 +249,9 @@ const workspacesStore = useWorkspacesStore();
const schemaExportStore = useSchemaExportStore(); const schemaExportStore = useSchemaExportStore();
const { showExportModal } = schemaExportStore; const { showExportModal } = schemaExportStore;
const connectionsStore = useConnectionsStore();
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore); const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
const { getConnectionByUid } = connectionsStore;
const { const {
getWorkspace, getWorkspace,
@@ -261,6 +264,7 @@ const isEditModal = ref(false);
const isImportSchemaModal = ref(false); const isImportSchemaModal = ref(false);
const workspace = computed(() => getWorkspace(selectedWorkspace.value)); const workspace = computed(() => getWorkspace(selectedWorkspace.value));
const connection = computed(() => getConnectionByUid(selectedWorkspace.value));
const openCreateTableTab = () => { const openCreateTableTab = () => {
emit('open-create-table-tab'); emit('open-create-table-tab');

View File

@@ -60,7 +60,7 @@
/> {{ t('application.settings') }}</span> /> {{ t('application.settings') }}</span>
</div> </div>
<div <div
v-if="selectedTable && selectedTable.type === 'table' && customizations.tableDuplicate" v-if="selectedTable && selectedTable.type === 'table' && customizations.tableDuplicate && !connection.readonly"
class="context-element" class="context-element"
@click="duplicateTable" @click="duplicateTable"
> >
@@ -72,7 +72,7 @@
/> {{ t('database.duplicateTable') }}</span> /> {{ t('database.duplicateTable') }}</span>
</div> </div>
<div <div
v-if="selectedTable && selectedTable.type === 'table'" v-if="selectedTable && selectedTable.type === 'table' && !connection.readonly"
class="context-element" class="context-element"
@click="showEmptyModal" @click="showEmptyModal"
> >
@@ -83,7 +83,11 @@
:size="18" :size="18"
/> {{ t('database.emptyTable') }}</span> /> {{ t('database.emptyTable') }}</span>
</div> </div>
<div class="context-element" @click="showDeleteModal"> <div
v-if="!connection.readonly"
class="context-element"
@click="showDeleteModal"
>
<span class="d-flex"> <span class="d-flex">
<BaseIcon <BaseIcon
class="text-light mt-1 mr-1" class="text-light mt-1 mr-1"
@@ -151,6 +155,7 @@ import BaseContextMenu from '@/components/BaseContextMenu.vue';
import BaseIcon from '@/components/BaseIcon.vue'; import BaseIcon from '@/components/BaseIcon.vue';
import Tables from '@/ipc-api/Tables'; import Tables from '@/ipc-api/Tables';
import { copyText } from '@/libs/copyText'; import { copyText } from '@/libs/copyText';
import { useConnectionsStore } from '@/stores/connections';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useSchemaExportStore } from '@/stores/schemaExport'; import { useSchemaExportStore } from '@/stores/schemaExport';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
@@ -168,6 +173,7 @@ const emit = defineEmits(['close-context', 'duplicate-table', 'reload', 'delete-
const { addNotification } = useNotificationsStore(); const { addNotification } = useNotificationsStore();
const workspacesStore = useWorkspacesStore(); const workspacesStore = useWorkspacesStore();
const { showExportModal } = useSchemaExportStore(); const { showExportModal } = useSchemaExportStore();
const { getConnectionByUid } = useConnectionsStore();
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore); const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
@@ -185,6 +191,7 @@ const forceTruncate = ref(false);
const workspace = computed(() => getWorkspace(selectedWorkspace.value)); const workspace = computed(() => getWorkspace(selectedWorkspace.value));
const customizations = computed(() => workspace.value && workspace.value.customizations ? workspace.value.customizations : null); const customizations = computed(() => workspace.value && workspace.value.customizations ? workspace.value.customizations : null);
const connection = computed(() => getConnectionByUid(selectedWorkspace.value));
const showTableExportModal = () => { const showTableExportModal = () => {
showExportModal(props.selectedSchema, props.selectedTable.name); showExportModal(props.selectedSchema, props.selectedTable.name);

View File

@@ -253,6 +253,7 @@
v-if="results" v-if="results"
v-show="!isQuering" v-show="!isQuering"
ref="queryTable" ref="queryTable"
:is-quering="isQuering"
:results="results" :results="results"
:tab-uid="tab.uid" :tab-uid="tab.uid"
:conn-uid="connection.uid" :conn-uid="connection.uid"

View File

@@ -38,7 +38,7 @@
<div class="thead"> <div class="thead">
<div class="tr"> <div class="tr">
<div <div
v-for="(field, index) in fields" v-for="(field, index) in filteredFields"
:key="index" :key="index"
class="th c-hand" class="th c-hand"
:title="`${field.type} ${fieldLength(field) ? `(${fieldLength(field)})` : ''}`" :title="`${field.type} ${fieldLength(field) ? `(${fieldLength(field)})` : ''}`"
@@ -291,6 +291,7 @@ const { consoleHeight } = storeToRefs(consoleStore);
const props = defineProps({ const props = defineProps({
results: Array as Prop<QueryResult[]>, results: Array as Prop<QueryResult[]>,
connUid: String, connUid: String,
isQuering: Boolean,
mode: String as Prop<'table' | 'query'>, mode: String as Prop<'table' | 'query'>,
page: { page: {
type: Number, type: Number,
@@ -382,6 +383,11 @@ const sortedResults = computed(() => {
const resultsWithRows = computed(() => props.results.filter(result => result.rows.length)); const resultsWithRows = computed(() => props.results.filter(result => result.rows.length));
const fields = computed(() => resultsWithRows.value.length ? resultsWithRows.value[resultsetIndex.value].fields : []); const fields = computed(() => resultsWithRows.value.length ? resultsWithRows.value[resultsetIndex.value].fields : []);
const filteredFields = computed(() => fields.value.reduce((acc, cur) => {
if (acc.findIndex(f => JSON.stringify(f) === JSON.stringify(cur)))
acc.push(cur);
return acc;
}, [] as TableField[]));
const keyUsage = computed(() => resultsWithRows.value.length ? resultsWithRows.value[resultsetIndex.value].keys : []); const keyUsage = computed(() => resultsWithRows.value.length ? resultsWithRows.value[resultsetIndex.value].keys : []);
const fieldsObj = computed(() => { const fieldsObj = computed(() => {
@@ -790,7 +796,7 @@ const contextMenu = (event: MouseEvent, cell: any) => {
}; };
const sort = (field: TableField) => { const sort = (field: TableField) => {
if (!isSortable.value) return; if (!isSortable.value || props.isQuering) return;
selectedRows.value = []; selectedRows.value = [];
let fieldName = field.name; let fieldName = field.name;

View File

@@ -202,6 +202,7 @@
v-if="results" v-if="results"
ref="queryTable" ref="queryTable"
:results="results" :results="results"
:is-quering="isQuering"
:page="page" :page="page"
:tab-uid="tabUid" :tab-uid="tabUid"
:conn-uid="connection.uid" :conn-uid="connection.uid"

View File

@@ -1,3 +1,13 @@
/**
* [TRANSLATION UPDATE HELPER]
* - Open a terminal in antares folder and run `npm run translation:check short-code` replacing short-code with the one you are updating.
* - The command will output which terms are missing or not translated from english.
* - Open antares folder with your editor of choice.
* - Go to antares/src/renderer/i18n/ and open the locale file you want to translate.
* - Add and translate missing terms and consider whether to translate untranslated terms.
*/
export const csCZ = { export const csCZ = {
general: { // General purpose terms general: { // General purpose terms
edit: 'Upravit', edit: 'Upravit',
@@ -18,7 +28,7 @@ export const csCZ = {
download: 'Stáhnout', download: 'Stáhnout',
add: 'Přidat', add: 'Přidat',
data: 'Data', data: 'Data',
properties: 'Vlastnosti', // Lawondyss: Not used properties: 'Vlastnosti',
name: 'Název', name: 'Název',
clear: 'Vyčistit', clear: 'Vyčistit',
options: 'Možnosti', options: 'Možnosti',
@@ -39,6 +49,7 @@ export const csCZ = {
new: 'Nové', new: 'Nové',
select: 'Vybrat', select: 'Vybrat',
change: 'Změnit', change: 'Změnit',
include: 'Včetně',
includes: 'Zahrnout', includes: 'Zahrnout',
completed: 'Dokončeno', completed: 'Dokončeno',
aborted: 'Zrušeno', aborted: 'Zrušeno',
@@ -46,15 +57,15 @@ export const csCZ = {
enable: 'Zapnuto', enable: 'Zapnuto',
disable: 'Vypnout', disable: 'Vypnout',
contributors: 'Přispěvatelé', contributors: 'Přispěvatelé',
pin: 'Připnout', // Lawondyss: Not used pin: 'Připnout',
unpin: 'Odepnout', // Lawondyss: Not used unpin: 'Odepnout',
folder: 'Složka | Složky', // Lawondyss: Used only 1 folder: 'Složka | Složky',
none: 'Nic', none: 'Nic',
singleQuote: 'Apostrofy', singleQuote: 'Apostrofy',
doubleQuote: 'Uvozovky', doubleQuote: 'Uvozovky',
deleteConfirm: 'Skutečně chcete smazat', deleteConfirm: 'Skutečně chcete smazat',
uploadFile: 'Nahrát soubor', uploadFile: 'Nahrát soubor',
format: 'Formátovat', // Format code format: 'Formátovat',
history: 'Historie', history: 'Historie',
filter: 'Filtrovat', filter: 'Filtrovat',
manualValue: 'Vlastní hodnota', manualValue: 'Vlastní hodnota',
@@ -64,9 +75,16 @@ export const csCZ = {
actionSuccessful: '{action} úspěšný', actionSuccessful: '{action} úspěšný',
outputFormat: 'Formát výstupu', outputFormat: 'Formát výstupu',
singleFile: 'Jediný {ext} soubor', singleFile: 'Jediný {ext} soubor',
zipCompressedFile: 'ZIP komprimovaný {ext} soubor' zipCompressedFile: 'ZIP komprimovaný {ext} soubor',
copyName: 'Kopírovat název',
search: 'Hledat',
title: 'Titulek',
archive: 'Archivovat', // verb
undo: 'Zpět',
moveTo: 'Přesunout do'
}, },
connection: { // Database connection connection: { // Database connection
connection: 'Připojení',
connectionName: 'Název', connectionName: 'Název',
hostName: 'Host', hostName: 'Host',
client: 'Klient', client: 'Klient',
@@ -75,9 +93,9 @@ export const csCZ = {
password: 'Heslo', password: 'Heslo',
credentials: 'Pověření', credentials: 'Pověření',
connect: 'Připojit', connect: 'Připojit',
connected: 'Připojeno', // Lawondyss: Not used connected: 'Připojeno',
disconnect: 'Odpojit', disconnect: 'Odpojit',
disconnected: 'Odpojeno', // Lawondyss: Not used disconnected: 'Odpojeno',
ssl: 'SSL', ssl: 'SSL',
enableSsl: 'Použít SSL', enableSsl: 'Použít SSL',
privateKey: 'Soukromý klíč', privateKey: 'Soukromý klíč',
@@ -90,28 +108,30 @@ export const csCZ = {
enableSsh: 'Použít SSH', enableSsh: 'Použít SSH',
connectionString: 'String připojení', connectionString: 'String připojení',
addConnection: 'Add connection', addConnection: 'Add connection',
createConnection: 'Vytvořit připojení', // Lawondyss: Not used createConnection: 'Vytvořit připojení',
createNewConnection: 'Vytvořit nové připojení', createNewConnection: 'Vytvořit nové připojení',
askCredentials: 'Vyžadovat přihlášení', askCredentials: 'Vyžadovat přihlášení',
testConnection: 'Vyzkoušet', testConnection: 'Vyzkoušet',
editConnection: 'Upravit připojení', // Lawondyss: Not used editConnection: 'Upravit připojení',
deleteConnection: 'Smazat připojení', deleteConnection: 'Smazat připojení',
connectionSuccessfullyMade: 'Spojení úspěšně navázáno!', connectionSuccessfullyMade: 'Spojení úspěšně navázáno!',
readOnlyMode: 'Pouze pro čtení', readOnlyMode: 'Pouze pro čtení',
allConnections: 'Všechna připojení', allConnections: 'Všechna připojení',
searchForConnections: 'Hledat připojení' searchForConnections: 'Hledat připojení',
keepAliveInterval: 'Keep alive interval',
singleConnection: 'Jediné spojení'
}, },
database: { // Database related terms database: { // Database related terms
schema: 'Schéma', schema: 'Schéma',
type: 'Typ', type: 'Typ',
insert: 'Vložit', // Lawondyss: Not used insert: 'Vložit',
indexes: 'Indexy', indexes: 'Indexy',
foreignKeys: 'Cizí klíče', foreignKeys: 'Cizí klíče',
length: 'Délka', length: 'Délka',
unsigned: 'Unsigned', unsigned: 'Unsigned',
default: 'Výchozí', default: 'Výchozí',
comment: 'Komentář', comment: 'Komentář',
key: 'Klíč | Klíče', // Lawondyss: Used only 2 key: 'Klíč | Klíče',
order: 'Pořadí', order: 'Pořadí',
expression: 'Výraz', expression: 'Výraz',
autoIncrement: 'Auto Increment', autoIncrement: 'Auto Increment',
@@ -119,8 +139,9 @@ export const csCZ = {
field: 'Sloupec | Sloupce', field: 'Sloupec | Sloupce',
approximately: 'Přibližně', approximately: 'Přibližně',
total: 'Celkem', total: 'Celkem',
table: 'Tabulka | Tabulky', // Lawondyss: Used only without argument table: 'Tabulka | Tabulky',
view: 'Pohled | Pohledy', // Lawondyss: Used only without argument view: 'Pohled | Pohledy',
materializedview: 'Materializovaný pohled',
definer: 'Definér', definer: 'Definér',
algorithm: 'Algoritmus', algorithm: 'Algoritmus',
trigger: 'Trigger | Triggery', trigger: 'Trigger | Triggery',
@@ -147,25 +168,25 @@ export const csCZ = {
row: 'Řádek | Řádky', row: 'Řádek | Řádky',
cell: 'Buňka | Buňky', cell: 'Buňka | Buňky',
triggerFunction: 'Trigger funkce | Trigger funkce', triggerFunction: 'Trigger funkce | Trigger funkce',
routine: 'Routina | Routiny', // Lawondyss: Not used routine: 'Routina | Routiny',
drop: 'Drop', drop: 'Drop',
commit: 'Commit', commit: 'Commit',
rollback: 'Rollback', rollback: 'Rollback',
ddl: 'DDL', ddl: 'DDL',
collation: 'Porovnání', collation: 'Porovnání',
resultsTable: 'Tabulka výsledků', resultsTable: 'Tabulka výsledků',
unableEditFieldWithoutPrimary: 'Nelze upravit buňku bez primárního klíče ve výsledku', // Lawondyss: Not used unableEditFieldWithoutPrimary: 'Nelze upravit buňku bez primárního klíče ve výsledku',
editCell: 'Upravit buňku', // Lawondyss: Not used editCell: 'Upravit buňku',
deleteRows: 'Smazat řádek | Smazat {count} řádků', deleteRows: 'Smazat řádek | Smazat {count} řádků',
confirmToDeleteRows: 'Skutečně chcete smazat řádek? | Skutečně chcete smazat {count} řádků?', confirmToDeleteRows: 'Skutečně chcete smazat řádek? | Skutečně chcete smazat {count} řádků?',
addNewRow: 'Přidat nový řádek', // Lawondyss: Not used addNewRow: 'Přidat nový řádek',
numberOfInserts: 'Počet opakování', numberOfInserts: 'Počet opakování',
affectedRows: 'Ovlivněno řádků', affectedRows: 'Ovlivněno řádků',
createNewDatabase: 'Vytvořit novou databázi', // Lawondyss: Not used createNewDatabase: 'Vytvořit novou databázi',
databaseName: 'Název databáze', // Lawondyss: Not use databaseName: 'Název databáze',
serverDefault: 'Porovnání serveru', serverDefault: 'Porovnání serveru',
deleteDatabase: 'Smazat databázi', // Lawondyss: Not used deleteDatabase: 'Smazat databázi',
editDatabase: 'Upravit databázi', // Lawondyss: Not used editDatabase: 'Upravit databázi',
clearChanges: 'Zrušit změny', clearChanges: 'Zrušit změny',
addNewField: 'Přidat nový sloupec', addNewField: 'Přidat nový sloupec',
manageIndexes: 'Správa indexů', manageIndexes: 'Správa indexů',
@@ -177,17 +198,18 @@ export const csCZ = {
deleteField: 'Smazat sloupec', deleteField: 'Smazat sloupec',
createNewIndex: 'Vytvořit nový index', createNewIndex: 'Vytvořit nový index',
addToIndex: 'Přidat do indexu', addToIndex: 'Přidat do indexu',
createNewTable: 'Vytvořit novou databázi', // Lawondyss: Not used createNewTable: 'Vytvořit novou databázi',
emptyTable: 'Smazat obsah tabulky', emptyTable: 'Smazat obsah tabulky',
duplicateTable: 'Duplikovat tabulku', duplicateTable: 'Duplikovat tabulku',
deleteTable: 'Smazat tabulku', deleteTable: 'Smazat tabulku',
exportTable: 'Exportovat tabulku',
emptyConfirm: 'Skutečně smazat obsah tabulky', emptyConfirm: 'Skutečně smazat obsah tabulky',
thereAreNoIndexes: 'Nemá žádné indexy', thereAreNoIndexes: 'Nemá žádné indexy',
thereAreNoForeign: 'Nemá žádné cizí klíče', thereAreNoForeign: 'Nemá žádné cizí klíče',
createNewForeign: 'Vytvořit nový cizí klíč', createNewForeign: 'Vytvořit nový cizí klíč',
referenceTable: 'Ref. tabulka', referenceTable: 'Ref. tabulka',
referenceField: 'Ref. sloupec', referenceField: 'Ref. sloupec',
foreignFields: 'Cizí sloupce', // Lawondyss: Not used foreignFields: 'Cizí sloupce',
invalidDefault: 'Neplatná výchozí hodnota', invalidDefault: 'Neplatná výchozí hodnota',
onDelete: 'Při smazání', onDelete: 'Při smazání',
selectStatement: 'Definice pohledu', selectStatement: 'Definice pohledu',
@@ -195,7 +217,8 @@ export const csCZ = {
sqlSecurity: 'SQL zabezpečení', sqlSecurity: 'SQL zabezpečení',
updateOption: 'Volba aktualizace', updateOption: 'Volba aktualizace',
deleteView: 'Smazat pohled', deleteView: 'Smazat pohled',
createNewView: 'Vytvořit nový pohled', // Lawondyss: Not used createNewView: 'Vytvořit nový pohled',
createNewMaterializedView: 'Vytvořit nový materializovaný pohled',
deleteTrigger: 'Smazat trigger', deleteTrigger: 'Smazat trigger',
createNewTrigger: 'Vytvořit nový trigger', createNewTrigger: 'Vytvořit nový trigger',
currentUser: 'Současný uživatel', currentUser: 'Současný uživatel',
@@ -212,7 +235,7 @@ export const csCZ = {
createNewScheduler: 'Vytvořit nový scheduler', createNewScheduler: 'Vytvořit nový scheduler',
deleteScheduler: 'Smazat scheduler', deleteScheduler: 'Smazat scheduler',
preserveOnCompletion: 'Uchovat po dokončení', preserveOnCompletion: 'Uchovat po dokončení',
tableFiller: 'Vyplňovač tabulky', // Lawondyss: Not used tableFiller: 'Vyplňovač tabulky',
fakeDataLanguage: 'Jazyk pro fake data', fakeDataLanguage: 'Jazyk pro fake data',
queryDuration: 'Doba trvání dotazu', queryDuration: 'Doba trvání dotazu',
setNull: 'Nastavit NULL', setNull: 'Nastavit NULL',
@@ -224,10 +247,11 @@ export const csCZ = {
editSchema: 'Upravit schéma', editSchema: 'Upravit schéma',
deleteSchema: 'Smazat schema', deleteSchema: 'Smazat schema',
noSchema: 'Bez schématu', noSchema: 'Bez schématu',
runQuery: 'Spustit dotaz', // Lawondyss: Not used runQuery: 'Spustit dotaz',
thereAreNoTableFields: 'Nemá žádné sloupce', thereAreNoTableFields: 'Nemá žádné sloupce',
newTable: 'Nová tabulka', newTable: 'Nová tabulka',
newView: 'Nový pohled', newView: 'Nový pohled',
newMaterializedView: 'Nový materializovaný pohled',
newTrigger: 'Nový trigger', newTrigger: 'Nový trigger',
newRoutine: 'Nová routina', newRoutine: 'Nová routina',
newFunction: 'Nová funkce', newFunction: 'Nová funkce',
@@ -244,17 +268,17 @@ export const csCZ = {
writingTableExport: 'Zapisuji data tabulky {table}', writingTableExport: 'Zapisuji data tabulky {table}',
checkAllTables: 'Vybrat všechny tabulky', checkAllTables: 'Vybrat všechny tabulky',
uncheckAllTables: 'Vybrat žádnou tabulku', uncheckAllTables: 'Vybrat žádnou tabulku',
killQuery: 'Zabít dotaz', // Lawondyss: Not used killQuery: 'Zabít dotaz',
insertRow: 'Vložit řádek | Vložit řádky', // Lawondyss: Used only 2 insertRow: 'Vložit řádek | Vložit řádky',
commitMode: 'Způsob commitování', commitMode: 'Způsob commitování',
autoCommit: 'Auto commit', autoCommit: 'Auto commit',
manualCommit: 'Ruční commit', manualCommit: 'Ruční commit',
importQueryErrors: 'Varování: došlo k chybě {n} | Varování: došlo k chybám {n}', // Lawondyss: Used without n argument importQueryErrors: 'Varování: došlo k chybě {n} | Varování: došlo k chybám {n}',
executedQueries: '{n} dotaz spuštěn | {n} dotazy spuštěny', // Lawondyss: Used withoum n argument executedQueries: '{n} dotaz spuštěn | {n} dotazy spuštěny',
disableFKChecks: 'Vypnout kontrolu cizích klíčů', disableFKChecks: 'Vypnout kontrolu cizích klíčů',
formatQuery: 'Formátovat dotaz', // Lawondyss: Not used, probably duplicate to general.format formatQuery: 'Formátovat dotaz',
queryHistory: 'Historie dotazů', // Lawondyss: Not used, probably duplicate to general.history queryHistory: 'Historie dotazů',
clearQuery: 'Clear query', // Lawondyss: Not used, probably duplicate to general.clear clearQuery: 'Clear query',
fillCell: 'Vyplnit buňku', fillCell: 'Vyplnit buňku',
executeSelectedQuery: 'Spustit vybraný dotaz', executeSelectedQuery: 'Spustit vybraný dotaz',
noResultsPresent: 'Nejsou k dispozici žádné výsledky', noResultsPresent: 'Nejsou k dispozici žádné výsledky',
@@ -262,12 +286,11 @@ export const csCZ = {
targetTable: 'Cílová tabulka', targetTable: 'Cílová tabulka',
switchDatabase: 'Přepnout databázi', switchDatabase: 'Přepnout databázi',
searchForElements: 'Vyhledávání prvků', searchForElements: 'Vyhledávání prvků',
searchForSchemas: 'Vyhledávání schémat' searchForSchemas: 'Vyhledávání schémat',
savedQueries: 'Uložit dotazy'
}, },
application: { // Application related terms application: { // Application related terms
settings: 'Nastavení', settings: 'Nastavení',
scratchpad: 'Zápisník',
disableScratchpad: 'Vypnout zápisník',
console: 'Konzole', console: 'Konzole',
general: 'Obecné', general: 'Obecné',
themes: 'Motivy', themes: 'Motivy',
@@ -275,7 +298,7 @@ export const csCZ = {
about: 'Informace', about: 'Informace',
language: 'Jazyk', language: 'Jazyk',
shortcuts: 'Zkratky', shortcuts: 'Zkratky',
key: 'Klávesa | Klávesy', // Keyboard key // Lawondyss: Usedn only 2 key: 'Klávesa | Klávesy', // Keyboard key
event: 'Akce', event: 'Akce',
light: 'Světlý', light: 'Světlý',
dark: 'Tmavý', dark: 'Tmavý',
@@ -283,13 +306,19 @@ export const csCZ = {
application: 'Aplikace', application: 'Aplikace',
editor: 'Editor', editor: 'Editor',
changelog: 'Changelog', changelog: 'Changelog',
small: 'Malé', // Lawondyss: Not used, probably obsolete font size settings small: 'Malé',
medium: 'Střední', // Lawondyss: Not used, probably obsolete font size settings medium: 'Střední',
large: 'Velké', // Lawondyss: Not used, probably obsolete font size settings large: 'Velké',
appearance: 'Vzhled', appearance: 'Vzhled',
color: 'Barva', color: 'Barva',
label: 'Název', label: 'Název',
icon: 'Ikona', icon: 'Ikona',
customIcon: 'Vlastní ikona',
fileName: 'Soubor',
choseFile: 'Vybrat soubor',
data: 'Data',
password: 'Heslo',
required: 'Povinné',
madeWithJS: 'Vytvořeno s 💛 a JavaScriptem!', madeWithJS: 'Vytvořeno s 💛 a JavaScriptem!',
checkForUpdates: 'Zkontrolovat aktualizace', checkForUpdates: 'Zkontrolovat aktualizace',
noUpdatesAvailable: 'Žádné dostupné aktualizace', noUpdatesAvailable: 'Žádné dostupné aktualizace',
@@ -308,7 +337,7 @@ export const csCZ = {
editorTheme: 'Motiv editoru', editorTheme: 'Motiv editoru',
wrapLongLines: 'Zalamovat dlouhé řádky', wrapLongLines: 'Zalamovat dlouhé řádky',
markdownSupported: 'Podporován Markdown', markdownSupported: 'Podporován Markdown',
plantATree: 'Zasaďte strom', // Lawondyss: Not used plantATree: 'Zasaďte strom',
dataTabPageSize: 'Počet řádků na stránku', dataTabPageSize: 'Počet řádků na stránku',
noOpenTabs: 'Žádné otevřené karty, vyberte z elementů vlevo nebo:', noOpenTabs: 'Žádné otevřené karty, vyberte z elementů vlevo nebo:',
restorePreviousSession: 'Pamatovat si otevřené karty', restorePreviousSession: 'Pamatovat si otevřené karty',
@@ -333,15 +362,16 @@ export const csCZ = {
saveContent: 'Uložit obsah', saveContent: 'Uložit obsah',
openAllConnections: 'Otevřít všechna připojení', openAllConnections: 'Otevřít všechna připojení',
openSettings: 'Otevřít nastavení', openSettings: 'Otevřít nastavení',
openScratchpad: 'Otevřít zápisník',
runOrReload: 'Spustit dotaz', runOrReload: 'Spustit dotaz',
openFilter: 'Otevřít filtr', openFilter: 'Otevřít filtr',
nextResultsPage: 'Další stránka výsledků', nextResultsPage: 'Další stránka výsledků',
previousResultsPage: 'Předešlá stránka výsledků', previousResultsPage: 'Předešlá stránka výsledků',
editFolder: 'Upravit složku', editFolder: 'Upravit složku',
folderName: 'Název složky', folderName: 'Název složky',
deleteFolder: 'Smazat složku', // Lawondyss: Not used deleteFolder: 'Smazat složku',
editConnectionAppearance: 'Upravit vzhled připojení', // Lawondyss: Not used newFolder: 'Nová složka',
outOfFolder: 'Mimo složku',
editConnectionAppearance: 'Upravit vzhled připojení',
defaultCopyType: 'Výchozí typ kopírování', defaultCopyType: 'Výchozí typ kopírování',
showTableSize: 'Velikost tabulky v panelu', showTableSize: 'Velikost tabulky v panelu',
showTableSizeDescription: 'Pouze MySQL/MariaDB. Povolení této možnosti může ovlivnit výkon u schémat s mnoha tabulkami.', showTableSizeDescription: 'Pouze MySQL/MariaDB. Povolení této možnosti může ovlivnit výkon u schémat s mnoha tabulkami.',
@@ -356,7 +386,33 @@ export const csCZ = {
csvStringDelimiter: 'Obalit text', csvStringDelimiter: 'Obalit text',
csvIncludeHeader: 'Včetně hlavičky', csvIncludeHeader: 'Včetně hlavičky',
csvExportOptions: 'Možnosti CSV exportu', csvExportOptions: 'Možnosti CSV exportu',
scratchPadDefaultValue: '# JAK PODPOŘIT ANTARES\n\n- [ ] Dát Antares hvězdičku [GitHub repo](https://github.com/antares-sql/antares)\n- [ ] Poslat názor či radu\n- [ ] Nahlásit chybu\n- [ ] Pokud se líbí, sdílet Antares s přáteli\n\n# O ZÁPISNÍKU\n\nToto je zápisník, který uchovává vaše **osobní poznámky**. Podporuje `markdown` formát, ale můžete použít obyčejný text.\nTento obsah je pouze ukázky, neváhejte ho smazat, abyste si udělali místo na poznámky.\n' exportData: 'Exportovat data',
exportDataExplanation: 'Export uložených připojení v Antaresu. Budete požádáni o zadání hesla pro zašifrování exportovaného souboru.',
importData: 'Importovat data',
importDataExplanation: 'Importuje soubor .antares obsahující připojení. Je třeba zadat heslo definované při exportu.',
includeConnectionPasswords: 'Včetně hesel připojení',
includeFolders: 'Včetně složek',
encryptionPassword: 'Heslo pro zašifrování souboru',
encryptionPasswordError: 'Heslo musí mít alespoň 8 znaků.',
ignoreDuplicates: 'Ignorovat duplicity',
wrongImportPassword: 'Chybné heslo pro import',
wrongFileFormat: 'Chybný formát souboru',
dataImportSuccess: 'Data úspěšně importována',
note: 'Poznámka',
thereAreNoNotesYet: 'Zatím tu nejsou žádné poznámky',
addNote: 'Přidat poznámku',
editNote: 'Upravit poznámku',
saveAsNote: 'Uložit jako poznámku',
showArchivedNotes: 'Zobrazit archivované poznámky',
hideArchivedNotes: 'Skrýt archivované poznámky',
tag: 'Tag', // Note tag
saveFile: 'Uložit soubor',
saveFileAs: 'Uložit do nového souboru',
openFile: 'Otevřít soubor',
openNotes: 'Otevřít poznámky',
debugConsole: 'Debug konzole', // <- console tab name
executedQueries: 'Log dotazů', // <- console tab name
sizeLimitError: 'Maximální velikost {size} překročena'
}, },
faker: { // Faker.js methods, used in random generated content faker: { // Faker.js methods, used in random generated content
address: 'Address', address: 'Address',

View File

@@ -15,7 +15,7 @@ export const nlNL = {
results: 'Resultaten', results: 'Resultaten',
size: 'Grootte', size: 'Grootte',
mimeType: 'Mime-Type', mimeType: 'Mime-Type',
download: 'Download', download: 'Download', // Same as English
add: 'Toevoegen', add: 'Toevoegen',
data: 'Data', data: 'Data',
properties: 'Eigenschappen', properties: 'Eigenschappen',
@@ -65,7 +65,13 @@ export const nlNL = {
outputFormat: 'Uitvoerformaat', outputFormat: 'Uitvoerformaat',
singleFile: 'Enkel {ext}-bestand', singleFile: 'Enkel {ext}-bestand',
zipCompressedFile: 'ZIP gecomprimeerd {ext}-bestand', zipCompressedFile: 'ZIP gecomprimeerd {ext}-bestand',
include: 'Inclusief' include: 'Inclusief',
search: 'Zoek',
copyName: 'Kopieer naam',
title: 'Titel',
archive: 'Archief',
undo: 'Ongedaan maken',
moveTo: 'Verplaats naar'
}, },
connection: { connection: {
connectionName: 'Naam verbinding', connectionName: 'Naam verbinding',
@@ -100,7 +106,10 @@ export const nlNL = {
readOnlyMode: 'Alleen lezen modus', readOnlyMode: 'Alleen lezen modus',
untrustedConnection: 'Niet vertrouwde verbinding', untrustedConnection: 'Niet vertrouwde verbinding',
allConnections: 'Alle verbindingen', allConnections: 'Alle verbindingen',
searchForConnections: 'Zoek naar verbindingen' searchForConnections: 'Zoek naar verbindingen',
singleConnection: 'Enkele verbinding',
connection: 'Verbinding',
keepAliveInterval: 'Keep alive interval'
}, },
database: { database: {
schema: 'Schema', schema: 'Schema',
@@ -260,7 +269,15 @@ export const nlNL = {
targetTable: 'Doeltabel', targetTable: 'Doeltabel',
switchDatabase: 'Wissel van database', switchDatabase: 'Wissel van database',
importQueryErrors: 'Waarschuwing: {n} fout is opgetreden | Waarschuwing: {n} fouten opgetreden', importQueryErrors: 'Waarschuwing: {n} fout is opgetreden | Waarschuwing: {n} fouten opgetreden',
executedQueries: '{n} query uitgevoerd | {n} queries uitgevoerd' executedQueries: '{n} query uitgevoerd | {n} queries uitgevoerd',
insert: 'Invoegen',
exportTable: 'Exporteer tabel',
savedQueries: 'Opgeslagen queries',
searchForElements: 'Zoek naar elementen',
searchForSchemas: 'Zoek naar schema\'s',
materializedview: 'Materialized view | Materialized views',
createNewMaterializedView: 'Materialized view maken',
newMaterializedView: 'Nieuwe materialized view'
}, },
application: { application: {
settings: 'Instellingen', settings: 'Instellingen',
@@ -367,7 +384,30 @@ export const nlNL = {
wrongFileFormat: 'Bestand is geen geldig .antares bestand', wrongFileFormat: 'Bestand is geen geldig .antares bestand',
required: 'Verplicht', required: 'Verplicht',
choseFile: 'Selecteer bestand', choseFile: 'Selecteer bestand',
password: 'Wachtwoord' password: 'Wachtwoord',
note: 'Notitie',
data: 'Data',
event: 'Event',
key: 'Key',
customIcon: 'Aangepast pictogram',
fileName: 'bestandsnaam',
newFolder: 'Nieuwe map',
outOfFolder: 'Out of folder',
dataImportSuccess: 'Data succesvol geïmporteerd',
thereAreNoNotesYet: 'Er zijn nog geen notities',
addNote: 'Voeg notitie toe',
editNote: 'Bewerk notitie',
saveAsNote: 'Sla op als notitie',
showArchivedNotes: 'Toon gearchiveerde notities',
hideArchivedNotes: 'Verberg gearchiveerde notities',
tag: 'Tag',
saveFile: 'Bestand opslaan',
saveFileAs: 'Bestand opslaan als',
openFile: 'Open bestand',
openNotes: 'Open notities',
debugConsole: 'Debug Console',
executedQueries: 'Voer queries uit',
sizeLimitError: 'Maximum grootte {size} overschreden'
}, },
faker: { faker: {
address: 'Adres', address: 'Adres',
@@ -434,7 +474,7 @@ export const nlNL = {
engine: 'Engine', engine: 'Engine',
past: 'Verleden', past: 'Verleden',
now: 'Nu', now: 'Nu',
future: 'Future', future: 'Toekomstig',
between: 'Between', between: 'Between',
recent: 'Recent', recent: 'Recent',
soon: 'Soon', soon: 'Soon',
@@ -447,11 +487,11 @@ export const nlNL = {
amount: 'Amount', amount: 'Amount',
transactionType: 'Transaction type', transactionType: 'Transaction type',
currencyCode: 'Currency code', currencyCode: 'Currency code',
currencyName: 'Currency name', currencyName: 'Valutanaam',
currencySymbol: 'Currency symbol', currencySymbol: 'Valutateken',
bitcoinAddress: 'Bitcoin address', bitcoinAddress: 'Bitcoin adres',
litecoinAddress: 'Litecoin address', litecoinAddress: 'Litecoin adres',
creditCardNumber: 'Credit card number', creditCardNumber: 'Credit card nummer',
creditCardCVV: 'Credit card CVV', creditCardCVV: 'Credit card CVV',
ethereumAddress: 'Ethereum adres', ethereumAddress: 'Ethereum adres',
iban: 'IBAN', iban: 'IBAN',
@@ -487,10 +527,10 @@ export const nlNL = {
sentence: 'Zin', sentence: 'Zin',
slug: 'Slug', slug: 'Slug',
sentences: 'Zinnen', sentences: 'Zinnen',
paragraph: 'Paragraph', paragraph: 'Paragraaf',
paragraphs: 'Paragraphs', paragraphs: 'Paragrafen',
text: 'Text', text: 'Tekst',
lines: 'Lines', lines: 'Regels',
genre: 'Genre', genre: 'Genre',
firstName: 'Voornaam', firstName: 'Voornaam',
lastName: 'Achternaam', lastName: 'Achternaam',
@@ -500,7 +540,7 @@ export const nlNL = {
gender: 'Gender', gender: 'Gender',
prefix: 'Prefix', prefix: 'Prefix',
suffix: 'Suffix', suffix: 'Suffix',
title: 'Title', title: 'Titel',
jobDescriptor: 'Job descriptor', jobDescriptor: 'Job descriptor',
jobArea: 'Job area', jobArea: 'Job area',
jobType: 'Job type', jobType: 'Job type',
@@ -514,12 +554,12 @@ export const nlNL = {
objectElement: 'Object element', objectElement: 'Object element',
uuid: 'Uuid', uuid: 'Uuid',
boolean: 'Boolean', boolean: 'Boolean',
image: 'Image', image: 'Afbeelding',
locale: 'Locale', locale: 'Locale',
alpha: 'Alpha', alpha: 'Alpha',
alphaNumeric: 'Alphanumeric', alphaNumeric: 'Alfanumeriek',
hexaDecimal: 'Hexadecimal', hexaDecimal: 'Hexadecimaal',
fileName: 'File name', fileName: 'Bestandsnaam',
commonFileName: 'Common file name', commonFileName: 'Common file name',
mimeType: 'Mime type', mimeType: 'Mime type',
commonFileType: 'Common file type', commonFileType: 'Common file type',
@@ -529,9 +569,9 @@ export const nlNL = {
directoryPath: 'Directory path', directoryPath: 'Directory path',
filePath: 'File path', filePath: 'File path',
semver: 'Semver', semver: 'Semver',
manufacturer: 'Manufacturer', manufacturer: 'Fabrikant',
model: 'Model', model: 'Model',
fuel: 'Fuel', fuel: 'Brandstof',
vin: 'Vin' vin: 'Vin'
} }
}; };

View File

@@ -15,6 +15,10 @@ export default class {
return ipcRenderer.invoke('connect', unproxify(newParams)); return ipcRenderer.invoke('connect', unproxify(newParams));
} }
static abortConnection (uid: string): void {
ipcRenderer.send('abort-connection', uid);
}
static checkConnection (uid: string): Promise<boolean> { static checkConnection (uid: string): Promise<boolean> {
return ipcRenderer.invoke('check-connection', uid); return ipcRenderer.invoke('check-connection', uid);
} }

View File

@@ -147,7 +147,7 @@ export const useWorkspacesStore = defineStore('workspaces', {
else else
this.selectedWorkspace = uid; this.selectedWorkspace = uid;
}, },
async connectWorkspace (connection: ConnectionParams & { pgConnString?: string }, mode?: string) { async connectWorkspace (connection: ConnectionParams & { pgConnString?: string }, args?: {mode?: string; signal?: AbortSignal}) {
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === connection.uid this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === connection.uid
? { ? {
...workspace, ...workspace,
@@ -155,14 +155,30 @@ export const useWorkspacesStore = defineStore('workspaces', {
breadcrumbs: {}, breadcrumbs: {},
loadedSchemas: new Set(), loadedSchemas: new Set(),
database: connection.database, database: connection.database,
connectionStatus: mode === 'switch' ? 'connected' : 'connecting' connectionStatus: args?.mode === 'switch' ? 'connected' : 'connecting'
} }
: workspace); : workspace);
const connectionsStore = useConnectionsStore(); const connectionsStore = useConnectionsStore();
const notificationsStore = useNotificationsStore(); const notificationsStore = useNotificationsStore();
const settingsStore = useSettingsStore(); const settingsStore = useSettingsStore();
return new Promise((resolve, reject) => {
const abortHandler = () => {
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === connection.uid
? {
...workspace,
structure: [],
breadcrumbs: {},
loadedSchemas: new Set(),
connectionStatus: 'disconnected'
}
: workspace);
return reject(new Error('Connection aborted by user'));
};
args?.signal?.addEventListener('abort', abortHandler);
(async () => {
try { try {
const { status, response } = await Connection.connect(connection); const { status, response } = await Connection.connect(connection);
@@ -177,7 +193,11 @@ export const useWorkspacesStore = defineStore('workspaces', {
connectionStatus: 'failed' connectionStatus: 'failed'
} }
: workspace); : workspace);
return reject(new Error(response));
} }
else if (status === 'abort')
return reject(new Error('Connection aborted by user'));
else { else {
let clientCustomizations: Customizations; let clientCustomizations: Customizations;
const { updateLastConnection } = connectionsStore; const { updateLastConnection } = connectionsStore;
@@ -252,15 +272,19 @@ export const useWorkspacesStore = defineStore('workspaces', {
} }
: workspace); : workspace);
args?.signal?.removeEventListener('abort', abortHandler);
this.refreshCollations(connection.uid); this.refreshCollations(connection.uid);
this.refreshVariables(connection.uid); this.refreshVariables(connection.uid);
this.refreshEngines(connection.uid); this.refreshEngines(connection.uid);
this.refreshUsers(connection.uid); this.refreshUsers(connection.uid);
resolve(true);
} }
} }
catch (err) { catch (err) {
notificationsStore.addNotification({ status: 'error', message: err.stack }); notificationsStore.addNotification({ status: 'error', message: err.stack });
} }
})();
});
}, },
async refreshStructure (uid: string) { async refreshStructure (uid: string) {
const notificationsStore = useNotificationsStore(); const notificationsStore = useNotificationsStore();
@@ -405,7 +429,7 @@ export const useWorkspacesStore = defineStore('workspaces', {
}, },
async switchConnection (connection: ConnectionParams & { pgConnString?: string }) { async switchConnection (connection: ConnectionParams & { pgConnString?: string }) {
await Connection.disconnect(connection.uid); await Connection.disconnect(connection.uid);
return this.connectWorkspace(connection, 'switch'); return this.connectWorkspace(connection, { mode: 'switch' });
}, },
addWorkspace (uid: string) { addWorkspace (uid: string) {
const workspace: Workspace = { const workspace: Workspace = {