@memberjunction/ng-dashboards 5.22.0 → 5.24.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 (245) hide show
  1. package/README.md +51 -0
  2. package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
  3. package/dist/AI/components/agents/agent-configuration.component.js +364 -362
  4. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  5. package/dist/AI/components/agents/agent-editor.component.js +2 -2
  6. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +947 -64
  7. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
  8. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +7645 -430
  9. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  10. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +285 -6
  11. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
  12. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +2454 -277
  13. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
  14. package/dist/AI/components/execution-monitoring.component.d.ts.map +1 -1
  15. package/dist/AI/components/execution-monitoring.component.js +191 -197
  16. package/dist/AI/components/execution-monitoring.component.js.map +1 -1
  17. package/dist/AI/components/models/model-management.component.js +9 -8
  18. package/dist/AI/components/models/model-management.component.js.map +1 -1
  19. package/dist/AI/components/prompts/prompt-management.component.js +305 -299
  20. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  21. package/dist/AI/components/system/system-configuration.component.js +319 -313
  22. package/dist/AI/components/system/system-configuration.component.js.map +1 -1
  23. package/dist/AI/components/vectors/vector-management-resource.component.d.ts +20 -2
  24. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  25. package/dist/AI/components/vectors/vector-management-resource.component.js +419 -232
  26. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  27. package/dist/APIKeys/api-applications-panel.component.js +10 -12
  28. package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
  29. package/dist/APIKeys/api-key-create-dialog.component.js +13 -19
  30. package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -1
  31. package/dist/APIKeys/api-key-edit-panel.component.js +12 -14
  32. package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
  33. package/dist/APIKeys/api-scopes-panel.component.js +61 -68
  34. package/dist/APIKeys/api-scopes-panel.component.js.map +1 -1
  35. package/dist/APIKeys/api-usage-panel.component.js +10 -11
  36. package/dist/APIKeys/api-usage-panel.component.js.map +1 -1
  37. package/dist/Actions/components/actions-list-view.component.js +82 -96
  38. package/dist/Actions/components/actions-list-view.component.js.map +1 -1
  39. package/dist/Actions/components/actions-overview.component.js +130 -134
  40. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  41. package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
  42. package/dist/Actions/components/categories-list-view.component.js +40 -46
  43. package/dist/Actions/components/categories-list-view.component.js.map +1 -1
  44. package/dist/Actions/components/code-management.component.js +2 -2
  45. package/dist/Actions/components/code-management.component.js.map +1 -1
  46. package/dist/Actions/components/entity-integration.component.js +2 -2
  47. package/dist/Actions/components/entity-integration.component.js.map +1 -1
  48. package/dist/Actions/components/execution-monitoring.component.js +127 -132
  49. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  50. package/dist/Actions/components/executions-list-view.component.js +2 -2
  51. package/dist/Actions/components/executions-list-view.component.js.map +1 -1
  52. package/dist/Actions/components/explorer/action-card.component.js +11 -17
  53. package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
  54. package/dist/Actions/components/explorer/action-explorer.component.js +5 -11
  55. package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
  56. package/dist/Actions/components/explorer/action-list-item.component.js +8 -10
  57. package/dist/Actions/components/explorer/action-list-item.component.js.map +1 -1
  58. package/dist/Actions/components/explorer/action-toolbar.component.js +112 -133
  59. package/dist/Actions/components/explorer/action-toolbar.component.js.map +1 -1
  60. package/dist/Actions/components/explorer/action-tree-panel.component.js +63 -83
  61. package/dist/Actions/components/explorer/action-tree-panel.component.js.map +1 -1
  62. package/dist/Actions/components/explorer/new-action-panel.component.js +17 -21
  63. package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
  64. package/dist/Actions/components/explorer/new-category-panel.component.js +17 -21
  65. package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
  66. package/dist/Actions/components/scheduled-actions.component.js +2 -2
  67. package/dist/Actions/components/scheduled-actions.component.js.map +1 -1
  68. package/dist/Actions/components/security-permissions.component.js +2 -2
  69. package/dist/Actions/components/security-permissions.component.js.map +1 -1
  70. package/dist/ComponentStudio/component-studio-dashboard.component.d.ts +13 -5
  71. package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
  72. package/dist/ComponentStudio/component-studio-dashboard.component.js +168 -145
  73. package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
  74. package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts +4 -5
  75. package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
  76. package/dist/ComponentStudio/components/artifact-load-dialog.component.js +197 -200
  77. package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
  78. package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts +5 -7
  79. package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
  80. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +142 -148
  81. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
  82. package/dist/ComponentStudio/components/browser/component-browser.component.js +153 -166
  83. package/dist/ComponentStudio/components/browser/component-browser.component.js.map +1 -1
  84. package/dist/ComponentStudio/components/editors/code-editor-panel.component.js +15 -20
  85. package/dist/ComponentStudio/components/editors/code-editor-panel.component.js.map +1 -1
  86. package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js +16 -21
  87. package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js.map +1 -1
  88. package/dist/ComponentStudio/components/editors/requirements-editor.component.js +18 -23
  89. package/dist/ComponentStudio/components/editors/requirements-editor.component.js.map +1 -1
  90. package/dist/ComponentStudio/components/editors/spec-editor.component.js +25 -30
  91. package/dist/ComponentStudio/components/editors/spec-editor.component.js.map +1 -1
  92. package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js +10 -11
  93. package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js.map +1 -1
  94. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.d.ts.map +1 -1
  95. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js +24 -35
  96. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js.map +1 -1
  97. package/dist/ComponentStudio/components/text-import-dialog.component.js +15 -17
  98. package/dist/ComponentStudio/components/text-import-dialog.component.js.map +1 -1
  99. package/dist/Credentials/components/credentials-categories-resource.component.js +7 -6
  100. package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
  101. package/dist/Credentials/components/credentials-list-resource.component.js +6 -5
  102. package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
  103. package/dist/Credentials/components/credentials-types-resource.component.js +7 -6
  104. package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
  105. package/dist/DashboardBrowser/dashboard-share-dialog.component.js +9 -9
  106. package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
  107. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  108. package/dist/DataExplorer/data-explorer-dashboard.component.js +17 -17
  109. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  110. package/dist/Home/home-dashboard.component.js +4 -4
  111. package/dist/Home/home-dashboard.component.js.map +1 -1
  112. package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
  113. package/dist/Integration/components/activity/activity.component.js +1 -0
  114. package/dist/Integration/components/activity/activity.component.js.map +1 -1
  115. package/dist/Integration/components/connections/connections.component.d.ts.map +1 -1
  116. package/dist/Integration/components/connections/connections.component.js +5 -4
  117. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  118. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.d.ts.map +1 -1
  119. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js +247 -259
  120. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js.map +1 -1
  121. package/dist/Integration/components/overview/overview.component.d.ts.map +1 -1
  122. package/dist/Integration/components/overview/overview.component.js +1 -0
  123. package/dist/Integration/components/overview/overview.component.js.map +1 -1
  124. package/dist/Integration/components/pipelines/pipelines.component.d.ts.map +1 -1
  125. package/dist/Integration/components/pipelines/pipelines.component.js +1 -0
  126. package/dist/Integration/components/pipelines/pipelines.component.js.map +1 -1
  127. package/dist/Integration/components/schedules/schedules.component.d.ts.map +1 -1
  128. package/dist/Integration/components/schedules/schedules.component.js +1 -0
  129. package/dist/Integration/components/schedules/schedules.component.js.map +1 -1
  130. package/dist/Integration/components/widgets/integration-card.component.js +7 -9
  131. package/dist/Integration/components/widgets/integration-card.component.js.map +1 -1
  132. package/dist/Integration/integration.module.d.ts +6 -10
  133. package/dist/Integration/integration.module.d.ts.map +1 -1
  134. package/dist/Integration/integration.module.js +12 -20
  135. package/dist/Integration/integration.module.js.map +1 -1
  136. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts +411 -0
  137. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts.map +1 -0
  138. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +4266 -0
  139. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -0
  140. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts +140 -0
  141. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -0
  142. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +780 -0
  143. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -0
  144. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts +8 -2
  145. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts.map +1 -1
  146. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +246 -195
  147. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
  148. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.d.ts +75 -0
  149. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.d.ts.map +1 -0
  150. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js +601 -0
  151. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js.map +1 -0
  152. package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.d.ts +93 -12
  153. package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.d.ts.map +1 -1
  154. package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.js +637 -107
  155. package/dist/KnowledgeHub/components/search/knowledge-search-resource.component.js.map +1 -1
  156. package/dist/KnowledgeHub/index.d.ts +3 -0
  157. package/dist/KnowledgeHub/index.d.ts.map +1 -1
  158. package/dist/KnowledgeHub/index.js +3 -0
  159. package/dist/KnowledgeHub/index.js.map +1 -1
  160. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  161. package/dist/Lists/components/lists-browse-resource.component.js +9 -7
  162. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  163. package/dist/Lists/components/lists-my-lists-resource.component.js +5 -4
  164. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  165. package/dist/Lists/components/lists-operations-resource.component.js +10 -9
  166. package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
  167. package/dist/MCP/components/mcp-connection-dialog.component.js +141 -132
  168. package/dist/MCP/components/mcp-connection-dialog.component.js.map +1 -1
  169. package/dist/MCP/components/mcp-log-detail-panel.component.js +4 -4
  170. package/dist/MCP/components/mcp-log-detail-panel.component.js.map +1 -1
  171. package/dist/MCP/components/mcp-server-dialog.component.js +141 -128
  172. package/dist/MCP/components/mcp-server-dialog.component.js.map +1 -1
  173. package/dist/MCP/components/mcp-test-tool-dialog.component.js +210 -218
  174. package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
  175. package/dist/MCP/mcp-dashboard.component.js +2 -2
  176. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  177. package/dist/MCP/mcp.module.d.ts +6 -9
  178. package/dist/MCP/mcp.module.d.ts.map +1 -1
  179. package/dist/MCP/mcp.module.js +20 -22
  180. package/dist/MCP/mcp.module.js.map +1 -1
  181. package/dist/Scheduling/components/scheduling-activity.component.js +5 -4
  182. package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
  183. package/dist/Scheduling/components/scheduling-jobs.component.js +6 -5
  184. package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
  185. package/dist/Scheduling/components/scheduling-overview.component.js +93 -92
  186. package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
  187. package/dist/Testing/testing-dashboard.component.js +9 -10
  188. package/dist/Testing/testing-dashboard.component.js.map +1 -1
  189. package/dist/__tests__/analytics-resource.test.d.ts +2 -0
  190. package/dist/__tests__/analytics-resource.test.d.ts.map +1 -0
  191. package/dist/__tests__/analytics-resource.test.js +181 -0
  192. package/dist/__tests__/analytics-resource.test.js.map +1 -0
  193. package/dist/__tests__/scheduling.test.d.ts +2 -0
  194. package/dist/__tests__/scheduling.test.d.ts.map +1 -0
  195. package/dist/__tests__/scheduling.test.js +205 -0
  196. package/dist/__tests__/scheduling.test.js.map +1 -0
  197. package/dist/actions-dashboards.module.d.ts +8 -13
  198. package/dist/actions-dashboards.module.d.ts.map +1 -1
  199. package/dist/actions-dashboards.module.js +6 -27
  200. package/dist/actions-dashboards.module.js.map +1 -1
  201. package/dist/ai-dashboards.module.d.ts +20 -20
  202. package/dist/ai-dashboards.module.d.ts.map +1 -1
  203. package/dist/ai-dashboards.module.js +43 -44
  204. package/dist/ai-dashboards.module.js.map +1 -1
  205. package/dist/communication-dashboards.module.d.ts +4 -8
  206. package/dist/communication-dashboards.module.d.ts.map +1 -1
  207. package/dist/communication-dashboards.module.js +0 -19
  208. package/dist/communication-dashboards.module.js.map +1 -1
  209. package/dist/component-studio-dashboards.module.d.ts +7 -11
  210. package/dist/component-studio-dashboards.module.d.ts.map +1 -1
  211. package/dist/component-studio-dashboards.module.js +22 -34
  212. package/dist/component-studio-dashboards.module.js.map +1 -1
  213. package/dist/core-dashboards.module.d.ts +12 -18
  214. package/dist/core-dashboards.module.d.ts.map +1 -1
  215. package/dist/core-dashboards.module.js +15 -31
  216. package/dist/core-dashboards.module.js.map +1 -1
  217. package/dist/credentials-dashboards.module.d.ts +5 -8
  218. package/dist/credentials-dashboards.module.d.ts.map +1 -1
  219. package/dist/credentials-dashboards.module.js +3 -19
  220. package/dist/credentials-dashboards.module.js.map +1 -1
  221. package/dist/data-explorer-dashboards.module.d.ts +7 -13
  222. package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
  223. package/dist/data-explorer-dashboards.module.js +0 -27
  224. package/dist/data-explorer-dashboards.module.js.map +1 -1
  225. package/dist/lists-dashboards.module.d.ts +5 -8
  226. package/dist/lists-dashboards.module.d.ts.map +1 -1
  227. package/dist/lists-dashboards.module.js +3 -19
  228. package/dist/lists-dashboards.module.js.map +1 -1
  229. package/dist/public-api.d.ts +2 -0
  230. package/dist/public-api.d.ts.map +1 -1
  231. package/dist/public-api.js +2 -0
  232. package/dist/public-api.js.map +1 -1
  233. package/dist/scheduling-dashboards.module.d.ts +6 -10
  234. package/dist/scheduling-dashboards.module.d.ts.map +1 -1
  235. package/dist/scheduling-dashboards.module.js +3 -23
  236. package/dist/scheduling-dashboards.module.js.map +1 -1
  237. package/dist/shared/entity-field-display.d.ts +44 -0
  238. package/dist/shared/entity-field-display.d.ts.map +1 -0
  239. package/dist/shared/entity-field-display.js +118 -0
  240. package/dist/shared/entity-field-display.js.map +1 -0
  241. package/dist/testing-dashboards.module.d.ts +7 -13
  242. package/dist/testing-dashboards.module.d.ts.map +1 -1
  243. package/dist/testing-dashboards.module.js +0 -27
  244. package/dist/testing-dashboards.module.js.map +1 -1
  245. package/package.json +48 -55
@@ -1 +1 @@
1
- {"version":3,"file":"action-tree-panel.component.js","sourceRoot":"","sources":["../../../../src/Actions/components/explorer/action-tree-panel.component.ts","../../../../src/Actions/components/explorer/action-tree-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnInit,\n OnDestroy,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n HostListener\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { MJActionCategoryEntity } from '@memberjunction/core-entities';\nimport { ActionExplorerStateService } from '../../services/action-explorer-state.service';\nimport { MJActionEntityExtended } from '@memberjunction/actions-base';\n\nexport interface CategoryTreeNode {\n category: MJActionCategoryEntity;\n children: CategoryTreeNode[];\n level: number;\n actionCount: number;\n totalActionCount: number; // Including descendants\n}\n\n@Component({\n standalone: false,\n selector: 'mj-action-tree-panel',\n templateUrl: './action-tree-panel.component.html',\n styleUrls: ['./action-tree-panel.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class ActionTreePanelComponent implements OnInit, OnDestroy {\n @Input() Categories: MJActionCategoryEntity[] = [];\n @Input() Actions: MJActionEntityExtended[] = [];\n @Output() CategorySelected = new EventEmitter<string>();\n @Output() NewCategoryClick = new EventEmitter<string | null>(); // parent ID or null for root\n @Output() EditCategoryClick = new EventEmitter<MJActionCategoryEntity>();\n\n public CategoryTree: CategoryTreeNode[] = [];\n public SelectedCategoryId = 'all';\n public ExpandedCategories: Set<string> = new Set();\n public TreeWidth = 280;\n public IsCollapsed = false;\n public IsResizing = false;\n public SearchTerm = '';\n public FilteredTree: CategoryTreeNode[] = [];\n\n private destroy$ = new Subject<void>();\n private categoryParentMap = new Map<string, string | null>();\n private categoryDescendants = new Map<string, Set<string>>();\n\n constructor(\n public StateService: ActionExplorerStateService,\n private cdr: ChangeDetectorRef\n ) {}\n\n ngOnInit(): void {\n this.subscribeToState();\n this.buildCategoryTree();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n private subscribeToState(): void {\n this.StateService.TreeWidth$.pipe(takeUntil(this.destroy$)).subscribe(width => {\n this.TreeWidth = width;\n this.cdr.markForCheck();\n });\n\n this.StateService.TreeCollapsed$.pipe(takeUntil(this.destroy$)).subscribe(collapsed => {\n this.IsCollapsed = collapsed;\n this.cdr.markForCheck();\n });\n\n this.StateService.SelectedCategoryId$.pipe(takeUntil(this.destroy$)).subscribe(id => {\n this.SelectedCategoryId = id;\n this.cdr.markForCheck();\n });\n\n this.StateService.ExpandedCategories$.pipe(takeUntil(this.destroy$)).subscribe(expanded => {\n this.ExpandedCategories = expanded;\n this.cdr.markForCheck();\n });\n }\n\n public buildCategoryTree(): void {\n const categoryMap = new Map<string, CategoryTreeNode>();\n this.categoryParentMap.clear();\n this.categoryDescendants.clear();\n\n // Build action counts per category\n const actionCounts = new Map<string, number>();\n this.Actions.forEach(action => {\n if (action.CategoryID) {\n actionCounts.set(action.CategoryID, (actionCounts.get(action.CategoryID) || 0) + 1);\n }\n });\n\n // First pass: create all nodes\n this.Categories.forEach(category => {\n categoryMap.set(category.ID, {\n category,\n children: [],\n level: 0,\n actionCount: actionCounts.get(category.ID) || 0,\n totalActionCount: 0\n });\n this.categoryParentMap.set(category.ID, category.ParentID || null);\n this.categoryDescendants.set(category.ID, new Set([category.ID]));\n });\n\n // Second pass: build tree structure\n const rootNodes: CategoryTreeNode[] = [];\n categoryMap.forEach(node => {\n const parentId = node.category.ParentID;\n if (parentId && categoryMap.has(parentId)) {\n const parent = categoryMap.get(parentId)!;\n parent.children.push(node);\n node.level = parent.level + 1;\n } else {\n rootNodes.push(node);\n }\n });\n\n // Build descendant mapping\n this.Categories.forEach(category => {\n if (category.ParentID) {\n let currentParentId: string | null = category.ParentID;\n while (currentParentId) {\n const descendants = this.categoryDescendants.get(currentParentId);\n if (descendants) {\n descendants.add(category.ID);\n }\n const parent = categoryMap.get(currentParentId);\n currentParentId = parent?.category.ParentID || null;\n }\n }\n });\n\n // Calculate total action counts (including descendants)\n const calculateTotalCounts = (node: CategoryTreeNode): number => {\n const descendants = this.categoryDescendants.get(node.category.ID);\n if (descendants) {\n let total = 0;\n descendants.forEach(descId => {\n total += actionCounts.get(descId) || 0;\n });\n node.totalActionCount = total;\n return total;\n }\n return node.actionCount;\n };\n\n // Sort children at each level and calculate totals\n const sortAndCalculate = (nodes: CategoryTreeNode[]) => {\n nodes.sort((a, b) => a.category.Name.localeCompare(b.category.Name));\n nodes.forEach(node => {\n sortAndCalculate(node.children);\n calculateTotalCounts(node);\n });\n };\n sortAndCalculate(rootNodes);\n\n this.CategoryTree = rootNodes;\n this.FilteredTree = this.SearchTerm ? this.filterTree(rootNodes, this.SearchTerm.toLowerCase()) : rootNodes;\n this.cdr.markForCheck();\n }\n\n private filterTree(nodes: CategoryTreeNode[], searchTerm: string): CategoryTreeNode[] {\n const result: CategoryTreeNode[] = [];\n for (const node of nodes) {\n const matchesSearch = node.category.Name.toLowerCase().includes(searchTerm);\n const filteredChildren = this.filterTree(node.children, searchTerm);\n\n if (matchesSearch || filteredChildren.length > 0) {\n result.push({\n ...node,\n children: filteredChildren\n });\n }\n }\n return result;\n }\n\n public onSearchChange(term: string): void {\n this.SearchTerm = term;\n this.FilteredTree = term ? this.filterTree(this.CategoryTree, term.toLowerCase()) : this.CategoryTree;\n this.cdr.markForCheck();\n }\n\n public getTotalActionCount(): number {\n return this.Actions.length;\n }\n\n public getUncategorizedCount(): number {\n return this.Actions.filter(a => !a.CategoryID).length;\n }\n\n public selectCategory(categoryId: string): void {\n this.StateService.setSelectedCategoryId(categoryId);\n this.CategorySelected.emit(categoryId);\n }\n\n public toggleExpanded(categoryId: string, event: MouseEvent): void {\n event.stopPropagation();\n this.StateService.toggleCategoryExpanded(categoryId);\n }\n\n public isExpanded(categoryId: string): boolean {\n return this.ExpandedCategories.has(categoryId);\n }\n\n public isSelected(categoryId: string): boolean {\n return this.SelectedCategoryId === categoryId;\n }\n\n public toggleCollapse(): void {\n this.StateService.toggleTreeCollapsed();\n }\n\n public onNewCategory(parentId: string | null, event: MouseEvent): void {\n event.stopPropagation();\n this.NewCategoryClick.emit(parentId);\n }\n\n public onEditCategory(category: MJActionCategoryEntity, event: MouseEvent): void {\n event.stopPropagation();\n this.EditCategoryClick.emit(category);\n }\n\n public expandAll(): void {\n this.StateService.expandAllCategories(this.Categories.map(c => c.ID));\n }\n\n public collapseAll(): void {\n this.StateService.collapseAllCategories();\n }\n\n // Resize handling\n public onResizeStart(event: MouseEvent): void {\n event.preventDefault();\n this.IsResizing = true;\n document.body.style.cursor = 'ew-resize';\n document.body.style.userSelect = 'none';\n }\n\n @HostListener('document:mousemove', ['$event'])\n onMouseMove(event: MouseEvent): void {\n if (!this.IsResizing) return;\n\n const newWidth = event.clientX;\n const clampedWidth = Math.min(\n Math.max(newWidth, this.StateService.TreeWidthMin),\n Math.min(this.StateService.TreeWidthMax, window.innerWidth - 400)\n );\n\n this.TreeWidth = clampedWidth;\n this.cdr.detectChanges();\n }\n\n @HostListener('document:mouseup')\n onMouseUp(): void {\n if (this.IsResizing) {\n this.IsResizing = false;\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n this.StateService.setTreeWidth(this.TreeWidth);\n }\n }\n\n public getCategoryDescendants(categoryId: string): Set<string> {\n return this.categoryDescendants.get(categoryId) || new Set([categoryId]);\n }\n}\n","@if (!IsCollapsed) {\n <div class=\"tree-panel\" [style.width.px]=\"TreeWidth\">\n <div class=\"tree-header\">\n <div class=\"header-content\">\n <h3><i class=\"fa-solid fa-folder-tree\"></i> Categories</h3>\n <div class=\"header-actions\">\n <button kendoButton\n [fillMode]=\"'flat'\"\n [size]=\"'small'\"\n title=\"Expand All\"\n (click)=\"expandAll()\">\n <i class=\"fa-solid fa-angles-down\"></i>\n </button>\n <button kendoButton\n [fillMode]=\"'flat'\"\n [size]=\"'small'\"\n title=\"Collapse All\"\n (click)=\"collapseAll()\">\n <i class=\"fa-solid fa-angles-up\"></i>\n </button>\n <button kendoButton\n [fillMode]=\"'flat'\"\n [size]=\"'small'\"\n title=\"Collapse Panel\"\n (click)=\"toggleCollapse()\">\n <i class=\"fa-solid fa-chevron-left\"></i>\n </button>\n </div>\n </div>\n\n <div class=\"tree-search\">\n <kendo-textbox\n [placeholder]=\"'Filter categories...'\"\n [value]=\"SearchTerm\"\n (valueChange)=\"onSearchChange($event)\"\n [size]=\"'small'\">\n <ng-template kendoTextBoxPrefixTemplate>\n <i class=\"fa-solid fa-search\"></i>\n </ng-template>\n @if (SearchTerm) {\n <ng-template kendoTextBoxSuffixTemplate>\n <button kendoButton\n [fillMode]=\"'flat'\"\n [size]=\"'small'\"\n (click)=\"onSearchChange('')\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </ng-template>\n }\n </kendo-textbox>\n </div>\n </div>\n\n <div class=\"tree-content\">\n <!-- All Categories -->\n <div class=\"tree-item root-item\"\n [class.selected]=\"isSelected('all')\"\n (click)=\"selectCategory('all')\">\n <span class=\"item-icon\">\n <i class=\"fa-solid fa-layer-group\"></i>\n </span>\n <span class=\"item-name\">All Actions</span>\n <span class=\"item-count\">{{ getTotalActionCount() }}</span>\n </div>\n\n <!-- Uncategorized -->\n @if (getUncategorizedCount() > 0) {\n <div class=\"tree-item uncategorized-item\"\n [class.selected]=\"isSelected('uncategorized')\"\n (click)=\"selectCategory('uncategorized')\">\n <span class=\"item-icon\">\n <i class=\"fa-solid fa-inbox\"></i>\n </span>\n <span class=\"item-name\">Uncategorized</span>\n <span class=\"item-count\">{{ getUncategorizedCount() }}</span>\n </div>\n }\n\n <!-- Category Tree -->\n <div class=\"tree-categories\">\n <ng-container *ngTemplateOutlet=\"categoryTreeTemplate; context: { nodes: FilteredTree }\"></ng-container>\n </div>\n\n <ng-template #categoryTreeTemplate let-nodes=\"nodes\">\n @for (node of nodes; track node.category.ID) {\n <div class=\"tree-node\" [style.--level]=\"node.level\">\n <div class=\"tree-item\"\n [class.selected]=\"isSelected(node.category.ID)\"\n [class.has-children]=\"node.children.length > 0\"\n (click)=\"selectCategory(node.category.ID)\">\n\n @if (node.children.length > 0) {\n <button class=\"expand-btn\"\n (click)=\"toggleExpanded(node.category.ID, $event)\"\n [title]=\"isExpanded(node.category.ID) ? 'Collapse' : 'Expand'\">\n <i [class]=\"isExpanded(node.category.ID) ? 'fa-solid fa-chevron-down' : 'fa-solid fa-chevron-right'\"></i>\n </button>\n } @else {\n <span class=\"expand-placeholder\"></span>\n }\n\n <span class=\"item-icon\">\n <i [class]=\"isExpanded(node.category.ID) ? 'fa-solid fa-folder-open' : 'fa-solid fa-folder'\"></i>\n </span>\n <span class=\"item-name\" [title]=\"node.category.Name\">{{ node.category.Name }}</span>\n <span class=\"item-count\" [title]=\"node.totalActionCount + ' total actions'\">{{ node.totalActionCount }}</span>\n\n <div class=\"item-actions\">\n <button kendoButton\n [fillMode]=\"'flat'\"\n [size]=\"'small'\"\n title=\"Add Subcategory\"\n (click)=\"onNewCategory(node.category.ID, $event)\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n </div>\n </div>\n\n @if (node.children.length > 0 && isExpanded(node.category.ID)) {\n <div class=\"tree-children\">\n <ng-container *ngTemplateOutlet=\"categoryTreeTemplate; context: { nodes: node.children }\"></ng-container>\n </div>\n }\n </div>\n }\n </ng-template>\n </div>\n\n <div class=\"tree-footer\">\n <button kendoButton\n [fillMode]=\"'outline'\"\n [themeColor]=\"'primary'\"\n [size]=\"'small'\"\n class=\"new-category-btn\"\n (click)=\"onNewCategory(null, $event)\">\n <i class=\"fa-solid fa-plus\"></i>\n New Category\n </button>\n </div>\n\n <!-- Resize Handle -->\n <div class=\"resize-handle\"\n (mousedown)=\"onResizeStart($event)\"\n title=\"Drag to resize\">\n </div>\n </div>\n} @else {\n <!-- Collapsed State -->\n <div class=\"tree-panel-collapsed\">\n <button kendoButton\n [fillMode]=\"'flat'\"\n title=\"Expand Category Panel\"\n (click)=\"toggleCollapse()\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n <button kendoButton\n [fillMode]=\"'flat'\"\n title=\"All Actions\"\n [class.selected]=\"isSelected('all')\"\n (click)=\"selectCategory('all')\">\n <i class=\"fa-solid fa-layer-group\"></i>\n </button>\n </div>\n}\n"]}
1
+ {"version":3,"file":"action-tree-panel.component.js","sourceRoot":"","sources":["../../../../src/Actions/components/explorer/action-tree-panel.component.ts","../../../../src/Actions/components/explorer/action-tree-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnInit,\n OnDestroy,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n HostListener\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { MJActionCategoryEntity } from '@memberjunction/core-entities';\nimport { ActionExplorerStateService } from '../../services/action-explorer-state.service';\nimport { MJActionEntityExtended } from '@memberjunction/actions-base';\n\nexport interface CategoryTreeNode {\n category: MJActionCategoryEntity;\n children: CategoryTreeNode[];\n level: number;\n actionCount: number;\n totalActionCount: number; // Including descendants\n}\n\n@Component({\n standalone: false,\n selector: 'mj-action-tree-panel',\n templateUrl: './action-tree-panel.component.html',\n styleUrls: ['./action-tree-panel.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class ActionTreePanelComponent implements OnInit, OnDestroy {\n @Input() Categories: MJActionCategoryEntity[] = [];\n @Input() Actions: MJActionEntityExtended[] = [];\n @Output() CategorySelected = new EventEmitter<string>();\n @Output() NewCategoryClick = new EventEmitter<string | null>(); // parent ID or null for root\n @Output() EditCategoryClick = new EventEmitter<MJActionCategoryEntity>();\n\n public CategoryTree: CategoryTreeNode[] = [];\n public SelectedCategoryId = 'all';\n public ExpandedCategories: Set<string> = new Set();\n public TreeWidth = 280;\n public IsCollapsed = false;\n public IsResizing = false;\n public SearchTerm = '';\n public FilteredTree: CategoryTreeNode[] = [];\n\n private destroy$ = new Subject<void>();\n private categoryParentMap = new Map<string, string | null>();\n private categoryDescendants = new Map<string, Set<string>>();\n\n constructor(\n public StateService: ActionExplorerStateService,\n private cdr: ChangeDetectorRef\n ) {}\n\n ngOnInit(): void {\n this.subscribeToState();\n this.buildCategoryTree();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n private subscribeToState(): void {\n this.StateService.TreeWidth$.pipe(takeUntil(this.destroy$)).subscribe(width => {\n this.TreeWidth = width;\n this.cdr.markForCheck();\n });\n\n this.StateService.TreeCollapsed$.pipe(takeUntil(this.destroy$)).subscribe(collapsed => {\n this.IsCollapsed = collapsed;\n this.cdr.markForCheck();\n });\n\n this.StateService.SelectedCategoryId$.pipe(takeUntil(this.destroy$)).subscribe(id => {\n this.SelectedCategoryId = id;\n this.cdr.markForCheck();\n });\n\n this.StateService.ExpandedCategories$.pipe(takeUntil(this.destroy$)).subscribe(expanded => {\n this.ExpandedCategories = expanded;\n this.cdr.markForCheck();\n });\n }\n\n public buildCategoryTree(): void {\n const categoryMap = new Map<string, CategoryTreeNode>();\n this.categoryParentMap.clear();\n this.categoryDescendants.clear();\n\n // Build action counts per category\n const actionCounts = new Map<string, number>();\n this.Actions.forEach(action => {\n if (action.CategoryID) {\n actionCounts.set(action.CategoryID, (actionCounts.get(action.CategoryID) || 0) + 1);\n }\n });\n\n // First pass: create all nodes\n this.Categories.forEach(category => {\n categoryMap.set(category.ID, {\n category,\n children: [],\n level: 0,\n actionCount: actionCounts.get(category.ID) || 0,\n totalActionCount: 0\n });\n this.categoryParentMap.set(category.ID, category.ParentID || null);\n this.categoryDescendants.set(category.ID, new Set([category.ID]));\n });\n\n // Second pass: build tree structure\n const rootNodes: CategoryTreeNode[] = [];\n categoryMap.forEach(node => {\n const parentId = node.category.ParentID;\n if (parentId && categoryMap.has(parentId)) {\n const parent = categoryMap.get(parentId)!;\n parent.children.push(node);\n node.level = parent.level + 1;\n } else {\n rootNodes.push(node);\n }\n });\n\n // Build descendant mapping\n this.Categories.forEach(category => {\n if (category.ParentID) {\n let currentParentId: string | null = category.ParentID;\n while (currentParentId) {\n const descendants = this.categoryDescendants.get(currentParentId);\n if (descendants) {\n descendants.add(category.ID);\n }\n const parent = categoryMap.get(currentParentId);\n currentParentId = parent?.category.ParentID || null;\n }\n }\n });\n\n // Calculate total action counts (including descendants)\n const calculateTotalCounts = (node: CategoryTreeNode): number => {\n const descendants = this.categoryDescendants.get(node.category.ID);\n if (descendants) {\n let total = 0;\n descendants.forEach(descId => {\n total += actionCounts.get(descId) || 0;\n });\n node.totalActionCount = total;\n return total;\n }\n return node.actionCount;\n };\n\n // Sort children at each level and calculate totals\n const sortAndCalculate = (nodes: CategoryTreeNode[]) => {\n nodes.sort((a, b) => a.category.Name.localeCompare(b.category.Name));\n nodes.forEach(node => {\n sortAndCalculate(node.children);\n calculateTotalCounts(node);\n });\n };\n sortAndCalculate(rootNodes);\n\n this.CategoryTree = rootNodes;\n this.FilteredTree = this.SearchTerm ? this.filterTree(rootNodes, this.SearchTerm.toLowerCase()) : rootNodes;\n this.cdr.markForCheck();\n }\n\n private filterTree(nodes: CategoryTreeNode[], searchTerm: string): CategoryTreeNode[] {\n const result: CategoryTreeNode[] = [];\n for (const node of nodes) {\n const matchesSearch = node.category.Name.toLowerCase().includes(searchTerm);\n const filteredChildren = this.filterTree(node.children, searchTerm);\n\n if (matchesSearch || filteredChildren.length > 0) {\n result.push({\n ...node,\n children: filteredChildren\n });\n }\n }\n return result;\n }\n\n public onSearchChange(term: string): void {\n this.SearchTerm = term;\n this.FilteredTree = term ? this.filterTree(this.CategoryTree, term.toLowerCase()) : this.CategoryTree;\n this.cdr.markForCheck();\n }\n\n public getTotalActionCount(): number {\n return this.Actions.length;\n }\n\n public getUncategorizedCount(): number {\n return this.Actions.filter(a => !a.CategoryID).length;\n }\n\n public selectCategory(categoryId: string): void {\n this.StateService.setSelectedCategoryId(categoryId);\n this.CategorySelected.emit(categoryId);\n }\n\n public toggleExpanded(categoryId: string, event: MouseEvent): void {\n event.stopPropagation();\n this.StateService.toggleCategoryExpanded(categoryId);\n }\n\n public isExpanded(categoryId: string): boolean {\n return this.ExpandedCategories.has(categoryId);\n }\n\n public isSelected(categoryId: string): boolean {\n return this.SelectedCategoryId === categoryId;\n }\n\n public toggleCollapse(): void {\n this.StateService.toggleTreeCollapsed();\n }\n\n public onNewCategory(parentId: string | null, event: MouseEvent): void {\n event.stopPropagation();\n this.NewCategoryClick.emit(parentId);\n }\n\n public onEditCategory(category: MJActionCategoryEntity, event: MouseEvent): void {\n event.stopPropagation();\n this.EditCategoryClick.emit(category);\n }\n\n public expandAll(): void {\n this.StateService.expandAllCategories(this.Categories.map(c => c.ID));\n }\n\n public collapseAll(): void {\n this.StateService.collapseAllCategories();\n }\n\n // Resize handling\n public onResizeStart(event: MouseEvent): void {\n event.preventDefault();\n this.IsResizing = true;\n document.body.style.cursor = 'ew-resize';\n document.body.style.userSelect = 'none';\n }\n\n @HostListener('document:mousemove', ['$event'])\n onMouseMove(event: MouseEvent): void {\n if (!this.IsResizing) return;\n\n const newWidth = event.clientX;\n const clampedWidth = Math.min(\n Math.max(newWidth, this.StateService.TreeWidthMin),\n Math.min(this.StateService.TreeWidthMax, window.innerWidth - 400)\n );\n\n this.TreeWidth = clampedWidth;\n this.cdr.detectChanges();\n }\n\n @HostListener('document:mouseup')\n onMouseUp(): void {\n if (this.IsResizing) {\n this.IsResizing = false;\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n this.StateService.setTreeWidth(this.TreeWidth);\n }\n }\n\n public getCategoryDescendants(categoryId: string): Set<string> {\n return this.categoryDescendants.get(categoryId) || new Set([categoryId]);\n }\n}\n","@if (!IsCollapsed) {\n <div class=\"tree-panel\" [style.width.px]=\"TreeWidth\">\n <div class=\"tree-header\">\n <div class=\"header-content\">\n <h3><i class=\"fa-solid fa-folder-tree\"></i> Categories</h3>\n <div class=\"header-actions\">\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n title=\"Expand All\"\n (click)=\"expandAll()\">\n <i class=\"fa-solid fa-angles-down\"></i>\n </button>\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n title=\"Collapse All\"\n (click)=\"collapseAll()\">\n <i class=\"fa-solid fa-angles-up\"></i>\n </button>\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n title=\"Collapse Panel\"\n (click)=\"toggleCollapse()\">\n <i class=\"fa-solid fa-chevron-left\"></i>\n </button>\n </div>\n </div>\n\n <div class=\"tree-search\">\n <div class=\"search-input-wrapper\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input type=\"text\" class=\"mj-input\"\n placeholder=\"Filter categories...\"\n [value]=\"SearchTerm\"\n (input)=\"onSearchChange($any($event.target).value)\" />\n @if (SearchTerm) {\n <button mjButton variant=\"flat\" size=\"sm\" class=\"search-clear\"\n (click)=\"onSearchChange('')\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n </div>\n </div>\n\n <div class=\"tree-content\">\n <!-- All Categories -->\n <div class=\"tree-item root-item\"\n [class.selected]=\"isSelected('all')\"\n (click)=\"selectCategory('all')\">\n <span class=\"item-icon\">\n <i class=\"fa-solid fa-layer-group\"></i>\n </span>\n <span class=\"item-name\">All Actions</span>\n <span class=\"item-count\">{{ getTotalActionCount() }}</span>\n </div>\n\n <!-- Uncategorized -->\n @if (getUncategorizedCount() > 0) {\n <div class=\"tree-item uncategorized-item\"\n [class.selected]=\"isSelected('uncategorized')\"\n (click)=\"selectCategory('uncategorized')\">\n <span class=\"item-icon\">\n <i class=\"fa-solid fa-inbox\"></i>\n </span>\n <span class=\"item-name\">Uncategorized</span>\n <span class=\"item-count\">{{ getUncategorizedCount() }}</span>\n </div>\n }\n\n <!-- Category Tree -->\n <div class=\"tree-categories\">\n <ng-container *ngTemplateOutlet=\"categoryTreeTemplate; context: { nodes: FilteredTree }\"></ng-container>\n </div>\n\n <ng-template #categoryTreeTemplate let-nodes=\"nodes\">\n @for (node of nodes; track node.category.ID) {\n <div class=\"tree-node\" [style.--level]=\"node.level\">\n <div class=\"tree-item\"\n [class.selected]=\"isSelected(node.category.ID)\"\n [class.has-children]=\"node.children.length > 0\"\n (click)=\"selectCategory(node.category.ID)\">\n\n @if (node.children.length > 0) {\n <button class=\"expand-btn\"\n (click)=\"toggleExpanded(node.category.ID, $event)\"\n [title]=\"isExpanded(node.category.ID) ? 'Collapse' : 'Expand'\">\n <i [class]=\"isExpanded(node.category.ID) ? 'fa-solid fa-chevron-down' : 'fa-solid fa-chevron-right'\"></i>\n </button>\n } @else {\n <span class=\"expand-placeholder\"></span>\n }\n\n <span class=\"item-icon\">\n <i [class]=\"isExpanded(node.category.ID) ? 'fa-solid fa-folder-open' : 'fa-solid fa-folder'\"></i>\n </span>\n <span class=\"item-name\" [title]=\"node.category.Name\">{{ node.category.Name }}</span>\n <span class=\"item-count\" [title]=\"node.totalActionCount + ' total actions'\">{{ node.totalActionCount }}</span>\n\n <div class=\"item-actions\">\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n title=\"Add Subcategory\"\n (click)=\"onNewCategory(node.category.ID, $event)\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n </div>\n </div>\n\n @if (node.children.length > 0 && isExpanded(node.category.ID)) {\n <div class=\"tree-children\">\n <ng-container *ngTemplateOutlet=\"categoryTreeTemplate; context: { nodes: node.children }\"></ng-container>\n </div>\n }\n </div>\n }\n </ng-template>\n </div>\n\n <div class=\"tree-footer\">\n <button mjButton\n variant=\"primary\"\n size=\"sm\"\n class=\"new-category-btn\"\n (click)=\"onNewCategory(null, $event)\">\n <i class=\"fa-solid fa-plus\"></i>\n New Category\n </button>\n </div>\n\n <!-- Resize Handle -->\n <div class=\"resize-handle\"\n (mousedown)=\"onResizeStart($event)\"\n title=\"Drag to resize\">\n </div>\n </div>\n} @else {\n <!-- Collapsed State -->\n <div class=\"tree-panel-collapsed\">\n <button mjButton\n variant=\"flat\"\n title=\"Expand Category Panel\"\n (click)=\"toggleCollapse()\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n <button mjButton\n variant=\"flat\"\n title=\"All Actions\"\n [class.selected]=\"isSelected('all')\"\n (click)=\"selectCategory('all')\">\n <i class=\"fa-solid fa-layer-group\"></i>\n </button>\n </div>\n}\n"]}
@@ -8,9 +8,7 @@ import * as i0 from "@angular/core";
8
8
  import * as i1 from "../../services/action-explorer-state.service";
9
9
  import * as i2 from "@memberjunction/ng-shared";
10
10
  import * as i3 from "@angular/forms";
11
- import * as i4 from "@progress/kendo-angular-buttons";
12
- import * as i5 from "@progress/kendo-angular-dropdowns";
13
- import * as i6 from "@progress/kendo-angular-inputs";
11
+ import * as i4 from "@memberjunction/ng-ui-components";
14
12
  const _forTrack0 = ($index, $item) => $item.value;
15
13
  function NewActionPanelComponent_Conditional_0_Conditional_9_Template(rf, ctx) { if (rf & 1) {
16
14
  i0.ɵɵelementStart(0, "div", 8);
@@ -102,22 +100,22 @@ function NewActionPanelComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
102
100
  i0.ɵɵelementStart(16, "div", 9)(17, "label", 13);
103
101
  i0.ɵɵtext(18, " Action Name ");
104
102
  i0.ɵɵelementEnd();
105
- i0.ɵɵelementStart(19, "kendo-textbox", 14);
106
- i0.ɵɵtwoWayListener("ngModelChange", function NewActionPanelComponent_Conditional_0_Template_kendo_textbox_ngModelChange_19_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.Name, $event) || (ctx_r1.Name = $event); return i0.ɵɵresetView($event); });
103
+ i0.ɵɵelementStart(19, "input", 14);
104
+ i0.ɵɵtwoWayListener("ngModelChange", function NewActionPanelComponent_Conditional_0_Template_input_ngModelChange_19_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.Name, $event) || (ctx_r1.Name = $event); return i0.ɵɵresetView($event); });
107
105
  i0.ɵɵelementEnd();
108
106
  i0.ɵɵconditionalCreate(20, NewActionPanelComponent_Conditional_0_Conditional_20_Template, 2, 1, "span", 15);
109
107
  i0.ɵɵelementEnd();
110
108
  i0.ɵɵelementStart(21, "div", 9)(22, "label", 16);
111
109
  i0.ɵɵtext(23, " Description ");
112
110
  i0.ɵɵelementEnd();
113
- i0.ɵɵelementStart(24, "kendo-textarea", 17);
114
- i0.ɵɵtwoWayListener("ngModelChange", function NewActionPanelComponent_Conditional_0_Template_kendo_textarea_ngModelChange_24_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.Description, $event) || (ctx_r1.Description = $event); return i0.ɵɵresetView($event); });
111
+ i0.ɵɵelementStart(24, "textarea", 17);
112
+ i0.ɵɵtwoWayListener("ngModelChange", function NewActionPanelComponent_Conditional_0_Template_textarea_ngModelChange_24_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.Description, $event) || (ctx_r1.Description = $event); return i0.ɵɵresetView($event); });
115
113
  i0.ɵɵelementEnd()();
116
114
  i0.ɵɵelementStart(25, "div", 9)(26, "label", 18);
117
115
  i0.ɵɵtext(27, " Category ");
118
116
  i0.ɵɵelementEnd();
119
- i0.ɵɵelementStart(28, "kendo-dropdownlist", 19);
120
- i0.ɵɵtwoWayListener("ngModelChange", function NewActionPanelComponent_Conditional_0_Template_kendo_dropdownlist_ngModelChange_28_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.CategoryID, $event) || (ctx_r1.CategoryID = $event); return i0.ɵɵresetView($event); });
117
+ i0.ɵɵelementStart(28, "mj-dropdown", 19);
118
+ i0.ɵɵtwoWayListener("ngModelChange", function NewActionPanelComponent_Conditional_0_Template_mj_dropdown_ngModelChange_28_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.CategoryID, $event) || (ctx_r1.CategoryID = $event); return i0.ɵɵresetView($event); });
121
119
  i0.ɵɵelementEnd();
122
120
  i0.ɵɵconditionalCreate(29, NewActionPanelComponent_Conditional_0_Conditional_29_Template, 2, 1, "span", 15);
123
121
  i0.ɵɵelementEnd();
@@ -138,33 +136,31 @@ function NewActionPanelComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
138
136
  const ctx_r1 = i0.ɵɵnextContext();
139
137
  i0.ɵɵadvance();
140
138
  i0.ɵɵproperty("@slideIn", undefined);
141
- i0.ɵɵadvance(5);
142
- i0.ɵɵproperty("fillMode", "flat");
143
- i0.ɵɵadvance(3);
139
+ i0.ɵɵadvance(8);
144
140
  i0.ɵɵconditional(ctx_r1.Errors["general"] ? 9 : -1);
145
141
  i0.ɵɵadvance(5);
146
142
  i0.ɵɵrepeater(ctx_r1.TypeOptions);
147
143
  i0.ɵɵadvance(5);
148
144
  i0.ɵɵclassProp("invalid", ctx_r1.Errors["name"]);
149
145
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.Name);
150
- i0.ɵɵproperty("placeholder", "Enter action name")("maxlength", 425);
146
+ i0.ɵɵproperty("maxlength", 425);
151
147
  i0.ɵɵadvance();
152
148
  i0.ɵɵconditional(ctx_r1.Errors["name"] ? 20 : -1);
153
149
  i0.ɵɵadvance(4);
154
150
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.Description);
155
- i0.ɵɵproperty("placeholder", "Describe what this action does")("rows", 3);
151
+ i0.ɵɵproperty("rows", 3);
156
152
  i0.ɵɵadvance(4);
157
153
  i0.ɵɵclassProp("invalid", ctx_r1.Errors["category"]);
158
154
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.CategoryID);
159
- i0.ɵɵproperty("data", ctx_r1.getCategoryOptions())("valuePrimitive", true);
155
+ i0.ɵɵproperty("Data", ctx_r1.getCategoryOptions())("ValuePrimitive", true);
160
156
  i0.ɵɵadvance();
161
157
  i0.ɵɵconditional(ctx_r1.Errors["category"] ? 29 : -1);
162
158
  i0.ɵɵadvance(6);
163
- i0.ɵɵproperty("fillMode", "solid")("themeColor", "primary")("disabled", ctx_r1.IsSaving);
159
+ i0.ɵɵproperty("disabled", ctx_r1.IsSaving);
164
160
  i0.ɵɵadvance();
165
161
  i0.ɵɵconditional(ctx_r1.IsSaving ? 36 : 37);
166
162
  i0.ɵɵadvance(2);
167
- i0.ɵɵproperty("fillMode", "outline")("disabled", ctx_r1.IsSaving);
163
+ i0.ɵɵproperty("disabled", ctx_r1.IsSaving);
168
164
  } }
169
165
  export class NewActionPanelComponent {
170
166
  StateService;
@@ -318,11 +314,11 @@ export class NewActionPanelComponent {
318
314
  return path.join(' / ');
319
315
  }
320
316
  static ɵfac = function NewActionPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || NewActionPanelComponent)(i0.ɵɵdirectiveInject(i1.ActionExplorerStateService), i0.ɵɵdirectiveInject(i2.NavigationService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
321
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: NewActionPanelComponent, selectors: [["mj-new-action-panel"]], inputs: { Categories: "Categories", PreselectedCategoryId: "PreselectedCategoryId" }, outputs: { ActionCreated: "ActionCreated", Close: "Close" }, standalone: false, decls: 1, vars: 1, consts: [[1, "panel-backdrop"], [1, "panel-backdrop", 3, "click"], [1, "slide-panel"], [1, "panel-header"], [1, "fa-solid", "fa-bolt"], ["kendoButton", "", 3, "click", "fillMode"], [1, "fa-solid", "fa-times"], [1, "panel-content"], [1, "error-banner"], [1, "form-group"], [1, "form-label", "required"], [1, "type-selector"], [1, "type-option", 3, "selected"], ["for", "actionName", 1, "form-label", "required"], ["id", "actionName", 3, "ngModelChange", "ngModel", "placeholder", "maxlength"], [1, "error-text"], ["for", "actionDescription", 1, "form-label"], ["id", "actionDescription", 3, "ngModelChange", "ngModel", "placeholder", "rows"], ["for", "actionCategory", 1, "form-label", "required"], ["id", "actionCategory", "textField", "text", "valueField", "value", 3, "ngModelChange", "ngModel", "data", "valuePrimitive"], [1, "info-box"], [1, "fa-solid", "fa-info-circle"], [1, "panel-footer"], ["kendoButton", "", 3, "click", "fillMode", "themeColor", "disabled"], ["kendoButton", "", 3, "click", "fillMode", "disabled"], [1, "fa-solid", "fa-exclamation-circle"], [1, "type-option", 3, "click"], [1, "type-icon"], [1, "type-info"], [1, "type-label"], [1, "type-description"], [1, "fa-solid", "fa-check", "check-icon"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-check"]], template: function NewActionPanelComponent_Template(rf, ctx) { if (rf & 1) {
322
- i0.ɵɵconditionalCreate(0, NewActionPanelComponent_Conditional_0_Template, 40, 24, "div", 0);
317
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: NewActionPanelComponent, selectors: [["mj-new-action-panel"]], inputs: { Categories: "Categories", PreselectedCategoryId: "PreselectedCategoryId" }, outputs: { ActionCreated: "ActionCreated", Close: "Close" }, standalone: false, decls: 1, vars: 1, consts: [[1, "panel-backdrop"], [1, "panel-backdrop", 3, "click"], [1, "slide-panel"], [1, "panel-header"], [1, "fa-solid", "fa-bolt"], ["mjButton", "", "variant", "flat", 3, "click"], [1, "fa-solid", "fa-times"], [1, "panel-content"], [1, "error-banner"], [1, "form-group"], [1, "form-label", "required"], [1, "type-selector"], [1, "type-option", 3, "selected"], ["for", "actionName", 1, "form-label", "required"], ["type", "text", "id", "actionName", "placeholder", "Enter action name", 1, "mj-input", 3, "ngModelChange", "ngModel", "maxlength"], [1, "error-text"], ["for", "actionDescription", 1, "form-label"], ["id", "actionDescription", "placeholder", "Describe what this action does", 1, "mj-textarea", 3, "ngModelChange", "ngModel", "rows"], ["for", "actionCategory", 1, "form-label", "required"], ["TextField", "text", "ValueField", "value", 3, "ngModelChange", "ngModel", "Data", "ValuePrimitive"], [1, "info-box"], [1, "fa-solid", "fa-info-circle"], [1, "panel-footer"], ["mjButton", "", "variant", "primary", 3, "click", "disabled"], ["mjButton", "", "variant", "outline", 3, "click", "disabled"], [1, "fa-solid", "fa-exclamation-circle"], [1, "type-option", 3, "click"], [1, "type-icon"], [1, "type-info"], [1, "type-label"], [1, "type-description"], [1, "fa-solid", "fa-check", "check-icon"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-check"]], template: function NewActionPanelComponent_Template(rf, ctx) { if (rf & 1) {
318
+ i0.ɵɵconditionalCreate(0, NewActionPanelComponent_Conditional_0_Template, 40, 18, "div", 0);
323
319
  } if (rf & 2) {
324
320
  i0.ɵɵconditional(ctx.IsOpen ? 0 : -1);
325
- } }, dependencies: [i3.NgControlStatus, i3.MaxLengthValidator, i3.NgModel, i4.ButtonComponent, i5.DropDownListComponent, i6.TextBoxComponent, i6.TextAreaComponent], styles: [".panel-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 1000;\n display: flex;\n justify-content: flex-end;\n}\n\n.slide-panel[_ngcontent-%COMP%] {\n width: 500px;\n max-width: 100%;\n height: 100%;\n background: var(--mj-bg-surface-card);\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 20px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--mj-text-primary);\n}\n\n.panel-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n.error-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n border-radius: 8px;\n margin-bottom: 20px;\n font-size: 14px;\n}\n\n.error-banner[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.form-group[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n.form-label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-label.required[_ngcontent-%COMP%]::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n\n\n.type-selector[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.type-option[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 14px 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface-card);\n cursor: pointer;\n transition: all 0.2s ease;\n text-align: left;\n}\n\n.type-option[_ngcontent-%COMP%]:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n background: var(--mj-bg-surface-hover);\n}\n\n.type-option.selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.type-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n border-radius: 10px;\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n.type-option.selected[_ngcontent-%COMP%] .type-icon[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.type-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 18px;\n color: var(--mj-text-muted);\n}\n\n.type-option.selected[_ngcontent-%COMP%] .type-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-inverse);\n}\n\n.type-info[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.type-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.type-description[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.check-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n\n\n.form-group[_ngcontent-%COMP%] kendo-textbox[_ngcontent-%COMP%], \n.form-group[_ngcontent-%COMP%] kendo-textarea[_ngcontent-%COMP%], \n.form-group[_ngcontent-%COMP%] kendo-dropdownlist[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.form-group[_ngcontent-%COMP%] kendo-textbox.invalid[_ngcontent-%COMP%], \n.form-group[_ngcontent-%COMP%] kendo-textarea.invalid[_ngcontent-%COMP%], \n.form-group[_ngcontent-%COMP%] kendo-dropdownlist.invalid[_ngcontent-%COMP%] {\n border-color: var(--mj-status-error);\n}\n\n.error-text[_ngcontent-%COMP%] {\n display: block;\n margin-top: 4px;\n font-size: 12px;\n color: var(--mj-status-error);\n}\n\n\n\n.info-box[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 14px 16px;\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n border-radius: 8px;\n margin-top: 24px;\n}\n\n.info-box[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-info);\n font-size: 16px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.info-box[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-primary);\n line-height: 1.5;\n}\n\n.panel-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 16px 24px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n\n.panel-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n\n\n@media (max-width: 520px) {\n .slide-panel[_ngcontent-%COMP%] {\n width: 100%;\n }\n}"], data: { animation: [
321
+ } }, dependencies: [i3.DefaultValueAccessor, i3.NgControlStatus, i3.MaxLengthValidator, i3.NgModel, i4.MJButtonDirective, i4.MJDropdownComponent], styles: [".panel-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 1000;\n display: flex;\n justify-content: flex-end;\n}\n\n.slide-panel[_ngcontent-%COMP%] {\n width: 500px;\n max-width: 100%;\n height: 100%;\n background: var(--mj-bg-surface-card);\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 20px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--mj-text-primary);\n}\n\n.panel-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n.error-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n border-radius: 8px;\n margin-bottom: 20px;\n font-size: 14px;\n}\n\n.error-banner[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.form-group[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n.form-label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-label.required[_ngcontent-%COMP%]::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n\n\n.type-selector[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.type-option[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 14px 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface-card);\n cursor: pointer;\n transition: all 0.2s ease;\n text-align: left;\n}\n\n.type-option[_ngcontent-%COMP%]:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n background: var(--mj-bg-surface-hover);\n}\n\n.type-option.selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.type-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n border-radius: 10px;\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n.type-option.selected[_ngcontent-%COMP%] .type-icon[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.type-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 18px;\n color: var(--mj-text-muted);\n}\n\n.type-option.selected[_ngcontent-%COMP%] .type-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-inverse);\n}\n\n.type-info[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.type-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.type-description[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.check-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n.error-text[_ngcontent-%COMP%] {\n display: block;\n margin-top: 4px;\n font-size: 12px;\n color: var(--mj-status-error);\n}\n\n\n\n.info-box[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 14px 16px;\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n border-radius: 8px;\n margin-top: 24px;\n}\n\n.info-box[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-info);\n font-size: 16px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.info-box[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-primary);\n line-height: 1.5;\n}\n\n.panel-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 16px 24px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n\n.panel-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n\n\n@media (max-width: 520px) {\n .slide-panel[_ngcontent-%COMP%] {\n width: 100%;\n }\n}"], data: { animation: [
326
322
  trigger('slideIn', [
327
323
  transition(':enter', [
328
324
  style({ transform: 'translateX(100%)', opacity: 0 }),
@@ -346,7 +342,7 @@ export class NewActionPanelComponent {
346
342
  animate('200ms ease-in', style({ transform: 'translateX(100%)', opacity: 0 }))
347
343
  ])
348
344
  ])
349
- ], template: "@if (IsOpen) {\n <div class=\"panel-backdrop\" (click)=\"onBackdropClick($event)\">\n <div class=\"slide-panel\" @slideIn>\n <div class=\"panel-header\">\n <h2>\n <i class=\"fa-solid fa-bolt\"></i>\n New Action\n </h2>\n <button kendoButton\n [fillMode]=\"'flat'\"\n (click)=\"onClose()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"panel-content\">\n @if (Errors['general']) {\n <div class=\"error-banner\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n {{ Errors['general'] }}\n </div>\n }\n\n <!-- Action Type Selection -->\n <div class=\"form-group\">\n <label class=\"form-label required\">Action Type</label>\n <div class=\"type-selector\">\n @for (option of TypeOptions; track option.value) {\n <button class=\"type-option\"\n [class.selected]=\"Type === option.value\"\n (click)=\"selectType(option.value)\">\n <div class=\"type-icon\">\n <i [class]=\"option.icon\"></i>\n </div>\n <div class=\"type-info\">\n <span class=\"type-label\">{{ option.label }}</span>\n <span class=\"type-description\">{{ option.description }}</span>\n </div>\n @if (Type === option.value) {\n <i class=\"fa-solid fa-check check-icon\"></i>\n }\n </button>\n }\n </div>\n </div>\n\n <div class=\"form-group\">\n <label for=\"actionName\" class=\"form-label required\">\n Action Name\n </label>\n <kendo-textbox\n id=\"actionName\"\n [(ngModel)]=\"Name\"\n [placeholder]=\"'Enter action name'\"\n [maxlength]=\"425\"\n [class.invalid]=\"Errors['name']\">\n </kendo-textbox>\n @if (Errors['name']) {\n <span class=\"error-text\">{{ Errors['name'] }}</span>\n }\n </div>\n\n <div class=\"form-group\">\n <label for=\"actionDescription\" class=\"form-label\">\n Description\n </label>\n <kendo-textarea\n id=\"actionDescription\"\n [(ngModel)]=\"Description\"\n [placeholder]=\"'Describe what this action does'\"\n [rows]=\"3\">\n </kendo-textarea>\n </div>\n\n <div class=\"form-group\">\n <label for=\"actionCategory\" class=\"form-label required\">\n Category\n </label>\n <kendo-dropdownlist\n id=\"actionCategory\"\n [(ngModel)]=\"CategoryID\"\n [data]=\"getCategoryOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n [class.invalid]=\"Errors['category']\">\n </kendo-dropdownlist>\n @if (Errors['category']) {\n <span class=\"error-text\">{{ Errors['category'] }}</span>\n }\n </div>\n\n <div class=\"info-box\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <p>\n After creating the action, you'll be taken to the full action editor\n where you can configure parameters, code, and other settings.\n </p>\n </div>\n </div>\n\n <div class=\"panel-footer\">\n <button kendoButton\n [fillMode]=\"'solid'\"\n [themeColor]=\"'primary'\"\n [disabled]=\"IsSaving\"\n (click)=\"onSave()\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Creating...\n } @else {\n <i class=\"fa-solid fa-check\"></i>\n Create Action\n }\n </button>\n <button kendoButton\n [fillMode]=\"'outline'\"\n [disabled]=\"IsSaving\"\n (click)=\"onClose()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n}\n", styles: [".panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 1000;\n display: flex;\n justify-content: flex-end;\n}\n\n.slide-panel {\n width: 500px;\n max-width: 100%;\n height: 100%;\n background: var(--mj-bg-surface-card);\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n}\n\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 20px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-header h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--mj-text-primary);\n}\n\n.panel-header h2 i {\n color: var(--mj-brand-primary);\n}\n\n.panel-content {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n.error-banner {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n border-radius: 8px;\n margin-bottom: 20px;\n font-size: 14px;\n}\n\n.error-banner i {\n font-size: 16px;\n}\n\n.form-group {\n margin-bottom: 20px;\n}\n\n.form-label {\n display: block;\n margin-bottom: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-label.required::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n/* Type Selector */\n.type-selector {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.type-option {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 14px 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface-card);\n cursor: pointer;\n transition: all 0.2s ease;\n text-align: left;\n}\n\n.type-option:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n background: var(--mj-bg-surface-hover);\n}\n\n.type-option.selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.type-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n border-radius: 10px;\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n.type-option.selected .type-icon {\n background: var(--mj-brand-primary);\n}\n\n.type-icon i {\n font-size: 18px;\n color: var(--mj-text-muted);\n}\n\n.type-option.selected .type-icon i {\n color: var(--mj-text-inverse);\n}\n\n.type-info {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.type-label {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.type-description {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.check-icon {\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n/* Form Fields */\n.form-group kendo-textbox,\n.form-group kendo-textarea,\n.form-group kendo-dropdownlist {\n width: 100%;\n}\n\n.form-group kendo-textbox.invalid,\n.form-group kendo-textarea.invalid,\n.form-group kendo-dropdownlist.invalid {\n border-color: var(--mj-status-error);\n}\n\n.error-text {\n display: block;\n margin-top: 4px;\n font-size: 12px;\n color: var(--mj-status-error);\n}\n\n/* Info Box */\n.info-box {\n display: flex;\n gap: 12px;\n padding: 14px 16px;\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n border-radius: 8px;\n margin-top: 24px;\n}\n\n.info-box i {\n color: var(--mj-status-info);\n font-size: 16px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.info-box p {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-primary);\n line-height: 1.5;\n}\n\n.panel-footer {\n display: flex;\n gap: 12px;\n padding: 16px 24px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n\n.panel-footer button {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* Mobile */\n@media (max-width: 520px) {\n .slide-panel {\n width: 100%;\n }\n}\n"] }]
345
+ ], template: "@if (IsOpen) {\n <div class=\"panel-backdrop\" (click)=\"onBackdropClick($event)\">\n <div class=\"slide-panel\" @slideIn>\n <div class=\"panel-header\">\n <h2>\n <i class=\"fa-solid fa-bolt\"></i>\n New Action\n </h2>\n <button mjButton\n variant=\"flat\"\n (click)=\"onClose()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"panel-content\">\n @if (Errors['general']) {\n <div class=\"error-banner\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n {{ Errors['general'] }}\n </div>\n }\n\n <!-- Action Type Selection -->\n <div class=\"form-group\">\n <label class=\"form-label required\">Action Type</label>\n <div class=\"type-selector\">\n @for (option of TypeOptions; track option.value) {\n <button class=\"type-option\"\n [class.selected]=\"Type === option.value\"\n (click)=\"selectType(option.value)\">\n <div class=\"type-icon\">\n <i [class]=\"option.icon\"></i>\n </div>\n <div class=\"type-info\">\n <span class=\"type-label\">{{ option.label }}</span>\n <span class=\"type-description\">{{ option.description }}</span>\n </div>\n @if (Type === option.value) {\n <i class=\"fa-solid fa-check check-icon\"></i>\n }\n </button>\n }\n </div>\n </div>\n\n <div class=\"form-group\">\n <label for=\"actionName\" class=\"form-label required\">\n Action Name\n </label>\n <input type=\"text\" class=\"mj-input\"\n id=\"actionName\"\n [(ngModel)]=\"Name\"\n placeholder=\"Enter action name\"\n [maxlength]=\"425\"\n [class.invalid]=\"Errors['name']\" />\n @if (Errors['name']) {\n <span class=\"error-text\">{{ Errors['name'] }}</span>\n }\n </div>\n\n <div class=\"form-group\">\n <label for=\"actionDescription\" class=\"form-label\">\n Description\n </label>\n <textarea class=\"mj-textarea\"\n id=\"actionDescription\"\n [(ngModel)]=\"Description\"\n placeholder=\"Describe what this action does\"\n [rows]=\"3\"></textarea>\n </div>\n\n <div class=\"form-group\">\n <label for=\"actionCategory\" class=\"form-label required\">\n Category\n </label>\n <mj-dropdown\n [(ngModel)]=\"CategoryID\"\n [Data]=\"getCategoryOptions()\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n [class.invalid]=\"Errors['category']\">\n </mj-dropdown>\n @if (Errors['category']) {\n <span class=\"error-text\">{{ Errors['category'] }}</span>\n }\n </div>\n\n <div class=\"info-box\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <p>\n After creating the action, you'll be taken to the full action editor\n where you can configure parameters, code, and other settings.\n </p>\n </div>\n </div>\n\n <div class=\"panel-footer\">\n <button mjButton\n variant=\"primary\"\n [disabled]=\"IsSaving\"\n (click)=\"onSave()\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Creating...\n } @else {\n <i class=\"fa-solid fa-check\"></i>\n Create Action\n }\n </button>\n <button mjButton\n variant=\"outline\"\n [disabled]=\"IsSaving\"\n (click)=\"onClose()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n}\n", styles: [".panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 1000;\n display: flex;\n justify-content: flex-end;\n}\n\n.slide-panel {\n width: 500px;\n max-width: 100%;\n height: 100%;\n background: var(--mj-bg-surface-card);\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n}\n\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 20px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-header h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--mj-text-primary);\n}\n\n.panel-header h2 i {\n color: var(--mj-brand-primary);\n}\n\n.panel-content {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n.error-banner {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n border-radius: 8px;\n margin-bottom: 20px;\n font-size: 14px;\n}\n\n.error-banner i {\n font-size: 16px;\n}\n\n.form-group {\n margin-bottom: 20px;\n}\n\n.form-label {\n display: block;\n margin-bottom: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-label.required::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n/* Type Selector */\n.type-selector {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.type-option {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 14px 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface-card);\n cursor: pointer;\n transition: all 0.2s ease;\n text-align: left;\n}\n\n.type-option:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n background: var(--mj-bg-surface-hover);\n}\n\n.type-option.selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.type-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n border-radius: 10px;\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n.type-option.selected .type-icon {\n background: var(--mj-brand-primary);\n}\n\n.type-icon i {\n font-size: 18px;\n color: var(--mj-text-muted);\n}\n\n.type-option.selected .type-icon i {\n color: var(--mj-text-inverse);\n}\n\n.type-info {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.type-label {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.type-description {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.check-icon {\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n.error-text {\n display: block;\n margin-top: 4px;\n font-size: 12px;\n color: var(--mj-status-error);\n}\n\n/* Info Box */\n.info-box {\n display: flex;\n gap: 12px;\n padding: 14px 16px;\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n border-radius: 8px;\n margin-top: 24px;\n}\n\n.info-box i {\n color: var(--mj-status-info);\n font-size: 16px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.info-box p {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-primary);\n line-height: 1.5;\n}\n\n.panel-footer {\n display: flex;\n gap: 12px;\n padding: 16px 24px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n\n.panel-footer button {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* Mobile */\n@media (max-width: 520px) {\n .slide-panel {\n width: 100%;\n }\n}\n"] }]
350
346
  }], () => [{ type: i1.ActionExplorerStateService }, { type: i2.NavigationService }, { type: i0.ChangeDetectorRef }], { Categories: [{
351
347
  type: Input
352
348
  }], PreselectedCategoryId: [{
@@ -1 +1 @@
1
- {"version":3,"file":"new-action-panel.component.js","sourceRoot":"","sources":["../../../../src/Actions/components/explorer/new-action-panel.component.ts","../../../../src/Actions/components/explorer/new-action-panel.component.html"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,YAAY,EAGZ,uBAAuB,EAExB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIxE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;;;;;;;;;;ICA1C,8BAA0B;IACxB,wBAA8C;IAC9C,YACF;IAAA,iBAAM;;;IADJ,eACF;IADE,yDACF;;;IAmBQ,wBAA4C;;;;IAXhD,kCAEqC;IAAnC,+NAAS,kCAAwB,KAAC;IAClC,+BAAuB;IACrB,oBAA6B;IAC/B,iBAAM;IAEJ,AADF,+BAAuB,eACI;IAAA,YAAkB;IAAA,iBAAO;IAClD,gCAA+B;IAAA,YAAwB;IACzD,AADyD,iBAAO,EAC1D;IACN,6GAA6B;IAG/B,iBAAS;;;;IAZP,2DAAwC;IAGnC,eAAqB;IAArB,6BAAqB;IAGC,eAAkB;IAAlB,qCAAkB;IACZ,eAAwB;IAAxB,2CAAwB;IAEzD,cAEC;IAFD,0DAEC;;;IAkBL,gCAAyB;IAAA,YAAoB;IAAA,iBAAO;;;IAA3B,cAAoB;IAApB,2CAAoB;;;IA8B7C,gCAAyB;IAAA,YAAwB;IAAA,iBAAO;;;IAA/B,cAAwB;IAAxB,+CAAwB;;;IAoBjD,wBAA2C;IAC3C,6BACF;;;IACE,wBAAiC;IACjC,+BACF;;;;IAhHR,8BAA8D;IAAlC,8LAAS,8BAAuB,KAAC;IAGvD,AADF,AADF,8BAAkC,aACN,SACpB;IACF,uBAAgC;IAChC,4BACF;IAAA,iBAAK;IACL,iCAEsB;IAApB,2LAAS,gBAAS,KAAC;IACnB,uBAAiC;IAErC,AADE,iBAAS,EACL;IAEN,8BAA2B;IACzB,uGAAyB;IASvB,AADF,+BAAwB,iBACa;IAAA,4BAAW;IAAA,iBAAQ;IACtD,gCAA2B;IACzB,8GAeC;IAEL,AADE,iBAAM,EACF;IAGJ,AADF,+BAAwB,iBAC8B;IAClD,8BACF;IAAA,iBAAQ;IACR,0CAKmC;IAHjC,gTAAkB;IAIpB,iBAAgB;IAChB,2GAAsB;IAGxB,iBAAM;IAGJ,AADF,+BAAwB,iBAC4B;IAChD,8BACF;IAAA,iBAAQ;IACR,2CAIa;IAFX,+TAAyB;IAI7B,AADE,iBAAiB,EACb;IAGJ,AADF,+BAAwB,iBACkC;IACtD,2BACF;IAAA,iBAAQ;IACR,+CAOuC;IALrC,iUAAwB;IAM1B,iBAAqB;IACrB,2GAA0B;IAG5B,iBAAM;IAEN,gCAAsB;IACpB,yBAAuC;IACvC,0BAAG;IACD,qJAEF;IAEJ,AADE,AADE,iBAAI,EACA,EACF;IAGJ,AADF,gCAA0B,kBAKH;IAAnB,4LAAS,eAAQ,KAAC;IAIhB,AAHF,+FAAgB,yEAGP;IAIX,iBAAS;IACT,mCAGsB;IAApB,4LAAS,gBAAS,KAAC;IACnB,yBACF;IAGN,AADE,AADE,AADE,iBAAS,EACL,EACF,EACF;;;IAzHqB,cAAQ;IAAR,oCAAQ;IAO3B,eAAmB;IAAnB,iCAAmB;IAOrB,eAKC;IALD,mDAKC;IAMG,eAeC;IAfD,iCAeC;IAaD,eAAgC;IAAhC,gDAAgC;IAHhC,2CAAkB;IAElB,AADA,iDAAmC,kBAClB;IAGnB,cAEC;IAFD,iDAEC;IASC,eAAyB;IAAzB,kDAAyB;IAEzB,AADA,8DAAgD,WACtC;IAeV,eAAoC;IAApC,oDAAoC;IALpC,iDAAwB;IAIxB,AAHA,kDAA6B,wBAGN;IAGzB,cAEC;IAFD,qDAEC;IAcD,eAAoB;IAEpB,AADA,AADA,kCAAoB,yBACI,6BACH;IAErB,cAMC;IAND,2CAMC;IAGD,eAAsB;IACtB,AADA,oCAAsB,6BACD;;AD9E/B,MAAM,OAAO,uBAAuB;IAoCzB;IACC;IACA;IArCD,UAAU,GAA6B,EAAE,CAAC;IAC1C,qBAAqB,GAAkB,IAAI,CAAC;IAC3C,aAAa,GAAG,IAAI,YAAY,EAAkB,CAAC;IACnD,KAAK,GAAG,IAAI,YAAY,EAAQ,CAAC;IAEpC,MAAM,GAAG,KAAK,CAAC;IACf,QAAQ,GAAG,KAAK,CAAC;IAExB,cAAc;IACP,IAAI,GAAG,EAAE,CAAC;IACV,WAAW,GAAG,EAAE,CAAC;IACjB,UAAU,GAAkB,IAAI,CAAC;IACjC,IAAI,GAAe,QAAQ,CAAC;IAEnC,aAAa;IACN,MAAM,GAA8B,EAAE,CAAC;IAEvC,WAAW,GAAmF;QACnG;YACE,KAAK,EAAE,QAAQ;YACf,KAAK,EAAE,eAAe;YACtB,IAAI,EAAE,kBAAkB;YACxB,WAAW,EAAE,8CAA8C;SAC5D;QACD;YACE,KAAK,EAAE,WAAW;YAClB,KAAK,EAAE,cAAc;YACrB,IAAI,EAAE,mBAAmB;YACzB,WAAW,EAAE,+CAA+C;SAC7D;KACF,CAAC;IAEM,QAAQ,GAAG,IAAI,OAAO,EAAQ,CAAC;IAEvC,YACS,YAAwC,EACvC,iBAAoC,EACpC,GAAsB;QAFvB,iBAAY,GAAZ,YAAY,CAA4B;QACvC,sBAAiB,GAAjB,iBAAiB,CAAmB;QACpC,QAAG,GAAH,GAAG,CAAmB;IAC7B,CAAC;IAEJ,QAAQ;QACN,IAAI,CAAC,YAAY,CAAC,mBAAmB,CAAC,IAAI,CACxC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CACzB,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;YACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;YACrB,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,WAAW;QACT,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;IAEO,SAAS;QACf,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;QACf,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,qBAAqB,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,kBAAkB,KAAK,KAAK,IAAI,IAAI,CAAC,YAAY,CAAC,kBAAkB,KAAK,eAAe;YACzJ,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,kBAAkB;YACtC,CAAC,CAAC,IAAI,CAAC,CAAC;QACV,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACxB,CAAC;IAEM,OAAO;QACZ,IAAI,CAAC,YAAY,CAAC,mBAAmB,EAAE,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAEM,eAAe,CAAC,KAAiB;QACtC,IAAK,KAAK,CAAC,MAAsB,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IAEM,QAAQ;QACb,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QAEjB,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,yBAAyB,CAAC;QAClD,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,2CAA2C,CAAC;QACpE,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACzC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,8CAA8C,CAAC;QACvE,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,0BAA0B,CAAC;QACvD,CAAC;QAED,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;IAC/C,CAAC;IAEM,KAAK,CAAC,MAAM;QACjB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;YACrB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YACxB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAExB,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,eAAe,CAAiB,aAAa,CAAC,CAAC;YAEvE,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;YACrD,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,UAAW,CAAC;YACrC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACxB,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,+BAA+B;YAE1D,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAElC,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAChC,IAAI,CAAC,YAAY,CAAC,mBAAmB,EAAE,CAAC;gBAExC,0CAA0C;gBAC1C,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;gBACtE,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;YAC9D,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,0CAA0C,CAAC;YACtE,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,yBAAyB,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;YACtD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,8CAA8C,CAAC;QAC1E,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;IAEM,UAAU,CAAC,IAAgB;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAEM,kBAAkB;QACvB,MAAM,OAAO,GAA2C,EAAE,CAAC;QAE3D,+CAA+C;QAC/C,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC1D,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAC/D,CAAC;QAEF,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;YAClC,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;gBACpC,KAAK,EAAE,QAAQ,CAAC,EAAE;aACnB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,eAAe,CAAC,QAAgC;QACtD,MAAM,IAAI,GAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,eAAe,GAAG,QAAQ,CAAC,QAAQ,CAAC;QAExC,OAAO,eAAe,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;YAC5E,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC1B,eAAe,GAAG,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC;YAC5C,CAAC;iBAAM,CAAC;gBACN,MAAM;YACR,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;iHA/KU,uBAAuB;6DAAvB,uBAAuB;YCvCpC,2FAAc;;YAAd,qCA4HC;4tKDjGa;gBACV,OAAO,CAAC,SAAS,EAAE;oBACjB,UAAU,CAAC,QAAQ,EAAE;wBACnB,KAAK,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;wBACpD,OAAO,CAAC,gBAAgB,EAAE,KAAK,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;qBAC7E,CAAC;oBACF,UAAU,CAAC,QAAQ,EAAE;wBACnB,OAAO,CAAC,eAAe,EAAE,KAAK,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;qBAC/E,CAAC;iBACH,CAAC;aACH;;iFAEU,uBAAuB;cAlBnC,SAAS;6BACI,KAAK,YACP,qBAAqB,mBAGd,uBAAuB,CAAC,MAAM,cACnC;oBACV,OAAO,CAAC,SAAS,EAAE;wBACjB,UAAU,CAAC,QAAQ,EAAE;4BACnB,KAAK,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;4BACpD,OAAO,CAAC,gBAAgB,EAAE,KAAK,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;yBAC7E,CAAC;wBACF,UAAU,CAAC,QAAQ,EAAE;4BACnB,OAAO,CAAC,eAAe,EAAE,KAAK,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;yBAC/E,CAAC;qBACH,CAAC;iBACH;;kBAGA,KAAK;;kBACL,KAAK;;kBACL,MAAM;;kBACN,MAAM;;kFAJI,uBAAuB","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnInit,\n OnDestroy,\n ChangeDetectionStrategy,\n ChangeDetectorRef\n} from '@angular/core';\nimport { trigger, transition, style, animate } from '@angular/animations';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { Metadata, LogError, CompositeKey } from '@memberjunction/core';\nimport { MJActionCategoryEntity, MJActionEntity } from '@memberjunction/core-entities';\nimport { NavigationService } from '@memberjunction/ng-shared';\nimport { ActionExplorerStateService } from '../../services/action-explorer-state.service';\nimport { UUIDsEqual } from '@memberjunction/global';\n\ntype ActionType = 'Custom' | 'Generated';\n\n@Component({\n standalone: false,\n selector: 'mj-new-action-panel',\n templateUrl: './new-action-panel.component.html',\n styleUrls: ['./new-action-panel.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n animations: [\n trigger('slideIn', [\n transition(':enter', [\n style({ transform: 'translateX(100%)', opacity: 0 }),\n animate('250ms ease-out', style({ transform: 'translateX(0)', opacity: 1 }))\n ]),\n transition(':leave', [\n animate('200ms ease-in', style({ transform: 'translateX(100%)', opacity: 0 }))\n ])\n ])\n ]\n})\nexport class NewActionPanelComponent implements OnInit, OnDestroy {\n @Input() Categories: MJActionCategoryEntity[] = [];\n @Input() PreselectedCategoryId: string | null = null;\n @Output() ActionCreated = new EventEmitter<MJActionEntity>();\n @Output() Close = new EventEmitter<void>();\n\n public IsOpen = false;\n public IsSaving = false;\n\n // Form fields\n public Name = '';\n public Description = '';\n public CategoryID: string | null = null;\n public Type: ActionType = 'Custom';\n\n // Validation\n public Errors: { [key: string]: string } = {};\n\n public TypeOptions: Array<{ value: ActionType; label: string; icon: string; description: string }> = [\n {\n value: 'Custom',\n label: 'Custom Action',\n icon: 'fa-solid fa-code',\n description: 'Write your own action code with full control'\n },\n {\n value: 'Generated',\n label: 'AI Generated',\n icon: 'fa-solid fa-robot',\n description: 'Let AI generate the action code from a prompt'\n }\n ];\n\n private destroy$ = new Subject<void>();\n\n constructor(\n public StateService: ActionExplorerStateService,\n private navigationService: NavigationService,\n private cdr: ChangeDetectorRef\n ) {}\n\n ngOnInit(): void {\n this.StateService.NewActionPanelOpen$.pipe(\n takeUntil(this.destroy$)\n ).subscribe(isOpen => {\n this.IsOpen = isOpen;\n if (isOpen) {\n this.resetForm();\n }\n this.cdr.markForCheck();\n });\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n private resetForm(): void {\n this.Name = '';\n this.Description = '';\n this.CategoryID = this.PreselectedCategoryId || (this.StateService.SelectedCategoryId !== 'all' && this.StateService.SelectedCategoryId !== 'uncategorized'\n ? this.StateService.SelectedCategoryId\n : null);\n this.Type = 'Custom';\n this.Errors = {};\n this.IsSaving = false;\n }\n\n public onClose(): void {\n this.StateService.closeNewActionPanel();\n this.Close.emit();\n }\n\n public onBackdropClick(event: MouseEvent): void {\n if ((event.target as HTMLElement).classList.contains('panel-backdrop')) {\n this.onClose();\n }\n }\n\n public validate(): boolean {\n this.Errors = {};\n\n if (!this.Name || this.Name.trim().length === 0) {\n this.Errors['name'] = 'Action name is required';\n } else if (this.Name.trim().length < 3) {\n this.Errors['name'] = 'Action name must be at least 3 characters';\n } else if (this.Name.trim().length > 425) {\n this.Errors['name'] = 'Action name must be less than 425 characters';\n }\n\n if (!this.CategoryID) {\n this.Errors['category'] = 'Please select a category';\n }\n\n return Object.keys(this.Errors).length === 0;\n }\n\n public async onSave(): Promise<void> {\n if (!this.validate()) {\n this.cdr.markForCheck();\n return;\n }\n\n this.IsSaving = true;\n this.cdr.markForCheck();\n\n try {\n const md = new Metadata();\n const action = await md.GetEntityObject<MJActionEntity>('MJ: Actions');\n\n action.Name = this.Name.trim();\n action.Description = this.Description.trim() || null;\n action.CategoryID = this.CategoryID!;\n action.Type = this.Type;\n action.Status = 'Pending'; // New actions start as pending\n\n const saved = await action.Save();\n\n if (saved) {\n this.ActionCreated.emit(action);\n this.StateService.closeNewActionPanel();\n\n // Open the full action record for editing\n const key = new CompositeKey([{ FieldName: 'ID', Value: action.ID }]);\n this.navigationService.OpenEntityRecord('MJ: Actions', key);\n } else {\n this.Errors['general'] = 'Failed to save action. Please try again.';\n }\n } catch (error) {\n LogError('Failed to create action', undefined, error);\n this.Errors['general'] = 'An error occurred while creating the action.';\n } finally {\n this.IsSaving = false;\n this.cdr.markForCheck();\n }\n }\n\n public selectType(type: ActionType): void {\n this.Type = type;\n }\n\n public getCategoryOptions(): Array<{ text: string; value: string }> {\n const options: Array<{ text: string; value: string }> = [];\n\n // Sort categories by path for easier selection\n const sortedCategories = [...this.Categories].sort((a, b) =>\n this.getCategoryPath(a).localeCompare(this.getCategoryPath(b))\n );\n\n sortedCategories.forEach(category => {\n options.push({\n text: this.getCategoryPath(category),\n value: category.ID\n });\n });\n\n return options;\n }\n\n private getCategoryPath(category: MJActionCategoryEntity): string {\n const path: string[] = [category.Name];\n let currentParentId = category.ParentID;\n\n while (currentParentId) {\n const parent = this.Categories.find(c => UUIDsEqual(c.ID, currentParentId));\n if (parent) {\n path.unshift(parent.Name);\n currentParentId = parent.ParentID || null;\n } else {\n break;\n }\n }\n\n return path.join(' / ');\n }\n}\n","@if (IsOpen) {\n <div class=\"panel-backdrop\" (click)=\"onBackdropClick($event)\">\n <div class=\"slide-panel\" @slideIn>\n <div class=\"panel-header\">\n <h2>\n <i class=\"fa-solid fa-bolt\"></i>\n New Action\n </h2>\n <button kendoButton\n [fillMode]=\"'flat'\"\n (click)=\"onClose()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"panel-content\">\n @if (Errors['general']) {\n <div class=\"error-banner\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n {{ Errors['general'] }}\n </div>\n }\n\n <!-- Action Type Selection -->\n <div class=\"form-group\">\n <label class=\"form-label required\">Action Type</label>\n <div class=\"type-selector\">\n @for (option of TypeOptions; track option.value) {\n <button class=\"type-option\"\n [class.selected]=\"Type === option.value\"\n (click)=\"selectType(option.value)\">\n <div class=\"type-icon\">\n <i [class]=\"option.icon\"></i>\n </div>\n <div class=\"type-info\">\n <span class=\"type-label\">{{ option.label }}</span>\n <span class=\"type-description\">{{ option.description }}</span>\n </div>\n @if (Type === option.value) {\n <i class=\"fa-solid fa-check check-icon\"></i>\n }\n </button>\n }\n </div>\n </div>\n\n <div class=\"form-group\">\n <label for=\"actionName\" class=\"form-label required\">\n Action Name\n </label>\n <kendo-textbox\n id=\"actionName\"\n [(ngModel)]=\"Name\"\n [placeholder]=\"'Enter action name'\"\n [maxlength]=\"425\"\n [class.invalid]=\"Errors['name']\">\n </kendo-textbox>\n @if (Errors['name']) {\n <span class=\"error-text\">{{ Errors['name'] }}</span>\n }\n </div>\n\n <div class=\"form-group\">\n <label for=\"actionDescription\" class=\"form-label\">\n Description\n </label>\n <kendo-textarea\n id=\"actionDescription\"\n [(ngModel)]=\"Description\"\n [placeholder]=\"'Describe what this action does'\"\n [rows]=\"3\">\n </kendo-textarea>\n </div>\n\n <div class=\"form-group\">\n <label for=\"actionCategory\" class=\"form-label required\">\n Category\n </label>\n <kendo-dropdownlist\n id=\"actionCategory\"\n [(ngModel)]=\"CategoryID\"\n [data]=\"getCategoryOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n [class.invalid]=\"Errors['category']\">\n </kendo-dropdownlist>\n @if (Errors['category']) {\n <span class=\"error-text\">{{ Errors['category'] }}</span>\n }\n </div>\n\n <div class=\"info-box\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <p>\n After creating the action, you'll be taken to the full action editor\n where you can configure parameters, code, and other settings.\n </p>\n </div>\n </div>\n\n <div class=\"panel-footer\">\n <button kendoButton\n [fillMode]=\"'solid'\"\n [themeColor]=\"'primary'\"\n [disabled]=\"IsSaving\"\n (click)=\"onSave()\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Creating...\n } @else {\n <i class=\"fa-solid fa-check\"></i>\n Create Action\n }\n </button>\n <button kendoButton\n [fillMode]=\"'outline'\"\n [disabled]=\"IsSaving\"\n (click)=\"onClose()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n}\n"]}
1
+ {"version":3,"file":"new-action-panel.component.js","sourceRoot":"","sources":["../../../../src/Actions/components/explorer/new-action-panel.component.ts","../../../../src/Actions/components/explorer/new-action-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnInit,\n OnDestroy,\n ChangeDetectionStrategy,\n ChangeDetectorRef\n} from '@angular/core';\nimport { trigger, transition, style, animate } from '@angular/animations';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { Metadata, LogError, CompositeKey } from '@memberjunction/core';\nimport { MJActionCategoryEntity, MJActionEntity } from '@memberjunction/core-entities';\nimport { NavigationService } from '@memberjunction/ng-shared';\nimport { ActionExplorerStateService } from '../../services/action-explorer-state.service';\nimport { UUIDsEqual } from '@memberjunction/global';\n\ntype ActionType = 'Custom' | 'Generated';\n\n@Component({\n standalone: false,\n selector: 'mj-new-action-panel',\n templateUrl: './new-action-panel.component.html',\n styleUrls: ['./new-action-panel.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n animations: [\n trigger('slideIn', [\n transition(':enter', [\n style({ transform: 'translateX(100%)', opacity: 0 }),\n animate('250ms ease-out', style({ transform: 'translateX(0)', opacity: 1 }))\n ]),\n transition(':leave', [\n animate('200ms ease-in', style({ transform: 'translateX(100%)', opacity: 0 }))\n ])\n ])\n ]\n})\nexport class NewActionPanelComponent implements OnInit, OnDestroy {\n @Input() Categories: MJActionCategoryEntity[] = [];\n @Input() PreselectedCategoryId: string | null = null;\n @Output() ActionCreated = new EventEmitter<MJActionEntity>();\n @Output() Close = new EventEmitter<void>();\n\n public IsOpen = false;\n public IsSaving = false;\n\n // Form fields\n public Name = '';\n public Description = '';\n public CategoryID: string | null = null;\n public Type: ActionType = 'Custom';\n\n // Validation\n public Errors: { [key: string]: string } = {};\n\n public TypeOptions: Array<{ value: ActionType; label: string; icon: string; description: string }> = [\n {\n value: 'Custom',\n label: 'Custom Action',\n icon: 'fa-solid fa-code',\n description: 'Write your own action code with full control'\n },\n {\n value: 'Generated',\n label: 'AI Generated',\n icon: 'fa-solid fa-robot',\n description: 'Let AI generate the action code from a prompt'\n }\n ];\n\n private destroy$ = new Subject<void>();\n\n constructor(\n public StateService: ActionExplorerStateService,\n private navigationService: NavigationService,\n private cdr: ChangeDetectorRef\n ) {}\n\n ngOnInit(): void {\n this.StateService.NewActionPanelOpen$.pipe(\n takeUntil(this.destroy$)\n ).subscribe(isOpen => {\n this.IsOpen = isOpen;\n if (isOpen) {\n this.resetForm();\n }\n this.cdr.markForCheck();\n });\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n private resetForm(): void {\n this.Name = '';\n this.Description = '';\n this.CategoryID = this.PreselectedCategoryId || (this.StateService.SelectedCategoryId !== 'all' && this.StateService.SelectedCategoryId !== 'uncategorized'\n ? this.StateService.SelectedCategoryId\n : null);\n this.Type = 'Custom';\n this.Errors = {};\n this.IsSaving = false;\n }\n\n public onClose(): void {\n this.StateService.closeNewActionPanel();\n this.Close.emit();\n }\n\n public onBackdropClick(event: MouseEvent): void {\n if ((event.target as HTMLElement).classList.contains('panel-backdrop')) {\n this.onClose();\n }\n }\n\n public validate(): boolean {\n this.Errors = {};\n\n if (!this.Name || this.Name.trim().length === 0) {\n this.Errors['name'] = 'Action name is required';\n } else if (this.Name.trim().length < 3) {\n this.Errors['name'] = 'Action name must be at least 3 characters';\n } else if (this.Name.trim().length > 425) {\n this.Errors['name'] = 'Action name must be less than 425 characters';\n }\n\n if (!this.CategoryID) {\n this.Errors['category'] = 'Please select a category';\n }\n\n return Object.keys(this.Errors).length === 0;\n }\n\n public async onSave(): Promise<void> {\n if (!this.validate()) {\n this.cdr.markForCheck();\n return;\n }\n\n this.IsSaving = true;\n this.cdr.markForCheck();\n\n try {\n const md = new Metadata();\n const action = await md.GetEntityObject<MJActionEntity>('MJ: Actions');\n\n action.Name = this.Name.trim();\n action.Description = this.Description.trim() || null;\n action.CategoryID = this.CategoryID!;\n action.Type = this.Type;\n action.Status = 'Pending'; // New actions start as pending\n\n const saved = await action.Save();\n\n if (saved) {\n this.ActionCreated.emit(action);\n this.StateService.closeNewActionPanel();\n\n // Open the full action record for editing\n const key = new CompositeKey([{ FieldName: 'ID', Value: action.ID }]);\n this.navigationService.OpenEntityRecord('MJ: Actions', key);\n } else {\n this.Errors['general'] = 'Failed to save action. Please try again.';\n }\n } catch (error) {\n LogError('Failed to create action', undefined, error);\n this.Errors['general'] = 'An error occurred while creating the action.';\n } finally {\n this.IsSaving = false;\n this.cdr.markForCheck();\n }\n }\n\n public selectType(type: ActionType): void {\n this.Type = type;\n }\n\n public getCategoryOptions(): Array<{ text: string; value: string }> {\n const options: Array<{ text: string; value: string }> = [];\n\n // Sort categories by path for easier selection\n const sortedCategories = [...this.Categories].sort((a, b) =>\n this.getCategoryPath(a).localeCompare(this.getCategoryPath(b))\n );\n\n sortedCategories.forEach(category => {\n options.push({\n text: this.getCategoryPath(category),\n value: category.ID\n });\n });\n\n return options;\n }\n\n private getCategoryPath(category: MJActionCategoryEntity): string {\n const path: string[] = [category.Name];\n let currentParentId = category.ParentID;\n\n while (currentParentId) {\n const parent = this.Categories.find(c => UUIDsEqual(c.ID, currentParentId));\n if (parent) {\n path.unshift(parent.Name);\n currentParentId = parent.ParentID || null;\n } else {\n break;\n }\n }\n\n return path.join(' / ');\n }\n}\n","@if (IsOpen) {\n <div class=\"panel-backdrop\" (click)=\"onBackdropClick($event)\">\n <div class=\"slide-panel\" @slideIn>\n <div class=\"panel-header\">\n <h2>\n <i class=\"fa-solid fa-bolt\"></i>\n New Action\n </h2>\n <button mjButton\n variant=\"flat\"\n (click)=\"onClose()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"panel-content\">\n @if (Errors['general']) {\n <div class=\"error-banner\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n {{ Errors['general'] }}\n </div>\n }\n\n <!-- Action Type Selection -->\n <div class=\"form-group\">\n <label class=\"form-label required\">Action Type</label>\n <div class=\"type-selector\">\n @for (option of TypeOptions; track option.value) {\n <button class=\"type-option\"\n [class.selected]=\"Type === option.value\"\n (click)=\"selectType(option.value)\">\n <div class=\"type-icon\">\n <i [class]=\"option.icon\"></i>\n </div>\n <div class=\"type-info\">\n <span class=\"type-label\">{{ option.label }}</span>\n <span class=\"type-description\">{{ option.description }}</span>\n </div>\n @if (Type === option.value) {\n <i class=\"fa-solid fa-check check-icon\"></i>\n }\n </button>\n }\n </div>\n </div>\n\n <div class=\"form-group\">\n <label for=\"actionName\" class=\"form-label required\">\n Action Name\n </label>\n <input type=\"text\" class=\"mj-input\"\n id=\"actionName\"\n [(ngModel)]=\"Name\"\n placeholder=\"Enter action name\"\n [maxlength]=\"425\"\n [class.invalid]=\"Errors['name']\" />\n @if (Errors['name']) {\n <span class=\"error-text\">{{ Errors['name'] }}</span>\n }\n </div>\n\n <div class=\"form-group\">\n <label for=\"actionDescription\" class=\"form-label\">\n Description\n </label>\n <textarea class=\"mj-textarea\"\n id=\"actionDescription\"\n [(ngModel)]=\"Description\"\n placeholder=\"Describe what this action does\"\n [rows]=\"3\"></textarea>\n </div>\n\n <div class=\"form-group\">\n <label for=\"actionCategory\" class=\"form-label required\">\n Category\n </label>\n <mj-dropdown\n [(ngModel)]=\"CategoryID\"\n [Data]=\"getCategoryOptions()\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n [class.invalid]=\"Errors['category']\">\n </mj-dropdown>\n @if (Errors['category']) {\n <span class=\"error-text\">{{ Errors['category'] }}</span>\n }\n </div>\n\n <div class=\"info-box\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <p>\n After creating the action, you'll be taken to the full action editor\n where you can configure parameters, code, and other settings.\n </p>\n </div>\n </div>\n\n <div class=\"panel-footer\">\n <button mjButton\n variant=\"primary\"\n [disabled]=\"IsSaving\"\n (click)=\"onSave()\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Creating...\n } @else {\n <i class=\"fa-solid fa-check\"></i>\n Create Action\n }\n </button>\n <button mjButton\n variant=\"outline\"\n [disabled]=\"IsSaving\"\n (click)=\"onClose()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n}\n"]}
@@ -7,9 +7,7 @@ import { UUIDsEqual } from '@memberjunction/global';
7
7
  import * as i0 from "@angular/core";
8
8
  import * as i1 from "../../services/action-explorer-state.service";
9
9
  import * as i2 from "@angular/forms";
10
- import * as i3 from "@progress/kendo-angular-buttons";
11
- import * as i4 from "@progress/kendo-angular-dropdowns";
12
- import * as i5 from "@progress/kendo-angular-inputs";
10
+ import * as i3 from "@memberjunction/ng-ui-components";
13
11
  function NewCategoryPanelComponent_Conditional_0_Conditional_9_Template(rf, ctx) { if (rf & 1) {
14
12
  i0.ɵɵelementStart(0, "div", 8);
15
13
  i0.ɵɵelement(1, "i", 21);
@@ -54,22 +52,22 @@ function NewCategoryPanelComponent_Conditional_0_Template(rf, ctx) { if (rf & 1)
54
52
  i0.ɵɵelementStart(10, "div", 9)(11, "label", 10);
55
53
  i0.ɵɵtext(12, " Category Name ");
56
54
  i0.ɵɵelementEnd();
57
- i0.ɵɵelementStart(13, "kendo-textbox", 11);
58
- i0.ɵɵtwoWayListener("ngModelChange", function NewCategoryPanelComponent_Conditional_0_Template_kendo_textbox_ngModelChange_13_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.Name, $event) || (ctx_r1.Name = $event); return i0.ɵɵresetView($event); });
55
+ i0.ɵɵelementStart(13, "input", 11);
56
+ i0.ɵɵtwoWayListener("ngModelChange", function NewCategoryPanelComponent_Conditional_0_Template_input_ngModelChange_13_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.Name, $event) || (ctx_r1.Name = $event); return i0.ɵɵresetView($event); });
59
57
  i0.ɵɵelementEnd();
60
58
  i0.ɵɵconditionalCreate(14, NewCategoryPanelComponent_Conditional_0_Conditional_14_Template, 2, 1, "span", 12);
61
59
  i0.ɵɵelementEnd();
62
60
  i0.ɵɵelementStart(15, "div", 9)(16, "label", 13);
63
61
  i0.ɵɵtext(17, " Description ");
64
62
  i0.ɵɵelementEnd();
65
- i0.ɵɵelementStart(18, "kendo-textarea", 14);
66
- i0.ɵɵtwoWayListener("ngModelChange", function NewCategoryPanelComponent_Conditional_0_Template_kendo_textarea_ngModelChange_18_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.Description, $event) || (ctx_r1.Description = $event); return i0.ɵɵresetView($event); });
63
+ i0.ɵɵelementStart(18, "textarea", 14);
64
+ i0.ɵɵtwoWayListener("ngModelChange", function NewCategoryPanelComponent_Conditional_0_Template_textarea_ngModelChange_18_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.Description, $event) || (ctx_r1.Description = $event); return i0.ɵɵresetView($event); });
67
65
  i0.ɵɵelementEnd()();
68
66
  i0.ɵɵelementStart(19, "div", 9)(20, "label", 15);
69
67
  i0.ɵɵtext(21, " Parent Category ");
70
68
  i0.ɵɵelementEnd();
71
- i0.ɵɵelementStart(22, "kendo-dropdownlist", 16);
72
- i0.ɵɵtwoWayListener("ngModelChange", function NewCategoryPanelComponent_Conditional_0_Template_kendo_dropdownlist_ngModelChange_22_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.ParentID, $event) || (ctx_r1.ParentID = $event); return i0.ɵɵresetView($event); });
69
+ i0.ɵɵelementStart(22, "mj-dropdown", 16);
70
+ i0.ɵɵtwoWayListener("ngModelChange", function NewCategoryPanelComponent_Conditional_0_Template_mj_dropdown_ngModelChange_22_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.ParentID, $event) || (ctx_r1.ParentID = $event); return i0.ɵɵresetView($event); });
73
71
  i0.ɵɵelementEnd();
74
72
  i0.ɵɵelementStart(23, "span", 17);
75
73
  i0.ɵɵtext(24, " Leave empty to create a root-level category ");
@@ -86,28 +84,26 @@ function NewCategoryPanelComponent_Conditional_0_Template(rf, ctx) { if (rf & 1)
86
84
  const ctx_r1 = i0.ɵɵnextContext();
87
85
  i0.ɵɵadvance();
88
86
  i0.ɵɵproperty("@slideIn", undefined);
89
- i0.ɵɵadvance(5);
90
- i0.ɵɵproperty("fillMode", "flat");
91
- i0.ɵɵadvance(3);
87
+ i0.ɵɵadvance(8);
92
88
  i0.ɵɵconditional(ctx_r1.Errors["general"] ? 9 : -1);
93
89
  i0.ɵɵadvance(4);
94
90
  i0.ɵɵclassProp("invalid", ctx_r1.Errors["name"]);
95
91
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.Name);
96
- i0.ɵɵproperty("placeholder", "Enter category name")("maxlength", 200);
92
+ i0.ɵɵproperty("maxlength", 200);
97
93
  i0.ɵɵadvance();
98
94
  i0.ɵɵconditional(ctx_r1.Errors["name"] ? 14 : -1);
99
95
  i0.ɵɵadvance(4);
100
96
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.Description);
101
- i0.ɵɵproperty("placeholder", "Optional description for this category")("rows", 3)("maxlength", 1000);
97
+ i0.ɵɵproperty("rows", 3)("maxlength", 1000);
102
98
  i0.ɵɵadvance(4);
103
99
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.ParentID);
104
- i0.ɵɵproperty("data", ctx_r1.getParentOptions())("valuePrimitive", true);
100
+ i0.ɵɵproperty("Data", ctx_r1.getParentOptions())("ValuePrimitive", true);
105
101
  i0.ɵɵadvance(4);
106
- i0.ɵɵproperty("fillMode", "solid")("themeColor", "primary")("disabled", ctx_r1.IsSaving);
102
+ i0.ɵɵproperty("disabled", ctx_r1.IsSaving);
107
103
  i0.ɵɵadvance();
108
104
  i0.ɵɵconditional(ctx_r1.IsSaving ? 27 : 28);
109
105
  i0.ɵɵadvance(2);
110
- i0.ɵɵproperty("fillMode", "outline")("disabled", ctx_r1.IsSaving);
106
+ i0.ɵɵproperty("disabled", ctx_r1.IsSaving);
111
107
  } }
112
108
  export class NewCategoryPanelComponent {
113
109
  StateService;
@@ -241,11 +237,11 @@ export class NewCategoryPanelComponent {
241
237
  return path.join(' / ');
242
238
  }
243
239
  static ɵfac = function NewCategoryPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || NewCategoryPanelComponent)(i0.ɵɵdirectiveInject(i1.ActionExplorerStateService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
244
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: NewCategoryPanelComponent, selectors: [["mj-new-category-panel"]], inputs: { Categories: "Categories", PreselectedParentId: "PreselectedParentId" }, outputs: { CategoryCreated: "CategoryCreated", Close: "Close" }, standalone: false, decls: 1, vars: 1, consts: [[1, "panel-backdrop"], [1, "panel-backdrop", 3, "click"], [1, "slide-panel"], [1, "panel-header"], [1, "fa-solid", "fa-folder-plus"], ["kendoButton", "", 3, "click", "fillMode"], [1, "fa-solid", "fa-times"], [1, "panel-content"], [1, "error-banner"], [1, "form-group"], ["for", "categoryName", 1, "form-label", "required"], ["id", "categoryName", 3, "ngModelChange", "ngModel", "placeholder", "maxlength"], [1, "error-text"], ["for", "categoryDescription", 1, "form-label"], ["id", "categoryDescription", 3, "ngModelChange", "ngModel", "placeholder", "rows", "maxlength"], ["for", "categoryParent", 1, "form-label"], ["id", "categoryParent", "textField", "text", "valueField", "value", 3, "ngModelChange", "ngModel", "data", "valuePrimitive"], [1, "help-text"], [1, "panel-footer"], ["kendoButton", "", 3, "click", "fillMode", "themeColor", "disabled"], ["kendoButton", "", 3, "click", "fillMode", "disabled"], [1, "fa-solid", "fa-exclamation-circle"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-check"]], template: function NewCategoryPanelComponent_Template(rf, ctx) { if (rf & 1) {
245
- i0.ɵɵconditionalCreate(0, NewCategoryPanelComponent_Conditional_0_Template, 31, 22, "div", 0);
240
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: NewCategoryPanelComponent, selectors: [["mj-new-category-panel"]], inputs: { Categories: "Categories", PreselectedParentId: "PreselectedParentId" }, outputs: { CategoryCreated: "CategoryCreated", Close: "Close" }, standalone: false, decls: 1, vars: 1, consts: [[1, "panel-backdrop"], [1, "panel-backdrop", 3, "click"], [1, "slide-panel"], [1, "panel-header"], [1, "fa-solid", "fa-folder-plus"], ["mjButton", "", "variant", "flat", 3, "click"], [1, "fa-solid", "fa-times"], [1, "panel-content"], [1, "error-banner"], [1, "form-group"], ["for", "categoryName", 1, "form-label", "required"], ["type", "text", "id", "categoryName", "placeholder", "Enter category name", 1, "mj-input", 3, "ngModelChange", "ngModel", "maxlength"], [1, "error-text"], ["for", "categoryDescription", 1, "form-label"], ["id", "categoryDescription", "placeholder", "Optional description for this category", 1, "mj-textarea", 3, "ngModelChange", "ngModel", "rows", "maxlength"], ["for", "categoryParent", 1, "form-label"], ["TextField", "text", "ValueField", "value", 3, "ngModelChange", "ngModel", "Data", "ValuePrimitive"], [1, "help-text"], [1, "panel-footer"], ["mjButton", "", "variant", "primary", 3, "click", "disabled"], ["mjButton", "", "variant", "outline", 3, "click", "disabled"], [1, "fa-solid", "fa-exclamation-circle"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-check"]], template: function NewCategoryPanelComponent_Template(rf, ctx) { if (rf & 1) {
241
+ i0.ɵɵconditionalCreate(0, NewCategoryPanelComponent_Conditional_0_Template, 31, 16, "div", 0);
246
242
  } if (rf & 2) {
247
243
  i0.ɵɵconditional(ctx.IsOpen ? 0 : -1);
248
- } }, dependencies: [i2.NgControlStatus, i2.MaxLengthValidator, i2.NgModel, i3.ButtonComponent, i4.DropDownListComponent, i5.TextBoxComponent, i5.TextAreaComponent], styles: [".panel-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 1000;\n display: flex;\n justify-content: flex-end;\n}\n\n.slide-panel[_ngcontent-%COMP%] {\n width: 450px;\n max-width: 100%;\n height: 100%;\n background: var(--mj-bg-surface-card);\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 20px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--mj-text-primary);\n}\n\n.panel-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n.error-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n border-radius: 8px;\n margin-bottom: 20px;\n font-size: 14px;\n}\n\n.error-banner[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.form-group[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n.form-label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-label.required[_ngcontent-%COMP%]::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n.form-group[_ngcontent-%COMP%] kendo-textbox[_ngcontent-%COMP%], \n.form-group[_ngcontent-%COMP%] kendo-textarea[_ngcontent-%COMP%], \n.form-group[_ngcontent-%COMP%] kendo-dropdownlist[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.form-group[_ngcontent-%COMP%] kendo-textbox.invalid[_ngcontent-%COMP%], \n.form-group[_ngcontent-%COMP%] kendo-textarea.invalid[_ngcontent-%COMP%] {\n border-color: var(--mj-status-error);\n}\n\n.error-text[_ngcontent-%COMP%] {\n display: block;\n margin-top: 4px;\n font-size: 12px;\n color: var(--mj-status-error);\n}\n\n.help-text[_ngcontent-%COMP%] {\n display: block;\n margin-top: 4px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.panel-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 16px 24px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n\n.panel-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n\n\n@media (max-width: 480px) {\n .slide-panel[_ngcontent-%COMP%] {\n width: 100%;\n }\n}"], data: { animation: [
244
+ } }, dependencies: [i2.DefaultValueAccessor, i2.NgControlStatus, i2.MaxLengthValidator, i2.NgModel, i3.MJButtonDirective, i3.MJDropdownComponent], styles: [".panel-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 1000;\n display: flex;\n justify-content: flex-end;\n}\n\n.slide-panel[_ngcontent-%COMP%] {\n width: 450px;\n max-width: 100%;\n height: 100%;\n background: var(--mj-bg-surface-card);\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 20px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--mj-text-primary);\n}\n\n.panel-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n.error-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n border-radius: 8px;\n margin-bottom: 20px;\n font-size: 14px;\n}\n\n.error-banner[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.form-group[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n.form-label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-label.required[_ngcontent-%COMP%]::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n.error-text[_ngcontent-%COMP%] {\n display: block;\n margin-top: 4px;\n font-size: 12px;\n color: var(--mj-status-error);\n}\n\n.help-text[_ngcontent-%COMP%] {\n display: block;\n margin-top: 4px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.panel-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 16px 24px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n\n.panel-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n\n\n@media (max-width: 480px) {\n .slide-panel[_ngcontent-%COMP%] {\n width: 100%;\n }\n}"], data: { animation: [
249
245
  trigger('slideIn', [
250
246
  transition(':enter', [
251
247
  style({ transform: 'translateX(100%)', opacity: 0 }),
@@ -269,7 +265,7 @@ export class NewCategoryPanelComponent {
269
265
  animate('200ms ease-in', style({ transform: 'translateX(100%)', opacity: 0 }))
270
266
  ])
271
267
  ])
272
- ], template: "@if (IsOpen) {\n <div class=\"panel-backdrop\" (click)=\"onBackdropClick($event)\">\n <div class=\"slide-panel\" @slideIn>\n <div class=\"panel-header\">\n <h2>\n <i class=\"fa-solid fa-folder-plus\"></i>\n New Category\n </h2>\n <button kendoButton\n [fillMode]=\"'flat'\"\n (click)=\"onClose()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"panel-content\">\n @if (Errors['general']) {\n <div class=\"error-banner\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n {{ Errors['general'] }}\n </div>\n }\n\n <div class=\"form-group\">\n <label for=\"categoryName\" class=\"form-label required\">\n Category Name\n </label>\n <kendo-textbox\n id=\"categoryName\"\n [(ngModel)]=\"Name\"\n [placeholder]=\"'Enter category name'\"\n [maxlength]=\"200\"\n [class.invalid]=\"Errors['name']\">\n </kendo-textbox>\n @if (Errors['name']) {\n <span class=\"error-text\">{{ Errors['name'] }}</span>\n }\n </div>\n\n <div class=\"form-group\">\n <label for=\"categoryDescription\" class=\"form-label\">\n Description\n </label>\n <kendo-textarea\n id=\"categoryDescription\"\n [(ngModel)]=\"Description\"\n [placeholder]=\"'Optional description for this category'\"\n [rows]=\"3\"\n [maxlength]=\"1000\">\n </kendo-textarea>\n </div>\n\n <div class=\"form-group\">\n <label for=\"categoryParent\" class=\"form-label\">\n Parent Category\n </label>\n <kendo-dropdownlist\n id=\"categoryParent\"\n [(ngModel)]=\"ParentID\"\n [data]=\"getParentOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\">\n </kendo-dropdownlist>\n <span class=\"help-text\">\n Leave empty to create a root-level category\n </span>\n </div>\n </div>\n\n <div class=\"panel-footer\">\n <button kendoButton\n [fillMode]=\"'solid'\"\n [themeColor]=\"'primary'\"\n [disabled]=\"IsSaving\"\n (click)=\"onSave()\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Creating...\n } @else {\n <i class=\"fa-solid fa-check\"></i>\n Create Category\n }\n </button>\n <button kendoButton\n [fillMode]=\"'outline'\"\n [disabled]=\"IsSaving\"\n (click)=\"onClose()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n}\n", styles: [".panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 1000;\n display: flex;\n justify-content: flex-end;\n}\n\n.slide-panel {\n width: 450px;\n max-width: 100%;\n height: 100%;\n background: var(--mj-bg-surface-card);\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n}\n\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 20px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-header h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--mj-text-primary);\n}\n\n.panel-header h2 i {\n color: var(--mj-brand-primary);\n}\n\n.panel-content {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n.error-banner {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n border-radius: 8px;\n margin-bottom: 20px;\n font-size: 14px;\n}\n\n.error-banner i {\n font-size: 16px;\n}\n\n.form-group {\n margin-bottom: 20px;\n}\n\n.form-label {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-label.required::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n.form-group kendo-textbox,\n.form-group kendo-textarea,\n.form-group kendo-dropdownlist {\n width: 100%;\n}\n\n.form-group kendo-textbox.invalid,\n.form-group kendo-textarea.invalid {\n border-color: var(--mj-status-error);\n}\n\n.error-text {\n display: block;\n margin-top: 4px;\n font-size: 12px;\n color: var(--mj-status-error);\n}\n\n.help-text {\n display: block;\n margin-top: 4px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.panel-footer {\n display: flex;\n gap: 12px;\n padding: 16px 24px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n\n.panel-footer button {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* Mobile */\n@media (max-width: 480px) {\n .slide-panel {\n width: 100%;\n }\n}\n"] }]
268
+ ], template: "@if (IsOpen) {\n <div class=\"panel-backdrop\" (click)=\"onBackdropClick($event)\">\n <div class=\"slide-panel\" @slideIn>\n <div class=\"panel-header\">\n <h2>\n <i class=\"fa-solid fa-folder-plus\"></i>\n New Category\n </h2>\n <button mjButton\n variant=\"flat\"\n (click)=\"onClose()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"panel-content\">\n @if (Errors['general']) {\n <div class=\"error-banner\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n {{ Errors['general'] }}\n </div>\n }\n\n <div class=\"form-group\">\n <label for=\"categoryName\" class=\"form-label required\">\n Category Name\n </label>\n <input type=\"text\" class=\"mj-input\"\n id=\"categoryName\"\n [(ngModel)]=\"Name\"\n placeholder=\"Enter category name\"\n [maxlength]=\"200\"\n [class.invalid]=\"Errors['name']\" />\n @if (Errors['name']) {\n <span class=\"error-text\">{{ Errors['name'] }}</span>\n }\n </div>\n\n <div class=\"form-group\">\n <label for=\"categoryDescription\" class=\"form-label\">\n Description\n </label>\n <textarea class=\"mj-textarea\"\n id=\"categoryDescription\"\n [(ngModel)]=\"Description\"\n placeholder=\"Optional description for this category\"\n [rows]=\"3\"\n [maxlength]=\"1000\"></textarea>\n </div>\n\n <div class=\"form-group\">\n <label for=\"categoryParent\" class=\"form-label\">\n Parent Category\n </label>\n <mj-dropdown\n [(ngModel)]=\"ParentID\"\n [Data]=\"getParentOptions()\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\">\n </mj-dropdown>\n <span class=\"help-text\">\n Leave empty to create a root-level category\n </span>\n </div>\n </div>\n\n <div class=\"panel-footer\">\n <button mjButton\n variant=\"primary\"\n [disabled]=\"IsSaving\"\n (click)=\"onSave()\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Creating...\n } @else {\n <i class=\"fa-solid fa-check\"></i>\n Create Category\n }\n </button>\n <button mjButton\n variant=\"outline\"\n [disabled]=\"IsSaving\"\n (click)=\"onClose()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n}\n", styles: [".panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 1000;\n display: flex;\n justify-content: flex-end;\n}\n\n.slide-panel {\n width: 450px;\n max-width: 100%;\n height: 100%;\n background: var(--mj-bg-surface-card);\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n}\n\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 20px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.panel-header h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--mj-text-primary);\n}\n\n.panel-header h2 i {\n color: var(--mj-brand-primary);\n}\n\n.panel-content {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n}\n\n.error-banner {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n border-radius: 8px;\n margin-bottom: 20px;\n font-size: 14px;\n}\n\n.error-banner i {\n font-size: 16px;\n}\n\n.form-group {\n margin-bottom: 20px;\n}\n\n.form-label {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-label.required::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n.error-text {\n display: block;\n margin-top: 4px;\n font-size: 12px;\n color: var(--mj-status-error);\n}\n\n.help-text {\n display: block;\n margin-top: 4px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.panel-footer {\n display: flex;\n gap: 12px;\n padding: 16px 24px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n\n.panel-footer button {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* Mobile */\n@media (max-width: 480px) {\n .slide-panel {\n width: 100%;\n }\n}\n"] }]
273
269
  }], () => [{ type: i1.ActionExplorerStateService }, { type: i0.ChangeDetectorRef }], { Categories: [{
274
270
  type: Input
275
271
  }], PreselectedParentId: [{