diff --git a/extensions/vscode/src/types/messages/webviewToHostMessages.ts b/extensions/vscode/src/types/messages/webviewToHostMessages.ts index cc1cf5835..798bd5793 100644 --- a/extensions/vscode/src/types/messages/webviewToHostMessages.ts +++ b/extensions/vscode/src/types/messages/webviewToHostMessages.ts @@ -16,6 +16,7 @@ export enum WebviewToHostMessageType { REQUEST_FILES_LISTS = "requestFilesLists", REQUEST_CREDENTIALS = "requestCredentials", VSCODE_OPEN_RELATIVE = "VSCodeOpenRelativeMsg", + ADD_SECRET = "addSecret", REFRESH_PYTHON_PACKAGES = "RefreshPythonPackagesMsg", SCAN_PYTHON_PACKAGE_REQUIREMENTS = "ScanPythonPackageRequirementsMsg", REFRESH_R_PACKAGES = "RefreshRPackagesMsg", @@ -50,6 +51,7 @@ export type WebviewToHostMessage = | ExcludeFileMsg | RequestFilesListsMsg | RequestCredentialsMsg + | AddSecretMsg | RefreshPythonPackagesMsg | VSCodeOpenRelativeMsg | ScanPythonPackageRequirementsMsg @@ -75,6 +77,7 @@ export function isWebviewToHostMessage(msg: any): msg is WebviewToHostMessage { msg.kind === WebviewToHostMessageType.EXCLUDE_FILE || msg.kind === WebviewToHostMessageType.REQUEST_FILES_LISTS || msg.kind === WebviewToHostMessageType.REQUEST_CREDENTIALS || + msg.kind === WebviewToHostMessageType.ADD_SECRET || msg.kind === WebviewToHostMessageType.REFRESH_PYTHON_PACKAGES || msg.kind === WebviewToHostMessageType.VSCODE_OPEN_RELATIVE || msg.kind === WebviewToHostMessageType.SCAN_PYTHON_PACKAGE_REQUIREMENTS || @@ -154,6 +157,9 @@ export type RequestFilesListsMsg = export type RequestCredentialsMsg = AnyWebviewToHostMessage; +export type AddSecretMsg = + AnyWebviewToHostMessage; + export type RefreshPythonPackagesMsg = AnyWebviewToHostMessage; diff --git a/extensions/vscode/src/views/homeView.ts b/extensions/vscode/src/views/homeView.ts index 939be385b..298142922 100644 --- a/extensions/vscode/src/views/homeView.ts +++ b/extensions/vscode/src/views/homeView.ts @@ -200,6 +200,8 @@ export class HomeViewProvider implements WebviewViewProvider, Disposable { return await this.debounceRefreshPythonPackages(); case WebviewToHostMessageType.REFRESH_R_PACKAGES: return await this.debounceRefreshRPackages(); + case WebviewToHostMessageType.ADD_SECRET: + return await this.addSecret(); case WebviewToHostMessageType.VSCODE_OPEN_RELATIVE: return await this.onRelativeOpenVSCode(msg); case WebviewToHostMessageType.SCAN_PYTHON_PACKAGE_REQUIREMENTS: @@ -936,6 +938,50 @@ export class HomeViewProvider implements WebviewViewProvider, Disposable { } } + private inputSecretName = async () => { + return await window.showInputBox({ + title: "Add a Secret", + prompt: "Enter the name of the secret.", + ignoreFocusOut: true, + validateInput: (value: string) => { + if (value.length === 0) { + return "Secret names cannot be empty."; + } + return; + }, + }); + }; + + public addSecret = async () => { + const activeConfig = await this.state.getSelectedConfiguration(); + if (activeConfig === undefined) { + console.error("homeView::addSecret: No active configuration."); + return; + } + + const name = await this.inputSecretName(); + if (name === undefined) { + // Cancelled by the user + return; + } + + try { + await showProgress("Adding Secret", Views.HomeView, async () => { + const api = await useApi(); + await api.secrets.add( + activeConfig.configurationName, + name, + activeConfig.projectDir, + ); + }); + } catch (error: unknown) { + const summary = getSummaryStringFromError("addSecret", error); + window.showInformationMessage( + `Failed to add secret to configuration. ${summary}`, + ); + } + }; + public removeSecret = async (context: { name: string }) => { const activeConfig = await this.state.getSelectedConfiguration(); if (activeConfig === undefined) { diff --git a/extensions/vscode/webviews/homeView/src/components/views/secrets/Secrets.vue b/extensions/vscode/webviews/homeView/src/components/views/secrets/Secrets.vue index f8946a69d..923d01386 100644 --- a/extensions/vscode/webviews/homeView/src/components/views/secrets/Secrets.vue +++ b/extensions/vscode/webviews/homeView/src/components/views/secrets/Secrets.vue @@ -21,11 +21,25 @@ import TreeSection from "src/components/tree/TreeSection.vue"; import WelcomeView from "src/components/WelcomeView.vue"; import { useHomeStore } from "src/stores/home"; import Secret from "src/components/views/secrets/Secret.vue"; +import { useHostConduitService } from "src/HostConduitService"; + +import { WebviewToHostMessageType } from "../../../../../../src/types/messages/webviewToHostMessages"; const home = useHomeStore(); +const { sendMsg } = useHostConduitService(); const sectionActions = computed(() => { - const result: ActionButton[] = []; + const result: ActionButton[] = [ + { + label: "Add Secret", + codicon: "codicon-add", + fn: () => { + sendMsg({ + kind: WebviewToHostMessageType.ADD_SECRET, + }); + }, + }, + ]; if (home.secretsWithValueCount > 0) { result.push({