feat(slideshow): per-event play order + category filter (#202)
The Live Slideshow already covers the core of #202 (fullscreen kiosk, live-appending new uploads, timing/transitions/watermark, per-event opt-in via the share link). This adds the two customization dimensions the reporter also asked for: - **Play order** (show_order): 'chronological' (upload order, default) or 'random' — the client shuffles the initial set (Fisher-Yates) so live-appended uploads keep working. - **Category filter** (show_category_id): restrict the slideshow to a single photo category (NULL = all photos, default). Enforced server-side on the slideshow /photos access and mirrored in the /session + /state photo_count, so the kiosk viewer can't widen the set. Per-event enable/disable (default off) is unchanged — it's the existing 'Generate/Disable slideshow link' flow (no token = no slideshow). - Migration 158: show_order (default 'chronological') + show_category_id. - Admin: Play-order dropdown + category picker in the Live Slideshow card (picker hidden for events without categories); EN + DE i18n. - Verified: migration (SQLite + PG); live API (category filter → 3/2/5 photos + matching count; order propagates) and the running kiosk requests exactly the filtered set; tsc clean, 136 backend tests pass.
This commit is contained in:
@@ -158,6 +158,8 @@ export const eventsService = {
|
||||
show_transition_ms?: number;
|
||||
show_watermark?: boolean | null;
|
||||
show_colorfilter?: string;
|
||||
show_order?: string;
|
||||
show_category_id?: number | null;
|
||||
}
|
||||
): Promise<Record<string, unknown>> {
|
||||
const response = await api.patch(`/admin/events/${id}/slideshow`, settings);
|
||||
|
||||
@@ -18,6 +18,9 @@ export const SLIDESHOW_WATERMARK_STYLES: SlideshowWatermarkStyle[] = ['white', '
|
||||
// (admin Settings → Slideshow); 'on'/'off' = explicit override.
|
||||
export type SlideshowWatermarkMode = 'inherit' | 'on' | 'off';
|
||||
export const SLIDESHOW_WATERMARK_MODES: SlideshowWatermarkMode[] = ['inherit', 'on', 'off'];
|
||||
// Play order (#202): 'chronological' = upload order; 'random' = client shuffle.
|
||||
export type SlideshowOrder = 'chronological' | 'random';
|
||||
export const SLIDESHOW_ORDERS: SlideshowOrder[] = ['chronological', 'random'];
|
||||
|
||||
export const SLIDESHOW_TRANSITIONS: SlideshowTransition[] = ['crossfade', 'cut', 'slide', 'kenburns', 'dipwhite', 'dipblack'];
|
||||
export const SLIDESHOW_COLORFILTERS: SlideshowColorFilter[] = ['none', 'bw', 'sepia', 'warm', 'cool', 'vignette'];
|
||||
@@ -37,6 +40,9 @@ export interface SlideshowStyle {
|
||||
transition_ms: number;
|
||||
watermark: SlideshowWatermarkMode;
|
||||
colorfilter: SlideshowColorFilter;
|
||||
// Play order + optional category filter (#202). category_id null = all photos.
|
||||
order: SlideshowOrder;
|
||||
category_id: number | null;
|
||||
}
|
||||
|
||||
export const DEFAULT_SLIDESHOW_STYLE: SlideshowStyle = {
|
||||
@@ -45,6 +51,8 @@ export const DEFAULT_SLIDESHOW_STYLE: SlideshowStyle = {
|
||||
transition_ms: 800,
|
||||
watermark: 'inherit',
|
||||
colorfilter: 'none',
|
||||
order: 'chronological',
|
||||
category_id: null,
|
||||
};
|
||||
|
||||
// Global slideshow defaults (admin Settings → Slideshow). The single source of
|
||||
@@ -81,6 +89,10 @@ export interface SlideshowSettings {
|
||||
transition: SlideshowTransition;
|
||||
transition_ms: number;
|
||||
colorfilter: SlideshowColorFilter;
|
||||
// Play order the kiosk applies (#202): 'random' shuffles client-side so
|
||||
// live-appended uploads keep working. The category filter is enforced
|
||||
// server-side, so it isn't echoed here.
|
||||
order: SlideshowOrder;
|
||||
fit: SlideshowFit;
|
||||
watermark: SlideshowWatermark | null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user