refactor: allow filtering schedule

This commit is contained in:
Carlos Valente
2025-09-17 06:27:25 +02:00
committed by Carlos Valente
parent 8d2db7ffcd
commit a8fe8b5f1e
3 changed files with 31 additions and 23 deletions
@@ -10,13 +10,14 @@ import {
makeProjectDataOptions, makeProjectDataOptions,
} from '../../common/components/view-params-editor/viewParams.utils'; } from '../../common/components/view-params-editor/viewParams.utils';
import { PresetContext } from '../../common/context/PresetContext'; import { PresetContext } from '../../common/context/PresetContext';
import { scheduleOptions } from '../common/schedule/schedule.options'; import { getScheduleOptions } from '../common/schedule/schedule.options';
export const getBackstageOptions = ( export const getBackstageOptions = (
timeFormat: string, timeFormat: string,
customFields: CustomFields, customFields: CustomFields,
projectData: ProjectData, projectData: ProjectData,
): ViewOption[] => { ): ViewOption[] => {
const customFieldOptions = makeOptionsFromCustomFields(customFields, []);
const secondaryOptions = makeOptionsFromCustomFields(customFields, [ const secondaryOptions = makeOptionsFromCustomFields(customFields, [
{ value: 'none', label: 'None' }, { value: 'none', label: 'None' },
{ value: 'note', label: 'Note' }, { value: 'note', label: 'Note' },
@@ -39,7 +40,7 @@ export const getBackstageOptions = (
}, },
], ],
}, },
scheduleOptions, getScheduleOptions(customFieldOptions),
{ {
title: OptionTitle.ElementVisibility, title: OptionTitle.ElementVisibility,
collapsible: true, collapsible: true,
@@ -1,14 +1,5 @@
import { import { createContext, PropsWithChildren, RefObject, use, useEffect, useLayoutEffect, useRef, useState } from 'react';
createContext, import { EntryId, isOntimeEvent, OntimeEntry, OntimeEvent } from 'ontime-types';
PropsWithChildren,
RefObject,
useContext,
useEffect,
useLayoutEffect,
useRef,
useState,
} from 'react';
import { isOntimeEvent, OntimeEntry, OntimeEvent } from 'ontime-types';
import { usePartialRundown } from '../../../common/hooks-query/useRundown'; import { usePartialRundown } from '../../../common/hooks-query/useRundown';
@@ -25,13 +16,18 @@ interface ScheduleContextState {
const ScheduleContext = createContext<ScheduleContextState | undefined>(undefined); const ScheduleContext = createContext<ScheduleContextState | undefined>(undefined);
interface ScheduleProviderProps { interface ScheduleProviderProps {
selectedEventId: string | null; selectedEventId: EntryId | null;
} }
export const ScheduleProvider = ({ children, selectedEventId }: PropsWithChildren<ScheduleProviderProps>) => { export const ScheduleProvider = ({ children, selectedEventId }: PropsWithChildren<ScheduleProviderProps>) => {
const { cycleInterval, stopCycle } = useScheduleOptions(); const { cycleInterval, stopCycle, filter } = useScheduleOptions();
const { data: events } = usePartialRundown((event: OntimeEntry) => { const { data: events } = usePartialRundown((entry: OntimeEntry) => {
return isOntimeEvent(event); if (filter) {
// custom keys are prepended with custom-
const customKey = filter.startsWith('custom-') ? filter.slice('custom-'.length) : filter;
return isOntimeEvent(entry) && Boolean(entry.custom[customKey]);
}
return isOntimeEvent(entry);
}); });
const [firstIndex, setFirstIndex] = useState(-1); const [firstIndex, setFirstIndex] = useState(-1);
@@ -135,7 +131,7 @@ export const ScheduleProvider = ({ children, selectedEventId }: PropsWithChildre
selectedEventIndex = 0; selectedEventIndex = 0;
return ( return (
<ScheduleContext.Provider <ScheduleContext
value={{ value={{
events: viewEvents as OntimeEvent[], events: viewEvents as OntimeEvent[],
selectedEventId, selectedEventId,
@@ -145,12 +141,12 @@ export const ScheduleProvider = ({ children, selectedEventId }: PropsWithChildre
}} }}
> >
{children} {children}
</ScheduleContext.Provider> </ScheduleContext>
); );
}; };
export const useSchedule = () => { export const useSchedule = () => {
const context = useContext(ScheduleContext); const context = use(ScheduleContext);
if (!context) { if (!context) {
throw new Error('useSchedule() can only be used inside a ScheduleContext'); throw new Error('useSchedule() can only be used inside a ScheduleContext');
} }
@@ -1,14 +1,23 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useSearchParams } from 'react-router'; import { useSearchParams } from 'react-router';
import { SelectOption } from '../../../common/components/select/Select';
import { OptionTitle } from '../../../common/components/view-params-editor/constants'; import { OptionTitle } from '../../../common/components/view-params-editor/constants';
import { ViewOption } from '../../../common/components/view-params-editor/viewParams.types'; import type { ViewOption } from '../../../common/components/view-params-editor/viewParams.types';
import { isStringBoolean } from '../../../features/viewers/common/viewUtils'; import { isStringBoolean } from '../../../features/viewers/common/viewUtils';
export const scheduleOptions: ViewOption = { export const getScheduleOptions = (customFieldOptions: SelectOption[]): ViewOption => ({
title: OptionTitle.Schedule, title: OptionTitle.Schedule,
collapsible: true, collapsible: true,
options: [ options: [
{
id: 'filter',
title: 'Filter',
description: 'Hide events without data in the selected custom field',
type: 'option',
values: customFieldOptions,
defaultValue: 'None',
},
{ {
id: 'stopCycle', id: 'stopCycle',
title: 'Stop cycling through event pages', title: 'Stop cycling through event pages',
@@ -31,9 +40,10 @@ export const scheduleOptions: ViewOption = {
defaultValue: false, defaultValue: false,
}, },
], ],
}; });
type ScheduleOptions = { type ScheduleOptions = {
filter: string | null;
cycleInterval: number; cycleInterval: number;
stopCycle: boolean; stopCycle: boolean;
showExpected: boolean; showExpected: boolean;
@@ -41,6 +51,7 @@ type ScheduleOptions = {
function getScheduleOptionsFromParams(searchParams: URLSearchParams): ScheduleOptions { function getScheduleOptionsFromParams(searchParams: URLSearchParams): ScheduleOptions {
return { return {
filter: searchParams.get('filter'),
cycleInterval: Number(searchParams.get('cycleInterval')) || 10, cycleInterval: Number(searchParams.get('cycleInterval')) || 10,
stopCycle: isStringBoolean(searchParams.get('stopCycle')), stopCycle: isStringBoolean(searchParams.get('stopCycle')),
showExpected: isStringBoolean(searchParams.get('showExpected')), showExpected: isStringBoolean(searchParams.get('showExpected')),