@flusys/ng-iam 1.0.0-rc → 1.1.1-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.
Files changed (28) hide show
  1. package/README.md +24 -175
  2. package/fesm2022/{flusys-ng-iam-action-form-page.component-C_BRrrWW.mjs → flusys-ng-iam-action-form-page.component-C1j10Qhw.mjs} +202 -174
  3. package/fesm2022/flusys-ng-iam-action-form-page.component-C1j10Qhw.mjs.map +1 -0
  4. package/fesm2022/flusys-ng-iam-action-list-page.component-BCzSardO.mjs +281 -0
  5. package/fesm2022/flusys-ng-iam-action-list-page.component-BCzSardO.mjs.map +1 -0
  6. package/fesm2022/{flusys-ng-iam-flusys-ng-iam-BPIpfrjN.mjs → flusys-ng-iam-flusys-ng-iam-DISrddPh.mjs} +829 -822
  7. package/fesm2022/flusys-ng-iam-flusys-ng-iam-DISrddPh.mjs.map +1 -0
  8. package/fesm2022/flusys-ng-iam-iam-container.component-BkhqmzLi.mjs +97 -0
  9. package/fesm2022/flusys-ng-iam-iam-container.component-BkhqmzLi.mjs.map +1 -0
  10. package/fesm2022/{flusys-ng-iam-permission-page.component-CmxOBJPu.mjs → flusys-ng-iam-permission-page.component-BSQFPt_N.mjs} +12 -41
  11. package/fesm2022/flusys-ng-iam-permission-page.component-BSQFPt_N.mjs.map +1 -0
  12. package/fesm2022/{flusys-ng-iam-role-form-page.component-ByNueI1a.mjs → flusys-ng-iam-role-form-page.component-Cqziu_BM.mjs} +134 -106
  13. package/fesm2022/flusys-ng-iam-role-form-page.component-Cqziu_BM.mjs.map +1 -0
  14. package/fesm2022/flusys-ng-iam-role-list-page.component-BObCxHiB.mjs +266 -0
  15. package/fesm2022/flusys-ng-iam-role-list-page.component-BObCxHiB.mjs.map +1 -0
  16. package/fesm2022/flusys-ng-iam.mjs +1 -1
  17. package/package.json +2 -2
  18. package/types/flusys-ng-iam.d.ts +21 -40
  19. package/fesm2022/flusys-ng-iam-action-form-page.component-C_BRrrWW.mjs.map +0 -1
  20. package/fesm2022/flusys-ng-iam-action-list-page.component-Daf93zpS.mjs +0 -289
  21. package/fesm2022/flusys-ng-iam-action-list-page.component-Daf93zpS.mjs.map +0 -1
  22. package/fesm2022/flusys-ng-iam-flusys-ng-iam-BPIpfrjN.mjs.map +0 -1
  23. package/fesm2022/flusys-ng-iam-iam-container.component-Bn4kQtxW.mjs +0 -92
  24. package/fesm2022/flusys-ng-iam-iam-container.component-Bn4kQtxW.mjs.map +0 -1
  25. package/fesm2022/flusys-ng-iam-permission-page.component-CmxOBJPu.mjs.map +0 -1
  26. package/fesm2022/flusys-ng-iam-role-form-page.component-ByNueI1a.mjs.map +0 -1
  27. package/fesm2022/flusys-ng-iam-role-list-page.component-CFly5KnH.mjs +0 -316
  28. package/fesm2022/flusys-ng-iam-role-list-page.component-CFly5KnH.mjs.map +0 -1
@@ -1,16 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, signal, computed, effect, ChangeDetectionStrategy, Component } from '@angular/core';
3
- import { toSignal } from '@angular/core/rxjs-interop';
2
+ import { inject, signal, computed, ChangeDetectionStrategy, Component } from '@angular/core';
4
3
  import { form, required, FormField } from '@angular/forms/signals';
5
4
  import { ActivatedRoute, Router } from '@angular/router';
6
5
  import { AngularModule, PrimeModule } from '@flusys/ng-shared';
7
6
  import { MessageService } from 'primeng/api';
8
7
  import { firstValueFrom } from 'rxjs';
9
- import { A as ActionApiService, a as ActionType, L as LogicBuilderComponent } from './flusys-ng-iam-flusys-ng-iam-BPIpfrjN.mjs';
8
+ import { A as ActionApiService, a as ActionType, L as LogicBuilderComponent } from './flusys-ng-iam-flusys-ng-iam-DISrddPh.mjs';
10
9
  import * as i1 from '@angular/forms';
11
10
  import * as i2 from 'primeng/button';
12
- import * as i3 from 'primeng/checkbox';
13
- import * as i4 from 'primeng/inputtext';
11
+ import * as i3 from 'primeng/inputtext';
14
12
 
15
13
  /**
16
14
  * Action Form Page Component
@@ -21,8 +19,6 @@ class ActionFormPageComponent {
21
19
  router = inject(Router);
22
20
  actionApi = inject(ActionApiService);
23
21
  messageService = inject(MessageService);
24
- routeParams = toSignal(this.route.paramMap);
25
- initialized = false;
26
22
  /** Loading state */
27
23
  isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
28
24
  /** Existing action data when editing */
@@ -70,16 +66,8 @@ class ActionFormPageComponent {
70
66
  const model = this.formModel();
71
67
  return model.name.trim().length > 0;
72
68
  }, ...(ngDevMode ? [{ debugName: "isFormValid" }] : []));
73
- constructor() {
74
- effect(() => {
75
- const params = this.routeParams();
76
- if (!params || this.initialized)
77
- return;
78
- this.initialized = true;
79
- this.initializeForm(params.get('id'));
80
- });
81
- }
82
- async initializeForm(id) {
69
+ async ngOnInit() {
70
+ const id = this.route.snapshot.paramMap.get('id');
83
71
  // Load ALL actions FIRST - critical for LogicBuilder to display action names
84
72
  try {
85
73
  const response = await firstValueFrom(this.actionApi.getAll('', {
@@ -136,12 +124,20 @@ class ActionFormPageComponent {
136
124
  });
137
125
  }
138
126
  else {
139
- // Error toast handled by global interceptor
127
+ this.messageService.add({
128
+ severity: 'error',
129
+ summary: 'Error',
130
+ detail: 'Action not found.',
131
+ });
140
132
  this.router.navigate(['/iam/actions']);
141
133
  }
142
134
  }
143
135
  catch {
144
- // Error toast handled by global interceptor
136
+ this.messageService.add({
137
+ severity: 'error',
138
+ summary: 'Error',
139
+ detail: 'Failed to load action.',
140
+ });
145
141
  this.router.navigate(['/iam/actions']);
146
142
  }
147
143
  finally {
@@ -188,8 +184,12 @@ class ActionFormPageComponent {
188
184
  }
189
185
  this.router.navigate(['/iam/actions']);
190
186
  }
191
- catch {
192
- // Error toast handled by global interceptor
187
+ catch (error) {
188
+ this.messageService.add({
189
+ severity: 'error',
190
+ summary: 'Error',
191
+ detail: error.message || 'Failed to save action.',
192
+ });
193
193
  }
194
194
  finally {
195
195
  this.isLoading.set(false);
@@ -210,90 +210,104 @@ class ActionFormPageComponent {
210
210
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ActionFormPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
211
211
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: ActionFormPageComponent, isStandalone: true, selector: "lib-action-form-page", ngImport: i0, template: `
212
212
  <div class="card">
213
- <h3 class="text-lg sm:text-xl font-semibold mb-4">
214
- {{ isEditMode() ? 'Edit Action' : 'New Action' }}
215
- </h3>
213
+ <div class="flex justify-between items-center mb-4">
214
+ <h3 class="text-xl font-semibold">
215
+ {{ isEditMode() ? 'Edit Action' : 'New Action' }}
216
+ </h3>
217
+ <p-button
218
+ label="Back"
219
+ icon="pi pi-arrow-left"
220
+ [outlined]="true"
221
+ (onClick)="onBack()" />
222
+ </div>
216
223
 
217
- <form (ngSubmit)="onSubmit()" class="grid grid-cols-1 md:grid-cols-2 gap-4">
218
- <!-- Name -->
219
- <div class="flex flex-col gap-2">
220
- <label for="name" class="font-medium">Name *</label>
221
- <input
222
- pInputText
223
- id="name"
224
- [formField]="actionForm.name"
225
- placeholder="Enter action name" />
226
- </div>
224
+ <form (ngSubmit)="onSubmit()">
225
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
226
+ <!-- Name -->
227
+ <div>
228
+ <label for="name" class="block font-medium mb-2">Name *</label>
229
+ <input
230
+ pInputText
231
+ id="name"
232
+ [formField]="actionForm.name"
233
+ class="w-full"
234
+ placeholder="Enter action name" />
235
+ </div>
227
236
 
228
- <!-- Code -->
229
- <div class="flex flex-col gap-2">
230
- <label for="code" class="font-medium">Code</label>
231
- <input
232
- pInputText
233
- id="code"
234
- [formField]="actionForm.code"
235
- placeholder="Enter action code" />
236
- </div>
237
+ <!-- Code -->
238
+ <div>
239
+ <label for="code" class="block font-medium mb-2">Code</label>
240
+ <input
241
+ pInputText
242
+ id="code"
243
+ [formField]="actionForm.code"
244
+ class="w-full"
245
+ placeholder="Enter action code" />
246
+ </div>
237
247
 
238
- <!-- Description -->
239
- <div class="flex flex-col gap-2">
240
- <label for="description" class="font-medium">Description</label>
241
- <input
242
- pInputText
243
- id="description"
244
- [formField]="actionForm.description"
245
- placeholder="Enter description" />
246
- </div>
248
+ <!-- Description -->
249
+ <div class="md:col-span-2">
250
+ <label for="description" class="block font-medium mb-2">Description</label>
251
+ <input
252
+ pInputText
253
+ id="description"
254
+ [formField]="actionForm.description"
255
+ class="w-full"
256
+ placeholder="Enter description" />
257
+ </div>
247
258
 
248
- <!-- Action Type -->
249
- <div class="flex flex-col gap-2">
250
- <label for="actionType" class="font-medium">Action Type *</label>
251
- <select
252
- id="actionType"
253
- class="p-inputtext w-full"
254
- [formField]="actionForm.actionType">
255
- @for (type of actionTypes; track type.value) {
256
- <option [value]="type.value">{{ type.label }}</option>
257
- }
258
- </select>
259
- </div>
259
+ <!-- Action Type -->
260
+ <div>
261
+ <label for="actionType" class="block font-medium mb-2">Action Type *</label>
262
+ <select
263
+ id="actionType"
264
+ class="p-select-native"
265
+ [formField]="actionForm.actionType">
266
+ @for (type of actionTypes; track type.value) {
267
+ <option [value]="type.value">{{ type.label }}</option>
268
+ }
269
+ </select>
270
+ </div>
260
271
 
261
- <!-- Parent Action -->
262
- <div class="flex flex-col gap-2">
263
- <label for="parentId" class="font-medium">Parent Action</label>
264
- <select
265
- id="parentId"
266
- class="p-inputtext w-full"
267
- [formField]="actionForm.parentId">
268
- <option value="">Select parent action</option>
269
- @for (action of availableActions(); track action.id) {
270
- <option [value]="action.id">{{ action.name }}</option>
271
- }
272
- </select>
273
- </div>
272
+ <!-- Parent Action -->
273
+ <div>
274
+ <label for="parentId" class="block font-medium mb-2">Parent Action</label>
275
+ <select
276
+ id="parentId"
277
+ class="p-select-native"
278
+ [formField]="actionForm.parentId">
279
+ <option value="">Select parent action</option>
280
+ @for (action of availableActions(); track action.id) {
281
+ <option [value]="action.id">{{ action.name }}</option>
282
+ }
283
+ </select>
284
+ </div>
274
285
 
275
- <!-- Order -->
276
- <div class="flex flex-col gap-2">
277
- <label for="serial" class="font-medium">Display Order</label>
278
- <input
279
- pInputText
280
- id="serial"
281
- type="number"
282
- [formField]="actionForm.serial"
283
- placeholder="Enter display order" />
284
- </div>
286
+ <!-- Order -->
287
+ <div>
288
+ <label for="serial" class="block font-medium mb-2">Display Order</label>
289
+ <input
290
+ pInputText
291
+ id="serial"
292
+ type="number"
293
+ [formField]="actionForm.serial"
294
+ class="w-full"
295
+ placeholder="Enter display order" />
296
+ </div>
285
297
 
286
- <!-- Is Active -->
287
- <div class="flex items-end gap-2 pb-1 md:col-span-2">
288
- <p-checkbox
289
- [formField]="actionForm.isActive"
290
- [binary]="true"
291
- inputId="isActive" />
292
- <label for="isActive">Active</label>
298
+ <!-- Is Active -->
299
+ <div class="flex items-center pt-6">
300
+ <label class="p-checkbox-native">
301
+ <input
302
+ type="checkbox"
303
+ [formField]="actionForm.isActive" />
304
+ <span>Active</span>
305
+ </label>
306
+ </div>
293
307
  </div>
294
308
 
295
309
  <!-- Permission Logic Builder -->
296
- <div class="md:col-span-2">
310
+ <div class="mt-6">
297
311
  <lib-logic-builder
298
312
  [logic]="formModel().permissionLogic"
299
313
  [actions]="allActionsForLogic()"
@@ -301,7 +315,7 @@ class ActionFormPageComponent {
301
315
  </div>
302
316
 
303
317
  <!-- Actions -->
304
- <div class="flex justify-end gap-2 md:col-span-2 pt-4">
318
+ <div class="flex justify-end gap-2 mt-6">
305
319
  <p-button
306
320
  label="Cancel"
307
321
  severity="secondary"
@@ -315,7 +329,7 @@ class ActionFormPageComponent {
315
329
  </div>
316
330
  </form>
317
331
  </div>
318
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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: "component", type: LogicBuilderComponent, selector: "lib-logic-builder", inputs: ["logic", "actions"], outputs: ["logicChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
332
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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"] }, { kind: "component", type: LogicBuilderComponent, selector: "lib-logic-builder", inputs: ["logic", "actions"], outputs: ["logicChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
319
333
  }
320
334
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ActionFormPageComponent, decorators: [{
321
335
  type: Component,
@@ -326,90 +340,104 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
326
340
  changeDetection: ChangeDetectionStrategy.OnPush,
327
341
  template: `
328
342
  <div class="card">
329
- <h3 class="text-lg sm:text-xl font-semibold mb-4">
330
- {{ isEditMode() ? 'Edit Action' : 'New Action' }}
331
- </h3>
343
+ <div class="flex justify-between items-center mb-4">
344
+ <h3 class="text-xl font-semibold">
345
+ {{ isEditMode() ? 'Edit Action' : 'New Action' }}
346
+ </h3>
347
+ <p-button
348
+ label="Back"
349
+ icon="pi pi-arrow-left"
350
+ [outlined]="true"
351
+ (onClick)="onBack()" />
352
+ </div>
332
353
 
333
- <form (ngSubmit)="onSubmit()" class="grid grid-cols-1 md:grid-cols-2 gap-4">
334
- <!-- Name -->
335
- <div class="flex flex-col gap-2">
336
- <label for="name" class="font-medium">Name *</label>
337
- <input
338
- pInputText
339
- id="name"
340
- [formField]="actionForm.name"
341
- placeholder="Enter action name" />
342
- </div>
354
+ <form (ngSubmit)="onSubmit()">
355
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
356
+ <!-- Name -->
357
+ <div>
358
+ <label for="name" class="block font-medium mb-2">Name *</label>
359
+ <input
360
+ pInputText
361
+ id="name"
362
+ [formField]="actionForm.name"
363
+ class="w-full"
364
+ placeholder="Enter action name" />
365
+ </div>
343
366
 
344
- <!-- Code -->
345
- <div class="flex flex-col gap-2">
346
- <label for="code" class="font-medium">Code</label>
347
- <input
348
- pInputText
349
- id="code"
350
- [formField]="actionForm.code"
351
- placeholder="Enter action code" />
352
- </div>
367
+ <!-- Code -->
368
+ <div>
369
+ <label for="code" class="block font-medium mb-2">Code</label>
370
+ <input
371
+ pInputText
372
+ id="code"
373
+ [formField]="actionForm.code"
374
+ class="w-full"
375
+ placeholder="Enter action code" />
376
+ </div>
353
377
 
354
- <!-- Description -->
355
- <div class="flex flex-col gap-2">
356
- <label for="description" class="font-medium">Description</label>
357
- <input
358
- pInputText
359
- id="description"
360
- [formField]="actionForm.description"
361
- placeholder="Enter description" />
362
- </div>
378
+ <!-- Description -->
379
+ <div class="md:col-span-2">
380
+ <label for="description" class="block font-medium mb-2">Description</label>
381
+ <input
382
+ pInputText
383
+ id="description"
384
+ [formField]="actionForm.description"
385
+ class="w-full"
386
+ placeholder="Enter description" />
387
+ </div>
363
388
 
364
- <!-- Action Type -->
365
- <div class="flex flex-col gap-2">
366
- <label for="actionType" class="font-medium">Action Type *</label>
367
- <select
368
- id="actionType"
369
- class="p-inputtext w-full"
370
- [formField]="actionForm.actionType">
371
- @for (type of actionTypes; track type.value) {
372
- <option [value]="type.value">{{ type.label }}</option>
373
- }
374
- </select>
375
- </div>
389
+ <!-- Action Type -->
390
+ <div>
391
+ <label for="actionType" class="block font-medium mb-2">Action Type *</label>
392
+ <select
393
+ id="actionType"
394
+ class="p-select-native"
395
+ [formField]="actionForm.actionType">
396
+ @for (type of actionTypes; track type.value) {
397
+ <option [value]="type.value">{{ type.label }}</option>
398
+ }
399
+ </select>
400
+ </div>
376
401
 
377
- <!-- Parent Action -->
378
- <div class="flex flex-col gap-2">
379
- <label for="parentId" class="font-medium">Parent Action</label>
380
- <select
381
- id="parentId"
382
- class="p-inputtext w-full"
383
- [formField]="actionForm.parentId">
384
- <option value="">Select parent action</option>
385
- @for (action of availableActions(); track action.id) {
386
- <option [value]="action.id">{{ action.name }}</option>
387
- }
388
- </select>
389
- </div>
402
+ <!-- Parent Action -->
403
+ <div>
404
+ <label for="parentId" class="block font-medium mb-2">Parent Action</label>
405
+ <select
406
+ id="parentId"
407
+ class="p-select-native"
408
+ [formField]="actionForm.parentId">
409
+ <option value="">Select parent action</option>
410
+ @for (action of availableActions(); track action.id) {
411
+ <option [value]="action.id">{{ action.name }}</option>
412
+ }
413
+ </select>
414
+ </div>
390
415
 
391
- <!-- Order -->
392
- <div class="flex flex-col gap-2">
393
- <label for="serial" class="font-medium">Display Order</label>
394
- <input
395
- pInputText
396
- id="serial"
397
- type="number"
398
- [formField]="actionForm.serial"
399
- placeholder="Enter display order" />
400
- </div>
416
+ <!-- Order -->
417
+ <div>
418
+ <label for="serial" class="block font-medium mb-2">Display Order</label>
419
+ <input
420
+ pInputText
421
+ id="serial"
422
+ type="number"
423
+ [formField]="actionForm.serial"
424
+ class="w-full"
425
+ placeholder="Enter display order" />
426
+ </div>
401
427
 
402
- <!-- Is Active -->
403
- <div class="flex items-end gap-2 pb-1 md:col-span-2">
404
- <p-checkbox
405
- [formField]="actionForm.isActive"
406
- [binary]="true"
407
- inputId="isActive" />
408
- <label for="isActive">Active</label>
428
+ <!-- Is Active -->
429
+ <div class="flex items-center pt-6">
430
+ <label class="p-checkbox-native">
431
+ <input
432
+ type="checkbox"
433
+ [formField]="actionForm.isActive" />
434
+ <span>Active</span>
435
+ </label>
436
+ </div>
409
437
  </div>
410
438
 
411
439
  <!-- Permission Logic Builder -->
412
- <div class="md:col-span-2">
440
+ <div class="mt-6">
413
441
  <lib-logic-builder
414
442
  [logic]="formModel().permissionLogic"
415
443
  [actions]="allActionsForLogic()"
@@ -417,7 +445,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
417
445
  </div>
418
446
 
419
447
  <!-- Actions -->
420
- <div class="flex justify-end gap-2 md:col-span-2 pt-4">
448
+ <div class="flex justify-end gap-2 mt-6">
421
449
  <p-button
422
450
  label="Cancel"
423
451
  severity="secondary"
@@ -433,7 +461,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
433
461
  </div>
434
462
  `,
435
463
  }]
436
- }], ctorParameters: () => [] });
464
+ }] });
437
465
 
438
466
  export { ActionFormPageComponent };
439
- //# sourceMappingURL=flusys-ng-iam-action-form-page.component-C_BRrrWW.mjs.map
467
+ //# sourceMappingURL=flusys-ng-iam-action-form-page.component-C1j10Qhw.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-iam-action-form-page.component-C1j10Qhw.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 {\n // Actions load failed - form will show empty parent dropdown\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 {\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":"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"}