mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-22 07:29:08 +00:00
refactor: improve navigation and settings locks
This commit is contained in:
committed by
Carlos Valente
parent
836fa52757
commit
efceb930e5
@@ -11,7 +11,7 @@ import Log from './features/log/Log';
|
|||||||
import Loader from './views/common/loader/Loader';
|
import Loader from './views/common/loader/Loader';
|
||||||
import NotFound from './views/common/not-found/NotFound';
|
import NotFound from './views/common/not-found/NotFound';
|
||||||
import ViewLoader from './views/ViewLoader';
|
import ViewLoader from './views/ViewLoader';
|
||||||
import { getIsViewLocked, sessionScope } from './externals';
|
import { getIsNavigationLocked, sessionScope } from './externals';
|
||||||
import { initializeSentry } from './sentry.config';
|
import { initializeSentry } from './sentry.config';
|
||||||
|
|
||||||
const Timer = lazy(() => import('./views/timer/Timer'));
|
const Timer = lazy(() => import('./views/timer/Timer'));
|
||||||
@@ -45,7 +45,7 @@ export default function AppRouter() {
|
|||||||
path='timer'
|
path='timer'
|
||||||
element={
|
element={
|
||||||
<ViewLoader>
|
<ViewLoader>
|
||||||
<ViewNavigationMenu isViewLocked={getIsViewLocked()} />
|
<ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} />
|
||||||
<Timer />
|
<Timer />
|
||||||
</ViewLoader>
|
</ViewLoader>
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ export default function AppRouter() {
|
|||||||
path='countdown'
|
path='countdown'
|
||||||
element={
|
element={
|
||||||
<ViewLoader>
|
<ViewLoader>
|
||||||
<ViewNavigationMenu isViewLocked={getIsViewLocked()} />
|
<ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} />
|
||||||
<Countdown />
|
<Countdown />
|
||||||
</ViewLoader>
|
</ViewLoader>
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ export default function AppRouter() {
|
|||||||
path='backstage'
|
path='backstage'
|
||||||
element={
|
element={
|
||||||
<ViewLoader>
|
<ViewLoader>
|
||||||
<ViewNavigationMenu isViewLocked={getIsViewLocked()} />
|
<ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} />
|
||||||
<Backstage />
|
<Backstage />
|
||||||
</ViewLoader>
|
</ViewLoader>
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ export default function AppRouter() {
|
|||||||
path='studio'
|
path='studio'
|
||||||
element={
|
element={
|
||||||
<ViewLoader>
|
<ViewLoader>
|
||||||
<ViewNavigationMenu isViewLocked={getIsViewLocked()} />
|
<ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} />
|
||||||
<StudioClock />
|
<StudioClock />
|
||||||
</ViewLoader>
|
</ViewLoader>
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,7 @@ export default function AppRouter() {
|
|||||||
path='timeline'
|
path='timeline'
|
||||||
element={
|
element={
|
||||||
<ViewLoader>
|
<ViewLoader>
|
||||||
<ViewNavigationMenu isViewLocked={getIsViewLocked()} />
|
<ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} />
|
||||||
<Timeline />
|
<Timeline />
|
||||||
</ViewLoader>
|
</ViewLoader>
|
||||||
}
|
}
|
||||||
@@ -90,7 +90,7 @@ export default function AppRouter() {
|
|||||||
path='info'
|
path='info'
|
||||||
element={
|
element={
|
||||||
<ViewLoader>
|
<ViewLoader>
|
||||||
<ViewNavigationMenu suppressSettings isViewLocked={getIsViewLocked()} />
|
<ViewNavigationMenu suppressSettings isNavigationLocked={getIsNavigationLocked()} />
|
||||||
<ProjectInfo />
|
<ProjectInfo />
|
||||||
</ViewLoader>
|
</ViewLoader>
|
||||||
}
|
}
|
||||||
@@ -198,7 +198,7 @@ function PresetView() {
|
|||||||
if (!preset) {
|
if (!preset) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewNavigationMenu isViewLocked={!showNav} suppressSettings />
|
<ViewNavigationMenu isNavigationLocked={!showNav} suppressSettings />
|
||||||
<NotFound />
|
<NotFound />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -212,7 +212,7 @@ function PresetView() {
|
|||||||
return (
|
return (
|
||||||
<PresetContext value={preset}>
|
<PresetContext value={preset}>
|
||||||
{preset.target !== OntimeView.Cuesheet && (
|
{preset.target !== OntimeView.Cuesheet && (
|
||||||
<ViewNavigationMenu isViewLocked={getIsViewLocked()} suppressSettings />
|
<ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} suppressSettings />
|
||||||
)}
|
)}
|
||||||
{Component ? <Component /> : <NotFound />}
|
{Component ? <Component /> : <NotFound />}
|
||||||
</PresetContext>
|
</PresetContext>
|
||||||
@@ -243,7 +243,7 @@ function RedirectPreset() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewNavigationMenu isViewLocked={getIsViewLocked()} suppressSettings />
|
<ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} suppressSettings />
|
||||||
<NotFound />
|
<NotFound />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ import ViewLockedIcon from './view-locked-icon/ViewLockedIcon';
|
|||||||
import NavigationMenu from './NavigationMenu';
|
import NavigationMenu from './NavigationMenu';
|
||||||
|
|
||||||
interface ViewNavigationMenuProps {
|
interface ViewNavigationMenuProps {
|
||||||
/** prevent navigation and settings*/
|
/** prevent navigation */
|
||||||
isViewLocked?: boolean;
|
isNavigationLocked?: boolean;
|
||||||
/** prevent showing settings */
|
/** prevent showing settings */
|
||||||
suppressSettings?: boolean;
|
suppressSettings?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(ViewNavigationMenu);
|
export default memo(ViewNavigationMenu);
|
||||||
function ViewNavigationMenu({ isViewLocked, suppressSettings }: ViewNavigationMenuProps) {
|
function ViewNavigationMenu({ isNavigationLocked, suppressSettings }: ViewNavigationMenuProps) {
|
||||||
const [isMenuOpen, menuHandler] = useDisclosure();
|
const [isMenuOpen, menuHandler] = useDisclosure();
|
||||||
const { open: showEditFormDrawer } = useViewParamsEditorStore();
|
const { open: showEditFormDrawer } = useViewParamsEditorStore();
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ function ViewNavigationMenu({ isViewLocked, suppressSettings }: ViewNavigationMe
|
|||||||
[
|
[
|
||||||
'Space',
|
'Space',
|
||||||
() => {
|
() => {
|
||||||
if (isViewLocked) return;
|
if (isNavigationLocked) return;
|
||||||
menuHandler.toggle();
|
menuHandler.toggle();
|
||||||
},
|
},
|
||||||
{ preventDefault: true },
|
{ preventDefault: true },
|
||||||
@@ -31,24 +31,24 @@ function ViewNavigationMenu({ isViewLocked, suppressSettings }: ViewNavigationMe
|
|||||||
[
|
[
|
||||||
'mod + ,',
|
'mod + ,',
|
||||||
() => {
|
() => {
|
||||||
if (isViewLocked || suppressSettings) return;
|
if (suppressSettings) return;
|
||||||
showEditFormDrawer();
|
showEditFormDrawer();
|
||||||
},
|
},
|
||||||
{ preventDefault: true },
|
{ preventDefault: true },
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (isViewLocked) {
|
if (isNavigationLocked && suppressSettings) {
|
||||||
return <ViewLockedIcon />;
|
return <ViewLockedIcon />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FloatingNavigation
|
<FloatingNavigation
|
||||||
toggleMenu={menuHandler.toggle}
|
toggleMenu={isNavigationLocked ? undefined : menuHandler.toggle}
|
||||||
toggleSettings={suppressSettings ? undefined : () => showEditFormDrawer()}
|
toggleSettings={suppressSettings ? undefined : showEditFormDrawer}
|
||||||
/>
|
/>
|
||||||
<NavigationMenu isOpen={isMenuOpen} onClose={menuHandler.close} />
|
{!isNavigationLocked && <NavigationMenu isOpen={isMenuOpen} onClose={menuHandler.close} />}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-10
@@ -8,7 +8,7 @@ import IconButton from '../../buttons/IconButton';
|
|||||||
import style from './FloatingNavigation.module.scss';
|
import style from './FloatingNavigation.module.scss';
|
||||||
|
|
||||||
interface FloatingNavigationProps {
|
interface FloatingNavigationProps {
|
||||||
toggleMenu: () => void;
|
toggleMenu?: () => void;
|
||||||
toggleSettings?: () => void;
|
toggleSettings?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,15 +20,17 @@ export default function FloatingNavigation({ toggleMenu, toggleSettings }: Float
|
|||||||
id='fadeable-navigation'
|
id='fadeable-navigation'
|
||||||
className={cx([style.fadeable, style.buttonContainer, !isButtonShown && style.hidden])}
|
className={cx([style.fadeable, style.buttonContainer, !isButtonShown && style.hidden])}
|
||||||
>
|
>
|
||||||
<IconButton
|
{toggleMenu && (
|
||||||
variant='subtle-white'
|
<IconButton
|
||||||
size='xlarge'
|
variant='subtle-white'
|
||||||
onClick={toggleMenu}
|
size='xlarge'
|
||||||
aria-label='toggle menu'
|
onClick={toggleMenu}
|
||||||
data-testid='navigation__toggle-menu'
|
aria-label='toggle menu'
|
||||||
>
|
data-testid='navigation__toggle-menu'
|
||||||
<IoApps />
|
>
|
||||||
</IconButton>
|
<IoApps />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
{toggleSettings && (
|
{toggleSettings && (
|
||||||
<IconButton
|
<IconButton
|
||||||
variant='subtle-white'
|
variant='subtle-white'
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ function resolveBaseURI(): string {
|
|||||||
* Resolves a session scope for the session
|
* Resolves a session scope for the session
|
||||||
*/
|
*/
|
||||||
export const sessionScope = resolveSessionScope();
|
export const sessionScope = resolveSessionScope();
|
||||||
export const getIsViewLocked = () => window.location.search.includes('n=1');
|
export const getIsNavigationLocked = () => new URLSearchParams(window.location.search).get('n') === '1';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The session scope is read from the cookie and will only exist if the app is password protected
|
* The session scope is read from the cookie and will only exist if the app is password protected
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import ViewNavigationMenu from '../../common/components/navigation-menu/ViewNavigationMenu';
|
import ViewNavigationMenu from '../../common/components/navigation-menu/ViewNavigationMenu';
|
||||||
import ProtectRoute from '../../common/components/protect-route/ProtectRoute';
|
import ProtectRoute from '../../common/components/protect-route/ProtectRoute';
|
||||||
import { getIsViewLocked } from '../../externals';
|
import { getIsNavigationLocked } from '../../externals';
|
||||||
|
|
||||||
import Operator from './Operator';
|
import Operator from './Operator';
|
||||||
|
|
||||||
export default function OperatorExport() {
|
export default function OperatorExport() {
|
||||||
return (
|
return (
|
||||||
<ProtectRoute permission='operator'>
|
<ProtectRoute permission='operator'>
|
||||||
<ViewNavigationMenu isViewLocked={getIsViewLocked()} />
|
<ViewNavigationMenu isNavigationLocked={getIsNavigationLocked()} />
|
||||||
<Operator />
|
<Operator />
|
||||||
</ProtectRoute>
|
</ProtectRoute>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -55,10 +55,11 @@ function RundownExport() {
|
|||||||
<ProtectRoute permission='editor'>
|
<ProtectRoute permission='editor'>
|
||||||
<div className={cx([style.rundownExport, isExtracted && style.extracted])} data-testid='panel-rundown'>
|
<div className={cx([style.rundownExport, isExtracted && style.extracted])} data-testid='panel-rundown'>
|
||||||
<FinderPlacement />
|
<FinderPlacement />
|
||||||
|
{isExtracted && <ViewNavigationMenu suppressSettings />}
|
||||||
<div className={style.rundown}>
|
<div className={style.rundown}>
|
||||||
<div className={style.list}>
|
<div className={style.list}>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<Corner onClick={(event) => handleLinks('rundown', event)} />
|
{!isExtracted && <Corner onClick={(event) => handleLinks('rundown', event)} />}
|
||||||
<RundownContextMenu>
|
<RundownContextMenu>
|
||||||
<RundownWrapper />
|
<RundownWrapper />
|
||||||
</RundownContextMenu>
|
</RundownContextMenu>
|
||||||
|
|||||||
@@ -227,16 +227,25 @@ export default function GenerateLinkForm({ hostOptions, pathOptions, presets, is
|
|||||||
name='lockNav'
|
name='lockNav'
|
||||||
checked={watch('lockNav')}
|
checked={watch('lockNav')}
|
||||||
onCheckedChange={(checked) => setValue('lockNav', checked, { shouldDirty: true })}
|
onCheckedChange={(checked) => setValue('lockNav', checked, { shouldDirty: true })}
|
||||||
|
disabled={watch('lockConfig')}
|
||||||
/>
|
/>
|
||||||
</Panel.ListItem>
|
</Panel.ListItem>
|
||||||
{watch('path') !== OntimeView.Cuesheet && (
|
{watch('path') !== OntimeView.Cuesheet && (
|
||||||
<Panel.ListItem>
|
<Panel.ListItem>
|
||||||
<Panel.Field title='Lock configuration' description='Whether to hide the configuration panel' />
|
<Panel.Field
|
||||||
|
title='Lock configuration'
|
||||||
|
description='Whether to hide the configuration panel (also hides navigation)'
|
||||||
|
/>
|
||||||
<Switch
|
<Switch
|
||||||
size='large'
|
size='large'
|
||||||
name='lockConfig'
|
name='lockConfig'
|
||||||
checked={watch('lockConfig')}
|
checked={watch('lockConfig')}
|
||||||
onCheckedChange={(checked) => setValue('lockConfig', checked, { shouldDirty: true })}
|
onCheckedChange={(checked) => {
|
||||||
|
if (checked) {
|
||||||
|
setValue('lockNav', checked, { shouldDirty: true });
|
||||||
|
}
|
||||||
|
setValue('lockConfig', checked, { shouldDirty: true });
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Panel.ListItem>
|
</Panel.ListItem>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useDisclosure } from '@mantine/hooks';
|
|||||||
import IconButton from '../../common/components/buttons/IconButton';
|
import IconButton from '../../common/components/buttons/IconButton';
|
||||||
import NavigationMenu from '../../common/components/navigation-menu/NavigationMenu';
|
import NavigationMenu from '../../common/components/navigation-menu/NavigationMenu';
|
||||||
import { useWindowTitle } from '../../common/hooks/useWindowTitle';
|
import { useWindowTitle } from '../../common/hooks/useWindowTitle';
|
||||||
import { getIsViewLocked } from '../../externals';
|
import { getIsNavigationLocked } from '../../externals';
|
||||||
import CuesheetOverview from '../../features/overview/CuesheetOverview';
|
import CuesheetOverview from '../../features/overview/CuesheetOverview';
|
||||||
|
|
||||||
import CuesheetEditModal from './cuesheet-edit-modal/CuesheetEditModal';
|
import CuesheetEditModal from './cuesheet-edit-modal/CuesheetEditModal';
|
||||||
@@ -18,7 +18,7 @@ export default function CuesheetPage() {
|
|||||||
|
|
||||||
useWindowTitle('Cuesheet');
|
useWindowTitle('Cuesheet');
|
||||||
|
|
||||||
const isLocked = getIsViewLocked();
|
const isLocked = getIsNavigationLocked();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
Reference in New Issue
Block a user