Skip to content

Commit 96c9d5b

Browse files
authored
feat: support route wise page titles (#993)
* feat: support route wise page titles
1 parent 5b795c2 commit 96c9d5b

File tree

8 files changed

+48
-10
lines changed

8 files changed

+48
-10
lines changed

projects/common/src/navigation/ht-route-data.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ import { Breadcrumb } from './breadcrumb';
44
export interface HtRouteData {
55
breadcrumb?: Breadcrumb | Observable<Breadcrumb>;
66
features?: string[];
7+
title?: string;
78
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import { InjectionToken } from '@angular/core';
12
import { Route } from '@angular/router';
23
import { HtRouteData } from './ht-route-data';
34

45
export interface HtRoute extends Route {
56
data?: HtRouteData;
67
children?: HtRoute[];
78
}
9+
10+
export const APP_TITLE = new InjectionToken<string>('APP_TITLE');

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

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { Location } from '@angular/common';
2+
import { Title } from '@angular/platform-browser';
23
import { Router, UrlSegment } from '@angular/router';
34
import { RouterTestingModule } from '@angular/router/testing';
45
import { IconType } from '@hypertrace/assets-library';
6+
import { APP_TITLE } from '@hypertrace/common';
57
import { NavItemType } from '@hypertrace/components';
68
import { patchRouterNavigateForTest } from '@hypertrace/test-utils';
79
import { createServiceFactory, mockProvider, SpectatorService } from '@ngneat/spectator/jest';
@@ -16,7 +18,10 @@ import {
1618
describe('Navigation Service', () => {
1719
const firstChildRouteConfig = {
1820
path: 'child',
19-
children: []
21+
children: [],
22+
data: {
23+
title: 'child1'
24+
}
2025
};
2126
const defaultChildRouteConfig = {
2227
path: '**',
@@ -44,7 +49,11 @@ describe('Navigation Service', () => {
4449

4550
const buildService = createServiceFactory({
4651
service: NavigationService,
47-
providers: [mockProvider(Location)],
52+
providers: [
53+
mockProvider(Location),
54+
mockProvider(Title, { setTitle: jest.fn().mockReturnValue(undefined) }),
55+
{ provide: APP_TITLE, useValue: 'defaultAppTitle' }
56+
],
4857
imports: [
4958
RouterTestingModule.withRoutes([
5059
{
@@ -318,4 +327,12 @@ describe('Navigation Service', () => {
318327
features: ['test-feature']
319328
});
320329
});
330+
331+
test('setting title should work as expected', () => {
332+
router.navigate(['root', 'child']);
333+
expect(spectator.inject(Title).setTitle).toHaveBeenCalledWith('defaultAppTitle | child1');
334+
335+
router.navigate(['root']);
336+
expect(spectator.inject(Title).setTitle).toHaveBeenCalledWith('defaultAppTitle');
337+
});
321338
});

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

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Location, PlatformLocation } from '@angular/common';
2-
import { Injectable, Type } from '@angular/core';
2+
import { Inject, Injectable, Optional, Type } from '@angular/core';
3+
import { Title } from '@angular/platform-browser';
34
import {
45
ActivatedRoute,
56
ActivatedRouteSnapshot,
@@ -16,10 +17,10 @@ import {
1617
import { NavItemConfig, NavItemType } from '@hypertrace/components';
1718
import { uniq } from 'lodash-es';
1819
import { from, Observable, of } from 'rxjs';
19-
import { distinctUntilChanged, filter, map, share, skip, startWith, switchMap, take } from 'rxjs/operators';
20+
import { distinctUntilChanged, filter, map, share, skip, startWith, switchMap, take, tap } from 'rxjs/operators';
2021
import { isEqualIgnoreFunctions, throwIfNil } from '../utilities/lang/lang-utils';
2122
import { Dictionary } from '../utilities/types/types';
22-
import { HtRoute } from './ht-route';
23+
import { APP_TITLE, HtRoute } from './ht-route';
2324

2425
@Injectable({ providedIn: 'root' })
2526
export class NavigationService {
@@ -34,11 +35,22 @@ export class NavigationService {
3435
public constructor(
3536
private readonly router: Router,
3637
private readonly location: Location,
37-
private readonly platformLocation: PlatformLocation
38+
private readonly platformLocation: PlatformLocation,
39+
private readonly titleService: Title,
40+
@Optional() @Inject(APP_TITLE) private readonly appTitle: string
3841
) {
3942
this.event$(RoutesRecognized)
4043
.pipe(skip(1), take(1))
4144
.subscribe(() => (this.isFirstNavigation = false));
45+
46+
this.navigation$
47+
.pipe(
48+
switchMap(() => this.getCurrentActivatedRoute().data),
49+
tap(routeData =>
50+
this.titleService.setTitle(routeData.title ? `${this.appTitle} | ${routeData.title}` : this.appTitle)
51+
)
52+
)
53+
.subscribe();
4254
}
4355

4456
public addQueryParametersToUrl(newParams: QueryParamObject): Observable<boolean> {

src/app/config.module.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { NgModule } from '@angular/core';
2-
import { ALTERNATE_COLOR_PALETTES, DEFAULT_COLOR_PALETTE, GLOBAL_HEADER_HEIGHT } from '@hypertrace/common';
2+
import { ALTERNATE_COLOR_PALETTES, APP_TITLE, DEFAULT_COLOR_PALETTE, GLOBAL_HEADER_HEIGHT } from '@hypertrace/common';
33
import { GRAPHQL_OPTIONS } from '@hypertrace/graphql-client';
44
import { ENTITY_METADATA, RED_COLOR_PALETTE } from '@hypertrace/observability';
55
import { environment } from '../environments/environment';
@@ -38,6 +38,10 @@ import { FeatureResolverModule } from './shared/feature-resolver/feature-resolve
3838
{
3939
provide: ENTITY_METADATA,
4040
useValue: entityMetadata
41+
},
42+
{
43+
provide: APP_TITLE,
44+
useValue: environment.appTitle
4145
}
4246
]
4347
})

src/environments/environment.prod.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export const environment = {
22
production: true,
3-
graphqlUri: '/graphql'
3+
graphqlUri: '/graphql',
4+
appTitle: 'Hypertrace'
45
};

src/environments/environment.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55

66
export const environment = {
77
production: false,
8-
graphqlUri: 'http://localhost:2020/graphql'
8+
graphqlUri: 'http://localhost:2020/graphql',
9+
appTitle: 'Hypertrace'
910
};
1011

1112
/*

src/index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
<head>
44
<meta charset="utf-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
6-
<title>Hypertrace</title>
76
<base href="/" />
87

98
<meta name="viewport" content="width=device-width, initial-scale=1" />

0 commit comments

Comments
 (0)