mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-06 06:49:10 +00:00
@@ -8,25 +8,12 @@
|
|||||||
"jest": true
|
"jest": true
|
||||||
},
|
},
|
||||||
"parser": "@typescript-eslint/parser",
|
"parser": "@typescript-eslint/parser",
|
||||||
"extends": [
|
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier", "eslint-config-prettier"],
|
||||||
"eslint:recommended",
|
"plugins": ["@typescript-eslint", "prettier"],
|
||||||
"plugin:@typescript-eslint/recommended",
|
|
||||||
"prettier",
|
|
||||||
"eslint-config-prettier"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"@typescript-eslint",
|
|
||||||
"prettier"
|
|
||||||
],
|
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
"files": [
|
"files": ["e2e/**/**.spec.ts", "e2e/**/**.test.ts"],
|
||||||
"e2e/**/**.spec.ts",
|
"extends": ["plugin:playwright/playwright-test"]
|
||||||
"e2e/**/**.test.ts"
|
|
||||||
],
|
|
||||||
"extends": [
|
|
||||||
"plugin:playwright/playwright-test"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
@@ -35,10 +22,13 @@
|
|||||||
"no-console": [
|
"no-console": [
|
||||||
"warn",
|
"warn",
|
||||||
{
|
{
|
||||||
"allow": [
|
"allow": ["warn", "error"]
|
||||||
"warn",
|
}
|
||||||
"error"
|
],
|
||||||
]
|
"no-restricted-imports": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"patterns": ["ontime-types/src/*", "ontime-utils/src/*"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||||
@@ -59,4 +49,4 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { UserFields } from 'ontime-types';
|
import { TimeFormat, UserFields } from 'ontime-types';
|
||||||
import { TimeFormat } from 'ontime-types/src/definitions/core/TimeFormat.type';
|
|
||||||
|
|
||||||
import { ParamField } from './types';
|
import { ParamField } from './types';
|
||||||
|
|
||||||
export const getTimeOption = (timeFormat: TimeFormat): ParamField => ({
|
const getTimeOption = (timeFormat: TimeFormat): ParamField => ({
|
||||||
id: 'format',
|
id: 'format',
|
||||||
title: '12 / 24 hour timer',
|
title: '12 / 24 hour timer',
|
||||||
description: 'Whether to show the time in 12 or 24 hour mode. Overrides the global setting from preferences',
|
description: 'Whether to show the time in 12 or 24 hour mode. Overrides the global setting from preferences',
|
||||||
@@ -12,6 +11,22 @@ export const getTimeOption = (timeFormat: TimeFormat): ParamField => ({
|
|||||||
defaultValue: timeFormat,
|
defaultValue: timeFormat,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const hideClockSeconds: ParamField = {
|
||||||
|
id: 'hideClockSeconds',
|
||||||
|
title: 'Hide seconds in clocks',
|
||||||
|
description: 'Whether to hide seconds in auxiliar time fields (not the running timer)',
|
||||||
|
type: 'boolean',
|
||||||
|
defaultValue: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const hideTimerSeconds: ParamField = {
|
||||||
|
id: 'hideTimerSeconds',
|
||||||
|
title: 'Hide seconds in timer',
|
||||||
|
description: 'Whether to hide seconds in the running timer',
|
||||||
|
type: 'boolean',
|
||||||
|
defaultValue: false,
|
||||||
|
};
|
||||||
|
|
||||||
export const getClockOptions = (timeFormat: TimeFormat): ParamField[] => [
|
export const getClockOptions = (timeFormat: TimeFormat): ParamField[] => [
|
||||||
getTimeOption(timeFormat),
|
getTimeOption(timeFormat),
|
||||||
{
|
{
|
||||||
@@ -86,6 +101,8 @@ export const getClockOptions = (timeFormat: TimeFormat): ParamField[] => [
|
|||||||
|
|
||||||
export const getTimerOptions = (timeFormat: TimeFormat): ParamField[] => [
|
export const getTimerOptions = (timeFormat: TimeFormat): ParamField[] => [
|
||||||
getTimeOption(timeFormat),
|
getTimeOption(timeFormat),
|
||||||
|
hideTimerSeconds,
|
||||||
|
hideClockSeconds,
|
||||||
{
|
{
|
||||||
id: 'hideClock',
|
id: 'hideClock',
|
||||||
title: 'Hide Time Now',
|
title: 'Hide Time Now',
|
||||||
@@ -124,6 +141,7 @@ export const getTimerOptions = (timeFormat: TimeFormat): ParamField[] => [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const MINIMAL_TIMER_OPTIONS: ParamField[] = [
|
export const MINIMAL_TIMER_OPTIONS: ParamField[] = [
|
||||||
|
hideTimerSeconds,
|
||||||
{
|
{
|
||||||
id: 'key',
|
id: 'key',
|
||||||
title: 'Key Colour',
|
title: 'Key Colour',
|
||||||
@@ -265,6 +283,7 @@ export const LOWER_THIRDS_OPTIONS: ParamField[] = [
|
|||||||
|
|
||||||
export const getBackstageOptions = (timeFormat: TimeFormat): ParamField[] => [
|
export const getBackstageOptions = (timeFormat: TimeFormat): ParamField[] => [
|
||||||
getTimeOption(timeFormat),
|
getTimeOption(timeFormat),
|
||||||
|
hideClockSeconds,
|
||||||
{
|
{
|
||||||
id: 'hidePast',
|
id: 'hidePast',
|
||||||
title: 'Hide past events',
|
title: 'Hide past events',
|
||||||
@@ -290,6 +309,7 @@ export const getBackstageOptions = (timeFormat: TimeFormat): ParamField[] => [
|
|||||||
|
|
||||||
export const getPublicOptions = (timeFormat: TimeFormat): ParamField[] => [
|
export const getPublicOptions = (timeFormat: TimeFormat): ParamField[] => [
|
||||||
getTimeOption(timeFormat),
|
getTimeOption(timeFormat),
|
||||||
|
hideClockSeconds,
|
||||||
{
|
{
|
||||||
id: 'hidePast',
|
id: 'hidePast',
|
||||||
title: 'Hide past events',
|
title: 'Hide past events',
|
||||||
@@ -314,6 +334,7 @@ export const getPublicOptions = (timeFormat: TimeFormat): ParamField[] => [
|
|||||||
];
|
];
|
||||||
export const getStudioClockOptions = (timeFormat: TimeFormat): ParamField[] => [
|
export const getStudioClockOptions = (timeFormat: TimeFormat): ParamField[] => [
|
||||||
getTimeOption(timeFormat),
|
getTimeOption(timeFormat),
|
||||||
|
hideClockSeconds,
|
||||||
{
|
{
|
||||||
id: 'seconds',
|
id: 'seconds',
|
||||||
title: 'Show Seconds',
|
title: 'Show Seconds',
|
||||||
@@ -389,3 +410,9 @@ export const getOperatorOptions = (userFields: UserFields, timeFormat: TimeForma
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getCountdownOptions = (timeFormat: TimeFormat): ParamField[] => [
|
||||||
|
getTimeOption(timeFormat),
|
||||||
|
hideTimerSeconds,
|
||||||
|
hideClockSeconds,
|
||||||
|
];
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
//@ts-nocheck -- working on it
|
|
||||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||||
import { OSCSettings } from 'ontime-types';
|
|
||||||
|
|
||||||
import { queryRefetchIntervalSlow } from '../../ontimeConfig';
|
import { queryRefetchIntervalSlow } from '../../ontimeConfig';
|
||||||
import { OSC_SETTINGS } from '../api/apiConstants';
|
import { OSC_SETTINGS } from '../api/apiConstants';
|
||||||
@@ -13,7 +10,10 @@ import { ontimeQueryClient } from '../queryClient';
|
|||||||
export default function useOscSettings() {
|
export default function useOscSettings() {
|
||||||
const { data, status, isFetching, isError, refetch } = useQuery({
|
const { data, status, isFetching, isError, refetch } = useQuery({
|
||||||
queryKey: OSC_SETTINGS,
|
queryKey: OSC_SETTINGS,
|
||||||
queryFn: getOSC,
|
queryFn: async () => {
|
||||||
|
const oscData = await getOSC();
|
||||||
|
return { ...oscData, portIn: String(oscData.portIn), portOut: String(oscData.portOut) };
|
||||||
|
},
|
||||||
placeholderData: oscPlaceholderSettings,
|
placeholderData: oscPlaceholderSettings,
|
||||||
retry: 5,
|
retry: 5,
|
||||||
retryDelay: (attempt: number) => attempt * 2500,
|
retryDelay: (attempt: number) => attempt * 2500,
|
||||||
@@ -21,8 +21,7 @@ export default function useOscSettings() {
|
|||||||
networkMode: 'always',
|
networkMode: 'always',
|
||||||
});
|
});
|
||||||
|
|
||||||
// we need to jump through some hoops because of the type op port
|
return { data: data ?? oscPlaceholderSettings, status, isFetching, isError, refetch };
|
||||||
return { data: data! as unknown as OSCSettings, status, isFetching, isError, refetch };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useOscSettingsMutation() {
|
export function useOscSettingsMutation() {
|
||||||
|
|||||||
@@ -14,4 +14,5 @@ export type OverridableOptions = {
|
|||||||
hideEndMessage?: boolean;
|
hideEndMessage?: boolean;
|
||||||
language?: string;
|
language?: string;
|
||||||
showProgressBar?: boolean;
|
showProgressBar?: boolean;
|
||||||
|
hideTimerSeconds?: boolean;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,4 +36,14 @@ describe('formatTime()', () => {
|
|||||||
const time = formatTime(ms, options, () => '12');
|
const time = formatTime(ms, options, () => '12');
|
||||||
expect(time).toStrictEqual('01:00 PM');
|
expect(time).toStrictEqual('01:00 PM');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handles negative times', () => {
|
||||||
|
const ms = 1 * 60 * 60 * 1000;
|
||||||
|
const options = {
|
||||||
|
showSeconds: false,
|
||||||
|
format: 'hh:mm:ss',
|
||||||
|
};
|
||||||
|
const time = formatTime(ms * -1, options, () => '24');
|
||||||
|
expect(time).toStrictEqual('-01:00');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,12 +46,21 @@ type FormatOptions = {
|
|||||||
* @param {function} resolver
|
* @param {function} resolver
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
export const formatTime = (milliseconds: number | null, options?: FormatOptions, resolver = resolveTimeFormat) => {
|
export const formatTime = (
|
||||||
|
milliseconds: number | null,
|
||||||
|
options?: FormatOptions,
|
||||||
|
resolver = resolveTimeFormat,
|
||||||
|
): string => {
|
||||||
if (milliseconds === null) {
|
if (milliseconds === null) {
|
||||||
return '...';
|
return '...';
|
||||||
}
|
}
|
||||||
const timeFormat = resolver();
|
const timeFormat = resolver();
|
||||||
const fallback = options?.showSeconds ? 'hh:mm:ss a' : 'hh:mm a';
|
const fallback = options?.showSeconds ? 'hh:mm:ss a' : 'hh:mm a';
|
||||||
const { showSeconds = false, format: formatString = fallback } = options || {};
|
const { showSeconds = false, format: formatString = fallback } = options || {};
|
||||||
return timeFormat === '12' ? formatFromMillis(milliseconds, formatString) : millisToString(milliseconds, showSeconds);
|
const isNegative = (milliseconds ?? 0) < 0;
|
||||||
|
const display =
|
||||||
|
timeFormat === '12'
|
||||||
|
? formatFromMillis(Math.abs(milliseconds), formatString)
|
||||||
|
: millisToString(Math.abs(milliseconds), showSeconds);
|
||||||
|
return `${isNegative ? '-' : ''}${display}`;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
//@ts-nocheck -- working on it
|
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { FormControl, Input, Switch } from '@chakra-ui/react';
|
import { FormControl, Input, Switch } from '@chakra-ui/react';
|
||||||
@@ -59,7 +57,6 @@ export default function OscSettings() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
// @ts-expect-error -- we know the types dont match
|
|
||||||
reset(data);
|
reset(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import QRCode from 'react-qr-code';
|
import QRCode from 'react-qr-code';
|
||||||
|
import { useSearchParams } from 'react-router-dom';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
import { Message, OntimeEvent, ProjectData, Settings, SupportedEvent, ViewSettings } from 'ontime-types';
|
import { Message, OntimeEvent, ProjectData, Settings, SupportedEvent, ViewSettings } from 'ontime-types';
|
||||||
import { formatDisplay } from 'ontime-utils';
|
import { formatDisplay } from 'ontime-utils';
|
||||||
@@ -16,17 +17,13 @@ import ViewParamsEditor from '../../../common/components/view-params-editor/View
|
|||||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||||
import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
||||||
import { formatTime } from '../../../common/utils/time';
|
import { formatTime } from '../../../common/utils/time';
|
||||||
|
import { isStringBoolean } from '../../../common/utils/viewUtils';
|
||||||
import { useTranslation } from '../../../translation/TranslationProvider';
|
import { useTranslation } from '../../../translation/TranslationProvider';
|
||||||
import { titleVariants } from '../common/animation';
|
import { titleVariants } from '../common/animation';
|
||||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||||
|
|
||||||
import './Backstage.scss';
|
import './Backstage.scss';
|
||||||
|
|
||||||
const formatOptions = {
|
|
||||||
showSeconds: true,
|
|
||||||
format: 'hh:mm:ss a',
|
|
||||||
};
|
|
||||||
|
|
||||||
interface BackstageProps {
|
interface BackstageProps {
|
||||||
isMirrored: boolean;
|
isMirrored: boolean;
|
||||||
publ: Message;
|
publ: Message;
|
||||||
@@ -43,6 +40,9 @@ interface BackstageProps {
|
|||||||
export default function Backstage(props: BackstageProps) {
|
export default function Backstage(props: BackstageProps) {
|
||||||
const { isMirrored, publ, eventNow, eventNext, time, backstageEvents, selectedId, general, viewSettings, settings } =
|
const { isMirrored, publ, eventNow, eventNext, time, backstageEvents, selectedId, general, viewSettings, settings } =
|
||||||
props;
|
props;
|
||||||
|
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
|
|
||||||
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
||||||
const { getLocalizedString } = useTranslation();
|
const { getLocalizedString } = useTranslation();
|
||||||
const [blinkClass, setBlinkClass] = useState(false);
|
const [blinkClass, setBlinkClass] = useState(false);
|
||||||
@@ -68,6 +68,12 @@ export default function Backstage(props: BackstageProps) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hideSeconds = isStringBoolean(searchParams.get('hideSeconds'));
|
||||||
|
const formatOptions = {
|
||||||
|
showSeconds: !hideSeconds,
|
||||||
|
format: 'hh:mm:ss a',
|
||||||
|
};
|
||||||
|
|
||||||
const clock = formatTime(time.clock, formatOptions);
|
const clock = formatTime(time.clock, formatOptions);
|
||||||
const startedAt = formatTime(time.startedAt, formatOptions);
|
const startedAt = formatTime(time.startedAt, formatOptions);
|
||||||
const isNegative = (time.current ?? 0) < 0;
|
const isNegative = (time.current ?? 0) < 0;
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { removePrependedZero } from '../viewerUtils.js';
|
||||||
|
|
||||||
|
describe('removePrependedZero', () => {
|
||||||
|
it('should remove "00:" from the start of the string', () => {
|
||||||
|
const timer = '00:10:10';
|
||||||
|
const result = removePrependedZero(timer);
|
||||||
|
expect(result).toBe('10:10');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove "00:0:" from the start of the string', () => {
|
||||||
|
const timer = '00:01:10';
|
||||||
|
const result = removePrependedZero(timer);
|
||||||
|
expect(result).toBe('1:10');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not modify the string if it does not start with "00:" or "00:0:"', () => {
|
||||||
|
const timer = '10:10:10';
|
||||||
|
const result = removePrependedZero(timer);
|
||||||
|
expect(result).toBe(timer);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -8,6 +8,9 @@ interface SuperscriptTimeProps {
|
|||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description receives a string like 12:00 AM and adds the period part to the superscript
|
||||||
|
*/
|
||||||
export default function SuperscriptTime(props: SuperscriptTimeProps) {
|
export default function SuperscriptTime(props: SuperscriptTimeProps) {
|
||||||
const { time, className, style } = props;
|
const { time, className, style } = props;
|
||||||
|
|
||||||
|
|||||||
@@ -1,43 +1,39 @@
|
|||||||
import { TimerType } from 'ontime-types';
|
import { TimerType } from 'ontime-types';
|
||||||
import { formatDisplay } from 'ontime-utils';
|
|
||||||
|
|
||||||
import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
import type { TimeManagerType } from '../../../common/models/TimeManager.type';
|
||||||
import { formatTime } from '../../../common/utils/time';
|
|
||||||
|
|
||||||
const formatOptions = {
|
|
||||||
showSeconds: true,
|
|
||||||
format: 'hh:mm:ss a',
|
|
||||||
};
|
|
||||||
|
|
||||||
type TimerTypeParams = Pick<TimeManagerType, 'timerType' | 'current' | 'elapsed' | 'clock'>;
|
type TimerTypeParams = Pick<TimeManagerType, 'timerType' | 'current' | 'elapsed' | 'clock'>;
|
||||||
|
|
||||||
export function getTimerByType(timerObject?: TimerTypeParams): string | number | null {
|
export function getTimerByType(timerObject?: TimerTypeParams): number | null {
|
||||||
let timer = null;
|
|
||||||
if (!timerObject) {
|
if (!timerObject) {
|
||||||
return timer;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timerObject.timerType === TimerType.CountDown || timerObject.timerType === TimerType.TimeToEnd) {
|
switch (timerObject.timerType) {
|
||||||
timer = timerObject.current;
|
case TimerType.CountDown:
|
||||||
} else if (timerObject.timerType === TimerType.CountUp) {
|
case TimerType.TimeToEnd:
|
||||||
timer = timerObject.elapsed;
|
return timerObject.current;
|
||||||
} else if (timerObject.timerType === TimerType.Clock) {
|
case TimerType.CountUp:
|
||||||
timer = formatTime(timerObject.clock, formatOptions);
|
return Math.abs(timerObject.elapsed ?? 0);
|
||||||
|
case TimerType.Clock:
|
||||||
|
return timerObject.clock;
|
||||||
|
default: {
|
||||||
|
const exhaustiveCheck: never = timerObject.timerType;
|
||||||
|
return exhaustiveCheck;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives a string such as 00:10:10 and removes the hours field if it is 00
|
||||||
|
* @param timer
|
||||||
|
*/
|
||||||
|
export const removePrependedZero = (timer: string): string => {
|
||||||
|
if (timer.startsWith('00:0')) {
|
||||||
|
return timer.slice(4);
|
||||||
|
}
|
||||||
|
if (timer.startsWith('00:')) {
|
||||||
|
return timer.slice(3);
|
||||||
|
}
|
||||||
return timer;
|
return timer;
|
||||||
}
|
};
|
||||||
|
|
||||||
export function formatTimerDisplay(timer?: string | number | null): string {
|
|
||||||
let display = '';
|
|
||||||
|
|
||||||
if (typeof timer === 'string') {
|
|
||||||
display = timer;
|
|
||||||
} else if (timer === null || typeof timer === 'undefined' || isNaN(timer)) {
|
|
||||||
display = '-- : -- : --';
|
|
||||||
} else {
|
|
||||||
display = formatDisplay(timer, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return display;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ import { formatDisplay } from 'ontime-utils';
|
|||||||
|
|
||||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||||
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
|
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
|
||||||
import { getTimeOption } from '../../../common/components/view-params-editor/constants';
|
import { getCountdownOptions } from '../../../common/components/view-params-editor/constants';
|
||||||
import ViewParamsEditor from '../../../common/components/view-params-editor/ViewParamsEditor';
|
import ViewParamsEditor from '../../../common/components/view-params-editor/ViewParamsEditor';
|
||||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||||
import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
||||||
import { formatTime } from '../../../common/utils/time';
|
import { formatTime } from '../../../common/utils/time';
|
||||||
|
import { isStringBoolean } from '../../../common/utils/viewUtils';
|
||||||
import { useTranslation } from '../../../translation/TranslationProvider';
|
import { useTranslation } from '../../../translation/TranslationProvider';
|
||||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||||
|
|
||||||
@@ -18,11 +19,6 @@ import CountdownSelect from './CountdownSelect';
|
|||||||
|
|
||||||
import './Countdown.scss';
|
import './Countdown.scss';
|
||||||
|
|
||||||
const formatOptions = {
|
|
||||||
showSeconds: true,
|
|
||||||
format: 'hh:mm:ss a',
|
|
||||||
};
|
|
||||||
|
|
||||||
const formatOptionsFinished = {
|
const formatOptionsFinished = {
|
||||||
showSeconds: false,
|
showSeconds: false,
|
||||||
format: 'hh:mm a',
|
format: 'hh:mm a',
|
||||||
@@ -99,6 +95,12 @@ export default function Countdown(props: CountdownProps) {
|
|||||||
const isSelected = runningMessage === TimerMessage.running;
|
const isSelected = runningMessage === TimerMessage.running;
|
||||||
const delayedTimerStyles = delay > 0 ? 'aux-timers__value--delayed' : '';
|
const delayedTimerStyles = delay > 0 ? 'aux-timers__value--delayed' : '';
|
||||||
|
|
||||||
|
const hideSeconds = isStringBoolean(searchParams.get('hideSeconds'));
|
||||||
|
const formatOptions = {
|
||||||
|
showSeconds: !hideSeconds,
|
||||||
|
format: 'hh:mm:ss a',
|
||||||
|
};
|
||||||
|
|
||||||
const clock = formatTime(time.clock, formatOptions);
|
const clock = formatTime(time.clock, formatOptions);
|
||||||
const startTime = follow === null ? '...' : formatTime(follow.timeStart + delay, formatOptions);
|
const startTime = follow === null ? '...' : formatTime(follow.timeStart + delay, formatOptions);
|
||||||
const endTime = follow === null ? '...' : formatTime(follow.timeEnd + delay, formatOptions);
|
const endTime = follow === null ? '...' : formatTime(follow.timeEnd + delay, formatOptions);
|
||||||
@@ -110,12 +112,12 @@ export default function Countdown(props: CountdownProps) {
|
|||||||
isSelected || runningMessage === TimerMessage.waiting,
|
isSelected || runningMessage === TimerMessage.waiting,
|
||||||
);
|
);
|
||||||
|
|
||||||
const timeOption = getTimeOption(settings?.timeFormat ?? '24');
|
const timeOption = getCountdownOptions(settings?.timeFormat ?? '24');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`countdown ${isMirrored ? 'mirror' : ''}`} data-testid='countdown-view'>
|
<div className={`countdown ${isMirrored ? 'mirror' : ''}`} data-testid='countdown-view'>
|
||||||
<NavigationMenu />
|
<NavigationMenu />
|
||||||
<ViewParamsEditor paramFields={[timeOption]} />
|
<ViewParamsEditor paramFields={timeOption} />
|
||||||
{follow === null ? (
|
{follow === null ? (
|
||||||
<CountdownSelect events={backstageEvents} />
|
<CountdownSelect events={backstageEvents} />
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ import ViewParamsEditor from '../../../common/components/view-params-editor/View
|
|||||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||||
import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
||||||
import { OverridableOptions } from '../../../common/models/View.types';
|
import { OverridableOptions } from '../../../common/models/View.types';
|
||||||
|
import { formatTime } from '../../../common/utils/time';
|
||||||
import { isStringBoolean } from '../../../common/utils/viewUtils';
|
import { isStringBoolean } from '../../../common/utils/viewUtils';
|
||||||
import { formatTimerDisplay, getTimerByType } from '../common/viewerUtils';
|
import { useTranslation } from '../../../translation/TranslationProvider';
|
||||||
|
import { getTimerByType, removePrependedZero } from '../common/viewerUtils';
|
||||||
|
|
||||||
import './MinimalTimer.scss';
|
import './MinimalTimer.scss';
|
||||||
|
|
||||||
@@ -24,6 +26,7 @@ interface MinimalTimerProps {
|
|||||||
export default function MinimalTimer(props: MinimalTimerProps) {
|
export default function MinimalTimer(props: MinimalTimerProps) {
|
||||||
const { isMirrored, pres, time, viewSettings } = props;
|
const { isMirrored, pres, time, viewSettings } = props;
|
||||||
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
||||||
|
const { getLocalizedString } = useTranslation();
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -35,9 +38,8 @@ export default function MinimalTimer(props: MinimalTimerProps) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get config from url: key, text, font, size, hideovertime
|
// TODO: this should be tied to the params
|
||||||
// eg. http://localhost:3000/minimal?key=f00&text=fff
|
// USER OPTIONS
|
||||||
// Check for user options
|
|
||||||
const userOptions: OverridableOptions = {
|
const userOptions: OverridableOptions = {
|
||||||
size: 1,
|
size: 1,
|
||||||
};
|
};
|
||||||
@@ -126,10 +128,12 @@ export default function MinimalTimer(props: MinimalTimerProps) {
|
|||||||
const hideEndMessage = searchParams.get('hideendmessage');
|
const hideEndMessage = searchParams.get('hideendmessage');
|
||||||
userOptions.hideEndMessage = isStringBoolean(hideEndMessage);
|
userOptions.hideEndMessage = isStringBoolean(hideEndMessage);
|
||||||
|
|
||||||
|
const hideTimerSeconds = searchParams.get('hideTimerSeconds');
|
||||||
|
userOptions.hideTimerSeconds = isStringBoolean(hideTimerSeconds);
|
||||||
|
|
||||||
const showOverlay = pres.text !== '' && pres.visible;
|
const showOverlay = pres.text !== '' && pres.visible;
|
||||||
const isPlaying = time.playback !== Playback.Pause;
|
const isPlaying = time.playback !== Playback.Pause;
|
||||||
const isNegative =
|
|
||||||
(time.current ?? 0) < 0 && time.timerType !== TimerType.Clock && time.timerType !== TimerType.CountUp;
|
|
||||||
const showEndMessage = (time.current ?? 0) < 0 && viewSettings.endMessage && !hideEndMessage;
|
const showEndMessage = (time.current ?? 0) < 0 && viewSettings.endMessage && !hideEndMessage;
|
||||||
const finished = time.playback === Playback.Play && (time.current ?? 0) < 0 && time.startedAt;
|
const finished = time.playback === Playback.Play && (time.current ?? 0) < 0 && time.startedAt;
|
||||||
const showFinished = finished && !userOptions?.hideOvertime && (time.timerType !== TimerType.Clock || showEndMessage);
|
const showFinished = finished && !userOptions?.hideOvertime && (time.timerType !== TimerType.Clock || showEndMessage);
|
||||||
@@ -149,9 +153,16 @@ export default function MinimalTimer(props: MinimalTimerProps) {
|
|||||||
: viewSettings.normalColor;
|
: viewSettings.normalColor;
|
||||||
|
|
||||||
const stageTimer = getTimerByType(time);
|
const stageTimer = getTimerByType(time);
|
||||||
let display = formatTimerDisplay(stageTimer);
|
let display = '-- : -- : --';
|
||||||
if (isNegative) {
|
if (stageTimer !== null) {
|
||||||
display = `-${display}`;
|
display = formatTime(stageTimer, {
|
||||||
|
showSeconds: !userOptions.hideTimerSeconds,
|
||||||
|
format: 'hh:mm:ss a',
|
||||||
|
});
|
||||||
|
display = removePrependedZero(display);
|
||||||
|
if (display.length < 3) {
|
||||||
|
display = `${display} ${getLocalizedString('common.minutes')}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const stageTimerCharacters = display.replace('/:/g', '').length;
|
const stageTimerCharacters = display.replace('/:/g', '').length;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import QRCode from 'react-qr-code';
|
import QRCode from 'react-qr-code';
|
||||||
|
import { useSearchParams } from 'react-router-dom';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
import { Message, OntimeEvent, ProjectData, Settings, ViewSettings } from 'ontime-types';
|
import { Message, OntimeEvent, ProjectData, Settings, ViewSettings } from 'ontime-types';
|
||||||
|
|
||||||
@@ -14,17 +15,13 @@ import ViewParamsEditor from '../../../common/components/view-params-editor/View
|
|||||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||||
import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
||||||
import { formatTime } from '../../../common/utils/time';
|
import { formatTime } from '../../../common/utils/time';
|
||||||
|
import { isStringBoolean } from '../../../common/utils/viewUtils';
|
||||||
import { useTranslation } from '../../../translation/TranslationProvider';
|
import { useTranslation } from '../../../translation/TranslationProvider';
|
||||||
import { titleVariants } from '../common/animation';
|
import { titleVariants } from '../common/animation';
|
||||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||||
|
|
||||||
import './Public.scss';
|
import './Public.scss';
|
||||||
|
|
||||||
const formatOptions = {
|
|
||||||
showSeconds: true,
|
|
||||||
format: 'hh:mm:ss a',
|
|
||||||
};
|
|
||||||
|
|
||||||
interface BackstageProps {
|
interface BackstageProps {
|
||||||
isMirrored: boolean;
|
isMirrored: boolean;
|
||||||
publ: Message;
|
publ: Message;
|
||||||
@@ -51,6 +48,9 @@ export default function Public(props: BackstageProps) {
|
|||||||
viewSettings,
|
viewSettings,
|
||||||
settings,
|
settings,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
|
|
||||||
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
||||||
const { getLocalizedString } = useTranslation();
|
const { getLocalizedString } = useTranslation();
|
||||||
|
|
||||||
@@ -64,6 +64,13 @@ export default function Public(props: BackstageProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const showPublicMessage = publ.text && publ.visible;
|
const showPublicMessage = publ.text && publ.visible;
|
||||||
|
|
||||||
|
const hideSeconds = isStringBoolean(searchParams.get('hideSeconds'));
|
||||||
|
const formatOptions = {
|
||||||
|
showSeconds: !hideSeconds,
|
||||||
|
format: 'hh:mm:ss a',
|
||||||
|
};
|
||||||
|
|
||||||
const clock = formatTime(time.clock, formatOptions);
|
const clock = formatTime(time.clock, formatOptions);
|
||||||
const qrSize = Math.max(window.innerWidth / 15, 128);
|
const qrSize = Math.max(window.innerWidth / 15, 128);
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ $orange-active: #f60;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ampmIndicator {
|
.clock__ampm {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-size: calc(var(--clock-size) / 20);
|
font-size: calc(var(--clock-size) / 20);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@@ -14,17 +14,13 @@ import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
|||||||
import { secondsInMillis } from '../../../common/utils/dateConfig';
|
import { secondsInMillis } from '../../../common/utils/dateConfig';
|
||||||
import { formatTime, resolveTimeFormat } from '../../../common/utils/time';
|
import { formatTime, resolveTimeFormat } from '../../../common/utils/time';
|
||||||
import { mth } from '../../../common/utils/timeConstants';
|
import { mth } from '../../../common/utils/timeConstants';
|
||||||
|
import { isStringBoolean } from '../../../common/utils/viewUtils';
|
||||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||||
|
|
||||||
import { trimRundown } from './studioClock.utils';
|
import { trimRundown } from './studioClock.utils';
|
||||||
|
|
||||||
import './StudioClock.scss';
|
import './StudioClock.scss';
|
||||||
|
|
||||||
const formatOptions = {
|
|
||||||
showSeconds: false,
|
|
||||||
format: 'hh:mm',
|
|
||||||
};
|
|
||||||
|
|
||||||
interface StudioClockProps {
|
interface StudioClockProps {
|
||||||
isMirrored: boolean;
|
isMirrored: boolean;
|
||||||
eventNext: OntimeEvent | null;
|
eventNext: OntimeEvent | null;
|
||||||
@@ -51,15 +47,17 @@ export default function StudioClock(props: StudioClockProps) {
|
|||||||
const MAX_TITLES = 11;
|
const MAX_TITLES = 11;
|
||||||
|
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const showSeconds = searchParams.get('seconds');
|
|
||||||
const timeFormat = resolveTimeFormat();
|
|
||||||
formatOptions.showSeconds = Boolean(showSeconds);
|
|
||||||
formatOptions.format = `hh:mm${formatOptions.showSeconds ? ':ss' : ''}`;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = 'ontime - Studio Clock';
|
document.title = 'ontime - Studio Clock';
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const hideSeconds = isStringBoolean(searchParams.get('hideSeconds'));
|
||||||
|
const formatOptions = {
|
||||||
|
showSeconds: !hideSeconds,
|
||||||
|
format: 'hh:mm:ss',
|
||||||
|
};
|
||||||
|
|
||||||
const clock = formatTime(time.clock, formatOptions);
|
const clock = formatTime(time.clock, formatOptions);
|
||||||
const secondsNow = secondsInMillis(time.clock);
|
const secondsNow = secondsInMillis(time.clock);
|
||||||
const isNegative = (time.current ?? 0) < 0;
|
const isNegative = (time.current ?? 0) < 0;
|
||||||
@@ -70,14 +68,15 @@ export default function StudioClock(props: StudioClockProps) {
|
|||||||
const delayed = backstageEvents.filter((event) => isOntimeEvent(event)) as OntimeEvent[];
|
const delayed = backstageEvents.filter((event) => isOntimeEvent(event)) as OntimeEvent[];
|
||||||
const trimmedRundown = trimRundown(delayed, selectedId, MAX_TITLES);
|
const trimmedRundown = trimRundown(delayed, selectedId, MAX_TITLES);
|
||||||
const isAm = time.clock / (mth * 12) > 12;
|
const isAm = time.clock / (mth * 12) > 12;
|
||||||
|
const timeFormat = resolveTimeFormat();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`studio-clock ${isMirrored ? 'mirror' : ''}`} data-testid='studio-view'>
|
<div className={`studio-clock ${isMirrored ? 'mirror' : ''}`} data-testid='studio-view'>
|
||||||
<NavigationMenu />
|
<NavigationMenu />
|
||||||
<ViewParamsEditor paramFields={studioClockOptions} />
|
<ViewParamsEditor paramFields={studioClockOptions} />
|
||||||
<div className='clock-container'>
|
<div className='clock-container'>
|
||||||
{timeFormat == '12' && <div className='ampmIndicator'>{isAm ? 'am' : 'pm'}</div>}
|
{timeFormat == '12' && <div className='clock__ampm'>{isAm ? 'am' : 'pm'}</div>}
|
||||||
<div className={`studio-timer ${showSeconds ? 'studio-timer--with-seconds' : ''}`}>{clock}</div>
|
<div className={`studio-timer ${formatOptions.showSeconds ? 'studio-timer--with-seconds' : ''}`}>{clock}</div>
|
||||||
<div
|
<div
|
||||||
ref={titleRef}
|
ref={titleRef}
|
||||||
className='next-title'
|
className='next-title'
|
||||||
|
|||||||
@@ -15,15 +15,10 @@ import { formatTime } from '../../../common/utils/time';
|
|||||||
import { isStringBoolean } from '../../../common/utils/viewUtils';
|
import { isStringBoolean } from '../../../common/utils/viewUtils';
|
||||||
import { useTranslation } from '../../../translation/TranslationProvider';
|
import { useTranslation } from '../../../translation/TranslationProvider';
|
||||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||||
import { formatTimerDisplay, getTimerByType } from '../common/viewerUtils';
|
import { getTimerByType, removePrependedZero } from '../common/viewerUtils';
|
||||||
|
|
||||||
import './Timer.scss';
|
import './Timer.scss';
|
||||||
|
|
||||||
const formatOptions = {
|
|
||||||
showSeconds: true,
|
|
||||||
format: 'hh:mm:ss a',
|
|
||||||
};
|
|
||||||
|
|
||||||
// motion
|
// motion
|
||||||
const titleVariants = {
|
const titleVariants = {
|
||||||
hidden: {
|
hidden: {
|
||||||
@@ -72,6 +67,8 @@ export default function Timer(props: TimerProps) {
|
|||||||
hideCards: false,
|
hideCards: false,
|
||||||
hideProgress: false,
|
hideProgress: false,
|
||||||
hideMessage: false,
|
hideMessage: false,
|
||||||
|
hideTimerSeconds: false,
|
||||||
|
hideClockSeconds: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const hideClock = searchParams.get('hideClock');
|
const hideClock = searchParams.get('hideClock');
|
||||||
@@ -86,12 +83,19 @@ export default function Timer(props: TimerProps) {
|
|||||||
const hideMessage = searchParams.get('hideMessage');
|
const hideMessage = searchParams.get('hideMessage');
|
||||||
userOptions.hideMessage = isStringBoolean(hideMessage);
|
userOptions.hideMessage = isStringBoolean(hideMessage);
|
||||||
|
|
||||||
const clock = formatTime(time.clock, formatOptions);
|
const hideClockSeconds = searchParams.get('hideClockSeconds');
|
||||||
|
userOptions.hideClockSeconds = isStringBoolean(hideClockSeconds);
|
||||||
|
const clock = formatTime(time.clock, {
|
||||||
|
showSeconds: !userOptions.hideClockSeconds,
|
||||||
|
format: 'hh:mm:ss a',
|
||||||
|
});
|
||||||
|
|
||||||
|
const hideTimerSeconds = searchParams.get('hideTimerSeconds');
|
||||||
|
userOptions.hideTimerSeconds = isStringBoolean(hideTimerSeconds);
|
||||||
|
|
||||||
const showOverlay = pres.text !== '' && pres.visible;
|
const showOverlay = pres.text !== '' && pres.visible;
|
||||||
const isPlaying = time.playback !== Playback.Pause;
|
const isPlaying = time.playback !== Playback.Pause;
|
||||||
|
|
||||||
const isNegative =
|
|
||||||
(time.current ?? 0) < 0 && time.timerType !== TimerType.Clock && time.timerType !== TimerType.CountUp;
|
|
||||||
const finished = time.playback === Playback.Play && (time.current ?? 0) < 0 && time.startedAt;
|
const finished = time.playback === Playback.Play && (time.current ?? 0) < 0 && time.startedAt;
|
||||||
const totalTime = (time.duration ?? 0) + (time.addedTime ?? 0);
|
const totalTime = (time.duration ?? 0) + (time.addedTime ?? 0);
|
||||||
|
|
||||||
@@ -113,11 +117,18 @@ export default function Timer(props: TimerProps) {
|
|||||||
: viewSettings.normalColor;
|
: viewSettings.normalColor;
|
||||||
|
|
||||||
const stageTimer = getTimerByType(time);
|
const stageTimer = getTimerByType(time);
|
||||||
let display = formatTimerDisplay(stageTimer);
|
let display = '-- : -- : --';
|
||||||
const stageTimerCharacters = display.replace('/:/g', '').length;
|
if (stageTimer !== null) {
|
||||||
if (isNegative) {
|
display = formatTime(stageTimer, {
|
||||||
display = `-${display}`;
|
showSeconds: !userOptions.hideTimerSeconds,
|
||||||
|
format: 'hh:mm:ss a',
|
||||||
|
});
|
||||||
|
display = removePrependedZero(display);
|
||||||
|
if (display.length < 3) {
|
||||||
|
display = `${display} ${getLocalizedString('common.minutes')}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
const stageTimerCharacters = display.replace('/:/g', '').length;
|
||||||
|
|
||||||
const baseClasses = `stage-timer ${isMirrored ? 'mirror' : ''} ${showBlackout ? 'blackout' : ''}`;
|
const baseClasses = `stage-timer ${isMirrored ? 'mirror' : ''} ${showBlackout ? 'blackout' : ''}`;
|
||||||
let timerFontSize = 89 / (stageTimerCharacters - 1);
|
let timerFontSize = 89 / (stageTimerCharacters - 1);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { TranslationObject } from './en';
|
|||||||
export const langDe: TranslationObject = {
|
export const langDe: TranslationObject = {
|
||||||
'common.end_time': 'Endzeit',
|
'common.end_time': 'Endzeit',
|
||||||
'common.expected_finish': 'Voraussichtliches Ende',
|
'common.expected_finish': 'Voraussichtliches Ende',
|
||||||
|
'common.minutes': 'min',
|
||||||
'common.now': 'Jetzt',
|
'common.now': 'Jetzt',
|
||||||
'common.next': 'Nächste',
|
'common.next': 'Nächste',
|
||||||
'common.public_message': 'Öffentliche Nachricht',
|
'common.public_message': 'Öffentliche Nachricht',
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export const langEn = {
|
export const langEn = {
|
||||||
'common.end_time': 'End Time',
|
'common.end_time': 'End Time',
|
||||||
'common.expected_finish': 'Expected Finish',
|
'common.expected_finish': 'Expected Finish',
|
||||||
|
'common.minutes': 'min',
|
||||||
'common.now': 'Now',
|
'common.now': 'Now',
|
||||||
'common.next': 'Next',
|
'common.next': 'Next',
|
||||||
'common.public_message': 'Public message',
|
'common.public_message': 'Public message',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { TranslationObject } from './en';
|
|||||||
export const langEs: TranslationObject = {
|
export const langEs: TranslationObject = {
|
||||||
'common.end_time': 'Hora de finalización',
|
'common.end_time': 'Hora de finalización',
|
||||||
'common.expected_finish': 'Finalización esperada',
|
'common.expected_finish': 'Finalización esperada',
|
||||||
|
'common.minutes': 'min',
|
||||||
'common.now': 'Ahora',
|
'common.now': 'Ahora',
|
||||||
'common.next': 'Siguiente',
|
'common.next': 'Siguiente',
|
||||||
'common.public_message': 'Mensaje público',
|
'common.public_message': 'Mensaje público',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { TranslationObject } from './en';
|
|||||||
export const langFr: TranslationObject = {
|
export const langFr: TranslationObject = {
|
||||||
'common.end_time': 'Termine à',
|
'common.end_time': 'Termine à',
|
||||||
'common.expected_finish': 'Fin estimée à',
|
'common.expected_finish': 'Fin estimée à',
|
||||||
|
'common.minutes': 'min',
|
||||||
'common.now': 'Maintenant',
|
'common.now': 'Maintenant',
|
||||||
'common.next': 'A suivre',
|
'common.next': 'A suivre',
|
||||||
'common.public_message': 'Message public',
|
'common.public_message': 'Message public',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { TranslationObject } from './en';
|
|||||||
export const langIt: TranslationObject = {
|
export const langIt: TranslationObject = {
|
||||||
'common.end_time': 'Ora di Fine',
|
'common.end_time': 'Ora di Fine',
|
||||||
'common.expected_finish': 'Fine Prevista',
|
'common.expected_finish': 'Fine Prevista',
|
||||||
|
'common.minutes': 'min',
|
||||||
'common.now': 'Adesso',
|
'common.now': 'Adesso',
|
||||||
'common.next': 'Prossimo',
|
'common.next': 'Prossimo',
|
||||||
'common.public_message': 'Messaggio pubblico',
|
'common.public_message': 'Messaggio pubblico',
|
||||||
@@ -14,6 +15,6 @@ export const langIt: TranslationObject = {
|
|||||||
'countdown.running': 'Evento in corso',
|
'countdown.running': 'Evento in corso',
|
||||||
'countdown.select_event': 'Seleziona un evento da seguire',
|
'countdown.select_event': 'Seleziona un evento da seguire',
|
||||||
'countdown.to_start': 'Tempo alla partenza',
|
'countdown.to_start': 'Tempo alla partenza',
|
||||||
'countdown.waiting': 'In attesa dell\'inizio dell\'evento',
|
'countdown.waiting': "In attesa dell'inizio dell'evento",
|
||||||
'countdown.overtime': 'in ritardo',
|
'countdown.overtime': 'in ritardo',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { TranslationObject } from './en';
|
|||||||
export const langNo: TranslationObject = {
|
export const langNo: TranslationObject = {
|
||||||
'common.end_time': 'Sluttid',
|
'common.end_time': 'Sluttid',
|
||||||
'common.expected_finish': 'Forventet slutt',
|
'common.expected_finish': 'Forventet slutt',
|
||||||
|
'common.minutes': 'min',
|
||||||
'common.now': 'Nå',
|
'common.now': 'Nå',
|
||||||
'common.next': 'Neste',
|
'common.next': 'Neste',
|
||||||
'common.public_message': 'Offentlig beskjed',
|
'common.public_message': 'Offentlig beskjed',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { TranslationObject } from './en';
|
|||||||
export const langPt: TranslationObject = {
|
export const langPt: TranslationObject = {
|
||||||
'common.end_time': 'Hora de término',
|
'common.end_time': 'Hora de término',
|
||||||
'common.expected_finish': 'Término esperado',
|
'common.expected_finish': 'Término esperado',
|
||||||
|
'common.minutes': 'min',
|
||||||
'common.now': 'Agora',
|
'common.now': 'Agora',
|
||||||
'common.next': 'Próximo',
|
'common.next': 'Próximo',
|
||||||
'common.public_message': 'Mensagem pública',
|
'common.public_message': 'Mensagem pública',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { TranslationObject } from './en';
|
|||||||
export const langSv: TranslationObject = {
|
export const langSv: TranslationObject = {
|
||||||
'common.end_time': 'Sluttid',
|
'common.end_time': 'Sluttid',
|
||||||
'common.expected_finish': 'Förväntat slut',
|
'common.expected_finish': 'Förväntat slut',
|
||||||
|
'common.minutes': 'min',
|
||||||
'common.now': 'Nu',
|
'common.now': 'Nu',
|
||||||
'common.next': 'Nästa',
|
'common.next': 'Nästa',
|
||||||
'common.public_message': 'Offentligt meddelande',
|
'common.public_message': 'Offentligt meddelande',
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { LogOrigin, OntimeEvent } from 'ontime-types';
|
import { LogOrigin, OntimeEvent, isKeyOfType, isOntimeEvent } from 'ontime-types';
|
||||||
import { EventLoader } from '../classes/event-loader/EventLoader.js';
|
import { EventLoader } from '../classes/event-loader/EventLoader.js';
|
||||||
import { editEvent } from '../services/rundown-service/RundownService.js';
|
import { editEvent } from '../services/rundown-service/RundownService.js';
|
||||||
import { coerceString, coerceNumber, coerceBoolean, coerceColour } from '../utils/coerceType.js';
|
import { coerceString, coerceNumber, coerceBoolean, coerceColour } from '../utils/coerceType.js';
|
||||||
import { logger } from '../classes/Logger.js';
|
import { logger } from '../classes/Logger.js';
|
||||||
import { isKeyOfType, isOntimeEvent } from 'ontime-types/src/utils/guards.js';
|
|
||||||
|
|
||||||
const whitelistedPayload = {
|
const whitelistedPayload = {
|
||||||
title: coerceString,
|
title: coerceString,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Message, TimerMessage } from 'ontime-types';
|
import { Message, TimerMessage } from 'ontime-types';
|
||||||
|
|
||||||
import { throttle } from '../../utils/throttle.js';
|
import { throttle } from '../../utils/throttle.js';
|
||||||
|
|
||||||
import type { PublishFn } from '../../stores/EventStore.js';
|
import type { PublishFn } from '../../stores/EventStore.js';
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export type { Settings } from './definitions/core/Settings.type.js';
|
|||||||
|
|
||||||
// ---> Views
|
// ---> Views
|
||||||
export type { ViewSettings } from './definitions/core/Views.type.js';
|
export type { ViewSettings } from './definitions/core/Views.type.js';
|
||||||
|
export type { TimeFormat } from './definitions/core/TimeFormat.type.js';
|
||||||
|
|
||||||
// ---> Aliases
|
// ---> Aliases
|
||||||
export type { Alias } from './definitions/core/Alias.type.js';
|
export type { Alias } from './definitions/core/Alias.type.js';
|
||||||
@@ -61,5 +62,5 @@ export type { TimerState } from './definitions/runtime/TimerState.type.js';
|
|||||||
// CLIENT
|
// CLIENT
|
||||||
|
|
||||||
// TYPE UTILITIES
|
// TYPE UTILITIES
|
||||||
export { isOntimeBlock, isOntimeDelay, isOntimeEvent } from './utils/guards.js';
|
export { isOntimeBlock, isOntimeDelay, isOntimeEvent, isKeyOfType } from './utils/guards.js';
|
||||||
export type { MaybeNumber } from './utils/utils.type.js';
|
export type { MaybeNumber } from './utils/utils.type.js';
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export function formatDisplay(milliseconds: number | null, hideZero = false): st
|
|||||||
return [hours, minutes, s % 60].map(format).join(':');
|
return [hours, minutes, s % 60].map(format).join(':');
|
||||||
}
|
}
|
||||||
|
|
||||||
export const millisToSeconds = (millis: number | null): number => {
|
const millisToSeconds = (millis: number | null): number => {
|
||||||
if (millis === null) {
|
if (millis === null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user