diff --git a/aio/src/app/app.component.html b/aio/src/app/app.component.html index 22127e12c2..0e89007f97 100644 --- a/aio/src/app/app.component.html +++ b/aio/src/app/app.component.html @@ -27,6 +27,7 @@
+
diff --git a/aio/src/app/app.component.spec.ts b/aio/src/app/app.component.spec.ts index 5aec4219d7..fb1e9f9b0e 100644 --- a/aio/src/app/app.component.spec.ts +++ b/aio/src/app/app.component.spec.ts @@ -12,6 +12,7 @@ import { of } from 'rxjs/observable/of'; import { AppComponent } from './app.component'; import { AppModule } from './app.module'; import { DocViewerComponent } from 'app/layout/doc-viewer/doc-viewer.component'; +import { Deployment } from 'app/shared/deployment.service'; import { GaService } from 'app/shared/ga.service'; import { LocationService } from 'app/shared/location.service'; import { Logger } from 'app/shared/logger.service'; @@ -332,10 +333,6 @@ describe('AppComponent', () => { }); describe('hostClasses', () => { - let host: DebugElement; - beforeEach(() => { - host = fixture.debugElement; - }); it('should set the css classes of the host container based on the current doc and navigation view', () => { locationService.go('guide/pipes'); @@ -359,7 +356,7 @@ describe('AppComponent', () => { }); it('should set the css class of the host container based on the open/closed state of the side nav', () => { - const sideNav = host.query(By.directive(MdSidenav)); + const sideNav = fixture.debugElement.query(By.directive(MdSidenav)); locationService.go('guide/pipes'); fixture.detectChanges(); @@ -376,7 +373,14 @@ describe('AppComponent', () => { checkHostClass('sidenav', 'open'); }); + it('should set the css class of the host container based on the initial deployment mode', () => { + createTestingModule('a/b', 'archive'); + initializeTest(); + checkHostClass('mode', 'archive'); + }); + function checkHostClass(type, value) { + const host = fixture.debugElement; const classes = host.properties['className']; const classArray = classes.split(' ').filter(c => c.indexOf(`${type}-`) === 0); expect(classArray.length).toBeLessThanOrEqual(1, `"${classes}" should have only one class matching ${type}-*`); @@ -627,6 +631,24 @@ describe('AppComponent', () => { }); }); + describe('deployment banner', () => { + it('should show a message if the deployment mode is "archive"', () => { + createTestingModule('a/b', 'archive'); + initializeTest(); + fixture.detectChanges(); + const banner: HTMLElement = fixture.debugElement.query(By.css('aio-mode-banner')).nativeElement; + expect(banner.textContent).toContain('archived documentation for Angular v4'); + }); + + it('should show no message if the deployment mode is not "archive"', () => { + createTestingModule('a/b', 'stable'); + initializeTest(); + fixture.detectChanges(); + const banner: HTMLElement = fixture.debugElement.query(By.css('aio-mode-banner')).nativeElement; + expect(banner.textContent.trim()).toEqual(''); + }); + }); + describe('search', () => { describe('initialization', () => { it('should initialize the search worker', inject([SearchService], (searchService: SearchService) => { @@ -883,7 +905,7 @@ describe('AppComponent', () => { //// test helpers //// -function createTestingModule(initialUrl: string) { +function createTestingModule(initialUrl: string, mode: string = 'stable') { TestBed.resetTestingModule(); TestBed.configureTestingModule({ imports: [ AppModule ], @@ -894,6 +916,11 @@ function createTestingModule(initialUrl: string) { { provide: LocationService, useFactory: () => new MockLocationService(initialUrl) }, { provide: Logger, useClass: MockLogger }, { provide: SearchService, useClass: MockSearchService }, + { provide: Deployment, useFactory: () => { + const deployment = new Deployment(); + deployment.mode = mode; + return deployment; + }}, ] }); } diff --git a/aio/src/app/app.component.ts b/aio/src/app/app.component.ts index 3ba0293a4b..284271d9f0 100644 --- a/aio/src/app/app.component.ts +++ b/aio/src/app/app.component.ts @@ -5,6 +5,7 @@ import { MdSidenav } from '@angular/material'; import { CurrentNodes, NavigationService, NavigationViews, NavigationNode, VersionInfo } from 'app/navigation/navigation.service'; import { DocumentService, DocumentContents } from 'app/documents/document.service'; import { DocViewerComponent } from 'app/layout/doc-viewer/doc-viewer.component'; +import { Deployment } from 'app/shared/deployment.service'; import { LocationService } from 'app/shared/location.service'; import { NavMenuComponent } from 'app/layout/nav-menu/nav-menu.component'; import { ScrollService } from 'app/shared/scroll.service'; @@ -99,6 +100,7 @@ export class AppComponent implements OnInit { sidenav: MdSidenav; constructor( + public deployment: Deployment, private documentService: DocumentService, private hostElement: ElementRef, private locationService: LocationService, @@ -256,12 +258,13 @@ export class AppComponent implements OnInit { } updateHostClasses() { + const mode = `mode-${this.deployment.mode}`; const sideNavOpen = `sidenav-${this.sidenav.opened ? 'open' : 'closed'}`; const pageClass = `page-${this.pageId}`; const folderClass = `folder-${this.folderId}`; const viewClasses = Object.keys(this.currentNodes || {}).map(view => `view-${view}`).join(' '); - this.hostClasses = `${sideNavOpen} ${pageClass} ${folderClass} ${viewClasses}`; + this.hostClasses = `${mode} ${sideNavOpen} ${pageClass} ${folderClass} ${viewClasses}`; } // Dynamically change height of table of contents container diff --git a/aio/src/app/app.module.ts b/aio/src/app/app.module.ts index 73e0154342..ca9545ab5b 100644 --- a/aio/src/app/app.module.ts +++ b/aio/src/app/app.module.ts @@ -26,8 +26,10 @@ import { SwUpdatesModule } from 'app/sw-updates/sw-updates.module'; import { AppComponent } from 'app/app.component'; import { ApiService } from 'app/embedded/api/api.service'; import { CustomMdIconRegistry, SVG_ICONS } from 'app/shared/custom-md-icon-registry'; +import { Deployment } from 'app/shared/deployment.service'; import { DocViewerComponent } from 'app/layout/doc-viewer/doc-viewer.component'; import { DtComponent } from 'app/layout/doc-viewer/dt.component'; +import { ModeBannerComponent } from 'app/layout/mode-banner/mode-banner.component'; import { EmbeddedModule } from 'app/embedded/embedded.module'; import { GaService } from 'app/shared/ga.service'; import { Logger } from 'app/shared/logger.service'; @@ -90,14 +92,16 @@ export const svgIconProviders = [ DocViewerComponent, DtComponent, FooterComponent, - TopMenuComponent, + ModeBannerComponent, NavMenuComponent, NavItemComponent, SearchResultsComponent, SearchBoxComponent, + TopMenuComponent, ], providers: [ ApiService, + Deployment, DocumentService, GaService, Logger, diff --git a/aio/src/app/layout/mode-banner/mode-banner.component.ts b/aio/src/app/layout/mode-banner/mode-banner.component.ts new file mode 100644 index 0000000000..366a0154e9 --- /dev/null +++ b/aio/src/app/layout/mode-banner/mode-banner.component.ts @@ -0,0 +1,16 @@ +import { Component, Input } from '@angular/core'; +import { VersionInfo } from 'app/navigation/navigation.service'; + +@Component({ + selector: 'aio-mode-banner', + template: ` +
+ This is the archived documentation for Angular v{{version?.major}}. + Please visit angular.io to see documentation for the current version of Angular. +
+ ` +}) +export class ModeBannerComponent { + @Input() mode: string; + @Input() version: VersionInfo; +} diff --git a/aio/src/app/shared/deployment.service.ts b/aio/src/app/shared/deployment.service.ts new file mode 100644 index 0000000000..9cf53dfd87 --- /dev/null +++ b/aio/src/app/shared/deployment.service.ts @@ -0,0 +1,7 @@ +import { Injectable } from '@angular/core'; +import { environment } from 'environments/environment'; + +@Injectable() +export class Deployment { + mode: string = environment.mode; +};