@flusys/ng-iam 3.0.0 → 4.0.0-lts

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/README.md +2 -2
  2. package/fesm2022/{flusys-ng-iam-action-form-page.component-eXpZNJ_H.mjs → flusys-ng-iam-action-form-page.component-BQx9yset.mjs} +62 -50
  3. package/fesm2022/flusys-ng-iam-action-form-page.component-BQx9yset.mjs.map +1 -0
  4. package/fesm2022/{flusys-ng-iam-action-list-page.component-BtJlGcTj.mjs → flusys-ng-iam-action-list-page.component-BrpZujxk.mjs} +51 -42
  5. package/fesm2022/flusys-ng-iam-action-list-page.component-BrpZujxk.mjs.map +1 -0
  6. package/fesm2022/{flusys-ng-iam-flusys-ng-iam-CJAQT60K.mjs → flusys-ng-iam-flusys-ng-iam-Co4ot9My.mjs} +641 -341
  7. package/fesm2022/flusys-ng-iam-flusys-ng-iam-Co4ot9My.mjs.map +1 -0
  8. package/fesm2022/{flusys-ng-iam-iam-container.component-UYJjqYV9.mjs → flusys-ng-iam-iam-container.component-CQA2B6cU.mjs} +14 -13
  9. package/fesm2022/flusys-ng-iam-iam-container.component-CQA2B6cU.mjs.map +1 -0
  10. package/fesm2022/{flusys-ng-iam-permission-page.component-DcgT7L3_.mjs → flusys-ng-iam-permission-page.component-Dpk90y72.mjs} +14 -13
  11. package/fesm2022/flusys-ng-iam-permission-page.component-Dpk90y72.mjs.map +1 -0
  12. package/fesm2022/{flusys-ng-iam-role-form-page.component-D_AAEay2.mjs → flusys-ng-iam-role-form-page.component-CVfRQpoa.mjs} +38 -35
  13. package/fesm2022/flusys-ng-iam-role-form-page.component-CVfRQpoa.mjs.map +1 -0
  14. package/fesm2022/{flusys-ng-iam-role-list-page.component-D4J1by6Q.mjs → flusys-ng-iam-role-list-page.component-BHB8X5r7.mjs} +41 -38
  15. package/fesm2022/flusys-ng-iam-role-list-page.component-BHB8X5r7.mjs.map +1 -0
  16. package/fesm2022/flusys-ng-iam.mjs +1 -1
  17. package/package.json +7 -5
  18. package/types/flusys-ng-iam.d.ts +13 -5
  19. package/fesm2022/flusys-ng-iam-action-form-page.component-eXpZNJ_H.mjs.map +0 -1
  20. package/fesm2022/flusys-ng-iam-action-list-page.component-BtJlGcTj.mjs.map +0 -1
  21. package/fesm2022/flusys-ng-iam-flusys-ng-iam-CJAQT60K.mjs.map +0 -1
  22. package/fesm2022/flusys-ng-iam-iam-container.component-UYJjqYV9.mjs.map +0 -1
  23. package/fesm2022/flusys-ng-iam-permission-page.component-DcgT7L3_.mjs.map +0 -1
  24. package/fesm2022/flusys-ng-iam-role-form-page.component-D_AAEay2.mjs.map +0 -1
  25. package/fesm2022/flusys-ng-iam-role-list-page.component-D4J1by6Q.mjs.map +0 -1
@@ -1,7 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, computed, ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { inject, computed, Component } from '@angular/core';
3
3
  import { RouterOutlet, RouterLink, RouterLinkActive } from '@angular/router';
4
4
  import { APP_CONFIG, getPermissionMode } from '@flusys/ng-core';
5
+ import { TranslatePipe } from '@flusys/ng-shared';
5
6
 
6
7
  /**
7
8
  * IAM Container Component
@@ -15,20 +16,20 @@ class IamContainerComponent {
15
16
  allTabs = [
16
17
  {
17
18
  id: 'actions',
18
- label: 'Actions',
19
+ labelKey: 'iam.action.title',
19
20
  icon: 'pi pi-bolt',
20
21
  route: 'actions',
21
22
  },
22
23
  {
23
24
  id: 'roles',
24
- label: 'Roles',
25
+ labelKey: 'iam.role.title',
25
26
  icon: 'pi pi-shield',
26
27
  route: 'roles',
27
28
  requiresRBAC: true,
28
29
  },
29
30
  {
30
31
  id: 'permissions',
31
- label: 'Permissions',
32
+ labelKey: 'iam.permission.title',
32
33
  icon: 'pi pi-key',
33
34
  route: 'permissions',
34
35
  },
@@ -42,8 +43,8 @@ class IamContainerComponent {
42
43
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: IamContainerComponent, isStandalone: true, selector: "lib-iam-container", ngImport: i0, template: `
43
44
  <div class="p-4">
44
45
  <div class="mb-4">
45
- <h1 class="text-xl sm:text-2xl font-bold m-0">Identity & Access Management</h1>
46
- <p class="text-muted-color mt-1">Manage actions, roles, and user permissions</p>
46
+ <h1 class="text-xl sm:text-2xl font-bold m-0">{{ 'iam.title' | translate }}</h1>
47
+ <p class="text-muted-color mt-1">{{ 'iam.subtitle' | translate }}</p>
47
48
  </div>
48
49
 
49
50
  <div class="scrollbar-hide flex gap-1 mb-4 border-b border-surface overflow-x-auto flex-nowrap">
@@ -53,22 +54,22 @@ class IamContainerComponent {
53
54
  routerLinkActive="tab-active"
54
55
  class="flex items-center gap-2 px-4 py-2 rounded-t-lg cursor-pointer transition-colors text-muted-color no-underline border-b-2 border-transparent -mb-px hover:bg-surface-hover [&.tab-active]:text-primary [&.tab-active]:border-primary [&.tab-active]:bg-surface-ground whitespace-nowrap shrink-0">
55
56
  <i [class]="tab.icon"></i>
56
- <span>{{ tab.label }}</span>
57
+ <span>{{ tab.labelKey | translate }}</span>
57
58
  </a>
58
59
  }
59
60
  </div>
60
61
 
61
62
  <router-outlet />
62
63
  </div>
63
- `, isInline: true, styles: [".scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-hide::-webkit-scrollbar{display:none}\n"], dependencies: [{ 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
64
+ `, isInline: true, styles: [".scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-hide::-webkit-scrollbar{display:none}\n"], dependencies: [{ 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"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
64
65
  }
65
66
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: IamContainerComponent, decorators: [{
66
67
  type: Component,
67
- args: [{ selector: 'lib-iam-container', imports: [RouterOutlet, RouterLink, RouterLinkActive], changeDetection: ChangeDetectionStrategy.OnPush, template: `
68
+ args: [{ selector: 'lib-iam-container', imports: [RouterOutlet, RouterLink, RouterLinkActive, TranslatePipe], template: `
68
69
  <div class="p-4">
69
70
  <div class="mb-4">
70
- <h1 class="text-xl sm:text-2xl font-bold m-0">Identity & Access Management</h1>
71
- <p class="text-muted-color mt-1">Manage actions, roles, and user permissions</p>
71
+ <h1 class="text-xl sm:text-2xl font-bold m-0">{{ 'iam.title' | translate }}</h1>
72
+ <p class="text-muted-color mt-1">{{ 'iam.subtitle' | translate }}</p>
72
73
  </div>
73
74
 
74
75
  <div class="scrollbar-hide flex gap-1 mb-4 border-b border-surface overflow-x-auto flex-nowrap">
@@ -78,7 +79,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
78
79
  routerLinkActive="tab-active"
79
80
  class="flex items-center gap-2 px-4 py-2 rounded-t-lg cursor-pointer transition-colors text-muted-color no-underline border-b-2 border-transparent -mb-px hover:bg-surface-hover [&.tab-active]:text-primary [&.tab-active]:border-primary [&.tab-active]:bg-surface-ground whitespace-nowrap shrink-0">
80
81
  <i [class]="tab.icon"></i>
81
- <span>{{ tab.label }}</span>
82
+ <span>{{ tab.labelKey | translate }}</span>
82
83
  </a>
83
84
  }
84
85
  </div>
@@ -89,4 +90,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
89
90
  }] });
90
91
 
91
92
  export { IamContainerComponent };
92
- //# sourceMappingURL=flusys-ng-iam-iam-container.component-UYJjqYV9.mjs.map
93
+ //# sourceMappingURL=flusys-ng-iam-iam-container.component-CQA2B6cU.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-iam-iam-container.component-CQA2B6cU.mjs","sources":["../../../projects/ng-iam/pages/iam-container/iam-container.component.ts"],"sourcesContent":["import { Component, computed, inject } from '@angular/core';\nimport { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';\nimport { APP_CONFIG, getPermissionMode } from '@flusys/ng-core';\nimport { TranslatePipe } from '@flusys/ng-shared';\n\ninterface ITab {\n id: string;\n labelKey: 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 imports: [RouterOutlet, RouterLink, RouterLinkActive, TranslatePipe],\n styles: `\n .scrollbar-hide {\n -ms-overflow-style: none;\n scrollbar-width: none;\n &::-webkit-scrollbar { display: none; }\n }\n `,\n template: `\n <div class=\"p-4\">\n <div class=\"mb-4\">\n <h1 class=\"text-xl sm:text-2xl font-bold m-0\">{{ 'iam.title' | translate }}</h1>\n <p class=\"text-muted-color mt-1\">{{ 'iam.subtitle' | translate }}</p>\n </div>\n\n <div class=\"scrollbar-hide flex gap-1 mb-4 border-b border-surface overflow-x-auto flex-nowrap\">\n @for (tab of visibleTabs(); track tab.id) {\n <a\n [routerLink]=\"tab.route\"\n routerLinkActive=\"tab-active\"\n class=\"flex items-center gap-2 px-4 py-2 rounded-t-lg cursor-pointer transition-colors text-muted-color no-underline border-b-2 border-transparent -mb-px hover:bg-surface-hover [&.tab-active]:text-primary [&.tab-active]:border-primary [&.tab-active]:bg-surface-ground whitespace-nowrap shrink-0\">\n <i [class]=\"tab.icon\"></i>\n <span>{{ tab.labelKey | translate }}</span>\n </a>\n }\n </div>\n\n <router-outlet />\n </div>\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 labelKey: 'iam.action.title',\n icon: 'pi pi-bolt',\n route: 'actions',\n },\n {\n id: 'roles',\n labelKey: 'iam.role.title',\n icon: 'pi pi-shield',\n route: 'roles',\n requiresRBAC: true,\n },\n {\n id: 'permissions',\n labelKey: 'iam.permission.title',\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;MAkCU,qBAAqB,CAAA;AACf,IAAA,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;;AAG9B,IAAA,OAAO,GAAW;AACjC,QAAA;AACE,YAAA,EAAE,EAAE,SAAS;AACb,YAAA,QAAQ,EAAE,kBAAkB;AAC5B,YAAA,IAAI,EAAE,YAAY;AAClB,YAAA,KAAK,EAAE,SAAS;AACjB,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,OAAO;AACX,YAAA,QAAQ,EAAE,gBAAgB;AAC1B,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,QAAQ,EAAE,sBAAsB;AAChC,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,EAvBtB;;;;;;;;;;;;;;;;;;;;;AAqBT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,iHAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EA7BS,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,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,aAAA,EAAA,UAAA,EAAA,qBAAA,EAAA,OAAA,EAAA,MAAA,EAAA,YAAA,EAAA,kBAAA,EAAA,oBAAA,EAAA,YAAA,EAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,gBAAgB,yMAAE,aAAa,EAAA,IAAA,EAAA,WAAA,EAAA,CAAA,EAAA,CAAA;;2FA+BxD,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBAjCjC,SAAS;+BACE,mBAAmB,EAAA,OAAA,EACpB,CAAC,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,aAAa,CAAC,EAAA,QAAA,EAQ1D;;;;;;;;;;;;;;;;;;;;;AAqBT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,iHAAA,CAAA,EAAA;;;;;"}
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, signal, computed, effect, untracked, ChangeDetectionStrategy, Component } from '@angular/core';
3
- import { COMPANY_ACTION_PERMISSIONS, USER_ACTION_PERMISSIONS, USER_ROLE_PERMISSIONS, ROLE_ACTION_PERMISSIONS, AngularModule, PrimeModule, HasPermissionDirective } from '@flusys/ng-shared';
2
+ import { inject, signal, computed, effect, untracked, Component } from '@angular/core';
3
+ import { COMPANY_ACTION_PERMISSIONS, USER_ACTION_PERMISSIONS, USER_ROLE_PERMISSIONS, ROLE_ACTION_PERMISSIONS, AngularModule, PrimeModule, HasPermissionDirective, TranslatePipe } from '@flusys/ng-shared';
4
4
  import { APP_CONFIG, getPermissionMode, isCompanyFeatureEnabled } from '@flusys/ng-core';
5
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-CJAQT60K.mjs';
8
+ import { b as RoleActionSelectorComponent, C as CompanyActionSelectorComponent, U as UserRoleSelectorComponent, d as UserActionSelectorComponent } from './flusys-ng-iam-flusys-ng-iam-Co4ot9My.mjs';
9
9
 
10
10
  /** Permission codes for each tab */
11
11
  const TAB_PERMISSIONS = {
@@ -23,13 +23,13 @@ class PermissionPageComponent {
23
23
  const permissionMode = getPermissionMode(this.appConfig);
24
24
  const tabs = [];
25
25
  if (permissionMode === 'rbac' || permissionMode === 'full') {
26
- tabs.push({ id: 'role-actions', label: 'Role-Actions', icon: 'pi pi-shield', permission: TAB_PERMISSIONS['role-actions'] }, { id: 'user-roles', label: 'User-Roles', icon: 'pi pi-user', permission: TAB_PERMISSIONS['user-roles'] });
26
+ tabs.push({ id: 'role-actions', labelKey: 'iam.permission.role.actions', icon: 'pi pi-shield', permission: TAB_PERMISSIONS['role-actions'] }, { id: 'user-roles', labelKey: 'iam.permission.user.roles', icon: 'pi pi-user', permission: TAB_PERMISSIONS['user-roles'] });
27
27
  }
28
28
  if (permissionMode === 'direct' || permissionMode === 'full') {
29
- tabs.push({ id: 'user-actions', label: 'User-Actions', icon: 'pi pi-key', permission: TAB_PERMISSIONS['user-actions'] });
29
+ tabs.push({ id: 'user-actions', labelKey: 'iam.permission.user.actions', icon: 'pi pi-key', permission: TAB_PERMISSIONS['user-actions'] });
30
30
  }
31
31
  if (isCompanyFeatureEnabled(this.appConfig)) {
32
- tabs.push({ id: 'company-actions', label: 'Company-Actions', icon: 'pi pi-building', permission: TAB_PERMISSIONS['company-actions'] });
32
+ tabs.push({ id: 'company-actions', labelKey: 'iam.permission.company.actions', icon: 'pi pi-building', permission: TAB_PERMISSIONS['company-actions'] });
33
33
  }
34
34
  return tabs;
35
35
  }, ...(ngDevMode ? [{ debugName: "availableTabs" }] : []));
@@ -50,13 +50,13 @@ class PermissionPageComponent {
50
50
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: PermissionPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
51
51
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: PermissionPageComponent, isStandalone: true, selector: "lib-permission-page", ngImport: i0, template: `
52
52
  <div class="card">
53
- <h3 class="text-xl font-semibold mb-4">Permission Management</h3>
53
+ <h3 class="text-xl font-semibold mb-4">{{ 'iam.permission.title' | translate }}</h3>
54
54
 
55
55
  <div class="scrollbar-hide flex gap-2 mb-4 overflow-x-auto flex-nowrap">
56
56
  @for (tab of availableTabs(); track tab.id) {
57
57
  <p-button
58
58
  *hasPermission="tab.permission"
59
- [label]="tab.label"
59
+ [label]="tab.labelKey | translate"
60
60
  [icon]="tab.icon"
61
61
  [outlined]="activeTab() !== tab.id"
62
62
  size="small"
@@ -82,29 +82,30 @@ class PermissionPageComponent {
82
82
  }
83
83
  </div>
84
84
  </div>
85
- `, isInline: true, styles: [".scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-hide::-webkit-scrollbar{display:none}\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: "directive", type: HasPermissionDirective, selector: "[hasPermission]", inputs: ["hasPermission"] }, { 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" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
85
+ `, isInline: true, styles: [".scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-hide::-webkit-scrollbar{display:none}\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: "directive", type: HasPermissionDirective, selector: "[hasPermission]", inputs: ["hasPermission"] }, { 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" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
86
86
  }
87
87
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: PermissionPageComponent, decorators: [{
88
88
  type: Component,
89
- args: [{ selector: 'lib-permission-page', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
89
+ args: [{ selector: 'lib-permission-page', imports: [
90
90
  AngularModule,
91
91
  PrimeModule,
92
92
  ButtonModule,
93
93
  TabsModule,
94
94
  HasPermissionDirective,
95
+ TranslatePipe,
95
96
  RoleActionSelectorComponent,
96
97
  CompanyActionSelectorComponent,
97
98
  UserRoleSelectorComponent,
98
99
  UserActionSelectorComponent
99
100
  ], template: `
100
101
  <div class="card">
101
- <h3 class="text-xl font-semibold mb-4">Permission Management</h3>
102
+ <h3 class="text-xl font-semibold mb-4">{{ 'iam.permission.title' | translate }}</h3>
102
103
 
103
104
  <div class="scrollbar-hide flex gap-2 mb-4 overflow-x-auto flex-nowrap">
104
105
  @for (tab of availableTabs(); track tab.id) {
105
106
  <p-button
106
107
  *hasPermission="tab.permission"
107
- [label]="tab.label"
108
+ [label]="tab.labelKey | translate"
108
109
  [icon]="tab.icon"
109
110
  [outlined]="activeTab() !== tab.id"
110
111
  size="small"
@@ -134,4 +135,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
134
135
  }], ctorParameters: () => [] });
135
136
 
136
137
  export { PermissionPageComponent };
137
- //# sourceMappingURL=flusys-ng-iam-permission-page.component-DcgT7L3_.mjs.map
138
+ //# sourceMappingURL=flusys-ng-iam-permission-page.component-Dpk90y72.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-iam-permission-page.component-Dpk90y72.mjs","sources":["../../../projects/ng-iam/pages/permission/permission-page.component.ts"],"sourcesContent":["import { Component, computed, effect, inject, signal, untracked } from '@angular/core';\nimport {\n AngularModule,\n HasPermissionDirective,\n PrimeModule,\n ROLE_ACTION_PERMISSIONS,\n USER_ROLE_PERMISSIONS,\n USER_ACTION_PERMISSIONS,\n COMPANY_ACTION_PERMISSIONS,\n TranslatePipe,\n} 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/** Permission codes for each tab */\nconst TAB_PERMISSIONS = {\n 'role-actions': ROLE_ACTION_PERMISSIONS.READ,\n 'user-roles': USER_ROLE_PERMISSIONS.READ,\n 'user-actions': USER_ACTION_PERMISSIONS.READ,\n 'company-actions': COMPANY_ACTION_PERMISSIONS.READ,\n} as const;\n\n/** Main permission management interface with tabs for role/user/company permission assignment */\n@Component({\n selector: 'lib-permission-page',\n imports: [\n AngularModule,\n PrimeModule,\n ButtonModule,\n TabsModule,\n HasPermissionDirective,\n TranslatePipe,\n RoleActionSelectorComponent,\n CompanyActionSelectorComponent,\n UserRoleSelectorComponent,\n UserActionSelectorComponent\n ],\n styles: `\n .scrollbar-hide {\n -ms-overflow-style: none;\n scrollbar-width: none;\n &::-webkit-scrollbar { display: none; }\n }\n `,\n template: `\n <div class=\"card\">\n <h3 class=\"text-xl font-semibold mb-4\">{{ 'iam.permission.title' | translate }}</h3>\n\n <div class=\"scrollbar-hide flex gap-2 mb-4 overflow-x-auto flex-nowrap\">\n @for (tab of availableTabs(); track tab.id) {\n <p-button\n *hasPermission=\"tab.permission\"\n [label]=\"tab.labelKey | translate\"\n [icon]=\"tab.icon\"\n [outlined]=\"activeTab() !== tab.id\"\n size=\"small\"\n styleClass=\"shrink-0\"\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})\nexport class PermissionPageComponent {\n private readonly appConfig = inject(APP_CONFIG);\n\n readonly activeTab = signal<string>('');\n\n /** Available tabs based on permission mode */\n readonly availableTabs = computed(() => {\n const permissionMode = getPermissionMode(this.appConfig);\n const tabs: Array<{ id: string; labelKey: string; icon: string; permission: string }> = [];\n\n if (permissionMode === 'rbac' || permissionMode === 'full') {\n tabs.push(\n { id: 'role-actions', labelKey: 'iam.permission.role.actions', icon: 'pi pi-shield', permission: TAB_PERMISSIONS['role-actions'] },\n { id: 'user-roles', labelKey: 'iam.permission.user.roles', icon: 'pi pi-user', permission: TAB_PERMISSIONS['user-roles'] }\n );\n }\n\n if (permissionMode === 'direct' || permissionMode === 'full') {\n tabs.push({ id: 'user-actions', labelKey: 'iam.permission.user.actions', icon: 'pi pi-key', permission: TAB_PERMISSIONS['user-actions'] });\n }\n\n if (isCompanyFeatureEnabled(this.appConfig)) {\n tabs.push({ id: 'company-actions', labelKey: 'iam.permission.company.actions', icon: 'pi pi-building', permission: TAB_PERMISSIONS['company-actions'] });\n }\n\n return tabs;\n });\n\n constructor() {\n effect(() => {\n const tabs = this.availableTabs();\n const currentTab = untracked(() => this.activeTab());\n if (!currentTab || !tabs.some((t) => t.id === currentTab)) {\n if (tabs.length > 0) {\n this.activeTab.set(tabs[0].id);\n }\n }\n });\n }\n\n setActiveTab(tabId: string): void {\n this.activeTab.set(tabId);\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,14 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, signal, computed, effect, ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { inject, signal, computed, effect, Component } from '@angular/core';
3
3
  import { toSignal } from '@angular/core/rxjs-interop';
4
4
  import { form, required, FormField } from '@angular/forms/signals';
5
5
  import { ActivatedRoute, Router } from '@angular/router';
6
- import { APP_CONFIG, isCompanyFeatureEnabled } from '@flusys/ng-core';
6
+ import { APP_CONFIG, TRANSLATE_ADAPTER, isCompanyFeatureEnabled } from '@flusys/ng-core';
7
7
  import { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';
8
- import { AngularModule, PrimeModule } from '@flusys/ng-shared';
8
+ import { AngularModule, PrimeModule, TranslatePipe } from '@flusys/ng-shared';
9
9
  import { MessageService } from 'primeng/api';
10
10
  import { firstValueFrom } from 'rxjs';
11
- import { R as RoleApiService } from './flusys-ng-iam-flusys-ng-iam-CJAQT60K.mjs';
11
+ import { R as RoleApiService } from './flusys-ng-iam-flusys-ng-iam-Co4ot9My.mjs';
12
12
  import * as i1 from '@angular/forms';
13
13
  import * as i2 from 'primeng/button';
14
14
  import * as i3 from 'primeng/checkbox';
@@ -21,8 +21,12 @@ class RoleFormPageComponent {
21
21
  companyContext = inject(LAYOUT_AUTH_STATE);
22
22
  roleApi = inject(RoleApiService);
23
23
  messageService = inject(MessageService);
24
+ translateAdapter = inject(TRANSLATE_ADAPTER, { optional: true });
24
25
  routeParams = toSignal(this.route.paramMap);
25
26
  initialized = false;
27
+ translate(key, vars) {
28
+ return this.translateAdapter?.translate(key, vars) ?? key;
29
+ }
26
30
  isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
27
31
  existingRole = signal(null, ...(ngDevMode ? [{ debugName: "existingRole" }] : []));
28
32
  isEditMode = computed(() => !!this.existingRole(), ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
@@ -34,7 +38,7 @@ class RoleFormPageComponent {
34
38
  isActive: true,
35
39
  }, ...(ngDevMode ? [{ debugName: "formModel" }] : []));
36
40
  roleForm = form(this.formModel, (f) => {
37
- required(f.name, { message: 'Name is required' });
41
+ required(f.name, { message: this.translate('shared.validation.required', { field: this.translate('iam.role.name') }) });
38
42
  });
39
43
  isFormValid = computed(() => {
40
44
  const model = this.formModel();
@@ -84,8 +88,8 @@ class RoleFormPageComponent {
84
88
  if (!this.isFormValid()) {
85
89
  this.messageService.add({
86
90
  severity: 'error',
87
- summary: 'Validation Error',
88
- detail: 'Please fill in all required fields.',
91
+ summary: this.translate('shared.validation.error'),
92
+ detail: this.translate('shared.fill.required.fields'),
89
93
  });
90
94
  return;
91
95
  }
@@ -107,16 +111,16 @@ class RoleFormPageComponent {
107
111
  await this.roleApi.updateAsync(dto);
108
112
  this.messageService.add({
109
113
  severity: 'success',
110
- summary: 'Success',
111
- detail: 'Role updated successfully.',
114
+ summary: this.translate('shared.success'),
115
+ detail: this.translate('iam.role.update.success'),
112
116
  });
113
117
  }
114
118
  else {
115
119
  await this.roleApi.insertAsync(dto);
116
120
  this.messageService.add({
117
121
  severity: 'success',
118
- summary: 'Success',
119
- detail: 'Role created successfully.',
122
+ summary: this.translate('shared.success'),
123
+ detail: this.translate('iam.role.create.success'),
120
124
  });
121
125
  }
122
126
  this.router.navigate(['/iam/roles']);
@@ -135,39 +139,39 @@ class RoleFormPageComponent {
135
139
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.5", type: RoleFormPageComponent, isStandalone: true, selector: "lib-role-form-page", ngImport: i0, template: `
136
140
  <div class="card">
137
141
  <h3 class="text-lg sm:text-xl font-semibold mb-4">
138
- {{ isEditMode() ? 'Edit Role' : 'New Role' }}
142
+ {{ isEditMode() ? ('iam.role.edit' | translate) : ('iam.role.new' | translate) }}
139
143
  </h3>
140
144
 
141
145
  <form (ngSubmit)="onSubmit()" class="grid grid-cols-1 md:grid-cols-2 gap-4">
142
146
  <!-- Name -->
143
147
  <div class="flex flex-col gap-2">
144
- <label for="name" class="font-medium">Name *</label>
148
+ <label for="name" class="font-medium">{{ 'iam.role.name' | translate }} *</label>
145
149
  <input
146
150
  pInputText
147
151
  id="name"
148
152
  [formField]="roleForm.name"
149
- placeholder="Enter role name" />
153
+ [placeholder]="'iam.role.name.placeholder' | translate" />
150
154
  </div>
151
155
 
152
156
  <!-- Description -->
153
157
  <div class="flex flex-col gap-2">
154
- <label for="description" class="font-medium">Description</label>
158
+ <label for="description" class="font-medium">{{ 'shared.description' | translate }}</label>
155
159
  <input
156
160
  pInputText
157
161
  id="description"
158
162
  [formField]="roleForm.description"
159
- placeholder="Enter description" />
163
+ [placeholder]="'shared.description.placeholder' | translate" />
160
164
  </div>
161
165
 
162
166
  <!-- Order -->
163
167
  <div class="flex flex-col gap-2">
164
- <label for="serial" class="font-medium">Display Order</label>
168
+ <label for="serial" class="font-medium">{{ 'shared.display.order' | translate }}</label>
165
169
  <input
166
170
  pInputText
167
171
  id="serial"
168
172
  type="number"
169
173
  [formField]="roleForm.serial"
170
- placeholder="Enter display order" />
174
+ [placeholder]="'shared.display.order.placeholder' | translate" />
171
175
  </div>
172
176
 
173
177
  <!-- Is Active -->
@@ -176,68 +180,67 @@ class RoleFormPageComponent {
176
180
  [formField]="roleForm.isActive"
177
181
  [binary]="true"
178
182
  inputId="isActive" />
179
- <label for="isActive">Active</label>
183
+ <label for="isActive">{{ 'shared.active' | translate }}</label>
180
184
  </div>
181
185
 
182
186
  <!-- Actions -->
183
187
  <div class="flex justify-end gap-2 md:col-span-2 pt-4">
184
188
  <p-button
185
- label="Cancel"
189
+ [label]="'shared.cancel' | translate"
186
190
  severity="secondary"
187
191
  [outlined]="true"
188
192
  (onClick)="onBack()" />
189
193
  <p-button
190
- [label]="isEditMode() ? 'Update' : 'Create'"
194
+ [label]="isEditMode() ? ('shared.update' | translate) : ('shared.create' | translate)"
191
195
  type="submit"
192
196
  [loading]="isLoading()"
193
197
  [disabled]="!isFormValid() || isLoading()" />
194
198
  </div>
195
199
  </form>
196
200
  </div>
197
- `, 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: "component", type: i3.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "directive", type: i4.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
201
+ `, 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: "component", type: i3.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "directive", type: i4.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
198
202
  }
199
203
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: RoleFormPageComponent, decorators: [{
200
204
  type: Component,
201
205
  args: [{
202
206
  selector: 'lib-role-form-page',
203
- imports: [AngularModule, PrimeModule, FormField],
204
- changeDetection: ChangeDetectionStrategy.OnPush,
207
+ imports: [AngularModule, PrimeModule, FormField, TranslatePipe],
205
208
  template: `
206
209
  <div class="card">
207
210
  <h3 class="text-lg sm:text-xl font-semibold mb-4">
208
- {{ isEditMode() ? 'Edit Role' : 'New Role' }}
211
+ {{ isEditMode() ? ('iam.role.edit' | translate) : ('iam.role.new' | translate) }}
209
212
  </h3>
210
213
 
211
214
  <form (ngSubmit)="onSubmit()" class="grid grid-cols-1 md:grid-cols-2 gap-4">
212
215
  <!-- Name -->
213
216
  <div class="flex flex-col gap-2">
214
- <label for="name" class="font-medium">Name *</label>
217
+ <label for="name" class="font-medium">{{ 'iam.role.name' | translate }} *</label>
215
218
  <input
216
219
  pInputText
217
220
  id="name"
218
221
  [formField]="roleForm.name"
219
- placeholder="Enter role name" />
222
+ [placeholder]="'iam.role.name.placeholder' | translate" />
220
223
  </div>
221
224
 
222
225
  <!-- Description -->
223
226
  <div class="flex flex-col gap-2">
224
- <label for="description" class="font-medium">Description</label>
227
+ <label for="description" class="font-medium">{{ 'shared.description' | translate }}</label>
225
228
  <input
226
229
  pInputText
227
230
  id="description"
228
231
  [formField]="roleForm.description"
229
- placeholder="Enter description" />
232
+ [placeholder]="'shared.description.placeholder' | translate" />
230
233
  </div>
231
234
 
232
235
  <!-- Order -->
233
236
  <div class="flex flex-col gap-2">
234
- <label for="serial" class="font-medium">Display Order</label>
237
+ <label for="serial" class="font-medium">{{ 'shared.display.order' | translate }}</label>
235
238
  <input
236
239
  pInputText
237
240
  id="serial"
238
241
  type="number"
239
242
  [formField]="roleForm.serial"
240
- placeholder="Enter display order" />
243
+ [placeholder]="'shared.display.order.placeholder' | translate" />
241
244
  </div>
242
245
 
243
246
  <!-- Is Active -->
@@ -246,18 +249,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
246
249
  [formField]="roleForm.isActive"
247
250
  [binary]="true"
248
251
  inputId="isActive" />
249
- <label for="isActive">Active</label>
252
+ <label for="isActive">{{ 'shared.active' | translate }}</label>
250
253
  </div>
251
254
 
252
255
  <!-- Actions -->
253
256
  <div class="flex justify-end gap-2 md:col-span-2 pt-4">
254
257
  <p-button
255
- label="Cancel"
258
+ [label]="'shared.cancel' | translate"
256
259
  severity="secondary"
257
260
  [outlined]="true"
258
261
  (onClick)="onBack()" />
259
262
  <p-button
260
- [label]="isEditMode() ? 'Update' : 'Create'"
263
+ [label]="isEditMode() ? ('shared.update' | translate) : ('shared.create' | translate)"
261
264
  type="submit"
262
265
  [loading]="isLoading()"
263
266
  [disabled]="!isFormValid() || isLoading()" />
@@ -269,4 +272,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
269
272
  }], ctorParameters: () => [] });
270
273
 
271
274
  export { RoleFormPageComponent };
272
- //# sourceMappingURL=flusys-ng-iam-role-form-page.component-D_AAEay2.mjs.map
275
+ //# sourceMappingURL=flusys-ng-iam-role-form-page.component-CVfRQpoa.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-iam-role-form-page.component-CVfRQpoa.mjs","sources":["../../../projects/ng-iam/pages/role/role-form-page.component.ts"],"sourcesContent":["import { Component, computed, effect, inject, signal } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { form, FormField, required } from '@angular/forms/signals';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { APP_CONFIG, isCompanyFeatureEnabled, TRANSLATE_ADAPTER } from '@flusys/ng-core';\nimport { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';\nimport { AngularModule, PrimeModule, TranslatePipe } 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\ninterface IRoleFormModel {\n id: string;\n name: string;\n description: string;\n serial: string;\n isActive: boolean;\n}\n\n@Component({\n selector: 'lib-role-form-page',\n imports: [AngularModule, PrimeModule, FormField, TranslatePipe],\n template: `\n <div class=\"card\">\n <h3 class=\"text-lg sm:text-xl font-semibold mb-4\">\n {{ isEditMode() ? ('iam.role.edit' | translate) : ('iam.role.new' | translate) }}\n </h3>\n\n <form (ngSubmit)=\"onSubmit()\" class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Name -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"name\" class=\"font-medium\">{{ 'iam.role.name' | translate }} *</label>\n <input\n pInputText\n id=\"name\"\n [formField]=\"roleForm.name\"\n [placeholder]=\"'iam.role.name.placeholder' | translate\" />\n </div>\n\n <!-- Description -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"description\" class=\"font-medium\">{{ 'shared.description' | translate }}</label>\n <input\n pInputText\n id=\"description\"\n [formField]=\"roleForm.description\"\n [placeholder]=\"'shared.description.placeholder' | translate\" />\n </div>\n\n <!-- Order -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"serial\" class=\"font-medium\">{{ 'shared.display.order' | translate }}</label>\n <input\n pInputText\n id=\"serial\"\n type=\"number\"\n [formField]=\"roleForm.serial\"\n [placeholder]=\"'shared.display.order.placeholder' | translate\" />\n </div>\n\n <!-- Is Active -->\n <div class=\"flex items-end gap-2 pb-1\">\n <p-checkbox\n [formField]=\"roleForm.isActive\"\n [binary]=\"true\"\n inputId=\"isActive\" />\n <label for=\"isActive\">{{ 'shared.active' | translate }}</label>\n </div>\n\n <!-- Actions -->\n <div class=\"flex justify-end gap-2 md:col-span-2 pt-4\">\n <p-button\n [label]=\"'shared.cancel' | translate\"\n severity=\"secondary\"\n [outlined]=\"true\"\n (onClick)=\"onBack()\" />\n <p-button\n [label]=\"isEditMode() ? ('shared.update' | translate) : ('shared.create' | translate)\"\n type=\"submit\"\n [loading]=\"isLoading()\"\n [disabled]=\"!isFormValid() || isLoading()\" />\n </div>\n </form>\n </div>\n `,\n})\nexport class RoleFormPageComponent {\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 private readonly translateAdapter = inject(TRANSLATE_ADAPTER, { optional: true });\n\n private readonly routeParams = toSignal(this.route.paramMap);\n private initialized = false;\n\n private translate(key: string, vars?: Record<string, string | number>): string {\n return this.translateAdapter?.translate(key, vars) ?? key;\n }\n\n readonly isLoading = signal(false);\n readonly existingRole = signal<IRole | null>(null);\n readonly isEditMode = computed(() => !!this.existingRole());\n\n readonly formModel = signal<IRoleFormModel>({\n id: '',\n name: '',\n description: '',\n serial: '',\n isActive: true,\n });\n\n readonly roleForm = form(this.formModel, (f) => {\n required(f.name, { message: this.translate('shared.validation.required', { field: this.translate('iam.role.name') }) });\n });\n\n readonly isFormValid = computed(() => {\n const model = this.formModel();\n return model.name.trim().length > 0;\n });\n\n constructor() {\n effect(() => {\n const params = this.routeParams();\n if (!params || this.initialized) return;\n\n this.initialized = true;\n const id = params.get('id');\n if (id && id !== 'new') {\n this.loadRole(id);\n }\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 // Error toast handled by global interceptor\n this.router.navigate(['/iam/roles']);\n }\n } catch {\n // Error toast handled by global interceptor\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: this.translate('shared.validation.error'),\n detail: this.translate('shared.fill.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: this.translate('shared.success'),\n detail: this.translate('iam.role.update.success'),\n });\n } else {\n await this.roleApi.insertAsync(dto);\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: this.translate('iam.role.create.success'),\n });\n }\n\n this.router.navigate(['/iam/roles']);\n } catch {\n // Error toast handled by global interceptor\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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"}