Skip to content

Commit

Permalink
feat(admin-ui): Add support for tabs on custom UI routes
Browse files Browse the repository at this point in the history
  • Loading branch information
rein1410 authored Jul 15, 2024
1 parent 65b4f3c commit 26b4ea5
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ export default [
registerRouteComponent({
component: TestComponent,
title: 'Test',
locationId: 'my-location-id'
// highlight-next-line
breadcrumb: 'Test',
}),
Expand Down
16 changes: 16 additions & 0 deletions docs/docs/guides/extending-the-admin-ui/page-tabs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ export default [

![./ui-extensions-tabs.webp](./ui-extensions-tabs.webp)

If you want to add page tabs to a custom admin page, specify the `locationId` property:

```ts title="src/plugins/my-plugin/ui/routes.ts"
import { registerRouteComponent } from '@vendure/admin-ui/core';
import { TestComponent } from './components/test/test.component';

export default [
registerRouteComponent({
component: TestComponent,
title: 'Test',
// highlight-next-line
locationId: 'my-location-id'
}),
];
```

:::note
Currently it is only possible to define new tabs using Angular components.
:::
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import MemberDescription from '@site/src/components/MemberDescription';

## registerRouteComponent

<GenerationInfo sourceFile="packages/admin-ui/src/lib/core/src/extension/register-route-component.ts" sourceLine="77" packageName="@vendure/admin-ui" />
<GenerationInfo sourceFile="packages/admin-ui/src/lib/core/src/extension/register-route-component.ts" sourceLine="79" packageName="@vendure/admin-ui" />

Registers an Angular standalone component to be rendered in a route.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, inject, InjectionToken } from '@angular/core';
import { Component, inject, InjectionToken, Input } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { notNullOrUndefined } from '@vendure/common/lib/shared-utils';
import { combineLatest, Observable, of, switchMap } from 'rxjs';
Expand All @@ -7,6 +7,9 @@ import { BreadcrumbValue } from '../../providers/breadcrumb/breadcrumb.service';
import { SharedModule } from '../../shared/shared.module';
import { PageMetadataService } from '../providers/page-metadata.service';
import { AngularRouteComponentOptions } from '../types';
import { HeaderTab } from '../../shared/components/page-header-tabs/page-header-tabs.component';
import { PageService } from '../../providers/page/page.service';
import { PageLocationId } from '../../common/component-registry-types';

export const ROUTE_COMPONENT_OPTIONS = new InjectionToken<AngularRouteComponentOptions>(
'ROUTE_COMPONENT_OPTIONS',
Expand All @@ -17,6 +20,8 @@ export const ROUTE_COMPONENT_OPTIONS = new InjectionToken<AngularRouteComponentO
template: `
<vdr-page-header>
<vdr-page-title *ngIf="title$ | async as title" [title]="title"></vdr-page-title>
<vdr-page-header-description *ngIf="description">{{ description }}</vdr-page-header-description>
<vdr-page-header-tabs *ngIf="headerTabs.length > 1" [tabs]="headerTabs"></vdr-page-header-tabs>
</vdr-page-header>
<vdr-page-body><ng-content /></vdr-page-body>
`,
Expand All @@ -26,8 +31,14 @@ export const ROUTE_COMPONENT_OPTIONS = new InjectionToken<AngularRouteComponentO
})
export class RouteComponent {
protected title$: Observable<string | undefined>;
@Input() protected locationId: PageLocationId;
@Input() protected description: string;
headerTabs: HeaderTab[] = [];

constructor(private route: ActivatedRoute) {
constructor(
private route: ActivatedRoute,
private pageService: PageService,
) {
const breadcrumbLabel$ = this.route.data.pipe(
switchMap(data => {
if (data.breadcrumb instanceof Observable) {
Expand All @@ -53,5 +64,14 @@ export class RouteComponent {
this.title$ = combineLatest([inject(ROUTE_COMPONENT_OPTIONS).title$, breadcrumbLabel$]).pipe(
map(([title, breadcrumbLabel]) => title ?? breadcrumbLabel),
);

this.locationId = this.route.snapshot.data.locationId;
this.description = this.route.snapshot.data.description;
this.headerTabs = this.pageService.getPageTabs(this.locationId).map(tab => ({
id: tab.tab,
label: tab.tab,
icon: tab.tabIcon,
route: tab.route ? [tab.route] : ['./'],
}));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export type RegisterRouteComponentOptions<
> = {
component: Type<Component> | Component;
title?: string;
locationId?: string;
description?: string;
breadcrumb?: BreadcrumbValue;
path?: string;
query?: T;
Expand Down Expand Up @@ -81,7 +83,7 @@ export function registerRouteComponent<
Field extends keyof ResultOf<T>,
R extends Field,
>(options: RegisterRouteComponentOptions<Component, Entity, T, Field, R>) {
const { query, entityKey, variables, getBreadcrumbs } = options;
const { query, entityKey, variables, getBreadcrumbs, locationId, description } = options;

const breadcrumbSubject$ = new BehaviorSubject<BreadcrumbValue>(options.breadcrumb ?? '');
const titleSubject$ = new BehaviorSubject<string | undefined>(options.title);
Expand Down Expand Up @@ -129,6 +131,8 @@ export function registerRouteComponent<
...(options.routeConfig ?? {}),
resolve: { ...(resolveFn ? { detail: resolveFn } : {}), ...(options.routeConfig?.resolve ?? {}) },
data: {
locationId,
description,
breadcrumb: breadcrumbSubject$,
...(options.routeConfig?.data ?? {}),
...(getBreadcrumbs && query && entityKey
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { addNavMenuSection } from '@vendure/admin-ui/core';
import { PageLocationId, addNavMenuSection, registerPageTab } from '@vendure/admin-ui/core';
import { AngularUiComponent } from './angular-components/angular-ui/angular-ui.component';

export default [
addNavMenuSection({
Expand All @@ -17,4 +18,33 @@ export default [
},
],
}),
//Testing page tabs on custom angular components
registerPageTab({
location: 'angular-ui' as PageLocationId,
tab: 'Example Tab 1',
route: '/extensions/ui-library/angular-ui',
tabIcon: 'star',
component: AngularUiComponent,
}),
registerPageTab({
location: 'angular-ui' as PageLocationId,
tab: 'Example Tab 2',
route: '/extensions/ui-library/angular-ui2',
tabIcon: 'star',
component: AngularUiComponent,
}),
registerPageTab({
location: 'react-ui' as PageLocationId,
tab: 'Example Tab 1',
route: '/extensions/ui-library/angular-ui',
tabIcon: 'star',
component: AngularUiComponent,
}),
registerPageTab({
location: 'react-ui' as PageLocationId,
tab: 'Example Tab 2',
route: '/extensions/ui-library/angular-ui2',
tabIcon: 'star',
component: AngularUiComponent,
}),
];
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,22 @@ export default [
path: 'react-ui',
component: ReactUi,
title: 'React UI',
description: "Test description",
locationId: "react-ui"
}),
registerRouteComponent({
path: 'angular-ui',
component: AngularUiComponent,
title: 'Angular UI',
locationId: "angular-ui",
description: "Test description 2"
}),
];
//Test page tabs on angular components
registerRouteComponent({
path: 'angular-ui2',
component: AngularUiComponent,
title: 'Angular UI 2',
locationId: "angular-ui",
description: "Test description 2"
})
]

0 comments on commit 26b4ea5

Please sign in to comment.