diff --git a/docs/app/@theme/services/article.service.ts b/docs/app/@theme/services/article.service.ts index 2239b4b9d4..268d07b9ea 100644 --- a/docs/app/@theme/services/article.service.ts +++ b/docs/app/@theme/services/article.service.ts @@ -1,13 +1,17 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; +import { map, shareReplay } from 'rxjs/operators'; +import { NgdMdSection, NgdTextService } from './text.service'; @Injectable() export class NgdArticleService { + constructor(private http: HttpClient, private textService: NgdTextService) {} - constructor(private http: HttpClient) { } - - getArticle(source: string): Observable { - return this.http.get(`articles/${source}`, { responseType: 'text' }); + getArticle(source: string): Observable { + return this.http.get(`articles/${source}`, { responseType: 'text' }).pipe( + map((article) => this.textService.mdToSectionsHTML(article)), + shareReplay(1), + ); } } diff --git a/docs/app/@theme/services/index.ts b/docs/app/@theme/services/index.ts index df67d132fc..1a43b9a85e 100644 --- a/docs/app/@theme/services/index.ts +++ b/docs/app/@theme/services/index.ts @@ -12,3 +12,4 @@ export * from './analytics.service'; export * from './menu.service'; export * from './metadata.service'; export * from './article.service'; +export * from './last-viewed-section.service'; diff --git a/docs/app/@theme/services/last-viewed-section.service.ts b/docs/app/@theme/services/last-viewed-section.service.ts new file mode 100644 index 0000000000..410a2cea97 --- /dev/null +++ b/docs/app/@theme/services/last-viewed-section.service.ts @@ -0,0 +1,22 @@ +import { Injectable } from '@angular/core'; +import { Observable, ReplaySubject } from 'rxjs'; +import { NgdMdSection } from './text.service'; + +/** + * We store the last viewed section here to prevent flickering when switching between articles. + * When a user clicks on an article link, `ngd-md-block` is destroyed and a new one is created. + * This service replays the last viewed article to the newly created `ngd-md-block` to show it + * while a requested article is loading. + * */ +@Injectable() +export class NgdLastViewedSectionService { + private _sections = new ReplaySubject(1); + + setSection(section: NgdMdSection[]): void { + this._sections.next(section); + } + + getSections(): Observable { + return this._sections.asObservable(); + } +} diff --git a/docs/app/@theme/services/structure.service.ts b/docs/app/@theme/services/structure.service.ts index 2f0c3192d3..a895c74dd6 100644 --- a/docs/app/@theme/services/structure.service.ts +++ b/docs/app/@theme/services/structure.service.ts @@ -62,9 +62,7 @@ export class NgdStructureService { } if (item.block === 'markdown') { - item.sections = this.articleService.getArticle(item.source).pipe( - map((article) => this.textService.mdToSectionsHTML(article)), - ); + item.sections = this.articleService.getArticle(item.source); } if (item.children) { diff --git a/docs/app/@theme/theme.module.ts b/docs/app/@theme/theme.module.ts index 43e004ede4..3d7f5fc9c1 100644 --- a/docs/app/@theme/theme.module.ts +++ b/docs/app/@theme/theme.module.ts @@ -59,6 +59,7 @@ import { NgdMenuService, NgdMetadataService, NgdArticleService, + NgdLastViewedSectionService, } from './services'; import { AkveoServicesBanner } from './components/hubspot-cta/akveo-services-banner.component'; @@ -144,6 +145,7 @@ export class NgdThemeModule { NgdVisibilityService, NgdMetadataService, NgdArticleService, + NgdLastViewedSectionService, ], }; } diff --git a/docs/app/blocks/blocks.module.ts b/docs/app/blocks/blocks.module.ts index 4367ffd56c..6fd9b2b12f 100644 --- a/docs/app/blocks/blocks.module.ts +++ b/docs/app/blocks/blocks.module.ts @@ -7,7 +7,7 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { CommonModule } from '@angular/common'; -import { NbInputModule } from '@nebular/theme'; +import { NbInputModule, NbSpinnerModule } from '@nebular/theme'; import { NgdThemeModule } from '../@theme/theme.module'; @@ -63,6 +63,7 @@ const blocks = [ RouterModule, NgdThemeModule, NbInputModule, + NbSpinnerModule, ], declarations: [ ...blocks, diff --git a/docs/app/blocks/components/md-block/md-block.component.ts b/docs/app/blocks/components/md-block/md-block.component.ts index 5fa11234bf..a7a5ef1fc1 100644 --- a/docs/app/blocks/components/md-block/md-block.component.ts +++ b/docs/app/blocks/components/md-block/md-block.component.ts @@ -4,28 +4,50 @@ * Licensed under the MIT License. See License.txt in the project root for license information. */ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, OnDestroy } from '@angular/core'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; +import { Observable, Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; import { NgdMdSection } from '../../../@theme/services/text.service'; +import { NgdLastViewedSectionService } from '../../../@theme/services'; @Component({ selector: 'ngd-md-block', template: ` - - -
-
-
+
+ + +
+
+
+
`, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class NgdMdBLockComponent { - @Input() sections: NgdMdSection[] = [] +export class NgdMdBLockComponent implements OnDestroy { + private destroy$ = new Subject(); + loading = true; + + @Input() + get sections$(): Observable { + return this.lastViewedSectionService.getSections(); + } + set sections$(value: Observable) { + value.pipe(takeUntil(this.destroy$)).subscribe((sections) => { + this.loading = false; + this.lastViewedSectionService.setSection(sections); + }); + } constructor( - private cd: ChangeDetectorRef, - private readonly domSanitizer: DomSanitizer) { + private readonly domSanitizer: DomSanitizer, + private lastViewedSectionService: NgdLastViewedSectionService, + ) {} + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); } getTemplate(content: string): SafeHtml { diff --git a/docs/app/documentation/page/page.component.html b/docs/app/documentation/page/page.component.html index d4607e0b4b..ef1a2c66c3 100644 --- a/docs/app/documentation/page/page.component.html +++ b/docs/app/documentation/page/page.component.html @@ -14,7 +14,7 @@

- +