Skip to content

Commit f336ec2

Browse files
authored
fix: reduce duplication when using useOverrideOpHelper for simple objects (Sofie-Automation#1619)
1 parent 4d0de2f commit f336ec2

File tree

7 files changed

+83
-110
lines changed

7 files changed

+83
-110
lines changed

packages/webui/src/client/ui/Settings/BlueprintConfigSchema/index.tsx

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,8 @@ import { MappingExt, MappingsExt } from '@sofie-automation/corelib/dist/dataMode
33
import { IBlueprintConfig, ISourceLayer, SchemaFormUIField } from '@sofie-automation/blueprints-integration'
44
import { groupByToMapFunc, literal } from '@sofie-automation/corelib/dist/lib'
55
import { useTranslation } from 'react-i18next'
6-
import {
7-
applyAndValidateOverrides,
8-
ObjectWithOverrides,
9-
SomeObjectOverrideOp,
10-
} from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
11-
import { useOverrideOpHelper, WrappedOverridableItemNormal } from '../util/OverrideOpHelper.js'
6+
import { ObjectWithOverrides, SomeObjectOverrideOp } from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
7+
import { useOverrideOpHelperForSimpleObject } from '../util/OverrideOpHelper.js'
128
import { JSONSchema } from '@sofie-automation/shared-lib/dist/lib/JSONSchemaTypes'
139
import deepmerge from 'deepmerge'
1410
import { SchemaFormSofieEnumDefinition, translateStringIfHasNamespaces } from '../../../lib/forms/schemaFormUtil.js'
@@ -87,41 +83,25 @@ export function BlueprintConfigSchemaSettings({
8783
}
8884
}, [layerMappings, sourceLayers])
8985

90-
const [wrappedItem, wrappedConfigObject] = useMemo(() => {
86+
const combinedObject = useMemo<ObjectWithOverrides<IBlueprintConfig>>(() => {
87+
// TODO - replace based around a custom implementation of OverrideOpHelperForItemContents?
88+
9189
const combinedDefaults: IBlueprintConfig = alternateConfig
9290
? deepmerge<IBlueprintConfig>(alternateConfig, rawConfigObject.defaults, {
9391
arrayMerge: (_destinationArray, sourceArray, _options) => sourceArray,
9492
})
9593
: rawConfigObject.defaults
9694

97-
const prefixedOps = rawConfigObject.overrides.map((op) => ({
98-
...op,
99-
// TODO: can we avoid doing this hack?
100-
path: `0.${op.path}`,
101-
}))
102-
103-
const computedValue = applyAndValidateOverrides({
95+
return {
10496
defaults: combinedDefaults,
10597
overrides: rawConfigObject.overrides,
106-
}).obj
107-
108-
const wrappedItem = literal<WrappedOverridableItemNormal<IBlueprintConfig>>({
109-
type: 'normal',
110-
id: '0',
111-
computed: computedValue,
112-
defaults: combinedDefaults,
113-
overrideOps: prefixedOps,
114-
})
115-
116-
const wrappedConfigObject: ObjectWithOverrides<IBlueprintConfig> = {
117-
defaults: combinedDefaults,
118-
overrides: prefixedOps,
11998
}
99+
}, [alternateConfig, rawConfigObject])
120100

121-
return [wrappedItem, wrappedConfigObject]
122-
}, [rawConfigObject])
123-
124-
const overrideHelper = useOverrideOpHelper(saveOverridesStrippingPrefix, wrappedConfigObject) // TODO - replace based around a custom implementation of OverrideOpHelperForItemContents?
101+
const { overrideHelper, wrappedItem } = useOverrideOpHelperForSimpleObject(
102+
saveOverridesStrippingPrefix,
103+
combinedObject
104+
)
125105

126106
const groupedSchema = useMemo(() => {
127107
if (schema?.type === 'object' && schema.properties) {

packages/webui/src/client/ui/Settings/Studio/Devices/IngestSubDevices.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { useTranslation } from 'react-i18next'
99
import { getAllCurrentAndDeletedItemsFromOverrides, useOverrideOpHelper } from '../../util/OverrideOpHelper.js'
1010
import {
1111
ObjectOverrideSetOp,
12+
ObjectWithOverrides,
1213
SomeObjectOverrideOp,
1314
wrapDefaultObject,
1415
} from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
@@ -43,7 +44,7 @@ export function StudioIngestSubDevices({
4344
[studio?._id]
4445
)
4546

46-
const baseSettings = useMemo(
47+
const baseSettings = useMemo<ObjectWithOverrides<Record<string, StudioIngestDevice>>>(
4748
() => studio?.peripheralDeviceSettings?.ingestDevices ?? wrapDefaultObject({}),
4849
[studio?.peripheralDeviceSettings?.ingestDevices]
4950
)

packages/webui/src/client/ui/Settings/Studio/Devices/InputSubDevices.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { useTranslation } from 'react-i18next'
99
import { getAllCurrentAndDeletedItemsFromOverrides, useOverrideOpHelper } from '../../util/OverrideOpHelper.js'
1010
import {
1111
ObjectOverrideSetOp,
12+
ObjectWithOverrides,
1213
SomeObjectOverrideOp,
1314
wrapDefaultObject,
1415
} from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
@@ -40,7 +41,7 @@ export function StudioInputSubDevices({ studioId, studioDevices }: Readonly<Stud
4041
[studio?._id]
4142
)
4243

43-
const baseSettings = useMemo(
44+
const baseSettings = useMemo<ObjectWithOverrides<Record<string, StudioInputDevice>>>(
4445
() => studio?.peripheralDeviceSettings?.inputDevices ?? wrapDefaultObject({}),
4546
[studio?.peripheralDeviceSettings?.inputDevices]
4647
)

packages/webui/src/client/ui/Settings/Studio/Devices/PlayoutSubDevices.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { useTranslation } from 'react-i18next'
99
import { getAllCurrentAndDeletedItemsFromOverrides, useOverrideOpHelper } from '../../util/OverrideOpHelper.js'
1010
import {
1111
ObjectOverrideSetOp,
12+
ObjectWithOverrides,
1213
SomeObjectOverrideOp,
1314
wrapDefaultObject,
1415
} from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
@@ -44,7 +45,7 @@ export function StudioPlayoutSubDevices({
4445
[studio?._id]
4546
)
4647

47-
const baseSettings = useMemo(
48+
const baseSettings = useMemo<ObjectWithOverrides<Record<string, StudioPlayoutDevice>>>(
4849
() => studio?.peripheralDeviceSettings?.playoutDevices ?? wrapDefaultObject({}),
4950
[studio?.peripheralDeviceSettings?.playoutDevices]
5051
)

packages/webui/src/client/ui/Settings/Studio/Generic.tsx

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react'
2-
import { DBStudio, IStudioSettings } from '@sofie-automation/corelib/dist/dataModel/Studio'
2+
import { DBStudio } from '@sofie-automation/corelib/dist/dataModel/Studio'
33
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
44
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'
55
import { useTranslation } from 'react-i18next'
@@ -18,14 +18,9 @@ import {
1818
} from '../../../lib/Components/LabelAndOverrides.js'
1919
import { catchError } from '../../../lib/lib.js'
2020
import { ForceQuickLoopAutoNext } from '@sofie-automation/shared-lib/dist/core/model/StudioSettings'
21-
import {
22-
applyAndValidateOverrides,
23-
ObjectWithOverrides,
24-
SomeObjectOverrideOp,
25-
} from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
26-
import { useOverrideOpHelper, WrappedOverridableItemNormal } from '../util/OverrideOpHelper.js'
21+
import { SomeObjectOverrideOp } from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
22+
import { useOverrideOpHelperForSimpleObject } from '../util/OverrideOpHelper.js'
2723
import { IntInputControl } from '../../../lib/Components/IntInput.js'
28-
import { literal } from '@sofie-automation/corelib/dist/lib'
2924
import { useMemo } from 'react'
3025
import { CheckboxControl } from '../../../lib/Components/Checkbox.js'
3126
import { TextInputControl } from '../../../lib/Components/TextInput.js'
@@ -161,32 +156,10 @@ function StudioSettings({ studio }: { studio: DBStudio }): JSX.Element {
161156
[studio._id]
162157
)
163158

164-
const [wrappedItem, wrappedConfigObject] = useMemo(() => {
165-
const prefixedOps = studio.settingsWithOverrides.overrides.map((op) => ({
166-
...op,
167-
// TODO: can we avoid doing this hack?
168-
path: `0.${op.path}`,
169-
}))
170-
171-
const computedValue = applyAndValidateOverrides(studio.settingsWithOverrides).obj
172-
173-
const wrappedItem = literal<WrappedOverridableItemNormal<IStudioSettings>>({
174-
type: 'normal',
175-
id: '0',
176-
computed: computedValue,
177-
defaults: studio.settingsWithOverrides.defaults,
178-
overrideOps: prefixedOps,
179-
})
180-
181-
const wrappedConfigObject: ObjectWithOverrides<IStudioSettings> = {
182-
defaults: studio.settingsWithOverrides.defaults,
183-
overrides: prefixedOps,
184-
}
185-
186-
return [wrappedItem, wrappedConfigObject]
187-
}, [studio.settingsWithOverrides])
188-
189-
const overrideHelper = useOverrideOpHelper(saveOverrides, wrappedConfigObject)
159+
const { overrideHelper, wrappedItem } = useOverrideOpHelperForSimpleObject(
160+
saveOverrides,
161+
studio.settingsWithOverrides
162+
)
190163

191164
const autoNextOptions: DropdownInputOption<ForceQuickLoopAutoNext>[] = useMemo(
192165
() => [

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

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { languageAnd } from '../../lib/language.js'
99
import { TriggeredActionsEditor } from './components/triggeredActions/TriggeredActionsEditor.js'
1010
import { TFunction, useTranslation } from 'react-i18next'
1111
import { Meteor } from 'meteor/meteor'
12-
import { literal } from '@sofie-automation/corelib/dist/lib'
1312
import { LogLevel } from '@sofie-automation/meteor-lib/dist/lib'
1413
import { CoreSystem } from '../../collections/index.js'
1514
import { CollectionCleanupResult } from '@sofie-automation/meteor-lib/dist/api/system'
@@ -21,13 +20,8 @@ import {
2120
} from '../../lib/Components/LabelAndOverrides.js'
2221
import { catchError } from '../../lib/lib.js'
2322
import { SystemManagementBlueprint } from './SystemManagement/Blueprint.js'
24-
import {
25-
applyAndValidateOverrides,
26-
ObjectWithOverrides,
27-
SomeObjectOverrideOp,
28-
} from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
29-
import { ICoreSystemSettings } from '@sofie-automation/blueprints-integration'
30-
import { WrappedOverridableItemNormal, useOverrideOpHelper } from './util/OverrideOpHelper.js'
23+
import { SomeObjectOverrideOp } from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
24+
import { useOverrideOpHelperForSimpleObject } from './util/OverrideOpHelper.js'
3125
import { CheckboxControl } from '../../lib/Components/Checkbox.js'
3226
import {
3327
CombinedMultiLineTextInputControl,
@@ -531,35 +525,5 @@ function useCoreSystemSettingsWithOverrides(coreSystem: ICoreSystem) {
531525
[coreSystem._id]
532526
)
533527

534-
const [wrappedItem, wrappedConfigObject] = useMemo(() => {
535-
const prefixedOps = coreSystem.settingsWithOverrides.overrides.map((op) => ({
536-
...op,
537-
// TODO: can we avoid doing this hack?
538-
path: `0.${op.path}`,
539-
}))
540-
541-
const computedValue = applyAndValidateOverrides(coreSystem.settingsWithOverrides).obj
542-
543-
const wrappedItem = literal<WrappedOverridableItemNormal<ICoreSystemSettings>>({
544-
type: 'normal',
545-
id: '0',
546-
computed: computedValue,
547-
defaults: coreSystem.settingsWithOverrides.defaults,
548-
overrideOps: prefixedOps,
549-
})
550-
551-
const wrappedConfigObject: ObjectWithOverrides<ICoreSystemSettings> = {
552-
defaults: coreSystem.settingsWithOverrides.defaults,
553-
overrides: prefixedOps,
554-
}
555-
556-
return [wrappedItem, wrappedConfigObject]
557-
}, [coreSystem.settingsWithOverrides])
558-
559-
const overrideHelper = useOverrideOpHelper(saveOverrides, wrappedConfigObject)
560-
561-
return {
562-
wrappedItem,
563-
overrideHelper,
564-
}
528+
return useOverrideOpHelperForSimpleObject(saveOverrides, coreSystem.settingsWithOverrides)
565529
}

packages/webui/src/client/ui/Settings/util/OverrideOpHelper.tsx

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
1-
import { SomeObjectOverrideOp, ObjectWithOverrides } from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
2-
import { useRef, useEffect, useCallback } from 'react'
3-
import { OverrideOpHelper, OverrideOpHelperImpl } from '@sofie-automation/corelib/dist/overrideOpHelper'
1+
import {
2+
SomeObjectOverrideOp,
3+
ObjectWithOverrides,
4+
applyAndValidateOverrides,
5+
} from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
6+
import { useRef, useEffect, useCallback, useMemo } from 'react'
7+
import {
8+
OverrideOpHelper,
9+
OverrideOpHelperImpl,
10+
WrappedOverridableItemNormal,
11+
} from '@sofie-automation/corelib/dist/overrideOpHelper'
12+
import { ReadonlyDeep } from 'type-fest/source/readonly-deep'
13+
import { literal } from '@sofie-automation/corelib/dist/lib'
414

515
export type * from '@sofie-automation/corelib/dist/overrideOpHelper'
616
export {
@@ -27,3 +37,46 @@ export function useOverrideOpHelper<T extends object>(
2737
return new OverrideOpHelperImpl(saveOverrides, objectWithOverridesRef.current)
2838
}, [saveOverrides, objectWithOverridesRef])
2939
}
40+
41+
/**
42+
* A helper to work with modifying an ObjectWithOverrides<T> where T is a simple object (not an array of items)
43+
*/
44+
export function useOverrideOpHelperForSimpleObject<T extends object>(
45+
saveOverrides: (newOps: SomeObjectOverrideOp[]) => void,
46+
rawConfigObject: ReadonlyDeep<ObjectWithOverrides<T>>
47+
): {
48+
wrappedItem: WrappedOverridableItemNormal<T>
49+
overrideHelper: OverrideOpHelper
50+
} {
51+
const [wrappedItem, wrappedConfigObject] = useMemo(() => {
52+
const prefixedOps = rawConfigObject.overrides.map((op) => ({
53+
...op,
54+
// Fixup the paths to match the wrappedItem produced below
55+
path: `0.${op.path}`,
56+
}))
57+
58+
const computedValue = applyAndValidateOverrides(rawConfigObject).obj
59+
60+
const wrappedItem = literal<WrappedOverridableItemNormal<T>>({
61+
type: 'normal',
62+
id: '0',
63+
computed: computedValue,
64+
defaults: rawConfigObject.defaults,
65+
overrideOps: prefixedOps,
66+
})
67+
68+
const wrappedConfigObject: ObjectWithOverrides<T> = {
69+
defaults: rawConfigObject.defaults as T,
70+
overrides: prefixedOps,
71+
}
72+
73+
return [wrappedItem, wrappedConfigObject]
74+
}, [rawConfigObject])
75+
76+
const overrideHelper = useOverrideOpHelper(saveOverrides, wrappedConfigObject)
77+
78+
return {
79+
wrappedItem,
80+
overrideHelper,
81+
}
82+
}

0 commit comments

Comments
 (0)