@cccteam/ccc-lib 0.0.21 → 0.0.23

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.
@@ -1,6 +1,39 @@
1
1
  import { FormGroup, FormArray } from '@angular/forms';
2
- import { isEqual } from 'lodash-es';
3
2
 
3
+ /**
4
+ * Deep equality comparison for two values.
5
+ * Handles primitives, arrays, objects, dates, and null/undefined.
6
+ */
7
+ function isEqual(a, b) {
8
+ // Same reference or both primitives with same value
9
+ if (a === b)
10
+ return true;
11
+ // Handle null/undefined
12
+ if (a == null || b == null)
13
+ return a === b;
14
+ // Handle different types
15
+ if (typeof a !== typeof b)
16
+ return false;
17
+ // Handle Date objects
18
+ if (a instanceof Date && b instanceof Date) {
19
+ return a.getTime() === b.getTime();
20
+ }
21
+ // Handle arrays
22
+ if (Array.isArray(a) && Array.isArray(b)) {
23
+ if (a.length !== b.length)
24
+ return false;
25
+ return a.every((item, index) => isEqual(item, b[index]));
26
+ }
27
+ // Handle objects
28
+ if (typeof a === 'object' && typeof b === 'object') {
29
+ const keysA = Object.keys(a);
30
+ const keysB = Object.keys(b);
31
+ if (keysA.length !== keysB.length)
32
+ return false;
33
+ return keysA.every((key) => isEqual(a[key], b[key]));
34
+ }
35
+ return false;
36
+ }
4
37
  /**
5
38
  * Compares two objects and returns a sparse object containing only the differing key-value pairs
6
39
  * @param data - object to compare
@@ -1 +1 @@
1
- {"version":3,"file":"cccteam-ccc-lib-forms.mjs","sources":["../../../projects/ccc-lib/forms/index.ts","../../../projects/ccc-lib/forms/cccteam-ccc-lib-forms.ts"],"sourcesContent":["import { AbstractControl, FormArray, FormGroup } from '@angular/forms';\nimport { isEqual } from 'lodash-es';\n\n/**\n * Compares two objects and returns a sparse object containing only the differing key-value pairs\n * @param data - object to compare\n * @param compareData - object to compare against\n * @returns Partial<T>\n * @example sparseData<UserCreate>(this.user, initUser)\n */\nexport function sparseData<T extends Record<string, unknown>>(data: T, compareData: T): Partial<T> {\n const sparseData: Partial<T> = {};\n\n for (const key in data) {\n if (Object.prototype.hasOwnProperty.call(data, key)) {\n if (!isEqual(data[key], compareData[key])) {\n sparseData[key] = data[key];\n }\n }\n }\n\n return sparseData;\n}\n\n/**\n * Iterates through a form group's controls and returns a sparse object with only the changed values.\n * @param form - The form group to iterate through\n * @param compareData - The object to compare the form's values to\n * @returns - A sparse object with only the changed values\n * @example sparseFormData<UserCreate>(this.userForm, initUser)\n */\nexport function sparseFormData<T>(form: FormGroup, compareData: T): T {\n const sparseFormData: T = {} as T;\n for (const key in form.controls) {\n if (Object.prototype.hasOwnProperty.call(form.controls, key)) {\n const control = form.controls[key];\n const controlValue = control.value;\n const compareValue = compareData[key as keyof T];\n if (controlValue !== compareValue) {\n sparseFormData[key as keyof T] = controlValue as T[keyof T];\n }\n }\n }\n return sparseFormData;\n}\n\n/**\n * Recursively cleans a FormGroup or FormArray, removing controls with empty string values.\n * Similar to sparseFormData, but doesn't compare to an initial state\n * @param control - The FormGroup or FormArray to clean.\n * @returns A cleaned object with non-empty values.\n */\nexport function cleanStringForm<T>(control: AbstractControl): T | undefined {\n if (control instanceof FormGroup) {\n const cleanedGroup: Record<string, unknown> = {};\n for (const key of Object.keys(control.controls)) {\n const childControl = control.get(key);\n if (childControl) {\n const cleanedValue = cleanStringForm(childControl);\n if (cleanedValue !== undefined && cleanedValue !== null && cleanedValue !== '') {\n cleanedGroup[key] = cleanedValue;\n }\n }\n }\n return cleanedGroup as T;\n } else if (control instanceof FormArray) {\n const cleanedArray = control.controls\n .map((childControl) => cleanStringForm(childControl))\n .filter((item) => item !== undefined && item !== null && item !== '');\n return cleanedArray as unknown as T;\n } else {\n return control.value !== '' ? control.value : undefined;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAGA;;;;;;AAMG;AACG,SAAU,UAAU,CAAoC,IAAO,EAAE,WAAc,EAAA;IACnF,MAAM,UAAU,GAAe,EAAE;AAEjC,IAAA,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;AACtB,QAAA,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE;AACnD,YAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE;gBACzC,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;YAC7B;QACF;IACF;AAEA,IAAA,OAAO,UAAU;AACnB;AAEA;;;;;;AAMG;AACG,SAAU,cAAc,CAAI,IAAe,EAAE,WAAc,EAAA;IAC/D,MAAM,cAAc,GAAM,EAAO;AACjC,IAAA,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE;AAC/B,QAAA,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE;YAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;AAClC,YAAA,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK;AAClC,YAAA,MAAM,YAAY,GAAG,WAAW,CAAC,GAAc,CAAC;AAChD,YAAA,IAAI,YAAY,KAAK,YAAY,EAAE;AACjC,gBAAA,cAAc,CAAC,GAAc,CAAC,GAAG,YAA0B;YAC7D;QACF;IACF;AACA,IAAA,OAAO,cAAc;AACvB;AAEA;;;;;AAKG;AACG,SAAU,eAAe,CAAI,OAAwB,EAAA;AACzD,IAAA,IAAI,OAAO,YAAY,SAAS,EAAE;QAChC,MAAM,YAAY,GAA4B,EAAE;AAChD,QAAA,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;YAC/C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;YACrC,IAAI,YAAY,EAAE;AAChB,gBAAA,MAAM,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC;AAClD,gBAAA,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,KAAK,EAAE,EAAE;AAC9E,oBAAA,YAAY,CAAC,GAAG,CAAC,GAAG,YAAY;gBAClC;YACF;QACF;AACA,QAAA,OAAO,YAAiB;IAC1B;AAAO,SAAA,IAAI,OAAO,YAAY,SAAS,EAAE;AACvC,QAAA,MAAM,YAAY,GAAG,OAAO,CAAC;aAC1B,GAAG,CAAC,CAAC,YAAY,KAAK,eAAe,CAAC,YAAY,CAAC;AACnD,aAAA,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE,CAAC;AACvE,QAAA,OAAO,YAA4B;IACrC;SAAO;AACL,QAAA,OAAO,OAAO,CAAC,KAAK,KAAK,EAAE,GAAG,OAAO,CAAC,KAAK,GAAG,SAAS;IACzD;AACF;;ACzEA;;AAEG;;;;"}
1
+ {"version":3,"file":"cccteam-ccc-lib-forms.mjs","sources":["../../../projects/ccc-lib/forms/index.ts","../../../projects/ccc-lib/forms/cccteam-ccc-lib-forms.ts"],"sourcesContent":["import { AbstractControl, FormArray, FormGroup } from '@angular/forms';\n\n/**\n * Deep equality comparison for two values.\n * Handles primitives, arrays, objects, dates, and null/undefined.\n */\nfunction isEqual(a: unknown, b: unknown): boolean {\n // Same reference or both primitives with same value\n if (a === b) return true;\n\n // Handle null/undefined\n if (a == null || b == null) return a === b;\n\n // Handle different types\n if (typeof a !== typeof b) return false;\n\n // Handle Date objects\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime();\n }\n\n // Handle arrays\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n return a.every((item, index) => isEqual(item, b[index]));\n }\n\n // Handle objects\n if (typeof a === 'object' && typeof b === 'object') {\n const keysA = Object.keys(a as object);\n const keysB = Object.keys(b as object);\n if (keysA.length !== keysB.length) return false;\n return keysA.every((key) => isEqual((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key]));\n }\n\n return false;\n}\n\n/**\n * Compares two objects and returns a sparse object containing only the differing key-value pairs\n * @param data - object to compare\n * @param compareData - object to compare against\n * @returns Partial<T>\n * @example sparseData<UserCreate>(this.user, initUser)\n */\nexport function sparseData<T extends Record<string, unknown>>(data: T, compareData: T): Partial<T> {\n const sparseData: Partial<T> = {};\n\n for (const key in data) {\n if (Object.prototype.hasOwnProperty.call(data, key)) {\n if (!isEqual(data[key], compareData[key])) {\n sparseData[key] = data[key];\n }\n }\n }\n\n return sparseData;\n}\n\n/**\n * Iterates through a form group's controls and returns a sparse object with only the changed values.\n * @param form - The form group to iterate through\n * @param compareData - The object to compare the form's values to\n * @returns - A sparse object with only the changed values\n * @example sparseFormData<UserCreate>(this.userForm, initUser)\n */\nexport function sparseFormData<T>(form: FormGroup, compareData: T): T {\n const sparseFormData: T = {} as T;\n for (const key in form.controls) {\n if (Object.prototype.hasOwnProperty.call(form.controls, key)) {\n const control = form.controls[key];\n const controlValue = control.value;\n const compareValue = compareData[key as keyof T];\n if (controlValue !== compareValue) {\n sparseFormData[key as keyof T] = controlValue as T[keyof T];\n }\n }\n }\n return sparseFormData;\n}\n\n/**\n * Recursively cleans a FormGroup or FormArray, removing controls with empty string values.\n * Similar to sparseFormData, but doesn't compare to an initial state\n * @param control - The FormGroup or FormArray to clean.\n * @returns A cleaned object with non-empty values.\n */\nexport function cleanStringForm<T>(control: AbstractControl): T | undefined {\n if (control instanceof FormGroup) {\n const cleanedGroup: Record<string, unknown> = {};\n for (const key of Object.keys(control.controls)) {\n const childControl = control.get(key);\n if (childControl) {\n const cleanedValue = cleanStringForm(childControl);\n if (cleanedValue !== undefined && cleanedValue !== null && cleanedValue !== '') {\n cleanedGroup[key] = cleanedValue;\n }\n }\n }\n return cleanedGroup as T;\n } else if (control instanceof FormArray) {\n const cleanedArray = control.controls\n .map((childControl) => cleanStringForm(childControl))\n .filter((item) => item !== undefined && item !== null && item !== '');\n return cleanedArray as unknown as T;\n } else {\n return control.value !== '' ? control.value : undefined;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,14 +1,15 @@
1
1
  import { inject } from '@angular/core';
2
2
  import { MatDialog } from '@angular/material/dialog';
3
- import { AuthService } from '@cccteam/ccc-lib/auth-service';
4
- import { FormStateService, LeavePageConfirmationModalComponent } from '@cccteam/ccc-lib/ccc-resource';
3
+ import { LeavePageConfirmationModalComponent } from '@cccteam/ccc-lib/ccc-resource-modals';
4
+ import { FormStateService } from '@cccteam/ccc-lib/ccc-resource-services';
5
+ import { FRONTEND_LOGIN_PATH } from '@cccteam/ccc-lib/types';
5
6
  import { tap, firstValueFrom } from 'rxjs';
6
7
 
7
8
  const canDeactivateGuard = async (_, __, ___, nextState) => {
8
- const auth = inject(AuthService);
9
9
  const dialog = inject(MatDialog);
10
10
  const formStateService = inject(FormStateService);
11
- if (nextState?.url.includes(auth.loginRoute())) {
11
+ const loginPath = inject(FRONTEND_LOGIN_PATH);
12
+ if (nextState?.url.includes(loginPath)) {
12
13
  return true;
13
14
  }
14
15
  if (!formStateService.isDirty()) {
@@ -1 +1 @@
1
- {"version":3,"file":"cccteam-ccc-lib-guards.mjs","sources":["../../../projects/ccc-lib/guards/can-deactivate.guard.ts","../../../projects/ccc-lib/guards/cccteam-ccc-lib-guards.ts"],"sourcesContent":["import { inject } from '@angular/core';\nimport { MatDialog } from '@angular/material/dialog';\nimport { CanDeactivateFn, UrlTree } from '@angular/router';\nimport { AuthService } from '@cccteam/ccc-lib/auth-service';\nimport { FormStateService, LeavePageConfirmationModalComponent } from '@cccteam/ccc-lib/ccc-resource';\nimport { firstValueFrom, Observable, tap } from 'rxjs';\n\nexport type CanDeactivateType = Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree;\n\nexport interface CanComponentDeactivate {\n canDeactivate: () => CanDeactivateType;\n}\n\nexport const canDeactivateGuard: CanDeactivateFn<CanComponentDeactivate> = async (_, __, ___, nextState) => {\n const auth = inject(AuthService);\n const dialog = inject(MatDialog);\n const formStateService = inject(FormStateService);\n\n if (nextState?.url.includes(auth.loginRoute())) {\n return true;\n }\n\n if (!formStateService.isDirty()) {\n return true;\n }\n\n const existingDialog = dialog.openDialogs.find(\n (d) => d.componentInstance instanceof LeavePageConfirmationModalComponent,\n );\n\n const dialogRef = existingDialog ?? dialog.open(LeavePageConfirmationModalComponent, { delayFocusTrap: false });\n\n const result = dialogRef.afterClosed().pipe(\n tap((value) => {\n if (value === true) {\n formStateService.resetDirtyForms();\n }\n }),\n );\n\n return firstValueFrom(result);\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;AAaO,MAAM,kBAAkB,GAA4C,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,KAAI;AACzG,IAAA,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC;AAChC,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;AAChC,IAAA,MAAM,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAEjD,IAAA,IAAI,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;AAC9C,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE;AAC/B,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,MAAM,cAAc,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAC5C,CAAC,CAAC,KAAK,CAAC,CAAC,iBAAiB,YAAY,mCAAmC,CAC1E;AAED,IAAA,MAAM,SAAS,GAAG,cAAc,IAAI,MAAM,CAAC,IAAI,CAAC,mCAAmC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;AAE/G,IAAA,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,IAAI,CACzC,GAAG,CAAC,CAAC,KAAK,KAAI;AACZ,QAAA,IAAI,KAAK,KAAK,IAAI,EAAE;YAClB,gBAAgB,CAAC,eAAe,EAAE;QACpC;IACF,CAAC,CAAC,CACH;AAED,IAAA,OAAO,cAAc,CAAC,MAAM,CAAC;AAC/B;;ACzCA;;AAEG;;;;"}
1
+ {"version":3,"file":"cccteam-ccc-lib-guards.mjs","sources":["../../../projects/ccc-lib/guards/can-deactivate.guard.ts","../../../projects/ccc-lib/guards/cccteam-ccc-lib-guards.ts"],"sourcesContent":["import { inject } from '@angular/core';\nimport { MatDialog } from '@angular/material/dialog';\nimport { CanDeactivateFn, UrlTree } from '@angular/router';\nimport { LeavePageConfirmationModalComponent } from '@cccteam/ccc-lib/ccc-resource-modals';\nimport { FormStateService } from '@cccteam/ccc-lib/ccc-resource-services';\nimport { FRONTEND_LOGIN_PATH } from '@cccteam/ccc-lib/types';\nimport { firstValueFrom, Observable, tap } from 'rxjs';\n\nexport type CanDeactivateType = Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree;\n\nexport interface CanComponentDeactivate {\n canDeactivate: () => CanDeactivateType;\n}\n\nexport const canDeactivateGuard: CanDeactivateFn<CanComponentDeactivate> = async (_, __, ___, nextState) => {\n const dialog = inject(MatDialog);\n const formStateService = inject(FormStateService);\n const loginPath = inject(FRONTEND_LOGIN_PATH);\n\n if (nextState?.url.includes(loginPath)) {\n return true;\n }\n\n if (!formStateService.isDirty()) {\n return true;\n }\n\n const existingDialog = dialog.openDialogs.find(\n (d) => d.componentInstance instanceof LeavePageConfirmationModalComponent,\n );\n\n const dialogRef = existingDialog ?? dialog.open(LeavePageConfirmationModalComponent, { delayFocusTrap: false });\n\n const result = dialogRef.afterClosed().pipe(\n tap((value) => {\n if (value === true) {\n formStateService.resetDirtyForms();\n }\n }),\n );\n\n return firstValueFrom(result);\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;AAcO,MAAM,kBAAkB,GAA4C,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,KAAI;AACzG,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;AAChC,IAAA,MAAM,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;AACjD,IAAA,MAAM,SAAS,GAAG,MAAM,CAAC,mBAAmB,CAAC;IAE7C,IAAI,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;AACtC,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE;AAC/B,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,MAAM,cAAc,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAC5C,CAAC,CAAC,KAAK,CAAC,CAAC,iBAAiB,YAAY,mCAAmC,CAC1E;AAED,IAAA,MAAM,SAAS,GAAG,cAAc,IAAI,MAAM,CAAC,IAAI,CAAC,mCAAmC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;AAE/G,IAAA,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,IAAI,CACzC,GAAG,CAAC,CAAC,KAAK,KAAI;AACZ,QAAA,IAAI,KAAK,KAAK,IAAI,EAAE;YAClB,gBAAgB,CAAC,eAAe,EAAE;QACpC;IACF,CAAC,CAAC,CACH;AAED,IAAA,OAAO,cAAc,CAAC,MAAM,CAAC;AAC/B;;AC1CA;;AAEG;;;;"}
@@ -3,7 +3,7 @@ import { inject, signal, computed, Injectable } from '@angular/core';
3
3
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
4
  import { Router } from '@angular/router';
5
5
  import { AuthService } from '@cccteam/ccc-lib/auth-service';
6
- import { IDLE_SESSION_DURATION, IDLE_WARNING_DURATION, IDLE_KEEPALIVE_DURATION, AlertLevel } from '@cccteam/ccc-lib/types';
6
+ import { FRONTEND_LOGIN_PATH, IDLE_SESSION_DURATION, IDLE_WARNING_DURATION, IDLE_KEEPALIVE_DURATION, AlertLevel } from '@cccteam/ccc-lib/types';
7
7
  import { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';
8
8
  import { NotificationService } from '@cccteam/ccc-lib/ui-notification-service';
9
9
  import { interval } from 'rxjs';
@@ -13,6 +13,7 @@ class IdleService {
13
13
  core = inject(UiCoreService);
14
14
  router = inject(Router);
15
15
  notifications = inject(NotificationService);
16
+ loginPath = inject(FRONTEND_LOGIN_PATH);
16
17
  sessionDuration = inject(IDLE_SESSION_DURATION);
17
18
  warningDuration = inject(IDLE_WARNING_DURATION);
18
19
  keepAliveDuration = inject(IDLE_KEEPALIVE_DURATION);
@@ -73,7 +74,7 @@ class IdleService {
73
74
  */
74
75
  logoutAndStop() {
75
76
  this.stop();
76
- this.router.navigate([this.auth.loginRoute()]);
77
+ this.router.navigate([this.loginPath]);
77
78
  this.core.publishError({
78
79
  message: 'You have been logged out due to inactivity.',
79
80
  level: AlertLevel.INFO,
@@ -1 +1 @@
1
- {"version":3,"file":"cccteam-ccc-lib-ui-idle-service.mjs","sources":["../../../projects/ccc-lib/ui-idle-service/idle.service.ts","../../../projects/ccc-lib/ui-idle-service/cccteam-ccc-lib-ui-idle-service.ts"],"sourcesContent":["import { computed, inject, Injectable, OnDestroy, signal, WritableSignal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { Router } from '@angular/router';\nimport { AuthService } from '@cccteam/ccc-lib/auth-service';\nimport {\n AlertLevel,\n IDLE_KEEPALIVE_DURATION,\n IDLE_SESSION_DURATION,\n IDLE_WARNING_DURATION,\n} from '@cccteam/ccc-lib/types';\nimport { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';\nimport { NotificationService } from '@cccteam/ccc-lib/ui-notification-service';\nimport { interval, Subscription } from 'rxjs';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class IdleService implements OnDestroy {\n private auth = inject(AuthService);\n private core = inject(UiCoreService);\n private router = inject(Router);\n private notifications = inject(NotificationService);\n\n private readonly sessionDuration = inject(IDLE_SESSION_DURATION);\n private readonly warningDuration = inject(IDLE_WARNING_DURATION);\n private readonly keepAliveDuration = inject(IDLE_KEEPALIVE_DURATION);\n private readonly idleCheckFrequency = 1000;\n private readonly warningThreshold = this.sessionDuration - this.warningDuration;\n\n public readonly isActive = signal(false);\n private lastActivityTimestamp: WritableSignal<number> = signal(0);\n private tick = signal(Date.now());\n\n public readonly secondsIdle = computed(() => {\n if (!this.isActive() || this.lastActivityTimestamp() === 0) {\n return 0;\n }\n // Depends on tick() to force re-evaluation as time passes\n return Math.floor((this.tick() - this.lastActivityTimestamp()) / 1000);\n });\n\n public readonly isWarning = computed(() => this.secondsIdle() >= this.warningThreshold);\n public readonly countdown = computed(() => {\n if (!this.isWarning()) {\n return 0;\n }\n const remaining = this.sessionDuration - this.secondsIdle();\n return Math.max(0, remaining);\n });\n\n private alertId: number | undefined;\n private mainTickerSubscription: Subscription | undefined;\n\n private readonly activityEvents = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart', 'click'];\n\n constructor() {\n interval(this.keepAliveDuration * 1000)\n .pipe(takeUntilDestroyed())\n .subscribe(() => this.checkSession());\n }\n\n ngOnDestroy(): void {\n this.stop();\n }\n\n /**\n * Starts the idle monitoring service.\n */\n start(): void {\n if (this.isActive()) {\n return;\n }\n this.isActive.set(true);\n this.lastActivityTimestamp.set(Date.now());\n this.addActivityListeners();\n this.startMainTicker();\n }\n\n /**\n * Stops the idle monitoring service and cleans up timers and alerts.\n */\n stop(): void {\n this.isActive.set(false);\n this.mainTickerSubscription?.unsubscribe();\n this.removeActivityListeners();\n this.dismissWarningAlert();\n }\n\n /**\n * Logs out the user due to inactivity and stops the service.\n */\n logoutAndStop(): void {\n this.stop();\n\n this.router.navigate([this.auth.loginRoute()]);\n this.core.publishError({\n message: 'You have been logged out due to inactivity.',\n level: AlertLevel.INFO,\n link: '',\n });\n }\n\n private startMainTicker(): void {\n this.mainTickerSubscription = interval(this.idleCheckFrequency).subscribe(() => {\n this.tick.set(Date.now());\n\n if (this.secondsIdle() >= this.sessionDuration) {\n this.logoutAndStop();\n return;\n }\n\n if (this.isWarning()) {\n this.showOrUpdateWarningAlert(this.countdown());\n } else {\n this.dismissWarningAlert();\n }\n });\n }\n\n private checkSession(): void {\n if (this.auth.authenticated()) {\n this.auth.checkUserSession().subscribe({\n next: () => {\n if (!this.auth.authenticated()) {\n this.logoutAndStop();\n }\n },\n });\n }\n }\n\n setLastActivity(): void {\n this.lastActivityTimestamp.set(Date.now());\n }\n boundActivity = this.setLastActivity.bind(this);\n\n private addActivityListeners(): void {\n this.activityEvents.forEach((event) => {\n document.addEventListener(event, this.boundActivity, true);\n });\n }\n\n private removeActivityListeners(): void {\n this.activityEvents.forEach((event) => {\n document.removeEventListener(event, this.boundActivity, true);\n });\n }\n\n private showOrUpdateWarningAlert(countdown: number): void {\n const message = `You will be logged out in ${countdown} seconds due to inactivity.`;\n if (this.alertId !== undefined) {\n this.notifications.updateNotification({ id: this.alertId, level: AlertLevel.INFO, link: '', message });\n } else {\n this.alertId = this.notifications.addGlobalNotification({\n message,\n level: AlertLevel.INFO,\n link: '',\n });\n }\n }\n\n private dismissWarningAlert(): void {\n if (this.alertId !== undefined) {\n this.notifications.dismissGlobalNotificationById(this.alertId);\n this.alertId = undefined;\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cccteam-ccc-lib-ui-idle-service.mjs","sources":["../../../projects/ccc-lib/ui-idle-service/idle.service.ts","../../../projects/ccc-lib/ui-idle-service/cccteam-ccc-lib-ui-idle-service.ts"],"sourcesContent":["import { computed, inject, Injectable, OnDestroy, signal, WritableSignal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { Router } from '@angular/router';\nimport { AuthService } from '@cccteam/ccc-lib/auth-service';\nimport {\n AlertLevel,\n FRONTEND_LOGIN_PATH,\n IDLE_KEEPALIVE_DURATION,\n IDLE_SESSION_DURATION,\n IDLE_WARNING_DURATION,\n} from '@cccteam/ccc-lib/types';\nimport { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';\nimport { NotificationService } from '@cccteam/ccc-lib/ui-notification-service';\nimport { interval, Subscription } from 'rxjs';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class IdleService implements OnDestroy {\n private auth = inject(AuthService);\n private core = inject(UiCoreService);\n private router = inject(Router);\n private notifications = inject(NotificationService);\n private readonly loginPath = inject(FRONTEND_LOGIN_PATH);\n\n private readonly sessionDuration = inject(IDLE_SESSION_DURATION);\n private readonly warningDuration = inject(IDLE_WARNING_DURATION);\n private readonly keepAliveDuration = inject(IDLE_KEEPALIVE_DURATION);\n private readonly idleCheckFrequency = 1000;\n private readonly warningThreshold = this.sessionDuration - this.warningDuration;\n\n public readonly isActive = signal(false);\n private lastActivityTimestamp: WritableSignal<number> = signal(0);\n private tick = signal(Date.now());\n\n public readonly secondsIdle = computed(() => {\n if (!this.isActive() || this.lastActivityTimestamp() === 0) {\n return 0;\n }\n // Depends on tick() to force re-evaluation as time passes\n return Math.floor((this.tick() - this.lastActivityTimestamp()) / 1000);\n });\n\n public readonly isWarning = computed(() => this.secondsIdle() >= this.warningThreshold);\n public readonly countdown = computed(() => {\n if (!this.isWarning()) {\n return 0;\n }\n const remaining = this.sessionDuration - this.secondsIdle();\n return Math.max(0, remaining);\n });\n\n private alertId: number | undefined;\n private mainTickerSubscription: Subscription | undefined;\n\n private readonly activityEvents = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart', 'click'];\n\n constructor() {\n interval(this.keepAliveDuration * 1000)\n .pipe(takeUntilDestroyed())\n .subscribe(() => this.checkSession());\n }\n\n ngOnDestroy(): void {\n this.stop();\n }\n\n /**\n * Starts the idle monitoring service.\n */\n start(): void {\n if (this.isActive()) {\n return;\n }\n this.isActive.set(true);\n this.lastActivityTimestamp.set(Date.now());\n this.addActivityListeners();\n this.startMainTicker();\n }\n\n /**\n * Stops the idle monitoring service and cleans up timers and alerts.\n */\n stop(): void {\n this.isActive.set(false);\n this.mainTickerSubscription?.unsubscribe();\n this.removeActivityListeners();\n this.dismissWarningAlert();\n }\n\n /**\n * Logs out the user due to inactivity and stops the service.\n */\n logoutAndStop(): void {\n this.stop();\n\n this.router.navigate([this.loginPath]);\n this.core.publishError({\n message: 'You have been logged out due to inactivity.',\n level: AlertLevel.INFO,\n link: '',\n });\n }\n\n private startMainTicker(): void {\n this.mainTickerSubscription = interval(this.idleCheckFrequency).subscribe(() => {\n this.tick.set(Date.now());\n\n if (this.secondsIdle() >= this.sessionDuration) {\n this.logoutAndStop();\n return;\n }\n\n if (this.isWarning()) {\n this.showOrUpdateWarningAlert(this.countdown());\n } else {\n this.dismissWarningAlert();\n }\n });\n }\n\n private checkSession(): void {\n if (this.auth.authenticated()) {\n this.auth.checkUserSession().subscribe({\n next: () => {\n if (!this.auth.authenticated()) {\n this.logoutAndStop();\n }\n },\n });\n }\n }\n\n setLastActivity(): void {\n this.lastActivityTimestamp.set(Date.now());\n }\n boundActivity = this.setLastActivity.bind(this);\n\n private addActivityListeners(): void {\n this.activityEvents.forEach((event) => {\n document.addEventListener(event, this.boundActivity, true);\n });\n }\n\n private removeActivityListeners(): void {\n this.activityEvents.forEach((event) => {\n document.removeEventListener(event, this.boundActivity, true);\n });\n }\n\n private showOrUpdateWarningAlert(countdown: number): void {\n const message = `You will be logged out in ${countdown} seconds due to inactivity.`;\n if (this.alertId !== undefined) {\n this.notifications.updateNotification({ id: this.alertId, level: AlertLevel.INFO, link: '', message });\n } else {\n this.alertId = this.notifications.addGlobalNotification({\n message,\n level: AlertLevel.INFO,\n link: '',\n });\n }\n }\n\n private dismissWarningAlert(): void {\n if (this.alertId !== undefined) {\n this.notifications.dismissGlobalNotificationById(this.alertId);\n this.alertId = undefined;\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { inject, NgZone, Injectable } from '@angular/core';
3
3
  import { Router } from '@angular/router';
4
4
  import { AuthService } from '@cccteam/ccc-lib/auth-service';
5
- import { BASE_URL, AlertLevel } from '@cccteam/ccc-lib/types';
5
+ import { BASE_URL, FRONTEND_LOGIN_PATH, AlertLevel } from '@cccteam/ccc-lib/types';
6
6
  import { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';
7
7
  import { CUSTOM_HTTP_REQUEST_OPTIONS } from '@cccteam/ccc-lib/util-request-options';
8
8
  import { catchError, throwError, finalize } from 'rxjs';
@@ -13,13 +13,14 @@ class ApiInterceptor {
13
13
  router = inject(Router);
14
14
  ngZone = inject(NgZone);
15
15
  baseUrl = inject(BASE_URL);
16
+ loginPath = inject(FRONTEND_LOGIN_PATH);
16
17
  intercept(request, next) {
17
18
  this.ui.beginActivity(request.method + ' ' + request.url);
18
19
  return next.handle(request).pipe(catchError((error) => {
19
20
  if (error.status === 401) {
20
21
  this.ngZone.run(() => {
21
22
  this.auth.redirectUrl.set(this.baseUrl + this.router.url);
22
- this.router.navigate([this.auth.loginRoute()]);
23
+ this.router.navigate([this.loginPath]);
23
24
  });
24
25
  }
25
26
  if (!request.context.get(CUSTOM_HTTP_REQUEST_OPTIONS).suppressGlobalError) {
@@ -1 +1 @@
1
- {"version":3,"file":"cccteam-ccc-lib-ui-interceptor.mjs","sources":["../../../projects/ccc-lib/ui-interceptor/api.interceptor.ts","../../../projects/ccc-lib/ui-interceptor/cccteam-ccc-lib-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 { AuthService } from '@cccteam/ccc-lib/auth-service';\nimport { AlertLevel, BASE_URL } from '@cccteam/ccc-lib/types';\nimport { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';\nimport { CUSTOM_HTTP_REQUEST_OPTIONS } from '@cccteam/ccc-lib/util-request-options';\nimport { catchError, finalize, Observable, throwError } from 'rxjs';\n\n@Injectable()\nexport class ApiInterceptor implements HttpInterceptor {\n private ui = inject(UiCoreService);\n private auth = inject(AuthService);\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.ui.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.auth.redirectUrl.set(this.baseUrl + this.router.url);\n this.router.navigate([this.auth.loginRoute()]);\n });\n }\n if (!request.context.get(CUSTOM_HTTP_REQUEST_OPTIONS).suppressGlobalError) {\n const message = error.error?.message ?? error.message ?? error.error;\n this.ui.publishError({\n message: message,\n level: AlertLevel.ERROR,\n link: '',\n });\n }\n\n return throwError(() => error);\n }),\n finalize(() => {\n this.ui.endActivity(request.method + ' ' + request.url);\n }),\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;MAUa,cAAc,CAAA;AACjB,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;AAC1B,IAAA,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC;AAC1B,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;AACxD,QAAA,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;AAEzD,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;AACnB,oBAAA,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;AACzD,oBAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;AAChD,gBAAA,CAAC,CAAC;YACJ;AACA,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;AACpE,gBAAA,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC;AACnB,oBAAA,OAAO,EAAE,OAAO;oBAChB,KAAK,EAAE,UAAU,CAAC,KAAK;AACvB,oBAAA,IAAI,EAAE,EAAE;AACT,iBAAA,CAAC;YACJ;AAEA,YAAA,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC;AAChC,QAAA,CAAC,CAAC,EACF,QAAQ,CAAC,MAAK;AACZ,YAAA,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACzD,CAAC,CAAC,CACH;IACH;uGAjCW,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;;;ACTD;;AAEG;;;;"}
1
+ {"version":3,"file":"cccteam-ccc-lib-ui-interceptor.mjs","sources":["../../../projects/ccc-lib/ui-interceptor/api.interceptor.ts","../../../projects/ccc-lib/ui-interceptor/cccteam-ccc-lib-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 { AuthService } from '@cccteam/ccc-lib/auth-service';\nimport { AlertLevel, BASE_URL, FRONTEND_LOGIN_PATH } from '@cccteam/ccc-lib/types';\nimport { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';\nimport { CUSTOM_HTTP_REQUEST_OPTIONS } from '@cccteam/ccc-lib/util-request-options';\nimport { catchError, finalize, Observable, throwError } from 'rxjs';\n\n@Injectable()\nexport class ApiInterceptor implements HttpInterceptor {\n private ui = inject(UiCoreService);\n private auth = inject(AuthService);\n private router = inject(Router);\n private ngZone = inject(NgZone);\n private baseUrl = inject(BASE_URL);\n private loginPath = inject(FRONTEND_LOGIN_PATH);\n\n intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\n this.ui.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.auth.redirectUrl.set(this.baseUrl + this.router.url);\n this.router.navigate([this.loginPath]);\n });\n }\n if (!request.context.get(CUSTOM_HTTP_REQUEST_OPTIONS).suppressGlobalError) {\n const message = error.error?.message ?? error.message ?? error.error;\n this.ui.publishError({\n message: message,\n level: AlertLevel.ERROR,\n link: '',\n });\n }\n\n return throwError(() => error);\n }),\n finalize(() => {\n this.ui.endActivity(request.method + ' ' + request.url);\n }),\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;MAUa,cAAc,CAAA;AACjB,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;AAC1B,IAAA,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC;AAC1B,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,IAAA,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC;AAC1B,IAAA,SAAS,GAAG,MAAM,CAAC,mBAAmB,CAAC;IAE/C,SAAS,CAAC,OAA6B,EAAE,IAAiB,EAAA;AACxD,QAAA,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;AAEzD,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;AACnB,oBAAA,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;oBACzD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACxC,gBAAA,CAAC,CAAC;YACJ;AACA,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;AACpE,gBAAA,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC;AACnB,oBAAA,OAAO,EAAE,OAAO;oBAChB,KAAK,EAAE,UAAU,CAAC,KAAK;AACvB,oBAAA,IAAI,EAAE,EAAE;AACT,iBAAA,CAAC;YACJ;AAEA,YAAA,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC;AAChC,QAAA,CAAC,CAAC,EACF,QAAQ,CAAC,MAAK;AACZ,YAAA,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACzD,CAAC,CAAC,CACH;IACH;uGAlCW,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;;;ACTD;;AAEG;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cccteam/ccc-lib",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git://github.com/cccteam/ccc-lib.git"
@@ -57,6 +57,14 @@
57
57
  "types": "./types/cccteam-ccc-lib-ccc-resource.d.ts",
58
58
  "default": "./fesm2022/cccteam-ccc-lib-ccc-resource.mjs"
59
59
  },
60
+ "./ccc-resource-modals": {
61
+ "types": "./types/cccteam-ccc-lib-ccc-resource-modals.d.ts",
62
+ "default": "./fesm2022/cccteam-ccc-lib-ccc-resource-modals.mjs"
63
+ },
64
+ "./ccc-resource-services": {
65
+ "types": "./types/cccteam-ccc-lib-ccc-resource-services.d.ts",
66
+ "default": "./fesm2022/cccteam-ccc-lib-ccc-resource-services.mjs"
67
+ },
60
68
  "./forms": {
61
69
  "types": "./types/cccteam-ccc-lib-forms.d.ts",
62
70
  "default": "./fesm2022/cccteam-ccc-lib-forms.mjs"
@@ -0,0 +1,8 @@
1
+ import * as i0 from '@angular/core';
2
+
3
+ declare class LeavePageConfirmationModalComponent {
4
+ static ɵfac: i0.ɵɵFactoryDeclaration<LeavePageConfirmationModalComponent, never>;
5
+ static ɵcmp: i0.ɵɵComponentDeclaration<LeavePageConfirmationModalComponent, "ccc-leave-page-confirmation-modal", never, {}, {}, never, never, true, never>;
6
+ }
7
+
8
+ export { LeavePageConfirmationModalComponent };
@@ -0,0 +1,13 @@
1
+ import * as _angular_core from '@angular/core';
2
+
3
+ declare class FormStateService {
4
+ dirtyForms: _angular_core.WritableSignal<number>;
5
+ incrementDirtyForms(): void;
6
+ decrementDirtyForms(): void;
7
+ resetDirtyForms(): void;
8
+ isDirty: _angular_core.Signal<boolean>;
9
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormStateService, never>;
10
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<FormStateService>;
11
+ }
12
+
13
+ export { FormStateService };
@@ -4,6 +4,7 @@ import * as _cccteam_ccc_lib_types from '@cccteam/ccc-lib/types';
4
4
  import { ResourceMeta, RecordData, Resource, DataType, ViewConfig, ConfigElement, RPCRecordData, MethodMeta, FieldSort, ColumnConfig, RPCConfig, FieldElement, Method, RPCBaseFormData, RootConfig, ParentResourceConfig, ChildResourceConfig, FormatType, PaddingElement, ArrayConfig, ListViewConfig, Meta, FieldMeta, RPCFieldMeta, ValidDisplayTypes, ComponentConfig } from '@cccteam/ccc-lib/types';
5
5
  import { MatDialog } from '@angular/material/dialog';
6
6
  import { Router, ActivatedRoute } from '@angular/router';
7
+ import { FormStateService } from '@cccteam/ccc-lib/ccc-resource-services';
7
8
  import { NotificationService } from '@cccteam/ccc-lib/ui-notification-service';
8
9
  import { HttpClient } from '@angular/common/http';
9
10
  import { Observable } from 'rxjs';
@@ -29,16 +30,6 @@ declare class ActionAccessControlWrapperComponent {
29
30
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ActionAccessControlWrapperComponent, "action-access-control-wrapper", never, { "actionContext": { "alias": "actionContext"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
30
31
  }
31
32
 
32
- declare class FormStateService {
33
- dirtyForms: _angular_core.WritableSignal<number>;
34
- incrementDirtyForms(): void;
35
- decrementDirtyForms(): void;
36
- resetDirtyForms(): void;
37
- isDirty: _angular_core.Signal<boolean>;
38
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormStateService, never>;
39
- static ɵprov: _angular_core.ɵɵInjectableDeclaration<FormStateService>;
40
- }
41
-
42
33
  interface Link {
43
34
  id: string;
44
35
  resource: Resource;
@@ -282,6 +273,15 @@ declare function hyphenSpaceConcatWithoutResource(args: string[]): string;
282
273
  * @example noSpaceConcatWithoutResource(['foo', 'bar', 'baz']) => 'foobarbaz'
283
274
  */
284
275
  declare function noSpaceConcatWithoutResource(args: string[]): string;
276
+ /**
277
+ * Converts a string to camelCase.
278
+ * @param str The string to convert.
279
+ * @returns The camelCase version of the string.
280
+ * @example camelCase('hello-world') => 'helloWorld'
281
+ * @example camelCase('HelloWorld') => 'helloWorld'
282
+ * @example camelCase('hello_world') => 'helloWorld'
283
+ */
284
+ declare function camelCase(str: string): string;
285
285
 
286
286
  declare class DeleteResourceConfirmationModalComponent {
287
287
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DeleteResourceConfirmationModalComponent, never>;
@@ -324,11 +324,6 @@ declare const resourceValidators: Readonly<{
324
324
  MAX_LENGTH: (maxLength: number) => _cccteam_ccc_lib_types.ResourceValidatorFn;
325
325
  }>;
326
326
 
327
- declare class LeavePageConfirmationModalComponent {
328
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<LeavePageConfirmationModalComponent, never>;
329
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<LeavePageConfirmationModalComponent, "ccc-leave-page-confirmation-modal", never, {}, {}, never, never, true, never>;
330
- }
331
-
332
327
  declare class PaddingElementComponent implements OnInit {
333
328
  paddingElement: _angular_core.InputSignal<PaddingElement>;
334
329
  class: string;
@@ -631,5 +626,5 @@ declare class ResourceViewComponent implements OnInit {
631
626
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ResourceViewComponent, "ccc-resource-view", never, { "uuid": { "alias": "uuid"; "required": true; "isSignal": true; }; "config": { "alias": "config"; "required": true; "isSignal": true; }; "relatedData": { "alias": "relatedData"; "required": false; "isSignal": true; }; "compoundResourceView": { "alias": "compoundResourceView"; "required": false; "isSignal": true; }; "navAfterDelete": { "alias": "navAfterDelete"; "required": false; "isSignal": true; }; "showCreateForm": { "alias": "showCreateForm"; "required": false; "isSignal": true; }; }, { "deleted": "deleted"; "showCreateForm": "showCreateFormChange"; }, never, never, true, never>;
632
627
  }
633
628
 
634
- export { ActionAccessControlWrapperComponent, BaseInputComponent, BaseRPCModalComponent, CompoundResourceComponent, DeleteResourceConfirmationModalComponent, EmptyReadonlyFieldComponent, FormStateService, LeavePageConfirmationModalComponent, PaddingElementComponent, ResourceArrayViewComponent, ResourceCreateComponent, ResourceFieldComponent, ResourceLayoutComponent, ResourceListComponent, ResourceListCreateComponent, ResourceResolverComponent, ResourceStore, ResourceViewComponent, RpcButtonComponent, ValueFormatters, applyFormatting, civildateCoercion, concatFunctions, createFormGroup, extractFieldNames, flattenElements, formatDateString, hyphenConcat, hyphenConcatWithoutResource, hyphenSpaceConcat, hyphenSpaceConcatWithoutResource, isUUID, maxConfigElementRecursionDepth, maxLayoutNestingDepth, metadataTypeCoercion, noSpaceConcatWithoutResource, resourceValidators, simpleSlashDateFormatter, spaceConcat, spaceConcatWithoutResource, spaceHyphenConcat, spaceHyphenConcatWithoutResource };
629
+ export { ActionAccessControlWrapperComponent, BaseInputComponent, BaseRPCModalComponent, CompoundResourceComponent, DeleteResourceConfirmationModalComponent, EmptyReadonlyFieldComponent, PaddingElementComponent, ResourceArrayViewComponent, ResourceCreateComponent, ResourceFieldComponent, ResourceLayoutComponent, ResourceListComponent, ResourceListCreateComponent, ResourceResolverComponent, ResourceStore, ResourceViewComponent, RpcButtonComponent, ValueFormatters, applyFormatting, camelCase, civildateCoercion, concatFunctions, createFormGroup, extractFieldNames, flattenElements, formatDateString, hyphenConcat, hyphenConcatWithoutResource, hyphenSpaceConcat, hyphenSpaceConcatWithoutResource, isUUID, maxConfigElementRecursionDepth, maxLayoutNestingDepth, metadataTypeCoercion, noSpaceConcatWithoutResource, resourceValidators, simpleSlashDateFormatter, spaceConcat, spaceConcatWithoutResource, spaceHyphenConcat, spaceHyphenConcatWithoutResource };
635
630
  export type { ActionButtonContext, CreateOperation, DeleteOperation, FormatterFn, Link, Operation, PatchOperation, PristineData, UpdateOperation };
@@ -6,6 +6,7 @@ declare class IdleService implements OnDestroy {
6
6
  private core;
7
7
  private router;
8
8
  private notifications;
9
+ private readonly loginPath;
9
10
  private readonly sessionDuration;
10
11
  private readonly warningDuration;
11
12
  private readonly keepAliveDuration;
@@ -8,6 +8,7 @@ declare class ApiInterceptor implements HttpInterceptor {
8
8
  private router;
9
9
  private ngZone;
10
10
  private baseUrl;
11
+ private loginPath;
11
12
  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>>;
12
13
  static ɵfac: i0.ɵɵFactoryDeclaration<ApiInterceptor, never>;
13
14
  static ɵprov: i0.ɵɵInjectableDeclaration<ApiInterceptor>;