@flusys/ng-iam 1.0.0-beta → 1.0.0-rc

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 +225 -24
  2. package/fesm2022/{flusys-ng-iam-action-form-page.component-0b9GwJqa.mjs → flusys-ng-iam-action-form-page.component-C_BRrrWW.mjs} +175 -203
  3. package/fesm2022/flusys-ng-iam-action-form-page.component-C_BRrrWW.mjs.map +1 -0
  4. package/fesm2022/flusys-ng-iam-action-list-page.component-Daf93zpS.mjs +289 -0
  5. package/fesm2022/flusys-ng-iam-action-list-page.component-Daf93zpS.mjs.map +1 -0
  6. package/fesm2022/{flusys-ng-iam-flusys-ng-iam-C-MQjakK.mjs → flusys-ng-iam-flusys-ng-iam-BPIpfrjN.mjs} +892 -818
  7. package/fesm2022/flusys-ng-iam-flusys-ng-iam-BPIpfrjN.mjs.map +1 -0
  8. package/fesm2022/flusys-ng-iam-iam-container.component-Bn4kQtxW.mjs +92 -0
  9. package/fesm2022/flusys-ng-iam-iam-container.component-Bn4kQtxW.mjs.map +1 -0
  10. package/fesm2022/{flusys-ng-iam-permission-page.component-e_RX5mky.mjs → flusys-ng-iam-permission-page.component-CmxOBJPu.mjs} +42 -13
  11. package/fesm2022/flusys-ng-iam-permission-page.component-CmxOBJPu.mjs.map +1 -0
  12. package/fesm2022/{flusys-ng-iam-role-form-page.component-eZM1EPps.mjs → flusys-ng-iam-role-form-page.component-ByNueI1a.mjs} +107 -135
  13. package/fesm2022/flusys-ng-iam-role-form-page.component-ByNueI1a.mjs.map +1 -0
  14. package/fesm2022/flusys-ng-iam-role-list-page.component-CFly5KnH.mjs +316 -0
  15. package/fesm2022/flusys-ng-iam-role-list-page.component-CFly5KnH.mjs.map +1 -0
  16. package/fesm2022/flusys-ng-iam.mjs +1 -1
  17. package/package.json +5 -5
  18. package/types/flusys-ng-iam.d.ts +87 -23
  19. package/fesm2022/flusys-ng-iam-action-form-page.component-0b9GwJqa.mjs.map +0 -1
  20. package/fesm2022/flusys-ng-iam-action-list-page.component-BpvewEGL.mjs +0 -281
  21. package/fesm2022/flusys-ng-iam-action-list-page.component-BpvewEGL.mjs.map +0 -1
  22. package/fesm2022/flusys-ng-iam-flusys-ng-iam-C-MQjakK.mjs.map +0 -1
  23. package/fesm2022/flusys-ng-iam-iam-container.component-Chl5MDkV.mjs +0 -97
  24. package/fesm2022/flusys-ng-iam-iam-container.component-Chl5MDkV.mjs.map +0 -1
  25. package/fesm2022/flusys-ng-iam-permission-page.component-e_RX5mky.mjs.map +0 -1
  26. package/fesm2022/flusys-ng-iam-role-form-page.component-eZM1EPps.mjs.map +0 -1
  27. package/fesm2022/flusys-ng-iam-role-list-page.component-BgzxmHjk.mjs +0 -266
  28. package/fesm2022/flusys-ng-iam-role-list-page.component-BgzxmHjk.mjs.map +0 -1
@@ -1,14 +1,16 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, signal, computed, ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { inject, signal, computed, effect, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { toSignal } from '@angular/core/rxjs-interop';
3
4
  import { form, required, FormField } from '@angular/forms/signals';
4
5
  import { ActivatedRoute, Router } from '@angular/router';
5
6
  import { AngularModule, PrimeModule } from '@flusys/ng-shared';
6
7
  import { MessageService } from 'primeng/api';
7
8
  import { firstValueFrom } from 'rxjs';
8
- import { A as ActionApiService, a as ActionType, L as LogicBuilderComponent } from './flusys-ng-iam-flusys-ng-iam-C-MQjakK.mjs';
9
+ import { A as ActionApiService, a as ActionType, L as LogicBuilderComponent } from './flusys-ng-iam-flusys-ng-iam-BPIpfrjN.mjs';
9
10
  import * as i1 from '@angular/forms';
10
- import * as i2 from 'primeng/inputtext';
11
- import * as i3 from 'primeng/button';
11
+ import * as i2 from 'primeng/button';
12
+ import * as i3 from 'primeng/checkbox';
13
+ import * as i4 from 'primeng/inputtext';
12
14
 
13
15
  /**
14
16
  * Action Form Page Component
@@ -19,6 +21,8 @@ class ActionFormPageComponent {
19
21
  router = inject(Router);
20
22
  actionApi = inject(ActionApiService);
21
23
  messageService = inject(MessageService);
24
+ routeParams = toSignal(this.route.paramMap);
25
+ initialized = false;
22
26
  /** Loading state */
23
27
  isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
24
28
  /** Existing action data when editing */
@@ -66,8 +70,16 @@ class ActionFormPageComponent {
66
70
  const model = this.formModel();
67
71
  return model.name.trim().length > 0;
68
72
  }, ...(ngDevMode ? [{ debugName: "isFormValid" }] : []));
69
- async ngOnInit() {
70
- const id = this.route.snapshot.paramMap.get('id');
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) {
71
83
  // Load ALL actions FIRST - critical for LogicBuilder to display action names
72
84
  try {
73
85
  const response = await firstValueFrom(this.actionApi.getAll('', {
@@ -124,20 +136,12 @@ class ActionFormPageComponent {
124
136
  });
125
137
  }
126
138
  else {
127
- this.messageService.add({
128
- severity: 'error',
129
- summary: 'Error',
130
- detail: 'Action not found.',
131
- });
139
+ // Error toast handled by global interceptor
132
140
  this.router.navigate(['/iam/actions']);
133
141
  }
134
142
  }
135
143
  catch {
136
- this.messageService.add({
137
- severity: 'error',
138
- summary: 'Error',
139
- detail: 'Failed to load action.',
140
- });
144
+ // Error toast handled by global interceptor
141
145
  this.router.navigate(['/iam/actions']);
142
146
  }
143
147
  finally {
@@ -184,12 +188,8 @@ class ActionFormPageComponent {
184
188
  }
185
189
  this.router.navigate(['/iam/actions']);
186
190
  }
187
- catch (error) {
188
- this.messageService.add({
189
- severity: 'error',
190
- summary: 'Error',
191
- detail: error.message || 'Failed to save action.',
192
- });
191
+ catch {
192
+ // Error toast handled by global interceptor
193
193
  }
194
194
  finally {
195
195
  this.isLoading.set(false);
@@ -210,104 +210,90 @@ 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
- <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>
213
+ <h3 class="text-lg sm:text-xl font-semibold mb-4">
214
+ {{ isEditMode() ? 'Edit Action' : 'New Action' }}
215
+ </h3>
223
216
 
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>
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>
236
227
 
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>
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>
247
237
 
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>
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>
258
247
 
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>
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>
271
260
 
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>
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>
285
274
 
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>
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>
297
285
 
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>
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>
307
293
  </div>
308
294
 
309
295
  <!-- Permission Logic Builder -->
310
- <div class="mt-6">
296
+ <div class="md:col-span-2">
311
297
  <lib-logic-builder
312
298
  [logic]="formModel().permissionLogic"
313
299
  [actions]="allActionsForLogic()"
@@ -315,7 +301,7 @@ class ActionFormPageComponent {
315
301
  </div>
316
302
 
317
303
  <!-- Actions -->
318
- <div class="flex justify-end gap-2 mt-6">
304
+ <div class="flex justify-end gap-2 md:col-span-2 pt-4">
319
305
  <p-button
320
306
  label="Cancel"
321
307
  severity="secondary"
@@ -329,7 +315,7 @@ class ActionFormPageComponent {
329
315
  </div>
330
316
  </form>
331
317
  </div>
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: "directive", type: i2.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i3.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: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "component", type: LogicBuilderComponent, selector: "lib-logic-builder", inputs: ["logic", "actions"], outputs: ["logicChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
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 });
333
319
  }
334
320
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ActionFormPageComponent, decorators: [{
335
321
  type: Component,
@@ -340,104 +326,90 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
340
326
  changeDetection: ChangeDetectionStrategy.OnPush,
341
327
  template: `
342
328
  <div class="card">
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>
329
+ <h3 class="text-lg sm:text-xl font-semibold mb-4">
330
+ {{ isEditMode() ? 'Edit Action' : 'New Action' }}
331
+ </h3>
353
332
 
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>
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>
366
343
 
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>
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>
377
353
 
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>
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>
388
363
 
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>
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>
401
376
 
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>
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>
415
390
 
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>
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>
427
401
 
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>
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>
437
409
  </div>
438
410
 
439
411
  <!-- Permission Logic Builder -->
440
- <div class="mt-6">
412
+ <div class="md:col-span-2">
441
413
  <lib-logic-builder
442
414
  [logic]="formModel().permissionLogic"
443
415
  [actions]="allActionsForLogic()"
@@ -445,7 +417,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
445
417
  </div>
446
418
 
447
419
  <!-- Actions -->
448
- <div class="flex justify-end gap-2 mt-6">
420
+ <div class="flex justify-end gap-2 md:col-span-2 pt-4">
449
421
  <p-button
450
422
  label="Cancel"
451
423
  severity="secondary"
@@ -461,7 +433,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
461
433
  </div>
462
434
  `,
463
435
  }]
464
- }] });
436
+ }], ctorParameters: () => [] });
465
437
 
466
438
  export { ActionFormPageComponent };
467
- //# sourceMappingURL=flusys-ng-iam-action-form-page.component-0b9GwJqa.mjs.map
439
+ //# sourceMappingURL=flusys-ng-iam-action-form-page.component-C_BRrrWW.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-iam-action-form-page.component-C_BRrrWW.mjs","sources":["../../../projects/ng-iam/pages/action/action-form-page.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, 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 { 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: ILogicNode | null;\n parentId: string;\n serial: string;\n isActive: boolean;\n metadata: Record<string, unknown> | 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 <h3 class=\"text-lg sm:text-xl font-semibold mb-4\">\n {{ isEditMode() ? 'Edit Action' : 'New Action' }}\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\">Name *</label>\n <input\n pInputText\n id=\"name\"\n [formField]=\"actionForm.name\"\n placeholder=\"Enter action name\" />\n </div>\n\n <!-- Code -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"code\" class=\"font-medium\">Code</label>\n <input\n pInputText\n id=\"code\"\n [formField]=\"actionForm.code\"\n placeholder=\"Enter action code\" />\n </div>\n\n <!-- Description -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"description\" class=\"font-medium\">Description</label>\n <input\n pInputText\n id=\"description\"\n [formField]=\"actionForm.description\"\n placeholder=\"Enter description\" />\n </div>\n\n <!-- Action Type -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"actionType\" class=\"font-medium\">Action Type *</label>\n <select\n id=\"actionType\"\n class=\"p-inputtext w-full\"\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 class=\"flex flex-col gap-2\">\n <label for=\"parentId\" class=\"font-medium\">Parent Action</label>\n <select\n id=\"parentId\"\n class=\"p-inputtext w-full\"\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 class=\"flex flex-col gap-2\">\n <label for=\"serial\" class=\"font-medium\">Display Order</label>\n <input\n pInputText\n id=\"serial\"\n type=\"number\"\n [formField]=\"actionForm.serial\"\n placeholder=\"Enter display order\" />\n </div>\n\n <!-- Is Active -->\n <div class=\"flex items-end gap-2 pb-1 md:col-span-2\">\n <p-checkbox\n [formField]=\"actionForm.isActive\"\n [binary]=\"true\"\n inputId=\"isActive\" />\n <label for=\"isActive\">Active</label>\n </div>\n\n <!-- Permission Logic Builder -->\n <div class=\"md:col-span-2\">\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 md:col-span-2 pt-4\">\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 {\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 private readonly routeParams = toSignal(this.route.paramMap);\n private initialized = false;\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 constructor() {\n effect(() => {\n const params = this.routeParams();\n if (!params || this.initialized) return;\n\n this.initialized = true;\n this.initializeForm(params.get('id'));\n });\n }\n\n private async initializeForm(id: string | null): Promise<void> {\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 // Error toast handled by global interceptor\n this.router.navigate(['/iam/actions']);\n }\n } catch {\n // Error toast handled by global interceptor\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 {\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/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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"}