mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
4adbc575c2 | |||
eb706c3e51 | |||
971df3a989 | |||
3129bf4baa | |||
c6d67cef01 | |||
1d7053ce03 | |||
41e797f9e2 | |||
704f70819b | |||
49a3589536 |
24
CHANGELOG.md
24
CHANGELOG.md
@@ -2,6 +2,30 @@
|
||||
|
||||
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.34](https://github.com/antares-sql/antares/compare/v0.7.33...v0.7.34) (2025-02-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* issue with some SSH connections, definitely ([eb706c3](https://github.com/antares-sql/antares/commit/eb706c3e51e9cb7577febd291a33594c0650a34a))
|
||||
|
||||
### [0.7.33](https://github.com/antares-sql/antares/compare/v0.7.32...v0.7.33) (2025-02-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* issue with some SSH connections, fixes [#947](https://github.com/antares-sql/antares/issues/947) ([3129bf4](https://github.com/antares-sql/antares/commit/3129bf4baa5e72b1d79df986605fd5fad1dce291))
|
||||
|
||||
### [0.7.32](https://github.com/antares-sql/antares/compare/v0.7.31...v0.7.32) (2025-02-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* black background with light theme, fixes [#945](https://github.com/antares-sql/antares/issues/945) ([1d7053c](https://github.com/antares-sql/antares/commit/1d7053ce032efec8377d9500f2e24618f6381ab4))
|
||||
* enhance SVG support in connection customization, fixes [#939](https://github.com/antares-sql/antares/issues/939) ([49a3589](https://github.com/antares-sql/antares/commit/49a3589536d2e75a14125be7b874e29b60fb56c4))
|
||||
* improve error handling in SSH connection ([704f708](https://github.com/antares-sql/antares/commit/704f70819b21a42194d8f68cf9b58ba337f1ada7))
|
||||
* **PostgreSQL:** error with materialized view tabs ([41e797f](https://github.com/antares-sql/antares/commit/41e797f9e27db66370d3ae7750c057f708af76f9))
|
||||
|
||||
### [0.7.31](https://github.com/antares-sql/antares/compare/v0.7.31-beta.5...v0.7.31) (2025-02-11)
|
||||
|
||||
### [0.7.31-beta.5](https://github.com/antares-sql/antares/compare/v0.7.31-beta.4...v0.7.31-beta.5) (2025-02-09)
|
||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "antares",
|
||||
"version": "0.7.31",
|
||||
"version": "0.7.34",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "antares",
|
||||
"version": "0.7.31",
|
||||
"version": "0.7.34",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "antares",
|
||||
"productName": "Antares",
|
||||
"version": "0.7.31",
|
||||
"version": "0.7.34",
|
||||
"description": "A modern, fast and productivity driven SQL client with a focus in UX.",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/antares-sql/antares.git",
|
||||
|
@@ -64,9 +64,9 @@ export default (connections: Record<string, antares.Client>) => {
|
||||
username: conn.sshUser,
|
||||
password: conn.sshPass,
|
||||
port: conn.sshPort ? conn.sshPort : 22,
|
||||
privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : null,
|
||||
privateKey: conn.sshKey ? fs.readFileSync(conn.sshKey).toString() : undefined,
|
||||
passphrase: conn.sshPassphrase,
|
||||
keepaliveInterval: conn.sshKeepAliveInterval ? conn.sshKeepAliveInterval*1000 : null
|
||||
keepaliveInterval: conn.sshKeepAliveInterval ? conn.sshKeepAliveInterval*1000 : undefined
|
||||
};
|
||||
}
|
||||
|
||||
@@ -90,11 +90,12 @@ export default (connections: Record<string, antares.Client>) => {
|
||||
|
||||
return { status: 'success' };
|
||||
}
|
||||
catch (err) {
|
||||
catch (error) {
|
||||
clearInterval(abortChecker);
|
||||
|
||||
if (!isLocalAborted)
|
||||
return { status: 'error', response: err.toString() };
|
||||
if (error instanceof AggregateError)
|
||||
throw new Error(error.errors.reduce((acc, curr) => acc +' | '+ curr.message, ''));
|
||||
else if (!isLocalAborted)
|
||||
return { status: 'error', response: error.toString() };
|
||||
else
|
||||
return { status: 'abort', response: 'Connection aborted' };
|
||||
}
|
||||
|
@@ -173,13 +173,13 @@ export class MySQLClient extends BaseClient {
|
||||
remotePort: this._params.port
|
||||
});
|
||||
|
||||
dbConfig.host = (this._ssh.config as SSHConfig[] & { host: string }).host;
|
||||
dbConfig.host = undefined;
|
||||
dbConfig.port = tunnel.localPort;
|
||||
}
|
||||
catch (err) {
|
||||
if (this._ssh) {
|
||||
this._ssh.close();
|
||||
this._ssh.closeTunnel();
|
||||
this._ssh.close();
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
@@ -227,8 +227,8 @@ export class MySQLClient extends BaseClient {
|
||||
clearInterval(this._keepaliveTimer);
|
||||
this._keepaliveTimer = undefined;
|
||||
if (this._ssh) {
|
||||
this._ssh.close();
|
||||
this._ssh.closeTunnel();
|
||||
this._ssh.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,6 +302,8 @@ export class MySQLClient extends BaseClient {
|
||||
await this.connect();
|
||||
return this.getConnection(args, true);
|
||||
}
|
||||
else if (error instanceof AggregateError)
|
||||
throw new Error(error.errors.reduce((acc, curr) => acc +' | '+ curr.message, ''));
|
||||
else
|
||||
throw new Error(error.message);
|
||||
}
|
||||
|
@@ -179,7 +179,7 @@ export class PostgreSQLClient extends BaseClient {
|
||||
remotePort: this._params.port
|
||||
});
|
||||
|
||||
dbConfig.host = (this._ssh.config as SSHConfig[] & { host: string }).host;
|
||||
dbConfig.host = undefined;
|
||||
dbConfig.port = tunnel.localPort;
|
||||
}
|
||||
catch (err) {
|
||||
@@ -348,7 +348,7 @@ export class PostgreSQLClient extends BaseClient {
|
||||
matviewowner AS owner,
|
||||
ispopulated AS is_populated,
|
||||
definition,
|
||||
'materializedview' AS table_type
|
||||
'materializedView' AS table_type
|
||||
FROM pg_matviews
|
||||
WHERE schemaname = '${db.database}'
|
||||
ORDER BY schema_name,
|
||||
@@ -408,8 +408,8 @@ export class PostgreSQLClient extends BaseClient {
|
||||
name: table.table_name,
|
||||
type: table.table_type === 'VIEW'
|
||||
? 'view'
|
||||
: table.table_type === 'materializedview'
|
||||
? 'materializedview'
|
||||
: table.table_type === 'materializedView'
|
||||
? 'materializedView'
|
||||
: 'table',
|
||||
rows: table.reltuples,
|
||||
size: tableSize,
|
||||
|
@@ -132,11 +132,21 @@ app.on('ready', async () => {
|
||||
// mainWindow.webContents.openDevTools();
|
||||
|
||||
process.on('uncaughtException', error => {
|
||||
mainWindow.webContents.send('unhandled-exception', error);
|
||||
if (error instanceof AggregateError) {
|
||||
for (const e of error.errors)
|
||||
mainWindow.webContents.send('unhandled-exception', e);
|
||||
}
|
||||
else
|
||||
mainWindow.webContents.send('unhandled-exception', error);
|
||||
});
|
||||
|
||||
process.on('unhandledRejection', error => {
|
||||
mainWindow.webContents.send('unhandled-exception', error);
|
||||
if (error instanceof AggregateError) {
|
||||
for (const e of error.errors)
|
||||
mainWindow.webContents.send('unhandled-exception', e);
|
||||
}
|
||||
else
|
||||
mainWindow.webContents.send('unhandled-exception', error);
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -39,11 +39,11 @@ const props = defineProps({
|
||||
default: () => 'mdi'
|
||||
},
|
||||
flip: {
|
||||
type: String as PropType<'horizontal' | 'vertical' | 'both'>,
|
||||
type: String as PropType<'horizontal' | 'vertical' | 'both' | null>,
|
||||
default: () => null
|
||||
},
|
||||
rotate: {
|
||||
type: Number,
|
||||
type: Number as PropType<number | null>,
|
||||
default: () => null
|
||||
}
|
||||
});
|
||||
@@ -55,8 +55,7 @@ const iconPath = computed(() => {
|
||||
const base64 = getIconByUid(props.iconName)?.base64;
|
||||
const svgString = Buffer
|
||||
.from(base64, 'base64')
|
||||
.toString('utf-8')
|
||||
.replaceAll(/width="[^"]*"|height="[^"]*"/g, '');
|
||||
.toString('utf-8');
|
||||
|
||||
return svgString;
|
||||
}
|
||||
|
@@ -131,8 +131,10 @@ import Application from '@/ipc-api/Application';
|
||||
import { camelize } from '@/libs/camelize';
|
||||
import { unproxify } from '@/libs/unproxify';
|
||||
import { SidebarElement, useConnectionsStore } from '@/stores/connections';
|
||||
import { useNotificationsStore } from '@/stores/notifications';
|
||||
|
||||
const connectionsStore = useConnectionsStore();
|
||||
const { addNotification } = useNotificationsStore();
|
||||
|
||||
const { addIcon, removeIcon, updateConnectionOrder, getConnectionName } = connectionsStore;
|
||||
const { customIcons } = storeToRefs(connectionsStore);
|
||||
@@ -225,12 +227,56 @@ const removeIconHandler = () => {
|
||||
isContext.value = false;
|
||||
};
|
||||
|
||||
const adjustSVGContent = (svgContent: string) => {
|
||||
try {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(svgContent, 'image/svg+xml');
|
||||
|
||||
const parseError = doc.querySelector('parsererror');
|
||||
if (parseError) {
|
||||
addNotification({ status: 'error', message: parseError.textContent });
|
||||
return null;
|
||||
}
|
||||
|
||||
const svg = doc.documentElement;
|
||||
if (svg.tagName.toLowerCase() !== 'svg') {
|
||||
addNotification({ status: 'error', message: t('application.invalidFIle') });
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!svg.hasAttribute('viewBox')) {
|
||||
const width = svg.getAttribute('width') || '36';
|
||||
const height = svg.getAttribute('height') || '36';
|
||||
svg.setAttribute('viewBox', `0 0 ${width} ${height}`);
|
||||
}
|
||||
|
||||
svg.removeAttribute('width');
|
||||
svg.removeAttribute('height');
|
||||
|
||||
const serializer = new XMLSerializer();
|
||||
return serializer.serializeToString(svg);
|
||||
}
|
||||
catch (error) {
|
||||
addNotification({ status: 'error', message: error.stack });
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const openFile = async () => {
|
||||
const result = await Application.showOpenDialog({ properties: ['openFile'], filters: [{ name: '"SVG"', extensions: ['svg'] }] });
|
||||
const result = await Application.showOpenDialog({
|
||||
properties: ['openFile'],
|
||||
filters: [{ name: '"SVG"', extensions: ['svg'] }]
|
||||
});
|
||||
|
||||
if (result && !result.canceled) {
|
||||
const file = result.filePaths[0];
|
||||
const content = await Application.readFile({ filePath: file, encoding: 'base64url' });
|
||||
addIcon(content);
|
||||
let content = await Application.readFile({ filePath: file, encoding: 'utf-8' });
|
||||
|
||||
content = adjustSVGContent(content);
|
||||
|
||||
const base64Content = Buffer.from(content).toString('base64');
|
||||
|
||||
addIcon(base64Content);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -64,7 +64,7 @@
|
||||
>
|
||||
<BaseIcon
|
||||
class="mt-1 mr-1"
|
||||
:icon-name="['view', 'materializedview'].includes(element.elementType) ? 'mdiTableEye' : 'mdiTable'"
|
||||
:icon-name="['view', 'materializedView'].includes(element.elementType) ? 'mdiTableEye' : 'mdiTable'"
|
||||
:size="18"
|
||||
/>
|
||||
<span :title="`${t('general.data').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
|
||||
@@ -81,7 +81,7 @@
|
||||
<a v-else-if="element.type === 'data'" class="tab-link">
|
||||
<BaseIcon
|
||||
class="mt-1 mr-1"
|
||||
:icon-name="['view', 'materializedview'].includes(element.elementType) ? 'mdiTableEye' : 'mdiTable'"
|
||||
:icon-name="['view', 'materializedView'].includes(element.elementType) ? 'mdiTableEye' : 'mdiTable'"
|
||||
:size="18"
|
||||
/>
|
||||
<span :title="`${t('general.data').toUpperCase()}: ${t(`database.${element.elementType}`)}`">
|
||||
|
@@ -143,7 +143,7 @@
|
||||
:selected-schema="selectedSchema"
|
||||
:context-event="miscContextEvent"
|
||||
@open-create-view-tab="openCreateElementTab('view')"
|
||||
@open-create-materializedview-tab="openCreateElementTab('materialized-view')"
|
||||
@open-create-materializedView-tab="openCreateElementTab('materialized-view')"
|
||||
@open-create-trigger-tab="openCreateElementTab('trigger')"
|
||||
@open-create-trigger-function-tab="openCreateElementTab('trigger-function')"
|
||||
@open-create-routine-tab="openCreateElementTab('routine')"
|
||||
|
@@ -16,9 +16,9 @@
|
||||
/> {{ t('database.createNewView') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="props.selectedMisc === 'materializedview'"
|
||||
v-if="props.selectedMisc === 'materializedView'"
|
||||
class="context-element"
|
||||
@click="emit('open-create-materializedview-tab')"
|
||||
@click="emit('open-create-materializedView-tab')"
|
||||
>
|
||||
<span class="d-flex">
|
||||
<BaseIcon
|
||||
@@ -106,7 +106,7 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits([
|
||||
'open-create-view-tab',
|
||||
'open-create-materializedview-tab',
|
||||
'open-create-materializedView-tab',
|
||||
'open-create-trigger-tab',
|
||||
'open-create-routine-tab',
|
||||
'open-create-function-tab',
|
||||
|
@@ -121,7 +121,7 @@
|
||||
<summary
|
||||
class="accordion-header misc-name"
|
||||
:class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.trigger}"
|
||||
@contextmenu.prevent="showMiscFolderContext($event, 'materializedview')"
|
||||
@contextmenu.prevent="showMiscFolderContext($event, 'materializedView')"
|
||||
>
|
||||
<BaseIcon
|
||||
class="misc-icon mr-1"
|
||||
@@ -133,7 +133,7 @@
|
||||
icon-name="mdiFolderOpen"
|
||||
:size="18"
|
||||
/>
|
||||
{{ t('database.materializedview', 2) }}
|
||||
{{ t('database.materializedView', 2) }}
|
||||
</summary>
|
||||
<div class="accordion-body">
|
||||
<div>
|
||||
@@ -496,9 +496,9 @@ const filteredViews = computed(() => {
|
||||
|
||||
const filteredMatViews = computed(() => {
|
||||
if (props.searchMethod === 'elements')
|
||||
return props.database.tables.filter(table => table.name.search(searchTerm.value) >= 0 && table.type === 'materializedview');
|
||||
return props.database.tables.filter(table => table.name.search(searchTerm.value) >= 0 && table.type === 'materializedView');
|
||||
else
|
||||
return props.database.tables.filter(table => table.type === 'materializedview');
|
||||
return props.database.tables.filter(table => table.type === 'materializedView');
|
||||
});
|
||||
|
||||
const filteredTriggers = computed(() => {
|
||||
|
@@ -50,7 +50,7 @@
|
||||
class="text-light mt-1 mr-1"
|
||||
icon-name="mdiTableEye"
|
||||
:size="18"
|
||||
/> {{ t('database.materializedview') }}</span>
|
||||
/> {{ t('database.materializedView') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="workspace.customizations.triggerAdd"
|
||||
|
@@ -48,7 +48,7 @@
|
||||
/> {{ t('application.settings') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedTable && selectedTable.type === 'materializedview' && customizations.materializedViewSettings"
|
||||
v-if="selectedTable && selectedTable.type === 'materializedView' && customizations.materializedViewSettings"
|
||||
class="context-element"
|
||||
@click="openMaterializedViewSettingTab"
|
||||
>
|
||||
|
@@ -195,7 +195,7 @@ const saveChanges = async () => {
|
||||
uid: props.connection.uid,
|
||||
schema: props.schema,
|
||||
elementName: localView.value.name,
|
||||
elementType: 'materializedview',
|
||||
elementType: 'materializedView',
|
||||
type: 'materialized-view-props'
|
||||
});
|
||||
|
||||
|
@@ -227,7 +227,7 @@ const saveChanges = async () => {
|
||||
schema: props.schema,
|
||||
elementName: oldName,
|
||||
elementNewName: localView.value.name,
|
||||
elementType: 'materializedview'
|
||||
elementType: 'materializedView'
|
||||
});
|
||||
|
||||
changeBreadcrumbs({ schema: props.schema, view: localView.value.name });
|
||||
|
@@ -141,7 +141,7 @@ export const csCZ = {
|
||||
total: 'Celkem',
|
||||
table: 'Tabulka | Tabulky',
|
||||
view: 'Pohled | Pohledy',
|
||||
materializedview: 'Materializovaný pohled',
|
||||
materializedView: 'Materializovaný pohled',
|
||||
definer: 'Definér',
|
||||
algorithm: 'Algoritmus',
|
||||
trigger: 'Trigger | Triggery',
|
||||
|
@@ -141,7 +141,7 @@ export const enUS = {
|
||||
total: 'Total',
|
||||
table: 'Table | Tables',
|
||||
view: 'View | Views',
|
||||
materializedview: 'Materialized view | Materialized views',
|
||||
materializedView: 'Materialized view | Materialized views',
|
||||
definer: 'Definer',
|
||||
algorithm: 'Algorithm',
|
||||
trigger: 'Trigger | Triggers',
|
||||
@@ -401,6 +401,7 @@ export const enUS = {
|
||||
ignoreDuplicates: 'Ignore duplicates',
|
||||
wrongImportPassword: 'Wrong import password',
|
||||
wrongFileFormat: 'Wrong file format',
|
||||
invalidFile: 'Invalid file',
|
||||
dataImportSuccess: 'Data successfully imported',
|
||||
note: 'Note | Notes',
|
||||
thereAreNoNotesYet: 'There are no notes yet',
|
||||
|
@@ -141,7 +141,7 @@ export const esES = {
|
||||
total: 'Total',
|
||||
table: 'Tabla | Tablas',
|
||||
view: 'Vista | Vistas',
|
||||
materializedview: 'Vista Materializada | Vistas Materializadas',
|
||||
materializedView: 'Vista Materializada | Vistas Materializadas',
|
||||
definer: 'Definidor',
|
||||
algorithm: 'Algoritmo',
|
||||
trigger: 'Disparador | Disparadores',
|
||||
|
@@ -140,7 +140,7 @@ export const heIL = {
|
||||
total: 'סך הכל',
|
||||
table: 'טבלה | טבלאות',
|
||||
view: 'תצוגה | תצוגות',
|
||||
materializedview: 'תצוגה ממומשת | תצוגות ממומשות',
|
||||
materializedView: 'תצוגה ממומשת | תצוגות ממומשות',
|
||||
definer: 'מגדיר',
|
||||
algorithm: 'אלגוריתם',
|
||||
trigger: 'טריגר | טריגרים',
|
||||
|
@@ -275,7 +275,7 @@ export const nlNL = {
|
||||
savedQueries: 'Opgeslagen queries',
|
||||
searchForElements: 'Zoek naar elementen',
|
||||
searchForSchemas: 'Zoek naar schema\'s',
|
||||
materializedview: 'Materialized view | Materialized views',
|
||||
materializedView: 'Materialized view | Materialized views',
|
||||
createNewMaterializedView: 'Materialized view maken',
|
||||
newMaterializedView: 'Nieuwe materialized view'
|
||||
},
|
||||
|
@@ -270,7 +270,7 @@ export const ruRU = {
|
||||
importQueryErrors: 'Внимание: {n} ошибка возникла | Внимание: {n} ошибок произошло',
|
||||
executedQueries: '{n} запрос выполнен | {n} запросов выполнено',
|
||||
insert: 'Вставить',
|
||||
materializedview: 'Материализованное представление | Материализованные представления',
|
||||
materializedView: 'Материализованное представление | Материализованные представления',
|
||||
exportTable: 'Экспорт таблицы',
|
||||
createNewMaterializedView: 'Создать новое материализованное представление',
|
||||
newMaterializedView: 'Новое материализованное представление',
|
||||
|
@@ -270,7 +270,7 @@ export const uzUZ = {
|
||||
importQueryErrors: 'Diqqat: {n} xato yuz berdi | Diqqat: {n} xatolar yuz berdi',
|
||||
executedQueries: '{n} soʻrov bajarildi | {n} soʻrovlar bajarildi',
|
||||
insert: 'Kiritish',
|
||||
materializedview: 'Materializatsiya qilingan ko‘rinish | Materializatsiya qilingan ko‘rinishlar',
|
||||
materializedView: 'Materializatsiya qilingan ko‘rinish | Materializatsiya qilingan ko‘rinishlar',
|
||||
exportTable: 'Jadvalni eksport qilish',
|
||||
createNewMaterializedView: 'Yangi materializatsiya qilingan ko‘rinish yaratish',
|
||||
newMaterializedView: 'Yangi materializatsiya qilingan ko‘rinish',
|
||||
|
@@ -132,7 +132,7 @@ export const zhCN = {
|
||||
total: '总计',
|
||||
table: '表 | 表',
|
||||
view: '视图 | 视图',
|
||||
materializedview: '实体化视图 | 实体化视图',
|
||||
materializedView: '实体化视图 | 实体化视图',
|
||||
definer: '定义者',
|
||||
algorithm: '算法',
|
||||
trigger: '触发器 | 触发器',
|
||||
|
@@ -1,5 +1,7 @@
|
||||
/* stylelint-disable function-no-unknown */
|
||||
.theme-light {
|
||||
background: $body-bg;
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #fff;
|
||||
}
|
||||
|
Reference in New Issue
Block a user