Skip to content

Commit 5d3a610

Browse files
Julusianjesperstarkar
authored andcommitted
fix: use the PartInstance instead of Part for PieceInstance content status SOFIE-2993
Adlibbed/orphaned parts don't have a Part, so never got any status
1 parent a5e7af4 commit 5d3a610

File tree

5 files changed

+106
-20
lines changed

5 files changed

+106
-20
lines changed

meteor/lib/api/rundownNotifications.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export interface UIPieceContentStatus {
3838
segmentId: SegmentId | undefined
3939

4040
pieceId: PieceId | AdLibActionId | RundownBaselineAdLibActionId | PieceInstanceId
41+
isPieceInstance: boolean
4142

4243
name: string | ITranslatableMessage
4344
segmentName: string | undefined

meteor/server/publications/pieceContentStatusUI/rundown/publication.ts

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
ExpectedPackageId,
55
PackageContainerPackageId,
66
PartId,
7+
PartInstanceId,
78
PieceId,
89
PieceInstanceId,
910
RundownBaselineAdLibActionId,
@@ -33,7 +34,7 @@ import { logger } from '../../../logging'
3334
import { resolveCredentials } from '../../../security/lib/credentials'
3435
import { NoSecurityReadAccess } from '../../../security/noSecurity'
3536
import { RundownPlaylistReadAccess } from '../../../security/rundownPlaylist'
36-
import { ContentCache, createReactiveContentCache } from './reactiveContentCache'
37+
import { ContentCache, PartInstanceFields, createReactiveContentCache } from './reactiveContentCache'
3738
import { RundownContentObserver } from './rundownContentObserver'
3839
import { RundownsObserver } from '../../lib/rundownsObserver'
3940
import { LiveQueryHandle } from '../../../lib/lib'
@@ -57,6 +58,7 @@ import {
5758
} from './regenerateItems'
5859
import { PieceContentStatusStudio } from '../checkPieceContentStatus'
5960
import { check, Match } from 'meteor/check'
61+
import { DBPartInstance } from '@sofie-automation/corelib/dist/dataModel/PartInstance'
6062

6163
interface UIPieceContentStatusesArgs {
6264
readonly rundownPlaylistId: RundownPlaylistId
@@ -80,6 +82,7 @@ interface UIPieceContentStatusesUpdateProps extends IContentStatusesUpdatePropsB
8082

8183
updatedSegmentIds: SegmentId[]
8284
updatedPartIds: PartId[]
85+
updatedPartInstanceIds: PartInstanceId[]
8386

8487
updatedPieceIds: PieceId[]
8588
updatedPieceInstanceIds: PieceInstanceId[]
@@ -137,13 +140,18 @@ async function setupUIPieceContentStatusesPublicationObservers(
137140
contentCache.Parts.find({}).observeChanges({
138141
added: (id) => triggerUpdate({ updatedPartIds: [protectString(id)] }),
139142
changed: (id) => triggerUpdate({ updatedPartIds: [protectString(id)] }),
140-
removed: (id) => triggerUpdate({ updatedSegmentIds: [protectString(id)] }),
143+
removed: (id) => triggerUpdate({ updatedPartIds: [protectString(id)] }),
141144
}),
142145
contentCache.Pieces.find({}).observeChanges({
143146
added: (id) => triggerUpdate({ updatedPieceIds: [protectString(id)] }),
144147
changed: (id) => triggerUpdate({ updatedPieceIds: [protectString(id)] }),
145148
removed: (id) => triggerUpdate({ updatedPieceIds: [protectString(id)] }),
146149
}),
150+
contentCache.PartInstances.find({}).observeChanges({
151+
added: (id) => triggerUpdate({ updatedPartInstanceIds: [protectString(id)] }),
152+
changed: (id) => triggerUpdate({ updatedPartInstanceIds: [protectString(id)] }),
153+
removed: (id) => triggerUpdate({ updatedPartInstanceIds: [protectString(id)] }),
154+
}),
147155
contentCache.PieceInstances.find({}).observeChanges({
148156
added: (id) => triggerUpdate({ updatedPieceInstanceIds: [protectString(id)] }),
149157
changed: (id) => triggerUpdate({ updatedPieceInstanceIds: [protectString(id)] }),
@@ -292,7 +300,8 @@ async function manipulateUIPieceContentStatusesPublicationData(
292300
state.contentCache,
293301
collection,
294302
new Set(updateProps?.updatedSegmentIds),
295-
new Set(updateProps?.updatedPartIds)
303+
new Set(updateProps?.updatedPartIds),
304+
new Set(updateProps?.updatedPartInstanceIds)
296305
)
297306

298307
let regeneratePieceIds: Set<PieceId>
@@ -414,20 +423,37 @@ function updatePartAndSegmentInfoForExistingDocs(
414423
contentCache: ReadonlyDeep<ContentCache>,
415424
collection: CustomPublishCollection<UIPieceContentStatus>,
416425
updatedSegmentIds: Set<SegmentId>,
417-
updatedPartIds: Set<PartId>
426+
updatedPartIds: Set<PartId>,
427+
updatedPartInstanceIds: Set<PartInstanceId>
418428
) {
429+
const updatedPartInstancesByPartId = new Map<PartId, Pick<DBPartInstance, PartInstanceFields>>()
430+
for (const partInstanceId of updatedPartInstanceIds) {
431+
const partInstance = contentCache.PartInstances.findOne(partInstanceId)
432+
if (partInstance) updatedPartInstancesByPartId.set(partInstance.part._id, partInstance)
433+
}
434+
419435
collection.updateAll((doc) => {
420436
let changed = false
421437

422438
// If the part for this doc changed, update its part.
423439
// Note: if the segment of the doc's part changes that will only be noticed here
424-
if (doc.partId && updatedPartIds.has(doc.partId)) {
440+
if (doc.partId && !doc.isPieceInstance && updatedPartIds.has(doc.partId)) {
425441
const part = contentCache.Parts.findOne(doc.partId)
426442
if (part && (part.segmentId !== doc.segmentId || part._rank !== doc.partRank)) {
427443
doc.segmentId = part.segmentId
428444
doc.partRank = part._rank
429445
changed = true
430446
}
447+
} else if (doc.partId && doc.isPieceInstance) {
448+
const newPartProps = updatedPartInstancesByPartId.get(doc.partId)
449+
if (
450+
newPartProps &&
451+
(newPartProps.segmentId !== doc.segmentId || newPartProps.part._rank !== doc.partRank)
452+
) {
453+
doc.segmentId = newPartProps.segmentId
454+
doc.partRank = newPartProps.part._rank
455+
changed = true
456+
}
431457
}
432458

433459
// If the segment for this doc changed, update its rank

meteor/server/publications/pieceContentStatusUI/rundown/reactiveContentCache.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { AdLibAction } from '@sofie-automation/corelib/dist/dataModel/AdlibActio
1313
import { RundownBaselineAdLibAction } from '@sofie-automation/corelib/dist/dataModel/RundownBaselineAdLibAction'
1414
import { BlueprintId } from '@sofie-automation/corelib/dist/dataModel/Ids'
1515
import { PieceInstance } from '@sofie-automation/corelib/dist/dataModel/PieceInstance'
16+
import { DBPartInstance } from '@sofie-automation/corelib/dist/dataModel/PartInstance'
1617

1718
export type SourceLayersDocId = ProtectedString<'SourceLayersDocId'>
1819
export interface SourceLayersDoc {
@@ -54,12 +55,23 @@ export const pieceFieldSpecifier = literal<MongoFieldSpecifierOnesStrict<Pick<Pi
5455
expectedPackages: 1,
5556
})
5657

57-
export type PieceInstanceFields = '_id' | 'rundownId' | 'piece'
58+
export type PartInstanceFields = '_id' | 'segmentId' | 'rundownId' | 'part'
59+
export const partInstanceFieldSpecifier = literal<
60+
MongoFieldSpecifierOnesStrict<Pick<DBPartInstance, PartInstanceFields>>
61+
>({
62+
_id: 1,
63+
segmentId: 1,
64+
rundownId: 1,
65+
part: 1, // This could be stricter, but this is unlikely to be changed once the PartInstance is created
66+
})
67+
68+
export type PieceInstanceFields = '_id' | 'rundownId' | 'partInstanceId' | 'piece'
5869
export const pieceInstanceFieldSpecifier = literal<
5970
MongoFieldSpecifierOnesStrict<Pick<PieceInstance, PieceInstanceFields>>
6071
>({
6172
_id: 1,
6273
rundownId: 1,
74+
partInstanceId: 1,
6375
piece: 1, // This could be stricter, but this is unlikely to be changed once the PieceInstance is created
6476
})
6577

@@ -110,6 +122,7 @@ export interface ContentCache {
110122
Segments: ReactiveCacheCollection<Pick<DBSegment, SegmentFields>>
111123
Parts: ReactiveCacheCollection<Pick<DBPart, PartFields>>
112124
Pieces: ReactiveCacheCollection<Pick<Piece, PieceFields>>
125+
PartInstances: ReactiveCacheCollection<Pick<DBPartInstance, PartInstanceFields>>
113126
PieceInstances: ReactiveCacheCollection<Pick<PieceInstance, PieceInstanceFields>>
114127
AdLibPieces: ReactiveCacheCollection<Pick<AdLibPiece, AdLibPieceFields>>
115128
AdLibActions: ReactiveCacheCollection<Pick<AdLibAction, AdLibActionFields>>
@@ -124,6 +137,7 @@ export function createReactiveContentCache(): ContentCache {
124137
Segments: new ReactiveCacheCollection<Pick<DBSegment, SegmentFields>>('segments'),
125138
Parts: new ReactiveCacheCollection<Pick<DBPart, PartFields>>('parts'),
126139
Pieces: new ReactiveCacheCollection<Pick<Piece, PieceFields>>('pieces'),
140+
PartInstances: new ReactiveCacheCollection<Pick<DBPartInstance, PartInstanceFields>>('partInstances'),
127141
PieceInstances: new ReactiveCacheCollection<Pick<PieceInstance, PieceInstanceFields>>('pieceInstances'),
128142
AdLibPieces: new ReactiveCacheCollection<Pick<AdLibPiece, AdLibPieceFields>>('adlibPieces'),
129143
AdLibActions: new ReactiveCacheCollection<Pick<AdLibAction, AdLibActionFields>>('adlibActions'),

meteor/server/publications/pieceContentStatusUI/rundown/regenerateItems.ts

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ async function regenerateGenericPiece(
5656
segmentName: segment.name,
5757
name: wrapTranslatableMessageFromBlueprintsIfNotString(doc.name, [sourceLayersForRundown.blueprintId]),
5858

59+
isPieceInstance: false,
60+
5961
status,
6062
},
6163
}
@@ -134,29 +136,54 @@ export async function regenerateForPieceInstanceIds(
134136
// Piece has been deleted, queue it for batching
135137
deletedPieceIds.add(pieceId)
136138
} else {
137-
const res = await regenerateGenericPiece(
138-
contentCache,
139-
uiStudio,
140-
{
141-
...pieceDoc.piece,
142-
_id: protectString(unprotectString(pieceDoc._id)),
143-
},
144-
pieceDoc.piece.sourceLayerId,
145-
{
139+
// Regenerate piece
140+
const rundown = contentCache.Rundowns.findOne(pieceDoc.rundownId)
141+
const sourceLayersForRundown = rundown
142+
? contentCache.ShowStyleSourceLayers.findOne(rundown.showStyleBaseId)
143+
: undefined
144+
145+
const partInstance = pieceDoc.partInstanceId
146+
? contentCache.PartInstances.findOne(pieceDoc.partInstanceId)
147+
: undefined
148+
const segment = partInstance ? contentCache.Segments.findOne(partInstance.segmentId) : undefined
149+
const sourceLayer =
150+
pieceDoc.piece.sourceLayerId && sourceLayersForRundown?.sourceLayers?.[pieceDoc.piece.sourceLayerId]
151+
152+
if (partInstance && segment && sourceLayer) {
153+
const [status, dependencies] = await checkPieceContentStatusAndDependencies(
154+
uiStudio,
155+
{
156+
...pieceDoc.piece,
157+
_id: protectString(unprotectString(pieceDoc._id)),
158+
},
159+
sourceLayer
160+
)
161+
162+
const res: UIPieceContentStatus = {
146163
_id: protectString(`piece_${pieceId}`),
147164

148165
partId: pieceDoc.piece.startPartId,
149166
rundownId: pieceDoc.rundownId,
150167
pieceId: pieceId,
151168

152-
name: pieceDoc.piece.name,
169+
segmentId: segment._id,
170+
171+
segmentRank: segment._rank,
172+
partRank: partInstance.part._rank,
173+
174+
segmentName: segment.name,
175+
name: wrapTranslatableMessageFromBlueprintsIfNotString(pieceDoc.piece.name, [
176+
sourceLayersForRundown.blueprintId,
177+
]),
178+
179+
isPieceInstance: true,
180+
181+
status,
153182
}
154-
)
155183

156-
if (res) {
157-
dependenciesState.set(pieceId, res.dependencies)
184+
dependenciesState.set(pieceId, dependencies)
158185

159-
collection.replace(res.doc)
186+
collection.replace(res)
160187
} else {
161188
deletedPieceIds.add(pieceId)
162189
}
@@ -323,6 +350,8 @@ export async function regenerateForBaselineAdLibPieceIds(
323350
segmentRank: -1,
324351
partRank: -1,
325352

353+
isPieceInstance: false,
354+
326355
status,
327356
})
328357
} else {
@@ -399,6 +428,8 @@ export async function regenerateForBaselineAdLibActionIds(
399428
segmentRank: -1,
400429
partRank: -1,
401430

431+
isPieceInstance: false,
432+
402433
status,
403434
})
404435
} else {

meteor/server/publications/pieceContentStatusUI/rundown/rundownContentObserver.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
adLibPieceFieldSpecifier,
77
ContentCache,
88
partFieldSpecifier,
9+
partInstanceFieldSpecifier,
910
pieceFieldSpecifier,
1011
pieceInstanceFieldSpecifier,
1112
rundownFieldSpecifier,
@@ -17,6 +18,7 @@ import {
1718
import {
1819
AdLibActions,
1920
AdLibPieces,
21+
PartInstances,
2022
Parts,
2123
PieceInstances,
2224
Pieces,
@@ -138,6 +140,18 @@ export class RundownContentObserver {
138140
projection: pieceFieldSpecifier,
139141
}
140142
),
143+
PartInstances.observe(
144+
{
145+
rundownId: {
146+
$in: rundownIds,
147+
},
148+
reset: { $ne: true },
149+
},
150+
cache.PartInstances.link(),
151+
{
152+
projection: partInstanceFieldSpecifier,
153+
}
154+
),
141155
PieceInstances.observe(
142156
{
143157
rundownId: {

0 commit comments

Comments
 (0)