Files
ontime/apps/client/src/features/operator/operator.options.tsx
T
2025-12-21 13:32:12 +01:00

134 lines
4.4 KiB
TypeScript

import { use, useMemo } from 'react';
import { useSearchParams } from 'react-router';
import { CustomFields, EntryId, OntimeEvent } from 'ontime-types';
import { getTimeOption } from '../../common/components/view-params-editor/common.options';
import { OptionTitle } from '../../common/components/view-params-editor/constants';
import { ViewOption } from '../../common/components/view-params-editor/viewParams.types';
import {
makeCustomFieldSelectOptions,
makeOptionsFromCustomFields,
} from '../../common/components/view-params-editor/viewParams.utils';
import { PresetContext } from '../../common/context/PresetContext';
import { isStringBoolean } from '../../views/common/viewUtils';
export const getOperatorOptions = (customFields: CustomFields, timeFormat: string): ViewOption[] => {
const fieldOptions = makeOptionsFromCustomFields(customFields, [
{ value: 'none', label: 'None' },
{ value: 'title', label: 'Title' },
{ value: 'note', label: 'Note' },
]);
const customFieldSelect = makeCustomFieldSelectOptions(customFields);
return [
{ title: OptionTitle.ClockOptions, collapsible: true, options: [getTimeOption(timeFormat)] },
{
title: OptionTitle.DataSources,
collapsible: true,
options: [
{
id: 'main',
title: 'Main data field',
description: 'Field to be shown in the first line of text',
type: 'option',
values: fieldOptions,
defaultValue: 'title',
},
{
id: 'secondary-src',
title: 'Secondary data field',
description: 'Field to be shown in the second line of text',
type: 'option',
values: fieldOptions,
defaultValue: 'none',
},
{
id: 'subscribe',
title: 'Highlight Fields',
description: 'Choose custom fields to highlight',
type: 'multi-option',
values: customFieldSelect,
},
{
id: 'shouldEdit',
title: 'Edit custom field',
description: 'Allows editing an highlighted custom field by long pressing',
type: 'boolean',
defaultValue: false,
},
],
},
{
title: OptionTitle.ElementVisibility,
collapsible: true,
options: [
{
id: 'hidePast',
title: 'Hide Past Events',
description: 'Whether to hide events that have passed',
type: 'boolean',
defaultValue: false,
},
{
id: 'showStart',
title: 'Show planned start',
description: 'Whether to prepend the planned start to the items',
type: 'boolean',
defaultValue: false,
},
],
},
];
};
type OperatorOptions = {
mainSource: keyof OntimeEvent | null;
secondarySource: keyof OntimeEvent | null;
subscribe: string[];
shouldEdit: boolean;
hidePast: boolean;
showStart: boolean;
};
/**
* Utility extract the view options from URL Params
* the names and fallback are manually matched with timerOptions
*/
function getOptionsFromParams(searchParams: URLSearchParams, defaultValues?: URLSearchParams): OperatorOptions {
// Helper to get value from either source, prioritizing defaultValues
const getValue = (key: string) => defaultValues?.get(key) ?? searchParams.get(key);
// Helper to get array values from either source
const getArrayValues = (key: string): EntryId[] => {
if (defaultValues?.has(key)) {
return defaultValues.getAll(key) as EntryId[];
}
return searchParams.getAll(key) as EntryId[];
};
// we manually make an object that matches the key above
return {
mainSource: getValue('main') as keyof OntimeEvent | null,
secondarySource: getValue('secondary-src') as keyof OntimeEvent | null,
subscribe: getArrayValues('subscribe'),
shouldEdit: isStringBoolean(getValue('shouldEdit')),
hidePast: isStringBoolean(getValue('hidePast')),
showStart: isStringBoolean(getValue('showStart')),
};
}
/**
* Hook exposes the operator view options
*/
export function useOperatorOptions(): OperatorOptions {
const [searchParams] = useSearchParams();
const maybePreset = use(PresetContext);
const options = useMemo(() => {
const defaultValues = maybePreset ? new URLSearchParams(maybePreset.search) : undefined;
return getOptionsFromParams(searchParams, defaultValues);
}, [maybePreset, searchParams]);
return options;
}