windmill-components 1.394.8 → 1.405.5

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 (305) hide show
  1. package/package/assets/app.css +20 -0
  2. package/package/ata/edgeCases.d.ts +0 -1
  3. package/package/ata/edgeCases.js +2 -8
  4. package/package/ata/index.js +4 -3
  5. package/package/common.d.ts +1 -1
  6. package/package/common.js +2 -2
  7. package/package/components/ApiConnectForm.svelte +33 -7
  8. package/package/components/AppConnectLightweightResourcePicker.svelte +66 -0
  9. package/package/components/AppConnectLightweightResourcePicker.svelte.d.ts +21 -0
  10. package/package/components/ArgInput.svelte +10 -4
  11. package/package/components/ArgInput.svelte.d.ts +1 -0
  12. package/package/components/CenteredModal.svelte +4 -1
  13. package/package/components/CenteredModal.svelte.d.ts +1 -0
  14. package/package/components/CustomPopover.svelte +1 -1
  15. package/package/components/DateInput.svelte +2 -0
  16. package/package/components/DateInput.svelte.d.ts +1 -0
  17. package/package/components/DefaultScripts.svelte +8 -3
  18. package/package/components/DefaultScripts.svelte.d.ts +5 -1
  19. package/package/components/DefaultScriptsInner.svelte +16 -7
  20. package/package/components/DefaultScriptsInner.svelte.d.ts +3 -1
  21. package/package/components/Dev.svelte +68 -11
  22. package/package/components/DisplayResult.svelte +1 -1
  23. package/package/components/DropdownV2.svelte.d.ts +3 -3
  24. package/package/components/DropdownV2Inner.svelte.d.ts +3 -3
  25. package/package/components/EditableSchemaForm.svelte +1 -0
  26. package/package/components/Editor.svelte +3 -2
  27. package/package/components/Editor.svelte.d.ts +1 -1
  28. package/package/components/ExecutionDuration.svelte +44 -0
  29. package/package/components/ExecutionDuration.svelte.d.ts +24 -0
  30. package/package/components/FlowBuilder.svelte +22 -12
  31. package/package/components/FlowBuilder.svelte.d.ts +1 -0
  32. package/package/components/FlowGraphViewer.svelte +9 -2
  33. package/package/components/FlowGraphViewerStep.svelte +23 -10
  34. package/package/components/FlowInputViewer.svelte +25 -0
  35. package/package/components/FlowInputViewer.svelte.d.ts +19 -0
  36. package/package/components/FlowJobResult.svelte +8 -2
  37. package/package/components/FlowJobResult.svelte.d.ts +1 -0
  38. package/package/components/FlowMetadata.svelte +2 -2
  39. package/package/components/FlowStatusViewer.svelte +3 -1
  40. package/package/components/FlowStatusViewer.svelte.d.ts +1 -0
  41. package/package/components/FlowStatusViewerInner.svelte +21 -5
  42. package/package/components/FlowTimeline.svelte +3 -3
  43. package/package/components/FlowViewer.svelte +2 -21
  44. package/package/components/HighlightCode.svelte +3 -0
  45. package/package/components/IconedResourceType.svelte +17 -10
  46. package/package/components/IconedResourceType.svelte.d.ts +2 -0
  47. package/package/components/IdEditorInput.svelte +0 -1
  48. package/package/components/InstanceSettings.svelte +247 -129
  49. package/package/components/InstanceSettings.svelte.d.ts +2 -0
  50. package/package/components/JobArgs.svelte +3 -1
  51. package/package/components/LightweightArgInput.svelte +35 -10
  52. package/package/components/LightweightArgInput.svelte.d.ts +1 -0
  53. package/package/components/LightweightObjectResourceInput.svelte +2 -0
  54. package/package/components/LightweightObjectResourceInput.svelte.d.ts +1 -0
  55. package/package/components/LightweightResourcePicker.svelte +34 -30
  56. package/package/components/LightweightSchemaForm.svelte +2 -0
  57. package/package/components/LightweightSchemaForm.svelte.d.ts +1 -0
  58. package/package/components/LogViewer.svelte +4 -3
  59. package/package/components/LogViewer.svelte.d.ts +1 -0
  60. package/package/components/Login.svelte +10 -5
  61. package/package/components/Login.svelte.d.ts +1 -0
  62. package/package/components/ManualPopover.svelte +1 -1
  63. package/package/components/ModulePreview.svelte +21 -2
  64. package/package/components/ModuleStatus.svelte +3 -0
  65. package/package/components/ModuleStatus.svelte.d.ts +1 -0
  66. package/package/components/OAuthSetting.svelte +40 -15
  67. package/package/components/ObjectResourceInput.svelte +5 -2
  68. package/package/components/ObjectResourceInput.svelte.d.ts +2 -0
  69. package/package/components/ObjectStoreConfigSettings.svelte +78 -76
  70. package/package/components/ParqetCsvTableRenderer.svelte +25 -3
  71. package/package/components/Password.svelte.d.ts +1 -1
  72. package/package/components/Path.svelte +74 -54
  73. package/package/components/Path.svelte.d.ts +2 -1
  74. package/package/components/Popover.svelte +1 -1
  75. package/package/components/Portal.svelte +7 -8
  76. package/package/components/Portal.svelte.d.ts +3 -7
  77. package/package/components/QueueMetricsDrawer.svelte +368 -3
  78. package/package/components/QueueMetricsDrawer.svelte.d.ts +2 -0
  79. package/package/components/ResourceEditor.svelte +38 -10
  80. package/package/components/ResourcePicker.svelte +14 -9
  81. package/package/components/ResourcePicker.svelte.d.ts +1 -0
  82. package/package/components/ResultJobLoader.svelte +6 -3
  83. package/package/components/ResultJobLoader.svelte.d.ts +1 -1
  84. package/package/components/RunForm.svelte +1 -1
  85. package/package/components/SavedInputs.svelte +2 -2
  86. package/package/components/ScheduleEditorInner.svelte +2 -2
  87. package/package/components/SchemaForm.svelte +6 -1
  88. package/package/components/ScriptBuilder.svelte +12 -5
  89. package/package/components/ScriptEditor.svelte +33 -3
  90. package/package/components/ScriptEditor.svelte.d.ts +1 -1
  91. package/package/components/ScriptVersionHistory.svelte +54 -59
  92. package/package/components/Scrollable.svelte +47 -0
  93. package/package/components/Scrollable.svelte.d.ts +21 -0
  94. package/package/components/ShareModal.svelte.d.ts +2 -2
  95. package/package/components/SuperadminSettings.svelte +5 -7
  96. package/package/components/TestConnection.svelte +1 -0
  97. package/package/components/TestJobLoader.svelte +46 -5
  98. package/package/components/TestJobLoader.svelte.d.ts +2 -1
  99. package/package/components/TimeAgo.svelte +5 -6
  100. package/package/components/TimeAgo.svelte.d.ts +1 -1
  101. package/package/components/ToggleHubWorkspaceQuick.svelte +14 -0
  102. package/package/components/ToggleHubWorkspaceQuick.svelte.d.ts +16 -0
  103. package/package/components/WorkspaceGroup.svelte +3 -2
  104. package/package/components/apps/components/buttons/AppButton.svelte +1 -1
  105. package/package/components/apps/components/display/dbtable/AppDbExplorer.svelte +1 -1
  106. package/package/components/apps/components/helpers/DebouncedInput.svelte +9 -1
  107. package/package/components/apps/components/inputs/AppMultiSelect.svelte +1 -1
  108. package/package/components/apps/components/inputs/AppMultiSelectV2.svelte +1 -1
  109. package/package/components/apps/components/inputs/AppSelect.svelte +1 -1
  110. package/package/components/apps/components/layout/AppDrawer.svelte +1 -1
  111. package/package/components/apps/components/layout/AppModal.svelte +1 -1
  112. package/package/components/apps/editor/AppEditor.svelte +11 -3
  113. package/package/components/apps/editor/GridEditor.svelte +57 -4
  114. package/package/components/apps/editor/GridEditor.svelte.d.ts +8 -0
  115. package/package/components/apps/editor/GridEditorMenu.svelte +1 -1
  116. package/package/components/apps/editor/SubGridEditor.svelte +82 -3
  117. package/package/components/apps/editor/SubGridEditor.svelte.d.ts +16 -0
  118. package/package/components/apps/editor/appUtils.d.ts +19 -2
  119. package/package/components/apps/editor/appUtils.js +103 -7
  120. package/package/components/apps/editor/component/Component.svelte +36 -8
  121. package/package/components/apps/editor/component/Component.svelte.d.ts +3 -1
  122. package/package/components/apps/editor/component/components.d.ts +79 -79
  123. package/package/components/apps/editor/contextPanel/components/OutputHeader.svelte +1 -1
  124. package/package/components/apps/svelte-grid/Grid.svelte +235 -12
  125. package/package/components/apps/svelte-grid/Grid.svelte.d.ts +7 -7
  126. package/package/components/apps/svelte-grid/MoveResize.svelte +104 -11
  127. package/package/components/apps/svelte-grid/MoveResize.svelte.d.ts +7 -0
  128. package/package/components/apps/svelte-grid/utils/item.d.ts +4 -1
  129. package/package/components/apps/svelte-grid/utils/item.js +2 -3
  130. package/package/components/apps/svelte-select/lib/ConditionalPortal.svelte +1 -1
  131. package/package/components/apps/svelte-select/lib/ConditionalPortalGlobal.svelte +1 -1
  132. package/package/components/apps/svelte-select/lib/Select.svelte +1 -1
  133. package/package/components/common/button/ButtonDropdown.svelte +1 -1
  134. package/package/components/common/drawer/ConditionalPortal.svelte +1 -1
  135. package/package/components/common/fileUpload/FileUpload.svelte +1 -1
  136. package/package/components/common/languageIcons/LanguageIcon.svelte +5 -2
  137. package/package/components/common/menu/Menu.svelte +2 -1
  138. package/package/components/common/menu/MenuV2.svelte +4 -2
  139. package/package/components/common/menu/MenuV2.svelte.d.ts +1 -0
  140. package/package/components/common/modal/AlwaysMountedModal.svelte +1 -1
  141. package/package/components/common/popup/Popup.svelte +22 -12
  142. package/package/components/common/popup/Popup.svelte.d.ts +2 -0
  143. package/package/components/common/popup/PopupV2.svelte +58 -0
  144. package/package/components/common/popup/PopupV2.svelte.d.ts +27 -0
  145. package/package/components/copilot/CronGen.svelte +1 -1
  146. package/package/components/copilot/RegexGen.svelte +4 -4
  147. package/package/components/copilot/StepGen.svelte +6 -6
  148. package/package/components/copilot/StepGenQuick.svelte +58 -0
  149. package/package/components/copilot/StepGenQuick.svelte.d.ts +24 -0
  150. package/package/components/copilot/flow.d.ts +2 -0
  151. package/package/components/copilot/flow.js +55 -0
  152. package/package/components/details/DetailPageDetailPanel.svelte +9 -1
  153. package/package/components/details/DetailPageDetailPanel.svelte.d.ts +2 -1
  154. package/package/components/details/DetailPageLayout.svelte +2 -0
  155. package/package/components/details/DetailPageLayout.svelte.d.ts +3 -0
  156. package/package/components/details/Menu.svelte +1 -1
  157. package/package/components/details/utils.d.ts +0 -1
  158. package/package/components/details/utils.js +1 -12
  159. package/package/components/flows/CreateActionsApp.svelte +1 -1
  160. package/package/components/flows/FlowEditor.svelte +4 -2
  161. package/package/components/flows/FlowEditor.svelte.d.ts +1 -0
  162. package/package/components/flows/FlowHistory.svelte +10 -195
  163. package/package/components/flows/FlowHistory.svelte.d.ts +0 -1
  164. package/package/components/flows/FlowHistoryInner.svelte +200 -0
  165. package/package/components/flows/FlowHistoryInner.svelte.d.ts +19 -0
  166. package/package/components/flows/FlowProgressBar.svelte +16 -1
  167. package/package/components/flows/FlowProgressBar.svelte.d.ts +1 -0
  168. package/package/components/flows/content/FlowBranchesAllWrapper.svelte +8 -0
  169. package/package/components/flows/content/FlowBranchesAllWrapper.svelte.d.ts +1 -0
  170. package/package/components/flows/content/FlowBranchesOneWrapper.svelte +8 -0
  171. package/package/components/flows/content/FlowBranchesOneWrapper.svelte.d.ts +1 -0
  172. package/package/components/flows/content/FlowConstants.svelte +1 -1
  173. package/package/components/flows/content/FlowEditorPanel.svelte +5 -1
  174. package/package/components/flows/content/FlowEditorPanel.svelte.d.ts +1 -0
  175. package/package/components/flows/content/FlowInput.svelte +66 -58
  176. package/package/components/flows/content/FlowInput.svelte.d.ts +1 -0
  177. package/package/components/flows/content/FlowInputs.svelte +7 -6
  178. package/package/components/flows/content/FlowInputs.svelte.d.ts +1 -0
  179. package/package/components/flows/content/FlowInputsFlowQuick.svelte +65 -0
  180. package/package/components/flows/content/FlowInputsFlowQuick.svelte.d.ts +19 -0
  181. package/package/components/flows/content/FlowInputsQuick.svelte +419 -0
  182. package/package/components/flows/content/FlowInputsQuick.svelte.d.ts +33 -0
  183. package/package/components/flows/content/FlowLoop.svelte +7 -1
  184. package/package/components/flows/content/FlowModuleComponent.svelte +12 -3
  185. package/package/components/flows/content/FlowModuleComponent.svelte.d.ts +1 -0
  186. package/package/components/flows/content/FlowModuleScript.svelte +1 -1
  187. package/package/components/flows/content/FlowModuleSkip.svelte +69 -0
  188. package/package/components/flows/content/FlowModuleSkip.svelte.d.ts +20 -0
  189. package/package/components/flows/content/FlowModuleWrapper.svelte +17 -4
  190. package/package/components/flows/content/FlowPreprocessorModule.svelte +16 -0
  191. package/package/components/flows/content/FlowPreprocessorModule.svelte.d.ts +16 -0
  192. package/package/components/flows/content/FlowWhileLoop.svelte +9 -0
  193. package/package/components/flows/content/FlowWhileLoop.svelte.d.ts +1 -0
  194. package/package/components/flows/content/GenAiQuick.svelte +30 -0
  195. package/package/components/flows/content/GenAiQuick.svelte.d.ts +20 -0
  196. package/package/components/flows/content/ScriptEditorDrawer.svelte +3 -2
  197. package/package/components/flows/flowInfers.js +1 -1
  198. package/package/components/flows/header/FlowPreviewButtons.svelte +1 -0
  199. package/package/components/flows/idUtils.js +3 -1
  200. package/package/components/flows/map/FlowCopilotButton.svelte +55 -0
  201. package/package/components/flows/map/FlowCopilotButton.svelte.d.ts +16 -0
  202. package/package/components/flows/map/FlowErrorHandlerItem.svelte +77 -47
  203. package/package/components/flows/map/FlowJobsMenu.svelte +1 -1
  204. package/package/components/flows/map/FlowModuleSchemaItem.svelte +25 -12
  205. package/package/components/flows/map/FlowModuleSchemaItem.svelte.d.ts +1 -0
  206. package/package/components/flows/map/FlowModuleSchemaMap.svelte +64 -20
  207. package/package/components/flows/map/InsertModuleButton.svelte +161 -138
  208. package/package/components/flows/map/InsertModuleButton.svelte.d.ts +7 -4
  209. package/package/components/flows/map/MapItem.svelte +11 -0
  210. package/package/components/flows/map/MapItem.svelte.d.ts +1 -0
  211. package/package/components/flows/pickers/FlowScriptPickerQuick.svelte +48 -0
  212. package/package/components/flows/pickers/FlowScriptPickerQuick.svelte.d.ts +23 -0
  213. package/package/components/flows/pickers/FlowToplevelNode.svelte +19 -0
  214. package/package/components/flows/pickers/FlowToplevelNode.svelte.d.ts +19 -0
  215. package/package/components/flows/pickers/PickHubScriptQuick.svelte +138 -0
  216. package/package/components/flows/pickers/PickHubScriptQuick.svelte.d.ts +33 -0
  217. package/package/components/flows/pickers/TopLevelNode.svelte +58 -0
  218. package/package/components/flows/pickers/TopLevelNode.svelte.d.ts +21 -0
  219. package/package/components/flows/pickers/WorkspaceScriptPickerQuick.svelte +120 -0
  220. package/package/components/flows/pickers/WorkspaceScriptPickerQuick.svelte.d.ts +35 -0
  221. package/package/components/flows/types.d.ts +1 -0
  222. package/package/components/graph/FlowGraphV2.svelte +93 -58
  223. package/package/components/graph/FlowGraphV2.svelte.d.ts +2 -1
  224. package/package/components/graph/graphBuilder.d.ts +2 -1
  225. package/package/components/graph/graphBuilder.js +345 -280
  226. package/package/components/graph/model.d.ts +2 -0
  227. package/package/components/graph/renderers/edges/BaseEdge.svelte +36 -14
  228. package/package/components/graph/renderers/nodes/BranchOneStart.svelte +1 -1
  229. package/package/components/graph/renderers/nodes/InputNode.svelte +31 -51
  230. package/package/components/graph/renderers/nodes/InputNode.svelte.d.ts +6 -1
  231. package/package/components/graph/renderers/nodes/ModuleNode.svelte +2 -1
  232. package/package/components/graph/util.d.ts +1 -1
  233. package/package/components/graph/util.js +7 -2
  234. package/package/components/home/ListFiltersQuick.svelte +51 -0
  235. package/package/components/home/ListFiltersQuick.svelte.d.ts +23 -0
  236. package/package/components/icons/AnsibleIcon.svelte +42 -0
  237. package/package/components/icons/AnsibleIcon.svelte.d.ts +25 -0
  238. package/package/components/icons/WindmillIcon.svelte +119 -105
  239. package/package/components/icons/WindmillIcon2.svelte +141 -0
  240. package/package/components/icons/WindmillIcon2.svelte.d.ts +20 -0
  241. package/package/components/icons/index.d.ts +2 -1
  242. package/package/components/icons/index.js +2 -1
  243. package/package/components/icons/store.d.ts +4 -0
  244. package/package/components/icons/store.js +1 -0
  245. package/package/components/instanceSettings.d.ts +2 -2
  246. package/package/components/instanceSettings.js +25 -58
  247. package/package/components/jobs/JobProgressBar.svelte +52 -0
  248. package/package/components/jobs/JobProgressBar.svelte.d.ts +23 -0
  249. package/package/components/multiselect/MultiSelectWrapper.svelte +1 -1
  250. package/package/components/progressBar/ProgressBar.svelte +18 -1
  251. package/package/components/progressBar/ProgressBar.svelte.d.ts +3 -0
  252. package/package/components/propertyPicker/ObjectViewer.svelte +1 -1
  253. package/package/components/runs/JobPreview.svelte +1 -0
  254. package/package/components/runs/PreprocessedArgsDisplay.svelte +71 -0
  255. package/package/components/runs/PreprocessedArgsDisplay.svelte.d.ts +16 -0
  256. package/package/components/runs/RunRow.svelte +3 -7
  257. package/package/components/schema/AddProperty.svelte +1 -0
  258. package/package/components/schema/EditableSchemaWrapper.svelte +142 -19
  259. package/package/components/schema/EditableSchemaWrapper.svelte.d.ts +1 -0
  260. package/package/components/schema/FlowPropertyEditor.svelte +13 -0
  261. package/package/components/schema/FlowPropertyEditor.svelte.d.ts +1 -0
  262. package/package/components/scriptEditor/LogPanel.svelte +1 -0
  263. package/package/components/scriptEditor/LogPanel.svelte.d.ts +3 -1
  264. package/package/components/search/GlobalSearchModal.svelte +3 -2
  265. package/package/components/sidebar/SidebarContent.svelte +69 -8
  266. package/package/components/sidebar/changelogs.js +10 -0
  267. package/package/components/triggers/RouteEditor.svelte +19 -0
  268. package/package/components/triggers/RouteEditor.svelte.d.ts +21 -0
  269. package/package/components/triggers/RouteEditorInner.svelte +327 -0
  270. package/package/components/triggers/RouteEditorInner.svelte.d.ts +21 -0
  271. package/package/components/triggers/RoutesPanel.svelte +74 -0
  272. package/package/components/triggers/RoutesPanel.svelte.d.ts +17 -0
  273. package/package/editorUtils.js +2 -0
  274. package/package/gen/core/OpenAPI.js +1 -1
  275. package/package/gen/schemas.gen.d.ts +159 -8
  276. package/package/gen/schemas.gen.js +161 -8
  277. package/package/gen/services.gen.d.ts +139 -1
  278. package/package/gen/services.gen.js +282 -1
  279. package/package/gen/types.gen.d.ts +455 -12
  280. package/package/hubPaths.json +6 -8
  281. package/package/infer.d.ts +4 -2
  282. package/package/infer.js +25 -23
  283. package/package/inferArgSig.js +8 -2
  284. package/package/monaco_workers/graphql.worker.bundle.js +45440 -174
  285. package/package/relative_imports.d.ts +3 -0
  286. package/package/relative_imports.js +25 -0
  287. package/package/script_helpers.d.ts +38 -34
  288. package/package/script_helpers.js +245 -35
  289. package/package/scripts.d.ts +1 -1
  290. package/package/scripts.js +5 -1
  291. package/package/stores.d.ts +1 -0
  292. package/package/stores.js +1 -0
  293. package/package/utils.d.ts +1 -0
  294. package/package/utils.js +4 -0
  295. package/package.json +38 -7
  296. package/package/components/flows/map/InsertTriggerButton.svelte +0 -48
  297. package/package/components/flows/map/InsertTriggerButton.svelte.d.ts +0 -24
  298. package/package/init_scripts/python_failure_module.d.ts +0 -2
  299. package/package/init_scripts/python_failure_module.js +0 -8
  300. package/package/init_scripts/python_init_code.d.ts +0 -2
  301. package/package/init_scripts/python_init_code.js +0 -40
  302. package/package/init_scripts/python_init_code_clear.d.ts +0 -2
  303. package/package/init_scripts/python_init_code_clear.js +0 -5
  304. package/package/init_scripts/python_init_code_trigger.d.ts +0 -2
  305. package/package/init_scripts/python_init_code_trigger.js +0 -14
@@ -1,13 +1,15 @@
1
1
  <script>
2
- import { APP_TO_ICON_COMPONENT } from './icons';
3
- export let name;
4
- export let silent = false;
5
- export let after = false;
6
- export let height = '24px';
7
- export let width = '24px';
8
- export let center = false;
9
- export let isSelected = false;
10
- $: iconComponent = APP_TO_ICON_COMPONENT[name] || APP_TO_ICON_COMPONENT[name.split('_')[0]];
2
+ import { FileText } from 'lucide-svelte'
3
+ import { APP_TO_ICON_COMPONENT } from './icons'
4
+ export let name
5
+ export let silent = false
6
+ export let after = false
7
+ export let height = '24px'
8
+ export let width = '24px'
9
+ export let center = false
10
+ export let isSelected = false
11
+ export let formatExtension = undefined
12
+ $: iconComponent = APP_TO_ICON_COMPONENT[name] || APP_TO_ICON_COMPONENT[name.split('_')[0]]
11
13
  </script>
12
14
 
13
15
  <div class="truncate flex flex-row gap-2 {center ? 'justify-center items-center' : ''} -pl-2">
@@ -18,10 +20,15 @@ $: iconComponent = APP_TO_ICON_COMPONENT[name] || APP_TO_ICON_COMPONENT[name.spl
18
20
  <span class={isSelected ? 'text-secondary' : 'text-secondary grayscale'}>
19
21
  <svelte:component this={iconComponent} {height} {width} />
20
22
  </span>
23
+ {:else if formatExtension}
24
+ <span class={isSelected ? 'text-secondary' : 'text-secondary grayscale'}>
25
+ <svelte:component this={FileText} {height} {width} />
26
+ </span>
21
27
  {:else}
22
28
  <span style="width: {width}; height: {height}" class="bg-gray-100 rounded-full" />
23
29
  {/if}
24
30
  {#if !silent && after}
25
31
  {name}
26
32
  {/if}
27
- </div>
33
+ </div>
34
+
@@ -9,6 +9,7 @@ export default class IconedResourceType extends SvelteComponent<{
9
9
  width?: string | undefined;
10
10
  silent?: boolean | undefined;
11
11
  isSelected?: boolean | undefined;
12
+ formatExtension?: any;
12
13
  }, {
13
14
  [evt: string]: CustomEvent<any>;
14
15
  }, {}> {
@@ -26,6 +27,7 @@ declare const __propDef: {
26
27
  width?: string | undefined;
27
28
  silent?: boolean | undefined;
28
29
  isSelected?: boolean | undefined;
30
+ formatExtension?: any;
29
31
  };
30
32
  events: {
31
33
  [evt: string]: CustomEvent<any>;
@@ -43,7 +43,6 @@ $: inputDiv?.focus();
43
43
  <div class="flex w-full">
44
44
  <input
45
45
  bind:this={inputDiv}
46
- autofocus
47
46
  type="text"
48
47
  bind:value
49
48
  class="!w-auto grow"
@@ -1,6 +1,6 @@
1
1
  <script>import { settings, settingsKeys } from './instanceSettings';
2
- import { Button, Tab, TabContent, Tabs } from './common';
3
- import { ConfigService, SettingService } from '../gen';
2
+ import { Button, Skeleton, Tab, TabContent, Tabs } from './common';
3
+ import { SettingService, SettingsService } from '../gen';
4
4
  import Toggle from './Toggle.svelte';
5
5
  import SecondsInput from './common/seconds/SecondsInput.svelte';
6
6
  import Tooltip from './Tooltip.svelte';
@@ -26,6 +26,8 @@ import ObjectStoreConfigSettings from './ObjectStoreConfigSettings.svelte';
26
26
  import { fade } from 'svelte/transition';
27
27
  import Popover from './Popover.svelte';
28
28
  import { base } from '../base';
29
+ import { createEventDispatcher } from 'svelte';
30
+ import { setLicense } from '../enterpriseUtils';
29
31
  export let tab = 'Core';
30
32
  export let hideTabs = false;
31
33
  export let hideSave = false;
@@ -35,23 +37,21 @@ let initialRequirePreexistingUserForOauth = false;
35
37
  let requirePreexistingUserForOauth = false;
36
38
  let ssoOrOauth = 'sso';
37
39
  let latestKeyRenewalAttempt = null;
38
- let serverConfig = {};
39
40
  let initialValues = {};
41
+ let loading = true;
42
+ let version = '';
40
43
  loadSettings();
44
+ loadVersion();
45
+ const dispatch = createEventDispatcher();
46
+ async function loadVersion() {
47
+ version = await SettingsService.backendVersion();
48
+ }
41
49
  async function loadSettings() {
42
- try {
43
- serverConfig = (await ConfigService.getConfig({ name: 'server' })) ?? {};
44
- }
45
- catch (e) {
46
- console.log("Sever config not found, assuming it's first setup");
47
- }
50
+ loading = true;
48
51
  async function getValue(key, storage) {
49
52
  if (storage == 'setting') {
50
53
  return SettingService.getGlobal({ key });
51
54
  }
52
- else if (storage == 'config') {
53
- return serverConfig[key];
54
- }
55
55
  }
56
56
  initialOauths = (await SettingService.getGlobal({ key: 'oauths' })) ?? {};
57
57
  requirePreexistingUserForOauth =
@@ -70,21 +70,16 @@ async function loadSettings() {
70
70
  if (values['base_url'] == undefined) {
71
71
  values['base_url'] = 'http://localhost';
72
72
  }
73
+ if (values['smtp_connect'] == undefined) {
74
+ values['smtp_connect'] = {};
75
+ }
76
+ loading = false;
73
77
  latestKeyRenewalAttempt = await SettingService.getLatestKeyRenewalAttempt();
74
78
  }
75
79
  export async function saveSettings() {
76
80
  if (values) {
77
81
  const allSettings = Object.values(settings).flatMap((x) => Object.entries(x));
78
- const newServerConfig = Object.fromEntries(allSettings
79
- .filter((x) => x[1].storage == 'config' && values?.[x[1].key] && values?.[x[1].key] != '')
80
- .map((x) => [x[1].key, values?.[x[1].key]]));
81
- if (!deepEqual(newServerConfig, serverConfig)) {
82
- await ConfigService.updateConfig({
83
- name: 'server',
84
- requestBody: newServerConfig
85
- });
86
- serverConfig = JSON.parse(JSON.stringify(newServerConfig));
87
- }
82
+ let licenseKeySet = false;
88
83
  await Promise.all(allSettings
89
84
  .filter((x) => {
90
85
  return (x[1].storage == 'setting' &&
@@ -94,7 +89,13 @@ export async function saveSettings() {
94
89
  initialValues?.[x[1].key] != null));
95
90
  })
96
91
  .map(async ([_, x]) => {
97
- await SettingService.setGlobal({ key: x.key, requestBody: { value: values?.[x.key] } });
92
+ if (x.key == 'license_key') {
93
+ licenseKeySet = true;
94
+ }
95
+ return await SettingService.setGlobal({
96
+ key: x.key,
97
+ requestBody: { value: values?.[x.key] }
98
+ });
98
99
  }));
99
100
  initialValues = JSON.parse(JSON.stringify(values));
100
101
  if (!deepEqual(initialOauths, oauths)) {
@@ -112,11 +113,15 @@ export async function saveSettings() {
112
113
  requestBody: { value: requirePreexistingUserForOauth }
113
114
  });
114
115
  }
116
+ if (licenseKeySet) {
117
+ setLicense();
118
+ }
115
119
  }
116
120
  else {
117
121
  console.error('Values not loaded');
118
122
  }
119
123
  sendUserToast('Settings updated');
124
+ dispatch('saved');
120
125
  }
121
126
  let oauths = {};
122
127
  let resourceName = '';
@@ -196,6 +201,14 @@ export async function openCustomerPortal() {
196
201
  opening = false;
197
202
  }
198
203
  }
204
+ function showSetting(setting, values) {
205
+ if (setting == 'dev_instance') {
206
+ if (values['license_key'] == undefined) {
207
+ return false;
208
+ }
209
+ }
210
+ return true;
211
+ }
199
212
  </script>
200
213
 
201
214
  <div class="pb-8">
@@ -207,33 +220,50 @@ export async function openCustomerPortal() {
207
220
 
208
221
  <svelte:fragment slot="content">
209
222
  <div class="pt-4" />
223
+
210
224
  {#each Object.keys(settings) as category}
211
225
  <TabContent value={category}>
212
226
  {#if category == 'SMTP'}
213
227
  <div class="text-secondary pb-4 text-xs"
214
- >Setting SMTP unlocks sending emails upon adding new users to the workspace or the
215
- instance.</div
228
+ >Setting SMTP unlocks sending emails upon adding new users to the workspace or the instance or sending critical alerts.
229
+ <a target="_blank" href="https://www.windmill.dev/docs/misc/setup_smtp">Learn more</a></div
216
230
  >
231
+ {:else if category == 'Registries'}
232
+ <div class="text-secondary pb-4 text-xs">
233
+ Add private registries for Pip, Bun and npm. <a target="_blank" href="https://www.windmill.dev/docs/advanced/imports">Learn more</a>
234
+ </div>
217
235
  {:else if category == 'Slack'}
218
236
  <div class="text-secondary pb-4 text-xs">
219
- Connecting your instance to a Slack workspace enables critical alerts to be sent to a
220
- Slack channel.
237
+ Connecting your instance to a Slack workspace enables critical alerts to be sent to a Slack channel.
238
+ <a target="_blank" href="https://www.windmill.dev/docs/misc/saml_and_scim">Learn more</a>
239
+ </div>
240
+ {:else if category == 'SCIM/SAML'}
241
+ <div class="text-secondary pb-4 text-xs">
242
+ Setting up SAML and SCIM allows you to authenticate users using your identity provider.
243
+ <a target="_blank" href="https://www.windmill.dev/docs/advanced/instance_settings#slack">Learn more</a>
244
+ </div>
245
+ {:else if category == 'Debug'}
246
+ <div class="text-secondary pb-4 text-xs">
247
+ Enable debug mode to get more detailed logs.
221
248
  </div>
222
249
  {:else if category == 'Telemetry'}
223
250
  <div class="text-secondary pb-4 text-xs">
224
251
  Anonymous usage data is collected to help improve Windmill.
225
252
  <br />The following information is collected:
226
253
  <ul class="list-disc list-inside pl-2">
227
- <li>version</li>
254
+ <li>version of your instance</li>
228
255
  <li>number and total duration of jobs</li>
229
256
  <li>accounts usage</li>
230
257
  <li>login type usage</li>
231
258
  <li>workers usage</li>
232
- <li>vcpus usage</li>
259
+ <li>vCPUs usage</li>
233
260
  <li>memory usage</li>
234
261
  </ul>
235
262
  </div>
236
263
  {#if $enterpriseLicense}
264
+ <div class="text-secondary pb-4 text-xs">
265
+ On Enterprise Edition, you must send data to check that usage is in line with the terms of the subscription. You can either enable telemetry or regularly send usage data by clicking the button below.
266
+ </div>
237
267
  <Button
238
268
  on:click={sendStats}
239
269
  variant="border"
@@ -243,8 +273,7 @@ export async function openCustomerPortal() {
243
273
  size="xs">Send usage</Button
244
274
  >
245
275
  {/if}
246
- {/if}
247
- {#if category == 'SSO/OAuth'}
276
+ {:else if category == 'SSO/OAuth'}
248
277
  <div>
249
278
  <Tabs bind:selected={ssoOrOauth} class="mt-2 mb-4">
250
279
  <Tab value="sso">SSO</Tab>
@@ -262,12 +291,12 @@ export async function openCustomerPortal() {
262
291
  {/if}
263
292
 
264
293
  <div class="py-1" />
265
- <Alert type="info" title="Single Sign On">
266
- When at least one of the below option is set, users will be able to login to
267
- Windmill via their third-party account.
268
- <br /> To test SSO, the recommended workflow is to to save the settings and try to
269
- login in an incognito window.
270
- </Alert>
294
+ <div class="mb-2">
295
+ <span class="text-primary text-sm">When at least one of the below options is set, users will be able to login to
296
+ Windmill via their third-party account.
297
+ <br /> To test SSO, the recommended workflow is to to save the settings and try to
298
+ login in an incognito window. <a target="_blank" href="https://www.windmill.dev/docs/misc/setup_oauth#sso">Learn more</a></span>
299
+ </div>
271
300
  <div class="flex flex-col gap-2 py-4">
272
301
  <OAuthSetting name="google" bind:value={oauths['google']} />
273
302
  <OAuthSetting name="microsoft" bind:value={oauths['microsoft']} />
@@ -346,13 +375,14 @@ export async function openCustomerPortal() {
346
375
  />
347
376
  </div>
348
377
  {:else if ssoOrOauth === 'oauth'}
349
- <Alert type="info" title="OAuth Resources">
350
- When one of the below option is set, you will be able to create a specific
351
- resource containing a token automatically generated by the third-party provider.
352
- <br />
353
- To test it after setting an oauth client, go to the Resources menu and create a new
354
- one of the type of your oauth client (i.e. a 'github' resource if you set Github OAuth).
355
- </Alert>
378
+ <div class="mb-2">
379
+ <span class="text-primary text-sm">When one of the below options is set, you will be able to create a specific
380
+ resource containing a token automatically generated by the third-party provider.
381
+ <br />
382
+ To test it after setting an oauth client, go to the Resources menu and create a new
383
+ one of the type of your oauth client (i.e. a 'github' resource if you set Github OAuth).
384
+ <br /><a target="_blank" href="https://www.windmill.dev/docs/misc/setup_oauth#oauth">Learn more</a></span>
385
+ </div>
356
386
  <div class="py-1" />
357
387
  <OAuthSetting login={false} name="slack" bind:value={oauths['slack']} />
358
388
  <div class="py-1" />
@@ -435,7 +465,7 @@ export async function openCustomerPortal() {
435
465
  <div>
436
466
  <div class="flex-col flex gap-2 pb-4">
437
467
  {#each settings[category] as setting}
438
- {#if !setting.cloudonly || isCloudHosted()}
468
+ {#if (!setting.cloudonly || isCloudHosted()) && showSetting(setting.key, values)}
439
469
  {#if setting.ee_only != undefined && !$enterpriseLicense}
440
470
  <div class="flex text-xs items-center gap-1 text-yellow-500 whitespace-nowrap">
441
471
  <AlertTriangle size={16} />
@@ -445,14 +475,18 @@ export async function openCustomerPortal() {
445
475
  <label class="block pb-2">
446
476
  <span class="text-primary font-semibold text-sm">{setting.label}</span>
447
477
  {#if setting.description}
448
- <span class="text-secondary text-xs">{setting.description}</span>
478
+ <span class="text-secondary text-xs">
479
+ {@html setting.description}
480
+ </span>
449
481
  {/if}
450
482
  {#if setting.tooltip}
451
483
  <Tooltip>{setting.tooltip}</Tooltip>
452
484
  {/if}
453
485
  {#if values}
454
486
  {@const hasError = setting.isValid && !setting.isValid(values[setting.key])}
455
- {#if setting.fieldType == 'text'}
487
+ {#if loading}
488
+ <Skeleton layout={[[2.5]]} />
489
+ {:else if setting.fieldType == 'text'}
456
490
  <input
457
491
  disabled={setting.ee_only != undefined && !$enterpriseLicense}
458
492
  type="text"
@@ -517,14 +551,16 @@ export async function openCustomerPortal() {
517
551
  {:else if expiration}
518
552
  <div class="flex flex-row gap-1 items-center">
519
553
  <AlertCircle size={12} class="text-red-600" />
520
- <span class="text-red-600 text-xs"
554
+ <span class="text-red-600 dark:text-red-400 text-xs"
521
555
  >License key expired on {expiration}</span
522
556
  >
523
557
  </div>
524
558
  {:else}
525
559
  <div class="flex flex-row gap-1 items-center">
526
560
  <AlertCircle size={12} class="text-red-600" />
527
- <span class="text-red-600 text-xs">Invalid license key format</span>
561
+ <span class="text-red-600 dark:text-red-400 text-xs"
562
+ >Invalid license key format</span
563
+ >
528
564
  </div>
529
565
  {/if}
530
566
  {/if}
@@ -575,13 +611,12 @@ export async function openCustomerPortal() {
575
611
  </div>
576
612
  {/if}
577
613
  {#if licenseKeyChanged && !$enterpriseLicense}
578
- <div class="flex flex-row items-center gap-1">
579
- <AlertCircle size={12} class="text-yellow-600" />
580
- <span class="text-xs text-yellow-600">
581
- Refresh page after setting and saving license key to unlock all
582
- features
583
- </span>
584
- </div>
614
+ {#if version.startsWith('CE')}
615
+ <div class="text-red-400"
616
+ >License key is set but image used is the Community Edition {version}.
617
+ Switch image to EE.</div
618
+ >
619
+ {/if}
585
620
  {/if}
586
621
 
587
622
  {#if valid || expiration}
@@ -611,79 +646,102 @@ export async function openCustomerPortal() {
611
646
  bind:value={values[setting.key]}
612
647
  />
613
648
  {:else if setting.fieldType == 'critical_error_channels'}
614
- <div class="w-full">
615
- <div class="flex max-w-md mt-1 gap-2 w-full items-center">
616
- <select disabled>
617
- <option>Tracing</option>
618
- </select>
619
- <input disabled />
620
- <button
621
- transition:fade|local={{ duration: 100 }}
622
- class="rounded-full p-1 bg-surface-secondary duration-200 hover:bg-surface-hover"
623
- aria-label="Clear"
624
- disabled
625
- >
626
- <X size={14} />
627
- </button>
628
- </div>
629
- {#if $enterpriseLicense && Array.isArray(values[setting.key])}
630
- {#each values[setting.key] ?? [] as v, i}
631
- <div class="flex max-w-md mt-1 gap-2 w-full items-center">
632
- <select
633
- on:change={(e) => {
634
- if (e.target?.['value']) {
635
- values[setting.key][i] = {
636
- [e.target['value']]: ''
637
- }
638
- }
639
- }}
640
- value={v && 'slack_channel' in v ? 'slack_channel' : 'email'}
641
- >
642
- <option value="email">Email</option>
643
- <option value="slack_channel">Slack</option>
644
- </select>
645
- {#if v && 'slack_channel' in v}
646
- <input
647
- type="text"
648
- placeholder="Slack channel"
649
- on:input={(e) => {
649
+ <div class="w-full flex gap-x-16 flex-wrap">
650
+ <div class="w-full max-w-lg">
651
+ <div class="flex w-full max-w-lg mt-1 gap-2 w-full items-center">
652
+ <input
653
+ type="text"
654
+ placeholder="Logs (critical errors are always logged)"
655
+ disabled
656
+ />
657
+ </div>
658
+
659
+ {#if $enterpriseLicense && Array.isArray(values[setting.key])}
660
+ {#each values[setting.key] ?? [] as v, i}
661
+ <div class="flex w-full max-w-lg mt-1 gap-2 w-full items-center">
662
+ <select
663
+ class="w-20"
664
+ on:change={(e) => {
650
665
  if (e.target?.['value']) {
651
666
  values[setting.key][i] = {
652
- slack_channel: e.target['value']
667
+ [e.target['value']]: ''
653
668
  }
654
669
  }
655
670
  }}
656
- value={v?.slack_channel ?? ''}
657
- />
658
- {:else}
659
- <input
660
- type="email"
661
- placeholder="Email address"
662
- on:input={(e) => {
663
- if (e.target?.['value']) {
664
- values[setting.key][i] = {
665
- email: e.target['value']
671
+ value={v && 'slack_channel' in v ? 'slack_channel' : 'email'}
672
+ >
673
+ <option value="email">Email</option>
674
+ <option value="slack_channel">Slack</option>
675
+ </select>
676
+ {#if v && 'slack_channel' in v}
677
+ <input
678
+ type="text"
679
+ placeholder="Slack channel"
680
+ on:input={(e) => {
681
+ if (e.target?.['value']) {
682
+ values[setting.key][i] = {
683
+ slack_channel: e.target['value']
684
+ }
666
685
  }
667
- }
686
+ }}
687
+ value={v?.slack_channel ?? ''}
688
+ />
689
+ {:else}
690
+ <input
691
+ type="email"
692
+ placeholder="Email address"
693
+ on:input={(e) => {
694
+ if (e.target?.['value']) {
695
+ values[setting.key][i] = {
696
+ email: e.target['value']
697
+ }
698
+ }
699
+ }}
700
+ value={v?.email ?? ''}
701
+ />
702
+ {/if}
703
+ <button
704
+ transition:fade|local={{ duration: 100 }}
705
+ class="rounded-full p-1 bg-surface-secondary duration-200 hover:bg-surface-hover"
706
+ aria-label="Clear"
707
+ on:click={() => {
708
+ values[setting.key] = values[setting.key].filter(
709
+ (_, index) => index !== i
710
+ )
668
711
  }}
669
- value={v?.email ?? ''}
670
- />
671
- {/if}
672
- <button
673
- transition:fade|local={{ duration: 100 }}
674
- class="rounded-full p-1 bg-surface-secondary duration-200 hover:bg-surface-hover"
675
- aria-label="Clear"
676
- on:click={() => {
677
- values[setting.key] = values[setting.key].filter(
678
- (_, index) => index !== i
712
+ >
713
+ <X size={14} />
714
+ </button>
715
+ </div>
716
+ {/each}
717
+ {/if}
718
+ </div>
719
+ <div
720
+ ><div class="flex mt-1">
721
+ <Button
722
+ size="xs"
723
+ variant="contained"
724
+ on:click={async () => {
725
+ try {
726
+ await SettingService.testCriticalChannels({
727
+ requestBody: values[setting.key]
728
+ })
729
+ sendUserToast(
730
+ 'Test message sent successfully to critical channels',
731
+ false
679
732
  )
680
- }}
681
- >
682
- <X size={14} />
683
- </button>
684
- </div>
685
- {/each}
686
- {/if}
733
+ } catch (error) {
734
+ sendUserToast(
735
+ 'Failed to send test message: ' + error.message,
736
+ true
737
+ )
738
+ }
739
+ }}
740
+ >
741
+ Test Critical Channels
742
+ </Button>
743
+ </div>
744
+ </div>
687
745
  </div>
688
746
  <div class="flex mt-2 gap-20 items-baseline">
689
747
  <Button
@@ -736,6 +794,65 @@ export async function openCustomerPortal() {
736
794
  </Button>
737
795
  {/if}
738
796
  </div>
797
+ {:else if setting.fieldType == 'smtp_connect'}
798
+ <div class="flex flex-col gap-4 mt-4">
799
+ {#if values[setting.key]}
800
+ <div>
801
+ <label for="smtp_host" class="block text-sm font-medium">Host</label>
802
+ <input
803
+ type="text"
804
+ id="smtp_host"
805
+ placeholder="smtp.gmail.com"
806
+ bind:value={values[setting.key].smtp_host}
807
+ />
808
+ </div>
809
+ <div>
810
+ <label for="smtp_port" class="block text-sm font-medium">Port</label>
811
+ <input
812
+ type="number"
813
+ id="smtp_port"
814
+ placeholder="587"
815
+ bind:value={values[setting.key].smtp_port}
816
+ />
817
+ </div>
818
+ <div>
819
+ <label for="smtp_username" class="block text-sm font-medium"
820
+ >Username</label
821
+ >
822
+ <input
823
+ type="text"
824
+ id="smtp_username"
825
+ placeholder="ruben@windmill.dev"
826
+ bind:value={values[setting.key].smtp_username}
827
+ />
828
+ </div>
829
+ <div>
830
+ <label for="smtp_password" class="block text-sm font-medium"
831
+ >Password</label
832
+ >
833
+ <Password bind:password={values[setting.key].smtp_password} />
834
+ </div>
835
+ <div>
836
+ <label for="smtp_from" class="block text-sm font-medium"
837
+ >From Address</label
838
+ >
839
+ <input
840
+ type="email"
841
+ id="smtp_from"
842
+ placeholder="noreply@windmill.dev"
843
+ bind:value={values[setting.key].smtp_from}
844
+ />
845
+ </div>
846
+ <div>
847
+ <Toggle
848
+ id="smtp_tls_implicit"
849
+ bind:checked={values[setting.key].smtp_tls_implicit}
850
+ options={{ right: 'Implicit TLS' }}
851
+ label="Implicit TLS"
852
+ />
853
+ </div>
854
+ {/if}
855
+ </div>
739
856
  {:else if setting.fieldType == 'object_store_config'}
740
857
  <ObjectStoreConfigSettings bind:bucket_config={values[setting.key]} />
741
858
  <div class="mb-6" />
@@ -768,7 +885,7 @@ export async function openCustomerPortal() {
768
885
  {/if}
769
886
 
770
887
  {#if hasError}
771
- <span class="text-red-500 text-xs">
888
+ <span class="text-red-500 dark:text-red-400 text-sm">
772
889
  {setting.error ?? ''}
773
890
  </span>
774
891
  {/if}
@@ -781,21 +898,22 @@ export async function openCustomerPortal() {
781
898
  </div>
782
899
  </div>
783
900
  {#if category == 'SMTP'}
901
+ {@const smtp = values['smtp_settings']}
784
902
  <div class="flex gap-4"
785
903
  ><input type="email" bind:value={to} placeholder="contact@windmill.dev" />
786
904
  <Button
787
- disabled={to == ''}
905
+ disabled={to == '' || !smtp}
788
906
  on:click={async () => {
789
907
  await SettingService.testSmtp({
790
908
  requestBody: {
791
909
  to,
792
910
  smtp: {
793
- host: values['smtp_host'],
794
- username: values['smtp_username'],
795
- password: values['smtp_password'],
796
- port: values['smtp_port'],
797
- from: values['smtp_from'],
798
- tls_implicit: values['smtp_tls_implicit']
911
+ host: smtp['smtp_host'],
912
+ username: smtp['smtp_username'],
913
+ password: smtp['smtp_password'],
914
+ port: smtp['smtp_port'],
915
+ from: smtp['smtp_from'],
916
+ tls_implicit: smtp['smtp_tls_implicit']
799
917
  }
800
918
  }
801
919
  })
@@ -9,6 +9,8 @@ declare const __propDef: {
9
9
  openCustomerPortal?: (() => Promise<void>) | undefined;
10
10
  };
11
11
  events: {
12
+ saved: CustomEvent<any>;
13
+ } & {
12
14
  [evt: string]: CustomEvent<any>;
13
15
  };
14
16
  slots: {};
@@ -46,7 +46,9 @@ ${Object.entries(args)
46
46
  }
47
47
  </script>
48
48
 
49
- {#if id && workspace && args && typeof args === 'object' && deepEqual( Object.keys(args), ['reason'] ) && args['reason'] == 'WINDMILL_TOO_BIG'}
49
+ {#if args && typeof args === 'object' && deepEqual( Object.keys(args), ['reason'] ) && args['reason'] == 'PREPROCESSOR_ARGS_ARE_DISCARDED'}
50
+ Preprocessor args are discarded
51
+ {:else if id && workspace && args && typeof args === 'object' && deepEqual( Object.keys(args), ['reason'] ) && args['reason'] == 'WINDMILL_TOO_BIG'}
50
52
  The args are too big in size to be able to fetch alongside job. Please <a
51
53
  href="/api/w/{workspace}/jobs_u/get_args/{id}"
52
54
  target="_blank">download the JSON file to view them</a