Skip to content
This repository has been archived by the owner on Nov 28, 2022. It is now read-only.

Commit

Permalink
If the explorer is disabled, ArrayField components should be addable …
Browse files Browse the repository at this point in the history
…but uneditable (#259)

* If the explorer is disabled, ArrayFields should be addable but uneditable.

* After a user has clicked a readOnly ArrayField, make it unaddable.

* Arrays of primitives can no longer be expanded if in read-only mode.

* Re-enabling the explorer on the `types` example.
  • Loading branch information
erunion authored Aug 12, 2019
1 parent 70909b5 commit 8e95e2a
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 12 deletions.
13 changes: 12 additions & 1 deletion example/swagger-files/types.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,23 @@
"type": "string"
}
},
"array (with a $ref)": {
"array (of strings, loaded via a $ref)": {
"type": "array",
"items": {
"$ref": "#/components/schemas/string_enum"
}
},
"array (of objects)": {
"type": "array",
"items": {
"type": "object",
"properties": {
"string": {
"type": "string"
}
}
}
},
"object": {
"type": "object",
"description": "This is an object with a description",
Expand Down
33 changes: 24 additions & 9 deletions packages/api-explorer/__tests__/Params.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,16 +219,31 @@ describe('x-explorer-enabled', () => {
const oasWithExplorerDisabled = Object.assign({}, oas, { [extensions.EXPLORER_ENABLED]: false });
const ParamsWithExplorerDisabled = createParams(oasWithExplorerDisabled);

test('array should not show add button', () => {
test('array should still show add button, but sub-elements should not be editable', () => {
const elem = mount(
<ParamsWithExplorerDisabled
{...props}
oas={new Oas(oasWithExplorerDisabled)}
operation={oas.operation('/pet', 'post')}
/>,
);

expect(elem.find('.field-array .array-item-add').length).toBe(2);

elem
.find('.field-array .array-item-add')
.at(0)
.simulate('click');

// Assert that after we've clicked to add array items into the view, everything is still in
// readOnly mode.
expect(elem.find('input').length).toBe(1);
expect(
mount(
<ParamsWithExplorerDisabled
{...props}
oas={new Oas(oasWithExplorerDisabled)}
operation={oas.operation('/pet', 'post')}
/>,
).find('.field-array .array-item-add').length,
).toBe(0);
elem
.find('input')
.at(0)
.props().type,
).toBe('hidden');
});

test('should not render any <input>', () => {
Expand Down
40 changes: 38 additions & 2 deletions packages/api-explorer/src/form-components/ArrayField.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,60 @@ const PropTypes = require('prop-types');
const extensions = require('@readme/oas-extensions');

const BaseArrayField = require('react-jsonschema-form/lib/components/fields/ArrayField').default;
const { getDefaultRegistry, retrieveSchema } = require('react-jsonschema-form/lib/utils');

function createArrayField(oas) {
const explorerEnabled = oas[extensions.EXPLORER_ENABLED];

function hasPrimitives(props) {
const { schema, registry = getDefaultRegistry() } = props;
const { definitions } = registry;
const itemsSchema = retrieveSchema(schema.items, definitions);

return itemsSchema.type !== 'array' && itemsSchema.type !== 'object';
}

function ArrayField(props) {
let uiSchema;
if (!explorerEnabled) {
// https://github.com/mozilla-services/react-jsonschema-form#addable-option
uiSchema = Object.assign(props.uiSchema, { 'ui:options': { addable: false } });
const uiOptions = {
readOnly: true,
addable: true,
};

// Two scenarios are accounted for here: if the array contains only primitives, and if the
// user has added a new entry within this ArrayField. For both scenarios, we want to disable
// any future entires from being added while the explorer is in readOnly mode.
//
// Why? If the array contains only primitives, expanding the array will result in a less than
// ideal UX of empty whitespace being added into view. As for if the user has already added
// an item into view, we want to disable further items from being added as since the explorer
// is in read-only mode, adding more items into view will just clutter up the view for the
// user.
//
// https://github.com/readmeio/api-explorer/pull/259#pullrequestreview-272110359
if (hasPrimitives(props)) {
uiOptions.addable = false;
} else if (props.formData.length > 0) {
uiOptions.addable = false;
}

uiSchema = Object.assign(props.uiSchema, { 'ui:options': uiOptions });
}

return <BaseArrayField {...props} uiSchema={uiSchema || props.uiSchema} />;
}

ArrayField.propTypes = {
// eslint-disable-next-line react/forbid-prop-types
formData: PropTypes.any,
uiSchema: PropTypes.shape({}).isRequired,
};

ArrayField.defaultProps = {
formData: [],
};

return ArrayField;
}

Expand Down

0 comments on commit 8e95e2a

Please sign in to comment.