feat: new option required-props-first

closes #191
This commit is contained in:
Roman Hotsiy 2017-02-27 12:08:57 +02:00
parent ffcedeeb8e
commit c724df48f4
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
5 changed files with 74 additions and 5 deletions

View File

@ -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.
## Advanced usage
Instead of adding `spec-url` attribute to the `<redoc>` element you can initialize ReDoc via globally exposed `Redoc` object:

View File

@ -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';
@ -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);
}
@ -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(

View File

@ -15,7 +15,8 @@ const OPTION_NAMES = new Set([
'suppressWarnings',
'hideHostname',
'lazyRendering',
'expandResponses'
'expandResponses',
'requiredPropsFirst'
]);
interface Options {
@ -27,6 +28,7 @@ interface Options {
lazyRendering?: boolean;
expandResponses?: Set<string> | 'all';
$scrollParent?: HTMLElement | Window;
requiredPropsFirst?: boolean;
}
@Injectable()
@ -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;

View File

@ -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');
});
});
});

View File

@ -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;
}
});
}
}