windmill-components 1.433.0 → 1.444.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 (286) hide show
  1. package/package/components/ArgInput.svelte +12 -16
  2. package/package/components/ArgInput.svelte.d.ts +1 -0
  3. package/package/components/AssignableTags.svelte +3 -1
  4. package/package/components/AssignableTags.svelte.d.ts +1 -0
  5. package/package/components/AuthSettings.svelte +248 -0
  6. package/package/components/AuthSettings.svelte.d.ts +19 -0
  7. package/package/components/AutoscalingConfigEditor.svelte +2 -2
  8. package/package/components/CronInput.svelte +2 -2
  9. package/package/components/DeployWorkspace.svelte +1 -1
  10. package/package/components/Description.svelte +9 -0
  11. package/package/components/Description.svelte.d.ts +18 -0
  12. package/package/components/Dev.svelte +18 -3
  13. package/package/components/DisplayResult.svelte +7 -4
  14. package/package/components/DisplayResult.svelte.d.ts +1 -0
  15. package/package/components/DropdownV2.svelte +2 -1
  16. package/package/components/DropdownV2.svelte.d.ts +1 -0
  17. package/package/components/EditableSchemaForm.svelte +2 -2
  18. package/package/components/Editor.svelte +9 -6
  19. package/package/components/Editor.svelte.d.ts +4 -2
  20. package/package/components/EditorBar.svelte +51 -6
  21. package/package/components/ErrorOrRecoveryHandler.svelte +4 -3
  22. package/package/components/ExecutionDuration.svelte +2 -1
  23. package/package/components/FieldHeader.svelte +9 -1
  24. package/package/components/FieldHeader.svelte.d.ts +1 -0
  25. package/package/components/FlowBuilder.svelte +16 -3
  26. package/package/components/FlowGraphViewer.svelte +2 -0
  27. package/package/components/FlowPreviewContent.svelte +6 -15
  28. package/package/components/FlowStatusViewerInner.svelte +80 -55
  29. package/package/components/FlowStatusViewerInner.svelte.d.ts +1 -0
  30. package/package/components/HighlightCode.svelte +3 -0
  31. package/package/components/InputTransformSchemaForm.svelte +1 -1
  32. package/package/components/InstanceSetting.svelte +774 -0
  33. package/package/components/InstanceSetting.svelte.d.ts +27 -0
  34. package/package/components/InstanceSettings.svelte +68 -1005
  35. package/package/components/InstanceSettings.svelte.d.ts +0 -4
  36. package/package/components/Label.svelte +16 -6
  37. package/package/components/Label.svelte.d.ts +3 -0
  38. package/package/components/Login.svelte +17 -9
  39. package/package/components/OAuthSetting.svelte +4 -3
  40. package/package/components/OauthExtraParams.svelte +1 -1
  41. package/package/components/OauthScopes.svelte +2 -2
  42. package/package/components/ObjectStoreConfigSettings.svelte +141 -128
  43. package/package/components/QueueMetricsDrawer.svelte +5 -5
  44. package/package/components/ResourceEditor.svelte +4 -0
  45. package/package/components/ResourceEditor.svelte.d.ts +1 -0
  46. package/package/components/ResourceEditorDrawer.svelte +15 -3
  47. package/package/components/ResourceEditorDrawer.svelte.d.ts +2 -2
  48. package/package/components/ResourcePicker.svelte +16 -5
  49. package/package/components/ResourcePicker.svelte.d.ts +1 -0
  50. package/package/components/ResultJobLoader.svelte.d.ts +1 -1
  51. package/package/components/RunPageSchedules.svelte +15 -10
  52. package/package/components/SavedInputs.svelte +1 -1
  53. package/package/components/ScheduleEditorInner.svelte +58 -27
  54. package/package/components/SchemaForm.svelte +7 -5
  55. package/package/components/SchemaForm.svelte.d.ts +1 -0
  56. package/package/components/ScriptBuilder.svelte +58 -5
  57. package/package/components/ScriptEditor.svelte +78 -40
  58. package/package/components/ScriptEditor.svelte.d.ts +17 -2
  59. package/package/components/ScriptPicker.svelte +41 -34
  60. package/package/components/ScriptPicker.svelte.d.ts +1 -0
  61. package/package/components/ScriptVersionHistory.svelte +1 -1
  62. package/package/components/Section.svelte +38 -35
  63. package/package/components/Section.svelte.d.ts +2 -0
  64. package/package/components/ServiceLogsInner.svelte +1 -1
  65. package/package/components/SimpleEditor.svelte +2 -0
  66. package/package/components/Subsection.svelte +52 -0
  67. package/package/components/Subsection.svelte.d.ts +27 -0
  68. package/package/components/SuperadminSettings.svelte +23 -13
  69. package/package/components/TemplateEditor.svelte +4 -3
  70. package/package/components/TestConnection.svelte +5 -0
  71. package/package/components/TestJobLoader.svelte +2 -1
  72. package/package/components/TestJobLoader.svelte.d.ts +1 -1
  73. package/package/components/Toggle.svelte +2 -4
  74. package/package/components/UserSettings.svelte +1 -1
  75. package/package/components/WorkerGroup.svelte +4 -4
  76. package/package/components/WorkerTagPicker.svelte +4 -2
  77. package/package/components/WorkerTagPicker.svelte.d.ts +1 -0
  78. package/package/components/WorkerTagSelect.svelte +2 -0
  79. package/package/components/WorkerTagSelect.svelte.d.ts +1 -0
  80. package/package/components/apps/components/display/AppDisplayComponent.svelte +2 -1
  81. package/package/components/apps/components/display/dbtable/utils.js +26 -1
  82. package/package/components/apps/components/helpers/RunnableComponent.svelte +8 -2
  83. package/package/components/apps/components/inputs/AppDateInput.svelte +7 -1
  84. package/package/components/apps/components/inputs/AppS3FileInput.svelte +1 -1
  85. package/package/components/apps/editor/AppEditor.svelte +5 -34
  86. package/package/components/apps/editor/AppEditor.svelte.d.ts +1 -0
  87. package/package/components/apps/editor/AppEditorBottomPanel.svelte +4 -7
  88. package/package/components/apps/editor/AppEditorBottomPanel.svelte.d.ts +1 -3
  89. package/package/components/apps/editor/AppEditorHeader.svelte +148 -58
  90. package/package/components/apps/editor/AppEditorHeader.svelte.d.ts +1 -0
  91. package/package/components/apps/editor/DeploymentHistory.svelte +1 -1
  92. package/package/components/apps/editor/RunnableJobPanel.svelte +6 -2
  93. package/package/components/apps/editor/RunnableJobPanel.svelte.d.ts +1 -0
  94. package/package/components/apps/editor/appUtils.d.ts +1 -0
  95. package/package/components/apps/editor/appUtils.js +17 -0
  96. package/package/components/apps/editor/component/components.d.ts +82 -81
  97. package/package/components/apps/editor/component/components.js +4 -3
  98. package/package/components/apps/editor/componentsPanel/ComponentList.svelte +1 -1
  99. package/package/components/apps/editor/componentsPanel/GroupList.svelte +12 -2
  100. package/package/components/apps/editor/contextPanel/ContextPanel.svelte +1 -1
  101. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditorDrawer.svelte +1 -1
  102. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte +53 -56
  103. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte +1 -1
  104. package/package/components/apps/editor/settingsPanel/inputEditor/EvalV2InputEditor.svelte +3 -2
  105. package/package/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte +1 -1
  106. package/package/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte +16 -9
  107. package/package/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte.d.ts +1 -0
  108. package/package/components/apps/inputType.d.ts +2 -2
  109. package/package/components/apps/types.d.ts +2 -0
  110. package/package/components/common/alert/ConnectionIndicator.svelte +30 -0
  111. package/package/components/common/alert/ConnectionIndicator.svelte.d.ts +20 -0
  112. package/package/components/common/alert/Notification.svelte +15 -0
  113. package/package/components/common/alert/Notification.svelte.d.ts +17 -0
  114. package/package/components/common/button/AnimatedButton.svelte +1 -1
  115. package/package/components/common/button/RefreshButton.svelte +30 -0
  116. package/package/components/common/button/RefreshButton.svelte.d.ts +18 -0
  117. package/package/components/common/fileDownload/FileDownload.svelte +4 -3
  118. package/package/components/common/fileDownload/FileDownload.svelte.d.ts +1 -0
  119. package/package/components/common/fileUpload/FileUpload.svelte +3 -3
  120. package/package/components/common/languageIcons/LanguageIcon.svelte +5 -2
  121. package/package/components/common/layout/List.svelte +35 -0
  122. package/package/components/common/layout/List.svelte.d.ts +21 -0
  123. package/package/components/common/layout/ListElement.svelte +3 -0
  124. package/package/components/common/layout/ListElement.svelte.d.ts +27 -0
  125. package/package/components/common/menu/MenuV2.svelte +3 -2
  126. package/package/components/common/menu/MenuV2.svelte.d.ts +1 -0
  127. package/package/components/common/modal/Modal.svelte +6 -4
  128. package/package/components/common/modal/Modal.svelte.d.ts +1 -0
  129. package/package/components/common/modal/Modal2.svelte +101 -0
  130. package/package/components/common/modal/Modal2.svelte.d.ts +28 -0
  131. package/package/components/common/popup/Popup.svelte +5 -1
  132. package/package/components/common/popup/Popup.svelte.d.ts +2 -0
  133. package/package/components/common/toggleButton-v2/ToggleButton.svelte +1 -1
  134. package/package/components/copilot/FlowCopilotStatus.svelte +1 -1
  135. package/package/components/details/ClipboardPanel.svelte +12 -2
  136. package/package/components/details/ClipboardPanel.svelte.d.ts +2 -0
  137. package/package/components/details/CopyableCodeBlock.svelte +24 -0
  138. package/package/components/details/CopyableCodeBlock.svelte.d.ts +19 -0
  139. package/package/components/details/DetailPageLayout.svelte +3 -1
  140. package/package/components/details/EmailTriggerConfigSection.svelte +119 -0
  141. package/package/components/details/EmailTriggerConfigSection.svelte.d.ts +38 -0
  142. package/package/components/details/EmailTriggerPanel.svelte +27 -74
  143. package/package/components/details/EmailTriggerPanel.svelte.d.ts +7 -1
  144. package/package/components/flows/FlowEditor.svelte +1 -1
  145. package/package/components/flows/FlowEditor.svelte.d.ts +1 -0
  146. package/package/components/flows/FlowHistoryInner.svelte +1 -1
  147. package/package/components/flows/content/BranchPredicateEditor.svelte +1 -1
  148. package/package/components/flows/content/FlowEditorPanel.svelte +30 -1
  149. package/package/components/flows/content/FlowEditorPanel.svelte.d.ts +2 -0
  150. package/package/components/flows/content/FlowInput.svelte +2 -15
  151. package/package/components/flows/content/FlowInputs.svelte +1 -1
  152. package/package/components/flows/content/FlowInputsQuick.svelte +2 -2
  153. package/package/components/flows/content/FlowModuleComponent.svelte +9 -5
  154. package/package/components/flows/content/FlowModuleEarlyStop.svelte +2 -2
  155. package/package/components/flows/content/FlowModuleHeader.svelte +4 -1
  156. package/package/components/flows/content/FlowModuleSuspend.svelte +1 -1
  157. package/package/components/flows/content/FlowPathViewer.svelte +3 -1
  158. package/package/components/flows/content/FlowRetries.svelte +32 -5
  159. package/package/components/flows/content/FlowSettings.svelte +56 -48
  160. package/package/components/flows/flowStateUtils.d.ts +10 -1
  161. package/package/components/flows/flowStateUtils.js +23 -0
  162. package/package/components/flows/map/FlowModuleSchemaMap.svelte +9 -19
  163. package/package/components/flows/map/InsertModuleButton.svelte +3 -3
  164. package/package/components/flows/map/VirtualItem.svelte +29 -1
  165. package/package/components/flows/map/VirtualItem.svelte.d.ts +2 -0
  166. package/package/components/flows/pickers/TopLevelNode.svelte +2 -2
  167. package/package/components/flows/previousResults.js +8 -2
  168. package/package/components/flows/types.d.ts +1 -0
  169. package/package/components/graph/FlowGraphV2.svelte +16 -2
  170. package/package/components/graph/FlowGraphV2.svelte.d.ts +2 -0
  171. package/package/components/graph/graphBuilder.js +1 -0
  172. package/package/components/graph/renderers/nodes/InputNode.svelte +2 -0
  173. package/package/components/graph/renderers/nodes/InputNode.svelte.d.ts +2 -0
  174. package/package/components/graph/renderers/triggers/TriggersWrapper.svelte +1 -1
  175. package/package/components/icons/CSharpIcon.svelte +14 -0
  176. package/package/components/icons/CSharpIcon.svelte.d.ts +25 -0
  177. package/package/components/icons/GitIcon.svelte +5 -2
  178. package/package/components/icons/XeroIcon.svelte +24 -0
  179. package/package/components/icons/XeroIcon.svelte.d.ts +17 -0
  180. package/package/components/icons/index.d.ts +3 -1
  181. package/package/components/icons/index.js +4 -2
  182. package/package/components/instanceSettings.d.ts +3 -1
  183. package/package/components/instanceSettings.js +77 -69
  184. package/package/components/meltComponents/Popover.svelte +82 -0
  185. package/package/components/meltComponents/Popover.svelte.d.ts +21 -0
  186. package/package/components/propertyPicker/PropPicker.svelte +5 -3
  187. package/package/components/runs/JobLoader.svelte +5 -2
  188. package/package/components/runs/JobPreview.svelte +5 -5
  189. package/package/components/runs/RunRow.svelte +3 -4
  190. package/package/components/runs/RunsFilter.svelte +4 -4
  191. package/package/components/schema/EditableSchemaDrawer.svelte +4 -4
  192. package/package/components/schema/PropertyEditor.svelte +1 -1
  193. package/package/components/schema/SchemaFormDND.svelte +2 -0
  194. package/package/components/schema/SchemaFormDND.svelte.d.ts +1 -0
  195. package/package/components/scriptEditor/LogPanel.svelte +176 -164
  196. package/package/components/scriptEditor/LogPanel.svelte.d.ts +2 -0
  197. package/package/components/search/GlobalSearchModal.svelte +3 -3
  198. package/package/components/sidebar/CriticalAlertModal.svelte +155 -9
  199. package/package/components/sidebar/CriticalAlertModalInner.svelte +65 -212
  200. package/package/components/sidebar/CriticalAlertModalInner.svelte.d.ts +2 -4
  201. package/package/components/sidebar/CriticalAlertTable.svelte +142 -0
  202. package/package/components/sidebar/CriticalAlertTable.svelte.d.ts +25 -0
  203. package/package/components/sidebar/OperatorMenu.svelte +30 -8
  204. package/package/components/sidebar/SideBarNotification.svelte +3 -6
  205. package/package/components/sidebar/SidebarContent.svelte +5 -5
  206. package/package/components/sidebar/WorkspaceMenu.svelte +9 -5
  207. package/package/components/sidebar/WorkspaceMenu.svelte.d.ts +1 -0
  208. package/package/components/sidebar/changelogs.js +82 -17
  209. package/package/components/splitPanes/SplitPanesOrColumnOnMobile.svelte +21 -21
  210. package/package/components/table/AutoDataTable.svelte +1 -1
  211. package/package/components/table/Cell.svelte +5 -3
  212. package/package/components/table/Cell.svelte.d.ts +1 -0
  213. package/package/components/table/DataTable.svelte +65 -58
  214. package/package/components/table/DataTable.svelte.d.ts +2 -0
  215. package/package/components/table/Head.svelte +1 -1
  216. package/package/components/table/Row.svelte +3 -1
  217. package/package/components/table/Row.svelte.d.ts +1 -0
  218. package/package/components/toast.js +3 -1
  219. package/package/components/triggers/CaptureButton.svelte +77 -0
  220. package/package/components/triggers/CaptureButton.svelte.d.ts +16 -0
  221. package/package/components/triggers/CaptureIcon.svelte +17 -0
  222. package/package/components/triggers/CaptureIcon.svelte.d.ts +23 -0
  223. package/package/components/triggers/CaptureSection.svelte +76 -0
  224. package/package/components/triggers/CaptureSection.svelte.d.ts +42 -0
  225. package/package/components/triggers/CaptureTable.svelte +224 -0
  226. package/package/components/triggers/CaptureTable.svelte.d.ts +43 -0
  227. package/package/components/triggers/CaptureWrapper.svelte +237 -0
  228. package/package/components/triggers/CaptureWrapper.svelte.d.ts +35 -0
  229. package/package/components/triggers/KafkaTriggerEditor.svelte +2 -2
  230. package/package/components/triggers/KafkaTriggerEditor.svelte.d.ts +2 -2
  231. package/package/components/triggers/KafkaTriggerEditorInner.svelte +47 -119
  232. package/package/components/triggers/KafkaTriggerEditorInner.svelte.d.ts +2 -2
  233. package/package/components/triggers/KafkaTriggersConfigSection.svelte +215 -0
  234. package/package/components/triggers/KafkaTriggersConfigSection.svelte.d.ts +36 -0
  235. package/package/components/triggers/KafkaTriggersPanel.svelte +73 -45
  236. package/package/components/triggers/KafkaTriggersPanel.svelte.d.ts +6 -0
  237. package/package/components/triggers/RouteEditor.svelte +2 -2
  238. package/package/components/triggers/RouteEditor.svelte.d.ts +2 -2
  239. package/package/components/triggers/RouteEditorConfigSection.svelte +162 -0
  240. package/package/components/triggers/RouteEditorConfigSection.svelte.d.ts +43 -0
  241. package/package/components/triggers/RouteEditorInner.svelte +98 -163
  242. package/package/components/triggers/RouteEditorInner.svelte.d.ts +2 -2
  243. package/package/components/triggers/RoutesPanel.svelte +69 -54
  244. package/package/components/triggers/RoutesPanel.svelte.d.ts +5 -0
  245. package/package/components/triggers/ScheduledPollPanel.svelte +5 -9
  246. package/package/components/triggers/TriggersEditor.svelte +119 -89
  247. package/package/components/triggers/TriggersEditor.svelte.d.ts +7 -0
  248. package/package/components/triggers/TriggersEditorSection.svelte +109 -0
  249. package/package/components/triggers/TriggersEditorSection.svelte.d.ts +29 -0
  250. package/package/components/triggers/TriggersWrapper.svelte +60 -0
  251. package/package/components/triggers/TriggersWrapper.svelte.d.ts +21 -0
  252. package/package/components/triggers/WebhooksConfigSection.svelte +382 -0
  253. package/package/components/triggers/WebhooksConfigSection.svelte.d.ts +39 -0
  254. package/package/components/triggers/WebhooksPanel.svelte +32 -331
  255. package/package/components/triggers/WebhooksPanel.svelte.d.ts +7 -1
  256. package/package/components/triggers/WebsocketEditorConfigSection.svelte +176 -0
  257. package/package/components/triggers/WebsocketEditorConfigSection.svelte.d.ts +37 -0
  258. package/package/components/triggers/WebsocketTriggerEditor.svelte +2 -2
  259. package/package/components/triggers/WebsocketTriggerEditor.svelte.d.ts +2 -2
  260. package/package/components/triggers/WebsocketTriggerEditorInner.svelte +29 -150
  261. package/package/components/triggers/WebsocketTriggerEditorInner.svelte.d.ts +2 -2
  262. package/package/components/triggers/WebsocketTriggersPanel.svelte +70 -45
  263. package/package/components/triggers/WebsocketTriggersPanel.svelte.d.ts +6 -0
  264. package/package/components/triggers.d.ts +6 -2
  265. package/package/components/triggers.js +16 -0
  266. package/package/components/wizards/AgGridWizard.svelte +4 -4
  267. package/package/editorUtils.d.ts +2 -0
  268. package/package/editorUtils.js +6 -3
  269. package/package/gen/core/OpenAPI.js +1 -1
  270. package/package/gen/schemas.gen.d.ts +17 -8
  271. package/package/gen/schemas.gen.js +17 -8
  272. package/package/gen/services.gen.d.ts +55 -5
  273. package/package/gen/services.gen.js +108 -5
  274. package/package/gen/types.gen.d.ts +180 -13
  275. package/package/hubPaths.json +6 -3
  276. package/package/infer.js +9 -0
  277. package/package/script_helpers.d.ts +5 -0
  278. package/package/script_helpers.js +68 -8
  279. package/package/scripts.d.ts +1 -1
  280. package/package/scripts.js +5 -1
  281. package/package/stores.d.ts +1 -0
  282. package/package/utils.d.ts +3 -1
  283. package/package/utils.js +20 -4
  284. package/package.json +11 -8
  285. package/package/components/flows/content/CapturePayload.svelte +0 -114
  286. package/package/components/flows/content/CapturePayload.svelte.d.ts +0 -17
@@ -1,53 +1,34 @@
1
- <script>import { settings, settingsKeys } from './instanceSettings';
2
- import { Button, Skeleton, Tab, TabContent, Tabs } from './common';
3
- import { IndexSearchService, SettingService, SettingsService } from '../gen';
4
- import Toggle from './Toggle.svelte';
5
- import SecondsInput from './common/seconds/SecondsInput.svelte';
6
- import Tooltip from './Tooltip.svelte';
1
+ <script>import { scimSamlSetting, settings, settingsKeys } from './instanceSettings';
2
+ import { Button, Tab, TabContent, Tabs } from './common';
3
+ import { SettingService, SettingsService } from '../gen';
7
4
  import { sendUserToast } from '../toast';
8
- import OAuthSetting from './OAuthSetting.svelte';
9
5
  import { deepEqual } from 'fast-equals';
10
- import OktaSetting from './OktaSetting.svelte';
11
- import CloseButton from './common/CloseButton.svelte';
12
- import KeycloakSetting from './KeycloakSetting.svelte';
13
- import Alert from './common/alert/Alert.svelte';
14
- import { isCloudHosted } from '../cloud';
15
- import { capitalize, classNames, sleep } from '../utils';
16
- import { enterpriseLicense, isCriticalAlertsUIOpen } from '../stores';
17
- import CustomOauth from './CustomOauth.svelte';
18
- import { AlertCircle, AlertTriangle, BadgeCheck, Info, Plus, X, BadgeX, Slack } from 'lucide-svelte';
19
- import CustomSso from './CustomSso.svelte';
20
- import AuthentikSetting from './AuthentikSetting.svelte';
21
- import AutheliaSetting from './AutheliaSetting.svelte';
22
- import KanidmSetting from './KanidmSetting.svelte';
23
- import ZitadelSetting from './ZitadelSetting.svelte';
24
- import Password from './Password.svelte';
25
- import ObjectStoreConfigSettings from './ObjectStoreConfigSettings.svelte';
26
- import { fade } from 'svelte/transition';
27
- import Popover from './Popover.svelte';
28
- import { base } from '../base';
6
+ import { sleep } from '../utils';
7
+ import { enterpriseLicense } from '../stores';
29
8
  import { createEventDispatcher } from 'svelte';
30
9
  import { setLicense } from '../enterpriseUtils';
31
- import ConfirmButton from './ConfirmButton.svelte';
10
+ import AuthSettings from './AuthSettings.svelte';
11
+ import InstanceSetting from './InstanceSetting.svelte';
12
+ import { writable } from 'svelte/store';
32
13
  export let tab = 'Core';
33
14
  export let hideTabs = false;
34
15
  export let hideSave = false;
35
16
  export let closeDrawer = () => { };
36
- let values = {};
17
+ let values = writable({});
37
18
  let initialOauths = {};
38
19
  let initialRequirePreexistingUserForOauth = false;
39
20
  let requirePreexistingUserForOauth = false;
40
- let ssoOrOauth = 'sso';
41
- let latestKeyRenewalAttempt = null;
42
21
  let initialValues = {};
43
- let loading = true;
22
+ let snowflakeAccountIdentifier = '';
44
23
  let version = '';
24
+ let loading = true;
45
25
  loadSettings();
46
26
  loadVersion();
47
27
  const dispatch = createEventDispatcher();
48
28
  async function loadVersion() {
49
29
  version = await SettingsService.backendVersion();
50
30
  }
31
+ let oauths = {};
51
32
  async function loadSettings() {
52
33
  loading = true;
53
34
  async function getValue(key, storage) {
@@ -62,24 +43,27 @@ async function loadSettings() {
62
43
  initialRequirePreexistingUserForOauth = requirePreexistingUserForOauth;
63
44
  oauths = JSON.parse(JSON.stringify(initialOauths));
64
45
  initialValues = Object.fromEntries((await Promise.all(Object.entries(settings).map(async ([_, y]) => await Promise.all(y.map(async (x) => [x.key, await getValue(x.key, x.storage)]))))).flat());
65
- values = JSON.parse(JSON.stringify(initialValues));
66
- if (values['base_url'] == undefined) {
67
- values['base_url'] = window.location.origin;
46
+ let nvalues = JSON.parse(JSON.stringify(initialValues));
47
+ if (nvalues['base_url'] == undefined) {
48
+ nvalues['base_url'] = window.location.origin;
68
49
  }
69
- if (values['retention_period_secs'] == undefined) {
70
- values['retention_period_secs'] = 60 * 60 * 24 * 30;
50
+ if (nvalues['retention_period_secs'] == undefined) {
51
+ nvalues['retention_period_secs'] = 60 * 60 * 24 * 30;
71
52
  }
72
- if (values['base_url'] == undefined) {
73
- values['base_url'] = 'http://localhost';
53
+ if (nvalues['base_url'] == undefined) {
54
+ nvalues['base_url'] = 'http://localhost';
74
55
  }
75
- if (values['smtp_settings'] == undefined) {
76
- values['smtp_settings'] = {};
56
+ if (nvalues['smtp_settings'] == undefined) {
57
+ nvalues['smtp_settings'] = {};
77
58
  }
78
- if (values['indexer_settings'] == undefined) {
79
- values['indexer_settings'] = {};
59
+ if (nvalues['otel'] == undefined) {
60
+ nvalues['otel'] = {};
80
61
  }
62
+ if (nvalues['indexer_settings'] == undefined) {
63
+ nvalues['indexer_settings'] = {};
64
+ }
65
+ $values = nvalues;
81
66
  loading = false;
82
- latestKeyRenewalAttempt = await SettingService.getLatestKeyRenewalAttempt();
83
67
  // populate snowflake account identifier from db
84
68
  const account_identifier = oauths?.snowflake_oauth?.connect_config?.extra_params?.account_identifier;
85
69
  if (account_identifier) {
@@ -93,14 +77,14 @@ export async function saveSettings() {
93
77
  setupSnowflakeUrls();
94
78
  }
95
79
  let shouldReloadPage = false;
96
- if (values) {
80
+ if ($values) {
97
81
  const allSettings = Object.values(settings).flatMap((x) => Object.entries(x));
98
82
  let licenseKeySet = false;
99
83
  await Promise.all(allSettings
100
84
  .filter((x) => {
101
85
  return (x[1].storage == 'setting' &&
102
- !deepEqual(initialValues?.[x[1].key], values?.[x[1].key]) &&
103
- (values?.[x[1].key] != '' ||
86
+ !deepEqual(initialValues?.[x[1].key], $values?.[x[1].key]) &&
87
+ ($values?.[x[1].key] != '' ||
104
88
  initialValues?.[x[1].key] != undefined ||
105
89
  initialValues?.[x[1].key] != null));
106
90
  })
@@ -113,10 +97,10 @@ export async function saveSettings() {
113
97
  }
114
98
  return await SettingService.setGlobal({
115
99
  key: x.key,
116
- requestBody: { value: values?.[x.key] }
100
+ requestBody: { value: $values?.[x.key] }
117
101
  });
118
102
  }));
119
- initialValues = JSON.parse(JSON.stringify(values));
103
+ initialValues = JSON.parse(JSON.stringify($values));
120
104
  if (!deepEqual(initialOauths, oauths)) {
121
105
  await SettingService.setGlobal({
122
106
  key: 'oauths',
@@ -149,95 +133,6 @@ export async function saveSettings() {
149
133
  dispatch('saved');
150
134
  }
151
135
  }
152
- let oauths = {};
153
- let resourceName = '';
154
- function parseLicenseKey(key) {
155
- let splitted = key.split('.');
156
- if (splitted.length >= 3) {
157
- try {
158
- let i = parseInt(splitted[1]);
159
- let date = new Date(i * 1000);
160
- const stringDate = date.toLocaleDateString();
161
- if (stringDate !== 'Invalid Date') {
162
- return {
163
- valid: date.getTime() > Date.now(),
164
- expiration: date.toLocaleDateString()
165
- };
166
- }
167
- }
168
- catch { }
169
- }
170
- return {
171
- valid: false
172
- };
173
- }
174
- let to = '';
175
- const windmillBuiltins = [
176
- 'github',
177
- 'gitlab',
178
- 'bitbucket',
179
- 'slack',
180
- 'gsheets',
181
- 'gdrive',
182
- 'gmail',
183
- 'gcal',
184
- 'gforms',
185
- 'gcloud',
186
- 'gworkspace',
187
- 'basecamp',
188
- 'linkedin',
189
- 'quickbooks',
190
- 'visma',
191
- 'spotify',
192
- 'snowflake_oauth'
193
- ];
194
- let oauth_name = undefined;
195
- async function sendStats() {
196
- await SettingService.sendStats();
197
- sendUserToast('Usage sent');
198
- }
199
- let clientName = '';
200
- let licenseKeyChanged = false;
201
- let renewing = false;
202
- export async function renewLicenseKey() {
203
- renewing = true;
204
- try {
205
- await SettingService.renewLicenseKey({
206
- licenseKey: values['license_key'] || undefined
207
- });
208
- sendUserToast('Key renewal successful');
209
- loadSettings();
210
- }
211
- catch (err) {
212
- latestKeyRenewalAttempt = await SettingService.getLatestKeyRenewalAttempt();
213
- throw err;
214
- }
215
- finally {
216
- renewing = false;
217
- }
218
- }
219
- let opening = false;
220
- export async function openCustomerPortal() {
221
- opening = true;
222
- try {
223
- const url = await SettingService.createCustomerPortalSession({
224
- licenseKey: values['license_key'] || undefined
225
- });
226
- window.open(url, '_blank');
227
- }
228
- finally {
229
- opening = false;
230
- }
231
- }
232
- function showSetting(setting, values) {
233
- if (setting == 'dev_instance') {
234
- if (values['license_key'] == undefined) {
235
- return false;
236
- }
237
- }
238
- return true;
239
- }
240
- let snowflakeAccountIdentifier = '';
241
136
  function setupSnowflakeUrls() {
242
137
  // strip all whitespaces from account identifier
243
138
  snowflakeAccountIdentifier = snowflakeAccountIdentifier.replace(/\s/g, '');
@@ -251,6 +146,11 @@ function setupSnowflakeUrls() {
251
146
  };
252
147
  oauths['snowflake_oauth'].connect_config = connect_config;
253
148
  }
149
+ let to = '';
150
+ async function sendStats() {
151
+ await SettingService.sendStats();
152
+ sendUserToast('Usage sent');
153
+ }
254
154
  </script>
255
155
 
256
156
  <div class="pb-8">
@@ -261,21 +161,23 @@ function setupSnowflakeUrls() {
261
161
  {/each}
262
162
 
263
163
  <svelte:fragment slot="content">
264
- <div class="pt-4" />
265
-
266
164
  {#each Object.keys(settings) as category}
267
165
  <TabContent value={category}>
268
166
  {#if category == 'SMTP'}
269
167
  <div class="text-secondary pb-4 text-xs"
270
168
  >Setting SMTP unlocks sending emails upon adding new users to the workspace or the
271
169
  instance or sending critical alerts.
272
- <a target="_blank" href="https://www.windmill.dev/docs/misc/setup_smtp">Learn more</a
170
+ <a
171
+ target="_blank"
172
+ href="https://www.windmill.dev/docs/advanced/instance_settings#smtp">Learn more</a
273
173
  ></div
274
174
  >
275
- {:else if category == "Indexer/Search"}
175
+ {:else if category == 'Indexer/Search'}
276
176
  <div class="text-secondary pb-4 text-xs"
277
- >The indexer service unlocks full text search across jobs and service logs. It requires spinning up its own separate container
278
- <a target="_blank" href="https://www.windmill.dev/docs/core_concepts/search_bar#setup">Learn how to</a
177
+ >The indexer service unlocks full text search across jobs and service logs. It
178
+ requires spinning up its own separate container
179
+ <a target="_blank" href="https://www.windmill.dev/docs/core_concepts/search_bar#setup"
180
+ >Learn how to</a
279
181
  ></div
280
182
  >
281
183
  {:else if category == 'Registries'}
@@ -335,877 +237,38 @@ function setupSnowflakeUrls() {
335
237
  size="xs">Send usage</Button
336
238
  >
337
239
  {/if}
338
- {:else if category == 'SSO/OAuth'}
339
- <div>
340
- <Tabs bind:selected={ssoOrOauth} class="mt-2 mb-4">
341
- <Tab value="sso">SSO</Tab>
342
- <Tab value="oauth">OAuth</Tab>
343
- </Tabs>
344
- </div>
345
-
346
- <div class="mb-6">
347
- {#if ssoOrOauth === 'sso'}
348
- {#if !$enterpriseLicense || $enterpriseLicense.endsWith('_pro')}
349
- <Alert type="warning" title="Limited to 10 SSO users">
350
- Without EE, the number of SSO users is limited to 10. SCIM/SAML is available on
351
- EE
352
- </Alert>
353
- {/if}
354
-
355
- <div class="py-1" />
356
- <div class="mb-2">
357
- <span class="text-primary text-sm"
358
- >When at least one of the below options is set, users will be able to login to
359
- Windmill via their third-party account.
360
- <br /> To test SSO, the recommended workflow is to to save the settings and try
361
- to login in an incognito window.
362
- <a target="_blank" href="https://www.windmill.dev/docs/misc/setup_oauth#sso"
363
- >Learn more</a
364
- ></span
365
- >
366
- </div>
367
- <div class="flex flex-col gap-2 py-4">
368
- <OAuthSetting name="google" bind:value={oauths['google']} />
369
- <OAuthSetting name="microsoft" bind:value={oauths['microsoft']} />
370
- <OktaSetting bind:value={oauths['okta']} />
371
- <OAuthSetting name="github" bind:value={oauths['github']} />
372
- <OAuthSetting name="gitlab" bind:value={oauths['gitlab']} />
373
- <OAuthSetting name="jumpcloud" bind:value={oauths['jumpcloud']} />
374
- <KeycloakSetting bind:value={oauths['keycloak']} />
375
- <AuthentikSetting bind:value={oauths['authentik']} />
376
- <AutheliaSetting bind:value={oauths['authelia']} />
377
- <KanidmSetting bind:value={oauths['kanidm']} />
378
- <ZitadelSetting bind:value={oauths['zitadel']} />
379
- {#each Object.keys(oauths) as k}
380
- {#if !['authelia', 'authentik', 'google', 'microsoft', 'github', 'gitlab', 'jumpcloud', 'okta', 'keycloak', 'slack', 'kanidm', 'zitadel'].includes(k) && 'login_config' in oauths[k]}
381
- {#if oauths[k]}
382
- <div class="flex flex-col gap-2 pb-4">
383
- <div class="flex flex-row items-center gap-2">
384
- <label class="text-md font-medium text-primary">{k}</label>
385
- <CloseButton
386
- on:close={() => {
387
- delete oauths[k]
388
- oauths = { ...oauths }
389
- }}
390
- />
391
- </div>
392
- <div class="p-2 border rounded">
393
- <label class="block pb-2">
394
- <span class="text-primary font-semibold text-sm">Custom Name</span>
395
- <input
396
- type="text"
397
- placeholder="Custom Name"
398
- bind:value={oauths[k]['display_name']}
399
- />
400
- </label>
401
- <label class="block pb-2">
402
- <span class="text-primary font-semibold text-sm">Client Id</span>
403
- <input
404
- type="text"
405
- placeholder="Client Id"
406
- bind:value={oauths[k]['id']}
407
- />
408
- </label>
409
- <label class="block pb-2">
410
- <span class="text-primary font-semibold text-sm">Client Secret</span>
411
- <input
412
- type="text"
413
- placeholder="Client Secret"
414
- bind:value={oauths[k]['secret']}
415
- />
416
- </label>
417
- {#if !windmillBuiltins.includes(k) && k != 'slack'}
418
- <CustomSso bind:login_config={oauths[k]['login_config']} />
419
- {/if}
420
- </div>
421
- </div>
422
- {/if}
423
- {/if}
240
+ {:else if category == 'Auth/OAuth'}
241
+ <AuthSettings bind:oauths bind:snowflakeAccountIdentifier>
242
+ <svelte:fragment slot="scim">
243
+ <div class="flex-col flex gap-2 pb-4">
244
+ {#each scimSamlSetting as setting}
245
+ <InstanceSetting
246
+ on:closeDrawer={() => closeDrawer?.()}
247
+ {loading}
248
+ {setting}
249
+ {values}
250
+ {version}
251
+ />
424
252
  {/each}
425
253
  </div>
426
- <div class="flex gap-2 py-4">
427
- <input type="text" placeholder="client_id" bind:value={clientName} />
428
- <Button
429
- variant="border"
430
- color="blue"
431
- hover="yo"
432
- size="sm"
433
- endIcon={{ icon: Plus }}
434
- disabled={clientName == ''}
435
- on:click={() => {
436
- oauths[clientName] = { id: '', secret: '', login_config: {} }
437
- clientName = ''
438
- }}
439
- >
440
- Add custom SSO client {!$enterpriseLicense ? '(requires ee)' : ''}
441
- </Button>
442
- </div>
443
- <div class="flex gap-2 py-4">
444
- <Toggle
445
- options={{
446
- right:
447
- 'Require users to have been added manually to Windmill to sign in through OAuth'
448
- }}
449
- bind:checked={requirePreexistingUserForOauth}
450
- />
451
- </div>
452
- {:else if ssoOrOauth === 'oauth'}
453
- <div class="mb-2">
454
- <span class="text-primary text-sm"
455
- >When one of the below options is set, you will be able to create a specific
456
- resource containing a token automatically generated by the third-party provider.
457
- <br />
458
- To test it after setting an oauth client, go to the Resources menu and create a new
459
- one of the type of your oauth client (i.e. a 'github' resource if you set Github
460
- OAuth).
461
- <br /><a
462
- target="_blank"
463
- href="https://www.windmill.dev/docs/misc/setup_oauth#oauth">Learn more</a
464
- ></span
465
- >
466
- </div>
467
- <div class="py-1" />
468
- <OAuthSetting login={false} name="slack" bind:value={oauths['slack']} />
469
- <div class="py-1" />
470
-
471
- {#each Object.keys(oauths) as k}
472
- {#if oauths[k] && !('login_config' in oauths[k])}
473
- {#if !['slack'].includes(k) && oauths[k]}
474
- <div class="flex flex-col gap-2 pb-4">
475
- <div class="flex flex-row items-center gap-2">
476
- <label class="text-md font-medium text-primary">{k}</label>
477
- <CloseButton
478
- on:close={() => {
479
- delete oauths[k]
480
- oauths = { ...oauths }
481
- }}
482
- />
483
- </div>
484
- <div class="p-2 border rounded">
485
- <label class="block pb-2">
486
- <span class="text-primary font-semibold text-sm">Client Id</span>
487
- <input
488
- type="text"
489
- placeholder="Client Id"
490
- bind:value={oauths[k]['id']}
491
- />
492
- </label>
493
- <label class="block pb-2">
494
- <span class="text-primary font-semibold text-sm">Client Secret</span>
495
- <input
496
- type="text"
497
- placeholder="Client Secret"
498
- bind:value={oauths[k]['secret']}
499
- />
500
- </label>
501
- {#if !windmillBuiltins.includes(k) && k != 'slack'}
502
- <CustomOauth bind:connect_config={oauths[k]['connect_config']} />
503
- {/if}
504
- {#if k == 'snowflake_oauth'}
505
- <label class="block pb-2">
506
- <span class="text-primary font-semibold text-sm"
507
- ><a
508
- href="https://docs.snowflake.com/en/user-guide/admin-account-identifier#using-an-account-name-as-an-identifier"
509
- target="_blank">Snowflake Account Identifier</a
510
- ></span
511
- >
512
- <input
513
- type="text"
514
- placeholder="<orgname>-<account_name>"
515
- required={true}
516
- bind:value={snowflakeAccountIdentifier}
517
- />
518
- </label>
519
- {/if}
520
- </div>
521
- </div>
522
- {/if}
523
- {/if}
524
- {/each}
525
-
526
- <div class="flex gap-2">
527
- <select name="oauth_name" id="oauth_name" bind:value={oauth_name}>
528
- <option value={undefined}>Select an OAuth client</option>
529
- <option value="custom">Fully Custom (requires ee)</option>
530
- {#each windmillBuiltins as name}
531
- <option value={name}>{capitalize(name)}</option>
532
- {/each}
533
- </select>
534
- {#if oauth_name == 'custom'}
535
- <input type="text" placeholder="client_id" bind:value={resourceName} />
536
- {:else}
537
- <input type="text" value={oauth_name ?? ''} disabled />
538
- {/if}
539
- <Button
540
- variant="border"
541
- color="blue"
542
- hover="yo"
543
- size="sm"
544
- endIcon={{ icon: Plus }}
545
- disabled={!oauth_name ||
546
- (oauth_name == 'custom' && resourceName == '') ||
547
- (oauth_name == 'custom' && !$enterpriseLicense)}
548
- on:click={() => {
549
- let name = oauth_name == 'custom' ? resourceName : oauth_name
550
- oauths[name ?? ''] = { id: '', secret: '' }
551
- resourceName = ''
552
- }}
553
- >
554
- Add OAuth client {oauth_name == 'custom' && !$enterpriseLicense
555
- ? '(requires ee)'
556
- : ''}
557
- </Button>
558
- </div>
559
- {/if}
560
- </div>
254
+ </svelte:fragment>
255
+ </AuthSettings>
561
256
  {/if}
562
257
  <div>
563
- <div class="flex-col flex gap-2 pb-4">
258
+ <div class="flex-col flex gap-4 pb-4">
564
259
  {#each settings[category] as setting}
565
- {#if (!setting.cloudonly || isCloudHosted()) && showSetting(setting.key, values) && !(setting.hiddenIfNull && values[setting.key] == null)}
566
- {#if setting.ee_only != undefined && !$enterpriseLicense}
567
- <div class="flex text-xs items-center gap-1 text-yellow-500 whitespace-nowrap">
568
- <AlertTriangle size={16} />
569
- EE only {#if setting.ee_only != ''}<Tooltip>{setting.ee_only}</Tooltip>{/if}
570
- </div>
571
- {/if}
572
- <label class="block pb-2">
573
- <span class="text-primary font-semibold text-sm">{setting.label}</span>
574
- {#if setting.description}
575
- <span class="text-secondary text-xs">
576
- {@html setting.description}
577
- </span>
578
- {/if}
579
- {#if setting.tooltip}
580
- <Tooltip>{setting.tooltip}</Tooltip>
581
- {/if}
582
- {#if values}
583
- {@const hasError = setting.isValid && !setting.isValid(values[setting.key])}
584
- {#if loading}
585
- <Skeleton layout={[[2.5]]} />
586
- {:else if setting.fieldType == 'text'}
587
- <input
588
- disabled={setting.ee_only != undefined && !$enterpriseLicense}
589
- type="text"
590
- placeholder={setting.placeholder}
591
- class={hasError
592
- ? 'border !border-red-700 !border-opacity-30 !focus:border-red-700 !focus:border-opacity-30'
593
- : ''}
594
- bind:value={values[setting.key]}
595
- />
596
- {#if setting.advancedToggle}
597
- <div class="mt-1">
598
- <Toggle
599
- size="xs"
600
- options={{ right: setting.advancedToggle.label }}
601
- checked={setting.advancedToggle.checked(values)}
602
- on:change={() => {
603
- if (setting.advancedToggle) {
604
- values = setting.advancedToggle.onChange(values)
605
- }
606
- }}
607
- />
608
- </div>
609
- {/if}
610
- {:else if setting.fieldType == 'textarea'}
611
- <textarea
612
- rows="2"
613
- placeholder={setting.placeholder}
614
- bind:value={values[setting.key]}
615
- />
616
- {#if setting.key == 'saml_metadata'}
617
- <div class="flex mt-2">
618
- <Button
619
- on:click={async (e) => {
620
- const res = await SettingService.testMetadata({
621
- requestBody: values[setting.key]
622
- })
623
- sendUserToast(`Metadata valid, see console for full content`)
624
- console.log(`Metadata content:`, res)
625
- }}>Test content/url</Button
626
- >
627
- </div>
628
- {/if}
629
- {:else if setting.fieldType == 'license_key'}
630
- {@const { valid, expiration } = parseLicenseKey(values[setting.key] ?? '')}
631
- <div class="flex gap-2">
632
- <Password
633
- small
634
- placeholder={setting.placeholder}
635
- on:keydown={() => {
636
- licenseKeyChanged = true
637
- }}
638
- bind:password={values[setting.key]}
639
- />
640
- <Button
641
- variant={values[setting.key] ? 'contained' : 'border'}
642
- size="xs"
643
- on:click={async () => {
644
- await SettingService.testLicenseKey({
645
- requestBody: { license_key: values[setting.key] }
646
- })
647
- sendUserToast('Valid key')
648
- }}
649
- >
650
- Test Key
651
- </Button>
652
- </div>
653
- <div class="mt-1 flex flex-col gap-1 items-start">
654
- {#if values[setting.key]?.length > 0}
655
- {#if valid}
656
- <div class="flex flex-row gap-1 items-center">
657
- <Info size={12} class="text-tertiary" />
658
- <span class="text-tertiary text-xs"
659
- >License key expires on {expiration ?? ''}</span
660
- >
661
- </div>
662
- {:else if expiration}
663
- <div class="flex flex-row gap-1 items-center">
664
- <AlertCircle size={12} class="text-red-600" />
665
- <span class="text-red-600 dark:text-red-400 text-xs"
666
- >License key expired on {expiration}</span
667
- >
668
- </div>
669
- {:else}
670
- <div class="flex flex-row gap-1 items-center">
671
- <AlertCircle size={12} class="text-red-600" />
672
- <span class="text-red-600 dark:text-red-400 text-xs"
673
- >Invalid license key format</span
674
- >
675
- </div>
676
- {/if}
677
- {/if}
678
- {#if latestKeyRenewalAttempt}
679
- {@const attemptedAt = new Date(
680
- latestKeyRenewalAttempt.attempted_at
681
- ).toLocaleString()}
682
- {@const isTrial =
683
- latestKeyRenewalAttempt.result.startsWith('error: trial:')}
684
- <div class="relative">
685
- <Popover notClickable>
686
- <div class="flex flex-row items-center gap-1">
687
- {#if latestKeyRenewalAttempt.result === 'success'}
688
- <BadgeCheck class="text-green-600" size={12} />
689
- {:else}
690
- <BadgeX
691
- class={isTrial ? 'text-yellow-600' : 'text-red-600'}
692
- size={12}
693
- />
694
- {/if}
695
- <span
696
- class={classNames(
697
- 'text-xs',
698
- latestKeyRenewalAttempt.result === 'success'
699
- ? 'text-green-600'
700
- : isTrial
701
- ? 'text-yellow-600'
702
- : 'text-red-600'
703
- )}
704
- >
705
- {latestKeyRenewalAttempt.result === 'success'
706
- ? 'Latest key renewal succeeded'
707
- : isTrial
708
- ? 'Latest key renewal ignored because in trial'
709
- : 'Latest key renewal failed'}
710
- on {attemptedAt}
711
- </span>
712
- </div>
713
- <div slot="text">
714
- {#if latestKeyRenewalAttempt.result === 'success'}
715
- <span class="text-green-300">
716
- Latest key renewal succeeded on {attemptedAt}
717
- </span>
718
- {:else if isTrial}
719
- <span class="text-yellow-300">
720
- License key cannot be renewed during trial ({attemptedAt})
721
- </span>
722
- {:else}
723
- <span class="text-red-300">
724
- Latest key renewal failed on {attemptedAt}: {latestKeyRenewalAttempt.result.replace(
725
- 'error: ',
726
- ''
727
- )}
728
- </span>
729
- {/if}
730
- <br />
731
- As long as invoices are paid and usage corresponds to the subscription,
732
- the key is renewed daily with a validity of 35 days (grace period).
733
- </div>
734
- </Popover>
735
- </div>
736
- {/if}
737
- {#if licenseKeyChanged && !$enterpriseLicense}
738
- {#if version.startsWith('CE')}
739
- <div class="text-red-400"
740
- >License key is set but image used is the Community Edition {version}.
741
- Switch image to EE.</div
742
- >
743
- {/if}
744
- {/if}
745
-
746
- {#if valid || expiration}
747
- <div class="flex flex-row gap-2 mt-1">
748
- <Button
749
- on:click={renewLicenseKey}
750
- loading={renewing}
751
- size="xs"
752
- color="dark"
753
- >Renew key
754
- </Button>
755
- <Button
756
- color="dark"
757
- size="xs"
758
- loading={opening}
759
- on:click={openCustomerPortal}
760
- >
761
- Open customer portal
762
- </Button>
763
- </div>
764
- {/if}
765
- </div>
766
- {:else if setting.fieldType == 'email'}
767
- <input
768
- type="email"
769
- placeholder={setting.placeholder}
770
- bind:value={values[setting.key]}
771
- />
772
- {:else if setting.key == 'critical_alert_mute_ui'}
773
- <div class="flex flex-col gap-y-2 my-2 py-2">
774
- <Toggle
775
- disabled={!$enterpriseLicense}
776
- bind:checked={values[setting.key]}
777
- options={{ right: setting.description }}
778
- />
779
- <div class="flex flex-row">
780
- <Button
781
- disabled={!$enterpriseLicense}
782
- size="sm"
783
- on:click={() => {
784
- isCriticalAlertsUIOpen.set(true)
785
- closeDrawer?.()
786
- }}
787
- >
788
- Show Critical Alerts
789
- </Button>
790
- </div>
791
- </div>
792
- {:else if setting.fieldType == 'critical_error_channels'}
793
- <div class="w-full flex gap-x-16 flex-wrap">
794
- <div class="w-full max-w-lg">
795
- <div class="flex w-full max-w-lg mt-1 gap-2 w-full items-center">
796
- <input
797
- type="text"
798
- placeholder="Logs (critical errors are always logged)"
799
- disabled
800
- />
801
- </div>
802
-
803
- {#if $enterpriseLicense && Array.isArray(values[setting.key])}
804
- {#each values[setting.key] ?? [] as v, i}
805
- <div class="flex w-full max-w-lg mt-1 gap-2 w-full items-center">
806
- <select
807
- class="w-20"
808
- on:change={(e) => {
809
- if (e.target?.['value']) {
810
- values[setting.key][i] = {
811
- [e.target['value']]: ''
812
- }
813
- }
814
- }}
815
- value={v && 'slack_channel' in v ? 'slack_channel' : 'email'}
816
- >
817
- <option value="email">Email</option>
818
- <option value="slack_channel">Slack</option>
819
- </select>
820
- {#if v && 'slack_channel' in v}
821
- <input
822
- type="text"
823
- placeholder="Slack channel"
824
- on:input={(e) => {
825
- if (e.target?.['value']) {
826
- values[setting.key][i] = {
827
- slack_channel: e.target['value']
828
- }
829
- }
830
- }}
831
- value={v?.slack_channel ?? ''}
832
- />
833
- {:else}
834
- <input
835
- type="email"
836
- placeholder="Email address"
837
- on:input={(e) => {
838
- if (e.target?.['value']) {
839
- values[setting.key][i] = {
840
- email: e.target['value']
841
- }
842
- }
843
- }}
844
- value={v?.email ?? ''}
845
- />
846
- {/if}
847
- <button
848
- transition:fade|local={{ duration: 100 }}
849
- class="rounded-full p-1 bg-surface-secondary duration-200 hover:bg-surface-hover"
850
- aria-label="Clear"
851
- on:click={() => {
852
- values[setting.key] = values[setting.key].filter(
853
- (_, index) => index !== i
854
- )
855
- }}
856
- >
857
- <X size={14} />
858
- </button>
859
- </div>
860
- {/each}
861
- {/if}
862
- </div>
863
- <div
864
- ><div class="flex mt-1">
865
- <Button
866
- size="xs"
867
- variant="contained"
868
- on:click={async () => {
869
- try {
870
- await SettingService.testCriticalChannels({
871
- requestBody: values[setting.key]
872
- })
873
- sendUserToast(
874
- 'Test message sent successfully to critical channels',
875
- false
876
- )
877
- } catch (error) {
878
- sendUserToast(
879
- 'Failed to send test message: ' + error.message,
880
- true
881
- )
882
- }
883
- }}
884
- >
885
- Test Critical Channels
886
- </Button>
887
- </div>
888
- </div>
889
- </div>
890
- <div class="flex mt-2 gap-20 items-baseline">
891
- <Button
892
- variant="border"
893
- color="light"
894
- size="xs"
895
- btnClasses="mt-1"
896
- on:click={() => {
897
- if (
898
- values[setting.key] == undefined ||
899
- !Array.isArray(values[setting.key])
900
- ) {
901
- values[setting.key] = []
902
- }
903
- values[setting.key] = values[setting.key].concat('')
904
- }}
905
- id="arg-input-add-item"
906
- startIcon={{ icon: Plus }}
907
- disabled={!$enterpriseLicense}
908
- >
909
- Add item
910
- </Button>
911
- </div>
912
- {:else if setting.fieldType == 'slack_connect'}
913
- <div class="flex flex-col items-start self-start">
914
- {#if values[setting.key] && 'team_name' in values[setting.key]}
915
- <div class="text-sm">
916
- Connected to <code>{values[setting.key]['team_name']}</code>
917
- </div>
918
- <Button
919
- size="sm"
920
- endIcon={{ icon: Slack }}
921
- btnClasses="mt-2"
922
- variant="border"
923
- on:click={async () => {
924
- values[setting.key] = undefined
925
- }}
926
- >
927
- Disconnect Slack
928
- </Button>
929
- {:else}
930
- <Button
931
- size="xs"
932
- color="dark"
933
- href="{base}/api/oauth/connect_slack?instance=true"
934
- startIcon={{ icon: Slack }}
935
- disabled={!$enterpriseLicense}
936
- >
937
- Connect to Slack
938
- </Button>
939
- {/if}
940
- </div>
941
- {:else if setting.fieldType == 'indexer_rates'}
942
- <div class="flex flex-col gap-4 mt-4">
943
- {#if values[setting.key]}
944
- <div>
945
- <label for="writer_memory_budget" class="block text-sm font-medium">
946
- Index writer memory budget (MB)
947
- <Tooltip>
948
- The allocated memory arena for the indexer. A bigger value means
949
- less writing to disk and potentially higher indexing throughput
950
- </Tooltip>
951
- </label>
952
- <input
953
- type="number"
954
- id="writer_memory_budget"
955
- placeholder="300"
956
- on:input={(e) => {
957
- if (e.target instanceof HTMLInputElement) {
958
- if (e.target.valueAsNumber) {
959
- values[setting.key].writer_memory_budget =
960
- e.target.valueAsNumber * (1024 * 1024)
961
- }
962
- }
963
- }}
964
- value={values[setting.key].writer_memory_budget / (1024 * 1024)}
965
- />
966
- </div>
967
- <h3>Completed Job Index</h3>
968
- <div>
969
- <label
970
- for="commit_job_max_batch_size"
971
- class="block text-sm font-medium"
972
- >
973
- Commit max batch size <Tooltip>
974
- The max amount of documents (here jobs) per commit. To optimize
975
- indexing throughput, it is best to keep this as high as possible.
976
- However, especially when reindexing the whole instance, it can be
977
- useful to have a limit on how many jobs can be written without
978
- being commited. A commit will make the jobs available for search,
979
- constitute a "checkpoint" state in the indexing and will be
980
- logged.
981
- </Tooltip>
982
- </label>
983
- <input
984
- type="number"
985
- id="commit_job_max_batch_size"
986
- placeholder="100000"
987
- bind:value={values[setting.key].commit_job_max_batch_size}
988
- />
989
- </div>
990
- <div>
991
- <label for="refresh_index_period" class="block text-sm font-medium">
992
- Refresh index period (s) <Tooltip>
993
- The index will query new jobs peridically and write them on the
994
- index. This setting sets that period.
995
- </Tooltip></label
996
- >
997
- <input
998
- type="number"
999
- id="refresh_index_period"
1000
- placeholder="300"
1001
- bind:value={values[setting.key].refresh_index_period}
1002
- />
1003
- </div>
1004
- <div>
1005
- <label
1006
- for="max_indexed_job_log_size"
1007
- class="block text-sm font-medium"
1008
- >
1009
- Max indexed job log size (KB) <Tooltip>
1010
- Job logs are included when indexing, but to avoid the index size
1011
- growing artificially, the logs will be truncated after a size has
1012
- been reached.
1013
- </Tooltip>
1014
- </label>
1015
- <input
1016
- type="number"
1017
- id="max_indexed_job_log_size"
1018
- placeholder="1024"
1019
- on:input={(e) => {
1020
- if (e.target instanceof HTMLInputElement) {
1021
- if (e.target.valueAsNumber) {
1022
- values[setting.key].max_indexed_job_log_size =
1023
- e.target.valueAsNumber * 1024
1024
- }
1025
- }
1026
- }}
1027
- value={values[setting.key].max_indexed_job_log_size / 1024}
1028
- />
1029
- </div>
1030
- <h3>Service Logs Index</h3>
1031
- <div>
1032
- <label
1033
- for="commit_log_max_batch_size"
1034
- class="block text-sm font-medium"
1035
- >Commit max batch size Commit max batch size <Tooltip>
1036
- The max amount of documents per commit. In this case 1 document is
1037
- one log file representing all logs during 1 minute for a specific
1038
- host. To optimize indexing throughput, it is best to keep this as
1039
- high as possible. However, especially when reindexing the whole
1040
- instance, it can be useful to have a limit on how many logs can be
1041
- written without being commited. A commit will make the logs
1042
- available for search, appear as a log line, and be a "checkpoint"
1043
- of the indexing progress.
1044
- </Tooltip>
1045
- </label>
1046
- <input
1047
- type="number"
1048
- id="commit_log_max_batch_size"
1049
- placeholder="10000"
1050
- bind:value={values[setting.key].commit_log_max_batch_size}
1051
- />
1052
- </div>
1053
- <div>
1054
- <label
1055
- for="refresh_log_index_period"
1056
- class="block text-sm font-medium"
1057
- >
1058
- Refresh index period (s) <Tooltip>
1059
- The index will query new service logs peridically and write them
1060
- on the index. This setting sets that period.
1061
- </Tooltip></label
1062
- >
1063
- <input
1064
- type="number"
1065
- id="refresh_log_index_period"
1066
- placeholder="300"
1067
- bind:value={values[setting.key].refresh_log_index_period}
1068
- />
1069
- </div>
1070
- <h3>Reset Index</h3>
1071
- This buttons will clear the whole index, and the service will start reindexing from scratch. Full text search might be down during this time.
1072
- <div>
1073
- <ConfirmButton
1074
- on:click={async () => {
1075
- let r = await IndexSearchService.clearIndex({idxName: "JobIndex"})
1076
- console.log("asasd")
1077
- sendUserToast(r)
1078
- }}>Clear <b>Jobs</b> Index</ConfirmButton
1079
- >
1080
- <ConfirmButton
1081
- on:click={async () => {
1082
- let r = await IndexSearchService.clearIndex({idxName: "ServiceLogIndex"})
1083
- console.log("asasd")
1084
- sendUserToast(r)
1085
- }}>Clear <b>Service Logs</b> Index</ConfirmButton
1086
- >
1087
- </div>
1088
- {/if}
1089
- </div>
1090
- {:else if setting.fieldType == 'smtp_connect'}
1091
- <div class="flex flex-col gap-4 mt-4">
1092
- {#if values[setting.key]}
1093
- <div>
1094
- <label for="smtp_host" class="block text-sm font-medium">Host</label>
1095
- <input
1096
- type="text"
1097
- id="smtp_host"
1098
- placeholder="smtp.gmail.com"
1099
- bind:value={values[setting.key].smtp_host}
1100
- />
1101
- </div>
1102
- <div>
1103
- <label for="smtp_port" class="block text-sm font-medium">Port</label>
1104
- <input
1105
- type="number"
1106
- id="smtp_port"
1107
- placeholder="587"
1108
- bind:value={values[setting.key].smtp_port}
1109
- />
1110
- </div>
1111
- <div>
1112
- <label for="smtp_username" class="block text-sm font-medium"
1113
- >Username</label
1114
- >
1115
- <input
1116
- type="text"
1117
- id="smtp_username"
1118
- placeholder="ruben@windmill.dev"
1119
- bind:value={values[setting.key].smtp_username}
1120
- />
1121
- </div>
1122
- <div>
1123
- <label for="smtp_password" class="block text-sm font-medium"
1124
- >Password</label
1125
- >
1126
- <Password bind:password={values[setting.key].smtp_password} />
1127
- </div>
1128
- <div>
1129
- <label for="smtp_from" class="block text-sm font-medium"
1130
- >From Address</label
1131
- >
1132
- <input
1133
- type="email"
1134
- id="smtp_from"
1135
- placeholder="noreply@windmill.dev"
1136
- bind:value={values[setting.key].smtp_from}
1137
- />
1138
- </div>
1139
- <div>
1140
- <Toggle
1141
- disabled={values[setting.key].smtp_disable_tls}
1142
- id="smtp_tls_implicit"
1143
- bind:checked={values[setting.key].smtp_tls_implicit}
1144
- options={{ right: 'Implicit TLS' }}
1145
- label="Implicit TLS"
1146
- />
1147
- </div>
1148
- <div>
1149
- <Toggle
1150
- id="smtp_disable_tls"
1151
- bind:checked={values[setting.key].smtp_disable_tls}
1152
- on:change={() => {
1153
- if (values[setting.key].smtp_disable_tls) {
1154
- values[setting.key].smtp_tls_implicit = false
1155
- }
1156
- }}
1157
- options={{ right: 'Disable TLS' }}
1158
- label="Disable TLS"
1159
- />
1160
- </div>
1161
- {/if}
1162
- </div>
1163
- {:else if setting.fieldType == 'object_store_config'}
1164
- <ObjectStoreConfigSettings bind:bucket_config={values[setting.key]} />
1165
- <div class="mb-6" />
1166
- {:else if setting.fieldType == 'number'}
1167
- <input
1168
- type="number"
1169
- placeholder={setting.placeholder}
1170
- bind:value={values[setting.key]}
1171
- />
1172
- {:else if setting.fieldType == 'password'}
1173
- <input
1174
- autocomplete="new-password"
1175
- type="password"
1176
- placeholder={setting.placeholder}
1177
- bind:value={values[setting.key]}
1178
- />
1179
- {:else if setting.fieldType == 'boolean'}
1180
- <div>
1181
- <Toggle bind:checked={values[setting.key]} />
1182
- </div>
1183
- {:else if setting.fieldType == 'seconds'}
1184
- <div>
1185
- <SecondsInput
1186
- max={setting.ee_only != undefined && !$enterpriseLicense
1187
- ? 60 * 60 * 24 * 30
1188
- : undefined}
1189
- bind:seconds={values[setting.key]}
1190
- />
1191
- </div>
1192
- {/if}
1193
-
1194
- {#if hasError}
1195
- <span class="text-red-500 dark:text-red-400 text-sm">
1196
- {setting.error ?? ''}
1197
- </span>
1198
- {/if}
1199
- {:else}
1200
- <input disabled placeholder="Loading..." />
1201
- {/if}
1202
- </label>
1203
- {/if}
260
+ <InstanceSetting
261
+ on:closeDrawer={() => closeDrawer?.()}
262
+ {loading}
263
+ {setting}
264
+ {values}
265
+ {version}
266
+ />
1204
267
  {/each}
1205
268
  </div>
1206
269
  </div>
1207
270
  {#if category == 'SMTP'}
1208
- {@const smtp = values['smtp_settings']}
271
+ {@const smtp = $values['smtp_settings']}
1209
272
  <div class="flex gap-4"
1210
273
  ><input type="email" bind:value={to} placeholder="contact@windmill.dev" />
1211
274
  <Button