-
-
-
-
-
-
{{ $t('connection.new') }}
-
-
+
-
+
+ {{ connection.name }}
+
+
+ {{ getDatabaseTypeLabel(connection.type) }}
+
+
+
+
+
+ {{ $t('connection.edit') }}
+
+
+ {{ $t('connection.delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ type.label }}
+
+
+
+
+
+
+
+
-
From 6ae15a1cc318cb04afcc9d621d1186b0f1674960 Mon Sep 17 00:00:00 2001
From: Fujun <1064980344@qq.com>
Date: Sun, 22 Dec 2024 15:45:34 +0800
Subject: [PATCH 07/19] feat: encapsulating logic in saveConnection and display
error message in ui
---
src/store/connectionStore.ts | 7 +++---
.../components/dynamodb-connect-dialog.vue | 22 +++++--------------
2 files changed, 9 insertions(+), 20 deletions(-)
diff --git a/src/store/connectionStore.ts b/src/store/connectionStore.ts
index c01739e..164815d 100644
--- a/src/store/connectionStore.ts
+++ b/src/store/connectionStore.ts
@@ -115,8 +115,7 @@ export const useConnectionStore = defineStore('connectionStore', {
return await client.get(con.indexName ?? undefined, 'format=json');
},
- async saveConnection(connection: Connection) {
- console.log('Saving connection:', connection);
+ async saveConnection(connection: Connection): Promise<{ success: boolean; message: string }> {
try {
const newConnection = {
...connection,
@@ -134,10 +133,10 @@ export const useConnectionStore = defineStore('connectionStore', {
}
await storeApi.set('connections', pureObject(this.connections));
- return newConnection;
+ return { success: true, message: 'Connection saved successfully' };
} catch (error) {
console.error('Error saving connection:', error);
- throw error;
+ return { success: false, message: error instanceof Error ? error.message : 'Unknown error' };
}
},
async removeConnection(connection: Connection) {
diff --git a/src/views/connect/components/dynamodb-connect-dialog.vue b/src/views/connect/components/dynamodb-connect-dialog.vue
index 2c0a0ec..534c41a 100644
--- a/src/views/connect/components/dynamodb-connect-dialog.vue
+++ b/src/views/connect/components/dynamodb-connect-dialog.vue
@@ -205,25 +205,15 @@ const testConnect = async () => {
};
const saveConnect = async () => {
- try {
- saveLoading.value = true;
- await connectionStore.saveConnection(formData.value);
+ saveLoading.value = true;
+ const result = await connectionStore.saveConnection(formData.value);
+ if (result.success) {
message.success(lang.t('connection.saveSuccess'));
closeModal();
- } catch (error) {
- if (!(error instanceof Error && error.message.includes('__TAURI_IPC__'))) {
- if (error instanceof Error) {
- message.error(error.message);
- } else {
- message.error(lang.t('connection.unknownError'));
- }
- } else {
- message.success(lang.t('connection.saveSuccess'));
- closeModal();
- }
- } finally {
- saveLoading.value = false;
+ } else {
+ message.error(result.message);
}
+ saveLoading.value = false;
};
defineExpose({ showMedal });
From 0806062ec5da7becf74941a8dc8b370e189d76b8 Mon Sep 17 00:00:00 2001
From: Fujun <1064980344@qq.com>
Date: Sun, 22 Dec 2024 17:25:53 +0800
Subject: [PATCH 08/19] feat: resolve type issue
---
components.d.ts | 5 +
src/common/constants.ts | 2 +-
src/store/backupRestoreStore.ts | 24 ++-
src/store/clusterManageStore.ts | 89 +++++++---
src/store/connectionStore.ts | 3 +
.../connect/components/connect-dialog.vue | 162 ++++++++++--------
6 files changed, 186 insertions(+), 99 deletions(-)
diff --git a/components.d.ts b/components.d.ts
index 66e8d53..13b1c93 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -17,9 +17,12 @@ declare module 'vue' {
NCollapse: typeof import('naive-ui')['NCollapse']
NCollapseItem: typeof import('naive-ui')['NCollapseItem']
NDataTable: typeof import('naive-ui')['NDataTable']
+ NDivider: typeof import('naive-ui')['NDivider']
NEmpty: typeof import('naive-ui')['NEmpty']
NForm: typeof import('naive-ui')['NForm']
NFormItem: typeof import('naive-ui')['NFormItem']
+ NFormItemRow: typeof import('naive-ui')['NFormItemRow']
+ NGi: typeof import('naive-ui')['NGi']
NGrid: typeof import('naive-ui')['NGrid']
NGridItem: typeof import('naive-ui')['NGridItem']
NIcon: typeof import('naive-ui')['NIcon']
@@ -33,6 +36,8 @@ declare module 'vue' {
NP: typeof import('naive-ui')['NP']
NPopover: typeof import('naive-ui')['NPopover']
NProgress: typeof import('naive-ui')['NProgress']
+ NRadio: typeof import('naive-ui')['NRadio']
+ NRadioGroup: typeof import('naive-ui')['NRadioGroup']
NScrollbar: typeof import('naive-ui')['NScrollbar']
NSelect: typeof import('naive-ui')['NSelect']
NSpace: typeof import('naive-ui')['NSpace']
diff --git a/src/common/constants.ts b/src/common/constants.ts
index f5cd8ac..a7a3898 100644
--- a/src/common/constants.ts
+++ b/src/common/constants.ts
@@ -4,7 +4,7 @@ export enum DatabaseType {
}
export interface BaseConnection {
- id?: string;
+ id?: number;
name: string;
type: DatabaseType;
}
diff --git a/src/store/backupRestoreStore.ts b/src/store/backupRestoreStore.ts
index f1ecc4f..68e16c3 100644
--- a/src/store/backupRestoreStore.ts
+++ b/src/store/backupRestoreStore.ts
@@ -3,7 +3,7 @@ import { open } from '@tauri-apps/api/dialog';
import { defineStore } from 'pinia';
import { CustomError } from '../common';
import { get } from 'lodash';
-import { Connection } from './connectionStore.ts';
+import { Connection, DatabaseType } from './connectionStore.ts';
import { loadHttpClient, sourceFileApi } from '../datasources';
export type BackupInput = {
@@ -80,7 +80,16 @@ export const useBackupRestoreStore = defineStore('backupRestoreStore', {
}
},
async backupToFile(input: BackupInput) {
- const client = loadHttpClient(input.connection);
+ let client;
+ if (input.connection.type === DatabaseType.ELASTICSEARCH) {
+ client = loadHttpClient({
+ host: input.connection.host,
+ port: input.connection.port,
+ sslCertVerification: input.connection.sslCertVerification,
+ });
+ } else {
+ throw new CustomError(400, 'Unsupported connection type');
+ }
const filePath = `${input.backupFolder}/${input.backupFileName}.${input.backupFileType}`;
let searchAfter: any[] | undefined = undefined;
let hasMore = true;
@@ -141,8 +150,17 @@ export const useBackupRestoreStore = defineStore('backupRestoreStore', {
}
},
async restoreFromFile(input: RestoreInput) {
+ let client;
+ if (input.connection.type === DatabaseType.ELASTICSEARCH) {
+ client = loadHttpClient({
+ host: input.connection.host,
+ port: input.connection.port,
+ sslCertVerification: input.connection.sslCertVerification,
+ });
+ } else {
+ throw new CustomError(400, 'Unsupported connection type');
+ }
const fileType = input.restoreFile.split('.').pop();
- const client = loadHttpClient(input.connection);
const bulkSize = 1000;
let data: string;
try {
diff --git a/src/store/clusterManageStore.ts b/src/store/clusterManageStore.ts
index 72a708f..5acb2ed 100644
--- a/src/store/clusterManageStore.ts
+++ b/src/store/clusterManageStore.ts
@@ -1,7 +1,7 @@
import { defineStore } from 'pinia';
import { loadHttpClient } from '../datasources';
import { lang } from '../lang';
-import { Connection, useConnectionStore } from './connectionStore.ts';
+import { Connection, DatabaseType, useConnectionStore } from './connectionStore.ts';
import { CustomError, optionalToNullableInt } from '../common';
export enum IndexHealth {
@@ -290,13 +290,18 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
async fetchCluster() {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
- const client = loadHttpClient(established as Connection);
- this.cluster = (await client.get('/_cluster/stats', 'format=json')) as RawClusterStats;
+ if (established.type === DatabaseType.ELASTICSEARCH) {
+ const client = loadHttpClient(established);
+ this.cluster = (await client.get('/_cluster/stats', 'format=json')) as RawClusterStats;
+ } else {
+ this.cluster = null;
+ }
},
async fetchNodes() {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
- const client = loadHttpClient(established as Connection);
+ if (established.type === DatabaseType.ELASTICSEARCH) {
+ const client = loadHttpClient(established);
try {
const data = await client.get('/_cat/nodes', 'format=json');
this.nodes = data
@@ -347,11 +352,14 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
)
.sort((a: SearchNode, b: SearchNode) => a.name.localeCompare(b.name));
} catch (err) {}
+ }
+ this.nodes = [];
},
async fetchNodeState(nodeName: string) {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
- const client = loadHttpClient(established as Connection);
+ if (established.type === DatabaseType.ELASTICSEARCH) {
+ const client = loadHttpClient(established);
const data = await client.get(
`/_cat/nodes`,
'format=json&bytes=b&h=ip,id,name,heap.percent,heap.current,heap.max,ram.percent,ram.current,ram.max,node.role,master,cpu,load_1m,load_5m,load_15m,disk.used_percent,disk.used,disk.total,shard_stats.total_count,mappings.total_count&full_id=true',
@@ -402,11 +410,15 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
},
}))
.find(({ name }) => name === nodeName);
+ } else {
+ this.nodes = [];
+ }
},
async fetchShards(includeHidden: boolean = false) {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
- const client = loadHttpClient(established as Connection);
+ if (established.type === DatabaseType.ELASTICSEARCH) {
+ const client = loadHttpClient(established);
try {
const data = (
await client.get(
@@ -419,11 +431,14 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
? data
: data.filter((shard: Shard) => !shard.index.startsWith('.'));
} catch (err) {}
- },
+ }
+ this.shards = [];
+ },
async getShardState(indexName: string) {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
- const client = loadHttpClient(established as Connection);
+ if (established.type === DatabaseType.ELASTICSEARCH) {
+ const client = loadHttpClient(established);
try {
const data = await client.get(
`/_cat/shards/${indexName}`,
@@ -600,10 +615,12 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
);
return { index: indexName, shards: result };
} catch (err) {}
- },
+ }
+ },
async fetchIndices() {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
+ if (established.type === DatabaseType.ELASTICSEARCH) {
const client = loadHttpClient(established);
const data = (await client.get('/_cat/indices', 'format=json&s=index')) as Array<{
[key: string]: string;
@@ -624,10 +641,13 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
deleted: parseInt(index['docs.deleted'], 10),
},
}));
- },
+ }
+ this.indices = [];
+ },
async fetchAliases() {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
+ if (established.type === DatabaseType.ELASTICSEARCH) {
const client = loadHttpClient(established);
const data = (await client.get('/_cat/aliases', 'format=json&s=alias')) as Array<{
[key: string]: string;
@@ -642,10 +662,13 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
},
isWriteIndex: alias['is_write_index'] === 'true',
}));
- },
+ }
+ this.aliases = [];
+ },
async fetchTemplates() {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
+ if (established.type === DatabaseType.ELASTICSEARCH) {
const client = loadHttpClient(established);
const fetchIndexTemplates = async () => {
const data = (await client.get('/_cat/templates', 'format=json')) as Array<{
@@ -683,7 +706,9 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
]);
this.templates = [...indexTemplates, ...componentTemplates];
- },
+ }
+ this.templates = [];
+ },
async createIndex({
indexName,
shards,
@@ -703,6 +728,7 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
}) {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
+ if (established.type === DatabaseType.ELASTICSEARCH) {
const client = loadHttpClient(established);
const queryParams = new URLSearchParams();
@@ -752,7 +778,9 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
err instanceof CustomError ? err.details : (err as Error).message,
);
}
- },
+ }
+ return undefined;
+ },
async createAlias({
aliasName,
indexName,
@@ -776,6 +804,7 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
}) {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
+ if (established.type === DatabaseType.ELASTICSEARCH) {
const client = loadHttpClient(established);
const queryParams = new URLSearchParams();
@@ -826,7 +855,9 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
}
// refresh data
Promise.all([this.fetchIndices(), this.fetchAliases()]).catch();
- },
+ }
+ return undefined;
+ },
async createTemplate({
name,
type,
@@ -842,6 +873,7 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
}) {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
+ if (established.type === DatabaseType.ELASTICSEARCH) {
const client = loadHttpClient(established);
const queryParams = new URLSearchParams();
[
@@ -874,12 +906,15 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
err instanceof CustomError ? err.details : (err as Error).message,
);
}
- },
+ }
+ return undefined;
+ },
async deleteIndex(indexName: string) {
// delete index
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
+ if (established.type === DatabaseType.ELASTICSEARCH) {
const client = loadHttpClient(established);
try {
const response = await client.delete(`/${indexName}`);
@@ -895,10 +930,13 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
err instanceof CustomError ? err.details : (err as Error).message,
);
}
- },
+ }
+ return undefined;
+ },
async closeIndex(indexName: string) {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
+ if (established.type === DatabaseType.ELASTICSEARCH) {
const client = loadHttpClient(established);
try {
const response = await client.post(`/${indexName}/_close`);
@@ -914,10 +952,13 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
err instanceof CustomError ? err.details : (err as Error).message,
);
}
- },
+ }
+ return undefined;
+ },
async openIndex(indexName: string) {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
+ if (established.type === DatabaseType.ELASTICSEARCH) {
const client = loadHttpClient(established);
try {
const response = await client.post(`/${indexName}/_open`);
@@ -933,10 +974,13 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
err instanceof CustomError ? err.details : (err as Error).message,
);
}
- },
+ }
+ return undefined;
+ },
async removeAlias(indexName: string, aliasName: string) {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
+ if (established.type === DatabaseType.ELASTICSEARCH) {
const client = loadHttpClient(established);
try {
const response = await client.delete(`/${indexName}/_alias/${aliasName}`);
@@ -952,10 +996,13 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
err instanceof CustomError ? err.details : (err as Error).message,
);
}
- },
+ }
+ return undefined;;
+ },
async switchAlias(aliasName: string, sourceIndexName: string, targetIndexName: string) {
const { established } = useConnectionStore();
if (!established) throw new Error(lang.global.t('connection.selectConnection'));
+ if (established.type === DatabaseType.ELASTICSEARCH) {
const client = loadHttpClient(established);
const payload = {
actions: [
@@ -987,6 +1034,8 @@ export const useClusterManageStore = defineStore('clusterManageStore', {
err instanceof CustomError ? err.details : (err as Error).message,
);
}
- },
+ }
+ return undefined;
+},
},
});
diff --git a/src/store/connectionStore.ts b/src/store/connectionStore.ts
index 164815d..460fc62 100644
--- a/src/store/connectionStore.ts
+++ b/src/store/connectionStore.ts
@@ -111,6 +111,9 @@ export const useConnectionStore = defineStore('connectionStore', {
}
},
async testElasticsearchConnection(con: ElasticsearchConnection) {
+ if (con.type !== DatabaseType.ELASTICSEARCH) {
+ throw new Error('Unsupported connection type');
+ }
const client = loadHttpClient(con);
return await client.get(con.indexName ?? undefined, 'format=json');
diff --git a/src/views/connect/components/connect-dialog.vue b/src/views/connect/components/connect-dialog.vue
index 9e6455a..3ac35f0 100644
--- a/src/views/connect/components/connect-dialog.vue
+++ b/src/views/connect/components/connect-dialog.vue
@@ -33,52 +33,73 @@
/>
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('connection.sslCertVerification') }}
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
- {{ $t('connection.sslCertVerification') }}
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
@@ -155,11 +157,11 @@
import { reactive, ref, watch } from 'vue';
import { Close, Locked, Unlocked } from '@vicons/carbon';
import { CustomError, inputProps } from '../../../common';
-import { Connection, useConnectionStore } from '../../../store';
+import { Connection, DatabaseType, ElasticsearchConnection, useConnectionStore } from '../../../store';
import { useLang } from '../../../lang';
import { FormItemRule, FormRules, FormValidationError } from 'naive-ui';
-const { testConnection, saveConnection } = useConnectionStore();
+const { testElasticsearchConnection,testDynamoDBConnection, saveConnection } = useConnectionStore();
const lang = useLang();
// DOM
const connectFormRef = ref();
@@ -178,6 +180,7 @@ const defaultFormData = {
indexName: undefined,
queryParameters: '',
sslCertVerification: true,
+ type: DatabaseType.ELASTICSEARCH as const,
};
const formData = ref