Skip to content

Commit 7b46c81

Browse files
committed
chore: convert some components to be functional
1 parent 4778988 commit 7b46c81

File tree

2 files changed

+125
-160
lines changed

2 files changed

+125
-160
lines changed

packages/webui/src/client/ui/Shelf/DashboardActionButton.tsx

Lines changed: 66 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -16,103 +16,87 @@ export interface IDashboardButtonProps {
1616
onButtonUp: (button: DashboardLayoutActionButton, e: React.SyntheticEvent<HTMLElement>) => void
1717
}
1818

19-
export class DashboardActionButton extends React.Component<IDashboardButtonProps> {
20-
constructor(props: IDashboardButtonProps) {
21-
super(props)
22-
}
23-
24-
private getSpecialClasses() {
25-
const { button } = this.props
19+
export function DashboardActionButton({
20+
button,
21+
playlist,
22+
studioMode,
23+
onButtonDown,
24+
onButtonUp,
25+
}: IDashboardButtonProps): JSX.Element {
26+
const getSpecialClasses = () => {
2627
switch (button.type) {
2728
case ActionButtonType.READY_ON_AIR:
2829
return {
29-
rehearsal: this.props.playlist.rehearsal,
30-
active: !!this.props.playlist.activationId,
30+
rehearsal: playlist.rehearsal,
31+
active: !!playlist.activationId,
3132
}
3233
default:
3334
return {}
3435
}
3536
}
3637

37-
private isToggled() {
38-
const { button } = this.props
39-
switch (button.type) {
40-
case ActionButtonType.READY_ON_AIR:
41-
return !!this.props.playlist.rehearsal || !!this.props.playlist.activationId
42-
default:
43-
return false
44-
}
45-
}
46-
47-
private getLabel() {
48-
const { button } = this.props
49-
return this.isToggled() && button.labelToggled && button.labelToggled.length > 0
50-
? button.labelToggled
51-
: button.label
52-
}
38+
const isToggled = button.type === ActionButtonType.READY_ON_AIR && (!!playlist.rehearsal || !!playlist.activationId)
5339

54-
render(): JSX.Element {
55-
const { button } = this.props
40+
const label = isToggled && button.labelToggled && button.labelToggled.length > 0 ? button.labelToggled : button.label
5641

57-
return (
58-
<div
59-
className="dashboard-panel dashboard-panel--actions"
60-
style={{
61-
width:
62-
button.width >= 0
63-
? `calc((${button.width} * var(--dashboard-button-grid-width)) + var(--dashboard-panel-margin-width))`
42+
return (
43+
<div
44+
className="dashboard-panel dashboard-panel--actions"
45+
style={{
46+
width:
47+
button.width >= 0
48+
? `calc((${button.width} * var(--dashboard-button-grid-width)) + var(--dashboard-panel-margin-width))`
49+
: undefined,
50+
height:
51+
button.height >= 0
52+
? `calc((${button.height} * var(--dashboard-button-grid-height)) + var(--dashboard-panel-margin-height))`
53+
: undefined,
54+
left:
55+
button.x >= 0
56+
? `calc(${button.x} * var(--dashboard-button-grid-width))`
57+
: button.width < 0
58+
? `calc(${-1 * button.width - 1} * var(--dashboard-button-grid-width))`
6459
: undefined,
65-
height:
66-
button.height >= 0
67-
? `calc((${button.height} * var(--dashboard-button-grid-height)) + var(--dashboard-panel-margin-height))`
60+
top:
61+
button.y >= 0
62+
? `calc(${button.y} * var(--dashboard-button-grid-height) * 1.022)`
63+
: button.height < 0
64+
? `calc(${-1 * button.height - 1} * var(--dashboard-button-grid-height)) * 1.022`
6865
: undefined,
69-
left:
70-
button.x >= 0
71-
? `calc(${button.x} * var(--dashboard-button-grid-width))`
72-
: button.width < 0
73-
? `calc(${-1 * button.width - 1} * var(--dashboard-button-grid-width))`
74-
: undefined,
75-
top:
76-
button.y >= 0
77-
? `calc(${button.y} * var(--dashboard-button-grid-height) * 1.022)`
78-
: button.height < 0
79-
? `calc(${-1 * button.height - 1} * var(--dashboard-button-grid-height)) * 1.022`
80-
: undefined,
81-
right:
82-
button.x < 0
83-
? `calc(${-1 * button.x - 1} * var(--dashboard-button-grid-width))`
84-
: button.width < 0
85-
? `calc(${-1 * button.width - 1} * var(--dashboard-button-grid-width))`
86-
: undefined,
87-
bottom:
88-
button.y < 0
89-
? `calc(${-1 * button.y - 1} * var(--dashboard-button-grid-height))`
90-
: button.height < 0
91-
? `calc(${-1 * button.height - 1} * var(--dashboard-button-grid-height))`
92-
: undefined,
93-
}}
94-
>
95-
<div className="dashboard-panel__panel">
96-
<div
97-
className={ClassNames(
98-
'dashboard-panel__panel__button',
99-
'dashboard-panel__panel__button--standalone',
100-
`type--${button.type}`,
101-
this.getSpecialClasses(),
102-
{ uninteractive: !this.props.studioMode }
103-
)}
104-
onMouseDown={(e) => this.props.onButtonDown(button, e)}
105-
onMouseUp={(e) => this.props.onButtonUp(button, e)}
106-
data-obj-id={button.type}
107-
>
108-
<div className="dashboard-panel__panel__button__content">
109-
<div className="dashboard-panel__panel__button__label-container">
110-
<span className="dashboard-panel__panel__button__label">{this.getLabel()}</span>
111-
</div>
66+
right:
67+
button.x < 0
68+
? `calc(${-1 * button.x - 1} * var(--dashboard-button-grid-width))`
69+
: button.width < 0
70+
? `calc(${-1 * button.width - 1} * var(--dashboard-button-grid-width))`
71+
: undefined,
72+
bottom:
73+
button.y < 0
74+
? `calc(${-1 * button.y - 1} * var(--dashboard-button-grid-height))`
75+
: button.height < 0
76+
? `calc(${-1 * button.height - 1} * var(--dashboard-button-grid-height))`
77+
: undefined,
78+
}}
79+
>
80+
<div className="dashboard-panel__panel">
81+
<div
82+
className={ClassNames(
83+
'dashboard-panel__panel__button',
84+
'dashboard-panel__panel__button--standalone',
85+
`type--${button.type}`,
86+
getSpecialClasses(),
87+
{ uninteractive: !studioMode }
88+
)}
89+
onMouseDown={(e) => onButtonDown(button, e)}
90+
onMouseUp={(e) => onButtonUp(button, e)}
91+
data-obj-id={button.type}
92+
>
93+
<div className="dashboard-panel__panel__button__content">
94+
<div className="dashboard-panel__panel__button__label-container">
95+
<span className="dashboard-panel__panel__button__label">{label}</span>
11296
</div>
11397
</div>
11498
</div>
11599
</div>
116-
)
117-
}
100+
</div>
101+
)
118102
}

packages/webui/src/client/ui/Shelf/MiniRundownPanel.tsx

Lines changed: 59 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as React from 'react'
1+
import React, { memo, useEffect } from 'react'
22
import _ from 'underscore'
33
import ClassNames from 'classnames'
44
import {
@@ -7,7 +7,7 @@ import {
77
RundownLayoutMiniRundown,
88
} from '@sofie-automation/meteor-lib/dist/collections/RundownLayouts'
99
import { RundownLayoutsAPI } from '../../lib/rundownLayouts.js'
10-
import { withTracker } from '../../lib/ReactMeteorData/ReactMeteorData.js'
10+
import { useTracker } from '../../lib/ReactMeteorData/ReactMeteorData.js'
1111
import { DBRundownPlaylist } from '@sofie-automation/corelib/dist/dataModel/RundownPlaylist'
1212
import { PartInstance } from '@sofie-automation/meteor-lib/dist/collections/PartInstances'
1313
import { DBSegment } from '@sofie-automation/corelib/dist/dataModel/Segment'
@@ -18,77 +18,80 @@ import { UIPartInstances } from '../Collections.js'
1818
import { RundownPlaylistClientUtil } from '../../lib/rundownPlaylistUtil.js'
1919

2020
interface IMiniRundownPanelProps {
21-
key: string
2221
visible?: boolean
2322
layout: RundownLayoutBase
2423
panel: RundownLayoutMiniRundown
2524
playlist: DBRundownPlaylist
2625
}
2726

28-
interface IMiniRundownPanelTrackedProps {
29-
currentPartInstance?: PartInstance
30-
nextPartInstance?: PartInstance
31-
allSegments?: DBSegment[]
32-
}
33-
34-
interface IState {}
35-
3627
interface MiniRundownSegment {
3728
identifier: string
3829
segmentName: string
3930
cssClass: string
4031
}
4132

42-
export class MiniRundownPanelInner extends React.Component<IMiniRundownPanelProps & IMiniRundownPanelTrackedProps> {
43-
static currentSegmentCssClass = 'current-segment'
44-
static nextSegmentCssClass = 'next-segment'
45-
static panelContainerId = 'mini-rundown-panel__container'
46-
static nextSegmentId = 'mini-rundown__next-segment'
47-
static currentSegmentId = 'mini-rundown__current-segment'
33+
const MiniRundownPanelClassesAndIds = {
34+
currentSegmentCssClass: 'current-segment',
35+
nextSegmentCssClass: 'next-segment',
36+
panelContainerId: 'mini-rundown-panel__container',
37+
nextSegmentId: 'mini-rundown__next-segment',
38+
currentSegmentId: 'mini-rundown__current-segment',
39+
}
4840

49-
componentDidMount(): void {
50-
this.scrollIntoView()
51-
}
41+
export const MiniRundownPanel = memo(
42+
function MiniRundownPanelInner2(props: IMiniRundownPanelProps) {
43+
// Trigger on mount, or when any props change
44+
useEffect(() => {
45+
Meteor.setTimeout(() => {
46+
const container = document.getElementById(MiniRundownPanelClassesAndIds.panelContainerId)
47+
if (!container) return
48+
const nextElement = document.getElementById(MiniRundownPanelClassesAndIds.nextSegmentId)
49+
const currentElement = document.getElementById(MiniRundownPanelClassesAndIds.currentSegmentId)
50+
if (nextElement) {
51+
container.scrollTop = nextElement.offsetTop - nextElement.clientHeight
52+
} else if (currentElement) {
53+
container.scrollTop = currentElement.offsetTop
54+
}
55+
}, 500)
56+
}, [...Object.values<any>(props)])
5257

53-
componentDidUpdate(): void {
54-
this.scrollIntoView()
55-
}
56-
57-
private scrollIntoView() {
58-
Meteor.setTimeout(() => {
59-
const container = document.getElementById(MiniRundownPanelInner.panelContainerId)
60-
if (!container) return
61-
const nextElement = document.getElementById(MiniRundownPanelInner.nextSegmentId)
62-
const currentElement = document.getElementById(MiniRundownPanelInner.currentSegmentId)
63-
if (nextElement) {
64-
container.scrollTop = nextElement.offsetTop - nextElement.clientHeight
65-
} else if (currentElement) {
66-
container.scrollTop = currentElement.offsetTop
67-
}
68-
}, 500)
69-
}
58+
const currentPartInstanceId: PartInstanceId | undefined = props.playlist.currentPartInfo?.partInstanceId
59+
const currentPartInstance = useTracker(
60+
() => currentPartInstanceId && UIPartInstances.findOne(currentPartInstanceId),
61+
[currentPartInstanceId]
62+
)
7063

71-
render(): JSX.Element {
72-
const isDashboardLayout = RundownLayoutsAPI.isDashboardLayout(this.props.layout)
73-
const style = getElementStyle(this.props, isDashboardLayout)
64+
const nextPartInstanceId: PartInstanceId | undefined = props.playlist.nextPartInfo?.partInstanceId
65+
const nextPartInstance = useTracker(
66+
() => nextPartInstanceId && UIPartInstances.findOne(nextPartInstanceId),
67+
[nextPartInstanceId]
68+
)
7469

75-
const miniRundowns: MiniRundownSegment[] = getMiniRundownList(
76-
this.props.allSegments,
77-
this.props.currentPartInstance,
78-
this.props.nextPartInstance
70+
const allSegments: DBSegment[] = useTracker(
71+
() => RundownPlaylistClientUtil.getSegments(props.playlist),
72+
[props.playlist._id, props.playlist.rundownIdsInOrder],
73+
[]
7974
)
8075

76+
const isDashboardLayout = RundownLayoutsAPI.isDashboardLayout(props.layout)
77+
const style = getElementStyle(props, isDashboardLayout)
78+
79+
const miniRundowns: MiniRundownSegment[] = getMiniRundownList(allSegments, currentPartInstance, nextPartInstance)
80+
8181
return (
8282
<div
8383
key={'miniRundownContainer'}
84-
className={ClassNames('dashboard-panel mini-rundown-panel', getContainerClass(this.props, isDashboardLayout))}
85-
style={getContainerStyle(this.props, isDashboardLayout)}
84+
className={ClassNames('dashboard-panel mini-rundown-panel', getContainerClass(props, isDashboardLayout))}
85+
style={getContainerStyle(props, isDashboardLayout)}
8686
>
8787
<span className="mini-rundown-panel__name" style={style} key={'miniRundownHeader'}>
88-
{this.props.panel.name}{' '}
88+
{props.panel.name}{' '}
8989
</span>
9090

91-
<div className={MiniRundownPanelInner.panelContainerId} id={MiniRundownPanelInner.panelContainerId}>
91+
<div
92+
className={MiniRundownPanelClassesAndIds.panelContainerId}
93+
id={MiniRundownPanelClassesAndIds.panelContainerId}
94+
>
9295
{miniRundowns.map((miniRundown: MiniRundownSegment, index: number) => (
9396
<div
9497
className={miniRundown.cssClass}
@@ -113,31 +116,9 @@ export class MiniRundownPanelInner extends React.Component<IMiniRundownPanelProp
113116
</div>
114117
</div>
115118
)
116-
}
117-
}
118-
119-
export const MiniRundownPanel = withTracker<IMiniRundownPanelProps, IState, IMiniRundownPanelTrackedProps>(
120-
(props: IMiniRundownPanelProps & IMiniRundownPanelTrackedProps) => {
121-
let currentPartInstance: PartInstance | undefined = undefined
122-
let nextPartInstance: PartInstance | undefined = undefined
123-
124-
const currentPartInstanceId: PartInstanceId | undefined = props.playlist.currentPartInfo?.partInstanceId
125-
if (currentPartInstanceId) {
126-
currentPartInstance = UIPartInstances.findOne(currentPartInstanceId)
127-
}
128-
129-
if (props.playlist.nextPartInfo) {
130-
nextPartInstance = UIPartInstances.findOne(props.playlist.nextPartInfo.partInstanceId)
131-
}
132-
133-
const allSegments: DBSegment[] = RundownPlaylistClientUtil.getSegments(props.playlist)
134-
135-
return { currentPartInstance, nextPartInstance, allSegments }
136119
},
137-
(_data, props: IMiniRundownPanelProps, nextProps: IMiniRundownPanelProps) => {
138-
return !_.isEqual(props, nextProps)
139-
}
140-
)(MiniRundownPanelInner)
120+
(prevProps, nextProps) => _.isEqual(prevProps, nextProps)
121+
)
141122

142123
function getMiniRundownList(
143124
allSegments?: DBSegment[],
@@ -160,11 +141,11 @@ function getMiniRundownList(
160141

161142
function getSegmentCssClass(segment: DBSegment, currentPart?: PartInstance, nextPart?: PartInstance): string {
162143
if (segment._id === currentPart?.segmentId) {
163-
return MiniRundownPanelInner.currentSegmentCssClass
144+
return MiniRundownPanelClassesAndIds.currentSegmentCssClass
164145
}
165146

166147
if (segment._id === nextPart?.segmentId) {
167-
return MiniRundownPanelInner.nextSegmentCssClass
148+
return MiniRundownPanelClassesAndIds.nextSegmentCssClass
168149
}
169150

170151
return ''
@@ -200,10 +181,10 @@ function getElementKey(prefix: string, identifier: string, index: number): strin
200181

201182
function getIdAttributeForNextSegment(cssClass: string) {
202183
switch (cssClass) {
203-
case MiniRundownPanelInner.nextSegmentCssClass:
204-
return { id: MiniRundownPanelInner.nextSegmentId }
205-
case MiniRundownPanelInner.currentSegmentCssClass:
206-
return { id: MiniRundownPanelInner.currentSegmentId }
184+
case MiniRundownPanelClassesAndIds.nextSegmentCssClass:
185+
return { id: MiniRundownPanelClassesAndIds.nextSegmentId }
186+
case MiniRundownPanelClassesAndIds.currentSegmentCssClass:
187+
return { id: MiniRundownPanelClassesAndIds.currentSegmentId }
207188
default:
208189
return {}
209190
}

0 commit comments

Comments
 (0)