From 43527b197d98e8c21da95d753435c3baa2b4884a Mon Sep 17 00:00:00 2001 From: Maksymilian Fryc Date: Thu, 17 Aug 2017 13:33:13 +0200 Subject: [PATCH] Small fixes, update docs and readme --- README.md | 1 + docs/redoc-vendor-extensions.md | 37 ++++ lib/components/SideMenu/fixed-array.ts | 188 +++++++++++++++++++ lib/components/SideMenu/side-menu.spec.ts | 15 +- lib/components/SideMenu/side-menu.ts | 20 +- lib/components/SideMenu/sort.ts | 217 ++-------------------- lib/services/menu.service.ts | 8 +- 7 files changed, 272 insertions(+), 214 deletions(-) create mode 100644 lib/components/SideMenu/fixed-array.ts diff --git a/README.md b/README.md index 469c6a23..553298df 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ ReDoc makes use of the following [vendor extensions](http://swagger.io/specifica * [`x-displayName`](docs/redoc-vendor-extensions.md#x-displayname) - specify human-friendly names for the menu categories * [`x-tagGroups`](docs/redoc-vendor-extensions.md#x-tagGroups) - group tags by categories in the side menu * [`x-servers`](docs/redoc-vendor-extensions.md#x-servers) - ability to specify different servers for API (backported from OpenAPI 3.0) +* [`x-sort-order`](docs/redoc-vendor-extensions.md#x-sort-order) - specify custom sorting for endpoints ### `` tag attributes * `spec-url` - relative or absolute url to your spec file; diff --git a/docs/redoc-vendor-extensions.md b/docs/redoc-vendor-extensions.md index b285aafb..da696779 100644 --- a/docs/redoc-vendor-extensions.md +++ b/docs/redoc-vendor-extensions.md @@ -243,3 +243,40 @@ PayPalPayment: In the example above the names of definitions (`PayPalPayment`) are named differently than names in the payload (`paypal`) which is not supported by default `discriminator`. + +### Sort endpoints vendor extensions +#### x-sort-order +| Field Name | Type | Description | +| :------------- | :------: | :---------- | +| x-sort-order | int | specifies sorting order | + +###### Usage in ReDoc +By using `x-sort-order` you can override default alphabetical sorting and arrange elements in any way you want. + + +Add `x-sort-order` with number from 0 to number of elements in group - 1 (e.g. for 3 items, the scope is 0-2). +Endpoints with lower `x-sort-order` number come first in a group. + +###### x-sort-order example + +``` +/store/inventory: + get: + tags: + - store + summary: Return pet inventories by status + x-sort-order: 1 + description: Returns a map of status codes to quantities + +/store/order: + post: + tags: + - store + summary: Place an order for a pet + x-sort-order: 0 + description: Places an order for a pet + +``` + +In this example "Place an order for a pet" endpoint will come before "Return pet inventories by status" +(because of the `x-sort-order` property). \ No newline at end of file diff --git a/lib/components/SideMenu/fixed-array.ts b/lib/components/SideMenu/fixed-array.ts new file mode 100644 index 00000000..34dd77bf --- /dev/null +++ b/lib/components/SideMenu/fixed-array.ts @@ -0,0 +1,188 @@ +export let fixedMenuItemsList = +[ + { + name: "Pagination", + id: "section/Pagination", + items: [] + }, + { + name: "JSONP", + id: "section/JSONP", + items: [] + }, + { + name: "Authentication", + id: "section/Authentication", + items: [] + }, + { + name: "pet", + id: "tag/pet", + items: [ + { + name: "Deletes a pet", + id: "/paths/~1pet~1{petId}/delete", + metadata: {operation: "delete"} + }, + { + name: "Find pet by ID", + id: "/paths/~1pet~1{petId}/get", + metadata: {operation: "get"} + }, + { + name: "Finds Pets by status", + id: "/paths/~1pet~1findByStatus/get", + metadata: {operation: "get"} + }, + { + name: "Finds Pets by tags", + id: "/paths/~1pet~1findByTags/get", + metadata: {operation: "get"} + }, + { + name: "Add a new pet to the store", + id: "/paths/~1pet/post", + metadata: {operation: "post"} + }, + { + name: "Updates a pet in the store with form data", + id: "/paths/~1pet~1{petId}/post", + metadata: {operation: "post"} + }, + { + name: "uploads an image", + id: "/paths/~1pet~1{petId}~1uploadImage/post", + metadata: {operation: "post"} + }, + { + name: "Update an existing pet", + id: "/paths/~1pet/put", + metadata: {operation: "put"} + } + ] + }, + { + name: "store", + id: "tag/store", + items: [ + { + name: "Delete purchase order by ID", + id: "/paths/~1store~1order~1{orderId}/delete", + metadata: {operation: "delete"} + }, + { + name: "Find purchase order by ID", + id: "/paths/~1store~1order~1{orderId}/get", + metadata: {operation: "get"} + }, + { + name: "Returns pet inventories by status", + id: "/paths/~1store~1inventory/get", + metadata: {operation: "get"} + }, + { + name: "Place an order for a pet", + id: "/paths/~1store~1order/post", + metadata: {operation: "post"} + } + ] + }, + { + name: "user", + id: "tag/user", + items: [ + { + name: "Delete user", + id: "/paths/~1user~1{username}/delete", + metadata: {operation: "delete"} + }, + { + name: "Get user by user name", + id: "/paths/~1user~1{username}/get", + metadata: {operation: "get"} + }, + { + name: "Logs out current logged in user session", + id: "/paths/~1user~1logout/get", + metadata: {operation: "get"} + }, + { + name: "Logs user into the system", + id: "/paths/~1user~1login/get", + metadata: {operation: "get"} + }, + { + name: "Create user", + id: "/paths/~1user/post", + metadata: {operation: "post"} + }, + { + name: "Creates list of users with given input array", + id: "/paths/~1user~1createWithArray/post", + metadata: {operation: "post"} + }, + { + name: "Creates list of users with given input array", + id: "/paths/~1user~1createWithList/post", + metadata: {operation: "post"} + }, + { + name: "Updated user", + id: "/paths/~1user~1{username}/put", + metadata: {operation: "put"} + } + ] + }, + { + name: "Pagination", + id: "tag/Pagination", + items: [ + { + name: "Finds Pets by status", + id: "/paths/~1pet~1findByStatus/get", + metadata: {operation: "get"} + }, + { + name: "Finds Pets by tags", + id: "/paths/~1pet~1findByTags/get", + metadata: {operation: "get"} + } + ] + }, + { + name: "JSONP", + id: "tag/JSONP", + items: [ + { + name: "Find pet by ID", + id: "/paths/~1pet~1{petId}/get", + metadata: {operation: "get"} + }, + { + name: "Find purchase order by ID", + id: "/paths/~1store~1order~1{orderId}/get", + metadata: {operation: "get"} + }, + { + name: "Finds Pets by status", + id: "/paths/~1pet~1findByStatus/get", + metadata: {operation: "get"} + }, + { + name: "Finds Pets by tags", + id: "/paths/~1pet~1findByTags/get", + metadata: {operation: "get"} + }, + { + name: "Get user by user name", + id: "/paths/~1user~1{username}/get", + metadata: {operation: "post"} + }, + { + name: "Returns pet inventories by status", + id: "/paths/~1store~1inventory/get", + metadata: {operation: "post"} + } + ] + } +]; \ No newline at end of file diff --git a/lib/components/SideMenu/side-menu.spec.ts b/lib/components/SideMenu/side-menu.spec.ts index b9ed63fa..e653d907 100644 --- a/lib/components/SideMenu/side-menu.spec.ts +++ b/lib/components/SideMenu/side-menu.spec.ts @@ -3,7 +3,8 @@ import { getChildDebugElement } from '../../../tests/helpers'; import { Component } from '@angular/core'; import { OptionsService, MenuItem } from '../../services/index'; -import { compareEndpoints, menuItemsList } from './sort'; +import { endpointComparator } from './sort'; +import { fixedMenuItemsList } from './fixed-array'; import { inject, @@ -66,12 +67,14 @@ describe('Redoc components', () => { }); it('should confirm that component is sorted', () => { - for(var i=0;i { +export const endpointComparator = (a, b) => { let sortOrderComparisonResult: number; - if(a.metadata.sortOrder != null && b.metadata.sortOrder != null) - sortOrderComparisonResult = a.metadata.sortOrder.localeCompare(b.metadata.sortOrder); let operationComparisonResult: number; - if(a.metadata.operation != null && b.metadata.operation != null) - operationComparisonResult = a.metadata.operation.localeCompare(b.metadata.operation); let nameComparisonResult: number = a.name.localeCompare(b.name); - if(sortOrderComparisonResult != null && sortOrderComparisonResult !== 0) - return sortOrderComparisonResult; - else if(operationComparisonResult != null && operationComparisonResult !== 0) - return operationComparisonResult; - else - return nameComparisonResult; -} -export let menuItemsList = -[ - { - name: "Pagination", - id: "section/Pagination", - items: [] - }, - { - name: "JSONP", - id: "section/JSONP", - items: [] - }, - { - name: "Authentication", - id: "section/Authentication", - items: [] - }, - { - name: "pet", - id: "tag/pet", - items: [ - { - name: "Deletes a pet", - id: "/paths/~1pet~1{petId}/delete", - metadata: {operation: "delete"} - }, - { - name: "Find pet by ID", - id: "/paths/~1pet~1{petId}/get", - metadata: {operation: "get"} - }, - { - name: "Finds Pets by status", - id: "/paths/~1pet~1findByStatus/get", - metadata: {operation: "get"} - }, - { - name: "Finds Pets by tags", - id: "/paths/~1pet~1findByTags/get", - metadata: {operation: "get"} - }, - { - name: "Add a new pet to the store", - id: "/paths/~1pet/post", - metadata: {operation: "post"} - }, - { - name: "Updates a pet in the store with form data", - id: "/paths/~1pet~1{petId}/post", - metadata: {operation: "post"} - }, - { - name: "uploads an image", - id: "/paths/~1pet~1{petId}~1uploadImage/post", - metadata: {operation: "post"} - }, - { - name: "Update an existing pet", - id: "/paths/~1pet/put", - metadata: {operation: "put"} - } - ] - }, - { - name: "store", - id: "tag/store", - items: [ - { - name: "Delete purchase order by ID", - id: "/paths/~1store~1order~1{orderId}/delete", - metadata: {operation: "delete"} - }, - { - name: "Find purchase order by ID", - id: "/paths/~1store~1order~1{orderId}/get", - metadata: {operation: "get"} - }, - { - name: "Returns pet inventories by status", - id: "/paths/~1store~1inventory/get", - metadata: {operation: "get"} - }, - { - name: "Place an order for a pet", - id: "/paths/~1store~1order/post", - metadata: {operation: "post"} - } - ] - }, - { - name: "user", - id: "tag/user", - items: [ - { - name: "Delete user", - id: "/paths/~1user~1{username}/delete", - metadata: {operation: "delete"} - }, - { - name: "Get user by user name", - id: "/paths/~1user~1{username}/get", - metadata: {operation: "get"} - }, - { - name: "Logs out current logged in user session", - id: "/paths/~1user~1logout/get", - metadata: {operation: "get"} - }, - { - name: "Logs user into the system", - id: "/paths/~1user~1login/get", - metadata: {operation: "get"} - }, - { - name: "Create user", - id: "/paths/~1user/post", - metadata: {operation: "post"} - }, - { - name: "Creates list of users with given input array", - id: "/paths/~1user~1createWithArray/post", - metadata: {operation: "post"} - }, - { - name: "Creates list of users with given input array", - id: "/paths/~1user~1createWithList/post", - metadata: {operation: "post"} - }, - { - name: "Updated user", - id: "/paths/~1user~1{username}/put", - metadata: {operation: "put"} - } - ] - }, - { - name: "Pagination", - id: "tag/Pagination", - items: [ - { - name: "Finds Pets by status", - id: "/paths/~1pet~1findByStatus/get", - metadata: {operation: "get"} - }, - { - name: "Finds Pets by tags", - id: "/paths/~1pet~1findByTags/get", - metadata: {operation: "get"} - } - ] - }, - { - name: "JSONP", - id: "tag/JSONP", - items: [ - { - name: "Find pet by ID", - id: "/paths/~1pet~1{petId}/get", - metadata: {operation: "get"} - }, - { - name: "Find purchase order by ID", - id: "/paths/~1store~1order~1{orderId}/get", - metadata: {operation: "get"} - }, - { - name: "Finds Pets by status", - id: "/paths/~1pet~1findByStatus/get", - metadata: {operation: "get"} - }, - { - name: "Finds Pets by tags", - id: "/paths/~1pet~1findByTags/get", - metadata: {operation: "get"} - }, - { - name: "Get user by user name", - id: "/paths/~1user~1{username}/get", - metadata: {operation: "post"} - }, - { - name: "Returns pet inventories by status", - id: "/paths/~1store~1inventory/get", - metadata: {operation: "post"} - } - ] + if(a.metadata.sortOrder != null && b.metadata.sortOrder != null) { + sortOrderComparisonResult = a.metadata.sortOrder.localeCompare(b.metadata.sortOrder); } -]; \ No newline at end of file + + if(a.metadata.operation != null && b.metadata.operation != null) { + operationComparisonResult = a.metadata.operation.localeCompare(b.metadata.operation); + } + + if(sortOrderComparisonResult != null && sortOrderComparisonResult !== 0) { + return sortOrderComparisonResult; + } + else if(operationComparisonResult != null && operationComparisonResult !== 0) { + return operationComparisonResult; + } + else { + return nameComparisonResult; + } +} \ No newline at end of file diff --git a/lib/services/menu.service.ts b/lib/services/menu.service.ts index 5c71173a..2b7efb92 100644 --- a/lib/services/menu.service.ts +++ b/lib/services/menu.service.ts @@ -334,7 +334,13 @@ export class MenuService { for (let operationInfo of tag.operations) { let xSortOrder; let orderInfo = operationInfo['x-sort-order']; - if(orderInfo>=0 && orderInfo= 0 && orderInfo < tag.operations.length && Number.isInteger(orderInfo)) { + xSortOrder = operationInfo['x-sort-order']; + } + } + let subItem = { name: SchemaHelper.operationSummary(operationInfo), id: operationInfo._pointer,