From a2fe4c9ca46319e40210e0ed10b0bd14a351045d Mon Sep 17 00:00:00 2001 From: Roman Gotsiy Date: Fri, 9 Oct 2015 23:19:35 +0300 Subject: [PATCH] Moved duplicated code into base class/decorator --- demo/index.html | 4 +- lib/components/ApiInfo/api-info.js | 25 +++---- lib/components/Method/method.js | 29 ++------ lib/components/MethodsList/methods-list.js | 29 ++------ lib/components/PathsList/paths-list.js | 26 +++---- lib/components/Redoc/redoc.js | 20 ++---- lib/components/base.js | 81 ++++++++++++++++++++++ lib/utils/JsonPointer.js | 2 +- 8 files changed, 119 insertions(+), 97 deletions(-) create mode 100644 lib/components/base.js diff --git a/demo/index.html b/demo/index.html index 354b0554..3cd89bef 100644 --- a/demo/index.html +++ b/demo/index.html @@ -4,7 +4,7 @@ ReDoc prototype - + Loading... @@ -12,7 +12,7 @@ diff --git a/lib/components/ApiInfo/api-info.js b/lib/components/ApiInfo/api-info.js index 6bd41add..e1cf1cc1 100644 --- a/lib/components/ApiInfo/api-info.js +++ b/lib/components/ApiInfo/api-info.js @@ -1,27 +1,18 @@ 'use strict'; -import {Component, View, CORE_DIRECTIVES} from 'angular2/angular2'; -import {SchemaManager} from '../../utils/SchemaManager'; +import {RedocComponent, BaseComponent} from '../base'; -@Component({ - selector: 'api-info' -}) -@View({ - templateUrl: './lib/components/ApiInfo/api-info.html', +@RedocComponent({ + selector: 'api-info', styleUrls: ['./lib/components/ApiInfo/api-info.css'], - directives: [CORE_DIRECTIVES] + templateUrl: './lib/components/ApiInfo/api-info.html' }) -export class ApiInfo { +export class ApiInfo extends BaseComponent { constructor(schemaMgr) { - this.data = null; - this.schema = schemaMgr.schema; - this.extractData(); + super(schemaMgr); } - extractData() { - this.data = this.schema.info; - - //TODO: check and apply hooks to modify data + prepareModel() { + this.data = this.componentSchema.info; } } -ApiInfo.parameters = [[SchemaManager]]; diff --git a/lib/components/Method/method.js b/lib/components/Method/method.js index 9aa5ae42..a2565db5 100644 --- a/lib/components/Method/method.js +++ b/lib/components/Method/method.js @@ -1,36 +1,21 @@ 'use strict'; -import {Component, View, OnInit, CORE_DIRECTIVES} from 'angular2/angular2'; -import {SchemaManager} from '../../utils/SchemaManager'; import {JsonPointer} from '../../utils/JsonPointer'; +import {RedocComponent, BaseComponent} from '../base'; -@Component({ +@RedocComponent({ selector: 'method', - properties: ['pointer'], - lifecycle: [OnInit] + templateUrl: './lib/components/Method/method.html' }) -@View({ - templateUrl: './lib/components/Method/method.html', - directives: [CORE_DIRECTIVES] -}) -export class Method { +export class Method extends BaseComponent { constructor(schemaMgr) { - this.data = null; - this.schemaMgr = schemaMgr; + super(schemaMgr); } - onInit() { - this.extractData(); - } - - extractData() { + prepareModel() { this.data = {}; - var methodInfo = this.schemaMgr.byPointer(this.pointer); - this.data.method = JsonPointer.baseName(this.pointer); this.data.path = JsonPointer.baseName(this.pointer, 2); - this.data.methodInfo = methodInfo; - //TODO: check and apply hooks to modify data + this.data.methodInfo = this.componentSchema; } } -Method.parameters = [[SchemaManager]]; diff --git a/lib/components/MethodsList/methods-list.js b/lib/components/MethodsList/methods-list.js index 9ab7753f..e0e7c4f0 100644 --- a/lib/components/MethodsList/methods-list.js +++ b/lib/components/MethodsList/methods-list.js @@ -1,39 +1,24 @@ 'use strict'; -import {Component, View, OnInit, CORE_DIRECTIVES} from 'angular2/angular2'; -import {SchemaManager} from '../../utils/SchemaManager'; +import {RedocComponent, BaseComponent} from '../base'; import {methods as swaggerMethods} from '../../utils/swagger-defs'; import {Method} from '../Method/method'; -@Component({ +@RedocComponent({ selector: 'methods-list', - properties: ['pointer'], - lifecycle: [OnInit] -}) -@View({ templateUrl: './lib/components/MethodsList/methods-list.html', - directives: [CORE_DIRECTIVES, Method] + directives: [Method] }) -export class MethodsList { - _name: string; +export class MethodsList extends BaseComponent { constructor(schemaMgr) { - this.data = null; - this.schemaMgr = schemaMgr; - //this.pointer = pointer; - //this.extractData(); + super(schemaMgr); } - onInit() { - this.extractData(); - } - - extractData() { + prepareModel() { this.data = {}; - var pathInfo = this.schemaMgr.byPointer(this.pointer); + let pathInfo = this.componentSchema; this.data.methods = Object.keys(pathInfo).filter((k) => swaggerMethods.has(k)); - //TODO: check and apply hooks to modify data } } -MethodsList.parameters = [[SchemaManager]]; diff --git a/lib/components/PathsList/paths-list.js b/lib/components/PathsList/paths-list.js index 9d822d3f..ba3ab03c 100644 --- a/lib/components/PathsList/paths-list.js +++ b/lib/components/PathsList/paths-list.js @@ -1,30 +1,20 @@ 'use strict'; -import {Component, View, CORE_DIRECTIVES} from 'angular2/angular2'; -import {SchemaManager} from '../../utils/SchemaManager'; +import {RedocComponent, BaseComponent} from '../base'; import {MethodsList} from '../MethodsList/methods-list'; -import {JsonPointerEscapePipe} from '../../utils/pipes'; -@Component({ - selector: 'paths-list' -}) -@View({ +@RedocComponent({ + selector: 'paths-list', templateUrl: './lib/components/PathsList/paths-list.html', - directives: [CORE_DIRECTIVES, MethodsList], - pipes: [JsonPointerEscapePipe] + directives: [MethodsList] }) -export class PathsList { +export class PathsList extends BaseComponent { constructor(schemaMgr) { - this.data = null; - this.schema = schemaMgr.schema; - this.extractData(); + super(schemaMgr); } - extractData() { + prepareModel() { this.data = {}; - this.data.paths = Object.keys(this.schema.paths); - - //TODO: check and apply hooks to modify data + this.data.paths = Object.keys(this.componentSchema.paths); } } -PathsList.parameters = [[SchemaManager]]; diff --git a/lib/components/Redoc/redoc.js b/lib/components/Redoc/redoc.js index f1e0459e..0f9c44b9 100644 --- a/lib/components/Redoc/redoc.js +++ b/lib/components/Redoc/redoc.js @@ -1,28 +1,18 @@ 'use strict'; -import {Component, View} from 'angular2/angular2'; +import {RedocComponent, BaseComponent} from '../base'; import {SchemaManager} from '../../utils/SchemaManager'; import {ApiInfo} from '../ApiInfo/api-info'; import {PathsList} from '../PathsList/paths-list'; -@Component({ +@RedocComponent({ selector: 'redoc', - bindings: [SchemaManager] -}) -@View({ + bindings: [SchemaManager], templateUrl: './lib/components/Redoc/redoc.html', directives: [ApiInfo, PathsList] }) -export class Redoc { +export class Redoc extends BaseComponent { constructor(schemaMgr) { - this.data = null; - this.schema = schemaMgr.schema; - this.extractData(); - } - - extractData() { - this.data = this.schema; - //TODO: check and apply hooks to modify data + super(schemaMgr); } } -Redoc.parameters = [[SchemaManager]]; diff --git a/lib/components/base.js b/lib/components/base.js new file mode 100644 index 00000000..030da682 --- /dev/null +++ b/lib/components/base.js @@ -0,0 +1,81 @@ +'use strict'; +import {Component, View, OnInit, CORE_DIRECTIVES} from 'angular2/angular2'; +import {SchemaManager} from '../utils/SchemaManager'; +import {JsonPointerEscapePipe} from '../utils/pipes'; + +// common inputs for all components +let commonInputs = ['pointer']; // json pointer to the schema chunk + +// internal helper function +function safeConcat(a, b) { + let res = a && a.slice() || []; + b = (b == null) ? [] : b; + return res.concat(b); +} + +/** + * Class decorator + * Simplifies setup of component metainfo + * All options are options from either Component or View angular2 decorator + * For detailed info look angular2 doc + * @param {Object} options - component options + * @param {string[]} options.inputs - component inputs + * @param {*[]} options.directives - directives used by component + * (except CORE_DIRECTIVES) + * @param {*[]} options.pipes - pipes used by component + * @param {*[]} options.bindings - component bindings + * @param {string} options.templateUrl - path to component template + * @param {string} options.template - component template html + * @param {string} options.styles - component css styles + */ +export function RedocComponent(options) { + let inputs = safeConcat(options.inputs, commonInputs); + let directives = safeConcat(options.directives, CORE_DIRECTIVES); + let pipes = safeConcat(options.pipes, [JsonPointerEscapePipe]); + + return function decorator(target) { + + let componentDecorator = Component({ + selector: options.selector, + inputs: inputs, + lifecycle: [OnInit], + bindings: options.bindings + }); + let viewDecorator = View({ + templateUrl: options.templateUrl, + template: options.template, + styles: options.styles, + directives: directives, + pipes: pipes + }); + + return componentDecorator(viewDecorator(target) || target) || target; + }; +} + +/** + * Generic Component + * @class + */ +export class BaseComponent { + constructor(schemaMgr) { + this.schemaMgr = schemaMgr; + this.schema = schemaMgr.schema; + this.componentSchema = null; + } + + /** + * onInit method is run by angular2 after all component inputs are resolved + */ + onInit() { + this.componentSchema = this.schemaMgr.byPointer(this.pointer || ''); + this.prepareModel(); + } + + /** + * Used to prepare model based on component schema + * @abstract + */ + prepareModel() {} +} +BaseComponent.parameters = [[SchemaManager]]; diff --git a/lib/utils/JsonPointer.js b/lib/utils/JsonPointer.js index dfb3d2a6..a6775c37 100644 --- a/lib/utils/JsonPointer.js +++ b/lib/utils/JsonPointer.js @@ -16,7 +16,7 @@ export class JsonPointer extends JsonPointerLib { * JsonPointerHelper.baseName('/path/foo/subpath', 2) */ static baseName(pointer, level=1) { - var tokens = JsonPointer.parse(pointer); + let tokens = JsonPointer.parse(pointer); return tokens[tokens.length - (level)]; } }