Skip to content

Commit 1848f9e

Browse files
olzzonOlzzonMint de Wit
committed
Properties Panel (bbc/sofie-core #22)
* wip: initial draft implementation of userEditPanel * wip: userEditPanel grouping * wip: userEditPanel cleanup remove schema as it's replaces by schemas * wip: userEditPanel styling and use <select> for list * wip: userEditPanel - make groupType optional to allow empty slots * wip: userEditPanel - convert to FC * wip: userEditPanel - uncomment context menu * wip: UserEditPanel - Add DefaultUserOperationsTypes for revert buttons in panel * wip: UserEditPanel - Default revert button on panel * wip: UserEditPanel - tracker on part and segment * wip: UserEditPanel - only render Segment or Part in panel * wip: UserEditPanel - initial header for part and segment * wip: UserEditPanel - comment for the usage of getTimePosition * wip: UserEditPanel - add Icons in header * wip: UserEditPanel - add button type in UserEditingDefinitions * wip: UserEditPanel - rename revert button to "Revert Changes" * wip: UserEditPanel - add support for SVG icons in grouping (e.g for split or DVE backgrounds) * wip: UserEditPanel - center revert button * wip: Renaming UserEditPanel to PropertiesPanel * wip: UI selection - Context for SelectedElements * wip: UI selection - refactor from useState() to useReducer() * wip: UI selection - use type for SelectedElement * wip: UI selection -Segment not updating upon selection * feat: unit tests for SelectedElementsContext * wip: UI selection - add isSelected to withSegmentTiming * wip: fix props withSelection * wip: fix props withSelection * wip: remove componentDidUpdate - leftover from previous debugging * fix: added listSelectedElements() instead of exposing the selectedElements * fix: add assertNever() to selectionReducer * fix: remove id and use ElementId as reference in context provider * fix: clean up isSelected should parse boolean not function as props * chore: update package with @testing-library/react * fix: tests for SelecedElementsContext updated and type fixed * fix: listSelectedElements is af function not an array * wip: implement useSelection in PropertiesPanel * wip: useSelection on Parts * fix: missing rundown id in propertiespanel actions * feat: add enabling of userediting in settings * feat: doubleclick on part selection for properties panel * fix: properties panel crash when no selection was made * feat: segment selection * feat: dbl click anywhere in segment header to select properties * feat: select part by double clicking a piece * feat: properties panel commit button for pending changes * feat: select/deselect an element - fix flickering upen commit changes * fix: render all userEditOperations when part is selected * feat: move Properties panel out of notification center logic * feat: use context.consumer instead of wrapping * feat: refactor userEditing structure * feat: properties panel with refactored data structure. * feat: Schema selection implemented in commit button logic * feat: implement Layer colors in group selectors * feat: only parse the selected source on useraction commit * feat: simplify structure for userEditing source * fix: rerender group selection when selecting new part * fix: read the SourceLayerType into UserEditingDefinition * feat: selected element indicator * feat: properties panel styling - is edited indication * wip: add close propterties icon (sketch) * wip: properties panel css dim commit+revert when not active * wip: properties panel clean up first iteration selector * wip: properties panel add close upper right * fix: crash UI - remove transiongroup * feat: properties panel animate in and shrink rundown view * fix: cleanup using notificationpanel for properties panel * wip: properties panel, rightbar icon color * fix: re-run only if part.segmentId has changed * wip: tests for properties panel * wip: properties panel tests - useFaketimers and implement mock useTracker() * wip: properties panel - element selection styling * wip: properties panel styling edit pencil icon * wip: properties panel close when notification is open * wip: properties panel selection glow on segment header * feat: StyledSchemaFormInPlace schema component * fix: Properties panel - StyledSchemaFormInPlace schema for normal form * feat: Properties panel is edited pencil styling * feat: Properties header styling * wip: Properties tests - more mocking to get correct rendering in test to work * chore: fix unit tests * feat: refactor form action to properties field * chore: update styles * chore: add actions back into property panel * chore: support translations for properties panel * chore: fix some build issues * feat: allow editing piece properties * chore: various review comments * chore: fix tests * chore: remove unused parameter * chore: removed commented styles --------- Co-authored-by: Olzzon <[email protected]> Co-authored-by: Mint de Wit <[email protected]>
1 parent ddab6df commit 1848f9e

Some content is hidden

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

50 files changed

+2604
-355
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ export function studioSettingsFrom(apiStudioSettings: APIStudioSettings): Comple
367367
enableQuickLoop: apiStudioSettings.enableQuickLoop,
368368
forceQuickLoopAutoNext: forceQuickLoopAutoNextFrom(apiStudioSettings.forceQuickLoopAutoNext),
369369
fallbackPartDuration: apiStudioSettings.fallbackPartDuration ?? DEFAULT_FALLBACK_PART_DURATION,
370+
enableUserEdits: apiStudioSettings.enableUserEdits,
370371
allowAdlibTestingSegment: apiStudioSettings.allowAdlibTestingSegment,
371372
allowHold: apiStudioSettings.allowHold ?? true, // Backwards compatible
372373
allowPieceDirectPlay: apiStudioSettings.allowPieceDirectPlay ?? true, // Backwards compatible
@@ -390,6 +391,7 @@ export function APIStudioSettingsFrom(settings: IStudioSettings): Complete<APISt
390391
enableQuickLoop: settings.enableQuickLoop,
391392
forceQuickLoopAutoNext: APIForceQuickLoopAutoNextFrom(settings.forceQuickLoopAutoNext),
392393
fallbackPartDuration: settings.fallbackPartDuration,
394+
enableUserEdits: settings.enableUserEdits,
393395
allowAdlibTestingSegment: settings.allowAdlibTestingSegment,
394396
allowHold: settings.allowHold,
395397
allowPieceDirectPlay: settings.allowPieceDirectPlay,

meteor/server/lib/rest/v1/studios.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ export interface APIStudioSettings {
216216
forceQuickLoopAutoNext?: 'disabled' | 'enabled_when_valid_duration' | 'enabled_forcing_min_duration'
217217
minimumTakeSpan?: number
218218
fallbackPartDuration?: number
219+
enableUserEdits?: boolean
219220
allowAdlibTestingSegment?: boolean
220221
allowHold?: boolean
221222
allowPieceDirectPlay?: boolean

packages/blueprints-integration/src/documents/part.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { UserEditingDefinition } from '../userEditing'
1+
import { UserEditingDefinition, UserEditingProperties } from '../userEditing'
22
import type { NoteSeverity } from '../lib'
33
import type { ITranslatableMessage } from '../translations'
44

@@ -88,6 +88,12 @@ export interface IBlueprintMutatablePart<TPrivateData = unknown, TPublicData = u
8888
* User editing definitions for this part
8989
*/
9090
userEditOperations?: UserEditingDefinition[]
91+
92+
/**
93+
* Properties that are user editable from the properties panel in the Sofie UI, if the user saves changes to these
94+
* it will trigger a user edit operation of type DefaultUserOperationEditProperties
95+
*/
96+
userEditProperties?: UserEditingProperties
9197
}
9298

9399
export interface HackPartMediaObjectSubscription {

packages/blueprints-integration/src/documents/piece.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { UserEditingDefinition } from '../userEditing'
1+
import { UserEditingDefinition, UserEditingProperties } from '../userEditing'
22
import type { IBlueprintPieceGeneric } from './pieceGeneric'
33

44
/** Special types of pieces. Some are not always used in all circumstances */
@@ -35,6 +35,12 @@ export interface IBlueprintPiece<TPrivateData = unknown, TPublicData = unknown>
3535
* User editing definitions for this piece
3636
*/
3737
userEditOperations?: UserEditingDefinition[]
38+
39+
/**
40+
* Properties that are user editable from the properties panel in the Sofie UI, if the user saves changes to these
41+
* it will trigger a user edit operation of type DefaultUserOperationEditProperties
42+
*/
43+
userEditProperties?: UserEditingProperties
3844
}
3945
export interface IBlueprintPieceDB<TPrivateData = unknown, TPublicData = unknown>
4046
extends IBlueprintPiece<TPrivateData, TPublicData> {

packages/blueprints-integration/src/documents/segment.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { UserEditingDefinition } from '../userEditing'
1+
import { UserEditingDefinition, UserEditingProperties } from '../userEditing'
22

33
export enum SegmentDisplayMode {
44
Timeline = 'timeline',
@@ -52,6 +52,12 @@ export interface IBlueprintSegment<TPrivateData = unknown, TPublicData = unknown
5252
* User editing definitions for this segment
5353
*/
5454
userEditOperations?: UserEditingDefinition[]
55+
56+
/**
57+
* Properties that are user editable from the properties panel in the Sofie UI, if the user saves changes to these
58+
* it will trigger a user edit operation of type DefaultUserOperationEditProperties
59+
*/
60+
userEditProperties?: UserEditingProperties
5561
}
5662
/** The Segment sent from Core */
5763
export interface IBlueprintSegmentDB<TPrivateData = unknown, TPublicData = unknown>

packages/blueprints-integration/src/ingest.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,41 @@ export interface UserOperationTarget {
124124
pieceExternalId: string | undefined
125125
}
126126

127-
export type DefaultUserOperations = {
128-
id: '__sofie-move-segment' // Future: define properly
127+
export enum DefaultUserOperationsTypes {
128+
REVERT_SEGMENT = '__sofie-revert-segment',
129+
REVERT_PART = '__sofie-revert-part',
130+
REVERT_RUNDOWN = '__sofie-revert-rundown',
131+
UPDATE_PROPS = '__sofie-update-props',
132+
}
133+
134+
export interface DefaultUserOperationRevertRundown {
135+
id: DefaultUserOperationsTypes.REVERT_RUNDOWN
136+
payload: Record<string, never>
137+
}
138+
139+
export interface DefaultUserOperationRevertSegment {
140+
id: DefaultUserOperationsTypes.REVERT_SEGMENT
129141
payload: Record<string, never>
130142
}
131143

144+
export interface DefaultUserOperationRevertPart {
145+
id: DefaultUserOperationsTypes.REVERT_PART
146+
}
147+
148+
export interface DefaultUserOperationEditProperties {
149+
id: DefaultUserOperationsTypes.UPDATE_PROPS
150+
payload: {
151+
pieceTypeProperties: { type: string; value: Record<string, any> }
152+
globalProperties: Record<string, any>
153+
}
154+
}
155+
156+
export type DefaultUserOperations =
157+
| DefaultUserOperationRevertRundown
158+
| DefaultUserOperationRevertSegment
159+
| DefaultUserOperationRevertPart
160+
| DefaultUserOperationEditProperties
161+
132162
export interface UserOperationChange<TCustomBlueprintOperations extends { id: string } = never> {
133163
/** Indicate that this change is from user operations */
134164
source: IngestChangeType.User

packages/blueprints-integration/src/userEditing.ts

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { JSONBlob } from '@sofie-automation/shared-lib/dist/lib/JSONBlob'
22
import type { ITranslatableMessage } from './translations'
3-
import type { JSONSchema } from '@sofie-automation/shared-lib/dist/lib/JSONSchemaTypes'
3+
import { JSONSchema } from '@sofie-automation/shared-lib/dist/lib/JSONSchemaTypes'
4+
import { SourceLayerType } from './content'
45

56
/**
67
* Description of a user performed editing operation allowed on an document
@@ -16,8 +17,10 @@ export interface UserEditingDefinitionAction {
1617
id: string
1718
/** Label to show to the user for this operation */
1819
label: ITranslatableMessage
19-
/** Icon to show to when this action is 'active' */
20+
/** Icon to show when this action is 'active' */
2021
svgIcon?: string
22+
/** Icon to show when this action is 'disabled' */
23+
svgIconInactive?: string
2124
/** Whether this action should be indicated as being active */
2225
isActive?: boolean
2326
}
@@ -40,6 +43,53 @@ export interface UserEditingDefinitionForm {
4043
export enum UserEditingType {
4144
/** Action */
4245
ACTION = 'action',
43-
/** Form of selections */
46+
/** Form */
4447
FORM = 'form',
4548
}
49+
50+
export interface UserEditingSourceLayer {
51+
sourceLayerLabel: string
52+
sourceLayerType: SourceLayerType
53+
schema: JSONBlob<JSONSchema>
54+
defaultValue?: Record<string, any>
55+
}
56+
57+
export interface UserEditingProperties {
58+
/**
59+
* These properties are dependent on the (primary) piece type, the user will get the option
60+
* to select the type of piece (from the SourceLayerTypes i.e. Camera or Split etc.) and then
61+
* be presented the corresponding form
62+
*
63+
* example:
64+
* {
65+
* schema: {
66+
* camera: '{ "type": "object", "properties": { "input": { "type": "number" } } }',
67+
* split: '{ "type": "object", ... }',
68+
* },
69+
* currentValue: {
70+
* type: 'camera',
71+
* value: {
72+
* input: 3
73+
* },
74+
* }
75+
* }
76+
*/
77+
pieceTypeProperties?: {
78+
schema: Record<string, UserEditingSourceLayer>
79+
currentValue: { type: string; value: Record<string, any> }
80+
}
81+
82+
/**
83+
* These are properties that are available to edit regardless of the piece type, examples
84+
* could be whether it an element is locked from NRCS updates
85+
*
86+
* if you do not want the piece type to be changed, then use only this field.
87+
*/
88+
globalProperties?: { schema: JSONBlob<JSONSchema>; currentValue: Record<string, any> }
89+
90+
/**
91+
* A list of id's of operations to be exposed on the properties panel as buttons. These operations
92+
* must be available on the element
93+
*/
94+
operations?: UserEditingDefinitionAction[]
95+
}

packages/corelib/src/dataModel/Part.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ITranslatableMessage } from '../TranslatableMessage'
33
import { PartId, RundownId, SegmentId } from './Ids'
44
import { PartNote } from './Notes'
55
import { ReadonlyDeep } from 'type-fest'
6-
import { CoreUserEditingDefinition } from './UserEditingDefinitions'
6+
import { CoreUserEditingDefinition, CoreUserEditingProperties } from './UserEditingDefinitions'
77

88
export interface PartInvalidReason {
99
message: ITranslatableMessage
@@ -41,6 +41,12 @@ export interface DBPart extends Omit<IBlueprintPart, 'userEditOperations'> {
4141
* User editing definitions for this part
4242
*/
4343
userEditOperations?: CoreUserEditingDefinition[]
44+
45+
/**
46+
* Properties that are user editable from the properties panel in the Sofie UI, if the user saves changes to these
47+
* it will trigger a user edit operation of type DefaultUserOperationEditProperties
48+
*/
49+
userEditProperties?: CoreUserEditingProperties
4450
}
4551

4652
export function isPartPlayable(part: Pick<ReadonlyDeep<DBPart>, 'invalid' | 'floated'>): boolean {

packages/corelib/src/dataModel/Piece.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from '@sofie-automation/blueprints-integration'
88
import { ProtectedString, protectString, unprotectString } from '../protectedString'
99
import { PieceId, RundownId, SegmentId, PartId } from './Ids'
10-
import { CoreUserEditingDefinition } from './UserEditingDefinitions'
10+
import { CoreUserEditingDefinition, CoreUserEditingProperties } from './UserEditingDefinitions'
1111

1212
/** A generic list of playback availability statuses for a Piece */
1313
export enum PieceStatusCode {
@@ -50,7 +50,9 @@ export interface PieceGeneric extends Omit<IBlueprintPieceGeneric, 'content'> {
5050
/** Stringified timelineObjects */
5151
timelineObjectsString: PieceTimelineObjectsBlob
5252
}
53-
export interface Piece extends PieceGeneric, Omit<IBlueprintPieceDB, '_id' | 'content' | 'userEditOperations'> {
53+
export interface Piece
54+
extends PieceGeneric,
55+
Omit<IBlueprintPieceDB, '_id' | 'content' | 'userEditOperations' | 'userEditProperties'> {
5456
/**
5557
* This is the id of the rundown this piece starts playing in.
5658
* Currently this is the only rundown the piece could be playing in
@@ -77,6 +79,12 @@ export interface Piece extends PieceGeneric, Omit<IBlueprintPieceDB, '_id' | 'co
7779
* User editing definitions for this piece
7880
*/
7981
userEditOperations?: CoreUserEditingDefinition[]
82+
83+
/**
84+
* Properties that are user editable from the properties panel in the Sofie UI, if the user saves changes to these
85+
* it will trigger a user edit operation of type DefaultUserOperationEditProperties
86+
*/
87+
userEditProperties?: CoreUserEditingProperties
8088
}
8189

8290
export type PieceTimelineObjectsBlob = ProtectedString<'PieceTimelineObjectsBlob'>

packages/corelib/src/dataModel/Segment.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { SegmentDisplayMode, SegmentTimingInfo } from '@sofie-automation/blueprints-integration'
22
import { SegmentId, RundownId } from './Ids'
33
import { SegmentNote } from './Notes'
4-
import { CoreUserEditingDefinition } from './UserEditingDefinitions'
4+
import { CoreUserEditingDefinition, CoreUserEditingProperties } from './UserEditingDefinitions'
55

66
export enum SegmentOrphanedReason {
77
/** Segment is deleted from the NRCS but we still need it */
@@ -51,4 +51,10 @@ export interface DBSegment {
5151
* User editing definitions for this segment
5252
*/
5353
userEditOperations?: CoreUserEditingDefinition[]
54+
55+
/**
56+
* Properties that are user editable from the properties panel in the Sofie UI, if the user saves changes to these
57+
* it will trigger a user edit operation of type DefaultUserOperationEditProperties
58+
*/
59+
userEditProperties?: CoreUserEditingProperties
5460
}

0 commit comments

Comments
 (0)