@genesislcap/blank-app-seed 3.21.0 → 3.23.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 (85) hide show
  1. package/.genx/package.json +1 -1
  2. package/.genx/static.js +3 -2
  3. package/.genx/templates/angular/chart.hbs +21 -9
  4. package/.genx/templates/angular/entityManager.hbs +57 -45
  5. package/.genx/templates/angular/form.hbs +21 -8
  6. package/.genx/templates/angular/grid.hbs +30 -18
  7. package/.genx/templates/angular/route.hbs +8 -5
  8. package/.genx/templates/react/chart.hbs +9 -0
  9. package/.genx/templates/react/entityManager.hbs +45 -0
  10. package/.genx/templates/react/form.hbs +8 -0
  11. package/.genx/templates/react/grid.hbs +18 -0
  12. package/.genx/templates/react/gridLayout.hbs +30 -0
  13. package/.genx/templates/react/horizontalLayout.hbs +7 -0
  14. package/.genx/templates/react/route.hbs +35 -0
  15. package/.genx/templates/react/route.styles.hbs +3 -0
  16. package/.genx/templates/react/tabsLayout.hbs +7 -0
  17. package/.genx/templates/web-components/entityManager.hbs +1 -1
  18. package/.genx/utils/generateRoute.js +21 -9
  19. package/CHANGELOG.md +14 -0
  20. package/client-tmp/angular/angular.json +21 -12
  21. package/client-tmp/angular/package.json +45 -20
  22. package/client-tmp/angular/src/app/app-routing.module.ts +10 -3
  23. package/client-tmp/angular/src/app/app.component.spec.ts +2 -8
  24. package/client-tmp/angular/src/app/app.component.ts +0 -1
  25. package/client-tmp/angular/src/app/app.config.ts +1 -0
  26. package/client-tmp/angular/src/app/components/error-message/error-message.component.html +15 -0
  27. package/client-tmp/angular/src/app/components/error-message/error-message.component.spec.ts +74 -0
  28. package/client-tmp/angular/src/app/components/error-message/error-message.component.ts +15 -0
  29. package/client-tmp/angular/src/app/guards/auth.guard.ts +3 -3
  30. package/client-tmp/angular/src/app/guards/permissions.guard.ts +24 -0
  31. package/client-tmp/angular/src/app/layouts/blank/blank.layout.html +0 -1
  32. package/client-tmp/angular/src/app/layouts/blank/blank.layout.spec.ts +1 -1
  33. package/client-tmp/angular/src/app/layouts/default/default.layout.html +0 -1
  34. package/client-tmp/angular/src/app/layouts/default/default.layout.spec.ts +30 -15
  35. package/client-tmp/angular/src/app/pages/auth-login/auth-login.component.spec.ts +6 -6
  36. package/client-tmp/angular/src/app/pages/not-permitted/not-permitted.component.html +4 -0
  37. package/client-tmp/angular/src/app/pages/not-permitted/not-permitted.component.scss +12 -0
  38. package/client-tmp/angular/src/app/pages/not-permitted/not-permitted.component.spec.ts +32 -0
  39. package/client-tmp/angular/src/app/pages/not-permitted/not-permitted.component.ts +13 -0
  40. package/client-tmp/angular/src/app/services/auth.service.ts +12 -4
  41. package/client-tmp/angular/src/app/share/foundation-login.ts +3 -0
  42. package/client-tmp/angular/src/app/utils/index.ts +1 -0
  43. package/client-tmp/angular/src/app/utils/permissions.ts +7 -0
  44. package/client-tmp/angular/src/styles/_mixins.scss +8 -0
  45. package/client-tmp/react/.eslintrc.cjs +18 -0
  46. package/client-tmp/react/README.md +48 -0
  47. package/client-tmp/react/git +0 -0
  48. package/client-tmp/react/index.html +13 -0
  49. package/client-tmp/react/package.json +54 -0
  50. package/client-tmp/react/src/App.tsx +66 -0
  51. package/client-tmp/react/src/assets/logo-icon--light.svg +3 -0
  52. package/client-tmp/react/src/config.ts +31 -0
  53. package/client-tmp/react/src/custom-elements.d.ts +11 -0
  54. package/client-tmp/react/src/guards/AuthGuard.tsx +32 -0
  55. package/client-tmp/react/src/index.js +17 -0
  56. package/client-tmp/react/src/layouts/LayoutWrapper.tsx +20 -0
  57. package/client-tmp/react/src/layouts/blank/BlankLayout.module.css +9 -0
  58. package/client-tmp/react/src/layouts/blank/BlankLayout.tsx +26 -0
  59. package/client-tmp/react/src/layouts/default/DefaultLayout.module.css +35 -0
  60. package/client-tmp/react/src/layouts/default/DefaultLayout.tsx +80 -0
  61. package/client-tmp/react/src/main.tsx +10 -0
  62. package/client-tmp/react/src/pages/auth/AuthPage.css +0 -0
  63. package/client-tmp/react/src/pages/auth/AuthPage.jsx +11 -0
  64. package/client-tmp/react/src/reportWebVitals.js +13 -0
  65. package/client-tmp/react/src/services/auth.service.ts +13 -0
  66. package/client-tmp/react/src/services/connect.service.ts +26 -0
  67. package/client-tmp/react/src/setupTests.js +5 -0
  68. package/client-tmp/react/src/share/foundation-login.ts +21 -0
  69. package/client-tmp/react/src/share/genesis-components.ts +32 -0
  70. package/client-tmp/react/src/store/AuthContext.tsx +56 -0
  71. package/client-tmp/react/src/styles/design-tokens.json +56 -0
  72. package/client-tmp/react/src/styles/styles.css +39 -0
  73. package/client-tmp/react/src/svg-elements.d.ts +4 -0
  74. package/client-tmp/react/src/types/RouteLayouts.ts +3 -0
  75. package/client-tmp/react/src/types/layers.ts +9 -0
  76. package/client-tmp/react/src/types/menu.ts +8 -0
  77. package/client-tmp/react/src/utils/history.ts +5 -0
  78. package/client-tmp/react/src/utils/navigation.ts +5 -0
  79. package/client-tmp/react/src/vite-env.d.ts +1 -0
  80. package/client-tmp/react/tsconfig.app.json +28 -0
  81. package/client-tmp/react/tsconfig.json +11 -0
  82. package/client-tmp/react/tsconfig.node.json +13 -0
  83. package/client-tmp/react/vite.config.ts +14 -0
  84. package/package.json +1 -1
  85. package/client-tmp/react/react-file.ts +0 -1
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "name": "{{pkgName}}",
3
+ "description": "",
3
4
  "version": "{{applicationVersionWeb}}",
5
+ "private": true,
6
+ "license": "UNLICENSED",
4
7
  "scripts": {
5
8
  "ng": "ng",
6
9
  "bootstrap": "npm install --no-fund --no-audit",
@@ -9,7 +12,25 @@
9
12
  "watch": "ng build --watch --configuration development",
10
13
  "test": "ng test"
11
14
  },
12
- "private": true,
15
+ "devDependencies": {
16
+ "@angular-builders/custom-webpack": "^18.0.0",
17
+ "@angular-devkit/build-angular": "^18.0.4",
18
+ "@angular/cli": "^18.0.4",
19
+ "@angular/compiler-cli": "^18.0.4",
20
+ "@genesislcap/build-kit": "{{versions.UI}}",
21
+ "@types/jasmine": "~5.1.0",
22
+ "@types/numeral": "^2.0.5",
23
+ "file-loader": "^6.2.0",
24
+ "jasmine-core": "~5.1.0",
25
+ "karma": "~6.4.0",
26
+ "karma-chrome-launcher": "~3.2.0",
27
+ "karma-coverage": "~2.2.0",
28
+ "karma-jasmine": "~5.1.0",
29
+ "karma-jasmine-html-reporter": "~2.1.0",
30
+ "svg-url-loader": "^8.0.0",
31
+ "typescript": "~5.4.5",
32
+ "ts-node": "10.9.2"
33
+ },
13
34
  "dependencies": {
14
35
  "@angular/animations": "^18.0.4",
15
36
  "@angular/common": "^18.0.4",
@@ -24,32 +45,36 @@
24
45
  "@genesislcap/foundation-entity-management": "{{versions.UI}}",
25
46
  "@genesislcap/foundation-header": "{{versions.UI}}",
26
47
  "@genesislcap/foundation-ui": "{{versions.UI}}",
48
+ "@genesislcap/foundation-user": "{{versions.UI}}",
27
49
  "@genesislcap/rapid-design-system": "{{versions.UI}}",
28
50
  "@genesislcap/rapid-grid-pro": "{{versions.UI}}",
29
51
  "@genesislcap/foundation-layout": "{{versions.UI}}",
30
52
  "@genesislcap/g2plot-chart": "{{versions.UI}}",
31
53
  "numeral": "2.0.6",
32
- "rxjs": "~7.8.0",
33
54
  "tslib": "^2.3.0",
34
55
  "zone.js": "~0.14.3"
35
56
  },
36
- "devDependencies": {
37
- "@angular-builders/custom-webpack": "^18.0.0",
38
- "@angular-devkit/build-angular": "^18.0.4",
39
- "@angular/cli": "^18.0.4",
40
- "@angular/compiler-cli": "^18.0.4",
41
- "@genesislcap/build-kit": "{{versions.UI}}",
42
- "@types/jasmine": "~5.1.0",
43
- "@types/numeral": "^2.0.5",
44
- "file-loader": "^6.2.0",
45
- "jasmine-core": "~5.1.0",
46
- "karma": "~6.4.0",
47
- "karma-chrome-launcher": "~3.2.0",
48
- "karma-coverage": "~2.2.0",
49
- "karma-jasmine": "~5.1.0",
50
- "karma-jasmine-html-reporter": "~2.1.0",
51
- "svg-url-loader": "^8.0.0",
52
- "typescript": "~5.4.5",
53
- "ts-node": "10.9.2"
57
+ "overrides": {
58
+ "@angular/animations": "^18.0.4",
59
+ "@angular/common": "^18.0.4",
60
+ "@angular/compiler": "^18.0.4",
61
+ "@angular/core": "^18.0.4",
62
+ "@angular/forms": "^18.0.4",
63
+ "@angular/platform-browser": "^18.0.4",
64
+ "@angular/platform-browser-dynamic": "^18.0.4",
65
+ "@angular/router": "^18.0.4",
66
+ "@genesislcap/foundation-comms": "{{versions.UI}}",
67
+ "@genesislcap/foundation-login": "{{versions.UI}}",
68
+ "@genesislcap/foundation-entity-management": "{{versions.UI}}",
69
+ "@genesislcap/foundation-header": "{{versions.UI}}",
70
+ "@genesislcap/foundation-ui": "{{versions.UI}}",
71
+ "@genesislcap/foundation-user": "{{versions.UI}}",
72
+ "@genesislcap/rapid-design-system": "{{versions.UI}}",
73
+ "@genesislcap/rapid-grid-pro": "{{versions.UI}}",
74
+ "@genesislcap/foundation-layout": "{{versions.UI}}",
75
+ "@genesislcap/g2plot-chart": "{{versions.UI}}",
76
+ "numeral": "2.0.6",
77
+ "tslib": "^2.3.0",
78
+ "zone.js": "~0.14.3"
54
79
  }
55
80
  }
@@ -1,11 +1,13 @@
1
1
  import { NgModule } from '@angular/core';
2
2
  import { RouterModule, Routes } from '@angular/router';
3
3
  import { AuthGuard } from './guards/auth.guard';
4
+ import { PermissionsGuard } from './guards/permissions.guard';
4
5
  import { AuthLoginComponent } from './pages/auth-login/auth-login.component';
6
+ import { NotPermittedComponent } from './pages/not-permitted/not-permitted.component';
5
7
  {{#each routes}}
6
8
  import { {{pascalCase this.name}}Component } from './pages/{{kebabCase this.name}}/{{kebabCase this.name}}.component';
7
9
  {{/each}}
8
- import { AUTH_PATH } from './app.config';
10
+ import { AUTH_PATH, NOT_PERMITTED_PATH } from './app.config';
9
11
 
10
12
  export const routes: Routes = [
11
13
  {
@@ -17,11 +19,16 @@ export const routes: Routes = [
17
19
  path: `${AUTH_PATH}`,
18
20
  component: AuthLoginComponent,
19
21
  },
22
+ {
23
+ path: `${NOT_PERMITTED_PATH}`,
24
+ component: NotPermittedComponent,
25
+ },
20
26
  {{#each routes}}
21
27
  {
22
28
  path: '{{kebabCase this.name}}',
23
- canActivate: [AuthGuard],
24
- component: {{pascalCase this.name}}Component ,
29
+ canActivate: [AuthGuard{{#if this.permissions.viewRight}}, PermissionsGuard{{/if}}],
30
+ component: {{pascalCase this.name}}Component,
31
+ data: { permissionCode: '{{this.permissions.viewRight}}' },
25
32
  },
26
33
  {{/each}}
27
34
  ];
@@ -4,7 +4,7 @@ import { AppComponent } from './app.component';
4
4
  describe('AppComponent', () => {
5
5
  beforeEach(async () => {
6
6
  await TestBed.configureTestingModule({
7
- imports: [AppComponent],
7
+ declarations: [AppComponent],
8
8
  }).compileComponents();
9
9
  });
10
10
 
@@ -19,11 +19,5 @@ describe('AppComponent', () => {
19
19
  const app = fixture.componentInstance;
20
20
  expect(app.title).toEqual('{{capitalCase appName}}');
21
21
  });
22
-
23
- it('should render title', () => {
24
- const fixture = TestBed.createComponent(AppComponent);
25
- fixture.detectChanges();
26
- const compiled = fixture.nativeElement as HTMLElement;
27
- expect(compiled.querySelector('h1')?.textContent).toContain('Hello, {{capitalCase appName}}');
28
- });
29
22
  });
23
+
@@ -20,7 +20,6 @@ export class AppComponent {
20
20
  private router: Router,
21
21
  ) {
22
22
  configureFoundationLogin({ router });
23
-
24
23
 
25
24
  // Set layout componet based on route
26
25
  router.events.subscribe((event: any) => {
@@ -2,6 +2,7 @@ import type { MainMenu } from './types/menu'
2
2
  import type { LayoutComponentName } from './types/layout';
3
3
 
4
4
  export const AUTH_PATH = 'login'
5
+ export const NOT_PERMITTED_PATH = 'not-permitted'
5
6
 
6
7
  export const layoutComponentName = {
7
8
  default: 'DefaultLayoutComponent',
@@ -0,0 +1,15 @@
1
+ <section class="error-message-wrapper">
2
+ <div class="error-message" style="color: var(--neutral-foreground-rest); background-color: var(--neutral-layer-4); border-color: var(--error-color); border-radius: 7px; border-style: solid; border-width: 4px; padding: 5px; margin: 15px; text-align: center; width: fit-content;">
3
+ <ng-container [ngSwitch]="elementType">
4
+ <h1 *ngSwitchCase="'h1'">\{{ message }}</h1>
5
+ <h2 *ngSwitchCase="'h2'">\{{ message }}</h2>
6
+ <h3 *ngSwitchCase="'h3'">\{{ message }}</h3>
7
+ <h4 *ngSwitchCase="'h4'">\{{ message }}</h4>
8
+ <h5 *ngSwitchCase="'h5'">\{{ message }}</h5>
9
+ <h6 *ngSwitchCase="'h6'">\{{ message }}</h6>
10
+ <p *ngSwitchCase="'p'">\{{ message }}</p>
11
+ <span *ngSwitchCase="'span'">\{{ message }}</span>
12
+ <div *ngSwitchDefault>\{{ message }}</div>
13
+ </ng-container>
14
+ </div>
15
+ </section>
@@ -0,0 +1,74 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { ErrorMessageComponent } from './error-message.component';
3
+
4
+ describe('ErrorMessageComponent', () => {
5
+ let component: ErrorMessageComponent;
6
+ let fixture: ComponentFixture<ErrorMessageComponent>;
7
+
8
+ beforeEach(async () => {
9
+ await TestBed.configureTestingModule({
10
+ imports: [ErrorMessageComponent],
11
+ }).compileComponents();
12
+
13
+ fixture = TestBed.createComponent(ErrorMessageComponent);
14
+ component = fixture.componentInstance;
15
+ fixture.detectChanges();
16
+ });
17
+
18
+ it('should create', () => {
19
+ expect(component).toBeTruthy();
20
+ });
21
+
22
+ it('should render a message inside an h1 element', () => {
23
+ component.elementType = 'h1';
24
+ component.message = 'Error: Something went wrong!';
25
+ fixture.detectChanges();
26
+
27
+ const compiled = fixture.nativeElement;
28
+ const element = compiled.querySelector('h1');
29
+ expect(element).toBeTruthy();
30
+ expect(element.textContent).toContain('Error: Something went wrong!');
31
+ });
32
+
33
+ it('should render a message inside an h3 element', () => {
34
+ component.elementType = 'h3';
35
+ component.message = 'Warning: Check your inputs.';
36
+ fixture.detectChanges();
37
+
38
+ const compiled = fixture.nativeElement;
39
+ const element = compiled.querySelector('h3');
40
+ expect(element).toBeTruthy();
41
+ expect(element.textContent).toContain('Warning: Check your inputs.');
42
+ });
43
+
44
+ it('should render a message inside a p element', () => {
45
+ component.elementType = 'p';
46
+ component.message = 'Info: Your operation was successful.';
47
+ fixture.detectChanges();
48
+
49
+ const compiled = fixture.nativeElement;
50
+ const element = compiled.querySelector('p');
51
+ expect(element).toBeTruthy();
52
+ expect(element.textContent).toContain('Info: Your operation was successful.');
53
+ });
54
+
55
+ it('should default to div element if no elementType is provided', () => {
56
+ component.elementType = '';
57
+ component.message = 'Default to div element.';
58
+ fixture.detectChanges();
59
+
60
+ const compiled = fixture.nativeElement;
61
+ const element = compiled.querySelector('div');
62
+ expect(element.textContent).toContain('Default to div element.');
63
+ });
64
+
65
+ it('should apply error-message class to the rendered element', () => {
66
+ component.elementType = 'h2';
67
+ component.message = 'Testing class application.';
68
+ fixture.detectChanges();
69
+
70
+ const compiled = fixture.nativeElement;
71
+ const element = compiled.querySelector('.error-message');
72
+ expect(element).toBeTruthy();
73
+ });
74
+ });
@@ -0,0 +1,15 @@
1
+ import { Component, Input } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+
4
+ @Component({
5
+ selector: 'app-error-message',
6
+ templateUrl: './error-message.component.html',
7
+ standalone: true,
8
+ imports: [
9
+ CommonModule,
10
+ ],
11
+ })
12
+ export class ErrorMessageComponent {
13
+ @Input() elementType: string = 'div';
14
+ @Input() message: string = '';
15
+ }
@@ -12,11 +12,11 @@ export class AuthGuard implements CanActivate {
12
12
  private router: Router,
13
13
  ) {}
14
14
 
15
- async canActivate(): Promise<boolean> {
16
- const isUserAuthenticated = await this.authService.isUserAuthenticated();
15
+ canActivate(): boolean {
16
+ const isUserAuthenticated = this.authService.isUserAuthenticated();
17
17
 
18
18
  if (!isUserAuthenticated) {
19
- await this.router.navigate([`/${AUTH_PATH}`]);
19
+ this.router.navigate([`/${AUTH_PATH}`]);
20
20
  return false;
21
21
  }
22
22
  return true;
@@ -0,0 +1,24 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { CanActivate, Router, ActivatedRouteSnapshot } from '@angular/router';
3
+ import { AuthService } from '../services/auth.service';
4
+ import { NOT_PERMITTED_PATH } from '../app.config';
5
+
6
+ @Injectable({
7
+ providedIn: 'root',
8
+ })
9
+ export class PermissionsGuard implements CanActivate {
10
+ constructor(
11
+ private authService: AuthService,
12
+ private router: Router,
13
+ ) {}
14
+
15
+ async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
16
+ const isPermitted = await this.authService.hasUserPermission(route.data['permissionCode']);
17
+
18
+ if (!isPermitted) {
19
+ await this.router.navigate([`/${NOT_PERMITTED_PATH}`]);
20
+ return false;
21
+ }
22
+ return true;
23
+ }
24
+ }
@@ -1,6 +1,5 @@
1
1
  <rapid-design-system-provider #designSystemProvider>
2
2
  <section class="content">
3
3
  <router-outlet></router-outlet>
4
- <app-messages></app-messages>
5
4
  </section>
6
5
  </rapid-design-system-provider>
@@ -10,7 +10,7 @@ describe('BlankLayoutComponent', () => {
10
10
  beforeEach(() => {
11
11
  TestBed.configureTestingModule({
12
12
  declarations: [BlankLayoutComponent],
13
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
13
+ schemas: [ CUSTOM_ELEMENTS_SCHEMA ],
14
14
  });
15
15
  fixture = TestBed.createComponent(BlankLayoutComponent);
16
16
  component = fixture.componentInstance;
@@ -15,6 +15,5 @@
15
15
  </foundation-header>
16
16
  <section class="content">
17
17
  <router-outlet></router-outlet>
18
- <app-messages></app-messages>
19
18
  </section>
20
19
  </rapid-design-system-provider>
@@ -1,34 +1,49 @@
1
- import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2
1
  import { ComponentFixture, TestBed } from '@angular/core/testing';
3
- import { provideMockStore } from '@ngrx/store/testing';
4
- import * as StateChangerSelector from '../../store/state-changer/state-changer.selectors';
5
-
2
+ import { Router } from '@angular/router';
6
3
  import { DefaultLayoutComponent } from './default.layout';
4
+ import { ElementRef, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
5
+
6
+ class MockRouter {
7
+ navigate = jasmine.createSpy('navigate');
8
+ }
9
+
10
+ class MockElementRef implements ElementRef {
11
+ nativeElement = {};
12
+ }
7
13
 
8
14
  describe('DefaultLayoutComponent', () => {
9
15
  let component: DefaultLayoutComponent;
10
16
  let fixture: ComponentFixture<DefaultLayoutComponent>;
17
+ let router: MockRouter;
18
+ let elementRef: MockElementRef;
11
19
 
12
- beforeEach(() => {
13
- TestBed.configureTestingModule({
20
+ beforeEach(async () => {
21
+ await TestBed.configureTestingModule({
14
22
  declarations: [DefaultLayoutComponent],
15
23
  providers: [
16
- provideMockStore({
17
- initialState: {},
18
- selectors: [
19
- { selector: StateChangerSelector.getCriteria, value: 'initial-criteria' },
20
- { selector: StateChangerSelector.getResourceName, value: 'initial-resource-name' },
21
- ],
22
- }),
24
+ { provide: Router, useClass: MockRouter },
25
+ { provide: ElementRef, useClass: MockElementRef }
23
26
  ],
24
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
25
- });
27
+ schemas: [ CUSTOM_ELEMENTS_SCHEMA ],
28
+ }).compileComponents();
29
+ });
30
+
31
+ beforeEach(() => {
26
32
  fixture = TestBed.createComponent(DefaultLayoutComponent);
27
33
  component = fixture.componentInstance;
34
+ router = TestBed.inject(Router) as unknown as MockRouter;
35
+ elementRef = TestBed.inject(ElementRef) as unknown as MockElementRef;
36
+ component.designSystemProviderElement = elementRef;
28
37
  fixture.detectChanges();
29
38
  });
30
39
 
31
40
  it('should create', () => {
32
41
  expect(component).toBeTruthy();
33
42
  });
43
+
44
+ it('should navigate to a path', () => {
45
+ const path = 'some/path';
46
+ component.navigateAngular(path);
47
+ expect(router.navigate).toHaveBeenCalledWith([path]);
48
+ });
34
49
  });
@@ -1,17 +1,17 @@
1
1
  import { ComponentFixture, TestBed } from '@angular/core/testing';
2
2
 
3
- import { AuthMockComponent } from './auth-mock.component';
3
+ import { AuthLoginComponent } from './auth-login.component';
4
4
 
5
- describe('AuthMockComponent', () => {
6
- let component: AuthMockComponent;
7
- let fixture: ComponentFixture<AuthMockComponent>;
5
+ describe('AuthLoginComponent', () => {
6
+ let component: AuthLoginComponent;
7
+ let fixture: ComponentFixture<AuthLoginComponent>;
8
8
 
9
9
  beforeEach(async () => {
10
10
  await TestBed.configureTestingModule({
11
- imports: [AuthMockComponent],
11
+ imports: [AuthLoginComponent],
12
12
  }).compileComponents();
13
13
 
14
- fixture = TestBed.createComponent(AuthMockComponent);
14
+ fixture = TestBed.createComponent(AuthLoginComponent);
15
15
  component = fixture.componentInstance;
16
16
  fixture.detectChanges();
17
17
  });
@@ -0,0 +1,4 @@
1
+ <app-error-message
2
+ elementType="h1"
3
+ message="You do not have permission to access this part of the application, please contact your administrator.">
4
+ </app-error-message>
@@ -0,0 +1,12 @@
1
+ @import '../../../styles/mixins';
2
+
3
+ :host {
4
+ @include screen('flex');
5
+ align-items: center;
6
+ justify-content: center;
7
+ }
8
+
9
+ h1 {
10
+ text-align: center;
11
+ color: var(--neutral-foreground-rest);
12
+ }
@@ -0,0 +1,32 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { NotPermittedComponent } from './not-permitted.component';
3
+
4
+ const MESSAGE_NOT_PERMITTED = 'You do not have permission to access this part of the application, please contact your administrator.';
5
+
6
+ describe('NotPermittedComponent', () => {
7
+ let component: NotPermittedComponent;
8
+ let fixture: ComponentFixture<NotPermittedComponent>;
9
+
10
+ beforeEach(async () => {
11
+ await TestBed.configureTestingModule({
12
+ imports: [ NotPermittedComponent ]
13
+ })
14
+ .compileComponents();
15
+ });
16
+
17
+ beforeEach(() => {
18
+ fixture = TestBed.createComponent(NotPermittedComponent);
19
+ component = fixture.componentInstance;
20
+ fixture.detectChanges();
21
+ });
22
+
23
+ it('should create', () => {
24
+ expect(component).toBeTruthy();
25
+ });
26
+
27
+ it('should display the correct error message', () => {
28
+ const compiled = fixture.nativeElement;
29
+ const errorMessageElement = compiled.querySelector('app-error-message h1');
30
+ expect(errorMessageElement.textContent).toBe(MESSAGE_NOT_PERMITTED);
31
+ });
32
+ });
@@ -0,0 +1,13 @@
1
+ import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2
+ import { ErrorMessageComponent } from '../../components/error-message/error-message.component';
3
+
4
+ @Component({
5
+ selector: 'app-not-permitted',
6
+ standalone: true,
7
+ imports: [ ErrorMessageComponent ],
8
+ templateUrl: './not-permitted.component.html',
9
+ styleUrls: ['./not-permitted.component.scss'],
10
+ schemas: [ CUSTOM_ELEMENTS_SCHEMA ],
11
+ })
12
+ export class NotPermittedComponent {
13
+ }
@@ -1,14 +1,22 @@
1
1
  import { Injectable } from '@angular/core';
2
2
  import { Auth } from '@genesislcap/foundation-comms';
3
- import {DI} from "@microsoft/fast-foundation";
3
+ import { DI } from "@microsoft/fast-foundation";
4
4
 
5
5
  @Injectable({
6
6
  providedIn: 'root',
7
7
  })
8
8
  export class AuthService {
9
+ auth: Auth;
9
10
 
10
- async isUserAuthenticated(): Promise<boolean> {
11
- const auth: Auth = DI.getOrCreateDOMContainer().get(Auth);
12
- return auth.isLoggedIn
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);
13
21
  }
14
22
  }
@@ -3,6 +3,9 @@ import type { Router } from '@angular/router';
3
3
  import { AUTH_PATH } from '../app.config';
4
4
  import { DI } from '@microsoft/fast-foundation';
5
5
 
6
+ // eslint-disable-next-line
7
+ declare var GENX_ENABLE_SSO: boolean;
8
+
6
9
  const ssoSettings =
7
10
  typeof GENX_ENABLE_SSO !== 'undefined' && GENX_ENABLE_SSO === true
8
11
  ? {
@@ -1,2 +1,3 @@
1
1
  export * from './formatters';
2
2
  export * from './getLayoutNameByRoute';
3
+ export * from './permissions';
@@ -0,0 +1,7 @@
1
+ import { User } from '@genesislcap/foundation-user';
2
+
3
+ export const getViewUpdateRightComponent = (
4
+ user: User,
5
+ right: string,
6
+ event: string | boolean = true,
7
+ ) => (!right || user.hasPermission(right) ? event : '');
@@ -0,0 +1,8 @@
1
+ @mixin screen($display: 'block') {
2
+ contain: content;
3
+ display: #{$display};
4
+ height: 100%;
5
+ width: 100%;
6
+ overflow-y: auto;
7
+ }
8
+
@@ -0,0 +1,18 @@
1
+ module.exports = {
2
+ root: true,
3
+ env: { browser: true, es2020: true },
4
+ extends: [
5
+ 'eslint:recommended',
6
+ 'plugin:@typescript-eslint/recommended',
7
+ 'plugin:react-hooks/recommended',
8
+ ],
9
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
10
+ parser: '@typescript-eslint/parser',
11
+ plugins: ['react-refresh'],
12
+ rules: {
13
+ 'react-refresh/only-export-components': [
14
+ 'warn',
15
+ { allowConstantExport: true },
16
+ ],
17
+ },
18
+ }
@@ -0,0 +1,48 @@
1
+
2
+ # {{capitalCase appName}}
3
+
4
+ This project is built with React.
5
+
6
+ ## Development
7
+
8
+ 1. Install dependencies:
9
+
10
+ ```shell
11
+ npm run bootstrap
12
+ ```
13
+
14
+ 2. Start the development server:
15
+
16
+ ```shell
17
+ npm run start
18
+ ```
19
+
20
+ 3. Build for production:
21
+
22
+ ```shell
23
+ npm run build
24
+ ```
25
+
26
+ Preview the production build:
27
+
28
+ ```shell
29
+ npm run serve
30
+ ```
31
+
32
+ ## Clean
33
+
34
+ Remove `build` and `node_modules` directories:
35
+
36
+ ```shell
37
+ npm run clean
38
+ ```
39
+
40
+ Baseline task combines `clean` and `install` tasks into a single command:
41
+
42
+ ```shell
43
+ npm run baseline
44
+ ```
45
+
46
+ ## Further help
47
+
48
+ To get more help on React, check out the [React documentation](https://reactjs.org/docs/getting-started.html).
File without changes
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>{{pkgName}}</title>
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>