mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-22 07:29:08 +00:00
feat: add link to context menu
This commit is contained in:
committed by
Carlos Valente
parent
46e9fcb3cb
commit
5501f57b45
@@ -1,15 +1,7 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import { isOntimeEvent, MaybeString, OntimeEvent, OntimeRundownEntry, RundownCached } from 'ontime-types';
|
import { isOntimeEvent, OntimeEvent, OntimeRundownEntry, RundownCached } from 'ontime-types';
|
||||||
import {
|
import { dayInMs, MILLIS_PER_SECOND, parseUserTime, reorderArray, swapEventData } from 'ontime-utils';
|
||||||
dayInMs,
|
|
||||||
getLinkedTimes,
|
|
||||||
getPreviousEventNormal,
|
|
||||||
MILLIS_PER_SECOND,
|
|
||||||
parseUserTime,
|
|
||||||
reorderArray,
|
|
||||||
swapEventData,
|
|
||||||
} from 'ontime-utils';
|
|
||||||
|
|
||||||
import { RUNDOWN } from '../api/constants';
|
import { RUNDOWN } from '../api/constants';
|
||||||
import {
|
import {
|
||||||
@@ -270,44 +262,6 @@ export const useEventAction = () => {
|
|||||||
[_updateEventMutation, queryClient],
|
[_updateEventMutation, queryClient],
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggles link of an event to the previous
|
|
||||||
*/
|
|
||||||
const linkTimer = useCallback(
|
|
||||||
async (eventId: string, linkStart: MaybeString) => {
|
|
||||||
let newEvent: Partial<OntimeEvent> = { id: eventId };
|
|
||||||
|
|
||||||
if (!linkStart) {
|
|
||||||
newEvent.linkStart = null;
|
|
||||||
} else {
|
|
||||||
const cachedRundown = queryClient.getQueryData<RundownCached>(RUNDOWN);
|
|
||||||
if (!cachedRundown) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const currentEvent = cachedRundown.rundown[eventId] as OntimeEvent;
|
|
||||||
if (!isOntimeEvent(currentEvent)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { previousEvent } = getPreviousEventNormal(cachedRundown.rundown, cachedRundown.order, eventId);
|
|
||||||
|
|
||||||
if (!previousEvent) {
|
|
||||||
newEvent.linkStart = null;
|
|
||||||
} else {
|
|
||||||
newEvent.linkStart = previousEvent.id;
|
|
||||||
const timePatch = getLinkedTimes(currentEvent, previousEvent);
|
|
||||||
newEvent = { ...newEvent, ...timePatch };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await _updateEventMutation.mutateAsync(newEvent);
|
|
||||||
} catch (error) {
|
|
||||||
logAxiosError('Error updating event', error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[_updateEventMutation, queryClient],
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls mutation to edit multiple events
|
* Calls mutation to edit multiple events
|
||||||
* @private
|
* @private
|
||||||
@@ -614,7 +568,6 @@ export const useEventAction = () => {
|
|||||||
batchUpdateEvents,
|
batchUpdateEvents,
|
||||||
deleteEvent,
|
deleteEvent,
|
||||||
deleteAllEvents,
|
deleteAllEvents,
|
||||||
linkTimer,
|
|
||||||
reorderEvent,
|
reorderEvent,
|
||||||
swapEvents,
|
swapEvents,
|
||||||
updateEvent,
|
updateEvent,
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ import { useSortable } from '@dnd-kit/sortable';
|
|||||||
import { CSS } from '@dnd-kit/utilities';
|
import { CSS } from '@dnd-kit/utilities';
|
||||||
import { IoAdd } from '@react-icons/all-files/io5/IoAdd';
|
import { IoAdd } from '@react-icons/all-files/io5/IoAdd';
|
||||||
import { IoDuplicateOutline } from '@react-icons/all-files/io5/IoDuplicateOutline';
|
import { IoDuplicateOutline } from '@react-icons/all-files/io5/IoDuplicateOutline';
|
||||||
|
import { IoLink } from '@react-icons/all-files/io5/IoLink';
|
||||||
import { IoPeople } from '@react-icons/all-files/io5/IoPeople';
|
import { IoPeople } from '@react-icons/all-files/io5/IoPeople';
|
||||||
import { IoPeopleOutline } from '@react-icons/all-files/io5/IoPeopleOutline';
|
import { IoPeopleOutline } from '@react-icons/all-files/io5/IoPeopleOutline';
|
||||||
import { IoReorderTwo } from '@react-icons/all-files/io5/IoReorderTwo';
|
import { IoReorderTwo } from '@react-icons/all-files/io5/IoReorderTwo';
|
||||||
import { IoSwapVertical } from '@react-icons/all-files/io5/IoSwapVertical';
|
import { IoSwapVertical } from '@react-icons/all-files/io5/IoSwapVertical';
|
||||||
import { IoTrash } from '@react-icons/all-files/io5/IoTrash';
|
import { IoTrash } from '@react-icons/all-files/io5/IoTrash';
|
||||||
|
import { IoUnlink } from '@react-icons/all-files/io5/IoUnlink';
|
||||||
import { EndAction, MaybeString, OntimeEvent, Playback, TimerType, TimeStrategy } from 'ontime-types';
|
import { EndAction, MaybeString, OntimeEvent, Playback, TimerType, TimeStrategy } from 'ontime-types';
|
||||||
|
|
||||||
import { useContextMenu } from '../../../common/hooks/useContextMenu';
|
import { useContextMenu } from '../../../common/hooks/useContextMenu';
|
||||||
@@ -93,6 +95,24 @@ export default function EventBlock(props: EventBlockProps) {
|
|||||||
const [onContextMenu] = useContextMenu<HTMLDivElement>(
|
const [onContextMenu] = useContextMenu<HTMLDivElement>(
|
||||||
selectedEvents.size > 1
|
selectedEvents.size > 1
|
||||||
? [
|
? [
|
||||||
|
{
|
||||||
|
label: 'Link to previous',
|
||||||
|
icon: IoLink,
|
||||||
|
onClick: () =>
|
||||||
|
actionHandler('update', {
|
||||||
|
field: 'linkStart',
|
||||||
|
value: 'true',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Unlink from previous',
|
||||||
|
icon: IoUnlink,
|
||||||
|
onClick: () =>
|
||||||
|
actionHandler('update', {
|
||||||
|
field: 'linkStart',
|
||||||
|
value: null,
|
||||||
|
}),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'Make public',
|
label: 'Make public',
|
||||||
icon: IoPeople,
|
icon: IoPeople,
|
||||||
@@ -101,6 +121,7 @@ export default function EventBlock(props: EventBlockProps) {
|
|||||||
field: 'isPublic',
|
field: 'isPublic',
|
||||||
value: true,
|
value: true,
|
||||||
}),
|
}),
|
||||||
|
withDivider: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Make private',
|
label: 'Make private',
|
||||||
@@ -114,6 +135,15 @@ export default function EventBlock(props: EventBlockProps) {
|
|||||||
{ withDivider: true, label: 'Delete', icon: IoTrash, onClick: () => actionHandler('delete') },
|
{ withDivider: true, label: 'Delete', icon: IoTrash, onClick: () => actionHandler('delete') },
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
|
{
|
||||||
|
label: 'Toggle link to previous',
|
||||||
|
icon: IoLink,
|
||||||
|
onClick: () =>
|
||||||
|
actionHandler('update', {
|
||||||
|
field: 'linkStart',
|
||||||
|
value: linkStart ? null : 'true',
|
||||||
|
}),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'Toggle public',
|
label: 'Toggle public',
|
||||||
icon: IoPeopleOutline,
|
icon: IoPeopleOutline,
|
||||||
@@ -122,6 +152,7 @@ export default function EventBlock(props: EventBlockProps) {
|
|||||||
field: 'isPublic',
|
field: 'isPublic',
|
||||||
value: !isPublic,
|
value: !isPublic,
|
||||||
}),
|
}),
|
||||||
|
withDivider: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Add to swap',
|
label: 'Add to swap',
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { IoLink } from '@react-icons/all-files/io5/IoLink';
|
|||||||
import { IoLockClosed } from '@react-icons/all-files/io5/IoLockClosed';
|
import { IoLockClosed } from '@react-icons/all-files/io5/IoLockClosed';
|
||||||
import { IoLockOpenOutline } from '@react-icons/all-files/io5/IoLockOpenOutline';
|
import { IoLockOpenOutline } from '@react-icons/all-files/io5/IoLockOpenOutline';
|
||||||
import { IoUnlink } from '@react-icons/all-files/io5/IoUnlink';
|
import { IoUnlink } from '@react-icons/all-files/io5/IoUnlink';
|
||||||
import { MaybeString, OntimeEvent, TimeStrategy } from 'ontime-types';
|
import { MaybeString, TimeStrategy } from 'ontime-types';
|
||||||
|
|
||||||
import TimeInputWithButton from '../../../common/components/input/time-input/TimeInputWithButton';
|
import TimeInputWithButton from '../../../common/components/input/time-input/TimeInputWithButton';
|
||||||
import { useEventAction } from '../../../common/hooks/useEventAction';
|
import { useEventAction } from '../../../common/hooks/useEventAction';
|
||||||
@@ -28,7 +28,7 @@ type TimeActions = 'timeStart' | 'timeEnd' | 'duration';
|
|||||||
|
|
||||||
const TimeInputFlow = (props: EventBlockTimerProps) => {
|
const TimeInputFlow = (props: EventBlockTimerProps) => {
|
||||||
const { eventId, timeStart, timeEnd, duration, timeStrategy, linkStart, delay } = props;
|
const { eventId, timeStart, timeEnd, duration, timeStrategy, linkStart, delay } = props;
|
||||||
const { updateEvent, updateTimer, linkTimer } = useEventAction();
|
const { updateEvent, updateTimer } = useEventAction();
|
||||||
|
|
||||||
// In sync with EventEditorTimes
|
// In sync with EventEditorTimes
|
||||||
const handleSubmit = (field: TimeActions, value: string) => {
|
const handleSubmit = (field: TimeActions, value: string) => {
|
||||||
@@ -36,14 +36,11 @@ const TimeInputFlow = (props: EventBlockTimerProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleChangeStrategy = (timeStrategy: TimeStrategy) => {
|
const handleChangeStrategy = (timeStrategy: TimeStrategy) => {
|
||||||
const newEvent: Partial<OntimeEvent> = { id: eventId, timeStrategy };
|
updateEvent({ id: eventId, timeStrategy });
|
||||||
updateEvent(newEvent);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLink = (doLink: boolean) => {
|
const handleLink = (doLink: boolean) => {
|
||||||
// the string doesnt mean much for now, not more than an intent to link
|
updateEvent({ id: eventId, linkStart: doLink ? 'true' : null });
|
||||||
// we imagine that we can leverage this to create offsets p+10
|
|
||||||
linkTimer(eventId, doLink ? 'p' : null);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const overMidnight = timeStart > timeEnd;
|
const overMidnight = timeStart > timeEnd;
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ export function handleLink(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sometimes the client cannot set the previous event
|
||||||
|
if (mutableEvent.linkStart === 'true') {
|
||||||
|
mutableEvent.linkStart = linkedEvent.id;
|
||||||
|
}
|
||||||
|
|
||||||
links[linkedEvent.id] = mutableEvent.id;
|
links[linkedEvent.id] = mutableEvent.id;
|
||||||
|
|
||||||
const timePatch = getLinkedTimes(mutableEvent, linkedEvent);
|
const timePatch = getLinkedTimes(mutableEvent, linkedEvent);
|
||||||
|
|||||||
Reference in New Issue
Block a user