diff --git a/example/swagger-files/types.json b/example/swagger-files/types.json index ec281d546..daf781c12 100644 --- a/example/swagger-files/types.json +++ b/example/swagger-files/types.json @@ -97,7 +97,6 @@ "format": "date" }, "string (format: date-time)": { - "description": "Temporarily disabled back to a simple string input due to a bug in RJSF", "type": "string", "format": "date-time" }, diff --git a/packages/api-explorer/__tests__/Params.test.jsx b/packages/api-explorer/__tests__/Params.test.jsx index 59891ffa7..08bc1ee20 100644 --- a/packages/api-explorer/__tests__/Params.test.jsx +++ b/packages/api-explorer/__tests__/Params.test.jsx @@ -264,9 +264,9 @@ describe('schema handling', () => { }); it.each([ - ['date', 'text', stringOas.operation('/format-date', 'get'), 'date'], - ['date-time', 'text', stringOas.operation('/format-date-time', 'get'), 'string'], - ['dateTime', 'text', stringOas.operation('/format-dateTime', 'get'), 'string'], + ['date', 'date', stringOas.operation('/format-date', 'get'), 'date'], + ['date-time', 'datetime-local', stringOas.operation('/format-date-time', 'get'), 'date-time'], + ['dateTime', 'datetime-local', stringOas.operation('/format-dateTime', 'get'), 'date-time'], ['password', 'password', stringOas.operation('/format-password', 'get'), 'password'], ['uri', 'url', stringOas.operation('/format-uri', 'get'), 'uri'], ['url', 'url', stringOas.operation('/format-url', 'get'), 'url'], diff --git a/packages/api-explorer/src/Params.jsx b/packages/api-explorer/src/Params.jsx index 8d76453cd..c67584989 100644 --- a/packages/api-explorer/src/Params.jsx +++ b/packages/api-explorer/src/Params.jsx @@ -4,7 +4,7 @@ const Form = require('@readme/react-jsonschema-form').default; const slug = require('lodash.kebabcase'); const { - // DateTimeWidget, + DateWidget, PasswordWidget, TextWidget, UpDownWidget, @@ -13,15 +13,16 @@ const { const Oas = require('@readme/oas-tooling'); const { parametersToJsonSchema } = require('@readme/oas-tooling/utils'); -const DescriptionField = require('./form-components/DescriptionField'); -const UnsupportedField = require('./form-components/UnsupportedField'); -const createBaseInput = require('./form-components/BaseInput'); -const createSelectWidget = require('./form-components/SelectWidget'); const createArrayField = require('./form-components/ArrayField'); +const createBaseInput = require('./form-components/BaseInput'); +const createDateTimeWidget = require('./form-components/DateTimeWidget'); +const createFileWidget = require('./form-components/FileWidget'); const createSchemaField = require('./form-components/SchemaField'); +const createSelectWidget = require('./form-components/SelectWidget'); const createTextareaWidget = require('./form-components/TextareaWidget'); -const createFileWidget = require('./form-components/FileWidget'); const createURLWidget = require('./form-components/URLWidget'); +const DescriptionField = require('./form-components/DescriptionField'); +const UnsupportedField = require('./form-components/UnsupportedField'); const { Operation } = Oas; @@ -46,6 +47,7 @@ class Params extends React.Component { const { ArrayField, BaseInput, + DateTimeWidget, FileWidget, formData, onChange, @@ -91,13 +93,9 @@ class Params extends React.Component { binary: FileWidget, blob: TextareaWidget, byte: TextWidget, - date: TextWidget, - - // 🚨 Temporarily disabling support for rendering the datetime widget as RJSF appears to be disabling it in - // browsers that don't fully support it. - /* dateTime: DateTimeWidget, - 'date-time': DateTimeWidget, */ - + date: DateWidget, + dateTime: DateTimeWidget, + 'date-time': DateTimeWidget, double: UpDownWidget, duration: TextWidget, float: UpDownWidget, @@ -133,6 +131,7 @@ class Params extends React.Component { Params.propTypes = { ArrayField: PropTypes.func.isRequired, BaseInput: PropTypes.func.isRequired, + DateTimeWidget: PropTypes.func.isRequired, FileWidget: PropTypes.func.isRequired, formData: PropTypes.shape({}).isRequired, oas: PropTypes.instanceOf(Oas).isRequired, @@ -153,6 +152,7 @@ Params.defaultProps = { function createParams(oas) { const ArrayField = createArrayField(oas); const BaseInput = createBaseInput(oas); + const DateTimeWidget = createDateTimeWidget(oas); const FileWidget = createFileWidget(oas); const SchemaField = createSchemaField(); const SelectWidget = createSelectWidget(oas); @@ -166,6 +166,7 @@ function createParams(oas) { {...props} ArrayField={ArrayField} BaseInput={BaseInput} + DateTimeWidget={DateTimeWidget} FileWidget={FileWidget} SchemaField={SchemaField} SelectWidget={SelectWidget} diff --git a/packages/api-explorer/src/form-components/DateTimeWidget.jsx b/packages/api-explorer/src/form-components/DateTimeWidget.jsx new file mode 100644 index 000000000..f1765e47d --- /dev/null +++ b/packages/api-explorer/src/form-components/DateTimeWidget.jsx @@ -0,0 +1,35 @@ +const React = require('react'); +const PropTypes = require('prop-types'); +const extensions = require('@readme/oas-extensions'); + +function createDateTimeWidget(oas) { + const explorerEnabled = oas[extensions.EXPLORER_ENABLED]; + + // Return a function that renders null when the explorer is disabled + if (!explorerEnabled) return () => null; + + // Why use this instead of the DateTimeWidget that RJSF provides? Well that's running UTC conversion on dates that + // doesn't actually need to happen for browsers that support `datetime-local`, and when it does that in browsers that + // don't support it, it's overwriting the data that the user inputs with an empty string. + function DateTimeWidget(props) { + const { + registry: { + widgets: { BaseInput }, + }, + } = props; + + return ; + } + + DateTimeWidget.propTypes = { + registry: PropTypes.shape({ + FieldTemplate: PropTypes.func, + rootSchema: PropTypes.object, + widgets: PropTypes.object, + }).isRequired, + }; + + return DateTimeWidget; +} + +module.exports = createDateTimeWidget;