Skip to content

Commit 70a697a

Browse files
committed
fix: define navigationListService
1 parent ff13594 commit 70a697a

File tree

10 files changed

+124
-79
lines changed

10 files changed

+124
-79
lines changed

projects/common/src/navigation/navigation.config.ts

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,4 @@
11
import { Observable } from 'rxjs';
2-
import { Color } from '../color/color';
3-
import { FeatureState} from '../feature/state/feature.state';
4-
5-
export type NavItemConfig = NavItemLinkConfig | NavItemHeaderConfig | NavItemDividerConfig;
6-
7-
export interface NavItemLinkConfig {
8-
type: NavItemType.Link;
9-
icon: string;
10-
iconSize?: string;
11-
label: string;
12-
matchPaths: string[]; // For now, default path is index 0
13-
features?: string[];
14-
replaceCurrentHistory?: boolean;
15-
isBeta?: boolean;
16-
trailingIcon?: string;
17-
trailingIconTooltip?: string;
18-
trailingIconColor?: Color;
19-
featureState$?: Observable<FeatureState>;
20-
}
212

223
export type FooterItemConfig = FooterItemLinkConfig;
234

projects/common/src/navigation/navigation.service.test.ts

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ import { Location } from '@angular/common';
22
import { Title } from '@angular/platform-browser';
33
import { Router, UrlSegment } from '@angular/router';
44
import { RouterTestingModule } from '@angular/router/testing';
5-
import { IconType } from '@hypertrace/assets-library';
6-
import { APP_TITLE, NavItemType } from '@hypertrace/common';
75
import { patchRouterNavigateForTest } from '@hypertrace/test-utils';
86
import { createServiceFactory, mockProvider, SpectatorService } from '@ngneat/spectator/jest';
7+
import { APP_TITLE } from './ht-route';
98
import {
109
ExternalNavigationPathParams,
1110
ExternalNavigationWindowHandling,
@@ -69,6 +68,7 @@ describe('Navigation Service', () => {
6968
patchRouterNavigateForTest(spectator);
7069
router = spectator.inject(Router);
7170
});
71+
7272
test('can retrieve a route config relative to the current route', () => {
7373
router.navigate(['root']);
7474
expect(spectator.service.getRouteConfig(['child'])).toEqual(firstChildRouteConfig);
@@ -297,36 +297,6 @@ describe('Navigation Service', () => {
297297
}
298298
});
299299

300-
test('decorating navItem with features work as expected', () => {
301-
expect(
302-
spectator.service.decorateNavItem(
303-
{
304-
type: NavItemType.Header,
305-
label: 'Label'
306-
},
307-
spectator.service.getCurrentActivatedRoute()
308-
)
309-
).toEqual({ type: NavItemType.Header, label: 'Label' });
310-
311-
expect(
312-
spectator.service.decorateNavItem(
313-
{
314-
type: NavItemType.Link,
315-
label: 'Label',
316-
icon: IconType.None,
317-
matchPaths: ['root']
318-
},
319-
spectator.service.rootRoute()
320-
)
321-
).toEqual({
322-
type: NavItemType.Link,
323-
label: 'Label',
324-
icon: IconType.None,
325-
matchPaths: ['root'],
326-
features: ['test-feature']
327-
});
328-
});
329-
330300
test('setting title should work as expected', () => {
331301
router.navigate(['root', 'child']);
332302
expect(spectator.inject(Title).setTitle).toHaveBeenCalledWith('defaultAppTitle | child1');

projects/common/src/navigation/navigation.service.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,11 @@ import {
1414
UrlSegment,
1515
UrlTree
1616
} from '@angular/router';
17-
import { uniq } from 'lodash-es';
1817
import { from, Observable, of } from 'rxjs';
1918
import { distinctUntilChanged, filter, map, share, skip, startWith, switchMap, take, tap } from 'rxjs/operators';
2019
import { isEqualIgnoreFunctions, throwIfNil } from '../utilities/lang/lang-utils';
2120
import { Dictionary } from '../utilities/types/types';
2221
import { APP_TITLE, HtRoute } from './ht-route';
23-
import { NavItemConfig, NavItemType } from './navigation.config';
2422

2523
@Injectable({ providedIn: 'root' })
2624
export class NavigationService {
@@ -243,26 +241,6 @@ export class NavigationService {
243241
return this.findRouteConfig(path, childRoutes ? childRoutes : []);
244242
}
245243

246-
public decorateNavItem(navItem: NavItemConfig, activatedRoute: ActivatedRoute): NavItemConfig {
247-
if (navItem.type !== NavItemType.Link) {
248-
return { ...navItem };
249-
}
250-
const features = navItem.matchPaths
251-
.map(path => this.getRouteConfig([path], activatedRoute))
252-
.filter((maybeRoute): maybeRoute is HtRoute => maybeRoute !== undefined)
253-
.flatMap(route => this.getFeaturesForRoute(route))
254-
.concat(navItem.features || []);
255-
256-
return {
257-
...navItem,
258-
features: uniq(features)
259-
};
260-
}
261-
262-
private getFeaturesForRoute(route: HtRoute): string[] {
263-
return (route.data && route.data.features) || [];
264-
}
265-
266244
public rootRoute(): ActivatedRoute {
267245
return this.router.routerState.root;
268246
}

projects/components/src/navigation/nav-item/nav-item.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
22
import { ActivatedRoute } from '@angular/router';
3-
import { FeatureState, NavigationParams, NavigationParamsType, NavItemLinkConfig } from '@hypertrace/common';
3+
import { FeatureState, NavigationParams, NavigationParamsType } from '@hypertrace/common';
44
import { IconSize } from '../../icon/icon-size';
5+
import { NavItemLinkConfig} from '../navigation-list.service';
56

67
@Component({
78
selector: 'ht-nav-item',

projects/components/src/navigation/navigation-list-component.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { Injectable } from '@angular/core';
2-
import { FeatureState, FeatureStateResolver, NavItemConfig, NavItemHeaderConfig, NavItemLinkConfig, NavItemType } from '@hypertrace/common';
2+
import { FeatureState, FeatureStateResolver, NavItemHeaderConfig, NavItemType } from '@hypertrace/common';
33
import { isEmpty } from 'lodash-es';
44
import { combineLatest, Observable, of } from 'rxjs';
55
import { map } from 'rxjs/operators';
6+
import { NavItemConfig, NavItemLinkConfig, } from './navigation-list.service';
67

78
@Injectable({ providedIn: 'root' })
89
export class NavigationListComponentService {

projects/components/src/navigation/navigation-list.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
22
import { ActivatedRoute } from '@angular/router';
33
import { IconType } from '@hypertrace/assets-library';
4-
import { FooterItemConfig, NavigationService, NavItemConfig, NavItemLinkConfig, NavItemType } from '@hypertrace/common';
4+
import { FooterItemConfig, NavigationService, NavItemType } from '@hypertrace/common';
55
import { Observable } from 'rxjs';
66
import { map, startWith } from 'rxjs/operators';
77
import { IconSize } from '../icon/icon-size';
88
import { NavigationListComponentService } from './navigation-list-component.service';
9+
import { NavItemConfig, NavItemLinkConfig } from './navigation-list.service';
910

1011
@Component({
1112
selector: 'ht-navigation-list',
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { ActivatedRoute } from '@angular/router';
2+
import { IconType } from '@hypertrace/assets-library';
3+
import { NavigationService, NavItemType } from '@hypertrace/common';
4+
import { NavigationListService } from '@hypertrace/components';
5+
import { createServiceFactory, mockProvider, SpectatorService } from '@ngneat/spectator/jest';
6+
7+
describe('Navigation List Service', () => {
8+
let spectator: SpectatorService<NavigationListService>;
9+
10+
const buildService = createServiceFactory({
11+
service: NavigationListService,
12+
providers: [
13+
mockProvider(ActivatedRoute),
14+
mockProvider(NavigationService, { getRouteConfig: jest.fn().mockReturnValue({
15+
path: 'root',
16+
data: { features: ['test-feature'] },
17+
children: []
18+
})}),
19+
]
20+
});
21+
22+
beforeEach(() => {
23+
spectator = buildService();
24+
});
25+
26+
test('decorating navItem with features work as expected', () => {
27+
expect(
28+
spectator.service.decorateNavItem(
29+
{
30+
type: NavItemType.Header,
31+
label: 'Label'
32+
},
33+
spectator.inject(ActivatedRoute)
34+
)
35+
).toEqual({ type: NavItemType.Header, label: 'Label' });
36+
37+
expect(
38+
spectator.service.decorateNavItem(
39+
{
40+
type: NavItemType.Link,
41+
label: 'Label',
42+
icon: IconType.None,
43+
matchPaths: ['root']
44+
},
45+
spectator.inject(ActivatedRoute)
46+
)
47+
).toEqual({
48+
type: NavItemType.Link,
49+
label: 'Label',
50+
icon: IconType.None,
51+
matchPaths: ['root'],
52+
features: ['test-feature']
53+
});
54+
});
55+
});
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Injectable } from '@angular/core';
2+
import { ActivatedRoute } from '@angular/router';
3+
import {
4+
Color,
5+
FeatureState,
6+
HtRoute,
7+
NavigationService,
8+
NavItemDividerConfig,
9+
NavItemHeaderConfig,
10+
NavItemType
11+
} from '@hypertrace/common';
12+
import { uniq } from 'lodash-es';
13+
import { Observable } from 'rxjs';
14+
import { IconSize } from '../icon/icon-size';
15+
16+
@Injectable({ providedIn: 'root'})
17+
export class NavigationListService {
18+
public constructor(private readonly navigationService: NavigationService) {}
19+
20+
public decorateNavItem(navItem: NavItemConfig, activatedRoute: ActivatedRoute): NavItemConfig {
21+
if (navItem.type !== NavItemType.Link) {
22+
return { ...navItem };
23+
}
24+
const features = navItem.matchPaths
25+
.map(path => this.navigationService.getRouteConfig([path], activatedRoute))
26+
.filter((maybeRoute): maybeRoute is HtRoute => maybeRoute !== undefined)
27+
.flatMap(route => this.getFeaturesForRoute(route))
28+
.concat(navItem.features || []);
29+
30+
return {
31+
...navItem,
32+
features: uniq(features)
33+
};
34+
}
35+
36+
private getFeaturesForRoute(route: HtRoute): string[] {
37+
return (route.data && route.data.features) || [];
38+
}
39+
}
40+
41+
export type NavItemConfig = NavItemLinkConfig | NavItemHeaderConfig | NavItemDividerConfig;
42+
43+
export interface NavItemLinkConfig {
44+
type: NavItemType.Link;
45+
icon: string;
46+
iconSize?: IconSize;
47+
label: string;
48+
matchPaths: string[]; // For now, default path is index 0
49+
features?: string[];
50+
replaceCurrentHistory?: boolean;
51+
isBeta?: boolean;
52+
trailingIcon?: string;
53+
trailingIconTooltip?: string;
54+
trailingIconColor?: Color;
55+
featureState$?: Observable<FeatureState>;
56+
}

projects/components/src/public-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ export * from './navigation/navigation-list.component';
156156
export * from './navigation/navigation-list.module';
157157
export * from './navigation/nav-item/nav-item.component';
158158
export * from './navigation/navigation-list-component.service';
159+
export * from './navigation/navigation-list.service';
159160

160161
// Let async
161162
export { LetAsyncDirective } from './let-async/let-async.directive';

src/app/shared/navigation/navigation.component.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { ChangeDetectionStrategy, Component } from '@angular/core';
22
import { ActivatedRoute } from '@angular/router';
33
import { IconType } from '@hypertrace/assets-library';
4-
import { NavigationService, NavItemConfig, NavItemType, PreferenceService } from '@hypertrace/common';
4+
import { NavItemType, PreferenceService } from '@hypertrace/common';
5+
import { NavigationListService, NavItemConfig } from '@hypertrace/components';
56
import { ObservabilityIconType } from '@hypertrace/observability';
67
import { Observable } from 'rxjs';
78

@@ -73,12 +74,12 @@ export class NavigationComponent {
7374
];
7475

7576
public constructor(
76-
private readonly navigationService: NavigationService,
77+
private readonly navigationListService: NavigationListService,
7778
private readonly preferenceService: PreferenceService,
7879
private readonly activatedRoute: ActivatedRoute
7980
) {
8081
this.navItems = this.navItemDefinitions.map(definition =>
81-
this.navigationService.decorateNavItem(definition, this.activatedRoute)
82+
this.navigationListService.decorateNavItem(definition, this.activatedRoute)
8283
);
8384
this.isCollapsed$ = this.preferenceService.get(NavigationComponent.COLLAPSED_PREFERENCE, false);
8485
}

0 commit comments

Comments
 (0)