refactor: freeze is view option

This commit is contained in:
Carlos Valente
2025-07-12 12:22:36 +02:00
parent 138c6523d2
commit d24d5c1365
17 changed files with 17 additions and 84 deletions
+13 -4
View File
@@ -2,14 +2,23 @@ import axios from 'axios';
import type { ViewSettings } from 'ontime-types'; import type { ViewSettings } from 'ontime-types';
import { apiEntryUrl } from './constants'; import { apiEntryUrl } from './constants';
const viewSettingsPath = apiEntryUrl + '/view-settings';
export async function getViewSettings() { const viewSettingsPath = `${apiEntryUrl}/view-settings`;
/**
* HTTP request to fetch view settings
* @returns
*/
export async function getViewSettings(): Promise<ViewSettings> {
const res = await axios.get(viewSettingsPath); const res = await axios.get(viewSettingsPath);
return res.data; return res.data;
} }
export async function postViewSettings(data: ViewSettings) { /**
* HTTP request to update view settings
* needs to update entire objects, not just a patch
*/
export async function postViewSettings(data: ViewSettings): Promise<ViewSettings> {
const res = await axios.post(viewSettingsPath, data); const res = await axios.post(viewSettingsPath, data);
return res.data as ViewSettings; return res.data;
} }
@@ -39,8 +39,6 @@ function ViewParamsEditor({ viewOptions }: EditFormDrawerProps) {
const newParamsObject = Object.fromEntries(new FormData(formEvent.currentTarget)); const newParamsObject = Object.fromEntries(new FormData(formEvent.currentTarget));
const newSearchParams = getURLSearchParamsFromObj(newParamsObject, viewOptions); const newSearchParams = getURLSearchParamsFromObj(newParamsObject, viewOptions);
console.log('New search params:', newParamsObject, newSearchParams.toString());
setSearchParams(newSearchParams); setSearchParams(newSearchParams);
}; };
@@ -2,8 +2,6 @@ import { ViewSettings } from 'ontime-types';
export const viewsSettingsPlaceholder: ViewSettings = { export const viewsSettingsPlaceholder: ViewSettings = {
dangerColor: '#ED3333', dangerColor: '#ED3333',
endMessage: '',
freezeEnd: false,
normalColor: '#ffffffcc', normalColor: '#ffffffcc',
overrideStyles: false, overrideStyles: false,
warningColor: '#FFAB33', warningColor: '#FFAB33',
@@ -7,7 +7,6 @@ import { maybeAxiosError } from '../../../../common/api/utils';
import Button from '../../../../common/components/buttons/Button'; import Button from '../../../../common/components/buttons/Button';
import Info from '../../../../common/components/info/Info'; import Info from '../../../../common/components/info/Info';
import { SwatchPickerRHF } from '../../../../common/components/input/colour-input/SwatchPicker'; import { SwatchPickerRHF } from '../../../../common/components/input/colour-input/SwatchPicker';
import Input from '../../../../common/components/input/input/Input';
import ExternalLink from '../../../../common/components/link/external-link/ExternalLink'; import ExternalLink from '../../../../common/components/link/external-link/ExternalLink';
import Switch from '../../../../common/components/switch/Switch'; import Switch from '../../../../common/components/switch/Switch';
import useViewSettings from '../../../../common/hooks-query/useViewSettings'; import useViewSettings from '../../../../common/hooks-query/useViewSettings';
@@ -26,7 +25,6 @@ export default function ViewSettings() {
control, control,
handleSubmit, handleSubmit,
setError, setError,
register,
reset, reset,
setValue, setValue,
watch, watch,
@@ -122,31 +120,6 @@ export default function ViewSettings() {
<SwatchPickerRHF name='dangerColor' control={control} /> <SwatchPickerRHF name='dangerColor' control={control} />
</Panel.ListItem> </Panel.ListItem>
</Panel.ListGroup> </Panel.ListGroup>
<Panel.ListGroup>
<Panel.ListItem>
<Panel.Field
title='Freeze timer on end'
description='When a timer hits 00:00:00, it freezes instead of going negative. It invalidates the End Message.'
/>
<Switch
size='large'
checked={watch('freezeEnd')}
onCheckedChange={(value: boolean) => setValue('freezeEnd', value, { shouldDirty: true })}
/>
</Panel.ListItem>
<Panel.ListItem>
<Panel.Field
title='End message'
description='Message for negative timers; applies only if the timer isn`t frozen on End. If no message is provided, it continues into negative time'
/>
<Input
maxLength={150}
style={{ width: '275px' }}
placeholder='Shown when timer reaches end'
{...register('endMessage')}
/>
</Panel.ListItem>
</Panel.ListGroup>
</Panel.Section> </Panel.Section>
</Panel.Card> </Panel.Card>
</Panel.Section> </Panel.Section>
@@ -126,28 +126,6 @@ export default function QuickStart({ isOpen, onClose }: QuickStartProps) {
/> />
</Panel.ListItem> </Panel.ListItem>
</Panel.ListGroup> </Panel.ListGroup>
<Panel.ListGroup>
<Panel.ListItem>
<Panel.Field
title='Freeze timer on end'
description='When a timer hits 00:00:00, it freezes instead of going negative. It invalidates the End Message.'
/>
<Switch
size='large'
name='viewSettings.freezeEnd'
checked={watch('viewSettings.freezeEnd')}
onCheckedChange={(checked) => setValue('viewSettings.freezeEnd', checked)}
/>
</Panel.ListItem>
<Panel.ListItem>
<Panel.Field
title='End message'
description='Message for negative timers; applies only if the timer isn`t frozen on End. If no message is provided, it continues into negative time'
/>
<Input maxLength={150} fluid placeholder='eg: Time is up!' {...register('viewSettings.endMessage')} />
</Panel.ListItem>
</Panel.ListGroup>
</form> </form>
} }
footerElements={ footerElements={
@@ -8,8 +8,4 @@ export const quickStartDefaults: QuickStartData = {
timeFormat: '24', timeFormat: '24',
language: 'en', language: 'en',
}, },
viewSettings: {
freezeEnd: false,
endMessage: '',
},
}; };
@@ -25,7 +25,7 @@ export default function TimerPreview() {
if (showTimerMessage) return 'Message'; if (showTimerMessage) return 'Message';
if (timerType === TimerType.None) return timerPlaceholder; if (timerType === TimerType.None) return timerPlaceholder;
if (phase === TimerPhase.Pending) return 'Standby to start'; if (phase === TimerPhase.Pending) return 'Standby to start';
if (phase === TimerPhase.Overtime && data.endMessage) return 'Custom end message'; if (phase === TimerPhase.Overtime) return 'Timer Overtime';
if (timerType === TimerType.Clock) return 'Clock'; if (timerType === TimerType.Clock) return 'Clock';
if (countToEnd) return 'Count to End'; if (countToEnd) return 'Count to End';
return 'Timer'; return 'Timer';
@@ -30,10 +30,6 @@ export const validateQuickProject = [
body('settings.timeFormat').optional().isIn(['12', '24']), body('settings.timeFormat').optional().isIn(['12', '24']),
body('settings.language').optional().isString().trim(), body('settings.language').optional().isString().trim(),
// ViewSettings fields
body('viewSettings.freezeEnd').optional().isBoolean(),
body('viewSettings.endMessage').optional().isString().trim(),
requestValidationFunction, requestValidationFunction,
]; ];
@@ -16,8 +16,6 @@ export function parseViewSettings(data: Partial<DatabaseModel>, emitError?: Erro
return { return {
dangerColor: data.viewSettings.dangerColor ?? dbModel.viewSettings.dangerColor, dangerColor: data.viewSettings.dangerColor ?? dbModel.viewSettings.dangerColor,
endMessage: data.viewSettings.endMessage ?? dbModel.viewSettings.endMessage,
freezeEnd: data.viewSettings.freezeEnd ?? dbModel.viewSettings.freezeEnd,
normalColor: data.viewSettings.normalColor ?? dbModel.viewSettings.normalColor, normalColor: data.viewSettings.normalColor ?? dbModel.viewSettings.normalColor,
overrideStyles: data.viewSettings.overrideStyles ?? dbModel.viewSettings.overrideStyles, overrideStyles: data.viewSettings.overrideStyles ?? dbModel.viewSettings.overrideStyles,
warningColor: data.viewSettings.warningColor ?? dbModel.viewSettings.warningColor, warningColor: data.viewSettings.warningColor ?? dbModel.viewSettings.warningColor,
@@ -18,17 +18,17 @@ router.post('/', validateViewSettings, async (req: Request, res: Response<ViewSe
try { try {
const newData = { const newData = {
dangerColor: req.body.dangerColor, dangerColor: req.body.dangerColor,
endMessage: req.body.endMessage,
freezeEnd: req.body.freezeEnd,
normalColor: req.body.normalColor, normalColor: req.body.normalColor,
overrideStyles: req.body.overrideStyles, overrideStyles: req.body.overrideStyles,
warningColor: req.body.warningColor, warningColor: req.body.warningColor,
} as ViewSettings; } as ViewSettings;
await getDataProvider().setViewSettings(newData); await getDataProvider().setViewSettings(newData);
res.status(200).send(newData);
setImmediate(() => { setImmediate(() => {
sendRefetch(RefetchKey.ViewSettings); sendRefetch(RefetchKey.ViewSettings);
}); });
res.status(200).send(newData);
} catch (error) { } catch (error) {
const message = getErrorMessage(error); const message = getErrorMessage(error);
res.status(400).send({ message }); res.status(400).send({ message });
@@ -6,8 +6,6 @@ import { requestValidationFunction } from '../validation-utils/validationFunctio
*/ */
export const validateViewSettings = [ export const validateViewSettings = [
body('dangerColor').isString().trim().withMessage('dangerColor value must be string'), body('dangerColor').isString().trim().withMessage('dangerColor value must be string'),
body('endMessage').isString().trim().withMessage('endMessage value must be string'),
body('freezeEnd').isBoolean().withMessage('freezeEnd value must be boolean'),
body('normalColor').isString().trim().withMessage('normalColor value must be string'), body('normalColor').isString().trim().withMessage('normalColor value must be string'),
body('overrideStyles').isBoolean().withMessage('overrideStyles value must be boolean'), body('overrideStyles').isBoolean().withMessage('overrideStyles value must be boolean'),
body('warningColor').isString().trim().withMessage('warningColor value must be string'), body('warningColor').isString().trim().withMessage('warningColor value must be string'),
-2
View File
@@ -35,8 +35,6 @@ export const dbModel: DatabaseModel = {
normalColor: '#ffffffcc', normalColor: '#ffffffcc',
warningColor: '#FFAB33', warningColor: '#FFAB33',
dangerColor: '#ED3333', dangerColor: '#ED3333',
freezeEnd: false,
endMessage: '',
}, },
urlPresets: [], urlPresets: [],
customFields: {}, customFields: {},
-2
View File
@@ -519,8 +519,6 @@ export const demoDb: DatabaseModel = {
}, },
viewSettings: { viewSettings: {
dangerColor: '#ED3333', dangerColor: '#ED3333',
endMessage: '',
freezeEnd: false,
normalColor: '#ffffffcc', normalColor: '#ffffffcc',
overrideStyles: false, overrideStyles: false,
warningColor: '#FFAB33', warningColor: '#FFAB33',
-2
View File
@@ -468,8 +468,6 @@
}, },
"viewSettings": { "viewSettings": {
"dangerColor": "#ED3333", "dangerColor": "#ED3333",
"endMessage": "",
"freezeEnd": false,
"normalColor": "#ffffffcc", "normalColor": "#ffffffcc",
"overrideStyles": false, "overrideStyles": false,
"warningColor": "#FFAB33" "warningColor": "#FFAB33"
-2
View File
@@ -485,8 +485,6 @@
}, },
"viewSettings": { "viewSettings": {
"dangerColor": "#ED3333", "dangerColor": "#ED3333",
"endMessage": "",
"freezeEnd": false,
"normalColor": "#ffffffcc", "normalColor": "#ffffffcc",
"overrideStyles": false, "overrideStyles": false,
"warningColor": "#FFAB33" "warningColor": "#FFAB33"
-1
View File
@@ -3,5 +3,4 @@ import { type DatabaseModel } from '../../definitions/DataModel.type.js';
export interface QuickStartData { export interface QuickStartData {
project: Pick<DatabaseModel['project'], 'title'>; project: Pick<DatabaseModel['project'], 'title'>;
settings: Pick<DatabaseModel['settings'], 'timeFormat' | 'language'>; settings: Pick<DatabaseModel['settings'], 'timeFormat' | 'language'>;
viewSettings: Pick<DatabaseModel['viewSettings'], 'freezeEnd' | 'endMessage'>;
} }
@@ -1,7 +1,5 @@
export type ViewSettings = { export type ViewSettings = {
dangerColor: string; dangerColor: string;
endMessage: string;
freezeEnd: boolean;
normalColor: string; normalColor: string;
overrideStyles: boolean; overrideStyles: boolean;
warningColor: string; warningColor: string;