@flusys/ng-iam 1.1.1-beta → 3.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 (30) hide show
  1. package/README.md +175 -24
  2. package/fesm2022/flusys-ng-iam-action-form-page.component-CVN8sV-c.mjs +389 -0
  3. package/fesm2022/flusys-ng-iam-action-form-page.component-CVN8sV-c.mjs.map +1 -0
  4. package/fesm2022/flusys-ng-iam-action-list-page.component-CQ6RazN0.mjs +262 -0
  5. package/fesm2022/flusys-ng-iam-action-list-page.component-CQ6RazN0.mjs.map +1 -0
  6. package/fesm2022/{flusys-ng-iam-flusys-ng-iam-DISrddPh.mjs → flusys-ng-iam-flusys-ng-iam-DrGHlTiz.mjs} +1016 -1585
  7. package/fesm2022/flusys-ng-iam-flusys-ng-iam-DrGHlTiz.mjs.map +1 -0
  8. package/fesm2022/flusys-ng-iam-iam-container.component-BToYxEej.mjs +92 -0
  9. package/fesm2022/flusys-ng-iam-iam-container.component-BToYxEej.mjs.map +1 -0
  10. package/fesm2022/flusys-ng-iam-permission-page.component-BS7xXmsn.mjs +137 -0
  11. package/fesm2022/flusys-ng-iam-permission-page.component-BS7xXmsn.mjs.map +1 -0
  12. package/fesm2022/{flusys-ng-iam-role-form-page.component-Cqziu_BM.mjs → flusys-ng-iam-role-form-page.component-BjPwXkip.mjs} +106 -148
  13. package/fesm2022/flusys-ng-iam-role-form-page.component-BjPwXkip.mjs.map +1 -0
  14. package/fesm2022/flusys-ng-iam-role-list-page.component-Cz-jk-R_.mjs +299 -0
  15. package/fesm2022/flusys-ng-iam-role-list-page.component-Cz-jk-R_.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 +75 -454
  19. package/fesm2022/flusys-ng-iam-action-form-page.component-C1j10Qhw.mjs +0 -467
  20. package/fesm2022/flusys-ng-iam-action-form-page.component-C1j10Qhw.mjs.map +0 -1
  21. package/fesm2022/flusys-ng-iam-action-list-page.component-BCzSardO.mjs +0 -281
  22. package/fesm2022/flusys-ng-iam-action-list-page.component-BCzSardO.mjs.map +0 -1
  23. package/fesm2022/flusys-ng-iam-flusys-ng-iam-DISrddPh.mjs.map +0 -1
  24. package/fesm2022/flusys-ng-iam-iam-container.component-BkhqmzLi.mjs +0 -97
  25. package/fesm2022/flusys-ng-iam-iam-container.component-BkhqmzLi.mjs.map +0 -1
  26. package/fesm2022/flusys-ng-iam-permission-page.component-BSQFPt_N.mjs +0 -143
  27. package/fesm2022/flusys-ng-iam-permission-page.component-BSQFPt_N.mjs.map +0 -1
  28. package/fesm2022/flusys-ng-iam-role-form-page.component-Cqziu_BM.mjs.map +0 -1
  29. package/fesm2022/flusys-ng-iam-role-list-page.component-BObCxHiB.mjs +0 -266
  30. package/fesm2022/flusys-ng-iam-role-list-page.component-BObCxHiB.mjs.map +0 -1
@@ -1,467 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { inject, signal, computed, ChangeDetectionStrategy, Component } from '@angular/core';
3
- import { form, required, FormField } from '@angular/forms/signals';
4
- import { ActivatedRoute, Router } from '@angular/router';
5
- import { AngularModule, PrimeModule } from '@flusys/ng-shared';
6
- import { MessageService } from 'primeng/api';
7
- import { firstValueFrom } from 'rxjs';
8
- import { A as ActionApiService, a as ActionType, L as LogicBuilderComponent } from './flusys-ng-iam-flusys-ng-iam-DISrddPh.mjs';
9
- import * as i1 from '@angular/forms';
10
- import * as i2 from 'primeng/button';
11
- import * as i3 from 'primeng/inputtext';
12
-
13
- /**
14
- * Action Form Page Component
15
- * Create/Edit action with signal-based form pattern (matches ng-auth)
16
- */
17
- class ActionFormPageComponent {
18
- route = inject(ActivatedRoute);
19
- router = inject(Router);
20
- actionApi = inject(ActionApiService);
21
- messageService = inject(MessageService);
22
- /** Loading state */
23
- isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
24
- /** Existing action data when editing */
25
- existingAction = signal(null, ...(ngDevMode ? [{ debugName: "existingAction" }] : []));
26
- /** Whether in edit mode */
27
- isEditMode = computed(() => !!this.existingAction(), ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
28
- /** All actions for LogicBuilder */
29
- allActionsForLogic = signal([], ...(ngDevMode ? [{ debugName: "allActionsForLogic" }] : []));
30
- /** All loaded actions for parent dropdown */
31
- allActions = signal([], ...(ngDevMode ? [{ debugName: "allActions" }] : []));
32
- /** Available actions for parent dropdown (excludes current action to prevent circular reference) */
33
- availableActions = computed(() => {
34
- const actions = this.allActions();
35
- const currentId = this.existingAction()?.id;
36
- return currentId ? actions.filter(a => a.id !== currentId) : actions;
37
- }, ...(ngDevMode ? [{ debugName: "availableActions" }] : []));
38
- // ============================================
39
- // Form (Signal Forms)
40
- // ============================================
41
- /** Form model */
42
- formModel = signal({
43
- id: '',
44
- name: '',
45
- description: '',
46
- code: '',
47
- actionType: ActionType.BACKEND,
48
- permissionLogic: null,
49
- parentId: '',
50
- serial: '',
51
- isActive: true,
52
- metadata: null,
53
- }, ...(ngDevMode ? [{ debugName: "formModel" }] : []));
54
- /** Available action types for dropdown */
55
- actionTypes = [
56
- { label: 'Backend (API Endpoints)', value: ActionType.BACKEND },
57
- { label: 'Frontend (UI Features)', value: ActionType.FRONTEND },
58
- { label: 'Both (Backend + Frontend)', value: ActionType.BOTH },
59
- ];
60
- /** Form with validation schema */
61
- actionForm = form(this.formModel, (f) => {
62
- required(f.name, { message: 'Name is required' });
63
- });
64
- /** Check if form is valid */
65
- isFormValid = computed(() => {
66
- const model = this.formModel();
67
- return model.name.trim().length > 0;
68
- }, ...(ngDevMode ? [{ debugName: "isFormValid" }] : []));
69
- async ngOnInit() {
70
- const id = this.route.snapshot.paramMap.get('id');
71
- // Load ALL actions FIRST - critical for LogicBuilder to display action names
72
- try {
73
- const response = await firstValueFrom(this.actionApi.getAll('', {
74
- pagination: { currentPage: 0, pageSize: 10000 },
75
- select: ['id', 'name', 'code', 'actionType', 'permissionLogic'],
76
- }));
77
- if (response?.success && response.data) {
78
- // Set actions for LogicBuilder dropdown
79
- this.allActionsForLogic.set(response.data.map(a => ({ id: a.id, name: a.name ?? 'Unnamed' })));
80
- // Store loaded actions locally for parent dropdown
81
- this.allActions.set(response.data);
82
- }
83
- }
84
- catch {
85
- // Actions load failed - form will show empty parent dropdown
86
- }
87
- // THEN load the specific action (ensures actions are loaded before setting permissionLogic)
88
- if (id && id !== 'new') {
89
- await this.loadAction(id);
90
- }
91
- }
92
- async loadAction(id) {
93
- this.isLoading.set(true);
94
- try {
95
- // Load fresh data from API to ensure permissionLogic is included
96
- const response = await this.actionApi.findByIdAsync(id, [
97
- 'id',
98
- 'name',
99
- 'description',
100
- 'code',
101
- 'actionType',
102
- 'permissionLogic',
103
- 'parentId',
104
- 'serial',
105
- 'isActive',
106
- 'metadata',
107
- ]);
108
- if (response?.success && response.data) {
109
- const action = response.data;
110
- // Set existing action for reference
111
- this.existingAction.set(action);
112
- // Populate form with action data
113
- this.formModel.set({
114
- id: action.id ?? '',
115
- name: action.name ?? '',
116
- description: action.description ?? '',
117
- code: action.code ?? '',
118
- actionType: action.actionType ?? ActionType.BACKEND,
119
- permissionLogic: action.permissionLogic ?? null,
120
- parentId: action.parentId ?? '',
121
- serial: action.serial?.toString() ?? '',
122
- isActive: action.isActive ?? true,
123
- metadata: action.metadata ?? null,
124
- });
125
- }
126
- else {
127
- this.messageService.add({
128
- severity: 'error',
129
- summary: 'Error',
130
- detail: 'Action not found.',
131
- });
132
- this.router.navigate(['/iam/actions']);
133
- }
134
- }
135
- catch {
136
- this.messageService.add({
137
- severity: 'error',
138
- summary: 'Error',
139
- detail: 'Failed to load action.',
140
- });
141
- this.router.navigate(['/iam/actions']);
142
- }
143
- finally {
144
- this.isLoading.set(false);
145
- }
146
- }
147
- async onSubmit() {
148
- if (!this.isFormValid()) {
149
- this.messageService.add({
150
- severity: 'error',
151
- summary: 'Validation Error',
152
- detail: 'Please fill in all required fields.',
153
- });
154
- return;
155
- }
156
- this.isLoading.set(true);
157
- try {
158
- const formValue = this.formModel();
159
- // Convert empty strings to undefined for DTO compatibility
160
- const dto = {
161
- ...formValue,
162
- description: formValue.description || undefined,
163
- code: formValue.code || undefined,
164
- parentId: formValue.parentId || undefined,
165
- serial: formValue.serial ? parseInt(formValue.serial, 10) : undefined,
166
- metadata: formValue.metadata ?? undefined,
167
- permissionLogic: formValue.permissionLogic ?? undefined,
168
- };
169
- if (this.isEditMode()) {
170
- await this.actionApi.updateAsync(dto);
171
- this.messageService.add({
172
- severity: 'success',
173
- summary: 'Success',
174
- detail: 'Action updated successfully.',
175
- });
176
- }
177
- else {
178
- await this.actionApi.insertAsync(dto);
179
- this.messageService.add({
180
- severity: 'success',
181
- summary: 'Success',
182
- detail: 'Action created successfully.',
183
- });
184
- }
185
- this.router.navigate(['/iam/actions']);
186
- }
187
- catch (error) {
188
- this.messageService.add({
189
- severity: 'error',
190
- summary: 'Error',
191
- detail: error.message || 'Failed to save action.',
192
- });
193
- }
194
- finally {
195
- this.isLoading.set(false);
196
- }
197
- }
198
- onBack() {
199
- this.router.navigate(['/iam/actions']);
200
- }
201
- /**
202
- * Handle permission logic changes from LogicBuilder
203
- */
204
- onLogicChange(logic) {
205
- this.formModel.update(model => ({
206
- ...model,
207
- permissionLogic: logic
208
- }));
209
- }
210
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ActionFormPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
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
- <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>
223
-
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>
236
-
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>
247
-
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>
258
-
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>
271
-
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>
285
-
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>
297
-
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>
307
- </div>
308
-
309
- <!-- Permission Logic Builder -->
310
- <div class="mt-6">
311
- <lib-logic-builder
312
- [logic]="formModel().permissionLogic"
313
- [actions]="allActionsForLogic()"
314
- (logicChange)="onLogicChange($event)" />
315
- </div>
316
-
317
- <!-- Actions -->
318
- <div class="flex justify-end gap-2 mt-6">
319
- <p-button
320
- label="Cancel"
321
- severity="secondary"
322
- [outlined]="true"
323
- (onClick)="onBack()" />
324
- <p-button
325
- [label]="isEditMode() ? 'Update' : 'Create'"
326
- type="submit"
327
- [loading]="isLoading()"
328
- [disabled]="!isFormValid() || isLoading()" />
329
- </div>
330
- </form>
331
- </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: "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 });
333
- }
334
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ActionFormPageComponent, decorators: [{
335
- type: Component,
336
- args: [{
337
- selector: 'lib-action-form-page',
338
- standalone: true,
339
- imports: [AngularModule, PrimeModule, FormField, LogicBuilderComponent],
340
- changeDetection: ChangeDetectionStrategy.OnPush,
341
- template: `
342
- <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>
353
-
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>
366
-
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>
377
-
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>
388
-
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>
401
-
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>
415
-
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>
427
-
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>
437
- </div>
438
-
439
- <!-- Permission Logic Builder -->
440
- <div class="mt-6">
441
- <lib-logic-builder
442
- [logic]="formModel().permissionLogic"
443
- [actions]="allActionsForLogic()"
444
- (logicChange)="onLogicChange($event)" />
445
- </div>
446
-
447
- <!-- Actions -->
448
- <div class="flex justify-end gap-2 mt-6">
449
- <p-button
450
- label="Cancel"
451
- severity="secondary"
452
- [outlined]="true"
453
- (onClick)="onBack()" />
454
- <p-button
455
- [label]="isEditMode() ? 'Update' : 'Create'"
456
- type="submit"
457
- [loading]="isLoading()"
458
- [disabled]="!isFormValid() || isLoading()" />
459
- </div>
460
- </form>
461
- </div>
462
- `,
463
- }]
464
- }] });
465
-
466
- export { ActionFormPageComponent };
467
- //# sourceMappingURL=flusys-ng-iam-action-form-page.component-C1j10Qhw.mjs.map
@@ -1 +0,0 @@
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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"}