fix: add credential delete button + fix OAuth token exchange error display

Delete button appears next to credential dropdown when a credential is
selected. Confirms before deleting, refreshes list after.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell 2026-03-17 11:42:27 -04:00
parent 901d9c257d
commit 944fd945ee

View File

@ -145,21 +145,32 @@
<!-- Credentials --> <!-- Credentials -->
<div> <div>
<label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Credential</label> <label class="block text-xs text-[var(--wraith-text-secondary)] mb-1">Credential</label>
<select <div class="flex gap-2">
v-model="form.credentialId" <select
class="w-full px-3 py-2 text-sm rounded bg-[#0d1117] border border-[#30363d] text-[var(--wraith-text-primary)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors cursor-pointer" v-model="form.credentialId"
> class="flex-1 px-3 py-2 text-sm rounded bg-[#0d1117] border border-[#30363d] text-[var(--wraith-text-primary)] outline-none focus:border-[var(--wraith-accent-blue)] transition-colors cursor-pointer"
<option :value="null">None</option>
<option
v-for="cred in credentials"
:key="cred.id"
:value="cred.id"
> >
{{ cred.name }} <option :value="null">None</option>
<template v-if="cred.type === 'ssh_key'"> (SSH Key)</template> <option
<template v-else> (Password{{ cred.username ? ` ${cred.username}` : '' }})</template> v-for="cred in credentials"
</option> :key="cred.id"
</select> :value="cred.id"
>
{{ cred.name }}
<template v-if="cred.type === 'ssh_key'"> (SSH Key)</template>
<template v-else> (Password{{ cred.username ? ` ${cred.username}` : '' }})</template>
</option>
</select>
<button
v-if="form.credentialId"
type="button"
class="px-2.5 py-2 text-xs rounded border border-red-500/30 text-red-400 hover:bg-red-500/10 transition-colors cursor-pointer"
title="Delete selected credential"
@click="deleteSelectedCredential"
>
Delete
</button>
</div>
</div> </div>
<!-- Add New Credential (collapsible) --> <!-- Add New Credential (collapsible) -->
@ -421,6 +432,20 @@ function resetNewCredForm(): void {
newCredError.value = ""; newCredError.value = "";
} }
async function deleteSelectedCredential(): Promise<void> {
if (!form.value.credentialId) return;
const cred = credentials.value.find(c => c.id === form.value.credentialId);
const name = cred?.name ?? `ID ${form.value.credentialId}`;
if (!confirm(`Delete credential "${name}"? This cannot be undone.`)) return;
try {
await Call.ByName(`${APP}.DeleteCredential`, form.value.credentialId);
form.value.credentialId = null;
await loadCredentials();
} catch (err) {
alert(`Failed to delete credential: ${err}`);
}
}
async function loadCredentials(): Promise<void> { async function loadCredentials(): Promise<void> {
try { try {
const result = await Call.ByName(`${APP}.ListCredentials`) as Credential[]; const result = await Call.ByName(`${APP}.ListCredentials`) as Credential[];