mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-13 11:23:50 +00:00
refactor: allow submitting same value
This commit is contained in:
committed by
Carlos Valente
parent
b173b5a8e8
commit
b38a7e5c92
@@ -16,6 +16,7 @@ export default function useReactiveTextInput(
|
||||
submitOnEnter?: boolean;
|
||||
submitOnCtrlEnter?: boolean;
|
||||
onCancelUpdate?: () => void;
|
||||
allowSubmitSameValue?: boolean;
|
||||
},
|
||||
): UseReactiveTextInputReturn {
|
||||
const [text, setText] = useState<string>(initialText);
|
||||
@@ -48,7 +49,7 @@ export default function useReactiveTextInput(
|
||||
const handleSubmit = useCallback(
|
||||
(valueToSubmit: string) => {
|
||||
// No need to update if it hasn't changed
|
||||
if (valueToSubmit === initialText) {
|
||||
if (valueToSubmit === initialText && !options?.allowSubmitSameValue) {
|
||||
options?.onCancelUpdate?.();
|
||||
} else {
|
||||
const cleanVal = valueToSubmit.trim();
|
||||
|
||||
@@ -225,38 +225,32 @@ export const useEventAction = () => {
|
||||
*/
|
||||
const updateTimer = useCallback(
|
||||
async (eventId: string, field: TimeField, value: string, lockOnUpdate?: boolean) => {
|
||||
let newValMillis = 0;
|
||||
|
||||
// check for previous keyword
|
||||
if (value === 'p' || value === 'prev' || value === 'previous') {
|
||||
newValMillis = getPreviousEnd();
|
||||
|
||||
// check for adding time keyword
|
||||
} else if (value.startsWith('+') || value.startsWith('p+') || value.startsWith('p +')) {
|
||||
// TODO: is this logic solid?
|
||||
const remainingString = value.substring(1);
|
||||
newValMillis = getPreviousEnd() + parseUserTime(remainingString);
|
||||
} else {
|
||||
newValMillis = parseUserTime(value);
|
||||
// an empty value with no lock has no domain validity
|
||||
if (!lockOnUpdate && value === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
// dont allow timer values over 23:59:59
|
||||
const cappedMillis = Math.min(newValMillis, dayInMs - MILLIS_PER_SECOND);
|
||||
const newEvent = {
|
||||
const newEvent: Partial<OntimeEvent> = {
|
||||
id: eventId,
|
||||
[field]: cappedMillis,
|
||||
};
|
||||
|
||||
// check if we should lock the field
|
||||
if (lockOnUpdate) {
|
||||
if (field === 'timeEnd') {
|
||||
newEvent.timeStrategy = TimeStrategy.LockEnd;
|
||||
// an empty value indicates that we should unlock the field
|
||||
newEvent.timeStrategy = value === '' ? TimeStrategy.LockDuration : TimeStrategy.LockEnd;
|
||||
newEvent.timeEnd = value === '' ? undefined : calculateNewValue();
|
||||
} else if (field === 'duration') {
|
||||
newEvent.timeStrategy = TimeStrategy.LockDuration;
|
||||
} else if (field === 'timeStart' && value === '') {
|
||||
// if user removes the time start, we should link to the previous
|
||||
newEvent.linkStart = 'true';
|
||||
// an empty value indicates that we should unlock the field
|
||||
newEvent.timeStrategy = value === '' ? TimeStrategy.LockEnd : TimeStrategy.LockDuration;
|
||||
newEvent.duration = value === '' ? undefined : calculateNewValue();
|
||||
} else if (field === 'timeStart') {
|
||||
// an empty values means we should link to the previous
|
||||
newEvent.linkStart = value === '' ? 'true' : null;
|
||||
newEvent.timeStart = value === '' ? undefined : calculateNewValue();
|
||||
}
|
||||
} else {
|
||||
newEvent[field] = calculateNewValue();
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -265,6 +259,31 @@ export const useEventAction = () => {
|
||||
logAxiosError('Error updating event', error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to calculate the new time value
|
||||
*/
|
||||
function calculateNewValue(): number {
|
||||
let newValMillis = 0;
|
||||
|
||||
// check for previous keyword
|
||||
if (value === 'p' || value === 'prev' || value === 'previous') {
|
||||
newValMillis = getPreviousEnd();
|
||||
|
||||
// check for adding time keyword
|
||||
} else if (value.startsWith('+') || value.startsWith('p+') || value.startsWith('p +')) {
|
||||
// TODO: is this logic solid?
|
||||
const remainingString = value.substring(1);
|
||||
newValMillis = getPreviousEnd() + parseUserTime(remainingString);
|
||||
} else {
|
||||
newValMillis = parseUserTime(value);
|
||||
}
|
||||
// dont allow timer values over 23:59:59
|
||||
return Math.min(newValMillis, dayInMs - MILLIS_PER_SECOND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to get the previous event end time
|
||||
*/
|
||||
function getPreviousEnd(): number {
|
||||
const cachedRundown = queryClient.getQueryData<RundownCached>(RUNDOWN);
|
||||
|
||||
|
||||
+3
-1
@@ -5,16 +5,18 @@ import useReactiveTextInput from '../../../../common/components/input/text-input
|
||||
|
||||
interface SingleLineCellProps {
|
||||
initialValue: string;
|
||||
allowSubmitSameValue?: boolean;
|
||||
handleUpdate: (newValue: string) => void;
|
||||
handleCancelUpdate?: () => void;
|
||||
}
|
||||
|
||||
const SingleLineCell = forwardRef((props: SingleLineCellProps, inputRef) => {
|
||||
const { initialValue, handleUpdate, handleCancelUpdate } = props;
|
||||
const { initialValue, allowSubmitSameValue, handleUpdate, handleCancelUpdate } = props;
|
||||
const ref = useRef<HTMLInputElement | null>(null);
|
||||
const submitCallback = useCallback((newValue: string) => handleUpdate(newValue), [handleUpdate]);
|
||||
|
||||
const { value, onChange, onBlur, onKeyDown } = useReactiveTextInput(initialValue, submitCallback, ref, {
|
||||
allowSubmitSameValue,
|
||||
submitOnEnter: true, // single line should submit on enter
|
||||
submitOnCtrlEnter: true,
|
||||
onCancelUpdate: handleCancelUpdate,
|
||||
|
||||
+6
-3
@@ -41,8 +41,9 @@ export default function TimeInputDuration(props: TimeInputDurationProps) {
|
||||
(newValue: string) => {
|
||||
setIsEditing(false);
|
||||
|
||||
// Check if there is anything there
|
||||
// if the user sends an empty string, we want to clear the value
|
||||
if (newValue === '') {
|
||||
onSubmit(newValue);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -59,14 +60,15 @@ export default function TimeInputDuration(props: TimeInputDurationProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (valueInMillis === initialValue) {
|
||||
// if the value is the same, we may still want to push the lock change
|
||||
if (valueInMillis === initialValue && lockedValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
onSubmit(newValue);
|
||||
setValue(Number(newValue));
|
||||
},
|
||||
[initialValue, onSubmit],
|
||||
[initialValue, lockedValue, onSubmit],
|
||||
);
|
||||
|
||||
// duration times have a special format
|
||||
@@ -77,6 +79,7 @@ export default function TimeInputDuration(props: TimeInputDurationProps) {
|
||||
<SingleLineCell
|
||||
ref={inputRef}
|
||||
initialValue={timeString}
|
||||
allowSubmitSameValue={!lockedValue} // if the value is not locked, submitting will lock the value
|
||||
handleUpdate={handleUpdate}
|
||||
handleCancelUpdate={handleFakeBlur}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user