Skip to content

Commit

Permalink
react-vanilla: Disable array buttons when readonly (#2303)
Browse files Browse the repository at this point in the history
* Add toggling readonly state to the example app
* Disable array control and array table control buttons when the controls are disabled.
  This is the case when controls are readonly
* Add unit tests for the controls' button enablement

Co-authored-by: Lucas Koehler <[email protected]>
  • Loading branch information
joefreeman and lucas-koehler authored Sep 13, 2024
1 parent 429f11a commit 52b843a
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/examples/src/example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export interface ExampleDescription {
config?: any;
actions?: { label: string; apply: (props: StateProps) => any }[];
i18n?: JsonFormsI18nState;
readonly?: boolean;
}

export interface StateProps {
Expand All @@ -51,4 +52,5 @@ export interface StateProps {
cells?: JsonFormsCellRendererRegistryEntry[];
config?: any;
uischemas?: JsonFormsUISchemaRegistryEntry[];
readonly?: boolean;
}
11 changes: 11 additions & 0 deletions packages/examples/src/examples/arrays-with-detail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
import { registerExamples } from '../register';
import { personCoreSchema } from './person';
import { StateProps } from '../example';

export const schema = {
type: 'object',
Expand Down Expand Up @@ -93,12 +94,22 @@ export const data = {
],
};

const actions = [
{
label: 'Toggle readonly',
apply: (props: StateProps) => {
return { ...props, readonly: !props.readonly };
},
},
];

registerExamples([
{
name: 'array-with-detail',
label: 'Array with detail',
data,
schema,
uischema,
actions,
},
]);
6 changes: 6 additions & 0 deletions packages/examples/src/examples/arrays.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ const actions = [
};
},
},
{
label: 'Toggle readonly',
apply: (props: StateProps) => {
return { ...props, readonly: !props.readonly };
},
},
];

registerExamples([
Expand Down
3 changes: 3 additions & 0 deletions packages/vanilla-renderers/src/complex/TableArrayControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class TableArrayControl extends React.Component<
getStyleAsClassName,
childErrors,
translations,
enabled,
} = this.props;

const controlElement = uischema as ControlElement;
Expand Down Expand Up @@ -112,6 +113,7 @@ class TableArrayControl extends React.Component<
<label className={labelClass}>{label}</label>
<button
type='button'
disabled={!enabled}
className={buttonClass}
onClick={addItem(path, createDefaultValue(schema, rootSchema))}
>
Expand Down Expand Up @@ -216,6 +218,7 @@ class TableArrayControl extends React.Component<
<td>
<button
type='button'
disabled={!enabled}
aria-label={translations.removeAriaLabel}
onClick={() => {
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export const ArrayControl = ({
renderers,
rootSchema,
translations,
enabled,
}: ArrayControlProps & VanillaRendererProps) => {
const controlElement = uischema as ControlElement;
const childUiSchema = useMemo(
Expand Down Expand Up @@ -98,6 +99,7 @@ export const ArrayControl = ({
<button
type='button'
className={buttonClassAdd}
disabled={!enabled}
onClick={addItem(path, createDefaultValue(schema, rootSchema))}
>
Add to {label}
Expand All @@ -121,6 +123,7 @@ export const ArrayControl = ({
<button
type='button'
className={buttonClassUp}
disabled={!enabled}
aria-label={translations.upAriaLabel}
onClick={() => {
moveUp(path, index)();
Expand All @@ -131,6 +134,7 @@ export const ArrayControl = ({
<button
type='button'
className={buttonClassDown}
disabled={!enabled}
aria-label={translations.downAriaLabel}
onClick={() => {
moveDown(path, index)();
Expand All @@ -141,6 +145,7 @@ export const ArrayControl = ({
<button
type='button'
className={buttonClassDelete}
disabled={!enabled}
aria-label={translations.removeAriaLabel}
onClick={() => {
if (
Expand Down
50 changes: 50 additions & 0 deletions packages/vanilla-renderers/test/renderers/ArrayControl.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,54 @@ describe('Array control renderer', () => {

expect(controls).toHaveLength(3);
});

test('renders buttons', () => {
const core = initCore(fixture.schema, fixture.uischema, fixture.data);
const cells = [{ tester: integerCellTester, cell: IntegerCell }];
const wrapper = mount(
<JsonFormsStateProvider
initState={{
renderers: vanillaRenderers,
cells,
core,
uischemas: [{ tester: () => 1, uischema: { type: 'Control' } }],
}}
>
<ArrayControl schema={fixture.schema} uischema={fixture.uischema} />
</JsonFormsStateProvider>
);

const buttons = wrapper.find('button');
expect(buttons).toHaveLength(4);
buttons.forEach((button) => {
expect(button.prop('disabled')).toBe(false);
});
});

test('disabled control renders disabled buttons', () => {
const core = initCore(fixture.schema, fixture.uischema, fixture.data);
const cells = [{ tester: integerCellTester, cell: IntegerCell }];
const wrapper = mount(
<JsonFormsStateProvider
initState={{
renderers: vanillaRenderers,
cells,
core,
uischemas: [{ tester: () => 1, uischema: { type: 'Control' } }],
}}
>
<ArrayControl
schema={fixture.schema}
uischema={fixture.uischema}
enabled={false}
/>
</JsonFormsStateProvider>
);

const buttons = wrapper.find('button');
expect(buttons).toHaveLength(4);
buttons.forEach((button) => {
expect(button.prop('disabled')).toBe(true);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,47 @@ const fixture2 = {
},
};

describe('Table array control', () => {
test('renders buttons', () => {
const core = initCore(fixture.schema, fixture.uischema, fixture.data);
const cells = [{ tester: integerCellTester, cell: IntegerCell }];
const wrapper = mount(
<JsonFormsStateProvider initState={{ core, cells }}>
<TableArrayControl
schema={fixture.schema}
uischema={fixture.uischema}
/>
</JsonFormsStateProvider>
);

const buttons = wrapper.find('button');
expect(buttons).toHaveLength(2);
buttons.forEach((button) => {
expect(button.prop('disabled')).toBe(false);
});
});

test('disabled control renders disabled buttons', () => {
const core = initCore(fixture.schema, fixture.uischema, fixture.data);
const cells = [{ tester: integerCellTester, cell: IntegerCell }];
const wrapper = mount(
<JsonFormsStateProvider initState={{ core, cells }}>
<TableArrayControl
schema={fixture.schema}
uischema={fixture.uischema}
enabled={false}
/>
</JsonFormsStateProvider>
);

const buttons = wrapper.find('button');
expect(buttons).toHaveLength(2);
buttons.forEach((button) => {
expect(button.prop('disabled')).toBe(true);
});
});
});

describe('Table array tester', () => {
test('tester with recursive document ref only', () => {
const control: ControlElement = {
Expand Down

0 comments on commit 52b843a

Please sign in to comment.