mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-20 06:29:07 +00:00
Feat/161 (#186)
* feat(time): add optional time format * feat(time): show 12 hour time in stage timer * feat(time): override locally * feat(time): show timer in selected format * feat(time): show 12 hour time in table header * refactor: extract time formatting into utility * refactor: migrate datetime library * refactor(formatTime): centralise time formatting for viewers * feature(12hour): version bump
This commit is contained in:
@@ -6,19 +6,24 @@ import NavLogo from '../../../common/components/nav/NavLogo';
|
||||
import Empty from '../../../common/components/state/Empty';
|
||||
import { formatDisplay, millisToSeconds } from '../../../common/utils/dateConfig';
|
||||
import getDelayTo from '../../../common/utils/getDelayTo';
|
||||
import { stringFromMillis } from '../../../common/utils/time';
|
||||
import { formatTime } from '../../../common/utils/time';
|
||||
|
||||
import { fetchTimerData, sanitiseTitle, timerMessages } from './countdown.helpers';
|
||||
|
||||
import style from './Countdown.module.scss';
|
||||
|
||||
const formatOptions = {
|
||||
showSeconds: true,
|
||||
format: 'hh:mm:ss a',
|
||||
};
|
||||
|
||||
export default function Countdown(props) {
|
||||
const [searchParams] = useSearchParams();
|
||||
const { backstageEvents, time, selectedId } = props;
|
||||
const [follow, setFollow] = useState(null);
|
||||
const [runningTimer, setRunningTimer] = useState(0);
|
||||
const [runningMessage, setRunningMessage] = useState('');
|
||||
const [delay, setDelay] = useState(0);
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
// Set window title
|
||||
useEffect(() => {
|
||||
@@ -46,8 +51,8 @@ export default function Countdown(props) {
|
||||
if (typeof followThis !== 'undefined') {
|
||||
setFollow(followThis);
|
||||
const idx = backstageEvents.findIndex((event) => event.id === followThis.id);
|
||||
const delay = getDelayTo(backstageEvents, idx);
|
||||
setDelay(delay);
|
||||
const delayToEvent = getDelayTo(backstageEvents, idx);
|
||||
setDelay(delayToEvent);
|
||||
}
|
||||
}, [backstageEvents, searchParams]);
|
||||
|
||||
@@ -73,6 +78,16 @@ export default function Countdown(props) {
|
||||
|
||||
const isSelected = useMemo(() => runningMessage === timerMessages.running, [runningMessage]);
|
||||
|
||||
const clock = formatTime(time.clock, formatOptions);
|
||||
const startTime =
|
||||
follow === null
|
||||
? '...'
|
||||
: formatTime(follow.timeStart + delay, formatOptions);
|
||||
const endTime =
|
||||
follow === null
|
||||
? '...'
|
||||
: formatTime(follow.timeEnd + delay, formatOptions);
|
||||
|
||||
return (
|
||||
<div className={style.container}>
|
||||
<NavLogo />
|
||||
@@ -100,19 +115,17 @@ export default function Countdown(props) {
|
||||
<div className={style.timers}>
|
||||
<div className={style.timer}>
|
||||
<div className={style.label}>Time Now</div>
|
||||
<span className={style.value}>{time.clock}</span>
|
||||
<span className={style.value}>{clock}</span>
|
||||
</div>
|
||||
<div className={style.timer}>
|
||||
<div className={style.label}>Start Time</div>
|
||||
<span className={`${style.value} ${delay > 0 ? style.delayed : ''}`}>
|
||||
{stringFromMillis(follow.timeStart + delay)}
|
||||
{startTime}
|
||||
</span>
|
||||
</div>
|
||||
<div className={style.timer}>
|
||||
<div className={style.label}>End Time</div>
|
||||
<span className={`${style.value} ${delay > 0 ? style.delayed : ''}`}>
|
||||
{stringFromMillis(follow.timeEnd + delay)}
|
||||
</span>
|
||||
<span className={`${style.value} ${delay > 0 ? style.delayed : ''}`}>{endTime}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className={style.status}>{runningMessage}</div>
|
||||
@@ -126,7 +139,7 @@ export default function Countdown(props) {
|
||||
isSelected || time.waiting
|
||||
)}
|
||||
</span>
|
||||
<div className={style.title}>{follow.title || 'Untitled Event'}</div>
|
||||
<div className={style.title}>{follow?.title || 'Untitled Event'}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -137,4 +150,5 @@ Countdown.propTypes = {
|
||||
backstageEvents: PropTypes.array,
|
||||
time: PropTypes.object,
|
||||
selectedId: PropTypes.string,
|
||||
settings: PropTypes.object,
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('fetchTimerData() function', () => {
|
||||
const startMockValue = 10000;
|
||||
const timeNow = 1000;
|
||||
const follow = { id: 'anotherevent', timeStart: startMockValue };
|
||||
const time = { clockMs: timeNow };
|
||||
const time = { clock: timeNow };
|
||||
|
||||
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent');
|
||||
expect(message).toBe(timerMessages.toStart);
|
||||
@@ -48,7 +48,7 @@ describe('fetchTimerData() function', () => {
|
||||
const timeNow = 15000;
|
||||
const followId = 'testId';
|
||||
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue };
|
||||
const time = { clockMs: timeNow, running: endMockValue - startMockValue };
|
||||
const time = { clock: timeNow, running: endMockValue - startMockValue };
|
||||
|
||||
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent');
|
||||
expect(message).toBe(timerMessages.waiting);
|
||||
@@ -61,7 +61,7 @@ describe('fetchTimerData() function', () => {
|
||||
const timeNow = 30000;
|
||||
const followId = 'testId';
|
||||
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue };
|
||||
const time = { clockMs: timeNow, running: endMockValue - startMockValue };
|
||||
const time = { clock: timeNow, running: endMockValue - startMockValue };
|
||||
|
||||
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent');
|
||||
expect(message).toBe(timerMessages.ended);
|
||||
@@ -74,7 +74,7 @@ describe('fetchTimerData() function', () => {
|
||||
const timeNow = 15000;
|
||||
const followId = 'testId';
|
||||
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue };
|
||||
const time = { clockMs: timeNow, running: DAY_TO_MS + endMockValue - startMockValue };
|
||||
const time = { clock: timeNow, running: DAY_TO_MS + endMockValue - startMockValue };
|
||||
|
||||
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent');
|
||||
expect(message).toBe(timerMessages.waiting);
|
||||
@@ -87,7 +87,7 @@ describe('fetchTimerData() function', () => {
|
||||
const timeNow = 15000;
|
||||
const followId = 'testId';
|
||||
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue };
|
||||
const time = { clockMs: timeNow, running: DAY_TO_MS + endMockValue - startMockValue };
|
||||
const time = { clock: timeNow, running: DAY_TO_MS + endMockValue - startMockValue };
|
||||
|
||||
const { message, timer } = fetchTimerData(time, follow, followId);
|
||||
expect(message).toBe(timerMessages.running);
|
||||
@@ -100,7 +100,7 @@ describe('fetchTimerData() function', () => {
|
||||
const timeNow = 2000;
|
||||
const followId = 'testId';
|
||||
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue };
|
||||
const time = { clockMs: timeNow, running: DAY_TO_MS + endMockValue - startMockValue };
|
||||
const time = { clock: timeNow, running: DAY_TO_MS + endMockValue - startMockValue };
|
||||
|
||||
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent');
|
||||
expect(message).toBe(timerMessages.toStart);
|
||||
|
||||
@@ -34,22 +34,22 @@ export const fetchTimerData = (time, follow, selectedId) => {
|
||||
// check that is not running
|
||||
message = time.playstate === 'pause' ? timerMessages.waiting : timerMessages.running;
|
||||
timer = time.running;
|
||||
} else if (time.clockMs < follow.timeStart) {
|
||||
} else if (time.clock < follow.timeStart) {
|
||||
// if it hasnt started, we count to start
|
||||
message = timerMessages.toStart;
|
||||
timer = millisToSeconds(follow.timeStart - time.clockMs);
|
||||
} else if (follow.timeStart <= time.clockMs && time.clockMs <= follow.timeEnd) {
|
||||
timer = millisToSeconds(follow.timeStart - time.clock);
|
||||
} else if (follow.timeStart <= time.clock && time.clock <= follow.timeEnd) {
|
||||
// if it has started, we show running timer
|
||||
message = timerMessages.waiting;
|
||||
timer = time.running;
|
||||
} else {
|
||||
if (follow.timeStart > follow.timeEnd) {
|
||||
// ends day after
|
||||
if (follow.timeStart > time.clockMs ) {
|
||||
if (follow.timeStart > time.clock ) {
|
||||
// if it hasnt started, we count to start
|
||||
message = timerMessages.toStart;
|
||||
timer = millisToSeconds(follow.timeStart - time.clockMs);
|
||||
} else if (follow.timeStart <= time.clockMs) {
|
||||
timer = millisToSeconds(follow.timeStart - time.clock);
|
||||
} else if (follow.timeStart <= time.clock) {
|
||||
// if it has started, we show running timer
|
||||
message = timerMessages.waiting;
|
||||
timer = time.running;
|
||||
|
||||
Reference in New Issue
Block a user