newportsite 1.1.3

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 (131) hide show
  1. package/newportsite-1.1.3.tgz +0 -0
  2. package/ng-package.json +7 -0
  3. package/obfuscate.js +70 -0
  4. package/package.json +15 -0
  5. package/src/lib/app.component.ts +47 -0
  6. package/src/lib/app.routing.ts +38 -0
  7. package/src/lib/auth/alert.component.html +5 -0
  8. package/src/lib/auth/alert.component.ts +24 -0
  9. package/src/lib/auth/auth.component.html +1 -0
  10. package/src/lib/auth/auth.component.ts +10 -0
  11. package/src/lib/auth/auth.routes.ts +16 -0
  12. package/src/lib/auth/index.ts +4 -0
  13. package/src/lib/auth/login.component.html +87 -0
  14. package/src/lib/auth/login.component.ts +158 -0
  15. package/src/lib/auth/models/index.ts +1 -0
  16. package/src/lib/auth/models/user.ts +25 -0
  17. package/src/lib/auth/register.component.html +157 -0
  18. package/src/lib/auth/register.component.ts +219 -0
  19. package/src/lib/auth/services/alert.service.ts +47 -0
  20. package/src/lib/auth/services/auth.service.ts +28 -0
  21. package/src/lib/auth/services/index.ts +3 -0
  22. package/src/lib/auth/services/user.service.spec.ts +112 -0
  23. package/src/lib/auth/services/user.service.ts +47 -0
  24. package/src/lib/common/card.component.html +72 -0
  25. package/src/lib/common/card.component.ts +102 -0
  26. package/src/lib/common/commands.component.html +8 -0
  27. package/src/lib/common/commands.component.ts +42 -0
  28. package/src/lib/common/context.component.html +9 -0
  29. package/src/lib/common/context.component.ts +38 -0
  30. package/src/lib/common/grid.component.html +20 -0
  31. package/src/lib/common/grid.component.ts +747 -0
  32. package/src/lib/common/index.ts +9 -0
  33. package/src/lib/common/loader.component.html +5 -0
  34. package/src/lib/common/loader.component.ts +27 -0
  35. package/src/lib/common/lookup.component.html +29 -0
  36. package/src/lib/common/lookup.component.ts +115 -0
  37. package/src/lib/common/messagebox.component.html +39 -0
  38. package/src/lib/common/messagebox.component.ts +74 -0
  39. package/src/lib/common/theme-toggle.component.ts +139 -0
  40. package/src/lib/config.ts +62 -0
  41. package/src/lib/containers/default-layout/default-layout.component.html +191 -0
  42. package/src/lib/containers/default-layout/default-layout.component.ts +158 -0
  43. package/src/lib/containers/default-layout/index.ts +1 -0
  44. package/src/lib/containers/index.ts +1 -0
  45. package/src/lib/directives/component.draggable.ts +80 -0
  46. package/src/lib/directives/index.ts +2 -0
  47. package/src/lib/directives/input.directive.spec.ts +158 -0
  48. package/src/lib/directives/input.directive.ts +210 -0
  49. package/src/lib/home/dashboard/dashboard.component.html +38 -0
  50. package/src/lib/home/dashboard/dashboard.component.ts +50 -0
  51. package/src/lib/home/dashboard/index.ts +1 -0
  52. package/src/lib/home/index.component.html +1 -0
  53. package/src/lib/home/index.component.ts +10 -0
  54. package/src/lib/home/index.routes.ts +29 -0
  55. package/src/lib/home/index.ts +1 -0
  56. package/src/lib/home/info/index.ts +1 -0
  57. package/src/lib/home/info/info.component.css +476 -0
  58. package/src/lib/home/info/info.component.html +174 -0
  59. package/src/lib/home/info/info.component.ts +287 -0
  60. package/src/lib/home/model/article.component.html +10 -0
  61. package/src/lib/home/model/article.component.ts +50 -0
  62. package/src/lib/home/model/barchart.component.html +8 -0
  63. package/src/lib/home/model/barchart.component.ts +59 -0
  64. package/src/lib/home/model/index.ts +7 -0
  65. package/src/lib/home/model/itemdetail.component.html +25 -0
  66. package/src/lib/home/model/itemdetail.component.ts +93 -0
  67. package/src/lib/home/model/itemtab.component.html +25 -0
  68. package/src/lib/home/model/itemtab.component.ts +105 -0
  69. package/src/lib/home/model/model.component.html +121 -0
  70. package/src/lib/home/model/model.component.ts +510 -0
  71. package/src/lib/home/model/modeltoolbar.component.html +111 -0
  72. package/src/lib/home/model/modeltoolbar.component.ts +157 -0
  73. package/src/lib/home/model/navigation.component.html +86 -0
  74. package/src/lib/home/model/navigation.component.ts +247 -0
  75. package/src/lib/home/model/services/index.ts +1 -0
  76. package/src/lib/home/model/services/model.service.spec.ts +423 -0
  77. package/src/lib/home/model/services/model.service.ts +319 -0
  78. package/src/lib/home/modelsearch/index.ts +1 -0
  79. package/src/lib/home/modelsearch/modelsearch.component.html +124 -0
  80. package/src/lib/home/modelsearch/modelsearch.component.ts +453 -0
  81. package/src/lib/interfaces/data.interface.ts +131 -0
  82. package/src/lib/interfaces/index.ts +2 -0
  83. package/src/lib/interfaces/item.interface.ts +438 -0
  84. package/src/lib/players/lookup/lookup.directive.ts +6 -0
  85. package/src/lib/players/lookup/lookup.item.component.ts +37 -0
  86. package/src/lib/players/lookup/lookup.item.ts +9 -0
  87. package/src/lib/players/lookup/lookup.player.component.ts +59 -0
  88. package/src/lib/players/lookup/lookup.selector.component.ts +41 -0
  89. package/src/lib/players/model/model.directive.ts +6 -0
  90. package/src/lib/players/model/model.item.component.spec.ts +311 -0
  91. package/src/lib/players/model/model.item.component.ts +3457 -0
  92. package/src/lib/players/model/model.item.ts +9 -0
  93. package/src/lib/players/model/model.player.component.ts +109 -0
  94. package/src/lib/players/model/model.selector.component.ts +59 -0
  95. package/src/lib/scheduler/scheduler.component.html +13 -0
  96. package/src/lib/scheduler/scheduler.component.scss +6 -0
  97. package/src/lib/scheduler/scheduler.component.ts +296 -0
  98. package/src/lib/scheduler/scheduler.routes.ts +15 -0
  99. package/src/lib/scheduler/schedulerdialog.component.html +72 -0
  100. package/src/lib/scheduler/schedulerdialog.component.ts +208 -0
  101. package/src/lib/scheduler/services/scheduler.service.ts +133 -0
  102. package/src/lib/services/auth-state.service.ts +129 -0
  103. package/src/lib/services/auth.interceptor.spec.ts +144 -0
  104. package/src/lib/services/auth.interceptor.ts +44 -0
  105. package/src/lib/services/cache.service.spec.ts +143 -0
  106. package/src/lib/services/cache.service.ts +71 -0
  107. package/src/lib/services/global-error-handler.spec.ts +39 -0
  108. package/src/lib/services/global-error-handler.ts +28 -0
  109. package/src/lib/services/global.service.spec.ts +801 -0
  110. package/src/lib/services/global.service.ts +724 -0
  111. package/src/lib/services/message.service.ts +556 -0
  112. package/src/lib/services/theme.service.ts +96 -0
  113. package/src/lib/template/authtemplate.component.html +6 -0
  114. package/src/lib/template/authtemplate.component.ts +13 -0
  115. package/src/lib/template/basetemplate.component.html +7 -0
  116. package/src/lib/template/basetemplate.component.ts +13 -0
  117. package/src/lib/template/index.ts +3 -0
  118. package/src/lib/template/modeltemplate.component.html +7 -0
  119. package/src/lib/template/modeltemplate.component.ts +21 -0
  120. package/src/lib/utils/piva.spec.ts +56 -0
  121. package/src/lib/utils/piva.ts +29 -0
  122. package/src/lib/validators/email.validator.spec.ts +57 -0
  123. package/src/lib/validators/email.validator.ts +17 -0
  124. package/src/lib/validators/equalPasswords.validator.spec.ts +54 -0
  125. package/src/lib/validators/equalPasswords.validator.ts +17 -0
  126. package/src/lib/validators/index.ts +2 -0
  127. package/src/lib/version.ts +1 -0
  128. package/src/public-api.ts +64 -0
  129. package/src/typings.d.ts +2 -0
  130. package/tsconfig.lib.json +18 -0
  131. package/tsconfig.lib.prod.json +9 -0
Binary file
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "lib": {
4
+ "entryFile": "src/public-api.ts"
5
+ },
6
+ "dest": "../../dist/newportsite"
7
+ }
package/obfuscate.js ADDED
@@ -0,0 +1,70 @@
1
+ const obfuscator = require('javascript-obfuscator');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const { execSync } = require('child_process');
5
+
6
+ const SRC_DIR = path.join(__dirname, '../../dist/newportsite');
7
+ const OUT_DIR = path.join(__dirname, '../../dist/newportsite-obfuscated');
8
+
9
+ // Sync version.ts with package.json so the displayed version is always correct
10
+ const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
11
+ const versionFile = path.join(__dirname, 'src/lib/version.ts');
12
+ fs.writeFileSync(versionFile, `export const PACKAGE_VERSION = '${pkg.version}';\n`, 'utf8');
13
+ console.log(`version.ts synced to ${pkg.version}`);
14
+
15
+ function ensureDirSync(dir) {
16
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
17
+ }
18
+
19
+ function obfuscateDir(src, out) {
20
+ ensureDirSync(out);
21
+ for (const file of fs.readdirSync(src)) {
22
+ const srcPath = path.join(src, file);
23
+ const outPath = path.join(out, file);
24
+ if (fs.statSync(srcPath).isDirectory()) {
25
+ obfuscateDir(srcPath, outPath);
26
+ } else if (file.endsWith('.map')) {
27
+ // drop source maps — they would reverse the obfuscation
28
+ } else if (file.endsWith('.js') || file.endsWith('.mjs')) {
29
+ const code = fs.readFileSync(srcPath, 'utf8');
30
+ const result = obfuscator.obfuscate(code, {
31
+ compact: true,
32
+ controlFlowFlattening: true,
33
+ controlFlowFlatteningThreshold: 0.5,
34
+ deadCodeInjection: false,
35
+ stringArray: true,
36
+ stringArrayThreshold: 0.75,
37
+ sourceMap: false,
38
+ });
39
+ fs.writeFileSync(outPath, result.getObfuscatedCode(), 'utf8');
40
+ } else if (file === 'package.json') {
41
+ // fix package.json: remove the wrong relative `main`, keep the rest
42
+ const pkg = JSON.parse(fs.readFileSync(srcPath, 'utf8'));
43
+ delete pkg.main;
44
+ fs.writeFileSync(outPath, JSON.stringify(pkg, null, 2), 'utf8');
45
+ } else {
46
+ fs.copyFileSync(srcPath, outPath);
47
+ }
48
+ }
49
+ }
50
+
51
+ if (!fs.existsSync(SRC_DIR)) {
52
+ console.error('ERROR: dist/newportsite not found. Run "ng build newportsite" first.');
53
+ process.exit(1);
54
+ }
55
+
56
+ // clean previous output to avoid stale files (e.g. old .map files)
57
+ if (fs.existsSync(OUT_DIR)) fs.rmSync(OUT_DIR, { recursive: true, force: true });
58
+
59
+ obfuscateDir(SRC_DIR, OUT_DIR);
60
+ console.log('Obfuscation complete:', OUT_DIR);
61
+
62
+ // Pack from the obfuscated dist so the .tgz is self-contained
63
+ execSync('npm pack', { cwd: OUT_DIR, stdio: 'inherit' });
64
+ const tgzFiles = fs.readdirSync(OUT_DIR).filter(f => f.endsWith('.tgz'));
65
+ if (tgzFiles.length) {
66
+ const tgzPath = path.join(OUT_DIR, tgzFiles[0]);
67
+ const dest = path.join(__dirname, tgzFiles[0]);
68
+ fs.copyFileSync(tgzPath, dest);
69
+ console.log('Package ready:', dest);
70
+ }
package/package.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "newportsite",
3
+ "version": "1.1.3",
4
+ "sideEffects": false,
5
+ "peerDependencies": {
6
+ "@angular/common": "^21.0.0",
7
+ "@angular/core": "^21.0.0",
8
+ "@angular/forms": "^21.0.0",
9
+ "@angular/router": "^21.0.0"
10
+ },
11
+ "scripts": {
12
+ "build": "ng build newportsite --configuration production",
13
+ "publish": "ng build newportsite --configuration production && node obfuscate.js && npm publish --access public"
14
+ }
15
+ }
@@ -0,0 +1,47 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ inject,
5
+ signal,
6
+ } from '@angular/core';
7
+ import { Router, NavigationEnd, RouterOutlet } from '@angular/router';
8
+ import { filter } from 'rxjs/operators';
9
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
10
+ import { GlobalErrorHandler } from './services/global-error-handler';
11
+
12
+ @Component({
13
+ selector: 'body',
14
+ template: `
15
+ <router-outlet><div [hidden]="!loading()" class="loader"></div></router-outlet>
16
+ @if (errorHandler.lastError()) {
17
+ <div
18
+ class="alert alert-danger alert-dismissible position-fixed bottom-0 start-50 translate-middle-x mb-3"
19
+ style="z-index:9999; min-width:300px"
20
+ role="alert"
21
+ >
22
+ {{ errorHandler.lastError() }}
23
+ <button type="button" class="btn-close" (click)="errorHandler.clearError()"></button>
24
+ </div>
25
+ }
26
+ `,
27
+ changeDetection: ChangeDetectionStrategy.OnPush,
28
+ imports: [RouterOutlet],
29
+ })
30
+ export class AppComponent {
31
+ private router = inject(Router);
32
+ readonly errorHandler = inject(GlobalErrorHandler);
33
+
34
+ loading = signal(true);
35
+
36
+ constructor() {
37
+ this.router.events
38
+ .pipe(
39
+ filter(evt => evt instanceof NavigationEnd),
40
+ takeUntilDestroyed()
41
+ )
42
+ .subscribe(() => {
43
+ this.loading.set(false);
44
+ window.scrollTo(0, 0);
45
+ });
46
+ }
47
+ }
@@ -0,0 +1,38 @@
1
+ import { Routes } from '@angular/router';
2
+ import { authGuard } from './auth/services/auth.service';
3
+
4
+ // Import Containers
5
+ import { DefaultLayoutComponent } from './containers';
6
+
7
+ export const APP_ROUTES: Routes = [
8
+ {
9
+ path: '',
10
+ component: DefaultLayoutComponent,
11
+ data: {
12
+ title: 'Home',
13
+ },
14
+ children: [
15
+ {
16
+ path: 'home',
17
+ loadChildren: () =>
18
+ import('./home/index.routes').then(r => r.INDEX_ROUTES),
19
+ },
20
+ {
21
+ path: 'auth',
22
+ loadChildren: () =>
23
+ import('./auth/auth.routes').then(r => r.AUTH_ROUTES),
24
+ },
25
+ {
26
+ path: 'scheduler',
27
+ canActivate: [authGuard],
28
+ loadChildren: () =>
29
+ import('./scheduler/scheduler.routes').then(r => r.SCHEDULER_ROUTES),
30
+ },
31
+ {
32
+ path: '**',
33
+ redirectTo: '/home',
34
+ pathMatch: 'full',
35
+ },
36
+ ],
37
+ },
38
+ ];
@@ -0,0 +1,5 @@
1
+ @if (message()) {
2
+ <div [ngClass]="alertClass">
3
+ {{ message()?.text }}
4
+ </div>
5
+ }
@@ -0,0 +1,24 @@
1
+ import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
2
+ import { AlertService } from './services/index';
3
+ import { NgClass } from '@angular/common';
4
+ import { toSignal } from '@angular/core/rxjs-interop';
5
+
6
+ @Component({
7
+ selector: 'alert',
8
+ templateUrl: 'alert.component.html',
9
+ changeDetection: ChangeDetectionStrategy.OnPush,
10
+ imports: [NgClass],
11
+ })
12
+ export class AlertComponent {
13
+ private alertService = inject(AlertService);
14
+
15
+ message = toSignal(this.alertService.getMessage());
16
+
17
+ get alertClass() {
18
+ return {
19
+ alert: !!this.message(),
20
+ 'alert-success': this.message()?.type === 'success',
21
+ 'alert-danger': this.message()?.type === 'error',
22
+ };
23
+ }
24
+ }
@@ -0,0 +1 @@
1
+ <router-outlet></router-outlet>
@@ -0,0 +1,10 @@
1
+ import { Component, ChangeDetectionStrategy } from '@angular/core';
2
+ import { RouterOutlet } from '@angular/router';
3
+
4
+ @Component({
5
+ selector: 'auth',
6
+ templateUrl: 'auth.component.html',
7
+ changeDetection: ChangeDetectionStrategy.OnPush,
8
+ imports: [RouterOutlet],
9
+ })
10
+ export class AuthComponent {}
@@ -0,0 +1,16 @@
1
+ import { Routes } from '@angular/router';
2
+ import { AuthComponent } from './auth.component';
3
+ import { LoginComponent } from './login.component';
4
+ import { RegisterComponent } from './register.component';
5
+
6
+ export const AUTH_ROUTES: Routes = [
7
+ {
8
+ path: '',
9
+ component: AuthComponent,
10
+ children: [
11
+ { path: 'login', component: LoginComponent },
12
+ { path: 'register', component: RegisterComponent },
13
+ { path: '**', redirectTo: '/auth/login', pathMatch: 'full' },
14
+ ],
15
+ },
16
+ ];
@@ -0,0 +1,4 @@
1
+ export * from './auth.component';
2
+ export * from './login.component';
3
+ export * from './register.component';
4
+ export * from './alert.component';
@@ -0,0 +1,87 @@
1
+ <!-- login.component -->
2
+ <authtemplate>
3
+ <div
4
+ class="auth-card"
5
+ [class.pe-none]="gsv?.getLoading()"
6
+ [class.loading-dimmed]="gsv?.getLoading()">
7
+ <div class="auth-brand">
8
+ <div class="auth-logo">
9
+ <i class="bi bi-grid-1x2-fill"></i>
10
+ </div>
11
+ <h1 class="auth-app-name">Newport</h1>
12
+ <p class="auth-subtitle">{{ msg.get('app.auth.accountAccess') }}</p>
13
+ </div>
14
+
15
+ <form
16
+ [formGroup]="form"
17
+ (ngSubmit)="onSubmit(form.value)"
18
+ aria-label="Modulo di accesso"
19
+ autocomplete="on">
20
+ <div class="auth-field">
21
+ <span class="auth-field-icon" aria-hidden="true"><i class="bi bi-person"></i></span>
22
+ <label for="login" class="visually-hidden">{{ msg.get('app.login') }}</label>
23
+ <input
24
+ nvg
25
+ [attr.data-state]="0"
26
+ [formControl]="login"
27
+ type="text"
28
+ class="form-control auth-input"
29
+ id="login"
30
+ [placeholder]="msg.get('app.login')"
31
+ [attr.aria-label]="msg.get('app.login')"
32
+ aria-required="true"
33
+ autocomplete="username" />
34
+ </div>
35
+
36
+ <div class="auth-field">
37
+ <span class="auth-field-icon" aria-hidden="true"><i class="bi bi-lock"></i></span>
38
+ <label for="password" class="visually-hidden">{{ msg.get('app.password') }}</label>
39
+ <input
40
+ nvg
41
+ [attr.data-state]="0"
42
+ [formControl]="password"
43
+ [type]="showPassword ? 'text' : 'password'"
44
+ class="form-control auth-input auth-input-padded"
45
+ id="password"
46
+ [placeholder]="msg.get('app.password')"
47
+ [attr.aria-label]="msg.get('app.password')"
48
+ aria-required="true"
49
+ autocomplete="current-password" />
50
+ <button
51
+ type="button"
52
+ class="auth-toggle-btn"
53
+ tabindex="-1"
54
+ [attr.aria-pressed]="showPassword"
55
+ [attr.aria-label]="showPassword ? 'Nascondi password' : 'Mostra password'"
56
+ (click)="showPassword = !showPassword"
57
+ [title]="showPassword ? 'Nascondi password' : 'Mostra password'">
58
+ <i
59
+ class="bi"
60
+ aria-hidden="true"
61
+ [class.bi-eye]="!showPassword"
62
+ [class.bi-eye-slash]="showPassword"></i>
63
+ </button>
64
+ </div>
65
+
66
+ <button
67
+ type="submit"
68
+ nvg
69
+ [attr.data-state]="0"
70
+ [disabled]="!form.valid"
71
+ [attr.aria-disabled]="!form.valid"
72
+ class="btn btn-primary btn-auth-submit">
73
+ {{ msg.get('app.authtitle') }}
74
+ </button>
75
+
76
+ <div class="auth-alt-action">
77
+ <span>{{ msg.get('app.auth.accountNoAccess') }}</span>
78
+ <a [routerLink]="'/auth/register'" class="auth-alt-link">{{
79
+ msg.get('app.register')
80
+ }}</a>
81
+ </div>
82
+ </form>
83
+
84
+ <alert></alert>
85
+ </div>
86
+ </authtemplate>
87
+ <!-- fine login.component -->
@@ -0,0 +1,158 @@
1
+ import {
2
+ Component,
3
+ AfterViewInit,
4
+ ChangeDetectionStrategy,
5
+ ChangeDetectorRef,
6
+ DestroyRef,
7
+ inject,
8
+ } from '@angular/core';
9
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
10
+ import {
11
+ FormGroup,
12
+ AbstractControl,
13
+ FormBuilder,
14
+ Validators,
15
+ ReactiveFormsModule,
16
+ } from '@angular/forms';
17
+ import { RouterLink } from '@angular/router';
18
+
19
+ import { GlobalService } from '../services/global.service';
20
+ import { AppMessageService } from '../services/message.service';
21
+ import { AlertService, UserService } from './services/index';
22
+ import { User } from '../auth/models/user';
23
+ import { ManagmentService } from '../home/model/services/index';
24
+ import { NEWPORT_CONFIG } from '../config';
25
+ import { AuthTemplateComponent } from '../template/authtemplate.component';
26
+ import { InputDirective } from '../directives/input.directive';
27
+ import { AlertComponent } from './alert.component';
28
+
29
+ @Component({
30
+ templateUrl: 'login.component.html',
31
+ changeDetection: ChangeDetectionStrategy.OnPush,
32
+ providers: [AlertService, UserService],
33
+ imports: [
34
+ AuthTemplateComponent,
35
+ ReactiveFormsModule,
36
+ RouterLink,
37
+ InputDirective,
38
+ AlertComponent,
39
+ ],
40
+ })
41
+ export class LoginComponent implements AfterViewInit {
42
+ gsv = inject(GlobalService);
43
+ als = inject(AlertService);
44
+ usv = inject(UserService);
45
+ fb = inject(FormBuilder);
46
+ msg = inject(AppMessageService);
47
+ msv = inject(ManagmentService);
48
+ private config = inject(NEWPORT_CONFIG);
49
+
50
+ private cdr = inject(ChangeDetectorRef);
51
+ private destroyRef = inject(DestroyRef);
52
+ public form!: FormGroup;
53
+ public login!: AbstractControl;
54
+ public password!: AbstractControl;
55
+ public submitted = false;
56
+ public showPassword = false;
57
+ public returnUrl = '/home/dashboard';
58
+
59
+ constructor() {
60
+ this.form = this.fb.group({
61
+ login: ['', Validators.required],
62
+ password: ['', Validators.required],
63
+ });
64
+
65
+ this.login = this.form.controls['login'];
66
+ this.password = this.form.controls['password'];
67
+
68
+ this.gsv
69
+ .getStateChanged()
70
+ .pipe(takeUntilDestroyed(this.destroyRef))
71
+ .subscribe(() => this.cdr.markForCheck());
72
+ }
73
+
74
+ /** Lifecycle: focuses the login field and clears any stale auth data from localStorage. */
75
+ public ngAfterViewInit(): void {
76
+ const loginElement = document.getElementById('login');
77
+ loginElement?.focus();
78
+ try {
79
+ localStorage.removeItem('currentUser');
80
+ } catch (error) {
81
+ console.error('Error clearing auth data from localStorage:', error);
82
+ }
83
+ }
84
+
85
+ /** Validates the form, authenticates via UserService, then stores user data and navigates to home. */
86
+ public onSubmit(user: User): void {
87
+ this.submitted = true;
88
+ if (!this.form.valid) {
89
+ return;
90
+ }
91
+
92
+ this.gsv.setLoaderState(true);
93
+ this.usv
94
+ .put(user)
95
+ .pipe(takeUntilDestroyed(this.destroyRef))
96
+ .subscribe({
97
+ next: (data: User) => {
98
+ const loggedUser = new User();
99
+ Object.assign(loggedUser, {
100
+ token: data.token,
101
+ login: data.login,
102
+ name: data.name,
103
+ email: data.email,
104
+ postalcode: data.postalcode,
105
+ address1: data.address1,
106
+ address2: data.address2,
107
+ cinnumber: data.cinnumber,
108
+ contact: data.contact,
109
+ country: data.country,
110
+ county: data.county,
111
+ faxnumber: data.faxnumber,
112
+ mobilenumber: data.mobilenumber,
113
+ telephonenumber: data.telephonenumber,
114
+ vatnumber: data.vatnumber,
115
+ city: data.city,
116
+ website: data.website,
117
+ });
118
+
119
+ this.gsv.setCurrentUser(loggedUser);
120
+ this.gsv.setYears(data.years);
121
+ this.gsv.setYear(data.years[0]);
122
+ this.gsv.setProjects(data.projects);
123
+ this.gsv.setProject(null);
124
+ this.loadBaseTable()
125
+ .then(() => {
126
+ this.gsv.navigate(this.returnUrl);
127
+ this.gsv.setLoaderState(false);
128
+ })
129
+ .catch(() => {
130
+ this.gsv.navigate(this.returnUrl);
131
+ this.gsv.setLoaderState(false);
132
+ });
133
+ },
134
+ error: () => {
135
+ this.als.error(this.msg.get('app.loginfailed'));
136
+ this.gsv.setLoaderState(false);
137
+ },
138
+ });
139
+ }
140
+
141
+ /** Preloads the base lookup tables (commune/postal-code) into the app data cache after login. */
142
+ public async loadBaseTable(): Promise<void> {
143
+ const lkFieldsIds: string[] = [
144
+ `TBB.MTBB_COM.${this.gsv.getYear()}`,
145
+ `TBB.MTBB_CAP.${this.gsv.getYear()}`,
146
+ ];
147
+
148
+ for (const entry of lkFieldsIds) {
149
+ const data = await (this.config.staticTableLoader?.(entry) ?? '');
150
+ this.gsv.setData(entry, JSON.parse(data));
151
+ }
152
+ }
153
+
154
+ /** Delegates client-side navigation to GlobalService. */
155
+ public navigate(url: string): void {
156
+ this.gsv.navigate(url);
157
+ }
158
+ }
@@ -0,0 +1 @@
1
+ export * from './user';
@@ -0,0 +1,25 @@
1
+ import { UserLicenses } from '../../interfaces/index';
2
+
3
+ export class User {
4
+ public login: string = '';
5
+ public name: string = '';
6
+ public email: string = '';
7
+ public password: string = '';
8
+ public token: string = '';
9
+ public refreshToken: string = '';
10
+ public address1: string = '';
11
+ public address2: string = '';
12
+ public cinnumber: string = '';
13
+ public contact: string = '';
14
+ public country: string = '';
15
+ public county: string = '';
16
+ public faxnumber: string = '';
17
+ public mobilenumber: string = '';
18
+ public postalcode: string = '';
19
+ public telephonenumber: string = '';
20
+ public vatnumber: string = '';
21
+ public city: string = '';
22
+ public website: string = '';
23
+ public years: number[] = [];
24
+ public projects: UserLicenses[][] = [];
25
+ }