Get rid of prepareModel method. Use init instead

This commit is contained in:
Roman Hotsiy 2016-07-20 11:07:08 +03:00
parent d75e9921c2
commit 82f1be1d11
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
26 changed files with 117 additions and 130 deletions

View File

@ -1,17 +1,17 @@
<div>
<h1 class="api-info-header">{{data.title}} ({{data.version}})</h1>
<p *ngIf="data.description" [innerHtml]="data.description | marked"> </p>
<h1 class="api-info-header">{{info.title}} ({{info.version}})</h1>
<p *ngIf="info.description" [innerHtml]="info.description | marked"> </p>
<p>
<!-- TODO: create separate components for contact and license ? -->
<span *ngIf="data.contact"> Contact:
<a *ngIf="data.contact.url" href="{{data.contact.url}}">
{{data.contact.name || data.contact.url}}</a>
<a *ngIf="data.contact.email" href="mailto:{{data.contact.email}}">
{{data.contact.email}}</a>
<span *ngIf="info.contact"> Contact:
<a *ngIf="info.contact.url" href="{{info.contact.url}}">
{{info.contact.name || info.contact.url}}</a>
<a *ngIf="info.contact.email" href="mailto:{{info.contact.email}}">
{{info.contact.email}}</a>
</span>
<span *ngIf="data.license"> License:
<a *ngIf="data.license.url" href="{{data.license.url}}"> {{data.license.name}} </a>
<span *ngIf="!data.license.url"> {{data.license.name}} </span>
<span *ngIf="info.license"> License:
<a *ngIf="info.license.url" href="{{info.license.url}}"> {{info.license.name}} </a>
<span *ngIf="!info.license.url"> {{info.license.name}} </span>
</span>
</p>
<p>

View File

@ -32,8 +32,8 @@ describe('Redoc components', () => {
it('should init component data', () => {
expect(component).not.toBeNull();
expect(component.data).not.toBeNull();
component.data.title.should.be.equal('Swagger Petstore');
expect(component.info).not.toBeNull();
component.info.title.should.be.equal('Swagger Petstore');
});
it('should render api name and version', () => {

View File

@ -9,17 +9,17 @@ import { OptionsService } from '../../services/index';
templateUrl: './api-info.html'
})
export class ApiInfo extends BaseComponent {
data: any;
info: any;
specUrl: String;
constructor(specMgr:SpecManager, private optionsService:OptionsService) {
super(specMgr);
}
prepareModel() {
this.data = this.componentSchema.info;
init() {
this.info = this.componentSchema.info;
this.specUrl = this.optionsService.options.specUrl;
if (parseInt(this.data.version.substring(0, 1)) !== NaN) {
this.data.version = 'v' + this.data.version;
if (parseInt(this.info.version.substring(0, 1)) !== NaN) {
this.info.version = 'v' + this.info.version;
}
}
}

View File

@ -1 +1 @@
<img *ngIf="data.imgUrl" [attr.src]="data.imgUrl" [ngStyle]="{'background-color': data.bgColor}">
<img *ngIf="logo.imgUrl" [attr.src]="logo.imgUrl" [ngStyle]="{'background-color': logo.bgColor}">

View File

@ -35,11 +35,11 @@ describe('Redoc components', () => {
it('should init component data', () => {
expect(component).not.toBeNull();
expect(component.data).not.toBeNull();
expect(component.logo).not.toBeNull();
});
it('should not display image when no x-logo', () => {
component.data.should.be.empty();
component.logo.should.be.empty();
let nativeElement = getChildDebugElement(fixture.debugElement, 'api-logo').nativeElement;
let imgElement = nativeElement.querySelector('img');
expect(imgElement).toBeNull();
@ -49,8 +49,8 @@ describe('Redoc components', () => {
});
it('should load values from spec and use transparent bgColor by default', () => {
component.data.imgUrl.should.endWith('petstore-logo.png');
component.data.bgColor.should.be.equal('transparent');
component.logo.imgUrl.should.endWith('petstore-logo.png');
component.logo.bgColor.should.be.equal('transparent');
});
});
});

View File

@ -8,16 +8,16 @@ import {RedocComponent, BaseComponent, SpecManager} from '../base';
templateUrl: './api-logo.html'
})
export class ApiLogo extends BaseComponent {
data:any = {};
logo:any = {};
constructor(specMgr:SpecManager) {
super(specMgr);
}
prepareModel() {
init() {
let logoInfo = this.componentSchema.info['x-logo'];
if (!logoInfo) return;
this.data.imgUrl = logoInfo.url;
this.data.bgColor = logoInfo.backgroundColor || 'transparent';
this.logo.imgUrl = logoInfo.url;
this.logo.bgColor = logoInfo.backgroundColor || 'transparent';
}
}

View File

@ -68,7 +68,7 @@ export class JsonSchema extends BaseComponent {
this.selectDescendant(0);
}
prepareModel() {
init() {
if (this.nestOdd) {
this._renderer.setElementAttribute(this._elementRef.nativeElement, 'nestodd', 'true');
}

View File

@ -1,13 +1,13 @@
<div class="method">
<div class="method-content">
<h2 class="method-header sharable-header">
<a class="share-link" href="#{{data.methodAnchor}}"></a>{{data.summary}}
<a class="share-link" href="#{{method.anchor}}"></a>{{method.summary}}
</h2>
<div class="method-tags" *ngIf="data.methodInfo.tags.length">
<a *ngFor="let tag of data.methodInfo.tags" attr.href="#{{tag}}"> {{tag}} </a>
<div class="method-tags" *ngIf="method.info.tags.length">
<a *ngFor="let tag of method.info.tags" attr.href="#{{tag}}"> {{tag}} </a>
</div>
<p *ngIf="data.methodInfo.description" class="method-description"
[innerHtml]="data.methodInfo.description | marked">
<p *ngIf="method.info.description" class="method-description"
[innerHtml]="method.info.description | marked">
</p>
<params-list pointer="{{pointer}}/parameters"> </params-list>
<responses-list pointer="{{pointer}}/responses"> </responses-list>
@ -16,15 +16,15 @@
<h5>Definition</h5>
<div class="method-endpoint">
<h5 class="http-method" [ngClass]="data.httpMethod">{{data.httpMethod}}</h5>
<h5 class="http-method" [ngClass]="method.httpMethod">{{method.httpMethod}}</h5>
<span select-on-click><!--
--><span class="api-url">{{data.apiUrl}}</span><span class="path">{{data.path}}</span><!--
--><span class="api-url">{{method.apiUrl}}</span><span class="path">{{method.path}}</span><!--
--></span>
</div>
<div *ngIf="data.bodyParam">
<div *ngIf="method.bodyParam">
<br>
<request-samples [pointer]="pointer" [schemaPointer]="data.bodyParam._pointer">
<request-samples [pointer]="pointer" [schemaPointer]="method.bodyParam._pointer">
</request-samples>
</div>
<div>

View File

@ -34,14 +34,14 @@ describe('Redoc components', () => {
});
it('should init basic component data', () => {
component.data.apiUrl.should.be.equal('http://petstore.swagger.io/v2');
component.data.httpMethod.should.be.equal('put');
component.data.path.should.be.equal('/user/{username}');
component.method.apiUrl.should.be.equal('http://petstore.swagger.io/v2');
component.method.httpMethod.should.be.equal('put');
component.method.path.should.be.equal('/user/{username}');
});
it('should main tag', () => {
component.data.methodInfo.tags.should.be.empty();
component.method.info.tags.should.be.empty();
});
});
});

View File

@ -20,25 +20,25 @@ import { SchemaHelper } from '../../services/schema-helper.service';
detect: true
})
export class Method extends BaseComponent {
data:any;
method:any;
@Input() tag:string;
constructor(specMgr:SpecManager) {
super(specMgr);
}
prepareModel() {
this.data = {};
this.data.apiUrl = this.specMgr.apiUrl;
this.data.httpMethod = JsonPointer.baseName(this.pointer);
this.data.path = JsonPointer.baseName(this.pointer, 2);
this.data.methodInfo = this.componentSchema;
this.data.methodInfo.tags = this.filterMainTags(this.data.methodInfo.tags);
this.data.bodyParam = this.findBodyParam();
this.data.summary = SchemaHelper.methodSummary(this.componentSchema);
init() {
this.method = {};
this.method.apiUrl = this.specMgr.apiUrl;
this.method.httpMethod = JsonPointer.baseName(this.pointer);
this.method.path = JsonPointer.baseName(this.pointer, 2);
this.method.info = this.componentSchema;
this.method.info.tags = this.filterMainTags(this.method.info.tags);
this.method.bodyParam = this.findBodyParam();
this.method.summary = SchemaHelper.methodSummary(this.componentSchema);
if (this.componentSchema.operationId) {
this.data.methodAnchor = 'operation/' + encodeURIComponent(this.componentSchema.operationId);
this.method.anchor = 'operation/' + encodeURIComponent(this.componentSchema.operationId);
} else {
this.data.methodAnchor = 'tag/' + encodeURIComponent(this.tag + this.pointer);
this.method.anchor = 'tag/' + encodeURIComponent(this.tag + this.pointer);
}
}

View File

@ -1,5 +1,5 @@
<div class="methods">
<div class="tag" *ngFor="let tag of data.tags;trackBy:trackByTagName">
<div class="tag" *ngFor="let tag of tags;trackBy:trackByTagName">
<div class="tag-info" [attr.tag]="tag.name" *ngIf="!tag.empty">
<h1 class="sharable-header"> <a class="share-link" href="#tag/{{tag.name | encodeURIComponent}}"></a>{{tag.name}} </h1>
<p *ngIf="tag.description" [innerHtml]="tag.description | marked"> </p>

View File

@ -35,12 +35,12 @@ describe('Redoc components', () => {
});
it('should get correct tags list', () => {
expect(component.data.tags).not.toBeNull();
component.data.tags.should.have.lengthOf(2);
component.data.tags[0].name.should.be.equal('traitTag');
component.data.tags[0].methods.should.be.empty();
component.data.tags[1].name.should.be.equal('tag1');
component.data.tags[1].methods.should.have.lengthOf(2);
expect(component.tags).not.toBeNull();
component.tags.should.have.lengthOf(2);
component.tags[0].name.should.be.equal('traitTag');
component.tags[0].methods.should.be.empty();
component.tags[1].name.should.be.equal('tag1');
component.tags[1].methods.should.have.lengthOf(2);
});
});
});

View File

@ -15,13 +15,13 @@ import { SchemaHelper } from '../../services/index';
detect: true
})
export class MethodsList extends BaseComponent {
data:any;
tags:Array<any>;
constructor(specMgr:SpecManager) {
super(specMgr);
}
prepareModel() {
this.data = {};
init() {
this.tags = [];
// follow SwaggerUI behavior for cases when one method has more than one tag:
// duplicate methods
@ -33,8 +33,7 @@ export class MethodsList extends BaseComponent {
method.tag = tagInfo.name;
});
});
this.data.tags = tags;
// TODO: check $ref field
this.tags = tags;
}
trackByPointer(idx, el) {

View File

@ -1,5 +1,5 @@
<h5 class="param-list-header" *ngIf="data.params.length"> Parameters </h5>
<template ngFor [ngForOf]="data.params" let-paramType="$implicit">
<h5 class="param-list-header" *ngIf="params.length"> Parameters </h5>
<template ngFor [ngForOf]="params" let-paramType="$implicit">
<header class="paramType">
{{paramType.place}} Parameters
<span class="hint--top-right hint--large" [attr.data-hint]="paramType.placeHint">?</span>
@ -26,13 +26,13 @@
</div>
</template>
<div *ngIf="data.bodyParam">
<h5 class="param-list-header" *ngIf="data.bodyParam"> Request Body </h5>
<div *ngIf="bodyParam">
<h5 class="param-list-header" *ngIf="bodyParam"> Request Body </h5>
<div class="body-param-description" [innerHtml]="data.bodyParam.description | marked"></div>
<div class="body-param-description" [innerHtml]="bodyParam.description | marked"></div>
<div>
<br>
<json-schema-lazy [isRequestSchema]="true" [auto]="true" pointer="{{data.bodyParam.pointer}}/schema">
<json-schema-lazy [isRequestSchema]="true" [auto]="true" pointer="{{bodyParam.pointer}}/schema">
</json-schema-lazy>
</div>
</div>

View File

@ -18,14 +18,16 @@ function safePush(obj, prop, item) {
})
export class ParamsList extends BaseComponent {
data:any;
params: Array<any>;
empty: boolean;
bodyParam: any;
constructor(specMgr:SpecManager) {
super(specMgr);
}
prepareModel() {
this.data = {};
init() {
this.params = [];
let paramsList = this.specMgr.getMethodParams(this.pointer, true);
paramsList = paramsList.map(paramSchema => {
@ -40,11 +42,11 @@ export class ParamsList extends BaseComponent {
if (paramsMap.body && paramsMap.body.length) {
let bodyParam = paramsMap.body[0];
bodyParam.pointer = bodyParam._pointer;
this.data.bodyParam = bodyParam;
this.bodyParam = bodyParam;
paramsMap.body = undefined;
}
this.data.noParams = !(Object.keys(paramsMap).length || this.data.bodyParam);
this.empty = !(Object.keys(paramsMap).length || this.bodyParam);
let paramsPlaces = ['path', 'query', 'formData', 'header', 'body'];
let placeHint = {
@ -64,7 +66,7 @@ export class ParamsList extends BaseComponent {
params.push({place: place, placeHint: placeHint[place], params: paramsMap[place]});
}
});
this.data.params = params;
this.params = params;
}
orderParams(params):any {

View File

@ -1,10 +1,10 @@
<header *ngIf="data.schemaPointer || data.samples.length"> Request samples </header>
<schema-sample *ngIf="!data.samples.length" [skipReadOnly]="true" [pointer]="data.schemaPointer"> </schema-sample>
<tabs *ngIf="data.samples.length" [selected] = "selectedLang" (change)=changeLangNotify($event)>
<header *ngIf="schemaPointer || samples.length"> Request samples </header>
<schema-sample *ngIf="!samples.length" [skipReadOnly]="true" [pointer]="schemaPointer"> </schema-sample>
<tabs *ngIf="samples.length" [selected] = "selectedLang" (change)=changeLangNotify($event)>
<tab tabTitle="JSON">
<schema-sample [pointer]="data.schemaPointer" [skipReadOnly]="true"> </schema-sample>
<schema-sample [pointer]="schemaPointer" [skipReadOnly]="true"> </schema-sample>
</tab>
<tab *ngFor="let sample of data.samples" [tabTitle]="sample.lang">
<tab *ngFor="let sample of samples" [tabTitle]="sample.lang">
<div class="code-sample">
<div class="action-buttons">
<span copy-button [copyText]="sample.source" class="hint--top-left hint--inversed"><a>Copy</a></span>

View File

@ -24,7 +24,9 @@ import { CopyButton } from '../../shared/components/CopyButton/copy-button.direc
export class RequestSamples extends BaseComponent {
childTabs: Tabs;
selectedLang: EventEmitter<any>;
data: any;
samples: Array<any>;
@Input() schemaPointer:string;
@ViewChildren(Tabs) childQuery:QueryList<Tabs>;
constructor(specMgr:SpecManager, public events:RedocEventsService) {
@ -38,9 +40,8 @@ export class RequestSamples extends BaseComponent {
this.events.samplesLanguageChanged.next(lang);
}
prepareModel() {
this.data = {};
this.data.schemaPointer = JsonPointer.join(this.schemaPointer, 'schema');
this.data.samples = this.componentSchema['x-code-samples'] || [];
init() {
this.schemaPointer = JsonPointer.join(this.schemaPointer, 'schema');;
this.samples = this.componentSchema['x-code-samples'] || [];
}
}

View File

@ -1,5 +1,5 @@
<h2 class="responses-list-header" *ngIf="data.responses.length"> Responses </h2>
<zippy *ngFor="let response of data.responses;trackBy:trackByCode" title="{{response.code}} {{response.description}}"
<h2 class="responses-list-header" *ngIf="responses.length"> Responses </h2>
<zippy *ngFor="let response of responses;trackBy:trackByCode" title="{{response.code}} {{response.description}}"
[type]="response.type" [empty]="response.empty" (open)="lazySchema.load()">
<div *ngIf="response.headers" class="response-headers">
<header>

View File

@ -20,16 +20,15 @@ function isNumeric(n) {
detect: true
})
export class ResponsesList extends BaseComponent {
data: any;
responses: Array<any>;
options: any;
constructor(specMgr:SpecManager, optionsMgr:OptionsService) {
super(specMgr);
this.options = optionsMgr.options;
}
prepareModel() {
this.data = {};
this.data.responses = [];
init() {
this.responses = [];
let responses = this.componentSchema;
if (!responses) return;
@ -60,7 +59,7 @@ export class ResponsesList extends BaseComponent {
resp.extendable = resp.headers || resp.length;
return resp;
});
this.data.responses = responses;
this.responses = responses;
}
trackByCode(idx, el) {

View File

@ -29,7 +29,7 @@ export class ResponsesSamples extends BaseComponent {
super(specMgr);
}
prepareModel() {
init() {
this.data = {};
this.data.responses = [];

View File

@ -1,10 +1,10 @@
<div class="snippet">
<!-- in case sample is not available for some reason -->
<pre *ngIf="data.sample == undefined"> Sample unavailable </pre>
<pre *ngIf="sample == undefined"> Sample unavailable </pre>
<div class="action-buttons">
<span> <a *ngIf="enableButtons" (click)="collapseAll()">Collapse all</a> </span>
<span> <a *ngIf="enableButtons" (click)="expandAll()">Expand all</a> </span>
<span copy-button [copyText]="data.sample | json" class="hint--top hint--inversed"> <a>Copy</a> </span>
<span copy-button [copyText]="sample | json" class="hint--top hint--inversed"> <a>Copy</a> </span>
</div>
<pre [innerHtml]="data.sample | jsonFormatter"></pre>
<pre [innerHtml]="sample | jsonFormatter"></pre>
</div>

View File

@ -19,7 +19,7 @@ import { CopyButton } from '../../shared/components/CopyButton/copy-button.direc
})
export class SchemaSample extends BaseComponent {
element: any;
data: any;
sample: any;
enableButtons: boolean = false;
@Input() skipReadOnly:boolean;
@ -33,7 +33,6 @@ export class SchemaSample extends BaseComponent {
init() {
this.bindEvents();
this.data = {};
let base:any = {};
let sample;
@ -78,12 +77,12 @@ export class SchemaSample extends BaseComponent {
}
}
this.cache(sample);
this.data.sample = sample;
this.sample = sample;
this.initButtons();
}
initButtons() {
if (typeof this.data.sample === 'object') {
if (typeof this.sample === 'object') {
this.enableButtons = true;
}
}
@ -98,10 +97,10 @@ export class SchemaSample extends BaseComponent {
fromCache() {
if (this.skipReadOnly && this.componentSchema['x-redoc-ro-sample']) {
this.data.sample = this.componentSchema['x-redoc-ro-sample'];
this.sample = this.componentSchema['x-redoc-ro-sample'];
return true;
} else if (this.componentSchema['x-redoc-rw-sample']) {
this.data.sample = this.componentSchema['x-redoc-rw-sample'];
this.sample = this.componentSchema['x-redoc-rw-sample'];
return true;
}
return false;

View File

@ -7,9 +7,9 @@
</div>
<div #desktop id="resources-nav">
<h5 class="menu-header"> API reference </h5>
<div *ngFor="let cat of data.menu; let idx = index" class="menu-cat">
<div *ngFor="let cat of categories; let idx = index" class="menu-cat">
<label class="menu-cat-header" (click)="activateAndScroll(idx, -1)" [hidden]="cat.empty"
<label class="menu-cat-header" (click)="activateAndScroll(idx, -1)" [hidden]="cat.empty"
[ngClass]="{active: cat.active}"> {{cat.name}}</label>
<ul class="menu-subitems" @itemAnimation="cat.active ? 'expanded' : 'collapsed'">
<li *ngFor="let method of cat.methods; let methIdx = index"

View File

@ -27,14 +27,16 @@ import { ScrollService, Hash, MenuService, OptionsService } from '../../services
],
})
export class SideMenu extends BaseComponent {
$element: any;
$mobileNav: any;
$resourcesNav: any;
$scrollParent: any;
activeCatCaption: string;
activeItemCaption: string;
options: any;
data: any;
categories: any;
private options: any;
private $element: any;
private $mobileNav: any;
private $resourcesNav: any;
private $scrollParent: any;
constructor(specMgr:SpecManager, elementRef:ElementRef, private dom:BrowserDomAdapter,
private scrollService:ScrollService, private menuService:MenuService, private hash:Hash,
optionsService:OptionsService, private detectorRef:ChangeDetectorRef) {
@ -66,6 +68,8 @@ export class SideMenu extends BaseComponent {
}
init() {
this.categories = this.menuService.categories;
this.$mobileNav = this.dom.querySelector(this.$element, '.mobile-nav');
this.$resourcesNav = this.dom.querySelector(this.$element, '#resources-nav');
@ -76,11 +80,6 @@ export class SideMenu extends BaseComponent {
};
}
prepareModel() {
this.data = {};
this.data.menu = this.menuService.categories;
}
mobileMode() {
return this.$mobileNav.clientHeight > 0;
}

View File

@ -29,14 +29,11 @@ describe('Redoc components', () => {
component.componentSchema.should.be.deepEqual(specMgr._schema.tags);
});
it('should call prepareModel and init virtual methods after init', () => {
spyOn(component, 'prepareModel');
it('should call init virtual methods after init', () => {
spyOn(component, 'init');
component.ngOnInit();
component.prepareModel.calls.count().should.be.equal(1);
component.init.calls.count().should.be.equal(1);
component.prepareModel.and.callThrough();
component.init.and.callThrough();
});
});

View File

@ -90,7 +90,6 @@ export class BaseComponent implements OnInit, OnDestroy {
*/
ngOnInit() {
this.componentSchema = this.specMgr.byPointer(this.pointer || '');
this.prepareModel();
this.init();
}
@ -99,15 +98,7 @@ export class BaseComponent implements OnInit, OnDestroy {
}
/**
* Used to prepare model based on component schema
* @abstract
*/
prepareModel():any {
// emtpy
}
/**
* Used to initialize component. Run after prepareModel
* Used to initialize component
* @abstract
*/
init() {