Skip to content

Commit 82cefc0

Browse files
committed
feat: add custom icon display on Pieces
chore: lint
1 parent 770e635 commit 82cefc0

15 files changed

Lines changed: 126 additions & 40 deletions

packages/webui/src/client/lib/Components/FloatInput.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export function FloatInputControl({
5252
const handleBlur = useCallback(
5353
(event: React.FocusEvent<HTMLInputElement>) => {
5454
if (readOnly) return
55-
55+
5656
const number = parseFloat(event.currentTarget.value.replace(',', '.'))
5757
if (!isNaN(number)) {
5858
handleUpdate(zeroBased ? number - 1 : number)
@@ -68,7 +68,7 @@ export function FloatInputControl({
6868
const handleKeyUp = useCallback(
6969
(event: React.KeyboardEvent<HTMLInputElement>) => {
7070
if (readOnly) return
71-
71+
7272
if (event.key === 'Escape') {
7373
setEditingValue(null)
7474
} else if (event.key === 'Enter') {

packages/webui/src/client/lib/Components/TimeMsInput.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,16 @@ export function TimeMsInputControl({
100100
}: Readonly<ITimeMsInputControlProps>): JSX.Element {
101101
const [editingValue, setEditingValue] = useState<string | null>(null)
102102

103-
const isValidValue = useCallback((value: number): boolean => {
104-
if (isNaN(value) || value < 0) return false
105-
if (min !== undefined && value < min) return false
106-
if (max !== undefined && value > max) return false
107-
if (multipleOf !== undefined && value % multipleOf !== 0) return false
108-
return true
109-
}, [min, max, multipleOf])
103+
const isValidValue = useCallback(
104+
(value: number): boolean => {
105+
if (isNaN(value) || value < 0) return false
106+
if (min !== undefined && value < min) return false
107+
if (max !== undefined && value > max) return false
108+
if (multipleOf !== undefined && value % multipleOf !== 0) return false
109+
return true
110+
},
111+
[min, max, multipleOf]
112+
)
110113

111114
const handleChange = useCallback(
112115
(event: React.ChangeEvent<HTMLInputElement>) => {

packages/webui/src/client/lib/forms/SchemaFormOneOfButtons/OneOfButtons.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@
3131
box-sizing: border-box;
3232
border-bottom: 3px solid transparent;
3333
padding-bottom: calc(var(--bs-btn-padding-y) - 3px);
34+
gap: 0.2em;
35+
36+
> .svg > svg {
37+
height: 1.2em;
38+
width: auto;
39+
}
3440
}
3541

3642
.field-one-of-button-complex > .btn-check-checked {

packages/webui/src/client/lib/forms/SchemaFormOneOfButtons/OneOfButtons.tsx

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const OneOfButtonsWithOverrides = (
2727
/** Helper to generate and save overrides for the item */
2828
overrideHelper: OverrideOpHelperForItemContents
2929
}
30-
) => {
30+
): JSX.Element => {
3131
const { t } = useTranslation()
3232

3333
const discProperty = getSchemaUIField(props.schema, SchemaFormUIField.OneOfDiscriminant)
@@ -100,34 +100,36 @@ export const OneOfButtonsWithOverrides = (
100100
return (
101101
<LabelAndOverridesForOneOfButtons {...childProps.commonAttrs}>
102102
{(value, handleUpdate) => {
103-
return props.schema.oneOf &&
104-
props.schema.oneOf.map((variant, index) => {
105-
const type = variant.properties?.[discProperty]?.const
106-
if (type === undefined)
103+
return (
104+
props.schema.oneOf &&
105+
props.schema.oneOf.map((variant, index) => {
106+
const type = variant.properties?.[discProperty]?.const
107+
if (type === undefined)
108+
return (
109+
<p key={`${index}_${type}`}>
110+
{t(
111+
'Discriminant property "{{ discProperty }}" used, but is undefined for variant at index {{ index }}',
112+
{
113+
discProperty,
114+
index,
115+
}
116+
)}
117+
</p>
118+
)
119+
107120
return (
108-
<p>
109-
{t(
110-
'Discriminant property "{{ discProperty }}" used, but is undefined for variant at index {{ index }}',
111-
{
112-
discProperty,
113-
index,
114-
}
115-
)}
116-
</p>
121+
<OneOfVariantButtonComplex
122+
value={value}
123+
key={`${index}_${type}`}
124+
discProperty={discProperty}
125+
selected={value?.[discProperty] === type}
126+
schema={variant}
127+
translationNamespaces={props.translationNamespaces}
128+
handleUpdate={handleUpdate}
129+
/>
117130
)
118-
119-
return (
120-
<OneOfVariantButtonComplex
121-
value={value}
122-
key={`${index}_${type}`}
123-
discProperty={discProperty}
124-
selected={value?.[discProperty] === type}
125-
schema={variant}
126-
translationNamespaces={props.translationNamespaces}
127-
handleUpdate={handleUpdate}
128-
/>
129-
)
130-
})
131+
})
132+
)
131133
}}
132134
</LabelAndOverridesForOneOfButtons>
133135
)
@@ -211,7 +213,7 @@ function OneOfVariantButtonComplex({
211213
onClick={handleSelect}
212214
>
213215
{variantTitle}
214-
{variantIcon && <BlueprintAssetIcon src={variantIcon} />}
216+
{variantIcon && <BlueprintAssetIcon className="svg" src={variantIcon} />}
215217
</Button>
216218
<SchemaFormWithState
217219
object={editingValue}

packages/webui/src/client/styles/propertiesPanel.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,12 @@
6868
letter-spacing: 0.5px;
6969

7070
> .svg {
71+
width: 1em;
7172
flex-shrink: 0;
73+
74+
> svg {
75+
display: block;
76+
}
7277
}
7378
> .title {
7479
flex-grow: 1;

packages/webui/src/client/styles/rundownView.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,6 +2115,21 @@ svg.icon {
21152115
> .label-icon.label-loop-icon {
21162116
margin: 0 0 0 0;
21172117
}
2118+
2119+
> .label-icon.label-custom-icon {
2120+
margin-top: -3px;
2121+
display: flex;
2122+
flex-direction: row-reverse;
2123+
2124+
> div {
2125+
flex: 0 0;
2126+
2127+
> svg {
2128+
height: 1em;
2129+
width: auto;
2130+
}
2131+
}
2132+
}
21182133
}
21192134

21202135
&.last-words {

packages/webui/src/client/ui/SegmentTimeline/Renderers/CustomLayerItemRenderer.tsx

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,18 @@ import type { ISourceLayerUi, IOutputLayerUi, PartUi } from '../SegmentTimelineC
55
import { RundownUtils } from '../../../lib/rundown.js'
66
import { faCut } from '@fortawesome/free-solid-svg-icons'
77
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
8-
import { PieceLifespan, type VTContent } from '@sofie-automation/blueprints-integration'
8+
import { PieceLifespan, UserEditingType, type VTContent } from '@sofie-automation/blueprints-integration'
99
import type { OffsetPosition } from '../../../utils/positions.js'
1010
import { LoopingPieceIcon } from '../../../lib/ui/icons/looping.js'
1111
import type { PieceUi } from '@sofie-automation/corelib/src/dataModel/Piece.js'
12+
import { BlueprintAssetIcon } from '../../../lib/Components/BlueprintAssetIcon.js'
13+
import { ReadonlyObjectDeep } from 'type-fest/source/readonly-deep.js'
14+
import {
15+
CoreUserEditingDefinitionAction,
16+
CoreUserEditingDefinitionForm,
17+
CoreUserEditingDefinitionSofie,
18+
CoreUserEditingDefinitionState,
19+
} from '@sofie-automation/corelib/dist/dataModel/UserEditingDefinitions'
1220

1321
export type SourceDurationLabelAlignment = 'left' | 'right'
1422

@@ -118,6 +126,39 @@ export class CustomLayerItemRenderer<IProps extends ICustomLayerItemProps, IStat
118126
return <LoopingPieceIcon className="segment-timeline__piece__label-icon" playing={this.props.showPreviewPopUp} />
119127
}
120128

129+
protected renderCustomPieceIcons(): JSX.Element | null {
130+
if (
131+
!this.props.piece.instance.piece.userEditOperations ||
132+
this.props.piece.instance.piece.userEditOperations.length === 0
133+
)
134+
return null
135+
136+
function operationWithUsefulIcon(
137+
op:
138+
| ReadonlyObjectDeep<CoreUserEditingDefinitionState>
139+
| ReadonlyObjectDeep<CoreUserEditingDefinitionAction>
140+
| ReadonlyObjectDeep<CoreUserEditingDefinitionForm>
141+
| ReadonlyObjectDeep<CoreUserEditingDefinitionSofie>
142+
): op is ReadonlyObjectDeep<CoreUserEditingDefinitionState> | ReadonlyObjectDeep<CoreUserEditingDefinitionAction> {
143+
return (
144+
((op.type === UserEditingType.ACTION || op.type === UserEditingType.STATE) &&
145+
((op.icon && op.isActive) || (op.iconInactive && !op.isActive))) ||
146+
false
147+
)
148+
}
149+
150+
return (
151+
<>
152+
{this.props.piece.instance.piece.userEditOperations.filter(operationWithUsefulIcon).map((op) => (
153+
<div className="segment-timeline__piece__label label-icon label-custom-icon" key={op.id}>
154+
{op.isActive && op.icon && <BlueprintAssetIcon src={op.icon} />}
155+
{!op.isActive && op.iconInactive && <BlueprintAssetIcon src={op.iconInactive} />}
156+
</div>
157+
))}
158+
</>
159+
)
160+
}
161+
121162
protected renderOverflowTimeLabel(): JSX.Element | null {
122163
const overflowTime = this.doesOverflowTime()
123164
if (

packages/webui/src/client/ui/SegmentTimeline/Renderers/DefaultLayerItemRenderer.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export class DefaultLayerItemRenderer extends CustomLayerItemRenderer<IProps, IS
7373
ref={this.setRightLabelRef}
7474
style={this.getItemLabelOffsetRight()}
7575
>
76+
{this.renderCustomPieceIcons()}
7677
{this.renderInfiniteIcon()}
7778
{this.renderOverflowTimeLabel()}
7879
</span>

packages/webui/src/client/ui/SegmentTimeline/Renderers/L3rdSourceRenderer.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ export class L3rdSourceRenderer extends CustomLayerItemRenderer<IProps, IState>
150150
ref={this.setRightLabelRef}
151151
style={this.getItemLabelOffsetRight()}
152152
>
153+
{this.renderCustomPieceIcons()}
153154
{this.renderInfiniteIcon()}
154155
{this.renderLoopIcon()}
155156
{this.renderOverflowTimeLabel()}

packages/webui/src/client/ui/SegmentTimeline/Renderers/LocalLayerItemRenderer.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export class LocalLayerItemRenderer extends CustomLayerItemRenderer<IProps, ISta
6767
ref={this.setRightLabelRef}
6868
style={this.getItemLabelOffsetRight()}
6969
>
70+
{this.renderCustomPieceIcons()}
7071
{this.renderInfiniteIcon()}
7172
{this.renderOverflowTimeLabel()}
7273
</span>

0 commit comments

Comments
 (0)