From 7c63ed0ef4a2c4fffbcdd98748e242f6a3863af8 Mon Sep 17 00:00:00 2001 From: Filip Van Ham Date: Wed, 26 Apr 2023 11:36:46 +0200 Subject: [PATCH 1/4] feat: add listening for redocUpdatePosition event on window to update scrollPosition by url/history --- package.json | 2 +- src/services/AppStore.ts | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 8a030a30..593e9a42 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "redoc", - "version": "2.0.0-0.2.0", + "version": "2.0.0-0.2.1", "description": "ReDoc", "repository": { "type": "git", diff --git a/src/services/AppStore.ts b/src/services/AppStore.ts index 0c0dba35..eb7ff0b1 100644 --- a/src/services/AppStore.ts +++ b/src/services/AppStore.ts @@ -58,6 +58,8 @@ export class AppStore { private scroll: ScrollService; private disposer: Lambda | null = null; + private readonly listener: EventListenerOrEventListenerObject = this.updateOnEvent.bind(this); + constructor( spec: OpenAPISpec, specUrl?: string, @@ -73,7 +75,7 @@ export class AppStore { MenuStore.updateOnHistory(this.history.currentId, this.scroll); // Listen for external event to update - window.addEventListener('redocUpdatePosition', this.updateOnEvent); + window.addEventListener('redocUpdatePosition', this.listener); // override the openApi standard to version 3.1.0 // TODO remove when fully supporting open API 3.1.0 @@ -101,7 +103,7 @@ export class AppStore { dispose() { this.scroll.dispose(); this.menu.dispose(); - window.removeEventListener('redocUpdatePosition', this.updateOnEvent); + window.removeEventListener('redocUpdatePosition', this.listener); if (this.search) { this.search.dispose(); } @@ -129,10 +131,6 @@ export class AppStore { }; } - private updateOnEvent(): void { - MenuStore.updateOnHistory(this.history.currentId, this.scroll); - } - private updateMarkOnMenu(idx: number) { const start = Math.max(0, idx); const end = Math.min(this.menu.flatItems.length, start + 5); @@ -157,6 +155,10 @@ export class AppStore { this.marker.addOnly(elements); this.marker.mark(); } + + private updateOnEvent(): void { + MenuStore.updateOnHistory(this.history.currentId, this.scroll); + } } const DEFAULT_OPTIONS: RedocRawOptions = { From fc586415607f21e3e0d5cbe04b9ba0124adfd577 Mon Sep 17 00:00:00 2001 From: Depickere Sven Date: Wed, 26 Apr 2023 16:04:31 +0100 Subject: [PATCH 2/4] feat(): add m2m badge to operations and fields --- src/components/Fields/FieldDetails.tsx | 6 ++++++ src/components/Operation/Operation.tsx | 11 ++++++++++- src/components/Schema/OneOfSchema.tsx | 1 + src/services/models/Field.ts | 2 ++ src/services/models/Operation.ts | 5 +++++ src/services/models/Schema.ts | 4 ++++ src/theme.ts | 13 ++++++++++--- src/types/miles.constants.ts | 1 + src/types/open-api.ts | 1 + 9 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/components/Fields/FieldDetails.tsx b/src/components/Fields/FieldDetails.tsx index b7f5afed..d7b7aa65 100644 --- a/src/components/Fields/FieldDetails.tsx +++ b/src/components/Fields/FieldDetails.tsx @@ -34,6 +34,7 @@ export const FieldDetailsComponent = observer((props: FieldProps) => { schema, description, deprecated, + m2m, extensions, in: _in, const: _const, @@ -105,6 +106,11 @@ export const FieldDetailsComponent = observer((props: FieldProps) => { {l('deprecated')} )} + {m2m && ( +
+ M2M +
+ )} {!renderDiscriminatorSwitch && ( diff --git a/src/components/Operation/Operation.tsx b/src/components/Operation/Operation.tsx index b6904f62..cdcbc916 100644 --- a/src/components/Operation/Operation.tsx +++ b/src/components/Operation/Operation.tsx @@ -28,7 +28,15 @@ export interface OperationProps { } export const Operation = observer(({ operation }: OperationProps): JSX.Element => { - const { name: summary, description, deprecated, externalDocs, isWebhook, httpVerb } = operation; + const { + name: summary, + description, + deprecated, + externalDocs, + isWebhook, + httpVerb, + m2m, + } = operation; const hasDescription = !!(description || externalDocs); const { showWebhookVerb } = React.useContext(OptionsContext); return ( @@ -39,6 +47,7 @@ export const Operation = observer(({ operation }: OperationProps): JSX.Element =

{summary} {deprecated && Deprecated } + {m2m && M2M } {isWebhook && ( {' '} diff --git a/src/components/Schema/OneOfSchema.tsx b/src/components/Schema/OneOfSchema.tsx index 311a3258..cdeb6457 100644 --- a/src/components/Schema/OneOfSchema.tsx +++ b/src/components/Schema/OneOfSchema.tsx @@ -60,6 +60,7 @@ export class OneOfSchema extends React.Component {
{oneOf[schema.activeOneOf].deprecated && Deprecated} + {oneOf[schema.activeOneOf].m2m && M2M}
diff --git a/src/services/models/Field.ts b/src/services/models/Field.ts index c502947f..f2df447b 100644 --- a/src/services/models/Field.ts +++ b/src/services/models/Field.ts @@ -51,6 +51,7 @@ export class FieldModel { example?: string; examples?: Record | any[]; deprecated: boolean; + m2m: boolean; in?: OpenAPIParameterLocation; kind: string; extensions?: Record; @@ -119,6 +120,7 @@ export class FieldModel { } this.deprecated = info.deprecated === undefined ? !!this.schema.deprecated : info.deprecated; + this.m2m = info.m2m === undefined ? !!this.schema.m2m : info.m2m; if (options.showExtensions) { this.extensions = extractExtensions(info, options.showExtensions); diff --git a/src/services/models/Operation.ts b/src/services/models/Operation.ts index e26b4a4c..04da3a64 100644 --- a/src/services/models/Operation.ts +++ b/src/services/models/Operation.ts @@ -25,6 +25,7 @@ import type { OpenAPIParser } from '../OpenAPIParser'; import type { RedocNormalizedOptions } from '../RedocNormalizedOptions'; import type { MediaContentModel } from './MediaContent'; import type { ContentItemModel, ExtendedOpenAPIOperation, IMenuItem } from '../types'; +import { MilesConstants } from '../../types'; export interface XPayloadSample { lang: 'payload'; @@ -72,6 +73,7 @@ export class OperationModel implements IMenuItem { operationHash?: string; httpVerb: string; deprecated: boolean; + m2m: boolean; path: string; servers: OpenAPIServer[]; security: SecurityRequirementModel[]; @@ -96,6 +98,9 @@ export class OperationModel implements IMenuItem { this.externalDocs = operationSpec.externalDocs; this.deprecated = !!operationSpec.deprecated; + this.m2m = !!extractExtensions(operationSpec, [MilesConstants.MILES_M2M])?.[ + MilesConstants.MILES_M2M + ]; this.httpVerb = operationSpec.httpVerb; this.deprecated = !!operationSpec.deprecated; this.operationId = operationSpec.operationId; diff --git a/src/services/models/Schema.ts b/src/services/models/Schema.ts index 5bd42245..1ab9e7f8 100644 --- a/src/services/models/Schema.ts +++ b/src/services/models/Schema.ts @@ -44,6 +44,7 @@ export class SchemaModel { displayFormat?: string; nullable: boolean; deprecated: boolean; + m2m: boolean; pattern?: string; example?: any; examples?: any[]; @@ -126,6 +127,9 @@ export class SchemaModel { this.example = schema.example; this.examples = schema.examples; this.deprecated = !!schema.deprecated; + this.m2m = !!extractExtensions(this.schema, [MilesConstants.MILES_M2M])?.[ + MilesConstants.MILES_M2M + ]; this.pattern = schema.pattern; this.externalDocs = schema.externalDocs; diff --git a/src/theme.ts b/src/theme.ts index b65546fa..36efed13 100644 --- a/src/theme.ts +++ b/src/theme.ts @@ -21,9 +21,15 @@ const defaultTheme: ThemeInterface = { }, secondary: { main: '#D47D17', - light: ({ colors }) => lighten(colors.tonalOffset, colors.primary.main), - dark: ({ colors }) => darken(colors.tonalOffset, colors.primary.main), - contrastText: ({ colors }) => readableColor(colors.primary.main), + light: ({ colors }) => lighten(colors.tonalOffset, colors.secondary.main), + dark: ({ colors }) => darken(colors.tonalOffset, colors.secondary.main), + contrastText: ({ colors }) => readableColor(colors.secondary.main), + }, + m2m: { + main: '#343A40', + light: ({ colors }) => lighten(colors.tonalOffset, colors.m2m.main), + dark: ({ colors }) => darken(colors.tonalOffset, colors.m2m.main), + contrastText: ({ colors }) => readableColor(colors.m2m.main), }, success: { main: '#1d8127', @@ -271,6 +277,7 @@ export interface ResolvedThemeInterface { tonalOffset: number; primary: ColorSetting; secondary: ColorSetting; + m2m: ColorSetting; success: ColorSetting; warning: ColorSetting; error: ColorSetting; diff --git a/src/types/miles.constants.ts b/src/types/miles.constants.ts index 4d73cdc3..720d4bab 100644 --- a/src/types/miles.constants.ts +++ b/src/types/miles.constants.ts @@ -1,4 +1,5 @@ export const MilesConstants = { MILES_EXTRA_DESCRIPTION_PROPERTY_NAME: 'x-miles-extra-description', + MILES_M2M: 'x-miles-m2m', HIDE_LOGO_QUERY_PARAM: 'hideLogo', }; diff --git a/src/types/open-api.ts b/src/types/open-api.ts index 62a1d584..2ef302f7 100644 --- a/src/types/open-api.ts +++ b/src/types/open-api.ts @@ -93,6 +93,7 @@ export interface OpenAPIParameter { description?: string; required?: boolean; deprecated?: boolean; + m2m?: boolean; allowEmptyValue?: boolean; style?: OpenAPIParameterStyle; explode?: boolean; From c9a32982cb9cdd7567fab01a56bf427644eec33a Mon Sep 17 00:00:00 2001 From: Depickere Sven Date: Wed, 26 Apr 2023 16:05:49 +0100 Subject: [PATCH 3/4] :package: bump to version 2.0.0-0.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 593e9a42..f7958bd7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "redoc", - "version": "2.0.0-0.2.1", + "version": "2.0.0-0.3.0", "description": "ReDoc", "repository": { "type": "git", From c971dc0fdbda39c288008fc9fd976e8e58cfae4b Mon Sep 17 00:00:00 2001 From: Depickere Sven Date: Wed, 26 Apr 2023 16:30:58 +0100 Subject: [PATCH 4/4] style(): Update styling --- src/common-elements/shelfs.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/common-elements/shelfs.tsx b/src/common-elements/shelfs.tsx index 8eb3d4a7..4e78b568 100644 --- a/src/common-elements/shelfs.tsx +++ b/src/common-elements/shelfs.tsx @@ -51,8 +51,10 @@ export const Badge = styled.span<{ type: string }>` display: inline-block; padding: 2px 8px; margin: 0; - background-color: ${props => props.theme.colors[props.type].main}; - color: ${props => props.theme.colors[props.type].contrastText}; + background-color: ${props => + props.type == 'm2m' ? 'none' : props.theme.colors[props.type].main}; + border: ${props => (props.type == 'm2m' ? 'rgba(38, 50, 56, 0.5) 1px solid' : 'none')}; + color: ${props => (props.type == 'm2m' ? 'black' : props.theme.colors[props.type].contrastText)}; font-size: ${props => props.theme.typography.code.fontSize}; vertical-align: middle; line-height: 1.6;