Skip to content

Commit 6d8670a

Browse files
committed
wip:
1 parent 055e580 commit 6d8670a

File tree

11 files changed

+230
-30
lines changed

11 files changed

+230
-30
lines changed

meteor/server/collections/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export const CoreSystem = createAsyncOnlyMongoCollection<ICoreSystem>(Collection
7575
'cron',
7676
'logo',
7777
'evaluations',
78+
'blueprintId',
7879
])
7980
},
8081
})

meteor/server/migration/api.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
validateConfigForShowStyleBase,
2121
validateConfigForStudio,
2222
} from './upgrades'
23-
import { ShowStyleBaseId, StudioId } from '@sofie-automation/corelib/dist/dataModel/Ids'
23+
import { CoreSystemId, ShowStyleBaseId, StudioId } from '@sofie-automation/corelib/dist/dataModel/Ids'
2424
import { BlueprintValidateConfigForStudioResult } from '@sofie-automation/corelib/dist/worker/studio'
2525
import { runUpgradeForCoreSystem } from './upgrades/system'
2626

@@ -125,10 +125,10 @@ class ServerMigrationAPI extends MethodContextAPI implements NewMigrationAPI {
125125
return runUpgradeForShowStyleBase(showStyleBaseId)
126126
}
127127

128-
async runUpgradeForCoreSystem(): Promise<void> {
128+
async runUpgradeForCoreSystem(coreSystemId: CoreSystemId): Promise<void> {
129129
await SystemWriteAccess.migrations(this)
130130

131-
return runUpgradeForCoreSystem()
131+
return runUpgradeForCoreSystem(coreSystemId)
132132
}
133133
}
134134
registerClassToMeteorMethods(MigrationAPIMethods, ServerMigrationAPI, false)

meteor/server/publications/blueprintUpgradeStatus/checkStatus.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,34 +32,42 @@ export interface BlueprintMapEntry {
3232

3333
export function checkDocUpgradeStatus(
3434
blueprintMap: Map<BlueprintId, BlueprintMapEntry>,
35-
doc: Pick<ICoreSystem, CoreSystemFields> | Pick<DBStudio, StudioFields> | Pick<DBShowStyleBase, ShowStyleBaseFields>
35+
doc:
36+
| Pick<ICoreSystem, CoreSystemFields>
37+
| Pick<DBStudio, StudioFields>
38+
| Pick<DBShowStyleBase, ShowStyleBaseFields>,
39+
blueprintUsesConfig: boolean
3640
): Pick<UIBlueprintUpgradeStatusBase, 'invalidReason' | 'changes' | 'pendingRunOfFixupFunction'> {
3741
// Check the blueprintId is valid
3842
const blueprint = doc.blueprintId ? blueprintMap.get(doc.blueprintId) : null
3943
if (!blueprint || !blueprint.configPresets) {
4044
// Studio blueprint is missing/invalid
4145
return {
4246
invalidReason: generateTranslation('Invalid blueprint: "{{blueprintId}}"', {
43-
blueprintId: doc.blueprintId,
47+
blueprintId: doc.blueprintId ?? 'undefined',
4448
}),
4549
pendingRunOfFixupFunction: false,
4650
changes: [],
4751
}
4852
}
4953

50-
// Check the blueprintConfigPresetId is valid
51-
const configPreset = doc.blueprintConfigPresetId ? blueprint.configPresets[doc.blueprintConfigPresetId] : undefined
52-
if (!configPreset) {
53-
return {
54-
invalidReason: generateTranslation(
55-
'Invalid config preset for blueprint: "{{configPresetId}}" ({{blueprintId}})',
56-
{
57-
configPresetId: doc.blueprintConfigPresetId ?? '',
58-
blueprintId: doc.blueprintId,
59-
}
60-
),
61-
pendingRunOfFixupFunction: false, // TODO - verify
62-
changes: [],
54+
if (blueprintUsesConfig) {
55+
// Check the blueprintConfigPresetId is valid
56+
const configPreset = doc.blueprintConfigPresetId
57+
? blueprint.configPresets[doc.blueprintConfigPresetId]
58+
: undefined
59+
if (!configPreset) {
60+
return {
61+
invalidReason: generateTranslation(
62+
'Invalid config preset for blueprint: "{{configPresetId}}" ({{blueprintId}})',
63+
{
64+
configPresetId: doc.blueprintConfigPresetId ?? '',
65+
blueprintId: doc.blueprintId,
66+
}
67+
),
68+
pendingRunOfFixupFunction: false, // TODO - verify
69+
changes: [],
70+
}
6371
}
6472
}
6573

meteor/server/publications/blueprintUpgradeStatus/publication.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ function updateCoreSystemUpgradeStatus(
225225
blueprintsMap: Map<BlueprintId, BlueprintMapEntry>,
226226
coreSystem: Pick<ICoreSystem, CoreSystemFields>
227227
) {
228-
const status = checkDocUpgradeStatus(blueprintsMap, coreSystem)
228+
const status = checkDocUpgradeStatus(blueprintsMap, coreSystem, false)
229229

230230
collection.replace({
231231
...status,
@@ -241,7 +241,7 @@ function updateStudioUpgradeStatus(
241241
blueprintsMap: Map<BlueprintId, BlueprintMapEntry>,
242242
studio: Pick<DBStudio, StudioFields>
243243
) {
244-
const status = checkDocUpgradeStatus(blueprintsMap, studio)
244+
const status = checkDocUpgradeStatus(blueprintsMap, studio, true)
245245

246246
collection.replace({
247247
...status,
@@ -257,7 +257,7 @@ function updateShowStyleUpgradeStatus(
257257
blueprintsMap: Map<BlueprintId, BlueprintMapEntry>,
258258
showStyleBase: Pick<DBShowStyleBase, ShowStyleBaseFields>
259259
) {
260-
const status = checkDocUpgradeStatus(blueprintsMap, showStyleBase)
260+
const status = checkDocUpgradeStatus(blueprintsMap, showStyleBase, true)
261261

262262
collection.replace({
263263
...status,

packages/webui/src/__mocks__/helpers/database.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export async function setupMockCore(doc?: Partial<ICoreSystem>): Promise<ICoreSy
7272
version: '0.0.0',
7373
previousVersion: '0.0.0',
7474
serviceMessages: {},
75+
lastBlueprintConfig: undefined,
7576
}
7677
const coreSystem = _.extend(defaultCore, doc)
7778
CoreSystem.remove(SYSTEM_ID)

packages/webui/src/client/ui/Settings/ShowStyle/BlueprintConfiguration/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { MeteorPubSub } from '@sofie-automation/meteor-lib/dist/api/pubsub'
1212
import { useSubscription, useTracker } from '../../../../lib/ReactMeteorData/ReactMeteorData'
1313
import { UIBlueprintUpgradeStatuses } from '../../../Collections'
1414
import { getUpgradeStatusMessage, UpgradeStatusButtons } from '../../Upgrades/Components'
15+
import { UIBlueprintUpgradeStatusShowStyle } from '@sofie-automation/meteor-lib/dist/api/upgradeStatus'
1516

1617
interface ShowStyleBaseBlueprintConfigurationSettingsProps {
1718
showStyleBase: DBShowStyleBase
@@ -33,7 +34,7 @@ export function ShowStyleBaseBlueprintConfigurationSettings(
3334
UIBlueprintUpgradeStatuses.findOne({
3435
documentId: props.showStyleBase._id,
3536
documentType: 'showStyle',
36-
}),
37+
}) as UIBlueprintUpgradeStatusShowStyle | undefined,
3738
[props.showStyleBase._id]
3839
)
3940
const statusMessage = isStatusReady && status ? getUpgradeStatusMessage(t, status) ?? t('OK') : t('Loading...')

packages/webui/src/client/ui/Settings/Studio/BlueprintConfiguration/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { SelectBlueprint } from './SelectBlueprint'
1515
import { MeteorPubSub } from '@sofie-automation/meteor-lib/dist/api/pubsub'
1616
import { UIBlueprintUpgradeStatuses } from '../../../Collections'
1717
import { getUpgradeStatusMessage, UpgradeStatusButtons } from '../../Upgrades/Components'
18+
import { UIBlueprintUpgradeStatusStudio } from '@sofie-automation/meteor-lib/dist/api/upgradeStatus'
1819

1920
interface StudioBlueprintConfigurationSettingsProps {
2021
studio: DBStudio
@@ -31,7 +32,7 @@ export function StudioBlueprintConfigurationSettings(
3132
UIBlueprintUpgradeStatuses.findOne({
3233
documentId: props.studio._id,
3334
documentType: 'studio',
34-
}),
35+
}) as UIBlueprintUpgradeStatusStudio | undefined,
3536
[props.studio._id]
3637
)
3738
const statusMessage = isStatusReady && status ? getUpgradeStatusMessage(t, status) ?? t('OK') : t('Loading...')

packages/webui/src/client/ui/Settings/SystemManagement.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { CoreSystem } from '../../collections'
1414
import { CollectionCleanupResult } from '@sofie-automation/meteor-lib/dist/api/system'
1515
import { LabelActual } from '../../lib/Components/LabelAndOverrides'
1616
import { catchError } from '../../lib/lib'
17+
import { SystemManagementBlueprint } from './SystemManagement/Blueprint'
1718

1819
interface WithCoreSystemProps {
1920
coreSystem: ICoreSystem | undefined
@@ -30,6 +31,8 @@ export default function SystemManagement(): JSX.Element | null {
3031
<div className="studio-edit mod mhl mvn">
3132
<SystemManagementGeneral coreSystem={coreSystem} />
3233

34+
<SystemManagementBlueprint coreSystem={coreSystem} />
35+
3336
<SystemManagementNotificationMessage coreSystem={coreSystem} />
3437

3538
<SystemManagementSupportPanel coreSystem={coreSystem} />
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { MeteorPubSub } from '@sofie-automation/meteor-lib/dist/api/pubsub'
2+
import { UIBlueprintUpgradeStatusCoreSystem } from '@sofie-automation/meteor-lib/dist/api/upgradeStatus'
3+
import { useTranslation } from 'react-i18next'
4+
import { useSubscription, useTracker } from '../../../lib/ReactMeteorData/ReactMeteorData'
5+
import { UIBlueprintUpgradeStatuses } from '../../Collections'
6+
import { getUpgradeStatusMessage, SystemUpgradeStatusButtons } from '../Upgrades/Components'
7+
import { ICoreSystem } from '@sofie-automation/meteor-lib/dist/collections/CoreSystem'
8+
import { Blueprints, CoreSystem } from '../../../collections'
9+
import { BlueprintManifestType } from '@sofie-automation/blueprints-integration'
10+
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'
11+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
12+
import { BlueprintId } from '@sofie-automation/corelib/dist/dataModel/Ids'
13+
import { unprotectString } from '@sofie-automation/corelib/dist/protectedString'
14+
import { useMemo } from 'react'
15+
import { LabelActual } from '../../../lib/Components/LabelAndOverrides'
16+
import { EditAttribute } from '../../../lib/EditAttribute'
17+
import { RedirectToBlueprintButton } from '../../../lib/SettingsNavigation'
18+
19+
interface SystemManagementBlueprintProps {
20+
coreSystem: ICoreSystem | undefined
21+
}
22+
export function SystemManagementBlueprint({ coreSystem }: Readonly<SystemManagementBlueprintProps>): JSX.Element {
23+
const { t } = useTranslation()
24+
25+
const isStatusReady = useSubscription(MeteorPubSub.uiBlueprintUpgradeStatuses)
26+
const status = useTracker(
27+
() =>
28+
coreSystem &&
29+
(UIBlueprintUpgradeStatuses.findOne({
30+
documentId: coreSystem._id,
31+
documentType: 'coreSystem',
32+
}) as UIBlueprintUpgradeStatusCoreSystem | undefined),
33+
[coreSystem?._id]
34+
)
35+
const statusMessage = isStatusReady && status ? getUpgradeStatusMessage(t, status) ?? t('OK') : t('Loading...')
36+
37+
return (
38+
<div className="row">
39+
<div className="col c12 r1-c12">
40+
<SelectBlueprint coreSystem={coreSystem} />
41+
42+
<p>
43+
{t('Upgrade Status')}: {statusMessage}
44+
{status && <SystemUpgradeStatusButtons upgradeResult={status} />}
45+
</p>
46+
</div>
47+
</div>
48+
)
49+
}
50+
51+
interface SelectBlueprintProps {
52+
coreSystem: ICoreSystem | undefined
53+
}
54+
55+
function SelectBlueprint({ coreSystem }: Readonly<SelectBlueprintProps>): JSX.Element {
56+
const { t } = useTranslation()
57+
58+
const allSystemBlueprints = useTracker(() => {
59+
return Blueprints.find({
60+
blueprintType: BlueprintManifestType.SYSTEM,
61+
}).fetch()
62+
}, [])
63+
const blueprintOptions: { name: string; value: BlueprintId | null }[] = useMemo(() => {
64+
if (allSystemBlueprints) {
65+
return allSystemBlueprints.map((blueprint) => {
66+
return {
67+
name: blueprint.name ? `${blueprint.name} (${blueprint._id})` : unprotectString(blueprint._id),
68+
value: blueprint._id,
69+
}
70+
})
71+
} else {
72+
return []
73+
}
74+
}, [allSystemBlueprints])
75+
76+
return (
77+
<div className="mod mvs mhs">
78+
<label className="field">
79+
<LabelActual label={t('Blueprint')} />
80+
{!coreSystem?.blueprintId ? (
81+
<div className="error-notice inline">
82+
{t('Blueprint not set')} <FontAwesomeIcon icon={faExclamationTriangle} />
83+
</div>
84+
) : null}
85+
86+
<EditAttribute
87+
modifiedClassName="bghl"
88+
attribute="blueprintId"
89+
obj={coreSystem}
90+
type="dropdown"
91+
options={blueprintOptions}
92+
collection={CoreSystem}
93+
className="input text-input input-l"
94+
/>
95+
<RedirectToBlueprintButton id={coreSystem?.blueprintId} />
96+
</label>
97+
</div>
98+
)
99+
}

packages/webui/src/client/ui/Settings/Upgrades/Components.tsx

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { NoteSeverity } from '@sofie-automation/blueprints-integration'
1010
import { NotificationCenter, NoticeLevel, Notification } from '../../../lib/notifications/notifications'
1111
import {
1212
UIBlueprintUpgradeStatusBase,
13+
UIBlueprintUpgradeStatusCoreSystem,
1314
UIBlueprintUpgradeStatusShowStyle,
1415
UIBlueprintUpgradeStatusStudio,
1516
} from '@sofie-automation/meteor-lib/dist/api/upgradeStatus'
@@ -288,3 +289,76 @@ export function UpgradeStatusButtons({ upgradeResult }: Readonly<UpgradeStatusBu
288289
</div>
289290
)
290291
}
292+
293+
interface SystemUpgradeStatusButtonsProps {
294+
upgradeResult: UIBlueprintUpgradeStatusCoreSystem
295+
}
296+
export function SystemUpgradeStatusButtons({ upgradeResult }: Readonly<SystemUpgradeStatusButtonsProps>): JSX.Element {
297+
const { t } = useTranslation()
298+
299+
const applyConfig = useCallback(
300+
async () => MeteorCall.migration.runUpgradeForCoreSystem(upgradeResult.documentId),
301+
[upgradeResult.documentId, upgradeResult.documentType]
302+
)
303+
304+
const clickApply = useCallback(() => {
305+
applyConfig()
306+
.then(() => {
307+
NotificationCenter.push(
308+
new Notification(
309+
undefined,
310+
NoticeLevel.NOTIFICATION,
311+
t('Config for {{name}} upgraded successfully', { name: upgradeResult.name }),
312+
'UpgradesView'
313+
)
314+
)
315+
})
316+
.catch((e) => {
317+
catchError('Upgrade applyConfig')(e)
318+
NotificationCenter.push(
319+
new Notification(
320+
undefined,
321+
NoticeLevel.WARNING,
322+
t('Config for {{name}} upgraded failed', { name: upgradeResult.name }),
323+
'UpgradesView'
324+
)
325+
)
326+
})
327+
}, [upgradeResult, applyConfig])
328+
329+
const clickShowChanges = useCallback(() => {
330+
doModalDialog({
331+
title: t('Upgrade config for {{name}}', { name: upgradeResult.name }),
332+
message: (
333+
<div>
334+
{upgradeResult.changes.length === 0 && <p>{t('No changes')}</p>}
335+
{upgradeResult.changes.map((msg, i) => (
336+
<p key={i}>{translateMessage(msg, i18nTranslator)}</p>
337+
))}
338+
</div>
339+
),
340+
acceptOnly: true,
341+
yes: t('Dismiss'),
342+
onAccept: () => {
343+
// Do nothing
344+
},
345+
})
346+
}, [upgradeResult])
347+
348+
return (
349+
<div className="mod mhn mvm">
350+
<button
351+
className="btn mrm"
352+
onClick={clickShowChanges}
353+
disabled={!!upgradeResult.invalidReason || upgradeResult.changes.length === 0}
354+
>
355+
<FontAwesomeIcon icon={faEye} />
356+
<span>{t('Show config changes')}</span>
357+
</button>
358+
<button className="btn mrm" onClick={clickApply} disabled={!!upgradeResult.invalidReason}>
359+
<FontAwesomeIcon icon={faDatabase} />
360+
<span>{t('Apply Config')}</span>
361+
</button>
362+
</div>
363+
)
364+
}

0 commit comments

Comments
 (0)