diff --git a/apps/client/src/features/rundown/entry-editor/composite/TargetDurationInput.tsx b/apps/client/src/features/rundown/entry-editor/composite/TargetDurationInput.tsx index b7709606b..cfb4b243b 100644 --- a/apps/client/src/features/rundown/entry-editor/composite/TargetDurationInput.tsx +++ b/apps/client/src/features/rundown/entry-editor/composite/TargetDurationInput.tsx @@ -1,5 +1,5 @@ import { MaybeNumber } from 'ontime-types'; -import { IoLockClosed, IoLockOpenOutline } from 'react-icons/io5'; +import { TbTargetArrow, TbTarget } from 'react-icons/tb'; import IconButton from '../../../../common/components/buttons/IconButton'; import * as Editor from '../../../../common/components/editor-utils/EditorUtils'; @@ -37,7 +37,7 @@ export default function TargetDurationInput({ duration, targetDuration, submitHa data-testid='lock__duration' render={} > - {isLocked ? : } + {isLocked ? : } diff --git a/apps/client/src/features/rundown/rundown-event/RundownEvent.tsx b/apps/client/src/features/rundown/rundown-event/RundownEvent.tsx index e530505c6..52551d241 100644 --- a/apps/client/src/features/rundown/rundown-event/RundownEvent.tsx +++ b/apps/client/src/features/rundown/rundown-event/RundownEvent.tsx @@ -1,6 +1,6 @@ import { useSortable } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; -import { Day, EndAction, EntryId, Playback, TimeStrategy, TimerType } from 'ontime-types'; +import { Day, EndAction, EntryId, Maybe, OntimeGroup, Playback, TimeStrategy, TimerType } from 'ontime-types'; import { isPlaybackActive } from 'ontime-utils'; import { MouseEvent, useEffect, useRef } from 'react'; import { @@ -16,6 +16,7 @@ import { import { TbClockPin, TbFlagFilled, TbListNumbers } from 'react-icons/tb'; import { useEntryActionsContext } from '../../../common/context/EntryActionsContext'; +import { useEntry } from '../../../common/hooks-query/useRundown'; import { useContextMenu } from '../../../common/hooks/useContextMenu'; import { useEntryCopy } from '../../../common/stores/entryCopyStore'; import { deviceAlt, deviceMod } from '../../../common/utils/deviceUtils'; @@ -102,6 +103,8 @@ export default function RundownEvent({ const clearSelectedEventId = useEventIdSwapping((state) => state.clearSelectedEventId); const openRenumberDialog = useRenumberCuesDialogStore((state) => state.onOpen); + const parentGroup = useEntry(parent) as Maybe; + const { updateEntry, batchUpdateEvents, clone, deleteEntry, groupEntries, swapEvents, matchGroupDuration } = useEntryActionsContext(); @@ -176,12 +179,16 @@ export default function RundownEvent({ { type: 'item', label: 'Match Group Target Duration', + description: 'Change event duration to fill the group target', icon: TbClockPin, onClick: () => { if (!parent) return; matchGroupDuration(eventId, parent); }, - disabled: !parent, + disabled: + !parentGroup || + parentGroup.targetDuration === null || + parentGroup.duration === parentGroup.targetDuration, }, { type: 'divider' }, { diff --git a/apps/client/src/features/rundown/rundown-group/RundownGroup.module.scss b/apps/client/src/features/rundown/rundown-group/RundownGroup.module.scss index ad3e094cf..af54c80bd 100644 --- a/apps/client/src/features/rundown/rundown-group/RundownGroup.module.scss +++ b/apps/client/src/features/rundown/rundown-group/RundownGroup.module.scss @@ -90,7 +90,12 @@ } .lockIcon { - opacity: 0.6; + &.inactive { + color: $muted-gray; + } + &.active { + color: $active-indicator; + } } .over { diff --git a/apps/client/src/features/rundown/rundown-group/RundownGroup.tsx b/apps/client/src/features/rundown/rundown-group/RundownGroup.tsx index 93ad11086..c6c42961b 100644 --- a/apps/client/src/features/rundown/rundown-group/RundownGroup.tsx +++ b/apps/client/src/features/rundown/rundown-group/RundownGroup.tsx @@ -8,11 +8,10 @@ import { IoChevronUp, IoDuplicateOutline, IoFolderOpenOutline, - IoLockClosed, IoReorderTwo, IoTrash, } from 'react-icons/io5'; -import { TbClockPin } from 'react-icons/tb'; +import { TbTargetArrow, TbClockPin } from 'react-icons/tb'; import IconButton from '../../../common/components/buttons/IconButton'; import Tag from '../../../common/components/tag/Tag'; @@ -47,6 +46,8 @@ export default function RundownGroup({ data, hasCursor, collapsed, onCollapse }: const selectedEvents = useEventSelection((state) => state.selectedEvents); const entryCopyId = useEntryCopy((state) => state.entryCopyId); + const isDurationMatching = data.targetDuration !== null && data.targetDuration === data.duration; + const matchDuration = useCallback(() => { updateEntry({ id: data.id, targetDuration: data.duration }); }, [data.duration, data.id, updateEntry]); @@ -72,6 +73,8 @@ export default function RundownGroup({ data, hasCursor, collapsed, onCollapse }: label: 'Match Content Duration', icon: TbClockPin, onClick: matchDuration, + disabled: isDurationMatching, + description: "Change group target duration to match it's contents", }, { type: 'divider' }, { @@ -198,7 +201,9 @@ export default function RundownGroup({ data, hasCursor, collapsed, onCollapse }: {planOffset} )} - {data.targetDuration !== null && } + {data.targetDuration !== null && ( + + )}