@flusys/ng-iam 1.1.0 → 1.2.0-rc.1

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 +44 -1179
  2. package/fesm2022/flusys-ng-iam-action-form-page.component-Vc5Toouu.mjs +502 -0
  3. package/fesm2022/flusys-ng-iam-action-form-page.component-Vc5Toouu.mjs.map +1 -0
  4. package/fesm2022/flusys-ng-iam-action-list-page.component-UGKclpFx.mjs +348 -0
  5. package/fesm2022/flusys-ng-iam-action-list-page.component-UGKclpFx.mjs.map +1 -0
  6. package/fesm2022/{flusys-ng-iam-flusys-ng-iam-CJAQT60K.mjs → flusys-ng-iam-flusys-ng-iam-CrycDULz.mjs} +1814 -1622
  7. package/fesm2022/flusys-ng-iam-flusys-ng-iam-CrycDULz.mjs.map +1 -0
  8. package/fesm2022/flusys-ng-iam-iam-container.component-D0m8u6nu.mjs +105 -0
  9. package/fesm2022/flusys-ng-iam-iam-container.component-D0m8u6nu.mjs.map +1 -0
  10. package/fesm2022/{flusys-ng-iam-permission-page.component-DcgT7L3_.mjs → flusys-ng-iam-permission-page.component-x88X4AgJ.mjs} +38 -32
  11. package/fesm2022/flusys-ng-iam-permission-page.component-x88X4AgJ.mjs.map +1 -0
  12. package/fesm2022/flusys-ng-iam-role-form-page.component-InsxdriD.mjs +335 -0
  13. package/fesm2022/flusys-ng-iam-role-form-page.component-InsxdriD.mjs.map +1 -0
  14. package/fesm2022/flusys-ng-iam-role-list-page.component-8NGXCeSZ.mjs +389 -0
  15. package/fesm2022/flusys-ng-iam-role-list-page.component-8NGXCeSZ.mjs.map +1 -0
  16. package/fesm2022/flusys-ng-iam.mjs +1 -1
  17. package/package.json +11 -10
  18. package/types/flusys-ng-iam.d.ts +53 -252
  19. package/fesm2022/flusys-ng-iam-action-form-page.component-eXpZNJ_H.mjs +0 -389
  20. package/fesm2022/flusys-ng-iam-action-form-page.component-eXpZNJ_H.mjs.map +0 -1
  21. package/fesm2022/flusys-ng-iam-action-list-page.component-BtJlGcTj.mjs +0 -262
  22. package/fesm2022/flusys-ng-iam-action-list-page.component-BtJlGcTj.mjs.map +0 -1
  23. package/fesm2022/flusys-ng-iam-flusys-ng-iam-CJAQT60K.mjs.map +0 -1
  24. package/fesm2022/flusys-ng-iam-iam-container.component-UYJjqYV9.mjs +0 -92
  25. package/fesm2022/flusys-ng-iam-iam-container.component-UYJjqYV9.mjs.map +0 -1
  26. package/fesm2022/flusys-ng-iam-permission-page.component-DcgT7L3_.mjs.map +0 -1
  27. package/fesm2022/flusys-ng-iam-role-form-page.component-D_AAEay2.mjs +0 -272
  28. package/fesm2022/flusys-ng-iam-role-form-page.component-D_AAEay2.mjs.map +0 -1
  29. package/fesm2022/flusys-ng-iam-role-list-page.component-D4J1by6Q.mjs +0 -299
  30. package/fesm2022/flusys-ng-iam-role-list-page.component-D4J1by6Q.mjs.map +0 -1
@@ -0,0 +1,502 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, computed, effect, Component } from '@angular/core';
3
+ import { toSignal } from '@angular/core/rxjs-interop';
4
+ import { form, required, FormField } from '@angular/forms/signals';
5
+ import { ActivatedRoute, Router } from '@angular/router';
6
+ import * as i2 from '@flusys/ng-ui';
7
+ import { MessageService, UiModule } from '@flusys/ng-ui';
8
+ import { TranslateService, AngularModule, TranslatePipe } from '@flusys/ng-shared';
9
+ import { A as ActionApiService, a as ActionType, L as LogicBuilderComponent } from './flusys-ng-iam-flusys-ng-iam-CrycDULz.mjs';
10
+ import * as i1 from '@angular/forms';
11
+
12
+ class ActionFormPageComponent {
13
+ route = inject(ActivatedRoute);
14
+ router = inject(Router);
15
+ actionApi = inject(ActionApiService);
16
+ messageService = inject(MessageService);
17
+ translateAdapter = inject(TranslateService, {
18
+ optional: true,
19
+ });
20
+ routeParams = toSignal(this.route.paramMap);
21
+ initialized = false;
22
+ translate(key, vars) {
23
+ return this.translateAdapter?.translate(key, vars) ?? key;
24
+ }
25
+ isLoading = signal(false, /* @ts-ignore */
26
+ ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
27
+ existingAction = signal(null, /* @ts-ignore */
28
+ ...(ngDevMode ? [{ debugName: "existingAction" }] : /* istanbul ignore next */ []));
29
+ isEditMode = computed(() => !!this.existingAction(), /* @ts-ignore */
30
+ ...(ngDevMode ? [{ debugName: "isEditMode" }] : /* istanbul ignore next */ []));
31
+ allActionsForLogic = signal([], /* @ts-ignore */
32
+ ...(ngDevMode ? [{ debugName: "allActionsForLogic" }] : /* istanbul ignore next */ []));
33
+ allActions = signal([], /* @ts-ignore */
34
+ ...(ngDevMode ? [{ debugName: "allActions" }] : /* istanbul ignore next */ []));
35
+ availableActions = computed(() => {
36
+ const actions = this.allActions();
37
+ const currentId = this.existingAction()?.id;
38
+ return currentId ? actions.filter((a) => a.id !== currentId) : actions;
39
+ }, /* @ts-ignore */
40
+ ...(ngDevMode ? [{ debugName: "availableActions" }] : /* istanbul ignore next */ []));
41
+ formModel = signal({
42
+ id: '',
43
+ name: '',
44
+ description: '',
45
+ code: '',
46
+ actionType: ActionType.BACKEND,
47
+ permissionLogic: null,
48
+ parentId: '',
49
+ serial: '',
50
+ isActive: true,
51
+ }, /* @ts-ignore */
52
+ ...(ngDevMode ? [{ debugName: "formModel" }] : /* istanbul ignore next */ []));
53
+ actionTypes = computed(() => [
54
+ {
55
+ label: this.translate('iam.action.type.backend.label'),
56
+ value: ActionType.BACKEND,
57
+ },
58
+ {
59
+ label: this.translate('iam.action.type.frontend.label'),
60
+ value: ActionType.FRONTEND,
61
+ },
62
+ {
63
+ label: this.translate('iam.action.type.both.label'),
64
+ value: ActionType.BOTH,
65
+ },
66
+ ], /* @ts-ignore */
67
+ ...(ngDevMode ? [{ debugName: "actionTypes" }] : /* istanbul ignore next */ []));
68
+ actionForm = form(this.formModel, (f) => {
69
+ required(f.name, {
70
+ message: this.translate('shared.validation.required', {
71
+ field: this.translate('iam.action.name'),
72
+ }),
73
+ });
74
+ });
75
+ isFormValid = computed(() => {
76
+ const model = this.formModel();
77
+ return model.name.trim().length > 0;
78
+ }, /* @ts-ignore */
79
+ ...(ngDevMode ? [{ debugName: "isFormValid" }] : /* istanbul ignore next */ []));
80
+ constructor() {
81
+ effect(() => {
82
+ const params = this.routeParams();
83
+ if (!params || this.initialized)
84
+ return;
85
+ this.initialized = true;
86
+ this.initializeForm(params.get('id'));
87
+ });
88
+ }
89
+ async initializeForm(id) {
90
+ try {
91
+ const response = await this.actionApi.getAll({
92
+ pagination: { currentPage: 0, pageSize: 10000 },
93
+ select: ['id', 'name', 'code', 'actionType', 'permissionLogic'],
94
+ });
95
+ if (response?.success && response.data) {
96
+ this.allActionsForLogic.set(response.data.map((a) => ({
97
+ id: a.id,
98
+ name: a.name ?? this.translate('shared.unnamed'),
99
+ })));
100
+ this.allActions.set(response.data);
101
+ }
102
+ }
103
+ catch {
104
+ // Ignored - form will show empty parent dropdown
105
+ }
106
+ if (id && id !== 'new') {
107
+ await this.loadAction(id);
108
+ }
109
+ }
110
+ async loadAction(id) {
111
+ this.isLoading.set(true);
112
+ try {
113
+ const response = await this.actionApi.findById(id, [
114
+ 'id',
115
+ 'name',
116
+ 'description',
117
+ 'code',
118
+ 'actionType',
119
+ 'permissionLogic',
120
+ 'parentId',
121
+ 'serial',
122
+ 'isActive',
123
+ ]);
124
+ if (response?.success && response.data) {
125
+ const action = response.data;
126
+ this.existingAction.set(action);
127
+ this.formModel.set({
128
+ id: action.id ?? '',
129
+ name: action.name ?? '',
130
+ description: action.description ?? '',
131
+ code: action.code ?? '',
132
+ actionType: action.actionType ?? ActionType.BACKEND,
133
+ permissionLogic: action.permissionLogic ?? null,
134
+ parentId: action.parentId ?? '',
135
+ serial: action.serial?.toString() ?? '',
136
+ isActive: action.isActive ?? true,
137
+ });
138
+ }
139
+ else {
140
+ this.router.navigate(['/iam/actions']);
141
+ }
142
+ }
143
+ catch {
144
+ this.router.navigate(['/iam/actions']);
145
+ }
146
+ finally {
147
+ this.isLoading.set(false);
148
+ }
149
+ }
150
+ async onSubmit() {
151
+ if (!this.isFormValid()) {
152
+ this.messageService.add({
153
+ severity: 'error',
154
+ summary: this.translate('shared.validation.error'),
155
+ detail: this.translate('shared.fill.required.fields'),
156
+ });
157
+ return;
158
+ }
159
+ this.isLoading.set(true);
160
+ try {
161
+ const formValue = this.formModel();
162
+ const dto = {
163
+ ...formValue,
164
+ description: formValue.description || undefined,
165
+ code: formValue.code || undefined,
166
+ parentId: formValue.parentId || undefined,
167
+ serial: formValue.serial ? parseInt(formValue.serial, 10) : undefined,
168
+ permissionLogic: formValue.permissionLogic ?? undefined,
169
+ };
170
+ const response = this.isEditMode()
171
+ ? await this.actionApi.update(dto)
172
+ : await this.actionApi.insert(dto);
173
+ this.messageService.add({
174
+ severity: 'success',
175
+ summary: this.translate('shared.success'),
176
+ detail: response.messageKey
177
+ ? this.translate(response.messageKey, response.messageVariables)
178
+ : (response.message ?? ''),
179
+ });
180
+ this.router.navigate(['/iam/actions']);
181
+ }
182
+ catch {
183
+ // Handled by global interceptor
184
+ }
185
+ finally {
186
+ this.isLoading.set(false);
187
+ }
188
+ }
189
+ onBack() {
190
+ this.router.navigate(['/iam/actions']);
191
+ }
192
+ onLogicChange(logic) {
193
+ this.formModel.update((model) => ({ ...model, permissionLogic: logic }));
194
+ }
195
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ActionFormPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
196
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: ActionFormPageComponent, isStandalone: true, selector: "lib-action-form-page", ngImport: i0, template: `
197
+ <div class="card">
198
+ <h3 class="text-lg sm:text-xl font-semibold mb-4">
199
+ {{
200
+ isEditMode()
201
+ ? ('iam.action.edit' | translate)
202
+ : ('iam.action.new' | translate)
203
+ }}
204
+ </h3>
205
+
206
+ <form
207
+ (ngSubmit)="onSubmit()"
208
+ class="grid grid-cols-1 md:grid-cols-2 gap-4"
209
+ >
210
+ <!-- Name -->
211
+ <div class="flex flex-col gap-2">
212
+ <label for="name" class="font-medium"
213
+ >{{ 'iam.action.name' | translate }} *</label
214
+ >
215
+ <input
216
+ fInputText
217
+ id="name"
218
+ [formField]="actionForm.name"
219
+ [placeholder]="'iam.action.name.placeholder' | translate"
220
+ />
221
+ </div>
222
+
223
+ <!-- Code -->
224
+ <div class="flex flex-col gap-2">
225
+ <label for="code" class="font-medium">{{
226
+ 'iam.action.code' | translate
227
+ }}</label>
228
+ <input
229
+ fInputText
230
+ id="code"
231
+ [formField]="actionForm.code"
232
+ [placeholder]="'iam.action.code.placeholder' | translate"
233
+ />
234
+ </div>
235
+
236
+ <!-- Description -->
237
+ <div class="flex flex-col gap-2">
238
+ <label for="description" class="font-medium">{{
239
+ 'shared.description' | translate
240
+ }}</label>
241
+ <input
242
+ fInputText
243
+ id="description"
244
+ [formField]="actionForm.description"
245
+ [placeholder]="'shared.description.placeholder' | translate"
246
+ />
247
+ </div>
248
+
249
+ <!-- Action Type -->
250
+ <div class="flex flex-col gap-2">
251
+ <label for="actionType" class="font-medium"
252
+ >{{ 'iam.action.type' | translate }} *</label
253
+ >
254
+ <f-select
255
+ inputId="actionType"
256
+ [options]="actionTypes()"
257
+ optionLabel="label"
258
+ optionValue="value"
259
+ [formField]="actionForm.actionType"
260
+ [placeholder]="'iam.action.type' | translate"
261
+ />
262
+ </div>
263
+
264
+ <!-- Parent Action -->
265
+ <div class="flex flex-col gap-2">
266
+ <label for="parentId" class="font-medium">{{
267
+ 'iam.action.parent' | translate
268
+ }}</label>
269
+ <f-select
270
+ inputId="parentId"
271
+ [options]="availableActions()"
272
+ optionLabel="name"
273
+ optionValue="id"
274
+ [formField]="actionForm.parentId"
275
+ [placeholder]="'iam.action.select.parent' | translate"
276
+ [filter]="true"
277
+ />
278
+ </div>
279
+
280
+ <!-- Order -->
281
+ <div class="flex flex-col gap-2">
282
+ <label for="serial" class="font-medium">{{
283
+ 'shared.display.order' | translate
284
+ }}</label>
285
+ <input
286
+ fInputText
287
+ id="serial"
288
+ type="number"
289
+ [formField]="actionForm.serial"
290
+ [placeholder]="'shared.display.order.placeholder' | translate"
291
+ />
292
+ </div>
293
+
294
+ <!-- Is Active -->
295
+ <div class="flex items-end gap-2 pb-1 md:col-span-2">
296
+ <f-checkbox
297
+ [formField]="actionForm.isActive"
298
+ [binary]="true"
299
+ inputId="isActive"
300
+ />
301
+ <label for="isActive">{{ 'shared.active' | translate }}</label>
302
+ </div>
303
+
304
+ <!-- Permission Logic Builder -->
305
+ <div class="md:col-span-2">
306
+ <lib-logic-builder
307
+ [logic]="formModel().permissionLogic"
308
+ [actions]="allActionsForLogic()"
309
+ (logicChange)="onLogicChange($event)"
310
+ />
311
+ </div>
312
+
313
+ <!-- Actions -->
314
+ <div class="flex justify-end gap-2 md:col-span-2 pt-4">
315
+ <button
316
+ fButton
317
+ severity="secondary"
318
+ [outlined]="true"
319
+ (click)="onBack()"
320
+ >
321
+ <span pButtonLabel>{{ 'shared.cancel' | translate }}</span>
322
+ </button>
323
+ <button
324
+ fButton
325
+ type="submit"
326
+ [disabled]="!isFormValid() || isLoading()"
327
+ >
328
+ @if (isLoading()) {
329
+ <ui-icon pButtonIcon name="spinner" [spin]="true"></ui-icon>
330
+ }
331
+ <span pButtonLabel>{{
332
+ isEditMode()
333
+ ? ('shared.update' | translate)
334
+ : ('shared.create' | translate)
335
+ }}</span>
336
+ </button>
337
+ </div>
338
+ </form>
339
+ </div>
340
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: UiModule }, { kind: "directive", type: i2.FButtonDirective, selector: "[fButton]", inputs: ["severity", "text", "outlined", "link", "variant", "rounded", "raised", "fluid", "disabled", "loading", "loadingIcon", "size", "label", "icon", "iconPos", "ariaLabel", "plain"] }, { kind: "component", type: i2.CheckboxComponent, selector: "f-checkbox", inputs: ["label", "binary", "disabled", "readonly", "inputId", "invalid", "indeterminate", "variant", "size", "touched", "styleClass", "style", "checked"], outputs: ["onChange", "onBlur", "touch", "checkedChange"] }, { kind: "directive", type: i2.InputTextDirective, selector: "[fInputText]", inputs: ["invalid", "touched", "variant", "size", "fluid"] }, { kind: "component", type: i2.SelectComponent, selector: "f-select", inputs: ["options", "optionLabel", "optionValue", "placeholder", "disabled", "filter", "filterBy", "filterMatchMode", "filterLocale", "filterPlaceholder", "resetFilterOnHide", "autofocusFilter", "emptyMessage", "emptyFilterMessage", "showClear", "loading", "loadingIcon", "dropdownIcon", "clearIcon", "inputId", "invalid", "touched", "styleClass", "style", "editable", "readonly", "autofocus", "checkmark", "group", "optionGroupLabel", "optionGroupChildren", "virtualScroll", "virtualScrollItemSize", "lazy"], outputs: ["onFilter", "onChange", "onShow", "onHide", "onBlur", "onFocus", "onClear", "onLazyLoad"] }, { kind: "component", type: i2.UiIconComponent, selector: "ui-icon", inputs: ["name", "size", "spin", "fill", "severity"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "component", type: LogicBuilderComponent, selector: "lib-logic-builder", inputs: ["logic", "actions"], outputs: ["logicChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
341
+ }
342
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ActionFormPageComponent, decorators: [{
343
+ type: Component,
344
+ args: [{
345
+ selector: 'lib-action-form-page',
346
+ imports: [
347
+ AngularModule,
348
+ UiModule,
349
+ FormField,
350
+ LogicBuilderComponent,
351
+ TranslatePipe,
352
+ ],
353
+ template: `
354
+ <div class="card">
355
+ <h3 class="text-lg sm:text-xl font-semibold mb-4">
356
+ {{
357
+ isEditMode()
358
+ ? ('iam.action.edit' | translate)
359
+ : ('iam.action.new' | translate)
360
+ }}
361
+ </h3>
362
+
363
+ <form
364
+ (ngSubmit)="onSubmit()"
365
+ class="grid grid-cols-1 md:grid-cols-2 gap-4"
366
+ >
367
+ <!-- Name -->
368
+ <div class="flex flex-col gap-2">
369
+ <label for="name" class="font-medium"
370
+ >{{ 'iam.action.name' | translate }} *</label
371
+ >
372
+ <input
373
+ fInputText
374
+ id="name"
375
+ [formField]="actionForm.name"
376
+ [placeholder]="'iam.action.name.placeholder' | translate"
377
+ />
378
+ </div>
379
+
380
+ <!-- Code -->
381
+ <div class="flex flex-col gap-2">
382
+ <label for="code" class="font-medium">{{
383
+ 'iam.action.code' | translate
384
+ }}</label>
385
+ <input
386
+ fInputText
387
+ id="code"
388
+ [formField]="actionForm.code"
389
+ [placeholder]="'iam.action.code.placeholder' | translate"
390
+ />
391
+ </div>
392
+
393
+ <!-- Description -->
394
+ <div class="flex flex-col gap-2">
395
+ <label for="description" class="font-medium">{{
396
+ 'shared.description' | translate
397
+ }}</label>
398
+ <input
399
+ fInputText
400
+ id="description"
401
+ [formField]="actionForm.description"
402
+ [placeholder]="'shared.description.placeholder' | translate"
403
+ />
404
+ </div>
405
+
406
+ <!-- Action Type -->
407
+ <div class="flex flex-col gap-2">
408
+ <label for="actionType" class="font-medium"
409
+ >{{ 'iam.action.type' | translate }} *</label
410
+ >
411
+ <f-select
412
+ inputId="actionType"
413
+ [options]="actionTypes()"
414
+ optionLabel="label"
415
+ optionValue="value"
416
+ [formField]="actionForm.actionType"
417
+ [placeholder]="'iam.action.type' | translate"
418
+ />
419
+ </div>
420
+
421
+ <!-- Parent Action -->
422
+ <div class="flex flex-col gap-2">
423
+ <label for="parentId" class="font-medium">{{
424
+ 'iam.action.parent' | translate
425
+ }}</label>
426
+ <f-select
427
+ inputId="parentId"
428
+ [options]="availableActions()"
429
+ optionLabel="name"
430
+ optionValue="id"
431
+ [formField]="actionForm.parentId"
432
+ [placeholder]="'iam.action.select.parent' | translate"
433
+ [filter]="true"
434
+ />
435
+ </div>
436
+
437
+ <!-- Order -->
438
+ <div class="flex flex-col gap-2">
439
+ <label for="serial" class="font-medium">{{
440
+ 'shared.display.order' | translate
441
+ }}</label>
442
+ <input
443
+ fInputText
444
+ id="serial"
445
+ type="number"
446
+ [formField]="actionForm.serial"
447
+ [placeholder]="'shared.display.order.placeholder' | translate"
448
+ />
449
+ </div>
450
+
451
+ <!-- Is Active -->
452
+ <div class="flex items-end gap-2 pb-1 md:col-span-2">
453
+ <f-checkbox
454
+ [formField]="actionForm.isActive"
455
+ [binary]="true"
456
+ inputId="isActive"
457
+ />
458
+ <label for="isActive">{{ 'shared.active' | translate }}</label>
459
+ </div>
460
+
461
+ <!-- Permission Logic Builder -->
462
+ <div class="md:col-span-2">
463
+ <lib-logic-builder
464
+ [logic]="formModel().permissionLogic"
465
+ [actions]="allActionsForLogic()"
466
+ (logicChange)="onLogicChange($event)"
467
+ />
468
+ </div>
469
+
470
+ <!-- Actions -->
471
+ <div class="flex justify-end gap-2 md:col-span-2 pt-4">
472
+ <button
473
+ fButton
474
+ severity="secondary"
475
+ [outlined]="true"
476
+ (click)="onBack()"
477
+ >
478
+ <span pButtonLabel>{{ 'shared.cancel' | translate }}</span>
479
+ </button>
480
+ <button
481
+ fButton
482
+ type="submit"
483
+ [disabled]="!isFormValid() || isLoading()"
484
+ >
485
+ @if (isLoading()) {
486
+ <ui-icon pButtonIcon name="spinner" [spin]="true"></ui-icon>
487
+ }
488
+ <span pButtonLabel>{{
489
+ isEditMode()
490
+ ? ('shared.update' | translate)
491
+ : ('shared.create' | translate)
492
+ }}</span>
493
+ </button>
494
+ </div>
495
+ </form>
496
+ </div>
497
+ `,
498
+ }]
499
+ }], ctorParameters: () => [] });
500
+
501
+ export { ActionFormPageComponent };
502
+ //# sourceMappingURL=flusys-ng-iam-action-form-page.component-Vc5Toouu.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-iam-action-form-page.component-Vc5Toouu.mjs","sources":["../../../projects/ng-iam/pages/action/action-form-page.component.ts"],"sourcesContent":["import { Component, computed, effect, inject, signal } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { form, FormField, required } from '@angular/forms/signals';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { MessageService } from '@flusys/ng-ui';\nimport {\n AngularModule,\n ILogicNode,\n TranslatePipe,\n TranslateService,\n} from '@flusys/ng-shared';\nimport { LogicBuilderComponent } from '../../components/logic-builder.component';\nimport { ActionType, IAction } from '../../interfaces/action.interface';\nimport { ActionApiService } from '../../services/action-api.service';\nimport { UiModule } from '@flusys/ng-ui';\n\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}\n\n@Component({\n selector: 'lib-action-form-page',\n imports: [\n AngularModule,\n UiModule,\n FormField,\n LogicBuilderComponent,\n TranslatePipe,\n ],\n template: `\n <div class=\"card\">\n <h3 class=\"text-lg sm:text-xl font-semibold mb-4\">\n {{\n isEditMode()\n ? ('iam.action.edit' | translate)\n : ('iam.action.new' | translate)\n }}\n </h3>\n\n <form\n (ngSubmit)=\"onSubmit()\"\n class=\"grid grid-cols-1 md:grid-cols-2 gap-4\"\n >\n <!-- Name -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"name\" class=\"font-medium\"\n >{{ 'iam.action.name' | translate }} *</label\n >\n <input\n fInputText\n id=\"name\"\n [formField]=\"actionForm.name\"\n [placeholder]=\"'iam.action.name.placeholder' | translate\"\n />\n </div>\n\n <!-- Code -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"code\" class=\"font-medium\">{{\n 'iam.action.code' | translate\n }}</label>\n <input\n fInputText\n id=\"code\"\n [formField]=\"actionForm.code\"\n [placeholder]=\"'iam.action.code.placeholder' | translate\"\n />\n </div>\n\n <!-- Description -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"description\" class=\"font-medium\">{{\n 'shared.description' | translate\n }}</label>\n <input\n fInputText\n id=\"description\"\n [formField]=\"actionForm.description\"\n [placeholder]=\"'shared.description.placeholder' | translate\"\n />\n </div>\n\n <!-- Action Type -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"actionType\" class=\"font-medium\"\n >{{ 'iam.action.type' | translate }} *</label\n >\n <f-select\n inputId=\"actionType\"\n [options]=\"actionTypes()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [formField]=\"actionForm.actionType\"\n [placeholder]=\"'iam.action.type' | translate\"\n />\n </div>\n\n <!-- Parent Action -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"parentId\" class=\"font-medium\">{{\n 'iam.action.parent' | translate\n }}</label>\n <f-select\n inputId=\"parentId\"\n [options]=\"availableActions()\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [formField]=\"actionForm.parentId\"\n [placeholder]=\"'iam.action.select.parent' | translate\"\n [filter]=\"true\"\n />\n </div>\n\n <!-- Order -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"serial\" class=\"font-medium\">{{\n 'shared.display.order' | translate\n }}</label>\n <input\n fInputText\n id=\"serial\"\n type=\"number\"\n [formField]=\"actionForm.serial\"\n [placeholder]=\"'shared.display.order.placeholder' | translate\"\n />\n </div>\n\n <!-- Is Active -->\n <div class=\"flex items-end gap-2 pb-1 md:col-span-2\">\n <f-checkbox\n [formField]=\"actionForm.isActive\"\n [binary]=\"true\"\n inputId=\"isActive\"\n />\n <label for=\"isActive\">{{ 'shared.active' | translate }}</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 />\n </div>\n\n <!-- Actions -->\n <div class=\"flex justify-end gap-2 md:col-span-2 pt-4\">\n <button\n fButton\n severity=\"secondary\"\n [outlined]=\"true\"\n (click)=\"onBack()\"\n >\n <span pButtonLabel>{{ 'shared.cancel' | translate }}</span>\n </button>\n <button\n fButton\n type=\"submit\"\n [disabled]=\"!isFormValid() || isLoading()\"\n >\n @if (isLoading()) {\n <ui-icon pButtonIcon name=\"spinner\" [spin]=\"true\"></ui-icon>\n }\n <span pButtonLabel>{{ \n isEditMode()\n ? ('shared.update' | translate)\n : ('shared.create' | translate)\n }}</span>\n </button>\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 private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n private readonly routeParams = toSignal(this.route.paramMap);\n private initialized = false;\n\n private translate(\n key: string,\n vars?: Record<string, string | number>,\n ): string {\n return this.translateAdapter?.translate(key, vars) ?? key;\n }\n\n readonly isLoading = signal(false);\n readonly existingAction = signal<IAction | null>(null);\n readonly isEditMode = computed(() => !!this.existingAction());\n readonly allActionsForLogic = signal<Array<{ id: string; name: string }>>([]);\n readonly allActions = signal<IAction[]>([]);\n\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 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 });\n\n readonly actionTypes = computed(() => [\n {\n label: this.translate('iam.action.type.backend.label'),\n value: ActionType.BACKEND,\n },\n {\n label: this.translate('iam.action.type.frontend.label'),\n value: ActionType.FRONTEND,\n },\n {\n label: this.translate('iam.action.type.both.label'),\n value: ActionType.BOTH,\n },\n ]);\n\n readonly actionForm = form(this.formModel, (f) => {\n required(f.name, {\n message: this.translate('shared.validation.required', {\n field: this.translate('iam.action.name'),\n }),\n });\n });\n\n readonly isFormValid = computed(() => {\n const model = this.formModel();\n return model.name.trim().length > 0;\n });\n\n constructor() {\n effect(() => {\n const params = this.routeParams();\n if (!params || this.initialized) return;\n\n this.initialized = true;\n this.initializeForm(params.get('id'));\n });\n }\n\n private async initializeForm(id: string | null): Promise<void> {\n try {\n const response = await this.actionApi.getAll({\n pagination: { currentPage: 0, pageSize: 10000 },\n select: ['id', 'name', 'code', 'actionType', 'permissionLogic'],\n });\n if (response?.success && response.data) {\n this.allActionsForLogic.set(\n response.data.map((a) => ({\n id: a.id!,\n name: a.name ?? this.translate('shared.unnamed'),\n })),\n );\n this.allActions.set(response.data);\n }\n } catch {\n // Ignored - form will show empty parent dropdown\n }\n\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 const response = await this.actionApi.findById(id, [\n 'id',\n 'name',\n 'description',\n 'code',\n 'actionType',\n 'permissionLogic',\n 'parentId',\n 'serial',\n 'isActive',\n ]);\n\n if (response?.success && response.data) {\n const action = response.data;\n this.existingAction.set(action);\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 });\n } else {\n this.router.navigate(['/iam/actions']);\n }\n } catch {\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: this.translate('shared.validation.error'),\n detail: this.translate('shared.fill.required.fields'),\n });\n return;\n }\n\n this.isLoading.set(true);\n\n try {\n const formValue = this.formModel();\n 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 permissionLogic: formValue.permissionLogic ?? undefined,\n };\n\n const response = this.isEditMode()\n ? await this.actionApi.update(dto)\n : await this.actionApi.insert(dto);\n\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: response.messageKey\n ? this.translate(\n response.messageKey,\n response.messageVariables as Record<string, string | number>,\n )\n : (response.message ?? ''),\n });\n\n this.router.navigate(['/iam/actions']);\n } catch {\n // 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 onLogicChange(logic: ILogicNode | null): void {\n this.formModel.update((model) => ({ ...model, permissionLogic: logic }));\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;MAuLa,uBAAuB,CAAA;AACjB,IAAA,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC;AAC9B,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,IAAA,SAAS,GAAG,MAAM,CAAC,gBAAgB,CAAC;AACpC,IAAA,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;AACvC,IAAA,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,EAAE;AAC3D,QAAA,QAAQ,EAAE,IAAI;AACf,KAAA,CAAC;IACe,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IACpD,WAAW,GAAG,KAAK;IAEnB,SAAS,CACf,GAAW,EACX,IAAsC,EAAA;AAEtC,QAAA,OAAO,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,GAAG;IAC3D;IAES,SAAS,GAAG,MAAM,CAAC,KAAK;kFAAC;IACzB,cAAc,GAAG,MAAM,CAAiB,IAAI;uFAAC;IAC7C,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE;mFAAC;IACpD,kBAAkB,GAAG,MAAM,CAAsC,EAAE;2FAAC;IACpE,UAAU,GAAG,MAAM,CAAY,EAAE;mFAAC;AAElC,IAAA,gBAAgB,GAAG,QAAQ,CAAC,MAAK;AACxC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE;QACjC,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,EAAE,EAAE;QAC3C,OAAO,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,GAAG,OAAO;IACxE,CAAC;yFAAC;IAEO,SAAS,GAAG,MAAM,CAAmB;AAC5C,QAAA,EAAE,EAAE,EAAE;AACN,QAAA,IAAI,EAAE,EAAE;AACR,QAAA,WAAW,EAAE,EAAE;AACf,QAAA,IAAI,EAAE,EAAE;QACR,UAAU,EAAE,UAAU,CAAC,OAAO;AAC9B,QAAA,eAAe,EAAE,IAAI;AACrB,QAAA,QAAQ,EAAE,EAAE;AACZ,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE,IAAI;AACf,KAAA;kFAAC;AAEO,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAM;AACpC,QAAA;AACE,YAAA,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,+BAA+B,CAAC;YACtD,KAAK,EAAE,UAAU,CAAC,OAAO;AAC1B,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,gCAAgC,CAAC;YACvD,KAAK,EAAE,UAAU,CAAC,QAAQ;AAC3B,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,4BAA4B,CAAC;YACnD,KAAK,EAAE,UAAU,CAAC,IAAI;AACvB,SAAA;AACF,KAAA;oFAAC;IAEO,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,KAAI;AAC/C,QAAA,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE;AACf,YAAA,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,4BAA4B,EAAE;AACpD,gBAAA,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC;aACzC,CAAC;AACH,SAAA,CAAC;AACJ,IAAA,CAAC,CAAC;AAEO,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAK;AACnC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE;QAC9B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;IACrC,CAAC;oFAAC;AAEF,IAAA,WAAA,GAAA;QACE,MAAM,CAAC,MAAK;AACV,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE;AACjC,YAAA,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW;gBAAE;AAEjC,YAAA,IAAI,CAAC,WAAW,GAAG,IAAI;YACvB,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACvC,QAAA,CAAC,CAAC;IACJ;IAEQ,MAAM,cAAc,CAAC,EAAiB,EAAA;AAC5C,QAAA,IAAI;YACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;gBAC3C,UAAU,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE;gBAC/C,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,iBAAiB,CAAC;AAChE,aAAA,CAAC;YACF,IAAI,QAAQ,EAAE,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;AACtC,gBAAA,IAAI,CAAC,kBAAkB,CAAC,GAAG,CACzB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM;oBACxB,EAAE,EAAE,CAAC,CAAC,EAAG;oBACT,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;iBACjD,CAAC,CAAC,CACJ;gBACD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;YACpC;QACF;AAAE,QAAA,MAAM;;QAER;AAEA,QAAA,IAAI,EAAE,IAAI,EAAE,KAAK,KAAK,EAAE;AACtB,YAAA,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B;IACF;IAEA,MAAM,UAAU,CAAC,EAAU,EAAA;AACzB,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AACxB,QAAA,IAAI;YACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE;gBACjD,IAAI;gBACJ,MAAM;gBACN,aAAa;gBACb,MAAM;gBACN,YAAY;gBACZ,iBAAiB;gBACjB,UAAU;gBACV,QAAQ;gBACR,UAAU;AACX,aAAA,CAAC;YAEF,IAAI,QAAQ,EAAE,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;AACtC,gBAAA,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI;AAC5B,gBAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;AAC/B,gBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;AACjB,oBAAA,EAAE,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE;AACnB,oBAAA,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;AACvB,oBAAA,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;AACrC,oBAAA,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;AACvB,oBAAA,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,UAAU,CAAC,OAAO;AACnD,oBAAA,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,IAAI;AAC/C,oBAAA,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE;oBAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;AACvC,oBAAA,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,IAAI;AAClC,iBAAA,CAAC;YACJ;iBAAO;gBACL,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAC;YACxC;QACF;AAAE,QAAA,MAAM;YACN,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAC;QACxC;gBAAU;AACR,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QAC3B;IACF;AAEA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE;AACvB,YAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;AACtB,gBAAA,QAAQ,EAAE,OAAO;AACjB,gBAAA,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,yBAAyB,CAAC;AAClD,gBAAA,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,6BAA6B,CAAC;AACtD,aAAA,CAAC;YACF;QACF;AAEA,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AAExB,QAAA,IAAI;AACF,YAAA,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE;AAClC,YAAA,MAAM,GAAG,GAAG;AACV,gBAAA,GAAG,SAAS;AACZ,gBAAA,WAAW,EAAE,SAAS,CAAC,WAAW,IAAI,SAAS;AAC/C,gBAAA,IAAI,EAAE,SAAS,CAAC,IAAI,IAAI,SAAS;AACjC,gBAAA,QAAQ,EAAE,SAAS,CAAC,QAAQ,IAAI,SAAS;AACzC,gBAAA,MAAM,EAAE,SAAS,CAAC,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,SAAS;AACrE,gBAAA,eAAe,EAAE,SAAS,CAAC,eAAe,IAAI,SAAS;aACxD;AAED,YAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU;kBAC5B,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG;kBAC/B,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC;AAEpC,YAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;AACtB,gBAAA,QAAQ,EAAE,SAAS;AACnB,gBAAA,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;gBACzC,MAAM,EAAE,QAAQ,CAAC;AACf,sBAAE,IAAI,CAAC,SAAS,CACZ,QAAQ,CAAC,UAAU,EACnB,QAAQ,CAAC,gBAAmD;AAEhE,uBAAG,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC;AAC7B,aAAA,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAC;QACxC;AAAE,QAAA,MAAM;;QAER;gBAAU;AACR,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QAC3B;IACF;IAEA,MAAM,GAAA;QACJ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAC;IACxC;AAEA,IAAA,aAAa,CAAC,KAAwB,EAAA;QACpC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,MAAM,EAAE,GAAG,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1E;uGAnMW,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAvB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,uBAAuB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,sBAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlJxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgJT,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAtJC,aAAa,ofACb,QAAQ,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,gBAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,SAAA,EAAA,SAAA,EAAA,QAAA,EAAA,OAAA,EAAA,UAAA,EAAA,SAAA,EAAA,aAAA,EAAA,MAAA,EAAA,OAAA,EAAA,MAAA,EAAA,SAAA,EAAA,WAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,iBAAA,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,UAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,eAAA,EAAA,SAAA,EAAA,MAAA,EAAA,SAAA,EAAA,YAAA,EAAA,OAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,kBAAA,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,aAAA,EAAA,aAAA,EAAA,aAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,mBAAA,EAAA,mBAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,oBAAA,EAAA,WAAA,EAAA,SAAA,EAAA,aAAA,EAAA,cAAA,EAAA,WAAA,EAAA,SAAA,EAAA,SAAA,EAAA,SAAA,EAAA,YAAA,EAAA,OAAA,EAAA,UAAA,EAAA,UAAA,EAAA,WAAA,EAAA,WAAA,EAAA,OAAA,EAAA,kBAAA,EAAA,qBAAA,EAAA,eAAA,EAAA,uBAAA,EAAA,MAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,QAAA,EAAA,SAAA,EAAA,SAAA,EAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACR,SAAS,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,WAAA,CAAA,EAAA,QAAA,EAAA,CAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACT,qBAAqB,iHACrB,aAAa,EAAA,IAAA,EAAA,WAAA,EAAA,CAAA,EAAA,CAAA;;2FAoJJ,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBA3JnC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,sBAAsB;AAChC,oBAAA,OAAO,EAAE;wBACP,aAAa;wBACb,QAAQ;wBACR,SAAS;wBACT,qBAAqB;wBACrB,aAAa;AACd,qBAAA;AACD,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgJT,EAAA,CAAA;AACF,iBAAA;;;;;"}