Skip to content
This repository was archived by the owner on Dec 18, 2024. It is now read-only.

Commit fd7d5d4

Browse files
josephperrottjelbourn
authored andcommitted
Add CDK section to material.angular.io. (#244)
1 parent 1f537eb commit fd7d5d4

19 files changed

+1624
-818
lines changed

package-lock.json

Lines changed: 1327 additions & 672 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/app-module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ import {DocumentationItems} from './shared/documentation-items/documentation-ite
2929
import {GuideListModule} from './pages/guide-list/guide-list';
3030
import {GuideViewerModule} from './pages/guide-viewer/guide-viewer';
3131
import {DocViewerModule} from './shared/doc-viewer/doc-viewer-module';
32+
import {
33+
CanActivateComponentSidenav
34+
} from './pages/component-sidenav/component-sidenav-can-load-guard';
3235

3336
@NgModule({
3437
imports: [
@@ -62,6 +65,7 @@ import {DocViewerModule} from './shared/doc-viewer/doc-viewer-module';
6265
GuideItems,
6366
StyleManager,
6467
ThemeStorage,
68+
CanActivateComponentSidenav,
6569
{provide: LocationStrategy, useClass: PathLocationStrategy},
6670
{provide: MATERIAL_COMPATIBILITY_MODE, useValue: true},
6771
],

src/app/pages/component-category-list/component-category-list.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div class="docs-component-category-list">
2-
<a *ngFor="let category of docItems.getItemsInCategories()"
3-
class="docs-component-category-list-item"
4-
[routerLink]="['/categories/', category.id]">
2+
<a *ngFor="let category of docItems.getCategories((params | async)?.section)"
3+
class="docs-component-category-list-item"
4+
[routerLink]="['../', category.id]">
55
<mat-card class="docs-component-category-list-card">
66
<mat-card-title>{{category.name}}</mat-card-title>
77
</mat-card>

src/app/pages/component-category-list/component-category-list.spec.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
1+
import {async, ComponentFixture, TestBed, inject} from '@angular/core/testing';
2+
import {Router} from '@angular/router';
3+
import {Observable} from 'rxjs/Observable'
24
import {ComponentCategoryList, ComponentCategoryListModule} from './component-category-list';
35
import {DocsAppTestingModule} from '../../testing/testing-module';
46

@@ -16,18 +18,21 @@ describe('ComponentCategoryList', () => {
1618
fixture = TestBed.createComponent(ComponentCategoryList);
1719
});
1820

19-
it('should set page title on init', () => {
21+
it('should set set up base param observable on init', () => {
2022
const component = fixture.componentInstance;
2123
spyOn(component, 'ngOnInit').and.callThrough();
2224
fixture.detectChanges();
2325
expect(component.ngOnInit).toHaveBeenCalled();
24-
expect(component._componentPageTitle.title).toEqual('Component Categories');
26+
expect(component.params).toBeDefined();
2527
});
2628

2729
it('should render a card for every category', () => {
28-
const component = fixture.componentInstance;
2930
fixture.detectChanges();
30-
const categories = component.docItems.getItemsInCategories();
31+
// Params is replaced after ngOnit runs since params is set on init.
32+
fixture.componentInstance.params = Observable.of({'section': 'components'});
33+
fixture.detectChanges();
34+
const component = fixture.componentInstance;
35+
const categories = component.docItems.getCategories('components');
3136
const cards = fixture
3237
.nativeElement.querySelectorAll('.docs-component-category-list-card');
3338
expect(cards.length).toEqual(categories.length);

src/app/pages/component-category-list/component-category-list.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
1-
import {Component, NgModule} from '@angular/core';
1+
import {Component, NgModule, OnInit} from '@angular/core';
22
import {MatCardModule} from '@angular/material';
33
import {CommonModule} from '@angular/common';
4-
import {RouterModule} from '@angular/router';
5-
import {DocumentationItems} from '../../shared/documentation-items/documentation-items';
4+
import {ActivatedRoute, Params, RouterModule} from '@angular/router';
5+
import {DocumentationItems, SECTIONS} from '../../shared/documentation-items/documentation-items';
66
import {ComponentPageTitle} from '../page-title/page-title';
77
import {SvgViewerModule} from '../../shared/svg-viewer/svg-viewer';
8+
import {Observable} from 'rxjs/Observable';
9+
import 'rxjs/add/observable/combineLatest';
810

911

1012
@Component({
1113
selector: 'app-component-category-list',
1214
templateUrl: './component-category-list.html',
1315
styleUrls: ['./component-category-list.scss']
1416
})
15-
export class ComponentCategoryList {
17+
export class ComponentCategoryList implements OnInit {
18+
params: Observable<Params>;
19+
1620
constructor(public docItems: DocumentationItems,
17-
public _componentPageTitle: ComponentPageTitle) {}
21+
public _componentPageTitle: ComponentPageTitle,
22+
private _route: ActivatedRoute) {}
1823

1924
ngOnInit() {
20-
this._componentPageTitle.title = 'Component Categories';
25+
// Combine params from all of the path into a single object.
26+
this.params = Observable.combineLatest(
27+
this._route.pathFromRoot.map(route => route.params),
28+
Object.assign);
2129
}
2230
}
2331

src/app/pages/component-list/component-list.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div class="docs-component-list-category">
22
<a *ngFor="let component of category.items"
33
class="docs-component-list-item"
4-
[routerLink]="['/components/', component.id]">
4+
[routerLink]="'/' + section + '/' + component.id">
55
<mat-card class="docs-component-list-card">
66
<mat-card-title class="docs-component-list-card-title">{{component.name}}</mat-card-title>
77
<div class="docs-component-list-icon-spacer"></div>

src/app/pages/component-list/component-list.spec.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@ import {DocsAppTestingModule} from '../../testing/testing-module';
66

77
const CATEGORY_ID = 'forms';
88
const mockActivatedRoute = {
9-
params: Observable.create(observer => {
10-
observer.next({id: CATEGORY_ID});
9+
pathFromRoot: Observable.create(observer => {
10+
observer.next({
11+
params: {
12+
section: 'components',
13+
id: CATEGORY_ID,
14+
}
15+
});
1116
observer.complete();
1217
})
1318
};

src/app/pages/component-list/component-list.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import {ComponentPageTitle} from '../page-title/page-title';
88
import {SvgViewerModule} from '../../shared/svg-viewer/svg-viewer';
99
import {CommonModule} from '@angular/common';
1010
import {MatCardModule} from '@angular/material';
11+
import {Observable} from 'rxjs/Observable';
12+
import 'rxjs/add/observable/combineLatest';
1113

1214
@Component({
1315
selector: 'app-components',
@@ -16,20 +18,24 @@ import {MatCardModule} from '@angular/material';
1618
})
1719
export class ComponentList {
1820
category: DocCategory;
21+
section: string;
1922

2023
constructor(public docItems: DocumentationItems,
2124
private _componentPageTitle: ComponentPageTitle,
2225
private _route: ActivatedRoute,
23-
private router: Router) {
24-
_route.params.subscribe(p => {
25-
this.category = docItems.getCategoryById(p['id']);
26+
public router: Router) {
27+
Observable
28+
.combineLatest(_route.pathFromRoot.map(route => route.params), Object.assign)
29+
.subscribe(p => {
30+
this.category = docItems.getCategoryById(p['id']);
31+
this.section = p['section'];
2632

27-
if (this.category) {
28-
this._componentPageTitle.title = this.category.name;
29-
} else {
30-
this.router.navigate(['/categories']);
31-
}
32-
});
33+
if (this.category) {
34+
this._componentPageTitle.title = this.category.name;
35+
} else {
36+
this.router.navigate(['../'], {relativeTo: this._route});
37+
}
38+
});
3339
}
3440
}
3541

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {Injectable} from '@angular/core';
2+
import {CanActivate, ActivatedRouteSnapshot, Router, RouterStateSnapshot} from '@angular/router';
3+
import {SECTIONS} from '../../shared/documentation-items/documentation-items';
4+
5+
/**
6+
* Guard to determine if the sidenav can load, based on if the section exists in documentation
7+
* items.
8+
*/
9+
@Injectable()
10+
export class CanActivateComponentSidenav implements CanActivate {
11+
constructor(private router: Router) {}
12+
13+
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
14+
// Searches if the section defined the base UrlSegment is a valid section from the documentation
15+
// items. If found, returns true to allow activation, otherwise blocks activation and navigates
16+
// to '/'.
17+
const sectionFound = Object.keys(SECTIONS).find(
18+
(val => val.toLowerCase() === route.url[0].path.toLowerCase()));
19+
if (sectionFound) { return true; }
20+
this.router.navigateByUrl('/');
21+
return false;
22+
}
23+
}

src/app/pages/component-sidenav/component-sidenav.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
<mat-sidenav #sidenav class="docs-component-viewer-sidenav"
33
[opened]="!isScreenSmall()"
44
[mode]="isScreenSmall() ? 'over' : 'side'">
5-
<nav *ngFor="let category of docItems.getItemsInCategories()">
5+
<nav *ngFor="let category of docItems.getCategories((params | async)?.section)">
66
<h3>{{category.name}}</h3>
77
<ul>
88
<li *ngFor="let component of category.items">
9-
<a [routerLink]="['/components/', component.id]"
9+
<a [routerLink]="'/' + (params | async)?.section+ '/' + component.id"
1010
routerLinkActive="docs-component-viewer-sidenav-item-selected">
1111
{{component.name}}
1212
</a>

src/app/pages/component-sidenav/component-sidenav.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ describe('ComponentSidenav', () => {
3737

3838
fixture.detectChanges();
3939

40-
const totalItems = component.docItems.getAllItems().length;
40+
const totalItems = component.docItems.getItems('categories').length;
4141
const totalLinks = fixture
4242
.nativeElement
4343
.querySelectorAll('.docs-component-viewer-sidenav li a')

src/app/pages/component-sidenav/component-sidenav.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import {Component, NgZone, ViewEncapsulation, ViewChild, OnInit, NgModule} from
22
import {DocumentationItems} from '../../shared/documentation-items/documentation-items';
33
import {MatSidenav, MatSidenavModule} from '@angular/material';
44
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
5-
import {Router, RouterModule} from '@angular/router';
5+
import {ActivatedRoute, Params, Router, RouterModule} from '@angular/router';
66
import {CommonModule} from '@angular/common';
77
import {ComponentHeaderModule} from '../component-page-header/component-page-header';
88
import {FooterModule} from '../../shared/footer/footer';
9+
import {Observable} from 'rxjs/Observable';
910

1011
const SMALL_WIDTH_BREAKPOINT = 840;
1112

@@ -18,7 +19,10 @@ const SMALL_WIDTH_BREAKPOINT = 840;
1819
export class ComponentSidenav implements OnInit {
1920
private mediaMatcher: MediaQueryList = matchMedia(`(max-width: ${SMALL_WIDTH_BREAKPOINT}px)`);
2021

22+
params: Observable<Params>;
23+
2124
constructor(public docItems: DocumentationItems,
25+
private _route: ActivatedRoute,
2226
private _router: Router,
2327
zone: NgZone) {
2428
// TODO(josephperrott): Move to CDK breakpoint management once available.
@@ -33,6 +37,10 @@ export class ComponentSidenav implements OnInit {
3337
this.sidenav.close();
3438
}
3539
});
40+
// Combine params from all of the path into a single object.
41+
this.params = Observable.combineLatest(
42+
this._route.pathFromRoot.map(route => route.params),
43+
Object.assign);
3644
}
3745

3846
isScreenSmall(): boolean {

src/app/pages/component-viewer/component-viewer.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div class="docs-component-viewer">
22
<nav mat-tab-nav-bar class="docs-component-viewer-tabbed-content">
33
<a mat-tab-link class="docs-component-viewer-section-tab"
4-
*ngFor="let section of ['Overview', 'API', 'Examples']"
4+
*ngFor="let section of sections"
55
[routerLink]="section.toLowerCase()"
66
routerLinkActive #rla="routerLinkActive"
77
[active]="rla.isActive">{{section}}</a>

src/app/pages/component-viewer/component-viewer.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {TableOfContentsModule} from '../../shared/table-of-contents/table-of-con
1616
export class ComponentViewer {
1717
componentDocItem: DocItem;
1818

19+
sections: Set<string> = new Set(['overview', 'api']);
20+
1921
constructor(private _route: ActivatedRoute,
2022
private router: Router,
2123
public _componentPageTitle: ComponentPageTitle,
@@ -25,6 +27,10 @@ export class ComponentViewer {
2527

2628
if (this.componentDocItem) {
2729
this._componentPageTitle.title = `${this.componentDocItem.name}`;
30+
this.componentDocItem.examples.length ?
31+
this.sections.add('examples') :
32+
this.sections.delete('examples');
33+
2834
} else {
2935
this.router.navigate(['/components']);
3036
}

src/app/routes.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,31 @@ import {
1010
} from './pages/component-viewer/component-viewer';
1111
import {ComponentCategoryList} from './pages/component-category-list/component-category-list';
1212
import {ComponentSidenav} from './pages/component-sidenav/component-sidenav';
13+
import {
14+
CanActivateComponentSidenav
15+
} from './pages/component-sidenav/component-sidenav-can-load-guard';
1316
import {GuideViewer} from './pages/guide-viewer/guide-viewer';
1417

1518
export const MATERIAL_DOCS_ROUTES: Routes = [
16-
{path: '', component: Homepage, pathMatch: 'full'},
17-
{
18-
path: 'categories',
19-
component: ComponentSidenav,
20-
children: [
21-
{path: '', component: ComponentCategoryList},
22-
{path: ':id', component: ComponentList},
23-
],
24-
},
19+
{path: '', component: Homepage, pathMatch: 'full', data: {}},
20+
{path: 'categories', redirectTo: '/components/categories'},
21+
{path: 'guides', component: GuideList, data: {}},
22+
{path: 'guide/:id', component: GuideViewer, data: {}},
2523
{
26-
path: 'components',
24+
path: ':section',
25+
canActivate: [CanActivateComponentSidenav],
2726
component: ComponentSidenav,
2827
children: [
29-
{path: '', component: ComponentCategoryList},
28+
{path: '', redirectTo: 'categories', pathMatch: 'full'},
3029
{path: 'component/:id', redirectTo: ':id', pathMatch: 'full'},
3130
{path: 'category/:id', redirectTo: '/categories/:id', pathMatch: 'full'},
31+
{
32+
path: 'categories',
33+
children: [
34+
{path: '', component: ComponentCategoryList},
35+
{path: ':id', component: ComponentList},
36+
],
37+
},
3238
{
3339
path: ':id',
3440
component: ComponentViewer,
@@ -42,7 +48,5 @@ export const MATERIAL_DOCS_ROUTES: Routes = [
4248
},
4349
],
4450
},
45-
{path: 'guides', component: GuideList},
46-
{path: 'guide/:id', component: GuideViewer},
4751
{path: '**', redirectTo: ''},
4852
];

src/app/shared/documentation-items/documentation-items.spec.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {TestBed, inject, async} from '@angular/core/testing';
22
import {DocumentationItems} from './documentation-items';
33

4+
const COMPONENTS = 'components';
45

56
describe('DocViewer', () => {
67
let docsItems: DocumentationItems;
@@ -16,9 +17,9 @@ describe('DocViewer', () => {
1617
}));
1718

1819
it('get a list of categories', () => {
19-
expect(docsItems.getItemsInCategories()).toBeDefined();
20-
expect(docsItems.getItemsInCategories().length).toBeGreaterThan(0);
21-
for (const category of docsItems.getItemsInCategories()) {
20+
expect(docsItems.getCategories(COMPONENTS)).toBeDefined();
21+
expect(docsItems.getCategories(COMPONENTS).length).toBeGreaterThan(0);
22+
for (const category of docsItems.getCategories(COMPONENTS)) {
2223
expect(category.id).toBeDefined();
2324
expect(category.name).toBeDefined();
2425
expect(category.items).toBeDefined();
@@ -27,9 +28,9 @@ describe('DocViewer', () => {
2728
});
2829

2930
it('should get a list of all doc items', () => {
30-
expect(docsItems.getAllItems()).toBeDefined();
31-
expect(docsItems.getAllItems().length).toBeGreaterThan(0);
32-
for (const item of docsItems.getAllItems()) {
31+
expect(docsItems.getItems(COMPONENTS)).toBeDefined();
32+
expect(docsItems.getItems(COMPONENTS).length).toBeGreaterThan(0);
33+
for (const item of docsItems.getItems(COMPONENTS)) {
3334
expect(item.id).toBeDefined();
3435
expect(item.name).toBeDefined();
3536
}

0 commit comments

Comments
 (0)