@flusys/ng-iam 0.1.0-beta.3 → 1.1.0-beta
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/README.md +51 -2
- package/fesm2022/{flusys-ng-iam-action-form-page.component-BVWZMlLU.mjs → flusys-ng-iam-action-form-page.component-DBJzC5GS.mjs} +11 -12
- package/fesm2022/flusys-ng-iam-action-form-page.component-DBJzC5GS.mjs.map +1 -0
- package/fesm2022/{flusys-ng-iam-action-list-page.component-CCp7M7xo.mjs → flusys-ng-iam-action-list-page.component-Dfts0JCt.mjs} +10 -11
- package/fesm2022/flusys-ng-iam-action-list-page.component-Dfts0JCt.mjs.map +1 -0
- package/fesm2022/{flusys-ng-iam-flusys-ng-iam-D_i24Gub.mjs → flusys-ng-iam-flusys-ng-iam-BjdM-Vgz.mjs} +185 -298
- package/fesm2022/flusys-ng-iam-flusys-ng-iam-BjdM-Vgz.mjs.map +1 -0
- package/fesm2022/{flusys-ng-iam-iam-container.component-BFKoNtdz.mjs → flusys-ng-iam-iam-container.component-Chl5MDkV.mjs} +4 -4
- package/fesm2022/{flusys-ng-iam-iam-container.component-BFKoNtdz.mjs.map → flusys-ng-iam-iam-container.component-Chl5MDkV.mjs.map} +1 -1
- package/fesm2022/{flusys-ng-iam-permission-page.component-C0yLMdW5.mjs → flusys-ng-iam-permission-page.component-cDrwUAQ_.mjs} +7 -7
- package/fesm2022/{flusys-ng-iam-permission-page.component-C0yLMdW5.mjs.map → flusys-ng-iam-permission-page.component-cDrwUAQ_.mjs.map} +1 -1
- package/fesm2022/{flusys-ng-iam-role-form-page.component-Co6bbHik.mjs → flusys-ng-iam-role-form-page.component-Ctigzpon.mjs} +8 -8
- package/fesm2022/{flusys-ng-iam-role-form-page.component-Co6bbHik.mjs.map → flusys-ng-iam-role-form-page.component-Ctigzpon.mjs.map} +1 -1
- package/fesm2022/{flusys-ng-iam-role-list-page.component-KJUVOrf0.mjs → flusys-ng-iam-role-list-page.component-BF-Z_TQK.mjs} +10 -11
- package/fesm2022/flusys-ng-iam-role-list-page.component-BF-Z_TQK.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam.mjs +1 -1
- package/package.json +4 -4
- package/types/flusys-ng-iam.d.ts +50 -17
- package/fesm2022/flusys-ng-iam-action-form-page.component-BVWZMlLU.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-action-list-page.component-CCp7M7xo.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-flusys-ng-iam-D_i24Gub.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-role-list-page.component-KJUVOrf0.mjs.map +0 -1
|
@@ -39,8 +39,8 @@ class IamContainerComponent {
|
|
|
39
39
|
const permissionMode = getPermissionMode(this.appConfig);
|
|
40
40
|
return this.allTabs.filter((tab) => !tab.requiresRBAC || permissionMode === 'rbac' || permissionMode === 'full');
|
|
41
41
|
}, ...(ngDevMode ? [{ debugName: "visibleTabs" }] : []));
|
|
42
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
43
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
42
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: IamContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
43
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: IamContainerComponent, isStandalone: true, selector: "lib-iam-container", ngImport: i0, template: `
|
|
44
44
|
<div class="iam-page p-4">
|
|
45
45
|
<div class="iam-header mb-4">
|
|
46
46
|
<h1 class="text-2xl font-bold m-0">Identity & Access Management</h1>
|
|
@@ -65,7 +65,7 @@ class IamContainerComponent {
|
|
|
65
65
|
</div>
|
|
66
66
|
`, isInline: true, styles: [".tab-link{color:var(--text-color-secondary, #6b7280);text-decoration:none;border-bottom:2px solid transparent;margin-bottom:-1px}.tab-link.active{color:var(--primary-color, #3b82f6);border-bottom-color:var(--primary-color, #3b82f6);background-color:var(--surface-ground, #f9fafb)}.tab-link:hover:not(.active){background-color:var(--surface-hover, #f3f4f6)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
|
|
67
67
|
}
|
|
68
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
68
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: IamContainerComponent, decorators: [{
|
|
69
69
|
type: Component,
|
|
70
70
|
args: [{ selector: 'lib-iam-container', standalone: true, imports: [CommonModule, RouterOutlet, RouterLink, RouterLinkActive], template: `
|
|
71
71
|
<div class="iam-page p-4">
|
|
@@ -94,4 +94,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
94
94
|
}] });
|
|
95
95
|
|
|
96
96
|
export { IamContainerComponent };
|
|
97
|
-
//# sourceMappingURL=flusys-ng-iam-iam-container.component-
|
|
97
|
+
//# sourceMappingURL=flusys-ng-iam-iam-container.component-Chl5MDkV.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flusys-ng-iam-iam-container.component-
|
|
1
|
+
{"version":3,"file":"flusys-ng-iam-iam-container.component-Chl5MDkV.mjs","sources":["../../../projects/ng-iam/pages/iam-container/iam-container.component.ts"],"sourcesContent":["import { Component, computed, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';\nimport { APP_CONFIG, getPermissionMode } from '@flusys/ng-core';\n\ninterface ITab {\n id: string;\n label: string;\n icon: string;\n route: string;\n requiresRBAC?: boolean;\n}\n\n/**\n * IAM Container Component\n *\n * Main container for IAM module with tab navigation\n * Routes: Actions | Roles (conditional) | Users (permission assignment)\n */\n@Component({\n selector: 'lib-iam-container',\n standalone: true,\n imports: [CommonModule, RouterOutlet, RouterLink, RouterLinkActive],\n template: `\n <div class=\"iam-page p-4\">\n <div class=\"iam-header mb-4\">\n <h1 class=\"text-2xl font-bold m-0\">Identity & Access Management</h1>\n <p class=\"text-gray-500 mt-1\">Manage actions, roles, and user permissions</p>\n </div>\n\n <div class=\"iam-tabs flex gap-1 mb-4 border-b border-gray-200\">\n @for (tab of visibleTabs(); track tab.id) {\n <a\n [routerLink]=\"tab.route\"\n routerLinkActive=\"active\"\n class=\"tab-link flex items-center gap-2 px-4 py-2 rounded-t-lg cursor-pointer transition-colors\">\n <i [class]=\"tab.icon\"></i>\n <span>{{ tab.label }}</span>\n </a>\n }\n </div>\n\n <div class=\"iam-content\">\n <router-outlet />\n </div>\n </div>\n `,\n styles: [\n `\n .tab-link {\n color: var(--text-color-secondary, #6b7280);\n text-decoration: none;\n border-bottom: 2px solid transparent;\n margin-bottom: -1px;\n }\n .tab-link.active {\n color: var(--primary-color, #3b82f6);\n border-bottom-color: var(--primary-color, #3b82f6);\n background-color: var(--surface-ground, #f9fafb);\n }\n .tab-link:hover:not(.active) {\n background-color: var(--surface-hover, #f3f4f6);\n }\n `,\n ],\n})\nexport class IamContainerComponent {\n private readonly appConfig = inject(APP_CONFIG);\n\n /** All available tabs */\n private readonly allTabs: ITab[] = [\n {\n id: 'actions',\n label: 'Actions',\n icon: 'pi pi-bolt',\n route: 'actions',\n },\n {\n id: 'roles',\n label: 'Roles',\n icon: 'pi pi-shield',\n route: 'roles',\n requiresRBAC: true,\n },\n {\n id: 'permissions',\n label: 'Permissions',\n icon: 'pi pi-key',\n route: 'permissions',\n },\n ];\n\n /** Visible tabs based on permission mode */\n readonly visibleTabs = computed(() => {\n const permissionMode = getPermissionMode(this.appConfig);\n return this.allTabs.filter(\n (tab) => !tab.requiresRBAC || permissionMode === 'rbac' || permissionMode === 'full'\n );\n });\n}\n"],"names":[],"mappings":";;;;;;AAaA;;;;;AAKG;MAgDU,qBAAqB,CAAA;AACf,IAAA,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;;AAG9B,IAAA,OAAO,GAAW;AACjC,QAAA;AACE,YAAA,EAAE,EAAE,SAAS;AACb,YAAA,KAAK,EAAE,SAAS;AAChB,YAAA,IAAI,EAAE,YAAY;AAClB,YAAA,KAAK,EAAE,SAAS;AACjB,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,OAAO;AACX,YAAA,KAAK,EAAE,OAAO;AACd,YAAA,IAAI,EAAE,cAAc;AACpB,YAAA,KAAK,EAAE,OAAO;AACd,YAAA,YAAY,EAAE,IAAI;AACnB,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,aAAa;AACjB,YAAA,KAAK,EAAE,aAAa;AACpB,YAAA,IAAI,EAAE,WAAW;AACjB,YAAA,KAAK,EAAE,aAAa;AACrB,SAAA;KACF;;AAGQ,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAK;QACnC,MAAM,cAAc,GAAG,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC;QACxD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CACxB,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,YAAY,IAAI,cAAc,KAAK,MAAM,IAAI,cAAc,KAAK,MAAM,CACrF;AACH,IAAA,CAAC,uDAAC;uGAhCS,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAArB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA3CtB;;;;;;;;;;;;;;;;;;;;;;;AAuBT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,wWAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAxBS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,YAAY,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,QAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,UAAU,oOAAE,gBAAgB,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,CAAA,yBAAA,EAAA,uBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,gBAAA,CAAA,EAAA,QAAA,EAAA,CAAA,kBAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;2FA4CvD,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBA/CjC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,mBAAmB,EAAA,UAAA,EACjB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,gBAAgB,CAAC,EAAA,QAAA,EACzD;;;;;;;;;;;;;;;;;;;;;;;AAuBT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,wWAAA,CAAA,EAAA;;;;;"}
|
|
@@ -2,10 +2,10 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { inject, signal, computed, Component } from '@angular/core';
|
|
3
3
|
import { AngularModule, PrimeModule } from '@flusys/ng-shared';
|
|
4
4
|
import { APP_CONFIG, getPermissionMode, isCompanyFeatureEnabled } from '@flusys/ng-core';
|
|
5
|
-
import * as
|
|
5
|
+
import * as i2 from 'primeng/button';
|
|
6
6
|
import { ButtonModule } from 'primeng/button';
|
|
7
7
|
import { TabsModule } from 'primeng/tabs';
|
|
8
|
-
import { b as RoleActionSelectorComponent, C as CompanyActionSelectorComponent, U as UserRoleSelectorComponent, d as UserActionSelectorComponent } from './flusys-ng-iam-flusys-ng-iam-
|
|
8
|
+
import { b as RoleActionSelectorComponent, C as CompanyActionSelectorComponent, U as UserRoleSelectorComponent, d as UserActionSelectorComponent } from './flusys-ng-iam-flusys-ng-iam-BjdM-Vgz.mjs';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Permission Page Component
|
|
@@ -58,8 +58,8 @@ class PermissionPageComponent {
|
|
|
58
58
|
setActiveTab(tabId) {
|
|
59
59
|
this.activeTab.set(tabId);
|
|
60
60
|
}
|
|
61
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
62
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
61
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PermissionPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
62
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: PermissionPageComponent, isStandalone: true, selector: "lib-permission-page", ngImport: i0, template: `
|
|
63
63
|
<div class="card">
|
|
64
64
|
<h3 class="text-xl font-semibold mb-4">Permission Management</h3>
|
|
65
65
|
|
|
@@ -91,9 +91,9 @@ class PermissionPageComponent {
|
|
|
91
91
|
}
|
|
92
92
|
</div>
|
|
93
93
|
</div>
|
|
94
|
-
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type:
|
|
94
|
+
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: RoleActionSelectorComponent, selector: "flusys-role-action-selector" }, { kind: "component", type: CompanyActionSelectorComponent, selector: "flusys-company-action-selector" }, { kind: "component", type: UserRoleSelectorComponent, selector: "flusys-user-role-selector" }, { kind: "component", type: UserActionSelectorComponent, selector: "flusys-user-action-selector" }] });
|
|
95
95
|
}
|
|
96
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
96
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PermissionPageComponent, decorators: [{
|
|
97
97
|
type: Component,
|
|
98
98
|
args: [{ selector: 'lib-permission-page', standalone: true, imports: [
|
|
99
99
|
AngularModule,
|
|
@@ -140,4 +140,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
140
140
|
}] });
|
|
141
141
|
|
|
142
142
|
export { PermissionPageComponent };
|
|
143
|
-
//# sourceMappingURL=flusys-ng-iam-permission-page.component-
|
|
143
|
+
//# sourceMappingURL=flusys-ng-iam-permission-page.component-cDrwUAQ_.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flusys-ng-iam-permission-page.component-
|
|
1
|
+
{"version":3,"file":"flusys-ng-iam-permission-page.component-cDrwUAQ_.mjs","sources":["../../../projects/ng-iam/pages/permission/permission-page.component.ts"],"sourcesContent":["import { Component, computed, inject, signal } from '@angular/core';\nimport { AngularModule, PrimeModule } from '@flusys/ng-shared';\nimport { APP_CONFIG, getPermissionMode, isCompanyFeatureEnabled } from '@flusys/ng-core';\nimport { ButtonModule } from 'primeng/button';\nimport { TabsModule } from 'primeng/tabs';\nimport { RoleActionSelectorComponent } from '../../components/role-action-selector.component';\nimport { CompanyActionSelectorComponent } from '../../components/company-action-selector.component';\nimport { UserRoleSelectorComponent } from '../../components/user-role-selector.component';\nimport { UserActionSelectorComponent } from '../../components/user-action-selector.component';\n\n/**\n * Permission Page Component\n *\n * Main permission management interface with tabs for:\n * - Role-Action Assignment (RBAC/FULL mode) - WITH LOGIC BUILDER\n * - User-Role Assignment (RBAC/FULL mode)\n * - User-Action Assignment (DIRECT/FULL mode)\n * - Company-Action Whitelist (if company feature enabled)\n */\n@Component({\n selector: 'lib-permission-page',\n standalone: true,\n imports: [\n AngularModule,\n PrimeModule,\n ButtonModule,\n TabsModule,\n RoleActionSelectorComponent,\n CompanyActionSelectorComponent,\n UserRoleSelectorComponent,\n UserActionSelectorComponent\n ],\n template: `\n <div class=\"card\">\n <h3 class=\"text-xl font-semibold mb-4\">Permission Management</h3>\n\n <div class=\"flex gap-2 mb-4\">\n @for (tab of availableTabs(); track tab.id) {\n <p-button\n [label]=\"tab.label\"\n [icon]=\"tab.icon\"\n [outlined]=\"activeTab() !== tab.id\"\n size=\"small\"\n (onClick)=\"setActiveTab(tab.id)\" />\n }\n </div>\n\n <div class=\"mt-4\">\n @switch (activeTab()) {\n @case ('role-actions') {\n <flusys-role-action-selector />\n }\n @case ('user-roles') {\n <flusys-user-role-selector />\n }\n @case ('user-actions') {\n <flusys-user-action-selector />\n }\n @case ('company-actions') {\n <flusys-company-action-selector />\n }\n }\n </div>\n </div>\n `,\n styles: [`\n :host {\n display: block;\n }\n `]\n})\nexport class PermissionPageComponent {\n private readonly appConfig = inject(APP_CONFIG);\n\n readonly activeTab = signal<string>('role-actions');\n\n /**\n * Available tabs based on configuration\n */\n readonly availableTabs = computed(() => {\n const permissionMode = getPermissionMode(this.appConfig);\n const tabs: Array<{ id: string; label: string; icon: string }> = [];\n\n // Role-Action assignment (RBAC or FULL mode)\n if (permissionMode === 'rbac' || permissionMode === 'full') {\n tabs.push(\n {\n id: 'role-actions',\n label: 'Role-Actions',\n icon: 'pi pi-shield',\n },\n {\n id: 'user-roles',\n label: 'User-Roles',\n icon: 'pi pi-user',\n }\n );\n }\n\n // User-Action direct assignment (DIRECT or FULL mode)\n if (permissionMode === 'direct' || permissionMode === 'full') {\n tabs.push({\n id: 'user-actions',\n label: 'User-Actions',\n icon: 'pi pi-key',\n });\n }\n\n // Company-Action whitelist (if company feature enabled)\n if (isCompanyFeatureEnabled(this.appConfig)) {\n tabs.push({\n id: 'company-actions',\n label: 'Company-Actions',\n icon: 'pi pi-building',\n });\n }\n\n return tabs;\n });\n\n setActiveTab(tabId: string): void {\n this.activeTab.set(tabId);\n }\n}\n"],"names":["i1"],"mappings":"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"}
|
|
@@ -7,10 +7,10 @@ import { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';
|
|
|
7
7
|
import { AngularModule, PrimeModule } from '@flusys/ng-shared';
|
|
8
8
|
import { MessageService } from 'primeng/api';
|
|
9
9
|
import { firstValueFrom } from 'rxjs';
|
|
10
|
-
import { R as RoleApiService } from './flusys-ng-iam-flusys-ng-iam-
|
|
10
|
+
import { R as RoleApiService } from './flusys-ng-iam-flusys-ng-iam-BjdM-Vgz.mjs';
|
|
11
11
|
import * as i1 from '@angular/forms';
|
|
12
|
-
import * as i2 from 'primeng/
|
|
13
|
-
import * as i3 from 'primeng/
|
|
12
|
+
import * as i2 from 'primeng/button';
|
|
13
|
+
import * as i3 from 'primeng/inputtext';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Role Form Page Component
|
|
@@ -146,8 +146,8 @@ class RoleFormPageComponent {
|
|
|
146
146
|
onBack() {
|
|
147
147
|
this.router.navigate(['/iam/roles']);
|
|
148
148
|
}
|
|
149
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
150
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.
|
|
149
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoleFormPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
150
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: RoleFormPageComponent, isStandalone: true, selector: "lib-role-form-page", ngImport: i0, template: `
|
|
151
151
|
<div class="card">
|
|
152
152
|
<div class="flex justify-between items-center mb-4">
|
|
153
153
|
<h3 class="text-xl font-semibold">
|
|
@@ -222,9 +222,9 @@ class RoleFormPageComponent {
|
|
|
222
222
|
</div>
|
|
223
223
|
</form>
|
|
224
224
|
</div>
|
|
225
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "
|
|
225
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
226
226
|
}
|
|
227
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
227
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoleFormPageComponent, decorators: [{
|
|
228
228
|
type: Component,
|
|
229
229
|
args: [{
|
|
230
230
|
selector: 'lib-role-form-page',
|
|
@@ -311,4 +311,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
311
311
|
}] });
|
|
312
312
|
|
|
313
313
|
export { RoleFormPageComponent };
|
|
314
|
-
//# sourceMappingURL=flusys-ng-iam-role-form-page.component-
|
|
314
|
+
//# sourceMappingURL=flusys-ng-iam-role-form-page.component-Ctigzpon.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flusys-ng-iam-role-form-page.component-Co6bbHik.mjs","sources":["../../../projects/ng-iam/pages/role/role-form-page.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, inject, OnInit, signal } from '@angular/core';\nimport { form, FormField, required } from '@angular/forms/signals';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { APP_CONFIG, isCompanyFeatureEnabled } from '@flusys/ng-core';\nimport { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';\nimport { AngularModule, PrimeModule } from '@flusys/ng-shared';\nimport { MessageService } from 'primeng/api';\nimport { firstValueFrom } from 'rxjs';\nimport { IRole } from '../../interfaces/role.interface';\nimport { RoleApiService } from '../../services/role-api.service';\n\n/** Role form model interface */\ninterface IRoleFormModel {\n id: string;\n name: string;\n description: string;\n serial: string;\n isActive: boolean;\n}\n\n/**\n * Role Form Page Component\n * Create/Edit role with signal-based form pattern (matches ng-auth)\n */\n@Component({\n selector: 'lib-role-form-page',\n standalone: true,\n imports: [AngularModule, PrimeModule, FormField],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"card\">\n <div class=\"flex justify-between items-center mb-4\">\n <h3 class=\"text-xl font-semibold\">\n {{ isEditMode() ? 'Edit Role' : 'New Role' }}\n </h3>\n <p-button\n label=\"Back\"\n icon=\"pi pi-arrow-left\"\n [outlined]=\"true\"\n (onClick)=\"onBack()\" />\n </div>\n\n <form (ngSubmit)=\"onSubmit()\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Name -->\n <div class=\"md:col-span-2\">\n <label for=\"name\" class=\"block font-medium mb-2\">Name *</label>\n <input\n pInputText\n id=\"name\"\n [formField]=\"roleForm.name\"\n class=\"w-full\"\n placeholder=\"Enter role name\" />\n </div>\n\n <!-- Description -->\n <div class=\"md:col-span-2\">\n <label for=\"description\" class=\"block font-medium mb-2\">Description</label>\n <input\n pInputText\n id=\"description\"\n [formField]=\"roleForm.description\"\n class=\"w-full\"\n placeholder=\"Enter description\" />\n </div>\n\n <!-- Order -->\n <div>\n <label for=\"serial\" class=\"block font-medium mb-2\">Display Order</label>\n <input\n pInputText\n id=\"serial\"\n type=\"number\"\n [formField]=\"roleForm.serial\"\n class=\"w-full\"\n placeholder=\"Enter display order\" />\n </div>\n\n <!-- Is Active -->\n <div class=\"flex items-center pt-6\">\n <label class=\"p-checkbox-native\">\n <input\n type=\"checkbox\"\n [formField]=\"roleForm.isActive\" />\n <span>Active</span>\n </label>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"flex justify-end gap-2 mt-6\">\n <p-button\n label=\"Cancel\"\n severity=\"secondary\"\n [outlined]=\"true\"\n (onClick)=\"onBack()\" />\n <p-button\n [label]=\"isEditMode() ? 'Update' : 'Create'\"\n type=\"submit\"\n [loading]=\"isLoading()\"\n [disabled]=\"!isFormValid() || isLoading()\" />\n </div>\n </form>\n </div>\n `,\n})\nexport class RoleFormPageComponent implements OnInit {\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n private readonly appConfig = inject(APP_CONFIG);\n private readonly companyContext = inject(LAYOUT_AUTH_STATE);\n private readonly roleApi = inject(RoleApiService);\n private readonly messageService = inject(MessageService);\n\n /** Loading state */\n readonly isLoading = signal(false);\n\n /** Existing role data when editing */\n readonly existingRole = signal<IRole | null>(null);\n\n /** Whether in edit mode */\n readonly isEditMode = computed(() => !!this.existingRole());\n\n // ============================================\n // Form (Signal Forms)\n // ============================================\n\n /** Form model */\n readonly formModel = signal<IRoleFormModel>({\n id: '',\n name: '',\n description: '',\n serial: '',\n isActive: true,\n });\n\n /** Form with validation schema */\n readonly roleForm = form(this.formModel, (f) => {\n required(f.name, { message: 'Name is required' });\n });\n\n /** Check if form is valid */\n readonly isFormValid = computed(() => {\n const model = this.formModel();\n return model.name.trim().length > 0;\n });\n\n ngOnInit(): void {\n const id = this.route.snapshot.paramMap.get('id');\n if (id && id !== 'new') {\n this.loadRole(id);\n }\n }\n\n async loadRole(id: string): Promise<void> {\n this.isLoading.set(true);\n try {\n const response = await firstValueFrom(this.roleApi.findById(id));\n const role = response?.data;\n\n if (role) {\n this.existingRole.set(role);\n this.formModel.set({\n id: role.id,\n name: role.name,\n description: role.description ?? '',\n serial: role.serial?.toString() ?? '',\n isActive: role.isActive,\n });\n } else {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Role not found.',\n });\n this.router.navigate(['/iam/roles']);\n }\n } catch (error) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Failed to load role.',\n });\n this.router.navigate(['/iam/roles']);\n } finally {\n this.isLoading.set(false);\n }\n }\n\n async onSubmit(): Promise<void> {\n if (!this.isFormValid()) {\n this.messageService.add({\n severity: 'error',\n summary: 'Validation Error',\n detail: 'Please fill in all required fields.',\n });\n return;\n }\n\n this.isLoading.set(true);\n\n try {\n const formValue = this.formModel();\n\n // Get company context if feature enabled\n const companyId = isCompanyFeatureEnabled(this.appConfig)\n ? this.companyContext.currentCompanyInfo()?.id || undefined\n : undefined;\n\n // Convert empty strings to undefined for DTO compatibility\n const dto = {\n ...formValue,\n description: formValue.description || undefined,\n serial: formValue.serial ? parseInt(formValue.serial, 10) : undefined,\n companyId: this.isEditMode() ? undefined : companyId,\n };\n\n if (this.isEditMode()) {\n await this.roleApi.updateAsync(dto);\n this.messageService.add({\n severity: 'success',\n summary: 'Success',\n detail: 'Role updated successfully.',\n });\n } else {\n await this.roleApi.insertAsync(dto);\n this.messageService.add({\n severity: 'success',\n summary: 'Success',\n detail: 'Role created successfully.',\n });\n }\n\n this.router.navigate(['/iam/roles']);\n } catch (error: any) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: error.message || 'Failed to save role.',\n });\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onBack(): void {\n this.router.navigate(['/iam/roles']);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"flusys-ng-iam-role-form-page.component-Ctigzpon.mjs","sources":["../../../projects/ng-iam/pages/role/role-form-page.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, inject, OnInit, signal } from '@angular/core';\nimport { form, FormField, required } from '@angular/forms/signals';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { APP_CONFIG, isCompanyFeatureEnabled } from '@flusys/ng-core';\nimport { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';\nimport { AngularModule, PrimeModule } from '@flusys/ng-shared';\nimport { MessageService } from 'primeng/api';\nimport { firstValueFrom } from 'rxjs';\nimport { IRole } from '../../interfaces/role.interface';\nimport { RoleApiService } from '../../services/role-api.service';\n\n/** Role form model interface */\ninterface IRoleFormModel {\n id: string;\n name: string;\n description: string;\n serial: string;\n isActive: boolean;\n}\n\n/**\n * Role Form Page Component\n * Create/Edit role with signal-based form pattern (matches ng-auth)\n */\n@Component({\n selector: 'lib-role-form-page',\n standalone: true,\n imports: [AngularModule, PrimeModule, FormField],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"card\">\n <div class=\"flex justify-between items-center mb-4\">\n <h3 class=\"text-xl font-semibold\">\n {{ isEditMode() ? 'Edit Role' : 'New Role' }}\n </h3>\n <p-button\n label=\"Back\"\n icon=\"pi pi-arrow-left\"\n [outlined]=\"true\"\n (onClick)=\"onBack()\" />\n </div>\n\n <form (ngSubmit)=\"onSubmit()\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Name -->\n <div class=\"md:col-span-2\">\n <label for=\"name\" class=\"block font-medium mb-2\">Name *</label>\n <input\n pInputText\n id=\"name\"\n [formField]=\"roleForm.name\"\n class=\"w-full\"\n placeholder=\"Enter role name\" />\n </div>\n\n <!-- Description -->\n <div class=\"md:col-span-2\">\n <label for=\"description\" class=\"block font-medium mb-2\">Description</label>\n <input\n pInputText\n id=\"description\"\n [formField]=\"roleForm.description\"\n class=\"w-full\"\n placeholder=\"Enter description\" />\n </div>\n\n <!-- Order -->\n <div>\n <label for=\"serial\" class=\"block font-medium mb-2\">Display Order</label>\n <input\n pInputText\n id=\"serial\"\n type=\"number\"\n [formField]=\"roleForm.serial\"\n class=\"w-full\"\n placeholder=\"Enter display order\" />\n </div>\n\n <!-- Is Active -->\n <div class=\"flex items-center pt-6\">\n <label class=\"p-checkbox-native\">\n <input\n type=\"checkbox\"\n [formField]=\"roleForm.isActive\" />\n <span>Active</span>\n </label>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"flex justify-end gap-2 mt-6\">\n <p-button\n label=\"Cancel\"\n severity=\"secondary\"\n [outlined]=\"true\"\n (onClick)=\"onBack()\" />\n <p-button\n [label]=\"isEditMode() ? 'Update' : 'Create'\"\n type=\"submit\"\n [loading]=\"isLoading()\"\n [disabled]=\"!isFormValid() || isLoading()\" />\n </div>\n </form>\n </div>\n `,\n})\nexport class RoleFormPageComponent implements OnInit {\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n private readonly appConfig = inject(APP_CONFIG);\n private readonly companyContext = inject(LAYOUT_AUTH_STATE);\n private readonly roleApi = inject(RoleApiService);\n private readonly messageService = inject(MessageService);\n\n /** Loading state */\n readonly isLoading = signal(false);\n\n /** Existing role data when editing */\n readonly existingRole = signal<IRole | null>(null);\n\n /** Whether in edit mode */\n readonly isEditMode = computed(() => !!this.existingRole());\n\n // ============================================\n // Form (Signal Forms)\n // ============================================\n\n /** Form model */\n readonly formModel = signal<IRoleFormModel>({\n id: '',\n name: '',\n description: '',\n serial: '',\n isActive: true,\n });\n\n /** Form with validation schema */\n readonly roleForm = form(this.formModel, (f) => {\n required(f.name, { message: 'Name is required' });\n });\n\n /** Check if form is valid */\n readonly isFormValid = computed(() => {\n const model = this.formModel();\n return model.name.trim().length > 0;\n });\n\n ngOnInit(): void {\n const id = this.route.snapshot.paramMap.get('id');\n if (id && id !== 'new') {\n this.loadRole(id);\n }\n }\n\n async loadRole(id: string): Promise<void> {\n this.isLoading.set(true);\n try {\n const response = await firstValueFrom(this.roleApi.findById(id));\n const role = response?.data;\n\n if (role) {\n this.existingRole.set(role);\n this.formModel.set({\n id: role.id,\n name: role.name,\n description: role.description ?? '',\n serial: role.serial?.toString() ?? '',\n isActive: role.isActive,\n });\n } else {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Role not found.',\n });\n this.router.navigate(['/iam/roles']);\n }\n } catch (error) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Failed to load role.',\n });\n this.router.navigate(['/iam/roles']);\n } finally {\n this.isLoading.set(false);\n }\n }\n\n async onSubmit(): Promise<void> {\n if (!this.isFormValid()) {\n this.messageService.add({\n severity: 'error',\n summary: 'Validation Error',\n detail: 'Please fill in all required fields.',\n });\n return;\n }\n\n this.isLoading.set(true);\n\n try {\n const formValue = this.formModel();\n\n // Get company context if feature enabled\n const companyId = isCompanyFeatureEnabled(this.appConfig)\n ? this.companyContext.currentCompanyInfo()?.id || undefined\n : undefined;\n\n // Convert empty strings to undefined for DTO compatibility\n const dto = {\n ...formValue,\n description: formValue.description || undefined,\n serial: formValue.serial ? parseInt(formValue.serial, 10) : undefined,\n companyId: this.isEditMode() ? undefined : companyId,\n };\n\n if (this.isEditMode()) {\n await this.roleApi.updateAsync(dto);\n this.messageService.add({\n severity: 'success',\n summary: 'Success',\n detail: 'Role updated successfully.',\n });\n } else {\n await this.roleApi.insertAsync(dto);\n this.messageService.add({\n severity: 'success',\n summary: 'Success',\n detail: 'Role created successfully.',\n });\n }\n\n this.router.navigate(['/iam/roles']);\n } catch (error: any) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: error.message || 'Failed to save role.',\n });\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onBack(): void {\n this.router.navigate(['/iam/roles']);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -4,13 +4,13 @@ import { Router } from '@angular/router';
|
|
|
4
4
|
import { APP_CONFIG, isCompanyFeatureEnabled } from '@flusys/ng-core';
|
|
5
5
|
import { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';
|
|
6
6
|
import { AngularModule, PrimeModule } from '@flusys/ng-shared';
|
|
7
|
-
import * as
|
|
7
|
+
import * as i2 from 'primeng/api';
|
|
8
8
|
import { MessageService, ConfirmationService } from 'primeng/api';
|
|
9
|
-
import * as
|
|
9
|
+
import * as i6 from 'primeng/tag';
|
|
10
10
|
import { TagModule } from 'primeng/tag';
|
|
11
11
|
import { firstValueFrom } from 'rxjs';
|
|
12
|
-
import { R as RoleApiService } from './flusys-ng-iam-flusys-ng-iam-
|
|
13
|
-
import * as
|
|
12
|
+
import { R as RoleApiService } from './flusys-ng-iam-flusys-ng-iam-BjdM-Vgz.mjs';
|
|
13
|
+
import * as i2$1 from 'primeng/button';
|
|
14
14
|
import * as i5 from 'primeng/table';
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -60,8 +60,7 @@ class RoleListPageComponent {
|
|
|
60
60
|
this.roles.set(response?.data ?? []);
|
|
61
61
|
this.total.set(response?.meta?.total ?? 0);
|
|
62
62
|
}
|
|
63
|
-
catch
|
|
64
|
-
console.error('[RoleListPage] Failed to load roles:', error);
|
|
63
|
+
catch {
|
|
65
64
|
this.messageService.add({
|
|
66
65
|
severity: 'error',
|
|
67
66
|
summary: 'Error',
|
|
@@ -109,8 +108,8 @@ class RoleListPageComponent {
|
|
|
109
108
|
this.pageSize.set(event.rows ?? 10);
|
|
110
109
|
this.loadRoles();
|
|
111
110
|
}
|
|
112
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
113
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.
|
|
111
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoleListPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
112
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: RoleListPageComponent, isStandalone: true, selector: "lib-role-list-page", ngImport: i0, template: `
|
|
114
113
|
<div class="card">
|
|
115
114
|
<div class="flex justify-between items-center mb-4">
|
|
116
115
|
<h3 class="text-xl font-semibold">Roles</h3>
|
|
@@ -180,9 +179,9 @@ class RoleListPageComponent {
|
|
|
180
179
|
</ng-template>
|
|
181
180
|
</p-table>
|
|
182
181
|
</div>
|
|
183
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "
|
|
182
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i2$1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i5.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "component", type: i6.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TagModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
184
183
|
}
|
|
185
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
184
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoleListPageComponent, decorators: [{
|
|
186
185
|
type: Component,
|
|
187
186
|
args: [{
|
|
188
187
|
selector: 'lib-role-list-page',
|
|
@@ -264,4 +263,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
264
263
|
}], ctorParameters: () => [] });
|
|
265
264
|
|
|
266
265
|
export { RoleListPageComponent };
|
|
267
|
-
//# sourceMappingURL=flusys-ng-iam-role-list-page.component-
|
|
266
|
+
//# sourceMappingURL=flusys-ng-iam-role-list-page.component-BF-Z_TQK.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flusys-ng-iam-role-list-page.component-BF-Z_TQK.mjs","sources":["../../../projects/ng-iam/pages/role/role-list-page.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, effect, inject, signal, untracked } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { APP_CONFIG, isCompanyFeatureEnabled } from '@flusys/ng-core';\nimport { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';\nimport { AngularModule, PrimeModule } from '@flusys/ng-shared';\nimport { ConfirmationService, MessageService } from 'primeng/api';\nimport { TagModule } from 'primeng/tag';\nimport { firstValueFrom } from 'rxjs';\nimport { IRole } from '../../interfaces/role.interface';\nimport { RoleApiService } from '../../services/role-api.service';\n\n/**\n * Role List Page Component\n *\n * Displays paginated list of roles with search, filter, and CRUD operations.\n * Uses RoleApiService directly with LAYOUT_AUTH_STATE for company context.\n */\n@Component({\n selector: 'lib-role-list-page',\n standalone: true,\n imports: [AngularModule, PrimeModule, TagModule],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"card\">\n <div class=\"flex justify-between items-center mb-4\">\n <h3 class=\"text-xl font-semibold\">Roles</h3>\n <p-button\n label=\"New Role\"\n icon=\"pi pi-plus\"\n (onClick)=\"onCreate()\" />\n </div>\n\n <p-table\n [value]=\"roles()\"\n [loading]=\"isLoading()\"\n [paginator]=\"true\"\n [rows]=\"pageSize()\"\n [first]=\"first()\"\n [totalRecords]=\"total()\"\n [lazy]=\"true\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n [rowsPerPageOptions]=\"[10, 25, 50]\"\n styleClass=\"p-datatable-sm\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th>Name</th>\n <th>Description</th>\n <th>Active</th>\n <th>Read Only</th>\n <th style=\"width: 150px\">Actions</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-role>\n <tr>\n <td>{{ role.name }}</td>\n <td>{{ role.description ?? '-' }}</td>\n <td>\n <p-tag\n [value]=\"role.isActive ? 'Active' : 'Inactive'\"\n [severity]=\"role.isActive ? 'success' : 'secondary'\" />\n </td>\n <td>\n <p-tag\n [value]=\"role.readOnly ? 'Yes' : 'No'\"\n [severity]=\"role.readOnly ? 'warn' : 'secondary'\" />\n </td>\n <td>\n <div class=\"flex gap-2\">\n <p-button\n icon=\"pi pi-pencil\"\n [outlined]=\"true\"\n severity=\"info\"\n size=\"small\"\n (onClick)=\"onEdit(role)\" />\n <p-button\n icon=\"pi pi-trash\"\n [outlined]=\"true\"\n severity=\"danger\"\n size=\"small\"\n [disabled]=\"role.readOnly\"\n (onClick)=\"onDelete(role)\" />\n </div>\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"emptymessage\">\n <tr>\n <td colspan=\"5\" class=\"text-center\">No roles found.</td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n `,\n})\nexport class RoleListPageComponent {\n private readonly router = inject(Router);\n private readonly appConfig = inject(APP_CONFIG);\n private readonly companyContext = inject(LAYOUT_AUTH_STATE);\n private readonly roleApi = inject(RoleApiService);\n private readonly messageService = inject(MessageService);\n private readonly confirmationService = inject(ConfirmationService);\n\n readonly roles = signal<IRole[]>([]);\n readonly isLoading = signal(false);\n readonly total = signal(0);\n readonly pageSize = signal(10);\n readonly first = signal(0);\n\n constructor() {\n effect(() => {\n this.companyContext.currentCompanyInfo();\n untracked(() => this.loadRoles());\n });\n }\n\n private async loadRoles(): Promise<void> {\n this.isLoading.set(true);\n try {\n const enableCompanyFeature = isCompanyFeatureEnabled(this.appConfig);\n const companyId = enableCompanyFeature\n ? this.companyContext.currentCompanyInfo()?.id || undefined\n : undefined;\n\n const selectFields = ['id', 'name', 'description', 'isActive', 'readOnly', 'serial', 'createdAt', 'deletedAt'];\n if (enableCompanyFeature) {\n selectFields.push('companyId');\n }\n\n const response = await firstValueFrom(\n this.roleApi.getAll('', {\n filter: companyId ? { companyId } : undefined,\n pagination: {\n currentPage: Math.floor(this.first() / this.pageSize()),\n pageSize: this.pageSize(),\n },\n select: selectFields,\n sort: { id: 'ASC' },\n })\n );\n\n this.roles.set(response?.data ?? []);\n this.total.set(response?.meta?.total ?? 0);\n } catch {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Failed to load roles',\n });\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onCreate(): void {\n this.router.navigate(['/iam/roles/new']);\n }\n\n onEdit(role: IRole): void {\n this.router.navigate(['/iam/roles', role.id]);\n }\n\n onDelete(role: IRole): void {\n this.confirmationService.confirm({\n message: `Are you sure you want to delete role \"${role.name}\"?`,\n header: 'Confirm Delete',\n icon: 'pi pi-exclamation-triangle',\n accept: async () => {\n try {\n await this.roleApi.deleteAsync({ id: role.id, type: 'delete' });\n\n this.roles.update((list) => list.filter((r) => r.id !== role.id));\n this.total.update((t) => Math.max(0, t - 1));\n\n this.messageService.add({\n severity: 'success',\n summary: 'Success',\n detail: 'Role deleted successfully',\n });\n } catch (error: any) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: error.message || 'Failed to delete role',\n });\n }\n },\n });\n }\n\n onLazyLoad(event: { first?: number | null; rows?: number | null }): void {\n this.first.set(event.first ?? 0);\n this.pageSize.set(event.rows ?? 10);\n this.loadRoles();\n }\n}\n"],"names":["i1","i2","i3","i4"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { A as ActionApiService, e as ActionPermissionLogicService, a as ActionType, C as CompanyActionSelectorComponent, I as IAM_ROUTES, L as LogicBuilderComponent, M as MAX_DROPDOWN_ITEMS, f as MyPermissionsApiService, P as PermissionApiService, g as PermissionStateService, b as RoleActionSelectorComponent, R as RoleApiService, d as UserActionSelectorComponent, U as UserRoleSelectorComponent } from './flusys-ng-iam-flusys-ng-iam-
|
|
1
|
+
export { A as ActionApiService, e as ActionPermissionLogicService, a as ActionType, C as CompanyActionSelectorComponent, I as IAM_ROUTES, L as LogicBuilderComponent, M as MAX_DROPDOWN_ITEMS, f as MyPermissionsApiService, P as PermissionApiService, g as PermissionStateService, h as ProfilePermissionProviderAdapter, b as RoleActionSelectorComponent, R as RoleApiService, d as UserActionSelectorComponent, U as UserRoleSelectorComponent, p as provideIamProviders } from './flusys-ng-iam-flusys-ng-iam-BjdM-Vgz.mjs';
|
|
2
2
|
//# sourceMappingURL=flusys-ng-iam.mjs.map
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flusys/ng-iam",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0-beta",
|
|
4
4
|
"description": "Identity and Access Management (IAM) for Angular - Independent from ng-auth through Provider Interface Pattern",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"peerDependencies": {
|
|
7
7
|
"@angular/common": "^21.0.0",
|
|
8
8
|
"@angular/core": "^21.0.0",
|
|
9
9
|
"@angular/forms": "^21.0.0",
|
|
10
|
-
"@flusys/ng-core": "^
|
|
11
|
-
"@flusys/ng-layout": "^
|
|
12
|
-
"@flusys/ng-shared": "^
|
|
10
|
+
"@flusys/ng-core": "^1.1.0-beta",
|
|
11
|
+
"@flusys/ng-layout": "^1.1.0-beta",
|
|
12
|
+
"@flusys/ng-shared": "^1.1.0-beta",
|
|
13
13
|
"@primeuix/themes": "^1.0.0",
|
|
14
14
|
"primeicons": "^7.0.0",
|
|
15
15
|
"primeng": "^21.0.0"
|
package/types/flusys-ng-iam.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IBaseEntity, ILogicNode, ApiResourceService, ISingleResponse } from '@flusys/ng-shared';
|
|
1
|
+
import { IBaseEntity, ILogicNode, ApiResourceService, ISingleResponse, IProfilePermissionProvider, IProfileRoleInfo, IProfileActionInfo } from '@flusys/ng-shared';
|
|
2
2
|
import * as _angular_core from '@angular/core';
|
|
3
|
-
import { Signal, OnDestroy } from '@angular/core';
|
|
3
|
+
import { Signal, OnDestroy, Provider } from '@angular/core';
|
|
4
4
|
import { Observable } from 'rxjs';
|
|
5
5
|
import { BaseApiService } from '@flusys/ng-core';
|
|
6
6
|
import * as primeng_api from 'primeng/api';
|
|
@@ -942,14 +942,12 @@ declare class CompanyActionSelectorComponent implements OnDestroy {
|
|
|
942
942
|
declare class UserRoleSelectorComponent {
|
|
943
943
|
private readonly appConfig;
|
|
944
944
|
private readonly companyContext;
|
|
945
|
-
private readonly userProvider;
|
|
946
945
|
private readonly userPermissionProvider;
|
|
947
946
|
private readonly roleApi;
|
|
948
947
|
private readonly permissionApi;
|
|
949
948
|
private readonly messageService;
|
|
950
|
-
readonly selectedUserId: _angular_core.WritableSignal<string |
|
|
949
|
+
readonly selectedUserId: _angular_core.WritableSignal<string | null>;
|
|
951
950
|
readonly selectedBranchId: _angular_core.WritableSignal<string | undefined>;
|
|
952
|
-
readonly users: _angular_core.WritableSignal<IUser[]>;
|
|
953
951
|
readonly branches: _angular_core.WritableSignal<IBranch[]>;
|
|
954
952
|
readonly loading: _angular_core.WritableSignal<boolean>;
|
|
955
953
|
readonly saving: _angular_core.WritableSignal<boolean>;
|
|
@@ -967,10 +965,6 @@ declare class UserRoleSelectorComponent {
|
|
|
967
965
|
readonly pendingRemove: _angular_core.Signal<IRole[]>;
|
|
968
966
|
readonly canSave: _angular_core.Signal<boolean>;
|
|
969
967
|
constructor();
|
|
970
|
-
/**
|
|
971
|
-
* Load users from provider
|
|
972
|
-
*/
|
|
973
|
-
private loadUsers;
|
|
974
968
|
/**
|
|
975
969
|
* Load user's permitted branches
|
|
976
970
|
*/
|
|
@@ -1045,15 +1039,13 @@ declare class UserRoleSelectorComponent {
|
|
|
1045
1039
|
declare class UserActionSelectorComponent {
|
|
1046
1040
|
private readonly appConfig;
|
|
1047
1041
|
private readonly companyContext;
|
|
1048
|
-
private readonly userProvider;
|
|
1049
1042
|
private readonly userPermissionProvider;
|
|
1050
1043
|
private readonly actionApi;
|
|
1051
1044
|
private readonly permissionApi;
|
|
1052
1045
|
private readonly permissionLogic;
|
|
1053
1046
|
private readonly messageService;
|
|
1054
|
-
readonly selectedUserId: _angular_core.WritableSignal<string |
|
|
1047
|
+
readonly selectedUserId: _angular_core.WritableSignal<string | null>;
|
|
1055
1048
|
readonly selectedBranchId: _angular_core.WritableSignal<string | undefined>;
|
|
1056
|
-
readonly users: _angular_core.WritableSignal<IUser[]>;
|
|
1057
1049
|
readonly branches: _angular_core.WritableSignal<IBranch[]>;
|
|
1058
1050
|
readonly loading: _angular_core.WritableSignal<boolean>;
|
|
1059
1051
|
readonly saving: _angular_core.WritableSignal<boolean>;
|
|
@@ -1076,10 +1068,6 @@ declare class UserActionSelectorComponent {
|
|
|
1076
1068
|
readonly pendingRemove: _angular_core.Signal<IAction[]>;
|
|
1077
1069
|
readonly canSave: _angular_core.Signal<boolean>;
|
|
1078
1070
|
constructor();
|
|
1079
|
-
/**
|
|
1080
|
-
* Load users from provider
|
|
1081
|
-
*/
|
|
1082
|
-
private loadUsers;
|
|
1083
1071
|
/**
|
|
1084
1072
|
* Load user's permitted branches
|
|
1085
1073
|
*/
|
|
@@ -1124,6 +1112,51 @@ declare class UserActionSelectorComponent {
|
|
|
1124
1112
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserActionSelectorComponent, "flusys-user-action-selector", never, {}, {}, never, never, true, never>;
|
|
1125
1113
|
}
|
|
1126
1114
|
|
|
1115
|
+
/**
|
|
1116
|
+
* Profile Permission Provider Adapter
|
|
1117
|
+
*
|
|
1118
|
+
* Implements IProfilePermissionProvider using ng-iam's PermissionApiService.
|
|
1119
|
+
* Allows ng-auth profile page to display user permissions without
|
|
1120
|
+
* depending on ng-iam directly.
|
|
1121
|
+
*
|
|
1122
|
+
* @example
|
|
1123
|
+
* // In app.config.ts
|
|
1124
|
+
* providers: [
|
|
1125
|
+
* ...provideIamProviders()
|
|
1126
|
+
* ]
|
|
1127
|
+
*
|
|
1128
|
+
* // In profile component
|
|
1129
|
+
* private readonly permissionProvider = inject(PROFILE_PERMISSION_PROVIDER, { optional: true });
|
|
1130
|
+
*/
|
|
1131
|
+
declare class ProfilePermissionProviderAdapter implements IProfilePermissionProvider {
|
|
1132
|
+
private readonly permissionApi;
|
|
1133
|
+
getUserRoles(userId: string, branchId?: string): Observable<ISingleResponse<IProfileRoleInfo[]>>;
|
|
1134
|
+
getUserActions(userId: string, branchId?: string): Observable<ISingleResponse<IProfileActionInfo[]>>;
|
|
1135
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ProfilePermissionProviderAdapter, never>;
|
|
1136
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<ProfilePermissionProviderAdapter>;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
/**
|
|
1140
|
+
* Provide IAM Provider Adapters
|
|
1141
|
+
*
|
|
1142
|
+
* Registers IAM implementations for provider interfaces from ng-shared.
|
|
1143
|
+
* This allows ng-auth profile page to display permissions without direct dependencies.
|
|
1144
|
+
*
|
|
1145
|
+
* @example
|
|
1146
|
+
* // In app.config.ts
|
|
1147
|
+
* import { provideIamProviders } from '@flusys/ng-iam';
|
|
1148
|
+
*
|
|
1149
|
+
* export const appConfig: ApplicationConfig = {
|
|
1150
|
+
* providers: [
|
|
1151
|
+
* ...provideIamProviders(),
|
|
1152
|
+
* // ... other providers
|
|
1153
|
+
* ]
|
|
1154
|
+
* };
|
|
1155
|
+
*
|
|
1156
|
+
* @returns Array of Angular providers
|
|
1157
|
+
*/
|
|
1158
|
+
declare function provideIamProviders(): Provider[];
|
|
1159
|
+
|
|
1127
1160
|
/**
|
|
1128
1161
|
* IAM Routes Configuration
|
|
1129
1162
|
*
|
|
@@ -1136,5 +1169,5 @@ declare class UserActionSelectorComponent {
|
|
|
1136
1169
|
*/
|
|
1137
1170
|
declare const IAM_ROUTES: Routes;
|
|
1138
1171
|
|
|
1139
|
-
export { ActionApiService, ActionPermissionLogicService, ActionType, CompanyActionSelectorComponent, IAM_ROUTES, LogicBuilderComponent, MAX_DROPDOWN_ITEMS, MyPermissionsApiService, PermissionApiService, PermissionStateService, RoleActionSelectorComponent, RoleApiService, UserActionSelectorComponent, UserRoleSelectorComponent };
|
|
1172
|
+
export { ActionApiService, ActionPermissionLogicService, ActionType, CompanyActionSelectorComponent, IAM_ROUTES, LogicBuilderComponent, MAX_DROPDOWN_ITEMS, MyPermissionsApiService, PermissionApiService, PermissionStateService, ProfilePermissionProviderAdapter, RoleActionSelectorComponent, RoleApiService, UserActionSelectorComponent, UserRoleSelectorComponent, provideIamProviders };
|
|
1140
1173
|
export type { IAction, IActionTreeDto, IAssignCompanyActionsDto, IAssignRoleActionsDto, IAssignUserActionsDto, IAssignUserRolesDto, IBranch, ICompany, ICompanyActionResponseDto, ICreateActionDto, ICreateRoleDto, IGetMyPermissionsDto, IGetRoleActionsDto, IGetUserActionsDto, IGetUserRolesDto, IMenuAction, IMyPermissionsResponseDto, IPermissionItemDto, IPermissionOperationResultDto, IPrerequisiteActionDto, IPrerequisiteValidationError, IRole, IRoleActionResponseDto, IRoleQueryDto, IUpdateActionDto, IUpdateRoleDto, IUser, IUserActionResponseDto, IUserRoleResponseDto, PermissionAction, PermissionMode };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"flusys-ng-iam-action-form-page.component-BVWZMlLU.mjs","sources":["../../../projects/ng-iam/pages/action/action-form-page.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, inject, OnInit, signal } from '@angular/core';\nimport { form, FormField, required } from '@angular/forms/signals';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { AngularModule, ILogicNode, PrimeModule } from '@flusys/ng-shared';\nimport { MessageService } from 'primeng/api';\nimport { firstValueFrom } from 'rxjs';\nimport { ActionApiService } from '../../services/action-api.service';\nimport { IAction, ActionType } from '../../interfaces/action.interface';\nimport { LogicBuilderComponent } from '../../components/logic-builder.component';\n\n/** Action form model interface */\ninterface IActionFormModel {\n id: string;\n name: string;\n description: string;\n code: string;\n actionType: ActionType;\n permissionLogic: any | null;\n parentId: string;\n serial: string;\n isActive: boolean;\n metadata: any | null;\n}\n\n/**\n * Action Form Page Component\n * Create/Edit action with signal-based form pattern (matches ng-auth)\n */\n@Component({\n selector: 'lib-action-form-page',\n standalone: true,\n imports: [AngularModule, PrimeModule, FormField, LogicBuilderComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"card\">\n <div class=\"flex justify-between items-center mb-4\">\n <h3 class=\"text-xl font-semibold\">\n {{ isEditMode() ? 'Edit Action' : 'New Action' }}\n </h3>\n <p-button\n label=\"Back\"\n icon=\"pi pi-arrow-left\"\n [outlined]=\"true\"\n (onClick)=\"onBack()\" />\n </div>\n\n <form (ngSubmit)=\"onSubmit()\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Name -->\n <div>\n <label for=\"name\" class=\"block font-medium mb-2\">Name *</label>\n <input\n pInputText\n id=\"name\"\n [formField]=\"actionForm.name\"\n class=\"w-full\"\n placeholder=\"Enter action name\" />\n </div>\n\n <!-- Code -->\n <div>\n <label for=\"code\" class=\"block font-medium mb-2\">Code</label>\n <input\n pInputText\n id=\"code\"\n [formField]=\"actionForm.code\"\n class=\"w-full\"\n placeholder=\"Enter action code\" />\n </div>\n\n <!-- Description -->\n <div class=\"md:col-span-2\">\n <label for=\"description\" class=\"block font-medium mb-2\">Description</label>\n <input\n pInputText\n id=\"description\"\n [formField]=\"actionForm.description\"\n class=\"w-full\"\n placeholder=\"Enter description\" />\n </div>\n\n <!-- Action Type -->\n <div>\n <label for=\"actionType\" class=\"block font-medium mb-2\">Action Type *</label>\n <select\n id=\"actionType\"\n class=\"p-select-native\"\n [formField]=\"actionForm.actionType\">\n @for (type of actionTypes; track type.value) {\n <option [value]=\"type.value\">{{ type.label }}</option>\n }\n </select>\n </div>\n\n <!-- Parent Action -->\n <div>\n <label for=\"parentId\" class=\"block font-medium mb-2\">Parent Action</label>\n <select\n id=\"parentId\"\n class=\"p-select-native\"\n [formField]=\"actionForm.parentId\">\n <option value=\"\">Select parent action</option>\n @for (action of availableActions(); track action.id) {\n <option [value]=\"action.id\">{{ action.name }}</option>\n }\n </select>\n </div>\n\n <!-- Order -->\n <div>\n <label for=\"serial\" class=\"block font-medium mb-2\">Display Order</label>\n <input\n pInputText\n id=\"serial\"\n type=\"number\"\n [formField]=\"actionForm.serial\"\n class=\"w-full\"\n placeholder=\"Enter display order\" />\n </div>\n\n <!-- Is Active -->\n <div class=\"flex items-center pt-6\">\n <label class=\"p-checkbox-native\">\n <input\n type=\"checkbox\"\n [formField]=\"actionForm.isActive\" />\n <span>Active</span>\n </label>\n </div>\n </div>\n\n <!-- Permission Logic Builder -->\n <div class=\"mt-6\">\n <lib-logic-builder\n [logic]=\"formModel().permissionLogic\"\n [actions]=\"allActionsForLogic()\"\n (logicChange)=\"onLogicChange($event)\" />\n </div>\n\n <!-- Actions -->\n <div class=\"flex justify-end gap-2 mt-6\">\n <p-button\n label=\"Cancel\"\n severity=\"secondary\"\n [outlined]=\"true\"\n (onClick)=\"onBack()\" />\n <p-button\n [label]=\"isEditMode() ? 'Update' : 'Create'\"\n type=\"submit\"\n [loading]=\"isLoading()\"\n [disabled]=\"!isFormValid() || isLoading()\" />\n </div>\n </form>\n </div>\n `,\n})\nexport class ActionFormPageComponent implements OnInit {\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n private readonly actionApi = inject(ActionApiService);\n private readonly messageService = inject(MessageService);\n\n /** Loading state */\n readonly isLoading = signal(false);\n\n /** Existing action data when editing */\n readonly existingAction = signal<IAction | null>(null);\n\n /** Whether in edit mode */\n readonly isEditMode = computed(() => !!this.existingAction());\n\n /** All actions for LogicBuilder */\n readonly allActionsForLogic = signal<Array<{ id: string; name: string }>>([]);\n\n /** All loaded actions for parent dropdown */\n readonly allActions = signal<IAction[]>([]);\n\n /** Available actions for parent dropdown (excludes current action to prevent circular reference) */\n readonly availableActions = computed(() => {\n const actions = this.allActions();\n const currentId = this.existingAction()?.id;\n return currentId ? actions.filter(a => a.id !== currentId) : actions;\n });\n\n // ============================================\n // Form (Signal Forms)\n // ============================================\n\n /** Form model */\n readonly formModel = signal<IActionFormModel>({\n id: '',\n name: '',\n description: '',\n code: '',\n actionType: ActionType.BACKEND,\n permissionLogic: null,\n parentId: '',\n serial: '',\n isActive: true,\n metadata: null,\n });\n\n /** Available action types for dropdown */\n readonly actionTypes = [\n { label: 'Backend (API Endpoints)', value: ActionType.BACKEND },\n { label: 'Frontend (UI Features)', value: ActionType.FRONTEND },\n { label: 'Both (Backend + Frontend)', value: ActionType.BOTH },\n ];\n\n /** Form with validation schema */\n readonly actionForm = form(this.formModel, (f) => {\n required(f.name, { message: 'Name is required' });\n });\n\n /** Check if form is valid */\n readonly isFormValid = computed(() => {\n const model = this.formModel();\n return model.name.trim().length > 0;\n });\n\n async ngOnInit(): Promise<void> {\n const id = this.route.snapshot.paramMap.get('id');\n\n // Load ALL actions FIRST - critical for LogicBuilder to display action names\n try {\n const response = await firstValueFrom(\n this.actionApi.getAll('', {\n pagination: { currentPage: 0, pageSize: 10000 },\n select: ['id', 'name', 'code', 'actionType', 'permissionLogic'],\n })\n );\n\n if (response?.success && response.data) {\n // Set actions for LogicBuilder dropdown\n this.allActionsForLogic.set(\n response.data.map(a => ({ id: a.id!, name: a.name ?? 'Unnamed' }))\n );\n\n // Store loaded actions locally for parent dropdown\n this.allActions.set(response.data);\n }\n } catch (error) {\n console.error('[ActionFormPage] Failed to load actions:', error);\n }\n\n // THEN load the specific action (ensures actions are loaded before setting permissionLogic)\n if (id && id !== 'new') {\n await this.loadAction(id);\n }\n }\n\n async loadAction(id: string): Promise<void> {\n this.isLoading.set(true);\n try {\n // Load fresh data from API to ensure permissionLogic is included\n const response = await this.actionApi.findByIdAsync(id, [\n 'id',\n 'name',\n 'description',\n 'code',\n 'actionType',\n 'permissionLogic',\n 'parentId',\n 'serial',\n 'isActive',\n 'metadata',\n ]);\n\n if (response?.success && response.data) {\n const action = response.data;\n\n // Set existing action for reference\n this.existingAction.set(action);\n\n // Populate form with action data\n this.formModel.set({\n id: action.id ?? '',\n name: action.name ?? '',\n description: action.description ?? '',\n code: action.code ?? '',\n actionType: action.actionType ?? ActionType.BACKEND,\n permissionLogic: action.permissionLogic ?? null,\n parentId: action.parentId ?? '',\n serial: action.serial?.toString() ?? '',\n isActive: action.isActive ?? true,\n metadata: action.metadata ?? null,\n });\n } else {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Action not found.',\n });\n this.router.navigate(['/iam/actions']);\n }\n } catch (error) {\n console.error('[ActionFormPage] Failed to load action:', error);\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Failed to load action.',\n });\n this.router.navigate(['/iam/actions']);\n } finally {\n this.isLoading.set(false);\n }\n }\n\n async onSubmit(): Promise<void> {\n if (!this.isFormValid()) {\n this.messageService.add({\n severity: 'error',\n summary: 'Validation Error',\n detail: 'Please fill in all required fields.',\n });\n return;\n }\n\n this.isLoading.set(true);\n\n try {\n const formValue = this.formModel();\n\n // Convert empty strings to undefined for DTO compatibility\n const dto = {\n ...formValue,\n description: formValue.description || undefined,\n code: formValue.code || undefined,\n parentId: formValue.parentId || undefined,\n serial: formValue.serial ? parseInt(formValue.serial, 10) : undefined,\n metadata: formValue.metadata ?? undefined,\n permissionLogic: formValue.permissionLogic ?? undefined,\n };\n\n if (this.isEditMode()) {\n await this.actionApi.updateAsync(dto);\n this.messageService.add({\n severity: 'success',\n summary: 'Success',\n detail: 'Action updated successfully.',\n });\n } else {\n await this.actionApi.insertAsync(dto);\n this.messageService.add({\n severity: 'success',\n summary: 'Success',\n detail: 'Action created successfully.',\n });\n }\n\n this.router.navigate(['/iam/actions']);\n } catch (error: any) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: error.message || 'Failed to save action.',\n });\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onBack(): void {\n this.router.navigate(['/iam/actions']);\n }\n\n /**\n * Handle permission logic changes from LogicBuilder\n */\n onLogicChange(logic: ILogicNode | null): void {\n this.formModel.update(model => ({\n ...model,\n permissionLogic: logic\n }));\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AAwBA;;;AAGG;MAiIU,uBAAuB,CAAA;AACjB,IAAA,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC;AAC9B,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,IAAA,SAAS,GAAG,MAAM,CAAC,gBAAgB,CAAC;AACpC,IAAA,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;;AAG/C,IAAA,SAAS,GAAG,MAAM,CAAC,KAAK,qDAAC;;AAGzB,IAAA,cAAc,GAAG,MAAM,CAAiB,IAAI,0DAAC;;AAG7C,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,sDAAC;;AAGpD,IAAA,kBAAkB,GAAG,MAAM,CAAsC,EAAE,8DAAC;;AAGpE,IAAA,UAAU,GAAG,MAAM,CAAY,EAAE,sDAAC;;AAGlC,IAAA,gBAAgB,GAAG,QAAQ,CAAC,MAAK;AACxC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE;QACjC,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,EAAE,EAAE;QAC3C,OAAO,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,GAAG,OAAO;AACtE,IAAA,CAAC,4DAAC;;;;;IAOO,SAAS,GAAG,MAAM,CAAmB;AAC5C,QAAA,EAAE,EAAE,EAAE;AACN,QAAA,IAAI,EAAE,EAAE;AACR,QAAA,WAAW,EAAE,EAAE;AACf,QAAA,IAAI,EAAE,EAAE;QACR,UAAU,EAAE,UAAU,CAAC,OAAO;AAC9B,QAAA,eAAe,EAAE,IAAI;AACrB,QAAA,QAAQ,EAAE,EAAE;AACZ,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE,IAAI;AACd,QAAA,QAAQ,EAAE,IAAI;AACf,KAAA,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,WAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC;;AAGO,IAAA,WAAW,GAAG;QACrB,EAAE,KAAK,EAAE,yBAAyB,EAAE,KAAK,EAAE,UAAU,CAAC,OAAO,EAAE;QAC/D,EAAE,KAAK,EAAE,wBAAwB,EAAE,KAAK,EAAE,UAAU,CAAC,QAAQ,EAAE;QAC/D,EAAE,KAAK,EAAE,2BAA2B,EAAE,KAAK,EAAE,UAAU,CAAC,IAAI,EAAE;KAC/D;;IAGQ,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,KAAI;QAC/C,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;AACnD,IAAA,CAAC,CAAC;;AAGO,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAK;AACnC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE;QAC9B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;AACrC,IAAA,CAAC,uDAAC;AAEF,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;;AAGjD,QAAA,IAAI;AACF,YAAA,MAAM,QAAQ,GAAG,MAAM,cAAc,CACnC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE;gBACxB,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE;gBAC/C,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,iBAAiB,CAAC;AAChE,aAAA,CAAC,CACH;YAED,IAAI,QAAQ,EAAE,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;;AAEtC,gBAAA,IAAI,CAAC,kBAAkB,CAAC,GAAG,CACzB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,EAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC,CACnE;;gBAGD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;YACpC;QACF;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,KAAK,CAAC;QAClE;;AAGA,QAAA,IAAI,EAAE,IAAI,EAAE,KAAK,KAAK,EAAE;AACtB,YAAA,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B;IACF;IAEA,MAAM,UAAU,CAAC,EAAU,EAAA;AACzB,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AACxB,QAAA,IAAI;;YAEF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,EAAE;gBACtD,IAAI;gBACJ,MAAM;gBACN,aAAa;gBACb,MAAM;gBACN,YAAY;gBACZ,iBAAiB;gBACjB,UAAU;gBACV,QAAQ;gBACR,UAAU;gBACV,UAAU;AACX,aAAA,CAAC;YAEF,IAAI,QAAQ,EAAE,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;AACtC,gBAAA,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI;;AAG5B,gBAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;;AAG/B,gBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;AACjB,oBAAA,EAAE,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE;AACnB,oBAAA,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;AACvB,oBAAA,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;AACrC,oBAAA,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;AACvB,oBAAA,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,UAAU,CAAC,OAAO;AACnD,oBAAA,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,IAAI;AAC/C,oBAAA,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE;oBAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;AACvC,oBAAA,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,IAAI;AACjC,oBAAA,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,IAAI;AAClC,iBAAA,CAAC;YACJ;iBAAO;AACL,gBAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;AACtB,oBAAA,QAAQ,EAAE,OAAO;AACjB,oBAAA,OAAO,EAAE,OAAO;AAChB,oBAAA,MAAM,EAAE,mBAAmB;AAC5B,iBAAA,CAAC;gBACF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAC;YACxC;QACF;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC;AAC/D,YAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;AACtB,gBAAA,QAAQ,EAAE,OAAO;AACjB,gBAAA,OAAO,EAAE,OAAO;AAChB,gBAAA,MAAM,EAAE,wBAAwB;AACjC,aAAA,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAC;QACxC;gBAAU;AACR,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QAC3B;IACF;AAEA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE;AACvB,YAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;AACtB,gBAAA,QAAQ,EAAE,OAAO;AACjB,gBAAA,OAAO,EAAE,kBAAkB;AAC3B,gBAAA,MAAM,EAAE,qCAAqC;AAC9C,aAAA,CAAC;YACF;QACF;AAEA,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AAExB,QAAA,IAAI;AACF,YAAA,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE;;AAGlC,YAAA,MAAM,GAAG,GAAG;AACV,gBAAA,GAAG,SAAS;AACZ,gBAAA,WAAW,EAAE,SAAS,CAAC,WAAW,IAAI,SAAS;AAC/C,gBAAA,IAAI,EAAE,SAAS,CAAC,IAAI,IAAI,SAAS;AACjC,gBAAA,QAAQ,EAAE,SAAS,CAAC,QAAQ,IAAI,SAAS;AACzC,gBAAA,MAAM,EAAE,SAAS,CAAC,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,SAAS;AACrE,gBAAA,QAAQ,EAAE,SAAS,CAAC,QAAQ,IAAI,SAAS;AACzC,gBAAA,eAAe,EAAE,SAAS,CAAC,eAAe,IAAI,SAAS;aACxD;AAED,YAAA,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;gBACrB,MAAM,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC;AACrC,gBAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;AACtB,oBAAA,QAAQ,EAAE,SAAS;AACnB,oBAAA,OAAO,EAAE,SAAS;AAClB,oBAAA,MAAM,EAAE,8BAA8B;AACvC,iBAAA,CAAC;YACJ;iBAAO;gBACL,MAAM,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC;AACrC,gBAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;AACtB,oBAAA,QAAQ,EAAE,SAAS;AACnB,oBAAA,OAAO,EAAE,SAAS;AAClB,oBAAA,MAAM,EAAE,8BAA8B;AACvC,iBAAA,CAAC;YACJ;YAEA,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAC;QACxC;QAAE,OAAO,KAAU,EAAE;AACnB,YAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;AACtB,gBAAA,QAAQ,EAAE,OAAO;AACjB,gBAAA,OAAO,EAAE,OAAO;AAChB,gBAAA,MAAM,EAAE,KAAK,CAAC,OAAO,IAAI,wBAAwB;AAClD,aAAA,CAAC;QACJ;gBAAU;AACR,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QAC3B;IACF;IAEA,MAAM,GAAA;QACJ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAC;IACxC;AAEA;;AAEG;AACH,IAAA,aAAa,CAAC,KAAwB,EAAA;QACpC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,KAAK;AAC9B,YAAA,GAAG,KAAK;AACR,YAAA,eAAe,EAAE;AAClB,SAAA,CAAC,CAAC;IACL;uGA1NW,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAvB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,uBAAuB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,sBAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA3HxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyHT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA3HS,aAAa,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,aAAA,EAAA,QAAA,EAAA,8CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,cAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,uBAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,sGAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,QAAA,EAAA,yEAAA,EAAA,MAAA,EAAA,CAAA,eAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,SAAA,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,aAAA,EAAA,cAAA,EAAA,oBAAA,EAAA,OAAA,EAAA,SAAA,EAAA,OAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,OAAA,EAAA,UAAA,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,OAAA,EAAA,UAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,SAAA,EAAA,OAAA,EAAA,YAAA,EAAA,YAAA,EAAA,eAAA,EAAA,WAAA,EAAA,WAAA,EAAA,SAAA,EAAA,MAAA,EAAA,OAAA,EAAA,SAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,SAAS,+EAAE,qBAAqB,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,aAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FA6H3D,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBAhInC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,sBAAsB;AAChC,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,qBAAqB,CAAC;oBACvE,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyHT,EAAA,CAAA;AACF,iBAAA;;;;;"}
|