mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-12 02:43:50 +00:00
refactor: unify progress bar logic
This commit is contained in:
committed by
Carlos Valente
parent
c3fb3061f6
commit
347f333b3e
@@ -1,12 +1,12 @@
|
||||
import { MaybeNumber } from 'ontime-types';
|
||||
|
||||
import { clamp } from '../../utils/math';
|
||||
import { getProgress } from '../../utils/getProgress';
|
||||
|
||||
import './MultiPartProgressBar.scss';
|
||||
|
||||
interface MultiPartProgressBar {
|
||||
now: MaybeNumber;
|
||||
complete: number;
|
||||
complete: MaybeNumber;
|
||||
normalColor: string;
|
||||
warning?: MaybeNumber;
|
||||
warningColor: string;
|
||||
@@ -31,10 +31,9 @@ export default function MultiPartProgressBar(props: MultiPartProgressBar) {
|
||||
className = '',
|
||||
} = props;
|
||||
|
||||
const percentRemaining = complete === 0 ? 0 : 100 - clamp(100 - (Math.max(now ?? 0, 0) * 100) / complete, 0, 100);
|
||||
|
||||
const dangerWidth = danger ? clamp((danger / complete) * 100, 0, 100) : 0;
|
||||
const warningWidth = warning ? clamp((warning / complete) * 100 - dangerWidth, 0, 100) : 0;
|
||||
const percentRemaining = 100 - getProgress(now, complete);
|
||||
const dangerWidth = danger ? 100 - getProgress(danger, complete) : 0;
|
||||
const warningWidth = warning ? 100 - dangerWidth - getProgress(warning, complete) : 0;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
import { clamp } from '../../utils/math';
|
||||
import { MaybeNumber } from 'ontime-types';
|
||||
|
||||
import { getProgress } from '../../utils/getProgress';
|
||||
|
||||
import './ProgressBar.scss';
|
||||
|
||||
interface ProgressBarProps {
|
||||
now?: number;
|
||||
complete?: number;
|
||||
current: MaybeNumber;
|
||||
duration: MaybeNumber;
|
||||
hidden?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function ProgressBar(props: ProgressBarProps) {
|
||||
const { now = 0, complete = 100, hidden, className = '' } = props;
|
||||
|
||||
const percentComplete = clamp(100 - (Math.max(now, 0) * 100) / complete, 0, 100);
|
||||
const { current, duration, hidden, className = '' } = props;
|
||||
const progress = getProgress(current, duration);
|
||||
|
||||
return (
|
||||
<div className={`progress-bar__bg ${hidden ? 'progress-bar__bg--hidden' : ''} ${className}`}>
|
||||
<div className='progress-bar__indicator' style={{ width: `${percentComplete}%` }} />
|
||||
<div className='progress-bar__indicator' style={{ width: `${progress}%` }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -150,7 +150,6 @@ export const useClock = () => {
|
||||
/** Used by the progress bar components */
|
||||
export const useProgressData = () => {
|
||||
const featureSelector = (state: RuntimeStore) => ({
|
||||
addedTime: state.timer.addedTime,
|
||||
current: state.timer.current,
|
||||
duration: state.timer.duration,
|
||||
timeWarning: state.eventNow?.timeWarning ?? null,
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { MaybeNumber } from 'ontime-types';
|
||||
|
||||
import { clamp } from './math';
|
||||
|
||||
/**
|
||||
* Returns completion percentage of a progress bar
|
||||
* This code assumes the current time and duration have addedTime already applied
|
||||
*/
|
||||
export function getProgress(current: MaybeNumber, duration: MaybeNumber) {
|
||||
if (current === null || duration === null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (current <= 0) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
if (current >= duration) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return clamp(((duration - current) / duration) * 100, 0, 100);
|
||||
}
|
||||
@@ -6,18 +6,17 @@ import styles from './CuesheetProgress.module.scss';
|
||||
|
||||
export default function CuesheetProgress() {
|
||||
const { data } = useViewSettings();
|
||||
const { addedTime, current, duration, timeWarning, timeDanger } = useProgressData();
|
||||
const totalTime = (duration ?? 0) + (addedTime ?? 0);
|
||||
const { current, duration, timeWarning, timeDanger } = useProgressData();
|
||||
|
||||
return (
|
||||
<MultiPartProgressBar
|
||||
now={current}
|
||||
complete={totalTime}
|
||||
normalColor={data!.normalColor}
|
||||
complete={duration}
|
||||
normalColor={data.normalColor}
|
||||
warning={timeWarning}
|
||||
warningColor={data!.warningColor}
|
||||
warningColor={data.warningColor}
|
||||
danger={timeDanger}
|
||||
dangerColor={data!.dangerColor}
|
||||
dangerColor={data.dangerColor}
|
||||
className={styles.progressOverride}
|
||||
ignoreCssOverride
|
||||
/>
|
||||
|
||||
@@ -11,13 +11,12 @@ interface StatusBarProgressProps {
|
||||
|
||||
export default function StatusBarProgress(props: StatusBarProgressProps) {
|
||||
const { viewSettings } = props;
|
||||
const { addedTime, current, duration, timeWarning, timeDanger } = useProgressData();
|
||||
const totalTime = (duration ?? 0) + (addedTime ?? 0);
|
||||
const { current, duration, timeWarning, timeDanger } = useProgressData();
|
||||
|
||||
return (
|
||||
<MultiPartProgressBar
|
||||
now={current}
|
||||
complete={totalTime}
|
||||
complete={duration}
|
||||
normalColor={viewSettings.normalColor}
|
||||
warning={timeWarning}
|
||||
warningColor={viewSettings.warningColor}
|
||||
|
||||
@@ -1,29 +1,12 @@
|
||||
import { MaybeNumber } from 'ontime-types';
|
||||
|
||||
import { useTimer } from '../../../../common/hooks/useSocket';
|
||||
import { clamp } from '../../../../common/utils/math';
|
||||
import { getProgress } from '../../../../common/utils/getProgress';
|
||||
|
||||
import style from './EventBlockProgressBar.module.scss';
|
||||
|
||||
export function getPercentComplete(remaining: MaybeNumber, total: MaybeNumber): number {
|
||||
if (remaining === null || total === null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (remaining <= 0) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
if (remaining === total) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return clamp(100 - (remaining * 100) / total, 0, 100);
|
||||
}
|
||||
|
||||
export default function EventBlockProgressBar() {
|
||||
const timer = useTimer();
|
||||
|
||||
const progress = `${getPercentComplete(timer.current, timer.duration)}%`;
|
||||
return <div className={style.progressBar} style={{ width: progress }} />;
|
||||
const progress = getProgress(timer.current, timer.duration);
|
||||
|
||||
return <div className={style.progressBar} style={{ width: `${progress}%` }} />;
|
||||
}
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
import { dayInMs } from 'ontime-utils';
|
||||
|
||||
import { getPercentComplete } from '../EventBlockProgressBar';
|
||||
|
||||
describe('getPercentComplete()', () => {
|
||||
describe('calculates progress in normal cases', () => {
|
||||
const testScenarios = [
|
||||
{ current: 0, duration: 0, expect: 100 },
|
||||
{ current: 0, duration: 100, expect: 100 },
|
||||
{ current: 0, duration: dayInMs, expect: 100 },
|
||||
{ current: 10, duration: 100, expect: 90 },
|
||||
{ current: 50, duration: 100, expect: 50 },
|
||||
{ current: 100, duration: 100, expect: 0 },
|
||||
];
|
||||
|
||||
testScenarios.forEach((testCase) => {
|
||||
it(`handles ${testCase.current} / ${testCase.duration}`, () => {
|
||||
const progress = getPercentComplete(testCase.current, testCase.duration);
|
||||
expect(progress).toBe(testCase.expect);
|
||||
});
|
||||
});
|
||||
});
|
||||
it('is 0 if we dont have a current or duration', () => {
|
||||
const progress = getPercentComplete(null, null);
|
||||
expect(progress).toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -94,7 +94,6 @@ export default function Backstage(props: BackstageProps) {
|
||||
let stageTimer = millisToString(time.current, { fallback: timerPlaceholderMin });
|
||||
stageTimer = removeLeadingZero(stageTimer);
|
||||
|
||||
const totalTime = (time.duration ?? 0) + (time.addedTime ?? 0);
|
||||
const defaultFormat = getDefaultFormat(settings?.timeFormat);
|
||||
const backstageOptions = getBackstageOptions(defaultFormat, customFields);
|
||||
|
||||
@@ -111,8 +110,8 @@ export default function Backstage(props: BackstageProps) {
|
||||
|
||||
<ProgressBar
|
||||
className='progress-container'
|
||||
now={time.current ?? undefined}
|
||||
complete={totalTime}
|
||||
current={time.current}
|
||||
duration={time.duration}
|
||||
hidden={!showProgress}
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user