feat: allow editing field from operator (#609)

* feat: allow editing field from operator

Co-authored-by: arc-alex <ac@omnivox.dk>

* style: functional and presentation tweaks
---------

Co-authored-by: arc-alex <ac@omnivox.dk>
This commit is contained in:
Carlos Valente
2023-11-24 12:04:22 +01:00
committed by GitHub
parent bdd216d881
commit bf8ebe942e
6 changed files with 234 additions and 9 deletions
+46 -7
View File
@@ -1,4 +1,4 @@
import { useEffect, useRef, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { isOntimeEvent, OntimeEvent, SupportedEvent, UserFields } from 'ontime-types';
import { getFirstEvent, getLastEvent } from 'ontime-utils';
@@ -15,6 +15,7 @@ import useUserFields from '../../common/hooks-query/useUserFields';
import { debounce } from '../../common/utils/debounce';
import { isStringBoolean } from '../../common/utils/viewUtils';
import EditModal from './edit-modal/EditModal';
import FollowButton from './follow-button/FollowButton';
import OperatorBlock from './operator-block/OperatorBlock';
import OperatorEvent from './operator-event/OperatorEvent';
@@ -25,14 +26,24 @@ import style from './Operator.module.scss';
const selectedOffset = 50;
type TitleFields = Pick<OntimeEvent, 'title' | 'subtitle' | 'presenter'>;
export type EditEvent = Pick<OntimeEvent, 'id' | 'cue'> & { fieldLabel?: string; fieldValue: string };
export type PartialEdit = EditEvent & {
field: keyof UserFields;
};
export default function Operator() {
const { data, status } = useRundown();
const { data: userFields, status: userFieldsStatus } = useUserFields();
const { data: projectData, status: projectDataStatus } = useProjectData();
const timeoutId = useRef<NodeJS.Timeout | null>(null);
const featureData = useOperator();
const [searchParams] = useSearchParams();
const [showEditPrompt, setShowEditPrompt] = useState(false);
const [editEvent, setEditEvent] = useState<PartialEdit | null>(null);
const [lockAutoScroll, setLockAutoScroll] = useState(false);
const selectedRef = useRef<HTMLDivElement | null>(null);
const scrollRef = useRef<HTMLDivElement | null>(null);
@@ -78,6 +89,30 @@ export default function Operator() {
};
const debouncedHandleScroll = debounce(handleUserScroll, 1000);
const handleScroll = () => {
if (timeoutId.current) {
clearTimeout(timeoutId.current);
}
timeoutId.current = setTimeout(() => {
setShowEditPrompt(false);
}, 700);
setShowEditPrompt(true);
debouncedHandleScroll();
};
const handleEdit = useCallback(
(event: EditEvent) => {
const field = searchParams.get('subscribe') as keyof UserFields | null;
if (field) {
setEditEvent({ ...event, field });
}
},
[searchParams],
);
const missingData = !data || !userFields || !projectData;
const isLoading = status === 'pending' || userFieldsStatus === 'pending' || projectDataStatus === 'pending';
@@ -103,6 +138,7 @@ export default function Operator() {
<div className={style.operatorContainer}>
<NavigationMenu />
<ViewParamsEditor paramFields={operatorOptions} />
{editEvent && <EditModal event={editEvent} onClose={() => setEditEvent(null)} />}
<StatusBar
projectTitle={projectData.title}
@@ -114,12 +150,13 @@ export default function Operator() {
lastId={lastEvent?.id}
/>
<div
className={style.operatorEvents}
onWheel={debouncedHandleScroll}
onTouchMove={debouncedHandleScroll}
ref={scrollRef}
>
{subscribe && (
<div className={`${style.editPrompt} ${showEditPrompt ? style.show : undefined}`}>
Press and hold to edit user field
</div>
)}
<div className={style.operatorEvents} onWheel={handleScroll} onTouchMove={handleScroll} ref={scrollRef}>
{data.map((entry) => {
if (isOntimeEvent(entry)) {
const isSelected = featureData.selectedEventId === entry.id;
@@ -139,6 +176,7 @@ export default function Operator() {
return (
<OperatorEvent
key={entry.id}
id={entry.id}
colour={entry.colour}
cue={entry.cue}
main={mainField}
@@ -153,6 +191,7 @@ export default function Operator() {
showSeconds={showSeconds}
isPast={isPast}
selectedRef={isSelected ? selectedRef : undefined}
onLongPress={subscribe ? handleEdit : () => undefined}
/>
);
}