2017-03-01 11:55:46 +00:00
|
|
|
import { Injectable } from '@angular/core';
|
|
|
|
|
import { Http } from '@angular/http';
|
|
|
|
|
import { Observable } from 'rxjs/Observable';
|
2017-03-04 16:05:12 +00:00
|
|
|
import { AsyncSubject } from 'rxjs/AsyncSubject';
|
2017-03-01 11:55:46 +00:00
|
|
|
import { combineLatest } from 'rxjs/observable/combineLatest';
|
2017-03-04 16:05:12 +00:00
|
|
|
import 'rxjs/add/operator/publishReplay';
|
|
|
|
|
import 'rxjs/add/operator/publishLast';
|
2017-03-01 11:55:46 +00:00
|
|
|
|
|
|
|
|
import { Logger } from 'app/shared/logger.service';
|
|
|
|
|
import { LocationService } from 'app/shared/location.service';
|
|
|
|
|
|
2017-03-05 19:58:55 +00:00
|
|
|
import { NavigationNode } from './navigation-node';
|
|
|
|
|
export { NavigationNode } from './navigation-node';
|
2017-03-01 11:55:46 +00:00
|
|
|
|
|
|
|
|
export interface NavigationViews {
|
2017-03-05 15:45:01 +00:00
|
|
|
[name: string]: NavigationNode[];
|
2017-03-01 11:55:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface NavigationMap {
|
|
|
|
|
[url: string]: NavigationMapItem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface NavigationMapItem {
|
|
|
|
|
node: NavigationNode;
|
|
|
|
|
parents: NavigationNode[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NAVIGATION_PATH = 'content/navigation.json';
|
|
|
|
|
|
|
|
|
|
@Injectable()
|
|
|
|
|
export class NavigationService {
|
|
|
|
|
|
2017-03-04 16:05:12 +00:00
|
|
|
navigationViews = this.fetchNavigation();
|
2017-03-06 10:13:49 +00:00
|
|
|
selectedNodes = this.getActiveNodes();
|
2017-03-01 11:55:46 +00:00
|
|
|
|
2017-03-04 16:05:12 +00:00
|
|
|
constructor(private http: Http, private location: LocationService, private logger: Logger) { }
|
2017-03-01 11:55:46 +00:00
|
|
|
|
2017-03-04 16:05:12 +00:00
|
|
|
private fetchNavigation(): Observable<NavigationViews> {
|
|
|
|
|
const response = this.http.get(NAVIGATION_PATH)
|
|
|
|
|
.map(res => res.json() as NavigationViews)
|
|
|
|
|
.publishLast();
|
|
|
|
|
response.connect();
|
|
|
|
|
return response;
|
2017-03-01 11:55:46 +00:00
|
|
|
}
|
|
|
|
|
|
2017-03-04 16:05:12 +00:00
|
|
|
private getActiveNodes() {
|
|
|
|
|
const currentMapItem = combineLatest(
|
|
|
|
|
this.navigationViews.map(this.computeNavMap),
|
|
|
|
|
this.location.currentUrl,
|
|
|
|
|
(navMap, url) => navMap[url]);
|
|
|
|
|
const activeNodes = currentMapItem
|
|
|
|
|
.map(item => item ? [item.node, ...item.parents] : [])
|
|
|
|
|
.publishReplay();
|
|
|
|
|
activeNodes.connect();
|
|
|
|
|
return activeNodes;
|
2017-03-01 11:55:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private computeNavMap(navigation: NavigationViews): NavigationMap {
|
|
|
|
|
const navMap: NavigationMap = {};
|
2017-03-04 16:05:12 +00:00
|
|
|
Object.keys(navigation).forEach(key => navigation[key].forEach(node => walkNodes(node, null)));
|
2017-03-01 11:55:46 +00:00
|
|
|
return navMap;
|
|
|
|
|
|
2017-03-04 16:05:12 +00:00
|
|
|
function walkNodes(node: NavigationNode, parent: NavigationMapItem | null) {
|
2017-03-05 15:45:01 +00:00
|
|
|
const item: NavigationMapItem = { node, parents: [] };
|
|
|
|
|
if (parent) {
|
|
|
|
|
item.parents = [parent.node, ...parent.parents];
|
|
|
|
|
}
|
|
|
|
|
if (node.url) {
|
|
|
|
|
// only map to this item if it has a url associated with it
|
|
|
|
|
navMap[node.url] = item;
|
2017-03-01 11:55:46 +00:00
|
|
|
}
|
|
|
|
|
if (node.children) {
|
2017-03-04 16:05:12 +00:00
|
|
|
node.children.forEach(child => walkNodes(child, item));
|
2017-03-01 11:55:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|