Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/UI useredit panel #22

Merged
merged 93 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
2b4c08c
wip: initial draft implementation of userEditPanel
olzzon Oct 14, 2024
c1e8e10
wip: userEditPanel grouping
olzzon Oct 15, 2024
fb54ad2
wip: userEditPanel cleanup remove schema as it's replaces by schemas
olzzon Oct 16, 2024
7fd9bf1
wip: userEditPanel styling and use <select> for list
olzzon Oct 16, 2024
040dbc4
wip: userEditPanel - make groupType optional to allow empty slots
olzzon Oct 16, 2024
d49b265
wip: userEditPanel - convert to FC
olzzon Oct 16, 2024
d93d0a9
wip: userEditPanel - uncomment context menu
olzzon Oct 17, 2024
9cbc324
wip: UserEditPanel - Add DefaultUserOperationsTypes for revert button…
olzzon Oct 17, 2024
0643ff3
wip: UserEditPanel - Default revert button on panel
olzzon Oct 17, 2024
9d46129
wip: UserEditPanel - tracker on part and segment
olzzon Oct 17, 2024
27a2680
wip: UserEditPanel - only render Segment or Part in panel
olzzon Oct 21, 2024
298d10c
wip: UserEditPanel - initial header for part and segment
olzzon Oct 21, 2024
526211e
wip: UserEditPanel - comment for the usage of getTimePosition
olzzon Oct 21, 2024
a673847
wip: UserEditPanel - add Icons in header
olzzon Oct 21, 2024
5324fa3
wip: UserEditPanel - add button type in UserEditingDefinitions
olzzon Oct 21, 2024
c8b7e79
wip: UserEditPanel - rename revert button to "Revert Changes"
olzzon Oct 21, 2024
a1fc06b
wip: UserEditPanel - add support for SVG icons in grouping (e.g for s…
olzzon Oct 22, 2024
c76ec35
wip: UserEditPanel - center revert button
olzzon Oct 22, 2024
c6d0bf5
wip: Renaming UserEditPanel to PropertiesPanel
olzzon Oct 22, 2024
163cb46
wip: UI selection - Context for SelectedElements
olzzon Oct 23, 2024
e037d59
wip: UI selection - refactor from useState() to useReducer()
olzzon Oct 24, 2024
7fe136f
wip: UI selection - use type for SelectedElement
olzzon Oct 24, 2024
061d61f
wip: UI selection -Segment not updating upon selection
olzzon Oct 24, 2024
2a252e8
feat: unit tests for SelectedElementsContext
olzzon Oct 24, 2024
1710bb4
wip: UI selection - add isSelected to withSegmentTiming
olzzon Oct 25, 2024
c00b2fd
wip: fix props withSelection
olzzon Oct 25, 2024
3a3b9ff
wip: fix props withSelection
olzzon Oct 25, 2024
02b9a41
wip: remove componentDidUpdate - leftover from previous debugging
olzzon Oct 25, 2024
030163e
fix: added listSelectedElements() instead of exposing the selectedEle…
olzzon Oct 25, 2024
ad46b36
fix: add assertNever() to selectionReducer
olzzon Oct 25, 2024
e760534
fix: remove id and use ElementId as reference in context provider
olzzon Oct 25, 2024
73753f8
fix: clean up isSelected should parse boolean not function as props
olzzon Oct 25, 2024
14e03fe
chore: update package with @testing-library/react
olzzon Oct 25, 2024
cb43189
fix: tests for SelecedElementsContext updated and type fixed
olzzon Oct 25, 2024
875a438
fix: listSelectedElements is af function not an array
olzzon Oct 25, 2024
382179c
wip: implement useSelection in PropertiesPanel
olzzon Oct 25, 2024
3222f65
wip: useSelection on Parts
olzzon Oct 25, 2024
ef2c47d
fix: missing rundown id in propertiespanel actions
olzzon Oct 25, 2024
2ad708a
feat: add enabling of userediting in settings
olzzon Oct 31, 2024
7a79afa
feat: doubleclick on part selection for properties panel
olzzon Oct 31, 2024
2169357
fix: properties panel crash when no selection was made
olzzon Oct 31, 2024
a6a431c
feat: segment selection
olzzon Oct 31, 2024
8dc7700
feat: dbl click anywhere in segment header to select properties
olzzon Oct 31, 2024
48521c6
feat: select part by double clicking a piece
olzzon Oct 31, 2024
8220392
feat: properties panel commit button for pending changes
olzzon Oct 31, 2024
3aaea87
feat: select/deselect an element - fix flickering upen commit changes
olzzon Nov 1, 2024
07bd3ec
fix: render all userEditOperations when part is selected
olzzon Nov 1, 2024
ba03df0
feat: move Properties panel out of notification center logic
olzzon Nov 4, 2024
52a0d54
feat: use context.consumer instead of wrapping
olzzon Nov 4, 2024
8bdc2cd
feat: refactor userEditing structure
olzzon Nov 6, 2024
662681e
feat: properties panel with refactored data structure.
olzzon Nov 6, 2024
091af40
feat: Schema selection implemented in commit button logic
olzzon Nov 6, 2024
4d58ce8
feat: implement Layer colors in group selectors
olzzon Nov 6, 2024
4ef35fd
feat: only parse the selected source on useraction commit
olzzon Nov 7, 2024
525cd59
feat: simplify structure for userEditing source
olzzon Nov 7, 2024
3a5bda0
fix: rerender group selection when selecting new part
olzzon Nov 7, 2024
5e547ce
fix: read the SourceLayerType into UserEditingDefinition
olzzon Nov 7, 2024
3978c2b
feat: selected element indicator
olzzon Nov 7, 2024
6470d43
feat: properties panel styling - is edited indication
olzzon Nov 8, 2024
b674e2d
wip: add close propterties icon (sketch)
olzzon Nov 8, 2024
4bd57d6
wip: properties panel css dim commit+revert when not active
olzzon Nov 8, 2024
cb2455b
wip: properties panel clean up first iteration selector
olzzon Nov 8, 2024
b4d75dd
wip: properties panel add close upper right
olzzon Nov 8, 2024
15d77e8
fix: crash UI - remove transiongroup
olzzon Nov 8, 2024
7b65130
feat: properties panel animate in and shrink rundown view
olzzon Nov 8, 2024
8666da3
fix: cleanup using notificationpanel for properties panel
olzzon Nov 8, 2024
631ef97
wip: properties panel, rightbar icon color
olzzon Nov 8, 2024
ad78549
fix: re-run only if part.segmentId has changed
olzzon Nov 9, 2024
d3e0ca7
wip: tests for properties panel
olzzon Nov 9, 2024
5fe974f
wip: properties panel tests - useFaketimers and implement mock useTra…
olzzon Nov 11, 2024
b86bc21
wip: properties panel - element selection styling
olzzon Nov 11, 2024
e6d4c94
wip: properties panel styling edit pencil icon
olzzon Nov 11, 2024
e0969ef
wip: properties panel close when notification is open
olzzon Nov 12, 2024
6a10475
wip: properties panel selection glow on segment header
olzzon Nov 12, 2024
61c73a0
feat: StyledSchemaFormInPlace schema component
olzzon Nov 13, 2024
958d8e3
fix: Properties panel - StyledSchemaFormInPlace schema for normal form
olzzon Nov 13, 2024
7f5fa09
feat: Properties panel is edited pencil styling
olzzon Nov 13, 2024
d623cc6
feat: Properties header styling
olzzon Nov 13, 2024
75b1930
wip: Properties tests - more mocking to get correct rendering in test…
olzzon Nov 13, 2024
91dae54
chore: fix unit tests
mint-dewit Nov 21, 2024
77bf227
feat: refactor form action to properties field
mint-dewit Nov 27, 2024
aa35b1b
chore: update styles
mint-dewit Dec 2, 2024
ea2fb4a
chore: add actions back into property panel
mint-dewit Dec 2, 2024
a671baa
chore: support translations for properties panel
mint-dewit Dec 5, 2024
53488d2
chore: fix some build issues
mint-dewit Dec 5, 2024
ffdde73
Merge pull request #38 from bbc/chore/ui-useredit-properties
mint-dewit Dec 5, 2024
80ae9d8
feat: allow editing piece properties
mint-dewit Dec 6, 2024
50d869e
chore: various review comments
mint-dewit Dec 10, 2024
e4cf90e
chore: fix tests
mint-dewit Dec 11, 2024
91e9431
chore: merge bbc-release52 into feat/ui-useredit-panel
mint-dewit Dec 11, 2024
8f9df89
chore: merge bbc-release52 into feat/useredit-panel
mint-dewit Dec 12, 2024
dedebee
chore: remove unused parameter
mint-dewit Dec 12, 2024
287f007
chore: removed commented styles
mint-dewit Dec 13, 2024
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
Prev Previous commit
Next Next commit
feat: doubleclick on part selection for properties panel
  • Loading branch information
olzzon committed Oct 31, 2024
commit 7a79afac14c0f06e8b704fe852ddfd77a0b601aa
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'
import {
AdLibActionId,
PartInstanceId,
PieceId,
PieceInstanceId,
RundownId,
SegmentId,
} from '@sofie-automation/corelib/dist/dataModel/Ids'
Expand All @@ -23,9 +23,9 @@ interface PartInstanceElement {
elementId: PartInstanceId
}

interface PieceElement {
type: 'piece'
elementId: PieceId
interface PieceInstanceElement {
type: 'pieceInstance'
elementId: PieceInstanceId
}

interface AdlibActionElement {
Expand All @@ -34,7 +34,7 @@ interface AdlibActionElement {
}

// Union types for all possible elements
type SelectedElement = RundownElement | SegmentElement | PartInstanceElement | PieceElement | AdlibActionElement
type SelectedElement = RundownElement | SegmentElement | PartInstanceElement | PieceInstanceElement | AdlibActionElement
type ElementId = SelectedElement['elementId']

export interface SelectionContextType {
Expand Down Expand Up @@ -155,11 +155,13 @@ export const useSelection = (): SelectionContextType => {
}

// Helper hook for common selection patterns
export const useElementSelection = (element: SelectedElement): { isSelected: boolean; toggleSelection: () => void } => {
const { isSelected, toggleSelection } = useSelection()
export const useElementSelection = (
element: SelectedElement
): { isSelected: boolean; clearAndSetSelection: () => void } => {
const { isSelected, clearAndSetSelection } = useSelection()

return {
isSelected: React.useMemo(() => isSelected(element.elementId), [isSelected, element.elementId]),
toggleSelection: React.useCallback(() => toggleSelection(element), [toggleSelection, element]),
clearAndSetSelection: React.useCallback(() => clearAndSetSelection(element), [clearAndSetSelection, element]),
}
}
46 changes: 39 additions & 7 deletions packages/webui/src/client/ui/SegmentTimeline/SourceLayerItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { TransitionSourceRenderer } from './Renderers/TransitionSourceRenderer'
import { UIStudio } from '@sofie-automation/meteor-lib/dist/api/studios'
import { ReadonlyDeep } from 'type-fest'
import { PieceContentStatusObj } from '@sofie-automation/meteor-lib/dist/api/pieceContentStatus'
import { useSelection } from '../RundownView/SelectedElementsContext'
const LEFT_RIGHT_ANCHOR_SPACER = 15
const MARGINAL_ANCHORED_WIDTH = 5

Expand Down Expand Up @@ -102,11 +103,20 @@ interface ISourceLayerItemState {
/** Set to `true` when the segment is "highlighted" (in focus, generally from a scroll event) */
highlight: boolean
}
export const SourceLayerItem = withTranslation()(
class SourceLayerItem extends React.Component<ISourceLayerItemProps & WithTranslation, ISourceLayerItemState> {

interface WithSelectionProps {
handlePieceSelect: (piece: PieceUi, e: React.MouseEvent<HTMLDivElement>) => void
isPieceSelected: boolean
}

const SourceLayerItemWithSelection = withTranslation()(
class SourceLayerItem extends React.Component<
ISourceLayerItemProps & WithTranslation & WithSelectionProps,
ISourceLayerItemState
> {
animFrameHandle: number | undefined

constructor(props: ISourceLayerItemProps & WithTranslation) {
constructor(props: ISourceLayerItemProps & WithTranslation & WithSelectionProps) {
super(props)
this.state = {
showMiniInspector: false,
Expand Down Expand Up @@ -465,11 +475,15 @@ export const SourceLayerItem = withTranslation()(
}

itemDblClick = (e: React.MouseEvent<HTMLDivElement>) => {
e.preventDefault()
e.stopPropagation()
if (this.props.studio?.settings.enableUserEdits) {
this.props.handlePieceSelect(this.props.piece, e)
} else {
e.preventDefault()
e.stopPropagation()

if (typeof this.props.onDoubleClick === 'function') {
this.props.onDoubleClick(this.props.piece, e)
if (typeof this.props.onDoubleClick === 'function') {
this.props.onDoubleClick(this.props.piece, e)
}
}
}

Expand Down Expand Up @@ -714,3 +728,21 @@ export const SourceLayerItem = withTranslation()(
}
}
)

export const SourceLayerItem = (props: ISourceLayerItemProps & WithTranslation): React.ReactElement => {
const { isSelected, clearAndSetSelection } = useSelection()

const isPieceSelected = isSelected(props.piece.instance._id)

const handlePieceSelect = React.useCallback(
(piece: PieceUi, e: React.MouseEvent<HTMLDivElement>) => {
clearAndSetSelection({ type: 'pieceInstance', elementId: piece.instance._id })
props.onClick?.(piece, e)
},
[isPieceSelected]
)

return (
<SourceLayerItemWithSelection {...props} handlePieceSelect={handlePieceSelect} isPieceSelected={isPieceSelected} />
)
}
122 changes: 63 additions & 59 deletions packages/webui/src/client/ui/UserEditOperations/PropertiesPanel.tsx
mint-dewit marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import * as React from 'react'
// @ts-expect-error No types available
import * as VelocityReact from 'velocity-react'
import { i18nTranslator } from '../i18n'
import { translateMessage } from '@sofie-automation/corelib/dist/TranslatableMessage'
import { doUserAction, UserAction } from '../../lib/clientUserAction'
Expand All @@ -22,7 +20,7 @@ import {
import { useTranslation } from 'react-i18next'
import { useTracker } from '../../lib/ReactMeteorData/ReactMeteorData'
import _ from 'underscore'
import { Segments } from '../../collections'
import { Segments, PieceInstances } from '../../collections'
import { UIPartInstances, UIParts } from '../Collections'
import { useSelection } from '../RundownView/SelectedElementsContext'
import { DBSegment } from '@sofie-automation/corelib/dist/dataModel/Segment'
Expand All @@ -46,75 +44,81 @@ export function PropertiesPanel(): JSX.Element {
}
}, [])

const pieceInstance = useTracker(
() => PieceInstances.findOne({ _id: selectedElement.elementId }),
[selectedElement?.elementId]
)

const partInstance = useTracker(
() => UIPartInstances.findOne({ _id: selectedElement.elementId }),
[selectedElement.elementId]
() => UIPartInstances.findOne({ _id: pieceInstance ? pieceInstance.partInstanceId : selectedElement.elementId }),
[selectedElement?.elementId]
)
const part = useTracker(() => UIParts.findOne({ _id: partInstance?.part._id }), [partInstance?.part._id])

const segment: DBSegment | undefined = useTracker(
() => Segments.findOne({ _id: part ? part.segmentId : selectedElement.elementId }),
[selectedElement.elementId]
[selectedElement?.elementId]
)
const rundownId = part ? part.rundownId : segment?.rundownId

if (!rundownId) return <></>

return (
<div className="propertiespanel-pop-up">
{selectedElement.type === 'partInstance' && (
<>
<div className="propertiespanel-pop-up__header">
{part?.userEditOperations &&
part.userEditOperations.map((operation) => {
if (operation.type === UserEditingType.FORM || !operation.svgIcon || !operation.isActive) return null
{selectedElement.type === 'partInstance' ||
(selectedElement.type === 'pieceInstance' && (
<>
<div className="propertiespanel-pop-up__header">
{part?.userEditOperations &&
part.userEditOperations.map((operation) => {
if (operation.type === UserEditingType.FORM || !operation.svgIcon || !operation.isActive) return null

return (
<div
key={operation.id}
className="svg"
dangerouslySetInnerHTML={{
__html: operation.svgIcon,
}}
></div>
)
})}
PART : {String(part?.title)}
</div>
<div className="propertiespanel-pop-up__contents">
{segment &&
part?._id &&
part.userEditOperations?.map((userEditOperation, i) => {
switch (userEditOperation.type) {
case UserEditingType.ACTION:
return (
<EditingTypeAction
key={i}
userEditOperation={userEditOperation}
segment={segment}
part={part}
rundownId={rundownId}
/>
)
case UserEditingType.FORM:
return (
<EditingTypeChangeSource
key={i}
userEditOperation={userEditOperation}
segment={segment}
part={part}
rundownId={rundownId}
/>
)
default:
assertNever(userEditOperation)
return null
}
})}
<hr />
</div>
</>
)}
return (
<div
key={operation.id}
className="svg"
dangerouslySetInnerHTML={{
__html: operation.svgIcon,
}}
></div>
)
})}
PART : {String(part?.title)}
</div>
<div className="propertiespanel-pop-up__contents">
{segment &&
part?._id &&
part.userEditOperations?.map((userEditOperation, i) => {
mint-dewit marked this conversation as resolved.
Show resolved Hide resolved
switch (userEditOperation.type) {
case UserEditingType.ACTION:
return (
<EditingTypeAction
key={i}
userEditOperation={userEditOperation}
segment={segment}
part={part}
rundownId={rundownId}
/>
)
case UserEditingType.FORM:
return (
<EditingTypeChangeSource
key={i}
userEditOperation={userEditOperation}
segment={segment}
part={part}
rundownId={rundownId}
/>
)
default:
assertNever(userEditOperation)
return null
}
})}
<hr />
</div>
</>
))}
{selectedElement.type === 'segment' && (
<>
<div className="propertiespanel-pop-up__header">
Expand Down Expand Up @@ -305,7 +309,7 @@ function EditingTypeChangeSource(props: {
enum: string[]
tsEnumNames: string[]
}
let groups: UserEditingGroupingType[] = clone(props.userEditOperation.grouping) || []
const groups: UserEditingGroupingType[] = clone(props.userEditOperation.grouping) || []
const numberOfEmptySlots = 14 - groups.length
for (let i = 0; i < numberOfEmptySlots; i++) {
groups.push({})
Expand Down