windmill-components 1.677.1 → 1.687.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 (354) hide show
  1. package/package/components/AppConnectInner.svelte +6 -0
  2. package/package/components/CiTestResults.svelte +64 -0
  3. package/package/components/CiTestResults.svelte.d.ts +7 -0
  4. package/package/components/CompareWorkspaces.svelte +626 -418
  5. package/package/components/DBManager.svelte +35 -4
  6. package/package/components/DBManager.svelte.d.ts +2 -0
  7. package/package/components/DBManagerContent.svelte +3 -1
  8. package/package/components/DBManagerContent.svelte.d.ts +3 -0
  9. package/package/components/DBManagerDrawer.svelte +145 -3
  10. package/package/components/DBTableEditor.svelte +14 -4
  11. package/package/components/DatatablePicker.svelte +2 -5
  12. package/package/components/DatatableSchemaDiff.svelte +531 -0
  13. package/package/components/DatatableSchemaDiff.svelte.d.ts +29 -0
  14. package/package/components/DedicatedWorkersSelector.svelte +4 -2
  15. package/package/components/DefaultTagsInner.svelte +42 -2
  16. package/package/components/DeployWorkspaceDrawer.svelte +1 -1
  17. package/package/components/Dev.svelte +20 -3
  18. package/package/components/Editor.svelte +1 -1
  19. package/package/components/EditorBar.svelte +1 -1
  20. package/package/components/EditorBar.svelte.d.ts +1 -1
  21. package/package/components/FlowStatusViewerInner.svelte +269 -220
  22. package/package/components/FlowTimeline.svelte +1 -1
  23. package/package/components/FolderEditor.svelte +189 -4
  24. package/package/components/ForkWorkspaceBanner.svelte +82 -11
  25. package/package/components/GlobalUserOffboardingModal.svelte +293 -0
  26. package/package/components/GlobalUserOffboardingModal.svelte.d.ts +10 -0
  27. package/package/components/InstanceSettings.svelte +22 -3
  28. package/package/components/Login.svelte +22 -10
  29. package/package/components/ModuleTest.svelte +2 -1
  30. package/package/components/NoMainFuncBadge.svelte +1 -1
  31. package/package/components/OffboardItemsBox.svelte +56 -0
  32. package/package/components/OffboardItemsBox.svelte.d.ts +12 -0
  33. package/package/components/OffboardReassignControls.svelte +47 -0
  34. package/package/components/OffboardReassignControls.svelte.d.ts +20 -0
  35. package/package/components/OffboardWorkspaceSection.svelte +110 -0
  36. package/package/components/OffboardWorkspaceSection.svelte.d.ts +24 -0
  37. package/package/components/OnBehalfOfSelector.svelte +21 -3
  38. package/package/components/OnBehalfOfSelector.svelte.d.ts +7 -0
  39. package/package/components/QueueAlerts.svelte +10 -10
  40. package/package/components/ResourcePicker.svelte +2 -2
  41. package/package/components/ScriptBuilder.svelte +52 -11
  42. package/package/components/ScriptEditor.svelte +1 -3
  43. package/package/components/ScriptEditor.svelte.d.ts +1 -1
  44. package/package/components/ShareModal.svelte +236 -98
  45. package/package/components/SuperadminSettingsInner.svelte +362 -315
  46. package/package/components/UserOffboardingModal.svelte +238 -0
  47. package/package/components/UserOffboardingModal.svelte.d.ts +10 -0
  48. package/package/components/WorkspaceDeployLayout.svelte +3 -3
  49. package/package/components/WorkspaceDeployLayout.svelte.d.ts +1 -0
  50. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptRunnableByPath.svelte +4 -2
  51. package/package/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte +12 -0
  52. package/package/components/assets/AssetsDropdownButton.svelte +1 -1
  53. package/package/components/common/confirmationModal/ConfirmationModal.svelte +1 -1
  54. package/package/components/common/table/AppRow.svelte +3 -3
  55. package/package/components/common/table/FlowRow.svelte +3 -3
  56. package/package/components/common/table/RawAppRow.svelte +4 -4
  57. package/package/components/common/table/Row.svelte +6 -2
  58. package/package/components/common/table/ScriptRow.svelte +11 -3
  59. package/package/components/copilot/chat/AIChatManager.svelte.js +2 -2
  60. package/package/components/copilot/chat/anthropic.d.ts +7 -1
  61. package/package/components/copilot/chat/anthropic.js +5 -2
  62. package/package/components/copilot/chat/app/core.js +129 -1
  63. package/package/components/copilot/chat/app/core.test.js +192 -0
  64. package/package/components/copilot/chat/chatLoop.d.ts +3 -0
  65. package/package/components/copilot/chat/chatLoop.js +13 -5
  66. package/package/components/copilot/chat/flow/FlowAIChat.svelte +55 -76
  67. package/package/components/copilot/chat/flow/core.d.ts +13 -3
  68. package/package/components/copilot/chat/flow/core.js +467 -116
  69. package/package/components/copilot/chat/flow/helperUtils.d.ts +19 -0
  70. package/package/components/copilot/chat/flow/helperUtils.js +68 -0
  71. package/package/components/copilot/chat/flow/helperUtils.test.js +116 -0
  72. package/package/components/copilot/chat/flow/inlineScriptsUtils.d.ts +5 -24
  73. package/package/components/copilot/chat/flow/inlineScriptsUtils.js +30 -55
  74. package/package/components/copilot/chat/flow/utils.test.js +59 -0
  75. package/package/components/copilot/chat/openai-responses.d.ts +7 -1
  76. package/package/components/copilot/chat/openai-responses.js +5 -2
  77. package/package/components/copilot/chat/shared.d.ts +1 -2
  78. package/package/components/copilot/chat/shared.js +94 -52
  79. package/package/components/copilot/chat/tokenUsage.d.ts +23 -0
  80. package/package/components/copilot/chat/tokenUsage.js +42 -0
  81. package/package/components/copilot/lib.d.ts +5 -1
  82. package/package/components/copilot/lib.js +21 -5
  83. package/package/components/deploymentRequest/DeploymentRequestPanel.svelte +337 -0
  84. package/package/components/deploymentRequest/DeploymentRequestPanel.svelte.d.ts +15 -0
  85. package/package/components/details/CopyableCodeBlock.svelte +18 -8
  86. package/package/components/details/CopyableCodeBlock.svelte.d.ts +1 -0
  87. package/package/components/flows/FlowAssetsHandler.svelte +19 -21
  88. package/package/components/flows/agentToolTree.d.ts +17 -0
  89. package/package/components/flows/agentToolTree.js +114 -0
  90. package/package/components/flows/agentToolTree.test.d.ts +1 -0
  91. package/package/components/flows/agentToolTree.test.js +86 -0
  92. package/package/components/flows/agentToolUtils.d.ts +0 -5
  93. package/package/components/flows/agentToolUtils.js +0 -49
  94. package/package/components/flows/content/FlowLoop.svelte +7 -4
  95. package/package/components/flows/content/FlowModuleDeleteAfterUse.svelte +15 -7
  96. package/package/components/flows/content/FlowSettings.svelte +29 -0
  97. package/package/components/flows/dfs.d.ts +6 -2
  98. package/package/components/flows/dfs.js +19 -11
  99. package/package/components/flows/flowDeleteController.d.ts +32 -0
  100. package/package/components/flows/flowDeleteController.js +54 -0
  101. package/package/components/flows/flowDeleteController.test.d.ts +1 -0
  102. package/package/components/flows/flowDeleteController.test.js +121 -0
  103. package/package/components/flows/flowDeleteUtils.d.ts +48 -0
  104. package/package/components/flows/flowDeleteUtils.js +150 -0
  105. package/package/components/flows/flowDeleteUtils.test.d.ts +1 -0
  106. package/package/components/flows/flowDeleteUtils.test.js +131 -0
  107. package/package/components/flows/flowDiff.d.ts +2 -47
  108. package/package/components/flows/flowDiff.js +16 -293
  109. package/package/components/flows/flowDiff.testUtils.d.ts +8 -0
  110. package/package/components/flows/flowDiff.testUtils.js +26 -0
  111. package/package/components/flows/flowDiffManager.svelte.js +20 -75
  112. package/package/components/flows/flowDiffManager.svelte.test.js +103 -2
  113. package/package/components/flows/flowExplorer.d.ts +4 -0
  114. package/package/components/flows/flowExplorer.js +7 -30
  115. package/package/components/flows/flowState.d.ts +1 -0
  116. package/package/components/flows/flowStateUtils.svelte.js +6 -1
  117. package/package/components/flows/flowTree.d.ts +91 -0
  118. package/package/components/flows/flowTree.js +326 -0
  119. package/package/components/flows/flowTree.test.d.ts +1 -0
  120. package/package/components/flows/flowTree.test.js +236 -0
  121. package/package/components/flows/map/FlowJobsMenu.svelte +36 -30
  122. package/package/components/flows/map/FlowModuleSchemaItem.svelte +1 -1
  123. package/package/components/flows/map/FlowModuleSchemaMap.svelte +70 -227
  124. package/package/components/flows/map/FlowModuleSchemaMap.svelte.d.ts +0 -2
  125. package/package/components/flows/pickers/PickHubScriptQuick.svelte +2 -2
  126. package/package/components/flows/previousResults.js +13 -41
  127. package/package/components/flows/previousResults.test.d.ts +1 -0
  128. package/package/components/flows/previousResults.test.js +65 -0
  129. package/package/components/flows/propPicker/OutputPicker.svelte +2 -1
  130. package/package/components/flows/propPicker/OutputPickerInner.svelte +41 -4
  131. package/package/components/flows/propPicker/StepHistory.svelte +9 -1
  132. package/package/components/git_sync/GitSyncContext.svelte.js +11 -5
  133. package/package/components/git_sync/GitSyncRepositoryCard.svelte +2 -29
  134. package/package/components/git_sync/PullWorkspaceModal.svelte +6 -7
  135. package/package/components/graph/FlowGraphV2.svelte +2 -2
  136. package/package/components/graph/FlowGraphV2.svelte.d.ts +1 -0
  137. package/package/components/graph/groupedModulesProxy.svelte.d.ts +10 -0
  138. package/package/components/graph/groupedModulesProxy.svelte.js +17 -1
  139. package/package/components/graph/renderers/triggers/TriggersBadge.svelte +5 -2
  140. package/package/components/home/HomeConnectDrawer.svelte +125 -0
  141. package/package/components/home/HomeConnectDrawer.svelte.d.ts +5 -0
  142. package/package/components/icons/GithubIcon.svelte +4 -4
  143. package/package/components/icons/GithubIcon.svelte.d.ts +5 -2
  144. package/package/components/instanceSettings/ExternalJwtTokens.svelte +85 -0
  145. package/package/components/instanceSettings/ExternalJwtTokens.svelte.d.ts +12 -0
  146. package/package/components/instanceSettings/GhesAppSettings.svelte +17 -0
  147. package/package/components/instanceSettings/IndexerMemorySettings.svelte +56 -29
  148. package/package/components/instanceSettings/SecretBackendConfig.svelte +9 -2
  149. package/package/components/instanceSettings.d.ts +1 -0
  150. package/package/components/instanceSettings.js +42 -8
  151. package/package/components/offboarding-utils.d.ts +11 -0
  152. package/package/components/offboarding-utils.js +100 -0
  153. package/package/components/raw_apps/RawAppDataTableDrawer.svelte +1 -1
  154. package/package/components/raw_apps/RawAppEditor.svelte +27 -0
  155. package/package/components/raw_apps/RawAppEditorHeader.svelte +6 -1
  156. package/package/components/raw_apps/RawAppEditorHeader.svelte.d.ts +1 -0
  157. package/package/components/raw_apps/RawAppYamlEditor.svelte +81 -0
  158. package/package/components/raw_apps/RawAppYamlEditor.svelte.d.ts +20 -0
  159. package/package/components/raw_apps/datatableUtils.svelte.js +1 -1
  160. package/package/components/runs/runsFilter.d.ts +1 -1
  161. package/package/components/script_builder.d.ts +1 -1
  162. package/package/components/select/Select.svelte +2 -1
  163. package/package/components/select/Select.svelte.d.ts +1 -0
  164. package/package/components/settings/CreateToken.svelte +113 -64
  165. package/package/components/settings/CreateToken.svelte.d.ts +3 -0
  166. package/package/components/settings/WorkspaceUserSettings.svelte +34 -28
  167. package/package/components/sidebar/SidebarContent.svelte +58 -2
  168. package/package/components/sidebar/WorkspaceMenu.svelte +8 -4
  169. package/package/components/triggers/AddTriggersButton.svelte +11 -0
  170. package/package/components/triggers/PermissionedAsLine.svelte +37 -3
  171. package/package/components/triggers/PermissionedAsLine.svelte.d.ts +6 -0
  172. package/package/components/triggers/TriggersEditor.svelte +5 -1
  173. package/package/components/triggers/TriggersWrapper.svelte +10 -0
  174. package/package/components/triggers/email/EmailTriggerEditorInner.svelte +13 -11
  175. package/package/components/triggers/gcp/GcpTriggerEditorInner.svelte +13 -11
  176. package/package/components/triggers/http/RouteEditorConfigSection.svelte +15 -7
  177. package/package/components/triggers/http/RouteEditorInner.svelte +14 -14
  178. package/package/components/triggers/http/RoutesGenerator.svelte +6 -1
  179. package/package/components/triggers/http/RoutesPanel.svelte +1 -1
  180. package/package/components/triggers/http/utils.d.ts +1 -1
  181. package/package/components/triggers/http/utils.js +2 -2
  182. package/package/components/triggers/kafka/KafkaTriggerEditorInner.svelte +13 -11
  183. package/package/components/triggers/mqtt/MqttTriggerEditorInner.svelte +13 -11
  184. package/package/components/triggers/native/NativeTriggerEditor.svelte +3 -0
  185. package/package/components/triggers/native/services/github/GitHubTriggerForm.svelte +118 -0
  186. package/package/components/triggers/native/services/github/GitHubTriggerForm.svelte.d.ts +17 -0
  187. package/package/components/triggers/native/utils.js +14 -0
  188. package/package/components/triggers/nats/NatsTriggerEditor.svelte.d.ts +4 -3
  189. package/package/components/triggers/nats/NatsTriggerEditorInner.svelte +13 -11
  190. package/package/components/triggers/postgres/PostgresTriggerEditor.svelte.d.ts +4 -3
  191. package/package/components/triggers/postgres/PostgresTriggerEditorInner.svelte +13 -11
  192. package/package/components/triggers/schedules/ScheduleEditorInner.svelte +13 -11
  193. package/package/components/triggers/sqs/SqsTriggerEditor.svelte.d.ts +4 -3
  194. package/package/components/triggers/sqs/SqsTriggerEditorInner.svelte +13 -11
  195. package/package/components/triggers/triggers.svelte.js +1 -0
  196. package/package/components/triggers/utils.js +27 -6
  197. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +13 -11
  198. package/package/components/triggers.d.ts +1 -1
  199. package/package/components/useFolderDefaultPermissionedAs.svelte.d.ts +13 -0
  200. package/package/components/useFolderDefaultPermissionedAs.svelte.js +63 -0
  201. package/package/components/workspaceSettings/CreateWorkspace.svelte +16 -677
  202. package/package/components/workspaceSettings/CreateWorkspaceInner.svelte +604 -0
  203. package/package/components/workspaceSettings/CreateWorkspaceInner.svelte.d.ts +7 -0
  204. package/package/components/workspaceSettings/CustomInstanceDbSelect.svelte +27 -25
  205. package/package/components/workspaceSettings/CustomInstanceDbWizardModal.svelte +46 -8
  206. package/package/components/workspaceSettings/DataTableSettings.svelte +27 -22
  207. package/package/components/workspaceSettings/DucklakeSettings.svelte +1 -1
  208. package/package/components/workspaceSettings/ForkDatatableSection.svelte +228 -0
  209. package/package/components/workspaceSettings/ForkDatatableSection.svelte.d.ts +28 -0
  210. package/package/components/workspaceSettings/GitSyncFilterSettings.svelte +8 -2
  211. package/package/components/workspaceSettings/RulesetEditor.svelte +27 -2
  212. package/package/components/workspaceSettings/VolumeStorageSettings.svelte +1 -1
  213. package/package/components/workspaceSettings/WorkspaceIntegrations.svelte +17 -1
  214. package/package/consts.d.ts +3 -0
  215. package/package/consts.js +10 -0
  216. package/package/gen/core/OpenAPI.js +1 -1
  217. package/package/gen/schemas.gen.d.ts +485 -19
  218. package/package/gen/schemas.gen.js +489 -20
  219. package/package/gen/services.gen.d.ts +229 -2
  220. package/package/gen/services.gen.js +463 -1
  221. package/package/gen/types.gen.d.ts +866 -29
  222. package/package/githubApp.js +5 -1
  223. package/package/hubPaths.json +1 -4
  224. package/package/infer.js +13 -1
  225. package/package/infer.svelte.js +10 -1
  226. package/package/monaco_workers/sqlTypePlugin.worker.d.ts +10 -0
  227. package/package/monaco_workers/sqlTypePlugin.worker.js +39 -0
  228. package/package/script_helpers.d.ts +8 -2
  229. package/package/script_helpers.js +14 -0
  230. package/package/stores.d.ts +4 -0
  231. package/package/stores.js +1 -0
  232. package/package/system_prompts/prompts.d.ts +4 -3
  233. package/package/system_prompts/prompts.js +270 -20
  234. package/package/templates/ci_test_bun.ts.template +19 -0
  235. package/package/templates/ci_test_python.py.template +18 -0
  236. package/package/utils_workspace_deploy.d.ts +8 -8
  237. package/package/utils_workspace_deploy.js +86 -420
  238. package/package.json +3 -3
  239. package/package/components/copilot/chat/__tests__/app/appChat.eval.test.js +0 -153
  240. package/package/components/copilot/chat/__tests__/app/appEvalComparison.d.ts +0 -21
  241. package/package/components/copilot/chat/__tests__/app/appEvalComparison.js +0 -136
  242. package/package/components/copilot/chat/__tests__/app/appEvalHelpers.d.ts +0 -15
  243. package/package/components/copilot/chat/__tests__/app/appEvalHelpers.js +0 -107
  244. package/package/components/copilot/chat/__tests__/app/appEvalRunner.d.ts +0 -50
  245. package/package/components/copilot/chat/__tests__/app/appEvalRunner.js +0 -93
  246. package/package/components/copilot/chat/__tests__/app/appFixtureLoader.d.ts +0 -29
  247. package/package/components/copilot/chat/__tests__/app/appFixtureLoader.js +0 -134
  248. package/package/components/copilot/chat/__tests__/app/appResultsWriter.d.ts +0 -30
  249. package/package/components/copilot/chat/__tests__/app/appResultsWriter.js +0 -197
  250. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/createFolder/main.d.ts +0 -10
  251. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/createFolder/main.js +0 -9
  252. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/createFolder/meta.json +0 -4
  253. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/deleteItem/main.d.ts +0 -6
  254. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/deleteItem/main.js +0 -5
  255. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/deleteItem/meta.json +0 -4
  256. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/listFiles/main.d.ts +0 -12
  257. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/listFiles/main.js +0 -14
  258. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/listFiles/meta.json +0 -4
  259. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/listFolders/main.d.ts +0 -8
  260. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/listFolders/main.js +0 -25
  261. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/listFolders/meta.json +0 -4
  262. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/moveItem/main.d.ts +0 -7
  263. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/moveItem/main.js +0 -5
  264. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/moveItem/meta.json +0 -4
  265. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/renameItem/main.d.ts +0 -8
  266. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/renameItem/main.js +0 -5
  267. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/renameItem/meta.json +0 -4
  268. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/Breadcrumb.d.ts +0 -10
  269. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/Breadcrumb.tsx +0 -26
  270. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/FileItem.d.ts +0 -10
  271. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/FileItem.tsx +0 -79
  272. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/FileList.d.ts +0 -10
  273. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/FileList.tsx +0 -46
  274. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/FolderTree.d.ts +0 -10
  275. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/FolderTree.tsx +0 -56
  276. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/Toolbar.d.ts +0 -6
  277. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/Toolbar.tsx +0 -59
  278. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/index.d.ts +0 -16
  279. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/index.tsx +0 -119
  280. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/addToCart/main.d.ts +0 -15
  281. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/addToCart/main.js +0 -14
  282. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/addToCart/meta.json +0 -4
  283. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/calculateTotal/main.d.ts +0 -14
  284. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/calculateTotal/main.js +0 -5
  285. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/calculateTotal/meta.json +0 -4
  286. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/getProducts/main.d.ts +0 -6
  287. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/getProducts/main.js +0 -41
  288. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/getProducts/meta.json +0 -4
  289. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/removeFromCart/main.d.ts +0 -15
  290. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/removeFromCart/main.js +0 -3
  291. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/removeFromCart/meta.json +0 -4
  292. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/components/Cart.d.ts +0 -9
  293. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/components/Cart.tsx +0 -51
  294. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/components/ProductCard.d.ts +0 -8
  295. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/components/ProductCard.tsx +0 -27
  296. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/components/ProductList.d.ts +0 -8
  297. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/components/ProductList.tsx +0 -18
  298. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/index.d.ts +0 -12
  299. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/index.tsx +0 -81
  300. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/backend/decrementCounter/main.d.ts +0 -3
  301. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/backend/decrementCounter/main.js +0 -3
  302. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/backend/decrementCounter/meta.json +0 -4
  303. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/backend/incrementCounter/main.d.ts +0 -3
  304. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/backend/incrementCounter/main.js +0 -3
  305. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/backend/incrementCounter/meta.json +0 -4
  306. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/frontend/index.d.ts +0 -2
  307. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/frontend/index.tsx +0 -38
  308. package/package/components/copilot/chat/__tests__/app/variants/baseline.d.ts +0 -6
  309. package/package/components/copilot/chat/__tests__/app/variants/baseline.js +0 -10
  310. package/package/components/copilot/chat/__tests__/app/variants/index.d.ts +0 -3
  311. package/package/components/copilot/chat/__tests__/app/variants/index.js +0 -3
  312. package/package/components/copilot/chat/__tests__/app/variants/streamlined.d.ts +0 -6
  313. package/package/components/copilot/chat/__tests__/app/variants/streamlined.js +0 -137
  314. package/package/components/copilot/chat/__tests__/flow/expected/test1.json +0 -134
  315. package/package/components/copilot/chat/__tests__/flow/expected/test2.json +0 -183
  316. package/package/components/copilot/chat/__tests__/flow/expected/test3.json +0 -204
  317. package/package/components/copilot/chat/__tests__/flow/expected/test4.json +0 -175
  318. package/package/components/copilot/chat/__tests__/flow/expected/test5_modify_simple.json +0 -68
  319. package/package/components/copilot/chat/__tests__/flow/expected/test6_modify_medium.json +0 -142
  320. package/package/components/copilot/chat/__tests__/flow/expected/test7_modify_complex.json +0 -136
  321. package/package/components/copilot/chat/__tests__/flow/flowChat.eval.test.js +0 -294
  322. package/package/components/copilot/chat/__tests__/flow/flowEvalComparison.d.ts +0 -17
  323. package/package/components/copilot/chat/__tests__/flow/flowEvalComparison.js +0 -49
  324. package/package/components/copilot/chat/__tests__/flow/flowEvalHelpers.d.ts +0 -12
  325. package/package/components/copilot/chat/__tests__/flow/flowEvalHelpers.js +0 -79
  326. package/package/components/copilot/chat/__tests__/flow/flowEvalRunner.d.ts +0 -50
  327. package/package/components/copilot/chat/__tests__/flow/flowEvalRunner.js +0 -102
  328. package/package/components/copilot/chat/__tests__/flow/initial/test5_initial.json +0 -53
  329. package/package/components/copilot/chat/__tests__/flow/initial/test6_initial.json +0 -68
  330. package/package/components/copilot/chat/__tests__/flow/initial/test7_initial.json +0 -120
  331. package/package/components/copilot/chat/__tests__/flow/variants/baseline.d.ts +0 -6
  332. package/package/components/copilot/chat/__tests__/flow/variants/baseline.js +0 -10
  333. package/package/components/copilot/chat/__tests__/flow/variants/index.d.ts +0 -3
  334. package/package/components/copilot/chat/__tests__/flow/variants/index.js +0 -3
  335. package/package/components/copilot/chat/__tests__/flow/variants/minimal-single-tool.d.ts +0 -15
  336. package/package/components/copilot/chat/__tests__/flow/variants/minimal-single-tool.js +0 -388
  337. package/package/components/copilot/chat/__tests__/shared/baseEvalRunner.d.ts +0 -45
  338. package/package/components/copilot/chat/__tests__/shared/baseEvalRunner.js +0 -121
  339. package/package/components/copilot/chat/__tests__/shared/baseLLMEvaluator.d.ts +0 -28
  340. package/package/components/copilot/chat/__tests__/shared/baseLLMEvaluator.js +0 -96
  341. package/package/components/copilot/chat/__tests__/shared/baseResultsWriter.d.ts +0 -32
  342. package/package/components/copilot/chat/__tests__/shared/baseResultsWriter.js +0 -130
  343. package/package/components/copilot/chat/__tests__/shared/baseVariants.d.ts +0 -45
  344. package/package/components/copilot/chat/__tests__/shared/baseVariants.js +0 -57
  345. package/package/components/copilot/chat/__tests__/shared/index.d.ts +0 -10
  346. package/package/components/copilot/chat/__tests__/shared/index.js +0 -5
  347. package/package/components/copilot/chat/__tests__/shared/types.d.ts +0 -105
  348. package/package/components/copilot/chat/__tests__/shared/types.js +0 -9
  349. package/package/components/copilot/chat/flow/utils.d.ts +0 -14
  350. package/package/components/copilot/chat/flow/utils.js +0 -108
  351. package/package/components/flows/agentToolUtils.test.js +0 -55
  352. /package/package/components/copilot/chat/{__tests__/app/appChat.eval.test.d.ts → app/core.test.d.ts} +0 -0
  353. /package/package/components/copilot/chat/{__tests__/flow/flowChat.eval.test.d.ts → flow/helperUtils.test.d.ts} +0 -0
  354. /package/package/components/{flows/agentToolUtils.test.d.ts → copilot/chat/flow/utils.test.d.ts} +0 -0
@@ -1,24 +1,35 @@
1
- <script lang="ts">import { AlertTriangle, ArrowDown, ArrowDownRight, ArrowRight, ArrowUp, ArrowUpRight, Building, DiffIcon, FileJson, GitFork, Loader2, Trash2, Upload } from 'lucide-svelte';
1
+ <script lang="ts">import { AlertTriangle, ArrowDown, ArrowDownRight, ArrowRight, ArrowUp, ArrowUpRight, Building, CircleCheck, CircleX, DiffIcon, Eye, FileJson, FlaskConical, GitFork, Loader2, Trash2, UserPlus } from 'lucide-svelte';
2
2
  import { Alert, Badge } from './common';
3
3
  import { AppService, EmailTriggerService, FlowService, FolderService, GcpTriggerService, HttpTriggerService, KafkaTriggerService, MqttTriggerService, NatsTriggerService, PostgresTriggerService, ScheduleService, ScriptService, SqsTriggerService, UserService, WebsocketTriggerService, WorkspaceService } from '../gen';
4
4
  import Button from './common/button/Button.svelte';
5
5
  import ConfirmationModal from './common/confirmationModal/ConfirmationModal.svelte';
6
- import Row from './common/table/Row.svelte';
7
6
  import DiffDrawer from './DiffDrawer.svelte';
8
- import DeployWorkspaceDrawer from './DeployWorkspaceDrawer.svelte';
9
7
  import ParentWorkspaceProtectionAlert from './ParentWorkspaceProtectionAlert.svelte';
8
+ import ScheduleEditor from './triggers/schedules/ScheduleEditor.svelte';
9
+ import RouteEditor from './triggers/http/RouteEditor.svelte';
10
+ import WebsocketTriggerEditor from './triggers/websocket/WebsocketTriggerEditor.svelte';
11
+ import KafkaTriggerEditor from './triggers/kafka/KafkaTriggerEditor.svelte';
12
+ import PostgresTriggerEditor from './triggers/postgres/PostgresTriggerEditor.svelte';
13
+ import NatsTriggerEditor from './triggers/nats/NatsTriggerEditor.svelte';
14
+ import MqttTriggerEditor from './triggers/mqtt/MqttTriggerEditor.svelte';
15
+ import SqsTriggerEditor from './triggers/sqs/SqsTriggerEditor.svelte';
16
+ import GcpTriggerEditor from './triggers/gcp/GcpTriggerEditor.svelte';
17
+ import EmailTriggerEditor from './triggers/email/EmailTriggerEditor.svelte';
10
18
  import { userWorkspaces, workspaceStore } from '../stores';
11
- import { deployItem, getItemValue, getOnBehalfOf } from '../utils_workspace_deploy';
19
+ import { deployItem, deleteItemInWorkspace, getItemValue, getOnBehalfOf } from '../utils_workspace_deploy';
12
20
  import Tooltip from './Tooltip.svelte';
13
21
  import OnBehalfOfSelector, { needsOnBehalfOfSelection } from './OnBehalfOfSelector.svelte';
14
22
  import { sendUserToast } from '../toast';
15
23
  import { deepEqual } from 'fast-equals';
16
24
  import WorkspaceDeployLayout from './WorkspaceDeployLayout.svelte';
25
+ import DeploymentRequestPanel from './deploymentRequest/DeploymentRequestPanel.svelte';
26
+ import { userStore } from '../stores';
17
27
  import { triggerDisplayNamesMap, triggerKindToTriggerType } from './triggers/utils';
18
28
  import { getEmailAddress, getEmailDomain } from './triggers/email/utils';
19
29
  import { base } from '../base';
20
30
  import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte';
21
31
  import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte';
32
+ import DatatableSchemaDiff from './DatatableSchemaDiff.svelte';
22
33
  let { currentWorkspaceId, parentWorkspaceId, comparison } = $props();
23
34
  let currentWorkspaceInfo = $derived($userWorkspaces.find((w) => w.id == currentWorkspaceId));
24
35
  let parentWorkspaceInfo = $derived($userWorkspaces.find((w) => w.id == parentWorkspaceId));
@@ -177,7 +188,10 @@ async function showDiff(kind, path) {
177
188
  });
178
189
  }
179
190
  }
180
- let allSelected = $derived(selectedItems.length == selectableDiffs.length);
191
+ // All *diff* items selected. Trigger items are opt-in and don't count
192
+ // toward "all selected" — see item merge below in deployableItems.
193
+ let allSelected = $derived(selectableDiffs.length > 0 &&
194
+ selectableDiffs.every((d) => selectedItems.includes(getItemKey(d))));
181
195
  async function selectAll() {
182
196
  selectedItems = selectableDiffs
183
197
  .map((d) => getItemKey(d))
@@ -196,21 +210,45 @@ const deploymentStatus = $state({});
196
210
  function getWorkspacedKey(workspace, key) {
197
211
  return `${workspace}/${key}`;
198
212
  }
199
- async function deploy(kind, path, workspaceToDeployTo, workspaceFrom, statusPath) {
200
- deploymentStatus[statusPath] = { status: 'loading' };
201
- const result = await deployItem({
202
- kind,
203
- path,
204
- workspaceFrom,
205
- workspaceTo: workspaceToDeployTo,
206
- onBehalfOf: getOnBehalfOfForDeploy(statusPath, kind)
207
- });
213
+ async function deploy(kind, path, workspaceToDeployTo, workspaceFrom, statusKey, trigger) {
214
+ deploymentStatus[statusKey] = { status: 'loading' };
215
+ // Check if the item was deleted in the source workspace.
216
+ // If so, archive/delete it in the target workspace instead of copying.
217
+ const diff = comparison?.diffs.find((d) => getItemKey(d) === statusKey);
218
+ const itemDeletedInSource = diff
219
+ ? mergeIntoParent
220
+ ? diff.exists_in_fork === false
221
+ : diff.exists_in_source === false
222
+ : false;
223
+ let result;
224
+ if (itemDeletedInSource) {
225
+ result = await deleteItemInWorkspace(kind, path, workspaceToDeployTo);
226
+ }
227
+ else if (trigger) {
228
+ result = await deployItem({
229
+ kind: 'trigger',
230
+ path,
231
+ workspaceFrom,
232
+ workspaceTo: workspaceToDeployTo,
233
+ additionalInformation: { triggers: { kind: trigger.triggerKind } },
234
+ onBehalfOf: getOnBehalfOfForDeploy(statusKey, 'trigger')
235
+ });
236
+ }
237
+ else {
238
+ result = await deployItem({
239
+ kind,
240
+ path,
241
+ workspaceFrom,
242
+ workspaceTo: workspaceToDeployTo,
243
+ onBehalfOf: getOnBehalfOfForDeploy(statusKey, kind)
244
+ });
245
+ }
208
246
  if (result.success) {
209
- deploymentStatus[statusPath] = { status: 'deployed' };
247
+ deploymentStatus[statusKey] = { status: 'deployed' };
210
248
  }
211
249
  else {
212
- deploymentStatus[statusPath] = { status: 'failed', error: result.error };
213
- sendUserToast(`Failed to deploy ${statusPath}: ${result.error}`);
250
+ deploymentStatus[statusKey] = { status: 'failed', error: result.error };
251
+ sendUserToast(`Failed to deploy ${statusKey}: ${result.error}`);
214
252
  }
215
253
  }
216
254
  let deploymentErrorMessage = $state('');
@@ -254,24 +292,43 @@ async function deployChanges() {
254
292
  return 1;
255
293
  return 0;
256
294
  });
295
+ let anyFailed = false;
257
296
  for (const itemKey of sortedItems) {
258
- const diff = selectableDiffs.find((d) => itemKey == getItemKey(d));
259
- if (!diff) {
297
+ const deployable = deployableItems.find((d) => d.key === itemKey);
298
+ if (!deployable) {
260
299
  sendUserToast(`Undeployable item: ${itemKey}`, true);
261
300
  continue;
262
301
  }
263
- if (mergeIntoParent) {
264
- await deploy(diff.kind, diff.path, parent, current, itemKey);
265
- }
266
- else {
267
- await deploy(diff.kind, diff.path, current, parent, itemKey);
302
+ const to = mergeIntoParent ? parent : current;
303
+ const from = mergeIntoParent ? current : parent;
304
+ await deploy(deployable.kind, deployable.path, to, from, itemKey, deployable.trigger);
305
+ if (deploymentStatus[itemKey]?.status === 'failed') {
306
+ anyFailed = true;
268
307
  }
269
308
  }
270
309
  deploying = false;
271
310
  deselectAll();
311
+ // If every selected item deployed cleanly and the direction was
312
+ // merge-into-parent, close any open deployment request for this fork.
313
+ if (!anyFailed && mergeIntoParent) {
314
+ try {
315
+ const open = await WorkspaceService.getOpenDeploymentRequest({
316
+ workspace: currentWorkspaceId
317
+ });
318
+ if (open) {
319
+ await WorkspaceService.closeDeploymentRequestMerged({
320
+ workspace: currentWorkspaceId,
321
+ id: open.id
322
+ });
323
+ deploymentRequestPanel?.refresh();
324
+ }
325
+ }
326
+ catch (e) {
327
+ console.error('Failed to close open deployment request after merge', e);
328
+ }
329
+ }
272
330
  }
273
- function toggleItem(diff) {
274
- const key = getItemKey(diff);
331
+ function toggleKey(key) {
275
332
  if (selectedItems.includes(key)) {
276
333
  selectedItems = selectedItems.filter((i) => i !== key);
277
334
  }
@@ -336,24 +393,143 @@ $effect(() => {
336
393
  [selectedItems, mergeIntoParent];
337
394
  allowBehindChangesOverride = false;
338
395
  });
339
- // Transform diffs to deployable item format for the shared layout
340
- let deployableItems = $derived((comparison?.diffs ?? [])
341
- .filter((diff) => {
342
- const key = getItemKey(diff);
343
- const isSelectable = selectableDiffs.includes(diff);
344
- const isDeployedAndIrrelevant = deploymentStatus[key]?.status === 'deployed' && !isSelectable;
345
- return !isDeployedAndIrrelevant;
346
- })
347
- .map((diff) => ({
348
- key: getItemKey(diff),
349
- path: diff.path,
350
- kind: diff.kind,
351
- diff
352
- })));
396
+ function getTriggerKey(trigger) {
397
+ return `trigger:${trigger.triggerKind}:${trigger.path}`;
398
+ }
399
+ // Transform diffs + fork triggers to deployable item format for the
400
+ // shared layout. Triggers render as inline rows alongside diff items;
401
+ // they carry no ahead/behind info and are selectable à la carte.
402
+ let deployableItems = $derived.by(() => {
403
+ const diffItems = (comparison?.diffs ?? [])
404
+ .filter((diff) => {
405
+ const key = getItemKey(diff);
406
+ const isSelectable = selectableDiffs.includes(diff);
407
+ const isDeployedAndIrrelevant = deploymentStatus[key]?.status === 'deployed' && !isSelectable;
408
+ return !isDeployedAndIrrelevant;
409
+ })
410
+ .map((diff) => ({
411
+ key: getItemKey(diff),
412
+ path: diff.path,
413
+ kind: diff.kind,
414
+ diff,
415
+ trigger: undefined
416
+ }));
417
+ const triggerItems = forkTriggers
418
+ .filter((t) => {
419
+ const key = getTriggerKey(t);
420
+ return deploymentStatus[key]?.status !== 'deployed';
421
+ })
422
+ .map((trigger) => ({
423
+ key: getTriggerKey(trigger),
424
+ path: trigger.path,
425
+ kind: 'trigger',
426
+ diff: undefined,
427
+ trigger
428
+ }));
429
+ return [...diffItems, ...triggerItems];
430
+ });
431
+ let ciTestResults = $state({});
432
+ async function fetchCiTests() {
433
+ if (!comparison?.diffs || !currentWorkspaceId)
434
+ return;
435
+ const items = comparison.diffs
436
+ .filter((d) => d.kind === 'script' || d.kind === 'flow' || d.kind === 'resource')
437
+ .map((d) => ({ path: d.path, kind: d.kind }));
438
+ if (items.length === 0)
439
+ return;
440
+ try {
441
+ ciTestResults = await ScriptService.getCiTestResultsBatch({
442
+ workspace: currentWorkspaceId,
443
+ requestBody: { items }
444
+ });
445
+ }
446
+ catch (e) {
447
+ console.error('Failed to fetch CI test results:', e);
448
+ }
449
+ }
450
+ $effect(() => {
451
+ if (comparison && comparison.diffs.length > 0) {
452
+ fetchCiTests();
453
+ }
454
+ });
455
+ function getCiTestStatus(diff) {
456
+ const key = `${diff.kind}:${diff.path}`;
457
+ const results = ciTestResults[key];
458
+ if (!results || results.length === 0)
459
+ return null;
460
+ if (results.some((r) => r.status === 'failure' || r.status === 'canceled'))
461
+ return 'fail';
462
+ if (results.some((r) => r.status === 'running' || (r.job_id && !r.status)))
463
+ return 'running';
464
+ if (results.every((r) => r.status === 'success'))
465
+ return 'pass';
466
+ return null;
467
+ }
468
+ // Deduplicated list of all CI tests across all items
469
+ let allCiTests = $derived.by(() => {
470
+ const seen = new Map();
471
+ for (const results of Object.values(ciTestResults)) {
472
+ for (const r of results) {
473
+ const existing = seen.get(r.test_script_path);
474
+ if (!existing ||
475
+ (r.started_at && (!existing.started_at || r.started_at > existing.started_at))) {
476
+ seen.set(r.test_script_path, r);
477
+ }
478
+ }
479
+ }
480
+ return [...seen.values()];
481
+ });
353
482
  let forkTriggers = $state([]);
354
- let loadingTriggers = $state(true);
355
- let deploymentDrawer = $state(undefined);
356
483
  let triggerToDelete = $state(undefined);
484
+ let deploymentRequestPanel = $state(undefined);
485
+ let hasOpenDeploymentRequest = $state(false);
486
+ // Trigger detail drawer refs — one per trigger kind. Each is lazy-mounted
487
+ // on first openEdit() call, so having them all sit here is cheap.
488
+ let scheduleEditor = $state();
489
+ let routeEditor = $state();
490
+ let websocketEditor = $state();
491
+ let kafkaEditor = $state();
492
+ let postgresEditor = $state();
493
+ let natsEditor = $state();
494
+ let mqttEditor = $state();
495
+ let sqsEditor = $state();
496
+ let gcpEditor = $state();
497
+ let emailEditor = $state();
498
+ function openTriggerDetails(trigger) {
499
+ const isFlow = trigger.isFlow;
500
+ switch (trigger.triggerKind) {
501
+ case 'schedules':
502
+ scheduleEditor?.openEdit(trigger.path, isFlow);
503
+ break;
504
+ case 'routes':
505
+ routeEditor?.openEdit(trigger.path, isFlow);
506
+ break;
507
+ case 'websockets':
508
+ websocketEditor?.openEdit(trigger.path, isFlow);
509
+ break;
510
+ case 'kafka':
511
+ kafkaEditor?.openEdit(trigger.path, isFlow);
512
+ break;
513
+ case 'postgres':
514
+ postgresEditor?.openEdit(trigger.path, isFlow);
515
+ break;
516
+ case 'nats':
517
+ natsEditor?.openEdit(trigger.path, isFlow);
518
+ break;
519
+ case 'mqtt':
520
+ mqttEditor?.openEdit(trigger.path, isFlow);
521
+ break;
522
+ case 'sqs':
523
+ sqsEditor?.openEdit(trigger.path, isFlow);
524
+ break;
525
+ case 'gcp':
526
+ gcpEditor?.openEdit(trigger.path, isFlow);
527
+ break;
528
+ case 'emails':
529
+ emailEditor?.openEdit(trigger.path, isFlow);
530
+ break;
531
+ }
532
+ }
357
533
  /** Deployable trigger kinds and their list+delete services */
358
534
  const triggerServices = {
359
535
  schedules: {
@@ -477,7 +653,6 @@ const triggerServices = {
477
653
  };
478
654
  let emailDomain = $state(undefined);
479
655
  async function fetchAllTriggers() {
480
- loadingTriggers = true;
481
656
  try {
482
657
  emailDomain = await getEmailDomain();
483
658
  const entries = Object.values(triggerServices);
@@ -491,9 +666,6 @@ async function fetchAllTriggers() {
491
666
  console.error('Failed to fetch fork triggers:', e);
492
667
  forkTriggers = [];
493
668
  }
494
- finally {
495
- loadingTriggers = false;
496
- }
497
669
  }
498
670
  function deleteTrigger(trigger) {
499
671
  triggerToDelete = trigger;
@@ -522,22 +694,6 @@ function getTriggerDisplayName(triggerKind) {
522
694
  const triggerType = triggerKindToTriggerType(triggerKind);
523
695
  return triggerType ? triggerDisplayNamesMap[triggerType] : triggerKind;
524
696
  }
525
- const triggerKindToPagePath = {
526
- schedules: '/schedules',
527
- routes: '/routes',
528
- websockets: '/websocket_triggers',
529
- kafka: '/kafka_triggers',
530
- postgres: '/postgres_triggers',
531
- nats: '/nats_triggers',
532
- mqtt: '/mqtt_triggers',
533
- sqs: '/sqs_triggers',
534
- gcp: '/gcp_triggers',
535
- emails: '/email_triggers'
536
- };
537
- function getTriggerHref(triggerKind) {
538
- const pagePath = triggerKindToPagePath[triggerKind];
539
- return pagePath ? `${base}${pagePath}` : undefined;
540
- }
541
697
  // Fetch triggers when workspace is available
542
698
  $effect(() => {
543
699
  if (currentWorkspaceId) {
@@ -561,386 +717,438 @@ $effect(() => {
561
717
  {@const selectedConflicts = conflictingDiffs.filter((e) =>
562
718
  selectedItems.includes(getItemKey(e))
563
719
  ).length}
564
-
565
- <WorkspaceDeployLayout
566
- items={deployableItems}
567
- {selectedItems}
568
- {deploymentStatus}
569
- selectablePredicate={(item) => selectableDiffs.some((d) => getItemKey(d) === item.key)}
570
- {allSelected}
571
- onToggleItem={(item) => {
572
- const diff = comparison?.diffs.find((d) => getItemKey(d) === item.key)
573
- if (diff) toggleItem(diff)
574
- }}
575
- onSelectAll={selectAll}
576
- onDeselectAll={deselectAll}
577
- emptyMessage="No comparison data available"
578
- >
579
- {#snippet header()}
580
- <div class="flex items-center justify-between">
581
- <div
582
- class="flex flex-col gap-2 border bg-surface-tertiary w-full p-4 border-radius-5 rounded"
583
- >
584
- <div class="flex flex-row gap-1 items-center">
585
- <ToggleButtonGroup
586
- disabled={deploying}
587
- selected="deploy_to"
588
- onSelected={toggleDeploymentDirection}
589
- noWFull
590
- >
591
- {#snippet children({ item })}
592
- <ToggleButton
593
- value="deploy_to"
594
- label="Deploy to {parentWorkspaceId}"
595
- icon={ArrowUp}
596
- {item}
597
- />
598
- <ToggleButton value="update" label="Update current" icon={ArrowDown} {item} />
599
- {/snippet}
600
- </ToggleButtonGroup>
601
- {#if currentWorkspaceInfo && parentWorkspaceInfo}
602
- <Badge
603
- color="transparent"
604
- class="ml-5 font-semibold"
605
- title={mergeIntoParent ? currentWorkspaceInfo.name : parentWorkspaceInfo.name}
606
- >
607
- <span class="text-secondary">merge:</span>
608
- {#if mergeIntoParent}
609
- <GitFork size={14} />
610
- <span class="text-emphasis">{currentWorkspaceInfo.id}</span>
611
- {:else}
612
- <Building size={14} />
613
- <span class="text-emphasis">{parentWorkspaceInfo.id}</span>
614
- {/if}
615
- </Badge>
616
- <ArrowRight size={16} />
617
- <Badge
618
- color="transparent"
619
- class="font-semibold"
620
- title={!mergeIntoParent ? currentWorkspaceInfo.name : parentWorkspaceInfo.name}
621
- >
622
- <span class="text-secondary">into:</span>
623
- {#if !mergeIntoParent}
624
- <GitFork size={14} />
625
- <span class="text-emphasis">{currentWorkspaceInfo.id}</span>
626
- {:else}
627
- <Building size={14} />
628
- <span class="text-emphasis">{parentWorkspaceInfo.id}</span>
720
+ <div class="flex flex-col gap-4">
721
+ <div class="bg-surface-tertiary p-4 rounded-md border">
722
+ <WorkspaceDeployLayout
723
+ items={deployableItems}
724
+ {selectedItems}
725
+ {deploymentStatus}
726
+ selectablePredicate={(item) =>
727
+ item.trigger != null || selectableDiffs.some((d) => getItemKey(d) === item.key)}
728
+ {allSelected}
729
+ onToggleItem={(item) => toggleKey(item.key)}
730
+ onSelectAll={selectAll}
731
+ onDeselectAll={deselectAll}
732
+ emptyMessage="No comparison data available"
733
+ >
734
+ {#snippet header()}
735
+ <div class="flex items-center justify-between bg-surface-tertiary">
736
+ <div class="flex flex-col gap-2 w-full pb-4 border-b">
737
+ <div class="flex flex-wrap gap-1 items-center">
738
+ <ToggleButtonGroup
739
+ disabled={deploying}
740
+ selected="deploy_to"
741
+ onSelected={toggleDeploymentDirection}
742
+ noWFull
743
+ >
744
+ {#snippet children({ item })}
745
+ <ToggleButton
746
+ value="deploy_to"
747
+ label="Deploy to {parentWorkspaceId}"
748
+ icon={ArrowUp}
749
+ {item}
750
+ />
751
+ <ToggleButton value="update" label="Update current" icon={ArrowDown} {item} />
752
+ {/snippet}
753
+ </ToggleButtonGroup>
754
+ {#if currentWorkspaceInfo && parentWorkspaceInfo}
755
+ <div class="flex-1 flex gap-1 items-center">
756
+ <Badge
757
+ color="transparent"
758
+ class="ml-5 font-semibold"
759
+ title={mergeIntoParent ? currentWorkspaceInfo.name : parentWorkspaceInfo.name}
760
+ >
761
+ <span class="text-secondary">merge:</span>
762
+ {#if mergeIntoParent}
763
+ <GitFork size={14} />
764
+ <span class="text-emphasis">{currentWorkspaceInfo.id}</span>
765
+ {:else}
766
+ <Building size={14} />
767
+ <span class="text-emphasis">{parentWorkspaceInfo.id}</span>
768
+ {/if}
769
+ </Badge>
770
+ <ArrowRight size={16} />
771
+ <Badge
772
+ color="transparent"
773
+ class="font-semibold"
774
+ title={!mergeIntoParent
775
+ ? currentWorkspaceInfo.name
776
+ : parentWorkspaceInfo.name}
777
+ >
778
+ <span class="text-secondary">into:</span>
779
+ {#if !mergeIntoParent}
780
+ <GitFork size={14} />
781
+ <span class="text-emphasis">{currentWorkspaceInfo.id}</span>
782
+ {:else}
783
+ <Building size={14} />
784
+ <span class="text-emphasis">{parentWorkspaceInfo.id}</span>
785
+ {/if}
786
+ </Badge>
787
+ </div>
629
788
  {/if}
630
- </Badge>
631
- {/if}
789
+ <div class="flex items-center gap-2 text-sm">
790
+ <Badge color="transparent">
791
+ {comparison.summary.total_diffs} total items
792
+ </Badge>
793
+ <Badge color="transparent">
794
+ {selectableDiffs.length}
795
+ {mergeIntoParent ? 'deployable' : 'updateable'}
796
+ </Badge>
797
+ {#if conflictingDiffs.length > 0}
798
+ <Badge color="orange">
799
+ <AlertTriangle class="w-3 h-3 inline mr-1" />
800
+ {conflictingDiffs.length} conflicts
801
+ </Badge>
802
+ {/if}
803
+ </div>
804
+ </div>
805
+ </div>
632
806
  </div>
633
- <div class="flex items-center gap-2 text-sm">
634
- <Badge color="transparent">
635
- {comparison.summary.total_diffs} total items
636
- </Badge>
637
- <Badge color="transparent">
638
- {selectableDiffs.length}
639
- {mergeIntoParent ? 'deployable' : 'updateable'}
640
- </Badge>
641
- {#if conflictingDiffs.length > 0}
642
- <Badge color="orange">
643
- <AlertTriangle class="w-3 h-3 inline mr-1" />
644
- {conflictingDiffs.length} conflicts
645
- </Badge>
646
- {/if}
807
+ {/snippet}
808
+ {#if allCiTests.length > 0}
809
+ <div class="flex flex-col gap-1.5 mt-3 p-3 border bg-surface-secondary rounded text-xs">
810
+ <div class="flex items-center gap-1.5 font-semibold text-secondary">
811
+ <FlaskConical size={14} />
812
+ CI tests
813
+ </div>
814
+ <div class="flex flex-col gap-1">
815
+ {#each allCiTests as test (test.test_script_path)}
816
+ <div class="flex items-center gap-2">
817
+ {#if test.status === 'success'}
818
+ <CircleCheck size={14} class="text-green-600" />
819
+ {:else if test.status === 'failure' || test.status === 'canceled'}
820
+ <CircleX size={14} class="text-red-600" />
821
+ {:else if test.status === 'running'}
822
+ <Loader2 size={14} class="text-yellow-600 animate-spin" />
823
+ {:else}
824
+ <div class="w-3.5 h-3.5 rounded-full border border-tertiary"></div>
825
+ {/if}
826
+ <span class="text-secondary">{test.test_script_path}</span>
827
+ {#if test.job_id}
828
+ <a
829
+ href="{base}/run/{test.job_id}?workspace={currentWorkspaceId}"
830
+ class="text-tertiary hover:text-secondary text-2xs"
831
+ >
832
+ view run
833
+ </a>
834
+ {/if}
835
+ </div>
836
+ {/each}
837
+ </div>
647
838
  </div>
648
- </div>
649
- </div>
650
- {/snippet}
839
+ {/if}
651
840
 
652
- {#snippet alerts()}
653
- {#if mergeIntoParent}
654
- <ParentWorkspaceProtectionAlert
655
- {parentWorkspaceId}
656
- onUpdateCanDeploy={(canDeploy) => {
657
- canDeployToParent = canDeploy
658
- }}
659
- />
660
- {/if}
661
- {#if conflictingDiffs.length > 0}
662
- <Alert title="Conflicting changes detected" type="warning" class="mt-2">
663
- <span>
664
- {conflictingDiffs.length} item{conflictingDiffs.length !== 1 ? 's have' : ' has'} conflicting
665
- changes, it was modified on the original workspace while changes were made on this fork.
666
- Make sure to resolve these before merging.
667
- </span>
668
- </Alert>
669
- {/if}
670
- {#if hasBehindChanges && hasAheadChanges && !(mergeIntoParent && !canDeployToParent)}
671
- <Alert
672
- title="This fork is behind {parentWorkspaceId} and needs to be up to date before deploying"
673
- type="warning"
674
- class="my-2"
675
- >
676
- You have items behind '{parentWorkspaceId}'. You need to update and test your changes
677
- before being able to deploy.
678
- <span class="font-medium flex flex-row gap-1 text-red-500">
679
- <input
680
- type="checkbox"
681
- bind:checked={allowBehindChangesOverride}
682
- class="rounded max-w-4"
841
+ {#snippet alerts()}
842
+ {#if mergeIntoParent}
843
+ <ParentWorkspaceProtectionAlert
844
+ {parentWorkspaceId}
845
+ onUpdateCanDeploy={(canDeploy) => {
846
+ canDeployToParent = canDeploy
847
+ }}
683
848
  />
684
- Override: Deploy despite {itemsWithBehindChanges.length} outdated item{itemsWithBehindChanges.length !==
685
- 1
686
- ? 's'
687
- : ''}
688
- </span>
689
- </Alert>
690
- {/if}
691
- {#if !comparison.all_ahead_items_visible || !comparison.all_behind_items_visible}
692
- <Alert title="This fork has changes not visible to your user" type="warning" class="my-2">
693
- {#if !comparison.all_ahead_items_visible && !comparison.all_behind_items_visible}
694
- This fork is ahead and behind its parent
695
- {:else if !comparison.all_behind_items_visible}
696
- This fork is behind of its parent
697
- {:else if !comparison.all_ahead_items_visible}
698
- This fork is ahead of its parent
699
849
  {/if}
700
- and some of the changes are not visible by you. Only a user with access to the whole context
701
- may deploy or update this fork. You can share the link to this page to someone with proper
702
- permissions to get it deployed.
703
- </Alert>
704
- {/if}
705
- {/snippet}
706
-
707
- {#snippet itemSummary(item)}
708
- {@const diff = item.diff as WorkspaceItemDiff}
709
- {@const key = item.key}
710
- {@const isSelectable = selectableDiffs.includes(diff)}
711
- {@const oldSummary = mergeIntoParent ? summaryCache[key]?.parent : summaryCache[key]?.current}
712
- {@const newSummary = mergeIntoParent ? summaryCache[key]?.current : summaryCache[key]?.parent}
713
- {@const existsInBothWorkspaces = !(
714
- (diff.exists_in_fork && !diff.exists_in_source) ||
715
- (!diff.exists_in_fork && diff.exists_in_source)
716
- )}
717
- {#if oldSummary != newSummary && isSelectable && existsInBothWorkspaces}
718
- <span class="line-through text-secondary">{oldSummary || diff.path}</span>
719
- {newSummary || diff.path}
720
- {:else if !existsInBothWorkspaces}
721
- {newSummary || oldSummary || diff.path}
722
- {:else}
723
- {newSummary || diff.path}
724
- {/if}
725
- {/snippet}
726
-
727
- {#snippet itemActions(item)}
728
- {@const diff = item.diff as WorkspaceItemDiff}
729
- {@const key = item.key}
730
- {@const targetOnBehalfOf = getTargetOnBehalfOf(key)}
731
- {@const isConflict = diff.ahead > 0 && diff.behind > 0}
732
- {@const existsInBothWorkspaces = !(
733
- (diff.exists_in_fork && !diff.exists_in_source) ||
734
- (!diff.exists_in_fork && diff.exists_in_source)
735
- )}
736
- <!-- On-behalf-of selector -->
737
- {#if itemNeedsOnBehalfOfSelection(key, diff.kind)}
738
- <OnBehalfOfSelector
739
- targetWorkspace={deployTargetWorkspace}
740
- targetValue={targetOnBehalfOf}
741
- selected={onBehalfOfChoice[key]}
742
- onSelect={(choice, details) => {
743
- onBehalfOfChoice[key] = choice
744
- if (details) customOnBehalfOf[key] = details
745
- }}
746
- kind={diff.kind}
747
- canPreserve={canPreserveOnBehalfOf}
748
- customValue={customOnBehalfOf[key]?.permissionedAs}
749
- />
750
- {/if}
751
- {#if diff.kind === 'raw_app'}
752
- <Badge small icon={{ icon: FileJson }}>Raw</Badge>
753
- {/if}
754
- <!-- Status badges -->
755
- {#if !diff.exists_in_fork && diff.exists_in_source && diff.ahead == 0 && diff.behind > 0}
756
- <Badge
757
- title="This item was newly created in the parent workspace '{parentWorkspaceId}'"
758
- color="indigo"
759
- size="xs">New</Badge
760
- >
761
- {/if}
762
- {#if !diff.exists_in_fork && diff.exists_in_source && diff.ahead > 0}
763
- <Badge title="This item was deleted in '{currentWorkspaceId}'" color="red" size="xs"
764
- >Deleted</Badge
765
- >
766
- {/if}
767
- {#if diff.exists_in_fork && !diff.exists_in_source && diff.behind > 0}
768
- <Badge
769
- title="This item was deleted in the parent workspace '{parentWorkspaceId}'"
770
- color="red"
771
- size="xs">Deleted</Badge
772
- >
773
- {/if}
774
- {#if diff.exists_in_fork && !diff.exists_in_source && diff.ahead > 0 && diff.behind == 0}
775
- <Badge
776
- title="This item was newly created in '{currentWorkspaceId}'"
777
- color="indigo"
778
- size="xs">New</Badge
779
- >
780
- {/if}
781
- {#if !deploymentStatus[key] || deploymentStatus[key].status != 'deployed'}
782
- <div class="flex items-center gap-2">
783
- {#if isConflict || existsInBothWorkspaces}
784
- {#if diff.ahead > 0}
785
- <Badge color="green" size="xs">
786
- <ArrowUpRight class="w-3 h-3 inline" />
787
- {diff.ahead} ahead
788
- </Badge>
789
- {/if}
790
- {#if diff.behind > 0}
791
- <Badge color="blue" size="xs">
792
- <ArrowDownRight class="w-3 h-3 inline" />
793
- {diff.behind} behind
794
- </Badge>
795
- {/if}
796
- {#if isConflict}
797
- <Badge color="orange" size="xs">
798
- <AlertTriangle class="w-3 h-3 inline" />
799
- Conflict
800
- </Badge>
801
- {/if}
802
- {/if}
803
- </div>
804
- <div class:invisible={!existsInBothWorkspaces}>
805
- <Button size="xs" variant="subtle" onclick={() => showDiff(diff.kind as Kind, diff.path)}>
806
- <DiffIcon class="w-3 h-3" />
807
- Show diff
808
- </Button>
809
- </div>
810
- {/if}
811
- {/snippet}
812
-
813
- {#snippet footer()}
814
- <div class="flex items-center justify-between">
815
- <div></div>
816
-
817
- <div class="flex flex-col items-end gap-2">
818
- {#if comparison.all_behind_items_visible && comparison.all_ahead_items_visible}
819
- {#if !(mergeIntoParent && !canDeployToParent)}
820
- <Button
821
- color="blue"
822
- disabled={selectedItems.length === 0 ||
823
- deploying ||
824
- (hasBehindChanges && !allowBehindChangesOverride) ||
825
- (mergeIntoParent && !canDeployToParent) ||
826
- hasUnselectedOnBehalfOf}
827
- loading={deploying}
828
- on:click={deployChanges}
829
- >
830
- {mergeIntoParent ? 'Deploy' : 'Update'}
831
- {selectedItems.length} Item{selectedItems.length !== 1 ? 's' : ''}
832
- {#if selectedConflicts != 0}
833
- ({selectedConflicts} conflicts)
834
- {/if}
835
- </Button>
836
- {#if hasUnselectedOnBehalfOf}
837
- <span class="text-xs text-yellow-600">
838
- You must set the "on behalf of" user for all items before deploying
839
- <Tooltip class="text-yellow-600">
840
- The "run on behalf of" field defines which user's permissions will be applied
841
- during execution. Make sure this is set to an appropriate user before deploying.
842
- </Tooltip>
843
- </span>
844
- {/if}
845
- {/if}
850
+ {#if conflictingDiffs.length > 0}
851
+ <Alert title="Conflicting changes detected" type="warning" class="mt-2">
852
+ <span>
853
+ {conflictingDiffs.length} item{conflictingDiffs.length !== 1 ? 's have' : ' has'} conflicting
854
+ changes, it was modified on the original workspace while changes were made on this fork.
855
+ Make sure to resolve these before merging.
856
+ </span>
857
+ </Alert>
846
858
  {/if}
847
-
848
- {#if deploymentErrorMessage != ''}
859
+ {#if hasBehindChanges && hasAheadChanges && !(mergeIntoParent && !canDeployToParent)}
849
860
  <Alert
850
- title="Cannot {mergeIntoParent ? 'deploy these changes' : 'update these items'}"
851
- type="error"
852
- class="my-2 max-w-80"
861
+ title="This fork is behind {parentWorkspaceId} and needs to be up to date before deploying"
862
+ type="warning"
863
+ class="my-2"
853
864
  >
854
- <span>
855
- {deploymentErrorMessage}
865
+ You have items behind '{parentWorkspaceId}'. You need to update and test your changes
866
+ before being able to deploy.
867
+ <span class="font-medium flex flex-row gap-1 text-red-500">
868
+ <input
869
+ type="checkbox"
870
+ bind:checked={allowBehindChangesOverride}
871
+ class="rounded max-w-4"
872
+ />
873
+ Override: Deploy despite {itemsWithBehindChanges.length} outdated item{itemsWithBehindChanges.length !==
874
+ 1
875
+ ? 's'
876
+ : ''}
856
877
  </span>
857
878
  </Alert>
858
879
  {/if}
859
- </div>
860
- </div>
861
- {/snippet}
862
- </WorkspaceDeployLayout>
863
-
864
- <!-- Fork Triggers Section -->
865
- <div class="mt-6">
866
- <div class="flex items-center gap-2 mb-2">
867
- <h3 class="text-sm font-semibold">Triggers created in this fork</h3>
868
- {#if !loadingTriggers}
869
- <Badge color="indigo" size="xs"
870
- >{forkTriggers.length} trigger{forkTriggers.length !== 1 ? 's' : ''}</Badge
871
- >
872
- {/if}
873
- </div>
880
+ {#if !comparison.all_ahead_items_visible || !comparison.all_behind_items_visible}
881
+ <Alert
882
+ title="This fork has changes not visible to your user"
883
+ type="warning"
884
+ class="my-2"
885
+ >
886
+ {#if !comparison.all_ahead_items_visible && !comparison.all_behind_items_visible}
887
+ This fork is ahead and behind its parent
888
+ {:else if !comparison.all_behind_items_visible}
889
+ This fork is behind of its parent
890
+ {:else if !comparison.all_ahead_items_visible}
891
+ This fork is ahead of its parent
892
+ {/if}
893
+ and some of the changes are not visible by you. Only a user with access to the whole context
894
+ may deploy or update this fork. You can share the link to this page to someone with proper
895
+ permissions to get it deployed.
896
+ </Alert>
897
+ {/if}
898
+ {/snippet}
874
899
 
875
- <Alert title="Deploy and/or delete these triggers" type="info" class="mb-2">
876
- When forking a workspace, triggers are not forked to avoid unnecessary executions or
877
- collisions. If you created this triggers with the intention of deploying them to the parent
878
- workspace, you can do so here. Otherwise it is recommended to delete them or disable them.
879
- </Alert>
900
+ {#snippet itemSummary(item)}
901
+ {#if item.trigger}
902
+ {@const t = item.trigger as ForkTrigger}
903
+ <span class="text-emphasis">{getTriggerDisplayName(t.triggerKind)}</span>
904
+ <span class="text-secondary mx-1">&rarr;</span>
905
+ <span class="text-secondary">{t.scriptPath}</span>
906
+ {:else}
907
+ {@const diff = item.diff as WorkspaceItemDiff}
908
+ {@const key = item.key}
909
+ {@const isSelectable = selectableDiffs.includes(diff)}
910
+ {@const oldSummary = mergeIntoParent
911
+ ? summaryCache[key]?.parent
912
+ : summaryCache[key]?.current}
913
+ {@const newSummary = mergeIntoParent
914
+ ? summaryCache[key]?.current
915
+ : summaryCache[key]?.parent}
916
+ {@const existsInBothWorkspaces = !(
917
+ (diff.exists_in_fork && !diff.exists_in_source) ||
918
+ (!diff.exists_in_fork && diff.exists_in_source)
919
+ )}
920
+ {#if oldSummary != newSummary && isSelectable && existsInBothWorkspaces}
921
+ <span class="line-through text-secondary">{oldSummary || diff.path}</span>
922
+ {newSummary || diff.path}
923
+ {:else if !existsInBothWorkspaces}
924
+ {newSummary || oldSummary || diff.path}
925
+ {:else}
926
+ {newSummary || diff.path}
927
+ {/if}
928
+ {/if}
929
+ {/snippet}
880
930
 
881
- {#if loadingTriggers}
882
- <div class="flex items-center gap-2 text-secondary text-sm p-4">
883
- <Loader2 class="animate-spin w-4 h-4" />
884
- Loading triggers...
885
- </div>
886
- {:else if forkTriggers.length === 0}
887
- <div class="text-secondary text-sm p-4 border rounded-md bg-surface-tertiary">
888
- No triggers in this fork workspace.
889
- </div>
890
- {:else}
891
- <div class="border rounded-md bg-surface-tertiary">
892
- {#each forkTriggers as trigger (trigger.triggerKind + ':' + trigger.path)}
893
- <Row
894
- kind="trigger"
895
- triggerKind={trigger.triggerKind}
896
- path={trigger.path}
897
- href={getTriggerHref(trigger.triggerKind)}
898
- marked={undefined}
899
- isSelectable={false}
900
- canFavorite={false}
901
- workspaceId={currentWorkspaceId}
902
- >
903
- {#snippet customSummary()}
904
- <span>{getTriggerDisplayName(trigger.triggerKind)}</span>
905
- <span class="text-secondary mx-1">&rarr;</span>
906
- <span class="text-secondary">{trigger.scriptPath}</span>
907
- {#if trigger.isFlow}
908
- <Badge color="blue" size="xs">flow</Badge>
909
- {/if}
910
- {#if trigger.extraLabel}
911
- <span class="text-tertiary text-xs">({trigger.extraLabel})</span>
912
- {/if}
913
- {/snippet}
914
- {#snippet actions()}
915
- {#if trigger.enabled != null}
916
- <Badge color={trigger.enabled ? 'green' : 'gray'} size="xs">
917
- {trigger.enabled ? 'Enabled' : 'Disabled'}
918
- </Badge>
919
- {/if}
931
+ {#snippet itemActions(item)}
932
+ {#if item.trigger}
933
+ {@const t = item.trigger as ForkTrigger}
934
+ {@const key = item.key}
935
+ <Badge color="indigo" size="xs">Fork-only</Badge>
936
+ {#if t.isFlow}
937
+ <Badge color="blue" size="xs">flow</Badge>
938
+ {/if}
939
+ {#if t.extraLabel}
940
+ <span class="text-tertiary text-xs">({t.extraLabel})</span>
941
+ {/if}
942
+ {#if t.enabled != null}
943
+ <Badge color={t.enabled ? 'green' : 'gray'} size="xs">
944
+ {t.enabled ? 'Enabled' : 'Disabled'}
945
+ </Badge>
946
+ {/if}
947
+ {#if !deploymentStatus[key] || deploymentStatus[key].status != 'deployed'}
920
948
  <Button
921
949
  size="xs"
922
950
  variant="subtle"
923
- onclick={() => {
924
- deploymentDrawer?.openDrawer(trigger.path, 'trigger', {
925
- triggers: { kind: trigger.triggerKind }
926
- })
927
- }}
951
+ startIcon={{ icon: Eye }}
952
+ onclick={() => openTriggerDetails(t)}
928
953
  >
929
- <Upload size={12} />
930
- Deploy
954
+ Details
931
955
  </Button>
932
- <Button size="xs" variant="subtle" color="red" onclick={() => deleteTrigger(trigger)}>
956
+ <Button size="xs" variant="subtle" color="red" onclick={() => deleteTrigger(t)}>
933
957
  <Trash2 size={12} />
934
958
  </Button>
935
- {/snippet}
936
- </Row>
937
- {/each}
938
- </div>
939
- {/if}
959
+ {/if}
960
+ {:else}
961
+ {@const diff = item.diff as WorkspaceItemDiff}
962
+ {@const key = item.key}
963
+ {@const targetOnBehalfOf = getTargetOnBehalfOf(key)}
964
+ {@const isConflict = diff.ahead > 0 && diff.behind > 0}
965
+ {@const existsInBothWorkspaces = !(
966
+ (diff.exists_in_fork && !diff.exists_in_source) ||
967
+ (!diff.exists_in_fork && diff.exists_in_source)
968
+ )}
969
+ <!-- On-behalf-of selector -->
970
+ {#if itemNeedsOnBehalfOfSelection(key, diff.kind)}
971
+ <OnBehalfOfSelector
972
+ targetWorkspace={deployTargetWorkspace}
973
+ targetValue={targetOnBehalfOf}
974
+ selected={onBehalfOfChoice[key]}
975
+ onSelect={(choice, details) => {
976
+ onBehalfOfChoice[key] = choice
977
+ if (details) customOnBehalfOf[key] = details
978
+ }}
979
+ kind={diff.kind}
980
+ canPreserve={canPreserveOnBehalfOf}
981
+ customValue={customOnBehalfOf[key]?.permissionedAs}
982
+ />
983
+ {/if}
984
+ {#if diff.kind === 'raw_app'}
985
+ <Badge small icon={{ icon: FileJson }}>Raw</Badge>
986
+ {/if}
987
+ <!-- Status badges -->
988
+ {#if !diff.exists_in_fork && diff.exists_in_source && diff.ahead == 0 && diff.behind > 0}
989
+ <Badge
990
+ title="This item was newly created in the parent workspace '{parentWorkspaceId}'"
991
+ color="indigo"
992
+ size="xs">New</Badge
993
+ >
994
+ {/if}
995
+ {#if !diff.exists_in_fork && diff.exists_in_source && diff.ahead > 0}
996
+ <Badge title="This item was deleted in '{currentWorkspaceId}'" color="red" size="xs"
997
+ >Deleted</Badge
998
+ >
999
+ {/if}
1000
+ {#if diff.exists_in_fork && !diff.exists_in_source && diff.behind > 0}
1001
+ <Badge
1002
+ title="This item was deleted in the parent workspace '{parentWorkspaceId}'"
1003
+ color="red"
1004
+ size="xs">Deleted</Badge
1005
+ >
1006
+ {/if}
1007
+ {#if diff.exists_in_fork && !diff.exists_in_source && diff.ahead > 0 && diff.behind == 0}
1008
+ <Badge
1009
+ title="This item was newly created in '{currentWorkspaceId}'"
1010
+ color="indigo"
1011
+ size="xs">New</Badge
1012
+ >
1013
+ {/if}
1014
+ {@const ciStatus = getCiTestStatus(diff)}
1015
+ {#if ciStatus === 'pass'}
1016
+ <Badge color="green" size="xs"><CircleCheck size={10} class="mr-0.5" />CI pass</Badge>
1017
+ {:else if ciStatus === 'fail'}
1018
+ <Badge color="red" size="xs"><CircleX size={10} class="mr-0.5" />CI fail</Badge>
1019
+ {:else if ciStatus === 'running'}
1020
+ <Badge color="yellow" size="xs"
1021
+ ><Loader2 size={10} class="mr-0.5 animate-spin" />CI</Badge
1022
+ >
1023
+ {/if}
1024
+ {#if !deploymentStatus[key] || deploymentStatus[key].status != 'deployed'}
1025
+ <div class="flex items-center gap-2">
1026
+ {#if isConflict || existsInBothWorkspaces}
1027
+ {#if diff.ahead > 0}
1028
+ <Badge color="green" size="xs">
1029
+ <ArrowUpRight class="w-3 h-3 inline" />
1030
+ {diff.ahead} ahead
1031
+ </Badge>
1032
+ {/if}
1033
+ {#if diff.behind > 0}
1034
+ <Badge color="blue" size="xs">
1035
+ <ArrowDownRight class="w-3 h-3 inline" />
1036
+ {diff.behind} behind
1037
+ </Badge>
1038
+ {/if}
1039
+ {#if isConflict}
1040
+ <Badge color="orange" size="xs">
1041
+ <AlertTriangle class="w-3 h-3 inline" />
1042
+ Conflict
1043
+ </Badge>
1044
+ {/if}
1045
+ {/if}
1046
+ </div>
1047
+ <div class:invisible={!existsInBothWorkspaces}>
1048
+ <Button
1049
+ size="xs"
1050
+ variant="subtle"
1051
+ onclick={() => showDiff(diff.kind as Kind, diff.path)}
1052
+ >
1053
+ <DiffIcon class="w-3 h-3" />
1054
+ Show diff
1055
+ </Button>
1056
+ </div>
1057
+ {/if}
1058
+ {/if}
1059
+ {/snippet}
1060
+
1061
+ {#snippet footer()}
1062
+ <div class="flex items-center justify-between">
1063
+ <div></div>
1064
+
1065
+ <div class="flex flex-col items-end gap-2">
1066
+ {#if comparison.all_behind_items_visible && comparison.all_ahead_items_visible}
1067
+ <div class="flex items-center gap-2">
1068
+ {#if mergeIntoParent && !hasOpenDeploymentRequest && !deploymentRequestPanel?.isDialogOpen()}
1069
+ <Button
1070
+ variant="default"
1071
+ startIcon={{ icon: UserPlus }}
1072
+ on:click={() => deploymentRequestPanel?.openRequestDialog()}
1073
+ >
1074
+ Request deployment
1075
+ </Button>
1076
+ {/if}
1077
+ <Button
1078
+ variant="accent"
1079
+ disabled={selectedItems.length === 0 ||
1080
+ deploying ||
1081
+ (hasBehindChanges && !allowBehindChangesOverride) ||
1082
+ (mergeIntoParent && !canDeployToParent) ||
1083
+ hasUnselectedOnBehalfOf}
1084
+ loading={deploying}
1085
+ on:click={deployChanges}
1086
+ >
1087
+ {mergeIntoParent ? 'Deploy' : 'Update'}
1088
+ {selectedItems.length} Item{selectedItems.length !== 1 ? 's' : ''}
1089
+ {#if selectedConflicts != 0}
1090
+ ({selectedConflicts} conflicts)
1091
+ {/if}
1092
+ </Button>
1093
+ </div>
1094
+ {#if !(mergeIntoParent && !canDeployToParent) && hasUnselectedOnBehalfOf}
1095
+ <span class="text-xs text-yellow-600">
1096
+ You must set the "on behalf of" user for all items before deploying
1097
+ <Tooltip class="text-yellow-600">
1098
+ The "run on behalf of" field defines which user's permissions will be applied
1099
+ during execution. Make sure this is set to an appropriate user before
1100
+ deploying.
1101
+ </Tooltip>
1102
+ </span>
1103
+ {/if}
1104
+ {/if}
1105
+
1106
+ {#if deploymentErrorMessage != ''}
1107
+ <Alert
1108
+ title="Cannot {mergeIntoParent ? 'deploy these changes' : 'update these items'}"
1109
+ type="error"
1110
+ class="my-2 max-w-80"
1111
+ >
1112
+ <span>
1113
+ {deploymentErrorMessage}
1114
+ </span>
1115
+ </Alert>
1116
+ {/if}
1117
+ </div>
1118
+ </div>
1119
+ {/snippet}
1120
+ </WorkspaceDeployLayout>
1121
+
1122
+ <DeploymentRequestPanel
1123
+ bind:this={deploymentRequestPanel}
1124
+ forkWorkspaceId={currentWorkspaceId}
1125
+ {parentWorkspaceId}
1126
+ currentUsername={$userStore?.username ?? ''}
1127
+ isAdmin={$userStore?.is_admin ?? false}
1128
+ onStateChange={(open) => {
1129
+ hasOpenDeploymentRequest = open
1130
+ }}
1131
+ />
1132
+ </div>
1133
+
1134
+ <div class="bg-surface-tertiary p-4 rounded-md border">
1135
+ <DatatableSchemaDiff {currentWorkspaceId} {parentWorkspaceId} />
1136
+ </div>
940
1137
  </div>
941
1138
 
942
- <DeployWorkspaceDrawer bind:this={deploymentDrawer} />
943
1139
  <DiffDrawer bind:this={diffDrawer} {isFlow} />
1140
+
1141
+ <ScheduleEditor bind:this={scheduleEditor} />
1142
+ <RouteEditor bind:this={routeEditor} />
1143
+ <WebsocketTriggerEditor bind:this={websocketEditor} />
1144
+ <KafkaTriggerEditor bind:this={kafkaEditor} />
1145
+ <PostgresTriggerEditor bind:this={postgresEditor} />
1146
+ <NatsTriggerEditor bind:this={natsEditor} />
1147
+ <MqttTriggerEditor bind:this={mqttEditor} />
1148
+ <SqsTriggerEditor bind:this={sqsEditor} />
1149
+ <GcpTriggerEditor bind:this={gcpEditor} />
1150
+ <EmailTriggerEditor bind:this={emailEditor} />
1151
+
944
1152
  <ConfirmationModal
945
1153
  title="Delete trigger"
946
1154
  confirmationText="Delete"