@flusys/ng-iam 1.1.1-beta → 1.2.0-rc.1
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 +44 -1027
- package/fesm2022/flusys-ng-iam-action-form-page.component-Vc5Toouu.mjs +502 -0
- package/fesm2022/flusys-ng-iam-action-form-page.component-Vc5Toouu.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-action-list-page.component-UGKclpFx.mjs +348 -0
- package/fesm2022/flusys-ng-iam-action-list-page.component-UGKclpFx.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-flusys-ng-iam-CrycDULz.mjs +4561 -0
- package/fesm2022/flusys-ng-iam-flusys-ng-iam-CrycDULz.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-iam-container.component-D0m8u6nu.mjs +105 -0
- package/fesm2022/flusys-ng-iam-iam-container.component-D0m8u6nu.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-permission-page.component-x88X4AgJ.mjs +143 -0
- package/fesm2022/flusys-ng-iam-permission-page.component-x88X4AgJ.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-role-form-page.component-InsxdriD.mjs +335 -0
- package/fesm2022/flusys-ng-iam-role-form-page.component-InsxdriD.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-role-list-page.component-8NGXCeSZ.mjs +389 -0
- package/fesm2022/flusys-ng-iam-role-list-page.component-8NGXCeSZ.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam.mjs +1 -1
- package/package.json +11 -10
- package/types/flusys-ng-iam.d.ts +107 -686
- package/fesm2022/flusys-ng-iam-action-form-page.component-C1j10Qhw.mjs +0 -467
- package/fesm2022/flusys-ng-iam-action-form-page.component-C1j10Qhw.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-action-list-page.component-BCzSardO.mjs +0 -281
- package/fesm2022/flusys-ng-iam-action-list-page.component-BCzSardO.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-flusys-ng-iam-DISrddPh.mjs +0 -4940
- package/fesm2022/flusys-ng-iam-flusys-ng-iam-DISrddPh.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-iam-container.component-BkhqmzLi.mjs +0 -97
- package/fesm2022/flusys-ng-iam-iam-container.component-BkhqmzLi.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-permission-page.component-BSQFPt_N.mjs +0 -143
- package/fesm2022/flusys-ng-iam-permission-page.component-BSQFPt_N.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-role-form-page.component-Cqziu_BM.mjs +0 -314
- package/fesm2022/flusys-ng-iam-role-form-page.component-Cqziu_BM.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-role-list-page.component-BObCxHiB.mjs +0 -266
- package/fesm2022/flusys-ng-iam-role-list-page.component-BObCxHiB.mjs.map +0 -1
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, computed, Component } from '@angular/core';
|
|
3
|
-
import { CommonModule } from '@angular/common';
|
|
4
|
-
import { RouterOutlet, RouterLink, RouterLinkActive } from '@angular/router';
|
|
5
|
-
import { APP_CONFIG, getPermissionMode } from '@flusys/ng-core';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* IAM Container Component
|
|
9
|
-
*
|
|
10
|
-
* Main container for IAM module with tab navigation
|
|
11
|
-
* Routes: Actions | Roles (conditional) | Users (permission assignment)
|
|
12
|
-
*/
|
|
13
|
-
class IamContainerComponent {
|
|
14
|
-
appConfig = inject(APP_CONFIG);
|
|
15
|
-
/** All available tabs */
|
|
16
|
-
allTabs = [
|
|
17
|
-
{
|
|
18
|
-
id: 'actions',
|
|
19
|
-
label: 'Actions',
|
|
20
|
-
icon: 'pi pi-bolt',
|
|
21
|
-
route: 'actions',
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
id: 'roles',
|
|
25
|
-
label: 'Roles',
|
|
26
|
-
icon: 'pi pi-shield',
|
|
27
|
-
route: 'roles',
|
|
28
|
-
requiresRBAC: true,
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
id: 'permissions',
|
|
32
|
-
label: 'Permissions',
|
|
33
|
-
icon: 'pi pi-key',
|
|
34
|
-
route: 'permissions',
|
|
35
|
-
},
|
|
36
|
-
];
|
|
37
|
-
/** Visible tabs based on permission mode */
|
|
38
|
-
visibleTabs = computed(() => {
|
|
39
|
-
const permissionMode = getPermissionMode(this.appConfig);
|
|
40
|
-
return this.allTabs.filter((tab) => !tab.requiresRBAC || permissionMode === 'rbac' || permissionMode === 'full');
|
|
41
|
-
}, ...(ngDevMode ? [{ debugName: "visibleTabs" }] : []));
|
|
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
|
-
<div class="iam-page p-4">
|
|
45
|
-
<div class="iam-header mb-4">
|
|
46
|
-
<h1 class="text-2xl font-bold m-0">Identity & Access Management</h1>
|
|
47
|
-
<p class="text-muted-color mt-1">Manage actions, roles, and user permissions</p>
|
|
48
|
-
</div>
|
|
49
|
-
|
|
50
|
-
<div class="iam-tabs flex gap-1 mb-4 border-b border-surface-200">
|
|
51
|
-
@for (tab of visibleTabs(); track tab.id) {
|
|
52
|
-
<a
|
|
53
|
-
[routerLink]="tab.route"
|
|
54
|
-
routerLinkActive="active"
|
|
55
|
-
class="tab-link flex items-center gap-2 px-4 py-2 rounded-t-lg cursor-pointer transition-colors">
|
|
56
|
-
<i [class]="tab.icon"></i>
|
|
57
|
-
<span>{{ tab.label }}</span>
|
|
58
|
-
</a>
|
|
59
|
-
}
|
|
60
|
-
</div>
|
|
61
|
-
|
|
62
|
-
<div class="iam-content">
|
|
63
|
-
<router-outlet />
|
|
64
|
-
</div>
|
|
65
|
-
</div>
|
|
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
|
-
}
|
|
68
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: IamContainerComponent, decorators: [{
|
|
69
|
-
type: Component,
|
|
70
|
-
args: [{ selector: 'lib-iam-container', standalone: true, imports: [CommonModule, RouterOutlet, RouterLink, RouterLinkActive], template: `
|
|
71
|
-
<div class="iam-page p-4">
|
|
72
|
-
<div class="iam-header mb-4">
|
|
73
|
-
<h1 class="text-2xl font-bold m-0">Identity & Access Management</h1>
|
|
74
|
-
<p class="text-muted-color mt-1">Manage actions, roles, and user permissions</p>
|
|
75
|
-
</div>
|
|
76
|
-
|
|
77
|
-
<div class="iam-tabs flex gap-1 mb-4 border-b border-surface-200">
|
|
78
|
-
@for (tab of visibleTabs(); track tab.id) {
|
|
79
|
-
<a
|
|
80
|
-
[routerLink]="tab.route"
|
|
81
|
-
routerLinkActive="active"
|
|
82
|
-
class="tab-link flex items-center gap-2 px-4 py-2 rounded-t-lg cursor-pointer transition-colors">
|
|
83
|
-
<i [class]="tab.icon"></i>
|
|
84
|
-
<span>{{ tab.label }}</span>
|
|
85
|
-
</a>
|
|
86
|
-
}
|
|
87
|
-
</div>
|
|
88
|
-
|
|
89
|
-
<div class="iam-content">
|
|
90
|
-
<router-outlet />
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
93
|
-
`, 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"] }]
|
|
94
|
-
}] });
|
|
95
|
-
|
|
96
|
-
export { IamContainerComponent };
|
|
97
|
-
//# sourceMappingURL=flusys-ng-iam-iam-container.component-BkhqmzLi.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"flusys-ng-iam-iam-container.component-BkhqmzLi.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-muted-color 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-surface-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;;;;;"}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, signal, computed, Component } from '@angular/core';
|
|
3
|
-
import { AngularModule, PrimeModule } from '@flusys/ng-shared';
|
|
4
|
-
import { APP_CONFIG, getPermissionMode, isCompanyFeatureEnabled } from '@flusys/ng-core';
|
|
5
|
-
import * as i2 from 'primeng/button';
|
|
6
|
-
import { ButtonModule } from 'primeng/button';
|
|
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-DISrddPh.mjs';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Permission Page Component
|
|
12
|
-
*
|
|
13
|
-
* Main permission management interface with tabs for:
|
|
14
|
-
* - Role-Action Assignment (RBAC/FULL mode) - WITH LOGIC BUILDER
|
|
15
|
-
* - User-Role Assignment (RBAC/FULL mode)
|
|
16
|
-
* - User-Action Assignment (DIRECT/FULL mode)
|
|
17
|
-
* - Company-Action Whitelist (if company feature enabled)
|
|
18
|
-
*/
|
|
19
|
-
class PermissionPageComponent {
|
|
20
|
-
appConfig = inject(APP_CONFIG);
|
|
21
|
-
activeTab = signal('role-actions', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
22
|
-
/**
|
|
23
|
-
* Available tabs based on configuration
|
|
24
|
-
*/
|
|
25
|
-
availableTabs = computed(() => {
|
|
26
|
-
const permissionMode = getPermissionMode(this.appConfig);
|
|
27
|
-
const tabs = [];
|
|
28
|
-
// Role-Action assignment (RBAC or FULL mode)
|
|
29
|
-
if (permissionMode === 'rbac' || permissionMode === 'full') {
|
|
30
|
-
tabs.push({
|
|
31
|
-
id: 'role-actions',
|
|
32
|
-
label: 'Role-Actions',
|
|
33
|
-
icon: 'pi pi-shield',
|
|
34
|
-
}, {
|
|
35
|
-
id: 'user-roles',
|
|
36
|
-
label: 'User-Roles',
|
|
37
|
-
icon: 'pi pi-user',
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
// User-Action direct assignment (DIRECT or FULL mode)
|
|
41
|
-
if (permissionMode === 'direct' || permissionMode === 'full') {
|
|
42
|
-
tabs.push({
|
|
43
|
-
id: 'user-actions',
|
|
44
|
-
label: 'User-Actions',
|
|
45
|
-
icon: 'pi pi-key',
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
// Company-Action whitelist (if company feature enabled)
|
|
49
|
-
if (isCompanyFeatureEnabled(this.appConfig)) {
|
|
50
|
-
tabs.push({
|
|
51
|
-
id: 'company-actions',
|
|
52
|
-
label: 'Company-Actions',
|
|
53
|
-
icon: 'pi pi-building',
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
return tabs;
|
|
57
|
-
}, ...(ngDevMode ? [{ debugName: "availableTabs" }] : []));
|
|
58
|
-
setActiveTab(tabId) {
|
|
59
|
-
this.activeTab.set(tabId);
|
|
60
|
-
}
|
|
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
|
-
<div class="card">
|
|
64
|
-
<h3 class="text-xl font-semibold mb-4">Permission Management</h3>
|
|
65
|
-
|
|
66
|
-
<div class="flex gap-2 mb-4">
|
|
67
|
-
@for (tab of availableTabs(); track tab.id) {
|
|
68
|
-
<p-button
|
|
69
|
-
[label]="tab.label"
|
|
70
|
-
[icon]="tab.icon"
|
|
71
|
-
[outlined]="activeTab() !== tab.id"
|
|
72
|
-
size="small"
|
|
73
|
-
(onClick)="setActiveTab(tab.id)" />
|
|
74
|
-
}
|
|
75
|
-
</div>
|
|
76
|
-
|
|
77
|
-
<div class="mt-4">
|
|
78
|
-
@switch (activeTab()) {
|
|
79
|
-
@case ('role-actions') {
|
|
80
|
-
<flusys-role-action-selector />
|
|
81
|
-
}
|
|
82
|
-
@case ('user-roles') {
|
|
83
|
-
<flusys-user-role-selector />
|
|
84
|
-
}
|
|
85
|
-
@case ('user-actions') {
|
|
86
|
-
<flusys-user-action-selector />
|
|
87
|
-
}
|
|
88
|
-
@case ('company-actions') {
|
|
89
|
-
<flusys-company-action-selector />
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
</div>
|
|
93
|
-
</div>
|
|
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
|
-
}
|
|
96
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PermissionPageComponent, decorators: [{
|
|
97
|
-
type: Component,
|
|
98
|
-
args: [{ selector: 'lib-permission-page', standalone: true, imports: [
|
|
99
|
-
AngularModule,
|
|
100
|
-
PrimeModule,
|
|
101
|
-
ButtonModule,
|
|
102
|
-
TabsModule,
|
|
103
|
-
RoleActionSelectorComponent,
|
|
104
|
-
CompanyActionSelectorComponent,
|
|
105
|
-
UserRoleSelectorComponent,
|
|
106
|
-
UserActionSelectorComponent
|
|
107
|
-
], template: `
|
|
108
|
-
<div class="card">
|
|
109
|
-
<h3 class="text-xl font-semibold mb-4">Permission Management</h3>
|
|
110
|
-
|
|
111
|
-
<div class="flex gap-2 mb-4">
|
|
112
|
-
@for (tab of availableTabs(); track tab.id) {
|
|
113
|
-
<p-button
|
|
114
|
-
[label]="tab.label"
|
|
115
|
-
[icon]="tab.icon"
|
|
116
|
-
[outlined]="activeTab() !== tab.id"
|
|
117
|
-
size="small"
|
|
118
|
-
(onClick)="setActiveTab(tab.id)" />
|
|
119
|
-
}
|
|
120
|
-
</div>
|
|
121
|
-
|
|
122
|
-
<div class="mt-4">
|
|
123
|
-
@switch (activeTab()) {
|
|
124
|
-
@case ('role-actions') {
|
|
125
|
-
<flusys-role-action-selector />
|
|
126
|
-
}
|
|
127
|
-
@case ('user-roles') {
|
|
128
|
-
<flusys-user-role-selector />
|
|
129
|
-
}
|
|
130
|
-
@case ('user-actions') {
|
|
131
|
-
<flusys-user-action-selector />
|
|
132
|
-
}
|
|
133
|
-
@case ('company-actions') {
|
|
134
|
-
<flusys-company-action-selector />
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
</div>
|
|
138
|
-
</div>
|
|
139
|
-
`, styles: [":host{display:block}\n"] }]
|
|
140
|
-
}] });
|
|
141
|
-
|
|
142
|
-
export { PermissionPageComponent };
|
|
143
|
-
//# sourceMappingURL=flusys-ng-iam-permission-page.component-BSQFPt_N.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"flusys-ng-iam-permission-page.component-BSQFPt_N.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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"}
|
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, signal, computed, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
-
import { form, required, FormField } from '@angular/forms/signals';
|
|
4
|
-
import { ActivatedRoute, Router } from '@angular/router';
|
|
5
|
-
import { APP_CONFIG, isCompanyFeatureEnabled } from '@flusys/ng-core';
|
|
6
|
-
import { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';
|
|
7
|
-
import { AngularModule, PrimeModule } from '@flusys/ng-shared';
|
|
8
|
-
import { MessageService } from 'primeng/api';
|
|
9
|
-
import { firstValueFrom } from 'rxjs';
|
|
10
|
-
import { R as RoleApiService } from './flusys-ng-iam-flusys-ng-iam-DISrddPh.mjs';
|
|
11
|
-
import * as i1 from '@angular/forms';
|
|
12
|
-
import * as i2 from 'primeng/button';
|
|
13
|
-
import * as i3 from 'primeng/inputtext';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Role Form Page Component
|
|
17
|
-
* Create/Edit role with signal-based form pattern (matches ng-auth)
|
|
18
|
-
*/
|
|
19
|
-
class RoleFormPageComponent {
|
|
20
|
-
route = inject(ActivatedRoute);
|
|
21
|
-
router = inject(Router);
|
|
22
|
-
appConfig = inject(APP_CONFIG);
|
|
23
|
-
companyContext = inject(LAYOUT_AUTH_STATE);
|
|
24
|
-
roleApi = inject(RoleApiService);
|
|
25
|
-
messageService = inject(MessageService);
|
|
26
|
-
/** Loading state */
|
|
27
|
-
isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
28
|
-
/** Existing role data when editing */
|
|
29
|
-
existingRole = signal(null, ...(ngDevMode ? [{ debugName: "existingRole" }] : []));
|
|
30
|
-
/** Whether in edit mode */
|
|
31
|
-
isEditMode = computed(() => !!this.existingRole(), ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
|
|
32
|
-
// ============================================
|
|
33
|
-
// Form (Signal Forms)
|
|
34
|
-
// ============================================
|
|
35
|
-
/** Form model */
|
|
36
|
-
formModel = signal({
|
|
37
|
-
id: '',
|
|
38
|
-
name: '',
|
|
39
|
-
description: '',
|
|
40
|
-
serial: '',
|
|
41
|
-
isActive: true,
|
|
42
|
-
}, ...(ngDevMode ? [{ debugName: "formModel" }] : []));
|
|
43
|
-
/** Form with validation schema */
|
|
44
|
-
roleForm = form(this.formModel, (f) => {
|
|
45
|
-
required(f.name, { message: 'Name is required' });
|
|
46
|
-
});
|
|
47
|
-
/** Check if form is valid */
|
|
48
|
-
isFormValid = computed(() => {
|
|
49
|
-
const model = this.formModel();
|
|
50
|
-
return model.name.trim().length > 0;
|
|
51
|
-
}, ...(ngDevMode ? [{ debugName: "isFormValid" }] : []));
|
|
52
|
-
ngOnInit() {
|
|
53
|
-
const id = this.route.snapshot.paramMap.get('id');
|
|
54
|
-
if (id && id !== 'new') {
|
|
55
|
-
this.loadRole(id);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
async loadRole(id) {
|
|
59
|
-
this.isLoading.set(true);
|
|
60
|
-
try {
|
|
61
|
-
const response = await firstValueFrom(this.roleApi.findById(id));
|
|
62
|
-
const role = response?.data;
|
|
63
|
-
if (role) {
|
|
64
|
-
this.existingRole.set(role);
|
|
65
|
-
this.formModel.set({
|
|
66
|
-
id: role.id,
|
|
67
|
-
name: role.name,
|
|
68
|
-
description: role.description ?? '',
|
|
69
|
-
serial: role.serial?.toString() ?? '',
|
|
70
|
-
isActive: role.isActive,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
this.messageService.add({
|
|
75
|
-
severity: 'error',
|
|
76
|
-
summary: 'Error',
|
|
77
|
-
detail: 'Role not found.',
|
|
78
|
-
});
|
|
79
|
-
this.router.navigate(['/iam/roles']);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
catch (error) {
|
|
83
|
-
this.messageService.add({
|
|
84
|
-
severity: 'error',
|
|
85
|
-
summary: 'Error',
|
|
86
|
-
detail: 'Failed to load role.',
|
|
87
|
-
});
|
|
88
|
-
this.router.navigate(['/iam/roles']);
|
|
89
|
-
}
|
|
90
|
-
finally {
|
|
91
|
-
this.isLoading.set(false);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
async onSubmit() {
|
|
95
|
-
if (!this.isFormValid()) {
|
|
96
|
-
this.messageService.add({
|
|
97
|
-
severity: 'error',
|
|
98
|
-
summary: 'Validation Error',
|
|
99
|
-
detail: 'Please fill in all required fields.',
|
|
100
|
-
});
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
this.isLoading.set(true);
|
|
104
|
-
try {
|
|
105
|
-
const formValue = this.formModel();
|
|
106
|
-
// Get company context if feature enabled
|
|
107
|
-
const companyId = isCompanyFeatureEnabled(this.appConfig)
|
|
108
|
-
? this.companyContext.currentCompanyInfo()?.id || undefined
|
|
109
|
-
: undefined;
|
|
110
|
-
// Convert empty strings to undefined for DTO compatibility
|
|
111
|
-
const dto = {
|
|
112
|
-
...formValue,
|
|
113
|
-
description: formValue.description || undefined,
|
|
114
|
-
serial: formValue.serial ? parseInt(formValue.serial, 10) : undefined,
|
|
115
|
-
companyId: this.isEditMode() ? undefined : companyId,
|
|
116
|
-
};
|
|
117
|
-
if (this.isEditMode()) {
|
|
118
|
-
await this.roleApi.updateAsync(dto);
|
|
119
|
-
this.messageService.add({
|
|
120
|
-
severity: 'success',
|
|
121
|
-
summary: 'Success',
|
|
122
|
-
detail: 'Role updated successfully.',
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
await this.roleApi.insertAsync(dto);
|
|
127
|
-
this.messageService.add({
|
|
128
|
-
severity: 'success',
|
|
129
|
-
summary: 'Success',
|
|
130
|
-
detail: 'Role created successfully.',
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
this.router.navigate(['/iam/roles']);
|
|
134
|
-
}
|
|
135
|
-
catch (error) {
|
|
136
|
-
this.messageService.add({
|
|
137
|
-
severity: 'error',
|
|
138
|
-
summary: 'Error',
|
|
139
|
-
detail: error.message || 'Failed to save role.',
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
finally {
|
|
143
|
-
this.isLoading.set(false);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
onBack() {
|
|
147
|
-
this.router.navigate(['/iam/roles']);
|
|
148
|
-
}
|
|
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
|
-
<div class="card">
|
|
152
|
-
<div class="flex justify-between items-center mb-4">
|
|
153
|
-
<h3 class="text-xl font-semibold">
|
|
154
|
-
{{ isEditMode() ? 'Edit Role' : 'New Role' }}
|
|
155
|
-
</h3>
|
|
156
|
-
<p-button
|
|
157
|
-
label="Back"
|
|
158
|
-
icon="pi pi-arrow-left"
|
|
159
|
-
[outlined]="true"
|
|
160
|
-
(onClick)="onBack()" />
|
|
161
|
-
</div>
|
|
162
|
-
|
|
163
|
-
<form (ngSubmit)="onSubmit()">
|
|
164
|
-
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
165
|
-
<!-- Name -->
|
|
166
|
-
<div class="md:col-span-2">
|
|
167
|
-
<label for="name" class="block font-medium mb-2">Name *</label>
|
|
168
|
-
<input
|
|
169
|
-
pInputText
|
|
170
|
-
id="name"
|
|
171
|
-
[formField]="roleForm.name"
|
|
172
|
-
class="w-full"
|
|
173
|
-
placeholder="Enter role name" />
|
|
174
|
-
</div>
|
|
175
|
-
|
|
176
|
-
<!-- Description -->
|
|
177
|
-
<div class="md:col-span-2">
|
|
178
|
-
<label for="description" class="block font-medium mb-2">Description</label>
|
|
179
|
-
<input
|
|
180
|
-
pInputText
|
|
181
|
-
id="description"
|
|
182
|
-
[formField]="roleForm.description"
|
|
183
|
-
class="w-full"
|
|
184
|
-
placeholder="Enter description" />
|
|
185
|
-
</div>
|
|
186
|
-
|
|
187
|
-
<!-- Order -->
|
|
188
|
-
<div>
|
|
189
|
-
<label for="serial" class="block font-medium mb-2">Display Order</label>
|
|
190
|
-
<input
|
|
191
|
-
pInputText
|
|
192
|
-
id="serial"
|
|
193
|
-
type="number"
|
|
194
|
-
[formField]="roleForm.serial"
|
|
195
|
-
class="w-full"
|
|
196
|
-
placeholder="Enter display order" />
|
|
197
|
-
</div>
|
|
198
|
-
|
|
199
|
-
<!-- Is Active -->
|
|
200
|
-
<div class="flex items-center pt-6">
|
|
201
|
-
<label class="p-checkbox-native">
|
|
202
|
-
<input
|
|
203
|
-
type="checkbox"
|
|
204
|
-
[formField]="roleForm.isActive" />
|
|
205
|
-
<span>Active</span>
|
|
206
|
-
</label>
|
|
207
|
-
</div>
|
|
208
|
-
</div>
|
|
209
|
-
|
|
210
|
-
<!-- Actions -->
|
|
211
|
-
<div class="flex justify-end gap-2 mt-6">
|
|
212
|
-
<p-button
|
|
213
|
-
label="Cancel"
|
|
214
|
-
severity="secondary"
|
|
215
|
-
[outlined]="true"
|
|
216
|
-
(onClick)="onBack()" />
|
|
217
|
-
<p-button
|
|
218
|
-
[label]="isEditMode() ? 'Update' : 'Create'"
|
|
219
|
-
type="submit"
|
|
220
|
-
[loading]="isLoading()"
|
|
221
|
-
[disabled]="!isFormValid() || isLoading()" />
|
|
222
|
-
</div>
|
|
223
|
-
</form>
|
|
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: "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
|
-
}
|
|
227
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoleFormPageComponent, decorators: [{
|
|
228
|
-
type: Component,
|
|
229
|
-
args: [{
|
|
230
|
-
selector: 'lib-role-form-page',
|
|
231
|
-
standalone: true,
|
|
232
|
-
imports: [AngularModule, PrimeModule, FormField],
|
|
233
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
234
|
-
template: `
|
|
235
|
-
<div class="card">
|
|
236
|
-
<div class="flex justify-between items-center mb-4">
|
|
237
|
-
<h3 class="text-xl font-semibold">
|
|
238
|
-
{{ isEditMode() ? 'Edit Role' : 'New Role' }}
|
|
239
|
-
</h3>
|
|
240
|
-
<p-button
|
|
241
|
-
label="Back"
|
|
242
|
-
icon="pi pi-arrow-left"
|
|
243
|
-
[outlined]="true"
|
|
244
|
-
(onClick)="onBack()" />
|
|
245
|
-
</div>
|
|
246
|
-
|
|
247
|
-
<form (ngSubmit)="onSubmit()">
|
|
248
|
-
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
249
|
-
<!-- Name -->
|
|
250
|
-
<div class="md:col-span-2">
|
|
251
|
-
<label for="name" class="block font-medium mb-2">Name *</label>
|
|
252
|
-
<input
|
|
253
|
-
pInputText
|
|
254
|
-
id="name"
|
|
255
|
-
[formField]="roleForm.name"
|
|
256
|
-
class="w-full"
|
|
257
|
-
placeholder="Enter role name" />
|
|
258
|
-
</div>
|
|
259
|
-
|
|
260
|
-
<!-- Description -->
|
|
261
|
-
<div class="md:col-span-2">
|
|
262
|
-
<label for="description" class="block font-medium mb-2">Description</label>
|
|
263
|
-
<input
|
|
264
|
-
pInputText
|
|
265
|
-
id="description"
|
|
266
|
-
[formField]="roleForm.description"
|
|
267
|
-
class="w-full"
|
|
268
|
-
placeholder="Enter description" />
|
|
269
|
-
</div>
|
|
270
|
-
|
|
271
|
-
<!-- Order -->
|
|
272
|
-
<div>
|
|
273
|
-
<label for="serial" class="block font-medium mb-2">Display Order</label>
|
|
274
|
-
<input
|
|
275
|
-
pInputText
|
|
276
|
-
id="serial"
|
|
277
|
-
type="number"
|
|
278
|
-
[formField]="roleForm.serial"
|
|
279
|
-
class="w-full"
|
|
280
|
-
placeholder="Enter display order" />
|
|
281
|
-
</div>
|
|
282
|
-
|
|
283
|
-
<!-- Is Active -->
|
|
284
|
-
<div class="flex items-center pt-6">
|
|
285
|
-
<label class="p-checkbox-native">
|
|
286
|
-
<input
|
|
287
|
-
type="checkbox"
|
|
288
|
-
[formField]="roleForm.isActive" />
|
|
289
|
-
<span>Active</span>
|
|
290
|
-
</label>
|
|
291
|
-
</div>
|
|
292
|
-
</div>
|
|
293
|
-
|
|
294
|
-
<!-- Actions -->
|
|
295
|
-
<div class="flex justify-end gap-2 mt-6">
|
|
296
|
-
<p-button
|
|
297
|
-
label="Cancel"
|
|
298
|
-
severity="secondary"
|
|
299
|
-
[outlined]="true"
|
|
300
|
-
(onClick)="onBack()" />
|
|
301
|
-
<p-button
|
|
302
|
-
[label]="isEditMode() ? 'Update' : 'Create'"
|
|
303
|
-
type="submit"
|
|
304
|
-
[loading]="isLoading()"
|
|
305
|
-
[disabled]="!isFormValid() || isLoading()" />
|
|
306
|
-
</div>
|
|
307
|
-
</form>
|
|
308
|
-
</div>
|
|
309
|
-
`,
|
|
310
|
-
}]
|
|
311
|
-
}] });
|
|
312
|
-
|
|
313
|
-
export { RoleFormPageComponent };
|
|
314
|
-
//# sourceMappingURL=flusys-ng-iam-role-form-page.component-Cqziu_BM.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"flusys-ng-iam-role-form-page.component-Cqziu_BM.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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"}
|