Skip to content

Commit d6483c5

Browse files
chore: update interactions on readonly state (#1041)
## Problem * Cannot select options in SingleSelect in edit mode (e.g., Tiles column) * Cannot open Suggestions Popover in edit mode ## Solution **Bug Fixes**: - Fix onChange in SingleSelect in edit mode - Allow Suggestions Popover to open in readonly, but disable selection - Autofocus on the Popover in readonly to close the popover on blur ## Tests - [ ] Can select options in SingleSelect fields, e.g., Tiles find single row column or filter selector - [ ] Popover opens in PUBLISHED pipe (both RTE and attachments) - [ ] Cannot select any variable in Popover - [ ] Cannot delete attachment in Popover --------- Co-authored-by: Ian Chen <[email protected]>
1 parent 1fc70db commit d6483c5

File tree

5 files changed

+49
-28
lines changed

5 files changed

+49
-28
lines changed

packages/frontend/src/components/AttachmentSuggestions/components/Suggestions.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export default function Suggestions(props: SuggestionsProps) {
9797
values.includes(`{{${name}}}`)
9898
}
9999
onClick={(variable, checked) => {
100-
onSuggestionClick(variable, checked)
100+
!readOnly && onSuggestionClick(variable, checked)
101101
}}
102102
onDelete={onDelete}
103103
/>
@@ -121,7 +121,7 @@ export default function Suggestions(props: SuggestionsProps) {
121121

122122
return (
123123
<ChakraPopover
124-
autoFocus={false}
124+
autoFocus={readOnly ? true : false}
125125
gutter={0}
126126
matchWidth={true}
127127
isLazy
@@ -130,15 +130,12 @@ export default function Suggestions(props: SuggestionsProps) {
130130
isOpen={isSuggestionsOpen}
131131
onClose={closeSuggestions}
132132
>
133-
<div
134-
style={divWrapperStyles}
135-
onClick={() => !readOnly && openSuggestions()}
136-
>
133+
<div style={divWrapperStyles} onClick={openSuggestions}>
137134
<PopoverTrigger>
138-
<Box sx={boxStyles} onClick={() => !readOnly && openSuggestions()}>
135+
<Box sx={boxStyles} onClick={openSuggestions}>
139136
<TagList
140137
onClick={(option) => {
141-
onSuggestionClick(option, false)
138+
!readOnly && onSuggestionClick(option, false)
142139
}}
143140
tags={tags}
144141
/>

packages/frontend/src/components/ControlledAutocomplete/index.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,13 @@ function ControlledAutocomplete(
9393
const freeSolo = useMemo(() => {
9494
if (
9595
options.length &&
96-
options.every((option) => typeof option.value !== 'string')
96+
options.every((option) => typeof option.value !== 'string') &&
97+
!readOnly
9798
) {
9899
return false
99100
}
100101
return rawFreeSolo
101-
}, [options, rawFreeSolo])
102+
}, [options, rawFreeSolo, readOnly])
102103

103104
/**
104105
* useController is used here instead of the Controller component
@@ -172,7 +173,7 @@ function ControlledAutocomplete(
172173
colorScheme="secondary"
173174
isClearable={!required}
174175
items={items}
175-
onChange={() => !readOnly && fieldOnChange}
176+
onChange={(e) => !readOnly && fieldOnChange(e)}
176177
value={fieldValue ?? defaultValue}
177178
placeholder={placeholder}
178179
ref={ref}
@@ -182,7 +183,7 @@ function ControlledAutocomplete(
182183
freeSolo={freeSolo}
183184
isSearchable={isSearchable}
184185
addNew={
185-
addNewOption
186+
addNewOption && !readOnly
186187
? {
187188
type: addNewOption.type,
188189
label: addNewOption.label,

packages/frontend/src/components/FlowStepTestController/index.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ export default function FlowStepTestController(
112112
'down',
113113
)
114114

115+
// isLastTestExecutionCurrent is used to determine if the last test execution corresponds
116+
// to the values in the form.
117+
// isLastTestExecutionCurrent is false if the form values are saved but not tested
115118
const isLastTestExecutionCurrent = useMemo(() => {
116119
const formValues = formContext.getValues()
117120
return matchParamsToDataIn(
@@ -136,8 +139,9 @@ export default function FlowStepTestController(
136139
}, [testExecutionSteps, step, substeps])
137140

138141
const shouldAllowCheckStep = isValid && !readOnly && !isSaving
142+
139143
const shouldShowSaveButton =
140-
!isLastTestExecutionCurrent || (isTestSuccessful && isDirty)
144+
!readOnly && (!isLastTestExecutionCurrent || (isTestSuccessful && isDirty))
141145
const shouldShowTestResults =
142146
currentTestExecutionStep && !lastErrorDetails && !shouldTestStepAgain
143147

@@ -229,6 +233,7 @@ export default function FlowStepTestController(
229233
isTestExecuting,
230234
isValid,
231235
readOnly,
236+
isMobile,
232237
],
233238
)
234239

@@ -322,13 +327,11 @@ export default function FlowStepTestController(
322327
size="sm"
323328
colorScheme="black"
324329
onClick={handleSave}
325-
isDisabled={!isLastTestExecutionCurrent && !isDirty}
330+
isDisabled={!isDirty}
326331
mr={2}
327332
>
328333
<Text noOfLines={1}>
329-
{!isLastTestExecutionCurrent && !isDirty
330-
? 'Saved'
331-
: 'Save without checking'}
334+
{!isDirty ? 'Saved' : 'Save without checking'}
332335
</Text>
333336
</Button>
334337
</GridItem>

packages/frontend/src/components/RichTextEditor/MenuBar.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,10 @@ const dialogPlaceholders: Partial<Record<MenuLabels, string>> = {
237237
interface MenuBarProps {
238238
editor: Editor | null
239239
variableMap: VariableInfoMap
240+
editable: boolean
240241
}
241242

242-
export const MenuBar = ({ editor, variableMap }: MenuBarProps) => {
243+
export const MenuBar = ({ editor, variableMap, editable }: MenuBarProps) => {
243244
const {
244245
isOpen: isDialogOpen,
245246
onClose,
@@ -329,19 +330,30 @@ export const MenuBar = ({ editor, variableMap }: MenuBarProps) => {
329330
<div className="editor__header">
330331
{menuButtons.map(({ onClick, label, icon, isActive }, index) => {
331332
if (!onClick) {
332-
return <div className="divider" key={`${label}${index}`} />
333+
return (
334+
<div
335+
className="divider"
336+
style={{
337+
opacity: editable ? 1 : 0.5,
338+
}}
339+
key={`${label}${index}`}
340+
/>
341+
)
333342
}
334343
return (
335344
<button
336345
key={`${label}${index}`}
337346
title={label}
347+
disabled={!editable}
338348
style={{
339349
borderRadius: '0.25rem',
340350
width: 'auto',
341351
minWidth: 0,
342352
backgroundColor: isActive?.(editor)
343353
? 'rgba(0,0,0,0.1)'
344354
: 'transparent',
355+
opacity: editable ? 1 : 0.5,
356+
cursor: editable ? 'pointer' : 'default',
345357
}}
346358
className={`menu-item${isActive?.(editor) ? ' is-active' : ''}`}
347359
onClick={() => {

packages/frontend/src/components/RichTextEditor/index.tsx

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ const RICH_TEXT_EXTENSIONS = [
8888
interface EditorProps {
8989
onChange: (...event: any[]) => void
9090
initialValue: string
91-
editable?: boolean
91+
editable: boolean
9292
placeholder?: string
9393
variablesEnabled?: boolean
9494
isRich?: boolean
@@ -235,22 +235,20 @@ const Editor = ({
235235

236236
return (
237237
<Popover
238-
autoFocus={false}
238+
autoFocus={editable ? false : true}
239239
gutter={2}
240240
matchWidth={isMulticol ? false : true}
241241
isLazy
242242
lazyBehavior="unmount"
243243
onClose={closeSuggestions}
244-
isOpen={isSuggestionsOpen && variablesEnabled && editable}
244+
isOpen={isSuggestionsOpen && variablesEnabled}
245245
placement={getPopoverPlacement(editor)}
246246
>
247247
<div
248248
className="editor"
249249
onClick={(e) => {
250-
if (editable) {
251-
e.stopPropagation()
252-
openSuggestions()
253-
}
250+
e.stopPropagation()
251+
openSuggestions()
254252
}}
255253
onBlur={(e) => {
256254
// Focus might shift to menu bar or other children, where we do _not_
@@ -268,7 +266,13 @@ const Editor = ({
268266
>
269267
<PopoverTrigger>
270268
<Box className={isMulticol ? 'single-line-editor' : undefined}>
271-
{isRich && <MenuBar editor={editor} variableMap={varInfo} />}
269+
{isRich && (
270+
<MenuBar
271+
editor={editor}
272+
variableMap={varInfo}
273+
editable={editable ?? false}
274+
/>
275+
)}
272276
<EditorContent className="editor__content" editor={editor} />
273277
<Portal>
274278
<PopoverContent
@@ -280,10 +284,14 @@ const Editor = ({
280284
e.relatedTarget?.focus()
281285
}
282286
}}
287+
_focus={{
288+
boxShadow: 'none',
289+
borderColor: 'inherit',
290+
}}
283291
>
284292
<Suggestions
285293
data={stepsWithVariables}
286-
onSuggestionClick={handleVariableClick}
294+
onSuggestionClick={(v) => editable && handleVariableClick(v)}
287295
/>
288296
</PopoverContent>
289297
</Portal>

0 commit comments

Comments
 (0)