Skip to content
This repository was archived by the owner on Oct 1, 2018. It is now read-only.

Commit 37ffd9d

Browse files
authored
Merge branch 'master' into doc-do-branch
2 parents 5eb3cab + 4432b01 commit 37ffd9d

21 files changed

+338
-161
lines changed

src/app/app.component.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
44
import { AppComponent } from './app.component';
55
import { ToolbarModule } from './toolbar/toolbar.module';
66
import { MatSidenavModule, MatListModule } from '@angular/material';
7+
import { SeoService } from './services/seo.service';
78

89
describe('AppComponent', () => {
910
let component: AppComponent;
@@ -19,7 +20,8 @@ describe('AppComponent', () => {
1920
MatSidenavModule,
2021
MatListModule
2122
],
22-
declarations: [AppComponent]
23+
declarations: [AppComponent],
24+
providers: [SeoService]
2325
}).compileComponents();
2426
})
2527
);

src/app/app.component.ts

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import { Component } from "@angular/core";
1+
import { Component, OnInit } from '@angular/core';
2+
import {
3+
Router,
4+
ActivatedRoute,
5+
NavigationEnd,
6+
RouterEvent
7+
} from '@angular/router';
8+
import { filter, map, mergeMap } from 'rxjs/operators';
9+
import { SeoService, SeoData } from './services/seo.service';
210

311
interface Menu {
412
title: string;
@@ -7,31 +15,55 @@ interface Menu {
715
}
816

917
@Component({
10-
selector: "app-root",
11-
templateUrl: "./app.component.html",
12-
styleUrls: ["./app.component.scss"]
18+
selector: 'app-root',
19+
templateUrl: './app.component.html',
20+
styleUrls: ['./app.component.scss']
1321
})
14-
export class AppComponent {
22+
export class AppComponent implements OnInit {
1523
menus: Menu[] = [
1624
{
17-
title: "Home",
18-
link: "/",
25+
title: 'Home',
26+
link: '/',
1927
options: { exact: true }
2028
},
2129
{
22-
title: "Operators",
23-
link: "/operators",
30+
title: 'Operators',
31+
link: '/operators',
2432
options: { exact: false }
2533
},
2634
{
27-
title: "Companies",
28-
link: "/companies",
35+
title: 'Companies',
36+
link: '/companies',
2937
options: { exact: false }
3038
},
3139
{
32-
title: "Team",
33-
link: "/team",
40+
title: 'Team',
41+
link: '/team',
3442
options: { exact: false }
3543
}
3644
];
45+
46+
constructor(
47+
private _router: Router,
48+
private _activatedRoute: ActivatedRoute,
49+
private _seo: SeoService
50+
) {}
51+
52+
ngOnInit() {
53+
this._router.events
54+
.pipe(
55+
filter((e: RouterEvent) => e instanceof NavigationEnd),
56+
map(() => {
57+
let route = this._activatedRoute;
58+
while (route.firstChild) {
59+
route = route.firstChild;
60+
}
61+
return route;
62+
}),
63+
filter(route => route.outlet === 'primary'),
64+
mergeMap(route => route.data),
65+
filter((data: SeoData) => data.title !== undefined)
66+
)
67+
.subscribe((data: SeoData) => this._seo.setHeaders(data));
68+
}
3769
}

src/app/app.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { SeoService } from './services/seo.service';
12
import { BrowserModule } from '@angular/platform-browser';
23
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
34
import { NgModule } from '@angular/core';
@@ -17,7 +18,7 @@ import { AppRoutingModule } from './app-routing.module';
1718
MatSidenavModule,
1819
AppRoutingModule
1920
],
20-
providers: [],
21+
providers: [SeoService],
2122
bootstrap: [AppComponent]
2223
})
2324
export class AppModule {}

src/app/companies/companies-routing.module.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ import { Routes, RouterModule } from '@angular/router';
33

44
import { CompaniesComponent } from './companies.component';
55

6-
const routes: Routes = [{ path: '', component: CompaniesComponent }];
6+
const routes: Routes = [
7+
{
8+
path: '',
9+
component: CompaniesComponent,
10+
data: { title: ['Companies'], description: 'Companies that use RxJS...' }
11+
}
12+
];
713

814
@NgModule({
915
imports: [RouterModule.forChild(routes)],
Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
import { Component, OnInit } from "@angular/core";
1+
import { Component } from '@angular/core';
22

33
@Component({
4-
selector: "app-companies",
5-
templateUrl: "./companies.component.html",
6-
styleUrls: ["./companies.component.scss"]
4+
selector: 'app-companies',
5+
templateUrl: './companies.component.html',
6+
styleUrls: ['./companies.component.scss']
77
})
8-
export class CompaniesComponent implements OnInit {
8+
export class CompaniesComponent {
99
constructor() {}
10-
11-
ngOnInit() {}
1210
}

src/app/operators/components/operator/operator.component.ts

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,64 @@ import {
22
Component,
33
Input,
44
OnInit,
5-
ChangeDetectionStrategy
6-
} from "@angular/core";
7-
import { OperatorDoc } from "../../../../operator-docs/operator.model";
5+
ChangeDetectionStrategy,
6+
Inject,
7+
InjectionToken
8+
} from '@angular/core';
9+
import { Router, ActivatedRoute } from '@angular/router';
10+
import { SeoService } from '../../../services/seo.service';
11+
import { OperatorDoc } from '../../../../operator-docs/operator.model';
12+
import { pluck } from 'rxjs/operators';
13+
14+
export const OPERATOR_TOKEN = new InjectionToken<string>('operators');
815

916
@Component({
10-
selector: "app-operator",
11-
templateUrl: "./operator.component.html",
12-
styleUrls: ["./operator.component.scss"],
13-
changeDetection: ChangeDetectionStrategy.OnPush
17+
selector: 'app-operator',
18+
templateUrl: './operator.component.html',
19+
styleUrls: ['./operator.component.scss']
1420
})
15-
export class OperatorComponent {
16-
@Input() operator: OperatorDoc;
17-
18-
private readonly baseSourceUrl = "https://github.com/ReactiveX/rxjs/blob/master/src/operators/";
19-
private readonly baseSpecUrl = "http://reactivex.io/rxjs/test-file/spec-js/operators";
21+
export class OperatorComponent implements OnInit {
22+
public operator: OperatorDoc;
23+
public operatorsMap = new Map<string, OperatorDoc>();
24+
25+
private readonly baseSourceUrl = 'https://github.com/ReactiveX/rxjs/blob/master/src/operators/';
26+
private readonly baseSpecUrl = 'http://reactivex.io/rxjs/test-file/spec-js/operators';
27+
28+
constructor(
29+
private _router: Router,
30+
private _activatedRoute: ActivatedRoute,
31+
@Inject(OPERATOR_TOKEN) public operators: OperatorDoc[],
32+
private _seo: SeoService
33+
) {}
34+
35+
ngOnInit() {
36+
this.operators.forEach((op: OperatorDoc) => {
37+
this.operatorsMap.set(op.name, op);
38+
});
39+
this._activatedRoute.params
40+
.pipe(pluck('operator'))
41+
.subscribe((name: string) => {
42+
if (this.operatorsMap.has(name)) {
43+
this.operator = this.operatorsMap.get(name);
44+
} else {
45+
this.notfound();
46+
return;
47+
}
48+
this._seo.setHeaders({
49+
title: [this.operator.name, this.operator.operatorType],
50+
description: this.operator.shortDescription
51+
? this.operator.shortDescription.description
52+
: ''
53+
});
54+
});
55+
}
2056

2157
get operatorName() {
2258
return this.operator.name;
2359
}
2460

2561
get signature() {
26-
return this.operator.signature || "Signature Placeholder";
62+
return this.operator.signature || 'Signature Placeholder';
2763
}
2864

2965
get marbleUrl() {
@@ -78,4 +114,9 @@ export class OperatorComponent {
78114
get additionalResources() {
79115
return this.operator.additionalResources || [];
80116
}
117+
118+
private notfound() {
119+
this._router.navigate(['/operators']);
120+
return {};
121+
}
81122
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<h2 class="related-operators"> Related Operators </h2>
22
<ul class="section-list">
33
<li *ngFor="let related of relatedOperators">
4-
<a [href]="'/operators#' + related"> {{ related }} </a>
4+
<a [routerLink]="['/operators', related]"> {{ related }} </a>
55
</li>
66
</ul>

src/app/operators/operators-routing.module.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,16 @@ import { NgModule } from '@angular/core';
22
import { Routes, RouterModule } from '@angular/router';
33

44
import { OperatorsComponent } from './operators.component';
5+
import { OperatorComponent } from './components/operator/operator.component';
56

6-
const routes: Routes = [{ path: '', component: OperatorsComponent }];
7+
const routes: Routes = [
8+
{
9+
path: '',
10+
component: OperatorsComponent,
11+
data: { title: ['Operators'], description: 'All the RxJS operators...' },
12+
children: [{ path: ':operator', component: OperatorComponent }]
13+
}
14+
];
715

816
@NgModule({
917
imports: [RouterModule.forChild(routes)],

src/app/operators/operators.component.html

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,13 @@
1111
<h3 mat-subheader class="category-subheader">{{ category }}</h3>
1212
<a mat-list-item
1313
*ngFor="let operator of groupedOperators[category]"
14-
[href]="'/operators#' + operator.name">
14+
[routerLink]="['/operators', operator.name]"
15+
routerLinkActive="active">
1516
{{ operator.name }}
1617
</a>
1718
</mat-nav-list>
1819
</mat-sidenav>
19-
<app-operator
20-
*ngFor="let operator of operators"
21-
[operator]="operator">
22-
</app-operator>
20+
<router-outlet></router-outlet>
2321
</mat-sidenav-container>
2422
<button
2523
*ngIf="smallScreen"
Lines changed: 29 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
1-
import { Component, Inject, InjectionToken, OnInit, AfterViewInit, ChangeDetectionStrategy } from '@angular/core';
2-
import { trigger, state, style, animate, transition } from '@angular/animations';
1+
import {
2+
Component,
3+
Inject,
4+
InjectionToken,
5+
OnInit,
6+
ChangeDetectionStrategy
7+
} from '@angular/core';
8+
import {
9+
trigger,
10+
state,
11+
style,
12+
animate,
13+
transition
14+
} from '@angular/animations';
315
import { Router, ActivatedRoute } from '@angular/router';
416
import { BreakpointObserver } from '@angular/cdk/layout';
517
import { Subscription } from 'rxjs/Subscription';
@@ -21,7 +33,7 @@ interface OperatorDocMap {
2133
styleUrls: ['./operators.component.scss'],
2234
animations: [
2335
trigger('growInOut', [
24-
state('in', style({opacity: 1})),
36+
state('in', style({ opacity: 1 })),
2537
transition('void => *', [
2638
style({
2739
opacity: 0,
@@ -30,55 +42,29 @@ interface OperatorDocMap {
3042
animate(`150ms ease-in`)
3143
]),
3244
transition('* => void', [
33-
animate(`150ms ease-out`, style({
34-
opacity: 0,
35-
transform: 'scale3d(.3, .3, .3)'
36-
}))
45+
animate(
46+
`150ms ease-out`,
47+
style({
48+
opacity: 0,
49+
transform: 'scale3d(.3, .3, .3)'
50+
})
51+
)
3752
])
3853
])
3954
]
4055
})
41-
export class OperatorsComponent implements OnInit, AfterViewInit {
56+
export class OperatorsComponent implements OnInit {
4257
public groupedOperators: OperatorDocMap;
4358
public categories: string[];
4459

45-
private _subscription: Subscription;
46-
4760
constructor(
4861
private _breakpointObserver: BreakpointObserver,
49-
private _router: Router,
50-
private _activatedRoute: ActivatedRoute,
5162
@Inject(OPERATORS_TOKEN) public operators: OperatorDoc[]
52-
) { }
63+
) {}
5364

5465
ngOnInit() {
5566
this.groupedOperators = groupOperatorsByType(this.operators);
5667
this.categories = Object.keys(this.groupedOperators);
57-
this._subscription = this._activatedRoute
58-
.fragment
59-
.subscribe(name => this.scrollToOperator(name));
60-
}
61-
62-
ngAfterViewInit() {
63-
// scroll initial param when applicable
64-
const name = this._activatedRoute.snapshot.fragment;
65-
66-
if (name) {
67-
// slight delay for scroll to be accurate
68-
setTimeout(() => this.scrollToOperator(name), 100);
69-
}
70-
}
71-
72-
updateUrl(name: string) {
73-
this._router.navigate([ '/operators' ], { fragment: name });
74-
}
75-
76-
scrollToOperator(name: string) {
77-
const element = document.getElementById(name);
78-
79-
if (element) {
80-
element.scrollIntoView();
81-
}
8268
}
8369

8470
get extraSmallScreen() {
@@ -90,20 +76,21 @@ export class OperatorsComponent implements OnInit, AfterViewInit {
9076
}
9177

9278
get operatorMenuGap() {
93-
return this.extraSmallScreen ? OPERATOR_MENU_GAP_SMALL : OPERATOR_MENU_GAP_LARGE;
79+
return this.extraSmallScreen
80+
? OPERATOR_MENU_GAP_SMALL
81+
: OPERATOR_MENU_GAP_LARGE;
9482
}
9583

9684
get sidenavMode() {
9785
return this.smallScreen ? 'over' : 'side';
9886
}
99-
10087
}
10188

10289
export function groupOperatorsByType(operators: OperatorDoc[]): OperatorDocMap {
10390
return operators.reduce((acc: OperatorDocMap, curr: OperatorDoc) => {
10491
if (acc[curr.operatorType]) {
105-
return { ...acc, [ curr.operatorType ] : [ ...acc[ curr.operatorType ], curr ] };
92+
return { ...acc, [curr.operatorType]: [...acc[curr.operatorType], curr] };
10693
}
107-
return { ...acc, [ curr.operatorType ]: [ curr ] };
94+
return { ...acc, [curr.operatorType]: [curr] };
10895
}, {});
10996
}

0 commit comments

Comments
 (0)