<script type="typescript">
import type { DeleteSshKeyResult, SshKey } from '../../../types/ssh_keys';
import { createEventDispatcher } from 'svelte';
import Icon from '../../../components/Icon.svelte';
import ErrorAlert from '../../../components/ErrorAlert.svelte';
import RelativeTime from '../../../components/RelativeTime.svelte';
import Spinner from '../../../components/Spinner.svelte';
import { auth, BASE_URL } from '../../../stores/auth';
import { getErrorMessage } from '../../../util';
const dispatch = createEventDispatcher();
* The key that the user requested to delete.
*/
export let deleting: SshKey;
* Any errors that came of the last submission. If this is not null the user will be shown
* an alert.
*/
let deleteError: string | null = null;
* Simple boolean flag to determine if a key is currently being submitted, so we can
* disable the buttons and prevent exiting the modal.
*/
let isDeleting = false;
* Binds helper keys for the modal, so we can provide some expected functions of a modal.
*/
function handleKeydown(event: KeyboardEvent) {
if (event.key == 'Escape') {
closeModal();
}
}
* Attempts the deletion of the key against the backend.
*/
async function deleteSshKey() {
deleteError = null;
isDeleting = true;
try {
let res = await fetch(`${BASE_URL}/web/v1/ssh-key/${deleting.uuid}`, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${$auth?.auth_key}`,
},
credentials: 'include',
});
let json: DeleteSshKeyResult = await res.json();
if (json.error) {
throw new Error(json.error);
}
isDeleting = false;
dispatch('complete');
closeModal();
} catch (e) {
isDeleting = false;
deleteError = getErrorMessage(e);
}
}
* Send an event to the main view to request to close us, by unsetting `deleting` on their end
*/
function closeModal() {
if (!isDeleting) {
dispatch('close');
}
}
</script>
<svelte:window on:keydown={handleKeydown} />
<div
on:click|self={closeModal}
class="overflow-y-auto overflow-x-hidden backdrop-blur-[4px] bg-black/20 h-screen w-screen fixed top-0 right-0 left-0 z-50 flex items-center justify-center"
>
<div class="p-4 bg-white rounded-lg shadow-2xl dark:bg-gray-700">
<button
on:click={closeModal}
type="button"
class="absolute top-3 right-2.5 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-800 dark:hover:text-white"
>
<Icon name="x" />
<span class="sr-only">Close modal</span>
</button>
{#if deleteError}
<ErrorAlert on:close={() => (deleteError = null)}>{deleteError}</ErrorAlert>
{/if}
<div class="p-6 text-center">
<div class="mx-auto text-[4rem] text-red-600">
<div class="inline-block">
<Icon name="alert-triangle" />
</div>
</div>
<h3 class="text-lg font-normal text-inherit dark:text-gray-400">
Are you sure you want to delete this SSH Key?
</h3>
<div class="break-all mb-5 mt-2 text-xs">
<code>{deleting.fingerprint} {deleting.name}</code>
<div>
<span>Added <RelativeTime time={deleting.created_at} /></span>
<span class="ml-2">
Last used
{#if deleting.last_used_at}
<RelativeTime time={deleting.last_used_at} />
{:else}
never
{/if}
</span>
</div>
</div>
{#if isDeleting}
<div class="relative h-4">
<Spinner />
</div>
{:else}
<button
on:click={deleteSshKey}
class="text-white bg-red-600 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 dark:focus:ring-red-800 font-medium rounded-lg text-sm inline-flex items-center px-5 py-2.5 text-center mr-2"
>
Yes, I'm sure
</button>
<button
on:click={closeModal}
autofocus
class="text-gray-500 bg-white hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-gray-200 rounded-lg border border-gray-200 text-sm font-medium px-5 py-2.5 hover:text-gray-900 focus:z-10 dark:bg-gray-700 dark:text-gray-300 dark:border-gray-500 dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-gray-600"
>
No, cancel
</button>
{/if}
</div>
</div>
</div>