Skip to content

Commit

Permalink
feat: refactor ssh connection flow #3
Browse files Browse the repository at this point in the history
Signed-off-by: seven <[email protected]>
  • Loading branch information
Blankll committed Mar 10, 2024
1 parent a30a3bf commit ccedc54
Show file tree
Hide file tree
Showing 19 changed files with 240 additions and 285 deletions.
1 change: 1 addition & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ declare module 'vue' {
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
NDropdown: typeof import('naive-ui')['NDropdown']
NFloatButton: typeof import('naive-ui')['NFloatButton']
NForm: typeof import('naive-ui')['NForm']
NFormItem: typeof import('naive-ui')['NFormItem']
NGi: typeof import('naive-ui')['NGi']
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"eslint-plugin-vue": "^9.20.1",
"husky": "^9.0.6",
"jest": "^29.7.0",
"naive-ui": "^2.37.3",
"naive-ui": "^2.38.1",
"prettier": "^3.2.4",
"sass": "^1.70.0",
"ts-jest": "^29.1.2",
Expand Down
4 changes: 4 additions & 0 deletions src/dataSource/clients/storeClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Store } from 'tauri-plugin-store-api';

export const secretClient = new Store('.secrets.st');
export const connectionClient = new Store('.connections.st');
30 changes: 30 additions & 0 deletions src/dataSource/connectionDataSource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { isTauri } from '../common';
import { connectionClient } from './clients/storeClient.ts';
import { Connection } from '../store';

const getConnections = async () => {
if (isTauri()) {
return connectionClient.values();
}
};
const saveConnection = async (connection: Connection) => {
if (isTauri()) {
await connectionClient.set(`${connection.id}`, connection);

await connectionClient.save();
}
};

const removeConnection = async ({ id }: Connection) => {
if (isTauri()) {
await connectionClient.delete(`${id}`);

await connectionClient.save();
}
};

export const loadConnectionDataSource = () => ({
getConnections,
saveConnection,
removeConnection,
});
2 changes: 2 additions & 0 deletions src/dataSource/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { loadSecretsDataSource } from './secretDataSource.ts';
export { loadConnectionDataSource } from './connectionDataSource.ts';
29 changes: 29 additions & 0 deletions src/dataSource/secretDataSource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Secret } from '../store';
import { isTauri } from '../common';
import { secretClient } from './clients/storeClient.ts';
const saveSecret = async (secret: Secret) => {
if (isTauri()) {
await secretClient.set(`${secret.id}`, secret);

await secretClient.save();
}
};
const removeSecret = async (secret: Secret) => {
if (isTauri()) {
await secretClient.delete(`${secret.id}`);

await secretClient.save();
}
};

const getSecrets = async () => {
if (isTauri()) {
return secretClient.values();
}
};

export const loadSecretsDataSource = () => ({
saveSecret,
removeSecret,
getSecrets,
});
2 changes: 2 additions & 0 deletions src/lang/enUS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const enUS = {
port: 'Port',
username: 'Username',
password: 'Password',
secret: 'Secret',
queryParameters: 'query parameters',
add: 'Add SSH',
edit: 'Edit SSH',
Expand All @@ -33,6 +34,7 @@ export const enUS = {
nameRequired: 'Name is required',
hostRequired: 'Host is required',
portRequired: 'Port is required',
secretRequired: 'Secret is required',
},
operations: {
connect: 'Connect',
Expand Down
2 changes: 2 additions & 0 deletions src/lang/zhCN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const zhCN = {
nameRequired: '请输入连接名称',
hostRequired: '请输入主机地址',
portRequired: '请输入端口号',
secretRequired: '请选择密钥',
},
operations: {
connect: '连接',
Expand Down Expand Up @@ -63,6 +64,7 @@ export const zhCN = {
pubKey: '公钥',
username: '用户名',
password: '密码',
secret: '密钥',
verify: '验证',
edit: '修改密钥',
formValidation: {
Expand Down
2 changes: 2 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
GiHouseKeys,
FaTerminal,
MdMorehoriz,
HiSolidPlus,
} from 'oh-vue-icons/icons';

const app = createApp(App);
Expand All @@ -41,6 +42,7 @@ addIcons(
GiHouseKeys,
FaTerminal,
MdMorehoriz,
HiSolidPlus,
);
app.component('VIcon', OhVueIcon);

Expand Down
27 changes: 0 additions & 27 deletions src/store/clients/secretClient.ts

This file was deleted.

64 changes: 18 additions & 46 deletions src/store/connectionStore.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { defineStore } from 'pinia';
import { loadHttpClient } from '../common/httpClient';
import { loadConnectionDataSource } from '../dataSource';
import { ulid } from 'ulidx';

export type Connection = {
id?: number;
id?: string;
name: string;
host: string;
port: number;
username?: string;
password?: string;
queryParameters?: string;
username: string;
secretId: number;
};
export type ConnectionIndex = {
health: string;
Expand All @@ -33,46 +34,43 @@ type Established =
| (Connection & { indices: Array<ConnectionIndex>; activeIndex?: ConnectionIndex })
| null;

const buildPath = (index: string | undefined, path: string | undefined) => {
return index &&
!['_nodes', '_cluster', '_cat', '_bulk', '_aliases', '_analyze'].includes(
path?.split('/')[0] ?? '',
)
? `/${index}/${path}`
: `/${path}`;
};
const connectionDataSource = loadConnectionDataSource();

export const useConnectionStore = defineStore('connectionStore', {
state(): {
state: (): {
connections: Connection[];
established: Established;
} {
} => {
return {
connections: [],
established: null,
};
},
persist: true,
getters: {
establishedIndexNames(state) {
return state.established?.indices.map(({ index }) => index) ?? [];
},
},
actions: {
async fetchConnections() {
this.connections = [];
const connections = (await connectionDataSource.getConnections()) || this.connections;
this.connections = connections as Connection[];
},
async testConnection(con: Connection) {
const client = loadHttpClient(con);

return await client.get(undefined, 'format=json');
},
saveConnection(connection: Connection) {
const index = this.connections.findIndex(item => item.id === connection.id);
if (index >= 0) {
this.connections[index] = connection;
async saveConnection(connection: Connection) {
if (!connection.id) {
connection.id = ulid();
this.connections.push(connection);
} else {
this.connections.push({ ...connection, id: this.connections.length + 1 });
const index = this.connections.findIndex(({ id }) => id === connection.id);
this.connections[index] = connection;
}
await connectionDataSource.saveConnection(connection);
},
removeConnection(connection: Connection) {
this.connections = this.connections.filter(item => item.id !== connection.id);
Expand All @@ -98,31 +96,5 @@ export const useConnectionStore = defineStore('connectionStore', {
activeIndex: this.established?.indices.find(({ index }) => index === indexName),
} as Established;
},
async searchQDSL({
method,
path,
index,
qdsl,
}: {
method: string;
path: string;
index?: string;
qdsl?: string;
}) {
if (!this.established) throw new Error('no connection established');
const client = loadHttpClient(this.established);

const reqPath = buildPath(index, path);
const body = qdsl ? JSON.parse(qdsl) : undefined;

const dispatch: { [method: string]: () => Promise<unknown> } = {
POST: async () => client.post(reqPath, undefined, body),
PUT: async () => client.put(reqPath, undefined, body),
DELETE: async () => client.delete(reqPath, undefined, body),
GET: async () =>
body ? client.post(reqPath, undefined, body) : client.get(reqPath, 'format=json'),
};
return dispatch[method]();
},
},
});
10 changes: 6 additions & 4 deletions src/store/secretStore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { defineStore } from 'pinia';
import { ulid } from 'ulidx';
import { secretClient } from './clients/secretClient.ts';
import { loadSecretsDataSource } from '../dataSource';

const secretDataSource = loadSecretsDataSource();
export enum SecretType {
SSH_KEY = 'SSH_KEY',
PASSWORD = 'PASSWORD',
Expand All @@ -26,7 +28,7 @@ export const useSecretStore = defineStore('secretStore', {
getters: {},
actions: {
async loadSecrets() {
const secrets = (await secretClient.getSecrets()) || this.secrets;
const secrets = (await secretDataSource.getSecrets()) || this.secrets;
this.secrets = secrets as Secret[];
},
async saveSecret(secret: Secret) {
Expand All @@ -37,12 +39,12 @@ export const useSecretStore = defineStore('secretStore', {
const index = this.secrets.findIndex(s => s.id === secret.id);
this.secrets[index] = secret;
}
await secretClient.saveSecret(secret);
await secretDataSource.saveSecret(secret);
},
async removeSecret(secret: Secret) {
const index = this.secrets.findIndex(s => s.id === secret.id);
this.secrets.splice(index, 1);
await secretClient.removeSecret(secret);
await secretDataSource.removeSecret(secret);
},
},
});
25 changes: 17 additions & 8 deletions src/views/ssh/components/ssh-dialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
</n-form-item>
</n-grid-item>
<n-grid-item span="8">
<n-form-item :label="$t('ssh.port')" path="port">
<n-select v-model:value="selectedSecret" :options="options" />
<n-form-item :label="$t('ssh.secret')" path="secret">
<n-select v-model:value="formData.secret" :options="options" />

Check failure on line 48 in src/views/ssh/components/ssh-dialog.vue

View workflow job for this annotation

GitHub Actions / pre-release (ubuntu-latest, 20.x)

Property 'secret' does not exist on type '{ id?: string | undefined; name: string; host: string; port: number; username: string; secretId: number; }'. Did you mean 'secretId'?
</n-form-item>
</n-grid-item>
</n-grid>
Expand Down Expand Up @@ -87,7 +87,7 @@ import { useLang } from '../../../lang';
import { FormValidationError } from 'naive-ui';
import { storeToRefs } from 'pinia';
const { testConnection, saveConnection } = useConnectionStore();
const { testConnection, saveConnection, fetchConnections } = useConnectionStore();
const lang = useLang();
// DOM
const connectFormRef = ref();
Expand All @@ -96,20 +96,20 @@ const { secrets } = storeToRefs(useSecretStore());
const options = computed(() => secrets.value.map(({ name, id }) => ({ label: name, value: id })));
const selectedSecret = ref('');
const showModal = ref(false);
const modalTitle = ref(lang.t('ssh.add'));
const testLoading = ref(false);
const saveLoading = ref(false);
const defaultFormData = {
name: '',
host: '',
port: 9200,
port: 22,
username: '',
password: '',
queryParameters: '',
secretId: -1,
};
const formData = ref<Connection>(defaultFormData);
const formData = ref<Connection>({ ...defaultFormData });
const formRules = reactive({
name: [
{
Expand All @@ -132,6 +132,13 @@ const formRules = reactive({
trigger: ['input', 'blur'],
},
],
secret: [
{
required: true,
renderMessage: () => lang.t('ssh.formValidation.secretRequired'),
trigger: ['input', 'blur'],
},
],
});
const message = useMessage();
Expand Down Expand Up @@ -188,6 +195,8 @@ const saveConnect = async (event: MouseEvent) => {
};
defineExpose({ showMedal });
fetchConnections();
</script>
<style lang="scss">
.add-connect-modal-card {
Expand Down
Loading

0 comments on commit ccedc54

Please sign in to comment.