@masterteam/governance 0.0.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.
@@ -0,0 +1,1482 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import * as i0 from '@angular/core';
3
+ import { inject, Injectable, computed, input, effect, Component, viewChild, linkedSignal, signal } from '@angular/core';
4
+ import { Table } from '@masterteam/components/table';
5
+ import * as i1 from 'primeng/skeleton';
6
+ import { SkeletonModule } from 'primeng/skeleton';
7
+ import { Action, Selector, State, Store, select } from '@ngxs/store';
8
+ import { HttpClient } from '@angular/common/http';
9
+ import { CrudStateBase, handleApiRequest, TextFieldConfig, NumberFieldConfig, TextareaFieldConfig, SelectFieldConfig, ToggleFieldConfig, ValidatorConfig, DateFieldConfig, MultiSelectFieldConfig } from '@masterteam/components';
10
+ import { TranslocoService, TranslocoDirective, TranslocoPipe } from '@jsverse/transloco';
11
+ import { ModalService } from '@masterteam/components/modal';
12
+ import * as i2 from '@angular/forms';
13
+ import { FormControl, ReactiveFormsModule } from '@angular/forms';
14
+ import { toSignal } from '@angular/core/rxjs-interop';
15
+ import { DynamicForm } from '@masterteam/forms/dynamic-form';
16
+ import { Button } from '@masterteam/components/button';
17
+ import { ModalRef, DialogService } from '@masterteam/components/dialog';
18
+ import { finalize } from 'rxjs';
19
+ import { Breadcrumb } from '@masterteam/components/breadcrumb';
20
+ import { Icon } from '@masterteam/icons';
21
+ import { Chip } from '@masterteam/components/chip';
22
+
23
+ class SetLevelId {
24
+ levelId;
25
+ static type = '[Governance] Set Level ID';
26
+ constructor(levelId) {
27
+ this.levelId = levelId;
28
+ }
29
+ }
30
+ class GetGovernanceRules {
31
+ static type = '[Governance] Get Rules';
32
+ }
33
+ class GetGovernanceRule {
34
+ id;
35
+ static type = '[Governance] Get Rule';
36
+ constructor(id) {
37
+ this.id = id;
38
+ }
39
+ }
40
+ class GetGovernanceRuleTypes {
41
+ static type = '[Governance] Get Rule Types';
42
+ }
43
+ class AddGovernanceRule {
44
+ rule;
45
+ static type = '[Governance] Add Rule';
46
+ constructor(rule) {
47
+ this.rule = rule;
48
+ }
49
+ }
50
+ class UpdateGovernanceRule {
51
+ id;
52
+ rule;
53
+ static type = '[Governance] Update Rule';
54
+ constructor(id, rule) {
55
+ this.id = id;
56
+ this.rule = rule;
57
+ }
58
+ }
59
+ class DeleteGovernanceRule {
60
+ id;
61
+ static type = '[Governance] Delete Rule';
62
+ constructor(id) {
63
+ this.id = id;
64
+ }
65
+ }
66
+ class ToggleGovernanceRuleActive {
67
+ id;
68
+ static type = '[Governance] Toggle Rule Active';
69
+ constructor(id) {
70
+ this.id = id;
71
+ }
72
+ }
73
+ class ClearSelectedRule {
74
+ static type = '[Governance] Clear Selected Rule';
75
+ }
76
+ class ResetGovernanceState {
77
+ static type = '[Governance] Reset State';
78
+ }
79
+ class GetModules {
80
+ static type = '[Governance] Get Modules';
81
+ }
82
+ /**
83
+ * Get request schemas for a specific scope
84
+ * @param targetScope - 'Level' or 'Module'
85
+ * @param targetModuleKey - Required if scope is 'Module'
86
+ */
87
+ class GetRequestSchemas {
88
+ targetScope;
89
+ targetModuleKey;
90
+ static type = '[Governance] Get Request Schemas';
91
+ constructor(targetScope, targetModuleKey) {
92
+ this.targetScope = targetScope;
93
+ this.targetModuleKey = targetModuleKey;
94
+ }
95
+ }
96
+ /**
97
+ * Get properties for a specific scope
98
+ * @param targetScope - 'Level' or 'Module'
99
+ * @param targetModuleKey - Required if scope is 'Module'
100
+ */
101
+ class GetProperties {
102
+ targetScope;
103
+ targetModuleKey;
104
+ static type = '[Governance] Get Properties';
105
+ constructor(targetScope, targetModuleKey) {
106
+ this.targetScope = targetScope;
107
+ this.targetModuleKey = targetModuleKey;
108
+ }
109
+ }
110
+ /**
111
+ * Clear request schemas (when scope/module changes)
112
+ */
113
+ class ClearRequestSchemas {
114
+ static type = '[Governance] Clear Request Schemas';
115
+ }
116
+ /**
117
+ * Clear properties (when scope/module changes)
118
+ */
119
+ class ClearProperties {
120
+ static type = '[Governance] Clear Properties';
121
+ }
122
+
123
+ // ============================================================================
124
+ // Rule Type Enum
125
+ // ============================================================================
126
+ var GovernanceRuleTypeEnum;
127
+ (function (GovernanceRuleTypeEnum) {
128
+ GovernanceRuleTypeEnum[GovernanceRuleTypeEnum["ModuleExists"] = 1] = "ModuleExists";
129
+ GovernanceRuleTypeEnum[GovernanceRuleTypeEnum["ModuleDoesNotExist"] = 2] = "ModuleDoesNotExist";
130
+ GovernanceRuleTypeEnum[GovernanceRuleTypeEnum["ModuleMaxCount"] = 3] = "ModuleMaxCount";
131
+ GovernanceRuleTypeEnum[GovernanceRuleTypeEnum["ModuleMinCount"] = 4] = "ModuleMinCount";
132
+ GovernanceRuleTypeEnum[GovernanceRuleTypeEnum["FieldRequired"] = 5] = "FieldRequired";
133
+ GovernanceRuleTypeEnum[GovernanceRuleTypeEnum["FieldValue"] = 6] = "FieldValue";
134
+ GovernanceRuleTypeEnum[GovernanceRuleTypeEnum["PhaseGateModuleRequired"] = 7] = "PhaseGateModuleRequired";
135
+ GovernanceRuleTypeEnum[GovernanceRuleTypeEnum["NoActiveRequest"] = 8] = "NoActiveRequest";
136
+ })(GovernanceRuleTypeEnum || (GovernanceRuleTypeEnum = {}));
137
+ // ============================================================================
138
+ // State Model
139
+ // ============================================================================
140
+ var GovernanceActionKey;
141
+ (function (GovernanceActionKey) {
142
+ GovernanceActionKey["GetRules"] = "getRules";
143
+ GovernanceActionKey["GetRule"] = "getRule";
144
+ GovernanceActionKey["GetRuleTypes"] = "getRuleTypes";
145
+ GovernanceActionKey["AddRule"] = "addRule";
146
+ GovernanceActionKey["UpdateRule"] = "updateRule";
147
+ GovernanceActionKey["DeleteRule"] = "deleteRule";
148
+ GovernanceActionKey["ToggleRuleActive"] = "toggleRuleActive";
149
+ GovernanceActionKey["GetModules"] = "getModules";
150
+ GovernanceActionKey["GetRequestSchemas"] = "getRequestSchemas";
151
+ GovernanceActionKey["GetProperties"] = "getProperties";
152
+ })(GovernanceActionKey || (GovernanceActionKey = {}));
153
+
154
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
155
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
156
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
157
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
158
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
159
+ };
160
+ const DEFAULTS = {
161
+ levelId: null,
162
+ rules: [],
163
+ ruleTypes: [],
164
+ modules: [],
165
+ requestSchemas: [],
166
+ properties: [],
167
+ selectedRule: null,
168
+ loadingActive: [],
169
+ errors: {},
170
+ };
171
+ let GovernanceState = class GovernanceState extends CrudStateBase {
172
+ http = inject(HttpClient);
173
+ // ============================================================================
174
+ // Selectors - Individual data selectors for fine-grained reactivity
175
+ // ============================================================================
176
+ static getLevelId(state) {
177
+ return state.levelId;
178
+ }
179
+ static getRules(state) {
180
+ return state.rules;
181
+ }
182
+ static getRuleTypes(state) {
183
+ return state.ruleTypes;
184
+ }
185
+ static getSelectedRule(state) {
186
+ return state.selectedRule;
187
+ }
188
+ static getModules(state) {
189
+ return state.modules;
190
+ }
191
+ static getRequestSchemas(state) {
192
+ return state.requestSchemas;
193
+ }
194
+ static getProperties(state) {
195
+ return state.properties;
196
+ }
197
+ // ============================================================================
198
+ // Loading/Error Slice Selectors - REQUIRED for optimal performance
199
+ // ============================================================================
200
+ static getLoadingActive(state) {
201
+ return state.loadingActive;
202
+ }
203
+ static getErrors(state) {
204
+ return state.errors;
205
+ }
206
+ // ============================================================================
207
+ // Level Context
208
+ // ============================================================================
209
+ setLevelId(ctx, { levelId }) {
210
+ ctx.patchState({ levelId });
211
+ }
212
+ resetState(ctx) {
213
+ ctx.setState(DEFAULTS);
214
+ }
215
+ // ============================================================================
216
+ // CRUD Actions
217
+ // ============================================================================
218
+ getRules(ctx) {
219
+ const { levelId } = ctx.getState();
220
+ if (!levelId) {
221
+ return;
222
+ }
223
+ const req$ = this.http.get(`control-panel/levels/${levelId}/governance-rules`);
224
+ return handleApiRequest({
225
+ ctx,
226
+ key: GovernanceActionKey.GetRules,
227
+ request$: req$,
228
+ onSuccess: (response) => ({
229
+ rules: response.data ?? [],
230
+ }),
231
+ });
232
+ }
233
+ getRule(ctx, { id }) {
234
+ const { levelId } = ctx.getState();
235
+ if (!levelId) {
236
+ return;
237
+ }
238
+ const req$ = this.http.get(`control-panel/levels/${levelId}/governance-rules/${id}`);
239
+ return handleApiRequest({
240
+ ctx,
241
+ key: GovernanceActionKey.GetRule,
242
+ request$: req$,
243
+ onSuccess: (response) => ({
244
+ selectedRule: response.data ?? null,
245
+ }),
246
+ });
247
+ }
248
+ getRuleTypes(ctx) {
249
+ const req$ = this.http.get('control-panel/governance/rule-types');
250
+ return handleApiRequest({
251
+ ctx,
252
+ key: GovernanceActionKey.GetRuleTypes,
253
+ request$: req$,
254
+ onSuccess: (response) => ({
255
+ ruleTypes: response.data ?? [],
256
+ }),
257
+ });
258
+ }
259
+ addRule(ctx, { rule }) {
260
+ const { levelId } = ctx.getState();
261
+ if (!levelId) {
262
+ return;
263
+ }
264
+ const req$ = this.http.post(`control-panel/levels/${levelId}/governance-rules`, rule);
265
+ return this.create(ctx, {
266
+ key: GovernanceActionKey.AddRule,
267
+ request$: req$,
268
+ stateProperty: (state) => state.rules,
269
+ });
270
+ }
271
+ updateRule(ctx, { id, rule }) {
272
+ const { levelId } = ctx.getState();
273
+ if (!levelId) {
274
+ return;
275
+ }
276
+ const req$ = this.http.put(`control-panel/levels/${levelId}/governance-rules/${id}`, rule);
277
+ return this.update(ctx, {
278
+ key: GovernanceActionKey.UpdateRule,
279
+ request$: req$,
280
+ uniqueKey: 'id',
281
+ id,
282
+ stateProperty: (state) => state.rules,
283
+ });
284
+ }
285
+ deleteRule(ctx, { id }) {
286
+ const { levelId } = ctx.getState();
287
+ if (!levelId) {
288
+ return;
289
+ }
290
+ const req$ = this.http.delete(`control-panel/levels/${levelId}/governance-rules/${id}`);
291
+ return this.delete(ctx, {
292
+ key: GovernanceActionKey.DeleteRule,
293
+ request$: req$,
294
+ uniqueKey: 'id',
295
+ id,
296
+ stateProperty: (state) => state.rules,
297
+ });
298
+ }
299
+ toggleRuleActive(ctx, { id }) {
300
+ const { levelId } = ctx.getState();
301
+ if (!levelId) {
302
+ return;
303
+ }
304
+ const req$ = this.http.patch(`control-panel/levels/${levelId}/governance-rules/${id}/toggle`, {});
305
+ return handleApiRequest({
306
+ ctx,
307
+ key: GovernanceActionKey.ToggleRuleActive,
308
+ request$: req$,
309
+ onSuccess: (response, state) => {
310
+ const updatedRule = response.data;
311
+ if (!updatedRule)
312
+ return {};
313
+ return {
314
+ rules: this.adapter.upsertOne(state.rules, updatedRule, 'id'),
315
+ };
316
+ },
317
+ });
318
+ }
319
+ // ============================================================================
320
+ // Reference Data Actions
321
+ // ============================================================================
322
+ getModules(ctx) {
323
+ const { levelId } = ctx.getState();
324
+ if (!levelId) {
325
+ return;
326
+ }
327
+ const req$ = this.http.get(`Modules?LevelId=${levelId}`);
328
+ return handleApiRequest({
329
+ ctx,
330
+ key: GovernanceActionKey.GetModules,
331
+ request$: req$,
332
+ onSuccess: (response) => ({
333
+ // Only keep active modules for Target Module selection
334
+ modules: (response.data ?? []).filter((m) => m.isActive),
335
+ }),
336
+ });
337
+ }
338
+ clearSelectedRule(ctx) {
339
+ ctx.patchState({ selectedRule: null });
340
+ }
341
+ // ============================================================================
342
+ // Request Schema & Properties Actions (for optionsSource)
343
+ // ============================================================================
344
+ getRequestSchemas(ctx, { targetScope, targetModuleKey }) {
345
+ const { levelId, modules } = ctx.getState();
346
+ if (!levelId) {
347
+ return;
348
+ }
349
+ // Build endpoint based on scope
350
+ // Level scope: ProcessBuilder/level/{levelId}/{moduleType}/{moduleId}/requestSchema
351
+ // Module scope: ProcessBuilder/level/{levelId}/module/{targetModuleId}/{moduleType}/{moduleId}/requestSchema
352
+ let basePath = `ProcessBuilder/level/${levelId}`;
353
+ // For Module scope, we need to find the module by key to get its ID
354
+ if (targetScope === 'Module' && targetModuleKey) {
355
+ const targetModule = modules.find((m) => m.key === targetModuleKey);
356
+ if (targetModule) {
357
+ basePath += `/module/${targetModule.id}`;
358
+ }
359
+ }
360
+ // Get request schemas (assuming a common endpoint pattern)
361
+ const req$ = this.http.get(`${basePath}/requestSchemas`);
362
+ return handleApiRequest({
363
+ ctx,
364
+ key: GovernanceActionKey.GetRequestSchemas,
365
+ request$: req$,
366
+ onSuccess: (response) => ({
367
+ requestSchemas: (response.data ?? []).filter((s) => s.isPublished),
368
+ }),
369
+ });
370
+ }
371
+ getProperties(ctx, { targetScope, targetModuleKey }) {
372
+ const { levelId, modules } = ctx.getState();
373
+ if (!levelId) {
374
+ return;
375
+ }
376
+ // Build endpoint based on scope
377
+ let basePath = `Properties?LevelId=${levelId}`;
378
+ // For Module scope, add module filter
379
+ if (targetScope === 'Module' && targetModuleKey) {
380
+ const targetModule = modules.find((m) => m.key === targetModuleKey);
381
+ if (targetModule) {
382
+ basePath = `Properties?LevelId=${levelId}&ModuleId=${targetModule.id}`;
383
+ }
384
+ }
385
+ const req$ = this.http.get(basePath);
386
+ return handleApiRequest({
387
+ ctx,
388
+ key: GovernanceActionKey.GetProperties,
389
+ request$: req$,
390
+ onSuccess: (response) => ({
391
+ properties: response.data ?? [],
392
+ }),
393
+ });
394
+ }
395
+ clearRequestSchemas(ctx) {
396
+ ctx.patchState({ requestSchemas: [] });
397
+ }
398
+ clearProperties(ctx) {
399
+ ctx.patchState({ properties: [] });
400
+ }
401
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GovernanceState, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
402
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GovernanceState });
403
+ };
404
+ __decorate([
405
+ Action(SetLevelId)
406
+ ], GovernanceState.prototype, "setLevelId", null);
407
+ __decorate([
408
+ Action(ResetGovernanceState)
409
+ ], GovernanceState.prototype, "resetState", null);
410
+ __decorate([
411
+ Action(GetGovernanceRules)
412
+ ], GovernanceState.prototype, "getRules", null);
413
+ __decorate([
414
+ Action(GetGovernanceRule)
415
+ ], GovernanceState.prototype, "getRule", null);
416
+ __decorate([
417
+ Action(GetGovernanceRuleTypes)
418
+ ], GovernanceState.prototype, "getRuleTypes", null);
419
+ __decorate([
420
+ Action(AddGovernanceRule)
421
+ ], GovernanceState.prototype, "addRule", null);
422
+ __decorate([
423
+ Action(UpdateGovernanceRule)
424
+ ], GovernanceState.prototype, "updateRule", null);
425
+ __decorate([
426
+ Action(DeleteGovernanceRule)
427
+ ], GovernanceState.prototype, "deleteRule", null);
428
+ __decorate([
429
+ Action(ToggleGovernanceRuleActive)
430
+ ], GovernanceState.prototype, "toggleRuleActive", null);
431
+ __decorate([
432
+ Action(GetModules)
433
+ ], GovernanceState.prototype, "getModules", null);
434
+ __decorate([
435
+ Action(ClearSelectedRule)
436
+ ], GovernanceState.prototype, "clearSelectedRule", null);
437
+ __decorate([
438
+ Action(GetRequestSchemas)
439
+ ], GovernanceState.prototype, "getRequestSchemas", null);
440
+ __decorate([
441
+ Action(GetProperties)
442
+ ], GovernanceState.prototype, "getProperties", null);
443
+ __decorate([
444
+ Action(ClearRequestSchemas)
445
+ ], GovernanceState.prototype, "clearRequestSchemas", null);
446
+ __decorate([
447
+ Action(ClearProperties)
448
+ ], GovernanceState.prototype, "clearProperties", null);
449
+ __decorate([
450
+ Selector()
451
+ ], GovernanceState, "getLevelId", null);
452
+ __decorate([
453
+ Selector()
454
+ ], GovernanceState, "getRules", null);
455
+ __decorate([
456
+ Selector()
457
+ ], GovernanceState, "getRuleTypes", null);
458
+ __decorate([
459
+ Selector()
460
+ ], GovernanceState, "getSelectedRule", null);
461
+ __decorate([
462
+ Selector()
463
+ ], GovernanceState, "getModules", null);
464
+ __decorate([
465
+ Selector()
466
+ ], GovernanceState, "getRequestSchemas", null);
467
+ __decorate([
468
+ Selector()
469
+ ], GovernanceState, "getProperties", null);
470
+ __decorate([
471
+ Selector()
472
+ ], GovernanceState, "getLoadingActive", null);
473
+ __decorate([
474
+ Selector()
475
+ ], GovernanceState, "getErrors", null);
476
+ GovernanceState = __decorate([
477
+ State({
478
+ name: 'governance',
479
+ defaults: DEFAULTS,
480
+ })
481
+ ], GovernanceState);
482
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GovernanceState, decorators: [{
483
+ type: Injectable
484
+ }], propDecorators: { setLevelId: [], resetState: [], getRules: [], getRule: [], getRuleTypes: [], addRule: [], updateRule: [], deleteRule: [], toggleRuleActive: [], getModules: [], clearSelectedRule: [], getRequestSchemas: [], getProperties: [], clearRequestSchemas: [], clearProperties: [] } });
485
+
486
+ class GovernanceFacade {
487
+ store = inject(Store);
488
+ // ============================================================================
489
+ // Data Selectors - Memoized by NGXS (fine-grained reactivity)
490
+ // ============================================================================
491
+ levelId = select(GovernanceState.getLevelId);
492
+ rules = select(GovernanceState.getRules);
493
+ ruleTypes = select(GovernanceState.getRuleTypes);
494
+ selectedRule = select(GovernanceState.getSelectedRule);
495
+ modules = select(GovernanceState.getModules);
496
+ requestSchemas = select(GovernanceState.getRequestSchemas);
497
+ properties = select(GovernanceState.getProperties);
498
+ // ============================================================================
499
+ // Loading/Error Slices - Memoized by NGXS
500
+ // ============================================================================
501
+ loadingActive = select(GovernanceState.getLoadingActive);
502
+ errors = select(GovernanceState.getErrors);
503
+ // ============================================================================
504
+ // Loading Signals - Computed from slice (minimal reactivity)
505
+ // ============================================================================
506
+ isLoadingRules = computed(() => this.loadingActive().includes(GovernanceActionKey.GetRules), ...(ngDevMode ? [{ debugName: "isLoadingRules" }] : []));
507
+ isLoadingRule = computed(() => this.loadingActive().includes(GovernanceActionKey.GetRule), ...(ngDevMode ? [{ debugName: "isLoadingRule" }] : []));
508
+ isLoadingRuleTypes = computed(() => this.loadingActive().includes(GovernanceActionKey.GetRuleTypes), ...(ngDevMode ? [{ debugName: "isLoadingRuleTypes" }] : []));
509
+ isAddingRule = computed(() => this.loadingActive().includes(GovernanceActionKey.AddRule), ...(ngDevMode ? [{ debugName: "isAddingRule" }] : []));
510
+ isUpdatingRule = computed(() => this.loadingActive().includes(GovernanceActionKey.UpdateRule), ...(ngDevMode ? [{ debugName: "isUpdatingRule" }] : []));
511
+ isDeletingRule = computed(() => this.loadingActive().includes(GovernanceActionKey.DeleteRule), ...(ngDevMode ? [{ debugName: "isDeletingRule" }] : []));
512
+ isTogglingRule = computed(() => this.loadingActive().includes(GovernanceActionKey.ToggleRuleActive), ...(ngDevMode ? [{ debugName: "isTogglingRule" }] : []));
513
+ isLoadingModules = computed(() => this.loadingActive().includes(GovernanceActionKey.GetModules), ...(ngDevMode ? [{ debugName: "isLoadingModules" }] : []));
514
+ isLoadingRequestSchemas = computed(() => this.loadingActive().includes(GovernanceActionKey.GetRequestSchemas), ...(ngDevMode ? [{ debugName: "isLoadingRequestSchemas" }] : []));
515
+ isLoadingProperties = computed(() => this.loadingActive().includes(GovernanceActionKey.GetProperties), ...(ngDevMode ? [{ debugName: "isLoadingProperties" }] : []));
516
+ // ============================================================================
517
+ // Error Signals - Computed from slice (minimal reactivity)
518
+ // ============================================================================
519
+ rulesError = computed(() => this.errors()[GovernanceActionKey.GetRules] ?? null, ...(ngDevMode ? [{ debugName: "rulesError" }] : []));
520
+ ruleError = computed(() => this.errors()[GovernanceActionKey.GetRule] ?? null, ...(ngDevMode ? [{ debugName: "ruleError" }] : []));
521
+ ruleTypesError = computed(() => this.errors()[GovernanceActionKey.GetRuleTypes] ?? null, ...(ngDevMode ? [{ debugName: "ruleTypesError" }] : []));
522
+ addRuleError = computed(() => this.errors()[GovernanceActionKey.AddRule] ?? null, ...(ngDevMode ? [{ debugName: "addRuleError" }] : []));
523
+ updateRuleError = computed(() => this.errors()[GovernanceActionKey.UpdateRule] ?? null, ...(ngDevMode ? [{ debugName: "updateRuleError" }] : []));
524
+ deleteRuleError = computed(() => this.errors()[GovernanceActionKey.DeleteRule] ?? null, ...(ngDevMode ? [{ debugName: "deleteRuleError" }] : []));
525
+ modulesError = computed(() => this.errors()[GovernanceActionKey.GetModules] ?? null, ...(ngDevMode ? [{ debugName: "modulesError" }] : []));
526
+ requestSchemasError = computed(() => this.errors()[GovernanceActionKey.GetRequestSchemas] ?? null, ...(ngDevMode ? [{ debugName: "requestSchemasError" }] : []));
527
+ propertiesError = computed(() => this.errors()[GovernanceActionKey.GetProperties] ?? null, ...(ngDevMode ? [{ debugName: "propertiesError" }] : []));
528
+ // ============================================================================
529
+ // Derived Data - Computed from data selectors
530
+ // ============================================================================
531
+ activeRules = computed(() => this.rules().filter((r) => r.isActive === true), ...(ngDevMode ? [{ debugName: "activeRules" }] : []));
532
+ inactiveRules = computed(() => this.rules().filter((r) => r.isActive === false), ...(ngDevMode ? [{ debugName: "inactiveRules" }] : []));
533
+ rulesCount = computed(() => this.rules().length, ...(ngDevMode ? [{ debugName: "rulesCount" }] : []));
534
+ // ============================================================================
535
+ // Action Dispatchers
536
+ // ============================================================================
537
+ setLevelId(levelId) {
538
+ return this.store.dispatch(new SetLevelId(levelId));
539
+ }
540
+ getRules() {
541
+ return this.store.dispatch(new GetGovernanceRules());
542
+ }
543
+ getRule(id) {
544
+ return this.store.dispatch(new GetGovernanceRule(id));
545
+ }
546
+ getRuleTypes() {
547
+ return this.store.dispatch(new GetGovernanceRuleTypes());
548
+ }
549
+ getModules() {
550
+ return this.store.dispatch(new GetModules());
551
+ }
552
+ addRule(rule) {
553
+ return this.store.dispatch(new AddGovernanceRule(rule));
554
+ }
555
+ updateRule(id, rule) {
556
+ return this.store.dispatch(new UpdateGovernanceRule(id, rule));
557
+ }
558
+ deleteRule(id) {
559
+ return this.store.dispatch(new DeleteGovernanceRule(id));
560
+ }
561
+ toggleRuleActive(id) {
562
+ return this.store.dispatch(new ToggleGovernanceRuleActive(id));
563
+ }
564
+ clearSelectedRule() {
565
+ return this.store.dispatch(new ClearSelectedRule());
566
+ }
567
+ resetState() {
568
+ return this.store.dispatch(new ResetGovernanceState());
569
+ }
570
+ // ============================================================================
571
+ // Request Schema & Properties Actions (for optionsSource)
572
+ // ============================================================================
573
+ getRequestSchemas(targetScope, targetModuleKey) {
574
+ return this.store.dispatch(new GetRequestSchemas(targetScope, targetModuleKey));
575
+ }
576
+ getProperties(targetScope, targetModuleKey) {
577
+ return this.store.dispatch(new GetProperties(targetScope, targetModuleKey));
578
+ }
579
+ clearRequestSchemas() {
580
+ return this.store.dispatch(new ClearRequestSchemas());
581
+ }
582
+ clearProperties() {
583
+ return this.store.dispatch(new ClearProperties());
584
+ }
585
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GovernanceFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
586
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GovernanceFacade, providedIn: 'root' });
587
+ }
588
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GovernanceFacade, decorators: [{
589
+ type: Injectable,
590
+ args: [{ providedIn: 'root' }]
591
+ }] });
592
+
593
+ class GovernanceRuleForm {
594
+ // ============================================================================
595
+ // Injected Services
596
+ // ============================================================================
597
+ modal = inject(ModalService);
598
+ ref = inject(ModalRef);
599
+ translocoService = inject(TranslocoService);
600
+ facade = inject(GovernanceFacade);
601
+ // ============================================================================
602
+ // Input - rule to edit (null for create)
603
+ // ============================================================================
604
+ ruleForEdit = input(null, ...(ngDevMode ? [{ debugName: "ruleForEdit" }] : []));
605
+ // ============================================================================
606
+ // Facade Data
607
+ // ============================================================================
608
+ selectedRule = this.facade.selectedRule;
609
+ ruleTypes = this.facade.ruleTypes;
610
+ isLoadingRule = this.facade.isLoadingRule;
611
+ isAddingRule = this.facade.isAddingRule;
612
+ isUpdatingRule = this.facade.isUpdatingRule;
613
+ // For optionsSource: 'auto-populated' (modules from API)
614
+ modules = this.facade.modules;
615
+ // For optionsSource: 'requestSchema' and 'properties'
616
+ requestSchemas = this.facade.requestSchemas;
617
+ properties = this.facade.properties;
618
+ isLoadingRequestSchemas = this.facade.isLoadingRequestSchemas;
619
+ isLoadingProperties = this.facade.isLoadingProperties;
620
+ // ============================================================================
621
+ // Form Control
622
+ // ============================================================================
623
+ ruleFormControl = new FormControl();
624
+ formValue = toSignal(this.ruleFormControl.valueChanges);
625
+ // ============================================================================
626
+ // Selected Rule Type (from form value)
627
+ // ============================================================================
628
+ selectedRuleType = computed(() => {
629
+ const formValue = this.formValue();
630
+ const ruleTypeKey = formValue?.ruleType;
631
+ if (!ruleTypeKey)
632
+ return null;
633
+ return this.ruleTypes().find((rt) => rt.type === ruleTypeKey) ?? null;
634
+ }, ...(ngDevMode ? [{ debugName: "selectedRuleType" }] : []));
635
+ // ============================================================================
636
+ // Target Scope and Module Key (from form value)
637
+ // ============================================================================
638
+ targetScope = computed(() => this.formValue()?.targetScope ?? 'Level', ...(ngDevMode ? [{ debugName: "targetScope" }] : []));
639
+ targetModuleKey = computed(() => this.formValue()?.targetModuleKey ?? null, ...(ngDevMode ? [{ debugName: "targetModuleKey" }] : []));
640
+ // ============================================================================
641
+ // Options from state for optionsSource: 'requestSchema'
642
+ // ============================================================================
643
+ requestSchemaOptions = computed(() => {
644
+ const lang = this.translocoService.getActiveLang();
645
+ return this.requestSchemas().map((schema) => ({
646
+ label: schema.name[lang] || schema.name.en,
647
+ value: schema.id.toString(),
648
+ }));
649
+ }, ...(ngDevMode ? [{ debugName: "requestSchemaOptions" }] : []));
650
+ // ============================================================================
651
+ // Options from state for optionsSource: 'properties'
652
+ // ============================================================================
653
+ propertyOptions = computed(() => {
654
+ const lang = this.translocoService.getActiveLang();
655
+ return this.properties().map((prop) => ({
656
+ label: prop.name[lang] || prop.name.en,
657
+ value: prop.key,
658
+ }));
659
+ }, ...(ngDevMode ? [{ debugName: "propertyOptions" }] : []));
660
+ // ============================================================================
661
+ // Module Options for optionsSource: 'auto-populated' (moduleKey, requiredModuleKey)
662
+ // ============================================================================
663
+ moduleOptions = computed(() => {
664
+ const lang = this.translocoService.getActiveLang();
665
+ return this.modules().map((mod) => ({
666
+ label: mod.name[lang] || mod.name.en,
667
+ value: mod.key,
668
+ }));
669
+ }, ...(ngDevMode ? [{ debugName: "moduleOptions" }] : []));
670
+ // ============================================================================
671
+ // Scope Options based on selected rule type
672
+ // ============================================================================
673
+ scopeOptions = computed(() => {
674
+ const t = (key) => this.translocoService.translate(`governance.scopes.${key.toLowerCase()}`);
675
+ const ruleType = this.selectedRuleType();
676
+ if (!ruleType) {
677
+ return [
678
+ { label: t('level'), value: 'Level' },
679
+ { label: t('module'), value: 'Module' },
680
+ { label: t('phasegate'), value: 'PhaseGate' },
681
+ ];
682
+ }
683
+ return ruleType.supportedScopes.map((scope) => ({
684
+ label: t(scope.toLowerCase()),
685
+ value: scope,
686
+ }));
687
+ }, ...(ngDevMode ? [{ debugName: "scopeOptions" }] : []));
688
+ // ============================================================================
689
+ // Operation Options based on selected rule type
690
+ // ============================================================================
691
+ operationOptions = computed(() => {
692
+ const t = (key) => this.translocoService.translate(`governance.operations.${key.toLowerCase()}`);
693
+ const ruleType = this.selectedRuleType();
694
+ if (!ruleType) {
695
+ return [
696
+ { label: t('all'), value: '' },
697
+ { label: t('create'), value: 'Create' },
698
+ { label: t('update'), value: 'Update' },
699
+ { label: t('delete'), value: 'Delete' },
700
+ ];
701
+ }
702
+ return [
703
+ { label: t('all'), value: '' },
704
+ ...ruleType.supportedOperations.map((op) => ({
705
+ label: t(op.toLowerCase()),
706
+ value: op,
707
+ })),
708
+ ];
709
+ }, ...(ngDevMode ? [{ debugName: "operationOptions" }] : []));
710
+ // ============================================================================
711
+ // Rule Type Options
712
+ // ============================================================================
713
+ ruleTypeOptions = computed(() => {
714
+ const lang = this.translocoService.getActiveLang();
715
+ return this.ruleTypes().map((rt) => ({
716
+ label: rt.name[lang] || rt.name.en,
717
+ value: rt.type,
718
+ }));
719
+ }, ...(ngDevMode ? [{ debugName: "ruleTypeOptions" }] : []));
720
+ // ============================================================================
721
+ // Dynamic Form Configuration
722
+ // ============================================================================
723
+ formConfig = computed(() => {
724
+ const t = (key) => this.translocoService.translate(`governance.${key}`);
725
+ const ruleType = this.selectedRuleType();
726
+ const isEdit = !!this.ruleForEdit()?.id;
727
+ return {
728
+ sections: [
729
+ // Section 1: Basic Information
730
+ {
731
+ key: 'basicInfo',
732
+ type: 'header',
733
+ label: t('basic-information'),
734
+ order: 1,
735
+ fields: [
736
+ new TextFieldConfig({
737
+ key: 'key',
738
+ label: t('rule-key'),
739
+ placeholder: 'e.g., charter-required',
740
+ validators: [
741
+ ValidatorConfig.required(),
742
+ ValidatorConfig.pattern('^[a-z0-9-]+$', 'Only lowercase letters, numbers and hyphens allowed'),
743
+ ],
744
+ order: 1,
745
+ colSpan: 6,
746
+ disabled: isEdit,
747
+ }),
748
+ new NumberFieldConfig({
749
+ key: 'priority',
750
+ label: t('priority'),
751
+ placeholder: '10',
752
+ validators: [ValidatorConfig.required()],
753
+ min: 0,
754
+ max: 1000,
755
+ order: 2,
756
+ colSpan: 6,
757
+ }),
758
+ new TextFieldConfig({
759
+ key: 'name_en',
760
+ label: t('name-en'),
761
+ placeholder: t('name-en-placeholder'),
762
+ validators: [ValidatorConfig.required()],
763
+ order: 3,
764
+ colSpan: 6,
765
+ }),
766
+ new TextFieldConfig({
767
+ key: 'name_ar',
768
+ label: t('name-ar'),
769
+ placeholder: t('name-ar-placeholder'),
770
+ validators: [ValidatorConfig.required()],
771
+ order: 4,
772
+ colSpan: 6,
773
+ }),
774
+ new TextareaFieldConfig({
775
+ key: 'description_en',
776
+ label: t('description-en'),
777
+ placeholder: t('description-en-placeholder'),
778
+ order: 5,
779
+ colSpan: 6,
780
+ }),
781
+ new TextareaFieldConfig({
782
+ key: 'description_ar',
783
+ label: t('description-ar'),
784
+ placeholder: t('description-ar-placeholder'),
785
+ order: 6,
786
+ colSpan: 6,
787
+ }),
788
+ new TextareaFieldConfig({
789
+ key: 'errorMessage_en',
790
+ label: t('error-message-en'),
791
+ placeholder: t('error-message-en-placeholder'),
792
+ validators: [ValidatorConfig.required()],
793
+ order: 7,
794
+ colSpan: 6,
795
+ }),
796
+ new TextareaFieldConfig({
797
+ key: 'errorMessage_ar',
798
+ label: t('error-message-ar'),
799
+ placeholder: t('error-message-ar-placeholder'),
800
+ validators: [ValidatorConfig.required()],
801
+ order: 8,
802
+ colSpan: 6,
803
+ }),
804
+ ],
805
+ },
806
+ // Section 2: Rule Target
807
+ {
808
+ key: 'ruleTarget',
809
+ type: 'header',
810
+ label: t('rule-target'),
811
+ order: 2,
812
+ fields: [
813
+ new SelectFieldConfig({
814
+ key: 'ruleType',
815
+ label: t('rule-type'),
816
+ options: this.ruleTypeOptions(),
817
+ optionLabel: 'label',
818
+ optionValue: 'value',
819
+ validators: [ValidatorConfig.required()],
820
+ order: 1,
821
+ colSpan: 6,
822
+ disabled: isEdit,
823
+ }),
824
+ new SelectFieldConfig({
825
+ key: 'targetScope',
826
+ label: t('target-scope'),
827
+ options: this.scopeOptions(),
828
+ optionLabel: 'label',
829
+ optionValue: 'value',
830
+ validators: [ValidatorConfig.required()],
831
+ order: 2,
832
+ colSpan: 6,
833
+ }),
834
+ new SelectFieldConfig({
835
+ key: 'targetModuleKey',
836
+ label: t('target-module'),
837
+ placeholder: t('select-target-module'),
838
+ options: this.moduleOptions(),
839
+ optionLabel: 'label',
840
+ optionValue: 'value',
841
+ order: 3,
842
+ colSpan: 6,
843
+ relations: [
844
+ {
845
+ key: 'targetScope',
846
+ value: 'Module',
847
+ action: 'show',
848
+ },
849
+ ],
850
+ }),
851
+ new SelectFieldConfig({
852
+ key: 'targetOperationKey',
853
+ label: t('target-operation'),
854
+ options: this.operationOptions(),
855
+ optionLabel: 'label',
856
+ optionValue: 'value',
857
+ order: 4,
858
+ colSpan: 6,
859
+ }),
860
+ ],
861
+ },
862
+ // Section 3: Rule-Specific Configuration (dynamic)
863
+ ...(ruleType ? [this.buildConfigurationSection(ruleType)] : []),
864
+ // Section 4: Execution Settings
865
+ {
866
+ key: 'executionSettings',
867
+ type: 'header',
868
+ label: t('execution-settings'),
869
+ order: 4,
870
+ fields: [
871
+ new ToggleFieldConfig({
872
+ key: 'stopOnFailure',
873
+ label: t('stop-on-failure'),
874
+ order: 1,
875
+ colSpan: 6,
876
+ }),
877
+ new ToggleFieldConfig({
878
+ key: 'isActive',
879
+ label: t('active-rule'),
880
+ order: 2,
881
+ colSpan: 6,
882
+ }),
883
+ ],
884
+ },
885
+ ],
886
+ };
887
+ }, ...(ngDevMode ? [{ debugName: "formConfig" }] : []));
888
+ // ============================================================================
889
+ // Constructor with Effect for Form Population
890
+ // ============================================================================
891
+ constructor() {
892
+ // Effect to populate form when editing existing rule
893
+ effect(() => {
894
+ const ruleId = this.ruleForEdit()?.id;
895
+ if (this.selectedRule() && ruleId) {
896
+ const rule = this.selectedRule();
897
+ if (!rule)
898
+ return;
899
+ // Unpack rule data to form format
900
+ const formData = this.unpackRuleToForm(rule);
901
+ this.ruleFormControl.patchValue(formData);
902
+ }
903
+ else {
904
+ // Default values for new rule
905
+ this.ruleFormControl.reset({
906
+ priority: 10,
907
+ stopOnFailure: true,
908
+ isActive: true,
909
+ targetScope: 'Module',
910
+ });
911
+ }
912
+ });
913
+ // Effect to apply default values when rule type changes (for new rules only)
914
+ effect(() => {
915
+ const ruleType = this.selectedRuleType();
916
+ const ruleId = this.ruleForEdit()?.id;
917
+ // Only apply defaults for new rules (not editing)
918
+ if (ruleType && !ruleId) {
919
+ const defaults = this.getDefaultsFromSchema(ruleType);
920
+ if (Object.keys(defaults).length > 0) {
921
+ const currentValue = this.ruleFormControl.value ?? {};
922
+ this.ruleFormControl.patchValue({ ...currentValue, ...defaults });
923
+ }
924
+ }
925
+ });
926
+ // Effect to fetch requestSchemas and properties when scope/module changes
927
+ // This runs when configurationSchema has fields with optionsSource = 'requestSchema' or 'properties'
928
+ effect(() => {
929
+ const ruleType = this.selectedRuleType();
930
+ const scope = this.targetScope();
931
+ const moduleKey = this.targetModuleKey();
932
+ if (!ruleType)
933
+ return;
934
+ // Check if any field needs requestSchema options
935
+ const needsRequestSchemas = ruleType.configurationSchema.some((f) => f.optionsSource === 'requestSchema');
936
+ // Check if any field needs properties options
937
+ const needsProperties = ruleType.configurationSchema.some((f) => f.optionsSource === 'properties');
938
+ // For Module scope, we need a target module key
939
+ if (scope === 'Module' && !moduleKey) {
940
+ // Clear options when module is not selected
941
+ if (needsRequestSchemas) {
942
+ this.facade.clearRequestSchemas();
943
+ }
944
+ if (needsProperties) {
945
+ this.facade.clearProperties();
946
+ }
947
+ return;
948
+ }
949
+ // Fetch options based on scope
950
+ if (needsRequestSchemas) {
951
+ this.facade.getRequestSchemas(scope, moduleKey ?? undefined);
952
+ }
953
+ if (needsProperties) {
954
+ this.facade.getProperties(scope, moduleKey ?? undefined);
955
+ }
956
+ });
957
+ }
958
+ /**
959
+ * Extract default values from rule type's configuration schema
960
+ */
961
+ getDefaultsFromSchema(ruleType) {
962
+ const defaults = {};
963
+ for (const field of ruleType.configurationSchema) {
964
+ if (field.defaultValue !== undefined) {
965
+ defaults[`config_${field.key}`] = field.defaultValue;
966
+ }
967
+ }
968
+ return defaults;
969
+ }
970
+ ngOnInit() {
971
+ const ruleId = this.ruleForEdit()?.id;
972
+ if (ruleId) {
973
+ this.facade.getRule(ruleId);
974
+ }
975
+ }
976
+ // ============================================================================
977
+ // Submit Handler
978
+ // ============================================================================
979
+ onSubmit() {
980
+ if (!this.ruleFormControl.valid) {
981
+ return;
982
+ }
983
+ const formValue = this.ruleFormControl.value;
984
+ const ruleId = this.ruleForEdit()?.id;
985
+ if (ruleId) {
986
+ // Update
987
+ const payload = this.packFormToUpdateDto(formValue);
988
+ this.facade.updateRule(ruleId, payload).subscribe({
989
+ next: () => {
990
+ this.ref.close(true);
991
+ },
992
+ error: () => { },
993
+ });
994
+ }
995
+ else {
996
+ // Create
997
+ const payload = this.packFormToCreateDto(formValue);
998
+ this.facade.addRule(payload).subscribe({
999
+ next: () => {
1000
+ this.ref.close(true);
1001
+ },
1002
+ error: () => { },
1003
+ });
1004
+ }
1005
+ }
1006
+ // ============================================================================
1007
+ // Build Configuration Section Based on Rule Type
1008
+ // ============================================================================
1009
+ buildConfigurationSection(ruleType) {
1010
+ const t = (key) => this.translocoService.translate(`governance.${key}`);
1011
+ return {
1012
+ key: 'configuration',
1013
+ type: 'header',
1014
+ label: t('rule-configuration'),
1015
+ order: 3,
1016
+ fields: this.buildConfigFieldsForType(ruleType),
1017
+ };
1018
+ }
1019
+ buildConfigFieldsForType(ruleType) {
1020
+ const lang = this.translocoService.getActiveLang();
1021
+ // Build fields dynamically from configurationSchema array
1022
+ return ruleType.configurationSchema.map((field, index) => this.schemaFieldToFormField(field, index + 1, lang));
1023
+ }
1024
+ /**
1025
+ * Convert a ConfigurationFieldSchema to DynamicForm BaseFieldConfig
1026
+ */
1027
+ schemaFieldToFormField(field, order, lang) {
1028
+ const label = field.label[lang] || field.label.en;
1029
+ const colSpan = field.colSpan ?? 6;
1030
+ const validators = field.required ? [ValidatorConfig.required()] : [];
1031
+ switch (field.type) {
1032
+ case 'text':
1033
+ return new TextFieldConfig({
1034
+ key: `config_${field.key}`,
1035
+ label,
1036
+ validators,
1037
+ order,
1038
+ colSpan,
1039
+ });
1040
+ case 'textarea':
1041
+ return new TextareaFieldConfig({
1042
+ key: `config_${field.key}`,
1043
+ label,
1044
+ validators,
1045
+ order,
1046
+ colSpan,
1047
+ });
1048
+ case 'number':
1049
+ return new NumberFieldConfig({
1050
+ key: `config_${field.key}`,
1051
+ label,
1052
+ validators,
1053
+ min: field.min,
1054
+ max: field.max,
1055
+ order,
1056
+ colSpan,
1057
+ });
1058
+ case 'select':
1059
+ return new SelectFieldConfig({
1060
+ key: `config_${field.key}`,
1061
+ label,
1062
+ options: this.getOptionsForField(field),
1063
+ optionLabel: 'label',
1064
+ optionValue: 'value',
1065
+ validators,
1066
+ order,
1067
+ colSpan,
1068
+ });
1069
+ case 'multi-select':
1070
+ return new MultiSelectFieldConfig({
1071
+ key: `config_${field.key}`,
1072
+ label,
1073
+ options: this.getOptionsForField(field),
1074
+ optionLabel: 'label',
1075
+ optionValue: 'value',
1076
+ validators,
1077
+ order,
1078
+ colSpan,
1079
+ });
1080
+ case 'checkbox':
1081
+ return new ToggleFieldConfig({
1082
+ key: `config_${field.key}`,
1083
+ label,
1084
+ order,
1085
+ colSpan,
1086
+ });
1087
+ case 'date':
1088
+ return new DateFieldConfig({
1089
+ key: `config_${field.key}`,
1090
+ label,
1091
+ validators,
1092
+ order,
1093
+ colSpan,
1094
+ });
1095
+ default:
1096
+ // Fallback to text field for unknown types
1097
+ return new TextFieldConfig({
1098
+ key: `config_${field.key}`,
1099
+ label,
1100
+ validators,
1101
+ order,
1102
+ colSpan,
1103
+ });
1104
+ }
1105
+ }
1106
+ /**
1107
+ * Get options for a field based on its optionsSource
1108
+ * - 'static' or 'auto-populated': Use options from schema (already in API response)
1109
+ * - 'requestSchema': Use fetched request schemas from state
1110
+ * - 'properties': Use fetched properties from state
1111
+ */
1112
+ getOptionsForField(field) {
1113
+ switch (field.optionsSource) {
1114
+ case 'requestSchema':
1115
+ return this.requestSchemaOptions();
1116
+ case 'properties':
1117
+ return this.propertyOptions();
1118
+ case 'auto-populated':
1119
+ case 'static':
1120
+ default:
1121
+ // Use options directly from schema
1122
+ return field.options ?? [];
1123
+ }
1124
+ }
1125
+ // ============================================================================
1126
+ // Data Transformation Helpers
1127
+ // ============================================================================
1128
+ unpackRuleToForm(rule) {
1129
+ const formData = {
1130
+ key: rule.key,
1131
+ priority: rule.priority,
1132
+ name_en: rule.name?.en ?? '',
1133
+ name_ar: rule.name?.ar ?? '',
1134
+ description_en: rule.description?.en ?? '',
1135
+ description_ar: rule.description?.ar ?? '',
1136
+ errorMessage_en: rule.errorMessage?.en ?? '',
1137
+ errorMessage_ar: rule.errorMessage?.ar ?? '',
1138
+ ruleType: rule.ruleTypeKey,
1139
+ targetScope: rule.targetScope,
1140
+ targetModuleKey: rule.targetModuleKey ?? '',
1141
+ targetOperationKey: rule.targetOperationKey ?? '',
1142
+ stopOnFailure: rule.stopOnFailure,
1143
+ isActive: rule.isActive,
1144
+ };
1145
+ // Unpack configuration fields with config_ prefix
1146
+ if (rule.configuration) {
1147
+ Object.entries(rule.configuration).forEach(([key, value]) => {
1148
+ formData[`config_${key}`] = value;
1149
+ });
1150
+ }
1151
+ return formData;
1152
+ }
1153
+ packFormToCreateDto(formValue) {
1154
+ return {
1155
+ key: formValue['key'],
1156
+ name: {
1157
+ en: formValue['name_en'],
1158
+ ar: formValue['name_ar'],
1159
+ },
1160
+ description: formValue['description_en'] || formValue['description_ar']
1161
+ ? {
1162
+ en: formValue['description_en'] ?? '',
1163
+ ar: formValue['description_ar'] ?? '',
1164
+ }
1165
+ : undefined,
1166
+ errorMessage: {
1167
+ en: formValue['errorMessage_en'],
1168
+ ar: formValue['errorMessage_ar'],
1169
+ },
1170
+ ruleType: formValue['ruleType'],
1171
+ targetScope: formValue['targetScope'],
1172
+ targetModuleKey: formValue['targetModuleKey'] || undefined,
1173
+ targetOperationKey: formValue['targetOperationKey'] || undefined,
1174
+ configuration: this.extractConfiguration(formValue),
1175
+ priority: formValue['priority'],
1176
+ stopOnFailure: formValue['stopOnFailure'] ?? true,
1177
+ };
1178
+ }
1179
+ packFormToUpdateDto(formValue) {
1180
+ return {
1181
+ ...this.packFormToCreateDto(formValue),
1182
+ isActive: formValue['isActive'] ?? true,
1183
+ };
1184
+ }
1185
+ extractConfiguration(formValue) {
1186
+ const config = {};
1187
+ Object.entries(formValue).forEach(([key, value]) => {
1188
+ if (key.startsWith('config_') &&
1189
+ value !== null &&
1190
+ value !== undefined &&
1191
+ value !== '') {
1192
+ const configKey = key.replace('config_', '');
1193
+ config[configKey] = value;
1194
+ }
1195
+ });
1196
+ return Object.keys(config).length > 0 ? config : undefined;
1197
+ }
1198
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GovernanceRuleForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
1199
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: GovernanceRuleForm, isStandalone: true, selector: "mt-governance-rule-form", inputs: { ruleForEdit: { classPropertyName: "ruleForEdit", publicName: "ruleForEdit", isSignal: true, isRequired: false, transformFunction: null } }, providers: [DialogService], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'governance'\">\r\n <div [class]=\"'flex flex-col gap-3 p-4 overflow-y-auto ' + modal.contentClass\">\r\n @if (isLoadingRule()) {\r\n <p-skeleton class=\"my-4 mt-7\" height=\"3rem\" />\r\n <p-skeleton class=\"my-4\" height=\"3rem\" />\r\n <p-skeleton class=\"my-4\" height=\"6rem\" />\r\n <p-skeleton class=\"my-4\" height=\"3rem\" />\r\n <p-skeleton class=\"my-4\" height=\"3rem\" />\r\n } @else {\r\n <mt-dynamic-form\r\n [formConfig]=\"formConfig()\"\r\n [formControl]=\"ruleFormControl\"\r\n />\r\n }\r\n </div>\r\n\r\n <div [class]=\"modal.footerClass\">\r\n <mt-button\r\n [label]=\"'cancel' | transloco\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n (click)=\"ref.close()\"\r\n />\r\n <mt-button\r\n [label]=\"ruleForEdit() ? t('update') : t('create')\"\r\n [loading]=\"isAddingRule() || isUpdatingRule()\"\r\n [disabled]=\"!ruleFormControl.valid\"\r\n (click)=\"onSubmit()\"\r\n />\r\n </div>\r\n</ng-container>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
1200
+ }
1201
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GovernanceRuleForm, decorators: [{
1202
+ type: Component,
1203
+ args: [{ selector: 'mt-governance-rule-form', standalone: true, imports: [
1204
+ CommonModule,
1205
+ Button,
1206
+ TranslocoDirective,
1207
+ SkeletonModule,
1208
+ DynamicForm,
1209
+ ReactiveFormsModule,
1210
+ TranslocoPipe,
1211
+ ], providers: [DialogService], template: "<ng-container *transloco=\"let t; prefix: 'governance'\">\r\n <div [class]=\"'flex flex-col gap-3 p-4 overflow-y-auto ' + modal.contentClass\">\r\n @if (isLoadingRule()) {\r\n <p-skeleton class=\"my-4 mt-7\" height=\"3rem\" />\r\n <p-skeleton class=\"my-4\" height=\"3rem\" />\r\n <p-skeleton class=\"my-4\" height=\"6rem\" />\r\n <p-skeleton class=\"my-4\" height=\"3rem\" />\r\n <p-skeleton class=\"my-4\" height=\"3rem\" />\r\n } @else {\r\n <mt-dynamic-form\r\n [formConfig]=\"formConfig()\"\r\n [formControl]=\"ruleFormControl\"\r\n />\r\n }\r\n </div>\r\n\r\n <div [class]=\"modal.footerClass\">\r\n <mt-button\r\n [label]=\"'cancel' | transloco\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n (click)=\"ref.close()\"\r\n />\r\n <mt-button\r\n [label]=\"ruleForEdit() ? t('update') : t('create')\"\r\n [loading]=\"isAddingRule() || isUpdatingRule()\"\r\n [disabled]=\"!ruleFormControl.valid\"\r\n (click)=\"onSubmit()\"\r\n />\r\n </div>\r\n</ng-container>\r\n" }]
1212
+ }], ctorParameters: () => [], propDecorators: { ruleForEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "ruleForEdit", required: false }] }] } });
1213
+
1214
+ class GovernanceRulesList {
1215
+ // ============================================================================
1216
+ // Input - levelId from parent page
1217
+ // ============================================================================
1218
+ levelId = input.required(...(ngDevMode ? [{ debugName: "levelId" }] : []));
1219
+ // ============================================================================
1220
+ // Template References for Custom Columns
1221
+ // ============================================================================
1222
+ typeCol = viewChild.required('typeCol');
1223
+ scopeCol = viewChild.required('scopeCol');
1224
+ priorityCol = viewChild.required('priorityCol');
1225
+ // ============================================================================
1226
+ // Services
1227
+ // ============================================================================
1228
+ facade = inject(GovernanceFacade);
1229
+ modal = inject(ModalService);
1230
+ translocoService = inject(TranslocoService);
1231
+ // ============================================================================
1232
+ // Breadcrumb
1233
+ // ============================================================================
1234
+ breadcrumbItems = linkedSignal(() => [
1235
+ {
1236
+ label: '',
1237
+ icon: 'general.home-line',
1238
+ routerLink: '/control-panel/workspaces',
1239
+ },
1240
+ {
1241
+ label: this.translocoService.translate('governance.control-panel'),
1242
+ routerLink: '/control-panel',
1243
+ },
1244
+ {
1245
+ label: this.translocoService.translate('governance.governance-rules'),
1246
+ },
1247
+ ], ...(ngDevMode ? [{ debugName: "breadcrumbItems" }] : []));
1248
+ // ============================================================================
1249
+ // Data Computed from Facade
1250
+ // ============================================================================
1251
+ rules = computed(() => {
1252
+ const tab = this.activeTab();
1253
+ const all = this.allRules();
1254
+ const activeRules = this.activeRules();
1255
+ const inactiveRules = this.inactiveRules();
1256
+ switch (tab) {
1257
+ case 'active':
1258
+ return activeRules;
1259
+ case 'inactive':
1260
+ return inactiveRules;
1261
+ case 'all':
1262
+ default:
1263
+ return all;
1264
+ }
1265
+ }, ...(ngDevMode ? [{ debugName: "rules" }] : []));
1266
+ // ============================================================================
1267
+ // Tabs
1268
+ // ============================================================================
1269
+ tabs = signal([
1270
+ {
1271
+ label: this.translocoService.translate('governance.all'),
1272
+ value: 'all',
1273
+ },
1274
+ {
1275
+ label: this.translocoService.translate('governance.active'),
1276
+ value: 'active',
1277
+ },
1278
+ {
1279
+ label: this.translocoService.translate('governance.inactive'),
1280
+ value: 'inactive',
1281
+ },
1282
+ ], ...(ngDevMode ? [{ debugName: "tabs" }] : []));
1283
+ activeTab = signal('all', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
1284
+ // ============================================================================
1285
+ // Table Actions
1286
+ // ============================================================================
1287
+ tableActions = signal([
1288
+ {
1289
+ icon: 'general.plus',
1290
+ label: this.translocoService.translate('governance.add-rule'),
1291
+ color: 'primary',
1292
+ action: () => {
1293
+ this.openRuleDialog();
1294
+ },
1295
+ },
1296
+ ], ...(ngDevMode ? [{ debugName: "tableActions" }] : []));
1297
+ deletingRowIds = signal([], ...(ngDevMode ? [{ debugName: "deletingRowIds" }] : []));
1298
+ rowActions = signal([
1299
+ {
1300
+ icon: 'custom.pencil',
1301
+ tooltip: this.translocoService.translate('edit'),
1302
+ color: 'primary',
1303
+ action: (row) => {
1304
+ this.facade.clearSelectedRule();
1305
+ this.openRuleDialog(row);
1306
+ },
1307
+ },
1308
+ {
1309
+ icon: 'general.trash-01',
1310
+ tooltip: this.translocoService.translate('delete'),
1311
+ color: 'danger',
1312
+ variant: 'outlined',
1313
+ action: (row) => {
1314
+ this.deletingRowIds.update((ids) => [...ids, row.id]);
1315
+ this.facade
1316
+ .deleteRule(row.id)
1317
+ .pipe(finalize(() => {
1318
+ this.deletingRowIds.update((ids) => ids.filter((id) => id !== row.id));
1319
+ }))
1320
+ .subscribe();
1321
+ },
1322
+ confirmation: {
1323
+ type: 'popup',
1324
+ confirmationType: 'delete',
1325
+ },
1326
+ loading: (row) => this.deletingRowIds().includes(row.id),
1327
+ },
1328
+ ], ...(ngDevMode ? [{ debugName: "rowActions" }] : []));
1329
+ // ============================================================================
1330
+ // Table Columns
1331
+ // ============================================================================
1332
+ tableColumns = linkedSignal(() => [
1333
+ {
1334
+ key: 'priority',
1335
+ label: this.translocoService.translate('governance.priority'),
1336
+ type: 'custom',
1337
+ customCellTpl: this.priorityCol(),
1338
+ sortable: true,
1339
+ },
1340
+ {
1341
+ key: 'name.en',
1342
+ label: this.translocoService.translate('governance.name'),
1343
+ type: 'text',
1344
+ sortable: true,
1345
+ },
1346
+ {
1347
+ key: 'ruleTypeKey',
1348
+ label: this.translocoService.translate('governance.rule-type'),
1349
+ type: 'custom',
1350
+ customCellTpl: this.typeCol(),
1351
+ filterConfig: {
1352
+ type: 'select',
1353
+ label: this.translocoService.translate('governance.rule-type'),
1354
+ options: this.getRuleTypeOptions(),
1355
+ },
1356
+ },
1357
+ {
1358
+ key: 'targetScope',
1359
+ label: this.translocoService.translate('governance.scope'),
1360
+ type: 'custom',
1361
+ customCellTpl: this.scopeCol(),
1362
+ filterConfig: {
1363
+ type: 'select',
1364
+ label: this.translocoService.translate('governance.scope'),
1365
+ options: [
1366
+ { label: 'Level', value: 'Level' },
1367
+ { label: 'Module', value: 'Module' },
1368
+ { label: 'PhaseGate', value: 'PhaseGate' },
1369
+ ],
1370
+ },
1371
+ },
1372
+ {
1373
+ key: 'targetModuleKey',
1374
+ label: this.translocoService.translate('governance.target-module'),
1375
+ type: 'text',
1376
+ },
1377
+ {
1378
+ key: 'isActive',
1379
+ label: this.translocoService.translate('governance.status'),
1380
+ type: 'boolean',
1381
+ filterConfig: {
1382
+ type: 'select',
1383
+ label: this.translocoService.translate('governance.status'),
1384
+ options: [
1385
+ {
1386
+ label: this.translocoService.translate('governance.active'),
1387
+ value: true,
1388
+ },
1389
+ {
1390
+ label: this.translocoService.translate('governance.inactive'),
1391
+ value: false,
1392
+ },
1393
+ ],
1394
+ },
1395
+ },
1396
+ ], ...(ngDevMode ? [{ debugName: "tableColumns" }] : []));
1397
+ // ============================================================================
1398
+ // Private
1399
+ // ============================================================================
1400
+ loading = this.facade.isLoadingRules;
1401
+ allRules = this.facade.rules;
1402
+ activeRules = this.facade.activeRules;
1403
+ inactiveRules = this.facade.inactiveRules;
1404
+ ngOnDestroy() {
1405
+ this.facade.resetState();
1406
+ }
1407
+ openRuleDialog(rule = null) {
1408
+ const modalType = rule ? 'drawer' : 'drawer';
1409
+ this.modal.openModal(GovernanceRuleForm, modalType, {
1410
+ header: rule
1411
+ ? this.translocoService.translate('governance.edit-rule')
1412
+ : this.translocoService.translate('governance.add-rule'),
1413
+ styleClass: '!w-[50rem] !absolute ',
1414
+ position: modalType === 'drawer' ? 'end' : '',
1415
+ appendTo: modalType === 'drawer' ? 'page-content' : 'body',
1416
+ dismissableMask: true,
1417
+ dismissible: true,
1418
+ inputValues: {
1419
+ ruleForEdit: rule,
1420
+ },
1421
+ });
1422
+ }
1423
+ onCellChange(event) {
1424
+ if (event.column === 'isActive' && event.type === 'boolean') {
1425
+ this.facade.toggleRuleActive(event.row.id);
1426
+ }
1427
+ }
1428
+ getRuleTypeOptions() {
1429
+ return [
1430
+ { label: 'Module Exists', value: 'ModuleExists' },
1431
+ { label: 'Module Does Not Exist', value: 'ModuleDoesNotExist' },
1432
+ { label: 'Module Max Count', value: 'ModuleMaxCount' },
1433
+ { label: 'Module Min Count', value: 'ModuleMinCount' },
1434
+ { label: 'Field Required', value: 'FieldRequired' },
1435
+ { label: 'Field Value', value: 'FieldValue' },
1436
+ { label: 'Phase Gate Module Required', value: 'PhaseGateModuleRequired' },
1437
+ { label: 'No Active Request', value: 'NoActiveRequest' },
1438
+ ];
1439
+ }
1440
+ getRuleTypeChipClass(ruleTypeKey) {
1441
+ const classes = {
1442
+ ModuleExists: 'bg-blue-100 text-blue-700',
1443
+ ModuleDoesNotExist: 'bg-red-100 text-red-700',
1444
+ ModuleMaxCount: 'bg-amber-100 text-amber-700',
1445
+ ModuleMinCount: 'bg-orange-100 text-orange-700',
1446
+ FieldRequired: 'bg-purple-100 text-purple-700',
1447
+ FieldValue: 'bg-indigo-100 text-indigo-700',
1448
+ PhaseGateModuleRequired: 'bg-green-100 text-green-700',
1449
+ NoActiveRequest: 'bg-rose-100 text-rose-700',
1450
+ };
1451
+ return classes[ruleTypeKey] ?? 'bg-slate-100 text-slate-700';
1452
+ }
1453
+ getScopeIcon(scope) {
1454
+ const icons = {
1455
+ Level: 'general.layers-three-01',
1456
+ Module: 'general.cube-01',
1457
+ PhaseGate: 'general.flag-01',
1458
+ };
1459
+ return icons[scope] ?? 'general.file-02';
1460
+ }
1461
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GovernanceRulesList, deps: [], target: i0.ɵɵFactoryTarget.Component });
1462
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: GovernanceRulesList, isStandalone: true, selector: "mt-governance-rules-list", inputs: { levelId: { classPropertyName: "levelId", publicName: "levelId", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "typeCol", first: true, predicate: ["typeCol"], descendants: true, isSignal: true }, { propertyName: "scopeCol", first: true, predicate: ["scopeCol"], descendants: true, isSignal: true }, { propertyName: "priorityCol", first: true, predicate: ["priorityCol"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'governance'\">\r\n <div class=\"space-y-4\">\r\n <div class=\"flex items-center justify-between\">\r\n <div class=\"space-y-1\">\r\n <h1 class=\"text-xl font-semibold text-slate-900 tracking-tight\">\r\n {{ t(\"governance-rules\") }}\r\n </h1>\r\n <mt-breadcrumb\r\n [items]=\"breadcrumbItems()\"\r\n [styleClass]=\"'flex justify-start mx-1'\"\r\n ></mt-breadcrumb>\r\n </div>\r\n </div>\r\n\r\n <!-- Rule Type Column Template -->\r\n <ng-template #typeCol let-row>\r\n <mt-chip\r\n [label]=\"row.ruleTypeKey\"\r\n [styleClass]=\"getRuleTypeChipClass(row.ruleTypeKey)\"\r\n />\r\n </ng-template>\r\n\r\n <!-- Scope Column Template -->\r\n <ng-template #scopeCol let-row>\r\n <div class=\"flex items-center gap-2\">\r\n <mt-icon\r\n class=\"text-lg\"\r\n [icon]=\"getScopeIcon(row.targetScope)\"\r\n ></mt-icon>\r\n <span>{{ row.targetScope }}</span>\r\n @if (row.targetModuleKey) {\r\n <span class=\"text-slate-500\">\u2192 {{ row.targetModuleKey }}</span>\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Priority Column Template -->\r\n <ng-template #priorityCol let-row>\r\n <div\r\n class=\"flex items-center justify-center w-8 h-8 rounded-full bg-slate-100 text-slate-700 font-semibold text-sm\"\r\n >\r\n {{ row.priority }}\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Table -->\r\n <mt-table\r\n [tabs]=\"tabs()\"\r\n [(activeTab)]=\"activeTab\"\r\n [data]=\"rules()\"\r\n [columns]=\"tableColumns()\"\r\n [actions]=\"tableActions()\"\r\n [rowActions]=\"rowActions()\"\r\n [generalSearch]=\"true\"\r\n [showFilters]=\"true\"\r\n [loading]=\"loading()\"\r\n (cellChange)=\"onCellChange($event)\"\r\n >\r\n </mt-table>\r\n </div>\r\n</ng-container>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "generalSearch", "showFilters", "loading", "updating", "lazy", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "exportable", "exportFilename", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "pageSize", "currentPage", "first", "filterTerm"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Breadcrumb, selector: "mt-breadcrumb", inputs: ["items", "styleClass"], outputs: ["onItemClick"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: Chip, selector: "mt-chip", inputs: ["label", "icon", "image", "removable", "removeIcon", "styleClass"], outputs: ["onRemove", "onImageError"] }] });
1463
+ }
1464
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GovernanceRulesList, decorators: [{
1465
+ type: Component,
1466
+ args: [{ selector: 'mt-governance-rules-list', standalone: true, imports: [
1467
+ CommonModule,
1468
+ SkeletonModule,
1469
+ Table,
1470
+ TranslocoDirective,
1471
+ Breadcrumb,
1472
+ Icon,
1473
+ Chip,
1474
+ ], template: "<ng-container *transloco=\"let t; prefix: 'governance'\">\r\n <div class=\"space-y-4\">\r\n <div class=\"flex items-center justify-between\">\r\n <div class=\"space-y-1\">\r\n <h1 class=\"text-xl font-semibold text-slate-900 tracking-tight\">\r\n {{ t(\"governance-rules\") }}\r\n </h1>\r\n <mt-breadcrumb\r\n [items]=\"breadcrumbItems()\"\r\n [styleClass]=\"'flex justify-start mx-1'\"\r\n ></mt-breadcrumb>\r\n </div>\r\n </div>\r\n\r\n <!-- Rule Type Column Template -->\r\n <ng-template #typeCol let-row>\r\n <mt-chip\r\n [label]=\"row.ruleTypeKey\"\r\n [styleClass]=\"getRuleTypeChipClass(row.ruleTypeKey)\"\r\n />\r\n </ng-template>\r\n\r\n <!-- Scope Column Template -->\r\n <ng-template #scopeCol let-row>\r\n <div class=\"flex items-center gap-2\">\r\n <mt-icon\r\n class=\"text-lg\"\r\n [icon]=\"getScopeIcon(row.targetScope)\"\r\n ></mt-icon>\r\n <span>{{ row.targetScope }}</span>\r\n @if (row.targetModuleKey) {\r\n <span class=\"text-slate-500\">\u2192 {{ row.targetModuleKey }}</span>\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Priority Column Template -->\r\n <ng-template #priorityCol let-row>\r\n <div\r\n class=\"flex items-center justify-center w-8 h-8 rounded-full bg-slate-100 text-slate-700 font-semibold text-sm\"\r\n >\r\n {{ row.priority }}\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Table -->\r\n <mt-table\r\n [tabs]=\"tabs()\"\r\n [(activeTab)]=\"activeTab\"\r\n [data]=\"rules()\"\r\n [columns]=\"tableColumns()\"\r\n [actions]=\"tableActions()\"\r\n [rowActions]=\"rowActions()\"\r\n [generalSearch]=\"true\"\r\n [showFilters]=\"true\"\r\n [loading]=\"loading()\"\r\n (cellChange)=\"onCellChange($event)\"\r\n >\r\n </mt-table>\r\n </div>\r\n</ng-container>\r\n" }]
1475
+ }], propDecorators: { levelId: [{ type: i0.Input, args: [{ isSignal: true, alias: "levelId", required: true }] }], typeCol: [{ type: i0.ViewChild, args: ['typeCol', { isSignal: true }] }], scopeCol: [{ type: i0.ViewChild, args: ['scopeCol', { isSignal: true }] }], priorityCol: [{ type: i0.ViewChild, args: ['priorityCol', { isSignal: true }] }] } });
1476
+
1477
+ /**
1478
+ * Generated bundle index. Do not edit.
1479
+ */
1480
+
1481
+ export { AddGovernanceRule, ClearProperties, ClearRequestSchemas, ClearSelectedRule, DeleteGovernanceRule, GetGovernanceRule, GetGovernanceRuleTypes, GetGovernanceRules, GetModules, GetProperties, GetRequestSchemas, GovernanceActionKey, GovernanceFacade, GovernanceRuleForm, GovernanceRuleTypeEnum, GovernanceRulesList, GovernanceState, ResetGovernanceState, SetLevelId, ToggleGovernanceRuleActive, UpdateGovernanceRule };
1482
+ //# sourceMappingURL=masterteam-governance.mjs.map