diff --git a/web/src/lib/components/workflows/WorkflowPickerField.svelte b/web/src/lib/components/workflows/WorkflowPickerField.svelte index b8ebadaca4..6ad4fdbeb2 100644 --- a/web/src/lib/components/workflows/WorkflowPickerField.svelte +++ b/web/src/lib/components/workflows/WorkflowPickerField.svelte @@ -2,8 +2,9 @@ import WorkflowPickerItemCard from '$lib/components/workflows/WorkflowPickerItemCard.svelte'; import AlbumPickerModal from '$lib/modals/AlbumPickerModal.svelte'; import PeoplePickerModal from '$lib/modals/PeoplePickerModal.svelte'; + import { fetchPickerMetadata, type PickerMetadata } from '$lib/services/workflow.service'; import type { ComponentConfig } from '$lib/utils/workflow'; - import { getAlbumInfo, getPerson, type AlbumResponseDto, type PersonResponseDto } from '@immich/sdk'; + import type { AlbumResponseDto, PersonResponseDto } from '@immich/sdk'; import { Button, Field, modalManager } from '@immich/ui'; import { mdiPlus } from '@mdi/js'; import { t } from 'svelte-i18n'; @@ -22,7 +23,7 @@ const isAlbum = $derived(subType === 'album-picker'); const multiple = $derived(component.type === 'multiselect' || Array.isArray(value)); - let pickerMetadata = $state(); + let pickerMetadata = $state(); $effect(() => { if (!value) { @@ -30,34 +31,20 @@ return; } - void fetchMetadata(); + if (!pickerMetadata) { + void loadMetadata(); + } }); - const fetchMetadata = async () => { - if (!value || pickerMetadata) { - return; - } - - try { - if (Array.isArray(value) && value.length > 0) { - // Multiple selection - pickerMetadata = await (isAlbum - ? Promise.all(value.map((id) => getAlbumInfo({ id }))) - : Promise.all(value.map((id) => getPerson({ id })))); - } else if (typeof value === 'string' && value) { - // Single selection - pickerMetadata = await (isAlbum ? getAlbumInfo({ id: value }) : getPerson({ id: value })); - } - } catch (error) { - console.error(`Failed to fetch metadata for ${configKey}:`, error); - } + const loadMetadata = async () => { + pickerMetadata = await fetchPickerMetadata(value, subType); }; const handlePicker = async () => { if (isAlbum) { const albums = await modalManager.show(AlbumPickerModal, { shared: false }); if (albums && albums.length > 0) { - const newValue = multiple ? albums.map((a) => a.id) : albums[0].id; + const newValue = multiple ? albums.map((album) => album.id) : albums[0].id; onchange(newValue); pickerMetadata = multiple ? albums : albums[0]; } @@ -66,7 +53,7 @@ const excludedIds = multiple ? currentIds : []; const people = await modalManager.show(PeoplePickerModal, { multiple, excludedIds }); if (people && people.length > 0) { - const newValue = multiple ? people.map((p) => p.id) : people[0].id; + const newValue = multiple ? people.map((person) => person.id) : people[0].id; onchange(newValue); pickerMetadata = multiple ? people : people[0]; } diff --git a/web/src/lib/services/workflow.service.ts b/web/src/lib/services/workflow.service.ts index f42f15cb10..4a2739926a 100644 --- a/web/src/lib/services/workflow.service.ts +++ b/web/src/lib/services/workflow.service.ts @@ -6,8 +6,12 @@ import { getFormatter } from '$lib/utils/i18n'; import { createWorkflow, deleteWorkflow, + getAlbumInfo, + getPerson, PluginTriggerType, updateWorkflow, + type AlbumResponseDto, + type PersonResponseDto, type PluginActionResponseDto, type PluginContextType, type PluginFilterResponseDto, @@ -21,6 +25,9 @@ import { modalManager, toastManager, type ActionItem } from '@immich/ui'; import { mdiCodeJson, mdiDelete, mdiPause, mdiPencil, mdiPlay } from '@mdi/js'; import type { MessageFormatter } from 'svelte-i18n'; +export type PickerSubType = 'album-picker' | 'people-picker'; +export type PickerMetadata = AlbumResponseDto | PersonResponseDto | AlbumResponseDto[] | PersonResponseDto[]; + export interface WorkflowPayload { name: string; description: string; @@ -412,3 +419,30 @@ export const handleDeleteWorkflow = async (workflow: WorkflowResponseDto): Promi export const handleNavigateToWorkflow = async (workflow: WorkflowResponseDto): Promise => { await goto(`${AppRoute.WORKFLOWS}/${workflow.id}`); }; + +export const fetchPickerMetadata = async ( + value: string | string[] | undefined, + subType: PickerSubType, +): Promise => { + if (!value) { + return undefined; + } + + const isAlbum = subType === 'album-picker'; + + try { + if (Array.isArray(value) && value.length > 0) { + // Multiple selection + return isAlbum + ? await Promise.all(value.map((id) => getAlbumInfo({ id }))) + : await Promise.all(value.map((id) => getPerson({ id }))); + } else if (typeof value === 'string' && value) { + // Single selection + return isAlbum ? await getAlbumInfo({ id: value }) : await getPerson({ id: value }); + } + } catch (error) { + console.error(`Failed to fetch picker metadata:`, error); + } + + return undefined; +};