import axios, { AxiosResponse } from 'axios'; import { EntryId, OntimeEntry, OntimeEvent, ProjectRundownsList, RenumberCues, Rundown, RundownImportPayload, TransientEventPayload, } from 'ontime-types'; import { apiEntryUrl } from './constants'; import type { RequestOptions } from './requestOptions'; type RundownId = string; const rundownPath = `${apiEntryUrl}/rundowns`; // #region operations on project rundowns ========================= /** * HTTP request to fetch a list of existing rundowns */ export async function fetchProjectRundownList(options?: RequestOptions): Promise { const res = await axios.get(rundownPath, { signal: options?.signal }); return res.data; } /** * HTTP request to fetch all entries in the currently loaded rundown */ export async function fetchCurrentRundown(options?: RequestOptions): Promise { const res = await axios.get(`${rundownPath}/current`, { signal: options?.signal }); if (!isValidRundown(res.data)) { throw new Error('Invalid rundown payload'); } return res.data; } /** * HTTP request to fetch all entries in the given rundown */ export async function fetchRundown(rundownId: RundownId, options?: RequestOptions): Promise { const res = await axios.get(`${rundownPath}/${rundownId}`, { signal: options?.signal }); if (!isValidRundown(res.data)) { throw new Error('Invalid rundown payload'); } return res.data; } /** * HTTP request to switch the currently loaded rundown */ export async function loadRundown(rundownId: RundownId): Promise> { return axios.post(`${rundownPath}/${rundownId}/load`); } /** * HTTP request to create a new rundown */ export async function createRundown(title: string): Promise> { return axios.post(rundownPath, { title }); } /** * HTTP request to duplicate an existing rundown */ export async function duplicateRundown(rundownId: RundownId): Promise> { return axios.post(`${rundownPath}/${rundownId}/duplicate`); } /** * HTTP request to rename an existing rundown */ export async function renameRundown(rundownId: RundownId, title: string): Promise> { return axios.patch(`${rundownPath}/${rundownId}`, { title }); } /** * HTTP request to delete a rundown */ export async function deleteRundown(rundownId: RundownId): Promise> { return axios.delete(`${rundownPath}/${rundownId}`); } /** * HTTP request to apply an imported rundown using a merge strategy or into a new rundown */ export async function importRundownWithOptions( payload: RundownImportPayload, ): Promise> { return axios.post(`${rundownPath}/import`, payload); } // #endregion operations on project rundowns ====================== // #region operations on rundown entries ========================== /** * HTTP request to post new entry */ export async function postAddEntry( rundownId: RundownId, data: TransientEventPayload, ): Promise> { return axios.post(`${rundownPath}/${rundownId}/entry`, data); } /** * HTTP request to edit an entry */ export async function putEditEntry( rundownId: RundownId, data: Partial, ): Promise> { return axios.put(`${rundownPath}/${rundownId}/entry`, data); } export type BatchEditEntry = { data: Partial; ids: EntryId[]; }; /** * HTTP request to edit multiple events */ export async function putBatchEditEvents(rundownId: RundownId, data: BatchEditEntry): Promise> { return axios.put(`${rundownPath}/${rundownId}/batch`, data); } /** * HTTP request to renumber cues for multiple events */ export function patchRenumberCues(rundownId: RundownId, data: RenumberCues): Promise> { return axios.patch(`${rundownPath}/${rundownId}/renumber`, data); } export type ReorderEntry = { entryId: EntryId; destinationId: EntryId; order: 'before' | 'after' | 'insert'; }; /** * HTTP request to reorder an entry */ export async function patchReorderEntry(rundownId: RundownId, data: ReorderEntry): Promise> { return axios.patch(`${rundownPath}/${rundownId}/reorder`, data); } /** * HTTP request to swap two events */ export async function requestEventSwap( rundownId: RundownId, from: EntryId, to: EntryId, ): Promise> { return axios.patch(`${rundownPath}/${rundownId}/swap`, { from, to }); } /** * HTTP request to request application of delay */ export async function requestApplyDelay(rundownId: RundownId, delayId: EntryId): Promise> { return axios.patch(`${rundownPath}/${rundownId}/applydelay/${delayId}`); } /** * HTTP request for cloning an entry */ export async function postCloneEntry( rundownId: RundownId, entryId: EntryId, options?: { before?: EntryId; after?: EntryId }, ): Promise> { return axios.post(`${rundownPath}/${rundownId}/clone/${entryId}`, options); } /** * HTTP request for grouping a list of entries into a group */ export async function requestGroupEntries(rundownId: RundownId, entryIds: EntryId[]): Promise> { return axios.post(`${rundownPath}/${rundownId}/group`, { ids: entryIds }); } /** * HTTP request for dissolving of a group */ export async function requestUngroup(rundownId: RundownId, groupId: EntryId): Promise> { return axios.post(`${rundownPath}/${rundownId}/ungroup/${groupId}`); } /** * HTTP request to delete entries of a given rundown */ export async function deleteEntries(rundownId: RundownId, entryIds: EntryId[]): Promise> { return axios.delete(`${rundownPath}/${rundownId}/entries`, { data: { ids: entryIds } }); } /** * HTTP request to delete all entries of a given rundown */ export async function requestDeleteAll(rundownId: RundownId): Promise> { return axios.delete(`${rundownPath}/${rundownId}/all`); } // #endregion operations on rundown entries ======================= function isValidRundown(x: any): x is Rundown { return ( x && typeof x === 'object' && typeof x.id === 'string' && Array.isArray(x.order) && Array.isArray(x.flatOrder) && x.entries && typeof x.entries === 'object' && typeof x.revision === 'number' ); }