Skip to content

Commit 00b0651

Browse files
committed
feat(portal): refactor to use dynamic portal navigation items and update related services
1 parent e5f375e commit 00b0651

File tree

14 files changed

+255
-137
lines changed

14 files changed

+255
-137
lines changed

gravitee-apim-portal-webui-next/src/app/app.component.spec.ts

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@
1616
import { HarnessLoader } from '@angular/cdk/testing';
1717
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
1818
import { provideHttpClientTesting } from '@angular/common/http/testing';
19-
import { Injectable } from '@angular/core';
19+
import { signal } from '@angular/core';
2020
import { ComponentFixture, TestBed } from '@angular/core/testing';
2121
import { MatButtonHarness } from '@angular/material/button/testing';
2222

2323
import { AppComponent } from './app.component';
24-
import { PortalMenuLinksService } from '../services/portal-menu-links.service';
24+
import { PortalNavigationItem } from '../entities/portal-navigation/portal-navigation';
25+
import { PortalNavigationItemsService } from '../services/portal-navigation-items.service';
2526
import { AppTestingModule } from '../testing/app-testing.module';
2627

2728
describe('AppComponent', () => {
@@ -45,37 +46,36 @@ describe('AppComponent', () => {
4546
});
4647

4748
describe('custom links', () => {
48-
@Injectable()
49-
class PortalMenuLinksServiceStub {
50-
links = () => [
49+
beforeEach(async () => {
50+
const mockItems: PortalNavigationItem[] = [
5151
{
52-
id: 'link-id-1',
53-
type: 'external',
54-
name: 'link-name-1',
55-
target: 'link-target-1',
56-
order: 1,
52+
id: 'l1',
53+
organizationId: 'org1',
54+
environmentId: 'env1',
55+
title: 'link-name-1',
56+
type: 'LINK',
57+
area: 'TOP_NAVBAR',
58+
order: 0,
59+
url: '/link1',
5760
},
5861
{
59-
id: 'link-id-2',
60-
type: 'external',
61-
name: 'link-name-2',
62-
target: 'link-target-2',
63-
order: 2,
62+
id: 'l2',
63+
organizationId: 'org1',
64+
environmentId: 'env1',
65+
title: 'link-name-2',
66+
type: 'LINK',
67+
area: 'TOP_NAVBAR',
68+
order: 1,
69+
url: '/link2',
6470
},
6571
];
66-
}
6772

68-
beforeEach(async () => {
6973
await TestBed.configureTestingModule({
7074
imports: [AppComponent, AppTestingModule],
71-
providers: [
72-
{
73-
provide: PortalMenuLinksService,
74-
useClass: PortalMenuLinksServiceStub,
75-
},
76-
],
75+
providers: [provideHttpClientTesting(), { provide: PortalNavigationItemsService, useValue: { topNavbar: signal(mockItems) } }],
7776
}).compileComponents();
7877
fixture = TestBed.createComponent(AppComponent);
78+
fixture.detectChanges();
7979
harnessLoader = TestbedHarnessEnvironment.loader(fixture);
8080
});
8181
it('should show custom links', async () => {

gravitee-apim-portal-webui-next/src/app/app.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { FooterComponent } from '../components/footer/footer.component';
2222
import { NavBarComponent } from '../components/nav-bar/nav-bar.component';
2323
import { ConfigService } from '../services/config.service';
2424
import { CurrentUserService } from '../services/current-user.service';
25-
import { PortalMenuLinksService } from '../services/portal-menu-links.service';
25+
import { PortalNavigationItemsService } from '../services/portal-navigation-items.service';
2626
import { ThemeService } from '../services/theme.service';
2727

2828
@Component({
@@ -35,7 +35,7 @@ export class AppComponent {
3535
currentUser = inject(CurrentUserService).user;
3636
logo = inject(ThemeService).logo;
3737
favicon = inject(ThemeService).favicon;
38-
customLinks = inject(PortalMenuLinksService).links;
38+
customLinks = inject(PortalNavigationItemsService).topNavbar;
3939
private siteTitle: string;
4040

4141
constructor(

gravitee-apim-portal-webui-next/src/app/app.config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ import { httpRequestInterceptor } from '../interceptors/http-request.interceptor
3030
import { AuthService } from '../services/auth.service';
3131
import { ConfigService } from '../services/config.service';
3232
import { CurrentUserService } from '../services/current-user.service';
33-
import { PortalMenuLinksService } from '../services/portal-menu-links.service';
33+
import { PortalNavigationItemsService } from '../services/portal-navigation-items.service';
3434
import { ThemeService } from '../services/theme.service';
3535

3636
function initApp(
3737
authService: AuthService,
3838
configService: ConfigService,
3939
themeService: ThemeService,
4040
currentUserService: CurrentUserService,
41-
portalMenuLinksService: PortalMenuLinksService,
41+
portalNavigationItemsService: PortalNavigationItemsService,
4242
router: Router,
4343
): () => Observable<unknown> {
4444
return () =>
@@ -47,7 +47,7 @@ function initApp(
4747
combineLatest([
4848
themeService.loadTheme(),
4949
configService.loadConfiguration(),
50-
portalMenuLinksService.loadCustomLinks(),
50+
portalNavigationItemsService.loadTopNavBarItems(),
5151
authService.load().pipe(switchMap(_ => currentUserService.loadUser())),
5252
]),
5353
),
@@ -70,7 +70,7 @@ export const appConfig: ApplicationConfig = {
7070
inject(ConfigService),
7171
inject(ThemeService),
7272
inject(CurrentUserService),
73-
inject(PortalMenuLinksService),
73+
inject(PortalNavigationItemsService),
7474
inject(Router),
7575
);
7676
return initializerFn();

gravitee-apim-portal-webui-next/src/app/log-in/log-in.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import { AuthService } from '../../services/auth.service';
3333
import { ConfigService } from '../../services/config.service';
3434
import { CurrentUserService } from '../../services/current-user.service';
3535
import { IdentityProviderService } from '../../services/identity-provider.service';
36-
import { PortalMenuLinksService } from '../../services/portal-menu-links.service';
36+
import { PortalNavigationItemsService } from '../../services/portal-navigation-items.service';
3737

3838
@Component({
3939
selector: 'app-log-in',
@@ -68,7 +68,7 @@ export class LogInComponent {
6868
constructor(
6969
private readonly authService: AuthService,
7070
private readonly currentUserService: CurrentUserService,
71-
private readonly portalMenuLinksService: PortalMenuLinksService,
71+
private readonly portalNavigationItemsService: PortalNavigationItemsService,
7272
private readonly router: Router,
7373
private readonly destroyRef: DestroyRef,
7474
) {}
@@ -78,7 +78,7 @@ export class LogInComponent {
7878
.login(this.logInForm.value.username, this.logInForm.value.password)
7979
.pipe(
8080
switchMap(_ => this.currentUserService.loadUser()),
81-
switchMap(_ => this.portalMenuLinksService.loadCustomLinks()),
81+
switchMap(_ => this.portalNavigationItemsService.loadTopNavBarItems()),
8282
tap(_ => this.router.navigate([this.redirectUrl()])),
8383
takeUntilDestroyed(this.destroyRef),
8484
)

gravitee-apim-portal-webui-next/src/app/log-out/log-out.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { switchMap, tap } from 'rxjs';
2020

2121
import { AuthService } from '../../services/auth.service';
2222
import { CurrentUserService } from '../../services/current-user.service';
23-
import { PortalMenuLinksService } from '../../services/portal-menu-links.service';
23+
import { PortalNavigationItemsService } from '../../services/portal-navigation-items.service';
2424

2525
@Component({
2626
selector: 'app-log-out',
@@ -33,7 +33,7 @@ export class LogOutComponent implements OnInit {
3333
constructor(
3434
private readonly authService: AuthService,
3535
private readonly currentUserService: CurrentUserService,
36-
private readonly portalMenuLinksService: PortalMenuLinksService,
36+
private readonly portalNavigationItemsService: PortalNavigationItemsService,
3737
private readonly router: Router,
3838
) {}
3939

@@ -43,7 +43,7 @@ export class LogOutComponent implements OnInit {
4343
.logout()
4444
.pipe(
4545
tap(_ => this.currentUserService.clear()),
46-
switchMap(_ => this.portalMenuLinksService.loadCustomLinks()),
46+
switchMap(_ => this.portalNavigationItemsService.loadTopNavBarItems()),
4747
tap(_ => this.router.navigate([''])),
4848
takeUntilDestroyed(this.destroyRef),
4949
)

gravitee-apim-portal-webui-next/src/components/nav-bar/desktop-nav-bar/desktop-nav-bar.component.html

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,23 @@
1919
<app-nav-bar-button i18n="@@catalog" [path]="['catalog']">Catalog</app-nav-bar-button>
2020
<app-nav-bar-button i18n="@@guides" [path]="['guides']">Guides</app-nav-bar-button>
2121
@for (link of customLinks(); track link.id) {
22-
<a
23-
[href]="link.target"
24-
mat-stroked-button
25-
color="primary"
26-
class="menu-items__custom_link"
27-
[target]="link.type === 'external' ? '_blank' : ''">
28-
{{ link.name }}
29-
</a>
22+
@switch (link.type) {
23+
@case ('LINK') {
24+
<a [href]="[link.url]" mat-stroked-button color="primary" class="menu-items__custom_link">
25+
{{ link.title }}
26+
</a>
27+
}
28+
@case ('PAGE') {
29+
<a [routerLink]="['/page', link.portalPageContentId]" mat-stroked-button color="primary" class="menu-items__custom_link">
30+
{{ link.title }}
31+
</a>
32+
}
33+
@case ('FOLDER') {
34+
<a [routerLink]="['/folder', link.id]" mat-stroked-button color="primary" class="menu-items__custom_link">
35+
{{ link.title }}
36+
</a>
37+
}
38+
}
3039
}
3140
</div>
3241

gravitee-apim-portal-webui-next/src/components/nav-bar/desktop-nav-bar/desktop-nav-bar.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ import { MatAnchor, MatButton } from '@angular/material/button';
1818
import { RouterLink } from '@angular/router';
1919
import { isEmpty } from 'lodash';
2020

21+
import { PortalNavigationItem } from '../../../entities/portal-navigation/portal-navigation';
2122
import { User } from '../../../entities/user/user';
22-
import { PortalMenuLink } from '../../../services/portal-menu-links.service';
2323
import { UserAvatarComponent } from '../../user-avatar/user-avatar.component';
2424
import { NavBarButtonComponent } from '../nav-bar-button/nav-bar-button.component';
2525

@@ -31,7 +31,7 @@ import { NavBarButtonComponent } from '../nav-bar-button/nav-bar-button.componen
3131
})
3232
export class DesktopNavBarComponent {
3333
currentUser: InputSignal<User> = input({});
34-
customLinks: InputSignal<PortalMenuLink[]> = input<PortalMenuLink[]>([]);
34+
customLinks: InputSignal<PortalNavigationItem[]> = input<PortalNavigationItem[]>([]);
3535
protected isLoggedIn = computed(() => {
3636
return !isEmpty(this.currentUser());
3737
});

gravitee-apim-portal-webui-next/src/components/nav-bar/mobile-nav-bar/mobile-nav-bar.component.html

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,23 @@
3838
<a class="mobile-menu__link" i18n="@@catalog" [routerLink]="['catalog']" routerLinkActive="active" (click)="closeMenu()">Catalog</a>
3939
<a class="mobile-menu__link" i18n="@@guides" [routerLink]="['guides']" routerLinkActive="active" (click)="closeMenu()">Guides</a>
4040
@for (link of customLinks(); track link.id) {
41-
<a class="mobile-menu__link" [href]="link.target" [attr.target]="link.type === 'external' ? '_blank' : null" (click)="closeMenu()">
42-
{{ link.name }}
43-
</a>
41+
@switch (link.type) {
42+
@case ('PAGE') {
43+
<a class="mobile-menu__link" [routerLink]="['/page', link.portalPageContentId]" routerLinkActive="active" (click)="closeMenu()">
44+
{{ link.title }}
45+
</a>
46+
}
47+
@case ('FOLDER') {
48+
<a class="mobile-menu__link" [routerLink]="['/folder', link.id]" routerLinkActive="active" (click)="closeMenu()">
49+
{{ link.title }}
50+
</a>
51+
}
52+
@case ('LINK') {
53+
<a class="mobile-menu__link" [href]="link.url" [attr.target]="'_blank'" (click)="closeMenu()">
54+
{{ link.title }}
55+
</a>
56+
}
57+
}
4458
}
4559
<div class="mobile-menu__hr"></div>
4660

gravitee-apim-portal-webui-next/src/components/nav-bar/mobile-nav-bar/mobile-nav-bar.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ import { isEmpty } from 'lodash';
2222
import { catchError, map } from 'rxjs';
2323
import { of } from 'rxjs/internal/observable/of';
2424

25+
import { PortalNavigationItem } from '../../../entities/portal-navigation/portal-navigation';
2526
import { User } from '../../../entities/user/user';
26-
import { PortalMenuLink } from '../../../services/portal-menu-links.service';
2727
import { PortalService } from '../../../services/portal.service';
2828

2929
@Component({
@@ -34,7 +34,7 @@ import { PortalService } from '../../../services/portal.service';
3434
})
3535
export class MobileNavBarComponent {
3636
currentUser: InputSignal<User> = input({});
37-
customLinks: InputSignal<PortalMenuLink[]> = input<PortalMenuLink[]>([]);
37+
customLinks: InputSignal<PortalNavigationItem[]> = input<PortalNavigationItem[]>([]);
3838
hasHomepage = toSignal(
3939
inject(PortalService)
4040
.getPortalHomepages()

gravitee-apim-portal-webui-next/src/components/nav-bar/nav-bar.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ import { Component, computed, inject, input, InputSignal } from '@angular/core';
1717
import { MatButtonModule } from '@angular/material/button';
1818
import { isEmpty } from 'lodash';
1919

20+
import { PortalNavigationItem } from '../../entities/portal-navigation/portal-navigation';
2021
import { User } from '../../entities/user/user';
2122
import { ObservabilityBreakpointService } from '../../services/observability-breakpoint.service';
22-
import { PortalMenuLink } from '../../services/portal-menu-links.service';
2323
import { CompanyTitleComponent } from '../company-title/company-title.component';
2424
import { DesktopNavBarComponent } from './desktop-nav-bar/desktop-nav-bar.component';
2525
import { MobileNavBarComponent } from './mobile-nav-bar/mobile-nav-bar.component';
@@ -31,7 +31,7 @@ import { MobileNavBarComponent } from './mobile-nav-bar/mobile-nav-bar.component
3131
styleUrls: ['./nav-bar.component.scss'],
3232
})
3333
export class NavBarComponent {
34-
customLinks: InputSignal<PortalMenuLink[]> = input<PortalMenuLink[]>([]);
34+
customLinks: InputSignal<PortalNavigationItem[]> = input<PortalNavigationItem[]>([]);
3535
currentUser: InputSignal<User> = input({});
3636
forceLogin: InputSignal<boolean> = input(false);
3737
logo: InputSignal<string> = input('');

0 commit comments

Comments
 (0)