feat: add shift-to-delete to prompts workspace

This commit adds the Shift key shortcut to the Prompts workspace page to reveal a trash can icon for quick deletion of prompts. This feature is already present for the Models, Tools, and Functions pages.
This commit is contained in:
silentoplayz 2025-08-22 16:09:21 -04:00
parent dafedf5675
commit 9e7ec0eb1e

View file

@ -24,6 +24,9 @@
import Tooltip from '../common/Tooltip.svelte'; import Tooltip from '../common/Tooltip.svelte';
import { capitalizeFirstLetter, slugify } from '$lib/utils'; import { capitalizeFirstLetter, slugify } from '$lib/utils';
import XMark from '../icons/XMark.svelte'; import XMark from '../icons/XMark.svelte';
import GarbageBin from '../icons/GarbageBin.svelte';
let shiftKey = false;
const i18n = getContext('i18n'); const i18n = getContext('i18n');
let promptsImportInputElement: HTMLInputElement; let promptsImportInputElement: HTMLInputElement;
@ -89,7 +92,16 @@
const deleteHandler = async (prompt) => { const deleteHandler = async (prompt) => {
const command = prompt.command; const command = prompt.command;
await deletePromptByCommand(localStorage.token, command);
const res = await deletePromptByCommand(localStorage.token, command).catch((err) => {
toast.error(err);
return null;
});
if (res) {
toast.success($i18n.t(`Deleted {{name}}`, { name: command }));
}
await init(); await init();
}; };
@ -101,6 +113,32 @@
onMount(async () => { onMount(async () => {
await init(); await init();
loaded = true; loaded = true;
const onKeyDown = (event) => {
if (event.key === 'Shift') {
shiftKey = true;
}
};
const onKeyUp = (event) => {
if (event.key === 'Shift') {
shiftKey = false;
}
};
const onBlur = () => {
shiftKey = false;
};
window.addEventListener('keydown', onKeyDown);
window.addEventListener('keyup', onKeyUp);
window.addEventListener('blur', onBlur);
return () => {
window.removeEventListener('keydown', onKeyDown);
window.removeEventListener('keyup', onKeyUp);
window.removeEventListener('blur', onBlur);
};
}); });
</script> </script>
@ -202,50 +240,64 @@
</a> </a>
</div> </div>
<div class="flex flex-row gap-0.5 self-center"> <div class="flex flex-row gap-0.5 self-center">
<a {#if shiftKey}
class="self-center w-fit text-sm px-2 py-2 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl" <Tooltip content={$i18n.t('Delete')}>
type="button" <button
href={`/workspace/prompts/edit?command=${encodeURIComponent(prompt.command)}`} class="self-center w-fit text-sm px-2 py-2 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
> type="button"
<svg on:click={() => {
xmlns="http://www.w3.org/2000/svg" deleteHandler(prompt);
fill="none" }}
viewBox="0 0 24 24" >
stroke-width="1.5" <GarbageBin />
stroke="currentColor" </button>
class="w-4 h-4" </Tooltip>
> {:else}
<path <a
stroke-linecap="round" class="self-center w-fit text-sm px-2 py-2 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
stroke-linejoin="round"
d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"
/>
</svg>
</a>
<PromptMenu
shareHandler={() => {
shareHandler(prompt);
}}
cloneHandler={() => {
cloneHandler(prompt);
}}
exportHandler={() => {
exportHandler(prompt);
}}
deleteHandler={async () => {
deletePrompt = prompt;
showDeleteConfirm = true;
}}
onClose={() => {}}
>
<button
class="self-center w-fit text-sm p-1.5 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
type="button" type="button"
href={`/workspace/prompts/edit?command=${encodeURIComponent(prompt.command)}`}
> >
<EllipsisHorizontal className="size-5" /> <svg
</button> xmlns="http://www.w3.org/2000/svg"
</PromptMenu> fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-4 h-4"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"
/>
</svg>
</a>
<PromptMenu
shareHandler={() => {
shareHandler(prompt);
}}
cloneHandler={() => {
cloneHandler(prompt);
}}
exportHandler={() => {
exportHandler(prompt);
}}
deleteHandler={async () => {
deletePrompt = prompt;
showDeleteConfirm = true;
}}
onClose={() => {}}
>
<button
class="self-center w-fit text-sm p-1.5 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
type="button"
>
<EllipsisHorizontal className="size-5" />
</button>
</PromptMenu>
{/if}
</div> </div>
</div> </div>
{/each} {/each}