feat(ui): add Clone option to automations 3-dots menu (#25790)

This commit is contained in:
G30
2026-06-29 03:00:23 -04:00
committed by GitHub
parent c8260745a6
commit f923edcaaa
3 changed files with 44 additions and 1 deletions

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { createEventDispatcher, getContext } from 'svelte';
import { createEventDispatcher, getContext, tick } from 'svelte';
import { toast } from 'svelte-sonner';
import Modal from '$lib/components/common/Modal.svelte';
@@ -21,6 +21,7 @@
export let show = false;
export let automation: AutomationResponse | null = null;
export let cloneFrom: AutomationResponse | null = null;
let name = '';
let prompt = '';
@@ -75,6 +76,8 @@
};
const init = async () => {
await tick();
if (automation) {
name = automation.name;
prompt = automation.data.prompt;
@@ -83,6 +86,14 @@
if (scheduleDropdown) {
scheduleDropdown.parseRrule(automation.data.rrule);
}
} else if (cloneFrom) {
name = cloneFrom.name;
prompt = cloneFrom.data.prompt;
model_id = cloneFrom.data.model_id;
is_active = true;
if (scheduleDropdown) {
scheduleDropdown.parseRrule(cloneFrom.data.rrule);
}
} else {
name = '';
prompt = '';

View File

@@ -3,11 +3,13 @@
import Dropdown from '$lib/components/common/Dropdown.svelte';
import GarbageBin from '$lib/components/icons/GarbageBin.svelte';
import DocumentDuplicate from '$lib/components/icons/DocumentDuplicate.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
const i18n = getContext('i18n');
export let editHandler: Function;
export let cloneHandler: Function;
export let runHandler: Function = () => {};
export let deleteHandler: Function;
export let onClose: Function = () => {};
@@ -57,6 +59,18 @@
<div class="flex items-center">{$i18n.t('Edit')}</div>
</button>
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
draggable="false"
on:click={() => {
cloneHandler();
show = false;
}}
>
<DocumentDuplicate />
<div class="flex items-center">{$i18n.t('Clone')}</div>
</button>
<button
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
draggable="false"

View File

@@ -40,6 +40,7 @@
let loading = false;
let showCreateModal = false;
let cloneFrom: AutomationResponse | null = null;
let showDeleteConfirm = false;
let deleteTarget: AutomationResponse | null = null;
@@ -69,6 +70,10 @@
getAutomationList();
}
$: if (!showCreateModal) {
cloneFrom = null;
}
const getAutomationList = async () => {
if (!loaded) return;
@@ -143,6 +148,14 @@
getAutomationList();
};
const cloneHandler = (automation: AutomationResponse) => {
cloneFrom = {
...automation,
name: `${automation.name} (Clone)`
};
showCreateModal = true;
};
const formatRRule = (rrule: string): string => {
// Detect one-time schedule (ONCE)
if (rrule.includes('COUNT=1')) {
@@ -229,6 +242,7 @@
<AutomationModal
bind:show={showCreateModal}
automation={null}
{cloneFrom}
on:save={(e) => {
getAutomationList();
if (e.detail?.id) {
@@ -275,6 +289,7 @@
<button
class="px-2 py-1.5 rounded-xl bg-black text-white dark:bg-white dark:text-black transition font-medium text-sm flex items-center"
on:click={() => {
cloneFrom = null;
showCreateModal = true;
}}
>
@@ -434,6 +449,9 @@
editHandler={() => {
goto(`/automations/${automation.id}`);
}}
cloneHandler={() => {
cloneHandler(automation);
}}
runHandler={() => {
runNowHandler(automation);
}}