b61394f057
Dispatch: honor {kind}_collection_mode on TrackingConfig — "per_collection"
fans out one event per album; "combined" pools assets as before. Extract
build_immich_dispatch_events shared by cron and test paths.
Assets: collect_scheduled_assets attaches album_name/album_url/album_public_url
to each asset so combined-mode templates can attribute rows to their source
album. Default scheduled_assets templates render a multi-album header with
inline album list and per-row album link; memory_mode follows the same pattern.
UI: "Reset to default" buttons on notification and command template slots
(per-slot and whole-template), backed by new GET /*-template-configs/defaults
endpoints. tracking-configs "Preview template" now opens an inline preview
modal with locale tabs instead of navigating away; Edit button deep-links
with ?edit_slot=<name> so the destination auto-opens the config and scrolls
to the slot. Reset confirmations use ConfirmModal instead of window.confirm.
Fixes:
* NotificationDispatcher._session_ctx infinite recursion when no shared
aiohttp.ClientSession was passed — broke test dispatch for periodic/
scheduled/memory (cron path was unaffected).
* telegram-bots /chats/{id}/test now resolves chat.language_override /
language_code instead of using the raw ?locale query param, matching
the resolution the tracker-target test endpoint already used.
* scheduled_assets default template no longer emits a blank line between
header and the first asset when the multi-album branch is taken.
53 lines
2.1 KiB
Svelte
53 lines
2.1 KiB
Svelte
<script lang="ts">
|
|
import { t } from '$lib/i18n';
|
|
import MdiIcon from '$lib/components/MdiIcon.svelte';
|
|
|
|
interface Props {
|
|
testMenuOpen: string | null;
|
|
testMenuStyle: string;
|
|
ttTesting: Record<string, string>;
|
|
/**
|
|
* When `disabledReason` is set, the button is rendered greyed out with a
|
|
* tooltip pointing the user at the missing setting (e.g. "Enable Periodic
|
|
* Summary in Tracking Config first"). Clicking is blocked — clicking an
|
|
* unconfigured test would have surfaced as a silent server-side skip.
|
|
*/
|
|
testTypes: { key: string; icon: string; labelKey: string; disabledReason?: string }[];
|
|
ontest: (ttId: number, testType: string) => void;
|
|
onclose: () => void;
|
|
}
|
|
|
|
let { testMenuOpen, testMenuStyle, ttTesting, testTypes, ontest, onclose }: Props = $props();
|
|
</script>
|
|
|
|
{#if testMenuOpen}
|
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
<div style="position:fixed; top:0; left:0; right:0; bottom:0; z-index:9998;"
|
|
onclick={onclose}
|
|
onkeydown={(e) => { if (e.key === 'Escape') onclose(); }}>
|
|
</div>
|
|
<div style="{testMenuStyle} background:var(--color-card); border:1px solid var(--color-border); border-radius:0.5rem; box-shadow:0 10px 25px rgba(0,0,0,0.3); padding:0.25rem; min-width:12rem;">
|
|
{#each testTypes as tt}
|
|
{@const busy = !!ttTesting[`${testMenuOpen}_${tt.key}`]}
|
|
{@const blocked = !!tt.disabledReason}
|
|
<button
|
|
onclick={() => { if (!blocked) ontest(Number(testMenuOpen), tt.key); }}
|
|
disabled={busy || blocked}
|
|
title={blocked ? t(tt.disabledReason!) : ''}
|
|
class="flex items-center gap-2 w-full px-3 py-1.5 text-sm rounded hover:bg-[var(--color-muted)] transition-colors disabled:opacity-50 text-left">
|
|
<MdiIcon name={tt.icon} size={14} />
|
|
{t(tt.labelKey)}
|
|
{#if blocked}
|
|
<MdiIcon name="mdiLock" size={12} />
|
|
{/if}
|
|
{#if busy}
|
|
<span class="ml-auto text-xs text-[var(--color-muted-foreground)]">...</span>
|
|
{/if}
|
|
</button>
|
|
{#if blocked}
|
|
<p class="px-3 pb-1 text-[10px]" style="color: var(--color-muted-foreground);">{t(tt.disabledReason!)}</p>
|
|
{/if}
|
|
{/each}
|
|
</div>
|
|
{/if}
|