@genesislcap/blank-app-seed 3.27.3 → 3.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/.genx/configure.js +7 -2
  2. package/.genx/package.json +1 -1
  3. package/.genx/templates/angular/chart.hbs +15 -20
  4. package/.genx/templates/angular/component/component.hbs +4 -2
  5. package/.genx/templates/angular/route.template.hbs +9 -3
  6. package/.genx/templates/angular/tabsPanel.hbs +5 -0
  7. package/.genx/utils/formatRouteData.js +6 -3
  8. package/.genx/utils/registerPartials.js +10 -1
  9. package/.gitignore +4 -0
  10. package/CHANGELOG.md +7 -0
  11. package/client-tmp/angular/angular.json +2 -1
  12. package/client-tmp/angular/globals.d.ts +1 -0
  13. package/client-tmp/angular/package.json +26 -8
  14. package/client-tmp/angular/src/app/app.component.ts +45 -6
  15. package/client-tmp/angular/src/app/app.config.ts +0 -13
  16. package/client-tmp/angular/src/app/app.module.ts +17 -4
  17. package/client-tmp/angular/src/app/guards/auth.guard.ts +5 -12
  18. package/client-tmp/angular/src/app/guards/chained.guard.ts +33 -0
  19. package/client-tmp/angular/src/app/guards/connection.guard.ts +21 -0
  20. package/client-tmp/angular/src/app/guards/permissions.guard.ts +6 -8
  21. package/client-tmp/angular/src/app/layouts/base.layout.ts +1 -5
  22. package/client-tmp/angular/src/app/layouts/default/default.layout.css +1 -0
  23. package/client-tmp/angular/src/app/layouts/default/default.layout.html +5 -6
  24. package/client-tmp/angular/src/app/layouts/default/default.layout.ts +9 -4
  25. package/client-tmp/angular/src/app/services/route.service.ts +95 -0
  26. package/client-tmp/angular/src/app/share/foundation-login.ts +5 -3
  27. package/client-tmp/angular/src/app/share/genesis-components.ts +48 -21
  28. package/client-tmp/angular/src/app/store/index.ts +1 -0
  29. package/client-tmp/angular/src/app/store/store.ts +34 -0
  30. package/client-tmp/angular/src/declaration.d.ts +7 -1
  31. package/client-tmp/angular/src/environments/environment.prod.ts +1 -0
  32. package/client-tmp/angular/src/environments/environment.ts +2 -1
  33. package/client-tmp/angular/src/main.ts +14 -3
  34. package/client-tmp/angular/src/pbc/README.md +7 -0
  35. package/client-tmp/angular/src/pbc/container.ts +40 -0
  36. package/client-tmp/angular/src/pbc/elementsRenderer.ts +57 -0
  37. package/client-tmp/angular/src/pbc/utils.ts +121 -0
  38. package/client-tmp/angular/tsconfig.app.json +2 -1
  39. package/client-tmp/angular/tsconfig.spec.json +3 -2
  40. package/client-tmp/angular/webpack.shared.config.js +17 -4
  41. package/package.json +1 -1
  42. package/client-tmp/angular/src/app/app-routing.module.ts +0 -40
  43. package/client-tmp/angular/src/app/services/auth.service.ts +0 -22
  44. package/client-tmp/angular/src/app/types/menu.ts +0 -8
@@ -21,8 +21,13 @@ module.exports = async (data, utils) => {
21
21
  data.versions = versions;
22
22
 
23
23
  registerPartials(utils, data.framework);
24
-
25
- data.routes = data.routes.filter(validateRoute).map(formatRouteData);
24
+ const formatRouteDataForFramework = formatRouteData.bind(
25
+ this,
26
+ data.framework,
27
+ );
28
+ data.routes = data.routes
29
+ .filter(validateRoute)
30
+ .map(formatRouteDataForFramework);
26
31
 
27
32
  const FDC3EventHandlersEnabled = data.routes.find(
28
33
  (route) => route.FDC3EventHandlersEnabled,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/blank-app-seed-config",
3
3
  "description": "Genesis Blank App Seed Configuration",
4
- "version": "3.27.3",
4
+ "version": "3.28.0",
5
5
  "license": "Apache-2.0",
6
6
  "scripts": {
7
7
  "lint": "eslint .",
@@ -1,21 +1,16 @@
1
- <section style="height: 100%; width: 100%;">
2
- <ng-container *ngIf="hasUserPermission('{{config.permissions.viewRight}}'); else notPermitted{{ config.index }}">
3
- <rapid-g2plot-chart
4
- type="{{ config.type }}"
5
- [config]="chartConfig"
6
- >
7
- <chart-datasource
8
- resourceName="{{ config.resourceName }}"
9
- server-fields="{{ config.xField }} {{ config.yField }}"
10
- ></chart-datasource>
11
- </rapid-g2plot-chart>
12
- </ng-container>
1
+ <rapid-g2plot-chart
2
+ type="{{ config.type }}"
3
+ [config]="chartConfig"
4
+ [ngStyle]="hasUserPermission('{{config.permissions.viewRight}}') ? { width: '100%', height: '100%' } : { display: 'none' }"
5
+ >
6
+ <chart-datasource
7
+ resourceName="{{ config.resourceName }}"
8
+ server-fields="{{ config.xField }} {{ config.yField }}"
9
+ ></chart-datasource>
10
+ </rapid-g2plot-chart>
13
11
 
14
- <ng-template #notPermitted{{ config.index }}>
15
- <app-error-message
16
- style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center;"
17
- elementType="h3"
18
- message="You do not have access to view this component.">
19
- </app-error-message>
20
- </ng-template>
21
- </section>
12
+ <app-error-message
13
+ [ngStyle]="!hasUserPermission('{{config.permissions.viewRight}}') ? { width: '100%', height: '100%', display: 'flex', 'justify-content': 'center', 'align-items': 'center' } : { display: 'none' }"
14
+ elementType="h3"
15
+ message="You do not have access to view this component.">
16
+ </app-error-message>
@@ -1,8 +1,10 @@
1
1
  import { Component, Input, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import { getUser } from '@genesislcap/foundation-user';
4
- import { GridOptionsConfig } from "@genesislcap/rapid-grid-pro";
5
4
  import { getViewUpdateRightComponent } from '../../../utils';
5
+ {{#if tile.config.gridOptions}}
6
+ import { GridOptionsConfig } from "@genesislcap/rapid-grid-pro";
7
+ {{/if}}
6
8
  {{#if tile.config.createFormUiSchema}}
7
9
  import { createFormSchema } from './{{kebabCase tile.title}}.create.form.schema';
8
10
  {{/if}}
@@ -37,7 +39,7 @@ export class {{pascalCase tile.componentName}} {
37
39
  columnDefs = columnDefs;{{/if}}{{#if tile.config.gridOptions}}
38
40
  gridOptions = gridOptions as GridOptionsConfig;{{/if}}{{#if tile.config.reqrep}}
39
41
  reqrep = { pollingInterval: 5000 };{{/if}}{{#if tile.config.type}}
40
- chartConfig = { {{#ifEquals this.config.type 'pie'}}
42
+ chartConfig = { {{#ifEquals tile.config.type 'pie'}}
41
43
  "radius": 0.75,
42
44
  "angleField": "value",
43
45
  "colorField": "groupBy",{{else}}
@@ -1,7 +1,13 @@
1
1
  {{#if route.tiles}}
2
- <rapid-layout [auto-save-key]="environment.production ? '{{route.layoutKey}}' : null">
3
- {{> (lookup ./route 'layoutType') }}
4
- </rapid-layout>
2
+ <rapid-flex-layout>
3
+ <rapid-tabs>
4
+ {{#each route.tiles}}
5
+ <rapid-tab slot="tab">{{this.title}}</rapid-tab>
6
+ {{/each}}
7
+
8
+ {{> (lookup ./route 'layoutType') }}
9
+ </rapid-tabs>
10
+ </rapid-flex-layout>
5
11
  {{else}}
6
12
  <!-- insert template code here -->
7
13
  Welcome to {{sentenceCase route.name}}
@@ -0,0 +1,5 @@
1
+ {{#each route.tiles}}
2
+ <rapid-tab-panel slot="tabpanel">
3
+ <app-{{kebabCase this.componentName}}></app-{{kebabCase this.componentName}}>
4
+ </rapid-tab-panel>
5
+ {{/each}}
@@ -4,11 +4,14 @@ const {
4
4
  } = require('./gridSerializers');
5
5
  const formatJSONValue = require('./formatJSONValue');
6
6
  const getLayoutType = require('./getLayoutType');
7
- const { COMPONENT_TYPE } = require('../static');
7
+ const { COMPONENT_TYPE, FRAMEWORK_ANGULAR_ALIAS } = require('../static');
8
8
 
9
- const formatRouteData = (route) => {
9
+ const formatRouteData = (framework, route) => {
10
10
  const layoutKey = route?.layoutKey || `${route.name}_${Date.now()}`;
11
- const layoutType = route?.layoutType || getLayoutType(route);
11
+ const layoutType =
12
+ framework === FRAMEWORK_ANGULAR_ALIAS
13
+ ? 'tabs-panel'
14
+ : route?.layoutType || getLayoutType(route);
12
15
 
13
16
  const FDC3ClickCategory = 'fdc3';
14
17
  const FDC3EventHandlersEnabled = !!route.tiles?.find(
@@ -1,10 +1,19 @@
1
1
  const { resolve } = require('node:path');
2
- const { DIR_TEMPLATE_BY_FRAMEWORK } = require('../static');
2
+ const {
3
+ DIR_TEMPLATE_BY_FRAMEWORK,
4
+ FRAMEWORK_ANGULAR_ALIAS,
5
+ } = require('../static');
3
6
 
4
7
  const registerPartials = ({ registerPartial }, framework) => {
5
8
  // It can be reverted after adding changes for angular
6
9
  const sourceTemplateDir = `../${DIR_TEMPLATE_BY_FRAMEWORK[framework]}`;
7
10
 
11
+ if (framework === FRAMEWORK_ANGULAR_ALIAS) {
12
+ registerPartial(
13
+ 'tabs-panel',
14
+ resolve(__dirname, `${sourceTemplateDir}/tabsPanel.hbs`),
15
+ );
16
+ }
8
17
  registerPartial(
9
18
  'grid-layout',
10
19
  resolve(__dirname, `${sourceTemplateDir}/gridLayout.hbs`),
package/.gitignore CHANGED
@@ -26,6 +26,9 @@ pids
26
26
  *.sln
27
27
  *.sw?
28
28
  .DS_Store
29
+ .idea/gradle.xml
30
+ .idea/misc.xml
31
+ .idea/vcs.xml
29
32
 
30
33
  # Development
31
34
  target/
@@ -36,6 +39,7 @@ build/
36
39
  *.ignore
37
40
  *~
38
41
  .gradle
42
+ client/.angular
39
43
  client/bootstrapDone
40
44
  .husky/.gitignore
41
45
  build-cache/
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.28.0](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.27.3...v3.28.0) (2024-07-29)
4
+
5
+
6
+ ### Features
7
+
8
+ * pbc support in angular [FUI-2065](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2065) (#289) 7662cde
9
+
3
10
  ## [3.27.3](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.27.2...v3.27.3) (2024-07-29)
4
11
 
5
12
 
@@ -66,7 +66,8 @@
66
66
  "vendorChunk": true,
67
67
  "extractLicenses": false,
68
68
  "sourceMap": true,
69
- "namedChunks": true
69
+ "namedChunks": true,
70
+ "preserveSymlinks": true
70
71
  }
71
72
  },
72
73
  "defaultConfiguration": "production"
@@ -1,6 +1,7 @@
1
1
  declare global {
2
2
  const API_HOST: string;
3
3
  const ENABLE_SSO: boolean;
4
+ const BUILDER: string;
4
5
  }
5
6
 
6
7
  export {};
@@ -77,20 +77,27 @@
77
77
  "@angular/platform-browser": "^18.0.4",
78
78
  "@angular/platform-browser-dynamic": "^18.0.4",
79
79
  "@angular/router": "^18.0.4",
80
+ "@genesislcap/foundation-comms": "{{versions.UI}}",
81
+ "@genesislcap/foundation-entity-management": "{{versions.UI}}",
82
+ "@genesislcap/foundation-events": "{{versions.UI}}",
80
83
  {{#if FDC3.includeDependencies}}
81
84
  "@genesislcap/foundation-fdc3": "{{versions.UI}}",
82
85
  {{/if}}
83
- "@genesislcap/foundation-comms": "{{versions.UI}}",
84
- "@genesislcap/foundation-login": "{{versions.UI}}",
85
- "@genesislcap/foundation-entity-management": "{{versions.UI}}",
86
+ "@genesislcap/foundation-forms": "{{versions.UI}}",
86
87
  "@genesislcap/foundation-header": "{{versions.UI}}",
88
+ "@genesislcap/foundation-layout": "{{versions.UI}}",
89
+ "@genesislcap/foundation-logger": "{{versions.UI}}",
90
+ "@genesislcap/foundation-login": "{{versions.UI}}",
91
+ "@genesislcap/foundation-shell": "{{versions.UI}}",
92
+ "@genesislcap/foundation-store": "{{versions.UI}}",
87
93
  "@genesislcap/foundation-ui": "{{versions.UI}}",
88
94
  "@genesislcap/foundation-utils": "{{versions.UI}}",
89
95
  "@genesislcap/foundation-user": "{{versions.UI}}",
96
+ "@genesislcap/foundation-zero": "{{versions.UI}}",
97
+ "@genesislcap/g2plot-chart": "{{versions.UI}}",
90
98
  "@genesislcap/rapid-design-system": "{{versions.UI}}",
91
99
  "@genesislcap/rapid-grid-pro": "{{versions.UI}}",
92
- "@genesislcap/foundation-layout": "{{versions.UI}}",
93
- "@genesislcap/g2plot-chart": "{{versions.UI}}",
100
+ "@genesislcap/web-core": "{{versions.UI}}",
94
101
  "numeral": "2.0.6",
95
102
  "tslib": "^2.3.0",
96
103
  "zone.js": "~0.14.3"
@@ -105,15 +112,26 @@
105
112
  "@angular/platform-browser-dynamic": "^18.0.4",
106
113
  "@angular/router": "^18.0.4",
107
114
  "@genesislcap/foundation-comms": "{{versions.UI}}",
108
- "@genesislcap/foundation-login": "{{versions.UI}}",
109
115
  "@genesislcap/foundation-entity-management": "{{versions.UI}}",
116
+ "@genesislcap/foundation-events": "{{versions.UI}}",
117
+ {{#if FDC3.includeDependencies}}
118
+ "@genesislcap/foundation-fdc3": "{{versions.UI}}",
119
+ {{/if}}
120
+ "@genesislcap/foundation-forms": "{{versions.UI}}",
110
121
  "@genesislcap/foundation-header": "{{versions.UI}}",
122
+ "@genesislcap/foundation-layout": "{{versions.UI}}",
123
+ "@genesislcap/foundation-logger": "{{versions.UI}}",
124
+ "@genesislcap/foundation-login": "{{versions.UI}}",
125
+ "@genesislcap/foundation-shell": "{{versions.UI}}",
126
+ "@genesislcap/foundation-store": "{{versions.UI}}",
111
127
  "@genesislcap/foundation-ui": "{{versions.UI}}",
128
+ "@genesislcap/foundation-utils": "{{versions.UI}}",
112
129
  "@genesislcap/foundation-user": "{{versions.UI}}",
130
+ "@genesislcap/foundation-zero": "{{versions.UI}}",
131
+ "@genesislcap/g2plot-chart": "{{versions.UI}}",
113
132
  "@genesislcap/rapid-design-system": "{{versions.UI}}",
114
133
  "@genesislcap/rapid-grid-pro": "{{versions.UI}}",
115
- "@genesislcap/foundation-layout": "{{versions.UI}}",
116
- "@genesislcap/g2plot-chart": "{{versions.UI}}",
134
+ "@genesislcap/web-core": "{{versions.UI}}",
117
135
  "numeral": "2.0.6",
118
136
  "tslib": "^2.3.0",
119
137
  "zone.js": "~0.14.3"
@@ -1,26 +1,28 @@
1
- import { Component, AfterViewInit } from '@angular/core';
1
+ import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit } from '@angular/core';
2
2
  import { Router, NavigationEnd } from '@angular/router';
3
3
  import getLayoutNameByRoute from './utils/getLayoutNameByRoute';
4
4
  import type { LayoutComponentName } from './types/layout';
5
5
  import { configureFoundationLogin } from './share/foundation-login';
6
+ import { registerComponents } from './share/genesis-components';
7
+ import { getStore } from './store';
8
+ import { customEventFactory, registerStylesTarget } from '../pbc/utils';
6
9
  {{#if FDC3.channels.length}}
7
10
  import { listenToChannel, onFDC3Ready } from './utils';
8
11
  {{/if}}
9
12
 
10
- // Genesis Components
11
- import './share/genesis-components';
12
-
13
13
  @Component({
14
14
  selector: '{{rootElement}}',
15
15
  templateUrl: './app.component.html',
16
16
  styleUrl: './app.component.css',
17
17
  })
18
- export class AppComponent implements AfterViewInit {
18
+ export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
19
19
  layoutName?: LayoutComponentName;
20
20
  title = '{{capitalCase appName}}';
21
+ store = getStore();
21
22
 
22
23
  constructor(
23
- private router: Router,
24
+ private el: ElementRef,
25
+ router: Router,
24
26
  ) {
25
27
  configureFoundationLogin({ router });
26
28
 
@@ -32,6 +34,43 @@ export class AppComponent implements AfterViewInit {
32
34
  });
33
35
  }
34
36
 
37
+ ngOnInit() {
38
+ this.addEventListeners();
39
+ this.readyStore();
40
+ registerStylesTarget(this.el.nativeElement, 'main');
41
+ this.loadRemotes();
42
+ }
43
+
44
+ ngOnDestroy() {
45
+ this.removeEventListeners();
46
+ this.disconnectStore();
47
+ }
48
+
49
+ async loadRemotes() {
50
+ await registerComponents();
51
+ }
52
+
53
+ addEventListeners() {
54
+ this.el.nativeElement.addEventListener('store-connected', this.store.onConnected);
55
+ }
56
+
57
+ removeEventListeners() {
58
+ this.el.nativeElement.removeEventListener('store-connected', this.store.onConnected);
59
+ }
60
+
61
+ readyStore() {
62
+ this.dispatchCustomEvent('store-connected', this.el.nativeElement);
63
+ this.dispatchCustomEvent('store-ready', true);
64
+ }
65
+
66
+ disconnectStore() {
67
+ this.dispatchCustomEvent('store-disconnected');
68
+ }
69
+
70
+ dispatchCustomEvent(type: string, detail?: any) {
71
+ this.el.nativeElement.dispatchEvent(customEventFactory(type, detail));
72
+ }
73
+
35
74
  ngAfterViewInit() {
36
75
  {{#if FDC3.channels.length}}
37
76
  onFDC3Ready(this.FDC3ReadyHandler);
@@ -1,4 +1,3 @@
1
- import type { MainMenu } from './types/menu'
2
1
  import type { LayoutComponentName } from './types/layout';
3
2
 
4
3
  export const AUTH_PATH = 'login'
@@ -19,15 +18,3 @@ export const layoutComponentImportsByName = {
19
18
  export const layoutNameByRouteMap: Map<string, LayoutComponentName> = new Map([
20
19
  [`/${AUTH_PATH}`, layoutComponentName.blank],
21
20
  ]);
22
-
23
- export const mainMenu: MainMenu = [
24
- {{#each routes}}
25
- {
26
- index: {{@index}},
27
- path: '{{kebabCase this.name}}',
28
- title: '{{#if this.title}}{{this.title}}{{else}}{{this.name}}{{/if}}',
29
- icon: '{{this.icon}}',
30
- variant: 'solid'
31
- }{{#unless @last}},{{/unless}}
32
- {{/each}}
33
- ];
@@ -1,11 +1,14 @@
1
- import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
1
+ import { NgModule, CUSTOM_ELEMENTS_SCHEMA, APP_INITIALIZER } from '@angular/core';
2
2
  import { BrowserModule } from '@angular/platform-browser';
3
3
  import { FormsModule } from '@angular/forms';
4
- import { AppRoutingModule } from './app-routing.module';
4
+ import { Router, RouterModule } from '@angular/router';
5
+ import { PBCContainer } from '../pbc/container';
6
+ import { PBCElementsRenderer } from '../pbc/elementsRenderer';
5
7
  import { AppComponent } from './app.component';
6
8
  import { DefaultLayoutComponent } from './layouts/default/default.layout';
7
9
  import { BlankLayoutComponent } from './layouts/blank/blank.layout';
8
10
  import { LayoutLazyLoadDirective } from './directive/app-lazy-load.directive';
11
+ import { RouteService } from './services/route.service';
9
12
 
10
13
  @NgModule({
11
14
  declarations: [
@@ -15,11 +18,21 @@ import { LayoutLazyLoadDirective } from './directive/app-lazy-load.directive';
15
18
  BlankLayoutComponent,
16
19
  ],
17
20
  imports: [
18
- AppRoutingModule,
19
21
  BrowserModule,
20
22
  FormsModule,
23
+ RouterModule.forRoot(RouteService.routes),
24
+ PBCContainer,
25
+ PBCElementsRenderer,
26
+ ],
27
+ providers: [
28
+ RouteService,
29
+ {
30
+ provide: APP_INITIALIZER,
31
+ useFactory: (service: RouteService, router: Router) => () => router.resetConfig(service.allRoutes()),
32
+ deps: [RouteService, Router],
33
+ multi: true,
34
+ },
21
35
  ],
22
- providers: [],
23
36
  bootstrap: [AppComponent],
24
37
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
25
38
  })
@@ -1,21 +1,14 @@
1
1
  import { Injectable } from '@angular/core';
2
- import { CanActivate, Router } from '@angular/router';
3
- import { AuthService } from '../services/auth.service';
4
2
  import { AUTH_PATH } from '../app.config';
3
+ import { PermissionsGuard } from './permissions.guard';
5
4
 
6
5
  @Injectable({
7
6
  providedIn: 'root',
8
7
  })
9
- export class AuthGuard implements CanActivate {
10
- constructor(
11
- private authService: AuthService,
12
- private router: Router,
13
- ) {}
14
-
15
- canActivate(): boolean {
16
- const isUserAuthenticated = this.authService.isUserAuthenticated();
17
-
18
- if (!isUserAuthenticated) {
8
+ export class AuthGuard extends PermissionsGuard {
9
+ override async canActivate(): Promise<boolean> {
10
+ if (!this.user.isAuthenticated) {
11
+ this.user.trackPath();
19
12
  this.router.navigate([`/${AUTH_PATH}`]);
20
13
  return false;
21
14
  }
@@ -0,0 +1,33 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
3
+ import { getUser } from '@genesislcap/foundation-user';
4
+ import { AuthGuard } from './auth.guard';
5
+ import { ConnectionGuard } from './connection.guard';
6
+ import { PermissionsGuard } from './permissions.guard';
7
+
8
+ @Injectable({
9
+ providedIn: 'root',
10
+ })
11
+ export class ChainedGuard implements CanActivate {
12
+ protected user = getUser();
13
+
14
+ constructor(
15
+ protected router: Router,
16
+ protected connectionGuard: ConnectionGuard,
17
+ protected authGuard: AuthGuard,
18
+ protected permissionsGuard: PermissionsGuard
19
+ ) {}
20
+
21
+ async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
22
+ let result = await this.connectionGuard.canActivate();
23
+ if (!result) {
24
+ return false;
25
+ }
26
+ result = await this.authGuard.canActivate();
27
+ if (!result) {
28
+ return false;
29
+ }
30
+ result = await this.permissionsGuard.canActivate(route);
31
+ return result;
32
+ }
33
+ }
@@ -0,0 +1,21 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { CanActivate} from '@angular/router';
3
+ import { getConnect } from '@genesislcap/foundation-comms';
4
+
5
+ @Injectable({
6
+ providedIn: 'root'
7
+ })
8
+ export class ConnectionGuard implements CanActivate {
9
+ protected connect = getConnect();
10
+
11
+ async canActivate(): Promise<boolean> {
12
+ if (this.connect.isConnected) {
13
+ return true;
14
+ }
15
+ const hostUrl = sessionStorage.getItem('hostUrl');
16
+ if (!hostUrl) {
17
+ return false;
18
+ }
19
+ return this.connect.connect(hostUrl);
20
+ }
21
+ }
@@ -1,21 +1,19 @@
1
1
  import { Injectable } from '@angular/core';
2
2
  import { CanActivate, Router, ActivatedRouteSnapshot } from '@angular/router';
3
- import { AuthService } from '../services/auth.service';
3
+ import { getUser } from '@genesislcap/foundation-user';
4
4
  import { NOT_PERMITTED_PATH } from '../app.config';
5
5
 
6
6
  @Injectable({
7
7
  providedIn: 'root',
8
8
  })
9
9
  export class PermissionsGuard implements CanActivate {
10
- constructor(
11
- private authService: AuthService,
12
- private router: Router,
13
- ) {}
10
+ protected user = getUser();
14
11
 
15
- async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
16
- const isPermitted = await this.authService.hasUserPermission(route.data['permissionCode']);
12
+ constructor(protected router: Router) {}
17
13
 
18
- if (!isPermitted) {
14
+ async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
15
+ const { permissionCode } = route.data;
16
+ if (permissionCode && !this.user.hasPermission(permissionCode)) {
19
17
  await this.router.navigate([`/${NOT_PERMITTED_PATH}`]);
20
18
  return false;
21
19
  }
@@ -1,11 +1,7 @@
1
1
  import { Router } from '@angular/router';
2
2
 
3
3
  export default class BaseLayout {
4
- router: Router;
5
-
6
- constructor(router: Router) {
7
- this.router = router;
8
- }
4
+ constructor(protected router: Router) {}
9
5
 
10
6
  navigate(path: string) {
11
7
  this.router.navigate([path]);
@@ -2,6 +2,7 @@
2
2
  display: flex;
3
3
  flex-direction: column;
4
4
  height: 100%;
5
+ contain: content;
5
6
  }
6
7
 
7
8
  .container {
@@ -1,19 +1,18 @@
1
1
  <rapid-design-system-provider #designSystemProvider>
2
+ <pbc-elements-renderer [target]="['layout-start']"></pbc-elements-renderer>
2
3
  <foundation-header
3
4
  #foundationHeader
4
5
  show-luminance-toggle-button
5
6
  show-misc-toggle-button
6
7
  (luminance-icon-clicked)="onLuminanceToogle()"
7
8
  [navigateTo]="navigateAngular"
9
+ [routeNavItems]="navItems"
8
10
  >
9
- <section class="routes-wrapper" slot="routes">
10
- <rapid-button *ngFor="let menuLink of allRoutes" (click)="navigate(menuLink.path)" >
11
- <rapid-icon name="\{{ menuLink.icon }}"></rapid-icon>
12
- \{{ menuLink.title }}
13
- </rapid-button>
14
- </section>
15
11
  </foundation-header>
16
12
  <section class="content">
13
+ <pbc-elements-renderer [target]="['content-start']"></pbc-elements-renderer>
17
14
  <router-outlet></router-outlet>
15
+ <pbc-elements-renderer [target]="['content', 'content-end']"></pbc-elements-renderer>
18
16
  </section>
17
+ <pbc-elements-renderer [target]="['layout', 'layout-end']"></pbc-elements-renderer>
19
18
  </rapid-design-system-provider>
@@ -1,10 +1,11 @@
1
1
  import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
2
2
  import { Router } from '@angular/router';
3
- import { baseLayerLuminance, StandardLuminance } from '@microsoft/fast-components';
4
- import { configureDesignSystem } from '@genesislcap/foundation-ui';
3
+ import { configureDesignSystem, FoundationRouteNavItem } from '@genesislcap/foundation-ui';
4
+ import { baseLayerLuminance, StandardLuminance } from '@genesislcap/web-core';
5
5
  import * as designTokens from '../../../styles/design-tokens.json';
6
+ import { RouteService } from '../../services/route.service';
6
7
  import BaseLayout from '../base.layout';
7
- import { mainMenu } from '../../app.config';
8
+ import { registerStylesTarget } from '../../../pbc/utils';
8
9
 
9
10
  @Component({
10
11
  selector: 'app-default-layout',
@@ -13,16 +14,20 @@ import { mainMenu } from '../../app.config';
13
14
  })
14
15
  export class DefaultLayoutComponent extends BaseLayout implements AfterViewInit {
15
16
  @ViewChild('designSystemProvider') designSystemProviderElement!: ElementRef;
16
- allRoutes = mainMenu;
17
+ navItems: FoundationRouteNavItem[] = [];
17
18
 
18
19
  constructor(
20
+ private el: ElementRef,
19
21
  router: Router,
22
+ routeService: RouteService,
20
23
  ) {
21
24
  super(router);
25
+ this.navItems = routeService.getNavItems();
22
26
  }
23
27
 
24
28
  ngAfterViewInit() {
25
29
  configureDesignSystem(this.designSystemProviderElement.nativeElement, designTokens);
30
+ registerStylesTarget(this.el.nativeElement, 'layout');
26
31
  }
27
32
 
28
33
  navigateAngular = (path: string) => {
@@ -0,0 +1,95 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { Route, Routes } from '@angular/router';
3
+ import { getApp } from '@genesislcap/foundation-shell/app';
4
+ import { FoundationRoute, FoundationRouteNavItem, getNavItems } from '@genesislcap/foundation-ui';
5
+ import { PBCContainer } from '../../pbc/container';
6
+ import { AUTH_PATH, NOT_PERMITTED_PATH } from '../app.config';
7
+ import { ChainedGuard } from '../guards/chained.guard';
8
+ import { AuthLoginComponent } from '../pages/auth-login/auth-login.component';
9
+ import { NotPermittedComponent } from '../pages/not-permitted/not-permitted.component';
10
+ {{#each routes}}
11
+ import { {{pascalCase this.name}}Component } from '../pages/{{kebabCase this.name}}/{{kebabCase this.name}}.component';
12
+ {{/each}}
13
+
14
+ @Injectable({
15
+ providedIn: 'root'
16
+ })
17
+ export class RouteService {
18
+ static routes: Routes = [
19
+ {
20
+ path: '',
21
+ redirectTo: `${AUTH_PATH}`,
22
+ pathMatch: 'full',
23
+ },
24
+ {
25
+ path: `${AUTH_PATH}`,
26
+ component: AuthLoginComponent,
27
+ },
28
+ {
29
+ path: `${NOT_PERMITTED_PATH}`,
30
+ component: NotPermittedComponent,
31
+ },
32
+ {{#each routes}}
33
+ {
34
+ path: '{{kebabCase this.name}}',
35
+ canActivate: [ChainedGuard],
36
+ component: {{pascalCase this.name}}Component,
37
+ data: {
38
+ permissionCode: '{{this.permissions.viewRight}}',
39
+ navItems: [
40
+ {
41
+ navId: 'header',
42
+ title: '{{#if this.title}}{{this.title}}{{else}}{{this.name}}{{/if}}',
43
+ icon: {
44
+ name: '{{this.icon}}',
45
+ variant: 'solid',
46
+ },
47
+ },
48
+ ],
49
+ },
50
+ },
51
+ {{/each}}
52
+ ];
53
+
54
+ /**
55
+ * @privateRemarks
56
+ * The shell has access to context, so it's possible for it to return a pre-mapped framework variant of routes.
57
+ * In this iteration we're doing it inline, given the angular version may move and here we know the shape we need.
58
+ */
59
+ pbcRoutes(): Routes {
60
+ return getApp().routes.map((route) => {
61
+ return <Route>{
62
+ title: route.title,
63
+ path: route.path,
64
+ /**
65
+ * Ask about permissions.viewRight in PBC context, as we may need to apply a data.permissionCode here.
66
+ * Not sure if they are added to the filesystem prior to handlebars template processing across the files.
67
+ */
68
+ canActivate: [ChainedGuard],
69
+ component: PBCContainer,
70
+ data: {
71
+ ...route.settings,
72
+ pbcElement: route.element,
73
+ // @ts-ignore
74
+ pbcElementTag: route.elementTag,
75
+ navItems: route.navItems
76
+ },
77
+ };
78
+ })
79
+ }
80
+
81
+ allRoutes(): Routes {
82
+ return [
83
+ ...RouteService.routes,
84
+ ...this.pbcRoutes(),
85
+ ];
86
+ }
87
+
88
+ getNavItems(): FoundationRouteNavItem[] {
89
+ const allNavItems = this.allRoutes().flatMap(route => (<FoundationRoute>{
90
+ path: route.path as string,
91
+ navItems: route.data?.['navItems'],
92
+ }));
93
+ return getNavItems(allNavItems);
94
+ }
95
+ }
@@ -1,8 +1,8 @@
1
1
  import {configure, define} from '@genesislcap/foundation-login';
2
2
  import type { Router } from '@angular/router';
3
+ import { getUser } from '@genesislcap/foundation-user';
4
+ import { css, DI } from '@genesislcap/web-core';
3
5
  import { AUTH_PATH } from '../app.config';
4
- import { css } from '@microsoft/fast-element';
5
- import { DI } from '@microsoft/fast-foundation';
6
6
  import logo from '../../assets/logo.svg';
7
7
 
8
8
  // eslint-disable-next-line
@@ -28,10 +28,12 @@ export const configureFoundationLogin = ({
28
28
  router: Router;
29
29
  }) => {
30
30
  configure(DI.getOrCreateDOMContainer(), {
31
+ // autoConnect: true, // < Guard in place to ensure connection. Keeping the connect form in place for now.
32
+ autoAuth: true, // < Allow users to skip login
31
33
  showConnectionIndicator: true,
32
34
  hostPath: AUTH_PATH,
33
35
  redirectHandler: () => {
34
- router.navigate(['{{kebabCase routes.[0].name}}'])
36
+ router.navigate([getUser().lastPath() ?? '{{kebabCase routes.[0].name}}'])
35
37
  },
36
38
  ...ssoSettings,
37
39
  logo: css `
@@ -1,29 +1,56 @@
1
- import { configure as configureHeader }from '@genesislcap/foundation-header/config';
2
- import { foundationLayoutComponents } from '@genesislcap/foundation-layout';
3
1
  import { EntityManagement } from '@genesislcap/foundation-entity-management';
2
+ import { Form } from '@genesislcap/foundation-forms';
3
+ import { foundationLayoutComponents } from '@genesislcap/foundation-layout';
4
+ import { getApp } from '@genesislcap/foundation-shell/app';
5
+ import * as zeroDesignSystem from '@genesislcap/foundation-zero';
4
6
  import { g2plotChartsComponents } from '@genesislcap/g2plot-chart';
5
7
  import * as rapidDesignSystem from '@genesislcap/rapid-design-system';
6
8
  import { rapidGridComponents } from '@genesislcap/rapid-grid-pro';
7
9
 
10
+ /**
11
+ * Ensure tree shaking doesn't remove these.
12
+ */
8
13
  EntityManagement;
14
+ Form;
15
+
16
+ /**
17
+ * registerComponents.
18
+ * @public
19
+ */
20
+ export async function registerComponents() {
21
+ const { configure: configureHeader } = await import('@genesislcap/foundation-header/config');
22
+ /**
23
+ * Register any PBC components with the design system
24
+ */
25
+ getApp().registerComponents({
26
+ designSystem: rapidDesignSystem,
27
+ });
9
28
 
10
- configureHeader({
11
- templateOptions: {
12
- provider: 'template',
13
- icon: 'rapid-icon',
14
- button: 'rapid-button',
15
- connectionIndicator: 'rapid-connection-indicator',
16
- select: 'rapid-select',
17
- option: 'rapid-option',
18
- flyout: 'rapid-flyout',
19
- },
20
- });
29
+ rapidDesignSystem
30
+ .provideDesignSystem()
31
+ .register(
32
+ rapidDesignSystem.baseComponents,
33
+ rapidGridComponents,
34
+ g2plotChartsComponents,
35
+ foundationLayoutComponents,
36
+ );
37
+
38
+ configureHeader({
39
+ templateOptions: {
40
+ provider: 'template',
41
+ icon: 'rapid-icon',
42
+ button: 'rapid-button',
43
+ connectionIndicator: 'rapid-connection-indicator',
44
+ select: 'rapid-select',
45
+ option: 'rapid-option',
46
+ flyout: 'rapid-flyout',
47
+ },
48
+ });
21
49
 
22
- rapidDesignSystem
23
- .provideDesignSystem()
24
- .register(
25
- rapidDesignSystem.baseComponents,
26
- rapidGridComponents,
27
- g2plotChartsComponents,
28
- foundationLayoutComponents,
29
- );
50
+ /**
51
+ * May be still required while we transition all PBCs to rapid. Remove when complete.
52
+ */
53
+ zeroDesignSystem
54
+ .provideDesignSystem()
55
+ .register(zeroDesignSystem.baseComponents, g2plotChartsComponents, foundationLayoutComponents);
56
+ }
@@ -0,0 +1 @@
1
+ export * from './store';
@@ -0,0 +1,34 @@
1
+ import { CustomEventMap } from '@genesislcap/foundation-events';
2
+ import { getApp } from '@genesislcap/foundation-shell/app';
3
+ import {
4
+ AbstractStoreRoot,
5
+ registerStore,
6
+ StoreRoot,
7
+ StoreRootEventDetailMap,
8
+ } from '@genesislcap/foundation-store';
9
+ import { DI } from '@genesislcap/web-core';
10
+
11
+ export interface Store extends StoreRoot {}
12
+
13
+ export type StoreEventDetailMap = StoreRootEventDetailMap & {};
14
+
15
+ declare global {
16
+ interface HTMLElementEventMap extends CustomEventMap<StoreEventDetailMap> {}
17
+ }
18
+
19
+ class DefaultStore extends AbstractStoreRoot<Store, StoreEventDetailMap> implements Store {
20
+ constructor() {
21
+ super();
22
+
23
+ /**
24
+ * Register the store root
25
+ */
26
+ getApp().registerStoreRoot(this);
27
+ }
28
+ }
29
+
30
+ export const Store = registerStore(DefaultStore, 'Store');
31
+
32
+ export function getStore(): Store {
33
+ return DI.getOrCreateDOMContainer().get(Store) as Store;
34
+ }
@@ -2,4 +2,10 @@ declare module "*.svg" {
2
2
  const content: any;
3
3
  export default content;
4
4
  }
5
-
5
+
6
+ /**
7
+ * Temp to unblock testing until we update the types pointer in all PBC packages
8
+ */
9
+ declare module '@genesislcap/pbc-auth-ui';
10
+ declare module '@genesislcap/pbc-documents-ui';
11
+ declare module '@genesislcap/pbc-reconciliation-ui';
@@ -4,4 +4,5 @@ export const environment = {
4
4
  ENABLE_SSO: {{enableSSO}},
5
5
  HOST: 'localhost',
6
6
  PROTOCOL: 'http',
7
+ BUILDER: 'webpack',
7
8
  };
@@ -5,4 +5,5 @@ export const environment = {
5
5
  ENABLE_SSO: {{enableSSO}},
6
6
  HOST: 'localhost',
7
7
  PROTOCOL: 'http',
8
- };
8
+ BUILDER: 'webpack'
9
+ };
@@ -1,6 +1,17 @@
1
1
  import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
2
+ import { createLogger } from '@genesislcap/foundation-logger';
2
3
  import { AppModule } from './app/app.module';
4
+ import { registerPBCs } from './pbc/utils';
3
5
 
4
- platformBrowserDynamic()
5
- .bootstrapModule(AppModule)
6
- .catch((err) => console.error(err));
6
+ const logger = createLogger('main');
7
+
8
+ function bootstrapApp() {
9
+ platformBrowserDynamic()
10
+ .bootstrapModule(AppModule)
11
+ .catch((err) => logger.error(err));
12
+ }
13
+
14
+ registerPBCs()
15
+ .then(hasAssets => logger.debug(hasAssets ? 'PBCs registered' : 'No PBCs detected'))
16
+ .catch((err) => logger.error(err))
17
+ .finally(bootstrapApp)
@@ -0,0 +1,7 @@
1
+ # PBC
2
+
3
+ This directory contains PBC `genx add` output.
4
+
5
+ The app will reload if you remove, add, or customise a packaged business capability.
6
+
7
+ See the expanded README.md in `@genesislcap/foundation-shell`.
@@ -0,0 +1,40 @@
1
+ import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, OnInit, ViewChild } from '@angular/core';
2
+ import { ActivatedRoute } from '@angular/router';
3
+ import { deriveElementTag } from './utils';
4
+
5
+ /**
6
+ * An app level container for the lazy loading of the web component based PBC routes in angular router.
7
+ */
8
+ @Component({
9
+ standalone: true,
10
+ selector: 'pbc-container',
11
+ template: `<div #container class="container"></div>`, // todo get rid of the extra div
12
+ styles: [`
13
+ .container {
14
+ width: 100%;
15
+ height: 100%;
16
+ }
17
+ `],
18
+ schemas: [
19
+ CUSTOM_ELEMENTS_SCHEMA
20
+ ],
21
+ })
22
+ export class PBCContainer implements OnInit {
23
+ @ViewChild('container', { static: true }) container!: ElementRef;
24
+
25
+ constructor(private route: ActivatedRoute) {}
26
+
27
+ async ngOnInit() {
28
+ const { pbcElement, pbcElementTag } = this.route.snapshot.data ?? {};
29
+ if (!pbcElement) {
30
+ return;
31
+ }
32
+ /**
33
+ * Account for PBC elements being a mix of constructors and lazy loading functions
34
+ */
35
+ const element = pbcElement.define ? pbcElement : await pbcElement();
36
+ const tagName = pbcElementTag || deriveElementTag(element.name);
37
+ const customElement = document.createElement(tagName);
38
+ this.container.nativeElement.appendChild(customElement);
39
+ }
40
+ }
@@ -0,0 +1,57 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, Input, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core';
3
+ import { AppElementPredicate, AppTargetId } from '@genesislcap/foundation-shell/app';
4
+ import { createLogger } from '@genesislcap/foundation-logger';
5
+ import type { ViewTemplate } from '@genesislcap/web-core';
6
+ import { customEventFactory, getTargetElements } from './utils';
7
+
8
+ /**
9
+ * An app level component for renderering target PBC elements to an angular template.
10
+ */
11
+ @Component({
12
+ standalone: true,
13
+ selector: 'pbc-elements-renderer',
14
+ template: `<div #container class="container"></div>`, // < can we get rid of the extra div?
15
+ styles: [`
16
+ .container {}
17
+ `],
18
+ schemas: [
19
+ CUSTOM_ELEMENTS_SCHEMA
20
+ ],
21
+ imports: [
22
+ CommonModule,
23
+ ]
24
+ })
25
+ export class PBCElementsRenderer implements OnChanges, OnInit {
26
+ @ViewChild('container', { static: true }) container!: ElementRef;
27
+ @Input() target: AppTargetId = [];
28
+ @Input() predicate: AppElementPredicate = () => true;
29
+ templates: ViewTemplate[] = [];
30
+ logger = createLogger('pbc-elements-renderer');
31
+
32
+ async ngOnInit() {
33
+ this.setTemplates();
34
+ this.renderTemplates();
35
+ }
36
+
37
+ $emit(type: string, detail?: any) {
38
+ this.container.nativeElement.dispatchEvent(customEventFactory(type, detail));
39
+ };
40
+
41
+ ngOnChanges(changes: SimpleChanges): void {
42
+ if (changes['target']) {
43
+ this.logger.debug('target changed, rendering qualifying elements');
44
+ this.setTemplates();
45
+ this.renderTemplates();
46
+ }
47
+ }
48
+
49
+ setTemplates() {
50
+ this.templates = getTargetElements(this.target, this.predicate);
51
+ }
52
+
53
+ renderTemplates() {
54
+ this.container.nativeElement.replaceChildren();
55
+ this.templates.forEach((template) => template.render(this, this.container.nativeElement));
56
+ }
57
+ }
@@ -0,0 +1,121 @@
1
+ import { createLogger } from '@genesislcap/foundation-logger';
2
+ import {
3
+ AppContext,
4
+ AppElement,
5
+ AppElementPredicate,
6
+ AppStyle,
7
+ AppStylePredicate,
8
+ AppTargetId,
9
+ assetPredicate,
10
+ getApp,
11
+ registrationPredicate,
12
+ targetIdPredicate
13
+ } from '@genesislcap/foundation-shell/app';
14
+ import { importPBCAssets } from '@genesislcap/foundation-shell/pbc';
15
+ import { toElementStyles } from '@genesislcap/foundation-utils';
16
+ import { ComposableStyles } from '@genesislcap/web-core';
17
+
18
+ const logger = createLogger('pbc-utils');
19
+
20
+ /**
21
+ * Some of this logic already exists in shell, but exists as part of a logic chain that assumes web components.
22
+ * After testing, we can backport the changes required.
23
+ */
24
+
25
+ /**
26
+ * @public
27
+ */
28
+ export async function registerPBCs(): Promise<boolean> {
29
+ const app = getApp();
30
+ const pbcAssets = await importPBCAssets();
31
+ app.registerAssets(pbcAssets);
32
+ return app.hasAssets();
33
+ }
34
+
35
+ /**
36
+ * @privateRemarks
37
+ * Shared across elements and styles.
38
+ */
39
+ const assetFilter = (
40
+ asset: AppElement | AppStyle,
41
+ targetId: AppTargetId,
42
+ predicate: AppElementPredicate | AppStylePredicate = () => true,
43
+ context: AppContext,
44
+ ) => targetIdPredicate(asset, targetId) &&
45
+ assetPredicate(asset, context) &&
46
+ registrationPredicate(
47
+ asset,
48
+ predicate,
49
+ context,
50
+ );
51
+
52
+ /**
53
+ * @public
54
+ */
55
+ export function getTargetStyles(
56
+ targetId: AppTargetId,
57
+ predicate: AppStylePredicate = () => true
58
+ ) {
59
+ const app = getApp();
60
+ return app.styles
61
+ .filter(asset => assetFilter(asset, targetId, predicate, app.config.context!))
62
+ .map((token) => token.styles)
63
+ .flat();
64
+ }
65
+
66
+
67
+ /**
68
+ * @public
69
+ */
70
+ export function getTargetElements(
71
+ targetId: AppTargetId,
72
+ predicate: AppElementPredicate = () => true
73
+ ) {
74
+ const app = getApp();
75
+ return app.elements
76
+ .filter(asset => assetFilter(asset, targetId, predicate, app.config.context!))
77
+ .map((token) => token.elements);
78
+ }
79
+
80
+ /**
81
+ * @public
82
+ */
83
+ export function registerStylesTarget(nativeElement: HTMLElement, targetId: AppTargetId) {
84
+ const styles = getTargetStyles(targetId);
85
+ if (!styles || styles.length === 0) {
86
+ return;
87
+ }
88
+ applyDynamicStyles(nativeElement, styles);
89
+ }
90
+
91
+ /**
92
+ * @public
93
+ */
94
+ export function applyDynamicStyles(nativeElement: HTMLElement, style: ComposableStyles | ComposableStyles[]) {
95
+ const elementStyles = toElementStyles(style);
96
+ const styleTarget = nativeElement.shadowRoot ? nativeElement.shadowRoot : document;
97
+ elementStyles.addStylesTo(styleTarget);
98
+ }
99
+
100
+ /**
101
+ * @public
102
+ */
103
+ export function customEventFactory(type: string, detail?: any) {
104
+ return new CustomEvent(type, {
105
+ bubbles: true,
106
+ cancelable: true,
107
+ composed: true,
108
+ detail,
109
+ });
110
+ };
111
+
112
+ /**
113
+ * @privateRemarks
114
+ * May need to add an elementTag to routes, ie. elementTag: 'notifications-dashboard'. May remove when complete.
115
+ * @public
116
+ */
117
+ export function deriveElementTag(name: string): string {
118
+ const tagName = name.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
119
+ logger.debug(`Guessing pbc element tag is '${tagName}' based on '${name}'. This may be incorrect, please set pbcElementTag in route data.`);
120
+ return tagName;
121
+ }
@@ -10,6 +10,7 @@
10
10
  ],
11
11
  "include": [
12
12
  "src/**/*.d.ts",
13
- "globals.d.ts",
13
+ "src/pbc/**/*.ts",
14
+ "globals.d.ts"
14
15
  ]
15
16
  }
@@ -8,7 +8,8 @@
8
8
  ]
9
9
  },
10
10
  "include": [
11
- "src/**/*.spec.ts",
12
- "src/**/*.d.ts"
11
+ "src/**/*.d.ts",
12
+ "src/pbc/**/*.ts",
13
+ "src/**/*.spec.ts"
13
14
  ]
14
15
  }
@@ -32,11 +32,24 @@ module.exports = {
32
32
  },
33
33
  resolve: {
34
34
  alias: {
35
- 'foundationZero/ZeroDesignSystem': path.resolve(
36
- __dirname,
37
- 'node_modules/@genesislcap/foundation-zero',
38
- ),
35
+ 'pbc': path.resolve(
36
+ __dirname,
37
+ 'src/pbc',
38
+ )
39
39
  },
40
40
  },
41
+ /**
42
+ * Ensure webpack handles module loading strictly to allow module federation fallbacks.
43
+ */
44
+ output: {
45
+ strictModuleErrorHandling: true,
46
+ strictModuleExceptionHandling: true,
47
+ },
48
+ /**
49
+ * Mark the 'foundationZero/ZeroDesignSystem' module federated remote as external.
50
+ */
51
+ externals: {
52
+ 'foundationZero/ZeroDesignSystem': 'foundationZero/ZeroDesignSystem',
53
+ },
41
54
  };
42
55
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/blank-app-seed",
3
3
  "description": "Genesis Blank App Seed",
4
- "version": "3.27.3",
4
+ "version": "3.28.0",
5
5
  "license": "Apache-2.0",
6
6
  "scripts": {
7
7
  "release": "semantic-release"
@@ -1,40 +0,0 @@
1
- import { NgModule } from '@angular/core';
2
- import { RouterModule, Routes } from '@angular/router';
3
- import { AuthGuard } from './guards/auth.guard';
4
- import { PermissionsGuard } from './guards/permissions.guard';
5
- import { AuthLoginComponent } from './pages/auth-login/auth-login.component';
6
- import { NotPermittedComponent } from './pages/not-permitted/not-permitted.component';
7
- {{#each routes}}
8
- import { {{pascalCase this.name}}Component } from './pages/{{kebabCase this.name}}/{{kebabCase this.name}}.component';
9
- {{/each}}
10
- import { AUTH_PATH, NOT_PERMITTED_PATH } from './app.config';
11
-
12
- export const routes: Routes = [
13
- {
14
- path: '',
15
- redirectTo: `${AUTH_PATH}`,
16
- pathMatch: 'full',
17
- },
18
- {
19
- path: `${AUTH_PATH}`,
20
- component: AuthLoginComponent,
21
- },
22
- {
23
- path: `${NOT_PERMITTED_PATH}`,
24
- component: NotPermittedComponent,
25
- },
26
- {{#each routes}}
27
- {
28
- path: '{{kebabCase this.name}}',
29
- canActivate: [AuthGuard{{#if this.permissions.viewRight}}, PermissionsGuard{{/if}}],
30
- component: {{pascalCase this.name}}Component,
31
- data: { permissionCode: '{{this.permissions.viewRight}}' },
32
- },
33
- {{/each}}
34
- ];
35
-
36
- @NgModule({
37
- imports: [RouterModule.forRoot(routes)],
38
- exports: [RouterModule],
39
- })
40
- export class AppRoutingModule {}
@@ -1,22 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
- import { Auth } from '@genesislcap/foundation-comms';
3
- import { DI } from "@microsoft/fast-foundation";
4
-
5
- @Injectable({
6
- providedIn: 'root',
7
- })
8
- export class AuthService {
9
- auth: Auth;
10
-
11
- constructor() {
12
- this.auth = DI.getOrCreateDOMContainer().get(Auth);
13
- }
14
-
15
- isUserAuthenticated(): boolean {
16
- return this.auth.isLoggedIn;
17
- }
18
-
19
- hasUserPermission(permissionCode: string): boolean {
20
- return this.auth.currentUser.hasPermission(permissionCode);
21
- }
22
- }
@@ -1,8 +0,0 @@
1
- export type MainMenuLink = {
2
- index: number;
3
- path: string;
4
- title: string;
5
- icon: string;
6
- variant?: string;
7
- };
8
- export type MainMenu = MainMenuLink[];