add freeze feature to rundown (#1106)

* add frozen flag to runtime store

* add middleware for when frozen

* prevent rundown editing when frozen

* add endpoint to router to set frozen state

* add frozen property to rundown placeholder in client
This commit is contained in:
2024-07-19 07:14:59 -05:00
committed by GitHub
parent edc7f20d7a
commit e6e00c0d4a
8 changed files with 48 additions and 4 deletions
+1
View File
@@ -48,6 +48,7 @@ export const runtimeStorePlaceholder: RuntimeStore = {
duration: 0, duration: 0,
playback: SimplePlayback.Stop, playback: SimplePlayback.Stop,
}, },
frozen: false,
}; };
const deepCompare = <T>(a: T, b: T) => isEqual(a, b); const deepCompare = <T>(a: T, b: T) => isEqual(a, b);
@@ -12,6 +12,7 @@ import {
deleteEvent, deleteEvent,
editEvent, editEvent,
reorderEvent, reorderEvent,
setFrozenState,
swapEvents, swapEvents,
} from '../../services/rundown-service/RundownService.js'; } from '../../services/rundown-service/RundownService.js';
import { import {
@@ -114,6 +115,17 @@ export async function rundownBatchPut(req: Request, res: Response<MessageRespons
} }
} }
export async function rundownFrozenPost(req: Request, res: Response<MessageResponse | ErrorResponse>) {
try {
const { frozen } = req.body;
setFrozenState(frozen);
res.status(200).send({ message: 'Rundown frozen state updated.' });
} catch (error) {
const message = getErrorMessage(error);
res.status(400).send({ message });
}
}
export async function rundownReorder(req: Request, res: Response<OntimeRundownEntry | ErrorResponse>) { export async function rundownReorder(req: Request, res: Response<OntimeRundownEntry | ErrorResponse>) {
if (failEmptyObjects(req.body, res)) { if (failEmptyObjects(req.body, res)) {
return; return;
@@ -0,0 +1,9 @@
import { eventStore } from '../../stores/EventStore.js';
export const preventIfFrozen = function (req, res, next) {
if (eventStore.get('frozen')) {
res.status(403).send({ message: 'Rundown is frozen' });
} else {
next();
}
};
@@ -5,6 +5,7 @@ import {
rundownApplyDelay, rundownApplyDelay,
rundownBatchPut, rundownBatchPut,
rundownDelete, rundownDelete,
rundownFrozenPost,
rundownGetById, rundownGetById,
rundownGetNormalised, rundownGetNormalised,
rundownGetPaginated, rundownGetPaginated,
@@ -17,12 +18,14 @@ import {
paramsMustHaveEventId, paramsMustHaveEventId,
rundownArrayOfIds, rundownArrayOfIds,
rundownBatchPutValidator, rundownBatchPutValidator,
rundownFrozenPostValidator,
rundownGetPaginatedQueryParams, rundownGetPaginatedQueryParams,
rundownPostValidator, rundownPostValidator,
rundownPutValidator, rundownPutValidator,
rundownReorderValidator, rundownReorderValidator,
rundownSwapValidator, rundownSwapValidator,
} from './rundown.validation.js'; } from './rundown.validation.js';
import { preventIfFrozen } from './rundown.middleware.js';
export const router = express.Router(); export const router = express.Router();
@@ -31,13 +34,14 @@ router.get('/normalised', rundownGetNormalised);
router.get('/:eventId', paramsMustHaveEventId, rundownGetById); // not used in Ontime frontend router.get('/:eventId', paramsMustHaveEventId, rundownGetById); // not used in Ontime frontend
router.post('/', rundownPostValidator, rundownPost); router.post('/', rundownPostValidator, rundownPost);
router.post('/frozen', rundownFrozenPostValidator, rundownFrozenPost);
router.put('/', rundownPutValidator, rundownPut); router.put('/', rundownPutValidator, rundownPut);
router.put('/batch', rundownBatchPutValidator, rundownBatchPut); router.put('/batch', rundownBatchPutValidator, rundownBatchPut);
router.patch('/reorder/', rundownReorderValidator, rundownReorder); router.patch('/reorder/', rundownReorderValidator, preventIfFrozen, rundownReorder);
router.patch('/swap', rundownSwapValidator, rundownSwap); router.patch('/swap', rundownSwapValidator, preventIfFrozen, rundownSwap);
router.patch('/applydelay/:eventId', paramsMustHaveEventId, rundownApplyDelay); router.patch('/applydelay/:eventId', paramsMustHaveEventId, rundownApplyDelay);
router.delete('/', rundownArrayOfIds, deletesEventById); router.delete('/', rundownArrayOfIds, preventIfFrozen, deletesEventById);
router.delete('/all', rundownDelete); router.delete('/all', preventIfFrozen, rundownDelete);
@@ -21,6 +21,15 @@ export const rundownPutValidator = [
}, },
]; ];
export const rundownFrozenPostValidator = [
body('frozen').isBoolean().exists(),
(req: Request, res: Response, next: NextFunction) => {
const errors = validationResult(req);
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
next();
},
]
export const rundownBatchPutValidator = [ export const rundownBatchPutValidator = [
body('data').isObject().exists(), body('data').isObject().exists(),
body('ids').isArray().exists(), body('ids').isArray().exists(),
+1
View File
@@ -188,6 +188,7 @@ export const startServer = async (
playback: SimplePlayback.Stop, playback: SimplePlayback.Stop,
direction: SimpleDirection.CountDown, direction: SimpleDirection.CountDown,
}, },
frozen: false,
}); });
// initialise logging service, escalateErrorFn is only exists in electron // initialise logging service, escalateErrorFn is only exists in electron
@@ -21,6 +21,7 @@ import { runtimeService } from '../runtime-service/RuntimeService.js';
import * as cache from './rundownCache.js'; import * as cache from './rundownCache.js';
import { getPlayableEvents } from './rundownUtils.js'; import { getPlayableEvents } from './rundownUtils.js';
import { eventStore } from '../../stores/EventStore.js';
type PatchWithId = (Partial<OntimeEvent> | Partial<OntimeBlock> | Partial<OntimeDelay>) & { id: string }; type PatchWithId = (Partial<OntimeEvent> | Partial<OntimeBlock> | Partial<OntimeDelay>) & { id: string };
@@ -262,3 +263,7 @@ export async function initRundown(rundown: Readonly<OntimeRundown>, customFields
// notify timer of change // notify timer of change
notifyChanges({ timer: true }); notifyChanges({ timer: true });
} }
export async function setFrozenState(state: boolean) {
eventStore.set('frozen', state);
}
@@ -22,4 +22,7 @@ export type RuntimeStore = {
// extra timers // extra timers
auxtimer1: SimpleTimerState; auxtimer1: SimpleTimerState;
// flags
frozen: boolean;
}; };