mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-16 04:43:35 +00:00
refactor: finish view directory migration
This commit is contained in:
committed by
Carlos Valente
parent
2f3cf9825a
commit
08b8e73393
@@ -14,10 +14,10 @@ import { useBackstageSocket, useClock } from '../../common/hooks/useSocket';
|
||||
import { useWindowTitle } from '../../common/hooks/useWindowTitle';
|
||||
import { cx, timerPlaceholderMin } from '../../common/utils/styleUtils';
|
||||
import { formatTime, getDefaultFormat } from '../../common/utils/time';
|
||||
import SuperscriptTime from '../../features/viewers/common/superscript-time/SuperscriptTime';
|
||||
import { useTranslation } from '../../translation/TranslationProvider';
|
||||
import Loader from '../common/loader/Loader';
|
||||
import ScheduleExport from '../common/schedule/ScheduleExport';
|
||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||
|
||||
import { getBackstageOptions, useBackstageOptions } from './backstage.options';
|
||||
import { getCardData, getIsPendingStart, getShowProgressBar, isOvertime } from './backstage.utils';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { MaybeNumber, OntimeEvent, Playback, TimerPhase } from 'ontime-types';
|
||||
|
||||
import { enDash } from '../../common/utils/styleUtils';
|
||||
import { getPropertyValue } from '../../features/viewers/common/viewUtils';
|
||||
import { getPropertyValue } from '../common/viewUtils';
|
||||
|
||||
/**
|
||||
* Whether the current time is in overtime
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* encapsulate logic related to showing a clock timer
|
||||
*/
|
||||
|
||||
import { MaybeNumber } from 'ontime-types';
|
||||
|
||||
import { formatTime } from '../../../common/utils/time';
|
||||
import { FORMAT_12, FORMAT_24 } from '../../../viewerConfig';
|
||||
import SuperscriptTime from '../superscript-time/SuperscriptTime';
|
||||
|
||||
interface ClockTimeProps {
|
||||
value: MaybeNumber;
|
||||
preferredFormat12?: string;
|
||||
preferredFormat24?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function ClockTime(props: ClockTimeProps) {
|
||||
const { value, preferredFormat12 = FORMAT_12, preferredFormat24 = FORMAT_24, className } = props;
|
||||
|
||||
// TODO: should we get the params from URL here to see if the user is overriding the default?
|
||||
const formattedTime = formatTime(value, { format12: preferredFormat12, format24: preferredFormat24 });
|
||||
|
||||
return <SuperscriptTime className={className} time={formattedTime} />;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* encapsulate logic related to showing a running timer
|
||||
*/
|
||||
|
||||
import { MaybeNumber } from 'ontime-types';
|
||||
import { removeLeadingZero, removeSeconds } from 'ontime-utils';
|
||||
|
||||
import { formattedTime } from '../../../features/overview/overview.utils';
|
||||
|
||||
interface RunningTimeProps {
|
||||
value: MaybeNumber;
|
||||
hideSeconds?: boolean;
|
||||
hideLeadingZero?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function RunningTime(props: RunningTimeProps) {
|
||||
const { value, hideSeconds, hideLeadingZero, className } = props;
|
||||
let display = formattedTime(value, hideSeconds || hideLeadingZero ? 2 : 3);
|
||||
|
||||
if (hideLeadingZero) {
|
||||
display = removeLeadingZero(display);
|
||||
}
|
||||
|
||||
if (hideSeconds) {
|
||||
display = removeSeconds(display);
|
||||
}
|
||||
|
||||
return <div className={className}>{display}</div>;
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { getOffsetState } from '../../../common/utils/offset';
|
||||
import { ExtendedEntry } from '../../../common/utils/rundownMetadata';
|
||||
import { cx } from '../../../common/utils/styleUtils';
|
||||
import { formatTime, getExpectedTimesFromExtendedEvent } from '../../../common/utils/time';
|
||||
import SuperscriptPeriod from '../../../features/viewers/common/superscript-time/SuperscriptPeriod';
|
||||
import SuperscriptPeriod from '../superscript-time/SuperscriptPeriod';
|
||||
|
||||
import { useScheduleOptions } from './schedule.options';
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useSearchParams } from 'react-router';
|
||||
import { SelectOption } from '../../../common/components/select/Select';
|
||||
import { OptionTitle } from '../../../common/components/view-params-editor/constants';
|
||||
import type { ViewOption } from '../../../common/components/view-params-editor/viewParams.types';
|
||||
import { isStringBoolean } from '../../../features/viewers/common/viewUtils';
|
||||
import { isStringBoolean } from '../viewUtils';
|
||||
|
||||
export const getScheduleOptions = (customFieldOptions: SelectOption[]): ViewOption => ({
|
||||
title: OptionTitle.Schedule,
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import './SuperscriptTime.scss';
|
||||
|
||||
interface SuperscriptPeriodProps {
|
||||
time: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives a time string and formats periods (am/pm) as superscript
|
||||
* @example 12:00 AM -> AM becomes a superscript
|
||||
* @example 12:00:10 -> no formatting changes applied
|
||||
*/
|
||||
export default function SuperscriptPeriod({ time, className }: SuperscriptPeriodProps) {
|
||||
// we assume anything after space is a period tag
|
||||
const [timeString, period] = time.split(' ');
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
{timeString}
|
||||
{period && <sup className='period'>{period}</sup>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
sup.period {
|
||||
top: -1em;
|
||||
font-size: 0.5em;
|
||||
}
|
||||
|
||||
.subscript {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { CSSProperties } from 'react';
|
||||
|
||||
import './SuperscriptTime.scss';
|
||||
|
||||
interface SuperscriptTimeProps {
|
||||
time: string;
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* When the timer includes seconds, we want to split it from the rest
|
||||
*/
|
||||
function getTimerParts(time: string) {
|
||||
if (time.length !== 8) {
|
||||
return [time, ''];
|
||||
}
|
||||
|
||||
return [time.slice(0, 5), time.slice(5)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives a time string and formats it with a subscript or superscript
|
||||
* @example 12:00 AM -> AM becomes a superscript
|
||||
* @example 12:00:10 -> the seconds become a subscript
|
||||
*/
|
||||
export default function SuperscriptTime({ time, className, style }: SuperscriptTimeProps) {
|
||||
// we assume anything after space is a period tag
|
||||
const [timeString, period] = time.split(' ');
|
||||
const [mainTime, subscript] = getTimerParts(timeString);
|
||||
|
||||
return (
|
||||
<div className={className} style={style}>
|
||||
{mainTime}
|
||||
{subscript && <span className='subscript'>{subscript}</span>}
|
||||
{period && <sup className='period'>{period}</sup>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
import { MaybeNumber, MaybeString, OntimeEvent, TimerState, TimerType } from 'ontime-types';
|
||||
import { MILLIS_PER_MINUTE, MILLIS_PER_SECOND, millisToString, removeLeadingZero, removeSeconds } from 'ontime-utils';
|
||||
|
||||
import { timerPlaceholder, timerPlaceholderMin } from '../../common/utils/styleUtils';
|
||||
import { formatTime } from '../../common/utils/time';
|
||||
|
||||
/**
|
||||
* Gathers all options that affect which timer is displayed and selects the correct data source to display
|
||||
* it also handles edge cases such as freezing on end
|
||||
*/
|
||||
export function getTimerByType(
|
||||
freezeEnd: boolean,
|
||||
timerTypeNow: TimerType,
|
||||
clock: number,
|
||||
timerObject: Pick<TimerState, 'current' | 'elapsed'>,
|
||||
timerTypeOverride?: TimerType,
|
||||
): number | null {
|
||||
if (!timerObject) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const viewTimerType = timerTypeOverride ?? timerTypeNow;
|
||||
|
||||
switch (viewTimerType) {
|
||||
case TimerType.CountDown:
|
||||
if (timerObject.current === null) {
|
||||
return null;
|
||||
}
|
||||
return freezeEnd ? Math.max(timerObject.current, 0) : timerObject.current;
|
||||
case TimerType.CountUp:
|
||||
return timerObject.elapsed;
|
||||
case TimerType.Clock:
|
||||
return clock;
|
||||
case TimerType.None:
|
||||
return null;
|
||||
default: {
|
||||
viewTimerType satisfies never;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string to semantically verify if it represents a true value
|
||||
* Used in the context of parsing search params and local storage items which can be strings or null
|
||||
*/
|
||||
export function isStringBoolean(text: string | null) {
|
||||
if (text === null) {
|
||||
return false;
|
||||
}
|
||||
return text?.toLowerCase() === 'true' || text === '1';
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a colour string for use in views
|
||||
* Colours in params do not have the #prefix
|
||||
*/
|
||||
export function makeColourString(hex: string | null): string | undefined {
|
||||
if (!hex) {
|
||||
return undefined;
|
||||
}
|
||||
// ensure the hex starts with a #
|
||||
return hex.startsWith('#') ? hex : `#${hex}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a dynamic property from an event
|
||||
* Considers custom fields
|
||||
*/
|
||||
export function getPropertyValue(event: OntimeEvent | null, property: MaybeString): string | undefined {
|
||||
if (!event || typeof property !== 'string' || property === 'none') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (property.startsWith('custom-')) {
|
||||
const field = property.split('custom-')[1];
|
||||
return event.custom?.[field];
|
||||
}
|
||||
|
||||
return event[property as keyof OntimeEvent] as string;
|
||||
}
|
||||
|
||||
type FormattingOptions = {
|
||||
removeSeconds: boolean;
|
||||
removeLeadingZero: boolean;
|
||||
};
|
||||
|
||||
export function getFormattedTimer(
|
||||
timer: MaybeNumber,
|
||||
timerType: TimerType,
|
||||
localisedMinutes: string,
|
||||
options: FormattingOptions,
|
||||
): string {
|
||||
if (timer == null || timerType === TimerType.None) {
|
||||
return options.removeSeconds ? timerPlaceholderMin : timerPlaceholder;
|
||||
}
|
||||
|
||||
if (timerType === TimerType.Clock) {
|
||||
return formatTime(timer);
|
||||
}
|
||||
|
||||
let timeToParse = timer;
|
||||
if (options.removeSeconds) {
|
||||
const isNegative = timeToParse < -MILLIS_PER_SECOND && timerType !== TimerType.CountUp;
|
||||
if (isNegative) {
|
||||
// in negative numbers, we need to round down
|
||||
timeToParse -= MILLIS_PER_MINUTE;
|
||||
}
|
||||
}
|
||||
|
||||
let display = millisToString(timeToParse, { direction: timerType });
|
||||
if (options.removeLeadingZero) {
|
||||
display = removeLeadingZero(display);
|
||||
}
|
||||
|
||||
if (options.removeSeconds) {
|
||||
display = formatDisplayWithMinutes(display, localisedMinutes);
|
||||
}
|
||||
return display;
|
||||
}
|
||||
|
||||
function formatDisplayWithMinutes(display: string, localisedMinutes: string): string {
|
||||
display = removeSeconds(display);
|
||||
return display.length < 3 ? `${display} ${localisedMinutes}` : display;
|
||||
}
|
||||
@@ -11,9 +11,9 @@ import { useClock } from '../../common/hooks/useSocket';
|
||||
import { useWindowTitle } from '../../common/hooks/useWindowTitle';
|
||||
import { ExtendedEntry } from '../../common/utils/rundownMetadata';
|
||||
import { formatTime, getDefaultFormat } from '../../common/utils/time';
|
||||
import SuperscriptTime from '../../features/viewers/common/superscript-time/SuperscriptTime';
|
||||
import { useTranslation } from '../../translation/TranslationProvider';
|
||||
import Loader from '../common/loader/Loader';
|
||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||
|
||||
import { getCountdownOptions, useCountdownOptions } from './countdown.options';
|
||||
import { getOrderedSubscriptions } from './countdown.utils';
|
||||
|
||||
@@ -6,7 +6,7 @@ import { EntryId, PlayableEvent } from 'ontime-types';
|
||||
import Button from '../../common/components/buttons/Button';
|
||||
import { ExtendedEntry } from '../../common/utils/rundownMetadata';
|
||||
import { cx } from '../../common/utils/styleUtils';
|
||||
import ClockTime from '../../features/viewers/common/clock-time/ClockTime';
|
||||
import ClockTime from '../common/clock-time/ClockTime';
|
||||
|
||||
import { makeSubscriptionsUrl } from './countdown.utils';
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ import { ExtendedEntry } from '../../common/utils/rundownMetadata';
|
||||
import { cx } from '../../common/utils/styleUtils';
|
||||
import { throttle } from '../../common/utils/throttle';
|
||||
import FollowButton from '../../features/operator/follow-button/FollowButton';
|
||||
import ClockTime from '../../features/viewers/common/clock-time/ClockTime';
|
||||
import SuperscriptTime from '../../features/viewers/common/superscript-time/SuperscriptTime';
|
||||
import { getPropertyValue } from '../../features/viewers/common/viewUtils';
|
||||
import ClockTime from '../common/clock-time/ClockTime';
|
||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||
import { getPropertyValue } from '../common/viewUtils';
|
||||
|
||||
import { useCountdownOptions } from './countdown.options';
|
||||
import {
|
||||
|
||||
@@ -8,8 +8,8 @@ import { useExpectedStartData } from '../../common/hooks/useSocket';
|
||||
import useReport from '../../common/hooks-query/useReport';
|
||||
import { ExtendedEntry } from '../../common/utils/rundownMetadata';
|
||||
import { cx } from '../../common/utils/styleUtils';
|
||||
import SuperscriptTime from '../../features/viewers/common/superscript-time/SuperscriptTime';
|
||||
import { getPropertyValue } from '../../features/viewers/common/viewUtils';
|
||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||
import { getPropertyValue } from '../common/viewUtils';
|
||||
|
||||
import { useCountdownOptions } from './countdown.options';
|
||||
import { useSubscriptionDisplayData } from './countdown.utils';
|
||||
|
||||
@@ -7,7 +7,7 @@ import { OptionTitle } from '../../common/components/view-params-editor/constant
|
||||
import { ViewOption } from '../../common/components/view-params-editor/viewParams.types';
|
||||
import { makeOptionsFromCustomFields } from '../../common/components/view-params-editor/viewParams.utils';
|
||||
import { PresetContext } from '../../common/context/PresetContext';
|
||||
import { isStringBoolean } from '../../features/viewers/common/viewUtils';
|
||||
import { isStringBoolean } from '../common/viewUtils';
|
||||
|
||||
export const getCountdownOptions = (
|
||||
timeFormat: string,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { FitText } from '../../../common/components/fit-text/FitText';
|
||||
import MultiPartProgressBar from '../../../common/components/multi-part-progress-bar/MultiPartProgressBar';
|
||||
import { useTimerSocket } from '../../../common/hooks/useSocket';
|
||||
import { cx } from '../../../common/utils/styleUtils';
|
||||
import { getFormattedTimer, getTimerByType } from '../../../features/viewers/common/viewUtils';
|
||||
import { getFormattedTimer, getTimerByType } from '../../common/viewUtils';
|
||||
import {
|
||||
getEstimatedFontSize,
|
||||
getIsPlaying,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useIsSmallScreen } from '../../common/hooks/useIsSmallScreen';
|
||||
import { useStudioClockSocket } from '../../common/hooks/useSocket';
|
||||
import { cx } from '../../common/utils/styleUtils';
|
||||
import { formatTime } from '../../common/utils/time';
|
||||
import SuperscriptTime from '../../features/viewers/common/superscript-time/SuperscriptTime';
|
||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||
|
||||
import { getLargeClockData } from './studioClock.utils';
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { getTimeOption } from '../../common/components/view-params-editor/common
|
||||
import { OptionTitle } from '../../common/components/view-params-editor/constants';
|
||||
import { ViewOption } from '../../common/components/view-params-editor/viewParams.types';
|
||||
import { PresetContext } from '../../common/context/PresetContext';
|
||||
import { isStringBoolean } from '../../features/viewers/common/viewUtils';
|
||||
import { isStringBoolean } from '../common/viewUtils';
|
||||
|
||||
export const getStudioOptions = (timeFormat: string): ViewOption[] => [
|
||||
{ title: OptionTitle.ClockOptions, collapsible: true, options: [getTimeOption(timeFormat)] },
|
||||
|
||||
@@ -7,9 +7,9 @@ import ViewParamsEditor from '../../common/components/view-params-editor/ViewPar
|
||||
import { useClock, useSelectedEventId } from '../../common/hooks/useSocket';
|
||||
import { useWindowTitle } from '../../common/hooks/useWindowTitle';
|
||||
import { formatTime, getDefaultFormat } from '../../common/utils/time';
|
||||
import SuperscriptTime from '../../features/viewers/common/superscript-time/SuperscriptTime';
|
||||
import { useTranslation } from '../../translation/TranslationProvider';
|
||||
import Loader from '../common/loader/Loader';
|
||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||
|
||||
import Timeline from './Timeline';
|
||||
import { getTimelineOptions } from './timeline.options';
|
||||
|
||||
@@ -5,7 +5,7 @@ import { getTimeOption } from '../../common/components/view-params-editor/common
|
||||
import { OptionTitle } from '../../common/components/view-params-editor/constants';
|
||||
import { ViewOption } from '../../common/components/view-params-editor/viewParams.types';
|
||||
import { PresetContext } from '../../common/context/PresetContext';
|
||||
import { isStringBoolean } from '../../features/viewers/common/viewUtils';
|
||||
import { isStringBoolean } from '../common/viewUtils';
|
||||
|
||||
export const getTimelineOptions = (timeFormat: string): ViewOption[] => {
|
||||
return [
|
||||
|
||||
@@ -11,10 +11,10 @@ import { useTimerSocket } from '../../common/hooks/useSocket';
|
||||
import { useWindowTitle } from '../../common/hooks/useWindowTitle';
|
||||
import { cx } from '../../common/utils/styleUtils';
|
||||
import { formatTime, getDefaultFormat } from '../../common/utils/time';
|
||||
import SuperscriptTime from '../../features/viewers/common/superscript-time/SuperscriptTime';
|
||||
import { getFormattedTimer, getTimerByType } from '../../features/viewers/common/viewUtils';
|
||||
import { useTranslation } from '../../translation/TranslationProvider';
|
||||
import Loader from '../common/loader/Loader';
|
||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||
import { getFormattedTimer, getTimerByType } from '../common/viewUtils';
|
||||
import { getTimerColour } from '../utils/presentation.utils';
|
||||
|
||||
import { getTimerOptions, useTimerOptions } from './timer.options';
|
||||
|
||||
@@ -13,7 +13,7 @@ import { OptionTitle } from '../../common/components/view-params-editor/constant
|
||||
import { ViewOption } from '../../common/components/view-params-editor/viewParams.types';
|
||||
import { makeOptionsFromCustomFields } from '../../common/components/view-params-editor/viewParams.utils';
|
||||
import { PresetContext } from '../../common/context/PresetContext';
|
||||
import { isStringBoolean, makeColourString } from '../../features/viewers/common/viewUtils';
|
||||
import { isStringBoolean, makeColourString } from '../common/viewUtils';
|
||||
|
||||
// manually match the properties of TimerType excluding the None
|
||||
const timerDisplayOptions: SelectOption[] = [
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { MaybeNumber, MessageState, OntimeEvent, Playback, TimerMessage, TimerPhase, TimerType } from 'ontime-types';
|
||||
import { isPlaybackActive } from 'ontime-utils';
|
||||
|
||||
import { getFormattedTimer, getPropertyValue } from '../../features/viewers/common/viewUtils';
|
||||
import { getFormattedTimer, getPropertyValue } from '../common/viewUtils';
|
||||
|
||||
/**
|
||||
* Whether a message should be shown
|
||||
|
||||
Reference in New Issue
Block a user