mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-17 13:23:35 +00:00
refactor: cuesheet time format (#1634)
This commit is contained in:
committed by
Carlos Valente
parent
fb9fdf6a38
commit
c8c2a05724
+108
@@ -0,0 +1,108 @@
|
|||||||
|
import { memo, PropsWithChildren, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
import { millisToString, parseUserTime } from 'ontime-utils';
|
||||||
|
|
||||||
|
import SingleLineCell from './SingleLineCell';
|
||||||
|
import TextLikeInput from './TextLikeInput';
|
||||||
|
|
||||||
|
interface DurationInputProps {
|
||||||
|
initialValue: number;
|
||||||
|
lockedValue: boolean;
|
||||||
|
delayed?: boolean;
|
||||||
|
onSubmit: (value: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ParentFocusableInput extends HTMLInputElement {
|
||||||
|
focusParentElement: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(DurationInput);
|
||||||
|
|
||||||
|
function DurationInput(props: PropsWithChildren<DurationInputProps>) {
|
||||||
|
const { initialValue, lockedValue, delayed, onSubmit, children } = props;
|
||||||
|
|
||||||
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
|
const [value, setValue] = useState(initialValue);
|
||||||
|
const inputRef = useRef<ParentFocusableInput>(null);
|
||||||
|
const textRef = useRef<ParentFocusableInput>(null);
|
||||||
|
|
||||||
|
// when we go into edit mode, set focus to the input
|
||||||
|
useEffect(() => {
|
||||||
|
if (isEditing && inputRef.current) {
|
||||||
|
inputRef.current.focus();
|
||||||
|
inputRef.current.select();
|
||||||
|
}
|
||||||
|
}, [isEditing]);
|
||||||
|
|
||||||
|
// reset value when initialValue changes, avoiding interrupting the user if we are in edit mode
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isEditing) {
|
||||||
|
setValue(initialValue);
|
||||||
|
}
|
||||||
|
}, [initialValue, isEditing]);
|
||||||
|
|
||||||
|
const handleFakeFocus = () => setIsEditing(true);
|
||||||
|
const handleFakeBlur = () => {
|
||||||
|
setIsEditing(false);
|
||||||
|
setTimeout(() => textRef.current?.focusParentElement()); // Immediate timeout to ensure state change takes place first
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpdate = useCallback(
|
||||||
|
(newValue: string) => {
|
||||||
|
setIsEditing(false);
|
||||||
|
|
||||||
|
// if the user sends an empty string, we want to clear the value
|
||||||
|
if (newValue === '') {
|
||||||
|
onSubmit(newValue);
|
||||||
|
inputRef.current?.focusParentElement();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we dont know the values in the rundown, escalate to handler
|
||||||
|
if (newValue.startsWith('p') || newValue.startsWith('+')) {
|
||||||
|
onSubmit(newValue);
|
||||||
|
inputRef.current?.focusParentElement();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const valueInMillis = parseUserTime(newValue);
|
||||||
|
if (valueInMillis < 0 || isNaN(valueInMillis)) {
|
||||||
|
setValue(initialValue);
|
||||||
|
setTimeout(() => textRef.current?.focusParentElement()); // Immediate timeout to ensure state change takes place first
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the value is the same, we may still want to push the lock change
|
||||||
|
if (valueInMillis === initialValue && lockedValue) {
|
||||||
|
inputRef.current?.focusParentElement();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit(newValue);
|
||||||
|
setValue(Number(newValue));
|
||||||
|
setTimeout(() => textRef.current?.focusParentElement()); // Immediate timeout to ensure state change takes place first
|
||||||
|
},
|
||||||
|
[initialValue, lockedValue, onSubmit],
|
||||||
|
);
|
||||||
|
|
||||||
|
const timeString = millisToString(value);
|
||||||
|
|
||||||
|
return isEditing ? (
|
||||||
|
<SingleLineCell
|
||||||
|
ref={inputRef}
|
||||||
|
initialValue={timeString}
|
||||||
|
allowSubmitSameValue={!lockedValue} // if the value is not locked, submitting will lock the value
|
||||||
|
handleUpdate={handleUpdate}
|
||||||
|
handleCancelUpdate={handleFakeBlur}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<TextLikeInput
|
||||||
|
onClick={handleFakeFocus}
|
||||||
|
onFocus={handleFakeFocus}
|
||||||
|
muted={!lockedValue}
|
||||||
|
delayed={delayed}
|
||||||
|
ref={textRef}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</TextLikeInput>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import { memo, PropsWithChildren, useCallback, useEffect, useRef, useState } from 'react';
|
import { memo, PropsWithChildren, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { millisToString, parseUserTime } from 'ontime-utils';
|
import { parseUserTime } from 'ontime-utils';
|
||||||
|
|
||||||
|
import { formatTime } from '../../../../common/utils/time';
|
||||||
|
|
||||||
import SingleLineCell from './SingleLineCell';
|
import SingleLineCell from './SingleLineCell';
|
||||||
import TextLikeInput from './TextLikeInput';
|
import TextLikeInput from './TextLikeInput';
|
||||||
@@ -84,7 +86,7 @@ function TimeInputDuration(props: PropsWithChildren<TimeInputDurationProps>) {
|
|||||||
[initialValue, lockedValue, onSubmit],
|
[initialValue, lockedValue, onSubmit],
|
||||||
);
|
);
|
||||||
|
|
||||||
const timeString = millisToString(value);
|
const timeString = formatTime(value);
|
||||||
|
|
||||||
return isEditing ? (
|
return isEditing ? (
|
||||||
<SingleLineCell
|
<SingleLineCell
|
||||||
|
|||||||
+11
-12
@@ -1,11 +1,12 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { CellContext, ColumnDef } from '@tanstack/react-table';
|
import { CellContext, ColumnDef } from '@tanstack/react-table';
|
||||||
import { CustomFields, isOntimeEvent, OntimeEntry, OntimeEvent, TimeStrategy } from 'ontime-types';
|
import { CustomFields, isOntimeEvent, OntimeEntry, OntimeEvent, TimeStrategy } from 'ontime-types';
|
||||||
import { millisToString, removeSeconds } from 'ontime-utils';
|
import { millisToString } from 'ontime-utils';
|
||||||
|
|
||||||
import DelayIndicator from '../../../../common/components/delay-indicator/DelayIndicator';
|
import DelayIndicator from '../../../../common/components/delay-indicator/DelayIndicator';
|
||||||
import { formatDuration } from '../../../../common/utils/time';
|
import { formatDuration, formatTime } from '../../../../common/utils/time';
|
||||||
|
|
||||||
|
import DurationInput from './DurationInput';
|
||||||
import EditableImage from './EditableImage';
|
import EditableImage from './EditableImage';
|
||||||
import MultiLineCell from './MultiLineCell';
|
import MultiLineCell from './MultiLineCell';
|
||||||
import SingleLineCell from './SingleLineCell';
|
import SingleLineCell from './SingleLineCell';
|
||||||
@@ -26,10 +27,9 @@ function MakeStart({ getValue, row, table }: CellContext<OntimeEntry, unknown>)
|
|||||||
const delayValue = (row.original as OntimeEvent)?.delay ?? 0;
|
const delayValue = (row.original as OntimeEvent)?.delay ?? 0;
|
||||||
|
|
||||||
const displayTime = showDelayedTimes ? startTime + delayValue : startTime;
|
const displayTime = showDelayedTimes ? startTime + delayValue : startTime;
|
||||||
let formattedTime = millisToString(displayTime);
|
|
||||||
if (hideTableSeconds) {
|
const formatOpts = hideTableSeconds ? { format12: 'hh:mm a', format24: 'HH:mm' } : undefined;
|
||||||
formattedTime = removeSeconds(formattedTime);
|
const formattedTime = formatTime(displayTime, formatOpts);
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TimeInput initialValue={startTime} onSubmit={update} lockedValue={isStartLocked} delayed={delayValue !== 0}>
|
<TimeInput initialValue={startTime} onSubmit={update} lockedValue={isStartLocked} delayed={delayValue !== 0}>
|
||||||
@@ -54,10 +54,9 @@ function MakeEnd({ getValue, row, table }: CellContext<OntimeEntry, unknown>) {
|
|||||||
const delayValue = (row.original as OntimeEvent)?.delay ?? 0;
|
const delayValue = (row.original as OntimeEvent)?.delay ?? 0;
|
||||||
|
|
||||||
const displayTime = showDelayedTimes ? endTime + delayValue : endTime;
|
const displayTime = showDelayedTimes ? endTime + delayValue : endTime;
|
||||||
let formattedTime = millisToString(displayTime);
|
|
||||||
if (hideTableSeconds) {
|
const formatOpts = hideTableSeconds ? { format12: 'hh:mm a', format24: 'HH:mm' } : undefined;
|
||||||
formattedTime = removeSeconds(formattedTime);
|
const formattedTime = formatTime(displayTime, formatOpts);
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TimeInput initialValue={endTime} onSubmit={update} lockedValue={isEndLocked} delayed={delayValue !== 0}>
|
<TimeInput initialValue={endTime} onSubmit={update} lockedValue={isEndLocked} delayed={delayValue !== 0}>
|
||||||
@@ -81,9 +80,9 @@ function MakeDuration({ getValue, row, table }: CellContext<OntimeEntry, unknown
|
|||||||
const formattedDuration = formatDuration(duration, false);
|
const formattedDuration = formatDuration(duration, false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TimeInput initialValue={duration} onSubmit={update} lockedValue={isDurationLocked}>
|
<DurationInput initialValue={duration} onSubmit={update} lockedValue={isDurationLocked}>
|
||||||
{formattedDuration}
|
{formattedDuration}
|
||||||
</TimeInput>
|
</DurationInput>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user