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;
+};