+
{page.map((e) => {
if (e.id === selectedId) selectedState = 1;
else if (selectedState === 1) selectedState = 2;
@@ -83,19 +93,10 @@ export default function Paginator(props) {
title={e.title}
colour={isBackstage ? e.colour : ''}
backstageEvent={!e.isPublic}
+ skip={e.skip}
/>
);
})}
);
}
-
-Paginator.propTypes = {
- events: PropTypes.array,
- selectedId: PropTypes.string,
- limit: PropTypes.number,
- time: PropTypes.number,
- isBackstage: PropTypes.bool,
- setPageNumber: PropTypes.func,
- setCurrentPage: PropTypes.func,
-};
diff --git a/client/src/common/components/views/TodayItem.tsx b/client/src/common/components/views/TodayItem.tsx
new file mode 100644
index 0000000000..5dd599d8eb
--- /dev/null
+++ b/client/src/common/components/views/TodayItem.tsx
@@ -0,0 +1,51 @@
+import PropTypes from 'prop-types';
+
+import { formatTime } from '../../utils/time';
+
+import style from './Paginator.module.scss';
+
+interface TodayItemProps {
+ selected: number;
+ timeStart: number;
+ timeEnd: number;
+ title: string;
+ backstageEvent: boolean;
+ colour: string;
+ skip: boolean;
+}
+
+// Todo: apply skip CSS and selector
+export default function TodayItem(props: TodayItemProps) {
+ // @ts-ignore
+ const { selected, timeStart, timeEnd, title, backstageEvent, colour, skip } = props;
+
+ // Format timers
+ const start = formatTime(timeStart, { format: 'hh:mm' });
+ const end = formatTime(timeEnd, { format: 'hh:mm' });
+
+ // user colours
+ const userColour = colour !== '' ? colour : 'transparent';
+
+ // select styling
+ let selectStyle = style.entryPast;
+ if (selected === 1) selectStyle = style.entryNow;
+ else if (selected === 2) selectStyle = style.entryFuture;
+ return (
+
+
+ {`${start} · ${end}`}
+
+
{title}
+ {backstageEvent &&
}
+
+ );
+}
+
+TodayItem.propTypes = {
+ selected: PropTypes.number,
+ timeStart: PropTypes.number,
+ timeEnd: PropTypes.number,
+ title: PropTypes.string,
+ backstageEvent: PropTypes.bool,
+ colour: PropTypes.string,
+};
diff --git a/client/src/common/context/CursorContext.jsx b/client/src/common/context/CursorContext.tsx
similarity index 65%
rename from client/src/common/context/CursorContext.jsx
rename to client/src/common/context/CursorContext.tsx
index 8f4fba8487..43a721c5fc 100644
--- a/client/src/common/context/CursorContext.jsx
+++ b/client/src/common/context/CursorContext.tsx
@@ -1,17 +1,32 @@
-import { createContext, useCallback, useMemo, useState } from 'react';
+import { createContext, ReactNode, useCallback, useMemo, useState } from 'react';
import { useLocalStorage } from '../hooks/useLocalStorage';
-export const CursorContext = createContext({
+interface CursorContextState {
+ cursor: number;
+ isCursorLocked: boolean;
+ toggleCursorLocked: (newValue?: boolean) => void;
+ setCursor: (index: number) => void;
+ moveCursorUp: () => void;
+ moveCursorDown: () => void;
+ moveCursorTo: (index: number) => void;
+}
+
+export const CursorContext = createContext
({
cursor: 0,
isCursorLocked: false,
-
+ toggleCursorLocked: () => undefined,
setCursor: () => undefined,
moveCursorUp: () => undefined,
moveCursorDown: () => undefined,
+ moveCursorTo: () => undefined,
});
-export const CursorProvider = ({ children }) => {
+interface CursorProviderProps {
+ children: ReactNode
+}
+
+export const CursorProvider = ({ children }: CursorProviderProps) => {
const [cursor, setCursor] = useState(0);
const [_cursorLocked, _setCursorLocked] = useLocalStorage('isCursorLocked', 'locked');
const isCursorLocked = useMemo(() => _cursorLocked === 'locked', [_cursorLocked]);
@@ -31,7 +46,7 @@ export const CursorProvider = ({ children }) => {
* @param {boolean | undefined} newValue
*/
const toggleCursorLocked = useCallback(
- (newValue = undefined) => {
+ (newValue?: boolean) => {
if (typeof newValue === 'undefined') {
if (isCursorLocked) {
cursorLockedOff();
@@ -46,6 +61,11 @@ export const CursorProvider = ({ children }) => {
},
[cursorLockedOff, cursorLockedOn, isCursorLocked]
);
+
+ // moves cursor to given index
+ const moveCursorTo = useCallback((index: number) => {
+ setCursor(index);
+ }, []);
return (
{
setCursor,
moveCursorUp,
moveCursorDown,
+ moveCursorTo,
}}
>
{children}
diff --git a/client/src/common/context/LoggingContext.tsx b/client/src/common/context/LoggingContext.tsx
index e431cb56f7..025000c34f 100644
--- a/client/src/common/context/LoggingContext.tsx
+++ b/client/src/common/context/LoggingContext.tsx
@@ -27,7 +27,7 @@ type LoggingProviderProps = {
}
const notInitialised = () => {
- throw new Error("Not initialised");
+ throw new Error('Not initialised');
};
export const LoggingContext = createContext({
@@ -35,7 +35,7 @@ export const LoggingContext = createContext({
emitInfo: notInitialised,
emitWarning: notInitialised,
emitError: notInitialised,
- clearLog: notInitialised
+ clearLog: notInitialised,
});
export const LoggingProvider = ({ children }: LoggingProviderProps) => {
@@ -52,7 +52,7 @@ export const LoggingProvider = ({ children }: LoggingProviderProps) => {
socket.emit('get-logger');
socket.on('logger', (data: Log) => {
- setLogData((l) => [data, ...l]);
+ setLogData((currentLog) => [data, ...currentLog]);
});
// Clear listener
@@ -70,21 +70,21 @@ export const LoggingProvider = ({ children }: LoggingProviderProps) => {
const _send = useCallback(
(text: string, level: LOG_LEVEL) => {
if (socket != null) {
- const m: Log = {
+ const newLogMessage: Log = {
id: generateId(),
origin,
time: stringFromMillis(nowInMillis()),
level,
text,
};
- setLogData((l) => [m, ...l]);
- socket.emit('logger', m);
+ setLogData((currentLog) => [newLogMessage, ...currentLog]);
+ socket.emit('logger', newLogMessage);
}
if (logData.length > MAX_MESSAGES) {
- setLogData((l) => l.slice(1));
+ setLogData((currentLog) => currentLog.slice(1));
}
},
- [logData, socket]
+ [logData.length, setLogData, socket],
);
/**
@@ -95,7 +95,7 @@ export const LoggingProvider = ({ children }: LoggingProviderProps) => {
(text: string) => {
_send(text, 'INFO');
},
- [_send]
+ [_send],
);
/**
@@ -106,7 +106,7 @@ export const LoggingProvider = ({ children }: LoggingProviderProps) => {
(text: string) => {
_send(text, 'WARN');
},
- [_send]
+ [_send],
);
/**
@@ -117,7 +117,7 @@ export const LoggingProvider = ({ children }: LoggingProviderProps) => {
(text: string) => {
_send(text, 'ERROR');
},
- [_send]
+ [_send],
);
/**
@@ -125,7 +125,7 @@ export const LoggingProvider = ({ children }: LoggingProviderProps) => {
*/
const clearLog = useCallback(() => {
setLogData([]);
- }, []);
+ }, [setLogData]);
return (
diff --git a/client/src/common/context/socketContext.tsx b/client/src/common/context/socketContext.tsx
index a291ae9757..330abd8603 100644
--- a/client/src/common/context/socketContext.tsx
+++ b/client/src/common/context/socketContext.tsx
@@ -1,4 +1,3 @@
-// @ts-nocheck
import { createContext, ReactNode, useContext, useEffect, useState } from 'react';
import { serverURL } from 'common/api/apiConstants';
import io, { Socket } from 'socket.io-client';
@@ -26,7 +25,7 @@ export const useSocket = () => {
};
function SocketProvider({ children }: SocketProviderProps) {
- const [socket, setSocket] = useState(null);
+ const [socket, setSocket] = useState(null);
useEffect(() => {
const socketInstance = io(serverURL, { transports: ["websocket"] });
diff --git a/client/src/common/context/useSubscription.tsx b/client/src/common/context/useSubscription.tsx
new file mode 100644
index 0000000000..8c85c6dccc
--- /dev/null
+++ b/client/src/common/context/useSubscription.tsx
@@ -0,0 +1,27 @@
+import { useEffect, useState } from 'react';
+
+import { useSocket } from './socketContext';
+
+export default function useSubscription(topic: string, initialState: T, requestString?: string) {
+ const socket = useSocket();
+ const [state, setState] = useState(initialState);
+
+ useEffect(() => {
+ if (!socket) {
+ return;
+ }
+
+ if (requestString) {
+ socket.emit(requestString);
+ } else {
+ socket.emit(`get-${topic}`);
+ }
+ socket.on(topic, setState);
+
+ return () => {
+ socket.off(topic);
+ };
+ }, [requestString, socket, topic]);
+
+ return [state, setState] as const;
+};
diff --git a/client/src/common/hooks/useElectronEvent.ts b/client/src/common/hooks/useElectronEvent.ts
index 504c76d603..065d1fa6ab 100644
--- a/client/src/common/hooks/useElectronEvent.ts
+++ b/client/src/common/hooks/useElectronEvent.ts
@@ -1,8 +1,7 @@
-// @ts-nocheck
export default function useElectronEvent() {
const isElectron = window?.process?.type === 'renderer';
- const sendToElectron = (channel: string, args: any) => {
+ const sendToElectron = (channel: string, args?: string | Record) => {
if (isElectron) {
window?.ipcRenderer.send(channel, args);
}
diff --git a/client/src/common/hooks/useFetch.js b/client/src/common/hooks/useFetch.js
deleted file mode 100644
index 7cab3a8929..0000000000
--- a/client/src/common/hooks/useFetch.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import { useQuery } from '@tanstack/react-query';
-
-const refetchIntervalMs = 10000;
-
-/**
- * @description utility hook to simplify query config
- * @param namespace
- * @param fn
- */
-export const useFetch = (namespace, fn) => {
- const { data, status, isError, refetch } = useQuery(namespace, fn, {
- refetchInterval: refetchIntervalMs,
- cacheTime: Infinity,
- });
-
- return { data, status, isError, refetch };
-};
diff --git a/client/src/common/hooks/useFetch.ts b/client/src/common/hooks/useFetch.ts
new file mode 100644
index 0000000000..9c8e4bf85a
--- /dev/null
+++ b/client/src/common/hooks/useFetch.ts
@@ -0,0 +1,18 @@
+import { QueryFunction, QueryKey, useQuery, UseQueryOptions } from '@tanstack/react-query';
+
+interface UseFetchState {
+ data: unknown;
+ status: "loading" | "error" | "success";
+ isError: boolean;
+ refetch: () => void;
+}
+
+export const useFetch = ( key: QueryKey, fn: QueryFunction, options?: UseQueryOptions): UseFetchState => {
+ const { data, status, isError, refetch } = useQuery(key, fn, {
+ refetchInterval: 10000,
+ cacheTime: Infinity,
+ ...options
+ });
+
+ return { data, status, isError, refetch };
+};
diff --git a/client/src/common/utils/eventsManager.js b/client/src/common/utils/eventsManager.ts
similarity index 71%
rename from client/src/common/utils/eventsManager.js
rename to client/src/common/utils/eventsManager.ts
index 408c81c3cf..61571f8607 100644
--- a/client/src/common/utils/eventsManager.js
+++ b/client/src/common/utils/eventsManager.ts
@@ -1,3 +1,5 @@
+import { OntimeEvent, OntimeEventEntry } from '../application-types/event';
+
import { formatTime } from './time';
/**
@@ -6,7 +8,7 @@ import { formatTime } from './time';
* @returns {Object[]} Filtered events with calculated delays
*/
-export const getEventsWithDelay = (events) => {
+export const getEventsWithDelay = (events: OntimeEventEntry[]) => {
if (events == null) return [];
const unfilteredEvents = [...events];
@@ -33,7 +35,7 @@ export const getEventsWithDelay = (events) => {
* @param {number} limit - max number of events to return
* @returns {Object[]} Event list with maximum objects
*/
-export const trimEventlist = (events, selectedId, limit) => {
+export const trimEventlist = (events: OntimeEventEntry[], selectedId: string, limit: number) => {
if (events == null) return [];
const BEFORE = 2;
@@ -53,6 +55,9 @@ export const trimEventlist = (events, selectedId, limit) => {
return trimmedEvents;
};
+type FormatEventListOptionsProp = {
+ showEnd?: boolean;
+}
/**
* @description Returns list of events formatted to be displayed
* @param {Object[]} events - given events
@@ -62,7 +67,7 @@ export const trimEventlist = (events, selectedId, limit) => {
* @param {boolean} [options.showEnd] - whether to show the end time
* @returns {Object[]} Formatted list of events [{time: -, title: -, isNow, isNext}]
*/
-export const formatEventList = (events, selectedId, nextId, options) => {
+export const formatEventList = (events: OntimeEvent[], selectedId: string, nextId: string, options: FormatEventListOptionsProp) => {
if (events == null) return [];
const { showEnd = false } = options;
@@ -71,7 +76,7 @@ export const formatEventList = (events, selectedId, nextId, options) => {
// format list
const formattedEvents = [];
for (const event of givenEvents) {
- const start = formatTime(event.timeStart)
+ const start = formatTime(event.timeStart);
const end = formatTime(event.timeEnd);
formattedEvents.push({
@@ -86,3 +91,23 @@ export const formatEventList = (events, selectedId, nextId, options) => {
return formattedEvents;
};
+
+/**
+ * @description Creates a safe duplicate of an event
+ * @param {object} event
+ * @return {object} clean event
+ */
+export const duplicateEvent = (event: OntimeEvent) => {
+ return {
+ type: 'event',
+ title: event.title,
+ subtitle: event.subtitle,
+ presenter: event.presenter,
+ note: event.note,
+ timeStart: event.timeStart,
+ timeEnd: event.timeEnd,
+ isPublic: event.isPublic,
+ skip: event.skip,
+ colour: event.colour,
+ };
+};
diff --git a/client/src/common/utils/styleUtils.ts b/client/src/common/utils/styleUtils.ts
new file mode 100644
index 0000000000..cc54b93423
--- /dev/null
+++ b/client/src/common/utils/styleUtils.ts
@@ -0,0 +1,23 @@
+import Color from 'color';
+
+type ColourCombination = {
+ backgroundColor: string;
+ color: string;
+}
+
+/**
+ * @description Selects text colour to maintain accessible contrast
+ * @param bgColour
+ * @return {{backgroundColor, color: string}}
+ */
+export const getAccessibleColour = (bgColour: string): ColourCombination => {
+ if (bgColour) {
+ try {
+ const textColor = Color(bgColour).isLight() ? 'black' : '#fffffa';
+ return { backgroundColor: bgColour, color: textColor };
+ } catch (error) {
+ console.log(`Unable to parse colour: ${bgColour}`);
+ }
+ }
+ return { backgroundColor: '#000', color: "#fffffa" };
+};
diff --git a/client/src/declarations/declaration.d.ts b/client/src/declarations/declaration.d.ts
index 77a73098ff..42ed86f0ff 100644
--- a/client/src/declarations/declaration.d.ts
+++ b/client/src/declarations/declaration.d.ts
@@ -3,8 +3,16 @@ declare module '*.scss' {
export default content;
}
-declare namespace NodeJS {
- export interface ProcessEnv {
- type: string
+declare global {
+ interface Window {
+ ipcRenderer: {
+ send: (channel: string, args?: string | object) => void;
+ };
+ process: {
+ type: string;
+ }
}
}
+
+// eslint-disable-next-line import/no-anonymous-default-export
+export default {}
\ No newline at end of file
diff --git a/client/src/features/editors/list/EventListWrapper.jsx b/client/src/features/editors/list/EventListWrapper.jsx
index fea78f725e..24cf21f3f9 100644
--- a/client/src/features/editors/list/EventListWrapper.jsx
+++ b/client/src/features/editors/list/EventListWrapper.jsx
@@ -12,7 +12,7 @@ import {
requestReorder,
} from 'common/api/eventsApi.js';
import Empty from 'common/components/state/Empty';
-import { useFetch } from 'common/hooks/useFetch.js';
+import { useFetch } from 'common/hooks/useFetch.ts';
import EventListMenu from 'features/menu/EventListMenu.jsx';
import { CollapseContext } from '../../../common/context/CollapseContext';
diff --git a/client/src/features/menu/__tests__/MenuBar.test.tsx b/client/src/features/menu/__tests__/MenuBar.test.tsx
index 5eba42f804..5741e6fd79 100644
--- a/client/src/features/menu/__tests__/MenuBar.test.tsx
+++ b/client/src/features/menu/__tests__/MenuBar.test.tsx
@@ -5,18 +5,22 @@ import { vi } from 'vitest';
import { queryClientMock } from '../../../__mocks__/QueryClient.mock';
import MenuBar from '../MenuBar';
-const onOpenHandler = vi.fn();
-const onCloseHandler = vi.fn();
-const isOpen = false;
+const onSettingOpenHandler = vi.fn();
+const onSettingsCloseHandler = vi.fn();
const onUploadOpenHandler = vi.fn();
+const isOpen = false;
const renderInMock = () => {
render(
-
- ,
+
+
);
};
diff --git a/client/src/features/table/tableRows/EventRow.jsx b/client/src/features/table/tableRows/EventRow.jsx
index 075acba0d5..e25ea7c525 100644
--- a/client/src/features/table/tableRows/EventRow.jsx
+++ b/client/src/features/table/tableRows/EventRow.jsx
@@ -1,29 +1,13 @@
-import Color from 'color';
import PropTypes from 'prop-types';
-import style from '../Table.module.scss';
+import { getAccessibleColour } from '../../../common/utils/styleUtils';
-/**
- * Selects text colour to maintain accessible contrast
- * @param bgColour
- * @return {{backgroundColor, color: string}}
- */
-const selCol = (bgColour) => {
- if (bgColour != null && bgColour !== '') {
- try {
- const textColor = Color(bgColour).isLight() ? 'black' : 'white';
- return { backgroundColor: bgColour, color: textColor };
- } catch (error) {
- console.log(`Unable to parse colour: ${bgColour}`);
- }
- }
-};
+import style from '../Table.module.scss';
export default function EventRow(props) {
const { row, index, selectedId, delay } = props;
const selected = row.original.id === selectedId;
- const colours = selCol(row.original.colour);
-
+ const colours = getAccessibleColour(row.original.colour);
return (
diff --git a/client/src/features/viewers/ViewWrapper.jsx b/client/src/features/viewers/ViewWrapper.jsx
index 876ba50353..efd6e4da60 100644
--- a/client/src/features/viewers/ViewWrapper.jsx
+++ b/client/src/features/viewers/ViewWrapper.jsx
@@ -1,22 +1,25 @@
/* eslint-disable react/display-name */
-import { useEffect, useState } from 'react';
-import { EVENT_TABLE, EVENTS_TABLE, VIEW_SETTINGS } from 'common/api/apiConstants';
-import { fetchEvent } from 'common/api/eventApi';
-import { fetchAllEvents } from 'common/api/eventsApi';
-import { useSocket } from 'common/context/socketContext';
-import { useFetch } from 'common/hooks/useFetch';
+import { useEffect, useMemo, useState } from 'react';
+import { EVENT_TABLE, EVENTS_TABLE } from '../../common/api/apiConstants';
+import { fetchEvent } from '../../common/api/eventApi';
+import { fetchAllEvents } from '../../common/api/eventsApi';
+import { useSocket } from '../../common/context/socketContext';
+import { useFetch } from '../../common/hooks/useFetch';
import { getView } from '../../common/api/ontimeApi';
+import useSubscription from '../../common/context/useSubscription';
+import { eventPlaceholderSettings } from '../../common/api/ontimeApi';
const withSocket = (Component) => {
return (props) => {
- const { data: eventsData } = useFetch(EVENTS_TABLE, fetchAllEvents);
- const { data: genData } = useFetch(EVENT_TABLE, fetchEvent);
+ const { data: eventsData } = useFetch(EVENTS_TABLE, fetchAllEvents, {
+ placeholderData: [],
+ });
+ const { data: genData } = useFetch(EVENT_TABLE, fetchEvent, {
+ placeholderData: eventPlaceholderSettings,
+ });
const { data: viewSettings } = useFetch(VIEW_SETTINGS, getView);
- const [publicEvents, setPublicEvents] = useState([]);
- const [backstageEvents, setBackstageEvents] = useState([]);
-
const socket = useSocket();
const [pres, setPres] = useState({
text: '',
@@ -30,14 +33,16 @@ const withSocket = (Component) => {
text: '',
visible: false,
});
- const [timer, setTimer] = useState({
+ const [publicSelectedId, setPublicSelectedId] = useState(null);
+
+ const [timer] = useSubscription('timer', {
clock: 0,
running: 0,
isNegative: false,
startedAt: null,
expectedFinish: null,
});
- const [titles, setTitles] = useState({
+ const [titles] = useSubscription('titles', {
titleNow: '',
subtitleNow: '',
presenterNow: '',
@@ -45,7 +50,7 @@ const withSocket = (Component) => {
subtitleNext: '',
presenterNext: '',
});
- const [publicTitles, setPublicTitles] = useState({
+ const [publicTitles] = useSubscription('publictitles', {
titleNow: '',
subtitleNow: '',
presenterNow: '',
@@ -53,18 +58,10 @@ const withSocket = (Component) => {
subtitleNext: '',
presenterNext: '',
});
- const [selectedId, setSelectedId] = useState(null);
- const [nextId, setNextId] = useState(null);
- const [publicSelectedId, setPublicSelectedId] = useState(null);
- const [general, setGeneral] = useState({
- title: '',
- url: '',
- publicInfo: '',
- backstageInfo: '',
- endMessage: '',
- });
- const [playback, setPlayback] = useState(null);
- const [onAir, setOnAir] = useState(false);
+ const [selectedId] = useSubscription('selected-id', null);
+ const [nextId] = useSubscription('next-id', null);
+ const [playback] = useSubscription('playstate', null);
+ const [onAir] = useSubscription('onAir', false);
// Ask for update on load
useEffect(() => {
@@ -87,96 +84,29 @@ const withSocket = (Component) => {
setLower({ ...data });
});
- // Handle timer
- socket.on('timer', (data) => {
- setTimer({ ...data });
- });
-
- // Handle playstate
- socket.on('playstate', (data) => {
- setPlayback(data);
- });
- socket.on('onAir', (data) => {
- setOnAir(data);
- });
-
- // Handle titles
- socket.on('titles', (data) => {
- setTitles({ ...data });
- });
- socket.on('publictitles', (data) => {
- setPublicTitles({ ...data });
- });
-
- // Handle selected event
- socket.on('selected-id', (data) => {
- setSelectedId(data);
- });
socket.on('publicselected-id', (data) => {
setPublicSelectedId(data);
});
- socket.on('next-id', (data) => {
- setNextId(data);
- });
// Ask for up to date data
socket.emit('get-messages');
- // Ask for up to data
- socket.emit('get-timer');
-
- // ask for timer
- socket.emit('get-timer');
-
- // ask for playstate
- socket.emit('get-playstate');
- socket.emit('get-onAir');
-
- // Ask for up titles
- socket.emit('get-titles');
- socket.emit('get-publictitles');
-
- // Ask for up selected
- socket.emit('get-selected-id');
- socket.emit('get-next-id');
-
// Clear listeners
return () => {
socket.off('messages-public');
socket.off('messages-timer');
socket.off('messages-lower');
- socket.off('timer');
- socket.off('playstate');
- socket.off('onAir');
- socket.off('titles');
- socket.off('publictitles');
- socket.off('selected-id');
- socket.emit('next-id');
};
}, [socket]);
- // Filter events only to pass down
- useEffect(() => {
- if (!eventsData) {
- return;
- }
- // filter just events with title
- if (Array.isArray(eventsData)) {
- const pe = eventsData.filter((d) => d.type === 'event' && d.title !== '' && d.isPublic);
- setPublicEvents(pe);
-
- // everything goes backstage
- setBackstageEvents(eventsData);
- }
- }, [eventsData]);
- // Set general data
- useEffect(() => {
- if (!genData) {
- return;
+ const publicEvents = useMemo(() => {
+ if (Array.isArray(eventsData)) {
+ return eventsData.filter((d) => d.type === 'event' && d.title !== '' && d.isPublic);
+ } else {
+ return [];
}
- setGeneral(genData);
- }, [genData]);
+ },[eventsData])
/********************************************/
/*** + titleManager ***/
@@ -245,12 +175,12 @@ const withSocket = (Component) => {
publicTitle={publicTitleManager}
time={timeManager}
events={publicEvents}
- backstageEvents={backstageEvents}
+ backstageEvents={eventsData}
selectedId={selectedId}
publicSelectedId={publicSelectedId}
viewSettings={viewSettings}
nextId={nextId}
- general={general}
+ general={genData}
onAir={onAir}
/>
);
diff --git a/client/src/features/viewers/backstage/Backstage.jsx b/client/src/features/viewers/backstage/Backstage.jsx
index 915bcede86..72037afb5f 100644
--- a/client/src/features/viewers/backstage/Backstage.jsx
+++ b/client/src/features/viewers/backstage/Backstage.jsx
@@ -1,13 +1,13 @@
import { useEffect, useState } from 'react';
import QRCode from 'react-qr-code';
import NavLogo from 'common/components/nav/NavLogo';
-import Paginator from 'common/components/paginator/Paginator';
import TitleSide from 'common/components/title-side/TitleSide';
import { formatDisplay } from 'common/utils/dateConfig';
import { AnimatePresence, motion } from 'framer-motion';
import PropTypes from 'prop-types';
import { overrideStylesURL } from '../../../common/api/apiConstants';
+import Paginator from '../../../common/components/views/Paginator';
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
import { getEventsWithDelay } from '../../../common/utils/eventsManager';
import { formatTime } from '../../../common/utils/time';
diff --git a/client/src/features/viewers/picture-in-picture/Pip.jsx b/client/src/features/viewers/picture-in-picture/Pip.jsx
index 8ea87fcd5a..c202ae7460 100644
--- a/client/src/features/viewers/picture-in-picture/Pip.jsx
+++ b/client/src/features/viewers/picture-in-picture/Pip.jsx
@@ -2,12 +2,12 @@ import { useEffect, useRef, useState } from 'react';
import QRCode from 'react-qr-code';
import { ReactComponent as Emptyimage } from 'assets/images/empty.svg';
import NavLogo from 'common/components/nav/NavLogo';
-import Paginator from 'common/components/paginator/Paginator';
import { formatDisplay } from 'common/utils/dateConfig';
import { AnimatePresence, motion } from 'framer-motion';
import PropTypes from 'prop-types';
import { overrideStylesURL } from '../../../common/api/apiConstants';
+import Paginator from '../../../common/components/views/Paginator';
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
import { formatTime } from '../../../common/utils/time';
diff --git a/client/src/features/viewers/public/Public.jsx b/client/src/features/viewers/public/Public.jsx
index 07f410da17..c4ce6fd3c3 100644
--- a/client/src/features/viewers/public/Public.jsx
+++ b/client/src/features/viewers/public/Public.jsx
@@ -1,12 +1,12 @@
import { useEffect, useState } from 'react';
import QRCode from 'react-qr-code';
import NavLogo from 'common/components/nav/NavLogo';
-import Paginator from 'common/components/paginator/Paginator';
import TitleSide from 'common/components/title-side/TitleSide';
import { AnimatePresence, motion } from 'framer-motion';
import PropTypes from 'prop-types';
import { overrideStylesURL } from '../../../common/api/apiConstants';
+import Paginator from '../../../common/components/views/Paginator';
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
import { formatTime } from '../../../common/utils/time';
import { titleVariants } from '../common/animation';
@@ -24,7 +24,6 @@ export default function Public(props) {
const [pageNumber, setPageNumber] = useState(0);
const [currentPage, setCurrentPage] = useState(0);
- // Set window title
useEffect(() => {
document.title = 'ontime - Public Screen';
}, []);
@@ -36,7 +35,6 @@ export default function Public(props) {
// Format messages
const showPubl = publ.text !== '' && publ.visible;
-
const clock = formatTime(time.clock, formatOptions);
return (
@@ -136,7 +134,7 @@ Public.propTypes = {
publ: PropTypes.object,
publicTitle: PropTypes.object,
time: PropTypes.object,
- events: PropTypes.object,
+ events: PropTypes.array,
publicSelectedId: PropTypes.string,
general: PropTypes.object,
viewSettings: PropTypes.object,
diff --git a/client/yarn.lock b/client/yarn.lock
index 47bfe28c49..b1c754478e 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -1583,6 +1583,25 @@
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.3.tgz#3c90752792660c4b562ad73b3fbd68bf3bc7ae07"
integrity sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==
+"@types/color-convert@*":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@types/color-convert/-/color-convert-2.0.0.tgz#8f5ee6b9e863dcbee5703f5a517ffb13d3ea4e22"
+ integrity sha512-m7GG7IKKGuJUXvkZ1qqG3ChccdIM/qBBo913z+Xft0nKCX4hAU/IxKwZBU4cpRZ7GS5kV4vOblUkILtSShCPXQ==
+ dependencies:
+ "@types/color-name" "*"
+
+"@types/color-name@*":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
+ integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
+
+"@types/color@^3.0.3":
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/@types/color/-/color-3.0.3.tgz#e6d8d72b7aaef4bb9fe80847c26c7c786191016d"
+ integrity sha512-X//qzJ3d3Zj82J9sC/C18ZY5f43utPbAJ6PhYt/M7uG6etcF6MRpKdN880KBy43B0BMzSfeT96MzrsNjFI3GbA==
+ dependencies:
+ "@types/color-convert" "*"
+
"@types/hoist-non-react-statics@^3.3.0":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"