From d12e410d99a988948b359093159df79572bc78ab Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Mon, 23 Nov 2020 14:00:17 +0200 Subject: [PATCH] feat: support multiple examples for parameters (#1470) --- src/components/Fields/FieldDetails.tsx | 60 +++++++++++++++++++++----- src/services/Labels.ts | 2 + src/services/models/Field.ts | 10 +++++ src/types/open-api.d.ts | 1 + 4 files changed, 63 insertions(+), 10 deletions(-) diff --git a/src/components/Fields/FieldDetails.tsx b/src/components/Fields/FieldDetails.tsx index 8584511b..839595a3 100644 --- a/src/components/Fields/FieldDetails.tsx +++ b/src/components/Fields/FieldDetails.tsx @@ -9,6 +9,8 @@ import { TypePrefix, TypeTitle, ToggleButton, + FieldLabel, + ExampleValue, } from '../../common-elements/fields'; import { serializeParameterValue } from '../../utils/openapi'; import { ExternalDocumentation } from '../ExternalDocumentation/ExternalDocumentation'; @@ -23,6 +25,8 @@ import { Badge } from '../../common-elements/'; import { l } from '../../services/Labels'; import { OptionsContext } from '../OptionsProvider'; +import { FieldModel } from '../../services/models/Field'; +import styled from '../../styled-components'; const MAX_PATTERN_LENGTH = 45; @@ -44,20 +48,19 @@ export class FieldDetails extends React.PureComponent; + if (showExamples && (example !== undefined || examples !== undefined)) { + if (examples !== undefined) { + renderedExamples = ; } else { - exampleField = ; + const label = l('example') + ':'; + const raw = !!field.in; + renderedExamples = ; } } @@ -100,7 +103,7 @@ export class FieldDetails extends React.PureComponent {!renderDiscriminatorSwitch && }{' '} - {exampleField} + {renderedExamples} {}
@@ -113,3 +116,40 @@ export class FieldDetails extends React.PureComponent + {l('examples')}: + + {Object.values(field.examples).map((example, idx) => { + return ( +
  • + {getSerializedValue(field, example.value)} - {example.summary || example.description} +
  • + ); + })} +
    + + ); +} + +function getSerializedValue(field: FieldModel, example: any) { + if (field.in) { + // decode for better readability in examples: see https://github.com/Redocly/redoc/issues/1138 + return decodeURIComponent(serializeParameterValue(field, example)); + } else { + return example; + } +} + + +const ExamplesList = styled.ul` + margin-top: 1em; + padding-left: 0; + list-style-position: inside; +`; diff --git a/src/services/Labels.ts b/src/services/Labels.ts index c0bddfed..c3568eb1 100644 --- a/src/services/Labels.ts +++ b/src/services/Labels.ts @@ -5,6 +5,7 @@ export interface LabelsConfig { default: string; deprecated: string; example: string; + examples: string; nullable: string; recursive: string; arrayOf: string; @@ -20,6 +21,7 @@ const labels: LabelsConfig = { default: 'Default', deprecated: 'Deprecated', example: 'Example', + examples: 'Examples', nullable: 'Nullable', recursive: 'Recursive', arrayOf: 'Array of ', diff --git a/src/services/models/Field.ts b/src/services/models/Field.ts index ab30d094..b763c66b 100644 --- a/src/services/models/Field.ts +++ b/src/services/models/Field.ts @@ -11,6 +11,8 @@ import { RedocNormalizedOptions } from '../RedocNormalizedOptions'; import { extractExtensions } from '../../utils/openapi'; import { OpenAPIParser } from '../OpenAPIParser'; import { SchemaModel } from './Schema'; +import { ExampleModel } from './Example'; +import { mapValues } from '../../utils/helpers'; const DEFAULT_SERIALIZATION: Record< OpenAPIParameterLocation, @@ -46,6 +48,7 @@ export class FieldModel { required: boolean; description: string; example?: string; + examples?: Record; deprecated: boolean; in?: OpenAPIParameterLocation; kind: string; @@ -81,6 +84,13 @@ export class FieldModel { info.description === undefined ? this.schema.description || '' : info.description; this.example = info.example || this.schema.example; + if (info.examples !== undefined) { + this.examples = mapValues( + info.examples, + example => new ExampleModel(parser, example, name, info.encoding), + ); + } + if (serializationMime) { this.serializationMime = serializationMime; } else if (info.style) { diff --git a/src/types/open-api.d.ts b/src/types/open-api.d.ts index aefc0b73..7134890e 100644 --- a/src/types/open-api.d.ts +++ b/src/types/open-api.d.ts @@ -95,6 +95,7 @@ export interface OpenAPIParameter { example?: any; examples?: { [media: string]: Referenced }; content?: { [media: string]: OpenAPIMediaType }; + encoding?: Record; } export interface OpenAPIExample {