Skip to content

Commit

Permalink
feat: new option required-props-first
Browse files Browse the repository at this point in the history
closes #191
  • Loading branch information
RomanHotsiy committed Feb 27, 2017
1 parent ffcedee commit c724df4
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 5 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -138,6 +138,7 @@ ReDoc makes use of the following [vendor extensions](http://swagger.io/specifica
* `lazy-rendering` - if set, enables lazy rendering mode in ReDoc. This mode is useful for APIs with big number of operations (e.g. > 50). In this mode ReDoc shows initial screen ASAP and then renders the rest operations asynchronously while showing progress bar on the top. Check out the [demo](\\rebilly.github.io/ReDoc) for the example.
* `hide-hostname` - if set, the protocol and hostname is not shown in the method definition.
* `expand-responses` - specify which responses to expand by default by response codes. Values should be passed as comma-separated list without spaces e.g. `expand-responses="200,201"`. Special value `"all"` expands all responses by default. Be careful: this option can slow-down documentation rendering time.
* `required-props-first` - show required properties first ordered in the same order as in `required` array.

This comment has been minimized.

Copy link
@yupitomets

yupitomets Jan 12, 2022

How and where this flag can be set?


## Advanced usage
Instead of adding `spec-url` attribute to the `<redoc>` element you can initialize ReDoc via globally exposed `Redoc` object:
Expand Down
13 changes: 9 additions & 4 deletions lib/components/JsonSchema/json-schema.ts
Expand Up @@ -10,7 +10,7 @@ import { Component,
} from '@angular/core';

import { BaseSearchableComponent, SpecManager } from '../base';
import { SchemaNormalizer, SchemaHelper, AppStateService } from '../../services/';
import { SchemaNormalizer, SchemaHelper, AppStateService, OptionsService } from '../../services/';
import { JsonPointer, DescendantInfo } from '../../utils/';
import { Zippy } from '../../shared/components';
import { JsonSchemaLazy } from './json-schema-lazy';
Expand Down Expand Up @@ -39,11 +39,12 @@ export class JsonSchema extends BaseSearchableComponent implements OnInit {
descendants: DescendantInfo[];

constructor(
specMgr:SpecManager,
specMgr: SpecManager,
app: AppStateService,
private _renderer: Renderer,
private cdr: ChangeDetectorRef,
private _elementRef: ElementRef) {
private _elementRef: ElementRef,
private optionsService: OptionsService) {
super(specMgr, app);
this.normalizer = new SchemaNormalizer(specMgr);
}
Expand Down Expand Up @@ -126,7 +127,11 @@ export class JsonSchema extends BaseSearchableComponent implements OnInit {

this.properties = this.schema._properties || [];
if (this.isRequestSchema) {
this.properties = this.properties && this.properties.filter(prop => !prop.readOnly);
this.properties = this.properties.filter(prop => !prop.readOnly);
}

if (this.optionsService.options.requiredPropsFirst) {
SchemaHelper.moveRequiredPropsFirst(this.properties, this.schema.required);
}

this._hasSubSchemas = this.properties && this.properties.some(
Expand Down
5 changes: 4 additions & 1 deletion lib/services/options.service.ts
Expand Up @@ -15,7 +15,8 @@ const OPTION_NAMES = new Set([
'suppressWarnings',
'hideHostname',
'lazyRendering',
'expandResponses'
'expandResponses',
'requiredPropsFirst'
]);

interface Options {
Expand All @@ -27,6 +28,7 @@ interface Options {
lazyRendering?: boolean;
expandResponses?: Set<string> | 'all';
$scrollParent?: HTMLElement | Window;
requiredPropsFirst?: boolean;
}

@Injectable()
Expand Down Expand Up @@ -91,6 +93,7 @@ export class OptionsService {
if (isString(this._options.suppressWarnings)) this._options.suppressWarnings = true;
if (isString(this._options.hideHostname)) this._options.hideHostname = true;
if (isString(this._options.lazyRendering)) this._options.lazyRendering = true;
if (isString(this._options.requiredPropsFirst)) this._options.requiredPropsFirst = true;
if (isString(this._options.expandResponses)) {
let str = this._options.expandResponses as string;
if (str === 'all') return;
Expand Down
45 changes: 45 additions & 0 deletions lib/services/schema-helper.service.spec.ts
Expand Up @@ -86,4 +86,49 @@ describe('Spec Helper', () => {
(() => SchemaHelper.preprocessProperties(schema, '#/', {})).should.not.throw();
});
});

describe('moveRequiredPropsFirst', () => {
it('should move required props to the top', () => {
let props = [{
name: 'prop2',
type: 'string'
},
{
name: 'prop1',
type: 'number',
_required: true
}];

let required = ['prop1'];

SchemaHelper.moveRequiredPropsFirst(props, required);
props[0].name.should.be.equal('prop1');
props[1].name.should.be.equal('prop2');
});

it('should sort required props by the order or required', () => {
var props = [{
name: 'prop2',
type: 'string'
},
{
name: 'prop1',
type: 'number',
_required: true
},
{
name: 'prop3',
type: 'number',
_required: true
}
];

let required = ['prop3', 'prop1'];

SchemaHelper.moveRequiredPropsFirst(props, required);
props[0].name.should.be.equal('prop3');
props[1].name.should.be.equal('prop1');
props[2].name.should.be.equal('prop2');
});
});
});
15 changes: 15 additions & 0 deletions lib/services/schema-helper.service.ts
Expand Up @@ -327,4 +327,19 @@ export class SchemaHelper {

return tags;
}

static moveRequiredPropsFirst(properties: any[], _required: string[]|null) {
let required = _required || [];
properties.sort((a, b) => {
if ((!a._required && b._required)) {
return 1;
} else if (a._required && !b._required) {
return -1;
} else if (a._required && b._required) {
return required.indexOf(a.name) > required.indexOf(b.name) ? 1 : -1;
} else {
return 0;
}
});
}
}

1 comment on commit c724df4

@dolmen
Copy link

@dolmen dolmen commented on c724df4 Mar 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sort function could be accelerated (code not tested):

if (a._required) {
  return (!b._required || required.indexOf(a.name) <= required.indexOf(b.name)) ? -1 : 1;
}
return b._required ? 1 : 0;

Please sign in to comment.