Skip to content

Commit 4f8fbfd

Browse files
committed
Merge remote-tracking branch 'origin/feat/segment-event-identifier' into bbc-main
2 parents 007d4bc + 3aa0091 commit 4f8fbfd

19 files changed

Lines changed: 366 additions & 272 deletions

File tree

packages/blueprints-integration/src/documents/part.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ export interface IBlueprintMutatablePart<TPrivateData = unknown, TPublicData = u
9191
/** User-facing identifier that can be used by the User to identify the contents of a segment in the Rundown source system */
9292
identifier?: string
9393

94+
/** User-facing notes shown in the segment header */
95+
segmentHeaderNotes?: ITranslatableMessage[]
96+
9497
/** MediaObjects that when created/updated, should cause the blueprint to be rerun for the Segment of this Part */
9598
hackListenToMediaObjectUpdates?: HackPartMediaObjectSubscription[]
9699

packages/job-worker/src/blueprints/context/lib.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import {
5353
IOutputLayer,
5454
ISourceLayer,
5555
NoteSeverity,
56+
ITranslatableMessage,
5657
PieceAbSessionInfo,
5758
RundownPlaylistTiming,
5859
} from '@sofie-automation/blueprints-integration'
@@ -143,6 +144,7 @@ export const PlayoutMutatablePartSampleKeys = allKeysOfObject<PlayoutMutatablePa
143144
displayDurationGroup: true,
144145
displayDuration: true,
145146
identifier: true,
147+
segmentHeaderNotes: true,
146148
hackListenToMediaObjectUpdates: true,
147149
userEditOperations: true,
148150
userEditProperties: true,
@@ -332,6 +334,7 @@ export function convertPartToBlueprints(part: ReadonlyDeep<DBPart>): IBlueprintP
332334
displayDurationGroup: part.displayDurationGroup,
333335
displayDuration: part.displayDuration,
334336
identifier: part.identifier,
337+
segmentHeaderNotes: clone<ITranslatableMessage[] | undefined>(part.segmentHeaderNotes),
335338
hackListenToMediaObjectUpdates: clone<HackPartMediaObjectSubscription[] | undefined>(
336339
part.hackListenToMediaObjectUpdates
337340
),
@@ -714,7 +717,13 @@ export function convertPartialBlueprintMutablePartToCore(
714717
blueprintId,
715718
])
716719
} else {
717-
delete playoutUpdatePart.userEditOperations
720+
delete playoutUpdatePart.userEditProperties
721+
}
722+
723+
if ('segmentHeaderNotes' in updatePart) {
724+
playoutUpdatePart.segmentHeaderNotes = updatePart.segmentHeaderNotes?.map((note) =>
725+
wrapTranslatableMessageFromBlueprints(note, [blueprintId])
726+
)
718727
}
719728

720729
return playoutUpdatePart

packages/job-worker/src/ingest/generationSegment.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,9 @@ function updateModelWithGeneratedPart(
405405
]),
406406
}
407407
: undefined,
408+
segmentHeaderNotes: blueprintPart.part.segmentHeaderNotes?.map((note) =>
409+
wrapTranslatableMessageFromBlueprints(note, [blueprintId])
410+
),
408411
userEditOperations: translateUserEditsFromBlueprint(blueprintPart.part.userEditOperations, [blueprintId]),
409412
userEditProperties: translateUserEditPropertiesFromBlueprint(blueprintPart.part.userEditProperties, [
410413
blueprintId,

packages/webui/src/client/styles/_colorScheme.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ $general-timecode-color: var(--general-timecode-color);
3232
$part-identifier: var(--part-identifier);
3333
$part-identifier-text: var(--part-identifier-text);
3434

35+
$segment-header-note-identifier: var(--segment-header-note-identifier);
36+
$segment-header-note-identifier-text: var(--segment-header-note-identifier-text);
37+
3538
$ui-button-primary: var(--ui-button-primary);
3639
$ui-button-primary--hover: var(--ui-button-primary--hover);
3740
$ui-button-primary--translucent: var(--ui-button-primary--translucent);

packages/webui/src/client/styles/defaultColors.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232

3333
--part-identifier: #363636;
3434
--part-identifier-text: #eee;
35+
36+
--segment-header-note-identifier: #363636;
37+
--segment-header-note-identifier-text: #fff;
38+
3539
--general-timecode-color: #ffff00;
3640

3741
--ui-button-primary: #1769ff;

packages/webui/src/client/styles/rundownView.scss

Lines changed: 97 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,8 @@ svg.icon {
283283
}
284284

285285
.segment-timeline__title {
286-
display: grid;
287-
grid-template-columns: auto;
288-
grid-template-rows: [title-title] min-content [title-notifications] 1fr [title-identifiers] min-content [end];
286+
display: flex;
287+
flex-direction: column;
289288

290289
margin: 0;
291290
padding: 0;
@@ -306,6 +305,12 @@ svg.icon {
306305
grid-row: title / timeline-header;
307306
}
308307

308+
.segment-timeline__title__content {
309+
display: flex;
310+
flex-direction: column;
311+
flex-grow: 1;
312+
}
313+
309314
h2 {
310315
margin: 0;
311316
padding: 0.2em;
@@ -315,7 +320,6 @@ svg.icon {
315320
hyphens: auto;
316321
-webkit-hyphens: auto;
317322
-ms-hyphens: auto;
318-
grid-row: title-title / title-notifications;
319323
}
320324

321325
.segment-timeline__title__notes {
@@ -324,27 +328,79 @@ svg.icon {
324328
line-height: 1.4em;
325329
font-size: 0.75em;
326330
font-weight: 400;
327-
grid-row: title-notifications / title-identifiers;
328331
}
329332

330333
.segment-timeline__part-identifiers {
331-
grid-row: title-identifiers / end;
334+
margin-top: auto;
332335

333336
.segment-timeline__part-identifiers__identifier {
334-
font-weight: 300;
335-
text-shadow: none;
336-
margin: 2.5px;
337-
padding: 1px 4px;
337+
// The pill-shaped labels that appear in the segment header, showing and linking to the part name or number
338+
margin: 0.1rem;
339+
padding: 0.1rem 0.35rem 0.1rem 0.35rem;
338340
background-color: $part-identifier;
339341
color: $part-identifier-text;
340-
border-radius: 10px;
341-
font-size: 0.85rem;
342+
border-radius: 99px;
343+
font-family: 'Roboto Flex', 'Roboto', sans-serif;
344+
font-style: normal;
345+
font-size: 0.9rem;
346+
letter-spacing: 0.03em;
347+
line-height: 100%;
348+
text-shadow: none;
349+
font-variant-numeric: proportional-nums;
350+
font-variation-settings:
351+
'wdth' 90,
352+
'wght' 500,
353+
'opsz' 120,
354+
'slnt' 0,
355+
'GRAD' 0,
356+
'XOPQ' 96,
357+
'XTRA' 468,
358+
'YOPQ' 79,
359+
'YTAS' 750,
360+
'YTDE' -203,
361+
'YTFI' 738,
362+
'YTLC' 514,
363+
'YTUC' 712;
342364

343365
&:hover {
344-
background-color: #8c8c8c;
366+
background-color: #6f6f6f;
345367
color: #fff;
346-
}
347-
}
368+
font-weight: 700;
369+
box-shadow: 0px 0px 4px 0px #fff;
370+
}
371+
}
372+
}
373+
.segment-timeline__segment-header-note-identifier {
374+
// The pill-shaped labels that appear in the segment header, showing extra information about the segment.
375+
align-self: flex-start;
376+
display: inline-block;
377+
margin-top: auto;
378+
margin: 0.25rem;
379+
padding: 0.1rem 0.35rem 0.1rem 0.35rem;
380+
background-color: $segment-header-note-identifier;
381+
color: $segment-header-note-identifier-text;
382+
border-radius: 99px;
383+
font-family: 'Roboto Flex', 'Roboto', sans-serif;
384+
font-style: normal;
385+
font-size: 0.9rem;
386+
letter-spacing: 0.03em;
387+
line-height: 100%;
388+
text-shadow: none;
389+
font-variant-numeric: proportional-nums;
390+
font-variation-settings:
391+
'wdth' 70,
392+
'wght' 500,
393+
'opsz' 120,
394+
'slnt' 0,
395+
'GRAD' 0,
396+
'XOPQ' 96,
397+
'XTRA' 468,
398+
'YOPQ' 79,
399+
'YTAS' 750,
400+
'YTDE' -203,
401+
'YTFI' 738,
402+
'YTLC' 514,
403+
'YTUC' 712;
348404
}
349405
}
350406

@@ -2284,13 +2340,36 @@ svg.icon {
22842340
}
22852341

22862342
.segment-timeline__identifier {
2343+
// The Parts identifier label on the right side of the part, showing the Part name or number
22872344
z-index: -1;
2288-
padding: 0 4px 0 10px;
2345+
padding: 0.1rem 0.35rem 0.1rem 0.6rem;
22892346
box-sizing: border-box;
2347+
border-radius: 0 99px 99px 0;
2348+
margin: 0rem;
2349+
22902350
background-color: $part-identifier;
2291-
border-radius: 0 8px 8px 0;
22922351
color: $part-identifier-text;
2293-
font-size: 0.85rem;
2352+
font-family: 'Roboto Flex', 'Roboto', sans-serif;
2353+
font-style: normal;
2354+
font-size: 0.9rem;
2355+
letter-spacing: 0.03em;
2356+
line-height: 100%;
2357+
text-shadow: none;
2358+
font-variant-numeric: proportional-nums;
2359+
font-variation-settings:
2360+
'wdth' 90,
2361+
'wght' 500,
2362+
'opsz' 120,
2363+
'slnt' 0,
2364+
'GRAD' 0,
2365+
'XOPQ' 96,
2366+
'XTRA' 468,
2367+
'YOPQ' 79,
2368+
'YTAS' 750,
2369+
'YTDE' -203,
2370+
'YTFI' 738,
2371+
'YTLC' 514,
2372+
'YTUC' 712;
22942373
}
22952374

22962375
&.gap {

packages/webui/src/client/ui/SegmentAdlibTesting/SegmentAdlibTesting.tsx

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'
22
import { NoteSeverity } from '@sofie-automation/blueprints-integration'
33
import type { IContextMenuContext } from '../RundownView.js'
4-
import type { IOutputLayerUi, PartUi, SegmentNoteCounts, SegmentUi } from '../SegmentContainer/withResolvedSegment.js'
4+
import type { IOutputLayerUi, PartUi, SegmentUi } from '../SegmentContainer/withResolvedSegment.js'
55
import { ContextMenuTrigger } from '@jstarpl/react-contextmenu'
6-
import { CriticalIconSmall, WarningIconSmall } from '../../lib/ui/icons/notifications.js'
76
import { contextMenuHoldToDisplayTime, useCombinedRefs, useRundownViewEventBusListener } from '../../lib/lib.js'
87
import { useTranslation } from 'react-i18next'
98
import { literal } from '@sofie-automation/corelib/dist/lib'
@@ -31,6 +30,7 @@ import type { UIStudio } from '@sofie-automation/corelib/src/dataModel/Studio.js
3130
import type { PieceUi } from '@sofie-automation/corelib/src/dataModel/Piece.js'
3231
import { isLoopRunning } from '@sofie-automation/corelib/src/playout/stateCacheResolver.js'
3332
import { HOVER_TIMEOUT } from '../Shelf/DashboardPieceButton/types.js'
33+
import { SegmentHeaderNotes } from '../SegmentHeader/SegmentHeaderNotes.js'
3434

3535
interface IProps {
3636
id: string
@@ -39,7 +39,6 @@ interface IProps {
3939
playlist: DBRundownPlaylist
4040
studio: UIStudio
4141
parts: Array<PartUi>
42-
segmentNoteCounts: SegmentNoteCounts
4342
hasAlreadyPlayed: boolean
4443
hasGuestItems: boolean
4544
hasRemoteItems: boolean
@@ -82,9 +81,6 @@ export const SegmentAdlibTesting = React.memo(
8281
const [squishedHover, setSquishedHover] = useState<null | number>(null)
8382
const squishedHoverTimeout = useRef<number | null>(null)
8483

85-
const criticalNotes = props.segmentNoteCounts.criticial
86-
const warningNotes = props.segmentNoteCounts.warning
87-
8884
const getSegmentContext = () => {
8985
const ctx = literal<IContextMenuContext>({
9086
segment: props.segment,
@@ -463,30 +459,7 @@ export const SegmentAdlibTesting = React.memo(
463459
>
464460
{t('Adlib Testing')}
465461
</h2>
466-
{(criticalNotes > 0 || warningNotes > 0) && (
467-
<div className="segment-timeline__title__notes">
468-
{criticalNotes > 0 && (
469-
<div
470-
className="segment-timeline__title__notes__note segment-timeline__title__notes__note--critical"
471-
onClick={() => props.onHeaderNoteClick?.(props.segment._id, NoteSeverity.ERROR)}
472-
aria-label={t('Critical problems')}
473-
>
474-
<CriticalIconSmall />
475-
<div className="segment-timeline__title__notes__count">{criticalNotes}</div>
476-
</div>
477-
)}
478-
{warningNotes > 0 && (
479-
<div
480-
className="segment-timeline__title__notes__note segment-timeline__title__notes__note--warning"
481-
onClick={() => props.onHeaderNoteClick?.(props.segment._id, NoteSeverity.WARNING)}
482-
aria-label={t('Warnings')}
483-
>
484-
<WarningIconSmall />
485-
<div className="segment-timeline__title__notes__count">{warningNotes}</div>
486-
</div>
487-
)}
488-
</div>
489-
)}
462+
<SegmentHeaderNotes segmentId={props.segment._id} onHeaderNoteClick={props.onHeaderNoteClick} />
490463
</ContextMenuTrigger>
491464
<div className="segment-timeline__source-layers" role="tree" aria-label={t('Sources')}>
492465
{Object.values<IOutputLayerUi>(props.segment.outputLayers)

packages/webui/src/client/ui/SegmentAdlibTesting/SegmentAdlibTestingContainer.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ export const SegmentAdlibTestingContainer = withResolvedSegment<IProps>(function
209209
segment={props.segmentui}
210210
studio={props.studio}
211211
parts={props.parts}
212-
segmentNoteCounts={props.segmentNoteCounts}
213212
onItemClick={props.onPieceClick}
214213
onItemDoubleClick={props.onPieceDoubleClick}
215214
playlist={props.playlist}

0 commit comments

Comments
 (0)