mirror of
https://github.com/samsonjs/immich.git
synced 2026-04-27 15:07:45 +00:00
refactor(web): workflow create action (#25369)
This commit is contained in:
parent
97a594556b
commit
2b77dc8e1f
3 changed files with 45 additions and 42 deletions
|
|
@ -73,6 +73,7 @@ export type Events = {
|
||||||
LibraryUpdate: [LibraryResponseDto];
|
LibraryUpdate: [LibraryResponseDto];
|
||||||
LibraryDelete: [{ id: string }];
|
LibraryDelete: [{ id: string }];
|
||||||
|
|
||||||
|
WorkflowCreate: [WorkflowResponseDto];
|
||||||
WorkflowUpdate: [WorkflowResponseDto];
|
WorkflowUpdate: [WorkflowResponseDto];
|
||||||
WorkflowDelete: [WorkflowResponseDto];
|
WorkflowDelete: [WorkflowResponseDto];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,13 @@ import {
|
||||||
type PluginFilterResponseDto,
|
type PluginFilterResponseDto,
|
||||||
type PluginTriggerResponseDto,
|
type PluginTriggerResponseDto,
|
||||||
type WorkflowActionItemDto,
|
type WorkflowActionItemDto,
|
||||||
|
type WorkflowCreateDto,
|
||||||
type WorkflowFilterItemDto,
|
type WorkflowFilterItemDto,
|
||||||
type WorkflowResponseDto,
|
type WorkflowResponseDto,
|
||||||
type WorkflowUpdateDto,
|
type WorkflowUpdateDto,
|
||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import { modalManager, toastManager, type ActionItem } from '@immich/ui';
|
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';
|
import type { MessageFormatter } from 'svelte-i18n';
|
||||||
|
|
||||||
export type PickerSubType = 'album-picker' | 'people-picker';
|
export type PickerSubType = 'album-picker' | 'people-picker';
|
||||||
|
|
@ -318,6 +319,23 @@ export const handleUpdateWorkflow = async (
|
||||||
return updateWorkflow({ id: workflowId, workflowUpdateDto: updateDto });
|
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) => {
|
export const getWorkflowActions = ($t: MessageFormatter, workflow: WorkflowResponseDto) => {
|
||||||
const ToggleEnabled: ActionItem = {
|
const ToggleEnabled: ActionItem = {
|
||||||
title: workflow.enabled ? $t('disable') : $t('enable'),
|
title: workflow.enabled ? $t('disable') : $t('enable'),
|
||||||
|
|
@ -356,22 +374,12 @@ export const getWorkflowShowSchemaAction = (
|
||||||
onAction: onToggle,
|
onAction: onToggle,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleCreateWorkflow = async (): Promise<WorkflowResponseDto | undefined> => {
|
const handleCreateWorkflow = async (dto: WorkflowCreateDto) => {
|
||||||
const $t = await getFormatter();
|
const $t = await getFormatter();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const workflow = await createWorkflow({
|
const response = await createWorkflow({ workflowCreateDto: dto });
|
||||||
workflowCreateDto: {
|
eventManager.emit('WorkflowCreate', response);
|
||||||
name: $t('untitled_workflow'),
|
|
||||||
triggerType: PluginTriggerType.AssetCreate,
|
|
||||||
filters: [],
|
|
||||||
actions: [],
|
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
await goto(Route.viewWorkflow(workflow));
|
|
||||||
return workflow;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(error, $t('errors.unable_to_create'));
|
handleError(error, $t('errors.unable_to_create'));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
import emptyWorkflows from '$lib/assets/empty-workflows.svg';
|
import emptyWorkflows from '$lib/assets/empty-workflows.svg';
|
||||||
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
|
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
|
||||||
import OnEvents from '$lib/components/OnEvents.svelte';
|
import OnEvents from '$lib/components/OnEvents.svelte';
|
||||||
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
|
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
|
||||||
|
import { Route } from '$lib/route';
|
||||||
import {
|
import {
|
||||||
getWorkflowActions,
|
getWorkflowActions,
|
||||||
|
getWorkflowsActions,
|
||||||
getWorkflowShowSchemaAction,
|
getWorkflowShowSchemaAction,
|
||||||
handleCreateWorkflow,
|
|
||||||
type WorkflowPayload,
|
type WorkflowPayload,
|
||||||
} from '$lib/services/workflow.service';
|
} from '$lib/services/workflow.service';
|
||||||
import type { PluginFilterResponseDto, WorkflowResponseDto } from '@immich/sdk';
|
import { type PluginFilterResponseDto, type WorkflowResponseDto } from '@immich/sdk';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
|
|
@ -18,15 +20,13 @@
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
CodeBlock,
|
CodeBlock,
|
||||||
HStack,
|
|
||||||
Icon,
|
|
||||||
IconButton,
|
IconButton,
|
||||||
MenuItemType,
|
MenuItemType,
|
||||||
menuManager,
|
menuManager,
|
||||||
Text,
|
Text,
|
||||||
VStack,
|
VStack,
|
||||||
} from '@immich/ui';
|
} from '@immich/ui';
|
||||||
import { mdiClose, mdiDotsVertical, mdiPlus } from '@mdi/js';
|
import { mdiClose, mdiDotsVertical } from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import { SvelteMap, SvelteSet } from 'svelte/reactivity';
|
import { SvelteMap, SvelteSet } from 'svelte/reactivity';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
|
|
@ -40,7 +40,6 @@
|
||||||
let workflows = $state<WorkflowResponseDto[]>(data.workflows);
|
let workflows = $state<WorkflowResponseDto[]>(data.workflows);
|
||||||
|
|
||||||
const expandedWorkflows = new SvelteSet<string>();
|
const expandedWorkflows = new SvelteSet<string>();
|
||||||
|
|
||||||
const pluginFilterLookup = new SvelteMap<string, PluginFilterResponseDto>();
|
const pluginFilterLookup = new SvelteMap<string, PluginFilterResponseDto>();
|
||||||
const pluginActionLookup = 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 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 getFilterLabel = (filterId: string) => {
|
||||||
const meta = pluginFilterLookup.get(filterId);
|
const meta = pluginFilterLookup.get(filterId);
|
||||||
return meta?.title ?? $t('filter');
|
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>
|
</script>
|
||||||
|
|
||||||
<OnEvents {onWorkflowUpdate} {onWorkflowDelete} />
|
<OnEvents {onWorkflowCreate} {onWorkflowUpdate} {onWorkflowDelete} />
|
||||||
|
|
||||||
{#snippet chipItem(title: string)}
|
{#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">
|
<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>
|
</span>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
<UserPageLayout title={data.meta.title} scrollbar={false}>
|
<UserPageLayout title={data.meta.title} actions={[Create]} 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}
|
|
||||||
|
|
||||||
<section class="flex place-content-center sm:mx-4">
|
<section class="flex place-content-center sm:mx-4">
|
||||||
<section class="w-full pb-28 sm:w-5/6 md:w-4xl">
|
<section class="w-full pb-28 sm:w-5/6 md:w-4xl">
|
||||||
{#if workflows.length === 0}
|
{#if workflows.length === 0}
|
||||||
<EmptyPlaceholder
|
<EmptyPlaceholder
|
||||||
title={$t('create_first_workflow')}
|
title={$t('create_first_workflow')}
|
||||||
text={$t('workflows_help_text')}
|
text={$t('workflows_help_text')}
|
||||||
onClick={handleCreateWorkflow}
|
onClick={() => Create.onAction(Create)}
|
||||||
src={emptyWorkflows}
|
src={emptyWorkflows}
|
||||||
class="mt-10 mx-auto"
|
class="mt-10 mx-auto"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue