mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-10 01:43:43 +00:00
style: clock period (#601)
* style: tweaks to studio override * style: improvements to 12 hour format
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
import SuperscriptTime from '../../../features/viewers/common/superscript-time/SuperscriptTime';
|
||||
import { formatTime } from '../../utils/time';
|
||||
|
||||
import './Schedule.scss';
|
||||
|
||||
const formatOptions = {
|
||||
format: 'hh:mm a',
|
||||
};
|
||||
|
||||
interface ScheduleItemProps {
|
||||
selected: 'past' | 'now' | 'future';
|
||||
timeStart: number;
|
||||
@@ -16,8 +21,8 @@ interface ScheduleItemProps {
|
||||
export default function ScheduleItem(props: ScheduleItemProps) {
|
||||
const { selected, timeStart, timeEnd, title, presenter, backstageEvent, colour, skip } = props;
|
||||
|
||||
const start = formatTime(timeStart, { format: 'hh:mm' });
|
||||
const end = formatTime(timeEnd, { format: 'hh:mm' });
|
||||
const start = formatTime(timeStart, formatOptions);
|
||||
const end = formatTime(timeEnd, formatOptions);
|
||||
const userColour = colour !== '' ? colour : '';
|
||||
const selectStyle = `entry--${selected}`;
|
||||
|
||||
@@ -25,7 +30,12 @@ export default function ScheduleItem(props: ScheduleItemProps) {
|
||||
<li className={`entry ${selectStyle} ${skip ? 'skip' : ''}`}>
|
||||
<div className='entry-times'>
|
||||
<span className='entry-colour' style={{ backgroundColor: userColour }} />
|
||||
{`${start} → ${end} ${backstageEvent ? '*' : ''}`}
|
||||
<div style={{ display: 'flex' }}>
|
||||
<SuperscriptTime time={start} />
|
||||
{' → '}
|
||||
<SuperscriptTime time={end} />
|
||||
{backstageEvent ? '*' : ''}
|
||||
</div>
|
||||
</div>
|
||||
<div className='entry-title'>{title}</div>
|
||||
{presenter && <div className='entry-presenter'>{presenter}</div>}
|
||||
|
||||
+10
@@ -26,4 +26,14 @@ describe('formatTime()', () => {
|
||||
const time = formatTime(ms);
|
||||
expect(time).toStrictEqual('...');
|
||||
});
|
||||
|
||||
it('shows 12h format without times', () => {
|
||||
const ms = 13 * 60 * 60 * 1000;
|
||||
const options = {
|
||||
showSeconds: false,
|
||||
format: 'hh:mm a',
|
||||
};
|
||||
const time = formatTime(ms, options, () => '12');
|
||||
expect(time).toStrictEqual('01:00 PM');
|
||||
});
|
||||
});
|
||||
@@ -60,6 +60,7 @@
|
||||
font-weight: 600;
|
||||
color: var(--secondary-color-override, $viewer-secondary-color);
|
||||
letter-spacing: 0.05em;
|
||||
line-height: 0.95em;
|
||||
}
|
||||
|
||||
.message {
|
||||
|
||||
@@ -18,6 +18,7 @@ import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
||||
import { formatTime } from '../../../common/utils/time';
|
||||
import { useTranslation } from '../../../translation/TranslationProvider';
|
||||
import { titleVariants } from '../common/animation';
|
||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||
|
||||
import './Backstage.scss';
|
||||
|
||||
@@ -97,7 +98,7 @@ export default function Backstage(props: BackstageProps) {
|
||||
{general.title}
|
||||
<div className='clock-container'>
|
||||
<div className='label'>{getLocalizedString('common.time_now')}</div>
|
||||
<div className='time'>{clock}</div>
|
||||
<SuperscriptTime time={clock} className='time' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -128,12 +129,16 @@ export default function Backstage(props: BackstageProps) {
|
||||
<div className='timer-group'>
|
||||
<div className='aux-timers'>
|
||||
<div className='aux-timers__label'>{getLocalizedString('common.started_at')}</div>
|
||||
<div className='aux-timers__value'>{startedAt}</div>
|
||||
<SuperscriptTime time={startedAt} className='aux-timers__value' />
|
||||
</div>
|
||||
<div className='timer-gap' />
|
||||
<div className='aux-timers'>
|
||||
<div className='aux-timers__label'>{getLocalizedString('common.expected_finish')}</div>
|
||||
<div className='aux-timers__value'>{expectedFinish}</div>
|
||||
{isNegative ? (
|
||||
<div className='aux-timers__value'>{expectedFinish}</div>
|
||||
) : (
|
||||
<SuperscriptTime time={startedAt} className='aux-timers__value' />
|
||||
)}
|
||||
</div>
|
||||
<div className='timer-gap' />
|
||||
<div className='aux-timers'>
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet
|
||||
import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
||||
import { OverridableOptions } from '../../../common/models/View.types';
|
||||
import { formatTime } from '../../../common/utils/time';
|
||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||
|
||||
import './Clock.scss';
|
||||
|
||||
@@ -135,7 +136,8 @@ export default function Clock(props: ClockProps) {
|
||||
>
|
||||
<NavigationMenu />
|
||||
<ViewParamsEditor paramFields={CLOCK_OPTIONS} />
|
||||
<div
|
||||
<SuperscriptTime
|
||||
time={clock}
|
||||
className='clock'
|
||||
style={{
|
||||
color: userOptions.textColour,
|
||||
@@ -145,9 +147,7 @@ export default function Clock(props: ClockProps) {
|
||||
left: userOptions.left,
|
||||
backgroundColor: userOptions.textBackground,
|
||||
}}
|
||||
>
|
||||
{clock}
|
||||
</div>
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
sup.period {
|
||||
top: -1em;
|
||||
font-size: 0.4em;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { CSSProperties } from 'react';
|
||||
|
||||
import './SuperscriptTime.scss';
|
||||
|
||||
interface SuperscriptTimeProps {
|
||||
time: string;
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
}
|
||||
|
||||
export default function SuperscriptTime(props: SuperscriptTimeProps) {
|
||||
const { time, className, style } = props;
|
||||
|
||||
// we assume anything after space is a period tag
|
||||
const [timeString, period] = time.split(' ');
|
||||
|
||||
return (
|
||||
<div className={className} style={style}>
|
||||
{timeString}
|
||||
{period && <sup className='period'>{period}</sup>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -68,6 +68,7 @@
|
||||
font-size: clamp(32px, 3.5vw, 50px);
|
||||
color: var(--secondary-color-override, $viewer-secondary-color);
|
||||
letter-spacing: 0.05em;
|
||||
line-height: 0.95em;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,6 +136,7 @@
|
||||
font-size: clamp(32px, 3.5vw, 50px);
|
||||
color: var(--secondary-color-override, $viewer-secondary-color);
|
||||
letter-spacing: 0.05em;
|
||||
line-height: 0.95em;
|
||||
|
||||
&--delayed {
|
||||
color: $delay-color;
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet
|
||||
import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
||||
import { formatTime } from '../../../common/utils/time';
|
||||
import { useTranslation } from '../../../translation/TranslationProvider';
|
||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||
|
||||
import { fetchTimerData, TimerMessage } from './countdown.helpers';
|
||||
import CountdownSelect from './CountdownSelect';
|
||||
@@ -118,26 +119,27 @@ export default function Countdown(props: CountdownProps) {
|
||||
<div className='countdown-container' data-testid='countdown-event'>
|
||||
<div className='clock-container'>
|
||||
<div className='label'>{getLocalizedString('common.time_now')}</div>
|
||||
<div className='time'>{clock}</div>
|
||||
<SuperscriptTime time={clock} className='time' />
|
||||
</div>
|
||||
|
||||
{runningMessage !== TimerMessage.unhandled && (
|
||||
<div className='status'>{getLocalizedString(`countdown.${runningMessage}`)}</div>
|
||||
)}
|
||||
|
||||
<span className={`timer ${standby ? 'timer--paused' : ''} ${isRunningFinished ? 'timer--finished' : ''}`}>
|
||||
{formattedTimer}
|
||||
</span>
|
||||
<SuperscriptTime
|
||||
time={formattedTimer}
|
||||
className={`timer ${standby ? 'timer--paused' : ''} ${isRunningFinished ? 'timer--finished' : ''}`}
|
||||
/>
|
||||
<div className='title'>{follow?.title || 'Untitled Event'}</div>
|
||||
|
||||
<div className='timer-group'>
|
||||
<div className='aux-timers'>
|
||||
<div className='aux-timers__label'>{getLocalizedString('common.start_time')}</div>
|
||||
<span className={`aux-timers__value ${delayedTimerStyles}`}>{startTime}</span>
|
||||
<SuperscriptTime time={startTime} className={`aux-timers__value ${delayedTimerStyles}`} />
|
||||
</div>
|
||||
<div className='aux-timers'>
|
||||
<div className='aux-timers__label'>{getLocalizedString('common.end_time')}</div>
|
||||
<span className={`aux-timers__value ${delayedTimerStyles}`}>{endTime}</span>
|
||||
<SuperscriptTime time={endTime} className={`aux-timers__value ${delayedTimerStyles}`} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,10 @@ import { sanitiseTitle } from './countdown.helpers';
|
||||
|
||||
import './Countdown.scss';
|
||||
|
||||
const formatOptions = {
|
||||
format: 'hh:mm a',
|
||||
};
|
||||
|
||||
interface CountdownSelectProps {
|
||||
events: OntimeRundownEntry[];
|
||||
}
|
||||
@@ -31,8 +35,8 @@ export default function CountdownSelect(props: CountdownSelectProps) {
|
||||
filteredEvents.map((event: OntimeEvent, counter: number) => {
|
||||
const index = counter + 1;
|
||||
const title = sanitiseTitle(event.title);
|
||||
const start = formatTime(event.timeStart, { format: 'hh:mm' });
|
||||
const end = formatTime(event.timeEnd, { format: 'hh:mm' });
|
||||
const start = formatTime(event.timeStart, formatOptions);
|
||||
const end = formatTime(event.timeEnd, formatOptions);
|
||||
|
||||
return (
|
||||
<li key={event.id}>
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
font-size: clamp(32px, 3.5vw, 50px);
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.05em;
|
||||
line-height: 0.95em;
|
||||
}
|
||||
|
||||
.message {
|
||||
|
||||
@@ -16,6 +16,7 @@ import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
||||
import { formatTime } from '../../../common/utils/time';
|
||||
import { useTranslation } from '../../../translation/TranslationProvider';
|
||||
import { titleVariants } from '../common/animation';
|
||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||
|
||||
import './Public.scss';
|
||||
|
||||
@@ -63,7 +64,7 @@ export default function Public(props: BackstageProps) {
|
||||
{general.title}
|
||||
<div className='clock-container'>
|
||||
<div className='label'>{getLocalizedString('common.time_now')}</div>
|
||||
<div className='time'>{clock}</div>
|
||||
<SuperscriptTime time={clock} className='time' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ $half-hours: min(1.5vh, 10px);
|
||||
$size-min: min(2.5vh, 18px);
|
||||
$half-min: min(1.25vh, 9px);
|
||||
$red-active: #c53030;
|
||||
$red-idle: #300000;
|
||||
$red-idle: #000000;
|
||||
$cyan-active: #0ff;
|
||||
$cyan-idle: #0aa;
|
||||
|
||||
@@ -56,11 +56,10 @@ $cyan-idle: #0aa;
|
||||
.hours {
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
background: $red-idle;
|
||||
background: var(--studio-idle, $red-idle);
|
||||
|
||||
&--active {
|
||||
background: $red-active;
|
||||
box-shadow: 0 0 10px 2px rgba(255, 0, 0, 0.25);
|
||||
background: var(--studio-active, $red-active);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +79,7 @@ $cyan-idle: #0aa;
|
||||
}
|
||||
|
||||
.studio-timer {
|
||||
color: $red-active;
|
||||
color: var(--studio-active, $red-active);
|
||||
font-size: calc(#{$clock-size} / 3);
|
||||
margin-top: calc(50% - calc(#{$clock-size} / 7));
|
||||
line-height: 0.8em;
|
||||
@@ -88,9 +87,8 @@ $cyan-idle: #0aa;
|
||||
&--with-seconds {
|
||||
font-size: calc(#{$clock-size} / 4.6);
|
||||
margin-top: calc(50% - calc(#{$clock-size} / 11));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.next-title:after,
|
||||
@@ -100,14 +98,15 @@ $cyan-idle: #0aa;
|
||||
}
|
||||
|
||||
.next-title {
|
||||
color: $cyan-idle;
|
||||
color: var(--studio-idle-label, $cyan-idle);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.next-countdown {
|
||||
color: var(--studio-active-label, $cyan-active);
|
||||
|
||||
font-size: 10vh;
|
||||
line-height: 1em;
|
||||
color: $cyan-active;
|
||||
|
||||
&--overtime {
|
||||
color: darken($red-active, 10%);
|
||||
@@ -131,16 +130,16 @@ $cyan-idle: #0aa;
|
||||
padding-bottom: 2vh;
|
||||
font-size: 15vh;
|
||||
line-height: 0.9em;
|
||||
color: $red-active;
|
||||
color: var(--studio-active, $red-active);
|
||||
|
||||
&--idle {
|
||||
color: $red-idle;
|
||||
color: var(--studio-idle, $red-active);
|
||||
}
|
||||
}
|
||||
|
||||
.schedule {
|
||||
ul {
|
||||
color: $cyan-idle;
|
||||
color: var(--studio-idle-label, $cyan-idle);
|
||||
font-size: 3.75vh;
|
||||
line-height: 1em;
|
||||
list-style: none;
|
||||
@@ -154,18 +153,18 @@ $cyan-idle: #0aa;
|
||||
}
|
||||
|
||||
.now {
|
||||
color: $cyan-active;
|
||||
color: var(--studio-active-label, $cyan-active);
|
||||
}
|
||||
|
||||
.next {
|
||||
color: $red-active;
|
||||
color: var(--studio-active, $red-active);
|
||||
}
|
||||
|
||||
.user-colour {
|
||||
width: 0.35em;
|
||||
height: 0.35em;
|
||||
aspect-ratio: 1;
|
||||
background-color: $red-idle;
|
||||
background-color: var(--studio-idle, $red-idle);
|
||||
margin-right: 0.35em;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
font-size: clamp(32px, 3.5vw, 50px);
|
||||
color: var(--secondary-color-override, $viewer-secondary-color);
|
||||
letter-spacing: 0.05em;
|
||||
line-height: 0.95em;
|
||||
}
|
||||
|
||||
&--hidden {
|
||||
@@ -115,11 +116,11 @@
|
||||
opacity: 1;
|
||||
transition: $viewer-transition-time;
|
||||
|
||||
&--paused {
|
||||
opacity: $viewer-opacity-disabled;
|
||||
transition: $viewer-transition-time;
|
||||
&--paused {
|
||||
opacity: $viewer-opacity-disabled;
|
||||
transition: $viewer-transition-time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* =================== OVERLAY ===================*/
|
||||
|
||||
@@ -12,6 +12,7 @@ import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet
|
||||
import { TimeManagerType } from '../../../common/models/TimeManager.type';
|
||||
import { formatTime } from '../../../common/utils/time';
|
||||
import { useTranslation } from '../../../translation/TranslationProvider';
|
||||
import SuperscriptTime from '../common/superscript-time/SuperscriptTime';
|
||||
import { formatTimerDisplay, getTimerByType } from '../common/viewerUtils';
|
||||
|
||||
import './Timer.scss';
|
||||
@@ -106,7 +107,7 @@ export default function Timer(props: TimerProps) {
|
||||
|
||||
<div className={`clock-container ${showClock ? '' : 'clock-container--hidden'}`}>
|
||||
<div className='label'>{getLocalizedString('common.time_now')}</div>
|
||||
<div className='clock'>{clock}</div>
|
||||
<SuperscriptTime time={clock} className='clock' />
|
||||
</div>
|
||||
|
||||
<div className={`timer-container ${showBlinking ? (showOverlay ? '' : 'blink') : ''}`}>
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
|
||||
--operator-running-bg-override: #D20300;
|
||||
--operator-highlight-override: #FFAB33;
|
||||
|
||||
--studio-active: #101010;
|
||||
--studio-idle: #cfcfcf;
|
||||
--studio-active-label: #101010;
|
||||
--studio-idle-label: #595959;
|
||||
}
|
||||
|
||||
.timer {
|
||||
|
||||
Reference in New Issue
Block a user