Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions meteor/__mocks__/defaultCollectionObjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ export function defaultStudio(_id: StudioId): DBStudio {
fallbackPartDuration: DEFAULT_FALLBACK_PART_DURATION,
},
_rundownVersionHash: '',
routeSets: {},
routeSetExclusivityGroups: {},
routeSetsWithOverrides: wrapDefaultObject({}),
routeSetExclusivityGroupsWithOverrides: wrapDefaultObject({}),
packageContainers: {},
previewContainerIds: [],
thumbnailContainerIds: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class StudioDeviceTriggerManager {
return
}

const context = createCurrentContextFromCache(cache)
const context = createCurrentContextFromCache(cache, studioId)
const actionManager = StudioActionManagers.get(studioId)
if (!actionManager)
throw new Meteor.Error(
Expand Down Expand Up @@ -271,7 +271,7 @@ function convertDocument(doc: ReadonlyObjectDeep<DBTriggeredActions>): UITrigger
})
}

function createCurrentContextFromCache(cache: ContentCache): ReactivePlaylistActionContext {
function createCurrentContextFromCache(cache: ContentCache, studioId: StudioId): ReactivePlaylistActionContext {
const rundownPlaylist = cache.RundownPlaylists.findOne({
activationId: {
$exists: true,
Expand Down Expand Up @@ -301,6 +301,7 @@ function createCurrentContextFromCache(cache: ContentCache): ReactivePlaylistAct
: []

return {
studioId: new DummyReactiveVar(studioId),
currentPartInstanceId: new DummyReactiveVar(currentPartInstance?._id ?? null),
currentPartId: new DummyReactiveVar(currentPartInstance?.part._id ?? null),
nextPartId: new DummyReactiveVar(nextPartInstance?.part._id ?? null),
Expand Down
1 change: 1 addition & 0 deletions meteor/server/api/deviceTriggers/triggersContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ function createContextForRundownPlaylistChain(
}

return {
studioId: new DummyReactiveVar(studioId),
rundownPlaylistId: new DummyReactiveVar(playlist?._id),
rundownPlaylist: new DummyReactiveVar(playlist),
currentRundownId: new DummyReactiveVar(currentPartInstance?.rundownId ?? playlist.rundownIdsInOrder[0] ?? null),
Expand Down
5 changes: 2 additions & 3 deletions meteor/server/api/ingest/mosDevice/actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { MOS } from '@sofie-automation/corelib'
import { logger } from '../../../logging'
import { Rundown } from '@sofie-automation/corelib/dist/dataModel/Rundown'
import { Meteor } from 'meteor/meteor'
Expand All @@ -13,7 +12,7 @@ import { generateRundownSource, getPeripheralDeviceFromRundown, runIngestOperati
import { IngestJobs } from '@sofie-automation/corelib/dist/worker/ingest'
import { DEFAULT_MOS_TIMEOUT_TIME } from '@sofie-automation/shared-lib/dist/core/constants'
import { executePeripheralDeviceFunctionWithCustomTimeout } from '../../peripheralDevice/executeFunction'
import { getMosTypes } from '@mos-connection/helper'
import { MOS } from '@sofie-automation/meteor-lib/dist/mos'

export namespace MOSDeviceActions {
export async function reloadRundown(
Expand Down Expand Up @@ -73,7 +72,7 @@ export namespace MOSDeviceActions {
if (!mosPayload.Body)
throw new Meteor.Error(500, `Part Cache for "${partCache.externalId}" missing FullStory content!`)

const mosTypes = getMosTypes(false)
const mosTypes = MOS.getMosTypes(false)

const story = mosPayload.Body.find(
(item) =>
Expand Down
38 changes: 8 additions & 30 deletions meteor/server/api/playout/playout.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
/* tslint:disable:no-use-before-declare */
import { Meteor } from 'meteor/meteor'
import * as _ from 'underscore'
import { StudioRouteBehavior } from '@sofie-automation/corelib/dist/dataModel/Studio'
import { PackageInfo } from '../../coreSystem'
import { StudioContentAccess } from '../../security/studio'
import { shouldUpdateStudioBaselineInner } from '@sofie-automation/corelib/dist/studio/baseline'
import { logger } from '../../logging'
import { Blueprints, RundownPlaylists, Studios, Timeline } from '../../collections'
import { Blueprints, RundownPlaylists, Timeline } from '../../collections'
import { StudioJobs } from '@sofie-automation/corelib/dist/worker/studio'
import { QueueStudioJob } from '../../worker/worker'

export namespace ServerPlayoutAPI {
export async function shouldUpdateStudioBaseline(access: StudioContentAccess): Promise<string | false> {
Expand Down Expand Up @@ -38,32 +36,12 @@ export namespace ServerPlayoutAPI {
export async function switchRouteSet(
access: StudioContentAccess,
routeSetId: string,
state: boolean
state: boolean | 'toggle'
): Promise<void> {
logger.debug(`switchRouteSet "${access.studioId}" "${routeSetId}"=${state}`)

const studio = access.studio

if (studio.routeSets[routeSetId] === undefined)
throw new Meteor.Error(404, `RouteSet "${routeSetId}" not found!`)
const routeSet = studio.routeSets[routeSetId]
if (routeSet.behavior === StudioRouteBehavior.ACTIVATE_ONLY && state === false)
throw new Meteor.Error(400, `RouteSet "${routeSetId}" is ACTIVATE_ONLY`)

const modification: Record<string, any> = {}
modification[`routeSets.${routeSetId}.active`] = state

if (studio.routeSets[routeSetId].exclusivityGroup && state === true) {
_.each(studio.routeSets, (otherRouteSet, otherRouteSetId) => {
if (otherRouteSetId === routeSetId) return
if (otherRouteSet.exclusivityGroup === routeSet.exclusivityGroup) {
modification[`routeSets.${otherRouteSetId}.active`] = false
}
})
}

await Studios.updateAsync(studio._id, {
$set: modification,
const queuedJob = await QueueStudioJob(StudioJobs.SwitchRouteSet, access.studioId, {
routeSetId,
state,
})
await queuedJob.complete
}
}
4 changes: 2 additions & 2 deletions meteor/server/api/rest/v1/typeConversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,9 @@ export async function studioFrom(apiStudio: APIStudio, existingId?: StudioId): P
supportedShowStyleBase: apiStudio.supportedShowStyleBase?.map((id) => protectString<ShowStyleBaseId>(id)) ?? [],
organizationId: null,
mappingsWithOverrides: wrapDefaultObject({}),
routeSets: {},
routeSetsWithOverrides: wrapDefaultObject({}),
_rundownVersionHash: '',
routeSetExclusivityGroups: {},
routeSetExclusivityGroupsWithOverrides: wrapDefaultObject({}),
packageContainers: {},
previewContainerIds: [],
thumbnailContainerIds: [],
Expand Down
6 changes: 3 additions & 3 deletions meteor/server/api/studio/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ export async function insertStudioInner(organizationId: OrganizationId | null, n
minimumTakeSpan: DEFAULT_MINIMUM_TAKE_SPAN,
},
_rundownVersionHash: '',
routeSets: {},
routeSetExclusivityGroups: {},
routeSetsWithOverrides: wrapDefaultObject({}),
routeSetExclusivityGroupsWithOverrides: wrapDefaultObject({}),
packageContainers: {},
thumbnailContainerIds: [],
previewContainerIds: [],
Expand Down Expand Up @@ -141,7 +141,7 @@ Studios.observeChanges(
{
fields: {
mappingsWithOverrides: 1,
routeSets: 1,
routeSetsWithOverrides: 1,
},
}
)
4 changes: 2 additions & 2 deletions meteor/server/api/userActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1114,7 +1114,7 @@ class ServerUserActionAPI
eventTime: Time,
studioId: StudioId,
routeSetId: string,
state: boolean
state: boolean | 'toggle'
): Promise<ClientAPI.ClientResponse<void>> {
return ServerClientAPI.runUserActionInLog(
this,
Expand All @@ -1125,7 +1125,7 @@ class ServerUserActionAPI
async () => {
check(studioId, String)
check(routeSetId, String)
check(state, Boolean)
check(state, Match.OneOf('toggle', Boolean))

const access = await StudioContentWriteAccess.routeSet(this, studioId)
return ServerPlayoutAPI.switchRouteSet(access, routeSetId, state)
Expand Down
4 changes: 2 additions & 2 deletions meteor/server/migration/0_1_0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,8 @@ export const addSteps = addMigrationSteps('0.1.0', [
mappingsWithOverrides: wrapDefaultObject({}),
blueprintConfigWithOverrides: wrapDefaultObject({}),
_rundownVersionHash: '',
routeSets: {},
routeSetExclusivityGroups: {},
routeSetsWithOverrides: wrapDefaultObject({}),
routeSetExclusivityGroupsWithOverrides: wrapDefaultObject({}),
packageContainers: {},
thumbnailContainerIds: [],
previewContainerIds: [],
Expand Down
38 changes: 0 additions & 38 deletions meteor/server/migration/1_42_0.ts

This file was deleted.

22 changes: 15 additions & 7 deletions meteor/server/migration/1_50_0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ function convertMappingsOverrideOps(studio: DBStudio) {
return changed && newOverrides
}

function convertRouteSetMappings(studio: DBStudio) {
function convertRouteSetMappings(routeSets: Record<string, StudioRouteSet>) {
let changed = false

const newRouteSets = clone(studio.routeSets || {})
const newRouteSets = clone(routeSets || {})
for (const routeSet of Object.values<StudioRouteSet>(newRouteSets)) {
for (const route of routeSet.routes) {
if (route.remapping && !route.remapping.options) {
Expand All @@ -95,7 +95,7 @@ function convertRouteSetMappings(studio: DBStudio) {
..._.pick(route.remapping, ...mappingBaseOptions),
options: _.omit(route.remapping, ...mappingBaseOptions),
}
console.log('new route', route)
// console.log('new route', route)
changed = true
}
}
Expand Down Expand Up @@ -247,10 +247,13 @@ export const addSteps = addMigrationSteps('1.50.0', [
canBeRunAutomatically: true,
validate: async () => {
const studios = await Studios.findFetchAsync({ routeSets: { $exists: true } })

for (const studio of studios) {
const newOverrides = convertRouteSetMappings(studio)
if (newOverrides) {
// Ignore this if the routeSets has been converted into an OverrideWithObjects:
if (studio.routeSetsWithOverrides) continue
//@ts-expect-error routeSets are not part of the typings:
const plainRouteSets = studio.routeSets as any as Record<string, StudioRouteSet>
const newRouteSets = convertRouteSetMappings(plainRouteSets)
if (newRouteSets) {
return `object needs to be updated`
}
}
Expand All @@ -261,7 +264,12 @@ export const addSteps = addMigrationSteps('1.50.0', [
const studios = await Studios.findFetchAsync({ routeSets: { $exists: true } })

for (const studio of studios) {
const newRouteSets = convertRouteSetMappings(studio)
// Ignore this if the routeSets already has been converted into an OverrideWithObjects:
if (studio.routeSetsWithOverrides) continue
//@ts-expect-error routeSets are not part of the typings:
const plainRouteSets = studio.routeSets as any as Record<string, StudioRouteSet>

const newRouteSets = convertRouteSetMappings(plainRouteSets)

if (newRouteSets) {
await Studios.updateAsync(studio._id, {
Expand Down
88 changes: 87 additions & 1 deletion meteor/server/migration/X_X_X.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { addMigrationSteps } from './databaseMigration'
import { CURRENT_SYSTEM_VERSION } from './currentSystemVersion'
import { Studios } from '../collections'
import { convertObjectIntoOverrides } from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
import { StudioRouteSet, StudioRouteSetExclusivityGroup } from '@sofie-automation/corelib/dist/dataModel/Studio'

/*
* **************************************************************************************
Expand All @@ -12,5 +15,88 @@ import { CURRENT_SYSTEM_VERSION } from './currentSystemVersion'
*/

export const addSteps = addMigrationSteps(CURRENT_SYSTEM_VERSION, [
// Add some migrations here:
{
id: `convert routesets to ObjectWithOverrides`,
canBeRunAutomatically: true,
validate: async () => {
const studios = await Studios.findFetchAsync({
routeSets: { $exists: true },
routeSetsWithOverrides: { $exists: false },
})

for (const studio of studios) {
//@ts-expect-error routeSets is not typed as ObjectWithOverrides
if (studio.routeSets) {
return 'routesets must be converted to an ObjectWithOverrides'
}
}

return false
},
migrate: async () => {
const studios = await Studios.findFetchAsync({
routeSets: { $exists: true },
routeSetsWithOverrides: { $exists: false },
})

for (const studio of studios) {
//@ts-expect-error routeSets is typed as Record<string, StudioRouteSet>
const oldRouteSets = studio.routeSets

const newRouteSets = convertObjectIntoOverrides<StudioRouteSet>(oldRouteSets || {})

await Studios.updateAsync(studio._id, {
$set: {
routeSetsWithOverrides: newRouteSets,
},
$unset: {
routeSets: 1,
},
})
}
},
},
{
id: `convert routeSetExclusivityGroups to ObjectWithOverrides`,
canBeRunAutomatically: true,
validate: async () => {
const studios = await Studios.findFetchAsync({
routeSetExclusivityGroups: { $exists: true },
routeSetExclusivityGroupsWithOverrides: { $exists: false },
})

for (const studio of studios) {
//@ts-expect-error routeSetExclusivityGroups is not typed as ObjectWithOverrides
if (studio.routeSetExclusivityGroups) {
return 'routesets must be converted to an ObjectWithOverrides'
}
}

return false
},
migrate: async () => {
const studios = await Studios.findFetchAsync({
routeSetExclusivityGroups: { $exists: true },
routeSetExclusivityGroupsWithOverrides: { $exists: false },
})

for (const studio of studios) {
//@ts-expect-error routeSets is typed as Record<string, StudioRouteSetExclusivityGroup>
const oldRouteSetExclusivityGroups = studio.routeSetExclusivityGroups

const newRouteSetExclusivityGroups = convertObjectIntoOverrides<StudioRouteSetExclusivityGroup>(
oldRouteSetExclusivityGroups || {}
)

await Studios.updateAsync(studio._id, {
$set: {
routeSetExclusivityGroupsWithOverrides: newRouteSetExclusivityGroups,
},
$unset: {
routeSetExclusivityGroups: 1,
},
})
}
},
},
])
Loading