mirror of
https://github.com/immich-app/immich.git
synced 2026-02-04 08:49:01 +03:00
refactor(web): workflow create action (#25369)
This commit is contained in:
@@ -73,6 +73,7 @@ export type Events = {
|
||||
LibraryUpdate: [LibraryResponseDto];
|
||||
LibraryDelete: [{ id: string }];
|
||||
|
||||
WorkflowCreate: [WorkflowResponseDto];
|
||||
WorkflowUpdate: [WorkflowResponseDto];
|
||||
WorkflowDelete: [WorkflowResponseDto];
|
||||
|
||||
|
||||
@@ -17,12 +17,13 @@ import {
|
||||
type PluginFilterResponseDto,
|
||||
type PluginTriggerResponseDto,
|
||||
type WorkflowActionItemDto,
|
||||
type WorkflowCreateDto,
|
||||
type WorkflowFilterItemDto,
|
||||
type WorkflowResponseDto,
|
||||
type WorkflowUpdateDto,
|
||||
} from '@immich/sdk';
|
||||
import { modalManager, toastManager, type ActionItem } from '@immich/ui';
|
||||
import { mdiCodeJson, mdiDelete, mdiPause, mdiPencil, mdiPlay } from '@mdi/js';
|
||||
import { mdiCodeJson, mdiDelete, mdiPause, mdiPencil, mdiPlay, mdiPlus } from '@mdi/js';
|
||||
import type { MessageFormatter } from 'svelte-i18n';
|
||||
|
||||
export type PickerSubType = 'album-picker' | 'people-picker';
|
||||
@@ -318,6 +319,23 @@ export const handleUpdateWorkflow = async (
|
||||
return updateWorkflow({ id: workflowId, workflowUpdateDto: updateDto });
|
||||
};
|
||||
|
||||
export const getWorkflowsActions = ($t: MessageFormatter) => {
|
||||
const Create: ActionItem = {
|
||||
title: $t('create_workflow'),
|
||||
icon: mdiPlus,
|
||||
onAction: () =>
|
||||
handleCreateWorkflow({
|
||||
name: $t('untitled_workflow'),
|
||||
triggerType: PluginTriggerType.AssetCreate,
|
||||
filters: [],
|
||||
actions: [],
|
||||
enabled: false,
|
||||
}),
|
||||
};
|
||||
|
||||
return { Create };
|
||||
};
|
||||
|
||||
export const getWorkflowActions = ($t: MessageFormatter, workflow: WorkflowResponseDto) => {
|
||||
const ToggleEnabled: ActionItem = {
|
||||
title: workflow.enabled ? $t('disable') : $t('enable'),
|
||||
@@ -356,22 +374,12 @@ export const getWorkflowShowSchemaAction = (
|
||||
onAction: onToggle,
|
||||
});
|
||||
|
||||
export const handleCreateWorkflow = async (): Promise<WorkflowResponseDto | undefined> => {
|
||||
const handleCreateWorkflow = async (dto: WorkflowCreateDto) => {
|
||||
const $t = await getFormatter();
|
||||
|
||||
try {
|
||||
const workflow = await createWorkflow({
|
||||
workflowCreateDto: {
|
||||
name: $t('untitled_workflow'),
|
||||
triggerType: PluginTriggerType.AssetCreate,
|
||||
filters: [],
|
||||
actions: [],
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
await goto(Route.viewWorkflow(workflow));
|
||||
return workflow;
|
||||
const response = await createWorkflow({ workflowCreateDto: dto });
|
||||
eventManager.emit('WorkflowCreate', response);
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_create'));
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import emptyWorkflows from '$lib/assets/empty-workflows.svg';
|
||||
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
|
||||
import OnEvents from '$lib/components/OnEvents.svelte';
|
||||
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import {
|
||||
getWorkflowActions,
|
||||
getWorkflowsActions,
|
||||
getWorkflowShowSchemaAction,
|
||||
handleCreateWorkflow,
|
||||
type WorkflowPayload,
|
||||
} from '$lib/services/workflow.service';
|
||||
import type { PluginFilterResponseDto, WorkflowResponseDto } from '@immich/sdk';
|
||||
import { type PluginFilterResponseDto, type WorkflowResponseDto } from '@immich/sdk';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
@@ -18,15 +20,13 @@
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
CodeBlock,
|
||||
HStack,
|
||||
Icon,
|
||||
IconButton,
|
||||
MenuItemType,
|
||||
menuManager,
|
||||
Text,
|
||||
VStack,
|
||||
} from '@immich/ui';
|
||||
import { mdiClose, mdiDotsVertical, mdiPlus } from '@mdi/js';
|
||||
import { mdiClose, mdiDotsVertical } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { SvelteMap, SvelteSet } from 'svelte/reactivity';
|
||||
import type { PageData } from './$types';
|
||||
@@ -40,7 +40,6 @@
|
||||
let workflows = $state<WorkflowResponseDto[]>(data.workflows);
|
||||
|
||||
const expandedWorkflows = new SvelteSet<string>();
|
||||
|
||||
const pluginFilterLookup = new SvelteMap<string, PluginFilterResponseDto>();
|
||||
const pluginActionLookup = new SvelteMap<string, PluginFilterResponseDto>();
|
||||
|
||||
@@ -90,16 +89,6 @@
|
||||
|
||||
const getJson = (workflow: WorkflowResponseDto) => JSON.stringify(constructPayload(workflow), null, 2);
|
||||
|
||||
const onWorkflowUpdate = (updatedWorkflow: WorkflowResponseDto) => {
|
||||
workflows = workflows.map((currentWorkflow) =>
|
||||
currentWorkflow.id === updatedWorkflow.id ? updatedWorkflow : currentWorkflow,
|
||||
);
|
||||
};
|
||||
|
||||
const onWorkflowDelete = (deletedWorkflow: WorkflowResponseDto) => {
|
||||
workflows = workflows.filter((currentWorkflow) => currentWorkflow.id !== deletedWorkflow.id);
|
||||
};
|
||||
|
||||
const getFilterLabel = (filterId: string) => {
|
||||
const meta = pluginFilterLookup.get(filterId);
|
||||
return meta?.title ?? $t('filter');
|
||||
@@ -138,9 +127,23 @@
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
const { Create } = $derived(getWorkflowsActions($t));
|
||||
|
||||
const onWorkflowCreate = async (response: WorkflowResponseDto) => {
|
||||
await goto(Route.viewWorkflow(response));
|
||||
};
|
||||
|
||||
const onWorkflowUpdate = (response: WorkflowResponseDto) => {
|
||||
workflows = workflows.map((workflow) => (workflow.id === response.id ? response : workflow));
|
||||
};
|
||||
|
||||
const onWorkflowDelete = (response: WorkflowResponseDto) => {
|
||||
workflows = workflows.filter(({ id }) => id !== response.id);
|
||||
};
|
||||
</script>
|
||||
|
||||
<OnEvents {onWorkflowUpdate} {onWorkflowDelete} />
|
||||
<OnEvents {onWorkflowCreate} {onWorkflowUpdate} {onWorkflowDelete} />
|
||||
|
||||
{#snippet chipItem(title: string)}
|
||||
<span class="rounded-xl border border-gray-200/80 px-3 py-1.5 text-sm dark:border-gray-600 bg-light">
|
||||
@@ -148,23 +151,14 @@
|
||||
</span>
|
||||
{/snippet}
|
||||
|
||||
<UserPageLayout title={data.meta.title} scrollbar={false}>
|
||||
{#snippet buttons()}
|
||||
<HStack gap={1}>
|
||||
<Button size="small" variant="ghost" color="secondary" onclick={handleCreateWorkflow}>
|
||||
<Icon icon={mdiPlus} size="18" />
|
||||
{$t('create_workflow')}
|
||||
</Button>
|
||||
</HStack>
|
||||
{/snippet}
|
||||
|
||||
<UserPageLayout title={data.meta.title} actions={[Create]} scrollbar={false}>
|
||||
<section class="flex place-content-center sm:mx-4">
|
||||
<section class="w-full pb-28 sm:w-5/6 md:w-4xl">
|
||||
{#if workflows.length === 0}
|
||||
<EmptyPlaceholder
|
||||
title={$t('create_first_workflow')}
|
||||
text={$t('workflows_help_text')}
|
||||
onClick={handleCreateWorkflow}
|
||||
onClick={() => Create.onAction(Create)}
|
||||
src={emptyWorkflows}
|
||||
class="mt-10 mx-auto"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user