mirror of
https://github.com/immich-app/immich
synced 2026-08-15 13:03:57 +00:00
feat: workflow asset tag trigger/filter/action (#29043)
* feat: workflow asset tag trigger and filter * feat(web): show tag names in workflow editor * fix(web): tag picker in schema config editor * fix: invalid plugin manifest * chore: update workflow method wrapper type * chore: update tag filter method declaration * feat: workflow action to add tags to assets
This commit is contained in:
parent
b82d480552
commit
a939561e70
17 changed files with 175 additions and 8 deletions
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import SchemaAlbumPicker from '$lib/components/SchemaAlbumPicker.svelte';
|
||||
import Self from '$lib/components/SchemaConfiguration.svelte';
|
||||
import SchemaTagPicker from '$lib/components/SchemaTagPicker.svelte';
|
||||
import type { JSONSchemaProperty, SchemaConfig } from '$lib/types';
|
||||
import {
|
||||
CodeBlock,
|
||||
|
|
@ -80,6 +81,8 @@
|
|||
</div>
|
||||
{:else if schema.uiHint?.type === 'AlbumId'}
|
||||
<SchemaAlbumPicker {label} {description} array={schema.array} bind:albumIds={getUiHintValue, setUiHintValue} />
|
||||
{:else if schema.uiHint?.type === 'TagId'}
|
||||
<SchemaTagPicker bind:tagIds={getUiHintValue, setUiHintValue} />
|
||||
{:else if schema.enum && schema.array}
|
||||
<Field {label} {description}>
|
||||
<MultiSelect options={schema.enum} bind:values={getEnum, setValue} />
|
||||
|
|
|
|||
32
web/src/lib/components/SchemaTagPicker.svelte
Normal file
32
web/src/lib/components/SchemaTagPicker.svelte
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<script lang="ts">
|
||||
import Combobox from '$lib/components/shared-components/Combobox.svelte';
|
||||
import TagPill from '$lib/components/shared-components/TagPill.svelte';
|
||||
import { getAllTags, type TagResponseDto } from '@immich/sdk';
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
let { tagIds = $bindable([]) }: { tagIds: string[] } = $props();
|
||||
let tags: TagResponseDto[] = $state([]);
|
||||
|
||||
onMount(async () => {
|
||||
tags = await getAllTags();
|
||||
});
|
||||
</script>
|
||||
|
||||
<Combobox
|
||||
onSelect={(option) => {
|
||||
if (option && !tagIds.includes(option.value)) {
|
||||
tagIds.push(option.value);
|
||||
}
|
||||
}}
|
||||
label={$t('tags')}
|
||||
defaultFirstOption
|
||||
options={tags.map((tag) => ({ label: tag.value, value: tag.id }))}
|
||||
placeholder={$t('search_tags')}
|
||||
/>
|
||||
|
||||
<section class="flex flex-wrap gap-1 pt-2">
|
||||
{#each tagIds as id, index (id)}
|
||||
<TagPill label={tags.find((t) => t.id === id)?.name ?? id} onRemove={() => tagIds.splice(index, 1)} />
|
||||
{/each}
|
||||
</section>
|
||||
|
|
@ -100,7 +100,7 @@ export type JSONSchemaProperty = {
|
|||
properties?: Record<string, JSONSchemaProperty>;
|
||||
required?: string[];
|
||||
uiHint?: {
|
||||
type?: 'AlbumId' | 'AssetId' | 'PersonId';
|
||||
type?: 'AlbumId' | 'AssetId' | 'PersonId' | 'TagId';
|
||||
order?: number;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ export const getTriggerName = ($t: MessageFormatter, type: WorkflowTrigger) => {
|
|||
case WorkflowTrigger.AssetMetadataExtraction: {
|
||||
return $t('trigger_asset_metadata_extraction');
|
||||
}
|
||||
case WorkflowTrigger.AssetTagged: {
|
||||
return $t('trigger_asset_tagged');
|
||||
}
|
||||
default: {
|
||||
return type;
|
||||
}
|
||||
|
|
@ -30,6 +33,12 @@ export const getTriggerDescription = ($t: MessageFormatter, type: WorkflowTrigge
|
|||
case WorkflowTrigger.AssetMetadataExtraction: {
|
||||
return $t('trigger_asset_metadata_extraction_description');
|
||||
}
|
||||
case WorkflowTrigger.AssetTagged: {
|
||||
return $t('trigger_asset_tagged_description');
|
||||
}
|
||||
default: {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script module lang="ts">
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { getAlbumInfo } from '@immich/sdk';
|
||||
import { getAlbumInfo, getTagById } from '@immich/sdk';
|
||||
|
||||
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
||||
const albumNameCache = new Map<string, Promise<string>>();
|
||||
|
|
@ -239,6 +239,16 @@
|
|||
{@render badge($t('album'), `"${truncate(albumName)}"`)}
|
||||
{/await}
|
||||
{/each}
|
||||
{:else if getUiHint(key) === 'TagId'}
|
||||
{#each toIds(value) as tagId (tagId)}
|
||||
{#await getTagById({ id: tagId })}
|
||||
{@render badge($t('tag'), '…')}
|
||||
{:then tag}
|
||||
{@render badge($t('tag'), `"${truncate(tag.name)}"`)}
|
||||
{:catch}
|
||||
{@render badge($t('tag'), `"${truncate(tagId)}"`)}
|
||||
{/await}
|
||||
{/each}
|
||||
{:else}
|
||||
{@render badge(key, formatConfigValue(value))}
|
||||
{/if}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue