Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .changeset/sdk-readonly-not-overridden-by-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@workflowbuilder/sdk': minor
---

Form-wide readonly mode is no longer overridden by a local uischema `rule`. Every JSON Form control now stays non-editable while `config.readonly` is `true`, even when a rule with an `ENABLE` effect applies to it.
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ import styles from './ai-tools-control.module.css';

import { FormControlWithLabel } from '../../../../components/form/form-control-with-label/form-control-with-label';
import { closeModal } from '../../../modals/stores/use-modal-store';
import { useIsControlEditable } from '../../hooks/use-is-control-editable';
import type { AiAgentTool, AiToolsControlProps } from '../../types/controls';
import { createControlRenderer } from '../../utils/rendering';
import { createAiTool, hasAnyValue } from './create-ai-tool';
import { openAddToolModal } from './open-add-tool-modal';
import { toolOptions } from './select-options';

function AiToolsControl({ path, handleChange, data, enabled, uischema }: AiToolsControlProps) {
function AiToolsControl(props: AiToolsControlProps) {
const { path, handleChange, data } = props;
const isEditable = useIsControlEditable(props);

const { t } = useTranslation(undefined, { keyPrefix: 'aiTools' });
const isDisabled = !enabled || uischema.disabled === true;

const handleSubmit = useCallback(
(change: AiAgentTool) => {
if (hasAnyValue(change)) {
Expand Down Expand Up @@ -61,7 +65,7 @@ function AiToolsControl({ path, handleChange, data, enabled, uischema }: AiTools
variant: 'secondary',
className: styles['selected-tool-button'],
onClick: () => openEditorModal(toolData),
disabled: isDisabled,
disabled: !isEditable,
};

return (
Expand All @@ -75,14 +79,14 @@ function AiToolsControl({ path, handleChange, data, enabled, uischema }: AiTools
) : (
<Button {...sharedButtonProps}>{label}</Button>
)}
<NavButton onClick={() => onRemoveTool(toolData.id)} disabled={isDisabled}>
<NavButton onClick={() => onRemoveTool(toolData.id)} disabled={!isEditable}>
<Trash weight="bold" />
</NavButton>
</div>
</FormControlWithLabel>
);
})}
<Button variant="primary" onClick={(_) => openEditorModal()} disabled={isDisabled}>
<Button variant="primary" onClick={(_) => openEditorModal()} disabled={!isEditable}>
<PlusCircle />
{t('addToolSlot')}
</Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { DatePicker, type DatePickerProps } from '@workflowbuilder/ui';

import { useIsControlEditable } from '../../hooks/use-is-control-editable';
import type { DatePickerControlProps } from '../../types/controls';
import { createControlRenderer } from '../../utils/rendering';
import { ControlWrapper } from '../control-wrapper';

function DatePickerControl(props: DatePickerControlProps) {
const { data, handleChange, path, enabled, uischema } = props;
const isDisabled = !enabled || uischema.disabled === true;
const { data, handleChange, path } = props;
const isEditable = useIsControlEditable(props);

const onChange: DatePickerProps['onChange'] = (value) => {
handleChange(path, value?.toString());
};

return (
<ControlWrapper {...props}>
<DatePicker value={data} onChange={onChange} disabled={isDisabled} />
<DatePicker value={data} onChange={onChange} disabled={!isEditable} />
</ControlWrapper>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import { useTranslation } from 'react-i18next';
import styles from './decision-branches-control.module.css';

import { PlaceholderButton } from '../../../diagram/nodes/components/placeholder-button/placeholder-button';
import { useIsControlEditable } from '../../hooks/use-is-control-editable';
import type { DecisionBranch, DecisionBranchesControlProps } from '../../types/controls';
import { createControlRenderer } from '../../utils/rendering';
import { BranchCard } from './branch-card/branch-card';
import { createDecisionBranch } from './create-decision-branch';

function DecisionBranchesControl(props: DecisionBranchesControlProps) {
const { data = [], handleChange, path, enabled, uischema } = props;
const isDisabled = !enabled || uischema.disabled === true;
const { data = [], handleChange, path } = props;
const isEditable = useIsControlEditable(props);

const decisionBranches = data as DecisionBranch[];

Expand All @@ -33,7 +34,7 @@ function DecisionBranchesControl(props: DecisionBranchesControlProps) {
}

function onAddBranch() {
if (isDisabled) {
if (!isEditable) {
return;
}
handleChange(path, [...decisionBranches, createDecisionBranch()]);
Expand All @@ -48,7 +49,7 @@ function DecisionBranchesControl(props: DecisionBranchesControlProps) {
branch={branch}
onUpdate={onUpdateBranch}
onRemove={onRemoveBranch}
enabled={!isDisabled}
enabled={isEditable}
/>
))}
<PlaceholderButton onClick={onAddBranch} label={t('decisionBranches.addBranch')} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ import { Icon } from '@workflow-builder/icons';
import styles from './dynamic-conditions-control.module.css';

import { closeModal, openModal } from '../../../modals/stores/use-modal-store';
import { useIsControlEditable } from '../../hooks/use-is-control-editable';
import type { DynamicCondition, DynamicConditionsControlProps } from '../../types/controls';
import { createControlRenderer } from '../../utils/rendering';
import { Dependencies } from './dependencies/dependencies';
import { ConditionModalFooter } from './dynamic-condition-modal-footer/condition-modal-footer';
import { ConditionsForm, type ConditionsFormHandle } from './dynamic-conditions-form/conditions-form';

function DynamicConditionsControl(props: DynamicConditionsControlProps) {
const { data = [], handleChange, path, enabled, uischema } = props;
const isDisabled = !enabled || uischema.disabled === true;
const { data = [], handleChange, path } = props;
const isEditable = useIsControlEditable(props);
const formRef = useRef<ConditionsFormHandle>(null);

const { t } = useTranslation(undefined, { keyPrefix: 'conditions' });
Expand Down Expand Up @@ -44,11 +45,11 @@ function DynamicConditionsControl(props: DynamicConditionsControlProps) {
<div className={styles['container']}>
<div className={styles['header']}>
<span className={clsx('ax-public-h10', styles['title'])}>{t('title')}</span>
<NavButton size="small" onClick={openEditorModal} tooltip={t('title')} disabled={isDisabled}>
<NavButton size="small" onClick={openEditorModal} tooltip={t('title')} disabled={!isEditable}>
<Icon name="FrameCorners" size="small" />
</NavButton>
</div>
<Dependencies conditions={data} onClick={openEditorModal} disabled={isDisabled} />
<Dependencies conditions={data} onClick={openEditorModal} disabled={!isEditable} />
<span className={styles['tag']}>{t('totalNumber', { count: data.length })}</span>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { Select, type SelectBaseProps } from '@workflowbuilder/ui';
import { Icon } from '@workflow-builder/icons';

import type { PrimitiveFieldSchema } from '../../../../node/node-schema';
import { useIsControlEditable } from '../../hooks/use-is-control-editable';
import type { SelectControlProps } from '../../types/controls';
import { createControlRenderer } from '../../utils/rendering';
import { ControlWrapper } from '../control-wrapper';

function SelectControl(props: SelectControlProps) {
const { data, handleChange, path, enabled, schema, uischema } = props;
const isDisabled = !enabled || uischema.disabled === true;
const { data, handleChange, path, schema } = props;
const isEditable = useIsControlEditable(props);

const items = (schema as PrimitiveFieldSchema).options?.map((option) =>
option.type === 'separator' || !option.icon
Expand All @@ -29,7 +30,7 @@ function SelectControl(props: SelectControlProps) {
<Select
value={data ?? null}
items={items ?? []}
disabled={isDisabled}
disabled={!isEditable}
onChange={onChange}
placeholder={schema.placeholder}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { Switch } from '@workflowbuilder/ui';

import { useIsControlEditable } from '../../hooks/use-is-control-editable';
import type { SwitchControlProps } from '../../types/controls';
import { createControlRenderer } from '../../utils/rendering';
import { ControlWrapper } from '../control-wrapper';

function SwitchControl(props: SwitchControlProps) {
const { data, handleChange, path, enabled, uischema } = props;
const isDisabled = !enabled || uischema.disabled === true;
const { data, handleChange, path } = props;
const isEditable = useIsControlEditable(props);

function onChange(checked: boolean) {
handleChange(path, checked);
}

return (
<ControlWrapper {...props}>
<Switch disabled={isDisabled} size="medium" checked={data ?? false} onChange={onChange} />
<Switch disabled={!isEditable} size="medium" checked={data ?? false} onChange={onChange} />
</ControlWrapper>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { TextArea } from '@workflowbuilder/ui';
import { useEffect, useState } from 'react';

import { useIsControlEditable } from '../../hooks/use-is-control-editable';
import type { TextAreaControlProps } from '../../types/controls';
import { createControlRenderer } from '../../utils/rendering';
import { ControlWrapper } from '../control-wrapper';

function TextAreaControl(props: TextAreaControlProps) {
const { data, handleChange, path, enabled, uischema } = props;
const { placeholder, minRows, maxRows, disabled } = uischema;
const isDisabled = !enabled || disabled === true;
const { data, handleChange, path, uischema } = props;
const { placeholder, minRows, maxRows } = uischema;
const isEditable = useIsControlEditable(props);

const [inputValue, setInputValue] = useState<string>(data);

Expand All @@ -27,7 +28,7 @@ function TextAreaControl(props: TextAreaControlProps) {
return (
<ControlWrapper {...props}>
<TextArea
disabled={isDisabled}
disabled={!isEditable}
value={inputValue}
minRows={minRows}
maxRows={maxRows}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { Input } from '@workflowbuilder/ui';
import { useEffect, useState } from 'react';

import { useIsControlEditable } from '../../hooks/use-is-control-editable';
import type { TextControlProps } from '../../types/controls';
import { createControlRenderer } from '../../utils/rendering';
import { ControlWrapper } from '../control-wrapper';

function TextControl(props: TextControlProps) {
const { schema, uischema, enabled, data, required, errors, path, handleChange } = props;

const { schema, uischema, data, required, errors, path, handleChange } = props;
const { type } = schema;
const { placeholder, disabled } = uischema;
const isDisabled = !enabled || disabled === true;
const { placeholder } = uischema;
const isEditable = useIsControlEditable(props);

const isNumberInput = type === 'number';
const hasErrors = errors.length > 0;
Expand Down Expand Up @@ -52,7 +52,7 @@ function TextControl(props: TextControlProps) {
onChange={onChange}
onBlur={onBlur}
error={hasErrors}
disabled={isDisabled}
disabled={!isEditable}
placeholder={placeholder}
/>
</ControlWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ import { useSingleSelectedElement } from '../../../../features/properties-bar/us
import { VariableText } from '../../../../features/variables/components/variable-text/variable-text';
import { variablesTypesToExcludeInText } from '../../../../features/variables/constants';
import { useAvailableVariables } from '../../../../features/variables/hooks/use-available-variables';
import { useIsControlEditable } from '../../hooks/use-is-control-editable';
import type { VariableTextAreaControlProps } from '../../types/controls';
import { createControlRenderer } from '../../utils/rendering';
import { ControlWrapper } from '../control-wrapper';

function VariableTextAreaControl(props: VariableTextAreaControlProps) {
const { data, handleChange, path, errors, enabled, uischema } = props;
const { placeholder, disabled } = uischema;
const { data, handleChange, path, errors, uischema } = props;
const { placeholder } = uischema;
const isEditable = useIsControlEditable(props);
const selection = useSingleSelectedElement();
// TODO: add param to pick what type of variables are available
const suggestionGroups = useAvailableVariables(selection?.node?.id, variablesTypesToExcludeInText);

const isDisabled = !enabled || disabled === true;

const [inputValue, setInputValue] = useState(data ?? '');

useEffect(() => {
Expand All @@ -35,7 +35,7 @@ function VariableTextAreaControl(props: VariableTextAreaControlProps) {
variant="text-area"
suggestionGroups={suggestionGroups}
hasError={errors.length > 0}
mentionsInputProps={{ disabled: isDisabled, placeholder, onBlur }}
mentionsInputProps={{ disabled: !isEditable, placeholder, onBlur }}
/>
</ControlWrapper>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ import { VariableText } from '../../../../features/variables/components/variable
import { variablesTypesToExcludeInText } from '../../../../features/variables/constants';
import { useAvailableVariables } from '../../../../features/variables/hooks/use-available-variables';
import { useSingleSelectedElement } from '../../../properties-bar/use-single-selected-element';
import { useIsControlEditable } from '../../hooks/use-is-control-editable';
import type { VariableTextControlProps } from '../../types/controls';
import { createControlRenderer } from '../../utils/rendering';
import { ControlWrapper } from '../control-wrapper';

function VariableTextControl(props: VariableTextControlProps) {
const { data, handleChange, path, errors, enabled, uischema } = props;
const { placeholder, disabled } = uischema;
const { data, handleChange, path, errors, uischema } = props;
const { placeholder } = uischema;
const isEditable = useIsControlEditable(props);
const selection = useSingleSelectedElement();
// TODO: add param to pick what type of variables are available
const suggestionGroups = useAvailableVariables(selection?.node?.id, variablesTypesToExcludeInText);

const isDisabled = !enabled || disabled === true;

const [inputValue, setInputValue] = useState(data ?? '');

useEffect(() => {
Expand All @@ -35,7 +35,7 @@ function VariableTextControl(props: VariableTextControlProps) {
variant="text"
suggestionGroups={suggestionGroups}
hasError={errors.length > 0}
mentionsInputProps={{ disabled: isDisabled, placeholder, onBlur }}
mentionsInputProps={{ disabled: !isEditable, placeholder, onBlur }}
/>
</ControlWrapper>
);
Expand Down
Loading
Loading