Skip to content

Commit c68df43

Browse files
committed
wip: move Studio.settings to Studio.settingsWithOverrides
1 parent 17be8be commit c68df43

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+746
-445
lines changed

meteor/__mocks__/defaultCollectionObjects.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ export function defaultStudio(_id: StudioId): DBStudio {
105105
mappingsWithOverrides: wrapDefaultObject({}),
106106
supportedShowStyleBase: [],
107107
blueprintConfigWithOverrides: wrapDefaultObject({}),
108-
settings: {
108+
settingsWithOverrides: wrapDefaultObject({
109109
frameRate: 25,
110110
mediaPreviewsUrl: '',
111111
minimumTakeSpan: DEFAULT_MINIMUM_TAKE_SPAN,
112112
fallbackPartDuration: DEFAULT_FALLBACK_PART_DURATION,
113-
},
113+
}),
114114
_rundownVersionHash: '',
115115
routeSetsWithOverrides: wrapDefaultObject({}),
116116
routeSetExclusivityGroupsWithOverrides: wrapDefaultObject({}),

meteor/server/api/evaluations.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { sendSlackMessageToWebhook } from './integration/slack'
1010
import { OrganizationId, UserId } from '@sofie-automation/corelib/dist/dataModel/Ids'
1111
import { DBRundownPlaylist } from '@sofie-automation/corelib/dist/dataModel/RundownPlaylist'
1212
import { Evaluations, RundownPlaylists } from '../collections'
13+
import { applyAndValidateOverrides } from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
1314

1415
export async function saveEvaluation(
1516
credentials: {
@@ -33,8 +34,9 @@ export async function saveEvaluation(
3334
deferAsync(async () => {
3435
const studio = await fetchStudioLight(evaluation.studioId)
3536
if (!studio) throw new Meteor.Error(500, `Studio ${evaluation.studioId} not found!`)
37+
const studioSettings = applyAndValidateOverrides(studio.settingsWithOverrides).obj
3638

37-
const webhookUrls = _.compact((studio.settings.slackEvaluationUrls || '').split(','))
39+
const webhookUrls = _.compact((studioSettings.slackEvaluationUrls || '').split(','))
3840

3941
if (webhookUrls.length) {
4042
// Only send notes if not everything is OK

meteor/server/api/rest/v1/typeConversion.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,13 +266,17 @@ export async function studioFrom(apiStudio: APIStudio, existingId?: StudioId): P
266266
? updateOverrides(studio.blueprintConfigWithOverrides, apiStudio.config as IBlueprintConfig)
267267
: wrapDefaultObject({})
268268

269+
const studioSettings = studioSettingsFrom(apiStudio.settings)
270+
269271
return {
270272
_id: existingId ?? getRandomId(),
271273
name: apiStudio.name,
272274
blueprintId: blueprint?._id,
273275
blueprintConfigPresetId: apiStudio.blueprintConfigPresetId,
274276
blueprintConfigWithOverrides: blueprintConfig,
275-
settings: studioSettingsFrom(apiStudio.settings),
277+
settingsWithOverrides: studio
278+
? updateOverrides(studio.settingsWithOverrides, studioSettings)
279+
: wrapDefaultObject(studioSettings),
276280
supportedShowStyleBase: apiStudio.supportedShowStyleBase?.map((id) => protectString<ShowStyleBaseId>(id)) ?? [],
277281
organizationId: null,
278282
mappingsWithOverrides: wrapDefaultObject({}),
@@ -293,7 +297,7 @@ export async function studioFrom(apiStudio: APIStudio, existingId?: StudioId): P
293297
}
294298

295299
export function APIStudioFrom(studio: DBStudio): APIStudio {
296-
const studioSettings = APIStudioSettingsFrom(studio.settings)
300+
const studioSettings = APIStudioSettingsFrom(applyAndValidateOverrides(studio.settingsWithOverrides).obj)
297301

298302
return {
299303
name: studio.name,

meteor/server/api/studio/api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ export async function insertStudioInner(organizationId: OrganizationId | null, n
4545
supportedShowStyleBase: [],
4646
blueprintConfigWithOverrides: wrapDefaultObject({}),
4747
// testToolsConfig?: ITestToolsConfig
48-
settings: {
48+
settingsWithOverrides: wrapDefaultObject({
4949
frameRate: 25,
5050
mediaPreviewsUrl: '',
5151
minimumTakeSpan: DEFAULT_MINIMUM_TAKE_SPAN,
52-
},
52+
}),
5353
_rundownVersionHash: '',
5454
routeSetsWithOverrides: wrapDefaultObject({}),
5555
routeSetExclusivityGroupsWithOverrides: wrapDefaultObject({}),

meteor/server/migration/0_1_0.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ export const addSteps = addMigrationSteps('0.1.0', [
2929
name: 'Default studio',
3030
organizationId: null,
3131
supportedShowStyleBase: [],
32-
settings: {
32+
settingsWithOverrides: wrapDefaultObject({
3333
frameRate: 25,
3434
mediaPreviewsUrl: '',
3535
minimumTakeSpan: DEFAULT_MINIMUM_TAKE_SPAN,
36-
},
36+
}),
3737
mappingsWithOverrides: wrapDefaultObject({}),
3838
blueprintConfigWithOverrides: wrapDefaultObject({}),
3939
_rundownVersionHash: '',

meteor/server/migration/X_X_X.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import { addMigrationSteps } from './databaseMigration'
22
import { CURRENT_SYSTEM_VERSION } from './currentSystemVersion'
33
import { Studios, TriggeredActions } from '../collections'
4-
import { convertObjectIntoOverrides } from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
4+
import {
5+
convertObjectIntoOverrides,
6+
wrapDefaultObject,
7+
} from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
58
import {
69
StudioRouteSet,
710
StudioRouteSetExclusivityGroup,
811
StudioPackageContainer,
12+
IStudioSettings,
913
} from '@sofie-automation/corelib/dist/dataModel/Studio'
1014
import { DEFAULT_CORE_TRIGGER_IDS } from './upgrades/defaultSystemActionTriggers'
1115

@@ -212,4 +216,46 @@ export const addSteps = addMigrationSteps(CURRENT_SYSTEM_VERSION, [
212216
})
213217
},
214218
},
219+
220+
{
221+
id: `convert studio.settings to ObjectWithOverrides`,
222+
canBeRunAutomatically: true,
223+
validate: async () => {
224+
const studios = await Studios.findFetchAsync({
225+
settings: { $exists: true },
226+
settingsWithOverrides: { $exists: false },
227+
})
228+
229+
for (const studio of studios) {
230+
//@ts-expect-error settings is not typed as ObjectWithOverrides
231+
if (studio.settings) {
232+
return 'settings must be converted to an ObjectWithOverrides'
233+
}
234+
}
235+
236+
return false
237+
},
238+
migrate: async () => {
239+
const studios = await Studios.findFetchAsync({
240+
settings: { $exists: true },
241+
settingsWithOverrides: { $exists: false },
242+
})
243+
244+
for (const studio of studios) {
245+
//@ts-expect-error settings is typed as Record<string, StudioRouteSet>
246+
const oldSettings = studio.settings
247+
248+
const newSettings = wrapDefaultObject<IStudioSettings>(oldSettings || {})
249+
250+
await Studios.updateAsync(studio._id, {
251+
$set: {
252+
settingsWithOverrides: newSettings,
253+
},
254+
$unset: {
255+
// settings: 1,
256+
},
257+
})
258+
}
259+
},
260+
},
215261
])

meteor/server/migration/__tests__/migrations.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,11 @@ describe('Migrations', () => {
121121
name: 'Default studio',
122122
organizationId: null,
123123
supportedShowStyleBase: [],
124-
settings: {
124+
settingsWithOverrides: wrapDefaultObject({
125125
mediaPreviewsUrl: '',
126126
frameRate: 25,
127127
minimumTakeSpan: DEFAULT_MINIMUM_TAKE_SPAN,
128-
},
128+
}),
129129
mappingsWithOverrides: wrapDefaultObject({}),
130130
blueprintConfigWithOverrides: wrapDefaultObject({}),
131131
_rundownVersionHash: '',
@@ -159,11 +159,11 @@ describe('Migrations', () => {
159159
name: 'Default studio',
160160
organizationId: null,
161161
supportedShowStyleBase: [],
162-
settings: {
162+
settingsWithOverrides: wrapDefaultObject({
163163
mediaPreviewsUrl: '',
164164
frameRate: 25,
165165
minimumTakeSpan: DEFAULT_MINIMUM_TAKE_SPAN,
166-
},
166+
}),
167167
mappingsWithOverrides: wrapDefaultObject({}),
168168
blueprintConfigWithOverrides: wrapDefaultObject({}),
169169
_rundownVersionHash: '',
@@ -197,11 +197,11 @@ describe('Migrations', () => {
197197
name: 'Default studio',
198198
organizationId: null,
199199
supportedShowStyleBase: [],
200-
settings: {
200+
settingsWithOverrides: wrapDefaultObject({
201201
mediaPreviewsUrl: '',
202202
frameRate: 25,
203203
minimumTakeSpan: DEFAULT_MINIMUM_TAKE_SPAN,
204-
},
204+
}),
205205
mappingsWithOverrides: wrapDefaultObject({}),
206206
blueprintConfigWithOverrides: wrapDefaultObject({}),
207207
_rundownVersionHash: '',

meteor/server/publications/lib/quickLoop.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { ProtectedString, unprotectString } from '@sofie-automation/corelib/dist
1010
import { DEFAULT_FALLBACK_PART_DURATION } from '@sofie-automation/shared-lib/dist/core/constants'
1111
import { getCurrentTime } from '../../lib/lib'
1212
import { generateTranslation } from '@sofie-automation/corelib/dist/lib'
13-
import { DBStudio } from '@sofie-automation/corelib/dist/dataModel/Studio'
13+
import { IStudioSettings } from '@sofie-automation/corelib/dist/dataModel/Studio'
1414
import { DBPartInstance } from '@sofie-automation/corelib/dist/dataModel/PartInstance'
1515
import { DBSegment } from '@sofie-automation/corelib/dist/dataModel/Segment'
1616
import { ReadonlyObjectDeep } from 'type-fest/source/readonly-deep'
@@ -47,7 +47,7 @@ export function modifyPartForQuickLoop(
4747
segmentRanks: Record<string, number>,
4848
rundownRanks: Record<string, number>,
4949
playlist: Pick<DBRundownPlaylist, 'quickLoop'>,
50-
studio: Pick<DBStudio, 'settings'>,
50+
studioSettings: IStudioSettings,
5151
quickLoopStartPosition: MarkerPosition | undefined,
5252
quickLoopEndPosition: MarkerPosition | undefined,
5353
canSetAutoNext = () => true
@@ -60,7 +60,7 @@ export function modifyPartForQuickLoop(
6060
compareMarkerPositions(quickLoopStartPosition, partPosition) >= 0 &&
6161
compareMarkerPositions(partPosition, quickLoopEndPosition) >= 0
6262

63-
const fallbackPartDuration = studio.settings.fallbackPartDuration ?? DEFAULT_FALLBACK_PART_DURATION
63+
const fallbackPartDuration = studioSettings.fallbackPartDuration ?? DEFAULT_FALLBACK_PART_DURATION
6464

6565
if (isLoopingOverriden && (part.expectedDuration ?? 0) < fallbackPartDuration) {
6666
if (playlist.quickLoop?.forceAutoNext === ForceQuickLoopAutoNext.ENABLED_FORCING_MIN_DURATION) {
@@ -82,7 +82,7 @@ export function modifyPartInstanceForQuickLoop(
8282
segmentRanks: Record<string, number>,
8383
rundownRanks: Record<string, number>,
8484
playlist: Pick<DBRundownPlaylist, 'quickLoop'>,
85-
studio: Pick<DBStudio, 'settings'>,
85+
studioSettings: IStudioSettings,
8686
quickLoopStartPosition: MarkerPosition | undefined,
8787
quickLoopEndPosition: MarkerPosition | undefined
8888
): void {
@@ -107,7 +107,7 @@ export function modifyPartInstanceForQuickLoop(
107107
segmentRanks,
108108
rundownRanks,
109109
playlist,
110-
studio,
110+
studioSettings,
111111
quickLoopStartPosition,
112112
quickLoopEndPosition,
113113
canAutoNext // do not adjust the part instance if we have passed the time where we can still enable auto next

meteor/server/publications/partInstancesUI/publication.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ async function setupUIPartInstancesPublicationObservers(
106106
changed: () => triggerUpdate({ invalidateQuickLoop: true }),
107107
removed: () => triggerUpdate({ invalidateQuickLoop: true }),
108108
}),
109-
cache.Studios.find({}).observeChanges({
109+
cache.StudioSettings.find({}).observeChanges({
110110
added: () => triggerUpdate({ invalidateQuickLoop: true }),
111111
changed: () => triggerUpdate({ invalidateQuickLoop: true }),
112112
removed: () => triggerUpdate({ invalidateQuickLoop: true }),
@@ -148,8 +148,8 @@ export async function manipulateUIPartInstancesPublicationData(
148148
const playlist = state.contentCache.RundownPlaylists.findOne({})
149149
if (!playlist) return
150150

151-
const studio = state.contentCache.Studios.findOne({})
152-
if (!studio) return
151+
const studioSettings = state.contentCache.StudioSettings.findOne({})
152+
if (!studioSettings) return
153153

154154
const rundownRanks = stringsToIndexLookup(playlist.rundownIdsInOrder as unknown as string[])
155155
const segmentRanks = extractRanks(state.contentCache.Segments.find({}).fetch())
@@ -191,7 +191,7 @@ export async function manipulateUIPartInstancesPublicationData(
191191
segmentRanks,
192192
rundownRanks,
193193
playlist,
194-
studio,
194+
studioSettings.settings,
195195
quickLoopStartPosition,
196196
quickLoopEndPosition
197197
)

meteor/server/publications/partInstancesUI/reactiveContentCache.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import { ReactiveCacheCollection } from '../lib/ReactiveCacheCollection'
33
import { literal } from '@sofie-automation/corelib/dist/lib'
44
import { MongoFieldSpecifierOnesStrict, MongoFieldSpecifierZeroes } from '@sofie-automation/corelib/dist/mongo'
55
import { DBRundownPlaylist } from '@sofie-automation/corelib/dist/dataModel/RundownPlaylist'
6-
import { DBStudio } from '@sofie-automation/corelib/dist/dataModel/Studio'
6+
import { DBStudio, IStudioSettings } from '@sofie-automation/corelib/dist/dataModel/Studio'
77
import { DBPartInstance } from '@sofie-automation/corelib/dist/dataModel/PartInstance'
88
import { DBPart } from '@sofie-automation/corelib/dist/dataModel/Part'
9+
import { StudioId } from '@sofie-automation/corelib/dist/dataModel/Ids'
910

1011
export type RundownPlaylistCompact = Pick<DBRundownPlaylist, '_id' | 'activationId' | 'quickLoop' | 'rundownIdsInOrder'>
1112
export const rundownPlaylistFieldSpecifier = literal<MongoFieldSpecifierOnesStrict<RundownPlaylistCompact>>({
@@ -36,14 +37,19 @@ export const partInstanceFieldSpecifier = literal<MongoFieldSpecifierZeroes<DBPa
3637
'part.privateData': 0,
3738
})
3839

39-
export type StudioFields = '_id' | 'settings'
40+
export type StudioFields = '_id' | 'settingsWithOverrides'
4041
export const studioFieldSpecifier = literal<MongoFieldSpecifierOnesStrict<Pick<DBStudio, StudioFields>>>({
4142
_id: 1,
42-
settings: 1,
43+
settingsWithOverrides: 1,
4344
})
4445

46+
export interface StudioSettingsDoc {
47+
_id: StudioId
48+
settings: IStudioSettings
49+
}
50+
4551
export interface ContentCache {
46-
Studios: ReactiveCacheCollection<Pick<DBStudio, StudioFields>>
52+
StudioSettings: ReactiveCacheCollection<StudioSettingsDoc>
4753
Segments: ReactiveCacheCollection<Pick<DBSegment, SegmentFields>>
4854
Parts: ReactiveCacheCollection<Pick<DBPart, PartFields>>
4955
PartInstances: ReactiveCacheCollection<Omit<DBPartInstance, PartInstanceOmitedFields>>
@@ -52,7 +58,7 @@ export interface ContentCache {
5258

5359
export function createReactiveContentCache(): ContentCache {
5460
const cache: ContentCache = {
55-
Studios: new ReactiveCacheCollection<Pick<DBStudio, StudioFields>>('studios'),
61+
StudioSettings: new ReactiveCacheCollection<StudioSettingsDoc>('studioSettings'),
5662
Segments: new ReactiveCacheCollection<Pick<DBSegment, SegmentFields>>('segments'),
5763
Parts: new ReactiveCacheCollection<Pick<DBPart, PartFields>>('parts'),
5864
PartInstances: new ReactiveCacheCollection<Omit<DBPartInstance, PartInstanceOmitedFields>>('partInstances'),

0 commit comments

Comments
 (0)