mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-13 11:23:50 +00:00
@@ -30,7 +30,7 @@ const SPip = withSocket(Pip);
|
||||
const SStudio = withSocket(StudioClock);
|
||||
|
||||
const FeatureWrapper = lazy(() => import('features/FeatureWrapper'));
|
||||
const EventList = lazy(() => import('features/editors/list/EventListExport'));
|
||||
const RundownPanel = lazy(() => import('features/rundown/RundownExport'));
|
||||
const TimerControl = lazy(() => import('features/control/playback/TimerControlExport'));
|
||||
const MessageControl = lazy(() => import('features/control/message/MessageControlExport'));
|
||||
const Info = lazy(() => import('features/info/InfoExport'));
|
||||
@@ -85,10 +85,10 @@ export default function AppRouter() {
|
||||
|
||||
{/*/!* Protected Routes - Elements *!/*/}
|
||||
<Route
|
||||
path='/eventlist'
|
||||
path='/rundown'
|
||||
element={
|
||||
<FeatureWrapper>
|
||||
<EventList />
|
||||
<RundownPanel />
|
||||
</FeatureWrapper>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -2,14 +2,14 @@ export const STATIC_PORT = 4001;
|
||||
export const EVENT_TABLE = ['event'];
|
||||
export const ALIASES = ['aliases'];
|
||||
export const USERFIELDS = ['userFields'];
|
||||
export const EVENTS_TABLE_KEY = 'events';
|
||||
export const EVENTS_TABLE = [EVENTS_TABLE_KEY];
|
||||
export const RUNDOWN_TABLE_KEY = 'rundown';
|
||||
export const RUNDOWN_TABLE = [RUNDOWN_TABLE_KEY];
|
||||
export const APP_INFO = ['appinfo'];
|
||||
export const OSC_SETTINGS = ['oscSettings'];
|
||||
export const APP_SETTINGS = ['appSettings'];
|
||||
export const VIEW_SETTINGS = ['viewSettings'];
|
||||
|
||||
export const FEAT_EVENTLIST = ['feat-eventList'];
|
||||
export const FEAT_RUNDOWN = ['feat-rundown'];
|
||||
export const FEAT_MESSAGECONTROL = ['feat-messagecontrol'];
|
||||
export const FEAT_PLAYBACKCONTROL = ['feat-playbackcontrol'];
|
||||
export const FEAT_INFO = ['feat-info'];
|
||||
@@ -24,8 +24,8 @@ export const calculateServer = () =>
|
||||
import.meta.env.DEV ? `http://localhost:${STATIC_PORT}` : window.location.origin;
|
||||
|
||||
export const serverURL = calculateServer();
|
||||
export const eventURL = `${serverURL}/${EVENT_TABLE}`;
|
||||
export const eventsURL = `${serverURL}/${EVENTS_TABLE}`;
|
||||
export const eventURL = `${serverURL}/event`;
|
||||
export const rundownURL = `${serverURL}/eventlist`;
|
||||
export const ontimeURL = `${serverURL}/ontime`;
|
||||
|
||||
export const stylesPath = 'external/styles/override.css';
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import axios from 'axios';
|
||||
|
||||
import { OntimeEventEntry } from '../models/EventTypes';
|
||||
import { OntimeRundown, OntimeRundownEntry } from '../models/EventTypes';
|
||||
|
||||
import { eventsURL } from './apiConstants';
|
||||
import { rundownURL } from './apiConstants';
|
||||
|
||||
/**
|
||||
* @description HTTP request to fetch all events
|
||||
* @return {Promise}
|
||||
*/
|
||||
export async function fetchAllEvents(): Promise<OntimeEventEntry[]> {
|
||||
const res = await axios.get(eventsURL);
|
||||
export async function fetchRundown(): Promise<OntimeRundown> {
|
||||
const res = await axios.get(rundownURL);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
@@ -17,32 +17,32 @@ export async function fetchAllEvents(): Promise<OntimeEventEntry[]> {
|
||||
* @description HTTP request to post new event
|
||||
* @return {Promise}
|
||||
*/
|
||||
export async function requestPostEvent(data: OntimeEventEntry) {
|
||||
return axios.post(eventsURL, data);
|
||||
export async function requestPostEvent(data: OntimeRundownEntry) {
|
||||
return axios.post(rundownURL, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description HTTP request to put new event
|
||||
* @return {Promise}
|
||||
*/
|
||||
export async function requestPutEvent(data: OntimeEventEntry) {
|
||||
return axios.put(eventsURL, data);
|
||||
export async function requestPutEvent(data: OntimeRundownEntry) {
|
||||
return axios.put(rundownURL, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description HTTP request to modify event
|
||||
* @return {Promise}
|
||||
*/
|
||||
export async function requestPatchEvent(data: OntimeEventEntry) {
|
||||
return axios.patch(eventsURL, data);
|
||||
export async function requestPatchEvent(data: OntimeRundownEntry) {
|
||||
return axios.patch(rundownURL, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description HTTP request to reorder events
|
||||
* @return {Promise}
|
||||
*/
|
||||
export async function requestReorderEvent(data: OntimeEventEntry) {
|
||||
return axios.patch(`${eventsURL}/reorder`, data);
|
||||
export async function requestReorderEvent(data: OntimeRundownEntry) {
|
||||
return axios.patch(`${rundownURL}/reorder`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,7 +50,7 @@ export async function requestReorderEvent(data: OntimeEventEntry) {
|
||||
* @return {Promise}
|
||||
*/
|
||||
export async function requestApplyDelay(eventId: string) {
|
||||
return axios.patch(`${eventsURL}/applydelay/${eventId}`);
|
||||
return axios.patch(`${rundownURL}/applydelay/${eventId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,7 +58,7 @@ export async function requestApplyDelay(eventId: string) {
|
||||
* @return {Promise}
|
||||
*/
|
||||
export async function requestDelete(eventId: string) {
|
||||
return axios.delete(`${eventsURL}/${eventId}`);
|
||||
return axios.delete(`${rundownURL}/${eventId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,5 +66,5 @@ export async function requestDelete(eventId: string) {
|
||||
* @return {Promise}
|
||||
*/
|
||||
export async function requestDeleteAll() {
|
||||
return axios.delete(`${eventsURL}/all`);
|
||||
return axios.delete(`${rundownURL}/all`);
|
||||
}
|
||||
|
||||
@@ -107,14 +107,14 @@ export async function postOSC(data: OscSettingsType) {
|
||||
* @description HTTP request to download db
|
||||
* @return {Promise}
|
||||
*/
|
||||
export const downloadEvents = async () => {
|
||||
export const downloadRundown = async () => {
|
||||
await axios({
|
||||
url: `${ontimeURL}/db`,
|
||||
method: 'GET',
|
||||
responseType: 'blob', // important
|
||||
}).then((response) => {
|
||||
const headerLine = response.headers['Content-Disposition'];
|
||||
let filename = 'events.json';
|
||||
let filename = 'rundown.json';
|
||||
|
||||
// try and get the filename from the response
|
||||
if (headerLine != null) {
|
||||
@@ -136,15 +136,15 @@ export const downloadEvents = async () => {
|
||||
* @description HTTP request to upload events db
|
||||
* @return {Promise}
|
||||
*/
|
||||
type UploadEventsOptions = {
|
||||
onlyEvents?: boolean;
|
||||
type UploadDataOptions = {
|
||||
onlyRundown?: boolean;
|
||||
}
|
||||
export const uploadEvents = async (file: string, setProgress: (value: number) => void, options?: UploadEventsOptions) => {
|
||||
export const uploadData = async (file: string, setProgress: (value: number) => void, options?: UploadDataOptions) => {
|
||||
const formData = new FormData();
|
||||
formData.append('userFile', file);
|
||||
const onlyEvents = options?.onlyEvents;
|
||||
const onlyRundown = options?.onlyRundown;
|
||||
await axios
|
||||
.post(`${ontimeURL}/db?onlyEvents=${onlyEvents}`, formData, {
|
||||
.post(`${ontimeURL}/db?onlyRundown=${onlyRundown}`, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
|
||||
@@ -19,8 +19,8 @@ import {
|
||||
import { IoCloseSharp } from '@react-icons/all-files/io5/IoCloseSharp';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { EVENTS_TABLE } from '../../api/apiConstants';
|
||||
import { uploadEvents } from '../../api/ontimeApi';
|
||||
import { RUNDOWN_TABLE } from '../../api/apiConstants';
|
||||
import { uploadData } from '../../api/ontimeApi';
|
||||
import { LoggingContext } from '../../context/LoggingContext';
|
||||
import TooltipActionBtn from '../buttons/TooltipActionBtn';
|
||||
|
||||
@@ -58,11 +58,11 @@ export default function UploadModal({ onClose, isOpen }: UploadModalProps) {
|
||||
const handleUpload = useCallback(async () => {
|
||||
if (file) {
|
||||
try {
|
||||
await uploadEvents(file, setProgress, { onlyEvents: overrideOptionRef?.current?.checked });
|
||||
await uploadData(file, setProgress, { onlyEvents: overrideOptionRef?.current?.checked });
|
||||
} catch (error) {
|
||||
emitError(`Failed uploading file: ${error}`);
|
||||
} finally {
|
||||
await queryClient.invalidateQueries(EVENTS_TABLE);
|
||||
await queryClient.invalidateQueries(RUNDOWN_TABLE);
|
||||
setFile(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { EVENTS_TABLE } from '../api/apiConstants';
|
||||
import { fetchAllEvents } from '../api/eventsApi';
|
||||
|
||||
export default function useEventsList() {
|
||||
const {
|
||||
data,
|
||||
status,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery(EVENTS_TABLE, fetchAllEvents, { placeholderData: [] });
|
||||
|
||||
return { data, status, isError, refetch };
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { RUNDOWN_TABLE } from '../api/apiConstants';
|
||||
import { fetchRundown } from '../api/eventsApi';
|
||||
|
||||
export default function useRundown() {
|
||||
const {
|
||||
data,
|
||||
status,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery(RUNDOWN_TABLE, fetchRundown, { placeholderData: [] });
|
||||
|
||||
return { data, status, isError, refetch };
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useCallback, useContext } from 'react';
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { EVENTS_TABLE, EVENTS_TABLE_KEY } from '../api/apiConstants';
|
||||
import { RUNDOWN_TABLE_KEY,RUNDOWN_TABLE } from '../api/apiConstants';
|
||||
import {
|
||||
requestApplyDelay,
|
||||
requestDelete,
|
||||
@@ -27,7 +27,7 @@ export const useEventAction = () => {
|
||||
// Mutation finished, failed or successful
|
||||
// Fetch anyway, just to be sure
|
||||
onSettled: () => {
|
||||
queryClient.invalidateQueries(EVENTS_TABLE);
|
||||
queryClient.invalidateQueries(RUNDOWN_TABLE);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -43,7 +43,7 @@ export const useEventAction = () => {
|
||||
// ************* CHECK OPTIONS
|
||||
// there is an option to pass an index of an array to use as start time
|
||||
if (typeof options?.startIsLastEnd !== 'undefined') {
|
||||
const events = queryClient.getQueryData(EVENTS_TABLE);
|
||||
const events = queryClient.getQueryData(RUNDOWN_TABLE);
|
||||
const previousEvent = events.find((event) => event.id === options.startIsLastEnd);
|
||||
newEvent.timeStart = previousEvent.timeEnd || 0;
|
||||
}
|
||||
@@ -71,13 +71,13 @@ export const useEventAction = () => {
|
||||
// we optimistically update here
|
||||
onMutate: async (newEvent) => {
|
||||
// cancel ongoing queries
|
||||
await queryClient.cancelQueries([EVENTS_TABLE_KEY, newEvent.id]);
|
||||
await queryClient.cancelQueries([RUNDOWN_TABLE_KEY, newEvent.id]);
|
||||
|
||||
// Snapshot the previous value
|
||||
const previousEvent = queryClient.getQueryData([EVENTS_TABLE_KEY, newEvent.id]);
|
||||
const previousEvent = queryClient.getQueryData([RUNDOWN_TABLE_KEY, newEvent.id]);
|
||||
|
||||
// optimistically update object
|
||||
queryClient.setQueryData([EVENTS_TABLE_KEY, newEvent.id], newEvent);
|
||||
queryClient.setQueryData([RUNDOWN_TABLE_KEY, newEvent.id], newEvent);
|
||||
|
||||
// Return a context with the previous and new events
|
||||
return { previousEvent, newEvent };
|
||||
@@ -85,12 +85,12 @@ export const useEventAction = () => {
|
||||
|
||||
// Mutation fails, rollback undoes optimist update
|
||||
onError: (error, newEvent, context) => {
|
||||
queryClient.setQueryData([EVENTS_TABLE_KEY, context.newEvent.id], context.previousEvent);
|
||||
queryClient.setQueryData([RUNDOWN_TABLE_KEY, context.newEvent.id], context.previousEvent);
|
||||
},
|
||||
// Mutation finished, failed or successful
|
||||
// Fetch anyway, just to be sure
|
||||
onSettled: async (newEvent) => {
|
||||
await queryClient.invalidateQueries([EVENTS_TABLE_KEY, newEvent.id]);
|
||||
await queryClient.invalidateQueries([RUNDOWN_TABLE_KEY, newEvent.id]);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -117,15 +117,15 @@ export const useEventAction = () => {
|
||||
// we optimistically update here
|
||||
onMutate: async (eventId) => {
|
||||
// cancel ongoing queries
|
||||
await queryClient.cancelQueries([EVENTS_TABLE_KEY, eventId]);
|
||||
await queryClient.cancelQueries([RUNDOWN_TABLE_KEY, eventId]);
|
||||
|
||||
// Snapshot the previous value
|
||||
const previousEvents = queryClient.getQueryData(EVENTS_TABLE);
|
||||
const previousEvents = queryClient.getQueryData(RUNDOWN_TABLE);
|
||||
|
||||
const filtered = [...previousEvents].filter((e) => e.id !== eventId);
|
||||
|
||||
// optimistically update object
|
||||
queryClient.setQueryData(EVENTS_TABLE, filtered);
|
||||
queryClient.setQueryData(RUNDOWN_TABLE, filtered);
|
||||
|
||||
// Return a context with the previous and new events
|
||||
return { previousEvents };
|
||||
@@ -133,12 +133,12 @@ export const useEventAction = () => {
|
||||
|
||||
// Mutation fails, rollback undoes optimist update
|
||||
onError: (error, eventId, context) => {
|
||||
queryClient.setQueryData(EVENTS_TABLE, context.previousEvents);
|
||||
queryClient.setQueryData(RUNDOWN_TABLE, context.previousEvents);
|
||||
},
|
||||
// Mutation finished, failed or successful
|
||||
// Fetch anyway, just to be sure
|
||||
onSettled: () => {
|
||||
queryClient.invalidateQueries(EVENTS_TABLE);
|
||||
queryClient.invalidateQueries(RUNDOWN_TABLE);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -165,15 +165,15 @@ export const useEventAction = () => {
|
||||
// we optimistically update here
|
||||
onMutate: async () => {
|
||||
// cancel ongoing queries
|
||||
await queryClient.cancelQueries(EVENTS_TABLE, { exact: true });
|
||||
await queryClient.cancelQueries(RUNDOWN_TABLE, { exact: true });
|
||||
|
||||
// Snapshot the previous value
|
||||
const previousEvents = queryClient.getQueryData(EVENTS_TABLE);
|
||||
const previousEvents = queryClient.getQueryData(RUNDOWN_TABLE);
|
||||
|
||||
const clear = [];
|
||||
|
||||
// optimistically update object
|
||||
queryClient.setQueryData(EVENTS_TABLE, clear);
|
||||
queryClient.setQueryData(RUNDOWN_TABLE, clear);
|
||||
|
||||
// Return a context with the previous and new events
|
||||
return { previousEvents };
|
||||
@@ -181,12 +181,12 @@ export const useEventAction = () => {
|
||||
|
||||
// Mutation fails, rollback undos optimist update
|
||||
onError: (error, eventId, context) => {
|
||||
queryClient.setQueryData(EVENTS_TABLE, context.previousEvents);
|
||||
queryClient.setQueryData(RUNDOWN_TABLE, context.previousEvents);
|
||||
},
|
||||
// Mutation finished, failed or successful
|
||||
// Fetch anyway, just to be sure
|
||||
onSettled: () => {
|
||||
queryClient.invalidateQueries(EVENTS_TABLE);
|
||||
queryClient.invalidateQueries(RUNDOWN_TABLE);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -208,7 +208,7 @@ export const useEventAction = () => {
|
||||
const _applyDelayMutation = useMutation(requestApplyDelay, {
|
||||
// Mutation finished, failed or successful
|
||||
onSettled: () => {
|
||||
queryClient.invalidateQueries(EVENTS_TABLE);
|
||||
queryClient.invalidateQueries(RUNDOWN_TABLE);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -235,17 +235,17 @@ export const useEventAction = () => {
|
||||
// we optimistically update here
|
||||
onMutate: async (data) => {
|
||||
// cancel ongoing queries
|
||||
await queryClient.cancelQueries(EVENTS_TABLE, { exact: true });
|
||||
await queryClient.cancelQueries(RUNDOWN_TABLE, { exact: true });
|
||||
|
||||
// Snapshot the previous value
|
||||
const previousEvents = queryClient.getQueryData(EVENTS_TABLE);
|
||||
const previousEvents = queryClient.getQueryData(RUNDOWN_TABLE);
|
||||
|
||||
const e = [...previousEvents];
|
||||
const [reorderedItem] = e.splice(data.from, 1);
|
||||
e.splice(data.to, 0, reorderedItem);
|
||||
|
||||
// optimistically update object
|
||||
queryClient.setQueryData(EVENTS_TABLE, e);
|
||||
queryClient.setQueryData(RUNDOWN_TABLE, e);
|
||||
|
||||
// Return a context with the previous and new events
|
||||
return { previousEvents };
|
||||
@@ -253,12 +253,12 @@ export const useEventAction = () => {
|
||||
|
||||
// Mutation fails, rollback undoes optimist update
|
||||
onError: (error, eventId, context) => {
|
||||
queryClient.setQueryData(EVENTS_TABLE, context.previousEvents);
|
||||
queryClient.setQueryData(RUNDOWN_TABLE, context.previousEvents);
|
||||
},
|
||||
// Mutation finished, failed or successful
|
||||
// Fetch anyway, just to be sure
|
||||
onSettled: () => {
|
||||
queryClient.invalidateQueries(EVENTS_TABLE);
|
||||
queryClient.invalidateQueries(RUNDOWN_TABLE);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { EVENTS_TABLE } from '../api/apiConstants';
|
||||
import { RUNDOWN_TABLE } from '../api/apiConstants';
|
||||
|
||||
/**
|
||||
* @description utility hook to handle mutations in events
|
||||
@@ -11,13 +11,13 @@ export default function useMutateEvents(mutation){
|
||||
return useMutation(mutation, {
|
||||
onMutate: async (newEvent) => {
|
||||
// cancel ongoing queries
|
||||
queryClient.cancelQueries(EVENTS_TABLE, { exact: true });
|
||||
queryClient.cancelQueries(RUNDOWN_TABLE, { exact: true });
|
||||
|
||||
// Snapshot the previous value
|
||||
const previousEvent = queryClient.getQueryData([EVENTS_TABLE, newEvent.id]);
|
||||
const previousEvent = queryClient.getQueryData([RUNDOWN_TABLE, newEvent.id]);
|
||||
|
||||
// optimistically update object
|
||||
queryClient.setQueryData([EVENTS_TABLE, newEvent.id], newEvent);
|
||||
queryClient.setQueryData([RUNDOWN_TABLE, newEvent.id], newEvent);
|
||||
|
||||
// Return a context with the previous and new event
|
||||
return { previousEvent, newEvent };
|
||||
@@ -25,13 +25,13 @@ export default function useMutateEvents(mutation){
|
||||
|
||||
// Mutation fails, rollback undoes optimist update
|
||||
onError: (error, newEvent, context) => {
|
||||
queryClient.setQueryData([EVENTS_TABLE, context.newEvent.id], context.previousEvent);
|
||||
queryClient.setQueryData([RUNDOWN_TABLE, context.newEvent.id], context.previousEvent);
|
||||
},
|
||||
|
||||
// Mutation finished, failed or successful
|
||||
// Fetch anyway, just to be sure
|
||||
onSettled: (newEvent) => {
|
||||
queryClient.invalidateQueries([EVENTS_TABLE, newEvent.id]);
|
||||
queryClient.invalidateQueries([RUNDOWN_TABLE, newEvent.id]);
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -3,16 +3,16 @@ import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import {
|
||||
FEAT_CUESHEET,
|
||||
FEAT_EVENTLIST,
|
||||
FEAT_INFO,
|
||||
FEAT_MESSAGECONTROL,
|
||||
FEAT_PLAYBACKCONTROL,
|
||||
FEAT_RUNDOWN,
|
||||
TIMER,
|
||||
} from '../api/apiConstants';
|
||||
import { useSocket } from '../context/socketContext';
|
||||
|
||||
export const useEventListProvider = () => {
|
||||
const { data } = useQuery(FEAT_EVENTLIST, () => undefined, {
|
||||
export const useRundownProvider = () => {
|
||||
const { data } = useQuery(FEAT_RUNDOWN, () => undefined, {
|
||||
cacheTime: Infinity,
|
||||
staleTime: Infinity,
|
||||
});
|
||||
@@ -211,8 +211,8 @@ export const useSocketProvider = () => {
|
||||
}
|
||||
|
||||
socket.emit('get-ontime-feat-eventlist');
|
||||
socket.on('ontime-feat-eventlist', (featureData) => {
|
||||
queryClient.setQueryData(FEAT_EVENTLIST, () => featureData);
|
||||
socket.on('ontime-feat-rundown', (featureData) => {
|
||||
queryClient.setQueryData(FEAT_RUNDOWN, () => featureData);
|
||||
});
|
||||
|
||||
socket.emit('get-ontime-feat-messagecontrol');
|
||||
@@ -241,7 +241,7 @@ export const useSocketProvider = () => {
|
||||
});
|
||||
|
||||
return () => {
|
||||
socket.off('ontime-feat-eventlist');
|
||||
socket.off('ontime-feat-rundown');
|
||||
socket.off('ontime-feat-messagecontrol');
|
||||
socket.off('ontime-feat-playbackcontrol');
|
||||
socket.off('ontime-feat-info');
|
||||
|
||||
@@ -41,4 +41,5 @@ export type OntimeEvent = OntimeBaseEvent & {
|
||||
revision: number,
|
||||
}
|
||||
|
||||
export type OntimeEventEntry = OntimeDelay | OntimeBlock | OntimeEvent;
|
||||
export type OntimeRundownEntry = OntimeDelay | OntimeBlock | OntimeEvent;
|
||||
export type OntimeRundown = OntimeRundownEntry[]
|
||||
@@ -1,4 +1,4 @@
|
||||
import { OntimeEvent, OntimeEventEntry } from '../models/EventTypes';
|
||||
import { OntimeEvent, OntimeRundownEntry } from '../models/EventTypes';
|
||||
|
||||
import { formatTime } from './time';
|
||||
|
||||
@@ -8,7 +8,7 @@ import { formatTime } from './time';
|
||||
* @returns {Object[]} Filtered events with calculated delays
|
||||
*/
|
||||
|
||||
export const getEventsWithDelay = (events: OntimeEventEntry[]) => {
|
||||
export const getEventsWithDelay = (events: OntimeRundownEntry[]) => {
|
||||
if (events == null) return [];
|
||||
|
||||
const unfilteredEvents = [...events];
|
||||
@@ -35,7 +35,7 @@ export const getEventsWithDelay = (events: OntimeEventEntry[]) => {
|
||||
* @param {number} limit - max number of events to return
|
||||
* @returns {Object[]} Event list with maximum <limit> objects
|
||||
*/
|
||||
export const trimEventlist = (events: OntimeEventEntry[], selectedId: string, limit: number) => {
|
||||
export const trimEventlist = (events: OntimeRundownEntry[], selectedId: string, limit: number) => {
|
||||
if (events == null) return [];
|
||||
|
||||
const BEFORE = 2;
|
||||
|
||||
@@ -27,7 +27,7 @@ export default function PlaybackTimer(props: PlaybackTimerProps) {
|
||||
const finish = stringFromMillis(timerData.expectedFinish, true);
|
||||
const isRolling = playback === 'roll';
|
||||
const isWaiting = timerData.secondaryTimer !== null && timerData.secondaryTimer > 0 && timerData.current === null;
|
||||
const disableButtons = selectedId == null || isRolling;
|
||||
const disableButtons = selectedId === null || isRolling;
|
||||
const isOvertime = timerData.current !== null && timerData.current < 0;
|
||||
|
||||
return (
|
||||
|
||||
@@ -9,7 +9,7 @@ import MenuBar from '../menu/MenuBar';
|
||||
|
||||
import styles from './Editor.module.scss';
|
||||
|
||||
const EventList = lazy(() => import('features/editors/list/EventListExport'));
|
||||
const Rundown = lazy(() => import('features/rundown/RundownExport'));
|
||||
const TimerControl = lazy(() => import('features/control/playback/TimerControlExport'));
|
||||
const MessageControl = lazy(() => import('features/control/message/MessageControlExport'));
|
||||
const Info = lazy(() => import('features/info/InfoExport'));
|
||||
@@ -51,7 +51,7 @@ export default function Editor() {
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
</Box>
|
||||
<EventList />
|
||||
<Rundown />
|
||||
<MessageControl />
|
||||
<TimerControl />
|
||||
<Info />
|
||||
|
||||
@@ -14,14 +14,14 @@ import { stringFromMillis } from 'common/utils/time';
|
||||
import { calculateDuration, validateEntry } from 'common/utils/timesManager';
|
||||
import { useAtom } from 'jotai';
|
||||
|
||||
import useEventsList from '../../common/hooks-query/useEventsList';
|
||||
import useRundown from '../../common/hooks-query/useRundown';
|
||||
|
||||
import style from './EventEditor.module.scss';
|
||||
import CopyTag from '../../common/components/osc-tag/CopyTag';
|
||||
|
||||
export default function EventEditor() {
|
||||
const [openId] = useAtom(editorEventId);
|
||||
const { data } = useEventsList();
|
||||
const { data } = useRundown();
|
||||
const { emitWarning, emitError } = useContext(LoggingContext);
|
||||
const { updateEvent } = useEventAction();
|
||||
const [event, setEvent] = useState(null);
|
||||
|
||||
@@ -6,7 +6,7 @@ import { FiMinimize } from '@react-icons/all-files/fi/FiMinimize';
|
||||
import { FiSave } from '@react-icons/all-files/fi/FiSave';
|
||||
import { FiUpload } from '@react-icons/all-files/fi/FiUpload';
|
||||
import { IoSettingsOutline } from '@react-icons/all-files/io5/IoSettingsOutline';
|
||||
import { downloadEvents } from 'common/api/ontimeApi';
|
||||
import { downloadRundown } from 'common/api/ontimeApi';
|
||||
|
||||
import QuitIconBtn from '../../common/components/buttons/QuitIconBtn';
|
||||
import TooltipActionBtn from '../../common/components/buttons/TooltipActionBtn';
|
||||
@@ -136,7 +136,7 @@ export default function MenuBar(props: MenuBarProps) {
|
||||
<TooltipActionBtn
|
||||
{...buttonStyle}
|
||||
icon={<FiSave />}
|
||||
clickHandler={downloadEvents}
|
||||
clickHandler={downloadRundown}
|
||||
tooltip='Export event list'
|
||||
aria-label=''
|
||||
/>
|
||||
|
||||
+3
-3
@@ -18,14 +18,14 @@ import { CursorContext } from 'common/context/CursorContext';
|
||||
|
||||
import { useEventAction } from '../../common/hooks/useEventAction';
|
||||
|
||||
import style from './EventListMenu.module.scss';
|
||||
import style from './RundownMenu.module.scss';
|
||||
|
||||
const menuStyle = {
|
||||
color: '#000000',
|
||||
backgroundColor: 'rgba(255,255,255,1)',
|
||||
};
|
||||
|
||||
const EventListMenu = () => {
|
||||
const RundownMenu = () => {
|
||||
const { isCursorLocked, toggleCursorLocked } = useContext(CursorContext);
|
||||
const { addEvent, deleteAllEvents } = useEventAction();
|
||||
|
||||
@@ -91,4 +91,4 @@ const EventListMenu = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(EventListMenu);
|
||||
export default memo(RundownMenu);
|
||||
+24
-24
@@ -9,20 +9,20 @@ import {
|
||||
import Empty from 'common/components/state/Empty';
|
||||
import { CursorContext } from 'common/context/CursorContext';
|
||||
import { useEventAction } from 'common/hooks/useEventAction';
|
||||
import { useEventListProvider } from 'common/hooks/useSocketProvider';
|
||||
import { useRundownProvider } from 'common/hooks/useSocketProvider';
|
||||
import { duplicateEvent } from 'common/utils/eventsManager';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import useSubscription from '../../../common/hooks/useSubscription';
|
||||
import QuickAddBlock from '../quick-add-block/QuickAddBlock';
|
||||
import useSubscription from '../../common/hooks/useSubscription';
|
||||
|
||||
import EventListItem from './EventListItem';
|
||||
import QuickAddBlock from './quick-add-block/QuickAddBlock';
|
||||
import RundownEntry from './RundownEntry';
|
||||
|
||||
import style from './List.module.scss';
|
||||
import style from './Rundown.module.scss';
|
||||
|
||||
export default function EventList(props) {
|
||||
const { events } = props;
|
||||
export default function Rundown(props) {
|
||||
const { entries } = props;
|
||||
const { cursor, moveCursorUp, moveCursorDown, moveCursorTo, isCursorLocked } =
|
||||
useContext(CursorContext);
|
||||
const startTimeIsLastEnd = useAtomValue(startTimeIsLastEndAtom);
|
||||
@@ -30,7 +30,7 @@ export default function EventList(props) {
|
||||
const { addEvent, reorderEvent } = useEventAction();
|
||||
const cursorRef = createRef();
|
||||
const showQuickEntry = useAtomValue(showQuickEntryAtom);
|
||||
const data = useEventListProvider();
|
||||
const data = useRundownProvider();
|
||||
const [selectedId] = useSubscription('selected-id', null);
|
||||
const [nextId] = useSubscription('next-id', null);
|
||||
|
||||
@@ -39,8 +39,8 @@ export default function EventList(props) {
|
||||
if (cursor === -1) {
|
||||
addEvent({ type: type });
|
||||
} else {
|
||||
const previousEvent = events?.[cursor];
|
||||
const nextEvent = events?.[cursor + 1];
|
||||
const previousEvent = entries?.[cursor];
|
||||
const nextEvent = entries?.[cursor + 1];
|
||||
|
||||
// prevent adding two non-event blocks consecutively
|
||||
const isPreviousDifferent = previousEvent?.type !== type;
|
||||
@@ -64,7 +64,7 @@ export default function EventList(props) {
|
||||
}
|
||||
}
|
||||
},
|
||||
[addEvent, defaultPublic, events, startTimeIsLastEnd],
|
||||
[addEvent, defaultPublic, entries, startTimeIsLastEnd],
|
||||
);
|
||||
|
||||
// Handle keyboard shortcuts
|
||||
@@ -77,7 +77,7 @@ export default function EventList(props) {
|
||||
if (e.altKey && (!e.ctrlKey || !e.shiftKey)) {
|
||||
// Arrow down
|
||||
if (e.keyCode === 40) {
|
||||
if (cursor < events.length - 1) moveCursorDown();
|
||||
if (cursor < entries.length - 1) moveCursorDown();
|
||||
}
|
||||
// Arrow up
|
||||
if (e.keyCode === 38) {
|
||||
@@ -103,21 +103,21 @@ export default function EventList(props) {
|
||||
}
|
||||
}
|
||||
},
|
||||
[cursor, events.length, insertAtCursor, moveCursorDown, moveCursorUp],
|
||||
[cursor, entries.length, insertAtCursor, moveCursorDown, moveCursorUp],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// attach the event listener
|
||||
document.addEventListener('keydown', handleKeyPress);
|
||||
|
||||
if (cursor > events.length - 1) moveCursorTo(events.length - 1);
|
||||
if (events.length > 0 && cursor === -1) moveCursorTo(0);
|
||||
if (cursor > entries.length - 1) moveCursorTo(entries.length - 1);
|
||||
if (entries.length > 0 && cursor === -1) moveCursorTo(0);
|
||||
|
||||
// remove the event listener
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handleKeyPress);
|
||||
};
|
||||
}, [handleKeyPress, cursor, events, moveCursorTo]);
|
||||
}, [handleKeyPress, cursor, entries, moveCursorTo]);
|
||||
|
||||
// when cursor moves, view should follow
|
||||
useEffect(() => {
|
||||
@@ -138,7 +138,7 @@ export default function EventList(props) {
|
||||
// move cursor
|
||||
let gotoIndex = -1;
|
||||
let found = false;
|
||||
for (const e of events) {
|
||||
for (const e of entries) {
|
||||
gotoIndex++;
|
||||
if (e.id === data.selectedEventId) {
|
||||
found = true;
|
||||
@@ -166,10 +166,10 @@ export default function EventList(props) {
|
||||
[reorderEvent],
|
||||
);
|
||||
|
||||
if (events.length < 1) {
|
||||
if (entries.length < 1) {
|
||||
return (
|
||||
<div className={style.alignCenter}>
|
||||
<Empty text='No Events' style={{ marginTop: '7vh' }} />
|
||||
<Empty text='No data yet' style={{ marginTop: '7vh' }} />
|
||||
<Button
|
||||
onClick={() => insertAtCursor('event', cursor)}
|
||||
variant='solid'
|
||||
@@ -192,7 +192,7 @@ export default function EventList(props) {
|
||||
<Droppable droppableId='eventlist'>
|
||||
{(provided) => (
|
||||
<div className={style.list} {...provided.droppableProps} ref={provided.innerRef}>
|
||||
{events.map((e, index) => {
|
||||
{entries.map((e, index) => {
|
||||
if (index === 0) {
|
||||
cumulativeDelay = 0;
|
||||
eventIndex = -1;
|
||||
@@ -207,7 +207,7 @@ export default function EventList(props) {
|
||||
thisEnd = e.timeEnd;
|
||||
previousEventId = e.id;
|
||||
}
|
||||
const isLast = index === events.length - 1;
|
||||
const isLast = index === entries.length - 1;
|
||||
return (
|
||||
<div
|
||||
key={e.id}
|
||||
@@ -218,7 +218,7 @@ export default function EventList(props) {
|
||||
ref={cursor === index ? cursorRef : undefined}
|
||||
className={cursor === index ? style.cursor : ''}
|
||||
>
|
||||
<EventListItem
|
||||
<RundownEntry
|
||||
type={e.type}
|
||||
index={index}
|
||||
eventIndex={eventIndex}
|
||||
@@ -251,6 +251,6 @@ export default function EventList(props) {
|
||||
);
|
||||
}
|
||||
|
||||
EventList.propTypes = {
|
||||
events: PropTypes.array,
|
||||
Rundown.propTypes = {
|
||||
entries: PropTypes.array,
|
||||
};
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
@use '../../../theme/main' as *;
|
||||
@use '../../../theme/mixins' as *;
|
||||
@use '../../theme/main' as *;
|
||||
@use '../../theme/mixins' as *;
|
||||
|
||||
.eventContainer {
|
||||
margin-top: 1em;
|
||||
+9
-8
@@ -6,16 +6,17 @@ import {
|
||||
} from 'common/atoms/LocalEventSettings';
|
||||
import { LoggingContext } from 'common/context/LoggingContext';
|
||||
import { useEventAction } from 'common/hooks/useEventAction';
|
||||
import { OntimeEvent, OntimeEventEntry } from 'common/models/EventTypes';
|
||||
import { OntimeEvent, OntimeRundownEntry } from 'common/models/EventTypes';
|
||||
import { Playstate } from 'common/models/OntimeTypes';
|
||||
import { duplicateEvent } from 'common/utils/eventsManager';
|
||||
import { calculateDuration } from 'common/utils/timesManager';
|
||||
import { useAtom, useAtomValue } from 'jotai';
|
||||
|
||||
import { CursorContext } from '../../../common/context/CursorContext';
|
||||
import BlockBlock from '../block-block/BlockBlock';
|
||||
import DelayBlock from '../delay-block/DelayBlock';
|
||||
import EventBlock from '../event-block/EventBlock';
|
||||
import { CursorContext } from '../../common/context/CursorContext';
|
||||
|
||||
import BlockBlock from './block-block/BlockBlock';
|
||||
import DelayBlock from './delay-block/DelayBlock';
|
||||
import EventBlock from './event-block/EventBlock';
|
||||
|
||||
export type EventItemActions =
|
||||
'set-cursor'
|
||||
@@ -26,10 +27,10 @@ export type EventItemActions =
|
||||
| 'clone'
|
||||
| 'update'
|
||||
|
||||
interface EventListItemProps {
|
||||
interface RundownEntryProps {
|
||||
index: number;
|
||||
eventIndex: number;
|
||||
data: OntimeEventEntry;
|
||||
data: OntimeRundownEntry;
|
||||
selected: boolean;
|
||||
next: boolean;
|
||||
delay: number;
|
||||
@@ -37,7 +38,7 @@ interface EventListItemProps {
|
||||
playback: Playstate;
|
||||
}
|
||||
|
||||
export default function EventListItem(props: EventListItemProps) {
|
||||
export default function RundownEntry(props: RundownEntryProps) {
|
||||
const { index, eventIndex, data, selected, next, delay, previousEnd, playback } = props;
|
||||
const { emitError } = useContext(LoggingContext);
|
||||
const startTimeIsLastEnd = useAtomValue(startTimeIsLastEndAtom);
|
||||
+6
-6
@@ -4,20 +4,20 @@ import ErrorBoundary from 'common/components/errorBoundary/ErrorBoundary';
|
||||
import { CursorProvider } from 'common/context/CursorContext';
|
||||
import { handleLinks } from 'common/utils/linkUtils';
|
||||
|
||||
import EventListWrapper from './EventListWrapper';
|
||||
import RundownWrapper from './RundownWrapper';
|
||||
|
||||
import style from '../Editor.module.scss';
|
||||
import style from '../editors/Editor.module.scss';
|
||||
|
||||
export default function EventListExport() {
|
||||
export default function RundownExport() {
|
||||
return (
|
||||
<CursorProvider>
|
||||
<Box className={style.editor} data-testid="panel-event-list">
|
||||
<Box className={style.editor} data-testid='panel-rundown'>
|
||||
<FiArrowUpRight
|
||||
className={style.corner}
|
||||
onClick={(event) => handleLinks(event, 'eventlist')}
|
||||
onClick={(event) => handleLinks(event, 'rundown')}
|
||||
/>
|
||||
<ErrorBoundary>
|
||||
<EventListWrapper />
|
||||
<RundownWrapper />
|
||||
</ErrorBoundary>
|
||||
</Box>
|
||||
</CursorProvider>
|
||||
+8
-8
@@ -1,17 +1,17 @@
|
||||
import { useContext, useEffect } from 'react';
|
||||
import Empty from 'common/components/state/Empty';
|
||||
import { LoggingContext } from 'common/context/LoggingContext';
|
||||
import EventListMenu from 'features/menu/EventListMenu';
|
||||
import RundownMenu from 'features/menu/RundownMenu';
|
||||
|
||||
import useEventsList from '../../../common/hooks-query/useEventsList';
|
||||
import useRundown from '../../common/hooks-query/useRundown';
|
||||
|
||||
import EventList from './EventList';
|
||||
import Rundown from './Rundown';
|
||||
|
||||
import styles from '../Editor.module.scss';
|
||||
import styles from '../editors/Editor.module.scss';
|
||||
|
||||
export default function EventListWrapper() {
|
||||
export default function RundownWrapper() {
|
||||
const { emitError } = useContext(LoggingContext);
|
||||
const { data, status, isError } = useEventsList();
|
||||
const { data, status, isError } = useRundown();
|
||||
|
||||
useEffect(() => {
|
||||
if (isError) {
|
||||
@@ -21,10 +21,10 @@ export default function EventListWrapper() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<EventListMenu />
|
||||
<RundownMenu />
|
||||
<div className={styles.content}>
|
||||
{status === 'success' && data ? (
|
||||
<EventList events={data} />
|
||||
<Rundown entries={data} />
|
||||
) : (
|
||||
<Empty text='Connecting to server' />
|
||||
)}
|
||||
+1
-1
@@ -20,7 +20,7 @@ import { useAtom } from 'jotai';
|
||||
import { useEventProvider } from '../../../common/hooks/useSocketProvider';
|
||||
import { Playstate } from '../../../common/models/OntimeTypes';
|
||||
import { tooltipDelayMid } from '../../../ontimeConfig';
|
||||
import { EventItemActions } from '../list/EventListItem';
|
||||
import { EventItemActions } from '../RundownEntry';
|
||||
|
||||
import EventBlockActionMenu from './composite/EventBlockActionMenu';
|
||||
import EventBlockTimers from './composite/EventBlockTimers';
|
||||
@@ -4,7 +4,7 @@ import { requestPatchEvent } from '../../common/api/eventsApi';
|
||||
import { TableSettingsContext } from '../../common/context/TableSettingsContext';
|
||||
import useMutateEvents from '../../common/hooks/useMutateEvents';
|
||||
import { useCuesheetProvider } from '../../common/hooks/useSocketProvider';
|
||||
import useEventsList from '../../common/hooks-query/useEventsList';
|
||||
import useRundown from '../../common/hooks-query/useRundown';
|
||||
import useUserFields from '../../common/hooks-query/useUserFields';
|
||||
|
||||
import OntimeTable from './OntimeTable';
|
||||
@@ -14,7 +14,7 @@ import { makeCSV, makeTable } from './utils';
|
||||
import style from './Table.module.scss';
|
||||
|
||||
export default function TableWrapper() {
|
||||
const { data: events } = useEventsList();
|
||||
const { data: events } = useRundown();
|
||||
const { data: userFields } = useUserFields();
|
||||
const mutation = useMutateEvents(requestPatchEvent);
|
||||
const { theme } = useContext(TableSettingsContext);
|
||||
|
||||
@@ -5,12 +5,12 @@ import { useSocket } from '../../common/context/socketContext';
|
||||
import { useMessageControlProvider } from '../../common/hooks/useSocketProvider';
|
||||
import useSubscription from '../../common/hooks/useSubscription';
|
||||
import useEvent from '../../common/hooks-query/useEvent';
|
||||
import useEventsList from '../../common/hooks-query/useEventsList';
|
||||
import useRundown from '../../common/hooks-query/useRundown';
|
||||
import useViewSettings from '../../common/hooks-query/useViewSettings';
|
||||
|
||||
const withSocket = (Component) => {
|
||||
return (props) => {
|
||||
const { data: eventsData } = useEventsList();
|
||||
const { data: eventsData } = useRundown();
|
||||
const { data: genData } = useEvent();
|
||||
const { data: viewSettings } = useViewSettings();
|
||||
const { data: messages } = useMessageControlProvider();
|
||||
|
||||
Reference in New Issue
Block a user