diff --git a/demo/openapi.yaml b/demo/openapi.yaml
index 790a76c7..558c4080 100644
--- a/demo/openapi.yaml
+++ b/demo/openapi.yaml
@@ -112,6 +112,9 @@ paths:
summary: Add a new pet to the store
description: Add new pet to the store inventory.
operationId: addPet
+ x-badges:
+ - name: Global
+ type: global
responses:
'405':
description: Invalid input
@@ -156,6 +159,9 @@ paths:
summary: Update an existing pet
description: ''
operationId: updatePet
+ x-badges:
+ - name: US Only
+ type: usonly
responses:
'400':
description: Invalid ID supplied
@@ -186,6 +192,9 @@ paths:
get:
description: Retrieve the history information associated with an order.
operationId: GetOrderHistory
+ x-badges:
+ - name: Success
+ type: success
parameters:
- description: ''
in: path
@@ -244,6 +253,11 @@ paths:
date range or specific query parameter (marked by * below) is
provided, the order results will be limited to the last two years.
operationId: GetTnOptionOrders
+ x-badges:
+ - name: 1st Badge
+ type: warning
+ - name: 2nd Badge
+ type: experimental
parameters:
- description: The status of the TN Option order being searched for.
example: PROCESSING
diff --git a/src/components/Operation/Operation.tsx b/src/components/Operation/Operation.tsx
index e135c31e..2f743597 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,
+ badges,
+ externalDocs,
+ isWebhook,
+ httpVerb,
+ } = operation;
const hasDescription = !!(description || externalDocs);
const { showWebhookVerb } = React.useContext(OptionsContext);
return (
@@ -45,6 +53,16 @@ export const Operation = observer(({ operation }: OperationProps): JSX.Element =
Webhook {showWebhookVerb && httpVerb && '| ' + httpVerb.toUpperCase()}
)}
+ {badges.map(badge => {
+ return (
+ badge && (
+
+ {' '}
+ {badge.name}{' '}
+
+ )
+ );
+ })}
{options.pathInMiddlePanel && !isWebhook && (
diff --git a/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap b/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap
index e5608f39..75158076 100644
--- a/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap
+++ b/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap
@@ -134,6 +134,18 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"light": "#eb6d6b",
"main": "#d41f1c",
},
+ "experimental": Object {
+ "contrastText": "#fff",
+ "dark": "#540297",
+ "light": "#ba68fd",
+ "main": "#8c03fc",
+ },
+ "global": Object {
+ "contrastText": "#fff",
+ "dark": "#4d02b0",
+ "light": "#b681fd",
+ "main": "#7c1cfc",
+ },
"gray": Object {
"100": "#F5F5F5",
"50": "#FAFAFA",
@@ -188,6 +200,12 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"secondary": "#666",
},
"tonalOffset": 0.2,
+ "usonly": Object {
+ "contrastText": "#fff",
+ "dark": "#045b8b",
+ "light": "#61c4fa",
+ "main": "#079cee",
+ },
"warning": Object {
"contrastText": "#ffffff",
"dark": "#996300",
@@ -405,6 +423,18 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"light": "#eb6d6b",
"main": "#d41f1c",
},
+ "experimental": Object {
+ "contrastText": "#fff",
+ "dark": "#540297",
+ "light": "#ba68fd",
+ "main": "#8c03fc",
+ },
+ "global": Object {
+ "contrastText": "#fff",
+ "dark": "#4d02b0",
+ "light": "#b681fd",
+ "main": "#7c1cfc",
+ },
"gray": Object {
"100": "#F5F5F5",
"50": "#FAFAFA",
@@ -459,6 +489,12 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"secondary": "#666",
},
"tonalOffset": 0.2,
+ "usonly": Object {
+ "contrastText": "#fff",
+ "dark": "#045b8b",
+ "light": "#61c4fa",
+ "main": "#079cee",
+ },
"warning": Object {
"contrastText": "#ffffff",
"dark": "#996300",
@@ -663,6 +699,18 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"light": "#eb6d6b",
"main": "#d41f1c",
},
+ "experimental": Object {
+ "contrastText": "#fff",
+ "dark": "#540297",
+ "light": "#ba68fd",
+ "main": "#8c03fc",
+ },
+ "global": Object {
+ "contrastText": "#fff",
+ "dark": "#4d02b0",
+ "light": "#b681fd",
+ "main": "#7c1cfc",
+ },
"gray": Object {
"100": "#F5F5F5",
"50": "#FAFAFA",
@@ -717,6 +765,12 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"secondary": "#666",
},
"tonalOffset": 0.2,
+ "usonly": Object {
+ "contrastText": "#fff",
+ "dark": "#045b8b",
+ "light": "#61c4fa",
+ "main": "#079cee",
+ },
"warning": Object {
"contrastText": "#ffffff",
"dark": "#996300",
@@ -983,6 +1037,18 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"light": "#eb6d6b",
"main": "#d41f1c",
},
+ "experimental": Object {
+ "contrastText": "#fff",
+ "dark": "#540297",
+ "light": "#ba68fd",
+ "main": "#8c03fc",
+ },
+ "global": Object {
+ "contrastText": "#fff",
+ "dark": "#4d02b0",
+ "light": "#b681fd",
+ "main": "#7c1cfc",
+ },
"gray": Object {
"100": "#F5F5F5",
"50": "#FAFAFA",
@@ -1037,6 +1103,12 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"secondary": "#666",
},
"tonalOffset": 0.2,
+ "usonly": Object {
+ "contrastText": "#fff",
+ "dark": "#045b8b",
+ "light": "#61c4fa",
+ "main": "#079cee",
+ },
"warning": Object {
"contrastText": "#ffffff",
"dark": "#996300",
@@ -1266,6 +1338,18 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"light": "#eb6d6b",
"main": "#d41f1c",
},
+ "experimental": Object {
+ "contrastText": "#fff",
+ "dark": "#540297",
+ "light": "#ba68fd",
+ "main": "#8c03fc",
+ },
+ "global": Object {
+ "contrastText": "#fff",
+ "dark": "#4d02b0",
+ "light": "#b681fd",
+ "main": "#7c1cfc",
+ },
"gray": Object {
"100": "#F5F5F5",
"50": "#FAFAFA",
@@ -1320,6 +1404,12 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"secondary": "#666",
},
"tonalOffset": 0.2,
+ "usonly": Object {
+ "contrastText": "#fff",
+ "dark": "#045b8b",
+ "light": "#61c4fa",
+ "main": "#079cee",
+ },
"warning": Object {
"contrastText": "#ffffff",
"dark": "#996300",
@@ -1520,6 +1610,18 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"light": "#eb6d6b",
"main": "#d41f1c",
},
+ "experimental": Object {
+ "contrastText": "#fff",
+ "dark": "#540297",
+ "light": "#ba68fd",
+ "main": "#8c03fc",
+ },
+ "global": Object {
+ "contrastText": "#fff",
+ "dark": "#4d02b0",
+ "light": "#b681fd",
+ "main": "#7c1cfc",
+ },
"gray": Object {
"100": "#F5F5F5",
"50": "#FAFAFA",
@@ -1574,6 +1676,12 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"secondary": "#666",
},
"tonalOffset": 0.2,
+ "usonly": Object {
+ "contrastText": "#fff",
+ "dark": "#045b8b",
+ "light": "#61c4fa",
+ "main": "#079cee",
+ },
"warning": Object {
"contrastText": "#ffffff",
"dark": "#996300",
@@ -1799,6 +1907,18 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"light": "#eb6d6b",
"main": "#d41f1c",
},
+ "experimental": Object {
+ "contrastText": "#fff",
+ "dark": "#540297",
+ "light": "#ba68fd",
+ "main": "#8c03fc",
+ },
+ "global": Object {
+ "contrastText": "#fff",
+ "dark": "#4d02b0",
+ "light": "#b681fd",
+ "main": "#7c1cfc",
+ },
"gray": Object {
"100": "#F5F5F5",
"50": "#FAFAFA",
@@ -1853,6 +1973,12 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"secondary": "#666",
},
"tonalOffset": 0.2,
+ "usonly": Object {
+ "contrastText": "#fff",
+ "dark": "#045b8b",
+ "light": "#61c4fa",
+ "main": "#079cee",
+ },
"warning": Object {
"contrastText": "#ffffff",
"dark": "#996300",
@@ -2108,6 +2234,18 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"light": "#eb6d6b",
"main": "#d41f1c",
},
+ "experimental": Object {
+ "contrastText": "#fff",
+ "dark": "#540297",
+ "light": "#ba68fd",
+ "main": "#8c03fc",
+ },
+ "global": Object {
+ "contrastText": "#fff",
+ "dark": "#4d02b0",
+ "light": "#b681fd",
+ "main": "#7c1cfc",
+ },
"gray": Object {
"100": "#F5F5F5",
"50": "#FAFAFA",
@@ -2162,6 +2300,12 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"secondary": "#666",
},
"tonalOffset": 0.2,
+ "usonly": Object {
+ "contrastText": "#fff",
+ "dark": "#045b8b",
+ "light": "#61c4fa",
+ "main": "#079cee",
+ },
"warning": Object {
"contrastText": "#ffffff",
"dark": "#996300",
@@ -2379,6 +2523,18 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"light": "#eb6d6b",
"main": "#d41f1c",
},
+ "experimental": Object {
+ "contrastText": "#fff",
+ "dark": "#540297",
+ "light": "#ba68fd",
+ "main": "#8c03fc",
+ },
+ "global": Object {
+ "contrastText": "#fff",
+ "dark": "#4d02b0",
+ "light": "#b681fd",
+ "main": "#7c1cfc",
+ },
"gray": Object {
"100": "#F5F5F5",
"50": "#FAFAFA",
@@ -2433,6 +2589,12 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"secondary": "#666",
},
"tonalOffset": 0.2,
+ "usonly": Object {
+ "contrastText": "#fff",
+ "dark": "#045b8b",
+ "light": "#61c4fa",
+ "main": "#079cee",
+ },
"warning": Object {
"contrastText": "#ffffff",
"dark": "#996300",
@@ -2637,6 +2799,18 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"light": "#eb6d6b",
"main": "#d41f1c",
},
+ "experimental": Object {
+ "contrastText": "#fff",
+ "dark": "#540297",
+ "light": "#ba68fd",
+ "main": "#8c03fc",
+ },
+ "global": Object {
+ "contrastText": "#fff",
+ "dark": "#4d02b0",
+ "light": "#b681fd",
+ "main": "#7c1cfc",
+ },
"gray": Object {
"100": "#F5F5F5",
"50": "#FAFAFA",
@@ -2691,6 +2865,12 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"secondary": "#666",
},
"tonalOffset": 0.2,
+ "usonly": Object {
+ "contrastText": "#fff",
+ "dark": "#045b8b",
+ "light": "#61c4fa",
+ "main": "#079cee",
+ },
"warning": Object {
"contrastText": "#ffffff",
"dark": "#996300",
diff --git a/src/services/models/Operation.ts b/src/services/models/Operation.ts
index e26b4a4c..96fbb43a 100644
--- a/src/services/models/Operation.ts
+++ b/src/services/models/Operation.ts
@@ -20,7 +20,12 @@ import { RequestBodyModel } from './RequestBody';
import { ResponseModel } from './Response';
import { SideNavStyleEnum } from '../types';
-import type { OpenAPIExternalDocumentation, OpenAPIServer, OpenAPIXCodeSample } from '../../types';
+import type {
+ OpenAPIExternalDocumentation,
+ OpenAPIServer,
+ OpenAPIXCodeSample,
+ OperationCustomBadge,
+} from '../../types';
import type { OpenAPIParser } from '../OpenAPIParser';
import type { RedocNormalizedOptions } from '../RedocNormalizedOptions';
import type { MediaContentModel } from './MediaContent';
@@ -72,6 +77,7 @@ export class OperationModel implements IMenuItem {
operationHash?: string;
httpVerb: string;
deprecated: boolean;
+ badges: OperationCustomBadge[];
path: string;
servers: OpenAPIServer[];
security: SecurityRequirementModel[];
@@ -96,6 +102,7 @@ export class OperationModel implements IMenuItem {
this.externalDocs = operationSpec.externalDocs;
this.deprecated = !!operationSpec.deprecated;
+ this.badges = operationSpec['x-badges'] ? operationSpec['x-badges'] : [];
this.httpVerb = operationSpec.httpVerb;
this.deprecated = !!operationSpec.deprecated;
this.operationId = operationSpec.operationId;
diff --git a/src/theme.ts b/src/theme.ts
index e11209b6..4fca8a65 100644
--- a/src/theme.ts
+++ b/src/theme.ts
@@ -37,6 +37,24 @@ const defaultTheme: ThemeInterface = {
dark: ({ colors }) => darken(colors.tonalOffset, colors.error.main),
contrastText: ({ colors }) => readableColor(colors.error.main),
},
+ global: {
+ main: '#7c1cfc',
+ light: ({ colors }) => lighten(colors.tonalOffset, colors.global.main),
+ dark: ({ colors }) => darken(colors.tonalOffset, colors.global.main),
+ contrastText: ({ colors }) => readableColor(colors.global.main),
+ },
+ usonly: {
+ main: '#079cee',
+ light: ({ colors }) => lighten(colors.tonalOffset, colors.usonly.main),
+ dark: ({ colors }) => darken(colors.tonalOffset, colors.usonly.main),
+ contrastText: ({ colors }) => readableColor(colors.global.main),
+ },
+ experimental: {
+ main: '#8c03fc',
+ light: ({ colors }) => lighten(colors.tonalOffset, colors.experimental.main),
+ dark: ({ colors }) => darken(colors.tonalOffset, colors.experimental.main),
+ contrastText: ({ colors }) => readableColor(colors.experimental.main),
+ },
gray: {
50: '#FAFAFA',
100: '#F5F5F5',
@@ -267,6 +285,9 @@ export interface ResolvedThemeInterface {
success: ColorSetting;
warning: ColorSetting;
error: ColorSetting;
+ global: ColorSetting;
+ usonly: ColorSetting;
+ experimental: ColorSetting;
gray: {
50: string;
100: string;
diff --git a/src/types/open-api.ts b/src/types/open-api.ts
index fd80bf8d..dab3729c 100644
--- a/src/types/open-api.ts
+++ b/src/types/open-api.ts
@@ -64,6 +64,20 @@ export interface OpenAPIPath {
$ref?: string;
}
+export type OperationCustomBadgeType =
+ | 'primary'
+ | 'success'
+ | 'warning'
+ | 'error'
+ | 'global'
+ | 'usonly'
+ | 'experimental';
+
+export interface OperationCustomBadge {
+ name: string;
+ type: OperationCustomBadgeType;
+}
+
export interface OpenAPIXCodeSample {
lang: string;
label?: string;
@@ -83,6 +97,7 @@ export interface OpenAPIOperation {
deprecated?: boolean;
security?: OpenAPISecurityRequirement[];
servers?: OpenAPIServer[];
+ 'x-badges'?: OperationCustomBadge[];
'x-codeSamples'?: OpenAPIXCodeSample[];
'x-code-samples'?: OpenAPIXCodeSample[]; // deprecated
}
diff --git a/src/utils/__tests__/__snapshots__/loadAndBundleSpec.test.ts.snap b/src/utils/__tests__/__snapshots__/loadAndBundleSpec.test.ts.snap
index c1618ad3..6f3fc77e 100644
--- a/src/utils/__tests__/__snapshots__/loadAndBundleSpec.test.ts.snap
+++ b/src/utils/__tests__/__snapshots__/loadAndBundleSpec.test.ts.snap
@@ -773,6 +773,16 @@ and standard method from web, mobile and desktop applications.
"tags": Array [
"Tn Option",
],
+ "x-badges": Array [
+ Object {
+ "name": "1st Badge",
+ "type": "warning",
+ },
+ Object {
+ "name": "2nd Badge",
+ "type": "experimental",
+ },
+ ],
},
"post": Object {
"description": "Create TN Option order to assign line features to the telephone number.
Attribute description:
- for A2pSettings attribute
Number attribute | Action value | Description of action |
---|
LongCode | systemDefault | Removes the per-TN A2P attributes, and it reverts to the Location/SIP Peer characteristics. Any values for Class or Campaign ID are not valid |
LongCode | asSpecified | Sets the message class and campaign ID - this is the default if unspecified |
LongCode | off | Will set the TN as a 'P' TN. Any values for Class or Campaign ID are not valid |
LongCode | delete | Will delete the campaign ID from TN. Any values for Class or Campaign ID are not valid |
LongCode | unchanged | Do nothing with respect to A2P |
TollFree | systemDefault | Removes the per-TN A2P attributes, and it reverts to the Location/SIP Peer characteristics. Any values for Class or Campaign ID are not valid |
TollFree | asSpecified | Sets the message class and campaign ID - this is the default if unspecified |
TollFree | off | If the Togglz value is set to 'on' this is invalid for Toll Free telephone numbers. Any values for Class or Campaign ID in the payload are invalid. If the Togglz value is set to off this behaves like and A2P TN, where the characteristics of the TNs is set to 'P' |
TollFree | unchanged | Do nothing with respect to A2P |
- for Origination Route plan attribute
Action value | Description of action |
---|
asSpecified | Creates/updates the origination route plan for the TN with route plan details provided in the request |
off | Removes the origination route plan for the TN. Route list is the request must be empty |
unchanged | Doesn't update/create the origination route plan, even when route plan details exist in the request |
- Origination route plan is validated against CallForward and RewriteUser
- Route plan and CallForward cannot co-exist. Order is accepted but will respond with error messages on GET.
- Route plan and RewriteUser cannot co-exist. Order is accepted but will respond with error messages on GET.
- for Pindrop Enabled attribute
Action value | Description of action |
---|
true | Enables Pindrop integration on each phone number in the option group |
false | Explicitly disables Pindrop integration on each phone number in the option group |
- for other attribute
- systemDefault - implies that the element profile value should be removed so that the TN changes back to the default system behavior;
- unchanged - the value should remain unchanged - implies a read before write model.
- Leaving the element out of the payload is equivalent to unchanged.
",
@@ -1095,6 +1105,12 @@ and standard method from web, mobile and desktop applications.
"tags": Array [
"Tn Option",
],
+ "x-badges": Array [
+ Object {
+ "name": "Success",
+ "type": "success",
+ },
+ ],
},
},
"/pet": Object {
@@ -1144,6 +1160,12 @@ and standard method from web, mobile and desktop applications.
"tags": Array [
"pet",
],
+ "x-badges": Array [
+ Object {
+ "name": "Global",
+ "type": "global",
+ },
+ ],
"x-codeSamples": Array [
Object {
"lang": "C#",
@@ -1208,6 +1230,12 @@ try {
"tags": Array [
"pet",
],
+ "x-badges": Array [
+ Object {
+ "name": "US Only",
+ "type": "usonly",
+ },
+ ],
"x-codeSamples": Array [
Object {
"lang": "PHP",
diff --git a/src/utils/openapi.ts b/src/utils/openapi.ts
index 22424e90..561811c7 100644
--- a/src/utils/openapi.ts
+++ b/src/utils/openapi.ts
@@ -662,6 +662,7 @@ export function isRedocExtension(key: string): boolean {
'x-traitTag': true,
'x-additionalPropertiesName': true,
'x-explicitMappingOnly': true,
+ 'x-badges': true,
};
return key in redocExtensions;