mirror of
https://github.com/immich-app/immich.git
synced 2026-05-21 23:26:31 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 54d7b0feb9 |
@@ -2417,6 +2417,7 @@
|
|||||||
"use_browser_locale_description": "Format dates, times, and numbers based on your browser locale",
|
"use_browser_locale_description": "Format dates, times, and numbers based on your browser locale",
|
||||||
"use_current_connection": "Use current connection",
|
"use_current_connection": "Use current connection",
|
||||||
"use_custom_date_range": "Use custom date range instead",
|
"use_custom_date_range": "Use custom date range instead",
|
||||||
|
"use_template": "Use template",
|
||||||
"user": "User",
|
"user": "User",
|
||||||
"user_has_been_deleted": "This user has been deleted.",
|
"user_has_been_deleted": "This user has been deleted.",
|
||||||
"user_id": "User ID",
|
"user_id": "User ID",
|
||||||
@@ -2491,6 +2492,7 @@
|
|||||||
"workflow_name": "Workflow name",
|
"workflow_name": "Workflow name",
|
||||||
"workflow_navigation_prompt": "Are you sure you want to leave without saving your changes?",
|
"workflow_navigation_prompt": "Are you sure you want to leave without saving your changes?",
|
||||||
"workflow_summary": "Workflow summary",
|
"workflow_summary": "Workflow summary",
|
||||||
|
"workflow_templates": "Workflow templates",
|
||||||
"workflow_update_success": "Workflow updated successfully",
|
"workflow_update_success": "Workflow updated successfully",
|
||||||
"workflow_updated": "Workflow updated",
|
"workflow_updated": "Workflow updated",
|
||||||
"workflows": "Workflows",
|
"workflows": "Workflows",
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { workflowTemplates, type WorkflowTemplate } from '$lib/templates/workflow-templates';
|
||||||
|
import { FormModal, Icon, ListButton, Text } from '@immich/ui';
|
||||||
|
import { t } from 'svelte-i18n';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
onClose: (template?: WorkflowTemplate) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { onClose }: Props = $props();
|
||||||
|
|
||||||
|
let selected = $state<WorkflowTemplate>();
|
||||||
|
|
||||||
|
const onSubmit = () => onClose(selected);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<FormModal title={$t('workflow_templates')} {onClose} {onSubmit} disabled={!selected} size="medium">
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
{#each workflowTemplates as template (template.id)}
|
||||||
|
<ListButton selected={selected?.id === template.id} onclick={() => (selected = template)}>
|
||||||
|
<div class="flex w-full items-center gap-3 text-start">
|
||||||
|
<div
|
||||||
|
class="flex size-9 shrink-0 items-center justify-center rounded-lg bg-immich-primary/10 text-immich-primary dark:bg-immich-dark-primary/15 dark:text-immich-dark-primary"
|
||||||
|
>
|
||||||
|
<Icon icon={template.icon} size="18" />
|
||||||
|
</div>
|
||||||
|
<div class="min-w-0 grow">
|
||||||
|
<Text fontWeight="medium">{template.name}</Text>
|
||||||
|
<Text size="tiny" color="muted">{template.description}</Text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ListButton>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</FormModal>
|
||||||
@@ -10,10 +10,11 @@ import {
|
|||||||
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, mdiPlus } from '@mdi/js';
|
import { mdiCodeJson, mdiDelete, mdiFileDocumentMultipleOutline, mdiPause, mdiPencil, mdiPlay, mdiPlus } from '@mdi/js';
|
||||||
import type { MessageFormatter } from 'svelte-i18n';
|
import type { MessageFormatter } from 'svelte-i18n';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { eventManager } from '$lib/managers/event-manager.svelte';
|
import { eventManager } from '$lib/managers/event-manager.svelte';
|
||||||
|
import WorkflowTemplatePicker from '$lib/modals/WorkflowTemplatePicker.svelte';
|
||||||
import { Route } from '$lib/route';
|
import { Route } from '$lib/route';
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
import { getFormatter } from '$lib/utils/i18n';
|
import { getFormatter } from '$lib/utils/i18n';
|
||||||
@@ -33,7 +34,25 @@ export const getWorkflowsActions = ($t: MessageFormatter) => {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
return { Create };
|
const UseTemplate: ActionItem = {
|
||||||
|
title: $t('use_template'),
|
||||||
|
icon: mdiFileDocumentMultipleOutline,
|
||||||
|
onAction: async () => {
|
||||||
|
const template = await modalManager.show(WorkflowTemplatePicker, {});
|
||||||
|
if (!template) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await handleCreateWorkflow({
|
||||||
|
trigger: template.trigger,
|
||||||
|
steps: template.steps,
|
||||||
|
name: template.name,
|
||||||
|
description: template.description,
|
||||||
|
enabled: false,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return { Create, UseTemplate };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getWorkflowActions = ($t: MessageFormatter, workflow: WorkflowResponseDto) => {
|
export const getWorkflowActions = ($t: MessageFormatter, workflow: WorkflowResponseDto) => {
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import { WorkflowTrigger, type WorkflowStepDto } from '@immich/sdk';
|
||||||
|
import { mdiAccountGroupOutline, mdiMonitorScreenshot } from '@mdi/js';
|
||||||
|
|
||||||
|
export type WorkflowTemplate = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
icon: string;
|
||||||
|
trigger: WorkflowTrigger;
|
||||||
|
steps: WorkflowStepDto[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const workflowTemplates: WorkflowTemplate[] = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: 'Archive screenshots to album',
|
||||||
|
description: 'Add uploads with "screenshot" in the filename to an album and archive them',
|
||||||
|
icon: mdiMonitorScreenshot,
|
||||||
|
trigger: WorkflowTrigger.AssetCreate,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
method: 'immich-plugin-core#assetFileFilter',
|
||||||
|
config: {
|
||||||
|
pattern: 'screenshot',
|
||||||
|
matchType: 'contains',
|
||||||
|
caseSensitive: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'immich-plugin-core#assetAddToAlbums',
|
||||||
|
config: { albumIds: [] },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'immich-plugin-core#assetArchive',
|
||||||
|
config: { inverse: false },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
name: 'Add person to album',
|
||||||
|
description: 'Add assets to an album when a specific person is recognized',
|
||||||
|
icon: mdiAccountGroupOutline,
|
||||||
|
trigger: WorkflowTrigger.PersonRecognized,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
method: 'immich-plugin-core#filterPerson',
|
||||||
|
config: { personIds: [], matchAny: true },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'immich-plugin-core#assetAddToAlbums',
|
||||||
|
config: { albumIds: [] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const { Create } = $derived(getWorkflowsActions($t));
|
const { Create, UseTemplate } = $derived(getWorkflowsActions($t));
|
||||||
|
|
||||||
const onWorkflowCreate = async (response: WorkflowResponseDto) => {
|
const onWorkflowCreate = async (response: WorkflowResponseDto) => {
|
||||||
await goto(Route.viewWorkflow(response));
|
await goto(Route.viewWorkflow(response));
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
|
|
||||||
<OnEvents {onWorkflowCreate} {onWorkflowUpdate} {onWorkflowDelete} />
|
<OnEvents {onWorkflowCreate} {onWorkflowUpdate} {onWorkflowDelete} />
|
||||||
|
|
||||||
<UserPageLayout title={data.meta.title} actions={[Create]} scrollbar={false}>
|
<UserPageLayout title={data.meta.title} actions={[UseTemplate, Create]} scrollbar={false}>
|
||||||
<section class="flex place-content-center sm:mx-4">
|
<section class="flex place-content-center sm:mx-4">
|
||||||
<Container center size="large" class="pb-28">
|
<Container center size="large" class="pb-28">
|
||||||
{#if workflows.length === 0}
|
{#if workflows.length === 0}
|
||||||
|
|||||||
Reference in New Issue
Block a user