@cccteam/ccc-lib 0.0.24 → 0.0.25
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.
- package/fesm2022/cccteam-ccc-lib-auth-forms.mjs +13 -13
- package/fesm2022/cccteam-ccc-lib-auth-forms.mjs.map +1 -1
- package/fesm2022/cccteam-ccc-lib-auth-has-permission.mjs +4 -4
- package/fesm2022/cccteam-ccc-lib-auth-has-permission.mjs.map +1 -1
- package/fesm2022/cccteam-ccc-lib-auth-service.mjs +15 -8
- package/fesm2022/cccteam-ccc-lib-auth-service.mjs.map +1 -1
- package/fesm2022/cccteam-ccc-lib-ccc-camel-case-to-title.mjs +3 -3
- package/fesm2022/cccteam-ccc-lib-ccc-grid.mjs +20 -20
- package/fesm2022/cccteam-ccc-lib-ccc-grid.mjs.map +1 -1
- package/fesm2022/cccteam-ccc-lib-ccc-resource-modals.mjs +3 -3
- package/fesm2022/cccteam-ccc-lib-ccc-resource-services.mjs +5 -5
- package/fesm2022/cccteam-ccc-lib-ccc-resource-services.mjs.map +1 -1
- package/fesm2022/cccteam-ccc-lib-ccc-resource.mjs +287 -281
- package/fesm2022/cccteam-ccc-lib-ccc-resource.mjs.map +1 -1
- package/fesm2022/cccteam-ccc-lib-types.mjs +70 -18
- package/fesm2022/cccteam-ccc-lib-types.mjs.map +1 -1
- package/fesm2022/cccteam-ccc-lib-ui-alert.mjs +3 -3
- package/fesm2022/cccteam-ccc-lib-ui-core-service.mjs +7 -7
- package/fesm2022/cccteam-ccc-lib-ui-core-service.mjs.map +1 -1
- package/fesm2022/cccteam-ccc-lib-ui-idle-service.mjs +18 -11
- package/fesm2022/cccteam-ccc-lib-ui-idle-service.mjs.map +1 -1
- package/fesm2022/cccteam-ccc-lib-ui-interceptor.mjs +3 -3
- package/fesm2022/cccteam-ccc-lib-ui-notification-service.mjs +5 -5
- package/fesm2022/cccteam-ccc-lib-ui-notification-service.mjs.map +1 -1
- package/fesm2022/cccteam-ccc-lib-ui-sidenav.mjs +4 -4
- package/fesm2022/cccteam-ccc-lib-ui-sidenav.mjs.map +1 -1
- package/package.json +1 -1
- package/types/cccteam-ccc-lib-auth-service.d.ts +2 -1
- package/types/cccteam-ccc-lib-forms.d.ts +1 -1
- package/types/cccteam-ccc-lib-types.d.ts +45 -1
- package/types/cccteam-ccc-lib-ui-idle-service.d.ts +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cccteam-ccc-lib-ui-notification-service.mjs","sources":["../../../projects/ccc-lib/ui-notification-service/notification.service.ts","../../../projects/ccc-lib/ui-notification-service/cccteam-ccc-lib-ui-notification-service.ts"],"sourcesContent":["import { Injectable, signal } from '@angular/core';\nimport { CreateNotificationMessage, NotificationMessage } from '@cccteam/ccc-lib/types';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class NotificationService {\n private notificationId = signal(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 this.notificationId.update((id) => id + 1);\n const newNotification: NotificationMessage = {\n ...notification,\n id: this.notificationId(),\n };\n const existingNotification = this._notifications().find((n) => n.message === newNotification.message);\n if (existingNotification) {\n this.updateNotification({ ...existingNotification, ...newNotification });\n return existingNotification.id;\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 './index';\n"],"names":[],"mappings":";;;MAMa,mBAAmB,CAAA;AACtB,IAAA,cAAc,GAAG,MAAM,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"cccteam-ccc-lib-ui-notification-service.mjs","sources":["../../../projects/ccc-lib/ui-notification-service/notification.service.ts","../../../projects/ccc-lib/ui-notification-service/cccteam-ccc-lib-ui-notification-service.ts"],"sourcesContent":["import { Injectable, signal } from '@angular/core';\nimport { CreateNotificationMessage, NotificationMessage } from '@cccteam/ccc-lib/types';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class NotificationService {\n private notificationId = signal(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 this.notificationId.update((id) => id + 1);\n const newNotification: NotificationMessage = {\n ...notification,\n id: this.notificationId(),\n };\n const existingNotification = this._notifications().find((n) => n.message === newNotification.message);\n if (existingNotification) {\n this.updateNotification({ ...existingNotification, ...newNotification });\n return existingNotification.id;\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 './index';\n"],"names":[],"mappings":";;;MAMa,mBAAmB,CAAA;AACtB,IAAA,cAAc,GAAG,MAAM,CAAC,CAAC,0DAAC;AAC1B,IAAA,cAAc,GAAG,MAAM,CAAwB,EAAE,0DAAC;AAC1D,IAAA,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE;AAEhD;;;;AAIG;AACH,IAAA,qBAAqB,CAAC,YAAuC,EAAA;AAC3D,QAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AAC1C,QAAA,MAAM,eAAe,GAAwB;AAC3C,YAAA,GAAG,YAAY;AACf,YAAA,EAAE,EAAE,IAAI,CAAC,cAAc,EAAE;SAC1B;QACD,MAAM,oBAAoB,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,KAAK,eAAe,CAAC,OAAO,CAAC;QACrG,IAAI,oBAAoB,EAAE;YACxB,IAAI,CAAC,kBAAkB,CAAC,EAAE,GAAG,oBAAoB,EAAE,GAAG,eAAe,EAAE,CAAC;YACxE,OAAO,oBAAoB,CAAC,EAAE;QAChC;AACA,QAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,OAAO,KAAK,CAAC,GAAG,OAAO,EAAE,eAAe,CAAC,CAAC;QACtE,OAAO,eAAe,CAAC,EAAE;IAC3B;AAEA;;;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;IAC/G;AAEA;;;AAGG;AACH,IAAA,yBAAyB,CAAC,YAAiC,EAAA;AACzD,QAAA,IAAI,CAAC,6BAA6B,CAAC,YAAY,CAAC,EAAE,CAAC;IACrD;AAEA;;;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;IACH;uGAnDW,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;;;;"}
|
|
@@ -17,7 +17,7 @@ class SidenavComponent {
|
|
|
17
17
|
navGroups;
|
|
18
18
|
currentNav = computed(() => {
|
|
19
19
|
return this.updateNavItems(this.ui.currentSidenavIdentifier());
|
|
20
|
-
},
|
|
20
|
+
}, ...(ngDevMode ? [{ debugName: "currentNav" }] : []));
|
|
21
21
|
/**
|
|
22
22
|
* Updates the currentNav based on the identifier
|
|
23
23
|
* @param identifier
|
|
@@ -34,10 +34,10 @@ class SidenavComponent {
|
|
|
34
34
|
}
|
|
35
35
|
return this.navGroups[identifier];
|
|
36
36
|
}
|
|
37
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
38
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
37
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: SidenavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
38
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", 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) {\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: "ngmodule", type: MatExpansionModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatSidenavModule }, { kind: "directive", type: HasPermissionDirective, selector: "[cccHasPermission]", inputs: ["cccHasPermission"] }, { kind: "pipe", type: i3.TitleCasePipe, name: "titlecase" }] });
|
|
39
39
|
}
|
|
40
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
40
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: SidenavComponent, decorators: [{
|
|
41
41
|
type: Component,
|
|
42
42
|
args: [{ selector: 'ccc-sidenav', imports: [
|
|
43
43
|
MatIconModule,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cccteam-ccc-lib-ui-sidenav.mjs","sources":["../../../projects/ccc-lib/ui-sidenav/sidenav.component.ts","../../../projects/ccc-lib/ui-sidenav/sidenav.component.html","../../../projects/ccc-lib/ui-sidenav/cccteam-ccc-lib-ui-sidenav.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { Component, computed, inject, Input, Signal } from '@angular/core';\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';\n\nimport { HasPermissionDirective } from '@cccteam/ccc-lib/auth-has-permission';\nimport { PermissionScope } from '@cccteam/ccc-lib/types';\nimport { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';\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?: Signal<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 {\n ui = inject(UiCoreService);\n\n @Input() navGroups?: NavGroups;\n currentNav = computed(() => {\n return this.updateNavItems(this.ui.currentSidenavIdentifier());\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) {\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 './index';\n"],"names":[],"mappings":";;;;;;;;;;;;;;MAuCa,gBAAgB,CAAA;AAC3B,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;AAEjB,IAAA,SAAS;AAClB,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAK;QACzB,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,wBAAwB,EAAE,CAAC;AAChE,IAAA,CAAC,
|
|
1
|
+
{"version":3,"file":"cccteam-ccc-lib-ui-sidenav.mjs","sources":["../../../projects/ccc-lib/ui-sidenav/sidenav.component.ts","../../../projects/ccc-lib/ui-sidenav/sidenav.component.html","../../../projects/ccc-lib/ui-sidenav/cccteam-ccc-lib-ui-sidenav.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { Component, computed, inject, Input, Signal } from '@angular/core';\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';\n\nimport { HasPermissionDirective } from '@cccteam/ccc-lib/auth-has-permission';\nimport { PermissionScope } from '@cccteam/ccc-lib/types';\nimport { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';\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?: Signal<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 {\n ui = inject(UiCoreService);\n\n @Input() navGroups?: NavGroups;\n currentNav = computed(() => {\n return this.updateNavItems(this.ui.currentSidenavIdentifier());\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) {\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 './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -7,6 +7,7 @@ declare class AuthService {
|
|
|
7
7
|
private apiUrl;
|
|
8
8
|
private loginUrl;
|
|
9
9
|
private sessionUrl;
|
|
10
|
+
private logoutAction;
|
|
10
11
|
http: HttpClient;
|
|
11
12
|
private authenticatedSignal;
|
|
12
13
|
private sessionInfoSignal;
|
|
@@ -19,7 +20,7 @@ declare class AuthService {
|
|
|
19
20
|
static requiresPermission(resource: Resource, permission: Permission): boolean;
|
|
20
21
|
private initializePermissionFn;
|
|
21
22
|
/**
|
|
22
|
-
* Logs a user out.
|
|
23
|
+
* Logs a user out and calls the configured logout action.
|
|
23
24
|
*
|
|
24
25
|
* @returns Observable with a boolean indicating whether they were logged out.
|
|
25
26
|
*/
|
|
@@ -913,21 +913,33 @@ interface SessionInfo {
|
|
|
913
913
|
|
|
914
914
|
/**
|
|
915
915
|
* The base URL for API requests (e.g., 'https://api.example.com/').
|
|
916
|
+
* @defaultValue '/'
|
|
916
917
|
*/
|
|
917
918
|
declare const BASE_URL: InjectionToken<string>;
|
|
918
919
|
/**
|
|
919
920
|
* The path to the frontend login page (e.g., '/login').
|
|
921
|
+
* @defaultValue '/login'
|
|
920
922
|
*/
|
|
921
923
|
declare const FRONTEND_LOGIN_PATH: InjectionToken<string>;
|
|
922
924
|
/**
|
|
923
925
|
* The path to the session endpoint (e.g., 'user/session').
|
|
926
|
+
* @defaultValue 'user/session'
|
|
924
927
|
*/
|
|
925
928
|
declare const SESSION_PATH: InjectionToken<string>;
|
|
926
929
|
/**
|
|
927
930
|
* The base URL for API requests (e.g., '/api').
|
|
931
|
+
* @defaultValue '/api'
|
|
928
932
|
*/
|
|
929
933
|
declare const API_URL: InjectionToken<string>;
|
|
934
|
+
/**
|
|
935
|
+
* A function to determine if a specific permission is required for a given resource.
|
|
936
|
+
* @defaultValue a function that always returns false
|
|
937
|
+
*/
|
|
930
938
|
declare const PERMISSION_REQUIRED: InjectionToken<(resource: Resource, permission: Permission) => boolean>;
|
|
939
|
+
/**
|
|
940
|
+
* The available permissions in the system.
|
|
941
|
+
* @defaultValue an empty array
|
|
942
|
+
*/
|
|
931
943
|
declare const AVAILABLE_PERMISSIONS: InjectionToken<{
|
|
932
944
|
Create: Permission;
|
|
933
945
|
Delete: Permission;
|
|
@@ -936,11 +948,43 @@ declare const AVAILABLE_PERMISSIONS: InjectionToken<{
|
|
|
936
948
|
Update: Permission;
|
|
937
949
|
}>;
|
|
938
950
|
declare const AVAILABLE_DOMAINS: InjectionToken<Record<string, Domain>[]>;
|
|
951
|
+
/**
|
|
952
|
+
* The generated resourceMeta from the output of the [ccc package](https://github.com/cccteam/ccc) typescript generator
|
|
953
|
+
* Required to work with generated routes and resource metadata
|
|
954
|
+
* @defaultValue a no-op function that returns an empty object
|
|
955
|
+
*/
|
|
939
956
|
declare const RESOURCE_META: InjectionToken<(resource: Resource) => ResourceMeta>;
|
|
957
|
+
/**
|
|
958
|
+
* The generated methodMeta from the output of the [ccc package](https://github.com/cccteam/ccc) typescript generator
|
|
959
|
+
* Required to work with generated method data
|
|
960
|
+
* @defaultValue a no-op function that returns an empty object
|
|
961
|
+
*/
|
|
940
962
|
declare const METHOD_META: InjectionToken<(method: string) => MethodMeta>;
|
|
963
|
+
/**
|
|
964
|
+
* The duration in seconds for the session to be considered idle.
|
|
965
|
+
* @defaultValue 300 seconds
|
|
966
|
+
*/
|
|
941
967
|
declare const IDLE_SESSION_DURATION: InjectionToken<number>;
|
|
968
|
+
/**
|
|
969
|
+
* The duration in seconds for the warning to be shown to the user before the session times out due to inactivity.
|
|
970
|
+
* @defaultValue 60 seconds
|
|
971
|
+
*/
|
|
942
972
|
declare const IDLE_WARNING_DURATION: InjectionToken<number>;
|
|
973
|
+
/**
|
|
974
|
+
* The duration in seconds for the keepalive ping to be sent to the server to keep the session alive.
|
|
975
|
+
* @defaultValue 30 seconds
|
|
976
|
+
*/
|
|
943
977
|
declare const IDLE_KEEPALIVE_DURATION: InjectionToken<number>;
|
|
978
|
+
/**
|
|
979
|
+
* A function to be called when the user logs out.
|
|
980
|
+
* @defaultValue a no-op function that returns 0
|
|
981
|
+
*/
|
|
982
|
+
declare const LOGOUT_ACTION: InjectionToken<() => void>;
|
|
983
|
+
/**
|
|
984
|
+
* A function to be called when the user is logged out due to inactivity.
|
|
985
|
+
* @defaultValue a no-op function that returns 0
|
|
986
|
+
*/
|
|
987
|
+
declare const IDLE_LOGOUT_ACTION: InjectionToken<() => void>;
|
|
944
988
|
|
|
945
|
-
export { API_URL, AVAILABLE_DOMAINS, AVAILABLE_PERMISSIONS, AlertLevel, BASE_URL, CustomConfigComponent, CustomTypes, FRONTEND_LOGIN_PATH, IDLE_KEEPALIVE_DURATION, IDLE_SESSION_DURATION, IDLE_WARNING_DURATION, METHOD_META, PERMISSION_REQUIRED, RESOURCE_META, ReadPermission, SESSION_PATH, UpdatePermission, actionButtonConfig, actionButtonConfigDefaults, additionalResourceConfig, additionalResourceConfigDefaults, arrayConfig, arrayConfigDefaults, componentConfig, componentConfigDefaults, computedDisplayField, computedDisplayFieldElementDefaults, createResourceValidator, defaultEmptyFieldValue, enumeratedConfig, enumeratedConfigDefaults, field, fieldElementDefaults, fieldSort, fieldSortDefaults, foreignKeyDefault, foreignKeyDefaultDefaults, listViewConfig, listViewConfigDefaults, multiColumnConfig, multiColumnConfigDefaults, nullBooleanConfig, nullBooleanConfigDefaults, padding, paddingElementDefaults, requiredIf, rootConfig, rootConfigDefaults, rpcConfig, rpcConfigDefaults, section, sectionElementDefaults, singleColumnConfig, singleColumnConfigDefaults, staticDefault, staticDefaultDefaults, switchParams, switchParamsDefaults, validatorsPresent, viewConfig, viewConfigDefaults };
|
|
989
|
+
export { API_URL, AVAILABLE_DOMAINS, AVAILABLE_PERMISSIONS, AlertLevel, BASE_URL, CustomConfigComponent, CustomTypes, FRONTEND_LOGIN_PATH, IDLE_KEEPALIVE_DURATION, IDLE_LOGOUT_ACTION, IDLE_SESSION_DURATION, IDLE_WARNING_DURATION, LOGOUT_ACTION, METHOD_META, PERMISSION_REQUIRED, RESOURCE_META, ReadPermission, SESSION_PATH, UpdatePermission, actionButtonConfig, actionButtonConfigDefaults, additionalResourceConfig, additionalResourceConfigDefaults, arrayConfig, arrayConfigDefaults, componentConfig, componentConfigDefaults, computedDisplayField, computedDisplayFieldElementDefaults, createResourceValidator, defaultEmptyFieldValue, enumeratedConfig, enumeratedConfigDefaults, field, fieldElementDefaults, fieldSort, fieldSortDefaults, foreignKeyDefault, foreignKeyDefaultDefaults, listViewConfig, listViewConfigDefaults, multiColumnConfig, multiColumnConfigDefaults, nullBooleanConfig, nullBooleanConfigDefaults, padding, paddingElementDefaults, requiredIf, rootConfig, rootConfigDefaults, rpcConfig, rpcConfigDefaults, section, sectionElementDefaults, singleColumnConfig, singleColumnConfigDefaults, staticDefault, staticDefaultDefaults, switchParams, switchParamsDefaults, validatorsPresent, viewConfig, viewConfigDefaults };
|
|
946
990
|
export type { ActionButtonConfig, ActionButtonConfigOptions, ActionType, AdditionalResourceConfig, AdditionalResourceConfigOptions, Affix, ArrayConfig, BaseConfig, BaseConfigOptions, ChildResourceConfig, ColSize, ColumnConfig, ComponentConfig, ComponentConfigOptions, ComputedDisplayFieldElement, ComputedDisplayFieldElementOptions, ConcatFn, ConfigElement, ConfigParam, ConfigType, CreateNotificationMessage, DataType, Domain, DomainPermissions, EnumeratedConfig, EnumeratedConfigOptions, FieldDefault, FieldElement, FieldElementOptions, FieldMeta, FieldName, FieldPointer, FieldSort, FieldSortOptions, ForeignKeyDefault, ForeignKeyDefaultOptions, FormatType, ListConcatFn, ListViewConfig, ListViewConfigOptions, MenuItem, Meta, Method, MethodMeta, MultiColumnConfig, MultiColumnConfigOptions, NotificationMessage, NullBoolean, NullBooleanConfig, NullBooleanConfigOptions, PaddingElement, PaddingElementOptions, ParentResourceConfig, Permission, PermissionScope, RPCBaseFormData, RPCConfig, RPCConfigOptions, RPCDataType, RPCFieldMeta, RPCPlacement, RPCRecordData, RecordData, Resource, ResourceMap, ResourceMeta, ResourceValidatorFn, RootConfig, RootConfigOptions, RootRouteData, RouteResourceData, RpcMethod, SectionElement, SectionElementOptions, SessionInfo, SingleColumnConfig, SingleColumnConfigOptions, StaticDefault, SwitchConfigParam, SwitchConfigParamOptions, ValidDisplayTypes, ValidRPCTypes, ViewConfig, ViewConfigOptions, ViewType, arrayConfigOptions, staticDefaultOptions, switchCase };
|
|
@@ -8,6 +8,7 @@ declare class IdleService implements OnDestroy {
|
|
|
8
8
|
private notifications;
|
|
9
9
|
private readonly loginPath;
|
|
10
10
|
private readonly sessionDuration;
|
|
11
|
+
private readonly logoutAction;
|
|
11
12
|
private readonly warningDuration;
|
|
12
13
|
private readonly keepAliveDuration;
|
|
13
14
|
private readonly idleCheckFrequency;
|
|
@@ -32,7 +33,7 @@ declare class IdleService implements OnDestroy {
|
|
|
32
33
|
*/
|
|
33
34
|
stop(): void;
|
|
34
35
|
/**
|
|
35
|
-
* Logs out the user due to inactivity and stops the service.
|
|
36
|
+
* Logs out the user due to inactivity, calls the configured logout action, and stops the service.
|
|
36
37
|
*/
|
|
37
38
|
logoutAndStop(): void;
|
|
38
39
|
private startMainTicker;
|