@memberjunction/ng-core-entity-forms 2.112.0 → 2.113.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 (152) hide show
  1. package/README.md +10 -10
  2. package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-diagram.component.d.ts.map +1 -1
  3. package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-diagram.component.js +45 -45
  4. package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-diagram.component.js.map +1 -1
  5. package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.d.ts.map +1 -1
  6. package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.js +7 -6
  7. package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.js.map +1 -1
  8. package/dist/lib/custom/AIAgents/FlowAgentType/mj-integrated-flow-editor.component.d.ts.map +1 -1
  9. package/dist/lib/custom/AIAgents/FlowAgentType/mj-integrated-flow-editor.component.js +32 -17
  10. package/dist/lib/custom/AIAgents/FlowAgentType/mj-integrated-flow-editor.component.js.map +1 -1
  11. package/dist/lib/custom/AIAgents/add-action-dialog.component.d.ts.map +1 -1
  12. package/dist/lib/custom/AIAgents/add-action-dialog.component.js +36 -37
  13. package/dist/lib/custom/AIAgents/add-action-dialog.component.js.map +1 -1
  14. package/dist/lib/custom/AIAgents/agent-advanced-settings-dialog.component.js +2 -2
  15. package/dist/lib/custom/AIAgents/agent-advanced-settings-dialog.component.js.map +1 -1
  16. package/dist/lib/custom/AIAgents/agent-permissions-dialog.component.d.ts +1 -1
  17. package/dist/lib/custom/AIAgents/agent-permissions-dialog.component.d.ts.map +1 -1
  18. package/dist/lib/custom/AIAgents/agent-permissions-dialog.component.js +25 -18
  19. package/dist/lib/custom/AIAgents/agent-permissions-dialog.component.js.map +1 -1
  20. package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.d.ts.map +1 -1
  21. package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.js +11 -10
  22. package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.js.map +1 -1
  23. package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
  24. package/dist/lib/custom/AIAgents/ai-agent-form.component.js +147 -159
  25. package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
  26. package/dist/lib/custom/AIAgents/create-prompt-dialog.component.d.ts.map +1 -1
  27. package/dist/lib/custom/AIAgents/create-prompt-dialog.component.js +10 -11
  28. package/dist/lib/custom/AIAgents/create-prompt-dialog.component.js.map +1 -1
  29. package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.d.ts.map +1 -1
  30. package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js +32 -36
  31. package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js.map +1 -1
  32. package/dist/lib/custom/AIAgents/new-agent-dialog.component.js +5 -5
  33. package/dist/lib/custom/AIAgents/new-agent-dialog.component.js.map +1 -1
  34. package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.d.ts.map +1 -1
  35. package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js +13 -15
  36. package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js.map +1 -1
  37. package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.d.ts.map +1 -1
  38. package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.js +15 -13
  39. package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.js.map +1 -1
  40. package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.d.ts.map +1 -1
  41. package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js +23 -28
  42. package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js.map +1 -1
  43. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts.map +1 -1
  44. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js +12 -15
  45. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
  46. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.d.ts.map +1 -1
  47. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js +86 -105
  48. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js.map +1 -1
  49. package/dist/lib/custom/AIPrompts/template-selector-dialog.component.d.ts.map +1 -1
  50. package/dist/lib/custom/AIPrompts/template-selector-dialog.component.js +20 -13
  51. package/dist/lib/custom/AIPrompts/template-selector-dialog.component.js.map +1 -1
  52. package/dist/lib/custom/Actions/action-execution-log-form.component.d.ts.map +1 -1
  53. package/dist/lib/custom/Actions/action-execution-log-form.component.js +7 -4
  54. package/dist/lib/custom/Actions/action-execution-log-form.component.js.map +1 -1
  55. package/dist/lib/custom/Actions/action-form.component.d.ts.map +1 -1
  56. package/dist/lib/custom/Actions/action-form.component.js +80 -99
  57. package/dist/lib/custom/Actions/action-form.component.js.map +1 -1
  58. package/dist/lib/custom/Actions/action-test-harness.component.d.ts.map +1 -1
  59. package/dist/lib/custom/Actions/action-test-harness.component.js +17 -24
  60. package/dist/lib/custom/Actions/action-test-harness.component.js.map +1 -1
  61. package/dist/lib/custom/Queries/query-category-dialog.component.d.ts.map +1 -1
  62. package/dist/lib/custom/Queries/query-category-dialog.component.js +8 -8
  63. package/dist/lib/custom/Queries/query-category-dialog.component.js.map +1 -1
  64. package/dist/lib/custom/Queries/query-form.component.d.ts +2 -2
  65. package/dist/lib/custom/Queries/query-form.component.d.ts.map +1 -1
  66. package/dist/lib/custom/Queries/query-form.component.js +44 -32
  67. package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
  68. package/dist/lib/custom/Queries/query-run-dialog.component.d.ts.map +1 -1
  69. package/dist/lib/custom/Queries/query-run-dialog.component.js +22 -24
  70. package/dist/lib/custom/Queries/query-run-dialog.component.js.map +1 -1
  71. package/dist/lib/custom/Templates/template-param-dialog.component.d.ts.map +1 -1
  72. package/dist/lib/custom/Templates/template-param-dialog.component.js +21 -15
  73. package/dist/lib/custom/Templates/template-param-dialog.component.js.map +1 -1
  74. package/dist/lib/custom/Templates/template-params-grid.component.d.ts.map +1 -1
  75. package/dist/lib/custom/Templates/template-params-grid.component.js +17 -29
  76. package/dist/lib/custom/Templates/template-params-grid.component.js.map +1 -1
  77. package/dist/lib/custom/Templates/templates-form.component.d.ts.map +1 -1
  78. package/dist/lib/custom/Templates/templates-form.component.js +26 -25
  79. package/dist/lib/custom/Templates/templates-form.component.js.map +1 -1
  80. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts.map +1 -1
  81. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +274 -335
  82. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js.map +1 -1
  83. package/dist/lib/custom/ai-agent-run/ai-agent-run-cost.service.d.ts.map +1 -1
  84. package/dist/lib/custom/ai-agent-run/ai-agent-run-cost.service.js +8 -8
  85. package/dist/lib/custom/ai-agent-run/ai-agent-run-cost.service.js.map +1 -1
  86. package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.d.ts.map +1 -1
  87. package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js +28 -24
  88. package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js.map +1 -1
  89. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.d.ts.map +1 -1
  90. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js +30 -25
  91. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js.map +1 -1
  92. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts.map +1 -1
  93. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js +21 -20
  94. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
  95. package/dist/lib/custom/shared/entity-selector-dialog.component.d.ts.map +1 -1
  96. package/dist/lib/custom/shared/entity-selector-dialog.component.js +7 -6
  97. package/dist/lib/custom/shared/entity-selector-dialog.component.js.map +1 -1
  98. package/dist/lib/generated/Entities/AIAgent/sections/aiagent-form-overview.component.d.ts.map +1 -1
  99. package/dist/lib/generated/Entities/AIAgent/sections/aiagent-form-overview.component.js +33 -47
  100. package/dist/lib/generated/Entities/AIAgent/sections/aiagent-form-overview.component.js.map +1 -1
  101. package/dist/lib/generated/Entities/AIAgent/sections/details.component.d.ts.map +1 -1
  102. package/dist/lib/generated/Entities/AIAgent/sections/details.component.js +31 -4
  103. package/dist/lib/generated/Entities/AIAgent/sections/details.component.js.map +1 -1
  104. package/dist/lib/generated/Entities/AIAgentExample/sections/details.component.d.ts.map +1 -1
  105. package/dist/lib/generated/Entities/AIAgentExample/sections/details.component.js +33 -4
  106. package/dist/lib/generated/Entities/AIAgentExample/sections/details.component.js.map +1 -1
  107. package/dist/lib/generated/Entities/AIAgentNote/sections/details.component.d.ts.map +1 -1
  108. package/dist/lib/generated/Entities/AIAgentNote/sections/details.component.js +33 -4
  109. package/dist/lib/generated/Entities/AIAgentNote/sections/details.component.js.map +1 -1
  110. package/dist/lib/generated/Entities/AIAgentRelationship/sections/details.component.d.ts.map +1 -1
  111. package/dist/lib/generated/Entities/AIAgentRelationship/sections/details.component.js +22 -4
  112. package/dist/lib/generated/Entities/AIAgentRelationship/sections/details.component.js.map +1 -1
  113. package/dist/lib/generated/Entities/AIAgentRun/aiagentrun.form.component.js +6 -6
  114. package/dist/lib/generated/Entities/AIAgentRun/aiagentrun.form.component.js.map +1 -1
  115. package/dist/lib/generated/Entities/AIConfiguration/aiconfiguration.form.component.js +8 -8
  116. package/dist/lib/generated/Entities/AIConfiguration/aiconfiguration.form.component.js.map +1 -1
  117. package/dist/lib/generated/Entities/AIModel/aimodel.form.component.js +34 -14
  118. package/dist/lib/generated/Entities/AIModel/aimodel.form.component.js.map +1 -1
  119. package/dist/lib/generated/Entities/ArtifactUse/artifactuse.form.component.d.ts +10 -0
  120. package/dist/lib/generated/Entities/ArtifactUse/artifactuse.form.component.d.ts.map +1 -0
  121. package/dist/lib/generated/Entities/ArtifactUse/artifactuse.form.component.js +59 -0
  122. package/dist/lib/generated/Entities/ArtifactUse/artifactuse.form.component.js.map +1 -0
  123. package/dist/lib/generated/Entities/ArtifactUse/sections/details.component.d.ts +11 -0
  124. package/dist/lib/generated/Entities/ArtifactUse/sections/details.component.d.ts.map +1 -0
  125. package/dist/lib/generated/Entities/ArtifactUse/sections/details.component.js +129 -0
  126. package/dist/lib/generated/Entities/ArtifactUse/sections/details.component.js.map +1 -0
  127. package/dist/lib/generated/Entities/ArtifactVersion/artifactversion.form.component.js +24 -4
  128. package/dist/lib/generated/Entities/ArtifactVersion/artifactversion.form.component.js.map +1 -1
  129. package/dist/lib/generated/Entities/CollectionArtifact/sections/details.component.js +10 -10
  130. package/dist/lib/generated/Entities/CollectionArtifact/sections/details.component.js.map +1 -1
  131. package/dist/lib/generated/Entities/ConversationArtifact/conversationartifact.form.component.js +6 -6
  132. package/dist/lib/generated/Entities/ConversationArtifact/conversationartifact.form.component.js.map +1 -1
  133. package/dist/lib/generated/Entities/ConversationDetail/conversationdetail.form.component.js +18 -8
  134. package/dist/lib/generated/Entities/ConversationDetail/conversationdetail.form.component.js.map +1 -1
  135. package/dist/lib/generated/Entities/ConversationDetailRating/conversationdetailrating.form.component.d.ts +10 -0
  136. package/dist/lib/generated/Entities/ConversationDetailRating/conversationdetailrating.form.component.d.ts.map +1 -0
  137. package/dist/lib/generated/Entities/ConversationDetailRating/conversationdetailrating.form.component.js +59 -0
  138. package/dist/lib/generated/Entities/ConversationDetailRating/conversationdetailrating.form.component.js.map +1 -0
  139. package/dist/lib/generated/Entities/ConversationDetailRating/sections/details.component.d.ts +11 -0
  140. package/dist/lib/generated/Entities/ConversationDetailRating/sections/details.component.d.ts.map +1 -0
  141. package/dist/lib/generated/Entities/ConversationDetailRating/sections/details.component.js +120 -0
  142. package/dist/lib/generated/Entities/ConversationDetailRating/sections/details.component.js.map +1 -0
  143. package/dist/lib/generated/Entities/User/user.form.component.js +49 -29
  144. package/dist/lib/generated/Entities/User/user.form.component.js.map +1 -1
  145. package/dist/lib/generated/generated-forms.module.d.ts +336 -327
  146. package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
  147. package/dist/lib/generated/generated-forms.module.js +199 -126
  148. package/dist/lib/generated/generated-forms.module.js.map +1 -1
  149. package/dist/lib/shared/components/template-editor.component.d.ts.map +1 -1
  150. package/dist/lib/shared/components/template-editor.component.js +27 -26
  151. package/dist/lib/shared/components/template-editor.component.js.map +1 -1
  152. package/package.json +17 -16
@@ -8,7 +8,7 @@ import { Component, inject, ViewContainerRef } from '@angular/core';
8
8
  import { RegisterClass } from '@memberjunction/global';
9
9
  import { BaseFormComponent } from '@memberjunction/ng-base-forms';
10
10
  import { SharedService } from '@memberjunction/ng-shared';
11
- import { Metadata, RunView, CompositeKey } from '@memberjunction/global';
11
+ import { Metadata, RunView, CompositeKey } from '@memberjunction/core';
12
12
  import { ActionFormComponent } from '../../generated/Entities/Action/action.form.component';
13
13
  import { DialogService } from '@progress/kendo-angular-dialog';
14
14
  import { ActionParamDialogComponent } from './action-param-dialog.component';
@@ -1076,7 +1076,7 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1076
1076
  params: true,
1077
1077
  resultCodes: true,
1078
1078
  execution: false,
1079
- configuration: false,
1079
+ configuration: false
1080
1080
  };
1081
1081
  // Test harness state
1082
1082
  this.showTestHarness = false;
@@ -1085,7 +1085,7 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1085
1085
  totalRuns: 0,
1086
1086
  successRate: 0,
1087
1087
  avgDuration: 0,
1088
- lastRun: null,
1088
+ lastRun: null
1089
1089
  };
1090
1090
  // Code editor config
1091
1091
  this.codeLanguage = 'typescript';
@@ -1103,7 +1103,7 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1103
1103
  this.loadResultCodes(),
1104
1104
  this.loadRecentExecutions(),
1105
1105
  this.loadActionLibraries(),
1106
- this.loadExecutionStats(),
1106
+ this.loadExecutionStats()
1107
1107
  ]);
1108
1108
  }
1109
1109
  }
@@ -1182,7 +1182,10 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1182
1182
  this.paramsToDelete = [];
1183
1183
  this.resultCodesToDelete = [];
1184
1184
  // Reload params and result codes to get updated data
1185
- await Promise.all([this.loadActionParams(), this.loadResultCodes()]);
1185
+ await Promise.all([
1186
+ this.loadActionParams(),
1187
+ this.loadResultCodes()
1188
+ ]);
1186
1189
  // Show success message
1187
1190
  this.sharedService.CreateSimpleNotification('Action and related records saved successfully', 'success', 3000);
1188
1191
  }
@@ -1216,16 +1219,16 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1216
1219
  EntityName: 'Action Params',
1217
1220
  ExtraFilter: `ActionID='${this.record.ID}'`,
1218
1221
  OrderBy: 'Name',
1219
- ResultType: 'entity_object', // This ensures we get proper entity instances
1222
+ ResultType: 'entity_object' // This ensures we get proper entity instances
1220
1223
  });
1221
1224
  if (result.Success) {
1222
1225
  this.actionParams = result.Results || [];
1223
1226
  // Update cached filtered params - trim and lowercase Type values to handle any whitespace and case
1224
- this._inputParams = this.actionParams.filter((p) => {
1227
+ this._inputParams = this.actionParams.filter(p => {
1225
1228
  const type = p.Type?.trim().toLowerCase();
1226
1229
  return type === 'input' || type === 'both';
1227
1230
  });
1228
- this._outputParams = this.actionParams.filter((p) => {
1231
+ this._outputParams = this.actionParams.filter(p => {
1229
1232
  const type = p.Type?.trim().toLowerCase();
1230
1233
  return type === 'output' || type === 'both';
1231
1234
  });
@@ -1256,7 +1259,7 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1256
1259
  EntityName: 'Action Result Codes',
1257
1260
  ExtraFilter: `ActionID='${this.record.ID}'`,
1258
1261
  OrderBy: 'IsSuccess DESC, ResultCode',
1259
- ResultType: 'entity_object', // This ensures we get proper entity instances
1262
+ ResultType: 'entity_object' // This ensures we get proper entity instances
1260
1263
  });
1261
1264
  if (result.Success) {
1262
1265
  this.resultCodes = result.Results || [];
@@ -1282,7 +1285,7 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1282
1285
  EntityName: 'Action Execution Logs',
1283
1286
  ExtraFilter: `ActionID='${this.record.ID}'`,
1284
1287
  OrderBy: 'StartedAt DESC',
1285
- MaxRows: 10,
1288
+ MaxRows: 10
1286
1289
  });
1287
1290
  if (result.Success) {
1288
1291
  this.recentExecutions = result.Results || [];
@@ -1307,13 +1310,13 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1307
1310
  const result = await rv.RunView({
1308
1311
  EntityName: 'Action Libraries',
1309
1312
  ExtraFilter: `ActionID='${this.record.ID}'`,
1310
- OrderBy: 'Library',
1313
+ OrderBy: 'Library'
1311
1314
  });
1312
1315
  if (result.Success) {
1313
1316
  this.actionLibraries = result.Results || [];
1314
1317
  // Load library details
1315
1318
  if (this.actionLibraries.length > 0) {
1316
- const libraryIds = this.actionLibraries.map((al) => al.LibraryID).filter((id) => id);
1319
+ const libraryIds = this.actionLibraries.map(al => al.LibraryID).filter(id => id);
1317
1320
  const md = new Metadata();
1318
1321
  this.libraries = [];
1319
1322
  for (const libId of libraryIds) {
@@ -1340,20 +1343,21 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1340
1343
  const result = await rv.RunView({
1341
1344
  EntityName: 'Action Execution Logs',
1342
1345
  ExtraFilter: `ActionID='${this.record.ID}'`,
1343
- OrderBy: 'StartedAt DESC',
1346
+ OrderBy: 'StartedAt DESC'
1344
1347
  });
1345
1348
  if (result.Success && result.Results && result.Results.length > 0) {
1346
1349
  const allExecutions = result.Results;
1347
1350
  this.executionStats.totalRuns = allExecutions.length;
1348
1351
  // Calculate success rate based on result codes
1349
- const successfulRuns = allExecutions.filter((e) => {
1350
- const resultCode = this.resultCodes.find((rc) => rc.ResultCode === e.ResultCode);
1352
+ const successfulRuns = allExecutions.filter(e => {
1353
+ const resultCode = this.resultCodes.find(rc => rc.ResultCode === e.ResultCode);
1351
1354
  return resultCode?.IsSuccess || false;
1352
1355
  });
1353
- this.executionStats.successRate =
1354
- this.executionStats.totalRuns > 0 ? (successfulRuns.length / this.executionStats.totalRuns) * 100 : 0;
1356
+ this.executionStats.successRate = this.executionStats.totalRuns > 0
1357
+ ? (successfulRuns.length / this.executionStats.totalRuns) * 100
1358
+ : 0;
1355
1359
  // Calculate average duration from ALL completed executions
1356
- const completedExecutions = allExecutions.filter((e) => e.StartedAt && e.EndedAt);
1360
+ const completedExecutions = allExecutions.filter(e => e.StartedAt && e.EndedAt);
1357
1361
  if (completedExecutions.length > 0) {
1358
1362
  const totalDuration = completedExecutions.reduce((sum, e) => {
1359
1363
  const duration = new Date(e.EndedAt).getTime() - new Date(e.StartedAt).getTime();
@@ -1373,26 +1377,18 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1373
1377
  // UI Helper Methods
1374
1378
  getStatusColor() {
1375
1379
  switch (this.record.Status) {
1376
- case 'Active':
1377
- return '#28a745';
1378
- case 'Pending':
1379
- return '#ffc107';
1380
- case 'Disabled':
1381
- return '#dc3545';
1382
- default:
1383
- return '#6c757d';
1380
+ case 'Active': return '#28a745';
1381
+ case 'Pending': return '#ffc107';
1382
+ case 'Disabled': return '#dc3545';
1383
+ default: return '#6c757d';
1384
1384
  }
1385
1385
  }
1386
1386
  getStatusIcon() {
1387
1387
  switch (this.record.Status) {
1388
- case 'Active':
1389
- return 'fa-check-circle';
1390
- case 'Pending':
1391
- return 'fa-clock';
1392
- case 'Disabled':
1393
- return 'fa-ban';
1394
- default:
1395
- return 'fa-question-circle';
1388
+ case 'Active': return 'fa-check-circle';
1389
+ case 'Pending': return 'fa-clock';
1390
+ case 'Disabled': return 'fa-ban';
1391
+ default: return 'fa-question-circle';
1396
1392
  }
1397
1393
  }
1398
1394
  getTypeColor() {
@@ -1403,50 +1399,34 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1403
1399
  }
1404
1400
  getApprovalStatusColor() {
1405
1401
  switch (this.record.CodeApprovalStatus) {
1406
- case 'Approved':
1407
- return '#28a745';
1408
- case 'Pending':
1409
- return '#ffc107';
1410
- case 'Rejected':
1411
- return '#dc3545';
1412
- default:
1413
- return '#6c757d';
1402
+ case 'Approved': return '#28a745';
1403
+ case 'Pending': return '#ffc107';
1404
+ case 'Rejected': return '#dc3545';
1405
+ default: return '#6c757d';
1414
1406
  }
1415
1407
  }
1416
1408
  getApprovalStatusIcon() {
1417
1409
  switch (this.record.CodeApprovalStatus) {
1418
- case 'Approved':
1419
- return 'fa-check-circle';
1420
- case 'Pending':
1421
- return 'fa-clock';
1422
- case 'Rejected':
1423
- return 'fa-times-circle';
1424
- default:
1425
- return 'fa-question-circle';
1410
+ case 'Approved': return 'fa-check-circle';
1411
+ case 'Pending': return 'fa-clock';
1412
+ case 'Rejected': return 'fa-times-circle';
1413
+ default: return 'fa-question-circle';
1426
1414
  }
1427
1415
  }
1428
1416
  getParamTypeIcon(type) {
1429
1417
  switch (type) {
1430
- case 'Input':
1431
- return 'fa-sign-in-alt';
1432
- case 'Output':
1433
- return 'fa-sign-out-alt';
1434
- case 'Both':
1435
- return 'fa-exchange-alt';
1436
- default:
1437
- return 'fa-question';
1418
+ case 'Input': return 'fa-sign-in-alt';
1419
+ case 'Output': return 'fa-sign-out-alt';
1420
+ case 'Both': return 'fa-exchange-alt';
1421
+ default: return 'fa-question';
1438
1422
  }
1439
1423
  }
1440
1424
  getParamTypeColor(type) {
1441
1425
  switch (type) {
1442
- case 'Input':
1443
- return '#007bff';
1444
- case 'Output':
1445
- return '#28a745';
1446
- case 'Both':
1447
- return '#6f42c1';
1448
- default:
1449
- return '#6c757d';
1426
+ case 'Input': return '#007bff';
1427
+ case 'Output': return '#28a745';
1428
+ case 'Both': return '#6f42c1';
1429
+ default: return '#6c757d';
1450
1430
  }
1451
1431
  }
1452
1432
  formatDuration(ms) {
@@ -1557,7 +1537,7 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1557
1537
  isExecutionSuccess(execution) {
1558
1538
  const code = execution.ResultCode?.toLowerCase();
1559
1539
  // First check if we have a result code definition
1560
- const resultCode = this.resultCodes.find((rc) => rc.ResultCode === execution.ResultCode);
1540
+ const resultCode = this.resultCodes.find(rc => rc.ResultCode === execution.ResultCode);
1561
1541
  if (resultCode) {
1562
1542
  return resultCode.IsSuccess;
1563
1543
  }
@@ -1597,13 +1577,13 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1597
1577
  const dialogRef = this.dialogService.open({
1598
1578
  content: ActionParamDialogComponent,
1599
1579
  width: 500,
1600
- appendTo: this.viewContainerRef,
1580
+ appendTo: this.viewContainerRef
1601
1581
  });
1602
1582
  const dialog = dialogRef.content.instance;
1603
1583
  dialog.param = newParam;
1604
1584
  dialog.isNew = true;
1605
1585
  dialog.editMode = true;
1606
- dialogRef.result.subscribe((result) => {
1586
+ dialogRef.result.subscribe(result => {
1607
1587
  if (result && result.save) {
1608
1588
  // The dialog has already modified the newParam entity directly
1609
1589
  // New entities are automatically dirty (IsSaved = false)
@@ -1612,7 +1592,7 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1612
1592
  // Add to pending records for saving
1613
1593
  this.PendingRecords.push({
1614
1594
  entityObject: newParam,
1615
- action: 'save',
1595
+ action: 'save'
1616
1596
  });
1617
1597
  // Update the filtered arrays
1618
1598
  this.updateParamArrays();
@@ -1624,22 +1604,22 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1624
1604
  const dialogRef = this.dialogService.open({
1625
1605
  content: ActionParamDialogComponent,
1626
1606
  width: 500,
1627
- appendTo: this.viewContainerRef,
1607
+ appendTo: this.viewContainerRef
1628
1608
  });
1629
1609
  const dialog = dialogRef.content.instance;
1630
1610
  dialog.param = param;
1631
1611
  dialog.isNew = false;
1632
1612
  dialog.editMode = this.EditMode;
1633
- dialogRef.result.subscribe((result) => {
1613
+ dialogRef.result.subscribe(result => {
1634
1614
  if (result && result.save && this.EditMode) {
1635
1615
  // Param will be dirty from property changes in dialog
1636
1616
  // Ensure it's in pending records if modified
1637
1617
  if (param.Dirty) {
1638
- const exists = this.PendingRecords.some((pr) => pr.entityObject === param && pr.action === 'save');
1618
+ const exists = this.PendingRecords.some(pr => pr.entityObject === param && pr.action === 'save');
1639
1619
  if (!exists) {
1640
1620
  this.PendingRecords.push({
1641
1621
  entityObject: param,
1642
- action: 'save',
1622
+ action: 'save'
1643
1623
  });
1644
1624
  }
1645
1625
  }
@@ -1660,12 +1640,12 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1660
1640
  }
1661
1641
  async updateParamArrays() {
1662
1642
  // Update cached filtered params - exclude deleted items
1663
- const activeParams = this.actionParams.filter((p) => !this.paramsToDelete || !this.paramsToDelete.includes(p));
1664
- this._inputParams = activeParams.filter((p) => {
1643
+ const activeParams = this.actionParams.filter(p => !this.paramsToDelete || !this.paramsToDelete.includes(p));
1644
+ this._inputParams = activeParams.filter(p => {
1665
1645
  const type = p.Type?.trim().toLowerCase();
1666
1646
  return type === 'input' || type === 'both';
1667
1647
  });
1668
- this._outputParams = activeParams.filter((p) => {
1648
+ this._outputParams = activeParams.filter(p => {
1669
1649
  const type = p.Type?.trim().toLowerCase();
1670
1650
  return type === 'output' || type === 'both';
1671
1651
  });
@@ -1679,8 +1659,9 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1679
1659
  // Re-add our preserved records
1680
1660
  for (const record of currentPendingRecords) {
1681
1661
  // Only re-add if it's an Action Param or Result Code (avoid duplicates)
1682
- if (record.entityObject.EntityInfo.Name === 'Action Params' || record.entityObject.EntityInfo.Name === 'Action Result Codes') {
1683
- const exists = this.PendingRecords.some((pr) => pr.entityObject === record.entityObject);
1662
+ if (record.entityObject.EntityInfo.Name === 'Action Params' ||
1663
+ record.entityObject.EntityInfo.Name === 'Action Result Codes') {
1664
+ const exists = this.PendingRecords.some(pr => pr.entityObject === record.entityObject);
1684
1665
  if (!exists) {
1685
1666
  this.PendingRecords.push(record);
1686
1667
  }
@@ -1690,11 +1671,11 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1690
1671
  for (const param of this.actionParams) {
1691
1672
  if (!param.IsSaved || param.Dirty) {
1692
1673
  // Check if not already in pending records
1693
- const exists = this.PendingRecords.some((pr) => pr.entityObject === param);
1674
+ const exists = this.PendingRecords.some(pr => pr.entityObject === param);
1694
1675
  if (!exists) {
1695
1676
  this.PendingRecords.push({
1696
1677
  entityObject: param,
1697
- action: 'save',
1678
+ action: 'save'
1698
1679
  });
1699
1680
  }
1700
1681
  }
@@ -1703,11 +1684,11 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1703
1684
  for (const param of this.paramsToDelete) {
1704
1685
  if (param.IsSaved) {
1705
1686
  // Check if not already in pending records
1706
- const exists = this.PendingRecords.some((pr) => pr.entityObject === param);
1687
+ const exists = this.PendingRecords.some(pr => pr.entityObject === param);
1707
1688
  if (!exists) {
1708
1689
  this.PendingRecords.push({
1709
1690
  entityObject: param,
1710
- action: 'delete',
1691
+ action: 'delete'
1711
1692
  });
1712
1693
  }
1713
1694
  }
@@ -1716,11 +1697,11 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1716
1697
  for (const resultCode of this.resultCodes) {
1717
1698
  if (!resultCode.IsSaved || resultCode.Dirty) {
1718
1699
  // Check if not already in pending records
1719
- const exists = this.PendingRecords.some((pr) => pr.entityObject === resultCode);
1700
+ const exists = this.PendingRecords.some(pr => pr.entityObject === resultCode);
1720
1701
  if (!exists) {
1721
1702
  this.PendingRecords.push({
1722
1703
  entityObject: resultCode,
1723
- action: 'save',
1704
+ action: 'save'
1724
1705
  });
1725
1706
  }
1726
1707
  }
@@ -1729,11 +1710,11 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1729
1710
  for (const resultCode of this.resultCodesToDelete) {
1730
1711
  if (resultCode.IsSaved) {
1731
1712
  // Check if not already in pending records
1732
- const exists = this.PendingRecords.some((pr) => pr.entityObject === resultCode);
1713
+ const exists = this.PendingRecords.some(pr => pr.entityObject === resultCode);
1733
1714
  if (!exists) {
1734
1715
  this.PendingRecords.push({
1735
1716
  entityObject: resultCode,
1736
- action: 'delete',
1717
+ action: 'delete'
1737
1718
  });
1738
1719
  }
1739
1720
  }
@@ -1760,20 +1741,20 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1760
1741
  const dialogRef = this.dialogService.open({
1761
1742
  content: ActionResultCodeDialogComponent,
1762
1743
  width: 500,
1763
- appendTo: this.viewContainerRef,
1744
+ appendTo: this.viewContainerRef
1764
1745
  });
1765
1746
  const dialog = dialogRef.content.instance;
1766
1747
  dialog.resultCode = newResultCode;
1767
1748
  dialog.isNew = true;
1768
1749
  dialog.editMode = true;
1769
- dialogRef.result.subscribe((result) => {
1750
+ dialogRef.result.subscribe(result => {
1770
1751
  if (result && result.save) {
1771
1752
  // Add to local array
1772
1753
  this.resultCodes.push(newResultCode);
1773
1754
  // Add to pending records for saving
1774
1755
  this.PendingRecords.push({
1775
1756
  entityObject: newResultCode,
1776
- action: 'save',
1757
+ action: 'save'
1777
1758
  });
1778
1759
  this.cdr.detectChanges();
1779
1760
  }
@@ -1783,21 +1764,21 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1783
1764
  const dialogRef = this.dialogService.open({
1784
1765
  content: ActionResultCodeDialogComponent,
1785
1766
  width: 500,
1786
- appendTo: this.viewContainerRef,
1767
+ appendTo: this.viewContainerRef
1787
1768
  });
1788
1769
  const dialog = dialogRef.content.instance;
1789
1770
  dialog.resultCode = resultCode;
1790
1771
  dialog.isNew = false;
1791
1772
  dialog.editMode = this.EditMode;
1792
- dialogRef.result.subscribe((result) => {
1773
+ dialogRef.result.subscribe(result => {
1793
1774
  if (result && result.save && this.EditMode) {
1794
1775
  // Ensure it's in pending records if modified
1795
1776
  if (resultCode.Dirty) {
1796
- const exists = this.PendingRecords.some((pr) => pr.entityObject === resultCode && pr.action === 'save');
1777
+ const exists = this.PendingRecords.some(pr => pr.entityObject === resultCode && pr.action === 'save');
1797
1778
  if (!exists) {
1798
1779
  this.PendingRecords.push({
1799
1780
  entityObject: resultCode,
1800
- action: 'save',
1781
+ action: 'save'
1801
1782
  });
1802
1783
  }
1803
1784
  }
@@ -1832,12 +1813,12 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1832
1813
  // Add to pending records for deletion
1833
1814
  this.PendingRecords.push({
1834
1815
  entityObject: resultCode,
1835
- action: 'delete',
1816
+ action: 'delete'
1836
1817
  });
1837
1818
  }
1838
1819
  else {
1839
1820
  // For unsaved result codes, just remove from pending records
1840
- const pendingIndex = this.PendingRecords.findIndex((pr) => pr.entityObject === resultCode && pr.action === 'save');
1821
+ const pendingIndex = this.PendingRecords.findIndex(pr => pr.entityObject === resultCode && pr.action === 'save');
1841
1822
  if (pendingIndex >= 0) {
1842
1823
  this.PendingRecords.splice(pendingIndex, 1);
1843
1824
  }
@@ -1862,12 +1843,12 @@ let ActionFormComponentExtended = class ActionFormComponentExtended extends Acti
1862
1843
  // Add to pending records for deletion
1863
1844
  this.PendingRecords.push({
1864
1845
  entityObject: param,
1865
- action: 'delete',
1846
+ action: 'delete'
1866
1847
  });
1867
1848
  }
1868
1849
  else {
1869
1850
  // For unsaved params, just remove from pending records
1870
- const pendingIndex = this.PendingRecords.findIndex((pr) => pr.entityObject === param && pr.action === 'save');
1851
+ const pendingIndex = this.PendingRecords.findIndex(pr => pr.entityObject === param && pr.action === 'save');
1871
1852
  if (pendingIndex >= 0) {
1872
1853
  this.PendingRecords.splice(pendingIndex, 1);
1873
1854
  }
@@ -1897,7 +1878,7 @@ export { ActionFormComponentExtended };
1897
1878
  type: Component,
1898
1879
  args: [{ selector: 'mj-action-form', template: "<div class=\"record-form-container\">\n @if (record) {\n <form class=\"record-form\" #form=\"ngForm\">\n <mj-form-toolbar [form]=\"this\"></mj-form-toolbar>\n\n <!-- Main Content Area -->\n <div class=\"action-main-area\" style=\"display: flex; flex-direction: column; height: 100%; overflow-y: auto;\">\n \n <!-- Header Section -->\n <div class=\"action-header\" style=\"flex-shrink: 0; padding: 20px; background: #f8f9fa; border-bottom: 2px solid #e9ecef;\">\n <div style=\"display: flex; justify-content: space-between; align-items: flex-start; gap: 20px;\">\n \n <!-- Left: Action Info -->\n <div style=\"flex: 1; min-width: 0;\">\n <div style=\"display: flex; align-items: center; gap: 12px; margin-bottom: 8px;\">\n <i [class]=\"getActionIcon()\" [style.color]=\"getTypeColor()\" style=\"font-size: 1.4em;\"></i>\n @if (EditMode) {\n <kendo-textbox [(ngModel)]=\"record.Name\" \n name=\"actionName\"\n placeholder=\"Enter action name...\"\n style=\"font-size: 1.2em; font-weight: 600; min-width: 300px; flex: 1;\">\n </kendo-textbox>\n } @else {\n <h4 style=\"margin: 0; color: #495057; font-weight: 600; flex: 1;\">{{ record.Name || 'Untitled Action' }}</h4>\n <span class=\"status-badge\" [style.background-color]=\"getStatusColor()\" \n style=\"color: white; padding: 4px 10px; border-radius: 12px; font-size: 0.75em; font-weight: 500;\">\n {{ record.Status }}\n </span>\n }\n </div>\n \n <!-- Status and Type Editors when in edit mode -->\n @if (EditMode) {\n <div style=\"display: flex; gap: 16px; margin-bottom: 12px; flex-wrap: wrap;\">\n <div>\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: #495057; font-size: 0.9em;\">Status</label>\n <kendo-dropdownlist [(ngModel)]=\"record.Status\"\n name=\"actionStatus\"\n [data]=\"[{text: 'Active', value: 'Active'}, {text: 'Pending', value: 'Pending'}, {text: 'Disabled', value: 'Disabled'}]\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n style=\"width: 150px;\">\n </kendo-dropdownlist>\n </div>\n <div>\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: #495057; font-size: 0.9em;\">\n Type <span style=\"color: #dc3545;\">*</span>\n </label>\n <kendo-dropdownlist [(ngModel)]=\"record.Type\"\n name=\"actionType\"\n [data]=\"[{text: 'Generated', value: 'Generated'}, {text: 'Custom', value: 'Custom'}]\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n style=\"width: 150px;\">\n </kendo-dropdownlist>\n </div>\n <div>\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: #495057; font-size: 0.9em;\">\n Category <span style=\"color: #dc3545;\">*</span>\n </label>\n <kendo-dropdownlist [(ngModel)]=\"record.CategoryID\"\n name=\"categoryID\"\n [data]=\"[]\"\n placeholder=\"Select category...\"\n style=\"width: 200px;\">\n </kendo-dropdownlist>\n </div>\n </div>\n }\n \n @if (EditMode) {\n <kendo-textarea [(ngModel)]=\"record.Description\" \n name=\"actionDescription\"\n [rows]=\"2\"\n placeholder=\"Enter action description...\"\n style=\"width: 100%; max-width: 600px; margin-bottom: 12px;\">\n </kendo-textarea>\n } @else if (record.Description) {\n <p style=\"margin: 0 0 12px 0; color: #6c757d; font-size: 0.9em; line-height: 1.4;\">{{ record.Description }}</p>\n }\n \n <!-- Quick Config Row -->\n <div class=\"quick-config\" style=\"display: flex; align-items: center; gap: 16px; flex-wrap: wrap;\">\n @if (category) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-folder\" style=\"color: #6c757d;\"></i>\n <span style=\"color: #6c757d;\">Category:</span>\n <span style=\"color: #495057; font-weight: 500; cursor: pointer;\" (click)=\"navigateToCategory()\">\n {{ category.Name }}\n <i class=\"fa-solid fa-external-link\" style=\"font-size: 0.75em; margin-left: 4px;\"></i>\n </span>\n </div>\n }\n \n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-cube\" style=\"color: #6c757d;\"></i>\n <span style=\"color: #6c757d;\">Type:</span>\n <span style=\"color: #495057; font-weight: 500;\">{{ record.Type }}</span>\n </div>\n \n @if (record.Type === 'Generated' && record.CodeApprovalStatus) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i [class]=\"'fa-solid ' + getApprovalStatusIcon()\" [style.color]=\"getApprovalStatusColor()\"></i>\n <span style=\"color: #6c757d;\">Code:</span>\n <span [style.color]=\"getApprovalStatusColor()\" style=\"font-weight: 500;\">{{ record.CodeApprovalStatus }}</span>\n </div>\n }\n \n @if (actionParams.length > 0) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-sliders\" style=\"color: #6c757d;\"></i>\n <span style=\"color: #495057; font-weight: 500;\">{{ actionParams.length }} Parameters</span>\n </div>\n }\n </div>\n </div>\n \n <!-- Right: Action Buttons -->\n <div class=\"action-buttons\" style=\"display: flex; flex-direction: column; gap: 8px; align-items: flex-end;\">\n <div style=\"display: flex; gap: 8px;\">\n @if (record.ID) {\n <button kendoButton themeColor=\"primary\" size=\"large\"\n (click)=\"openTestHarness()\"\n title=\"Open Run Harness\"\n [disabled]=\"record.Status !== 'Active'\">\n <i class=\"fa-solid fa-play\"></i> Run\n </button>\n }\n @if (EditMode && record.Type === 'Generated') {\n <button kendoButton themeColor=\"info\" size=\"medium\"\n (click)=\"regenerateCode()\"\n title=\"Regenerate Code\">\n <i class=\"fa-solid fa-robot\"></i> Regenerate\n </button>\n }\n </div>\n \n @if (EditMode && record.CodeApprovalStatus === 'Pending' && record.Type === 'Generated') {\n <div style=\"display: flex; gap: 8px;\">\n <button kendoButton themeColor=\"success\" size=\"small\"\n (click)=\"approveCode()\">\n <i class=\"fa-solid fa-check\"></i> Approve\n </button>\n <button kendoButton themeColor=\"error\" size=\"small\"\n (click)=\"rejectCode()\">\n <i class=\"fa-solid fa-times\"></i> Reject\n </button>\n </div>\n }\n \n @if (!EditMode && record.Status !== 'Active' && record.ID) {\n <div style=\"font-size: 0.75em; color: #dc3545; text-align: right;\">\n Action must be Active to execute\n </div>\n }\n </div>\n </div>\n </div>\n\n <!-- Configuration Sections with Expansion Panels -->\n <div class=\"configuration-sections\" style=\"flex: 1; background: white; border-top: 2px solid #e9ecef; padding: 16px; min-height: 0;\">\n \n <!-- Parameters Section (FIRST) -->\n <kendo-expansionpanel \n [expanded]=\"true\"\n style=\"margin-bottom: 12px;\">\n <ng-template kendoExpansionPanelTitleDirective>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-sliders\" style=\"color: #6c757d;\"></i>\n Parameters\n @if (actionParams.length > 0) {\n <span style=\"background: #17a2b8; color: white; padding: 2px 6px; border-radius: 10px; font-size: 0.7em;\">\n {{ actionParams.length }}\n </span>\n }\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n @if (isLoadingParams) {\n <div class=\"loading-state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading parameters...\n </div>\n } @else if (actionParams.length === 0) {\n <div class=\"empty-state\" style=\"padding: 30px; text-align: center;\">\n <i class=\"fa-solid fa-sliders\" style=\"font-size: 2em; color: #6c757d; opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: #6c757d;\">No parameters defined</p>\n @if (EditMode && record.IsSaved) {\n <p style=\"margin: 8px 0 0 0; font-size: 0.85em; color: #6c757d;\">Add parameters to define inputs and outputs for this action</p>\n }\n </div>\n } @else {\n <!-- Input Parameters Grid -->\n <div class=\"params-section\">\n <div class=\"params-header\">\n <h3><i class=\"fa-solid fa-sign-in-alt\"></i> Input Parameters</h3>\n @if (EditMode && record.IsSaved) {\n <button kendoButton fillMode=\"flat\" size=\"small\" (click)=\"addParameter('Input')\">\n <i class=\"fa-solid fa-plus\"></i> Add Input\n </button>\n }\n </div>\n \n @if (getInputParams().length === 0) {\n <div class=\"empty-state\" style=\"padding: 30px; text-align: center;\">\n <i class=\"fa-solid fa-inbox\" style=\"font-size: 2em; color: #6c757d; opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: #6c757d;\">No input parameters defined</p>\n </div>\n } @else {\n <div class=\"params-grid\">\n @for (param of getInputParams(); track param.ID) {\n <div class=\"param-card\" [class.required]=\"param.IsRequired\" \n [class.clickable]=\"true\"\n (click)=\"onParamClick(param, $event)\">\n <div class=\"param-header\">\n <span class=\"param-name\">{{ param.Name }}</span>\n <div class=\"param-badges\">\n @if (param.IsRequired) {\n <span class=\"required-badge\">Required</span>\n }\n @if (param.IsArray) {\n <span class=\"array-badge\">Array</span>\n }\n @if (EditMode) {\n <button class=\"param-edit-btn\" (click)=\"editParameter(param)\" title=\"Edit parameter\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button class=\"param-delete-btn\" (click)=\"deleteParameter(param)\" title=\"Delete parameter\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n </div>\n </div>\n <div class=\"param-details\">\n <div class=\"param-type\">{{ param.ValueType }}</div>\n @if (param.Description) {\n <div class=\"param-description\">{{ param.Description }}</div>\n }\n @if (param.DefaultValue) {\n <div class=\"param-default\">\n <span class=\"default-label\">Default:</span>\n <code>{{ param.DefaultValue }}</code>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Output Parameters Grid -->\n <div class=\"params-section\" style=\"margin-top: 24px;\" \n [class.params-section-compact]=\"getOutputParams().length === 0\">\n <div class=\"params-header\">\n <h3><i class=\"fa-solid fa-sign-out-alt\"></i> Output Parameters</h3>\n @if (EditMode && record.IsSaved) {\n <button kendoButton fillMode=\"flat\" size=\"small\" (click)=\"addParameter('Output')\">\n <i class=\"fa-solid fa-plus\"></i> Add Output\n </button>\n }\n </div>\n \n @if (getOutputParams().length === 0) {\n <div class=\"empty-state\" style=\"padding: 20px; text-align: center;\">\n <i class=\"fa-solid fa-inbox\" style=\"font-size: 2em; color: #6c757d; opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: #6c757d;\">No output parameters defined</p>\n </div>\n } @else {\n <div class=\"params-grid\">\n @for (param of getOutputParams(); track param.ID) {\n <div class=\"param-card\"\n [class.clickable]=\"true\"\n (click)=\"onParamClick(param, $event)\">\n <div class=\"param-header\">\n <span class=\"param-name\">{{ param.Name }}</span>\n <div class=\"param-badges\">\n @if (param.IsArray) {\n <span class=\"array-badge\">Array</span>\n }\n @if (EditMode) {\n <button class=\"param-edit-btn\" (click)=\"editParameter(param)\" title=\"Edit parameter\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button class=\"param-delete-btn\" (click)=\"deleteParameter(param)\" title=\"Delete parameter\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n </div>\n </div>\n <div class=\"param-details\">\n <div class=\"param-type\">{{ param.ValueType }}</div>\n @if (param.Description) {\n <div class=\"param-description\">{{ param.Description }}</div>\n }\n @if (param.DefaultValue) {\n <div class=\"param-default\">\n <span class=\"default-label\">Default:</span>\n <code>{{ param.DefaultValue }}</code>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </kendo-expansionpanel>\n\n <!-- Code & Generation Section (Only for Generated type) -->\n @if (record.Type === 'Generated') {\n <kendo-expansionpanel \n [expanded]=\"expandedSections.code\"\n style=\"margin-bottom: 12px;\">\n <ng-template kendoExpansionPanelTitleDirective>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-code\" style=\"color: #6c757d;\"></i>\n Code & Generation\n @if (record.CodeLocked) {\n <span style=\"background: #ffc107; color: #856404; padding: 2px 6px; border-radius: 10px; font-size: 0.7em;\">\n <i class=\"fa-solid fa-lock\"></i> Locked\n </span>\n }\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n @if (EditMode) {\n <div class=\"generation-panel\">\n <h3><i class=\"fa-solid fa-robot\"></i> AI Generation</h3>\n <div class=\"prompt-section\">\n <label>User Prompt</label>\n <kendo-textarea [(ngModel)]=\"record.UserPrompt\"\n name=\"userPrompt\"\n [rows]=\"8\"\n placeholder=\"Describe what this action should do...\"\n style=\"width: 100%; min-height: 120px;\">\n </kendo-textarea>\n </div>\n <div class=\"comments-section\">\n <label>Internal Comments (not sent to AI)</label>\n <kendo-textarea [(ngModel)]=\"record.UserComments\"\n name=\"userComments\"\n [rows]=\"2\"\n placeholder=\"Internal notes...\"\n style=\"width: 100%;\">\n </kendo-textarea>\n </div>\n <div class=\"generation-controls\">\n <kendo-switch [(ngModel)]=\"record.CodeLocked\"\n name=\"codeLocked\">\n </kendo-switch>\n <label style=\"margin-left: 8px;\">Lock Code (prevent regeneration)</label>\n </div>\n </div>\n }\n \n <div class=\"code-editor-section\">\n <div class=\"code-toolbar\">\n <h3><i class=\"fa-solid fa-file-code\"></i> Action Code</h3>\n <div class=\"code-actions\">\n @if (record.CodeComments) {\n <button kendoButton fillMode=\"flat\" size=\"small\" (click)=\"toggleCodeComments()\">\n <i class=\"fa-solid fa-comment\"></i> \n {{ showCodeComments ? 'Hide' : 'Show' }} AI Comments\n </button>\n }\n <button kendoButton fillMode=\"flat\" size=\"small\" (click)=\"copyToClipboard(record.Code || '')\">\n <i class=\"fa-solid fa-copy\"></i> Copy\n </button>\n </div>\n </div>\n <mj-code-editor \n [(ngModel)]=\"record.Code\"\n name=\"actionCode\"\n [readonly]=\"!EditMode || record.CodeLocked\"\n [language]=\"codeLanguage\"\n [lineWrapping]=\"true\"\n style=\"height: 400px; width: 100%;\">\n </mj-code-editor>\n \n @if (showCodeComments && record.CodeComments) {\n <div class=\"code-comments\">\n <h4><i class=\"fa-solid fa-robot\"></i> AI Explanation</h4>\n <p>{{ record.CodeComments }}</p>\n </div>\n }\n \n @if (EditMode && record.CodeApprovalStatus === 'Rejected') {\n <div class=\"approval-comments\">\n <label>Rejection Comments</label>\n <kendo-textarea [(ngModel)]=\"record.CodeApprovalComments\"\n name=\"codeApprovalComments\"\n [rows]=\"2\"\n placeholder=\"Explain why the code was rejected...\"\n style=\"width: 100%;\">\n </kendo-textarea>\n </div>\n }\n </div>\n </div>\n </kendo-expansionpanel>\n }\n\n <!-- Result Codes Section -->\n <kendo-expansionpanel \n [expanded]=\"expandedSections.resultCodes\"\n style=\"margin-bottom: 12px;\">\n <ng-template kendoExpansionPanelTitleDirective>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-flag-checkered\" style=\"color: #6c757d;\"></i>\n Result Codes\n @if (resultCodes.length > 0) {\n <span style=\"background: #28a745; color: white; padding: 2px 6px; border-radius: 10px; font-size: 0.7em;\">\n {{ resultCodes.length }}\n </span>\n }\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n <!-- Add Result Code Button -->\n @if (EditMode && record.IsSaved) {\n <div style=\"display: flex; justify-content: flex-end; margin-bottom: 12px;\">\n <button kendoButton [primary]=\"true\" size=\"small\" (click)=\"addResultCode()\">\n <i class=\"fa-solid fa-plus\"></i> Add Result Code\n </button>\n </div>\n }\n \n @if (isLoadingResultCodes) {\n <div class=\"loading-state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading result codes...\n </div>\n } @else if (resultCodes.length === 0) {\n <div class=\"empty-state\" style=\"padding: 30px; text-align: center;\">\n <i class=\"fa-solid fa-flag-checkered\" style=\"font-size: 2em; color: #6c757d; opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: #6c757d;\">No result codes defined</p>\n @if (EditMode && record.IsSaved) {\n <p style=\"margin: 8px 0 0 0; font-size: 0.85em; color: #6c757d;\">Add result codes to define possible outcomes</p>\n }\n </div>\n } @else {\n <div class=\"result-codes-grid\">\n @for (code of resultCodes; track code.ID) {\n <div class=\"result-code-card\" \n [class.success]=\"code.IsSuccess\" \n [class.failure]=\"!code.IsSuccess\"\n [class.clickable]=\"true\"\n (click)=\"onResultCodeClick(code, $event)\">\n <div class=\"result-icon\">\n <i [class]=\"code.IsSuccess ? 'fa-solid fa-check-circle' : 'fa-solid fa-times-circle'\"></i>\n </div>\n <div class=\"result-content\">\n <div class=\"result-code\">{{ code.ResultCode }}</div>\n @if (code.Description) {\n <div class=\"result-description\">{{ code.Description }}</div>\n }\n </div>\n @if (EditMode) {\n <div class=\"result-actions\">\n <button class=\"result-edit-btn\" (click)=\"editResultCode(code); $event.stopPropagation()\" title=\"Edit result code\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button class=\"result-delete-btn\" (click)=\"deleteResultCode(code); $event.stopPropagation()\" title=\"Delete result code\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </kendo-expansionpanel>\n\n <!-- Execution & Monitoring Section -->\n @if (record.IsSaved) {\n <kendo-expansionpanel \n [expanded]=\"expandedSections.execution\"\n style=\"margin-bottom: 12px;\">\n <ng-template kendoExpansionPanelTitleDirective>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-chart-line\" style=\"color: #6c757d;\"></i>\n Execution & Monitoring\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n @if (isLoadingExecutions) {\n <div class=\"loading-state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading executions...\n </div>\n } @else if (recentExecutions.length === 0) {\n <div class=\"empty-state\" style=\"padding: 30px; text-align: center;\">\n <i class=\"fa-solid fa-chart-line\" style=\"font-size: 2em; color: #6c757d; opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: #6c757d;\">No executions yet</p>\n </div>\n } @else {\n <div class=\"execution-stats-row\">\n <div class=\"stat-box\">\n <i class=\"fa-solid fa-tachometer-alt\"></i>\n <div class=\"stat-info\">\n <div class=\"stat-label\" style=\"color: #212529;\">Avg Duration</div>\n <div class=\"stat-value\" style=\"color: #212529;\">{{ formatDuration(executionStats.avgDuration) }}</div>\n </div>\n </div>\n <div class=\"stat-box\">\n <i class=\"fa-solid fa-check-circle\" [style.color]=\"getSuccessRateColor()\"></i>\n <div class=\"stat-info\">\n <div class=\"stat-label\" style=\"color: #212529;\">Success Rate</div>\n <div class=\"stat-value\" [style.color]=\"getSuccessRateColor()\" style=\"font-weight: 600;\">{{ executionStats.successRate.toFixed(0) }}%</div>\n </div>\n </div>\n <div class=\"stat-box\">\n <i class=\"fa-solid fa-play-circle\"></i>\n <div class=\"stat-info\">\n <div class=\"stat-label\" style=\"color: #212529;\">Total Runs</div>\n <div class=\"stat-value\" style=\"color: #212529;\">{{ executionStats.totalRuns }}</div>\n </div>\n </div>\n </div>\n\n <h3 style=\"margin-top: 24px;\"><i class=\"fa-solid fa-history\"></i> Recent Executions</h3>\n <div class=\"executions-table\">\n <table>\n <thead>\n <tr>\n <th>Started</th>\n <th>Duration</th>\n <th>User</th>\n <th>Result</th>\n <th>Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (execution of recentExecutions; track execution.ID) {\n <tr class=\"execution-row\" [class.success]=\"isExecutionSuccess(execution)\">\n <td>{{ execution.StartedAt | date:'short' }}</td>\n <td>\n @if (execution.EndedAt) {\n {{ formatDuration(getExecutionDuration(execution)) }}\n } @else {\n <span class=\"running\">Running...</span>\n }\n </td>\n <td>{{ execution.User }}</td>\n <td>\n <span class=\"result-code\" \n [class.success]=\"isExecutionSuccess(execution)\"\n [class.failure]=\"!isExecutionSuccess(execution)\">\n {{ execution.ResultCode }}\n </span>\n </td>\n <td>\n <button kendoButton fillMode=\"flat\" size=\"small\" (click)=\"navigateToExecution(execution.ID)\">\n <i class=\"fa-solid fa-external-link\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n </kendo-expansionpanel>\n }\n\n <!-- Related Configuration Section -->\n @if (record.IsSaved) {\n <kendo-expansionpanel \n [expanded]=\"expandedSections.configuration\"\n style=\"margin-bottom: 12px;\">\n <ng-template kendoExpansionPanelTitleDirective>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-cogs\" style=\"color: #6c757d;\"></i>\n Related Configuration\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n <!-- Libraries -->\n <div class=\"config-subsection\">\n <h3><i class=\"fa-solid fa-book\"></i> Libraries</h3>\n @if (isLoadingLibraries) {\n <div class=\"loading-state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading libraries...\n </div>\n } @else if (actionLibraries.length === 0) {\n <div class=\"empty-state mini\">\n <p>No libraries configured</p>\n </div>\n } @else {\n <div class=\"library-cards\">\n @for (lib of libraries; track lib.ID; let i = $index) {\n <div class=\"library-card\" (click)=\"navigateToLibrary(lib.ID)\">\n <i class=\"fa-solid fa-book\"></i>\n <div class=\"library-info\">\n <div class=\"library-name\">{{ lib.Name }}</div>\n @if (actionLibraries[i].ItemsUsed) {\n <div class=\"library-items\">{{ actionLibraries[i].ItemsUsed }}</div>\n }\n </div>\n <i class=\"fa-solid fa-external-link\"></i>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Other Related Entities -->\n <div class=\"related-entities-grid\">\n <div class=\"related-entity-link\">\n <i class=\"fa-solid fa-shield-alt\"></i>\n <span>Authorizations</span>\n <span class=\"entity-count\">View</span>\n </div>\n <div class=\"related-entity-link\">\n <i class=\"fa-solid fa-layer-group\"></i>\n <span>Contexts</span>\n <span class=\"entity-count\">View</span>\n </div>\n <div class=\"related-entity-link\">\n <i class=\"fa-solid fa-calendar\"></i>\n <span>Scheduled Actions</span>\n <span class=\"entity-count\">View</span>\n </div>\n <div class=\"related-entity-link\">\n <i class=\"fa-solid fa-cube\"></i>\n <span>Entity Actions</span>\n <span class=\"entity-count\">View</span>\n </div>\n </div>\n </div>\n </kendo-expansionpanel>\n }\n </div>\n </div>\n </form>\n }\n</div>\n\n<!-- Action Test Harness -->\n@if (showTestHarness) {\n <kendo-window \n [width]=\"1200\" \n [height]=\"800\" \n [minWidth]=\"800\"\n [minHeight]=\"600\"\n [draggable]=\"true\"\n [resizable]=\"true\"\n [state]=\"'default'\"\n (close)=\"onTestHarnessVisibilityChanged(false)\"\n title=\"Run Action - {{ record.Name || 'Untitled' }}\">\n <mj-action-test-harness\n [action]=\"record\"\n [actionParams]=\"actionParams\"\n [isVisible]=\"showTestHarness\"\n (visibilityChange)=\"onTestHarnessVisibilityChanged($event)\">\n </mj-action-test-harness>\n </kendo-window>\n}", styles: ["/* Hero Header Section */\n.action-hero-header {\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n padding: 32px;\n margin: -20px -20px 24px -20px;\n border-radius: 0 0 16px 16px;\n box-shadow: 0 4px 20px rgba(0,0,0,0.1);\n}\n\n.hero-content {\n max-width: 1400px;\n margin: 0 auto;\n}\n\n.action-identity {\n display: flex;\n align-items: flex-start;\n gap: 24px;\n margin-bottom: 24px;\n}\n\n.action-icon-wrapper {\n width: 80px;\n height: 80px;\n border-radius: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n background: rgba(255,255,255,0.2);\n backdrop-filter: blur(10px);\n}\n\n.action-icon-wrapper i {\n font-size: 36px;\n}\n\n.action-info {\n flex: 1;\n min-width: 0;\n}\n\n.action-title-row {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-bottom: 12px;\n flex-wrap: wrap;\n}\n\n.action-title {\n margin: 0;\n font-size: 2em;\n font-weight: 600;\n color: white;\n}\n\n.action-name-input {\n font-size: 1.8em;\n font-weight: 600;\n background: rgba(255,255,255,0.2);\n border: 2px solid rgba(255,255,255,0.3);\n color: white;\n padding: 8px 16px;\n border-radius: 8px;\n min-width: 400px;\n}\n\n.action-name-input::placeholder {\n color: rgba(255,255,255,0.6);\n}\n\n.action-badges {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.status-badge, .type-badge, .approval-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border-radius: 20px;\n font-size: 0.85em;\n font-weight: 500;\n background: rgba(255,255,255,0.2);\n backdrop-filter: blur(10px);\n border: 1px solid rgba(255,255,255,0.3);\n}\n\n.action-category {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n color: rgba(255,255,255,0.9);\n font-size: 0.95em;\n cursor: pointer;\n transition: all 0.2s;\n margin-bottom: 12px;\n}\n\n.action-category:hover {\n color: white;\n transform: translateX(4px);\n}\n\n.action-description {\n color: rgba(255,255,255,0.9);\n font-size: 1.05em;\n line-height: 1.5;\n margin: 0;\n}\n\n.action-description-input {\n width: 100%;\n max-width: 600px;\n background: rgba(255,255,255,0.2);\n border: 2px solid rgba(255,255,255,0.3);\n color: white;\n border-radius: 8px;\n}\n\n.action-description-input::placeholder {\n color: rgba(255,255,255,0.6);\n}\n\n/* Quick Stats */\n.action-stats {\n display: flex;\n gap: 24px;\n margin-bottom: 24px;\n flex-wrap: wrap;\n}\n\n.stat-card {\n background: rgba(255,255,255,0.1);\n backdrop-filter: blur(10px);\n border: 1px solid rgba(255,255,255,0.2);\n border-radius: 12px;\n padding: 16px 24px;\n display: flex;\n align-items: center;\n gap: 16px;\n min-width: 160px;\n}\n\n.stat-card i {\n font-size: 24px;\n color: rgba(255,255,255,0.8);\n}\n\n.stat-content {\n display: flex;\n flex-direction: column;\n}\n\n.stat-value {\n font-size: 1.4em;\n font-weight: 700;\n color: white;\n}\n\n.stat-label {\n font-size: 0.85em;\n color: rgba(255,255,255,0.7);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n/* Hero Actions */\n.hero-actions {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.hero-actions kendo-button {\n backdrop-filter: blur(10px);\n}\n\n/* Main Content Sections */\n.action-content {\n padding: 0 20px 20px;\n}\n\n.content-section {\n background: white;\n border: 1px solid #e9ecef;\n border-radius: 12px;\n margin-bottom: 20px;\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.content-section:hover {\n box-shadow: 0 4px 12px rgba(0,0,0,0.08);\n}\n\n.section-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n background: #f8f9fa;\n cursor: pointer;\n user-select: none;\n transition: background 0.2s;\n}\n\n.section-header:hover {\n background: #e9ecef;\n}\n\n.section-header h2 {\n margin: 0;\n font-size: 1.3em;\n color: #2c3e50;\n flex: 1;\n}\n\n.section-header i:first-child {\n font-size: 1.2em;\n color: #6c757d;\n}\n\n.section-count {\n background: #007bff;\n color: white;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 0.85em;\n font-weight: 500;\n}\n\n.toggle-icon {\n color: #6c757d;\n transition: transform 0.3s;\n}\n\n.toggle-icon.rotated {\n transform: rotate(-90deg);\n}\n\n.section-content {\n padding: 24px;\n animation: slideDown 0.3s ease;\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Overview Section */\n.overview-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n}\n\n.overview-field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.overview-field label {\n font-weight: 600;\n color: #495057;\n font-size: 0.9em;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.required {\n color: #dc3545;\n}\n\n.full-width {\n width: 100%;\n}\n\n.overview-display {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 24px;\n}\n\n.display-field {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.display-field label {\n font-size: 0.85em;\n color: #6c757d;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.display-value {\n font-size: 1.1em;\n color: #2c3e50;\n}\n\n.display-value.code {\n font-family: 'Courier New', monospace;\n background: #f8f9fa;\n padding: 4px 8px;\n border-radius: 4px;\n}\n\n.approval-date {\n color: #6c757d;\n font-size: 0.85em;\n margin-left: 8px;\n}\n\n/* Code Section */\n.generation-panel {\n background: #f8f9fa;\n border: 1px solid #e9ecef;\n border-radius: 8px;\n padding: 20px;\n margin-bottom: 24px;\n}\n\n.generation-panel h3 {\n margin: 0 0 16px 0;\n color: #6f42c1;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.prompt-section, .comments-section {\n margin-bottom: 16px;\n}\n\n.prompt-section label, .comments-section label {\n display: block;\n margin-bottom: 8px;\n font-weight: 600;\n color: #495057;\n}\n\n.generation-controls {\n display: flex;\n align-items: center;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid #dee2e6;\n}\n\n.code-locked-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: #ffc107;\n color: #856404;\n border-radius: 12px;\n font-size: 0.8em;\n font-weight: 500;\n}\n\n.code-editor-section {\n border: 1px solid #e9ecef;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.code-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #e9ecef;\n}\n\n.code-toolbar h3 {\n margin: 0;\n font-size: 1.1em;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.code-actions {\n display: flex;\n gap: 8px;\n}\n\n.code-comments {\n background: #e3f2fd;\n border: 1px solid #90caf9;\n border-radius: 8px;\n padding: 16px;\n margin-top: 16px;\n}\n\n.code-comments h4 {\n margin: 0 0 8px 0;\n color: #1976d2;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.code-comments p {\n margin: 0;\n color: #424242;\n line-height: 1.5;\n}\n\n.approval-comments {\n margin-top: 16px;\n}\n\n.approval-comments label {\n display: block;\n margin-bottom: 8px;\n font-weight: 600;\n color: #dc3545;\n}\n\n/* Parameters Section */\n.params-section {\n background: #f8f9fa;\n border-radius: 12px;\n padding: 20px;\n}\n\n.params-section.params-section-compact {\n padding: 12px 20px;\n}\n\n.params-section-compact .empty-state {\n padding: 12px !important;\n}\n\n.params-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n}\n\n.params-header h3 {\n margin: 0;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.params-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n\n.param-card {\n background: white;\n border: 2px solid #e9ecef;\n border-radius: 8px;\n padding: 16px;\n transition: all 0.2s;\n}\n\n.param-card:hover {\n border-color: #007bff;\n box-shadow: 0 2px 8px rgba(0,123,255,0.1);\n}\n\n.param-card.required {\n border-color: #ffc107;\n}\n\n.param-card.clickable {\n cursor: pointer;\n}\n\n.param-card.clickable:hover {\n background: #e7f3ff;\n border-color: #2196f3;\n transform: translateY(-1px);\n}\n\n.param-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.param-name {\n font-weight: 600;\n color: #2c3e50;\n}\n\n.param-badges {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.param-edit-btn,\n.param-delete-btn {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: #6c757d;\n border-radius: 4px;\n transition: all 0.2s;\n}\n\n.param-edit-btn:hover {\n background: #e3f2fd;\n color: #2196f3;\n}\n\n.param-delete-btn:hover {\n background: #ffebee;\n color: #f44336;\n}\n\n.param-details {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.required-badge {\n background: #ffc107;\n color: #856404;\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 0.75em;\n font-weight: 500;\n}\n\n.array-badge {\n background: #6f42c1;\n color: white;\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 0.75em;\n font-weight: 500;\n}\n\n.param-type {\n color: #6c757d;\n font-size: 0.9em;\n margin-bottom: 8px;\n}\n\n.param-description {\n color: #495057;\n font-size: 0.9em;\n line-height: 1.4;\n margin-bottom: 8px;\n}\n\n.param-default {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid #e9ecef;\n}\n\n.default-label {\n color: #6c757d;\n font-size: 0.85em;\n}\n\n.param-default code {\n background: #f8f9fa;\n padding: 2px 6px;\n border-radius: 4px;\n font-family: 'Courier New', monospace;\n color: #e83e8c;\n}\n\n\n/* Result Codes Section */\n.result-codes-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n\n.result-code-card {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 16px;\n border: 2px solid #e9ecef;\n border-radius: 8px;\n background: white;\n transition: all 0.2s;\n position: relative;\n}\n\n.result-code-card.clickable {\n cursor: pointer;\n}\n\n.result-code-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n}\n\n.result-code-card.success {\n border-color: #28a745;\n background: #d4edda;\n}\n\n.result-code-card.failure {\n border-color: #dc3545;\n background: #f8d7da;\n}\n\n.result-actions {\n position: absolute;\n top: 8px;\n right: 8px;\n display: flex;\n gap: 4px;\n opacity: 0;\n transition: opacity 0.2s;\n}\n\n.result-code-card:hover .result-actions {\n opacity: 1;\n}\n\n.result-edit-btn,\n.result-delete-btn {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 4px 8px;\n cursor: pointer;\n transition: all 0.2s;\n font-size: 0.85em;\n}\n\n.result-edit-btn:hover {\n background: #007bff;\n color: white;\n border-color: #007bff;\n}\n\n.result-delete-btn:hover {\n background: #dc3545;\n color: white;\n border-color: #dc3545;\n}\n\n.result-icon {\n font-size: 1.5em;\n flex-shrink: 0;\n}\n\n.result-code-card.success .result-icon {\n color: #28a745;\n}\n\n.result-code-card.failure .result-icon {\n color: #dc3545;\n}\n\n.result-content {\n flex: 1;\n min-width: 0;\n}\n\n.result-code {\n font-weight: 600;\n color: #2c3e50;\n margin-bottom: 4px;\n font-family: 'Courier New', monospace;\n}\n\n.result-description {\n color: #495057;\n font-size: 0.9em;\n line-height: 1.4;\n}\n\n/* Execution Section */\n.execution-stats-row {\n display: flex;\n gap: 20px;\n margin-bottom: 32px;\n flex-wrap: wrap;\n}\n\n.stat-box {\n flex: 1;\n min-width: 200px;\n background: #f8f9fa;\n border: 1px solid #e9ecef;\n border-radius: 8px;\n padding: 20px;\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.stat-box i {\n font-size: 2em;\n color: #6c757d;\n}\n\n.stat-info {\n flex: 1;\n}\n\n.executions-table {\n overflow-x: auto;\n border: 1px solid #e9ecef;\n border-radius: 8px;\n}\n\n.executions-table table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.executions-table th {\n background: #f8f9fa;\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: #495057;\n border-bottom: 2px solid #e9ecef;\n}\n\n.executions-table td {\n padding: 12px;\n border-bottom: 1px solid #e9ecef;\n}\n\n.execution-row {\n transition: background 0.2s;\n}\n\n.execution-row:hover {\n background: #f8f9fa;\n}\n\n.execution-row.success {\n background: #d4edda20;\n}\n\n.running {\n color: #ffc107;\n font-style: italic;\n}\n\n.result-code {\n display: inline-block;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 0.85em;\n font-weight: 500;\n font-family: 'Courier New', monospace;\n}\n\n.result-code.success {\n background: #d4edda;\n color: #155724;\n}\n\n.result-code.failure {\n background: #f8d7da;\n color: #721c24;\n}\n\n/* Configuration Section */\n.config-subsection {\n margin-bottom: 32px;\n}\n\n.config-subsection h3 {\n margin: 0 0 16px 0;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.library-cards {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.library-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 16px;\n background: #f8f9fa;\n border: 1px solid #e9ecef;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.library-card:hover {\n background: #e9ecef;\n transform: translateX(4px);\n}\n\n.library-card i:first-child {\n font-size: 1.5em;\n color: #6c757d;\n}\n\n.library-info {\n flex: 1;\n min-width: 0;\n}\n\n.library-name {\n font-weight: 600;\n color: #2c3e50;\n margin-bottom: 4px;\n}\n\n.library-items {\n color: #6c757d;\n font-size: 0.9em;\n font-family: 'Courier New', monospace;\n}\n\n.related-entities-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 12px;\n}\n\n.related-entity-link {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: #f8f9fa;\n border: 1px solid #e9ecef;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.related-entity-link:hover {\n background: #e9ecef;\n border-color: #007bff;\n}\n\n.related-entity-link i {\n font-size: 1.2em;\n color: #6c757d;\n}\n\n.related-entity-link span:first-of-type {\n flex: 1;\n font-weight: 500;\n color: #495057;\n}\n\n.entity-count {\n color: #007bff;\n font-size: 0.9em;\n}\n\n/* Common States */\n.loading-state {\n text-align: center;\n padding: 60px;\n color: #6c757d;\n}\n\n.loading-state i {\n font-size: 2em;\n margin-bottom: 12px;\n}\n\n.empty-state {\n text-align: center;\n padding: 60px;\n color: #6c757d;\n}\n\n.empty-state.mini {\n padding: 20px;\n}\n\n.empty-state i {\n font-size: 3em;\n margin-bottom: 16px;\n opacity: 0.3;\n}\n\n.empty-state p {\n margin: 0;\n font-size: 1.1em;\n}\n\n.empty-hint {\n margin-top: 8px !important;\n font-size: 0.9em !important;\n opacity: 0.7;\n}\n\n.no-params {\n text-align: center;\n padding: 20px;\n color: #6c757d;\n font-style: italic;\n}\n\n.no-params p {\n margin: 0;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .action-hero-header {\n padding: 20px;\n }\n \n .action-identity {\n flex-direction: column;\n text-align: center;\n }\n \n .action-icon-wrapper {\n margin: 0 auto;\n }\n \n .action-title-row {\n justify-content: center;\n }\n \n .action-stats {\n justify-content: center;\n }\n \n .params-grid {\n grid-template-columns: 1fr;\n }\n}"] }]
1899
1880
  }], () => [{ type: i0.ElementRef }, { type: i1.SharedService }, { type: i2.Router }, { type: i2.ActivatedRoute }, { type: i0.ChangeDetectorRef }], null); })();
1900
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ActionFormComponentExtended, { className: "ActionFormComponentExtended", filePath: "src/lib/custom/Actions/action-form.component.ts", lineNumber: 27 }); })();
1881
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ActionFormComponentExtended, { className: "ActionFormComponentExtended", filePath: "src/lib/custom/Actions/action-form.component.ts", lineNumber: 19 }); })();
1901
1882
  // Loader function required for the component to be properly registered
1902
1883
  export function LoadActionFormComponentExtended() {
1903
1884
  // This function is called to ensure the form is loaded and registered