mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-18 21:54:09 +00:00
feat: create offline indicator
This commit is contained in:
committed by
Carlos Valente
parent
cfcf6a5684
commit
c7faab00a3
@@ -4,6 +4,23 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.isOffline {
|
||||||
|
.info {
|
||||||
|
opacity: $opacity-disabled;
|
||||||
|
}
|
||||||
|
&::after {
|
||||||
|
content: 'Disconnected';
|
||||||
|
position: absolute;
|
||||||
|
padding-inline: 0.5rem;
|
||||||
|
bottom: 0.5rem;
|
||||||
|
right: 0.5rem;
|
||||||
|
background-color: $red-700;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-size: calc(1rem - 2px);
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.nav {
|
.nav {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { memo, useMemo } from 'react';
|
import { memo, PropsWithChildren, ReactNode, useMemo } from 'react';
|
||||||
import { millisToString } from 'ontime-utils';
|
import { millisToString } from 'ontime-utils';
|
||||||
|
|
||||||
import ErrorBoundary from '../../common/components/error-boundary/ErrorBoundary';
|
import ErrorBoundary from '../../common/components/error-boundary/ErrorBoundary';
|
||||||
import { useRuntimeOverview, useRuntimePlaybackOverview, useTimer } from '../../common/hooks/useSocket';
|
import { useIsOnline, useRuntimeOverview, useRuntimePlaybackOverview, useTimer } from '../../common/hooks/useSocket';
|
||||||
import useProjectData from '../../common/hooks-query/useProjectData';
|
import useProjectData from '../../common/hooks-query/useProjectData';
|
||||||
import { enDash } from '../../common/utils/styleUtils';
|
import { cx, enDash } from '../../common/utils/styleUtils';
|
||||||
|
|
||||||
import { TimeColumn, TimeRow } from './composite/TimeLayout';
|
import { TimeColumn, TimeRow } from './composite/TimeLayout';
|
||||||
import { calculateEndAndDaySpan, formatedTime, getOffsetText } from './overviewUtils';
|
import { calculateEndAndDaySpan, formatedTime, getOffsetText } from './overviewUtils';
|
||||||
@@ -13,7 +13,7 @@ import style from './Overview.module.scss';
|
|||||||
|
|
||||||
export const EditorOverview = memo(_EditorOverview);
|
export const EditorOverview = memo(_EditorOverview);
|
||||||
|
|
||||||
function _EditorOverview({ children }: { children: React.ReactNode }) {
|
function _EditorOverview({ children }: PropsWithChildren) {
|
||||||
const { plannedEnd, plannedStart, actualStart, expectedEnd } = useRuntimeOverview();
|
const { plannedEnd, plannedStart, actualStart, expectedEnd } = useRuntimeOverview();
|
||||||
|
|
||||||
const [maybePlannedEnd, maybePlannedDaySpan] = useMemo(() => calculateEndAndDaySpan(plannedEnd), [plannedEnd]);
|
const [maybePlannedEnd, maybePlannedDaySpan] = useMemo(() => calculateEndAndDaySpan(plannedEnd), [plannedEnd]);
|
||||||
@@ -23,36 +23,26 @@ function _EditorOverview({ children }: { children: React.ReactNode }) {
|
|||||||
const expectedEndText = formatedTime(maybeExpectedEnd);
|
const expectedEndText = formatedTime(maybeExpectedEnd);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={style.overview}>
|
<OverviewWrapper navElements={children}>
|
||||||
<ErrorBoundary>
|
<TitlesOverview />
|
||||||
<div className={style.nav}>{children}</div>
|
<div>
|
||||||
<div className={style.info}>
|
<TimeRow label='Planned start' value={formatedTime(plannedStart)} className={style.start} />
|
||||||
<TitlesOverview />
|
<TimeRow label='Actual start' value={formatedTime(actualStart)} className={style.start} />
|
||||||
<div>
|
</div>
|
||||||
<TimeRow label='Planned start' value={formatedTime(plannedStart)} className={style.start} />
|
<ProgressOverview />
|
||||||
<TimeRow label='Actual start' value={formatedTime(actualStart)} className={style.start} />
|
<CurrentBlockOverview />
|
||||||
</div>
|
<RuntimeOverview />
|
||||||
<ProgressOverview />
|
<div>
|
||||||
<CurrentBlockOverview />
|
<TimeRow label='Planned end' value={plannedEndText} className={style.end} daySpan={maybePlannedDaySpan} />
|
||||||
<RuntimeOverview />
|
<TimeRow label='Expected end' value={expectedEndText} className={style.end} daySpan={maybeExpectedDaySpan} />
|
||||||
<div>
|
</div>
|
||||||
<TimeRow label='Planned end' value={plannedEndText} className={style.end} daySpan={maybePlannedDaySpan} />
|
</OverviewWrapper>
|
||||||
<TimeRow
|
|
||||||
label='Expected end'
|
|
||||||
value={expectedEndText}
|
|
||||||
className={style.end}
|
|
||||||
daySpan={maybeExpectedDaySpan}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ErrorBoundary>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CuesheetOverview = memo(_CuesheetOverview);
|
export const CuesheetOverview = memo(_CuesheetOverview);
|
||||||
|
|
||||||
function _CuesheetOverview({ children }: { children: React.ReactNode }) {
|
function _CuesheetOverview({ children }: PropsWithChildren) {
|
||||||
const { plannedEnd, expectedEnd } = useRuntimeOverview();
|
const { plannedEnd, expectedEnd } = useRuntimeOverview();
|
||||||
|
|
||||||
const [maybePlannedEnd, maybePlannedDaySpan] = useMemo(() => calculateEndAndDaySpan(plannedEnd), [plannedEnd]);
|
const [maybePlannedEnd, maybePlannedDaySpan] = useMemo(() => calculateEndAndDaySpan(plannedEnd), [plannedEnd]);
|
||||||
@@ -62,23 +52,29 @@ function _CuesheetOverview({ children }: { children: React.ReactNode }) {
|
|||||||
const expectedEndText = formatedTime(maybeExpectedEnd);
|
const expectedEndText = formatedTime(maybeExpectedEnd);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={style.overview}>
|
<OverviewWrapper navElements={children}>
|
||||||
|
<TitlesOverview />
|
||||||
|
<TimerOverview />
|
||||||
|
<RuntimeOverview />
|
||||||
|
<div>
|
||||||
|
<TimeRow label='Planned end' value={plannedEndText} className={style.end} daySpan={maybePlannedDaySpan} />
|
||||||
|
<TimeRow label='Expected end' value={expectedEndText} className={style.end} daySpan={maybeExpectedDaySpan} />
|
||||||
|
</div>
|
||||||
|
</OverviewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OverviewWrapperProps {
|
||||||
|
navElements: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function OverviewWrapper({ navElements, children }: PropsWithChildren<OverviewWrapperProps>) {
|
||||||
|
const { isOnline } = useIsOnline();
|
||||||
|
return (
|
||||||
|
<div className={cx([style.overview, !isOnline && style.isOffline])}>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<div className={style.nav}>{children}</div>
|
<div className={style.nav}>{navElements}</div>
|
||||||
<div className={style.info}>
|
<div className={style.info}>{children}</div>
|
||||||
<TitlesOverview />
|
|
||||||
<TimerOverview />
|
|
||||||
<RuntimeOverview />
|
|
||||||
<div>
|
|
||||||
<TimeRow label='Planned end' value={plannedEndText} className={style.end} daySpan={maybePlannedDaySpan} />
|
|
||||||
<TimeRow
|
|
||||||
label='Expected end'
|
|
||||||
value={expectedEndText}
|
|
||||||
className={style.end}
|
|
||||||
daySpan={maybeExpectedDaySpan}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user