@memberjunction/ng-core-entity-forms 3.2.0 → 3.4.0

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 (170) hide show
  1. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js +16 -17
  2. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js.map +1 -1
  3. package/dist/lib/custom/Actions/action-form.component.d.ts.map +1 -1
  4. package/dist/lib/custom/Actions/action-form.component.js +16 -30
  5. package/dist/lib/custom/Actions/action-form.component.js.map +1 -1
  6. package/dist/lib/custom/EntityActions/entityaction.form.component.js +9 -10
  7. package/dist/lib/custom/EntityActions/entityaction.form.component.js.map +1 -1
  8. package/dist/lib/custom/Queries/query-form.component.js +7 -7
  9. package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
  10. package/dist/lib/custom/Templates/templates-form.component.js +195 -112
  11. package/dist/lib/custom/Templates/templates-form.component.js.map +1 -1
  12. package/dist/lib/custom/Tests/test-form.component.d.ts +4 -1
  13. package/dist/lib/custom/Tests/test-form.component.d.ts.map +1 -1
  14. package/dist/lib/custom/Tests/test-form.component.js +401 -380
  15. package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
  16. package/dist/lib/custom/Tests/test-suite-form.component.d.ts +4 -1
  17. package/dist/lib/custom/Tests/test-suite-form.component.d.ts.map +1 -1
  18. package/dist/lib/custom/Tests/test-suite-form.component.js +539 -518
  19. package/dist/lib/custom/Tests/test-suite-form.component.js.map +1 -1
  20. package/dist/lib/custom/Tests/test-suite-run-form.component.d.ts +4 -1
  21. package/dist/lib/custom/Tests/test-suite-run-form.component.d.ts.map +1 -1
  22. package/dist/lib/custom/Tests/test-suite-run-form.component.js +535 -518
  23. package/dist/lib/custom/Tests/test-suite-run-form.component.js.map +1 -1
  24. package/dist/lib/custom/custom-forms.module.d.ts +48 -52
  25. package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
  26. package/dist/lib/custom/custom-forms.module.js +11 -25
  27. package/dist/lib/custom/custom-forms.module.js.map +1 -1
  28. package/dist/lib/generated/Entities/AIAgent/aiagent.form.component.d.ts.map +1 -1
  29. package/dist/lib/generated/Entities/AIAgent/aiagent.form.component.js +141 -113
  30. package/dist/lib/generated/Entities/AIAgent/aiagent.form.component.js.map +1 -1
  31. package/dist/lib/generated/Entities/AIAgentExample/aiagentexample.form.component.js +28 -14
  32. package/dist/lib/generated/Entities/AIAgentExample/aiagentexample.form.component.js.map +1 -1
  33. package/dist/lib/generated/Entities/AIAgentNote/aiagentnote.form.component.js +26 -12
  34. package/dist/lib/generated/Entities/AIAgentNote/aiagentnote.form.component.js.map +1 -1
  35. package/dist/lib/generated/Entities/AIAgentRun/aiagentrun.form.component.d.ts.map +1 -1
  36. package/dist/lib/generated/Entities/AIAgentRun/aiagentrun.form.component.js +67 -47
  37. package/dist/lib/generated/Entities/AIAgentRun/aiagentrun.form.component.js.map +1 -1
  38. package/dist/lib/generated/Entities/AIAgentRunStep/aiagentrunstep.form.component.d.ts.map +1 -1
  39. package/dist/lib/generated/Entities/AIAgentRunStep/aiagentrunstep.form.component.js +18 -24
  40. package/dist/lib/generated/Entities/AIAgentRunStep/aiagentrunstep.form.component.js.map +1 -1
  41. package/dist/lib/generated/Entities/AIResultCache/airesultcache.form.component.d.ts.map +1 -1
  42. package/dist/lib/generated/Entities/AIResultCache/airesultcache.form.component.js +11 -17
  43. package/dist/lib/generated/Entities/AIResultCache/airesultcache.form.component.js.map +1 -1
  44. package/dist/lib/generated/Entities/APIApplication/apiapplication.form.component.d.ts +11 -0
  45. package/dist/lib/generated/Entities/APIApplication/apiapplication.form.component.d.ts.map +1 -0
  46. package/dist/lib/generated/Entities/APIApplication/apiapplication.form.component.js +120 -0
  47. package/dist/lib/generated/Entities/APIApplication/apiapplication.form.component.js.map +1 -0
  48. package/dist/lib/generated/Entities/APIApplicationScope/apiapplicationscope.form.component.d.ts +11 -0
  49. package/dist/lib/generated/Entities/APIApplicationScope/apiapplicationscope.form.component.d.ts.map +1 -0
  50. package/dist/lib/generated/Entities/APIApplicationScope/apiapplicationscope.form.component.js +75 -0
  51. package/dist/lib/generated/Entities/APIApplicationScope/apiapplicationscope.form.component.js.map +1 -0
  52. package/dist/lib/generated/Entities/APIKey/apikey.form.component.d.ts.map +1 -1
  53. package/dist/lib/generated/Entities/APIKey/apikey.form.component.js +25 -7
  54. package/dist/lib/generated/Entities/APIKey/apikey.form.component.js.map +1 -1
  55. package/dist/lib/generated/Entities/APIKeyApplication/apikeyapplication.form.component.d.ts +11 -0
  56. package/dist/lib/generated/Entities/APIKeyApplication/apikeyapplication.form.component.d.ts.map +1 -0
  57. package/dist/lib/generated/Entities/APIKeyApplication/apikeyapplication.form.component.js +61 -0
  58. package/dist/lib/generated/Entities/APIKeyApplication/apikeyapplication.form.component.js.map +1 -0
  59. package/dist/lib/generated/Entities/APIKeyScope/apikeyscope.form.component.js +17 -9
  60. package/dist/lib/generated/Entities/APIKeyScope/apikeyscope.form.component.js.map +1 -1
  61. package/dist/lib/generated/Entities/APIKeyUsageLog/apikeyusagelog.form.component.js +19 -7
  62. package/dist/lib/generated/Entities/APIKeyUsageLog/apikeyusagelog.form.component.js.map +1 -1
  63. package/dist/lib/generated/Entities/APIScope/apiscope.form.component.d.ts.map +1 -1
  64. package/dist/lib/generated/Entities/APIScope/apiscope.form.component.js +67 -11
  65. package/dist/lib/generated/Entities/APIScope/apiscope.form.component.js.map +1 -1
  66. package/dist/lib/generated/Entities/Action/action.form.component.d.ts.map +1 -1
  67. package/dist/lib/generated/Entities/Action/action.form.component.js +44 -26
  68. package/dist/lib/generated/Entities/Action/action.form.component.js.map +1 -1
  69. package/dist/lib/generated/Entities/ActionCategory/actioncategory.form.component.d.ts.map +1 -1
  70. package/dist/lib/generated/Entities/ActionCategory/actioncategory.form.component.js +23 -5
  71. package/dist/lib/generated/Entities/ActionCategory/actioncategory.form.component.js.map +1 -1
  72. package/dist/lib/generated/Entities/Company/company.form.component.d.ts.map +1 -1
  73. package/dist/lib/generated/Entities/Company/company.form.component.js +28 -10
  74. package/dist/lib/generated/Entities/Company/company.form.component.js.map +1 -1
  75. package/dist/lib/generated/Entities/Conversation/conversation.form.component.js +3 -3
  76. package/dist/lib/generated/Entities/ConversationDetailArtifact/conversationdetailartifact.form.component.js +3 -3
  77. package/dist/lib/generated/Entities/ConversationDetailArtifact/conversationdetailartifact.form.component.js.map +1 -1
  78. package/dist/lib/generated/Entities/ConversationDetailRating/conversationdetailrating.form.component.js +3 -3
  79. package/dist/lib/generated/Entities/ConversationDetailRating/conversationdetailrating.form.component.js.map +1 -1
  80. package/dist/lib/generated/Entities/Credential/credential.form.component.d.ts.map +1 -1
  81. package/dist/lib/generated/Entities/Credential/credential.form.component.js +23 -5
  82. package/dist/lib/generated/Entities/Credential/credential.form.component.js.map +1 -1
  83. package/dist/lib/generated/Entities/CredentialType/credentialtype.form.component.d.ts.map +1 -1
  84. package/dist/lib/generated/Entities/CredentialType/credentialtype.form.component.js +23 -5
  85. package/dist/lib/generated/Entities/CredentialType/credentialtype.form.component.js.map +1 -1
  86. package/dist/lib/generated/Entities/DuplicateRunDetail/duplicaterundetail.form.component.d.ts.map +1 -1
  87. package/dist/lib/generated/Entities/DuplicateRunDetail/duplicaterundetail.form.component.js +14 -20
  88. package/dist/lib/generated/Entities/DuplicateRunDetail/duplicaterundetail.form.component.js.map +1 -1
  89. package/dist/lib/generated/Entities/EmployeeCompanyIntegration/employeecompanyintegration.form.component.d.ts.map +1 -1
  90. package/dist/lib/generated/Entities/EmployeeCompanyIntegration/employeecompanyintegration.form.component.js +9 -15
  91. package/dist/lib/generated/Entities/EmployeeCompanyIntegration/employeecompanyintegration.form.component.js.map +1 -1
  92. package/dist/lib/generated/Entities/EmployeeRole/employeerole.form.component.js +3 -3
  93. package/dist/lib/generated/Entities/EmployeeRole/employeerole.form.component.js.map +1 -1
  94. package/dist/lib/generated/Entities/EmployeeSkill/employeeskill.form.component.d.ts.map +1 -1
  95. package/dist/lib/generated/Entities/EmployeeSkill/employeeskill.form.component.js +6 -12
  96. package/dist/lib/generated/Entities/EmployeeSkill/employeeskill.form.component.js.map +1 -1
  97. package/dist/lib/generated/Entities/Entity/entity.form.component.d.ts.map +1 -1
  98. package/dist/lib/generated/Entities/Entity/entity.form.component.js +110 -56
  99. package/dist/lib/generated/Entities/Entity/entity.form.component.js.map +1 -1
  100. package/dist/lib/generated/Entities/EntityActionFilter/entityactionfilter.form.component.d.ts.map +1 -1
  101. package/dist/lib/generated/Entities/EntityActionFilter/entityactionfilter.form.component.js +5 -11
  102. package/dist/lib/generated/Entities/EntityActionFilter/entityactionfilter.form.component.js.map +1 -1
  103. package/dist/lib/generated/Entities/EntityActionInvocation/entityactioninvocation.form.component.d.ts.map +1 -1
  104. package/dist/lib/generated/Entities/EntityActionInvocation/entityactioninvocation.form.component.js +8 -14
  105. package/dist/lib/generated/Entities/EntityActionInvocation/entityactioninvocation.form.component.js.map +1 -1
  106. package/dist/lib/generated/Entities/EntityActionParam/entityactionparam.form.component.d.ts.map +1 -1
  107. package/dist/lib/generated/Entities/EntityActionParam/entityactionparam.form.component.js +6 -12
  108. package/dist/lib/generated/Entities/EntityActionParam/entityactionparam.form.component.js.map +1 -1
  109. package/dist/lib/generated/Entities/EntityCommunicationField/entitycommunicationfield.form.component.d.ts.map +1 -1
  110. package/dist/lib/generated/Entities/EntityCommunicationField/entitycommunicationfield.form.component.js +6 -12
  111. package/dist/lib/generated/Entities/EntityCommunicationField/entitycommunicationfield.form.component.js.map +1 -1
  112. package/dist/lib/generated/Entities/ErrorLog/errorlog.form.component.d.ts.map +1 -1
  113. package/dist/lib/generated/Entities/ErrorLog/errorlog.form.component.js +11 -17
  114. package/dist/lib/generated/Entities/ErrorLog/errorlog.form.component.js.map +1 -1
  115. package/dist/lib/generated/Entities/MCPServer/mcpserver.form.component.d.ts +11 -0
  116. package/dist/lib/generated/Entities/MCPServer/mcpserver.form.component.d.ts.map +1 -0
  117. package/dist/lib/generated/Entities/MCPServer/mcpserver.form.component.js +142 -0
  118. package/dist/lib/generated/Entities/MCPServer/mcpserver.form.component.js.map +1 -0
  119. package/dist/lib/generated/Entities/MCPServerConnection/mcpserverconnection.form.component.d.ts +11 -0
  120. package/dist/lib/generated/Entities/MCPServerConnection/mcpserverconnection.form.component.d.ts.map +1 -0
  121. package/dist/lib/generated/Entities/MCPServerConnection/mcpserverconnection.form.component.js +158 -0
  122. package/dist/lib/generated/Entities/MCPServerConnection/mcpserverconnection.form.component.js.map +1 -0
  123. package/dist/lib/generated/Entities/MCPServerConnectionPermission/mcpserverconnectionpermission.form.component.d.ts +11 -0
  124. package/dist/lib/generated/Entities/MCPServerConnectionPermission/mcpserverconnectionpermission.form.component.d.ts.map +1 -0
  125. package/dist/lib/generated/Entities/MCPServerConnectionPermission/mcpserverconnectionpermission.form.component.js +77 -0
  126. package/dist/lib/generated/Entities/MCPServerConnectionPermission/mcpserverconnectionpermission.form.component.js.map +1 -0
  127. package/dist/lib/generated/Entities/MCPServerConnectionTool/mcpserverconnectiontool.form.component.d.ts +11 -0
  128. package/dist/lib/generated/Entities/MCPServerConnectionTool/mcpserverconnectiontool.form.component.d.ts.map +1 -0
  129. package/dist/lib/generated/Entities/MCPServerConnectionTool/mcpserverconnectiontool.form.component.js +73 -0
  130. package/dist/lib/generated/Entities/MCPServerConnectionTool/mcpserverconnectiontool.form.component.js.map +1 -0
  131. package/dist/lib/generated/Entities/MCPServerTool/mcpservertool.form.component.d.ts +11 -0
  132. package/dist/lib/generated/Entities/MCPServerTool/mcpservertool.form.component.d.ts.map +1 -0
  133. package/dist/lib/generated/Entities/MCPServerTool/mcpservertool.form.component.js +132 -0
  134. package/dist/lib/generated/Entities/MCPServerTool/mcpservertool.form.component.js.map +1 -0
  135. package/dist/lib/generated/Entities/MCPToolExecutionLog/mcptoolexecutionlog.form.component.d.ts +11 -0
  136. package/dist/lib/generated/Entities/MCPToolExecutionLog/mcptoolexecutionlog.form.component.d.ts.map +1 -0
  137. package/dist/lib/generated/Entities/MCPToolExecutionLog/mcptoolexecutionlog.form.component.js +101 -0
  138. package/dist/lib/generated/Entities/MCPToolExecutionLog/mcptoolexecutionlog.form.component.js.map +1 -0
  139. package/dist/lib/generated/Entities/Role/role.form.component.d.ts.map +1 -1
  140. package/dist/lib/generated/Entities/Role/role.form.component.js +30 -12
  141. package/dist/lib/generated/Entities/Role/role.form.component.js.map +1 -1
  142. package/dist/lib/generated/Entities/Task/task.form.component.d.ts.map +1 -1
  143. package/dist/lib/generated/Entities/Task/task.form.component.js +26 -32
  144. package/dist/lib/generated/Entities/Task/task.form.component.js.map +1 -1
  145. package/dist/lib/generated/Entities/User/user.form.component.d.ts.map +1 -1
  146. package/dist/lib/generated/Entities/User/user.form.component.js +182 -146
  147. package/dist/lib/generated/Entities/User/user.form.component.js.map +1 -1
  148. package/dist/lib/generated/generated-forms.module.d.ts +142 -128
  149. package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
  150. package/dist/lib/generated/generated-forms.module.js +194 -101
  151. package/dist/lib/generated/generated-forms.module.js.map +1 -1
  152. package/dist/public-api.js +1 -0
  153. package/dist/public-api.js.map +1 -1
  154. package/package.json +30 -30
  155. package/dist/lib/custom/Actions/action-param-dialog.component.d.ts +0 -32
  156. package/dist/lib/custom/Actions/action-param-dialog.component.d.ts.map +0 -1
  157. package/dist/lib/custom/Actions/action-param-dialog.component.js +0 -321
  158. package/dist/lib/custom/Actions/action-param-dialog.component.js.map +0 -1
  159. package/dist/lib/custom/Actions/action-result-code-dialog.component.d.ts +0 -20
  160. package/dist/lib/custom/Actions/action-result-code-dialog.component.d.ts.map +0 -1
  161. package/dist/lib/custom/Actions/action-result-code-dialog.component.js +0 -127
  162. package/dist/lib/custom/Actions/action-result-code-dialog.component.js.map +0 -1
  163. package/dist/lib/custom/Actions/action-test-harness-dialog.component.d.ts +0 -15
  164. package/dist/lib/custom/Actions/action-test-harness-dialog.component.d.ts.map +0 -1
  165. package/dist/lib/custom/Actions/action-test-harness-dialog.component.js +0 -96
  166. package/dist/lib/custom/Actions/action-test-harness-dialog.component.js.map +0 -1
  167. package/dist/lib/custom/Actions/action-test-harness.component.d.ts +0 -50
  168. package/dist/lib/custom/Actions/action-test-harness.component.d.ts.map +0 -1
  169. package/dist/lib/custom/Actions/action-test-harness.component.js +0 -710
  170. package/dist/lib/custom/Actions/action-test-harness.component.js.map +0 -1
@@ -24,11 +24,10 @@ import * as i8 from "@progress/kendo-angular-dialog";
24
24
  import * as i9 from "@progress/kendo-angular-inputs";
25
25
  import * as i10 from "@progress/kendo-angular-dropdowns";
26
26
  import * as i11 from "@progress/kendo-angular-buttons";
27
- import * as i12 from "@memberjunction/ng-user-view-grid";
28
- import * as i13 from "@memberjunction/ng-base-forms";
29
- import * as i14 from "@memberjunction/ng-form-toolbar";
30
- import * as i15 from "@memberjunction/ng-code-editor";
31
- import * as i16 from "../../shared/components/template-editor.component";
27
+ import * as i12 from "@memberjunction/ng-base-forms";
28
+ import * as i13 from "@memberjunction/ng-form-toolbar";
29
+ import * as i14 from "@memberjunction/ng-code-editor";
30
+ import * as i15 from "../../shared/components/template-editor.component";
32
31
  const _c0 = ["templateEditor"];
33
32
  function _forTrack0($index, $item) { return this.getModelTrackId($item) || $index; }
34
33
  const _forTrack1 = ($index, $item) => $item.ID;
@@ -1410,17 +1409,17 @@ function AIPromptFormComponentExtended_form_2_Conditional_64_Template(rf, ctx) {
1410
1409
  i0.ɵɵelementStart(0, "kendo-expansionpanel", 30);
1411
1410
  i0.ɵɵtemplate(1, AIPromptFormComponentExtended_form_2_Conditional_64_ng_template_1_Template, 3, 0, "ng-template", 31);
1412
1411
  i0.ɵɵelementStart(2, "div", 37);
1413
- i0.ɵɵelement(3, "mj-user-view-grid", 220);
1412
+ i0.ɵɵelement(3, "mj-explorer-entity-data-grid", 220);
1414
1413
  i0.ɵɵelementEnd()();
1415
1414
  } if (rf & 2) {
1416
1415
  const ctx_r1 = i0.ɵɵnextContext(2);
1417
1416
  i0.ɵɵproperty("expanded", false);
1418
1417
  i0.ɵɵadvance(3);
1419
- i0.ɵɵproperty("Params", ctx_r1.BuildRelationshipViewParamsByEntityName("AI Result Cache", "AIPromptID"))("NewRecordValues", ctx_r1.NewRecordValues("AI Result Cache"))("AllowLoad", true)("EditMode", ctx_r1.GridEditMode());
1418
+ i0.ɵɵproperty("Params", ctx_r1.BuildRelationshipViewParamsByEntityName("AI Result Cache", "AIPromptID"))("NewRecordValues", ctx_r1.NewRecordValues("AI Result Cache"))("AllowLoad", true)("ShowToolbar", false);
1420
1419
  } }
1421
1420
  function AIPromptFormComponentExtended_form_2_Conditional_65_ng_template_1_Template(rf, ctx) { if (rf & 1) {
1422
1421
  i0.ɵɵelementStart(0, "span", 65);
1423
- i0.ɵɵelement(1, "i", 224);
1422
+ i0.ɵɵelement(1, "i", 223);
1424
1423
  i0.ɵɵtext(2, " Related Items ");
1425
1424
  i0.ɵɵelementEnd();
1426
1425
  } }
@@ -1430,20 +1429,20 @@ function AIPromptFormComponentExtended_form_2_Conditional_65_Template(rf, ctx) {
1430
1429
  i0.ɵɵelementStart(2, "div", 37)(3, "div", 38)(4, "div")(5, "h6", 222);
1431
1430
  i0.ɵɵtext(6, "AI Agents Using This Prompt");
1432
1431
  i0.ɵɵelementEnd();
1433
- i0.ɵɵelement(7, "mj-user-view-grid", 223);
1432
+ i0.ɵɵelement(7, "mj-explorer-entity-data-grid", 220);
1434
1433
  i0.ɵɵelementEnd();
1435
1434
  i0.ɵɵelementStart(8, "div")(9, "h6", 222);
1436
1435
  i0.ɵɵtext(10, "Prompts Using This as Result Selector");
1437
1436
  i0.ɵɵelementEnd();
1438
- i0.ɵɵelement(11, "mj-user-view-grid", 223);
1437
+ i0.ɵɵelement(11, "mj-explorer-entity-data-grid", 220);
1439
1438
  i0.ɵɵelementEnd()()()();
1440
1439
  } if (rf & 2) {
1441
1440
  const ctx_r1 = i0.ɵɵnextContext(2);
1442
1441
  i0.ɵɵproperty("expanded", false);
1443
1442
  i0.ɵɵadvance(7);
1444
- i0.ɵɵproperty("Params", ctx_r1.BuildRelationshipViewParamsByEntityName("MJ: AI Agent Prompts", "PromptID"))("NewRecordValues", ctx_r1.NewRecordValues("MJ: AI Agent Prompts"))("AllowLoad", true)("EditMode", ctx_r1.GridEditMode());
1443
+ i0.ɵɵproperty("Params", ctx_r1.BuildRelationshipViewParamsByEntityName("MJ: AI Agent Prompts", "PromptID"))("NewRecordValues", ctx_r1.NewRecordValues("MJ: AI Agent Prompts"))("AllowLoad", true)("ShowToolbar", false);
1445
1444
  i0.ɵɵadvance(4);
1446
- i0.ɵɵproperty("Params", ctx_r1.BuildRelationshipViewParamsByEntityName("AI Prompts", "ResultSelectorPromptID"))("NewRecordValues", ctx_r1.NewRecordValues("AI Prompts"))("AllowLoad", true)("EditMode", ctx_r1.GridEditMode());
1445
+ i0.ɵɵproperty("Params", ctx_r1.BuildRelationshipViewParamsByEntityName("AI Prompts", "ResultSelectorPromptID"))("NewRecordValues", ctx_r1.NewRecordValues("AI Prompts"))("AllowLoad", true)("ShowToolbar", false);
1447
1446
  } }
1448
1447
  function AIPromptFormComponentExtended_form_2_Template(rf, ctx) { if (rf & 1) {
1449
1448
  i0.ɵɵelementStart(0, "form", 6, 0);
@@ -1563,9 +1562,9 @@ function AIPromptFormComponentExtended_form_2_Template(rf, ctx) { if (rf & 1) {
1563
1562
  } }
1564
1563
  function AIPromptFormComponentExtended_Conditional_3_Template(rf, ctx) { if (rf & 1) {
1565
1564
  const _r36 = i0.ɵɵgetCurrentView();
1566
- i0.ɵɵelementStart(0, "kendo-window", 225);
1565
+ i0.ɵɵelementStart(0, "kendo-window", 224);
1567
1566
  i0.ɵɵlistener("close", function AIPromptFormComponentExtended_Conditional_3_Template_kendo_window_close_0_listener() { i0.ɵɵrestoreView(_r36); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onTestHarnessVisibilityChanged(false)); });
1568
- i0.ɵɵelementStart(1, "mj-ai-test-harness", 226);
1567
+ i0.ɵɵelementStart(1, "mj-ai-test-harness", 225);
1569
1568
  i0.ɵɵlistener("visibilityChange", function AIPromptFormComponentExtended_Conditional_3_Template_mj_ai_test_harness_visibilityChange_1_listener($event) { i0.ɵɵrestoreView(_r36); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onTestHarnessVisibilityChanged($event)); });
1570
1569
  i0.ɵɵelementEnd()();
1571
1570
  } if (rf & 2) {
@@ -3046,7 +3045,7 @@ let AIPromptFormComponentExtended = class AIPromptFormComponentExtended extends
3046
3045
  } if (rf & 2) {
3047
3046
  let _t;
3048
3047
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.templateEditor = _t.first);
3049
- } }, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 2, consts: [["form", "ngForm"], ["templateEditor", ""], [1, "record-form-container"], ["kendoDialogContainer", ""], ["class", "record-form", 4, "ngIf"], [3, "width", "height", "minWidth", "minHeight", "draggable", "resizable", "state", "title"], [1, "record-form"], [3, "form"], [1, "prompt-main-area", 2, "display", "flex", "flex-direction", "column", "height", "100%", "overflow-y", "auto"], [1, "prompt-header", 2, "flex-shrink", "0", "padding", "20px", "background", "#f8f9fa", "border-bottom", "2px solid #e9ecef"], [2, "display", "flex", "justify-content", "space-between", "align-items", "flex-start", "gap", "20px"], [2, "flex", "1", "min-width", "0"], [2, "display", "flex", "align-items", "center", "gap", "12px", "margin-bottom", "8px"], [1, "fa-solid", "fa-robot", 2, "color", "#6f42c1", "font-size", "1.4em"], ["name", "promptName", "placeholder", "Enter prompt name...", 2, "font-size", "1.2em", "font-weight", "600", "min-width", "300px", "flex", "1", 3, "ngModel"], [2, "display", "flex", "gap", "16px", "margin-bottom", "12px", "flex-wrap", "wrap"], ["name", "promptDescription", "placeholder", "Enter prompt description...", 2, "width", "100%", "max-width", "600px", "margin-bottom", "12px", 3, "ngModel", "rows"], [2, "margin", "0 0 12px 0", "color", "#6c757d", "font-size", "0.9em", "line-height", "1.4"], [1, "quick-config", 2, "display", "flex", "align-items", "center", "gap", "16px", "flex-wrap", "wrap"], [1, "config-item", 2, "display", "flex", "align-items", "center", "gap", "6px", "font-size", "0.85em"], [1, "fa-solid", "fa-layer-group", 2, "color", "#6c757d"], [2, "color", "#6c757d"], [2, "color", "#495057", "font-weight", "500"], [1, "fa-solid", "fa-code", 2, "color", "#6c757d"], [2, "font-weight", "500"], [1, "action-buttons", 2, "display", "flex", "flex-direction", "column", "gap", "8px", "align-items", "flex-end"], [2, "display", "flex", "gap", "8px"], ["kendoButton", "", "title", "Run AI Prompt Test Harness", 3, "themeColor", "size"], [2, "font-size", "0.75em", "color", "#dc3545", "text-align", "right", "max-width", "200px"], [1, "configuration-sections", 2, "flex", "1", "background", "white", "border-top", "2px solid #e9ecef", "padding", "16px", "min-height", "0"], [2, "margin-bottom", "12px", 3, "expanded"], ["kendoExpansionPanelTitleDirective", ""], [1, "template-section", 2, "display", "flex", "flex-direction", "column", "min-height", "400px", "padding", "8px"], [1, "loading-state", 2, "flex", "1", "display", "flex", "align-items", "center", "justify-content", "center", "color", "#6c757d"], [1, "no-template-state", 2, "flex", "1", "display", "flex", "flex-direction", "column", "align-items", "center", "justify-content", "center", "padding", "40px", "color", "#6c757d"], [1, "invalid-template-state", 2, "flex", "1", "display", "flex", "flex-direction", "column", "align-items", "center", "justify-content", "center", "padding", "40px", "color", "#dc3545"], [1, "template-editor-container", 2, "flex", "1", "display", "flex", "flex-direction", "column", "min-height", "350px"], [2, "padding", "16px 0"], [2, "display", "grid", "grid-template-columns", "1fr 1fr", "gap", "20px"], ["FieldName", "ParallelizationMode", "Type", "dropdownlist", 3, "record", "ShowLabel", "EditMode"], ["FieldName", "ParallelCount", "Type", "numerictextbox", 3, "record", "ShowLabel", "EditMode"], ["FieldName", "ParallelConfigParam", "Type", "textbox", 3, "record", "ShowLabel", "EditMode"], ["FieldName", "OutputType", "Type", "dropdownlist", 3, "record", "ShowLabel", "EditMode"], ["FieldName", "EffortLevel", "Type", "numerictextbox", "Caption", "Effort Level (1-100)", "Description", "Higher values request more thorough reasoning", 3, "record", "ShowLabel", "EditMode"], ["FieldName", "ValidationBehavior", "Type", "dropdownlist", 3, "record", "ShowLabel", "EditMode"], ["FieldName", "EnableCaching", "Type", "checkbox", 3, "record", "ShowLabel", "EditMode"], [2, "margin-bottom", "16px"], [2, "display", "block", "margin-bottom", "4px", "font-weight", "600", "color", "#495057", "font-size", "0.9em"], [2, "color", "#495057"], ["name", "promptName", "placeholder", "Enter prompt name...", 2, "font-size", "1.2em", "font-weight", "600", "min-width", "300px", "flex", "1", 3, "ngModelChange", "ngModel"], [2, "margin", "0", "color", "#495057", "font-weight", "600", "flex", "1"], [1, "status-badge", 2, "color", "white", "padding", "4px 10px", "border-radius", "12px", "font-size", "0.75em", "font-weight", "500"], ["name", "promptStatus", "textField", "text", "valueField", "value", 2, "width", "150px", 3, "ngModelChange", "ngModel", "data", "valuePrimitive"], [2, "color", "#dc3545"], [2, "padding", "8px", "color", "#6c757d", "font-style", "italic", "width", "200px"], ["name", "promptTypeID", "textField", "Name", "valueField", "ID", "placeholder", "Select prompt type...", 2, "width", "200px", 3, "ngModel", "data", "valuePrimitive", "filterable"], [1, "fa-solid", "fa-spinner", "fa-spin"], ["name", "promptTypeID", "textField", "Name", "valueField", "ID", "placeholder", "Select prompt type...", 2, "width", "200px", 3, "ngModelChange", "ngModel", "data", "valuePrimitive", "filterable"], ["name", "promptDescription", "placeholder", "Enter prompt description...", 2, "width", "100%", "max-width", "600px", "margin-bottom", "12px", 3, "ngModelChange", "ngModel", "rows"], [1, "fa-solid", "fa-tag", 2, "color", "#6c757d"], [1, "fa-solid", "fa-database", 2, "color", "#28a745"], [2, "color", "#28a745", "font-weight", "500"], [1, "fa-solid", "fa-tachometer-alt", 2, "color", "#6c757d"], ["kendoButton", "", "title", "Run AI Prompt Test Harness", 3, "click", "themeColor", "size"], [1, "fa-solid", "fa-play"], [2, "display", "flex", "align-items", "center", "gap", "8px", "font-weight", "600"], [2, "color", "#6c757d", "font-size", "0.9em", "font-weight", "normal"], [1, "fa-solid", "fa-spinner", "fa-spin", 2, "font-size", "24px", "margin-right", "12px"], [1, "fa-solid", "fa-code", 2, "font-size", "64px", "margin-bottom", "20px", "opacity", "0.3"], [2, "margin-bottom", "12px", "color", "#495057"], [2, "margin-bottom", "24px", "text-align", "center", "max-width", "400px"], [2, "display", "flex", "gap", "12px"], ["kendoButton", "", 3, "themeColor"], ["kendoButton", "", 3, "fillMode"], ["kendoButton", "", 3, "click", "themeColor"], [1, "fa-solid", "fa-plus"], ["kendoButton", "", 3, "click", "fillMode"], [1, "fa-solid", "fa-link"], [1, "fa-solid", "fa-exclamation-triangle", 2, "font-size", "64px", "margin-bottom", "20px", "opacity", "0.7"], [2, "margin-bottom", "12px"], [1, "fa-solid", "fa-refresh"], [1, "template-actions", 2, "display", "flex", "gap", "8px", "padding", "8px", "border-bottom", "1px solid #e9ecef", "background", "#f8f9fa"], [2, "flex", "1", "background", "white", "border-radius", "6px", "border", "1px solid #e9ecef"], [2, "display", "block", "min-height", "300px", 3, "contentChange", "runTemplate", "template", "config"], ["kendoButton", "", "title", "Change to a different template", 3, "fillMode", "size"], ["kendoButton", "", "title", "Open template in new window", 3, "fillMode", "size"], ["kendoButton", "", "title", "Change to a different template", 3, "click", "fillMode", "size"], [1, "fa-solid", "fa-exchange-alt"], ["kendoButton", "", "title", "Open template in new window", 3, "click", "fillMode", "size"], [1, "fa-solid", "fa-external-link-alt"], [1, "model-management", 2, "border", "1px solid #dee2e6", "border-radius", "6px", "background", "#f8f9fa"], [1, "loading-state", 2, "padding", "20px", "text-align", "center", "color", "#6c757d"], [1, "fa-solid", "fa-microchip", 2, "color", "#6c757d"], [1, "badge", 2, "background", "#17a2b8", "color", "white", "padding", "2px 6px", "border-radius", "10px", "font-size", "0.7em"], [2, "color", "#6c757d", "font-size", "0.8em", "font-weight", "normal", "margin-left", "8px"], ["title", "Models are tried in order from top to bottom. The first available model will be used.", 1, "fa-solid", "fa-info-circle"], [1, "empty-state", 2, "padding", "20px", "text-align", "center", "color", "#6c757d"], [1, "fa-solid", "fa-info-circle"], [2, "margin-top", "10px"], ["kendoButton", "", "fillMode", "outline", "themeColor", "primary", "size", "small", 3, "click"], [2, "padding", "12px 16px", "background", "#e3f2fd", "border-bottom", "1px solid #bbdefb", "color", "#1565c0", "font-size", "0.85em"], [1, "model-header", 2, "display", "grid", "grid-template-columns", "40px 2fr 1fr 1fr 1fr 60px", "gap", "12px", "padding", "12px 16px", "background", "#e9ecef", "font-weight", "600", "font-size", "0.85em", "color", "#495057", "border-bottom", "1px solid #dee2e6"], ["title", "Priority order - models are tried from top to bottom"], [1, "fa-solid", "fa-sort", 2, "color", "#6c757d"], [1, "add-model-row", 2, "padding", "12px 16px", "text-align", "center", "background", "#f8f9fa", "border-top", "1px solid #dee2e6"], [1, "fa-solid", "fa-info-circle", 2, "margin-right", "6px"], [1, "model-row", 2, "display", "grid", "grid-template-columns", "40px 2fr 1fr 1fr 1fr 60px", "gap", "12px", "padding", "12px 16px", "border-bottom", "1px solid #e9ecef", "align-items", "start", "transition", "background 0.2s, opacity 0.2s", 3, "dragstart", "dragover", "drop", "dragend", "draggable"], [1, "drag-handle", 2, "display", "flex", "flex-direction", "column", "align-items", "center", "justify-content", "center", "color", "#6c757d"], [2, "font-size", "0.9em", "font-weight", "600", 3, "title"], [1, "model-select"], ["textField", "Name", "valueField", "ID", "placeholder", "Select a model...", 2, "width", "100%", 3, "ngModel", "name", "data", "valuePrimitive", "filterable"], [1, "model-vendor"], [1, "model-configuration"], [2, "font-size", "0.9em"], [1, "model-created"], [2, "color", "#6c757d", "font-size", "0.8em"], [2, "color", "#28a745", "font-size", "0.8em", "font-style", "italic"], [1, "model-actions", 2, "display", "flex", "gap", "2px", "flex-direction", "column"], [2, "display", "grid", "grid-template-columns", "40px 1fr", "gap", "12px", "padding", "8px 16px", "border-bottom", "1px solid #e9ecef", "background", "#f8f9fa", "font-size", "0.85em", "color", "#6c757d"], [2, "display", "flex", "gap", "16px", "flex-wrap", "wrap", "align-items", "center", "margin-bottom", "8px"], [2, "padding", "8px", "background", "#fff", "border", "1px solid #dee2e6", "border-radius", "4px", "margin-top", "8px"], ["title", "Drag to reorder priority", 1, "fa-solid", "fa-grip-vertical", 2, "cursor", "move"], [2, "font-size", "0.7em", "margin-top", "2px"], ["textField", "Name", "valueField", "ID", "placeholder", "Select a model...", 2, "width", "100%", 3, "ngModelChange", "valueChange", "ngModel", "name", "data", "valuePrimitive", "filterable"], [2, "color", "#6c757d", "font-style", "italic", "font-size", "0.9em"], ["textField", "Name", "valueField", "ID", "placeholder", "Select vendor...", 2, "width", "100%", 3, "ngModel", "name", "data", "valuePrimitive", "filterable"], ["textField", "Name", "valueField", "ID", "placeholder", "Select vendor...", 2, "width", "100%", 3, "ngModelChange", "ngModel", "name", "data", "valuePrimitive", "filterable"], ["kendoDropDownListItemTemplate", ""], [2, "font-size", "0.8em", "margin-left", "4px"], [2, "font-size", "0.9em", "font-weight", "500", 3, "color"], [2, "font-size", "0.9em", "font-weight", "500"], [2, "font-size", "0.9em", 3, "color"], [2, "color", "#6c757d", "font-size", "0.9em"], [2, "padding", "4px", "color", "#6c757d", "font-style", "italic", "font-size", "0.85em"], ["textField", "Name", "valueField", "ID", "placeholder", "Default", 2, "width", "100%", 3, "ngModel", "name", "data", "valuePrimitive", "filterable"], ["textField", "Name", "valueField", "ID", "placeholder", "Default", 2, "width", "100%", 3, "ngModelChange", "valueChange", "ngModel", "name", "data", "valuePrimitive", "filterable"], ["kendoDropDownListNoDataTemplate", ""], [2, "padding", "8px", "text-align", "center", "color", "#6c757d"], [2, "display", "flex", "gap", "2px", "margin-bottom", "4px"], ["kendoButton", "", "fillMode", "flat", "themeColor", "error", "size", "small", "title", "Remove model"], ["kendoButton", "", "fillMode", "flat", "size", "small", "title", "Move up", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-up"], ["kendoButton", "", "fillMode", "flat", "size", "small", "title", "Move down", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-down"], ["kendoButton", "", "fillMode", "flat", "themeColor", "error", "size", "small", "title", "Remove model", 3, "click"], [1, "fa-solid", "fa-times"], [2, "margin-bottom", "6px", "font-weight", "600", "color", "#495057", "font-size", "0.9em"], [1, "fa-solid", "fa-layer-group"], [2, "display", "grid", "grid-template-columns", "1fr 1fr 1fr", "gap", "12px", "align-items", "center"], [2, "display", "flex", "gap", "16px", "flex-wrap", "wrap", "align-items", "center"], [2, "display", "block", "margin-bottom", "2px", "font-size", "0.8em", "font-weight", "600", "color", "#495057"], ["textField", "text", "valueField", "value", "placeholder", "Select mode...", 2, "width", "100%", "font-size", "0.85em", 3, "ngModelChange", "ngModel", "name", "data", "valuePrimitive"], ["placeholder", "Count...", 2, "width", "100%", "font-size", "0.85em", 3, "ngModelChange", "ngModel", "name", "min", "step", "format"], ["placeholder", "Parameter name...", 2, "width", "100%", "font-size", "0.85em", 3, "ngModelChange", "ngModel", "name"], ["kendoButton", "", "fillMode", "outline", "themeColor", "success", "size", "small", 3, "click"], [1, "fa-solid", "fa-cogs", 2, "color", "#6c757d"], [2, "padding", "8px", "color", "#6c757d", "font-style", "italic"], ["name", "resultSelectorPromptID", "textField", "text", "valueField", "value", "placeholder", "Select a result selector prompt...", 2, "width", "100%", 3, "ngModel", "data", "valuePrimitive", "filterable"], ["name", "resultSelectorPromptID", "textField", "text", "valueField", "value", "placeholder", "Select a result selector prompt...", 2, "width", "100%", 3, "ngModelChange", "valueChange", "ngModel", "data", "valuePrimitive", "filterable"], [1, "fa-solid", "fa-sliders", 2, "color", "#6c757d"], [1, "badge", 2, "background", "#6f42c1", "color", "white", "padding", "2px 6px", "border-radius", "10px", "font-size", "0.7em"], ["title", "These parameters are defined in the template and will be available when executing this prompt", 1, "fa-solid", "fa-info-circle"], [2, "display", "grid", "gap", "12px"], [1, "parameter-card", 2, "border", "1px solid #e9ecef", "border-radius", "8px", "padding", "16px", "background", "#f8f9fa", "transition", "all 0.2s", 3, "border-left"], [2, "margin-top", "16px", "padding", "12px", "background", "#e3f2fd", "border-radius", "6px", "border", "1px solid #bbdefb"], [2, "display", "flex", "align-items", "flex-start", "gap", "8px"], [1, "fa-solid", "fa-lightbulb", 2, "color", "#1976d2", "margin-top", "2px"], [2, "flex", "1", "font-size", "0.85em", "color", "#1565c0", "line-height", "1.5"], [1, "parameter-card", 2, "border", "1px solid #e9ecef", "border-radius", "8px", "padding", "16px", "background", "#f8f9fa", "transition", "all 0.2s"], [2, "display", "flex", "justify-content", "space-between", "align-items", "flex-start", "margin-bottom", "8px"], [2, "display", "flex", "align-items", "center", "gap", "8px"], [2, "font-size", "1.2em"], [2, "margin", "0", "color", "#495057", "font-weight", "600"], [2, "color", "#dc3545", "font-size", "0.9em", "margin-left", "4px"], [1, "type-badge", 2, "color", "white", "padding", "4px 8px", "border-radius", "12px", "font-size", "0.75em", "font-weight", "500"], [2, "color", "#dc3545", "font-size", "0.85em", "font-weight", "500"], [2, "color", "#6c757d", "font-size", "0.85em"], [2, "margin", "0 0 8px 0", "color", "#6c757d", "font-size", "0.9em", "line-height", "1.4"], [2, "font-size", "0.85em", "color", "#495057"], [2, "display", "flex", "align-items", "center", "gap", "4px", "margin-bottom", "4px"], [1, "fa-solid", "fa-info-circle", 2, "color", "#6c757d"], [2, "display", "grid", "grid-template-columns", "repeat(auto-fit, minmax(200px, 1fr))", "gap", "12px", "margin-top", "12px"], [2, "background", "white", "padding", "8px 12px", "border-radius", "4px", "border", "1px solid #dee2e6"], [2, "display", "block", "font-size", "0.8em", "color", "#6c757d", "margin-bottom", "2px"], [2, "font-size", "0.85em", "color", "#495057", "word-break", "break-all"], [2, "font-size", "0.8em", "color", "#495057", "word-break", "break-all"], [2, "padding", "16px"], [2, "background", "#f8f9fa", "border", "1px solid #dee2e6", "border-radius", "4px", "padding", "12px", "font-family", "'Courier New', monospace", "font-size", "0.9em", "white-space", "pre-wrap", "overflow", "auto", "max-height", "250px"], [2, "background", "#fff3cd", "border", "1px solid #ffeaa7", "border-radius", "4px", "padding", "12px", "color", "#856404", "text-align", "center"], [2, "color", "#dc3545", "font-size", "0.8em", "font-weight", "normal"], ["name", "outputExample", "language", "json", "placeholder", "Enter JSON example structure...", 2, "width", "100%", "height", "200px", "border", "1px solid #dee2e6", "border-radius", "4px", 3, "ngModelChange", "ngModel"], [2, "margin-top", "8px", "color", "#6c757d", "font-size", "0.85em"], [1, "fa-solid", "fa-exclamation-triangle"], [2, "text-align", "center", "padding", "40px", "color", "#6c757d"], [1, "fa-solid", "fa-history", 2, "color", "#6c757d"], [2, "color", "#6c757d", "font-weight", "normal"], [1, "fa-solid", "fa-spinner", "fa-spin", 2, "font-size", "2em", "margin-bottom", "12px"], [1, "fa-solid", "fa-history", 2, "font-size", "3em", "margin-bottom", "12px", "opacity", "0.3"], [2, "display", "flex", "justify-content", "space-between", "align-items", "center", "margin-bottom", "16px"], [2, "display", "flex", "gap", "8px", "align-items", "center"], ["selection", "single"], ["kendoButton", "", "size", "small", 3, "click", "selected"], [2, "margin-left", "4px", "font-size", "0.8em", 3, "class"], [2, "border", "1px solid #e9ecef", "border-radius", "8px", "overflow", "hidden"], [2, "width", "100%", "border-collapse", "collapse"], [2, "background", "#f8f9fa", "border-bottom", "2px solid #e9ecef"], [2, "padding", "12px", "text-align", "left", "font-weight", "600", "color", "#495057"], [2, "padding", "12px", "text-align", "right", "font-weight", "600", "color", "#495057"], [2, "padding", "12px", "text-align", "center", "font-weight", "600", "color", "#495057"], [1, "history-row", 2, "border-bottom", "1px solid #f1f3f5", 3, "even-row"], [2, "margin-left", "4px", "font-size", "0.8em"], [1, "history-row", 2, "border-bottom", "1px solid #f1f3f5"], [2, "padding", "12px"], [2, "display", "flex", "align-items", "center", "gap", "6px"], [2, "padding", "12px", "color", "#495057"], [2, "padding", "12px", "text-align", "right", "color", "#495057"], [2, "padding", "12px", "text-align", "center"], [2, "padding", "4px 8px", "border-radius", "12px", "background", "#e9ecef", "color", "#495057", "font-size", "0.85em", "font-weight", "500"], ["kendoButton", "", "fillMode", "flat", "size", "small", "title", "View details", 3, "click"], [1, "fa-solid", "fa-external-link"], [2, "height", "300px", 3, "Params", "NewRecordValues", "AllowLoad", "EditMode"], [1, "fa-solid", "fa-database", 2, "color", "#6c757d"], [2, "margin", "0 0 12px 0", "color", "#495057"], [2, "height", "200px", 3, "Params", "NewRecordValues", "AllowLoad", "EditMode"], [1, "fa-solid", "fa-link", 2, "color", "#6c757d"], [3, "close", "width", "height", "minWidth", "minHeight", "draggable", "resizable", "state", "title"], [3, "visibilityChange", "entity", "mode", "isVisible"]], template: function AIPromptFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
3048
+ } }, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 2, consts: [["form", "ngForm"], ["templateEditor", ""], [1, "record-form-container"], ["kendoDialogContainer", ""], ["class", "record-form", 4, "ngIf"], [3, "width", "height", "minWidth", "minHeight", "draggable", "resizable", "state", "title"], [1, "record-form"], [3, "form"], [1, "prompt-main-area", 2, "display", "flex", "flex-direction", "column", "height", "100%", "overflow-y", "auto"], [1, "prompt-header", 2, "flex-shrink", "0", "padding", "20px", "background", "#f8f9fa", "border-bottom", "2px solid #e9ecef"], [2, "display", "flex", "justify-content", "space-between", "align-items", "flex-start", "gap", "20px"], [2, "flex", "1", "min-width", "0"], [2, "display", "flex", "align-items", "center", "gap", "12px", "margin-bottom", "8px"], [1, "fa-solid", "fa-robot", 2, "color", "#6f42c1", "font-size", "1.4em"], ["name", "promptName", "placeholder", "Enter prompt name...", 2, "font-size", "1.2em", "font-weight", "600", "min-width", "300px", "flex", "1", 3, "ngModel"], [2, "display", "flex", "gap", "16px", "margin-bottom", "12px", "flex-wrap", "wrap"], ["name", "promptDescription", "placeholder", "Enter prompt description...", 2, "width", "100%", "max-width", "600px", "margin-bottom", "12px", 3, "ngModel", "rows"], [2, "margin", "0 0 12px 0", "color", "#6c757d", "font-size", "0.9em", "line-height", "1.4"], [1, "quick-config", 2, "display", "flex", "align-items", "center", "gap", "16px", "flex-wrap", "wrap"], [1, "config-item", 2, "display", "flex", "align-items", "center", "gap", "6px", "font-size", "0.85em"], [1, "fa-solid", "fa-layer-group", 2, "color", "#6c757d"], [2, "color", "#6c757d"], [2, "color", "#495057", "font-weight", "500"], [1, "fa-solid", "fa-code", 2, "color", "#6c757d"], [2, "font-weight", "500"], [1, "action-buttons", 2, "display", "flex", "flex-direction", "column", "gap", "8px", "align-items", "flex-end"], [2, "display", "flex", "gap", "8px"], ["kendoButton", "", "title", "Run AI Prompt Test Harness", 3, "themeColor", "size"], [2, "font-size", "0.75em", "color", "#dc3545", "text-align", "right", "max-width", "200px"], [1, "configuration-sections", 2, "flex", "1", "background", "white", "border-top", "2px solid #e9ecef", "padding", "16px", "min-height", "0"], [2, "margin-bottom", "12px", 3, "expanded"], ["kendoExpansionPanelTitleDirective", ""], [1, "template-section", 2, "display", "flex", "flex-direction", "column", "min-height", "400px", "padding", "8px"], [1, "loading-state", 2, "flex", "1", "display", "flex", "align-items", "center", "justify-content", "center", "color", "#6c757d"], [1, "no-template-state", 2, "flex", "1", "display", "flex", "flex-direction", "column", "align-items", "center", "justify-content", "center", "padding", "40px", "color", "#6c757d"], [1, "invalid-template-state", 2, "flex", "1", "display", "flex", "flex-direction", "column", "align-items", "center", "justify-content", "center", "padding", "40px", "color", "#dc3545"], [1, "template-editor-container", 2, "flex", "1", "display", "flex", "flex-direction", "column", "min-height", "350px"], [2, "padding", "16px 0"], [2, "display", "grid", "grid-template-columns", "1fr 1fr", "gap", "20px"], ["FieldName", "ParallelizationMode", "Type", "dropdownlist", 3, "record", "ShowLabel", "EditMode"], ["FieldName", "ParallelCount", "Type", "numerictextbox", 3, "record", "ShowLabel", "EditMode"], ["FieldName", "ParallelConfigParam", "Type", "textbox", 3, "record", "ShowLabel", "EditMode"], ["FieldName", "OutputType", "Type", "dropdownlist", 3, "record", "ShowLabel", "EditMode"], ["FieldName", "EffortLevel", "Type", "numerictextbox", "Caption", "Effort Level (1-100)", "Description", "Higher values request more thorough reasoning", 3, "record", "ShowLabel", "EditMode"], ["FieldName", "ValidationBehavior", "Type", "dropdownlist", 3, "record", "ShowLabel", "EditMode"], ["FieldName", "EnableCaching", "Type", "checkbox", 3, "record", "ShowLabel", "EditMode"], [2, "margin-bottom", "16px"], [2, "display", "block", "margin-bottom", "4px", "font-weight", "600", "color", "#495057", "font-size", "0.9em"], [2, "color", "#495057"], ["name", "promptName", "placeholder", "Enter prompt name...", 2, "font-size", "1.2em", "font-weight", "600", "min-width", "300px", "flex", "1", 3, "ngModelChange", "ngModel"], [2, "margin", "0", "color", "#495057", "font-weight", "600", "flex", "1"], [1, "status-badge", 2, "color", "white", "padding", "4px 10px", "border-radius", "12px", "font-size", "0.75em", "font-weight", "500"], ["name", "promptStatus", "textField", "text", "valueField", "value", 2, "width", "150px", 3, "ngModelChange", "ngModel", "data", "valuePrimitive"], [2, "color", "#dc3545"], [2, "padding", "8px", "color", "#6c757d", "font-style", "italic", "width", "200px"], ["name", "promptTypeID", "textField", "Name", "valueField", "ID", "placeholder", "Select prompt type...", 2, "width", "200px", 3, "ngModel", "data", "valuePrimitive", "filterable"], [1, "fa-solid", "fa-spinner", "fa-spin"], ["name", "promptTypeID", "textField", "Name", "valueField", "ID", "placeholder", "Select prompt type...", 2, "width", "200px", 3, "ngModelChange", "ngModel", "data", "valuePrimitive", "filterable"], ["name", "promptDescription", "placeholder", "Enter prompt description...", 2, "width", "100%", "max-width", "600px", "margin-bottom", "12px", 3, "ngModelChange", "ngModel", "rows"], [1, "fa-solid", "fa-tag", 2, "color", "#6c757d"], [1, "fa-solid", "fa-database", 2, "color", "#28a745"], [2, "color", "#28a745", "font-weight", "500"], [1, "fa-solid", "fa-tachometer-alt", 2, "color", "#6c757d"], ["kendoButton", "", "title", "Run AI Prompt Test Harness", 3, "click", "themeColor", "size"], [1, "fa-solid", "fa-play"], [2, "display", "flex", "align-items", "center", "gap", "8px", "font-weight", "600"], [2, "color", "#6c757d", "font-size", "0.9em", "font-weight", "normal"], [1, "fa-solid", "fa-spinner", "fa-spin", 2, "font-size", "24px", "margin-right", "12px"], [1, "fa-solid", "fa-code", 2, "font-size", "64px", "margin-bottom", "20px", "opacity", "0.3"], [2, "margin-bottom", "12px", "color", "#495057"], [2, "margin-bottom", "24px", "text-align", "center", "max-width", "400px"], [2, "display", "flex", "gap", "12px"], ["kendoButton", "", 3, "themeColor"], ["kendoButton", "", 3, "fillMode"], ["kendoButton", "", 3, "click", "themeColor"], [1, "fa-solid", "fa-plus"], ["kendoButton", "", 3, "click", "fillMode"], [1, "fa-solid", "fa-link"], [1, "fa-solid", "fa-exclamation-triangle", 2, "font-size", "64px", "margin-bottom", "20px", "opacity", "0.7"], [2, "margin-bottom", "12px"], [1, "fa-solid", "fa-refresh"], [1, "template-actions", 2, "display", "flex", "gap", "8px", "padding", "8px", "border-bottom", "1px solid #e9ecef", "background", "#f8f9fa"], [2, "flex", "1", "background", "white", "border-radius", "6px", "border", "1px solid #e9ecef"], [2, "display", "block", "min-height", "300px", 3, "contentChange", "runTemplate", "template", "config"], ["kendoButton", "", "title", "Change to a different template", 3, "fillMode", "size"], ["kendoButton", "", "title", "Open template in new window", 3, "fillMode", "size"], ["kendoButton", "", "title", "Change to a different template", 3, "click", "fillMode", "size"], [1, "fa-solid", "fa-exchange-alt"], ["kendoButton", "", "title", "Open template in new window", 3, "click", "fillMode", "size"], [1, "fa-solid", "fa-external-link-alt"], [1, "model-management", 2, "border", "1px solid #dee2e6", "border-radius", "6px", "background", "#f8f9fa"], [1, "loading-state", 2, "padding", "20px", "text-align", "center", "color", "#6c757d"], [1, "fa-solid", "fa-microchip", 2, "color", "#6c757d"], [1, "badge", 2, "background", "#17a2b8", "color", "white", "padding", "2px 6px", "border-radius", "10px", "font-size", "0.7em"], [2, "color", "#6c757d", "font-size", "0.8em", "font-weight", "normal", "margin-left", "8px"], ["title", "Models are tried in order from top to bottom. The first available model will be used.", 1, "fa-solid", "fa-info-circle"], [1, "empty-state", 2, "padding", "20px", "text-align", "center", "color", "#6c757d"], [1, "fa-solid", "fa-info-circle"], [2, "margin-top", "10px"], ["kendoButton", "", "fillMode", "outline", "themeColor", "primary", "size", "small", 3, "click"], [2, "padding", "12px 16px", "background", "#e3f2fd", "border-bottom", "1px solid #bbdefb", "color", "#1565c0", "font-size", "0.85em"], [1, "model-header", 2, "display", "grid", "grid-template-columns", "40px 2fr 1fr 1fr 1fr 60px", "gap", "12px", "padding", "12px 16px", "background", "#e9ecef", "font-weight", "600", "font-size", "0.85em", "color", "#495057", "border-bottom", "1px solid #dee2e6"], ["title", "Priority order - models are tried from top to bottom"], [1, "fa-solid", "fa-sort", 2, "color", "#6c757d"], [1, "add-model-row", 2, "padding", "12px 16px", "text-align", "center", "background", "#f8f9fa", "border-top", "1px solid #dee2e6"], [1, "fa-solid", "fa-info-circle", 2, "margin-right", "6px"], [1, "model-row", 2, "display", "grid", "grid-template-columns", "40px 2fr 1fr 1fr 1fr 60px", "gap", "12px", "padding", "12px 16px", "border-bottom", "1px solid #e9ecef", "align-items", "start", "transition", "background 0.2s, opacity 0.2s", 3, "dragstart", "dragover", "drop", "dragend", "draggable"], [1, "drag-handle", 2, "display", "flex", "flex-direction", "column", "align-items", "center", "justify-content", "center", "color", "#6c757d"], [2, "font-size", "0.9em", "font-weight", "600", 3, "title"], [1, "model-select"], ["textField", "Name", "valueField", "ID", "placeholder", "Select a model...", 2, "width", "100%", 3, "ngModel", "name", "data", "valuePrimitive", "filterable"], [1, "model-vendor"], [1, "model-configuration"], [2, "font-size", "0.9em"], [1, "model-created"], [2, "color", "#6c757d", "font-size", "0.8em"], [2, "color", "#28a745", "font-size", "0.8em", "font-style", "italic"], [1, "model-actions", 2, "display", "flex", "gap", "2px", "flex-direction", "column"], [2, "display", "grid", "grid-template-columns", "40px 1fr", "gap", "12px", "padding", "8px 16px", "border-bottom", "1px solid #e9ecef", "background", "#f8f9fa", "font-size", "0.85em", "color", "#6c757d"], [2, "display", "flex", "gap", "16px", "flex-wrap", "wrap", "align-items", "center", "margin-bottom", "8px"], [2, "padding", "8px", "background", "#fff", "border", "1px solid #dee2e6", "border-radius", "4px", "margin-top", "8px"], ["title", "Drag to reorder priority", 1, "fa-solid", "fa-grip-vertical", 2, "cursor", "move"], [2, "font-size", "0.7em", "margin-top", "2px"], ["textField", "Name", "valueField", "ID", "placeholder", "Select a model...", 2, "width", "100%", 3, "ngModelChange", "valueChange", "ngModel", "name", "data", "valuePrimitive", "filterable"], [2, "color", "#6c757d", "font-style", "italic", "font-size", "0.9em"], ["textField", "Name", "valueField", "ID", "placeholder", "Select vendor...", 2, "width", "100%", 3, "ngModel", "name", "data", "valuePrimitive", "filterable"], ["textField", "Name", "valueField", "ID", "placeholder", "Select vendor...", 2, "width", "100%", 3, "ngModelChange", "ngModel", "name", "data", "valuePrimitive", "filterable"], ["kendoDropDownListItemTemplate", ""], [2, "font-size", "0.8em", "margin-left", "4px"], [2, "font-size", "0.9em", "font-weight", "500", 3, "color"], [2, "font-size", "0.9em", "font-weight", "500"], [2, "font-size", "0.9em", 3, "color"], [2, "color", "#6c757d", "font-size", "0.9em"], [2, "padding", "4px", "color", "#6c757d", "font-style", "italic", "font-size", "0.85em"], ["textField", "Name", "valueField", "ID", "placeholder", "Default", 2, "width", "100%", 3, "ngModel", "name", "data", "valuePrimitive", "filterable"], ["textField", "Name", "valueField", "ID", "placeholder", "Default", 2, "width", "100%", 3, "ngModelChange", "valueChange", "ngModel", "name", "data", "valuePrimitive", "filterable"], ["kendoDropDownListNoDataTemplate", ""], [2, "padding", "8px", "text-align", "center", "color", "#6c757d"], [2, "display", "flex", "gap", "2px", "margin-bottom", "4px"], ["kendoButton", "", "fillMode", "flat", "themeColor", "error", "size", "small", "title", "Remove model"], ["kendoButton", "", "fillMode", "flat", "size", "small", "title", "Move up", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-up"], ["kendoButton", "", "fillMode", "flat", "size", "small", "title", "Move down", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-down"], ["kendoButton", "", "fillMode", "flat", "themeColor", "error", "size", "small", "title", "Remove model", 3, "click"], [1, "fa-solid", "fa-times"], [2, "margin-bottom", "6px", "font-weight", "600", "color", "#495057", "font-size", "0.9em"], [1, "fa-solid", "fa-layer-group"], [2, "display", "grid", "grid-template-columns", "1fr 1fr 1fr", "gap", "12px", "align-items", "center"], [2, "display", "flex", "gap", "16px", "flex-wrap", "wrap", "align-items", "center"], [2, "display", "block", "margin-bottom", "2px", "font-size", "0.8em", "font-weight", "600", "color", "#495057"], ["textField", "text", "valueField", "value", "placeholder", "Select mode...", 2, "width", "100%", "font-size", "0.85em", 3, "ngModelChange", "ngModel", "name", "data", "valuePrimitive"], ["placeholder", "Count...", 2, "width", "100%", "font-size", "0.85em", 3, "ngModelChange", "ngModel", "name", "min", "step", "format"], ["placeholder", "Parameter name...", 2, "width", "100%", "font-size", "0.85em", 3, "ngModelChange", "ngModel", "name"], ["kendoButton", "", "fillMode", "outline", "themeColor", "success", "size", "small", 3, "click"], [1, "fa-solid", "fa-cogs", 2, "color", "#6c757d"], [2, "padding", "8px", "color", "#6c757d", "font-style", "italic"], ["name", "resultSelectorPromptID", "textField", "text", "valueField", "value", "placeholder", "Select a result selector prompt...", 2, "width", "100%", 3, "ngModel", "data", "valuePrimitive", "filterable"], ["name", "resultSelectorPromptID", "textField", "text", "valueField", "value", "placeholder", "Select a result selector prompt...", 2, "width", "100%", 3, "ngModelChange", "valueChange", "ngModel", "data", "valuePrimitive", "filterable"], [1, "fa-solid", "fa-sliders", 2, "color", "#6c757d"], [1, "badge", 2, "background", "#6f42c1", "color", "white", "padding", "2px 6px", "border-radius", "10px", "font-size", "0.7em"], ["title", "These parameters are defined in the template and will be available when executing this prompt", 1, "fa-solid", "fa-info-circle"], [2, "display", "grid", "gap", "12px"], [1, "parameter-card", 2, "border", "1px solid #e9ecef", "border-radius", "8px", "padding", "16px", "background", "#f8f9fa", "transition", "all 0.2s", 3, "border-left"], [2, "margin-top", "16px", "padding", "12px", "background", "#e3f2fd", "border-radius", "6px", "border", "1px solid #bbdefb"], [2, "display", "flex", "align-items", "flex-start", "gap", "8px"], [1, "fa-solid", "fa-lightbulb", 2, "color", "#1976d2", "margin-top", "2px"], [2, "flex", "1", "font-size", "0.85em", "color", "#1565c0", "line-height", "1.5"], [1, "parameter-card", 2, "border", "1px solid #e9ecef", "border-radius", "8px", "padding", "16px", "background", "#f8f9fa", "transition", "all 0.2s"], [2, "display", "flex", "justify-content", "space-between", "align-items", "flex-start", "margin-bottom", "8px"], [2, "display", "flex", "align-items", "center", "gap", "8px"], [2, "font-size", "1.2em"], [2, "margin", "0", "color", "#495057", "font-weight", "600"], [2, "color", "#dc3545", "font-size", "0.9em", "margin-left", "4px"], [1, "type-badge", 2, "color", "white", "padding", "4px 8px", "border-radius", "12px", "font-size", "0.75em", "font-weight", "500"], [2, "color", "#dc3545", "font-size", "0.85em", "font-weight", "500"], [2, "color", "#6c757d", "font-size", "0.85em"], [2, "margin", "0 0 8px 0", "color", "#6c757d", "font-size", "0.9em", "line-height", "1.4"], [2, "font-size", "0.85em", "color", "#495057"], [2, "display", "flex", "align-items", "center", "gap", "4px", "margin-bottom", "4px"], [1, "fa-solid", "fa-info-circle", 2, "color", "#6c757d"], [2, "display", "grid", "grid-template-columns", "repeat(auto-fit, minmax(200px, 1fr))", "gap", "12px", "margin-top", "12px"], [2, "background", "white", "padding", "8px 12px", "border-radius", "4px", "border", "1px solid #dee2e6"], [2, "display", "block", "font-size", "0.8em", "color", "#6c757d", "margin-bottom", "2px"], [2, "font-size", "0.85em", "color", "#495057", "word-break", "break-all"], [2, "font-size", "0.8em", "color", "#495057", "word-break", "break-all"], [2, "padding", "16px"], [2, "background", "#f8f9fa", "border", "1px solid #dee2e6", "border-radius", "4px", "padding", "12px", "font-family", "'Courier New', monospace", "font-size", "0.9em", "white-space", "pre-wrap", "overflow", "auto", "max-height", "250px"], [2, "background", "#fff3cd", "border", "1px solid #ffeaa7", "border-radius", "4px", "padding", "12px", "color", "#856404", "text-align", "center"], [2, "color", "#dc3545", "font-size", "0.8em", "font-weight", "normal"], ["name", "outputExample", "language", "json", "placeholder", "Enter JSON example structure...", 2, "width", "100%", "height", "200px", "border", "1px solid #dee2e6", "border-radius", "4px", 3, "ngModelChange", "ngModel"], [2, "margin-top", "8px", "color", "#6c757d", "font-size", "0.85em"], [1, "fa-solid", "fa-exclamation-triangle"], [2, "text-align", "center", "padding", "40px", "color", "#6c757d"], [1, "fa-solid", "fa-history", 2, "color", "#6c757d"], [2, "color", "#6c757d", "font-weight", "normal"], [1, "fa-solid", "fa-spinner", "fa-spin", 2, "font-size", "2em", "margin-bottom", "12px"], [1, "fa-solid", "fa-history", 2, "font-size", "3em", "margin-bottom", "12px", "opacity", "0.3"], [2, "display", "flex", "justify-content", "space-between", "align-items", "center", "margin-bottom", "16px"], [2, "display", "flex", "gap", "8px", "align-items", "center"], ["selection", "single"], ["kendoButton", "", "size", "small", 3, "click", "selected"], [2, "margin-left", "4px", "font-size", "0.8em", 3, "class"], [2, "border", "1px solid #e9ecef", "border-radius", "8px", "overflow", "hidden"], [2, "width", "100%", "border-collapse", "collapse"], [2, "background", "#f8f9fa", "border-bottom", "2px solid #e9ecef"], [2, "padding", "12px", "text-align", "left", "font-weight", "600", "color", "#495057"], [2, "padding", "12px", "text-align", "right", "font-weight", "600", "color", "#495057"], [2, "padding", "12px", "text-align", "center", "font-weight", "600", "color", "#495057"], [1, "history-row", 2, "border-bottom", "1px solid #f1f3f5", 3, "even-row"], [2, "margin-left", "4px", "font-size", "0.8em"], [1, "history-row", 2, "border-bottom", "1px solid #f1f3f5"], [2, "padding", "12px"], [2, "display", "flex", "align-items", "center", "gap", "6px"], [2, "padding", "12px", "color", "#495057"], [2, "padding", "12px", "text-align", "right", "color", "#495057"], [2, "padding", "12px", "text-align", "center"], [2, "padding", "4px 8px", "border-radius", "12px", "background", "#e9ecef", "color", "#495057", "font-size", "0.85em", "font-weight", "500"], ["kendoButton", "", "fillMode", "flat", "size", "small", "title", "View details", 3, "click"], [1, "fa-solid", "fa-external-link"], [3, "Params", "NewRecordValues", "AllowLoad", "ShowToolbar"], [1, "fa-solid", "fa-database", 2, "color", "#6c757d"], [2, "margin", "0 0 12px 0", "color", "#495057"], [1, "fa-solid", "fa-link", 2, "color", "#6c757d"], [3, "close", "width", "height", "minWidth", "minHeight", "draggable", "resizable", "state", "title"], [3, "visibilityChange", "entity", "mode", "isVisible"]], template: function AIPromptFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
3050
3049
  i0.ɵɵelementStart(0, "div", 2);
3051
3050
  i0.ɵɵelement(1, "div", 3);
3052
3051
  i0.ɵɵtemplate(2, AIPromptFormComponentExtended_form_2_Template, 66, 40, "form", 4)(3, AIPromptFormComponentExtended_Conditional_3_Template, 2, 12, "kendo-window", 5);
@@ -3056,7 +3055,7 @@ let AIPromptFormComponentExtended = class AIPromptFormComponentExtended extends
3056
3055
  i0.ɵɵproperty("ngIf", ctx.record);
3057
3056
  i0.ɵɵadvance();
3058
3057
  i0.ɵɵconditional(ctx.showTestHarness ? 3 : -1);
3059
- } }, dependencies: [i5.NgIf, i6.ɵNgNoValidate, i6.NgControlStatus, i6.NgControlStatusGroup, i6.NgModel, i6.NgForm, i7.ExpansionPanelComponent, i7.ExpansionPanelTitleDirective, i8.DialogContainerDirective, i8.WindowComponent, i9.TextAreaComponent, i9.TextBoxComponent, i9.NumericTextBoxComponent, i10.ItemTemplateDirective, i10.NoDataTemplateDirective, i10.DropDownListComponent, i10.DropDownTreeComponent, i11.ButtonGroupComponent, i11.ButtonComponent, i12.UserViewGridComponent, i13.MJFormField, i14.FormToolbarComponent, i15.CodeEditorComponent, i3.AITestHarnessComponent, i16.TemplateEditorComponent, i5.DatePipe], styles: [".record-form-container[_ngcontent-%COMP%] {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n padding: 10px;\n}\n\n.custom-toolbar-actions[_ngcontent-%COMP%] {\n margin-left: auto;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n font-weight: 500;\n letter-spacing: 0.02em;\n}\n\n.config-summary[_ngcontent-%COMP%] {\n position: sticky;\n top: 0;\n max-height: 600px;\n overflow-y: auto;\n}\n\n.config-item[_ngcontent-%COMP%] {\n padding: 8px 0;\n border-bottom: 1px solid #e9ecef;\n}\n\n.config-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.template-tab-content[_ngcontent-%COMP%] {\n background: #fff;\n}\n\n.template-header[_ngcontent-%COMP%] h5[_ngcontent-%COMP%] {\n font-size: 1.1em;\n}\n\n.loading-state[_ngcontent-%COMP%], \n.no-template-state[_ngcontent-%COMP%], \n.invalid-template-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n}\n\n.no-template-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.invalid-template-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n opacity: 0.6;\n}\n\n.template-editor-container[_ngcontent-%COMP%] {\n background: #fff;\n border-radius: 6px;\n}\n\n\n\n@media (max-width: 1200px) {\n .record-form-container[_ngcontent-%COMP%] .mj-tab-body[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] {\n grid-template-columns: 1fr !important;\n gap: 20px;\n }\n \n .config-summary[_ngcontent-%COMP%] {\n order: -1;\n position: static;\n max-height: none;\n }\n}\n\n\n\n@media (max-width: 768px) {\n .custom-toolbar-actions[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 4px !important;\n }\n \n .status-badge[_ngcontent-%COMP%] {\n align-self: flex-start;\n }\n}\n\n\n\n.record-form-container[_ngcontent-%COMP%] mj-form-section[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n\n\n.status-badge[_ngcontent-%COMP%], \n.config-item[_ngcontent-%COMP%], \n.template-header[_ngcontent-%COMP%] {\n transition: all 0.2s ease;\n}\n\n.config-item[_ngcontent-%COMP%]:hover {\n background-color: rgba(0,0,0,0.02);\n border-radius: 4px;\n margin: 0 -8px;\n padding: 8px;\n}\n\n\n\n.history-row[_ngcontent-%COMP%] {\n transition: background 0.2s;\n}\n\n.history-row[_ngcontent-%COMP%]:not(.even-row) {\n background: #f8f9fa;\n}\n\n.history-row.even-row[_ngcontent-%COMP%] {\n background: white;\n}\n\n.history-row[_ngcontent-%COMP%]:hover {\n background: #e9ecef !important;\n}\n\n\n\n.parameter-card[_ngcontent-%COMP%] {\n position: relative;\n overflow: hidden;\n}\n\n.parameter-card[_ngcontent-%COMP%]::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 4px;\n background: inherit;\n transition: width 0.2s;\n}\n\n.parameter-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n}\n\n.parameter-card[_ngcontent-%COMP%]:hover::before {\n width: 6px;\n}\n\n.type-badge[_ngcontent-%COMP%] {\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n transition: transform 0.2s;\n}\n\n.parameter-card[_ngcontent-%COMP%]:hover .type-badge[_ngcontent-%COMP%] {\n transform: scale(1.05);\n}\n\n\n\n.parameter-card[_ngcontent-%COMP%] i.fa-solid[_ngcontent-%COMP%] {\n transition: transform 0.3s;\n}\n\n.parameter-card[_ngcontent-%COMP%]:hover i.fa-solid[_ngcontent-%COMP%] {\n transform: rotate(360deg);\n}\n\n\n\n@media (max-width: 768px) {\n .parameter-card[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n }\n \n .parameter-card[_ngcontent-%COMP%] h6[_ngcontent-%COMP%] {\n font-size: 0.95em;\n }\n \n .type-badge[_ngcontent-%COMP%] {\n font-size: 0.7em !important;\n }\n}"] }); }
3058
+ } }, dependencies: [i5.NgIf, i6.ɵNgNoValidate, i6.NgControlStatus, i6.NgControlStatusGroup, i6.NgModel, i6.NgForm, i7.ExpansionPanelComponent, i7.ExpansionPanelTitleDirective, i8.DialogContainerDirective, i8.WindowComponent, i9.TextAreaComponent, i9.TextBoxComponent, i9.NumericTextBoxComponent, i10.ItemTemplateDirective, i10.NoDataTemplateDirective, i10.DropDownListComponent, i10.DropDownTreeComponent, i11.ButtonGroupComponent, i11.ButtonComponent, i12.MJFormField, i12.ExplorerEntityDataGridComponent, i13.FormToolbarComponent, i14.CodeEditorComponent, i3.AITestHarnessComponent, i15.TemplateEditorComponent, i5.DatePipe], styles: [".record-form-container[_ngcontent-%COMP%] {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n padding: 10px;\n}\n\n.custom-toolbar-actions[_ngcontent-%COMP%] {\n margin-left: auto;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n font-weight: 500;\n letter-spacing: 0.02em;\n}\n\n.config-summary[_ngcontent-%COMP%] {\n position: sticky;\n top: 0;\n max-height: 600px;\n overflow-y: auto;\n}\n\n.config-item[_ngcontent-%COMP%] {\n padding: 8px 0;\n border-bottom: 1px solid #e9ecef;\n}\n\n.config-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.template-tab-content[_ngcontent-%COMP%] {\n background: #fff;\n}\n\n.template-header[_ngcontent-%COMP%] h5[_ngcontent-%COMP%] {\n font-size: 1.1em;\n}\n\n.loading-state[_ngcontent-%COMP%], \n.no-template-state[_ngcontent-%COMP%], \n.invalid-template-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n}\n\n.no-template-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.invalid-template-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n opacity: 0.6;\n}\n\n.template-editor-container[_ngcontent-%COMP%] {\n background: #fff;\n border-radius: 6px;\n}\n\n\n\n@media (max-width: 1200px) {\n .record-form-container[_ngcontent-%COMP%] .mj-tab-body[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] {\n grid-template-columns: 1fr !important;\n gap: 20px;\n }\n \n .config-summary[_ngcontent-%COMP%] {\n order: -1;\n position: static;\n max-height: none;\n }\n}\n\n\n\n@media (max-width: 768px) {\n .custom-toolbar-actions[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 4px !important;\n }\n \n .status-badge[_ngcontent-%COMP%] {\n align-self: flex-start;\n }\n}\n\n\n\n.record-form-container[_ngcontent-%COMP%] mj-form-section[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n\n\n.status-badge[_ngcontent-%COMP%], \n.config-item[_ngcontent-%COMP%], \n.template-header[_ngcontent-%COMP%] {\n transition: all 0.2s ease;\n}\n\n.config-item[_ngcontent-%COMP%]:hover {\n background-color: rgba(0,0,0,0.02);\n border-radius: 4px;\n margin: 0 -8px;\n padding: 8px;\n}\n\n\n\n.history-row[_ngcontent-%COMP%] {\n transition: background 0.2s;\n}\n\n.history-row[_ngcontent-%COMP%]:not(.even-row) {\n background: #f8f9fa;\n}\n\n.history-row.even-row[_ngcontent-%COMP%] {\n background: white;\n}\n\n.history-row[_ngcontent-%COMP%]:hover {\n background: #e9ecef !important;\n}\n\n\n\n.parameter-card[_ngcontent-%COMP%] {\n position: relative;\n overflow: hidden;\n}\n\n.parameter-card[_ngcontent-%COMP%]::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 4px;\n background: inherit;\n transition: width 0.2s;\n}\n\n.parameter-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n}\n\n.parameter-card[_ngcontent-%COMP%]:hover::before {\n width: 6px;\n}\n\n.type-badge[_ngcontent-%COMP%] {\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n transition: transform 0.2s;\n}\n\n.parameter-card[_ngcontent-%COMP%]:hover .type-badge[_ngcontent-%COMP%] {\n transform: scale(1.05);\n}\n\n\n\n.parameter-card[_ngcontent-%COMP%] i.fa-solid[_ngcontent-%COMP%] {\n transition: transform 0.3s;\n}\n\n.parameter-card[_ngcontent-%COMP%]:hover i.fa-solid[_ngcontent-%COMP%] {\n transform: rotate(360deg);\n}\n\n\n\n@media (max-width: 768px) {\n .parameter-card[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n }\n \n .parameter-card[_ngcontent-%COMP%] h6[_ngcontent-%COMP%] {\n font-size: 0.95em;\n }\n \n .type-badge[_ngcontent-%COMP%] {\n font-size: 0.7em !important;\n }\n}"] }); }
3060
3059
  };
3061
3060
  AIPromptFormComponentExtended = __decorate([
3062
3061
  RegisterClass(BaseFormComponent, 'AI Prompts')
@@ -3064,7 +3063,7 @@ AIPromptFormComponentExtended = __decorate([
3064
3063
  export { AIPromptFormComponentExtended };
3065
3064
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AIPromptFormComponentExtended, [{
3066
3065
  type: Component,
3067
- args: [{ selector: 'mj-ai-prompt-form', template: "<div class=\"record-form-container\">\n <!-- Dialog container for Kendo dialogs -->\n <div kendoDialogContainer></div>\n <form *ngIf=\"record\" class=\"record-form\" #form=\"ngForm\" >\n <mj-form-toolbar [form]=\"this\"></mj-form-toolbar>\n\n <!-- Main Content Area - Template Editor and Configuration -->\n <div class=\"prompt-main-area\" style=\"display: flex; flex-direction: column; height: 100%; overflow-y: auto;\">\n \n <!-- Header Section -->\n <div class=\"prompt-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: Prompt 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=\"fa-solid fa-robot\" style=\"color: #6f42c1; font-size: 1.4em;\"></i>\n @if (EditMode) {\n <kendo-textbox [(ngModel)]=\"record.Name\" \n name=\"promptName\"\n placeholder=\"Enter prompt 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 AI Prompt' }}</h4>\n <span class=\"status-badge\" [style.background-color]=\"getStatusBadgeColor()\" \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=\"promptStatus\"\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 @if (isLoadingPromptTypes) {\n <div style=\"padding: 8px; color: #6c757d; font-style: italic; width: 200px;\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading types...\n </div>\n } @else {\n <kendo-dropdownlist [(ngModel)]=\"record.TypeID\"\n name=\"promptTypeID\"\n [data]=\"availablePromptTypes\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n [filterable]=\"true\"\n placeholder=\"Select prompt type...\"\n style=\"width: 200px;\">\n </kendo-dropdownlist>\n }\n </div>\n </div>\n }\n \n @if (EditMode) {\n <kendo-textarea [(ngModel)]=\"record.Description\" \n name=\"promptDescription\"\n [rows]=\"2\"\n placeholder=\"Enter prompt 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 (record.TypeID) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-tag\" style=\"color: #6c757d;\"></i>\n <span style=\"color: #6c757d;\">Type:</span>\n <span style=\"color: #495057; font-weight: 500;\">{{ getPromptTypeDisplayName(record.TypeID) }}</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-layer-group\" style=\"color: #6c757d;\"></i>\n <span style=\"color: #6c757d;\">Parallelization:</span>\n <span style=\"color: #495057; font-weight: 500;\">{{ getParallelizationModeDisplay() }}</span>\n </div>\n \n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-code\" style=\"color: #6c757d;\"></i>\n <span style=\"color: #6c757d;\">Output:</span>\n <span [style.color]=\"getValidationColor()\" style=\"font-weight: 500;\">{{ getOutputTypeDisplay() }}</span>\n </div>\n \n @if (record.EnableCaching) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-database\" style=\"color: #28a745;\"></i>\n <span style=\"color: #28a745; font-weight: 500;\">Caching Enabled</span>\n </div>\n }\n \n @if (record.EffortLevel) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-tachometer-alt\" style=\"color: #6c757d;\"></i>\n <span style=\"color: #6c757d;\">Effort Level:</span>\n <span style=\"color: #495057; font-weight: 500;\">{{ record.EffortLevel }}</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=\"Run AI Prompt Test Harness\">\n <i class=\"fa-solid fa-play\"></i> Run\n </button>\n }\n </div>\n \n @if (!canExecute && record.ID) {\n <div style=\"font-size: 0.75em; color: #dc3545; text-align: right; max-width: 200px;\">\n @if (record.Status !== 'Active') {\n \u2022 Prompt must be Active<br>\n }\n @if (!record.TemplateID) {\n \u2022 Template is required<br>\n }\n @if (!template && record.TemplateID) {\n \u2022 Template not found<br>\n }\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 <!-- Template Editor Section -->\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-code\" style=\"color: #6c757d;\"></i>\n Template Editor\n @if (template) {\n <span style=\"color: #6c757d; font-size: 0.9em; font-weight: normal;\">\u2022 {{ template.Name }}</span>\n }\n </span>\n </ng-template>\n \n <!-- Direct Content Projection -->\n <div class=\"template-section\" style=\"display: flex; flex-direction: column; min-height: 400px; padding: 8px;\">\n @if (isLoadingTemplate) {\n <div class=\"loading-state\" style=\"flex: 1; display: flex; align-items: center; justify-content: center; color: #6c757d;\">\n <i class=\"fa-solid fa-spinner fa-spin\" style=\"font-size: 24px; margin-right: 12px;\"></i>\n Loading template...\n </div>\n } @else if (!record.TemplateID) {\n <div class=\"no-template-state\" style=\"flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 40px; color: #6c757d;\">\n <i class=\"fa-solid fa-code\" style=\"font-size: 64px; margin-bottom: 20px; opacity: 0.3;\"></i>\n <h5 style=\"margin-bottom: 12px; color: #495057;\">No Template Associated</h5>\n <p style=\"margin-bottom: 24px; text-align: center; max-width: 400px;\">\n This AI prompt needs a template to define its structure and parameters. \n Create a new template or link to an existing one.\n </p>\n <div style=\"display: flex; gap: 12px;\">\n @if (UserCanCreateTemplates) {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"createNewTemplate()\">\n <i class=\"fa-solid fa-plus\"></i> Create New Template\n </button>\n }\n @if (UserCanReadTemplates) {\n <button kendoButton [fillMode]=\"'outline'\" (click)=\"linkExistingTemplate()\">\n <i class=\"fa-solid fa-link\"></i> Link Existing Template\n </button>\n }\n </div>\n </div>\n } @else if (templateNotFoundInDatabase) {\n <div class=\"invalid-template-state\" style=\"flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 40px; color: #dc3545;\">\n <i class=\"fa-solid fa-exclamation-triangle\" style=\"font-size: 64px; margin-bottom: 20px; opacity: 0.7;\"></i>\n <h5 style=\"margin-bottom: 12px;\">Template Not Found</h5>\n <p style=\"margin-bottom: 24px; text-align: center; max-width: 400px;\">\n The referenced template could not be loaded. It may have been deleted or moved.\n </p>\n <div style=\"display: flex; gap: 12px;\">\n <button kendoButton [fillMode]=\"'outline'\" (click)=\"loadTemplate()\">\n <i class=\"fa-solid fa-refresh\"></i> Retry Loading\n </button>\n @if (UserCanCreateTemplates) {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"createNewTemplate()\">\n <i class=\"fa-solid fa-plus\"></i> Create New Template\n </button>\n }\n </div>\n </div>\n } @else {\n <!-- Active Template Editor -->\n <div class=\"template-editor-container\" style=\"flex: 1; display: flex; flex-direction: column; min-height: 350px;\">\n <!-- Template Actions Bar -->\n @if (template && EditMode) {\n <div class=\"template-actions\" style=\"display: flex; gap: 8px; padding: 8px; border-bottom: 1px solid #e9ecef; background: #f8f9fa;\">\n @if (UserCanUpdateTemplates) {\n <button kendoButton \n [fillMode]=\"'outline'\" \n [size]=\"'small'\"\n (click)=\"linkExistingTemplate()\"\n title=\"Change to a different template\">\n <i class=\"fa-solid fa-exchange-alt\"></i> Change Template\n </button>\n }\n @if (UserCanReadTemplates) {\n <button kendoButton \n [fillMode]=\"'outline'\" \n [size]=\"'small'\"\n (click)=\"openTemplateInNewWindow()\"\n title=\"Open template in new window\">\n <i class=\"fa-solid fa-external-link-alt\"></i> Open in New Window\n </button>\n }\n </div>\n }\n \n <!-- Template Editor -->\n <div style=\"flex: 1; background: white; border-radius: 6px; border: 1px solid #e9ecef;\">\n <mj-template-editor \n #templateEditor\n [template]=\"template\"\n [config]=\"templateEditorConfig\"\n (contentChange)=\"onTemplateContentChange($event)\"\n (runTemplate)=\"onTemplateRun($event)\"\n style=\"display: block; min-height: 300px;\">\n </mj-template-editor>\n </div>\n </div>\n }\n </div>\n </kendo-expansionpanel> \n\n <!-- Model Configuration Expansion Panel -->\n @if (record.IsSaved) {\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-microchip\" style=\"color: #6c757d;\"></i>\n Models\n @if (promptModels.length > 0) {\n <span class=\"badge\" style=\"background: #17a2b8; color: white; padding: 2px 6px; border-radius: 10px; font-size: 0.7em;\">\n {{ promptModels.length }}\n </span>\n }\n <span style=\"color: #6c757d; font-size: 0.8em; font-weight: normal; margin-left: 8px;\">\n <i class=\"fa-solid fa-info-circle\" title=\"Models are tried in order from top to bottom. The first available model will be used.\"></i>\n Priority order (first available model will be used)\n </span>\n </span>\n </ng-template>\n \n <!-- Direct Content Projection -->\n <div style=\"padding: 16px 0;\">\n <!-- Model Management Interface -->\n <div class=\"model-management\" style=\"border: 1px solid #dee2e6; border-radius: 6px; background: #f8f9fa;\">\n @if (isLoadingModels) {\n <div class=\"loading-state\" style=\"padding: 20px; text-align: center; color: #6c757d;\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading models...\n </div>\n } @else {\n @if (promptModels.length === 0) {\n <div class=\"empty-state\" style=\"padding: 20px; text-align: center; color: #6c757d;\">\n <i class=\"fa-solid fa-info-circle\"></i> No models configured\n @if (EditMode && UserCanCreatePromptModels) {\n <div style=\"margin-top: 10px;\">\n <button kendoButton fillMode=\"outline\" themeColor=\"primary\" size=\"small\"\n (click)=\"addNewModel()\">\n <i class=\"fa-solid fa-plus\"></i> Add Model\n </button>\n </div>\n }\n </div>\n } @else {\n <!-- Priority explanation for multiple models -->\n @if (promptModels.length > 1) {\n <div style=\"padding: 12px 16px; background: #e3f2fd; border-bottom: 1px solid #bbdefb; color: #1565c0; font-size: 0.85em;\">\n <i class=\"fa-solid fa-info-circle\" style=\"margin-right: 6px;\"></i>\n Models are tried in priority order (highest priority first). The first available model that meets requirements will be used for execution.\n </div>\n }\n <!-- Column Headers -->\n <div class=\"model-header\" style=\"display: grid; grid-template-columns: 40px 2fr 1fr 1fr 1fr 60px; gap: 12px; padding: 12px 16px; background: #e9ecef; font-weight: 600; font-size: 0.85em; color: #495057; border-bottom: 1px solid #dee2e6;\">\n <div title=\"Priority order - models are tried from top to bottom\">\n <i class=\"fa-solid fa-sort\" style=\"color: #6c757d;\"></i>\n </div>\n <div>AI Model <span style=\"color: #dc3545;\">*</span></div>\n <div>Vendor</div>\n <div>Configuration</div>\n <div>Created</div>\n <div>Actions</div>\n </div>\n \n @for (model of promptModels; track getModelTrackId(model) || $index; let i = $index) {\n <div class=\"model-row\" \n [draggable]=\"EditMode\"\n (dragstart)=\"onDragStart($event, i)\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop($event, i)\"\n (dragend)=\"onDragEnd($event)\"\n [style.background]=\"!model.ModelID ? '#fff3cd' : (draggedIndex === i ? '#e3f2fd' : 'white')\"\n [style.border-left]=\"!model.ModelID ? '3px solid #ffc107' : 'none'\"\n [style.opacity]=\"draggedIndex === i ? '0.5' : '1'\"\n style=\"display: grid; grid-template-columns: 40px 2fr 1fr 1fr 1fr 60px; gap: 12px; padding: 12px 16px; border-bottom: 1px solid #e9ecef; align-items: start; transition: background 0.2s, opacity 0.2s;\">\n \n <!-- Drag Handle / Priority -->\n <div class=\"drag-handle\" style=\"display: flex; flex-direction: column; align-items: center; justify-content: center; color: #6c757d;\">\n @if (EditMode) {\n <i class=\"fa-solid fa-grip-vertical\" title=\"Drag to reorder priority\" style=\"cursor: move;\"></i>\n <span style=\"font-size: 0.7em; margin-top: 2px;\">#{{ i + 1 }}</span>\n } @else {\n <span style=\"font-size: 0.9em; font-weight: 600;\" title=\"Priority {{ model.Priority }} - Higher priority numbers are tried first\">#{{ i + 1 }}</span>\n }\n </div>\n \n <!-- Model Selection -->\n <div class=\"model-select\">\n @if (EditMode) {\n <kendo-dropdownlist [(ngModel)]=\"model.ModelID\"\n [name]=\"'modelId_' + getModelTrackId(model)\"\n [data]=\"availableModels\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n [filterable]=\"true\"\n placeholder=\"Select a model...\"\n (valueChange)=\"onModelChange($event, i)\"\n style=\"width: 100%;\">\n </kendo-dropdownlist>\n } @else {\n <span style=\"font-weight: 500;\">{{ getModelDisplayName(model.ModelID) }}</span>\n }\n </div>\n \n <!-- Vendor -->\n <div class=\"model-vendor\">\n @if (EditMode) {\n @if (model.ModelID) {\n @if (shouldShowVendorDropdown(model.ModelID)) {\n <kendo-dropdownlist [(ngModel)]=\"model.VendorID\"\n [name]=\"'vendorId_' + getModelTrackId(model)\"\n [data]=\"getVendorsForModelSync(model.ModelID)\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n [filterable]=\"true\"\n placeholder=\"Select vendor...\"\n style=\"width: 100%;\">\n <ng-template kendoDropDownListItemTemplate let-dataItem>\n <span [style.color]=\"getVendorStatusColor(model.ModelID, dataItem.ID)\">\n {{ dataItem.Name }}\n @if (getModelVendorStatus(model.ModelID, dataItem.ID) !== 'Active') {\n <span style=\"font-size: 0.8em; margin-left: 4px;\">({{ getModelVendorStatus(model.ModelID, dataItem.ID) }})</span>\n }\n </span>\n </ng-template>\n </kendo-dropdownlist>\n } @else {\n <!-- Single vendor - just show the name -->\n @if (getVendorsForModelSync(model.ModelID).length === 1) {\n <span [style.color]=\"getVendorStatusColor(model.ModelID, getVendorsForModelSync(model.ModelID)[0].ID)\" style=\"font-size: 0.9em; font-weight: 500;\">\n {{ getVendorsForModelSync(model.ModelID)[0].Name }}\n @if (getModelVendorStatus(model.ModelID, getVendorsForModelSync(model.ModelID)[0].ID) !== 'Active') {\n <span style=\"font-size: 0.8em; margin-left: 4px;\">({{ getModelVendorStatus(model.ModelID, getVendorsForModelSync(model.ModelID)[0].ID) }})</span>\n }\n </span>\n } @else {\n <span style=\"color: #6c757d; font-style: italic; font-size: 0.9em;\">No vendors available</span>\n }\n }\n } @else {\n <span style=\"color: #6c757d; font-style: italic; font-size: 0.9em;\">Select model first</span>\n }\n } @else {\n @if (model.VendorID && model.ModelID) {\n <span [style.color]=\"getVendorStatusColor(model.ModelID, model.VendorID)\" style=\"font-size: 0.9em;\">\n {{ getVendorDisplayName(model.VendorID) }}\n @if (getModelVendorStatus(model.ModelID, model.VendorID) !== 'Active') {\n <span style=\"font-size: 0.8em; margin-left: 4px;\">({{ getModelVendorStatus(model.ModelID, model.VendorID) }})</span>\n }\n </span>\n } @else {\n <span style=\"color: #6c757d; font-size: 0.9em;\">-</span>\n }\n }\n </div>\n \n <!-- Configuration -->\n <div class=\"model-configuration\">\n @if (EditMode) {\n @if (isLoadingConfigurations) {\n <div style=\"padding: 4px; color: #6c757d; font-style: italic; font-size: 0.85em;\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading...\n </div>\n } @else {\n <kendo-dropdownlist [(ngModel)]=\"model.ConfigurationID\"\n [name]=\"'configurationId_' + getModelTrackId(model)\"\n [data]=\"availableConfigurations\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n [filterable]=\"true\"\n placeholder=\"Default\"\n (valueChange)=\"onConfigurationChange($event, i)\"\n style=\"width: 100%;\">\n <ng-template kendoDropDownListNoDataTemplate>\n <div style=\"padding: 8px; text-align: center; color: #6c757d;\">\n No configurations available\n </div>\n </ng-template>\n </kendo-dropdownlist>\n }\n } @else {\n <span style=\"font-size: 0.9em;\">{{ getConfigurationDisplayName(model.ConfigurationID) }}</span>\n }\n </div>\n \n <!-- Created Date -->\n <div class=\"model-created\">\n @if (model.ID) {\n <span style=\"color: #6c757d; font-size: 0.8em;\">{{ model.__mj_CreatedAt | date:'short' }}</span>\n } @else {\n <span style=\"color: #28a745; font-size: 0.8em; font-style: italic;\">New</span>\n }\n </div>\n \n <!-- Actions -->\n <div class=\"model-actions\" style=\"display: flex; gap: 2px; flex-direction: column;\">\n @if (EditMode) {\n <div style=\"display: flex; gap: 2px; margin-bottom: 4px;\">\n @if (UserCanUpdatePromptModels) {\n <button kendoButton fillMode=\"flat\" size=\"small\"\n (click)=\"moveModelUp(i)\"\n [disabled]=\"i === 0\"\n title=\"Move up\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <button kendoButton fillMode=\"flat\" size=\"small\"\n (click)=\"moveModelDown(i)\"\n [disabled]=\"i === promptModels.length - 1\"\n title=\"Move down\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n }\n </div>\n @if (UserCanDeletePromptModels) {\n <button kendoButton fillMode=\"flat\" themeColor=\"error\" size=\"small\"\n (click)=\"removePromptModel(i)\"\n title=\"Remove model\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n }\n </div>\n </div>\n \n <!-- Second row with additional details -->\n <div style=\"display: grid; grid-template-columns: 40px 1fr; gap: 12px; padding: 8px 16px; border-bottom: 1px solid #e9ecef; background: #f8f9fa; font-size: 0.85em; color: #6c757d;\">\n <div></div>\n <div>\n <!-- Basic model details -->\n <div style=\"display: flex; gap: 16px; flex-wrap: wrap; align-items: center; margin-bottom: 8px;\">\n @if (model.Status) {\n <span><strong>Status:</strong> {{ model.Status }}</span>\n }\n </div>\n \n <!-- Parallel execution fields when prompt is ModelSpecific -->\n @if (record.ParallelizationMode === 'ModelSpecific') {\n <div style=\"padding: 8px; background: #fff; border: 1px solid #dee2e6; border-radius: 4px; margin-top: 8px;\">\n <div style=\"margin-bottom: 6px; font-weight: 600; color: #495057; font-size: 0.9em;\">\n <i class=\"fa-solid fa-layer-group\"></i> Model-Specific Parallel Execution\n </div>\n \n @if (EditMode) {\n <div style=\"display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; align-items: center;\">\n <!-- Parallel Mode -->\n <div>\n <label style=\"display: block; margin-bottom: 2px; font-size: 0.8em; font-weight: 600; color: #495057;\">Parallel Mode</label>\n <kendo-dropdownlist [(ngModel)]=\"model.ParallelizationMode\"\n [name]=\"'parallelMode_' + i\"\n [data]=\"[{text: 'None', value: 'None'}, {text: 'Static Count', value: 'StaticCount'}, {text: 'Config Param', value: 'ConfigParam'}]\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n placeholder=\"Select mode...\"\n style=\"width: 100%; font-size: 0.85em;\">\n </kendo-dropdownlist>\n </div>\n \n <!-- Parallel Count (when StaticCount) -->\n @if (model.ParallelizationMode === 'StaticCount') {\n <div>\n <label style=\"display: block; margin-bottom: 2px; font-size: 0.8em; font-weight: 600; color: #495057;\">Parallel Count</label>\n <kendo-numerictextbox [(ngModel)]=\"model.ParallelCount\"\n [name]=\"'parallelCount_' + i\"\n [min]=\"1\"\n [step]=\"1\"\n [format]=\"'n0'\"\n placeholder=\"Count...\"\n style=\"width: 100%; font-size: 0.85em;\">\n </kendo-numerictextbox>\n </div>\n }\n \n <!-- Config Param (when ConfigParam) -->\n @if (model.ParallelizationMode === 'ConfigParam') {\n <div>\n <label style=\"display: block; margin-bottom: 2px; font-size: 0.8em; font-weight: 600; color: #495057;\">Config Parameter</label>\n <kendo-textbox [(ngModel)]=\"model.ParallelConfigParam\"\n [name]=\"'parallelConfigParam_' + i\"\n placeholder=\"Parameter name...\"\n style=\"width: 100%; font-size: 0.85em;\">\n </kendo-textbox>\n </div>\n }\n </div>\n } @else {\n <!-- Read-only display -->\n <div style=\"display: flex; gap: 16px; flex-wrap: wrap; align-items: center;\">\n @if (model.ParallelizationMode) {\n <span><strong>Parallel Mode:</strong> {{ model.ParallelizationMode }}</span>\n }\n @if (model.ParallelCount) {\n <span><strong>Parallel Count:</strong> {{ model.ParallelCount }}</span>\n }\n @if (model.ParallelConfigParam) {\n <span><strong>Config Param:</strong> {{ model.ParallelConfigParam }}</span>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n \n @if (EditMode && UserCanCreatePromptModels) {\n <div class=\"add-model-row\" style=\"padding: 12px 16px; text-align: center; background: #f8f9fa; border-top: 1px solid #dee2e6;\">\n <button kendoButton fillMode=\"outline\" themeColor=\"success\" size=\"small\"\n (click)=\"addNewModel()\">\n <i class=\"fa-solid fa-plus\"></i> Add Model\n </button>\n </div>\n }\n }\n }\n </div>\n </div>\n </kendo-expansionpanel>\n }\n\n <!-- Advanced Configuration Expansion Panel -->\n <kendo-expansionpanel \n [expanded]=\"false\"\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 Advanced Configuration\n </span>\n </ng-template>\n \n <!-- Direct Content Projection -->\n <div style=\"padding: 16px 0;\">\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 20px;\">\n \n <!-- Left Column -->\n <div>\n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ParallelizationMode\"\n Type=\"dropdownlist\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n \n @if (showParallelCount) {\n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ParallelCount\"\n Type=\"numerictextbox\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n }\n \n @if (showParallelConfigParam) {\n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ParallelConfigParam\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n }\n \n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"OutputType\"\n Type=\"dropdownlist\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n \n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"EffortLevel\"\n Type=\"numerictextbox\"\n Caption=\"Effort Level (1-100)\"\n Description=\"Higher values request more thorough reasoning\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n \n </div>\n \n <!-- Right Column -->\n <div>\n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ValidationBehavior\"\n Type=\"dropdownlist\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n \n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"EnableCaching\"\n Type=\"checkbox\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n \n <!-- Result Selector Prompt with Tree Selector -->\n <div style=\"margin-bottom: 16px;\">\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: #495057; font-size: 0.9em;\">\n Result Selector Prompt\n </label>\n @if (EditMode) {\n @if (isLoadingResultSelectorData) {\n <div style=\"padding: 8px; color: #6c757d; font-style: italic;\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading prompts...\n </div>\n } @else {\n <kendo-dropdowntree \n [(ngModel)]=\"record.ResultSelectorPromptID\"\n name=\"resultSelectorPromptID\"\n [data]=\"resultSelectorTreeData\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n [filterable]=\"true\"\n placeholder=\"Select a result selector prompt...\"\n style=\"width: 100%;\"\n (valueChange)=\"onResultSelectorChange($event)\">\n </kendo-dropdowntree>\n }\n } @else {\n <span style=\"color: #495057;\">{{ getPromptDisplayName(record.ResultSelectorPromptID || '') || 'None selected' }}</span>\n }\n </div>\n </div>\n </div>\n </div>\n </kendo-expansionpanel>\n\n <!-- Template Parameters Expansion Panel -->\n @if (template && templateParams.length > 0) {\n <kendo-expansionpanel \n [expanded]=\"false\"\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 Template Parameters\n <span class=\"badge\" style=\"background: #6f42c1; color: white; padding: 2px 6px; border-radius: 10px; font-size: 0.7em;\">\n {{ templateParams.length }}\n </span>\n <span style=\"color: #6c757d; font-size: 0.8em; font-weight: normal; margin-left: 8px;\">\n <i class=\"fa-solid fa-info-circle\" title=\"These parameters are defined in the template and will be available when executing this prompt\"></i>\n Parameters defined in the template\n </span>\n </span>\n </ng-template>\n \n <!-- Template Parameters Display -->\n <div style=\"padding: 16px 0;\">\n @if (isLoadingTemplateParams) {\n <div class=\"loading-state\" style=\"padding: 20px; text-align: center; color: #6c757d;\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading template parameters...\n </div>\n } @else if (templateParams.length === 0) {\n <div class=\"empty-state\" style=\"padding: 20px; text-align: center; color: #6c757d;\">\n <i class=\"fa-solid fa-info-circle\"></i> This template has no parameters defined\n </div>\n } @else {\n <!-- Parameters Grid -->\n <div style=\"display: grid; gap: 12px;\">\n @for (param of templateParams; track param.ID) {\n <div class=\"parameter-card\" \n style=\"border: 1px solid #e9ecef; border-radius: 8px; padding: 16px; background: #f8f9fa; transition: all 0.2s;\"\n [style.border-left]=\"'4px solid ' + getParamTypeColor(param.Type)\">\n \n <!-- Parameter Header -->\n <div style=\"display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 8px;\">\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <i [class]=\"'fa-solid ' + getParamTypeIcon(param.Type)\" \n [style.color]=\"getParamTypeColor(param.Type)\"\n style=\"font-size: 1.2em;\"></i>\n <h6 style=\"margin: 0; color: #495057; font-weight: 600;\">\n {{ param.Name }}\n @if (param.IsRequired) {\n <span style=\"color: #dc3545; font-size: 0.9em; margin-left: 4px;\">*</span>\n }\n </h6>\n </div>\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <span class=\"type-badge\" \n [style.background-color]=\"getParamTypeColor(param.Type)\"\n style=\"color: white; padding: 4px 8px; border-radius: 12px; font-size: 0.75em; font-weight: 500;\">\n {{ param.Type }}\n </span>\n @if (param.IsRequired) {\n <span style=\"color: #dc3545; font-size: 0.85em; font-weight: 500;\">Required</span>\n } @else {\n <span style=\"color: #6c757d; font-size: 0.85em;\">Optional</span>\n }\n </div>\n </div>\n \n <!-- Parameter Description -->\n @if (param.Description) {\n <p style=\"margin: 0 0 8px 0; color: #6c757d; font-size: 0.9em; line-height: 1.4;\">\n {{ param.Description }}\n </p>\n }\n \n <!-- Type-specific Information -->\n <div style=\"font-size: 0.85em; color: #495057;\">\n <span style=\"display: flex; align-items: center; gap: 4px; margin-bottom: 4px;\">\n <i class=\"fa-solid fa-info-circle\" style=\"color: #6c757d;\"></i>\n {{ getParamTypeDescription(param) }}\n </span>\n </div>\n \n <!-- Additional Parameter Details -->\n <div style=\"display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-top: 12px;\">\n @if (param.DefaultValue) {\n <div style=\"background: white; padding: 8px 12px; border-radius: 4px; border: 1px solid #dee2e6;\">\n <label style=\"display: block; font-size: 0.8em; color: #6c757d; margin-bottom: 2px;\">Default Value</label>\n <code style=\"font-size: 0.85em; color: #495057; word-break: break-all;\">{{ param.DefaultValue }}</code>\n </div>\n }\n \n @if (param.EntityID) {\n <div style=\"background: white; padding: 8px 12px; border-radius: 4px; border: 1px solid #dee2e6;\">\n <label style=\"display: block; font-size: 0.8em; color: #6c757d; margin-bottom: 2px;\">Entity</label>\n <span style=\"font-size: 0.85em; color: #495057;\">{{ param.Entity || 'Entity ID: ' + param.EntityID }}</span>\n </div>\n }\n \n @if (param.LinkedParameterName) {\n <div style=\"background: white; padding: 8px 12px; border-radius: 4px; border: 1px solid #dee2e6;\">\n <label style=\"display: block; font-size: 0.8em; color: #6c757d; margin-bottom: 2px;\">Linked To</label>\n <span style=\"font-size: 0.85em; color: #495057;\">\n {{ param.LinkedParameterName }}\n @if (param.LinkedParameterField) {\n ({{ param.LinkedParameterField }})\n }\n </span>\n </div>\n }\n \n @if (param.ExtraFilter) {\n <div style=\"background: white; padding: 8px 12px; border-radius: 4px; border: 1px solid #dee2e6;\">\n <label style=\"display: block; font-size: 0.8em; color: #6c757d; margin-bottom: 2px;\">Filter</label>\n <code style=\"font-size: 0.8em; color: #495057; word-break: break-all;\">{{ param.ExtraFilter }}</code>\n </div>\n }\n \n @if (param.RecordID) {\n <div style=\"background: white; padding: 8px 12px; border-radius: 4px; border: 1px solid #dee2e6;\">\n <label style=\"display: block; font-size: 0.8em; color: #6c757d; margin-bottom: 2px;\">Record ID</label>\n <code style=\"font-size: 0.85em; color: #495057;\">{{ param.RecordID }}</code>\n </div>\n }\n </div>\n </div>\n }\n </div>\n \n <!-- Help Text -->\n <div style=\"margin-top: 16px; padding: 12px; background: #e3f2fd; border-radius: 6px; border: 1px solid #bbdefb;\">\n <div style=\"display: flex; align-items: flex-start; gap: 8px;\">\n <i class=\"fa-solid fa-lightbulb\" style=\"color: #1976d2; margin-top: 2px;\"></i>\n <div style=\"flex: 1; font-size: 0.85em; color: #1565c0; line-height: 1.5;\">\n <strong>Using Template Parameters:</strong> When executing this prompt, you'll be prompted to provide values for all required parameters. \n Parameters can be simple values (text, numbers) or complex data structures (JSON objects, database records, or entire entity collections).\n The template will use these parameters to generate dynamic content based on the values provided at execution time.\n </div>\n </div>\n </div>\n }\n </div>\n </kendo-expansionpanel>\n }\n\n <!-- Output Example Expansion Panel (when OutputType = object) -->\n @if (showOutputExample) {\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-code\" style=\"color: #6c757d;\"></i>\n Output Example (JSON)\n <span style=\"color: #dc3545; font-size: 0.8em; font-weight: normal;\">\u2022 Required for object output type</span>\n </span>\n </ng-template>\n \n <!-- Direct Content Projection -->\n <div style=\"padding: 16px;\">\n @if (EditMode) {\n <mj-code-editor \n [(ngModel)]=\"record.OutputExample\"\n name=\"outputExample\"\n language=\"json\"\n placeholder=\"Enter JSON example structure...\"\n style=\"width: 100%; height: 200px; border: 1px solid #dee2e6; border-radius: 4px;\">\n </mj-code-editor>\n <div style=\"margin-top: 8px; color: #6c757d; font-size: 0.85em;\">\n <i class=\"fa-solid fa-info-circle\"></i> Provide a JSON example that defines the expected structure for object output validation.\n </div>\n } @else if (record.OutputExample) {\n <div style=\"background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 4px; padding: 12px; font-family: 'Courier New', monospace; font-size: 0.9em; white-space: pre-wrap; overflow: auto; max-height: 250px;\">{{ record.OutputExample }}</div>\n } @else {\n <div style=\"background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 4px; padding: 12px; color: #856404; text-align: center;\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i> Output example is required when output type is 'object'\n </div>\n }\n </div>\n </kendo-expansionpanel>\n }\n\n <!-- Execution History Expansion Panel -->\n @if (record.IsSaved) {\n <kendo-expansionpanel \n [expanded]=\"false\"\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-history\" style=\"color: #6c757d;\"></i>\n Execution History\n @if (executionHistory.length > 0) {\n <span style=\"color: #6c757d; font-weight: normal;\">({{ executionHistory.length }})</span>\n }\n </span>\n </ng-template>\n \n <!-- Custom Execution History Viewer -->\n <div style=\"padding: 16px;\">\n @if (isLoadingHistory) {\n <div style=\"text-align: center; padding: 40px; color: #6c757d;\">\n <i class=\"fa-solid fa-spinner fa-spin\" style=\"font-size: 2em; margin-bottom: 12px;\"></i>\n <p>Loading execution history...</p>\n </div>\n } @else if (executionHistory.length === 0) {\n <div style=\"text-align: center; padding: 40px; color: #6c757d;\">\n <i class=\"fa-solid fa-history\" style=\"font-size: 3em; margin-bottom: 12px; opacity: 0.3;\"></i>\n <p>No execution history yet</p>\n <p style=\"font-size: 0.9em;\">Run this prompt to see execution history here</p>\n </div>\n } @else {\n <!-- Sort Controls -->\n <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;\">\n <div style=\"color: #6c757d; font-size: 0.9em;\">\n Showing {{ executionHistory.length }} executions\n </div>\n <div style=\"display: flex; gap: 8px; align-items: center;\">\n <span style=\"color: #6c757d; font-size: 0.85em;\">Sort by:</span>\n <kendo-buttongroup selection=\"single\">\n <button kendoButton \n [selected]=\"historySortField === 'runAt'\"\n (click)=\"changeHistorySort('runAt')\"\n size=\"small\">\n Date\n @if (historySortField === 'runAt') {\n <i [class]=\"'fa-solid fa-sort-' + (historySortDirection === 'asc' ? 'up' : 'down')\" \n style=\"margin-left: 4px; font-size: 0.8em;\"></i>\n }\n </button>\n <button kendoButton \n [selected]=\"historySortField === 'executionTime'\"\n (click)=\"changeHistorySort('executionTime')\"\n size=\"small\">\n Duration\n @if (historySortField === 'executionTime') {\n <i [class]=\"'fa-solid fa-sort-' + (historySortDirection === 'asc' ? 'up' : 'down')\" \n style=\"margin-left: 4px; font-size: 0.8em;\"></i>\n }\n </button>\n <button kendoButton \n [selected]=\"historySortField === 'tokens'\"\n (click)=\"changeHistorySort('tokens')\"\n size=\"small\">\n Tokens\n @if (historySortField === 'tokens') {\n <i [class]=\"'fa-solid fa-sort-' + (historySortDirection === 'asc' ? 'up' : 'down')\" \n style=\"margin-left: 4px; font-size: 0.8em;\"></i>\n }\n </button>\n <button kendoButton \n [selected]=\"historySortField === 'cost'\"\n (click)=\"changeHistorySort('cost')\"\n size=\"small\">\n Cost\n @if (historySortField === 'cost') {\n <i [class]=\"'fa-solid fa-sort-' + (historySortDirection === 'asc' ? 'up' : 'down')\" \n style=\"margin-left: 4px; font-size: 0.8em;\"></i>\n }\n </button>\n </kendo-buttongroup>\n </div>\n </div>\n \n <!-- Execution History Table -->\n <div style=\"border: 1px solid #e9ecef; border-radius: 8px; overflow: hidden;\">\n <table style=\"width: 100%; border-collapse: collapse;\">\n <thead>\n <tr style=\"background: #f8f9fa; border-bottom: 2px solid #e9ecef;\">\n <th style=\"padding: 12px; text-align: left; font-weight: 600; color: #495057;\">Status</th>\n <th style=\"padding: 12px; text-align: left; font-weight: 600; color: #495057;\">Date & Time</th>\n <th style=\"padding: 12px; text-align: left; font-weight: 600; color: #495057;\">Model</th>\n <th style=\"padding: 12px; text-align: left; font-weight: 600; color: #495057;\">Duration</th>\n <th style=\"padding: 12px; text-align: right; font-weight: 600; color: #495057;\">Tokens</th>\n <th style=\"padding: 12px; text-align: right; font-weight: 600; color: #495057;\">Cost</th>\n <th style=\"padding: 12px; text-align: center; font-weight: 600; color: #495057;\">Type</th>\n <th style=\"padding: 12px; text-align: center; font-weight: 600; color: #495057;\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (run of executionHistory; track run.ID; let i = $index) {\n <tr class=\"history-row\"\n [class.even-row]=\"i % 2 === 0\"\n style=\"border-bottom: 1px solid #f1f3f5;\">\n <td style=\"padding: 12px;\">\n <span style=\"display: flex; align-items: center; gap: 6px;\">\n <i [class]=\"'fa-solid ' + getExecutionStatusIcon(run.Success)\" \n [style.color]=\"getExecutionStatusColor(run.Success)\"></i>\n <span [style.color]=\"getExecutionStatusColor(run.Success)\" style=\"font-weight: 500;\">\n {{ run.Success === true ? 'Success' : run.Success === false ? 'Failed' : 'Running' }}\n </span>\n </span>\n </td>\n <td style=\"padding: 12px; color: #495057;\">\n {{ run.RunAt | date:'short' }}\n </td>\n <td style=\"padding: 12px; color: #495057;\">\n <span style=\"display: flex; align-items: center; gap: 6px;\">\n <i class=\"fa-solid fa-microchip\" style=\"color: #6c757d;\"></i>\n {{ run.Model || 'Unknown' }}\n </span>\n </td>\n <td style=\"padding: 12px; color: #495057;\">\n {{ formatDuration(run.ExecutionTimeMS) }}\n </td>\n <td style=\"padding: 12px; text-align: right; color: #495057;\">\n {{ formatTokens(run.TokensUsed) }}\n </td>\n <td style=\"padding: 12px; text-align: right; color: #495057;\">\n {{ formatCost(run.TotalCost || run.Cost) }}\n </td>\n <td style=\"padding: 12px; text-align: center;\">\n @if (run.RunType) {\n <span style=\"padding: 4px 8px; border-radius: 12px; background: #e9ecef; \n color: #495057; font-size: 0.85em; font-weight: 500;\">\n {{ run.RunType }}\n </span>\n }\n </td>\n <td style=\"padding: 12px; text-align: center;\">\n <button kendoButton \n fillMode=\"flat\"\n size=\"small\"\n (click)=\"navigateToPromptRun(run.ID)\"\n title=\"View details\">\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 <!-- Cache Expansion Panel -->\n @if (record.IsSaved && record.EnableCaching) {\n <kendo-expansionpanel \n [expanded]=\"false\"\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-database\" style=\"color: #6c757d;\"></i>\n Result Cache\n </span>\n </ng-template>\n \n <!-- Direct Content Projection -->\n <div style=\"padding: 16px 0;\">\n <mj-user-view-grid \n [Params]=\"BuildRelationshipViewParamsByEntityName('AI Result Cache','AIPromptID')\" \n [NewRecordValues]=\"NewRecordValues('AI Result Cache')\"\n [AllowLoad]=\"true\"\n [EditMode]=\"GridEditMode()\" \n style=\"height: 300px;\">\n </mj-user-view-grid>\n </div>\n </kendo-expansionpanel>\n }\n\n <!-- Related Items Expansion Panel -->\n @if (record.IsSaved) {\n <kendo-expansionpanel \n [expanded]=\"false\"\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-link\" style=\"color: #6c757d;\"></i>\n Related Items\n </span>\n </ng-template>\n \n <!-- Direct Content Projection -->\n <div style=\"padding: 16px 0;\">\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 20px;\">\n <!-- AI Agents -->\n <div>\n <h6 style=\"margin: 0 0 12px 0; color: #495057;\">AI Agents Using This Prompt</h6>\n <mj-user-view-grid \n [Params]=\"BuildRelationshipViewParamsByEntityName('MJ: AI Agent Prompts','PromptID')\" \n [NewRecordValues]=\"NewRecordValues('MJ: AI Agent Prompts')\"\n [AllowLoad]=\"true\"\n [EditMode]=\"GridEditMode()\" \n style=\"height: 200px;\">\n </mj-user-view-grid>\n </div>\n \n <!-- Result Selector References -->\n <div>\n <h6 style=\"margin: 0 0 12px 0; color: #495057;\">Prompts Using This as Result Selector</h6>\n <mj-user-view-grid \n [Params]=\"BuildRelationshipViewParamsByEntityName('AI Prompts','ResultSelectorPromptID')\" \n [NewRecordValues]=\"NewRecordValues('AI Prompts')\"\n [AllowLoad]=\"true\"\n [EditMode]=\"GridEditMode()\" \n style=\"height: 200px;\">\n </mj-user-view-grid>\n </div>\n </div>\n </div>\n </kendo-expansionpanel>\n }\n </div>\n </div>\n </form>\n\n \n <!-- AI Prompt 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 AI Prompt - {{ record.Name || 'Untitled' }}\">\n <mj-ai-test-harness\n [entity]=\"record\"\n [mode]=\"'prompt'\"\n [isVisible]=\"showTestHarness\"\n (visibilityChange)=\"onTestHarnessVisibilityChanged($event)\">\n </mj-ai-test-harness>\n </kendo-window>\n }\n</div>", styles: [".record-form-container {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n padding: 10px;\n}\n\n.custom-toolbar-actions {\n margin-left: auto;\n}\n\n.status-badge {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n font-weight: 500;\n letter-spacing: 0.02em;\n}\n\n.config-summary {\n position: sticky;\n top: 0;\n max-height: 600px;\n overflow-y: auto;\n}\n\n.config-item {\n padding: 8px 0;\n border-bottom: 1px solid #e9ecef;\n}\n\n.config-item:last-child {\n border-bottom: none;\n}\n\n.template-tab-content {\n background: #fff;\n}\n\n.template-header h5 {\n font-size: 1.1em;\n}\n\n.loading-state,\n.no-template-state,\n.invalid-template-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n}\n\n.no-template-state i,\n.invalid-template-state i {\n opacity: 0.6;\n}\n\n.template-editor-container {\n background: #fff;\n border-radius: 6px;\n}\n\n/* Grid layout adjustments */\n@media (max-width: 1200px) {\n .record-form-container .mj-tab-body > div {\n grid-template-columns: 1fr !important;\n gap: 20px;\n }\n \n .config-summary {\n order: -1;\n position: static;\n max-height: none;\n }\n}\n\n/* Responsive toolbar */\n@media (max-width: 768px) {\n .custom-toolbar-actions {\n flex-direction: column;\n gap: 4px !important;\n }\n \n .status-badge {\n align-self: flex-start;\n }\n}\n\n/* Ensure proper spacing in form sections */\n.record-form-container mj-form-section {\n padding: 16px;\n}\n\n/* Smooth transitions for better UX */\n.status-badge,\n.config-item,\n.template-header {\n transition: all 0.2s ease;\n}\n\n.config-item:hover {\n background-color: rgba(0,0,0,0.02);\n border-radius: 4px;\n margin: 0 -8px;\n padding: 8px;\n}\n\n/* Execution History Table Styles */\n.history-row {\n transition: background 0.2s;\n}\n\n.history-row:not(.even-row) {\n background: #f8f9fa;\n}\n\n.history-row.even-row {\n background: white;\n}\n\n.history-row:hover {\n background: #e9ecef !important;\n}\n\n/* Template Parameters Styles */\n.parameter-card {\n position: relative;\n overflow: hidden;\n}\n\n.parameter-card::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 4px;\n background: inherit;\n transition: width 0.2s;\n}\n\n.parameter-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n}\n\n.parameter-card:hover::before {\n width: 6px;\n}\n\n.type-badge {\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n transition: transform 0.2s;\n}\n\n.parameter-card:hover .type-badge {\n transform: scale(1.05);\n}\n\n/* Parameter type icons animation */\n.parameter-card i.fa-solid {\n transition: transform 0.3s;\n}\n\n.parameter-card:hover i.fa-solid {\n transform: rotate(360deg);\n}\n\n/* Grid responsive behavior */\n@media (max-width: 768px) {\n .parameter-card {\n margin-bottom: 8px;\n }\n \n .parameter-card h6 {\n font-size: 0.95em;\n }\n \n .type-badge {\n font-size: 0.7em !important;\n }\n}"] }]
3066
+ args: [{ selector: 'mj-ai-prompt-form', template: "<div class=\"record-form-container\">\n <!-- Dialog container for Kendo dialogs -->\n <div kendoDialogContainer></div>\n <form *ngIf=\"record\" class=\"record-form\" #form=\"ngForm\" >\n <mj-form-toolbar [form]=\"this\"></mj-form-toolbar>\n\n <!-- Main Content Area - Template Editor and Configuration -->\n <div class=\"prompt-main-area\" style=\"display: flex; flex-direction: column; height: 100%; overflow-y: auto;\">\n \n <!-- Header Section -->\n <div class=\"prompt-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: Prompt 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=\"fa-solid fa-robot\" style=\"color: #6f42c1; font-size: 1.4em;\"></i>\n @if (EditMode) {\n <kendo-textbox [(ngModel)]=\"record.Name\" \n name=\"promptName\"\n placeholder=\"Enter prompt 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 AI Prompt' }}</h4>\n <span class=\"status-badge\" [style.background-color]=\"getStatusBadgeColor()\" \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=\"promptStatus\"\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 @if (isLoadingPromptTypes) {\n <div style=\"padding: 8px; color: #6c757d; font-style: italic; width: 200px;\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading types...\n </div>\n } @else {\n <kendo-dropdownlist [(ngModel)]=\"record.TypeID\"\n name=\"promptTypeID\"\n [data]=\"availablePromptTypes\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n [filterable]=\"true\"\n placeholder=\"Select prompt type...\"\n style=\"width: 200px;\">\n </kendo-dropdownlist>\n }\n </div>\n </div>\n }\n \n @if (EditMode) {\n <kendo-textarea [(ngModel)]=\"record.Description\" \n name=\"promptDescription\"\n [rows]=\"2\"\n placeholder=\"Enter prompt 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 (record.TypeID) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-tag\" style=\"color: #6c757d;\"></i>\n <span style=\"color: #6c757d;\">Type:</span>\n <span style=\"color: #495057; font-weight: 500;\">{{ getPromptTypeDisplayName(record.TypeID) }}</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-layer-group\" style=\"color: #6c757d;\"></i>\n <span style=\"color: #6c757d;\">Parallelization:</span>\n <span style=\"color: #495057; font-weight: 500;\">{{ getParallelizationModeDisplay() }}</span>\n </div>\n \n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-code\" style=\"color: #6c757d;\"></i>\n <span style=\"color: #6c757d;\">Output:</span>\n <span [style.color]=\"getValidationColor()\" style=\"font-weight: 500;\">{{ getOutputTypeDisplay() }}</span>\n </div>\n \n @if (record.EnableCaching) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-database\" style=\"color: #28a745;\"></i>\n <span style=\"color: #28a745; font-weight: 500;\">Caching Enabled</span>\n </div>\n }\n \n @if (record.EffortLevel) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-tachometer-alt\" style=\"color: #6c757d;\"></i>\n <span style=\"color: #6c757d;\">Effort Level:</span>\n <span style=\"color: #495057; font-weight: 500;\">{{ record.EffortLevel }}</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=\"Run AI Prompt Test Harness\">\n <i class=\"fa-solid fa-play\"></i> Run\n </button>\n }\n </div>\n \n @if (!canExecute && record.ID) {\n <div style=\"font-size: 0.75em; color: #dc3545; text-align: right; max-width: 200px;\">\n @if (record.Status !== 'Active') {\n \u2022 Prompt must be Active<br>\n }\n @if (!record.TemplateID) {\n \u2022 Template is required<br>\n }\n @if (!template && record.TemplateID) {\n \u2022 Template not found<br>\n }\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 <!-- Template Editor Section -->\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-code\" style=\"color: #6c757d;\"></i>\n Template Editor\n @if (template) {\n <span style=\"color: #6c757d; font-size: 0.9em; font-weight: normal;\">\u2022 {{ template.Name }}</span>\n }\n </span>\n </ng-template>\n \n <!-- Direct Content Projection -->\n <div class=\"template-section\" style=\"display: flex; flex-direction: column; min-height: 400px; padding: 8px;\">\n @if (isLoadingTemplate) {\n <div class=\"loading-state\" style=\"flex: 1; display: flex; align-items: center; justify-content: center; color: #6c757d;\">\n <i class=\"fa-solid fa-spinner fa-spin\" style=\"font-size: 24px; margin-right: 12px;\"></i>\n Loading template...\n </div>\n } @else if (!record.TemplateID) {\n <div class=\"no-template-state\" style=\"flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 40px; color: #6c757d;\">\n <i class=\"fa-solid fa-code\" style=\"font-size: 64px; margin-bottom: 20px; opacity: 0.3;\"></i>\n <h5 style=\"margin-bottom: 12px; color: #495057;\">No Template Associated</h5>\n <p style=\"margin-bottom: 24px; text-align: center; max-width: 400px;\">\n This AI prompt needs a template to define its structure and parameters. \n Create a new template or link to an existing one.\n </p>\n <div style=\"display: flex; gap: 12px;\">\n @if (UserCanCreateTemplates) {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"createNewTemplate()\">\n <i class=\"fa-solid fa-plus\"></i> Create New Template\n </button>\n }\n @if (UserCanReadTemplates) {\n <button kendoButton [fillMode]=\"'outline'\" (click)=\"linkExistingTemplate()\">\n <i class=\"fa-solid fa-link\"></i> Link Existing Template\n </button>\n }\n </div>\n </div>\n } @else if (templateNotFoundInDatabase) {\n <div class=\"invalid-template-state\" style=\"flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 40px; color: #dc3545;\">\n <i class=\"fa-solid fa-exclamation-triangle\" style=\"font-size: 64px; margin-bottom: 20px; opacity: 0.7;\"></i>\n <h5 style=\"margin-bottom: 12px;\">Template Not Found</h5>\n <p style=\"margin-bottom: 24px; text-align: center; max-width: 400px;\">\n The referenced template could not be loaded. It may have been deleted or moved.\n </p>\n <div style=\"display: flex; gap: 12px;\">\n <button kendoButton [fillMode]=\"'outline'\" (click)=\"loadTemplate()\">\n <i class=\"fa-solid fa-refresh\"></i> Retry Loading\n </button>\n @if (UserCanCreateTemplates) {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"createNewTemplate()\">\n <i class=\"fa-solid fa-plus\"></i> Create New Template\n </button>\n }\n </div>\n </div>\n } @else {\n <!-- Active Template Editor -->\n <div class=\"template-editor-container\" style=\"flex: 1; display: flex; flex-direction: column; min-height: 350px;\">\n <!-- Template Actions Bar -->\n @if (template && EditMode) {\n <div class=\"template-actions\" style=\"display: flex; gap: 8px; padding: 8px; border-bottom: 1px solid #e9ecef; background: #f8f9fa;\">\n @if (UserCanUpdateTemplates) {\n <button kendoButton \n [fillMode]=\"'outline'\" \n [size]=\"'small'\"\n (click)=\"linkExistingTemplate()\"\n title=\"Change to a different template\">\n <i class=\"fa-solid fa-exchange-alt\"></i> Change Template\n </button>\n }\n @if (UserCanReadTemplates) {\n <button kendoButton \n [fillMode]=\"'outline'\" \n [size]=\"'small'\"\n (click)=\"openTemplateInNewWindow()\"\n title=\"Open template in new window\">\n <i class=\"fa-solid fa-external-link-alt\"></i> Open in New Window\n </button>\n }\n </div>\n }\n \n <!-- Template Editor -->\n <div style=\"flex: 1; background: white; border-radius: 6px; border: 1px solid #e9ecef;\">\n <mj-template-editor \n #templateEditor\n [template]=\"template\"\n [config]=\"templateEditorConfig\"\n (contentChange)=\"onTemplateContentChange($event)\"\n (runTemplate)=\"onTemplateRun($event)\"\n style=\"display: block; min-height: 300px;\">\n </mj-template-editor>\n </div>\n </div>\n }\n </div>\n </kendo-expansionpanel> \n\n <!-- Model Configuration Expansion Panel -->\n @if (record.IsSaved) {\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-microchip\" style=\"color: #6c757d;\"></i>\n Models\n @if (promptModels.length > 0) {\n <span class=\"badge\" style=\"background: #17a2b8; color: white; padding: 2px 6px; border-radius: 10px; font-size: 0.7em;\">\n {{ promptModels.length }}\n </span>\n }\n <span style=\"color: #6c757d; font-size: 0.8em; font-weight: normal; margin-left: 8px;\">\n <i class=\"fa-solid fa-info-circle\" title=\"Models are tried in order from top to bottom. The first available model will be used.\"></i>\n Priority order (first available model will be used)\n </span>\n </span>\n </ng-template>\n \n <!-- Direct Content Projection -->\n <div style=\"padding: 16px 0;\">\n <!-- Model Management Interface -->\n <div class=\"model-management\" style=\"border: 1px solid #dee2e6; border-radius: 6px; background: #f8f9fa;\">\n @if (isLoadingModels) {\n <div class=\"loading-state\" style=\"padding: 20px; text-align: center; color: #6c757d;\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading models...\n </div>\n } @else {\n @if (promptModels.length === 0) {\n <div class=\"empty-state\" style=\"padding: 20px; text-align: center; color: #6c757d;\">\n <i class=\"fa-solid fa-info-circle\"></i> No models configured\n @if (EditMode && UserCanCreatePromptModels) {\n <div style=\"margin-top: 10px;\">\n <button kendoButton fillMode=\"outline\" themeColor=\"primary\" size=\"small\"\n (click)=\"addNewModel()\">\n <i class=\"fa-solid fa-plus\"></i> Add Model\n </button>\n </div>\n }\n </div>\n } @else {\n <!-- Priority explanation for multiple models -->\n @if (promptModels.length > 1) {\n <div style=\"padding: 12px 16px; background: #e3f2fd; border-bottom: 1px solid #bbdefb; color: #1565c0; font-size: 0.85em;\">\n <i class=\"fa-solid fa-info-circle\" style=\"margin-right: 6px;\"></i>\n Models are tried in priority order (highest priority first). The first available model that meets requirements will be used for execution.\n </div>\n }\n <!-- Column Headers -->\n <div class=\"model-header\" style=\"display: grid; grid-template-columns: 40px 2fr 1fr 1fr 1fr 60px; gap: 12px; padding: 12px 16px; background: #e9ecef; font-weight: 600; font-size: 0.85em; color: #495057; border-bottom: 1px solid #dee2e6;\">\n <div title=\"Priority order - models are tried from top to bottom\">\n <i class=\"fa-solid fa-sort\" style=\"color: #6c757d;\"></i>\n </div>\n <div>AI Model <span style=\"color: #dc3545;\">*</span></div>\n <div>Vendor</div>\n <div>Configuration</div>\n <div>Created</div>\n <div>Actions</div>\n </div>\n \n @for (model of promptModels; track getModelTrackId(model) || $index; let i = $index) {\n <div class=\"model-row\" \n [draggable]=\"EditMode\"\n (dragstart)=\"onDragStart($event, i)\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop($event, i)\"\n (dragend)=\"onDragEnd($event)\"\n [style.background]=\"!model.ModelID ? '#fff3cd' : (draggedIndex === i ? '#e3f2fd' : 'white')\"\n [style.border-left]=\"!model.ModelID ? '3px solid #ffc107' : 'none'\"\n [style.opacity]=\"draggedIndex === i ? '0.5' : '1'\"\n style=\"display: grid; grid-template-columns: 40px 2fr 1fr 1fr 1fr 60px; gap: 12px; padding: 12px 16px; border-bottom: 1px solid #e9ecef; align-items: start; transition: background 0.2s, opacity 0.2s;\">\n \n <!-- Drag Handle / Priority -->\n <div class=\"drag-handle\" style=\"display: flex; flex-direction: column; align-items: center; justify-content: center; color: #6c757d;\">\n @if (EditMode) {\n <i class=\"fa-solid fa-grip-vertical\" title=\"Drag to reorder priority\" style=\"cursor: move;\"></i>\n <span style=\"font-size: 0.7em; margin-top: 2px;\">#{{ i + 1 }}</span>\n } @else {\n <span style=\"font-size: 0.9em; font-weight: 600;\" title=\"Priority {{ model.Priority }} - Higher priority numbers are tried first\">#{{ i + 1 }}</span>\n }\n </div>\n \n <!-- Model Selection -->\n <div class=\"model-select\">\n @if (EditMode) {\n <kendo-dropdownlist [(ngModel)]=\"model.ModelID\"\n [name]=\"'modelId_' + getModelTrackId(model)\"\n [data]=\"availableModels\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n [filterable]=\"true\"\n placeholder=\"Select a model...\"\n (valueChange)=\"onModelChange($event, i)\"\n style=\"width: 100%;\">\n </kendo-dropdownlist>\n } @else {\n <span style=\"font-weight: 500;\">{{ getModelDisplayName(model.ModelID) }}</span>\n }\n </div>\n \n <!-- Vendor -->\n <div class=\"model-vendor\">\n @if (EditMode) {\n @if (model.ModelID) {\n @if (shouldShowVendorDropdown(model.ModelID)) {\n <kendo-dropdownlist [(ngModel)]=\"model.VendorID\"\n [name]=\"'vendorId_' + getModelTrackId(model)\"\n [data]=\"getVendorsForModelSync(model.ModelID)\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n [filterable]=\"true\"\n placeholder=\"Select vendor...\"\n style=\"width: 100%;\">\n <ng-template kendoDropDownListItemTemplate let-dataItem>\n <span [style.color]=\"getVendorStatusColor(model.ModelID, dataItem.ID)\">\n {{ dataItem.Name }}\n @if (getModelVendorStatus(model.ModelID, dataItem.ID) !== 'Active') {\n <span style=\"font-size: 0.8em; margin-left: 4px;\">({{ getModelVendorStatus(model.ModelID, dataItem.ID) }})</span>\n }\n </span>\n </ng-template>\n </kendo-dropdownlist>\n } @else {\n <!-- Single vendor - just show the name -->\n @if (getVendorsForModelSync(model.ModelID).length === 1) {\n <span [style.color]=\"getVendorStatusColor(model.ModelID, getVendorsForModelSync(model.ModelID)[0].ID)\" style=\"font-size: 0.9em; font-weight: 500;\">\n {{ getVendorsForModelSync(model.ModelID)[0].Name }}\n @if (getModelVendorStatus(model.ModelID, getVendorsForModelSync(model.ModelID)[0].ID) !== 'Active') {\n <span style=\"font-size: 0.8em; margin-left: 4px;\">({{ getModelVendorStatus(model.ModelID, getVendorsForModelSync(model.ModelID)[0].ID) }})</span>\n }\n </span>\n } @else {\n <span style=\"color: #6c757d; font-style: italic; font-size: 0.9em;\">No vendors available</span>\n }\n }\n } @else {\n <span style=\"color: #6c757d; font-style: italic; font-size: 0.9em;\">Select model first</span>\n }\n } @else {\n @if (model.VendorID && model.ModelID) {\n <span [style.color]=\"getVendorStatusColor(model.ModelID, model.VendorID)\" style=\"font-size: 0.9em;\">\n {{ getVendorDisplayName(model.VendorID) }}\n @if (getModelVendorStatus(model.ModelID, model.VendorID) !== 'Active') {\n <span style=\"font-size: 0.8em; margin-left: 4px;\">({{ getModelVendorStatus(model.ModelID, model.VendorID) }})</span>\n }\n </span>\n } @else {\n <span style=\"color: #6c757d; font-size: 0.9em;\">-</span>\n }\n }\n </div>\n \n <!-- Configuration -->\n <div class=\"model-configuration\">\n @if (EditMode) {\n @if (isLoadingConfigurations) {\n <div style=\"padding: 4px; color: #6c757d; font-style: italic; font-size: 0.85em;\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading...\n </div>\n } @else {\n <kendo-dropdownlist [(ngModel)]=\"model.ConfigurationID\"\n [name]=\"'configurationId_' + getModelTrackId(model)\"\n [data]=\"availableConfigurations\"\n textField=\"Name\"\n valueField=\"ID\"\n [valuePrimitive]=\"true\"\n [filterable]=\"true\"\n placeholder=\"Default\"\n (valueChange)=\"onConfigurationChange($event, i)\"\n style=\"width: 100%;\">\n <ng-template kendoDropDownListNoDataTemplate>\n <div style=\"padding: 8px; text-align: center; color: #6c757d;\">\n No configurations available\n </div>\n </ng-template>\n </kendo-dropdownlist>\n }\n } @else {\n <span style=\"font-size: 0.9em;\">{{ getConfigurationDisplayName(model.ConfigurationID) }}</span>\n }\n </div>\n \n <!-- Created Date -->\n <div class=\"model-created\">\n @if (model.ID) {\n <span style=\"color: #6c757d; font-size: 0.8em;\">{{ model.__mj_CreatedAt | date:'short' }}</span>\n } @else {\n <span style=\"color: #28a745; font-size: 0.8em; font-style: italic;\">New</span>\n }\n </div>\n \n <!-- Actions -->\n <div class=\"model-actions\" style=\"display: flex; gap: 2px; flex-direction: column;\">\n @if (EditMode) {\n <div style=\"display: flex; gap: 2px; margin-bottom: 4px;\">\n @if (UserCanUpdatePromptModels) {\n <button kendoButton fillMode=\"flat\" size=\"small\"\n (click)=\"moveModelUp(i)\"\n [disabled]=\"i === 0\"\n title=\"Move up\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <button kendoButton fillMode=\"flat\" size=\"small\"\n (click)=\"moveModelDown(i)\"\n [disabled]=\"i === promptModels.length - 1\"\n title=\"Move down\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n }\n </div>\n @if (UserCanDeletePromptModels) {\n <button kendoButton fillMode=\"flat\" themeColor=\"error\" size=\"small\"\n (click)=\"removePromptModel(i)\"\n title=\"Remove model\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n }\n </div>\n </div>\n \n <!-- Second row with additional details -->\n <div style=\"display: grid; grid-template-columns: 40px 1fr; gap: 12px; padding: 8px 16px; border-bottom: 1px solid #e9ecef; background: #f8f9fa; font-size: 0.85em; color: #6c757d;\">\n <div></div>\n <div>\n <!-- Basic model details -->\n <div style=\"display: flex; gap: 16px; flex-wrap: wrap; align-items: center; margin-bottom: 8px;\">\n @if (model.Status) {\n <span><strong>Status:</strong> {{ model.Status }}</span>\n }\n </div>\n \n <!-- Parallel execution fields when prompt is ModelSpecific -->\n @if (record.ParallelizationMode === 'ModelSpecific') {\n <div style=\"padding: 8px; background: #fff; border: 1px solid #dee2e6; border-radius: 4px; margin-top: 8px;\">\n <div style=\"margin-bottom: 6px; font-weight: 600; color: #495057; font-size: 0.9em;\">\n <i class=\"fa-solid fa-layer-group\"></i> Model-Specific Parallel Execution\n </div>\n \n @if (EditMode) {\n <div style=\"display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; align-items: center;\">\n <!-- Parallel Mode -->\n <div>\n <label style=\"display: block; margin-bottom: 2px; font-size: 0.8em; font-weight: 600; color: #495057;\">Parallel Mode</label>\n <kendo-dropdownlist [(ngModel)]=\"model.ParallelizationMode\"\n [name]=\"'parallelMode_' + i\"\n [data]=\"[{text: 'None', value: 'None'}, {text: 'Static Count', value: 'StaticCount'}, {text: 'Config Param', value: 'ConfigParam'}]\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n placeholder=\"Select mode...\"\n style=\"width: 100%; font-size: 0.85em;\">\n </kendo-dropdownlist>\n </div>\n \n <!-- Parallel Count (when StaticCount) -->\n @if (model.ParallelizationMode === 'StaticCount') {\n <div>\n <label style=\"display: block; margin-bottom: 2px; font-size: 0.8em; font-weight: 600; color: #495057;\">Parallel Count</label>\n <kendo-numerictextbox [(ngModel)]=\"model.ParallelCount\"\n [name]=\"'parallelCount_' + i\"\n [min]=\"1\"\n [step]=\"1\"\n [format]=\"'n0'\"\n placeholder=\"Count...\"\n style=\"width: 100%; font-size: 0.85em;\">\n </kendo-numerictextbox>\n </div>\n }\n \n <!-- Config Param (when ConfigParam) -->\n @if (model.ParallelizationMode === 'ConfigParam') {\n <div>\n <label style=\"display: block; margin-bottom: 2px; font-size: 0.8em; font-weight: 600; color: #495057;\">Config Parameter</label>\n <kendo-textbox [(ngModel)]=\"model.ParallelConfigParam\"\n [name]=\"'parallelConfigParam_' + i\"\n placeholder=\"Parameter name...\"\n style=\"width: 100%; font-size: 0.85em;\">\n </kendo-textbox>\n </div>\n }\n </div>\n } @else {\n <!-- Read-only display -->\n <div style=\"display: flex; gap: 16px; flex-wrap: wrap; align-items: center;\">\n @if (model.ParallelizationMode) {\n <span><strong>Parallel Mode:</strong> {{ model.ParallelizationMode }}</span>\n }\n @if (model.ParallelCount) {\n <span><strong>Parallel Count:</strong> {{ model.ParallelCount }}</span>\n }\n @if (model.ParallelConfigParam) {\n <span><strong>Config Param:</strong> {{ model.ParallelConfigParam }}</span>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n \n @if (EditMode && UserCanCreatePromptModels) {\n <div class=\"add-model-row\" style=\"padding: 12px 16px; text-align: center; background: #f8f9fa; border-top: 1px solid #dee2e6;\">\n <button kendoButton fillMode=\"outline\" themeColor=\"success\" size=\"small\"\n (click)=\"addNewModel()\">\n <i class=\"fa-solid fa-plus\"></i> Add Model\n </button>\n </div>\n }\n }\n }\n </div>\n </div>\n </kendo-expansionpanel>\n }\n\n <!-- Advanced Configuration Expansion Panel -->\n <kendo-expansionpanel \n [expanded]=\"false\"\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 Advanced Configuration\n </span>\n </ng-template>\n \n <!-- Direct Content Projection -->\n <div style=\"padding: 16px 0;\">\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 20px;\">\n \n <!-- Left Column -->\n <div>\n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ParallelizationMode\"\n Type=\"dropdownlist\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n \n @if (showParallelCount) {\n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ParallelCount\"\n Type=\"numerictextbox\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n }\n \n @if (showParallelConfigParam) {\n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ParallelConfigParam\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n }\n \n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"OutputType\"\n Type=\"dropdownlist\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n \n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"EffortLevel\"\n Type=\"numerictextbox\"\n Caption=\"Effort Level (1-100)\"\n Description=\"Higher values request more thorough reasoning\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n \n </div>\n \n <!-- Right Column -->\n <div>\n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ValidationBehavior\"\n Type=\"dropdownlist\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n \n <mj-form-field \n [record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"EnableCaching\"\n Type=\"checkbox\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n \n <!-- Result Selector Prompt with Tree Selector -->\n <div style=\"margin-bottom: 16px;\">\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: #495057; font-size: 0.9em;\">\n Result Selector Prompt\n </label>\n @if (EditMode) {\n @if (isLoadingResultSelectorData) {\n <div style=\"padding: 8px; color: #6c757d; font-style: italic;\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading prompts...\n </div>\n } @else {\n <kendo-dropdowntree \n [(ngModel)]=\"record.ResultSelectorPromptID\"\n name=\"resultSelectorPromptID\"\n [data]=\"resultSelectorTreeData\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n [filterable]=\"true\"\n placeholder=\"Select a result selector prompt...\"\n style=\"width: 100%;\"\n (valueChange)=\"onResultSelectorChange($event)\">\n </kendo-dropdowntree>\n }\n } @else {\n <span style=\"color: #495057;\">{{ getPromptDisplayName(record.ResultSelectorPromptID || '') || 'None selected' }}</span>\n }\n </div>\n </div>\n </div>\n </div>\n </kendo-expansionpanel>\n\n <!-- Template Parameters Expansion Panel -->\n @if (template && templateParams.length > 0) {\n <kendo-expansionpanel \n [expanded]=\"false\"\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 Template Parameters\n <span class=\"badge\" style=\"background: #6f42c1; color: white; padding: 2px 6px; border-radius: 10px; font-size: 0.7em;\">\n {{ templateParams.length }}\n </span>\n <span style=\"color: #6c757d; font-size: 0.8em; font-weight: normal; margin-left: 8px;\">\n <i class=\"fa-solid fa-info-circle\" title=\"These parameters are defined in the template and will be available when executing this prompt\"></i>\n Parameters defined in the template\n </span>\n </span>\n </ng-template>\n \n <!-- Template Parameters Display -->\n <div style=\"padding: 16px 0;\">\n @if (isLoadingTemplateParams) {\n <div class=\"loading-state\" style=\"padding: 20px; text-align: center; color: #6c757d;\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading template parameters...\n </div>\n } @else if (templateParams.length === 0) {\n <div class=\"empty-state\" style=\"padding: 20px; text-align: center; color: #6c757d;\">\n <i class=\"fa-solid fa-info-circle\"></i> This template has no parameters defined\n </div>\n } @else {\n <!-- Parameters Grid -->\n <div style=\"display: grid; gap: 12px;\">\n @for (param of templateParams; track param.ID) {\n <div class=\"parameter-card\" \n style=\"border: 1px solid #e9ecef; border-radius: 8px; padding: 16px; background: #f8f9fa; transition: all 0.2s;\"\n [style.border-left]=\"'4px solid ' + getParamTypeColor(param.Type)\">\n \n <!-- Parameter Header -->\n <div style=\"display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 8px;\">\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <i [class]=\"'fa-solid ' + getParamTypeIcon(param.Type)\" \n [style.color]=\"getParamTypeColor(param.Type)\"\n style=\"font-size: 1.2em;\"></i>\n <h6 style=\"margin: 0; color: #495057; font-weight: 600;\">\n {{ param.Name }}\n @if (param.IsRequired) {\n <span style=\"color: #dc3545; font-size: 0.9em; margin-left: 4px;\">*</span>\n }\n </h6>\n </div>\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <span class=\"type-badge\" \n [style.background-color]=\"getParamTypeColor(param.Type)\"\n style=\"color: white; padding: 4px 8px; border-radius: 12px; font-size: 0.75em; font-weight: 500;\">\n {{ param.Type }}\n </span>\n @if (param.IsRequired) {\n <span style=\"color: #dc3545; font-size: 0.85em; font-weight: 500;\">Required</span>\n } @else {\n <span style=\"color: #6c757d; font-size: 0.85em;\">Optional</span>\n }\n </div>\n </div>\n \n <!-- Parameter Description -->\n @if (param.Description) {\n <p style=\"margin: 0 0 8px 0; color: #6c757d; font-size: 0.9em; line-height: 1.4;\">\n {{ param.Description }}\n </p>\n }\n \n <!-- Type-specific Information -->\n <div style=\"font-size: 0.85em; color: #495057;\">\n <span style=\"display: flex; align-items: center; gap: 4px; margin-bottom: 4px;\">\n <i class=\"fa-solid fa-info-circle\" style=\"color: #6c757d;\"></i>\n {{ getParamTypeDescription(param) }}\n </span>\n </div>\n \n <!-- Additional Parameter Details -->\n <div style=\"display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-top: 12px;\">\n @if (param.DefaultValue) {\n <div style=\"background: white; padding: 8px 12px; border-radius: 4px; border: 1px solid #dee2e6;\">\n <label style=\"display: block; font-size: 0.8em; color: #6c757d; margin-bottom: 2px;\">Default Value</label>\n <code style=\"font-size: 0.85em; color: #495057; word-break: break-all;\">{{ param.DefaultValue }}</code>\n </div>\n }\n \n @if (param.EntityID) {\n <div style=\"background: white; padding: 8px 12px; border-radius: 4px; border: 1px solid #dee2e6;\">\n <label style=\"display: block; font-size: 0.8em; color: #6c757d; margin-bottom: 2px;\">Entity</label>\n <span style=\"font-size: 0.85em; color: #495057;\">{{ param.Entity || 'Entity ID: ' + param.EntityID }}</span>\n </div>\n }\n \n @if (param.LinkedParameterName) {\n <div style=\"background: white; padding: 8px 12px; border-radius: 4px; border: 1px solid #dee2e6;\">\n <label style=\"display: block; font-size: 0.8em; color: #6c757d; margin-bottom: 2px;\">Linked To</label>\n <span style=\"font-size: 0.85em; color: #495057;\">\n {{ param.LinkedParameterName }}\n @if (param.LinkedParameterField) {\n ({{ param.LinkedParameterField }})\n }\n </span>\n </div>\n }\n \n @if (param.ExtraFilter) {\n <div style=\"background: white; padding: 8px 12px; border-radius: 4px; border: 1px solid #dee2e6;\">\n <label style=\"display: block; font-size: 0.8em; color: #6c757d; margin-bottom: 2px;\">Filter</label>\n <code style=\"font-size: 0.8em; color: #495057; word-break: break-all;\">{{ param.ExtraFilter }}</code>\n </div>\n }\n \n @if (param.RecordID) {\n <div style=\"background: white; padding: 8px 12px; border-radius: 4px; border: 1px solid #dee2e6;\">\n <label style=\"display: block; font-size: 0.8em; color: #6c757d; margin-bottom: 2px;\">Record ID</label>\n <code style=\"font-size: 0.85em; color: #495057;\">{{ param.RecordID }}</code>\n </div>\n }\n </div>\n </div>\n }\n </div>\n \n <!-- Help Text -->\n <div style=\"margin-top: 16px; padding: 12px; background: #e3f2fd; border-radius: 6px; border: 1px solid #bbdefb;\">\n <div style=\"display: flex; align-items: flex-start; gap: 8px;\">\n <i class=\"fa-solid fa-lightbulb\" style=\"color: #1976d2; margin-top: 2px;\"></i>\n <div style=\"flex: 1; font-size: 0.85em; color: #1565c0; line-height: 1.5;\">\n <strong>Using Template Parameters:</strong> When executing this prompt, you'll be prompted to provide values for all required parameters. \n Parameters can be simple values (text, numbers) or complex data structures (JSON objects, database records, or entire entity collections).\n The template will use these parameters to generate dynamic content based on the values provided at execution time.\n </div>\n </div>\n </div>\n }\n </div>\n </kendo-expansionpanel>\n }\n\n <!-- Output Example Expansion Panel (when OutputType = object) -->\n @if (showOutputExample) {\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-code\" style=\"color: #6c757d;\"></i>\n Output Example (JSON)\n <span style=\"color: #dc3545; font-size: 0.8em; font-weight: normal;\">\u2022 Required for object output type</span>\n </span>\n </ng-template>\n \n <!-- Direct Content Projection -->\n <div style=\"padding: 16px;\">\n @if (EditMode) {\n <mj-code-editor \n [(ngModel)]=\"record.OutputExample\"\n name=\"outputExample\"\n language=\"json\"\n placeholder=\"Enter JSON example structure...\"\n style=\"width: 100%; height: 200px; border: 1px solid #dee2e6; border-radius: 4px;\">\n </mj-code-editor>\n <div style=\"margin-top: 8px; color: #6c757d; font-size: 0.85em;\">\n <i class=\"fa-solid fa-info-circle\"></i> Provide a JSON example that defines the expected structure for object output validation.\n </div>\n } @else if (record.OutputExample) {\n <div style=\"background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 4px; padding: 12px; font-family: 'Courier New', monospace; font-size: 0.9em; white-space: pre-wrap; overflow: auto; max-height: 250px;\">{{ record.OutputExample }}</div>\n } @else {\n <div style=\"background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 4px; padding: 12px; color: #856404; text-align: center;\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i> Output example is required when output type is 'object'\n </div>\n }\n </div>\n </kendo-expansionpanel>\n }\n\n <!-- Execution History Expansion Panel -->\n @if (record.IsSaved) {\n <kendo-expansionpanel \n [expanded]=\"false\"\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-history\" style=\"color: #6c757d;\"></i>\n Execution History\n @if (executionHistory.length > 0) {\n <span style=\"color: #6c757d; font-weight: normal;\">({{ executionHistory.length }})</span>\n }\n </span>\n </ng-template>\n \n <!-- Custom Execution History Viewer -->\n <div style=\"padding: 16px;\">\n @if (isLoadingHistory) {\n <div style=\"text-align: center; padding: 40px; color: #6c757d;\">\n <i class=\"fa-solid fa-spinner fa-spin\" style=\"font-size: 2em; margin-bottom: 12px;\"></i>\n <p>Loading execution history...</p>\n </div>\n } @else if (executionHistory.length === 0) {\n <div style=\"text-align: center; padding: 40px; color: #6c757d;\">\n <i class=\"fa-solid fa-history\" style=\"font-size: 3em; margin-bottom: 12px; opacity: 0.3;\"></i>\n <p>No execution history yet</p>\n <p style=\"font-size: 0.9em;\">Run this prompt to see execution history here</p>\n </div>\n } @else {\n <!-- Sort Controls -->\n <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;\">\n <div style=\"color: #6c757d; font-size: 0.9em;\">\n Showing {{ executionHistory.length }} executions\n </div>\n <div style=\"display: flex; gap: 8px; align-items: center;\">\n <span style=\"color: #6c757d; font-size: 0.85em;\">Sort by:</span>\n <kendo-buttongroup selection=\"single\">\n <button kendoButton \n [selected]=\"historySortField === 'runAt'\"\n (click)=\"changeHistorySort('runAt')\"\n size=\"small\">\n Date\n @if (historySortField === 'runAt') {\n <i [class]=\"'fa-solid fa-sort-' + (historySortDirection === 'asc' ? 'up' : 'down')\" \n style=\"margin-left: 4px; font-size: 0.8em;\"></i>\n }\n </button>\n <button kendoButton \n [selected]=\"historySortField === 'executionTime'\"\n (click)=\"changeHistorySort('executionTime')\"\n size=\"small\">\n Duration\n @if (historySortField === 'executionTime') {\n <i [class]=\"'fa-solid fa-sort-' + (historySortDirection === 'asc' ? 'up' : 'down')\" \n style=\"margin-left: 4px; font-size: 0.8em;\"></i>\n }\n </button>\n <button kendoButton \n [selected]=\"historySortField === 'tokens'\"\n (click)=\"changeHistorySort('tokens')\"\n size=\"small\">\n Tokens\n @if (historySortField === 'tokens') {\n <i [class]=\"'fa-solid fa-sort-' + (historySortDirection === 'asc' ? 'up' : 'down')\" \n style=\"margin-left: 4px; font-size: 0.8em;\"></i>\n }\n </button>\n <button kendoButton \n [selected]=\"historySortField === 'cost'\"\n (click)=\"changeHistorySort('cost')\"\n size=\"small\">\n Cost\n @if (historySortField === 'cost') {\n <i [class]=\"'fa-solid fa-sort-' + (historySortDirection === 'asc' ? 'up' : 'down')\" \n style=\"margin-left: 4px; font-size: 0.8em;\"></i>\n }\n </button>\n </kendo-buttongroup>\n </div>\n </div>\n \n <!-- Execution History Table -->\n <div style=\"border: 1px solid #e9ecef; border-radius: 8px; overflow: hidden;\">\n <table style=\"width: 100%; border-collapse: collapse;\">\n <thead>\n <tr style=\"background: #f8f9fa; border-bottom: 2px solid #e9ecef;\">\n <th style=\"padding: 12px; text-align: left; font-weight: 600; color: #495057;\">Status</th>\n <th style=\"padding: 12px; text-align: left; font-weight: 600; color: #495057;\">Date & Time</th>\n <th style=\"padding: 12px; text-align: left; font-weight: 600; color: #495057;\">Model</th>\n <th style=\"padding: 12px; text-align: left; font-weight: 600; color: #495057;\">Duration</th>\n <th style=\"padding: 12px; text-align: right; font-weight: 600; color: #495057;\">Tokens</th>\n <th style=\"padding: 12px; text-align: right; font-weight: 600; color: #495057;\">Cost</th>\n <th style=\"padding: 12px; text-align: center; font-weight: 600; color: #495057;\">Type</th>\n <th style=\"padding: 12px; text-align: center; font-weight: 600; color: #495057;\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (run of executionHistory; track run.ID; let i = $index) {\n <tr class=\"history-row\"\n [class.even-row]=\"i % 2 === 0\"\n style=\"border-bottom: 1px solid #f1f3f5;\">\n <td style=\"padding: 12px;\">\n <span style=\"display: flex; align-items: center; gap: 6px;\">\n <i [class]=\"'fa-solid ' + getExecutionStatusIcon(run.Success)\" \n [style.color]=\"getExecutionStatusColor(run.Success)\"></i>\n <span [style.color]=\"getExecutionStatusColor(run.Success)\" style=\"font-weight: 500;\">\n {{ run.Success === true ? 'Success' : run.Success === false ? 'Failed' : 'Running' }}\n </span>\n </span>\n </td>\n <td style=\"padding: 12px; color: #495057;\">\n {{ run.RunAt | date:'short' }}\n </td>\n <td style=\"padding: 12px; color: #495057;\">\n <span style=\"display: flex; align-items: center; gap: 6px;\">\n <i class=\"fa-solid fa-microchip\" style=\"color: #6c757d;\"></i>\n {{ run.Model || 'Unknown' }}\n </span>\n </td>\n <td style=\"padding: 12px; color: #495057;\">\n {{ formatDuration(run.ExecutionTimeMS) }}\n </td>\n <td style=\"padding: 12px; text-align: right; color: #495057;\">\n {{ formatTokens(run.TokensUsed) }}\n </td>\n <td style=\"padding: 12px; text-align: right; color: #495057;\">\n {{ formatCost(run.TotalCost || run.Cost) }}\n </td>\n <td style=\"padding: 12px; text-align: center;\">\n @if (run.RunType) {\n <span style=\"padding: 4px 8px; border-radius: 12px; background: #e9ecef; \n color: #495057; font-size: 0.85em; font-weight: 500;\">\n {{ run.RunType }}\n </span>\n }\n </td>\n <td style=\"padding: 12px; text-align: center;\">\n <button kendoButton \n fillMode=\"flat\"\n size=\"small\"\n (click)=\"navigateToPromptRun(run.ID)\"\n title=\"View details\">\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 <!-- Cache Expansion Panel -->\n @if (record.IsSaved && record.EnableCaching) {\n <kendo-expansionpanel \n [expanded]=\"false\"\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-database\" style=\"color: #6c757d;\"></i>\n Result Cache\n </span>\n </ng-template>\n \n <!-- Direct Content Projection -->\n <div style=\"padding: 16px 0;\">\n <mj-explorer-entity-data-grid\n [Params]=\"BuildRelationshipViewParamsByEntityName('AI Result Cache','AIPromptID')\"\n [NewRecordValues]=\"NewRecordValues('AI Result Cache')\"\n [AllowLoad]=\"true\"\n [ShowToolbar]=\"false\">\n </mj-explorer-entity-data-grid>\n </div>\n </kendo-expansionpanel>\n }\n\n <!-- Related Items Expansion Panel -->\n @if (record.IsSaved) {\n <kendo-expansionpanel \n [expanded]=\"false\"\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-link\" style=\"color: #6c757d;\"></i>\n Related Items\n </span>\n </ng-template>\n \n <!-- Direct Content Projection -->\n <div style=\"padding: 16px 0;\">\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 20px;\">\n <!-- AI Agents -->\n <div>\n <h6 style=\"margin: 0 0 12px 0; color: #495057;\">AI Agents Using This Prompt</h6>\n <mj-explorer-entity-data-grid\n [Params]=\"BuildRelationshipViewParamsByEntityName('MJ: AI Agent Prompts','PromptID')\"\n [NewRecordValues]=\"NewRecordValues('MJ: AI Agent Prompts')\"\n [AllowLoad]=\"true\"\n [ShowToolbar]=\"false\">\n </mj-explorer-entity-data-grid>\n </div>\n \n <!-- Result Selector References -->\n <div>\n <h6 style=\"margin: 0 0 12px 0; color: #495057;\">Prompts Using This as Result Selector</h6>\n <mj-explorer-entity-data-grid\n [Params]=\"BuildRelationshipViewParamsByEntityName('AI Prompts','ResultSelectorPromptID')\"\n [NewRecordValues]=\"NewRecordValues('AI Prompts')\"\n [AllowLoad]=\"true\"\n [ShowToolbar]=\"false\">\n </mj-explorer-entity-data-grid>\n </div>\n </div>\n </div>\n </kendo-expansionpanel>\n }\n </div>\n </div>\n </form>\n\n \n <!-- AI Prompt 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 AI Prompt - {{ record.Name || 'Untitled' }}\">\n <mj-ai-test-harness\n [entity]=\"record\"\n [mode]=\"'prompt'\"\n [isVisible]=\"showTestHarness\"\n (visibilityChange)=\"onTestHarnessVisibilityChanged($event)\">\n </mj-ai-test-harness>\n </kendo-window>\n }\n</div>", styles: [".record-form-container {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n padding: 10px;\n}\n\n.custom-toolbar-actions {\n margin-left: auto;\n}\n\n.status-badge {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n font-weight: 500;\n letter-spacing: 0.02em;\n}\n\n.config-summary {\n position: sticky;\n top: 0;\n max-height: 600px;\n overflow-y: auto;\n}\n\n.config-item {\n padding: 8px 0;\n border-bottom: 1px solid #e9ecef;\n}\n\n.config-item:last-child {\n border-bottom: none;\n}\n\n.template-tab-content {\n background: #fff;\n}\n\n.template-header h5 {\n font-size: 1.1em;\n}\n\n.loading-state,\n.no-template-state,\n.invalid-template-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n}\n\n.no-template-state i,\n.invalid-template-state i {\n opacity: 0.6;\n}\n\n.template-editor-container {\n background: #fff;\n border-radius: 6px;\n}\n\n/* Grid layout adjustments */\n@media (max-width: 1200px) {\n .record-form-container .mj-tab-body > div {\n grid-template-columns: 1fr !important;\n gap: 20px;\n }\n \n .config-summary {\n order: -1;\n position: static;\n max-height: none;\n }\n}\n\n/* Responsive toolbar */\n@media (max-width: 768px) {\n .custom-toolbar-actions {\n flex-direction: column;\n gap: 4px !important;\n }\n \n .status-badge {\n align-self: flex-start;\n }\n}\n\n/* Ensure proper spacing in form sections */\n.record-form-container mj-form-section {\n padding: 16px;\n}\n\n/* Smooth transitions for better UX */\n.status-badge,\n.config-item,\n.template-header {\n transition: all 0.2s ease;\n}\n\n.config-item:hover {\n background-color: rgba(0,0,0,0.02);\n border-radius: 4px;\n margin: 0 -8px;\n padding: 8px;\n}\n\n/* Execution History Table Styles */\n.history-row {\n transition: background 0.2s;\n}\n\n.history-row:not(.even-row) {\n background: #f8f9fa;\n}\n\n.history-row.even-row {\n background: white;\n}\n\n.history-row:hover {\n background: #e9ecef !important;\n}\n\n/* Template Parameters Styles */\n.parameter-card {\n position: relative;\n overflow: hidden;\n}\n\n.parameter-card::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 4px;\n background: inherit;\n transition: width 0.2s;\n}\n\n.parameter-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n}\n\n.parameter-card:hover::before {\n width: 6px;\n}\n\n.type-badge {\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n transition: transform 0.2s;\n}\n\n.parameter-card:hover .type-badge {\n transform: scale(1.05);\n}\n\n/* Parameter type icons animation */\n.parameter-card i.fa-solid {\n transition: transform 0.3s;\n}\n\n.parameter-card:hover i.fa-solid {\n transform: rotate(360deg);\n}\n\n/* Grid responsive behavior */\n@media (max-width: 768px) {\n .parameter-card {\n margin-bottom: 8px;\n }\n \n .parameter-card h6 {\n font-size: 0.95em;\n }\n \n .type-badge {\n font-size: 0.7em !important;\n }\n}"] }]
3068
3067
  }], () => [{ type: i0.ElementRef }, { type: i1.SharedService }, { type: i2.Router }, { type: i2.ActivatedRoute }, { type: i0.ChangeDetectorRef }, { type: i3.AITestHarnessDialogService }, { type: i0.ViewContainerRef }, { type: i4.AIPromptManagementService }], { templateEditor: [{
3069
3068
  type: ViewChild,
3070
3069
  args: ['templateEditor']