mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-15 20:33:47 +00:00
Default Values in ParamEditor (#610)
* add `defaultvalue` to `Field` types * add `defaultValue` to constants; turn into functions for time values * update constant imports/calls in view components * use `defaultValue`s in `ParamInput` * change `Clear` to `Reset`to better reflect actions * make `defaultValue` optional rather than `undefined` * update forgotten constants * add `defaultValue` to boolean input * change `101010` to `000000` * add `prefix` property to types * implement `prefix` for `ParamInput`s * change `paramField` to `prop` * add `onEditDrawerClose` to `resetParams` * `ViewParamsEditor` omits default values * undo close on reset * move `useSettings` into `ViewWrapper` * change `settings` to include `undefined`
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { Input, Select, Switch } from '@chakra-ui/react';
|
||||
import { Input, InputGroup, InputLeftElement, Select, Switch } from '@chakra-ui/react';
|
||||
|
||||
import { isStringBoolean } from '../../utils/viewUtils';
|
||||
|
||||
@@ -9,16 +9,22 @@ interface EditFormInputProps {
|
||||
paramField: ParamField;
|
||||
}
|
||||
|
||||
export default function ParamInput({ paramField }: EditFormInputProps) {
|
||||
export default function ParamInput(props: EditFormInputProps) {
|
||||
const [searchParams] = useSearchParams();
|
||||
const { id, type } = paramField;
|
||||
const { paramField } = props;
|
||||
const { id, type, defaultValue } = paramField;
|
||||
|
||||
if (type === 'option') {
|
||||
const optionFromParams = searchParams.get(id);
|
||||
const defaultOptionValue = optionFromParams || undefined;
|
||||
const defaultOptionValue = optionFromParams || defaultValue;
|
||||
|
||||
return (
|
||||
<Select placeholder='Select an option' variant='ontime' name={id} defaultValue={defaultOptionValue}>
|
||||
<Select
|
||||
placeholder={defaultValue ? undefined : 'Select an option'}
|
||||
variant='ontime'
|
||||
name={id}
|
||||
defaultValue={defaultOptionValue}
|
||||
>
|
||||
{Object.entries(paramField.values).map(([key, value]) => (
|
||||
<option key={key} value={key}>
|
||||
{value}
|
||||
@@ -29,19 +35,31 @@ export default function ParamInput({ paramField }: EditFormInputProps) {
|
||||
}
|
||||
|
||||
if (type === 'boolean') {
|
||||
const defaultCheckedValue = isStringBoolean(searchParams.get(id)) ?? false;
|
||||
const defaultCheckedValue = isStringBoolean(searchParams.get(id)) || defaultValue;
|
||||
|
||||
// checked value should be 'true', so it can be captured by the form event
|
||||
return <Switch variant='ontime' name={id} defaultChecked={defaultCheckedValue} value='true' />;
|
||||
}
|
||||
|
||||
if (type === 'number') {
|
||||
const defaultNumberValue = searchParams.get(id) ?? '';
|
||||
const { prefix } = paramField;
|
||||
const defaultNumberValue = searchParams.get(id) ?? defaultValue;
|
||||
|
||||
return <Input type='number' step='any' variant='ontime-filled' name={id} defaultValue={defaultNumberValue} />;
|
||||
return (
|
||||
<InputGroup variant='ontime-filled'>
|
||||
{prefix && <InputLeftElement pointerEvents='none'>{prefix}</InputLeftElement>}
|
||||
<Input type='number' step='any' variant='ontime-filled' name={id} defaultValue={defaultNumberValue} />
|
||||
</InputGroup>
|
||||
);
|
||||
}
|
||||
|
||||
const defaultStringValue = searchParams.get(id) ?? '';
|
||||
const defaultStringValue = searchParams.get(id) ?? defaultValue;
|
||||
const { prefix } = paramField;
|
||||
|
||||
return <Input variant='ontime-filled' name={id} defaultValue={defaultStringValue} />;
|
||||
return (
|
||||
<InputGroup variant='ontime-filled'>
|
||||
{prefix && <InputLeftElement pointerEvents='none'>{prefix}</InputLeftElement>}
|
||||
<Input name={id} defaultValue={defaultStringValue} />
|
||||
</InputGroup>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,9 +22,15 @@ import style from './ViewParamsEditor.module.scss';
|
||||
type ViewParamsObj = { [key: string]: string | FormDataEntryValue };
|
||||
type SavedViewParams = Record<string, ViewParamsObj>;
|
||||
|
||||
const getURLSearchParamsFromObj = (paramsObj: ViewParamsObj) =>
|
||||
Object.entries(paramsObj).reduce((newSearchParams, [id, value]) => {
|
||||
const getURLSearchParamsFromObj = (paramsObj: ViewParamsObj, paramFields: ParamField[]) => {
|
||||
const defaultValues = paramFields.map(({ defaultValue }) => String(defaultValue));
|
||||
|
||||
return Object.entries(paramsObj).reduce((newSearchParams, [id, value]) => {
|
||||
if (typeof value === 'string' && value.length) {
|
||||
if (defaultValues.includes(value)) {
|
||||
return newSearchParams;
|
||||
}
|
||||
|
||||
newSearchParams.set(id, value);
|
||||
|
||||
return newSearchParams;
|
||||
@@ -32,6 +38,7 @@ const getURLSearchParamsFromObj = (paramsObj: ViewParamsObj) =>
|
||||
|
||||
return newSearchParams;
|
||||
}, new URLSearchParams());
|
||||
};
|
||||
|
||||
interface EditFormDrawerProps {
|
||||
paramFields: ParamField[];
|
||||
@@ -72,31 +79,30 @@ export default function ViewParamsEditor({ paramFields }: EditFormDrawerProps) {
|
||||
|
||||
*/
|
||||
|
||||
const onEditDrawerClose = () => {
|
||||
const onCloseWithoutSaving = () => {
|
||||
onClose();
|
||||
|
||||
searchParams.delete('edit');
|
||||
setSearchParams(searchParams);
|
||||
};
|
||||
|
||||
const clearParams = () => {
|
||||
const resetParams = () => {
|
||||
setStoredViewParams({ ...storedViewParams, [pathname]: {} });
|
||||
setSearchParams();
|
||||
onClose();
|
||||
};
|
||||
|
||||
const onParamsFormSubmit = (formEvent: FormEvent<HTMLFormElement>) => {
|
||||
formEvent.preventDefault();
|
||||
|
||||
const newParamsObject = Object.fromEntries(new FormData(formEvent.currentTarget));
|
||||
const newSearchParams = getURLSearchParamsFromObj(newParamsObject);
|
||||
const newSearchParams = getURLSearchParamsFromObj(newParamsObject, paramFields);
|
||||
|
||||
setStoredViewParams({ ...storedViewParams, [pathname]: newParamsObject });
|
||||
setSearchParams(newSearchParams);
|
||||
};
|
||||
|
||||
return (
|
||||
<Drawer isOpen={isOpen} placement='right' onClose={onEditDrawerClose} size='lg'>
|
||||
<Drawer isOpen={isOpen} placement='right' onClose={onCloseWithoutSaving} size='lg'>
|
||||
<DrawerOverlay />
|
||||
<DrawerContent>
|
||||
<DrawerHeader className={style.drawerHeader}>
|
||||
@@ -119,10 +125,10 @@ export default function ViewParamsEditor({ paramFields }: EditFormDrawerProps) {
|
||||
</DrawerBody>
|
||||
|
||||
<DrawerFooter className={style.drawerFooter}>
|
||||
<Button variant='ontime-ghosted' onClick={clearParams} type='reset'>
|
||||
Clear
|
||||
<Button variant='ontime-ghosted' onClick={resetParams} type='reset'>
|
||||
Reset
|
||||
</Button>
|
||||
<Button variant='ontime-subtle' onClick={onEditDrawerClose}>
|
||||
<Button variant='ontime-subtle' onClick={onCloseWithoutSaving}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant='ontime-filled' form='edit-params-form' type='submit'>
|
||||
|
||||
@@ -1,46 +1,56 @@
|
||||
import { UserFields } from 'ontime-types';
|
||||
import { TimeFormat } from 'ontime-types/src/definitions/core/TimeFormat.type';
|
||||
|
||||
import { ParamField } from './types';
|
||||
|
||||
export const TIME_FORMAT_OPTION: ParamField = {
|
||||
export const getTimeOption = (timeFormat: TimeFormat): ParamField => ({
|
||||
id: 'format',
|
||||
title: '12 / 24 hour timer',
|
||||
description: 'Whether to show the time in 12 or 24 hour mode. Overrides the global setting from preferences',
|
||||
type: 'option',
|
||||
values: { '12': '12 hour AM/PM', '24': '24 hour' },
|
||||
};
|
||||
defaultValue: timeFormat,
|
||||
});
|
||||
|
||||
export const CLOCK_OPTIONS: ParamField[] = [
|
||||
TIME_FORMAT_OPTION,
|
||||
export const getClockOptions = (timeFormat: TimeFormat): ParamField[] => [
|
||||
getTimeOption(timeFormat),
|
||||
{
|
||||
id: 'key',
|
||||
title: 'Key Colour',
|
||||
description: 'Background colour in hexadecimal',
|
||||
prefix: '#',
|
||||
type: 'string',
|
||||
defaultValue: '00000000',
|
||||
},
|
||||
{
|
||||
id: 'text',
|
||||
title: 'Text Colour',
|
||||
description: 'Text colour in hexadecimal',
|
||||
prefix: '#',
|
||||
type: 'string',
|
||||
defaultValue: 'fffff',
|
||||
},
|
||||
{
|
||||
id: 'textbg',
|
||||
title: 'Text Background',
|
||||
description: 'Colour of text background in hexadecimal',
|
||||
prefix: '#',
|
||||
type: 'string',
|
||||
defaultValue: '00000000',
|
||||
},
|
||||
{
|
||||
id: 'font',
|
||||
title: 'Font',
|
||||
description: 'Font family, will use the fonts available in the system',
|
||||
type: 'string',
|
||||
defaultValue: 'Arial Black',
|
||||
},
|
||||
{
|
||||
id: 'size',
|
||||
title: 'Text Size',
|
||||
description: 'Scales the current style (0.5 = 50% 1 = 100% 2 = 200%)',
|
||||
type: 'number',
|
||||
defaultValue: 1,
|
||||
},
|
||||
{
|
||||
id: 'alignx',
|
||||
@@ -48,12 +58,14 @@ export const CLOCK_OPTIONS: ParamField[] = [
|
||||
description: 'Moves the horizontally in page to start = left | center | end = right',
|
||||
type: 'option',
|
||||
values: { start: 'Start', center: 'Center', end: 'End' },
|
||||
defaultValue: 'center',
|
||||
},
|
||||
{
|
||||
id: 'offsetx',
|
||||
title: 'Offset Horizontal',
|
||||
description: 'Offsets the timer horizontal position by a given amount in pixels',
|
||||
type: 'number',
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: 'aligny',
|
||||
@@ -61,46 +73,53 @@ export const CLOCK_OPTIONS: ParamField[] = [
|
||||
description: 'Moves the vertically in page to start = left | center | end = right',
|
||||
type: 'option',
|
||||
values: { start: 'Start', center: 'Center', end: 'End' },
|
||||
defaultValue: 'center',
|
||||
},
|
||||
{
|
||||
id: 'offsety',
|
||||
title: 'Offset Vertical',
|
||||
description: 'Offsets the timer vertical position by a given amount in pixels',
|
||||
type: 'number',
|
||||
defaultValue: 0,
|
||||
},
|
||||
];
|
||||
|
||||
export const TIMER_OPTIONS: ParamField[] = [
|
||||
TIME_FORMAT_OPTION,
|
||||
export const getTimerOptions = (timeFormat: TimeFormat): ParamField[] => [
|
||||
getTimeOption(timeFormat),
|
||||
{
|
||||
id: 'hideClock',
|
||||
title: 'Hide Time Now',
|
||||
description: 'Hides the Time Now field',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
id: 'hideCards',
|
||||
title: 'Hide Cards',
|
||||
description: 'Hides the Now and Next cards',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
id: 'hideProgress',
|
||||
title: 'Hide progress bar',
|
||||
description: 'Hides the progress bar',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
id: 'hideMessage',
|
||||
title: 'Hide Presenter Message',
|
||||
description: 'Prevents the screen from displaying messages from the presenter',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
id: 'hideExternal',
|
||||
title: 'Hide External',
|
||||
description: 'Prevents the screen from displaying the external field',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -109,31 +128,39 @@ export const MINIMAL_TIMER_OPTIONS: ParamField[] = [
|
||||
id: 'key',
|
||||
title: 'Key Colour',
|
||||
description: 'Background colour in hexadecimal',
|
||||
prefix: '#',
|
||||
type: 'string',
|
||||
defaultValue: '00000000',
|
||||
},
|
||||
{
|
||||
id: 'text',
|
||||
title: 'Text Colour',
|
||||
description: 'Text colour in hexadecimal',
|
||||
prefix: '#',
|
||||
type: 'string',
|
||||
defaultValue: 'fffff',
|
||||
},
|
||||
{
|
||||
id: 'textbg',
|
||||
title: 'Text Background',
|
||||
description: 'Colour of text background in hexadecimal',
|
||||
prefix: '#',
|
||||
type: 'string',
|
||||
defaultValue: '00000000',
|
||||
},
|
||||
{
|
||||
id: 'font',
|
||||
title: 'Font',
|
||||
description: 'Font family, will use the fonts available in the system',
|
||||
type: 'string',
|
||||
defaultValue: 'Arial Black',
|
||||
},
|
||||
{
|
||||
id: 'size',
|
||||
title: 'Text Size',
|
||||
description: 'Scales the current style (0.5 = 50% 1 = 100% 2 = 200%)',
|
||||
type: 'number',
|
||||
defaultValue: 1,
|
||||
},
|
||||
{
|
||||
id: 'alignx',
|
||||
@@ -141,12 +168,14 @@ export const MINIMAL_TIMER_OPTIONS: ParamField[] = [
|
||||
description: 'Moves the horizontally in page to start = left | center | end = right',
|
||||
type: 'option',
|
||||
values: { start: 'Start', center: 'Center', end: 'End' },
|
||||
defaultValue: 'center',
|
||||
},
|
||||
{
|
||||
id: 'offsetx',
|
||||
title: 'Offset Horizontal',
|
||||
description: 'Offsets the timer horizontal position by a given amount in pixels',
|
||||
type: 'number',
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: 'aligny',
|
||||
@@ -154,145 +183,162 @@ export const MINIMAL_TIMER_OPTIONS: ParamField[] = [
|
||||
description: 'Moves the vertically in page to start = left | center | end = right',
|
||||
type: 'option',
|
||||
values: { start: 'Start', center: 'Center', end: 'End' },
|
||||
defaultValue: 'center',
|
||||
},
|
||||
{
|
||||
id: 'offsety',
|
||||
title: 'Offset Vertical',
|
||||
description: 'Offsets the timer vertical position by a given amount in pixels',
|
||||
type: 'number',
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: 'hideovertime',
|
||||
title: 'Hide Overtime',
|
||||
description: 'Whether to suppress overtime styles (red borders and red text)',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
id: 'hidemessages',
|
||||
title: 'Hide Message Overlay',
|
||||
description: 'Whether to hide the overlay from showing timer screen messages',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
id: 'hideendmessage',
|
||||
title: 'Hide End Message',
|
||||
description: 'Whether to hide end message and continue showing the clock if timer is in overtime',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
];
|
||||
|
||||
export const LOWER_THIRDS_OPTIONS: ParamField[] = [
|
||||
{
|
||||
id: 'preset',
|
||||
title: 'Preset',
|
||||
description: 'Selects a style preset (0-1)',
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
id: 'size',
|
||||
title: 'Size',
|
||||
description: 'Scales the current style (0.5 = 50% 1 = 100% 2 = 200%)',
|
||||
type: 'number',
|
||||
defaultValue: 1,
|
||||
},
|
||||
{
|
||||
id: 'transition',
|
||||
title: 'Transition',
|
||||
description: 'Transition in time in seconds (default 5)',
|
||||
description: 'Transition in time in seconds (default 3)',
|
||||
type: 'number',
|
||||
defaultValue: 3,
|
||||
},
|
||||
{
|
||||
id: 'text',
|
||||
title: 'Text Colour',
|
||||
description: 'Text colour in hexadecimal',
|
||||
prefix: '#',
|
||||
type: 'string',
|
||||
defaultValue: '#fffffa',
|
||||
},
|
||||
{
|
||||
id: 'bg',
|
||||
title: 'Text Background',
|
||||
description: 'Text background colour in hexadecimal',
|
||||
prefix: '#',
|
||||
type: 'string',
|
||||
defaultValue: '00000033',
|
||||
},
|
||||
{
|
||||
id: 'key',
|
||||
title: 'Key Colour',
|
||||
description: 'Screen background colour in hexadecimal',
|
||||
prefix: '#',
|
||||
type: 'string',
|
||||
defaultValue: '00000033',
|
||||
},
|
||||
{
|
||||
id: 'fadeout',
|
||||
title: 'Fadeout',
|
||||
description: 'Time (in seconds) the lower third displays before fading out',
|
||||
type: 'number',
|
||||
defaultValue: 3,
|
||||
},
|
||||
];
|
||||
|
||||
export const BACKSTAGE_OPTIONS: ParamField[] = [
|
||||
TIME_FORMAT_OPTION,
|
||||
export const getBackstageOptions = (timeFormat: TimeFormat): ParamField[] => [
|
||||
getTimeOption(timeFormat),
|
||||
{
|
||||
id: 'hidePast',
|
||||
title: 'Hide past events',
|
||||
description: 'Scheduler will only show upcoming events',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
id: 'stopCycle',
|
||||
title: 'Stop cycling through event pages',
|
||||
description: 'Schedule will not auto-cycle through events',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
id: 'eventsPerPage',
|
||||
title: 'Events per page',
|
||||
description: 'Sets the number of events on the page, can cause overlow',
|
||||
type: 'number',
|
||||
defaultValue: 7,
|
||||
},
|
||||
];
|
||||
|
||||
export const PUBLIC_OPTIONS: ParamField[] = [
|
||||
TIME_FORMAT_OPTION,
|
||||
export const getPublicOptions = (timeFormat: TimeFormat): ParamField[] => [
|
||||
getTimeOption(timeFormat),
|
||||
{
|
||||
id: 'hidePast',
|
||||
title: 'Hide past events',
|
||||
description: 'Scheduler will only show upcoming events',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
id: 'stopCycle',
|
||||
title: 'Stop cycling through event pages',
|
||||
description: 'Schedule will not auto-cycle through events',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
id: 'eventsPerPage',
|
||||
title: 'Events per page',
|
||||
description: 'Sets the number of events on the page, can cause overlow',
|
||||
type: 'number',
|
||||
defaultValue: 7,
|
||||
},
|
||||
];
|
||||
export const STUDIO_CLOCK_OPTIONS: ParamField[] = [
|
||||
TIME_FORMAT_OPTION,
|
||||
export const getStudioClockOptions = (timeFormat: TimeFormat): ParamField[] => [
|
||||
getTimeOption(timeFormat),
|
||||
{
|
||||
id: 'seconds',
|
||||
title: 'Show Seconds',
|
||||
description: 'Shows seconds in clock',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
];
|
||||
|
||||
export const getOperatorOptions = (userFields: UserFields): ParamField[] => {
|
||||
export const getOperatorOptions = (userFields: UserFields, timeFormat: TimeFormat): ParamField[] => {
|
||||
return [
|
||||
TIME_FORMAT_OPTION,
|
||||
getTimeOption(timeFormat),
|
||||
{
|
||||
id: 'showseconds',
|
||||
title: 'Show seconds',
|
||||
description: 'Schedule shows hh:mm:ss',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
id: 'hidepast',
|
||||
title: 'Hide Past Events',
|
||||
description: 'Whether to events that have passed',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
id: 'main',
|
||||
|
||||
@@ -4,9 +4,13 @@ type BaseField = {
|
||||
description: string;
|
||||
};
|
||||
|
||||
type OptionsField = { type: 'option'; values: Record<string, string> };
|
||||
type StringField = { type: 'string' };
|
||||
type BooleanField = { type: 'boolean' };
|
||||
type NumberField = { type: 'number' };
|
||||
type OptionsField = {
|
||||
type: 'option';
|
||||
values: Record<string, string>;
|
||||
defaultValue?: string;
|
||||
};
|
||||
type StringField = { type: 'string'; defaultValue: string; prefix?: string };
|
||||
type NumberField = { type: 'number'; defaultValue: number; prefix?: string };
|
||||
type BooleanField = { type: 'boolean'; defaultValue: boolean };
|
||||
|
||||
export type ParamField = BaseField & (StringField | BooleanField | NumberField | OptionsField);
|
||||
|
||||
Reference in New Issue
Block a user