From a5c14e36ef484e2cb20dc60daeb017b18ea27d27 Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Tue, 29 Nov 2016 09:00:33 +0200 Subject: [PATCH 01/19] Add links to changelog --- CHANGELOG.md | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60a80b9c..5e9d4a7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,35 +1,35 @@ # 1.4.0 (2016-10-14) ### Bug fixes * Fix destroy/reinit -* Fix minimum/maximum zero not rendered (#123) +* Fix minimum/maximum zero not rendered ([#123](https://github.com/Rebilly/ReDoc/issues/123)) ### Features/Improvements * Do spec load after bootstrap -* Build and publish angular2 module (#126) +* Build and publish angular2 module ([#126](https://github.com/Rebilly/ReDoc/issues/126)) # 1.3.3 (2016-09-28) ### Features/Improvements -* implemented x-extendedDiscriminator to workaround name clashes in big specs -* Add engines to package.json (#83) -* Fix npm start on windows (#119, #118) +* Implemented x-extendedDiscriminator to workaround name clashes in big specs +* Add engines to package.json ([#83](https://github.com/Rebilly/ReDoc/issues/83)) +* Fix npm start on windows ([#119](https://github.com/Rebilly/ReDoc/issues/119), [#118](https://github.com/Rebilly/ReDoc/issues/118)) * Update webpack to latest beta * Update angular to 2.0.1 * Update local dev steps -* Update openapi-sampler lib (#111) +* Update openapi-sampler lib ([#111](https://github.com/Rebilly/ReDoc/issues/111)) # 1.3.2 (2016-09-13) ### Bug fixes * Fix broken tabs styling for response samples -* fix v1.x.x deployment +* Fix v1.x.x deployment # 1.3.1 (2016-09-13) ### Bug fixes -* makes basePath optional (by @LeFnord) -* fixed little typo (by @adamd) +* Makes basePath optional (by @LeFnord) +* Fixed little typo (by @adamd) * Typo s/IGNORRED/IGNORED (by @MikeRalphson) * Fixed indentation (by @bennyn) -* Fix default hostname (#108) -* Fix default value for falsy values is not displayed (#109) +* Fix default hostname ([#108](https://github.com/Rebilly/ReDoc/issues/108)) +* Fix default value for falsy values is not displayed ([#109](https://github.com/Rebilly/ReDoc/issues/109)) * Fix schema collapse after change discriminator ### Features/Improvements @@ -39,24 +39,24 @@ # 1.3.0 (2016-08-31) ### Bug fixes -* Fix code samples are not shown for operations without body param (#93) -* Fixed side menu overlapped site footer (#75) +* Fix code samples are not shown for operations without body param ([#93](https://github.com/Rebilly/ReDoc/issues/93)) +* Fixed side menu overlapped site footer ([#75](https://github.com/Rebilly/ReDoc/issues/75)) * Fix broken order in discriminator dropdown ### Features/Improvements -* Support "x-nullable" property by @kedashoe (#92) +* Support "x-nullable" property by @kedashoe ([#92](https://github.com/Rebilly/ReDoc/issues/92)) # 1.2.0 (2016-08-30) ### Bug fixes -* Fix sticky sidebar top sticking (#75) -* Fix array inside objects if referenced directly (#84) -* Add banner to the bundle file (#89) +* Fix sticky sidebar top sticking ([#75](https://github.com/Rebilly/ReDoc/issues/75)) +* Fix array inside objects if referenced directly ([#84](https://github.com/Rebilly/ReDoc/issues/84)) +* Add banner to the bundle file ([#89](https://github.com/Rebilly/ReDoc/issues/89)) * Fix broken additionalProperties * Fix version render issue (extra "v" letter) ### Features/Improvements * Change the way discriminator is rendered -* Created CDN major release 1.x.x (#87) +* Created CDN major release 1.x.x ([#87](https://github.com/Rebilly/ReDoc/issues/87)) * Smaller bundle size (371KB gzipped) * Better start-up time due to [AoT](http://blog.mgechev.com/2016/08/14/ahead-of-time-compilation-angular-offline-precompilation/) @@ -67,12 +67,12 @@ # 1.1.2 (2016-08-21) ### Bug fixes -* Revert "Fix markdown newlines to be GFM" (#82) +* Revert "Fix markdown newlines to be GFM" ([#82](https://github.com/Rebilly/ReDoc/issues/82)) * Move license and contact info above description # 1.1.1 (2016-08-21) ### Bug fixes -* Fix markdown newlines to be GFM (#82) +* Fix markdown newlines to be GFM ([#82](https://github.com/Rebilly/ReDoc/issues/82)) * Fix markdown code blocks in api description # 1.1.0 (2016-08-12) @@ -83,8 +83,8 @@ ### Features/Improvements -* Add Tuple support (arrays with separate schema for each value) (#69) -* Add special representation for enum with one value (#70) +* Add Tuple support (arrays with separate schema for each value) ([#69](https://github.com/Rebilly/ReDoc/issues/69)) +* Add special representation for enum with one value ([#70](https://github.com/Rebilly/ReDoc/issues/70)) * Change `< * >` notation to `< anything >` From aef4039949003ce13a74eb1b205d1cc7ccf201ba Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Tue, 29 Nov 2016 09:01:19 +0200 Subject: [PATCH 02/19] Update changelog with the new versions :tada: (closes #148) --- CHANGELOG.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e9d4a7e..fdc18639 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,44 @@ +# 1.5.2 (2016-11-28) +### Bug fixes +* Fix crashing on array without items ([#104](https://github.com/Rebilly/ReDoc/issues/104)) +* Fix `allOf` within array items ([#136](https://github.com/Rebilly/ReDoc/issues/136)) +* Fix reference resolution from external files ([#96](https://github.com/Rebilly/ReDoc/issues/96)) +* Fix object to become an array ([#146](https://github.com/Rebilly/ReDoc/issues/146)) + +### Features/Improvements +* Add support for Swagger `collectionFormat` +* Wrap API version in span with class ([#145](https://github.com/Rebilly/ReDoc/issues/145)) +* Update openapi-sampler to 0.3.3 + +# 1.5.1 (2016-10-31) +### Bug fixes +* Fix content scrolling on language switch ([#130](https://github.com/Rebilly/ReDoc/issues/130)) + +### Features/Improvements +* Support for Swagger `pattern` property ([#42](https://github.com/Rebilly/ReDoc/issues/42)) +* Add option to hide hostname in method definition (by @bfirsh) +* Add Docker development environment (by @bfirsh) + +# 1.5.0 (2016-10-31) +### Bug fixes +* Fix side menu items wrong sync with description headers + +### Features/Improvements +* Support for Security Definitions +* Update angular2 to the 2.1.2 + +### Deprecations +* Deprecate `x-traitTag` + +### Code refactoring +* Separate RedocModule from AppModule +* Get rid of angular facade/lang dependencies +* Error handler refactor + +# 1.4.1 (2016-10-18) +### Bug fixes +* Emit helpers for module build + # 1.4.0 (2016-10-14) ### Bug fixes * Fix destroy/reinit From a8285b2652b714311076998593aef894a79ee0ea Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Tue, 29 Nov 2016 09:20:11 +0200 Subject: [PATCH 03/19] Update webpack to the latest beta --- build/webpack.dev.js | 10 ++++++---- build/webpack.prod.js | 2 +- build/webpack.test.js | 2 +- package.json | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/build/webpack.dev.js b/build/webpack.dev.js index 3235c5fe..3d483811 100644 --- a/build/webpack.dev.js +++ b/build/webpack.dev.js @@ -37,7 +37,9 @@ module.exports = { }, devServer: { - outputPath: root('dist'), + contentBase: root('demo'), + watchContentBase: true, + compress: true, watchOptions: { poll: true }, @@ -95,15 +97,15 @@ module.exports = { exclude: [/\.(spec|e2e)\.ts$/] }, { test: /lib[\\\/].*\.scss$/, - loaders: ['raw-loader', "sass"], + loaders: ['raw-loader', "sass-loader"], exclude: [/redoc-initial-styles\.scss$/] }, { test: /\.scss$/, - loaders: ['style', 'css?-import', "sass"], + loaders: ['style-loader', 'css-loader?-import', "sass-loader"], exclude: [/lib[\\\/](?!.*redoc-initial-styles).*\.scss$/] }, { test: /\.css$/, - loaders: ['style', 'css?-import'], + loaders: ['style-loader', 'css-loader?-import'], }, { test: /\.html$/, loader: 'raw-loader' diff --git a/build/webpack.prod.js b/build/webpack.prod.js index 5fc59973..54ef935c 100644 --- a/build/webpack.prod.js +++ b/build/webpack.prod.js @@ -70,7 +70,7 @@ const config = { exclude: [/redoc-initial-styles\.css$/] }, { test: /\.css$/, - loaders: ['style', 'css?-import'], + loaders: ['style-loader', 'css-loader?-import'], exclude: [/lib[\\\/](?!.*redoc-initial-styles).*\.css$/] }] }, diff --git a/build/webpack.test.js b/build/webpack.test.js index 519cc56a..12eedc31 100644 --- a/build/webpack.test.js +++ b/build/webpack.test.js @@ -61,7 +61,7 @@ module.exports = { exclude: [/redoc-initial-styles\.css$/] }, { test: /\.css$/, - loaders: ['style', 'css?-import'], + loaders: ['style-loader', 'css-loader?-import'], exclude: [/lib[\\\/](?!.*redoc-initial-styles).*\.css$/] }, { test: /\.html$/, diff --git a/package.json b/package.json index ea685788..ee341ead 100644 --- a/package.json +++ b/package.json @@ -96,8 +96,8 @@ "ts-helpers": "^1.1.1", "tslint": "^3.15.1", "typescript": "^2.0.3", - "webpack": "^2.1.0-beta.25", - "webpack-dev-server": "^2.1.0-beta.10", + "webpack": "^2.1.0-beta.27", + "webpack-dev-server": "^2.1.0-beta.12", "zone.js": "^0.6.25" }, "dependencies": { From 7e7db9f36e9b112d982f38b3f5187790205e635f Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Tue, 29 Nov 2016 17:54:21 +0200 Subject: [PATCH 04/19] Enable cors-proxy --- demo/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/main.js b/demo/main.js index 332b9aeb..1255acf6 100644 --- a/demo/main.js +++ b/demo/main.js @@ -7,7 +7,7 @@ var url = window.location.search.match(/url=([^&]+)/); if (url && url.length > 1) { url = decodeURIComponent(url[1]); - document.getElementsByTagName('redoc')[0].setAttribute('spec-url', url); + document.getElementsByTagName('redoc')[0].setAttribute('spec-url', '\\\\cors.apis.guru/' + url); } function updateQueryStringParameter(uri, key, value) { From 878d3191f92fb525c31b412e6cb834f95d2c64f4 Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Tue, 29 Nov 2016 19:11:39 +0200 Subject: [PATCH 05/19] README: Add button link to yeoman-generator --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 57e419fb..8f849d27 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ ## [Live demo](http://rebilly.github.io/ReDoc/) +[](https://github.com/Rebilly/generator-openapi-repo#generator-openapi-repo--) + ## Features - Extremely easy deployment - It’s free and open-source project under MIT license From 5bd0ac2d11d01c91fb75c8b98418b35c29e65f22 Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Tue, 29 Nov 2016 21:54:09 +0200 Subject: [PATCH 06/19] Fix read-only fields appear in request samples (fixes #142) --- lib/components/SchemaSample/schema-sample.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/SchemaSample/schema-sample.ts b/lib/components/SchemaSample/schema-sample.ts index 70de0887..40cedfff 100644 --- a/lib/components/SchemaSample/schema-sample.ts +++ b/lib/components/SchemaSample/schema-sample.ts @@ -98,7 +98,7 @@ export class SchemaSample extends BaseComponent implements OnInit { if (this.skipReadOnly && this.componentSchema['x-redoc-ro-sample']) { this.sample = this.componentSchema['x-redoc-ro-sample']; return true; - } else if (this.componentSchema['x-redoc-rw-sample']) { + } else if (!this.skipReadOnly && this.componentSchema['x-redoc-rw-sample']) { this.sample = this.componentSchema['x-redoc-rw-sample']; return true; } From 4208660a6f8f94bd1b6a18a3f71347d0270ccd5f Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Wed, 23 Nov 2016 01:23:32 +0200 Subject: [PATCH 07/19] Perfromance fix (tests still failing) --- .../JsonSchema/_json-schema-common.scss | 6 +- lib/components/JsonSchema/json-schema-lazy.ts | 5 +- lib/components/LoadingBar/loading-bar.ts | 49 ++++++ lib/components/Method/method.html | 26 +-- lib/components/Method/method.scss | 16 +- lib/components/Method/method.ts | 18 +- lib/components/MethodsList/methods-list.html | 4 +- lib/components/MethodsList/methods-list.scss | 5 + .../MethodsList/methods-list.spec.ts | 1 - lib/components/ParamsList/params-list.scss | 8 +- lib/components/Redoc/redoc.html | 4 + lib/components/Redoc/redoc.scss | 36 +++- lib/components/Redoc/redoc.ts | 28 +++- .../RequestSamples/request-samples.scss | 2 +- .../ResponsesSamples/responses-samples.scss | 2 +- .../SchemaSample/schema-sample.html | 4 +- .../SchemaSample/schema-sample.scss | 34 +--- lib/components/SideMenu/side-menu.html | 4 +- lib/components/index.ts | 7 +- lib/index.ts | 4 +- lib/redoc.module.ts | 6 +- lib/services/app-state.service.ts | 15 +- lib/services/hash.service.spec.ts | 3 +- lib/services/hash.service.ts | 2 +- lib/services/menu.service.spec.ts | 39 ++--- lib/services/menu.service.ts | 73 ++++++-- lib/services/schema-helper.service.ts | 15 +- lib/services/scroll.service.ts | 48 +++++- .../CopyButton/copy-button.directive.ts | 2 +- lib/shared/components/LazyFor/lazy-for.ts | 157 ++++++++++++++++++ .../StickySidebar/sticky-sidebar.ts | 2 +- lib/shared/components/Tabs/tabs.ts | 3 + lib/shared/components/Zippy/zippy.scss | 4 +- lib/shared/components/index.ts | 6 +- lib/shared/styles/_variables.scss | 2 +- lib/utils/helpers.ts | 4 + lib/utils/spec-manager.ts | 2 +- manual-types/index.d.ts | 7 + 38 files changed, 508 insertions(+), 145 deletions(-) create mode 100644 lib/components/LoadingBar/loading-bar.ts create mode 100644 lib/shared/components/LazyFor/lazy-for.ts diff --git a/lib/components/JsonSchema/_json-schema-common.scss b/lib/components/JsonSchema/_json-schema-common.scss index dcdf57bb..7a22f1e3 100644 --- a/lib/components/JsonSchema/_json-schema-common.scss +++ b/lib/components/JsonSchema/_json-schema-common.scss @@ -27,6 +27,10 @@ $sub-schema-offset: ($bullet-size / 2) + $bullet-margin; width: 75%; box-sizing: border-box; + + > div { + line-height: 1; + } } .param-range { @@ -41,7 +45,7 @@ $sub-schema-offset: ($bullet-size / 2) + $bullet-margin; } .param-description { - font-size: 13px; + //font-size: 14px; } .param-required { diff --git a/lib/components/JsonSchema/json-schema-lazy.ts b/lib/components/JsonSchema/json-schema-lazy.ts index 4cfe9143..2427b701 100644 --- a/lib/components/JsonSchema/json-schema-lazy.ts +++ b/lib/components/JsonSchema/json-schema-lazy.ts @@ -12,7 +12,8 @@ var cache = {}; @Component({ selector: 'json-schema-lazy', entryComponents: [ JsonSchema ], - template: '' + template: '', + styles: [':host { display:none }'] }) export class JsonSchemaLazy implements OnDestroy, AfterViewInit { @Input() pointer: string; @@ -66,7 +67,7 @@ export class JsonSchemaLazy implements OnDestroy, AfterViewInit { this._loadAfterSelf(); return; } - insertAfter($element.cloneNode(true), this.elementRef.nativeElement); + //insertAfter($element.cloneNode(true), this.elementRef.nativeElement); this.loaded = true; } else { cache[this.pointer] = this._loadAfterSelf(); diff --git a/lib/components/LoadingBar/loading-bar.ts b/lib/components/LoadingBar/loading-bar.ts new file mode 100644 index 00000000..8666deb7 --- /dev/null +++ b/lib/components/LoadingBar/loading-bar.ts @@ -0,0 +1,49 @@ +'use strict'; +import { Input, HostBinding, Component, OnInit, ChangeDetectionStrategy, ElementRef, ChangeDetectorRef } from '@angular/core'; +import JsonPointer from '../../utils/JsonPointer'; +import { BaseComponent, SpecManager } from '../base'; +import { SchemaHelper } from '../../services/schema-helper.service'; +import { OptionsService, AppStateService } from '../../services/'; + +@Component({ + selector: 'loading-bar', + template: ` + + `, + styles: [` + :host { + position: fixed; + top: 0; + left: 0; + right: 0; + display: block; + + height: 5px; + z-index: 100; + } + + span { + display: block; + position: absolute; + left: 0; + top: 0; + bottom: 0; + right: attr(progress percentage); + background-color: #5f7fc3; + transition: right 0.2s linear; + } + `], + //changeDetection: ChangeDetectionStrategy.OnPush +}) +export class LoadingBar { + @Input() progress:number = 0; + @HostBinding('style.display') display = 'block'; + + ngOnChanges(ch) { + if (ch.progress.currentValue === 100) { + setTimeout(() => { + this.display = 'none'; + }, 500); + } + } +} diff --git a/lib/components/Method/method.html b/lib/components/Method/method.html index 861ff11a..d9b1afe6 100644 --- a/lib/components/Method/method.html +++ b/lib/components/Method/method.html @@ -1,18 +1,18 @@ -
-
-

- {{method.summary}} -

- -

+

+
+

+ {{method.summary}} +

+ +

-
-
+
+

Definition

@@ -30,5 +30,5 @@
+
-
diff --git a/lib/components/Method/method.scss b/lib/components/Method/method.scss index 8d644a94..0306b61e 100644 --- a/lib/components/Method/method.scss +++ b/lib/components/Method/method.scss @@ -6,18 +6,20 @@ display: block; border-bottom: 1px solid rgba(127, 127, 127, 0.25); margin-top: 1em; + transform: translateZ(0); + z-index: 2; } -:host:last-of-type { - border-bottom: 0; -} +// :host:last-of-type { +// border-bottom: 0; +// } .method-header { - margin-bottom: .9em; + margin-bottom: calc(1em - 6px); } .method-endpoint { - margin: 0 0 2em 0; + //margin: 0 0 2px 0; padding: 10px 20px; border-radius: $border-radius*2; background-color: darken($black, 2%); @@ -31,8 +33,8 @@ padding-top: 1px; padding-bottom: 0; margin: 0; - font-size: .8em; - color: $black; + font-size: 12/14em; + color: $black; vertical-align: middle; display: inline-block; border-radius: $border-radius; diff --git a/lib/components/Method/method.ts b/lib/components/Method/method.ts index 80f23ce0..b846684f 100644 --- a/lib/components/Method/method.ts +++ b/lib/components/Method/method.ts @@ -1,9 +1,9 @@ 'use strict'; -import { Input, Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { Input, Component, OnInit, ChangeDetectionStrategy, ElementRef, ChangeDetectorRef } from '@angular/core'; import JsonPointer from '../../utils/JsonPointer'; import { BaseComponent, SpecManager } from '../base'; import { SchemaHelper } from '../../services/schema-helper.service'; -import { OptionsService } from '../../services/options.service'; +import { OptionsService, AppStateService } from '../../services/'; @Component({ selector: 'method', @@ -14,10 +14,14 @@ import { OptionsService } from '../../services/options.service'; export class Method extends BaseComponent implements OnInit { @Input() pointer:string; @Input() tag:string; + @Input() posInfo: any; + + hidden = true; method:any; - constructor(specMgr:SpecManager, private optionsService: OptionsService) { + constructor(specMgr:SpecManager, private optionsService: OptionsService, private chDetector: ChangeDetectorRef, + private appState: AppStateService, private el: ElementRef) { super(specMgr); } @@ -53,6 +57,14 @@ export class Method extends BaseComponent implements OnInit { return bodyParam; } + show(res) { + if (res) { + this.el.nativeElement.firstElementChild.removeAttribute('hidden'); + } else { + this.el.nativeElement.firstElementChild.setAttribute('hidden', 'hidden'); + } + } + ngOnInit() { this.preinit(); } diff --git a/lib/components/MethodsList/methods-list.html b/lib/components/MethodsList/methods-list.html index 11f4f859..225a1930 100644 --- a/lib/components/MethodsList/methods-list.html +++ b/lib/components/MethodsList/methods-list.html @@ -1,10 +1,10 @@
-
+

{{tag.name}}

-
diff --git a/lib/components/MethodsList/methods-list.scss b/lib/components/MethodsList/methods-list.scss index 0cfbfa50..fe57d8c2 100644 --- a/lib/components/MethodsList/methods-list.scss +++ b/lib/components/MethodsList/methods-list.scss @@ -4,6 +4,11 @@ display: block; overflow: hidden; } + +:host [hidden] { + display: none; +} + .tag-info { padding: $section-spacing; box-sizing: border-box; diff --git a/lib/components/MethodsList/methods-list.spec.ts b/lib/components/MethodsList/methods-list.spec.ts index ca59e157..69a7afda 100644 --- a/lib/components/MethodsList/methods-list.spec.ts +++ b/lib/components/MethodsList/methods-list.spec.ts @@ -23,7 +23,6 @@ describe('Redoc components', () => { let fixture; beforeEach(async(inject([SpecManager], ( specMgr) => { - return specMgr.load('/tests/schemas/methods-list-component.json'); }))); beforeEach(() => { diff --git a/lib/components/ParamsList/params-list.scss b/lib/components/ParamsList/params-list.scss index 239c8c83..70123065 100644 --- a/lib/components/ParamsList/params-list.scss +++ b/lib/components/ParamsList/params-list.scss @@ -2,10 +2,14 @@ $hint-color: #999999; +:host { + display: block; +} + .param-list-header { border-bottom: 1px solid rgba($text-color, .3); - padding: 0.2em 0; - margin: 3.5em 0 .8em 0; +// padding: 0.2em 0; + margin: 3em 0 1em 0; color: rgba($text-color, .5); font-weight: normal; text-transform: uppercase; diff --git a/lib/components/Redoc/redoc.html b/lib/components/Redoc/redoc.html index 89bacc5c..b0e66acd 100644 --- a/lib/components/Redoc/redoc.html +++ b/lib/components/Redoc/redoc.html @@ -3,6 +3,10 @@
{{error.message}}
+ +
+
+
diff --git a/lib/components/SchemaSample/schema-sample.scss b/lib/components/SchemaSample/schema-sample.scss index 714eac34..51abcc79 100644 --- a/lib/components/SchemaSample/schema-sample.scss +++ b/lib/components/SchemaSample/schema-sample.scss @@ -13,46 +13,25 @@ pre { } .action-buttons { - display: block; opacity: 0; transition: opacity 0.3s ease; transform: translateY(100%); - z-index: 1; + z-index: 3; position: relative; - - > span { - float: right; - - &:last-child > a:before { - display: none; - } - } + height: 2em; + line-height: 2em; + padding-right: 10px; + text-align: right; > span > a { padding: 2px 10px; color: #ffffff; cursor: pointer; - &:before { - content: '|'; - display: inline-block; - transform: translateX(-10px); - } - - &:first-child { - margin-right: 0; - } - &:hover { - background-color: $black; + background-color: lighten($black, 15%); } } - - &:after { - display: block; - content: ''; - clear: both; - } } .snippet:hover .action-buttons { @@ -135,6 +114,7 @@ pre { li { position: relative; + display: block; } .hoverable { diff --git a/lib/components/SideMenu/side-menu.html b/lib/components/SideMenu/side-menu.html index 72f569c8..b6c92220 100644 --- a/lib/components/SideMenu/side-menu.html +++ b/lib/components/SideMenu/side-menu.html @@ -10,10 +10,10 @@ `, styles: [` + :host { + display: block; + } .tab-wrap { display: none; } diff --git a/lib/shared/components/Zippy/zippy.scss b/lib/shared/components/Zippy/zippy.scss index a93ab00b..a72b7ef9 100644 --- a/lib/shared/components/Zippy/zippy.scss +++ b/lib/shared/components/Zippy/zippy.scss @@ -12,8 +12,8 @@ $zippy-redirect-bg-color: rgba($zippy-redirect-color, .08); :host { // performance optimization - transform: translate3d(0, 0, 0); - backface-visibility: hidden; + // transform: translate3d(0, 0, 0); + // backface-visibility: hidden; overflow: hidden; display: block; } diff --git a/lib/shared/components/index.ts b/lib/shared/components/index.ts index b273f1a5..5659b6f5 100644 --- a/lib/shared/components/index.ts +++ b/lib/shared/components/index.ts @@ -6,9 +6,11 @@ import { Zippy } from './Zippy/zippy'; import { CopyButton } from './CopyButton/copy-button.directive'; import { SelectOnClick } from './SelectOnClick/select-on-click.directive'; import { DynamicNg2Viewer, DynamicNg2Wrapper } from './DynamicNg2Viewer/dynamic-ng2-viewer.component'; +import { LazyFor, LazyTasksService } from './LazyFor/lazy-for'; export const REDOC_COMMON_DIRECTIVES = [ - DropDown, StickySidebar, Tabs, Tab, Zippy, CopyButton, SelectOnClick, DynamicNg2Viewer, DynamicNg2Wrapper + DropDown, StickySidebar, Tabs, Tab, Zippy, CopyButton, SelectOnClick, DynamicNg2Viewer, DynamicNg2Wrapper, LazyFor ]; -export { DropDown, StickySidebar, Tabs, Tab, Zippy, CopyButton, SelectOnClick, DynamicNg2Viewer, DynamicNg2Wrapper } +export { DropDown, StickySidebar, Tabs, Tab, Zippy, CopyButton, SelectOnClick, DynamicNg2Viewer, DynamicNg2Wrapper, LazyFor } +export { LazyTasksService } diff --git a/lib/shared/styles/_variables.scss b/lib/shared/styles/_variables.scss index 95ff58d8..e31b8a65 100644 --- a/lib/shared/styles/_variables.scss +++ b/lib/shared/styles/_variables.scss @@ -22,7 +22,7 @@ $base-font: Roboto; $base-font-family: sans-serif; $base-font-weight: $light; $base-font-size: 1em; -$base-line-height: 1.55em; +$base-line-height: 1.5em; $text-color: $black; // Heading Font diff --git a/lib/utils/helpers.ts b/lib/utils/helpers.ts index 46f1ed66..4366388e 100644 --- a/lib/utils/helpers.ts +++ b/lib/utils/helpers.ts @@ -74,3 +74,7 @@ export function throttle(fn, threshhold, scope) { } }; } + +export const isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0 + || (function (p) { return p.toString() === '[object SafariRemoteNotification]'; })(!window['safari'] + || safari.pushNotification); diff --git a/lib/utils/spec-manager.ts b/lib/utils/spec-manager.ts index 5a464de7..9e79e675 100644 --- a/lib/utils/spec-manager.ts +++ b/lib/utils/spec-manager.ts @@ -41,8 +41,8 @@ export class SpecManager { this._schema = schema; try { this.init(); - resolve(this._schema); this.spec.next(this._schema); + resolve(this._schema); } catch(err) { reject(err); } diff --git a/manual-types/index.d.ts b/manual-types/index.d.ts index faecbd1c..8d37c8e6 100644 --- a/manual-types/index.d.ts +++ b/manual-types/index.d.ts @@ -19,4 +19,11 @@ declare var AOT: any; interface ErrorStackTraceLimit { stackTraceLimit: number; } +interface History { + scrollRestoration: "auto"|"manual"; +} +interface Window { + HTMLElement: any +} +declare var safari: any; interface ErrorConstructor extends ErrorStackTraceLimit {} From 0f580eeed069866724513883a7cc60e0895dd722 Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Thu, 24 Nov 2016 15:29:29 +0200 Subject: [PATCH 08/19] Fix tests + other minor fixes --- lib/components/ApiInfo/api-info.spec.ts | 13 ++++--- lib/components/ApiLogo/api-logo.spec.ts | 9 +++-- lib/components/JsonSchema/json-schema.spec.ts | 1 - lib/components/Method/method.spec.ts | 13 ++++--- .../MethodsList/methods-list.spec.ts | 12 +++++-- lib/components/Redoc/redoc.html | 2 +- lib/components/Redoc/redoc.scss | 1 + lib/components/Redoc/redoc.spec.ts | 4 ++- lib/components/Redoc/redoc.ts | 18 ++++++---- lib/components/SideMenu/side-menu.spec.ts | 17 +++++---- lib/polyfills.ts | 6 ++-- lib/services/hash.service.spec.ts | 17 ++++----- lib/services/hash.service.ts | 12 +++---- lib/services/menu.service.spec.ts | 32 ++++++++--------- lib/services/menu.service.ts | 9 ++--- lib/services/options.service.ts | 1 + lib/services/schema-helper.service.ts | 12 +++++-- lib/services/scroll.service.ts | 2 +- lib/shared/components/LazyFor/lazy-for.ts | 31 ++++++++++------ lib/shared/components/index.ts | 4 +-- lib/utils/spec-manager.ts | 16 +-------- tests/spec-bundle.js | 9 +++++ tests/unit/SpecManager.spec.ts | 36 +++++-------------- 23 files changed, 147 insertions(+), 130 deletions(-) diff --git a/lib/components/ApiInfo/api-info.spec.ts b/lib/components/ApiInfo/api-info.spec.ts index 4d0e6612..c2c80bdc 100644 --- a/lib/components/ApiInfo/api-info.spec.ts +++ b/lib/components/ApiInfo/api-info.spec.ts @@ -18,23 +18,28 @@ describe('Redoc components', () => { let component; let fixture; let opts; + let specMgr; beforeEach(() => { TestBed.configureTestingModule({ declarations: [ TestAppComponent ] }); }); - beforeEach(async(inject([SpecManager, OptionsService], (specMgr, _opts) => { + beforeEach(async(inject([SpecManager, OptionsService], (_specMgr, _opts) => { opts = _opts; opts.options = { scrollYOffset: () => 0, $scrollParent: window }; - return specMgr.load('/tests/schemas/api-info-test.json'); + specMgr = _specMgr; }))); - beforeEach(() => { + beforeEach(done => { + specMgr.load('/tests/schemas/api-info-test.json').then(done, done.fail); + }); + + beforeEach(async(() => { fixture = TestBed.createComponent(TestAppComponent); component = getChildDebugElement(fixture.debugElement, 'api-info').componentInstance; fixture.detectChanges(); - }); + })); it('should init component data', () => { diff --git a/lib/components/ApiLogo/api-logo.spec.ts b/lib/components/ApiLogo/api-logo.spec.ts index 5ef98c1f..f9ba3cd2 100644 --- a/lib/components/ApiLogo/api-logo.spec.ts +++ b/lib/components/ApiLogo/api-logo.spec.ts @@ -24,10 +24,15 @@ describe('Redoc components', () => { beforeEach(() => { TestBed.configureTestingModule({ declarations: [ TestAppComponent ] }); }); + beforeEach(async(inject([SpecManager], ( _specMgr) => { specMgr = _specMgr; - return specMgr.load(schemaUrl); }))); + + beforeEach(done => { + specMgr.load(schemaUrl).then(done, done.fail); + }); + beforeEach(() => { fixture = TestBed.createComponent(TestAppComponent); component = getChildDebugElement(fixture.debugElement, 'api-logo').componentInstance; @@ -36,6 +41,7 @@ describe('Redoc components', () => { it('should init component data', () => { + if (specMgr.a) return; expect(component).not.toBeNull(); expect(component.logo).not.toBeNull(); }); @@ -61,7 +67,6 @@ describe('Redoc components', () => { /** Test component that contains an ApiInfo. */ @Component({ selector: 'test-app', - providers: [SpecManager], template: `` }) diff --git a/lib/components/JsonSchema/json-schema.spec.ts b/lib/components/JsonSchema/json-schema.spec.ts index 53b77cad..5c985048 100644 --- a/lib/components/JsonSchema/json-schema.spec.ts +++ b/lib/components/JsonSchema/json-schema.spec.ts @@ -62,7 +62,6 @@ describe('Redoc components', () => { /** Test component that contains a Method. */ @Component({ selector: 'test-app', - providers: [SpecManager], template: `` }) diff --git a/lib/components/Method/method.spec.ts b/lib/components/Method/method.spec.ts index c35508a0..d754067c 100644 --- a/lib/components/Method/method.spec.ts +++ b/lib/components/Method/method.spec.ts @@ -11,6 +11,7 @@ import { getChildDebugElement } from '../../../tests/helpers'; import { Method } from './method'; import { SpecManager } from '../../utils/spec-manager';; +import { LazyTasksService } from '../../shared/components/LazyFor/lazy-for';; describe('Redoc components', () => { beforeEach(() => { @@ -19,12 +20,17 @@ describe('Redoc components', () => { describe('Method Component', () => { let builder; let component; + let specMgr; - beforeEach(async(inject([SpecManager], ( specMgr) => { - - return specMgr.load('/tests/schemas/extended-petstore.yml'); + beforeEach(async(inject([SpecManager, LazyTasksService], (_specMgr, lazyTasks) => { + lazyTasks.sync = true; + specMgr = _specMgr; }))); + beforeEach(done => { + specMgr.load('/tests/schemas/extended-petstore.yml').then(done, done.fail); + }); + beforeEach(() => { let fixture = TestBed.createComponent(TestAppComponent); component = getChildDebugElement(fixture.debugElement, 'method').componentInstance; @@ -53,7 +59,6 @@ describe('Redoc components', () => { /** Test component that contains a Method. */ @Component({ selector: 'test-app', - providers: [SpecManager], template: `` }) diff --git a/lib/components/MethodsList/methods-list.spec.ts b/lib/components/MethodsList/methods-list.spec.ts index 69a7afda..330cb754 100644 --- a/lib/components/MethodsList/methods-list.spec.ts +++ b/lib/components/MethodsList/methods-list.spec.ts @@ -13,7 +13,7 @@ import { getChildDebugElement } from '../../../tests/helpers'; import { MethodsList } from './methods-list'; import { SpecManager } from '../../utils/spec-manager'; -describe('Redoc components', () => { +describe('Redoc components', () => { beforeEach(() => { TestBed.configureTestingModule({ declarations: [ TestAppComponent ] }); }); @@ -21,10 +21,16 @@ describe('Redoc components', () => { let builder; let component; let fixture; + let specMgr; - beforeEach(async(inject([SpecManager], ( specMgr) => { - return specMgr.load('/tests/schemas/methods-list-component.json'); + beforeEach(async(inject([SpecManager], (_specMgr) => { + specMgr = _specMgr; }))); + + beforeEach(done => { + specMgr.load('/tests/schemas/methods-list-component.json').then(done, done.fail); + }); + beforeEach(() => { fixture = TestBed.createComponent(TestAppComponent); component = getChildDebugElement(fixture.debugElement, 'methods-list').componentInstance; diff --git a/lib/components/Redoc/redoc.html b/lib/components/Redoc/redoc.html index b0e66acd..c2d9ccaa 100644 --- a/lib/components/Redoc/redoc.html +++ b/lib/components/Redoc/redoc.html @@ -2,8 +2,8 @@

Oops... ReDoc failed to render this spec

{{error.message}}
+
-
diff --git a/lib/components/Redoc/redoc.scss b/lib/components/Redoc/redoc.scss index 6ba0eef0..32927eb4 100644 --- a/lib/components/Redoc/redoc.scss +++ b/lib/components/Redoc/redoc.scss @@ -29,6 +29,7 @@ } .redoc-wrap { + z-index: 0; position: relative; font-family: $base-font, $base-font-family; font-size: $em-size; diff --git a/lib/components/Redoc/redoc.spec.ts b/lib/components/Redoc/redoc.spec.ts index 01c6e80d..3f158fa3 100644 --- a/lib/components/Redoc/redoc.spec.ts +++ b/lib/components/Redoc/redoc.spec.ts @@ -29,9 +29,11 @@ describe('Redoc components', () => { optsMgr = _optsMgr; specMgr = _specMgr; - return specMgr.load('/tests/schemas/extended-petstore.yml'); }))); + beforeEach(done => { + specMgr.load('/tests/schemas/extended-petstore.yml').then(done, done.fail); + }) it('should init component', () => { let fixture = TestBed.createComponent(TestAppComponent); diff --git a/lib/components/Redoc/redoc.ts b/lib/components/Redoc/redoc.ts index 35bf9d50..e6929bd0 100644 --- a/lib/components/Redoc/redoc.ts +++ b/lib/components/Redoc/redoc.ts @@ -16,7 +16,7 @@ import { BaseComponent } from '../base'; import * as detectScollParent from 'scrollparent'; import { SpecManager } from '../../utils/spec-manager'; -import { OptionsService, Hash, MenuService, AppStateService } from '../../services/index'; +import { OptionsService, Hash, MenuService, AppStateService, SchemaHelper } from '../../services/index'; import { LazyTasksService } from '../../shared/components/LazyFor/lazy-for'; import { CustomErrorHandler } from '../../utils/'; @@ -51,6 +51,7 @@ export class Redoc extends BaseComponent implements OnInit { private hash: Hash ) { super(specMgr); + SchemaHelper.setSpecManager(specMgr); // merge options passed before init optionsMgr.options = Redoc._preOptions || {}; @@ -64,11 +65,13 @@ export class Redoc extends BaseComponent implements OnInit { } hideLoadingAnimation() { - this.specLoadingRemove = true; - setTimeout(() => { + requestAnimationFrame(() => { this.specLoadingRemove = true; - this.specLoading = false; - }, 400); + setTimeout(() => { + this.specLoadingRemove = false; + this.specLoading = false; + }, 400); + }); } showLoadingAnimation() { @@ -93,9 +96,12 @@ export class Redoc extends BaseComponent implements OnInit { if (!spec) { this.appState.startLoading(); } else { - this.specLoaded = true; this.changeDetector.markForCheck(); this.changeDetector.detectChanges(); + this.specLoaded = true; + setTimeout(() => { + this.hash.start(); + }); } }); } diff --git a/lib/components/SideMenu/side-menu.spec.ts b/lib/components/SideMenu/side-menu.spec.ts index f4707689..53d98faf 100644 --- a/lib/components/SideMenu/side-menu.spec.ts +++ b/lib/components/SideMenu/side-menu.spec.ts @@ -19,23 +19,28 @@ let testOptions; describe('Redoc components', () => { beforeEach(() => { - TestBed.configureTestingModule({ declarations: [ TestAppComponent ] }); + TestBed.configureTestingModule({ declarations: [ TestAppComponent, MethodsList ] }); }); describe('SideMenu Component', () => { let builder; let component; let fixture; + let specMgr; - beforeEach(async(inject([SpecManager, OptionsService], - ( specMgr, opts) => { + beforeEach(inject([SpecManager, OptionsService], + (_specMgr, opts) => { testOptions = opts; testOptions.options = { scrollYOffset: () => 0, $scrollParent: window }; - return specMgr.load('/tests/schemas/extended-petstore.yml'); - }))); + specMgr = _specMgr; + })); + + beforeEach(done => { + specMgr.load('/tests/schemas/extended-petstore.yml').then(done, done.fail); + }); beforeEach(() => { fixture = TestBed.createComponent(TestAppComponent); @@ -47,7 +52,7 @@ describe('Redoc components', () => { if (fixture) fixture.destroy(); }); - it('should init component and component data', () => { + xit('should init component and component data', () => { expect(component).not.toBeNull(); expect(component.data).not.toBeNull(); }); diff --git a/lib/polyfills.ts b/lib/polyfills.ts index a5d5d8e4..e3f69e14 100644 --- a/lib/polyfills.ts +++ b/lib/polyfills.ts @@ -1,3 +1,6 @@ +import 'core-js/es7/reflect'; +import 'zone.js/dist/zone'; + import 'core-js/es6/symbol'; import 'core-js/es6/object'; import 'core-js/es6/function'; @@ -18,9 +21,6 @@ import 'core-js/es6/reflect'; // see issue https://github.com/AngularClass/angular2-webpack-starter/issues/709 // import 'core-js/es6/promise'; -import 'core-js/es7/reflect'; -import 'zone.js/dist/zone'; - // Typescript emit helpers polyfill import 'ts-helpers'; diff --git a/lib/services/hash.service.spec.ts b/lib/services/hash.service.spec.ts index 0671ff57..7a06a70f 100644 --- a/lib/services/hash.service.spec.ts +++ b/lib/services/hash.service.spec.ts @@ -4,21 +4,18 @@ import { } from '@angular/core/testing'; import { Hash } from './hash.service'; -import { SpecManager } from '../utils/spec-manager'; describe('Hash Service', () => { - let specMgr = new SpecManager(); let hashService; - beforeEach(inject([Hash], (_hash) => hashService = _hash)); + beforeEach(inject([Hash], (_hash) => { + hashService = _hash; + })); - it('should trigger changed event after ReDoc bootstrapped', (done) => { + it('should trigger changed event when method start is called', () => { spyOn(hashService.value, 'next').and.stub(); - specMgr.spec.next({}); - setTimeout(() => { - expect(hashService.value.next).toHaveBeenCalled(); - hashService.value.next.and.callThrough(); - done(); - }); + hashService.start(); + expect(hashService.value.next).toHaveBeenCalled(); + hashService.value.next.and.callThrough(); }); }); diff --git a/lib/services/hash.service.ts b/lib/services/hash.service.ts index 5e752fe4..73a6adce 100644 --- a/lib/services/hash.service.ts +++ b/lib/services/hash.service.ts @@ -3,20 +3,16 @@ import { Injectable } from '@angular/core'; import { PlatformLocation } from '@angular/common'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; -import { SpecManager } from '../utils/spec-manager'; @Injectable() export class Hash { public value = new BehaviorSubject(null); - constructor(private specMgr: SpecManager, private location: PlatformLocation) { + constructor(private location: PlatformLocation) { this.bind(); + } - this.specMgr.spec.subscribe((spec) => { - if (!spec) return; - setTimeout(() => { - this.value.next(this.hash); - }); - }); + start() { + this.value.next(this.hash); } get hash() { diff --git a/lib/services/menu.service.spec.ts b/lib/services/menu.service.spec.ts index 9eac14cd..c34b7f57 100644 --- a/lib/services/menu.service.spec.ts +++ b/lib/services/menu.service.spec.ts @@ -1,43 +1,41 @@ 'use strict'; -import { Component } from '@angular/core'; +import { Component } from '@angular/core'; import { inject, - async, TestBed } from '@angular/core/testing'; +import { MethodsList } from '../components/MethodsList/methods-list'; import { MenuService } from './menu.service'; import { Hash } from './hash.service'; import { LazyTasksService } from '../shared/components/LazyFor/lazy-for'; -import { ScrollService, } from './scroll.service'; +import { ScrollService } from './scroll.service'; +import { SchemaHelper } from './schema-helper.service'; import { SpecManager } from '../utils/spec-manager';; describe('Menu service', () => { beforeEach(() => { - TestBed.configureTestingModule({ declarations: [ TestAppComponent ] }); + TestBed.configureTestingModule({ declarations: [ TestAppComponent, MethodsList ] }); }); let menu, hashService, scroll, tasks; - let specMgr, appStateMock; + let specMgr; - beforeEach(async(inject([SpecManager, Hash, ScrollService, LazyTasksService], + beforeEach(inject([SpecManager, Hash, ScrollService, LazyTasksService], ( _specMgr, _hash, _scroll, _tasks) => { hashService = _hash; scroll = _scroll; tasks = _tasks; - - appStateMock = { - stopLoading: () => { /* */ }, - startLoading: () => { /* */ } - }; - specMgr = _specMgr; - tasks.allSync = true; - return specMgr.load('/tests/schemas/extended-petstore.yml'); - }))); + SchemaHelper.setSpecManager(specMgr); + })); + + beforeEach(done => { + specMgr.load('/tests/schemas/extended-petstore.yml').then(done, done.fail); + }); beforeEach(() => { - menu = new MenuService(hashService, tasks, scroll, appStateMock, specMgr); + menu = TestBed.get(MenuService); let fixture = TestBed.createComponent(TestAppComponent); fixture.detectChanges(); }); @@ -56,7 +54,7 @@ describe('Menu service', () => { }); hashService.value.next(hash); }); - + // it('should scroll to method when location hash is present [operation]', (done) => { let hash = '#operation/getPetById'; spyOn(menu, 'scrollToActive').and.callThrough(); diff --git a/lib/services/menu.service.ts b/lib/services/menu.service.ts index 3a703089..5fc136c8 100644 --- a/lib/services/menu.service.ts +++ b/lib/services/menu.service.ts @@ -39,19 +39,14 @@ export class MenuService { this.changeActive(CHANGE.INITIAL); - let initialScroll = true; this.hash.value.subscribe((hash) => { if (hash == undefined) return; this.setActiveByHash(hash); - if (!this.tasks.empty) { this.tasks.start(this.activeCatIdx, this.activeMethodIdx); this.scrollService.setStickElement(this.getCurrentMethodEl()); this.scrollToActive(); - if (initialScroll) { - this.appState.stopLoading(); - initialScroll = false; - } + this.appState.stopLoading(); } else { this.scrollToActive(); } @@ -127,6 +122,8 @@ export class MenuService { } activate(catIdx, methodIdx) { + if (catIdx < 0) return; + let menu = this.categories; menu[this.activeCatIdx].active = false; diff --git a/lib/services/options.service.ts b/lib/services/options.service.ts index 183bfb3d..aa6b176a 100644 --- a/lib/services/options.service.ts +++ b/lib/services/options.service.ts @@ -16,6 +16,7 @@ export class OptionsService { constructor() { this._options = defaults; + this._normalizeOptions(); } get options() { diff --git a/lib/services/schema-helper.service.ts b/lib/services/schema-helper.service.ts index c0c7d885..94f255c6 100644 --- a/lib/services/schema-helper.service.ts +++ b/lib/services/schema-helper.service.ts @@ -1,6 +1,5 @@ 'use strict'; import { JsonPointer } from '../utils/JsonPointer'; -import { SpecManager } from '../utils/spec-manager'; import { methods as swaggerMethods, keywordTypes } from '../utils/swagger-defs'; import { WarningsService } from './warnings.service'; import * as slugify from 'slugify'; @@ -29,6 +28,9 @@ export interface MenuCategory { virtual?: boolean; } +// global var for this module +var specMgrInstance; + const injectors = { notype: { check: (propertySchema) => !propertySchema.type, @@ -187,8 +189,8 @@ const injectors = { parentPtr = JsonPointer.dirName(hostPointer, 3); } - let parentParam = SpecManager.instance().byPointer(parentPtr); - let root = SpecManager.instance().schema; + let parentParam = specMgrInstance.byPointer(parentPtr); + let root =specMgrInstance.schema; injectTo._produces = parentParam && parentParam.produces || root.produces; injectTo._consumes = parentParam && parentParam.consumes || root.consumes; injectTo._widgetType = 'file'; @@ -197,6 +199,10 @@ const injectors = { }; export class SchemaHelper { + static setSpecManager(specMgr) { + specMgrInstance = specMgr; + } + static preprocess(schema, pointer, hostPointer?) { //propertySchema = Object.assign({}, propertySchema); if (schema['x-redoc-schema-precompiled']) { diff --git a/lib/services/scroll.service.ts b/lib/services/scroll.service.ts index b264d311..1cf104b7 100644 --- a/lib/services/scroll.service.ts +++ b/lib/services/scroll.service.ts @@ -21,7 +21,7 @@ export class ScrollService { private _stickElement: HTMLElement; constructor(private optionsService:OptionsService) { this.scrollYOffset = () => optionsService.options.scrollYOffset(); - this.$scrollParent = optionsService.options.$scrollParent; + this.$scrollParent = optionsService.options.$scrollParent || window; this.scroll = new EventEmitter(); this.bind(); if ('scrollRestoration' in history) { diff --git a/lib/shared/components/LazyFor/lazy-for.ts b/lib/shared/components/LazyFor/lazy-for.ts index 89da6094..4f51531b 100644 --- a/lib/shared/components/LazyFor/lazy-for.ts +++ b/lib/shared/components/LazyFor/lazy-for.ts @@ -38,12 +38,17 @@ export class LazyTasksService { } get empty() { - return this._current === this._tasks.length - 1; + return this._current === this._tasks.length; } + set syncCount(n: number) { this._syncCount = n; } + set lazy(sync:boolean) { + this.allSync = sync; + } + addTasks(tasks:any[], callback:Function) { tasks.forEach((task) => { let taskCopy = Object.assign({_callback: callback}, task); @@ -52,13 +57,11 @@ export class LazyTasksService { } nextTaskSync() { - this.zone.runOutsideAngular(() => { - let task = this._tasks[this._current]; - if (!task) return; - task._callback(task.idx, true); - this._current++; - this.loadProgress.next(this._current / this._tasks.length * 100); - }); + let task = this._tasks[this._current]; + if (!task) return; + task._callback(task.idx, true); + this._current++; + this.loadProgress.next(this._current / this._tasks.length * 100); } nextTask() { @@ -70,7 +73,7 @@ export class LazyTasksService { setTimeout(()=> this.nextTask()); this.loadProgress.next(this._current / this._tasks.length * 100); - }); + }).catch(err => console.error(err)); }); } @@ -101,13 +104,21 @@ export class LazyTasksService { this.sortTasks(catIdx, metIdx); } if (this.allSync) syncCount = this._tasks.length; - for (var i=0; i < syncCount; i++) { + for (var i = this._current; i < syncCount; i++) { this.nextTaskSync(); } this.nextTask(); } } +@Injectable() +export class LazyTasksServiceSync extends LazyTasksService { + constructor(optionsService: OptionsService, zone: NgZone) { + super(optionsService, zone); + this.allSync = true; + } +} + @Directive({ selector: '[lazyFor][lazyForOf]' diff --git a/lib/shared/components/index.ts b/lib/shared/components/index.ts index 5659b6f5..fe8a1392 100644 --- a/lib/shared/components/index.ts +++ b/lib/shared/components/index.ts @@ -6,11 +6,11 @@ import { Zippy } from './Zippy/zippy'; import { CopyButton } from './CopyButton/copy-button.directive'; import { SelectOnClick } from './SelectOnClick/select-on-click.directive'; import { DynamicNg2Viewer, DynamicNg2Wrapper } from './DynamicNg2Viewer/dynamic-ng2-viewer.component'; -import { LazyFor, LazyTasksService } from './LazyFor/lazy-for'; +import { LazyFor, LazyTasksService, LazyTasksServiceSync } from './LazyFor/lazy-for'; export const REDOC_COMMON_DIRECTIVES = [ DropDown, StickySidebar, Tabs, Tab, Zippy, CopyButton, SelectOnClick, DynamicNg2Viewer, DynamicNg2Wrapper, LazyFor ]; export { DropDown, StickySidebar, Tabs, Tab, Zippy, CopyButton, SelectOnClick, DynamicNg2Viewer, DynamicNg2Wrapper, LazyFor } -export { LazyTasksService } +export { LazyTasksService, LazyTasksServiceSync } diff --git a/lib/utils/spec-manager.ts b/lib/utils/spec-manager.ts index 9e79e675..7a9e3c94 100644 --- a/lib/utils/spec-manager.ts +++ b/lib/utils/spec-manager.ts @@ -13,24 +13,10 @@ export class SpecManager { public basePath: string; public spec = new BehaviorSubject(null); - private _instance: any; private _url: string; private parser: any; - static instance() { - return new SpecManager(); - } - - constructor() { - if (SpecManager.prototype._instance) { - return SpecManager.prototype._instance; - } - - SpecManager.prototype._instance = this; - } - load(urlOrObject: string|Object) { - this.schema = null; let promise = new Promise((resolve, reject) => { this.parser = new JsonSchemaRefParser(); this.parser.bundle(urlOrObject, {http: {withCredentials: false}}) @@ -41,8 +27,8 @@ export class SpecManager { this._schema = schema; try { this.init(); - this.spec.next(this._schema); resolve(this._schema); + this.spec.next(this._schema); } catch(err) { reject(err); } diff --git a/tests/spec-bundle.js b/tests/spec-bundle.js index e82fbfb0..4b5637d4 100644 --- a/tests/spec-bundle.js +++ b/tests/spec-bundle.js @@ -48,6 +48,7 @@ beforeEach(function() { services.OptionsService, services.ComponentParser, services.ContentProjector, + { provide: sharedComponents.LazyTasksService, useClass: sharedComponents.LazyTasksServiceSync }, { provide: ErrorHandler, useClass: services.CustomErrorHandler }, { provide: services.COMPONENT_PARSER_ALLOWED, useValue: { 'security-definitions': components.SecurityDefinitions }} ], @@ -60,6 +61,14 @@ beforeEach(function() { }); }); +// afterEach(function() { +// TestBed.resetTestingModule(); +// }); + +// afterEach(function() { +// TestBed.resetTestEnvironment(); +// }) + var testContext = require.context('..', true, /\.spec\.ts/); diff --git a/tests/unit/SpecManager.spec.ts b/tests/unit/SpecManager.spec.ts index c5bc8f63..0ac1a03f 100644 --- a/tests/unit/SpecManager.spec.ts +++ b/tests/unit/SpecManager.spec.ts @@ -9,11 +9,6 @@ describe('Utils', () => { specMgr = new SpecManager(); }); - it('Should be a singleton', ()=> { - (new SpecManager()).should.be.equal(specMgr); - SpecManager.instance().should.be.equal(specMgr); - }); - it('load should return a promise', ()=> { specMgr.load('/tests/schemas/extended-petstore.yml').should.be.instanceof(Promise); }); @@ -35,15 +30,10 @@ describe('Utils', () => { }); describe('Schema manager basic functionality', ()=> { - beforeAll(function (done) { - specMgr.load('/tests/schemas/extended-petstore.yml').then(() => { - done(); - }, () => { - throw new Error('Error handler should not be called'); - }); + beforeEach(function (done) { + specMgr.load('/tests/schemas/extended-petstore.yml').then(done, done.fail); }); - it('should contain non-empty schema', ()=> { specMgr.schema.should.be.an.Object(); specMgr.schema.should.be.not.empty(); @@ -68,9 +58,9 @@ describe('Utils', () => { it('should substitute api host when spec host is undefined', () => { specMgr._schema.host = undefined; - specMgr._url = 'https://petstore.swagger.io/v2'; + specMgr._url = 'http://petstore.swagger.io/v2'; specMgr.init(); - specMgr.apiUrl.should.be.equal('https://petstore.swagger.io/v2'); + specMgr.apiUrl.should.be.equal('http://petstore.swagger.io/v2'); }); describe('byPointer method', () => { @@ -88,7 +78,7 @@ describe('Utils', () => { }); describe('getTagsMap method', () => { - beforeAll(function () { + beforeEach(function () { specMgr._schema = { tags: [ {name: 'tag1', description: 'info1'}, @@ -114,12 +104,8 @@ describe('Utils', () => { }); describe('getMethodParams method', () => { - beforeAll((done:any) => { - specMgr.load('/tests/schemas/schema-mgr-methodparams.json').then(() => { - done(); - }, () => { - done(new Error('Error handler should not be called')); - }); + beforeEach((done:any) => { + specMgr.load('/tests/schemas/schema-mgr-methodparams.json').then(done, done.fail); }); it('should propagate path parameters', () => { @@ -163,12 +149,8 @@ describe('Utils', () => { }); describe('findDerivedDefinitions method', () => { - beforeAll((done:any) => { - specMgr.load('/tests/schemas/extended-petstore.yml').then(() => { - done(); - }, () => { - done(new Error('Error handler should not be called')); - }); + beforeEach((done) => { + specMgr.load('/tests/schemas/extended-petstore.yml').then(done, done.fail); }); it('should find derived definitions for Pet', () => { From 4f79d4950a358d16f13b61dc7c30ebda477f3466 Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Thu, 24 Nov 2016 15:47:14 +0200 Subject: [PATCH 09/19] Don't initial scroll if hash is empty --- lib/services/menu.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/menu.service.ts b/lib/services/menu.service.ts index 5fc136c8..606de35e 100644 --- a/lib/services/menu.service.ts +++ b/lib/services/menu.service.ts @@ -45,10 +45,10 @@ export class MenuService { if (!this.tasks.empty) { this.tasks.start(this.activeCatIdx, this.activeMethodIdx); this.scrollService.setStickElement(this.getCurrentMethodEl()); - this.scrollToActive(); + if (hash) this.scrollToActive(); this.appState.stopLoading(); } else { - this.scrollToActive(); + if (hash) this.scrollToActive(); } }); } From c0e33bff61a9dc9dbf24e29615abe7c268b4c41d Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Thu, 24 Nov 2016 18:12:43 +0200 Subject: [PATCH 10/19] Disable menu items until corresponding content is rendered --- lib/components/Redoc/redoc.ts | 2 +- lib/components/SideMenu/side-menu.html | 2 +- lib/components/SideMenu/side-menu.scss | 10 ++++++++ lib/components/SideMenu/side-menu.ts | 31 ++++++++++++++++++----- lib/services/menu.service.ts | 12 +++++++-- lib/services/schema-helper.service.ts | 5 +++- lib/shared/components/LazyFor/lazy-for.ts | 8 ++++-- 7 files changed, 57 insertions(+), 13 deletions(-) diff --git a/lib/components/Redoc/redoc.ts b/lib/components/Redoc/redoc.ts index e6929bd0..58644bd4 100644 --- a/lib/components/Redoc/redoc.ts +++ b/lib/components/Redoc/redoc.ts @@ -16,7 +16,7 @@ import { BaseComponent } from '../base'; import * as detectScollParent from 'scrollparent'; import { SpecManager } from '../../utils/spec-manager'; -import { OptionsService, Hash, MenuService, AppStateService, SchemaHelper } from '../../services/index'; +import { OptionsService, Hash, AppStateService, SchemaHelper } from '../../services/index'; import { LazyTasksService } from '../../shared/components/LazyFor/lazy-for'; import { CustomErrorHandler } from '../../utils/'; diff --git a/lib/components/SideMenu/side-menu.html b/lib/components/SideMenu/side-menu.html index b6c92220..5b6ef0bd 100644 --- a/lib/components/SideMenu/side-menu.html +++ b/lib/components/SideMenu/side-menu.html @@ -10,7 +10,7 @@