feat: shift quick delete for automations (#29640)

This commit is contained in:
G30 2026-09-04 11:58:05 -04:00 committed by GitHub
parent bfed5f8950
commit 78c4f9f83d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -33,6 +33,7 @@
import Search from '$lib/components/icons/Search.svelte';
import XMark from '$lib/components/icons/XMark.svelte';
import EllipsisHorizontal from '$lib/components/icons/EllipsisHorizontal.svelte';
import GarbageBin from '$lib/components/icons/GarbageBin.svelte';
import Select from '$lib/components/common/Select.svelte';
import Dropdown from '$lib/components/common/Dropdown.svelte';
import DropdownMenu from '$lib/components/common/DropdownMenu.svelte';
@ -57,6 +58,7 @@
let cloneFrom: AutomationResponse | null = null;
let showDeleteConfirm = false;
let shiftKey = false;
let deleteTarget: AutomationResponse | null = null;
let openAutomationMenuId: string | null = null;
@ -367,8 +369,33 @@
syncHeader();
ensureChannels();
const onKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Shift') {
shiftKey = true;
openAutomationMenuId = null;
}
};
const onKeyUp = (event: KeyboardEvent) => {
if (event.key === 'Shift') {
shiftKey = false;
}
};
const onBlur = () => {
shiftKey = false;
};
window.addEventListener('keydown', onKeyDown);
window.addEventListener('keyup', onKeyUp);
window.addEventListener('blur', onBlur);
return () => {
clearTimeout(searchDebounceTimer);
window.removeEventListener('keydown', onKeyDown);
window.removeEventListener('keyup', onKeyUp);
window.removeEventListener('blur', onBlur);
};
});
@ -617,60 +644,79 @@
</Tooltip>
</div>
<div class="flex shrink-0 flex-row items-center gap-1.5 self-center">
<AutomationMenu
show={openAutomationMenuId === automation.id}
editHandler={() => {
goto(`/automations/${automation.id}`);
}}
cloneHandler={() => {
cloneHandler(automation);
}}
runHandler={() => {
runNowHandler(automation);
}}
deleteHandler={() => {
deleteTarget = automation;
showDeleteConfirm = true;
}}
onClose={() => {
openAutomationMenuId = null;
}}
>
<button
class="flex size-6 items-center justify-center rounded-lg text-gray-400 transition dark:text-gray-500"
type="button"
aria-label={$i18n.t('Automation Menu')}
on:click={(e) => {
e.preventDefault();
e.stopPropagation();
openAutomationMenuId =
openAutomationMenuId === automation.id ? null : automation.id;
}}
>
<EllipsisHorizontal className="size-4" />
</button>
</AutomationMenu>
<button
class="flex h-6 items-center"
type="button"
on:click={(e) => {
e.stopPropagation();
e.preventDefault();
}}
>
<Tooltip
content={automation.is_active ? $i18n.t('Enabled') : $i18n.t('Disabled')}
>
<Switch
bind:state={automation.is_active}
on:change={() => {
toggleHandler(automation);
<div class="flex shrink-0 flex-row items-center self-center">
{#if shiftKey}
<Tooltip content={$i18n.t('Delete')}>
<button
class="flex size-6 items-center justify-center rounded-lg text-gray-400 transition dark:text-gray-500"
type="button"
aria-label={$i18n.t('Delete')}
on:click={(e) => {
e.preventDefault();
e.stopPropagation();
deleteHandler(automation);
}}
/>
>
<GarbageBin className="size-4" />
</button>
</Tooltip>
</button>
{:else}
<div class="flex shrink-0 flex-row items-center gap-1.5 self-center">
<AutomationMenu
show={openAutomationMenuId === automation.id}
editHandler={() => {
goto(`/automations/${automation.id}`);
}}
cloneHandler={() => {
cloneHandler(automation);
}}
runHandler={() => {
runNowHandler(automation);
}}
deleteHandler={() => {
deleteTarget = automation;
showDeleteConfirm = true;
}}
onClose={() => {
openAutomationMenuId = null;
}}
>
<button
class="flex size-6 items-center justify-center rounded-lg text-gray-400 transition dark:text-gray-500"
type="button"
aria-label={$i18n.t('Automation Menu')}
on:click={(e) => {
e.preventDefault();
e.stopPropagation();
openAutomationMenuId =
openAutomationMenuId === automation.id ? null : automation.id;
}}
>
<EllipsisHorizontal className="size-4" />
</button>
</AutomationMenu>
<button
class="flex h-6 items-center"
type="button"
on:click={(e) => {
e.stopPropagation();
e.preventDefault();
}}
>
<Tooltip
content={automation.is_active ? $i18n.t('Enabled') : $i18n.t('Disabled')}
>
<Switch
bind:state={automation.is_active}
on:change={() => {
toggleHandler(automation);
}}
/>
</Tooltip>
</button>
</div>
{/if}
</div>
</div>
{/each}