mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-08 00:43:54 +00:00
Feat/104 (#140)
* feat/104: isolate control components * feat/104: open components in isolated window * feat/104: update tests
This commit is contained in:
@@ -27,6 +27,12 @@ const SLowerThird = withSocket(Lower);
|
||||
const SPip = withSocket(Pip);
|
||||
const SStudio = withSocket(StudioClock);
|
||||
|
||||
const FeatureWrapper = lazy(() => import('features/FeatureWrapper'));
|
||||
const EventList = lazy(() => import('features/editors/list/EventListExport'));
|
||||
const TimerControl = lazy(() => import('features/control/playback/TimerControlExport'));
|
||||
const MessageControl = lazy(() => import('features/control/message/MessageControlExport'));
|
||||
const Info = lazy(() => import('features/info/InfoExport'));
|
||||
|
||||
function App() {
|
||||
const { data } = useFetch(ALIASES, getAliases);
|
||||
const location = useLocation();
|
||||
@@ -99,6 +105,39 @@ function App() {
|
||||
<Route path='/cuelist' element={<Table />} />
|
||||
<Route path='/table' element={<Table />} />
|
||||
|
||||
{/*/!* Protected Routes - Elements *!/*/}
|
||||
<Route
|
||||
path='/eventlist'
|
||||
element={
|
||||
<FeatureWrapper>
|
||||
<EventList />
|
||||
</FeatureWrapper>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path='/timercontrol'
|
||||
element={
|
||||
<FeatureWrapper>
|
||||
<TimerControl />
|
||||
</FeatureWrapper>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path='/messagecontrol'
|
||||
element={
|
||||
<FeatureWrapper>
|
||||
<MessageControl />
|
||||
</FeatureWrapper>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path='/info'
|
||||
element={
|
||||
<FeatureWrapper>
|
||||
<Info />
|
||||
</FeatureWrapper>
|
||||
}
|
||||
/>
|
||||
{/* Send to default if nothing found */}
|
||||
<Route path='*' element={<STimer />} />
|
||||
</Routes>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import ProtectRoute from '../common/components/protectRoute/ProtectRoute';
|
||||
import PropTypes from 'prop-types';
|
||||
import style from './FeatureWrapper.module.scss';
|
||||
|
||||
export default function FeatureWrapper({ children }) {
|
||||
return (
|
||||
<ProtectRoute>
|
||||
<div className={style.wrapper}>{children}</div>
|
||||
</ProtectRoute>
|
||||
);
|
||||
}
|
||||
|
||||
FeatureWrapper.propTypes = {
|
||||
children: PropTypes.element,
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
@use '../styles/main' as *;
|
||||
|
||||
.wrapper {
|
||||
background: $bg-black;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: auto;
|
||||
color: $title-white;
|
||||
padding: max(16px, 2vh);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
import { Box } from '@chakra-ui/layout';
|
||||
import ErrorBoundary from '../../../common/components/errorBoundary/ErrorBoundary';
|
||||
import MessageControl from './MessageControl';
|
||||
import style from '../../editors/Editor.module.scss';
|
||||
import { FiArrowUpRight } from '@react-icons/all-files/fi/FiArrowUpRight';
|
||||
import { handleLinks } from '../../../common/utils/linkUtils';
|
||||
|
||||
export default function MessageControlExport() {
|
||||
return (
|
||||
<Box className={style.messages}>
|
||||
<h1>Messages Control</h1>
|
||||
<FiArrowUpRight className={style.corner} onClick={(event) => handleLinks(event, 'messagecontrol')} />
|
||||
<div className={style.content}>
|
||||
<ErrorBoundary>
|
||||
<MessageControl />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
import { Box } from '@chakra-ui/layout';
|
||||
import ErrorBoundary from '../../../common/components/errorBoundary/ErrorBoundary';
|
||||
import PlaybackControl from './PlaybackControl';
|
||||
import styles from '../../editors/Editor.module.scss';
|
||||
import style from '../../editors/Editor.module.scss';
|
||||
import { FiArrowUpRight } from '@react-icons/all-files/fi/FiArrowUpRight';
|
||||
import { handleLinks } from '../../../common/utils/linkUtils';
|
||||
|
||||
export default function TimerControlExport() {
|
||||
return (
|
||||
<Box className={styles.playback}>
|
||||
<h1>Timer Control</h1>
|
||||
<FiArrowUpRight className={style.corner} onClick={(event) => handleLinks(event, 'timercontrol')} />
|
||||
<div className={styles.content}>
|
||||
<ErrorBoundary>
|
||||
<PlaybackControl />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -1,19 +1,17 @@
|
||||
import React, { lazy, useEffect } from 'react';
|
||||
import { Box } from '@chakra-ui/layout';
|
||||
import { useDisclosure } from '@chakra-ui/hooks';
|
||||
import MenuBar from 'features/menu/MenuBar';
|
||||
import ModalManager from 'features/modals/ModalManager';
|
||||
import ErrorBoundary from 'common/components/errorBoundary/ErrorBoundary';
|
||||
import { LoggingProvider } from '../../app/context/LoggingContext';
|
||||
import { LocalEventSettingsProvider } from '../../app/context/LocalEventSettingsContext';
|
||||
import { CursorProvider } from '../../app/context/CursorContext';
|
||||
import { CollapseProvider } from '../../app/context/CollapseContext';
|
||||
import { Box } from '@chakra-ui/layout';
|
||||
import MenuBar from '../menu/MenuBar';
|
||||
import styles from './Editor.module.scss';
|
||||
|
||||
const EventListWrapper = lazy(() => import('features/editors/list/EventListWrapper'));
|
||||
const PlaybackControl = lazy(() => import('features/control/playback/PlaybackControl'));
|
||||
const MessageControl = lazy(() => import('features/control/message/MessageControl'));
|
||||
const Info = lazy(() => import('features/info/Info'));
|
||||
const EventList = lazy(() => import('features/editors/list/EventListExport'));
|
||||
const TimerControl = lazy(() => import('features/control/playback/TimerControlExport'));
|
||||
const MessageControl = lazy(() => import('features/control/message/MessageControlExport'));
|
||||
const Info = lazy(() => import('features/info/InfoExport'));
|
||||
|
||||
export default function Editor() {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
@@ -29,51 +27,16 @@ export default function Editor() {
|
||||
<ErrorBoundary>
|
||||
<ModalManager isOpen={isOpen} onClose={onClose} />
|
||||
</ErrorBoundary>
|
||||
|
||||
<div className={styles.mainContainer}>
|
||||
<CursorProvider>
|
||||
<CollapseProvider>
|
||||
<Box id='settings' className={styles.settings}>
|
||||
<ErrorBoundary>
|
||||
<MenuBar onOpen={onOpen} isOpen={isOpen} onClose={onClose} />
|
||||
</ErrorBoundary>
|
||||
</Box>
|
||||
|
||||
<Box className={styles.editor}>
|
||||
<h1>Event List</h1>
|
||||
<ErrorBoundary>
|
||||
<EventListWrapper />
|
||||
</ErrorBoundary>
|
||||
</Box>
|
||||
</CollapseProvider>
|
||||
</CursorProvider>
|
||||
|
||||
<Box className={styles.messages}>
|
||||
<h1>Display Messages</h1>
|
||||
<div className={styles.content}>
|
||||
<ErrorBoundary>
|
||||
<MessageControl />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</Box>
|
||||
|
||||
<Box className={styles.playback}>
|
||||
<h1>Timer Control</h1>
|
||||
<div className={styles.content}>
|
||||
<ErrorBoundary>
|
||||
<PlaybackControl />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</Box>
|
||||
|
||||
<Box className={styles.info}>
|
||||
<h1>Info</h1>
|
||||
<div className={styles.content}>
|
||||
<ErrorBoundary>
|
||||
<Info />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
<Box id='settings' className={styles.settings}>
|
||||
<ErrorBoundary>
|
||||
<MenuBar onOpen={onOpen} isOpen={isOpen} onClose={onClose} />
|
||||
</ErrorBoundary>
|
||||
</Box>
|
||||
<EventList onOpen={onOpen} isOpen={isOpen} onClose={onClose} />
|
||||
<MessageControl />
|
||||
<TimerControl />
|
||||
<Info />
|
||||
</div>
|
||||
</LocalEventSettingsProvider>
|
||||
</LoggingProvider>
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
@use '../../styles/main' as *;
|
||||
|
||||
.corner {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
cursor: pointer;
|
||||
color: $ontime-pink;
|
||||
}
|
||||
|
||||
.mainContainer {
|
||||
background: $bg-black;
|
||||
width: 100%;
|
||||
@@ -15,6 +24,18 @@
|
||||
'sett even play info'
|
||||
'sett even mess info';
|
||||
gap: max(16px, 2vh);
|
||||
|
||||
.editor,
|
||||
.playback,
|
||||
.messages,
|
||||
.info,
|
||||
.settings {
|
||||
position: relative;
|
||||
|
||||
.corner {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 2/3 window, hide info */
|
||||
@@ -112,6 +133,7 @@ h1 {
|
||||
|
||||
.editor {
|
||||
grid-area: even;
|
||||
height: calc(100% - 3em);
|
||||
|
||||
.content {
|
||||
height: calc(100% - 3em);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import { CursorProvider } from '../../../app/context/CursorContext';
|
||||
import { CollapseProvider } from '../../../app/context/CollapseContext';
|
||||
import { Box } from '@chakra-ui/layout';
|
||||
import ErrorBoundary from '../../../common/components/errorBoundary/ErrorBoundary';
|
||||
import EventListWrapper from './EventListWrapper';
|
||||
import { FiArrowUpRight } from '@react-icons/all-files/fi/FiArrowUpRight';
|
||||
import { handleLinks } from '../../../common/utils/linkUtils';
|
||||
import style from '../Editor.module.scss';
|
||||
|
||||
export default function EventListExport() {
|
||||
return (
|
||||
<CursorProvider>
|
||||
<CollapseProvider>
|
||||
<Box className={style.editor}>
|
||||
<h1>Event List</h1>
|
||||
<FiArrowUpRight
|
||||
className={style.corner}
|
||||
onClick={(event) => handleLinks(event, 'eventlist')}
|
||||
/>
|
||||
<ErrorBoundary>
|
||||
<EventListWrapper />
|
||||
</ErrorBoundary>
|
||||
</Box>
|
||||
</CollapseProvider>
|
||||
</CursorProvider>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
import { Box } from '@chakra-ui/layout';
|
||||
import { FiArrowUpRight } from '@react-icons/all-files/fi/FiArrowUpRight';
|
||||
import ErrorBoundary from '../../common/components/errorBoundary/ErrorBoundary';
|
||||
import Info from './Info';
|
||||
import style from '../editors/Editor.module.scss';
|
||||
import { handleLinks } from '../../common/utils/linkUtils';
|
||||
|
||||
export default function InfoExport() {
|
||||
return (
|
||||
<Box className={style.info}>
|
||||
<h1>Info</h1>
|
||||
<FiArrowUpRight className={style.corner} onClick={(event) => handleLinks(event, 'info')} />
|
||||
<div className={style.content}>
|
||||
<ErrorBoundary>
|
||||
<Info />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -38,11 +38,23 @@ describe('validate routes', () => {
|
||||
cy.visit('http://localhost:4001/studio');
|
||||
cy.contains('ON AIR');
|
||||
});
|
||||
|
||||
it('editor routes', () => {
|
||||
cy.visit('http://localhost:4001/editor');
|
||||
cy.contains('Event List');
|
||||
cy.contains('Timer Control');
|
||||
cy.contains('Display Messages');
|
||||
cy.contains('Messages Control');
|
||||
cy.contains('Info');
|
||||
});
|
||||
|
||||
it('self contained editor routes', () => {
|
||||
cy.visit('http://localhost:4001/eventlist');
|
||||
cy.contains('Event List');
|
||||
cy.visit('http://localhost:4001/timercontrol');
|
||||
cy.contains('Timer Control');
|
||||
cy.visit('http://localhost:4001/messagecontrol');
|
||||
cy.contains('Messages Control');
|
||||
cy.visit('http://localhost:4001/info');
|
||||
cy.contains('Info');
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user