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 && (
+
+ )}