@cccteam/ccc-lib 0.0.11 → 0.0.12

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 (77) hide show
  1. package/fesm2022/cccteam-ccc-lib-src-auth-authentication-guard.mjs +44 -0
  2. package/fesm2022/cccteam-ccc-lib-src-auth-authentication-guard.mjs.map +1 -0
  3. package/fesm2022/cccteam-ccc-lib-src-auth-authorization-guard.mjs +24 -0
  4. package/fesm2022/cccteam-ccc-lib-src-auth-authorization-guard.mjs.map +1 -0
  5. package/fesm2022/cccteam-ccc-lib-src-auth-forms.mjs +118 -0
  6. package/fesm2022/cccteam-ccc-lib-src-auth-forms.mjs.map +1 -0
  7. package/fesm2022/cccteam-ccc-lib-src-auth-has-permission.mjs +51 -0
  8. package/fesm2022/cccteam-ccc-lib-src-auth-has-permission.mjs.map +1 -0
  9. package/fesm2022/cccteam-ccc-lib-src-auth-service.mjs +56 -0
  10. package/fesm2022/cccteam-ccc-lib-src-auth-service.mjs.map +1 -0
  11. package/fesm2022/cccteam-ccc-lib-src-auth-state.mjs +109 -0
  12. package/fesm2022/cccteam-ccc-lib-src-auth-state.mjs.map +1 -0
  13. package/fesm2022/cccteam-ccc-lib-src-types.mjs +137 -0
  14. package/fesm2022/cccteam-ccc-lib-src-types.mjs.map +1 -0
  15. package/fesm2022/cccteam-ccc-lib-src-ui-alert.mjs +48 -0
  16. package/fesm2022/cccteam-ccc-lib-src-ui-alert.mjs.map +1 -0
  17. package/fesm2022/cccteam-ccc-lib-src-ui-core-state.mjs +100 -0
  18. package/fesm2022/cccteam-ccc-lib-src-ui-core-state.mjs.map +1 -0
  19. package/fesm2022/cccteam-ccc-lib-src-ui-interceptor.mjs +48 -0
  20. package/fesm2022/cccteam-ccc-lib-src-ui-interceptor.mjs.map +1 -0
  21. package/fesm2022/cccteam-ccc-lib-src-ui-notification-service.mjs +57 -0
  22. package/fesm2022/cccteam-ccc-lib-src-ui-notification-service.mjs.map +1 -0
  23. package/fesm2022/cccteam-ccc-lib-src-ui-sidenav.mjs +70 -0
  24. package/fesm2022/cccteam-ccc-lib-src-ui-sidenav.mjs.map +1 -0
  25. package/fesm2022/cccteam-ccc-lib-src-util-request-options.mjs +19 -0
  26. package/fesm2022/cccteam-ccc-lib-src-util-request-options.mjs.map +1 -0
  27. package/fesm2022/cccteam-ccc-lib.mjs +13 -729
  28. package/fesm2022/cccteam-ccc-lib.mjs.map +1 -1
  29. package/package.json +54 -2
  30. package/public-api.d.ts +13 -19
  31. package/src/auth-authentication-guard/index.d.ts +5 -0
  32. package/src/auth-authentication-guard/public-api.d.ts +1 -0
  33. package/src/auth-authorization-guard/index.d.ts +5 -0
  34. package/src/auth-authorization-guard/public-api.d.ts +1 -0
  35. package/{lib/auth/forms → src/auth-forms}/ccc-field/ccc-field.component.d.ts +1 -1
  36. package/src/auth-forms/index.d.ts +5 -0
  37. package/src/auth-forms/public-api.d.ts +2 -0
  38. package/{lib/auth/directives → src/auth-has-permission}/has-permission.directive.d.ts +1 -1
  39. package/src/auth-has-permission/index.d.ts +5 -0
  40. package/src/auth-has-permission/public-api.d.ts +1 -0
  41. package/{lib/auth/services → src/auth-service}/auth.service.d.ts +1 -1
  42. package/src/auth-service/index.d.ts +5 -0
  43. package/src/auth-service/public-api.d.ts +1 -0
  44. package/{lib/auth/state → src/auth-state}/auth.state.d.ts +1 -2
  45. package/src/auth-state/index.d.ts +5 -0
  46. package/src/auth-state/public-api.d.ts +1 -0
  47. package/{lib/auth/state → src/types}/auth.actions.d.ts +1 -1
  48. package/{lib/ui/state → src/types}/core.actions.d.ts +1 -1
  49. package/src/types/index.d.ts +5 -0
  50. package/src/types/public-api.d.ts +6 -0
  51. package/{lib/types/base → src/types}/tokens.d.ts +1 -1
  52. package/{lib/ui/components/alert → src/ui-alert}/alert.component.d.ts +2 -2
  53. package/src/ui-alert/index.d.ts +5 -0
  54. package/src/ui-alert/public-api.d.ts +1 -0
  55. package/{lib/ui/state → src/ui-core-state}/core.state.d.ts +1 -2
  56. package/src/ui-core-state/index.d.ts +5 -0
  57. package/src/ui-core-state/public-api.d.ts +1 -0
  58. package/src/ui-interceptor/index.d.ts +5 -0
  59. package/src/ui-interceptor/public-api.d.ts +1 -0
  60. package/src/ui-notification-service/index.d.ts +5 -0
  61. package/{lib/ui/services → src/ui-notification-service}/notification.service.d.ts +1 -1
  62. package/src/ui-notification-service/public-api.d.ts +1 -0
  63. package/src/ui-sidenav/index.d.ts +5 -0
  64. package/src/ui-sidenav/public-api.d.ts +1 -0
  65. package/{lib/ui/components/sidenav → src/ui-sidenav}/sidenav.component.d.ts +1 -1
  66. package/src/util-request-options/index.d.ts +5 -0
  67. package/src/util-request-options/public-api.d.ts +1 -0
  68. package/cccteam-ccc-lib-0.0.10.tgz +0 -0
  69. package/cccteam-ccc-lib-0.0.11.tgz +0 -0
  70. /package/{lib/auth/guards → src/auth-authentication-guard}/authentication.guard.d.ts +0 -0
  71. /package/{lib/auth/guards → src/auth-authorization-guard}/authorization.guard.d.ts +0 -0
  72. /package/{lib/auth/forms → src/auth-forms}/form-helpers.d.ts +0 -0
  73. /package/{lib → src}/types/notification-message.d.ts +0 -0
  74. /package/{lib → src}/types/permissions.d.ts +0 -0
  75. /package/{lib → src}/types/session-info.d.ts +0 -0
  76. /package/{lib/ui/interceptor → src/ui-interceptor}/api.interceptor.d.ts +0 -0
  77. /package/{lib/auth/services → src/util-request-options}/request-options.d.ts +0 -0
@@ -0,0 +1,48 @@
1
+ import * as i3 from '@angular/common';
2
+ import { CommonModule } from '@angular/common';
3
+ import * as i0 from '@angular/core';
4
+ import { EventEmitter, inject, Component, Input, Output } from '@angular/core';
5
+ import * as i2 from '@angular/material/button';
6
+ import { MatButtonModule } from '@angular/material/button';
7
+ import * as i1 from '@angular/material/icon';
8
+ import { MatIconModule } from '@angular/material/icon';
9
+ import * as i4 from '@angular/router';
10
+ import { RouterModule } from '@angular/router';
11
+ import { NotificationService } from '@cccteam/ccc-lib/src/ui-notification-service';
12
+
13
+ class AlertComponent {
14
+ error;
15
+ dismiss = new EventEmitter();
16
+ errors = inject(NotificationService);
17
+ ngOnInit() {
18
+ if (this.error.duration === undefined) {
19
+ this.error.duration = 30000;
20
+ }
21
+ setTimeout(() => {
22
+ this.dismissAlert();
23
+ }, this.error.duration);
24
+ }
25
+ dismissAlert() {
26
+ if (this.error.id !== undefined) {
27
+ this.errors.dismissGlobalNotification(this.error);
28
+ }
29
+ }
30
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: AlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
31
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.3", type: AlertComponent, isStandalone: true, selector: "ccc-alert", inputs: { error: "error" }, outputs: { dismiss: "dismiss" }, ngImport: i0, template: "<div class=\"alert\" [ngClass]=\"error.level\">\n <div class=\"message\">\n <span>{{ error.message }}</span>\n </div>\n <div class=\"alert-end\">\n @if (error.link) {\n <span [routerLink]=\"error.link\" class=\"link\">View</span>\n }\n <button (click)=\"dismissAlert()\" mat-icon-button aria-label=\"Close Alert\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n</div>\n", styles: [".alert{margin:auto;border:1px solid;max-width:450px;border-radius:5px;background-color:#d3d3d3;display:flex;flex-direction:row;align-items:center;justify-content:space-between}.message{padding-left:15px;max-width:400px;display:flex;justify-content:space-between}.alert-end{display:flex;flex-direction:row;align-items:center;gap:5px}.link{cursor:pointer}.link:hover{text-decoration:underline}.warn{border-color:red;background-color:#fff5f4}.accent{border-color:#dfb51d;background-color:#fff8e0}.success{border-color:#4caf50;background-color:#f0fff0}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i4.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
32
+ }
33
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: AlertComponent, decorators: [{
34
+ type: Component,
35
+ args: [{ selector: 'ccc-alert', imports: [MatIconModule, MatButtonModule, CommonModule, RouterModule], template: "<div class=\"alert\" [ngClass]=\"error.level\">\n <div class=\"message\">\n <span>{{ error.message }}</span>\n </div>\n <div class=\"alert-end\">\n @if (error.link) {\n <span [routerLink]=\"error.link\" class=\"link\">View</span>\n }\n <button (click)=\"dismissAlert()\" mat-icon-button aria-label=\"Close Alert\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n</div>\n", styles: [".alert{margin:auto;border:1px solid;max-width:450px;border-radius:5px;background-color:#d3d3d3;display:flex;flex-direction:row;align-items:center;justify-content:space-between}.message{padding-left:15px;max-width:400px;display:flex;justify-content:space-between}.alert-end{display:flex;flex-direction:row;align-items:center;gap:5px}.link{cursor:pointer}.link:hover{text-decoration:underline}.warn{border-color:red;background-color:#fff5f4}.accent{border-color:#dfb51d;background-color:#fff8e0}.success{border-color:#4caf50;background-color:#f0fff0}\n"] }]
36
+ }], propDecorators: { error: [{
37
+ type: Input,
38
+ args: [{ required: true }]
39
+ }], dismiss: [{
40
+ type: Output
41
+ }] } });
42
+
43
+ /**
44
+ * Generated bundle index. Do not edit.
45
+ */
46
+
47
+ export { AlertComponent };
48
+ //# sourceMappingURL=cccteam-ccc-lib-src-ui-alert.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cccteam-ccc-lib-src-ui-alert.mjs","sources":["../../../projects/ccc-lib/src/ui-alert/alert.component.ts","../../../projects/ccc-lib/src/ui-alert/alert.component.html","../../../projects/ccc-lib/src/ui-alert/cccteam-ccc-lib-src-ui-alert.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { RouterModule } from '@angular/router';\nimport { NotificationMessage } from '@cccteam/ccc-lib/src/types';\nimport { NotificationService } from '@cccteam/ccc-lib/src/ui-notification-service';\n\n@Component({\n selector: 'ccc-alert',\n templateUrl: './alert.component.html',\n styleUrls: ['./alert.component.scss'],\n imports: [MatIconModule, MatButtonModule, CommonModule, RouterModule],\n})\nexport class AlertComponent implements OnInit {\n @Input({ required: true }) error!: NotificationMessage;\n @Output() dismiss = new EventEmitter();\n\n errors = inject(NotificationService);\n ngOnInit(): void {\n if (this.error.duration === undefined) {\n this.error.duration = 30000;\n }\n\n setTimeout(() => {\n this.dismissAlert();\n }, this.error.duration);\n }\n\n dismissAlert(): void {\n if (this.error.id !== undefined) {\n this.errors.dismissGlobalNotification(this.error);\n }\n }\n}\n","<div class=\"alert\" [ngClass]=\"error.level\">\n <div class=\"message\">\n <span>{{ error.message }}</span>\n </div>\n <div class=\"alert-end\">\n @if (error.link) {\n <span [routerLink]=\"error.link\" class=\"link\">View</span>\n }\n <button (click)=\"dismissAlert()\" mat-icon-button aria-label=\"Close Alert\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;;;;;;MAca,cAAc,CAAA;AACE,IAAA,KAAK;AACtB,IAAA,OAAO,GAAG,IAAI,YAAY,EAAE;AAEtC,IAAA,MAAM,GAAG,MAAM,CAAC,mBAAmB,CAAC;IACpC,QAAQ,GAAA;QACN,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE;AACrC,YAAA,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,KAAK;;QAG7B,UAAU,CAAC,MAAK;YACd,IAAI,CAAC,YAAY,EAAE;AACrB,SAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;;IAGzB,YAAY,GAAA;QACV,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,SAAS,EAAE;YAC/B,IAAI,CAAC,MAAM,CAAC,yBAAyB,CAAC,IAAI,CAAC,KAAK,CAAC;;;uGAjB1C,cAAc,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAd,cAAc,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,EAAA,OAAA,EAAA,EAAA,OAAA,EAAA,SAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECd3B,mZAaA,EDDY,MAAA,EAAA,CAAA,wiBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,aAAa,mLAAE,eAAe,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,aAAA,EAAA,QAAA,EAAA,yBAAA,EAAA,QAAA,EAAA,CAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,UAAA,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,aAAA,EAAA,UAAA,EAAA,qBAAA,EAAA,OAAA,EAAA,MAAA,EAAA,YAAA,EAAA,kBAAA,EAAA,oBAAA,EAAA,YAAA,EAAA,YAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;2FAEzD,cAAc,EAAA,UAAA,EAAA,CAAA;kBAN1B,SAAS;+BACE,WAAW,EAAA,OAAA,EAGZ,CAAC,aAAa,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,CAAC,EAAA,QAAA,EAAA,mZAAA,EAAA,MAAA,EAAA,CAAA,wiBAAA,CAAA,EAAA;8BAG1C,KAAK,EAAA,CAAA;sBAA/B,KAAK;uBAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;gBACf,OAAO,EAAA,CAAA;sBAAhB;;;AEhBH;;AAEG;;;;"}
@@ -0,0 +1,100 @@
1
+ import { __decorate } from 'tslib';
2
+ import * as i0 from '@angular/core';
3
+ import { inject, Injectable } from '@angular/core';
4
+ import { AppAction, ApiInterceptorAction, LoginAction, HeaderAction } from '@cccteam/ccc-lib/src/types';
5
+ import { NotificationService } from '@cccteam/ccc-lib/src/ui-notification-service';
6
+ import { Action, Selector, State } from '@ngxs/store';
7
+ import { patch } from '@ngxs/store/operators';
8
+
9
+ const initState = {
10
+ loading: [],
11
+ sidenavOpened: true,
12
+ currentSidenavIdentifier: '',
13
+ };
14
+ let CoreState = class CoreState {
15
+ notifications = inject(NotificationService);
16
+ static sidenavOpened(state) {
17
+ return state?.sidenavOpened;
18
+ }
19
+ static isLoading(state) {
20
+ return state.loading.length > 0;
21
+ }
22
+ static currentSidenavIdentifier(state) {
23
+ return state.currentSidenavIdentifier;
24
+ }
25
+ setNavIdentifier(ctx, action) {
26
+ ctx.setState(patch({
27
+ currentSidenavIdentifier: action.identifier,
28
+ }));
29
+ }
30
+ publishError(ctx, action) {
31
+ this.notifications.addGlobalNotification(action.message);
32
+ }
33
+ beginActivity(ctx, action) {
34
+ const state = ctx.getState();
35
+ ctx.patchState({
36
+ loading: [action.process, ...state.loading],
37
+ });
38
+ return ctx.getState();
39
+ }
40
+ endActivity(ctx, action) {
41
+ const loading = ctx.getState().loading;
42
+ // There can be multiple activities running with the same process signature
43
+ const index = loading.findIndex((activity) => activity === action.process);
44
+ if (index !== -1) {
45
+ const newLoading = [...loading.slice(0, index), ...loading.slice(index + 1)];
46
+ ctx.patchState({
47
+ loading: newLoading,
48
+ });
49
+ return ctx.getState();
50
+ }
51
+ return null;
52
+ }
53
+ toggleSidenav(ctx) {
54
+ ctx.setState(patch({
55
+ sidenavOpened: !ctx.getState().sidenavOpened,
56
+ }));
57
+ }
58
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: CoreState, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
59
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: CoreState });
60
+ };
61
+ __decorate([
62
+ Action([AppAction.SetNavIdentifier])
63
+ ], CoreState.prototype, "setNavIdentifier", null);
64
+ __decorate([
65
+ Action([ApiInterceptorAction.PublishError, LoginAction.PublishError])
66
+ ], CoreState.prototype, "publishError", null);
67
+ __decorate([
68
+ Action([ApiInterceptorAction.BeginActivity])
69
+ ], CoreState.prototype, "beginActivity", null);
70
+ __decorate([
71
+ Action([ApiInterceptorAction.EndActivity])
72
+ ], CoreState.prototype, "endActivity", null);
73
+ __decorate([
74
+ Action([HeaderAction.ToggleSidenav])
75
+ ], CoreState.prototype, "toggleSidenav", null);
76
+ __decorate([
77
+ Selector()
78
+ ], CoreState, "sidenavOpened", null);
79
+ __decorate([
80
+ Selector()
81
+ ], CoreState, "isLoading", null);
82
+ __decorate([
83
+ Selector()
84
+ ], CoreState, "currentSidenavIdentifier", null);
85
+ CoreState = __decorate([
86
+ State({
87
+ name: 'coreState',
88
+ defaults: initState,
89
+ })
90
+ ], CoreState);
91
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: CoreState, decorators: [{
92
+ type: Injectable
93
+ }], propDecorators: { setNavIdentifier: [], publishError: [], beginActivity: [], endActivity: [], toggleSidenav: [] } });
94
+
95
+ /**
96
+ * Generated bundle index. Do not edit.
97
+ */
98
+
99
+ export { CoreState };
100
+ //# sourceMappingURL=cccteam-ccc-lib-src-ui-core-state.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cccteam-ccc-lib-src-ui-core-state.mjs","sources":["../../../projects/ccc-lib/src/ui-core-state/core.state.ts","../../../projects/ccc-lib/src/ui-core-state/cccteam-ccc-lib-src-ui-core-state.ts"],"sourcesContent":["import { Injectable, inject } from '@angular/core';\nimport {\n ApiInterceptorAction,\n AppAction,\n CreateNotificationMessage,\n HeaderAction,\n LoginAction,\n} from '@cccteam/ccc-lib/src/types';\nimport { NotificationService } from '@cccteam/ccc-lib/src/ui-notification-service';\nimport { Action, Selector, State, StateContext } from '@ngxs/store';\nimport { patch } from '@ngxs/store/operators';\n\ninterface CoreStateModel {\n loading: string[];\n sidenavOpened: boolean;\n currentSidenavIdentifier: string;\n}\n\nconst initState: CoreStateModel = {\n loading: [],\n sidenavOpened: true,\n currentSidenavIdentifier: '',\n};\n\n@State<CoreStateModel>({\n name: 'coreState',\n defaults: initState,\n})\n@Injectable()\nexport class CoreState {\n private notifications = inject(NotificationService);\n\n @Selector()\n static sidenavOpened(state: CoreStateModel): boolean {\n return state?.sidenavOpened;\n }\n\n @Selector()\n static isLoading(state: CoreStateModel): boolean {\n return state.loading.length > 0;\n }\n\n @Selector()\n static currentSidenavIdentifier(state: CoreStateModel): string {\n return state.currentSidenavIdentifier;\n }\n\n @Action([AppAction.SetNavIdentifier])\n setNavIdentifier(ctx: StateContext<CoreStateModel>, action: AppAction.SetNavIdentifier): void {\n ctx.setState(\n patch({\n currentSidenavIdentifier: action.identifier,\n }),\n );\n }\n\n @Action([ApiInterceptorAction.PublishError, LoginAction.PublishError])\n publishError(ctx: StateContext<CoreStateModel>, action: { message: CreateNotificationMessage }): void {\n this.notifications.addGlobalNotification(action.message);\n }\n\n @Action([ApiInterceptorAction.BeginActivity])\n beginActivity(ctx: StateContext<CoreStateModel>, action: { process: string }): CoreStateModel {\n const state = ctx.getState();\n ctx.patchState({\n loading: [action.process, ...state.loading],\n });\n return ctx.getState();\n }\n\n @Action([ApiInterceptorAction.EndActivity])\n endActivity(ctx: StateContext<CoreStateModel>, action: { process: string }): CoreStateModel | null {\n const loading = ctx.getState().loading;\n // There can be multiple activities running with the same process signature\n const index = loading.findIndex((activity) => activity === action.process);\n if (index !== -1) {\n const newLoading = [...loading.slice(0, index), ...loading.slice(index + 1)];\n ctx.patchState({\n loading: newLoading,\n });\n return ctx.getState();\n }\n return null;\n }\n\n @Action([HeaderAction.ToggleSidenav])\n toggleSidenav(ctx: StateContext<CoreStateModel>): void {\n ctx.setState(\n patch({\n sidenavOpened: !ctx.getState().sidenavOpened,\n }),\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, NgZone, Injectable } from '@angular/core';
3
+ import { Router } from '@angular/router';
4
+ import { BASE_URL, ApiInterceptorAction, AlertLevel } from '@cccteam/ccc-lib/src/types';
5
+ import { CUSTOM_HTTP_REQUEST_OPTIONS } from '@cccteam/ccc-lib/src/util-request-options';
6
+ import { Store } from '@ngxs/store';
7
+ import { catchError, throwError, finalize } from 'rxjs';
8
+
9
+ class ApiInterceptor {
10
+ store = inject(Store);
11
+ router = inject(Router);
12
+ ngZone = inject(NgZone);
13
+ baseUrl = inject(BASE_URL);
14
+ intercept(request, next) {
15
+ this.store.dispatch(new ApiInterceptorAction.BeginActivity(request.method + ' ' + request.url));
16
+ return next.handle(request).pipe(catchError((error) => {
17
+ if (error.status === 401) {
18
+ this.ngZone.run(() => {
19
+ this.store.dispatch(new ApiInterceptorAction.SetRedirectUrl(this.baseUrl + this.router.url));
20
+ this.router.navigate(['/login']);
21
+ });
22
+ }
23
+ if (!request.context.get(CUSTOM_HTTP_REQUEST_OPTIONS).suppressGlobalError) {
24
+ const message = error.error?.message ?? error.message ?? error.error;
25
+ this.store.dispatch(new ApiInterceptorAction.PublishError({
26
+ message: message,
27
+ level: AlertLevel.ERROR,
28
+ link: '',
29
+ }));
30
+ }
31
+ return throwError(() => error);
32
+ }), finalize(() => {
33
+ this.store.dispatch(new ApiInterceptorAction.EndActivity(request.method + ' ' + request.url));
34
+ }));
35
+ }
36
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: ApiInterceptor, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
37
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: ApiInterceptor });
38
+ }
39
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: ApiInterceptor, decorators: [{
40
+ type: Injectable
41
+ }] });
42
+
43
+ /**
44
+ * Generated bundle index. Do not edit.
45
+ */
46
+
47
+ export { ApiInterceptor };
48
+ //# sourceMappingURL=cccteam-ccc-lib-src-ui-interceptor.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cccteam-ccc-lib-src-ui-interceptor.mjs","sources":["../../../projects/ccc-lib/src/ui-interceptor/api.interceptor.ts","../../../projects/ccc-lib/src/ui-interceptor/cccteam-ccc-lib-src-ui-interceptor.ts"],"sourcesContent":["import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';\nimport { inject, Injectable, NgZone } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { AlertLevel, ApiInterceptorAction, BASE_URL } from '@cccteam/ccc-lib/src/types';\nimport { CUSTOM_HTTP_REQUEST_OPTIONS } from '@cccteam/ccc-lib/src/util-request-options';\nimport { Store } from '@ngxs/store';\nimport { catchError, finalize, Observable, throwError } from 'rxjs';\n\n@Injectable()\nexport class ApiInterceptor implements HttpInterceptor {\n private store = inject(Store);\n private router = inject(Router);\n private ngZone = inject(NgZone);\n private baseUrl = inject(BASE_URL);\n\n intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\n this.store.dispatch(new ApiInterceptorAction.BeginActivity(request.method + ' ' + request.url));\n\n return next.handle(request).pipe(\n catchError((error: HttpErrorResponse): Observable<HttpEvent<unknown>> => {\n if (error.status === 401) {\n this.ngZone.run(() => {\n this.store.dispatch(new ApiInterceptorAction.SetRedirectUrl(this.baseUrl + this.router.url));\n this.router.navigate(['/login']);\n });\n }\n if (!request.context.get(CUSTOM_HTTP_REQUEST_OPTIONS).suppressGlobalError) {\n const message = error.error?.message ?? error.message ?? error.error;\n this.store.dispatch(\n new ApiInterceptorAction.PublishError({\n message: message,\n level: AlertLevel.ERROR,\n link: '',\n }),\n );\n }\n\n return throwError(() => error);\n }),\n finalize(() => {\n this.store.dispatch(new ApiInterceptorAction.EndActivity(request.method + ' ' + request.url));\n }),\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;;MASa,cAAc,CAAA;AACjB,IAAA,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;AACrB,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,IAAA,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC;IAElC,SAAS,CAAC,OAA6B,EAAE,IAAiB,EAAA;QACxD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,oBAAoB,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;AAE/F,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAC9B,UAAU,CAAC,CAAC,KAAwB,KAAoC;AACtE,YAAA,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE;AACxB,gBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAK;oBACnB,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,oBAAoB,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBAC5F,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC;AAClC,iBAAC,CAAC;;AAEJ,YAAA,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC,mBAAmB,EAAE;AACzE,gBAAA,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK;gBACpE,IAAI,CAAC,KAAK,CAAC,QAAQ,CACjB,IAAI,oBAAoB,CAAC,YAAY,CAAC;AACpC,oBAAA,OAAO,EAAE,OAAO;oBAChB,KAAK,EAAE,UAAU,CAAC,KAAK;AACvB,oBAAA,IAAI,EAAE,EAAE;AACT,iBAAA,CAAC,CACH;;AAGH,YAAA,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC;AAChC,SAAC,CAAC,EACF,QAAQ,CAAC,MAAK;YACZ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,oBAAoB,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;SAC9F,CAAC,CACH;;uGAjCQ,cAAc,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;2GAAd,cAAc,EAAA,CAAA;;2FAAd,cAAc,EAAA,UAAA,EAAA,CAAA;kBAD1B;;;ACRD;;AAEG;;;;"}
@@ -0,0 +1,57 @@
1
+ import * as i0 from '@angular/core';
2
+ import { signal, Injectable } from '@angular/core';
3
+
4
+ class NotificationService {
5
+ notificationId = 0;
6
+ _notifications = signal([]);
7
+ notifications = this._notifications.asReadonly();
8
+ /**
9
+ * Adds a new global notification.
10
+ * @param notification The notification message to add.
11
+ * @returns The unique ID assigned to the notification.
12
+ */
13
+ addGlobalNotification(notification) {
14
+ const newNotification = {
15
+ ...notification,
16
+ id: this.notificationId++,
17
+ };
18
+ this._notifications.update((current) => [...current, newNotification]);
19
+ return newNotification.id;
20
+ }
21
+ /**
22
+ * Dismisses a global notification by its ID.
23
+ * @param notificationId The ID of the notification to dismiss.
24
+ */
25
+ dismissGlobalNotificationById(notificationId) {
26
+ this._notifications.update((current) => current.filter((notification) => notification.id !== notificationId));
27
+ }
28
+ /**
29
+ * Dismisses a specific global notification.
30
+ * @param notification The notification to dismiss.
31
+ */
32
+ dismissGlobalNotification(notification) {
33
+ this.dismissGlobalNotificationById(notification.id);
34
+ }
35
+ /**
36
+ * Updates an existing notification.
37
+ * @param updatedNotification The notification with updated information.
38
+ */
39
+ updateNotification(updatedNotification) {
40
+ this._notifications.update((current) => current.map((notification) => notification.id === updatedNotification.id ? { ...notification, ...updatedNotification } : notification));
41
+ }
42
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: NotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
43
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: NotificationService, providedIn: 'root' });
44
+ }
45
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: NotificationService, decorators: [{
46
+ type: Injectable,
47
+ args: [{
48
+ providedIn: 'root',
49
+ }]
50
+ }] });
51
+
52
+ /**
53
+ * Generated bundle index. Do not edit.
54
+ */
55
+
56
+ export { NotificationService };
57
+ //# sourceMappingURL=cccteam-ccc-lib-src-ui-notification-service.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cccteam-ccc-lib-src-ui-notification-service.mjs","sources":["../../../projects/ccc-lib/src/ui-notification-service/notification.service.ts","../../../projects/ccc-lib/src/ui-notification-service/cccteam-ccc-lib-src-ui-notification-service.ts"],"sourcesContent":["import { Injectable, signal } from '@angular/core';\nimport { CreateNotificationMessage, NotificationMessage } from '@cccteam/ccc-lib/src/types';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class NotificationService {\n private notificationId = 0;\n private _notifications = signal<NotificationMessage[]>([]);\n notifications = this._notifications.asReadonly();\n\n /**\n * Adds a new global notification.\n * @param notification The notification message to add.\n * @returns The unique ID assigned to the notification.\n */\n addGlobalNotification(notification: CreateNotificationMessage): number {\n const newNotification: NotificationMessage = {\n ...notification,\n id: this.notificationId++,\n };\n this._notifications.update((current) => [...current, newNotification]);\n return newNotification.id;\n }\n\n /**\n * Dismisses a global notification by its ID.\n * @param notificationId The ID of the notification to dismiss.\n */\n dismissGlobalNotificationById(notificationId: number): void {\n this._notifications.update((current) => current.filter((notification) => notification.id !== notificationId));\n }\n\n /**\n * Dismisses a specific global notification.\n * @param notification The notification to dismiss.\n */\n dismissGlobalNotification(notification: NotificationMessage): void {\n this.dismissGlobalNotificationById(notification.id);\n }\n\n /**\n * Updates an existing notification.\n * @param updatedNotification The notification with updated information.\n */\n updateNotification(updatedNotification: NotificationMessage): void {\n this._notifications.update((current) =>\n current.map((notification) =>\n notification.id === updatedNotification.id ? { ...notification, ...updatedNotification } : notification,\n ),\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;MAMa,mBAAmB,CAAA;IACtB,cAAc,GAAG,CAAC;AAClB,IAAA,cAAc,GAAG,MAAM,CAAwB,EAAE,CAAC;AAC1D,IAAA,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE;AAEhD;;;;AAIG;AACH,IAAA,qBAAqB,CAAC,YAAuC,EAAA;AAC3D,QAAA,MAAM,eAAe,GAAwB;AAC3C,YAAA,GAAG,YAAY;AACf,YAAA,EAAE,EAAE,IAAI,CAAC,cAAc,EAAE;SAC1B;AACD,QAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,OAAO,KAAK,CAAC,GAAG,OAAO,EAAE,eAAe,CAAC,CAAC;QACtE,OAAO,eAAe,CAAC,EAAE;;AAG3B;;;AAGG;AACH,IAAA,6BAA6B,CAAC,cAAsB,EAAA;QAClD,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,YAAY,KAAK,YAAY,CAAC,EAAE,KAAK,cAAc,CAAC,CAAC;;AAG/G;;;AAGG;AACH,IAAA,yBAAyB,CAAC,YAAiC,EAAA;AACzD,QAAA,IAAI,CAAC,6BAA6B,CAAC,YAAY,CAAC,EAAE,CAAC;;AAGrD;;;AAGG;AACH,IAAA,kBAAkB,CAAC,mBAAwC,EAAA;AACzD,QAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,OAAO,KACjC,OAAO,CAAC,GAAG,CAAC,CAAC,YAAY,KACvB,YAAY,CAAC,EAAE,KAAK,mBAAmB,CAAC,EAAE,GAAG,EAAE,GAAG,YAAY,EAAE,GAAG,mBAAmB,EAAE,GAAG,YAAY,CACxG,CACF;;uGA5CQ,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,mBAAmB,cAFlB,MAAM,EAAA,CAAA;;2FAEP,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAH/B,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE,MAAM;AACnB,iBAAA;;;ACLD;;AAEG;;;;"}
@@ -0,0 +1,70 @@
1
+ import * as i3 from '@angular/common';
2
+ import { CommonModule } from '@angular/common';
3
+ import * as i0 from '@angular/core';
4
+ import { inject, DestroyRef, Component, Input } from '@angular/core';
5
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
+ import { MatButtonModule } from '@angular/material/button';
7
+ import { MatExpansionModule } from '@angular/material/expansion';
8
+ import * as i1 from '@angular/material/icon';
9
+ import { MatIconModule } from '@angular/material/icon';
10
+ import { MatSidenavModule } from '@angular/material/sidenav';
11
+ import * as i2 from '@angular/router';
12
+ import { RouterModule } from '@angular/router';
13
+ import { Store } from '@ngxs/store';
14
+ import { HasPermissionDirective } from '@cccteam/ccc-lib/src/auth-has-permission';
15
+ import { CoreState } from '@cccteam/ccc-lib/src/ui-core-state';
16
+ import { tap } from 'rxjs';
17
+
18
+ class SidenavComponent {
19
+ store = inject(Store);
20
+ destroyRef = inject(DestroyRef);
21
+ navGroups;
22
+ currentNav = [];
23
+ ngOnInit() {
24
+ this.store
25
+ .select(CoreState.currentSidenavIdentifier)
26
+ .pipe(tap((identifier) => {
27
+ this.currentNav = this.updateNavItems(identifier);
28
+ }), takeUntilDestroyed(this.destroyRef))
29
+ .subscribe();
30
+ }
31
+ /**
32
+ * Updates the currentNav based on the identifier
33
+ * @param identifier
34
+ * @returns NavItem[]
35
+ * @memberof SidenavComponent
36
+ */
37
+ updateNavItems(identifier) {
38
+ if (!this.navGroups) {
39
+ return [];
40
+ }
41
+ if (!this.navGroups[identifier]) {
42
+ // pick the first one if the identifier is not found so we don't break the UI
43
+ identifier = Object.keys(this.navGroups)[0];
44
+ }
45
+ return this.navGroups[identifier];
46
+ }
47
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: SidenavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
48
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.3", type: SidenavComponent, isStandalone: true, selector: "ccc-sidenav", inputs: { navGroups: "navGroups" }, ngImport: i0, template: "<div class=\"nav-container\">\n <nav>\n @for (navItem of currentNav; track navItem.label) {\n <ng-container *ngTemplateOutlet=\"typeRendererTemplate; context: { navItem: navItem }\"></ng-container>\n }\n </nav>\n</div>\n<ng-template #typeRendererTemplate let-navItem=\"navItem\">\n @switch (navItem.type) {\n @case ('header') {\n <ng-container [ngTemplateOutlet]=\"headerTemplate\" [ngTemplateOutletContext]=\"{ navItem: navItem }\"></ng-container>\n }\n @case ('link') {\n <ng-container [ngTemplateOutlet]=\"linkTemplate\" [ngTemplateOutletContext]=\"{ navItem: navItem }\"></ng-container>\n }\n @case ('expandable') {\n <ng-container\n [ngTemplateOutlet]=\"expandableTemplate\"\n [ngTemplateOutletContext]=\"{ navItem: navItem }\"></ng-container>\n }\n }\n</ng-template>\n<ng-template #headerTemplate let-navItem=\"navItem\">\n <div class=\"link-header\">{{ navItem.label }}</div>\n</ng-template>\n<ng-template #linkTemplate let-navItem=\"navItem\">\n <a [routerLink]=\"navItem.routerLink\" *cccHasPermission=\"navItem.permission\">\n <div class=\"nav-item\" routerLinkActive=\"active-link\">\n <div class=\"link-button\">\n <div class=\"icon\">\n <mat-icon class=\"material-icons-outlined\" [inline]=\"true\">\n {{ navItem.icon }}\n </mat-icon>\n </div>\n <div class=\"text\">\n {{ navItem.label | titlecase }}\n </div>\n </div>\n </div>\n </a>\n</ng-template>\n<ng-template #expandableTemplate let-navItem=\"navItem\">\n <div class=\"nav-item\" aria-hidden=\"true\" (click)=\"navItem.isExpanded = !navItem.isExpanded\">\n <div class=\"link-button\">\n <div class=\"icon\">\n <mat-icon class=\"material-icons-outlined\" [inline]=\"true\">\n {{ navItem.isExpanded ? 'expand_less' : 'expand_more' }}\n </mat-icon>\n </div>\n <div class=\"text\">{{ navItem.label }}</div>\n </div>\n </div>\n @if (navItem.isExpanded) {\n <div class=\"expandable-links\">\n @for (navItemChild of navItem.children; track navItemChild) {\n <ng-container *ngTemplateOutlet=\"typeRendererTemplate; context: { navItem: navItemChild }\"> </ng-container>\n }\n </div>\n }\n</ng-template>\n", styles: [".nav-container{padding:0;height:100%}nav{max-width:100%;margin:0 10px}.nav-item{width:100%;height:48px;font-size:18px;display:flex;flex-direction:column;justify-content:center;color:#003b49;padding:0 15px;position:relative}.nav-item:hover{background-color:#0000000a;transition:background-color .1s ease}.nav-item:active{background-color:#0000001a;transition:background-color .1s ease}.link-header{color:#003b49;text-transform:uppercase;font-weight:700;font-size:12px;margin:20px 0 0 5px}.link-button{display:flex;flex-direction:row;width:100%}.link-button .icon{min-width:20px;margin-right:10px;display:flex;flex-direction:column;justify-content:center}.link-button .text{margin-right:10px;text-align:left;display:flex;flex-direction:row;justify-content:left;text-decoration:capitalize}.expandable-links{display:flex;flex-direction:column;width:100%;padding-left:30px}a:active,a:link,a:visited{color:#003b49!important}a{text-decoration:none}.active-link:before{content:\"\";position:absolute;left:3px;width:5px;height:38px;background-color:#003b49}.active-link{background-color:#0000000a;position:relative}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i3.TitleCasePipe, name: "titlecase" }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatSidenavModule }, { kind: "directive", type: HasPermissionDirective, selector: "[cccHasPermission]", inputs: ["cccHasPermission"] }] });
49
+ }
50
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: SidenavComponent, decorators: [{
51
+ type: Component,
52
+ args: [{ selector: 'ccc-sidenav', imports: [
53
+ MatIconModule,
54
+ RouterModule,
55
+ CommonModule,
56
+ MatExpansionModule,
57
+ MatButtonModule,
58
+ MatSidenavModule,
59
+ HasPermissionDirective,
60
+ ], template: "<div class=\"nav-container\">\n <nav>\n @for (navItem of currentNav; track navItem.label) {\n <ng-container *ngTemplateOutlet=\"typeRendererTemplate; context: { navItem: navItem }\"></ng-container>\n }\n </nav>\n</div>\n<ng-template #typeRendererTemplate let-navItem=\"navItem\">\n @switch (navItem.type) {\n @case ('header') {\n <ng-container [ngTemplateOutlet]=\"headerTemplate\" [ngTemplateOutletContext]=\"{ navItem: navItem }\"></ng-container>\n }\n @case ('link') {\n <ng-container [ngTemplateOutlet]=\"linkTemplate\" [ngTemplateOutletContext]=\"{ navItem: navItem }\"></ng-container>\n }\n @case ('expandable') {\n <ng-container\n [ngTemplateOutlet]=\"expandableTemplate\"\n [ngTemplateOutletContext]=\"{ navItem: navItem }\"></ng-container>\n }\n }\n</ng-template>\n<ng-template #headerTemplate let-navItem=\"navItem\">\n <div class=\"link-header\">{{ navItem.label }}</div>\n</ng-template>\n<ng-template #linkTemplate let-navItem=\"navItem\">\n <a [routerLink]=\"navItem.routerLink\" *cccHasPermission=\"navItem.permission\">\n <div class=\"nav-item\" routerLinkActive=\"active-link\">\n <div class=\"link-button\">\n <div class=\"icon\">\n <mat-icon class=\"material-icons-outlined\" [inline]=\"true\">\n {{ navItem.icon }}\n </mat-icon>\n </div>\n <div class=\"text\">\n {{ navItem.label | titlecase }}\n </div>\n </div>\n </div>\n </a>\n</ng-template>\n<ng-template #expandableTemplate let-navItem=\"navItem\">\n <div class=\"nav-item\" aria-hidden=\"true\" (click)=\"navItem.isExpanded = !navItem.isExpanded\">\n <div class=\"link-button\">\n <div class=\"icon\">\n <mat-icon class=\"material-icons-outlined\" [inline]=\"true\">\n {{ navItem.isExpanded ? 'expand_less' : 'expand_more' }}\n </mat-icon>\n </div>\n <div class=\"text\">{{ navItem.label }}</div>\n </div>\n </div>\n @if (navItem.isExpanded) {\n <div class=\"expandable-links\">\n @for (navItemChild of navItem.children; track navItemChild) {\n <ng-container *ngTemplateOutlet=\"typeRendererTemplate; context: { navItem: navItemChild }\"> </ng-container>\n }\n </div>\n }\n</ng-template>\n", styles: [".nav-container{padding:0;height:100%}nav{max-width:100%;margin:0 10px}.nav-item{width:100%;height:48px;font-size:18px;display:flex;flex-direction:column;justify-content:center;color:#003b49;padding:0 15px;position:relative}.nav-item:hover{background-color:#0000000a;transition:background-color .1s ease}.nav-item:active{background-color:#0000001a;transition:background-color .1s ease}.link-header{color:#003b49;text-transform:uppercase;font-weight:700;font-size:12px;margin:20px 0 0 5px}.link-button{display:flex;flex-direction:row;width:100%}.link-button .icon{min-width:20px;margin-right:10px;display:flex;flex-direction:column;justify-content:center}.link-button .text{margin-right:10px;text-align:left;display:flex;flex-direction:row;justify-content:left;text-decoration:capitalize}.expandable-links{display:flex;flex-direction:column;width:100%;padding-left:30px}a:active,a:link,a:visited{color:#003b49!important}a{text-decoration:none}.active-link:before{content:\"\";position:absolute;left:3px;width:5px;height:38px;background-color:#003b49}.active-link{background-color:#0000000a;position:relative}\n"] }]
61
+ }], propDecorators: { navGroups: [{
62
+ type: Input
63
+ }] } });
64
+
65
+ /**
66
+ * Generated bundle index. Do not edit.
67
+ */
68
+
69
+ export { SidenavComponent };
70
+ //# sourceMappingURL=cccteam-ccc-lib-src-ui-sidenav.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cccteam-ccc-lib-src-ui-sidenav.mjs","sources":["../../../projects/ccc-lib/src/ui-sidenav/sidenav.component.ts","../../../projects/ccc-lib/src/ui-sidenav/sidenav.component.html","../../../projects/ccc-lib/src/ui-sidenav/cccteam-ccc-lib-src-ui-sidenav.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { Component, DestroyRef, inject, Input, OnInit } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatExpansionModule } from '@angular/material/expansion';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatSidenavModule } from '@angular/material/sidenav';\nimport { RouterModule } from '@angular/router';\nimport { Store } from '@ngxs/store';\n\nimport { HasPermissionDirective } from '@cccteam/ccc-lib/src/auth-has-permission';\nimport { PermissionScope } from '@cccteam/ccc-lib/src/types';\nimport { CoreState } from '@cccteam/ccc-lib/src/ui-core-state';\nimport { Observable, tap } from 'rxjs';\n\nexport interface NavItem {\n type: 'link' | 'header' | 'expandable';\n routerLink?: string[];\n label: string;\n icon?: string;\n permission?: PermissionScope;\n children?: NavItem[];\n isExpanded?: boolean;\n attentionCount?: Observable<number>;\n}\n\nexport type NavGroups = Record<string, NavItem[]>;\n\n@Component({\n selector: 'ccc-sidenav',\n templateUrl: './sidenav.component.html',\n styleUrls: ['./sidenav.component.scss'],\n imports: [\n MatIconModule,\n RouterModule,\n CommonModule,\n MatExpansionModule,\n MatButtonModule,\n MatSidenavModule,\n HasPermissionDirective,\n ],\n})\nexport class SidenavComponent implements OnInit {\n private store = inject(Store);\n private destroyRef = inject(DestroyRef);\n\n @Input() navGroups?: NavGroups;\n currentNav: NavItem[] = [];\n\n ngOnInit(): void {\n this.store\n .select(CoreState.currentSidenavIdentifier)\n .pipe(\n tap((identifier) => {\n this.currentNav = this.updateNavItems(identifier);\n }),\n takeUntilDestroyed(this.destroyRef),\n )\n .subscribe();\n }\n\n /**\n * Updates the currentNav based on the identifier\n * @param identifier\n * @returns NavItem[]\n * @memberof SidenavComponent\n */\n updateNavItems(identifier: string): NavItem[] {\n if (!this.navGroups) {\n return [];\n }\n if (!this.navGroups[identifier]) {\n // pick the first one if the identifier is not found so we don't break the UI\n identifier = Object.keys(this.navGroups)[0];\n }\n return this.navGroups[identifier];\n }\n}\n","<div class=\"nav-container\">\n <nav>\n @for (navItem of currentNav; track navItem.label) {\n <ng-container *ngTemplateOutlet=\"typeRendererTemplate; context: { navItem: navItem }\"></ng-container>\n }\n </nav>\n</div>\n<ng-template #typeRendererTemplate let-navItem=\"navItem\">\n @switch (navItem.type) {\n @case ('header') {\n <ng-container [ngTemplateOutlet]=\"headerTemplate\" [ngTemplateOutletContext]=\"{ navItem: navItem }\"></ng-container>\n }\n @case ('link') {\n <ng-container [ngTemplateOutlet]=\"linkTemplate\" [ngTemplateOutletContext]=\"{ navItem: navItem }\"></ng-container>\n }\n @case ('expandable') {\n <ng-container\n [ngTemplateOutlet]=\"expandableTemplate\"\n [ngTemplateOutletContext]=\"{ navItem: navItem }\"></ng-container>\n }\n }\n</ng-template>\n<ng-template #headerTemplate let-navItem=\"navItem\">\n <div class=\"link-header\">{{ navItem.label }}</div>\n</ng-template>\n<ng-template #linkTemplate let-navItem=\"navItem\">\n <a [routerLink]=\"navItem.routerLink\" *cccHasPermission=\"navItem.permission\">\n <div class=\"nav-item\" routerLinkActive=\"active-link\">\n <div class=\"link-button\">\n <div class=\"icon\">\n <mat-icon class=\"material-icons-outlined\" [inline]=\"true\">\n {{ navItem.icon }}\n </mat-icon>\n </div>\n <div class=\"text\">\n {{ navItem.label | titlecase }}\n </div>\n </div>\n </div>\n </a>\n</ng-template>\n<ng-template #expandableTemplate let-navItem=\"navItem\">\n <div class=\"nav-item\" aria-hidden=\"true\" (click)=\"navItem.isExpanded = !navItem.isExpanded\">\n <div class=\"link-button\">\n <div class=\"icon\">\n <mat-icon class=\"material-icons-outlined\" [inline]=\"true\">\n {{ navItem.isExpanded ? 'expand_less' : 'expand_more' }}\n </mat-icon>\n </div>\n <div class=\"text\">{{ navItem.label }}</div>\n </div>\n </div>\n @if (navItem.isExpanded) {\n <div class=\"expandable-links\">\n @for (navItemChild of navItem.children; track navItemChild) {\n <ng-container *ngTemplateOutlet=\"typeRendererTemplate; context: { navItem: navItemChild }\"> </ng-container>\n }\n </div>\n }\n</ng-template>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { HttpContextToken, HttpContext } from '@angular/common/http';
2
+
3
+ const CUSTOM_HTTP_REQUEST_OPTIONS = new HttpContextToken(() => ({
4
+ suppressGlobalError: false,
5
+ }));
6
+ function errorOptions(suppressGlobalError) {
7
+ return {
8
+ context: new HttpContext().set(CUSTOM_HTTP_REQUEST_OPTIONS, {
9
+ suppressGlobalError: suppressGlobalError ?? false,
10
+ }),
11
+ };
12
+ }
13
+
14
+ /**
15
+ * Generated bundle index. Do not edit.
16
+ */
17
+
18
+ export { CUSTOM_HTTP_REQUEST_OPTIONS, errorOptions };
19
+ //# sourceMappingURL=cccteam-ccc-lib-src-util-request-options.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cccteam-ccc-lib-src-util-request-options.mjs","sources":["../../../projects/ccc-lib/src/util-request-options/request-options.ts","../../../projects/ccc-lib/src/util-request-options/cccteam-ccc-lib-src-util-request-options.ts"],"sourcesContent":["import { HttpContext, HttpContextToken } from '@angular/common/http';\n\nexport interface CustomHttpRequestOptions {\n suppressGlobalError: boolean;\n}\n\nexport const CUSTOM_HTTP_REQUEST_OPTIONS = new HttpContextToken<CustomHttpRequestOptions>(() => ({\n suppressGlobalError: false,\n}));\n\nexport function errorOptions(suppressGlobalError: boolean | undefined): { context: HttpContext } {\n return {\n context: new HttpContext().set(CUSTOM_HTTP_REQUEST_OPTIONS, {\n suppressGlobalError: suppressGlobalError ?? false,\n }),\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAMa,MAAA,2BAA2B,GAAG,IAAI,gBAAgB,CAA2B,OAAO;AAC/F,IAAA,mBAAmB,EAAE,KAAK;AAC3B,CAAA,CAAC;AAEI,SAAU,YAAY,CAAC,mBAAwC,EAAA;IACnE,OAAO;QACL,OAAO,EAAE,IAAI,WAAW,EAAE,CAAC,GAAG,CAAC,2BAA2B,EAAE;YAC1D,mBAAmB,EAAE,mBAAmB,IAAI,KAAK;SAClD,CAAC;KACH;AACH;;AChBA;;AAEG;;;;"}