@flusys/ng-iam 0.1.0-beta.3 → 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.
- package/README.md +225 -25
- package/fesm2022/{flusys-ng-iam-action-form-page.component-BVWZMlLU.mjs → flusys-ng-iam-action-form-page.component-C_BRrrWW.mjs} +181 -210
- package/fesm2022/flusys-ng-iam-action-form-page.component-C_BRrrWW.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-action-list-page.component-Daf93zpS.mjs +289 -0
- package/fesm2022/flusys-ng-iam-action-list-page.component-Daf93zpS.mjs.map +1 -0
- package/fesm2022/{flusys-ng-iam-flusys-ng-iam-D_i24Gub.mjs → flusys-ng-iam-flusys-ng-iam-BPIpfrjN.mjs} +967 -1087
- package/fesm2022/flusys-ng-iam-flusys-ng-iam-BPIpfrjN.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-iam-container.component-Bn4kQtxW.mjs +92 -0
- package/fesm2022/flusys-ng-iam-iam-container.component-Bn4kQtxW.mjs.map +1 -0
- package/fesm2022/{flusys-ng-iam-permission-page.component-C0yLMdW5.mjs → flusys-ng-iam-permission-page.component-CmxOBJPu.mjs} +45 -16
- package/fesm2022/flusys-ng-iam-permission-page.component-CmxOBJPu.mjs.map +1 -0
- package/fesm2022/{flusys-ng-iam-role-form-page.component-Co6bbHik.mjs → flusys-ng-iam-role-form-page.component-ByNueI1a.mjs} +110 -138
- package/fesm2022/flusys-ng-iam-role-form-page.component-ByNueI1a.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-role-list-page.component-CFly5KnH.mjs +316 -0
- package/fesm2022/flusys-ng-iam-role-list-page.component-CFly5KnH.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam.mjs +1 -1
- package/package.json +5 -5
- package/types/flusys-ng-iam.d.ts +89 -37
- package/fesm2022/flusys-ng-iam-action-form-page.component-BVWZMlLU.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-action-list-page.component-CCp7M7xo.mjs +0 -282
- package/fesm2022/flusys-ng-iam-action-list-page.component-CCp7M7xo.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-flusys-ng-iam-D_i24Gub.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-iam-container.component-BFKoNtdz.mjs +0 -97
- package/fesm2022/flusys-ng-iam-iam-container.component-BFKoNtdz.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-permission-page.component-C0yLMdW5.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-role-form-page.component-Co6bbHik.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-role-list-page.component-KJUVOrf0.mjs +0 -267
- package/fesm2022/flusys-ng-iam-role-list-page.component-KJUVOrf0.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-
|
|
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/
|
|
11
|
-
import * as i3 from 'primeng/
|
|
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
|
-
|
|
70
|
-
|
|
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('', {
|
|
@@ -81,8 +93,8 @@ class ActionFormPageComponent {
|
|
|
81
93
|
this.allActions.set(response.data);
|
|
82
94
|
}
|
|
83
95
|
}
|
|
84
|
-
catch
|
|
85
|
-
|
|
96
|
+
catch {
|
|
97
|
+
// Actions load failed - form will show empty parent dropdown
|
|
86
98
|
}
|
|
87
99
|
// THEN load the specific action (ensures actions are loaded before setting permissionLogic)
|
|
88
100
|
if (id && id !== 'new') {
|
|
@@ -124,21 +136,12 @@ class ActionFormPageComponent {
|
|
|
124
136
|
});
|
|
125
137
|
}
|
|
126
138
|
else {
|
|
127
|
-
|
|
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
|
-
catch
|
|
136
|
-
|
|
137
|
-
this.messageService.add({
|
|
138
|
-
severity: 'error',
|
|
139
|
-
summary: 'Error',
|
|
140
|
-
detail: 'Failed to load action.',
|
|
141
|
-
});
|
|
143
|
+
catch {
|
|
144
|
+
// Error toast handled by global interceptor
|
|
142
145
|
this.router.navigate(['/iam/actions']);
|
|
143
146
|
}
|
|
144
147
|
finally {
|
|
@@ -185,12 +188,8 @@ class ActionFormPageComponent {
|
|
|
185
188
|
}
|
|
186
189
|
this.router.navigate(['/iam/actions']);
|
|
187
190
|
}
|
|
188
|
-
catch
|
|
189
|
-
|
|
190
|
-
severity: 'error',
|
|
191
|
-
summary: 'Error',
|
|
192
|
-
detail: error.message || 'Failed to save action.',
|
|
193
|
-
});
|
|
191
|
+
catch {
|
|
192
|
+
// Error toast handled by global interceptor
|
|
194
193
|
}
|
|
195
194
|
finally {
|
|
196
195
|
this.isLoading.set(false);
|
|
@@ -208,107 +207,93 @@ class ActionFormPageComponent {
|
|
|
208
207
|
permissionLogic: logic
|
|
209
208
|
}));
|
|
210
209
|
}
|
|
211
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
212
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
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: `
|
|
213
212
|
<div class="card">
|
|
214
|
-
<
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
</h3>
|
|
218
|
-
<p-button
|
|
219
|
-
label="Back"
|
|
220
|
-
icon="pi pi-arrow-left"
|
|
221
|
-
[outlined]="true"
|
|
222
|
-
(onClick)="onBack()" />
|
|
223
|
-
</div>
|
|
213
|
+
<h3 class="text-lg sm:text-xl font-semibold mb-4">
|
|
214
|
+
{{ isEditMode() ? 'Edit Action' : 'New Action' }}
|
|
215
|
+
</h3>
|
|
224
216
|
|
|
225
|
-
<form (ngSubmit)="onSubmit()">
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
<
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
placeholder="Enter action name" />
|
|
236
|
-
</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>
|
|
237
227
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
</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>
|
|
248
237
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
</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>
|
|
259
247
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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>
|
|
272
260
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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>
|
|
286
274
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
</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>
|
|
298
285
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
</label>
|
|
307
|
-
</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>
|
|
308
293
|
</div>
|
|
309
294
|
|
|
310
295
|
<!-- Permission Logic Builder -->
|
|
311
|
-
<div class="
|
|
296
|
+
<div class="md:col-span-2">
|
|
312
297
|
<lib-logic-builder
|
|
313
298
|
[logic]="formModel().permissionLogic"
|
|
314
299
|
[actions]="allActionsForLogic()"
|
|
@@ -316,7 +301,7 @@ class ActionFormPageComponent {
|
|
|
316
301
|
</div>
|
|
317
302
|
|
|
318
303
|
<!-- Actions -->
|
|
319
|
-
<div class="flex justify-end gap-2
|
|
304
|
+
<div class="flex justify-end gap-2 md:col-span-2 pt-4">
|
|
320
305
|
<p-button
|
|
321
306
|
label="Cancel"
|
|
322
307
|
severity="secondary"
|
|
@@ -330,9 +315,9 @@ class ActionFormPageComponent {
|
|
|
330
315
|
</div>
|
|
331
316
|
</form>
|
|
332
317
|
</div>
|
|
333
|
-
`, 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: "
|
|
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 });
|
|
334
319
|
}
|
|
335
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
320
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ActionFormPageComponent, decorators: [{
|
|
336
321
|
type: Component,
|
|
337
322
|
args: [{
|
|
338
323
|
selector: 'lib-action-form-page',
|
|
@@ -341,104 +326,90 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
341
326
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
342
327
|
template: `
|
|
343
328
|
<div class="card">
|
|
344
|
-
<
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
</h3>
|
|
348
|
-
<p-button
|
|
349
|
-
label="Back"
|
|
350
|
-
icon="pi pi-arrow-left"
|
|
351
|
-
[outlined]="true"
|
|
352
|
-
(onClick)="onBack()" />
|
|
353
|
-
</div>
|
|
329
|
+
<h3 class="text-lg sm:text-xl font-semibold mb-4">
|
|
330
|
+
{{ isEditMode() ? 'Edit Action' : 'New Action' }}
|
|
331
|
+
</h3>
|
|
354
332
|
|
|
355
|
-
<form (ngSubmit)="onSubmit()">
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
<
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
placeholder="Enter action name" />
|
|
366
|
-
</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>
|
|
367
343
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
</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>
|
|
378
353
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
</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>
|
|
389
363
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
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>
|
|
402
376
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
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>
|
|
416
390
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
</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>
|
|
428
401
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
</label>
|
|
437
|
-
</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>
|
|
438
409
|
</div>
|
|
439
410
|
|
|
440
411
|
<!-- Permission Logic Builder -->
|
|
441
|
-
<div class="
|
|
412
|
+
<div class="md:col-span-2">
|
|
442
413
|
<lib-logic-builder
|
|
443
414
|
[logic]="formModel().permissionLogic"
|
|
444
415
|
[actions]="allActionsForLogic()"
|
|
@@ -446,7 +417,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
446
417
|
</div>
|
|
447
418
|
|
|
448
419
|
<!-- Actions -->
|
|
449
|
-
<div class="flex justify-end gap-2
|
|
420
|
+
<div class="flex justify-end gap-2 md:col-span-2 pt-4">
|
|
450
421
|
<p-button
|
|
451
422
|
label="Cancel"
|
|
452
423
|
severity="secondary"
|
|
@@ -462,7 +433,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
462
433
|
</div>
|
|
463
434
|
`,
|
|
464
435
|
}]
|
|
465
|
-
}] });
|
|
436
|
+
}], ctorParameters: () => [] });
|
|
466
437
|
|
|
467
438
|
export { ActionFormPageComponent };
|
|
468
|
-
//# sourceMappingURL=flusys-ng-iam-action-form-page.component-
|
|
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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"}
|