Skip to content

Commit 8a370d3

Browse files
committed
Allow AB display settings to be set by blueprints
And add a reset button in the UI to return them to the blueprints default state,
1 parent e278dfe commit 8a370d3

File tree

5 files changed

+97
-17
lines changed

5 files changed

+97
-17
lines changed

meteor/server/migration/upgrades/showStyleBase.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -129,17 +129,28 @@ export async function runUpgradeForShowStyleBase(showStyleBaseId: ShowStyleBaseI
129129

130130
const result = blueprintManifest.applyConfig(blueprintContext, rawBlueprintConfig)
131131

132-
await ShowStyleBases.updateAsync(showStyleBaseId, {
133-
$set: {
134-
'sourceLayersWithOverrides.defaults': normalizeArray(result.sourceLayers, '_id'),
135-
'outputLayersWithOverrides.defaults': normalizeArray(result.outputLayers, '_id'),
136-
lastBlueprintConfig: {
137-
blueprintHash: blueprint.blueprintHash,
138-
blueprintId: blueprint._id,
139-
blueprintConfigPresetId: showStyleBase.blueprintConfigPresetId ?? '',
140-
config: rawBlueprintConfig,
141-
},
132+
const updateSet: Record<string, any> = {
133+
'sourceLayersWithOverrides.defaults': normalizeArray(result.sourceLayers, '_id'),
134+
'outputLayersWithOverrides.defaults': normalizeArray(result.outputLayers, '_id'),
135+
lastBlueprintConfig: {
136+
blueprintHash: blueprint.blueprintHash,
137+
blueprintId: blueprint._id,
138+
blueprintConfigPresetId: showStyleBase.blueprintConfigPresetId ?? '',
139+
config: rawBlueprintConfig,
142140
},
141+
}
142+
143+
// Store the blueprint-defined abChannelDisplay config if provided
144+
if (result.abChannelDisplay !== undefined) {
145+
updateSet.blueprintAbChannelDisplay = result.abChannelDisplay
146+
// Initialize abChannelDisplay from blueprint if not already set by user
147+
if (!showStyleBase.abChannelDisplay) {
148+
updateSet.abChannelDisplay = result.abChannelDisplay
149+
}
150+
}
151+
152+
await ShowStyleBases.updateAsync(showStyleBaseId, {
153+
$set: updateSet,
143154
})
144155

145156
await updateTriggeredActionsForShowStyleBaseId(showStyleBaseId, result.triggeredActions)
@@ -153,6 +164,7 @@ async function loadShowStyleAndBlueprint(showStyleBaseId: ShowStyleBaseId) {
153164
blueprintConfigPresetId: 1,
154165
blueprintConfigWithOverrides: 1,
155166
lastBlueprintFixUpHash: 1,
167+
abChannelDisplay: 1,
156168
},
157169
})) as
158170
| Pick<
@@ -161,6 +173,7 @@ async function loadShowStyleAndBlueprint(showStyleBaseId: ShowStyleBaseId) {
161173
| 'blueprintId'
162174
| 'blueprintConfigPresetId'
163175
| 'blueprintConfigWithOverrides'
176+
| 'abChannelDisplay'
164177
| 'lastBlueprintFixUpHash'
165178
>
166179
| undefined

packages/blueprints-integration/src/api/showStyle.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import type {
3737
IBlueprintPart,
3838
} from '../documents/index.js'
3939
import type { IBlueprintShowStyleVariant, IOutputLayer, ISourceLayer } from '../showStyle.js'
40+
import type { SourceLayerType } from '../content.js'
4041
import type { TSR, OnGenerateTimelineObj, TimelineObjectCoreExt } from '../timeline.js'
4142
import type { IBlueprintConfig } from '../common.js'
4243
import type { ReadonlyDeep } from 'type-fest'
@@ -322,6 +323,19 @@ export interface BlueprintResultApplyShowStyleConfig {
322323
outputLayers: IOutputLayer[]
323324

324325
triggeredActions: IBlueprintTriggeredActions[]
326+
327+
/** Configuration for displaying AB resolver channel assignments */
328+
abChannelDisplay?: {
329+
/** Source layer IDs that should show AB channel info */
330+
sourceLayerIds: string[]
331+
/** Configure by source layer type */
332+
sourceLayerTypes: SourceLayerType[]
333+
/** Only show for specific output layers (e.g., only PGM) */
334+
outputLayerIds: string[]
335+
/** Enable display on Director screen */
336+
showOnDirectorScreen: boolean
337+
// Future: showOnPresenterScreen, showOnCameraScreen when those views are implemented
338+
}
325339
}
326340

327341
export interface IShowStyleConfigPreset<TConfig = IBlueprintConfig> {

packages/corelib/src/dataModel/ShowStyleBase.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ export interface DBShowStyleBase {
6161
// Future: showOnPresenterScreen, showOnCameraScreen when those views are implemented
6262
}
6363

64+
/** Blueprint default for abChannelDisplay (saved during blueprint upgrade) */
65+
blueprintAbChannelDisplay?: {
66+
sourceLayerIds: string[]
67+
sourceLayerTypes: SourceLayerType[]
68+
outputLayerIds: string[]
69+
showOnDirectorScreen: boolean
70+
}
71+
6472
_rundownVersionHash: string
6573

6674
/** Details on the last blueprint used to generate the defaults values for this */

packages/webui/src/client/ui/Settings/ShowStyle/AbChannelDisplay.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
.ab-channel-display {
2+
&__header {
3+
display: flex;
4+
justify-content: space-between;
5+
align-items: center;
6+
}
7+
28
&__section {
39
margin-top: 1rem;
410

packages/webui/src/client/ui/Settings/ShowStyle/AbChannelDisplay.tsx

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { useCallback, useMemo } from 'react'
55
import { DBShowStyleBase, SourceLayers, OutputLayers } from '@sofie-automation/corelib/dist/dataModel/ShowStyleBase'
66
import { applyAndValidateOverrides } from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
77
import { ColumnPackedGrid, ColumnPackedGridGroup, ColumnPackedGridItem } from '../components/ColumnPackedGrid'
8+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
9+
import { faSync } from '@fortawesome/free-solid-svg-icons'
810
import '../components/ColumnPackedGrid.scss'
911
import './AbChannelDisplay.scss'
1012

@@ -44,12 +46,27 @@ export function AbChannelDisplaySettings({ showStyleBase }: Readonly<AbChannelDi
4446
[]
4547
)
4648

47-
const config = showStyleBase.abChannelDisplay ?? {
48-
sourceLayerIds: [],
49-
sourceLayerTypes: [SourceLayerType.VT, SourceLayerType.LIVE_SPEAK],
50-
outputLayerIds: [],
51-
showOnDirectorScreen: false,
52-
}
49+
const blueprintDefault = showStyleBase.blueprintAbChannelDisplay
50+
const config = showStyleBase.abChannelDisplay ??
51+
blueprintDefault ?? {
52+
sourceLayerIds: [],
53+
sourceLayerTypes: [SourceLayerType.VT, SourceLayerType.LIVE_SPEAK],
54+
outputLayerIds: [],
55+
showOnDirectorScreen: false,
56+
}
57+
58+
// Check if current config differs from blueprint default
59+
const hasOverrides = useMemo(() => {
60+
if (!blueprintDefault || !showStyleBase.abChannelDisplay) return false
61+
62+
const current = showStyleBase.abChannelDisplay
63+
return (
64+
JSON.stringify(current.sourceLayerIds.sort()) !== JSON.stringify(blueprintDefault.sourceLayerIds.sort()) ||
65+
JSON.stringify(current.sourceLayerTypes.sort()) !== JSON.stringify(blueprintDefault.sourceLayerTypes.sort()) ||
66+
JSON.stringify(current.outputLayerIds.sort()) !== JSON.stringify(blueprintDefault.outputLayerIds.sort()) ||
67+
current.showOnDirectorScreen !== blueprintDefault.showOnDirectorScreen
68+
)
69+
}, [showStyleBase.abChannelDisplay, blueprintDefault])
5370

5471
const updateConfig = useCallback(
5572
(updates: Partial<NonNullable<DBShowStyleBase['abChannelDisplay']>>) => {
@@ -70,6 +87,14 @@ export function AbChannelDisplaySettings({ showStyleBase }: Readonly<AbChannelDi
7087
[showStyleBase._id, config]
7188
)
7289

90+
const resetToBlueprint = useCallback(() => {
91+
ShowStyleBases.update(showStyleBase._id, {
92+
$unset: {
93+
abChannelDisplay: 1,
94+
},
95+
})
96+
}, [showStyleBase._id])
97+
7398
const toggleDirectorScreen = useCallback(() => {
7499
updateConfig({ showOnDirectorScreen: !config.showOnDirectorScreen })
75100
}, [updateConfig, config.showOnDirectorScreen])
@@ -160,7 +185,21 @@ export function AbChannelDisplaySettings({ showStyleBase }: Readonly<AbChannelDi
160185

161186
return (
162187
<div className="studio-edit ab-channel-display">
163-
<h2>{t('AB Resolver Channel Display')}</h2>
188+
<div className="ab-channel-display__header">
189+
<h2>{t('AB Resolver Channel Display')}</h2>
190+
{blueprintDefault && (
191+
<button
192+
type="button"
193+
className="btn btn-primary"
194+
onClick={resetToBlueprint}
195+
title={t('Reset to default')}
196+
disabled={!hasOverrides}
197+
>
198+
<span>{t('Reset')}</span>
199+
<FontAwesomeIcon icon={faSync} />
200+
</button>
201+
)}
202+
</div>
164203
<p>
165204
{t(
166205
'Configure which pieces should display their assigned AB resolver channel (e.g., "Server A") on various screens. This helps operators identify which video server is playing each clip.'

0 commit comments

Comments
 (0)