diff --git a/apps/client/src/views/countdown/Countdown.tsx b/apps/client/src/views/countdown/Countdown.tsx index e7d665c90..ee49a6e8d 100644 --- a/apps/client/src/views/countdown/Countdown.tsx +++ b/apps/client/src/views/countdown/Countdown.tsx @@ -1,6 +1,6 @@ import { useMemo, useState } from 'react'; import { IoAdd } from 'react-icons/io5'; -import { EntryId, isOntimeEvent, isPlayableEvent, OntimeEvent, OntimeView } from 'ontime-types'; +import { isOntimeEvent, isPlayableEvent, OntimeEvent, OntimeView } from 'ontime-types'; import Button from '../../common/components/buttons/Button'; import Empty from '../../common/components/state/Empty'; @@ -16,7 +16,7 @@ import { useTranslation } from '../../translation/TranslationProvider'; import Loader from '../common/loader/Loader'; import { getCountdownOptions, useCountdownOptions } from './countdown.options'; -import { getOrderedSubscriptions } from './countdown.utils'; +import { CountdownSubscription, getOrderedSubscriptions } from './countdown.utils'; import CountdownSelect from './CountdownSelect'; import CountdownSubscriptions from './CountdownSubscriptions'; import SingleEventCountdown from './SingleEventCountdown'; @@ -59,6 +59,8 @@ function Countdown({ customFields, rundownData, projectData, isMirrored, setting [defaultFormat, customFields, subscriptions], ); + console.log(subscriptions) + return (
@@ -87,7 +89,7 @@ function Countdown({ customFields, rundownData, projectData, isMirrored, setting interface CountdownContentsProps { playableEvents: ExtendedEntry[]; - subscriptions: EntryId[]; + subscriptions: CountdownSubscription; goToEditMode: () => void; } diff --git a/apps/client/src/views/countdown/CountdownSelect.tsx b/apps/client/src/views/countdown/CountdownSelect.tsx index a14131e0f..920b8a7f2 100644 --- a/apps/client/src/views/countdown/CountdownSelect.tsx +++ b/apps/client/src/views/countdown/CountdownSelect.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { IoArrowBack, IoClose, IoSaveOutline } from 'react-icons/io5'; +import { IoArrowBack, IoClose, IoSaveOutline, IoAlbumsOutline } from 'react-icons/io5'; import { useNavigate } from 'react-router'; import { EntryId, OntimeEvent } from 'ontime-types'; @@ -7,18 +7,19 @@ import Button from '../../common/components/buttons/Button'; import { cx } from '../../common/utils/styleUtils'; import ClockTime from '../../features/viewers/common/clock-time/ClockTime'; -import { makeSubscriptionsUrl } from './countdown.utils'; +import { CountdownSubscription, makeSubscriptionsUrl } from './countdown.utils'; import './Countdown.scss'; interface CountdownSelectProps { events: OntimeEvent[]; - subscriptions: EntryId[]; + subscriptions: CountdownSubscription; disableEdit: () => void; } export default function CountdownSelect({ events, subscriptions, disableEdit }: CountdownSelectProps) { - const [selected, setSelected] = useState(subscriptions); + const maybeAllSubscriptions: EntryId[] = subscriptions === 'all' ? events.map((event) => event.id) : subscriptions; + const [selected, setSelected] = useState(maybeAllSubscriptions); const navigate = useNavigate(); /** @@ -47,6 +48,18 @@ export default function CountdownSelect({ events, subscriptions, disableEdit }: navigate(url.search.toString()); }; + /** + * Creates a URL with all + * and navigates to it + */ + const applyAll = () => { + // we remove events that no longer exist to avoid stale subscriptions + const url = makeSubscriptionsUrl(window.location.href, 'all'); + disableEdit(); + setSelected([]); + navigate(url.search.toString()); + }; + // make a copy of the selected array for quick lookup const selectedIds = new Set(selected); @@ -86,6 +99,10 @@ export default function CountdownSelect({ events, subscriptions, disableEdit }: + diff --git a/apps/client/src/views/countdown/countdown.options.ts b/apps/client/src/views/countdown/countdown.options.ts index 1cb11c33e..edd2506cb 100644 --- a/apps/client/src/views/countdown/countdown.options.ts +++ b/apps/client/src/views/countdown/countdown.options.ts @@ -8,11 +8,12 @@ import { ViewOption } from '../../common/components/view-params-editor/viewParam import { makeOptionsFromCustomFields } from '../../common/components/view-params-editor/viewParams.utils'; import { PresetContext } from '../../common/context/PresetContext'; import { isStringBoolean } from '../../features/viewers/common/viewUtils'; +import { CountdownSubscription } from './countdown.utils'; export const getCountdownOptions = ( timeFormat: string, customFields: CustomFields, - persistedSubscriptions: EntryId[], + persistedSubscriptions: CountdownSubscription, ): ViewOption[] => { const secondaryOptions = makeOptionsFromCustomFields(customFields, [ { value: 'none', label: 'None' }, @@ -55,7 +56,7 @@ export const getCountdownOptions = ( id: 'sub', title: 'Event subscription', description: 'The events to follow', - values: persistedSubscriptions, + values: persistedSubscriptions === 'all' ? ['all'] : persistedSubscriptions, type: 'persist', }, ], @@ -64,7 +65,7 @@ export const getCountdownOptions = ( }; type CountdownOptions = { - subscriptions: EntryId[]; + subscriptions: CountdownSubscription; secondarySource: keyof OntimeEvent | null; showExpected: boolean; }; @@ -85,8 +86,10 @@ function getOptionsFromParams(searchParams: URLSearchParams, defaultValues?: URL return searchParams.getAll(key) as EntryId[]; }; + const subscriptions = getArrayValues('sub'); + return { - subscriptions: getArrayValues('sub'), + subscriptions: subscriptions.at(0) === 'all' ? 'all' : subscriptions, secondarySource: getValue('secondary-src') as keyof OntimeEvent | null, showExpected: isStringBoolean(getValue('showExpected')), }; diff --git a/apps/client/src/views/countdown/countdown.utils.ts b/apps/client/src/views/countdown/countdown.utils.ts index 12d825bbd..63b043833 100644 --- a/apps/client/src/views/countdown/countdown.utils.ts +++ b/apps/client/src/views/countdown/countdown.utils.ts @@ -14,6 +14,8 @@ export function sanitiseTitle(title: string | null) { return title ?? '{no title}'; } +export type CountdownSubscription = EntryId[] | 'all'; + export const preferredFormat12 = 'h:mm a'; export const preferredFormat24 = 'HH:mm'; @@ -120,7 +122,7 @@ export function useSubscriptionDisplayData( /** * Adds a set of subscriptions to the URL parameters */ -export function makeSubscriptionsUrl(urlRef: string, subscriptions: EntryId[]) { +export function makeSubscriptionsUrl(urlRef: string, subscriptions: CountdownSubscription) { const url = new URL(urlRef); const newParams = new URLSearchParams(); @@ -131,10 +133,14 @@ export function makeSubscriptionsUrl(urlRef: string, subscriptions: EntryId[]) { } } - // add new subscriptions - subscriptions.forEach((id) => { - newParams.append('sub', id); - }); + if (subscriptions === 'all') { + newParams.append('sub', 'all'); + } else { + // add new subscriptions + subscriptions.forEach((id) => { + newParams.append('sub', id); + }); + } url.search = newParams.toString(); @@ -146,7 +152,11 @@ export function makeSubscriptionsUrl(urlRef: string, subscriptions: EntryId[]) { * Since the original array is already ordered, we simply filter out the events * which are not in the subscriptions list. */ -export function getOrderedSubscriptions(subscriptions: EntryId[], playableEvents: T[]): T[] { +export function getOrderedSubscriptions( + subscriptions: CountdownSubscription, + playableEvents: T[], +): T[] { + if (subscriptions === 'all') return playableEvents; return playableEvents.filter((event) => subscriptions.includes(event.id)); }