windmill-components 1.665.1 → 1.677.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/dist/sharedUtils/assets/tokens/colorTokensConfig.d.ts +2 -0
  2. package/dist/sharedUtils/base.d.ts +1 -0
  3. package/dist/sharedUtils/cloud.d.ts +1 -0
  4. package/dist/sharedUtils/common.d.ts +111 -0
  5. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/count.d.ts +5 -0
  6. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/delete.d.ts +5 -0
  7. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/insert.d.ts +5 -0
  8. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/select.d.ts +13 -0
  9. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/update.d.ts +11 -0
  10. package/dist/sharedUtils/components/apps/components/display/dbtable/utils.d.ts +95 -0
  11. package/dist/sharedUtils/components/apps/editor/appPolicy.d.ts +6 -0
  12. package/dist/sharedUtils/components/apps/editor/appUtilsCore.d.ts +7 -0
  13. package/dist/sharedUtils/components/apps/editor/appUtilsS3.d.ts +33 -0
  14. package/dist/sharedUtils/components/apps/editor/commonAppUtils.d.ts +10 -0
  15. package/dist/sharedUtils/components/apps/editor/component/components.d.ts +5371 -0
  16. package/dist/sharedUtils/components/apps/editor/component/default-codes.d.ts +3 -0
  17. package/dist/sharedUtils/components/apps/editor/component/index.d.ts +3 -0
  18. package/dist/sharedUtils/components/apps/editor/component/sets.d.ts +7 -0
  19. package/dist/sharedUtils/components/apps/editor/componentsPanel/componentDefaultProps.d.ts +3 -0
  20. package/dist/sharedUtils/components/apps/gridUtils.d.ts +14 -0
  21. package/dist/sharedUtils/components/apps/inputType.d.ts +178 -0
  22. package/dist/sharedUtils/components/apps/rx.d.ts +29 -0
  23. package/dist/sharedUtils/components/apps/sharedTypes.d.ts +21 -0
  24. package/dist/sharedUtils/components/apps/types.d.ts +274 -0
  25. package/dist/sharedUtils/components/assets/lib.d.ts +25 -0
  26. package/dist/sharedUtils/components/common/alert/model.d.ts +2 -0
  27. package/dist/sharedUtils/components/common/badge/model.d.ts +8 -0
  28. package/dist/sharedUtils/components/common/button/model.d.ts +45 -0
  29. package/dist/sharedUtils/components/common/fileInput/model.d.ts +1 -0
  30. package/dist/sharedUtils/components/common/index.d.ts +24 -0
  31. package/dist/sharedUtils/components/common/skeleton/model.d.ts +21 -0
  32. package/dist/sharedUtils/components/dbTypes.d.ts +14 -0
  33. package/dist/sharedUtils/components/diff_drawer.d.ts +26 -0
  34. package/dist/sharedUtils/components/ducklake.d.ts +1 -0
  35. package/dist/sharedUtils/components/flows/scheduleUtils.d.ts +7 -0
  36. package/dist/sharedUtils/components/icons/index.d.ts +101 -0
  37. package/dist/sharedUtils/components/random_positive_adjetive.d.ts +1 -0
  38. package/dist/sharedUtils/components/raw_apps/rawAppPolicy.d.ts +10 -0
  39. package/dist/sharedUtils/components/raw_apps/utils.d.ts +15 -0
  40. package/dist/sharedUtils/components/triggers/email/utils.d.ts +4 -0
  41. package/dist/sharedUtils/components/triggers/gcp/utils.d.ts +2 -0
  42. package/dist/sharedUtils/components/triggers/http/utils.d.ts +11 -0
  43. package/dist/sharedUtils/components/triggers/kafka/utils.d.ts +2 -0
  44. package/dist/sharedUtils/components/triggers/mqtt/utils.d.ts +2 -0
  45. package/dist/sharedUtils/components/triggers/nats/utils.d.ts +2 -0
  46. package/dist/sharedUtils/components/triggers/postgres/utils.d.ts +8 -0
  47. package/dist/sharedUtils/components/triggers/sqs/utils.d.ts +2 -0
  48. package/dist/sharedUtils/components/triggers/triggers.svelte.d.ts +32 -0
  49. package/dist/sharedUtils/components/triggers/utils.d.ts +80 -0
  50. package/dist/sharedUtils/components/triggers/websocket/utils.d.ts +2 -0
  51. package/dist/sharedUtils/components/triggers.d.ts +20 -0
  52. package/dist/sharedUtils/gen/core/ApiError.d.ts +10 -0
  53. package/dist/sharedUtils/gen/core/ApiRequestOptions.d.ts +13 -0
  54. package/dist/sharedUtils/gen/core/ApiResult.d.ts +7 -0
  55. package/dist/sharedUtils/gen/core/CancelablePromise.d.ts +26 -0
  56. package/dist/sharedUtils/gen/core/OpenAPI.d.ts +27 -0
  57. package/dist/sharedUtils/gen/core/request.d.ts +29 -0
  58. package/dist/sharedUtils/gen/index.d.ts +6 -0
  59. package/dist/sharedUtils/gen/schemas.gen.d.ts +7036 -0
  60. package/dist/sharedUtils/gen/services.gen.d.ts +6047 -0
  61. package/dist/sharedUtils/gen/types.gen.d.ts +21881 -0
  62. package/dist/sharedUtils/history.svelte.d.ts +9 -0
  63. package/dist/sharedUtils/hub.d.ts +49 -0
  64. package/dist/sharedUtils/jsr.json +6 -0
  65. package/dist/sharedUtils/lib.d.ts +5 -0
  66. package/dist/sharedUtils/lib.es.js +1588 -0
  67. package/dist/sharedUtils/package.json +12 -0
  68. package/dist/sharedUtils/schema.d.ts +3 -0
  69. package/dist/sharedUtils/stores.d.ts +97 -0
  70. package/dist/sharedUtils/svelte5Utils.svelte.d.ts +80 -0
  71. package/dist/sharedUtils/toast.d.ts +8 -0
  72. package/dist/sharedUtils/utils.d.ts +265 -0
  73. package/package/components/AddUser.svelte +67 -34
  74. package/package/components/AppConnectInner.svelte +9 -1
  75. package/package/components/ArgInfo.svelte +9 -1
  76. package/package/components/ArgInput.svelte +21 -1
  77. package/package/components/CompareWorkspaces.svelte +11 -2
  78. package/package/components/DedicatedWorkersSelector.svelte +262 -247
  79. package/package/components/DefaultTagsInner.svelte +40 -2
  80. package/package/components/DeployWorkspace.svelte +13 -0
  81. package/package/components/DiffEditor.svelte +44 -1
  82. package/package/components/EditableSchemaForm.svelte +5 -2
  83. package/package/components/EditableSchemaForm.svelte.d.ts +1 -0
  84. package/package/components/Editor.svelte +5 -1
  85. package/package/components/EditorBar.svelte +12 -3
  86. package/package/components/FilterSearchbar.svelte +26 -2
  87. package/package/components/FlowBuilder.svelte +6 -3
  88. package/package/components/FlowGraphDiffViewer.svelte +16 -17
  89. package/package/components/FlowGraphViewer.svelte +20 -6
  90. package/package/components/FlowGraphViewer.svelte.d.ts +2 -0
  91. package/package/components/FlowGraphViewerStep.svelte +14 -32
  92. package/package/components/FlowMetadata.svelte +4 -1
  93. package/package/components/FlowPreviewContent.svelte +2 -0
  94. package/package/components/FlowStatusWaitingForEvents.svelte +25 -4
  95. package/package/components/HighlightCode.svelte +3 -0
  96. package/package/components/InstanceSetting.svelte +9 -25
  97. package/package/components/InstanceSettings.svelte +16 -0
  98. package/package/components/LabelsInput.svelte +149 -0
  99. package/package/components/LabelsInput.svelte.d.ts +8 -0
  100. package/package/components/Login.svelte +6 -1
  101. package/package/components/ObjectStoreConfigSettings.svelte +273 -1
  102. package/package/components/OktaSetting.svelte +6 -5
  103. package/package/components/Password.svelte +74 -20
  104. package/package/components/Password.svelte.d.ts +1 -0
  105. package/package/components/PasswordArgInput.svelte +2 -2
  106. package/package/components/PasswordArgInput.svelte.d.ts +1 -0
  107. package/package/components/Path.svelte +8 -10
  108. package/package/components/PathNameAutocomplete.svelte +308 -0
  109. package/package/components/PathNameAutocomplete.svelte.d.ts +27 -0
  110. package/package/components/PowerShellCommonParams.svelte +84 -0
  111. package/package/components/PowerShellCommonParams.svelte.d.ts +6 -0
  112. package/package/components/Range.svelte +8 -3
  113. package/package/components/ResourceEditor.svelte +6 -2
  114. package/package/components/RunForm.svelte +71 -7
  115. package/package/components/RunForm.svelte.d.ts +2 -1
  116. package/package/components/ScriptBuilder.svelte +7 -3
  117. package/package/components/ScriptEditor.svelte +221 -187
  118. package/package/components/ScriptEditor.svelte.d.ts +1 -1
  119. package/package/components/ScriptSchema.svelte +1 -1
  120. package/package/components/StringTypeNarrowing.svelte +1 -1
  121. package/package/components/StringTypeNarrowing.svelte.d.ts +1 -1
  122. package/package/components/SummaryPathDisplay.svelte +32 -10
  123. package/package/components/SummaryPathDisplay.svelte.d.ts +2 -1
  124. package/package/components/VariableEditor.svelte +9 -2
  125. package/package/components/WorkerGroup.svelte +47 -2
  126. package/package/components/apps/editor/DeploymentHistory.svelte +112 -13
  127. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptRunnableByPath.svelte +135 -35
  128. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptRunnableByPath.svelte.d.ts +3 -1
  129. package/package/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte +11 -35
  130. package/package/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.d.ts +10 -0
  131. package/package/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.js +14 -0
  132. package/package/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.test.d.ts +1 -0
  133. package/package/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.test.js +34 -0
  134. package/package/components/assets/AssetButtons.svelte +21 -25
  135. package/package/components/assets/AssetsUsageDrawer.svelte +7 -9
  136. package/package/components/common/fileUpload/FileUpload.svelte +6 -2
  137. package/package/components/common/languageIcons/LanguageIcon.svelte +3 -0
  138. package/package/components/common/table/AppRow.svelte +18 -0
  139. package/package/components/common/table/FlowRow.svelte +18 -0
  140. package/package/components/common/table/ScriptRow.svelte +18 -0
  141. package/package/components/copilot/chat/AIChatManager.svelte.js +3 -3
  142. package/package/components/copilot/chat/flow/openFlow.json +1 -1
  143. package/package/components/copilot/chat/flow/openFlowZod.js +3 -3
  144. package/package/components/custom_ui.d.ts +2 -0
  145. package/package/components/details/DetailPageHeader.svelte +2 -2
  146. package/package/components/details/DetailPageHeader.svelte.d.ts +2 -1
  147. package/package/components/flows/agentToolUtils.d.ts +5 -0
  148. package/package/components/flows/agentToolUtils.js +49 -0
  149. package/package/components/flows/agentToolUtils.test.d.ts +1 -0
  150. package/package/components/flows/agentToolUtils.test.js +55 -0
  151. package/package/components/flows/content/FlowInput.svelte +2 -0
  152. package/package/components/flows/content/FlowInputsQuick.svelte +1 -1
  153. package/package/components/flows/content/FlowLoop.svelte +5 -12
  154. package/package/components/flows/content/FlowModuleScript.svelte +5 -3
  155. package/package/components/flows/content/FlowPathViewer.svelte +2 -2
  156. package/package/components/flows/content/FlowPathViewer.svelte.d.ts +1 -0
  157. package/package/components/flows/content/FlowSettings.svelte +2 -0
  158. package/package/components/flows/content/FlowWhileLoop.svelte +5 -12
  159. package/package/components/flows/flowInfers.js +8 -3
  160. package/package/components/flows/flowStore.svelte.d.ts +1 -1
  161. package/package/components/flows/map/FlowModuleSchemaMap.svelte +49 -9
  162. package/package/components/flows/pickers/PickHubScriptQuick.svelte +5 -3
  163. package/package/components/flows/scheduleUtils.js +2 -1
  164. package/package/components/graph/FlowGraphV2.svelte +13 -1
  165. package/package/components/graph/WacDiagram.svelte +96 -0
  166. package/package/components/graph/WacDiagram.svelte.d.ts +7 -0
  167. package/package/components/graph/noteEditor.svelte.d.ts +1 -1
  168. package/package/components/graph/noteEditor.svelte.js +12 -1
  169. package/package/components/graph/noteUtils.svelte.d.ts +1 -1
  170. package/package/components/graph/noteUtils.svelte.js +9 -2
  171. package/package/components/graph/renderers/edges/WacEdge.svelte +41 -0
  172. package/package/components/graph/renderers/edges/WacEdge.svelte.d.ts +4 -0
  173. package/package/components/graph/renderers/nodes/WacControlNode.svelte +51 -0
  174. package/package/components/graph/renderers/nodes/WacControlNode.svelte.d.ts +9 -0
  175. package/package/components/graph/renderers/nodes/WacStepNode.svelte +35 -0
  176. package/package/components/graph/renderers/nodes/WacStepNode.svelte.d.ts +9 -0
  177. package/package/components/graph/wacDagLayout.d.ts +10 -0
  178. package/package/components/graph/wacDagLayout.js +120 -0
  179. package/package/components/graph/wacToFlow.js +1 -1
  180. package/package/components/home/ItemsList.svelte +28 -4
  181. package/package/components/icons/RIcon.svelte +32 -0
  182. package/package/components/icons/RIcon.svelte.d.ts +7 -0
  183. package/package/components/instanceSettings/DbHealth.svelte +723 -0
  184. package/package/components/instanceSettings/DbHealth.svelte.d.ts +3 -0
  185. package/package/components/instanceSettings/SecretBackendConfig.svelte +343 -304
  186. package/package/components/instanceSettings/SmtpSettings.svelte +8 -0
  187. package/package/components/instanceSettings.js +14 -5
  188. package/package/components/mcp/McpScopeSelector.svelte +82 -16
  189. package/package/components/moveRenameManager.d.ts +1 -0
  190. package/package/components/moveRenameManager.js +7 -4
  191. package/package/components/raw_apps/RawAppInlineScriptRunnable.svelte +14 -1
  192. package/package/components/raw_apps/rawAppPolicy.js +3 -2
  193. package/package/components/raw_apps/utils.test.d.ts +1 -0
  194. package/package/components/raw_apps/utils.test.js +38 -0
  195. package/package/components/resources/resourcesFilter.d.ts +15 -2
  196. package/package/components/resources/resourcesFilter.js +11 -2
  197. package/package/components/runs/JobDetailFieldConfig.js +5 -3
  198. package/package/components/runs/JobDetailHeader.svelte +5 -2
  199. package/package/components/runs/JobRunsPreview.svelte +1 -0
  200. package/package/components/runs/RunBadges.svelte +7 -4
  201. package/package/components/runs/RunRow.svelte +7 -7
  202. package/package/components/schedules/schedulesFilter.d.ts +15 -2
  203. package/package/components/schedules/schedulesFilter.js +11 -2
  204. package/package/components/schema/EditableSchemaWrapper.svelte +6 -8
  205. package/package/components/schema/PropertyEditor.svelte +22 -1
  206. package/package/components/schema/PropertyEditor.svelte.d.ts +1 -0
  207. package/package/components/schema/editable_schema_wrapper.d.ts +1 -0
  208. package/package/components/secretArgUtils.d.ts +7 -0
  209. package/package/components/secretArgUtils.js +45 -0
  210. package/package/components/settings/WorkspaceUserSettings.svelte +359 -286
  211. package/package/components/sidebar/OperatorMenu.svelte +215 -197
  212. package/package/components/triggers/CaptureWrapper.svelte +1 -1
  213. package/package/components/triggers/TriggerFilters.svelte +17 -5
  214. package/package/components/triggers/TriggerFilters.svelte.d.ts +2 -1
  215. package/package/components/triggers/kafka/KafkaCapture.svelte +6 -2
  216. package/package/components/triggers/kafka/KafkaCapture.svelte.d.ts +1 -1
  217. package/package/components/triggers/kafka/KafkaTriggerEditorInner.svelte +5 -1
  218. package/package/components/triggers/kafka/utils.js +1 -0
  219. package/package/components/triggers/mqtt/MqttEditorConfigSection.svelte.d.ts +1 -1
  220. package/package/components/triggers/schedules/ScheduleEditorInner.svelte +6 -0
  221. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +87 -1
  222. package/package/components/triggers/websocket/utils.js +2 -0
  223. package/package/components/variables/variablesFilter.d.ts +15 -2
  224. package/package/components/variables/variablesFilter.js +11 -2
  225. package/package/components/worker_group.js +1 -0
  226. package/package/components/workspaceSettings/DucklakeSettings.svelte +33 -41
  227. package/package/consts.d.ts +1 -0
  228. package/package/consts.js +1 -0
  229. package/package/editorLangUtils.d.ts +1 -1
  230. package/package/editorLangUtils.js +2 -0
  231. package/package/gen/core/OpenAPI.js +1 -1
  232. package/package/gen/schemas.gen.d.ts +346 -4
  233. package/package/gen/schemas.gen.js +347 -5
  234. package/package/gen/services.gen.d.ts +163 -1
  235. package/package/gen/services.gen.js +323 -17
  236. package/package/gen/types.gen.d.ts +671 -5
  237. package/package/hubPaths.json +6 -3
  238. package/package/infer.d.ts +55 -0
  239. package/package/infer.js +131 -0
  240. package/package/infer.svelte.js +2 -0
  241. package/package/mcpEndpointTools.js +213 -22
  242. package/package/script_helpers.d.ts +3 -0
  243. package/package/script_helpers.js +26 -0
  244. package/package/scripts.d.ts +2 -1
  245. package/package/scripts.js +15 -3
  246. package/package/stores.d.ts +2 -0
  247. package/package/system_prompts/prompts.d.ts +6 -5
  248. package/package/system_prompts/prompts.js +188 -29
  249. package/package/user.js +5 -1
  250. package/package/utils.js +21 -0
  251. package/package/utils_deployable.d.ts +11 -0
  252. package/package/utils_workspace_deploy.js +36 -8
  253. package/package.json +5 -4
@@ -2,7 +2,7 @@
2
2
  import { JobService } from '../gen';
3
3
  import { workspaceStore } from '../stores';
4
4
  import { sendUserToast } from '../toast';
5
- import { X } from 'lucide-svelte';
5
+ import { ExternalLink, X } from 'lucide-svelte';
6
6
  import DisplayResult from './DisplayResult.svelte';
7
7
  import Tooltip from './Tooltip.svelte';
8
8
  import { Button } from './common';
@@ -13,6 +13,7 @@ let { isOwner: _isOwner, workspaceId, job, light = false } = $props();
13
13
  let default_payload = $state({});
14
14
  let description = $state(undefined);
15
15
  let hide_cancel = $state(false);
16
+ let approvalPageUrl = $state(undefined);
16
17
  let defaultValues = $state({});
17
18
  let schema = $state({});
18
19
  let lastJobId = undefined;
@@ -33,10 +34,13 @@ async function getDefaultArgs() {
33
34
  description = job_result?.description;
34
35
  defaultValues = JSON.parse(JSON.stringify(args));
35
36
  default_payload = args;
37
+ approvalPageUrl = job_result?.['approvalPage'];
38
+ actionTaken = false;
36
39
  hide_cancel = job?.raw_flow?.modules?.[approvalStep]?.suspend?.hide_cancel ?? false;
37
40
  schema = mergeSchema(job?.raw_flow?.modules?.[approvalStep]?.suspend?.resume_form?.schema ?? {}, job_result?.enums ?? {});
38
41
  }
39
42
  let loading = $state(false);
43
+ let actionTaken = $state(false);
40
44
  async function continu(approve) {
41
45
  loading = true;
42
46
  try {
@@ -48,6 +52,7 @@ async function continu(approve) {
48
52
  approved: approve
49
53
  }
50
54
  });
55
+ actionTaken = true;
51
56
  }
52
57
  catch (e) {
53
58
  sendUserToast(e?.body ?? e?.message ?? 'Failed', true);
@@ -68,7 +73,7 @@ $effect(() => {
68
73
  <div class="mt-2"></div>
69
74
  {/if}
70
75
  <div>
71
- <div class={twMerge('flex gap-2', light ? 'flex-col' : 'flex-row ')}>
76
+ <div class={twMerge('flex gap-2 items-center', light ? 'flex-col' : 'flex-row ')}>
72
77
  {#if !hide_cancel}
73
78
  <div>
74
79
  <Button
@@ -76,7 +81,7 @@ $effect(() => {
76
81
  iconOnly
77
82
  startIcon={{ icon: X }}
78
83
  variant="default"
79
- disabled={loading}
84
+ disabled={loading || actionTaken}
80
85
  destructive
81
86
  unifiedSize="md"
82
87
  on:click={() => continu(false)}
@@ -84,12 +89,28 @@ $effect(() => {
84
89
  </div>
85
90
  {/if}
86
91
  <div>
87
- <Button variant="accent" onClick={() => continu(true)} disabled={loading} unifiedSize="md">
92
+ <Button
93
+ variant="accent"
94
+ onClick={() => continu(true)}
95
+ disabled={loading || actionTaken}
96
+ unifiedSize="md"
97
+ >
88
98
  Resume
89
99
  <Tooltip class="text-white">Resume or approve this suspended step</Tooltip>
90
100
  </Button>
91
101
  </div>
92
102
 
103
+ {#if approvalPageUrl}
104
+ <a
105
+ href={approvalPageUrl}
106
+ target="_blank"
107
+ rel="noreferrer"
108
+ class="text-accent flex items-center gap-1 whitespace-nowrap"
109
+ >
110
+ Approval page <ExternalLink size={12} />
111
+ </a>
112
+ {/if}
113
+
93
114
  {#if job?.raw_flow?.modules?.[approvalStep]?.suspend?.resume_form?.schema}
94
115
  <div
95
116
  class={twMerge(
@@ -13,6 +13,7 @@ import csharp from 'svelte-highlight/languages/csharp';
13
13
  import yaml from 'svelte-highlight/languages/yaml';
14
14
  import java from 'svelte-highlight/languages/java';
15
15
  import ruby from 'svelte-highlight/languages/ruby';
16
+ import r from 'svelte-highlight/languages/r';
16
17
  import { Button } from './common';
17
18
  import { copyToClipboard } from '../utils';
18
19
  import { ClipboardCopy } from 'lucide-svelte';
@@ -67,6 +68,8 @@ function getLang(lang) {
67
68
  return java;
68
69
  case 'ruby':
69
70
  return ruby;
71
+ case 'rlang':
72
+ return r;
70
73
  case 'json':
71
74
  return json;
72
75
  // for related places search: ADD_NEW_LANG
@@ -565,32 +565,16 @@ $effect(() => {
565
565
  for="OTEL_EXPORTER_OTLP_PROTOCOL"
566
566
  class="block text-xs font-semibold text-emphasis">Protocol</label
567
567
  >
568
- <span class="text-primary font-normal text-xs">gRPC</span>
568
+ <select
569
+ id="OTEL_EXPORTER_OTLP_PROTOCOL"
570
+ class="!text-xs"
571
+ disabled={!$enterpriseLicense}
572
+ bind:value={$values[setting.key].otel_exporter_otlp_protocol}
573
+ >
574
+ <option value={undefined}>grpc (default)</option>
575
+ <option value="http/protobuf">http/protobuf</option>
576
+ </select>
569
577
  </div>
570
- <!-- <div>
571
- <label for="OTEL_EXPORTER_OTLP_PROTOCOL" class="block text-sm font-semibold"
572
- >Protocol<span class="text-2xs text-primary ml-4"
573
- >grpc, http/protobuf, http/json</span
574
- ></label
575
- >
576
- <input
577
- type="text"
578
- id="OTEL_EXPORTER_OTLP_PROTOCOL"
579
- placeholder="grpc"
580
- bind:value={$values[setting.key].otel_exporter_otlp_protocol}
581
- />
582
- </div>
583
- <div>
584
- <label for="OTEL_EXPORTER_OTLP_COMPRESSION" class="block text-sm font-semibold"
585
- >Compression <span class="text-2xs text-primary ml-4">none, gzip</span></label
586
- >
587
- <input
588
- type="text"
589
- id="OTEL_EXPORTER_OTLP_COMPRESSION"
590
- placeholder="none"
591
- bind:value={$values[setting.key].otel_exporter_otlp_compression}
592
- />
593
- </div> -->
594
578
  {/if}
595
579
  </div>
596
580
  {:else if setting.fieldType == 'otel_tracing_proxy'}
@@ -16,6 +16,7 @@ import Toggle from './Toggle.svelte';
16
16
  import SettingsFooter from './workspaceSettings/SettingsFooter.svelte';
17
17
  import SettingsPageHeader from './settings/SettingsPageHeader.svelte';
18
18
  import WorkspaceRegistries from './instanceSettings/WorkspaceRegistries.svelte';
19
+ import DbHealth from './instanceSettings/DbHealth.svelte';
19
20
  let { tab = $bindable('Core'), hideTabs = false, closeDrawer = () => { }, authSubTab = $bindable('sso'), onNavigateToTab, quickSetup = false, yamlMode = $bindable(false), hasUnsavedChanges = $bindable(false), hasAnyInvalid = $bindable(false) } = $props();
20
21
  let values = writable({});
21
22
  let initialOauths = $state({});
@@ -34,6 +35,15 @@ export function getLicenseKey() {
34
35
  }
35
36
  loadSettings();
36
37
  loadVersion();
38
+ // When the user enables object storage for the first time, default
39
+ // `monitor_logs_on_s3` to true so S3 log files get cleaned up with their
40
+ // jobs. Backend still defaults to false for backwards compat with
41
+ // operators who never touched the setting.
42
+ $effect(() => {
43
+ if ($values['object_store_cache_config'] && $values['monitor_logs_on_s3'] === undefined) {
44
+ values.update((v) => ({ ...v, monitor_logs_on_s3: true }));
45
+ }
46
+ });
37
47
  const dispatch = createEventDispatcher();
38
48
  async function loadVersion() {
39
49
  version = await SettingsService.backendVersion();
@@ -920,6 +930,12 @@ $effect(() => {
920
930
  title="GitHub Enterprise App"
921
931
  description="Configure a self-managed GitHub App for GitHub Enterprise Server git sync."
922
932
  />
933
+ {:else if category == 'DB Health'}
934
+ <SettingsPageHeader
935
+ title="DB Health"
936
+ description="On-demand database diagnostics. Analyze table sizes, job retention, connection pool health, vacuum status, and more."
937
+ />
938
+ <DbHealth />
923
939
  {:else if category == 'Auth/OAuth/SAML'}
924
940
  <AuthSettings
925
941
  bind:oauths
@@ -0,0 +1,149 @@
1
+ <script lang="ts">import Badge from './common/badge/Badge.svelte';
2
+ import { Plus, Tag, X } from 'lucide-svelte';
3
+ import { workspaceStore } from '../stores';
4
+ let { labels = $bindable(), onchange, class: clazz = '' } = $props();
5
+ let adding = $state(false);
6
+ let inputValue = $state('');
7
+ let inputEl = $state();
8
+ let existingLabels = $state([]);
9
+ let selectedIdx = $state(-1);
10
+ let suggestions = $derived(existingLabels
11
+ .filter((l) => (!inputValue || l.toLowerCase().includes(inputValue.toLowerCase())) &&
12
+ !(labels ?? []).includes(l))
13
+ .slice(0, 8));
14
+ let trimmedInput = $derived(inputValue.trim());
15
+ let showCreateNew = $derived(trimmedInput.length > 0 &&
16
+ !suggestions.some((s) => s.toLowerCase() === trimmedInput.toLowerCase()) &&
17
+ !(labels ?? []).includes(trimmedInput));
18
+ async function loadExistingLabels() {
19
+ try {
20
+ const resp = await fetch(`/api/w/${$workspaceStore}/labels/list`);
21
+ if (resp.ok)
22
+ existingLabels = await resp.json();
23
+ }
24
+ catch { }
25
+ }
26
+ function startAdding() {
27
+ adding = true;
28
+ inputValue = '';
29
+ selectedIdx = -1;
30
+ loadExistingLabels();
31
+ setTimeout(() => inputEl?.focus(), 0);
32
+ }
33
+ function addLabel(value) {
34
+ const v = (value ?? inputValue).trim().slice(0, 50);
35
+ if (!v) {
36
+ adding = false;
37
+ return;
38
+ }
39
+ if (!labels) {
40
+ labels = [];
41
+ }
42
+ if (!labels.includes(v)) {
43
+ labels = [...labels, v];
44
+ onchange?.();
45
+ }
46
+ inputValue = '';
47
+ adding = false;
48
+ }
49
+ function removeLabel(label) {
50
+ if (labels) {
51
+ labels = labels.filter((l) => l !== label);
52
+ onchange?.();
53
+ }
54
+ }
55
+ function onKeydown(e) {
56
+ if (e.key === 'Enter') {
57
+ e.preventDefault();
58
+ if (selectedIdx >= 0 && selectedIdx < suggestions.length) {
59
+ addLabel(suggestions[selectedIdx]);
60
+ }
61
+ else {
62
+ addLabel(); // either "Create new" selected or free text
63
+ }
64
+ }
65
+ else if (e.key === 'Escape') {
66
+ inputValue = '';
67
+ adding = false;
68
+ }
69
+ else if (e.key === 'ArrowDown') {
70
+ e.preventDefault();
71
+ const maxIdx = suggestions.length + (showCreateNew ? 1 : 0) - 1;
72
+ selectedIdx = Math.min(selectedIdx + 1, maxIdx);
73
+ }
74
+ else if (e.key === 'ArrowUp') {
75
+ e.preventDefault();
76
+ selectedIdx = Math.max(selectedIdx - 1, -1);
77
+ }
78
+ }
79
+ function onBlur() {
80
+ // Delay to allow click on suggestion
81
+ setTimeout(() => {
82
+ if (adding)
83
+ addLabel();
84
+ }, 150);
85
+ }
86
+ </script>
87
+
88
+ <div class="inline-flex items-center gap-1 ml-0.5 h-5 {clazz}">
89
+ {#each labels ?? [] as label (label)}
90
+ <Badge color="blue" small>
91
+ {label}
92
+ <button class="ml-0.5 hover:text-red-500" onclick={() => removeLabel(label)}>
93
+ <X size={10} />
94
+ </button>
95
+ </Badge>
96
+ {/each}
97
+ {#if adding}
98
+ <div class="relative">
99
+ <input
100
+ bind:this={inputEl}
101
+ bind:value={inputValue}
102
+ onkeydown={onKeydown}
103
+ onblur={onBlur}
104
+ class="text-2xs border border-blue-300 rounded px-1.5 py-0 h-5 max-w-32 outline-none focus:ring-1 focus:ring-blue-400"
105
+ placeholder="label"
106
+ />
107
+ {#if suggestions.length > 0 || showCreateNew}
108
+ <div
109
+ class="absolute top-6 left-0 z-50 bg-surface border border-light rounded shadow-md max-h-32 overflow-y-auto min-w-32"
110
+ >
111
+ {#each suggestions as suggestion, i}
112
+ <button
113
+ class="w-full text-left text-2xs px-2 py-1 hover:bg-surface-hover {i === selectedIdx
114
+ ? 'bg-surface-hover'
115
+ : ''}"
116
+ onmousedown={(e) => {
117
+ e.preventDefault()
118
+ addLabel(suggestion)
119
+ }}
120
+ >
121
+ {suggestion}
122
+ </button>
123
+ {/each}
124
+ {#if showCreateNew}
125
+ <button
126
+ class="w-full text-left text-2xs px-2 py-1 hover:bg-surface-hover text-blue-600 {selectedIdx ===
127
+ suggestions.length
128
+ ? 'bg-surface-hover'
129
+ : ''}"
130
+ onmousedown={(e) => {
131
+ e.preventDefault()
132
+ addLabel()
133
+ }}
134
+ >
135
+ + Create "{trimmedInput}"
136
+ </button>
137
+ {/if}
138
+ </div>
139
+ {/if}
140
+ </div>
141
+ {:else}
142
+ <button
143
+ class="text-tertiary hover:text-secondary text-2xs flex items-center gap-0.5"
144
+ onclick={startAdding}
145
+ >
146
+ <Tag size={12} /><Plus size={8} />
147
+ </button>
148
+ {/if}
149
+ </div>
@@ -0,0 +1,8 @@
1
+ interface Props {
2
+ labels: string[] | undefined;
3
+ onchange?: () => void;
4
+ class?: string;
5
+ }
6
+ declare const LabelsInput: import("svelte").Component<Props, {}, "labels">;
7
+ type LabelsInput = ReturnType<typeof LabelsInput>;
8
+ export default LabelsInput;
@@ -19,6 +19,7 @@ import { onDestroy, onMount } from 'svelte';
19
19
  import Skeleton from './common/skeleton/Skeleton.svelte';
20
20
  import Button from './common/button/Button.svelte';
21
21
  import { sameTopDomainOrigin } from '../cookies';
22
+ import { isValidLogoutRedirect } from '../logoutRedirect';
22
23
  let { rd = undefined, email = $bindable(undefined), password = $bindable(undefined), error = undefined, popup = false, firstTime = false, onLoginSuccess = undefined } = $props();
23
24
  const providers = [
24
25
  {
@@ -99,7 +100,11 @@ async function login() {
99
100
  }
100
101
  async function redirectUser() {
101
102
  if (rd?.startsWith('http')) {
102
- window.location.href = rd;
103
+ if (isValidLogoutRedirect(rd)) {
104
+ window.location.href = rd;
105
+ return;
106
+ }
107
+ goto('/');
103
108
  return;
104
109
  }
105
110
  if ($workspaceStore) {
@@ -1,10 +1,12 @@
1
- <script lang="ts">import { Database, Loader2 } from 'lucide-svelte';
1
+ <script lang="ts">import { Database, HardDrive, Loader2, Trash2 } from 'lucide-svelte';
2
+ import { onDestroy } from 'svelte';
2
3
  import Toggle from './Toggle.svelte';
3
4
  import { Button, Tab, Tabs } from './common';
4
5
  import { SettingService } from '../gen';
5
6
  import { sendUserToast } from '../toast';
6
7
  import TestConnection from './TestConnection.svelte';
7
8
  import { enterpriseLicense } from '../stores';
9
+ import { displaySize } from '../utils';
8
10
  import SimpleEditor from './SimpleEditor.svelte';
9
11
  import Label from './Label.svelte';
10
12
  import TextInput from './text_input/TextInput.svelte';
@@ -28,6 +30,126 @@ async function testConnection() {
28
30
  loading = false;
29
31
  }
30
32
  }
33
+ let usageStatus = $state(undefined);
34
+ let usageStarting = $state(false);
35
+ let usagePollHandle = undefined;
36
+ async function fetchUsageStatus() {
37
+ try {
38
+ usageStatus = (await SettingService.getObjectStorageUsage()) ?? null;
39
+ }
40
+ catch (e) {
41
+ // Silent — polling errors shouldn't spam toasts.
42
+ console.warn('failed to fetch storage usage status', e);
43
+ }
44
+ }
45
+ function startUsagePolling() {
46
+ if (usagePollHandle !== undefined)
47
+ return;
48
+ usagePollHandle = setInterval(async () => {
49
+ await fetchUsageStatus();
50
+ if (usageStatus && !usageStatus.running) {
51
+ stopUsagePolling();
52
+ }
53
+ }, 1500);
54
+ }
55
+ function stopUsagePolling() {
56
+ if (usagePollHandle !== undefined) {
57
+ clearInterval(usagePollHandle);
58
+ usagePollHandle = undefined;
59
+ }
60
+ }
61
+ async function startUsage() {
62
+ usageStarting = true;
63
+ try {
64
+ await SettingService.computeObjectStorageUsage();
65
+ await fetchUsageStatus();
66
+ startUsagePolling();
67
+ }
68
+ catch (e) {
69
+ sendUserToast(e?.body ?? e?.message ?? 'Failed to start storage usage computation', true);
70
+ }
71
+ finally {
72
+ usageStarting = false;
73
+ }
74
+ }
75
+ let cleanupStatus = $state(undefined);
76
+ let cleanupStarting = $state(false);
77
+ let cleanupPollHandle = undefined;
78
+ let cleanupProgress = $derived.by(() => {
79
+ if (!cleanupStatus)
80
+ return 0;
81
+ const total = cleanupStatus.total_service + cleanupStatus.total_jobs;
82
+ const processed = cleanupStatus.processed_service + cleanupStatus.processed_jobs;
83
+ return total > 0 ? Math.min(100, Math.round((processed / total) * 100)) : 0;
84
+ });
85
+ async function fetchCleanupStatus() {
86
+ try {
87
+ cleanupStatus = (await SettingService.getLogCleanupStatus()) ?? null;
88
+ }
89
+ catch (e) {
90
+ // Silent — polling errors shouldn't spam toasts.
91
+ console.warn('failed to fetch log cleanup status', e);
92
+ }
93
+ }
94
+ function startPolling() {
95
+ if (cleanupPollHandle !== undefined)
96
+ return;
97
+ cleanupPollHandle = setInterval(async () => {
98
+ await fetchCleanupStatus();
99
+ if (cleanupStatus && !cleanupStatus.running) {
100
+ stopPolling();
101
+ }
102
+ }, 1000);
103
+ }
104
+ function stopPolling() {
105
+ if (cleanupPollHandle !== undefined) {
106
+ clearInterval(cleanupPollHandle);
107
+ cleanupPollHandle = undefined;
108
+ }
109
+ }
110
+ async function startCleanup() {
111
+ cleanupStarting = true;
112
+ try {
113
+ await SettingService.runLogCleanup();
114
+ await fetchCleanupStatus();
115
+ startPolling();
116
+ }
117
+ catch (e) {
118
+ sendUserToast(e?.body ?? e?.message ?? 'Failed to start cleanup', true);
119
+ }
120
+ finally {
121
+ cleanupStarting = false;
122
+ }
123
+ }
124
+ let hasConfig = $derived(Boolean(bucket_config));
125
+ $effect(() => {
126
+ if (hasConfig) {
127
+ let cancelled = false;
128
+ fetchCleanupStatus().then(() => {
129
+ if (!cancelled && cleanupStatus?.running) {
130
+ startPolling();
131
+ }
132
+ });
133
+ fetchUsageStatus().then(() => {
134
+ if (!cancelled && usageStatus?.running) {
135
+ startUsagePolling();
136
+ }
137
+ });
138
+ return () => {
139
+ cancelled = true;
140
+ };
141
+ }
142
+ else {
143
+ stopPolling();
144
+ stopUsagePolling();
145
+ cleanupStatus = undefined;
146
+ usageStatus = undefined;
147
+ }
148
+ });
149
+ onDestroy(() => {
150
+ stopPolling();
151
+ stopUsagePolling();
152
+ });
31
153
  let simpleEditor = $state(undefined);
32
154
  let serviceAccountKeyCode = $state(bucket_config?.type === 'Gcs'
33
155
  ? JSON.stringify(bucket_config.serviceAccountKey, null, '\t')
@@ -93,6 +215,156 @@ $effect(() => {
93
215
  />
94
216
  </div>
95
217
 
218
+ <div class="border rounded-md p-3 my-2">
219
+ <div class="flex items-center justify-between gap-2">
220
+ <div class="flex flex-col">
221
+ <span class="text-xs font-semibold text-emphasis">Storage usage by folder</span>
222
+ <span class="text-tertiary text-2xs">
223
+ Runs in the background — large buckets can take several minutes.
224
+ </span>
225
+ </div>
226
+ <Button
227
+ spacingSize="sm"
228
+ size="xs"
229
+ btnClasses="h-8"
230
+ variant="border"
231
+ disabled={usageStarting || usageStatus?.running}
232
+ on:click={startUsage}
233
+ >
234
+ {#if usageStarting || usageStatus?.running}
235
+ <Loader2 class="animate-spin mr-2 !h-4 !w-4" />
236
+ {:else}
237
+ <HardDrive class="mr-2 !h-4 !w-4" />
238
+ {/if}
239
+ {usageStatus?.running
240
+ ? 'Running…'
241
+ : usageStatus && usageStatus.folders.length > 0
242
+ ? 'Refresh'
243
+ : 'Show usage'}
244
+ </Button>
245
+ </div>
246
+
247
+ {#if usageStatus}
248
+ <div class="mt-2 flex flex-col gap-1">
249
+ {#if usageStatus.running}
250
+ <div class="text-2xs text-tertiary">
251
+ Scanning…
252
+ {usageStatus.scanned_objects.toLocaleString()} objects inspected
253
+ {#if usageStatus.current_prefix}
254
+ — currently under
255
+ <span class="font-mono">{usageStatus.current_prefix}</span>
256
+ {/if}
257
+ </div>
258
+ {:else if usageStatus.finished_at}
259
+ <div class="text-2xs text-tertiary">
260
+ Scanned {usageStatus.scanned_objects.toLocaleString()} objects · finished at {new Date(
261
+ usageStatus.finished_at
262
+ ).toLocaleString()}
263
+ </div>
264
+ {/if}
265
+ {#if usageStatus.error}
266
+ <div class="text-red-500 text-2xs">Error: {usageStatus.error}</div>
267
+ {/if}
268
+ {#if usageStatus.folders.length > 0}
269
+ <div class="flex flex-col gap-0.5 mt-1">
270
+ {#each usageStatus.folders as item (item.prefix)}
271
+ <div
272
+ class="flex justify-between items-center text-xs py-1 px-2 rounded hover:bg-surface-hover"
273
+ title={item.partial
274
+ ? 'Listing errored mid-stream; size is a lower bound, not the true total.'
275
+ : undefined}
276
+ >
277
+ <span class="font-mono text-secondary">{item.prefix}</span>
278
+ <span class="text-tertiary font-semibold">
279
+ {displaySize(item.size) ?? '0 B'}{item.partial ? ' (partial)' : ''}
280
+ </span>
281
+ </div>
282
+ {/each}
283
+ <div
284
+ class="flex justify-between items-center text-xs py-1 px-2 border-t mt-1 pt-2 font-semibold"
285
+ >
286
+ <span>Total{usageStatus.running ? ' (partial)' : ''}</span>
287
+ <span
288
+ >{displaySize(usageStatus.folders.reduce((acc, item) => acc + item.size, 0)) ??
289
+ '0 B'}</span
290
+ >
291
+ </div>
292
+ </div>
293
+ {:else if !usageStatus.running && usageStatus.finished_at}
294
+ <div class="text-tertiary text-xs">No objects found in the bucket.</div>
295
+ {/if}
296
+ </div>
297
+ {/if}
298
+ </div>
299
+
300
+ <div class="border rounded-md p-3 my-2">
301
+ <div class="flex items-center justify-between gap-2">
302
+ <div class="flex flex-col">
303
+ <span class="text-xs font-semibold text-emphasis">Clean up expired logs</span>
304
+ <span class="text-tertiary text-2xs">
305
+ Delete expired service &amp; job logs from object storage and disk now, then scan the
306
+ bucket for orphan log files left behind by previously deleted jobs. Uses batched deletes
307
+ (up to 1000 objects per request).
308
+ </span>
309
+ </div>
310
+ <Button
311
+ spacingSize="sm"
312
+ size="xs"
313
+ btnClasses="h-8"
314
+ variant="border"
315
+ disabled={cleanupStarting || cleanupStatus?.running}
316
+ on:click={startCleanup}
317
+ >
318
+ {#if cleanupStarting || cleanupStatus?.running}
319
+ <Loader2 class="animate-spin mr-2 !h-4 !w-4" />
320
+ {:else}
321
+ <Trash2 class="mr-2 !h-4 !w-4" />
322
+ {/if}
323
+ {cleanupStatus?.running ? 'Running…' : 'Run cleanup'}
324
+ </Button>
325
+ </div>
326
+
327
+ {#if cleanupStatus}
328
+ {@const total = cleanupStatus.total_service + cleanupStatus.total_jobs}
329
+ {@const processed = cleanupStatus.processed_service + cleanupStatus.processed_jobs}
330
+ <div class="mt-3 flex flex-col gap-1">
331
+ <div class="w-full h-2 bg-surface-secondary rounded overflow-hidden">
332
+ <div class="h-full bg-blue-500 transition-all" style:width="{cleanupProgress}%"></div>
333
+ </div>
334
+ <div class="flex justify-between text-2xs text-tertiary">
335
+ <span>
336
+ Phase: <span class="font-semibold">{cleanupStatus.phase}</span>
337
+ </span>
338
+ <span>
339
+ S3 deleted: {cleanupStatus.s3_deleted.toLocaleString()}
340
+ {#if cleanupStatus.errors > 0}
341
+ &middot; errors: {cleanupStatus.errors.toLocaleString()}
342
+ {/if}
343
+ </span>
344
+ </div>
345
+ <div class="text-2xs text-tertiary">
346
+ DB: {processed.toLocaleString()} / {total.toLocaleString()} rows deleted ({cleanupProgress}%)
347
+ &middot; service {cleanupStatus.processed_service.toLocaleString()}/{cleanupStatus.total_service.toLocaleString()},
348
+ job {cleanupStatus.processed_jobs.toLocaleString()}/{cleanupStatus.total_jobs.toLocaleString()}
349
+ </div>
350
+ <div class="text-2xs text-tertiary">
351
+ Orphan scan: {cleanupStatus.orphans_scanned.toLocaleString()} scanned,
352
+ {cleanupStatus.orphans_deleted.toLocaleString()} deleted
353
+ </div>
354
+ {#if !cleanupStatus.running && cleanupStatus.finished_at}
355
+ <div class="text-2xs text-tertiary">
356
+ Finished at {new Date(cleanupStatus.finished_at).toLocaleString()}
357
+ </div>
358
+ {/if}
359
+ {#if cleanupStatus.last_error}
360
+ <div class="text-red-500 text-2xs mt-1">
361
+ Last error: {cleanupStatus.last_error}
362
+ </div>
363
+ {/if}
364
+ </div>
365
+ {/if}
366
+ </div>
367
+
96
368
  <Tabs
97
369
  selected={bucket_config?.type ?? 'S3'}
98
370
  on:selected={(e) => {
@@ -10,17 +10,18 @@ let lastValues = { domain: undefined, custom: undefined };
10
10
  function changeDomain(domain, custom) {
11
11
  if (value) {
12
12
  let baseUrl = custom ? `https://${domain}` : `https://${domain}.okta.com`;
13
+ let authPath = custom ? '/v1' : '/oauth2/v1';
13
14
  value = {
14
15
  ...value,
15
16
  login_config: {
16
- auth_url: `${baseUrl}/oauth2/v1/authorize`,
17
- token_url: `${baseUrl}/oauth2/v1/token`,
18
- userinfo_url: `${baseUrl}/oauth2/v1/userinfo`,
17
+ auth_url: `${baseUrl}${authPath}/authorize`,
18
+ token_url: `${baseUrl}${authPath}/token`,
19
+ userinfo_url: `${baseUrl}${authPath}/userinfo`,
19
20
  scopes: ['openid', 'profile', 'email']
20
21
  },
21
22
  connect_config: {
22
- auth_url: `${baseUrl}/oauth2/v1/authorize`,
23
- token_url: `${baseUrl}/oauth2/v1/token`,
23
+ auth_url: `${baseUrl}${authPath}/authorize`,
24
+ token_url: `${baseUrl}${authPath}/token`,
24
25
  scopes: ['openid', 'profile', 'email']
25
26
  }
26
27
  };