feat(aio): add tooltip to nav node if none specified
This commit is contained in:
parent
efaf502e95
commit
d32bc5df3e
|
@ -80,20 +80,54 @@ describe('NavigationService', () => {
|
|||
it('should do WHAT(?) if the request fails');
|
||||
});
|
||||
|
||||
describe('node.tooltip', () => {
|
||||
let view: NavigationNode[];
|
||||
|
||||
const sideNav: NavigationNode[] = [
|
||||
{ title: 'a', tooltip: 'a tip' },
|
||||
{ title: 'b' },
|
||||
{ title: 'c!'},
|
||||
{ url: 'foo' }
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
navService.navigationViews.subscribe(views => view = views.sideNav);
|
||||
backend.connectionsArray[0].mockRespond(createResponse({sideNav}));
|
||||
});
|
||||
|
||||
it('should have the supplied tooltip', () => {
|
||||
expect(view[0].tooltip).toEqual('a tip');
|
||||
});
|
||||
|
||||
it('should create a tooltip from title + period', () => {
|
||||
expect(view[1].tooltip).toEqual('b.');
|
||||
});
|
||||
|
||||
it('should create a tooltip from title, keeping its trailing punctuation', () => {
|
||||
expect(view[2].tooltip).toEqual('c!');
|
||||
});
|
||||
|
||||
it('should not create a tooltip if there is no title', () => {
|
||||
expect(view[3].tooltip).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('currentNode', () => {
|
||||
let currentNode: CurrentNode;
|
||||
let locationService: MockLocationService;
|
||||
|
||||
const topBarNodes: NavigationNode[] = [{ url: 'features', title: 'Features' }];
|
||||
const topBarNodes: NavigationNode[] = [
|
||||
{ url: 'features', title: 'Features', tooltip: 'tip' }
|
||||
];
|
||||
const sideNavNodes: NavigationNode[] = [
|
||||
{ title: 'a', children: [
|
||||
{ url: 'b', title: 'b', children: [
|
||||
{ url: 'c', title: 'c' },
|
||||
{ url: 'd', title: 'd' }
|
||||
{ title: 'a', tooltip: 'tip', children: [
|
||||
{ url: 'b', title: 'b', tooltip: 'tip', children: [
|
||||
{ url: 'c', title: 'c', tooltip: 'tip' },
|
||||
{ url: 'd', title: 'd', tooltip: 'tip' }
|
||||
] },
|
||||
{ url: 'e', title: 'e' }
|
||||
{ url: 'e', title: 'e', tooltip: 'tip' }
|
||||
] },
|
||||
{ url: 'f', title: 'f' }
|
||||
{ url: 'f', title: 'f', tooltip: 'tip' }
|
||||
];
|
||||
|
||||
const navJson = {
|
||||
|
@ -199,6 +233,7 @@ describe('NavigationService', () => {
|
|||
describe('docVersions', () => {
|
||||
let actualDocVersions: NavigationNode[];
|
||||
let docVersions: NavigationNode[];
|
||||
let expectedDocVersions: NavigationNode[];
|
||||
|
||||
beforeEach(() => {
|
||||
actualDocVersions = [];
|
||||
|
@ -207,12 +242,16 @@ describe('NavigationService', () => {
|
|||
{ title: 'v2', url: 'https://v2.angular.io' }
|
||||
];
|
||||
|
||||
expectedDocVersions = docVersions.map(v => (
|
||||
{...v, ...{ tooltip: v.title + '.'}})
|
||||
);
|
||||
|
||||
navService.navigationViews.subscribe(views => actualDocVersions = views.docVersions);
|
||||
});
|
||||
|
||||
it('should extract the docVersions', () => {
|
||||
backend.connectionsArray[0].mockRespond(createResponse({ docVersions }));
|
||||
expect(actualDocVersions).toEqual(docVersions);
|
||||
expect(actualDocVersions).toEqual(expectedDocVersions);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -90,7 +90,7 @@ export class NavigationService {
|
|||
*/
|
||||
private getCurrentNode(navigationViews: Observable<NavigationViews>): Observable<CurrentNode> {
|
||||
const currentNode = combineLatest(
|
||||
navigationViews.map(this.computeUrlToNavNodesMap),
|
||||
navigationViews.map(views => this.computeUrlToNavNodesMap(views)),
|
||||
this.location.currentPath,
|
||||
(navMap, url) => {
|
||||
const urlKey = url.startsWith('api/') ? 'api' : url;
|
||||
|
@ -110,21 +110,42 @@ export class NavigationService {
|
|||
private computeUrlToNavNodesMap(navigation: NavigationViews) {
|
||||
const navMap = new Map<string, CurrentNode>();
|
||||
Object.keys(navigation)
|
||||
.forEach(view => navigation[view].forEach(node => walkNodes(view, node)));
|
||||
.forEach(view => navigation[view]
|
||||
.forEach(node => this.walkNodes(view, navMap, node)));
|
||||
return navMap;
|
||||
}
|
||||
|
||||
function walkNodes(view: string, node: NavigationNode, ancestors: NavigationNode[] = []) {
|
||||
/**
|
||||
* Add tooltip to node if it doesn't have one and have title.
|
||||
* If don't want tooltip, specify `"tooltip": ""` in navigation.json
|
||||
*/
|
||||
private ensureHasTooltip(node: NavigationNode) {
|
||||
const title = node.title;
|
||||
const tooltip = node.tooltip;
|
||||
if (tooltip == null && title ) {
|
||||
// add period if no trailing punctuation
|
||||
node.tooltip = title + (/[a-zA-Z0-9]$/.test(title) ? '.' : '');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Walk the nodes of a navigation tree-view,
|
||||
* patching them and computing their ancestor nodes
|
||||
*/
|
||||
private walkNodes(
|
||||
view: string, navMap: Map<string, CurrentNode>,
|
||||
node: NavigationNode, ancestors: NavigationNode[] = []) {
|
||||
const nodes = [node, ...ancestors];
|
||||
const url = node.url;
|
||||
this.ensureHasTooltip(node);
|
||||
|
||||
// only map to this node if it has a url associated with it
|
||||
// only map to this node if it has a url
|
||||
if (url) {
|
||||
// Strip off trailing slashes from nodes in the navMap - they are not relevant to matching
|
||||
navMap[url.replace(/\/$/, '')] = { url, view, nodes };
|
||||
}
|
||||
|
||||
if (node.children) {
|
||||
node.children.forEach(child => walkNodes(view, child, nodes));
|
||||
}
|
||||
node.children.forEach(child => this.walkNodes(view, navMap, child, nodes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue