windmill-components 1.511.1 → 1.522.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 (232) hide show
  1. package/package/components/AppConnectInner.svelte.d.ts +1 -1
  2. package/package/components/ArgInput.svelte +42 -14
  3. package/package/components/ArgInput.svelte.d.ts +2 -10
  4. package/package/components/AssignableTagsInner.svelte +5 -0
  5. package/package/components/AuthSettings.svelte +4 -2
  6. package/package/components/AuthSettings.svelte.d.ts +1 -0
  7. package/package/components/DBManagerDrawer.svelte +154 -151
  8. package/package/components/DBManagerDrawer.svelte.d.ts +2 -2
  9. package/package/components/DBTable.svelte +3 -3
  10. package/package/components/DBTable.svelte.d.ts +1 -0
  11. package/package/components/DBTableEditor.svelte +7 -7
  12. package/package/components/DBTableEditor.svelte.d.ts +1 -1
  13. package/package/components/DeployWorkspace.svelte +1 -1
  14. package/package/components/DisplayResult.svelte +34 -8
  15. package/package/components/DisplayResult.svelte.d.ts +4 -1
  16. package/package/components/DynSelect.svelte +58 -34
  17. package/package/components/DynSelect.svelte.d.ts +3 -11
  18. package/package/components/EditableSchemaForm.svelte +126 -6
  19. package/package/components/EditableSchemaForm.svelte.d.ts +5 -1
  20. package/package/components/Editor.svelte +1 -1
  21. package/package/components/EditorBar.svelte +82 -4
  22. package/package/components/ErrorOrRecoveryHandler.svelte +76 -8
  23. package/package/components/ErrorOrRecoveryHandler.svelte.d.ts +2 -1
  24. package/package/components/ExploreAssetButton.svelte +14 -4
  25. package/package/components/ExploreAssetButton.svelte.d.ts +1 -0
  26. package/package/components/FlowJobResult.svelte +3 -3
  27. package/package/components/FlowJobResult.svelte.d.ts +1 -0
  28. package/package/components/FlowPreviewContent.svelte +9 -1
  29. package/package/components/FlowPreviewResult.svelte +4 -1
  30. package/package/components/FlowPreviewResult.svelte.d.ts +1 -0
  31. package/package/components/FlowStatusViewerInner.svelte +21 -3
  32. package/package/components/FlowStatusViewerInner.svelte.d.ts +7 -1
  33. package/package/components/FolderEditor.svelte +1 -1
  34. package/package/components/GitDiffPreview.svelte +14 -18
  35. package/package/components/GitDiffPreview.svelte.d.ts +2 -8
  36. package/package/components/GitHubAppIntegration.svelte +3 -1
  37. package/package/components/IdEditorInput.svelte +25 -22
  38. package/package/components/IdEditorInput.svelte.d.ts +11 -23
  39. package/package/components/InstanceSetting.svelte +7 -2
  40. package/package/components/InstanceSettings.svelte +1 -0
  41. package/package/components/JobLoader.svelte +48 -5
  42. package/package/components/JobLoader.svelte.d.ts +7 -2
  43. package/package/components/Login.svelte +8 -2
  44. package/package/components/MemoryFootprintViewer.svelte +1 -1
  45. package/package/components/ModulePreviewResultViewer.svelte +2 -2
  46. package/package/components/MoveDrawer.svelte.d.ts +2 -2
  47. package/package/components/NextcloudSetting.svelte +84 -0
  48. package/package/components/NextcloudSetting.svelte.d.ts +7 -0
  49. package/package/components/ObjectResourceInput.svelte +3 -2
  50. package/package/components/ObjectResourceInput.svelte.d.ts +1 -0
  51. package/package/components/ParqetCsvTableRenderer.svelte +1 -1
  52. package/package/components/ResourceEditor.svelte +1 -1
  53. package/package/components/ResourcePicker.svelte +8 -1
  54. package/package/components/ResourcePicker.svelte.d.ts +1 -0
  55. package/package/components/ResultStreamDisplay.svelte +5 -0
  56. package/package/components/ResultStreamDisplay.svelte.d.ts +5 -0
  57. package/package/components/RunForm.svelte +9 -1
  58. package/package/components/SchemaForm.svelte +2 -2
  59. package/package/components/SchemaForm.svelte.d.ts +2 -10
  60. package/package/components/ScriptBuilder.svelte +13 -8
  61. package/package/components/ScriptBuilder.svelte.d.ts +1 -1
  62. package/package/components/ScriptEditor.svelte.d.ts +1 -1
  63. package/package/components/ScriptWrapper.svelte +1 -1
  64. package/package/components/ShareModal.svelte.d.ts +1 -1
  65. package/package/components/SimpleAgTable.svelte +2 -0
  66. package/package/components/SimpleAgTable.svelte.d.ts +2 -0
  67. package/package/components/SqlRepl.svelte +21 -7
  68. package/package/components/SqlRepl.svelte.d.ts +2 -2
  69. package/package/components/StringTypeNarrowing.svelte.d.ts +1 -1
  70. package/package/components/WorkerTagSelect.svelte +70 -1
  71. package/package/components/apps/components/display/AppDisplayComponent.svelte +13 -1
  72. package/package/components/apps/components/display/AppText.svelte +2 -2
  73. package/package/components/apps/components/display/dbtable/AppDbExplorer.svelte +8 -1
  74. package/package/components/apps/components/display/dbtable/InsertRow.svelte +5 -4
  75. package/package/components/apps/components/display/dbtable/queries/count.js +11 -1
  76. package/package/components/apps/components/display/dbtable/queries/createTable.d.ts +1 -1
  77. package/package/components/apps/components/display/dbtable/queries/createTable.js +3 -3
  78. package/package/components/apps/components/display/dbtable/queries/delete.js +7 -0
  79. package/package/components/apps/components/display/dbtable/queries/insert.js +2 -0
  80. package/package/components/apps/components/display/dbtable/queries/select.js +14 -0
  81. package/package/components/apps/components/display/dbtable/queries/update.js +7 -0
  82. package/package/components/apps/components/display/dbtable/utils.d.ts +6 -5
  83. package/package/components/apps/components/display/dbtable/utils.js +52 -28
  84. package/package/components/apps/components/display/table/AppAggridExplorerTable.svelte +1 -1
  85. package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte +1 -0
  86. package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte.d.ts +1 -0
  87. package/package/components/apps/components/display/table/AppAggridTable.svelte +5 -4
  88. package/package/components/apps/components/display/table/AppAggridTable.svelte.d.ts +1 -0
  89. package/package/components/apps/components/display/table/utils.js +7 -4
  90. package/package/components/apps/components/helpers/HiddenComponent.svelte +2 -2
  91. package/package/components/apps/components/helpers/RunnableComponent.svelte +4 -1
  92. package/package/components/apps/components/helpers/RunnableComponent.svelte.d.ts +2 -1
  93. package/package/components/apps/components/inputs/AppS3FileInput.svelte +2 -2
  94. package/package/components/apps/components/layout/AppDecisionTree.svelte +1 -1
  95. package/package/components/apps/components/layout/AppStepper.svelte +1 -1
  96. package/package/components/apps/components/layout/AppTabs.svelte +1 -1
  97. package/package/components/apps/editor/AppEditorHeader.svelte +13 -2
  98. package/package/components/apps/editor/GridViewer.svelte +1 -0
  99. package/package/components/apps/editor/RunnableJobPanelInner.svelte +2 -1
  100. package/package/components/apps/editor/contextPanel/components/IdEditor.svelte +7 -7
  101. package/package/components/apps/editor/contextPanel/components/IdEditor.svelte.d.ts +7 -19
  102. package/package/components/apps/editor/contextPanel/components/OutputHeader.svelte +8 -12
  103. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte.d.ts +1 -1
  104. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditorDrawer.svelte.d.ts +1 -1
  105. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptRunnableByPath.svelte.d.ts +1 -1
  106. package/package/components/apps/editor/settingsPanel/DecisionTreeGraphEditor.svelte +3 -3
  107. package/package/components/apps/editor/settingsPanel/decisionTree/DecisionTreePreview.svelte +1 -3
  108. package/package/components/assets/AssetsDropdownButton.svelte +1 -1
  109. package/package/components/assets/JobAssetsViewer.svelte +2 -2
  110. package/package/components/assets/lib.js +4 -0
  111. package/package/components/auditLogs/AuditLogsFilters.svelte +7 -9
  112. package/package/components/common/button/Button.svelte +4 -3
  113. package/package/components/common/button/Button.svelte.d.ts +1 -0
  114. package/package/components/common/confirmationModal/ConfirmationModal.svelte +6 -5
  115. package/package/components/common/confirmationModal/ConfirmationModal.svelte.d.ts +6 -11
  116. package/package/components/common/confirmationModal/asyncConfirmationModal.svelte.d.ts +26 -0
  117. package/package/components/common/confirmationModal/asyncConfirmationModal.svelte.js +50 -0
  118. package/package/components/common/modal/Modal.svelte +2 -5
  119. package/package/components/common/tabs/TabsV2.svelte +2 -1
  120. package/package/components/common/tabs/TabsV2.svelte.d.ts +1 -0
  121. package/package/components/copilot/chat/AIChatManager.svelte.js +61 -7
  122. package/package/components/copilot/chat/ContextTextarea.svelte +1 -1
  123. package/package/components/copilot/chat/script/core.js +28 -29
  124. package/package/components/copilot/chat/shared.d.ts +1 -1
  125. package/package/components/copilot/chat/shared.js +8 -2
  126. package/package/components/custom_ui.d.ts +2 -0
  127. package/package/components/dbOps.d.ts +20 -8
  128. package/package/components/dbOps.js +85 -40
  129. package/package/components/details/DetailPageHeader.svelte +0 -2
  130. package/package/components/flows/content/FlowInput.svelte +5 -0
  131. package/package/components/flows/content/FlowModuleScript.svelte +0 -1
  132. package/package/components/flows/idUtils.js +2 -1
  133. package/package/components/flows/map/FlowModuleSchemaItem.svelte +3 -3
  134. package/package/components/flows/map/FlowModuleSchemaMap.svelte +5 -0
  135. package/package/components/flows/map/InsertModuleButton.svelte +4 -1
  136. package/package/components/flows/propPicker/OutputBadge.svelte +5 -1
  137. package/package/components/flows/propPicker/OutputPickerInner.svelte +9 -5
  138. package/package/components/flows/propPicker/OutputPickerInner.svelte.d.ts +6 -2
  139. package/package/components/flows/propPicker/StepHistory.svelte +4 -1
  140. package/package/components/git_sync/DetectionFlow.svelte +202 -0
  141. package/package/components/git_sync/DetectionFlow.svelte.d.ts +6 -0
  142. package/package/components/git_sync/GitSyncContext.svelte.d.ts +82 -0
  143. package/package/components/git_sync/GitSyncContext.svelte.js +461 -0
  144. package/package/components/git_sync/GitSyncModalManager.svelte +99 -0
  145. package/package/components/git_sync/GitSyncModalManager.svelte.d.ts +18 -0
  146. package/package/components/git_sync/GitSyncRepositoryCard.svelte +339 -0
  147. package/package/components/git_sync/GitSyncRepositoryCard.svelte.d.ts +6 -0
  148. package/package/components/git_sync/GitSyncRepositoryList.svelte +17 -0
  149. package/package/components/git_sync/GitSyncRepositoryList.svelte.d.ts +18 -0
  150. package/package/components/git_sync/GitSyncSection.svelte +89 -0
  151. package/package/components/git_sync/GitSyncSection.svelte.d.ts +3 -0
  152. package/package/components/git_sync/GitSyncSuccessModal.svelte +58 -0
  153. package/package/components/git_sync/GitSyncSuccessModal.svelte.d.ts +7 -0
  154. package/package/components/git_sync/PullWorkspaceModal.svelte +575 -0
  155. package/package/components/git_sync/PullWorkspaceModal.svelte.d.ts +15 -0
  156. package/package/components/git_sync/PushWorkspaceModal.svelte +320 -0
  157. package/package/components/git_sync/PushWorkspaceModal.svelte.d.ts +12 -0
  158. package/package/components/graph/FlowGraphV2.svelte +5 -1
  159. package/package/components/graph/graphBuilder.svelte.js +1 -1
  160. package/package/components/graph/renderers/nodes/AssetNode.svelte +4 -4
  161. package/package/components/icons/AssetDucklakeIcon.svelte +28 -0
  162. package/package/components/icons/AssetDucklakeIcon.svelte.d.ts +9 -0
  163. package/package/components/icons/AssetGenericIcon.svelte +3 -0
  164. package/package/components/icons/DucklakeIcon.svelte +18 -0
  165. package/package/components/icons/DucklakeIcon.svelte.d.ts +6 -0
  166. package/package/components/instanceSettings.js +11 -3
  167. package/package/components/runs/JobPreview.svelte +2 -2
  168. package/package/components/runs/NoWorkerWithTagWarning.svelte +3 -3
  169. package/package/components/runs/RunsFilter.svelte.d.ts +1 -1
  170. package/package/components/schema/FlowPropertyEditor.svelte +3 -2
  171. package/package/components/schema/FlowPropertyEditor.svelte.d.ts +1 -1
  172. package/package/components/schema/PropertyEditor.svelte +0 -2
  173. package/package/components/schema/PropertyEditor.svelte.d.ts +1 -1
  174. package/package/components/schema/SchemaFormDND.svelte +2 -1
  175. package/package/components/schema/SchemaFormDND.svelte.d.ts +2 -0
  176. package/package/components/scriptEditor/LogPanel.svelte +5 -3
  177. package/package/components/scriptEditor/LogPanel.svelte.d.ts +5 -1
  178. package/package/components/select/Select.svelte +7 -4
  179. package/package/components/select/Select.svelte.d.ts +5 -0
  180. package/package/components/select/SelectDropdown.svelte +2 -1
  181. package/package/components/select/SelectDropdown.svelte.d.ts +3 -0
  182. package/package/components/sidebar/changelogs.js +5 -0
  183. package/package/components/table/AutoDataTable.svelte +6 -4
  184. package/package/components/table/AutoDataTable.svelte.d.ts +1 -0
  185. package/package/components/table/DataTable.svelte +12 -10
  186. package/package/components/table/DataTable.svelte.d.ts +1 -0
  187. package/package/components/triggers/TriggerRetriesAndErrorHandler.svelte.d.ts +2 -2
  188. package/package/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte +1 -1
  189. package/package/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte.d.ts +2 -1
  190. package/package/components/triggers/gcp/GcpTriggerEditorInner.svelte +50 -11
  191. package/package/components/triggers/gcp/utils.js +1 -0
  192. package/package/components/triggers/http/utils.js +1 -1
  193. package/package/components/triggers/kafka/utils.js +1 -1
  194. package/package/components/triggers/mqtt/utils.js +1 -1
  195. package/package/components/triggers/nats/utils.js +1 -1
  196. package/package/components/triggers/postgres/utils.js +1 -1
  197. package/package/components/triggers/sqs/utils.js +1 -1
  198. package/package/components/triggers/utils.js +2 -1
  199. package/package/components/triggers/webhook/WebhooksConfigSection.svelte +24 -26
  200. package/package/components/triggers/webhook/WebhooksPanel.svelte +1 -15
  201. package/package/components/triggers/websocket/utils.js +1 -1
  202. package/package/components/workspaceSettings/AISettings.svelte +52 -36
  203. package/package/components/workspaceSettings/DucklakeSettings.svelte +321 -0
  204. package/package/components/workspaceSettings/DucklakeSettings.svelte.d.ts +23 -0
  205. package/package/components/workspaceSettings/GitSyncFilterSettings.svelte +122 -499
  206. package/package/components/workspaceSettings/GitSyncFilterSettings.svelte.d.ts +8 -10
  207. package/package/consts.js +2 -1
  208. package/package/gen/core/OpenAPI.js +1 -1
  209. package/package/gen/schemas.gen.d.ts +7 -6
  210. package/package/gen/schemas.gen.js +7 -6
  211. package/package/gen/services.gen.d.ts +19 -1
  212. package/package/gen/services.gen.js +38 -0
  213. package/package/gen/types.gen.d.ts +78 -3
  214. package/package/git-sync.d.ts +36 -0
  215. package/package/git-sync.js +1 -0
  216. package/package/hub.d.ts +1 -0
  217. package/package/hubPaths.json +5 -2
  218. package/package/infer.js +3 -2
  219. package/package/script_helpers.d.ts +2 -2
  220. package/package/script_helpers.js +29 -11
  221. package/package/services/JobManager.d.ts +28 -0
  222. package/package/services/JobManager.js +114 -0
  223. package/package/stores.d.ts +1 -1
  224. package/package/utils.d.ts +18 -1
  225. package/package/utils.js +55 -2
  226. package/package.json +5 -4
  227. package/package/components/InitGitRepoPopover.svelte +0 -410
  228. package/package/components/InitGitRepoPopover.svelte.d.ts +0 -13
  229. package/package/components/PullGitRepoPopover.svelte +0 -355
  230. package/package/components/PullGitRepoPopover.svelte.d.ts +0 -18
  231. package/package/inferArgSig.d.ts +0 -42
  232. package/package/inferArgSig.js +0 -198
@@ -7,18 +7,21 @@ import { base } from '../base';
7
7
  import { enterpriseLicense, workspaceStore } from '../stores';
8
8
  import MsTeamsIcon from './icons/MSTeamsIcon.svelte';
9
9
  import { emptySchema, emptyString, sendUserToast, tryEvery } from '../utils';
10
+ import Description from './Description.svelte';
11
+ import MultiSelect from './select/MultiSelect.svelte';
10
12
  import { FlowService, JobService, ScriptService, WorkspaceService } from '../gen';
11
13
  import { inferArgs } from '../infer';
12
14
  import { hubBaseUrlStore } from '../stores';
13
15
  import { CheckCircle2, Loader2, RotateCw, XCircle, RefreshCcw } from 'lucide-svelte';
14
16
  import { hubPaths } from '../hub';
17
+ import { isCloudHosted } from '../cloud';
15
18
  const slackRecoveryHandler = hubPaths.slackRecoveryHandler;
16
19
  const slackHandlerScriptPath = hubPaths.slackErrorHandler;
17
20
  const slackSuccessHandler = hubPaths.slackSuccessHandler;
18
21
  const teamsRecoveryHandler = hubPaths.teamsRecoveryHandler;
19
22
  const teamsHandlerScriptPath = hubPaths.teamsErrorHandler;
20
23
  const teamsSuccessHandler = hubPaths.teamsSuccessHandler;
21
- let { errorOrRecovery, isEditable, toggleText = 'Enable', showScriptHelpText = false, handlerSelected = $bindable(), handlerPath = $bindable(), handlerExtraArgs = $bindable(), customScriptTemplate, customHandlerKind = $bindable('script'), customTabTooltip } = $props();
24
+ let { errorOrRecovery, isEditable, toggleText = 'Enable', showScriptHelpText = false, handlerSelected = $bindable('custom'), handlerPath = $bindable(), handlerExtraArgs = $bindable(), customScriptTemplate, customHandlerKind = $bindable('script'), customTabTooltip, } = $props();
22
25
  let customHandlerSchema = $state();
23
26
  let slackHandlerSchema = $state();
24
27
  let isFetching = $state(false);
@@ -27,6 +30,8 @@ let teams_team_name = $state(undefined);
27
30
  let workspaceConnectedToSlack = $state(undefined);
28
31
  let workspaceConnectedToTeams = $state(undefined);
29
32
  let connectionTestJob = $state();
33
+ const EMAIL_RECIPIENTS_KEY = 'email_recipients';
34
+ const CHANNEL_KEY = 'channel';
30
35
  async function loadSlackResources() {
31
36
  const settings = await WorkspaceService.getSettings({ workspace: $workspaceStore });
32
37
  if (!emptyString(settings.slack_name) && !emptyString(settings.slack_team_id)) {
@@ -166,6 +171,12 @@ function isTeamsHandler(scriptPath) {
166
171
  return scriptPath.startsWith('hub/') && scriptPath.endsWith('/schedule-success-handler-teams');
167
172
  }
168
173
  }
174
+ function isEmailHandler(scriptPath) {
175
+ if (!scriptPath) {
176
+ return false;
177
+ }
178
+ return scriptPath.startsWith('hub/') && scriptPath.endsWith('/workspace-or-error-handler-email');
179
+ }
169
180
  $effect(() => {
170
181
  if ($workspaceStore) {
171
182
  loadSlackResources();
@@ -181,21 +192,27 @@ $effect(() => {
181
192
  }
182
193
  });
183
194
  let lastHandlerSelected = $state(undefined);
184
- let channelCache = $state({
195
+ let handlerCache = $state({
185
196
  slack: undefined,
186
- teams: undefined
197
+ teams: undefined,
198
+ email: undefined
187
199
  });
188
200
  $effect(() => {
189
201
  if (lastHandlerSelected !== handlerSelected && lastHandlerSelected !== undefined) {
190
- if (lastHandlerSelected === 'teams' || lastHandlerSelected === 'slack') {
191
- channelCache[lastHandlerSelected] = handlerExtraArgs['channel'];
202
+ if (lastHandlerSelected != 'custom') {
203
+ const key = lastHandlerSelected === 'email' ? EMAIL_RECIPIENTS_KEY : CHANNEL_KEY;
204
+ handlerCache[lastHandlerSelected] = handlerExtraArgs[key];
192
205
  }
193
206
  if (handlerSelected === 'custom') {
194
- handlerExtraArgs['channel'] = '';
207
+ handlerExtraArgs[CHANNEL_KEY] = '';
208
+ handlerExtraArgs[EMAIL_RECIPIENTS_KEY] = [];
195
209
  handlerPath = undefined;
196
210
  }
211
+ else if (handlerSelected === 'email') {
212
+ handlerExtraArgs[EMAIL_RECIPIENTS_KEY] = handlerCache[handlerSelected] ?? [];
213
+ }
197
214
  else {
198
- handlerExtraArgs['channel'] = channelCache[handlerSelected] ?? '';
215
+ handlerExtraArgs[CHANNEL_KEY] = handlerCache[handlerSelected] ?? '';
199
216
  }
200
217
  }
201
218
  lastHandlerSelected = handlerSelected;
@@ -204,6 +221,7 @@ $effect(() => {
204
221
  handlerPath &&
205
222
  !isSlackHandler(handlerPath) &&
206
223
  !isTeamsHandler(handlerPath) &&
224
+ !isEmailHandler(handlerPath) &&
207
225
  loadHandlerScriptArgs(handlerPath, [
208
226
  'path',
209
227
  'workspace_id',
@@ -242,12 +260,18 @@ $effect(() => {
242
260
  'slack'
243
261
  ]).then((schema) => (slackHandlerSchema = schema));
244
262
  });
263
+ $effect(() => {
264
+ if (handlerSelected === 'email') {
265
+ handlerPath = hubPaths.emailErrorHandler;
266
+ }
267
+ });
245
268
  </script>
246
269
 
247
270
  <div>
248
271
  <Tabs bind:selected={handlerSelected} class="mt-2 mb-4">
249
272
  <Tab value="slack" disabled={!isEditable}>Slack</Tab>
250
273
  <Tab value="teams" disabled={!isEditable}>Teams</Tab>
274
+ <Tab value="email" disabled={!isEditable}>Email</Tab>
251
275
  <Tab value="custom" disabled={!isEditable}>
252
276
  Custom
253
277
  {@render customTabTooltip?.()}
@@ -274,8 +298,10 @@ $effect(() => {
274
298
  size="xs"
275
299
  href={customScriptTemplate}
276
300
  disabled={!isEditable}
277
- target="_blank">Create from template</Button
301
+ target="_blank"
278
302
  >
303
+ Create from template
304
+ </Button>
279
305
  {/if}
280
306
  </div>
281
307
  {#if showScriptHelpText}
@@ -503,4 +529,46 @@ $effect(() => {
503
529
  {/if}
504
530
  {/if}
505
531
  {/if}
532
+ {:else if handlerSelected === 'email'}
533
+ {#if isCloudHosted()}
534
+ <Alert type="info" title="Email notifications are not available in Cloud">
535
+ Email notifications for trigger failures are only available in self-hosted Windmill instances.
536
+ </Alert>
537
+ {:else}
538
+ <div class="flex flex-col gap-4 my-4">
539
+ <Description>
540
+ Configure email addresses to receive notifications when jobs fail. This feature requires
541
+ SMTP to be configured.
542
+ </Description>
543
+ </div>
544
+ <div class="flex flex-col gap-2 my-4">
545
+ <MultiSelect
546
+ items={[] as { label: string; value: string }[]}
547
+ bind:value={
548
+ () => handlerExtraArgs[EMAIL_RECIPIENTS_KEY] ?? [],
549
+ (recipients) => (handlerExtraArgs[EMAIL_RECIPIENTS_KEY] = recipients)
550
+ }
551
+ placeholder="Enter email addresses..."
552
+ onCreateItem={(email) => {
553
+ const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
554
+ if (!emailRegex.test(email)) {
555
+ sendUserToast('Invalid email format', true)
556
+ return
557
+ }
558
+ const currentArray = handlerExtraArgs[EMAIL_RECIPIENTS_KEY] ?? []
559
+ handlerExtraArgs[EMAIL_RECIPIENTS_KEY] = [...currentArray, email]
560
+ }}
561
+ class="w-full"
562
+ />
563
+ {#if handlerExtraArgs[EMAIL_RECIPIENTS_KEY]?.length > 0}
564
+ <span class="text-sm text-tertiary">
565
+ {handlerExtraArgs[EMAIL_RECIPIENTS_KEY]?.length} email{handlerExtraArgs[
566
+ EMAIL_RECIPIENTS_KEY
567
+ ]?.length === 1
568
+ ? ''
569
+ : 's'} configured
570
+ </span>
571
+ {/if}
572
+ </div>
573
+ {/if}
506
574
  {/if}
@@ -1,9 +1,10 @@
1
+ import type { ErrorHandler } from '../gen/types.gen';
1
2
  interface Props {
2
3
  errorOrRecovery: 'error' | 'recovery' | 'success';
3
4
  isEditable: boolean;
4
5
  toggleText?: string;
5
6
  showScriptHelpText?: boolean;
6
- handlerSelected: 'custom' | 'slack' | 'teams';
7
+ handlerSelected: ErrorHandler;
7
8
  handlerPath: string | undefined;
8
9
  handlerExtraArgs: Record<string, any>;
9
10
  customScriptTemplate: string;
@@ -1,5 +1,6 @@
1
1
  <script module lang="ts">export function assetCanBeExplored(asset, _resourceMetadata) {
2
- return (asset.kind === 's3object' ||
2
+ return (asset.kind === 'ducklake' ||
3
+ asset.kind === 's3object' ||
3
4
  (asset.kind === 'resource' && isDbType(_resourceMetadata?.resource_type)));
4
5
  }
5
6
  </script>
@@ -12,12 +13,13 @@ import S3FilePicker from './S3FilePicker.svelte';
12
13
  import { userStore } from '../stores';
13
14
  import { isS3Uri } from '../utils';
14
15
  import { Database, File } from 'lucide-svelte';
15
- const { asset, _resourceMetadata, s3FilePicker, dbManagerDrawer, onClick, class: className = '', noText = false, buttonVariant = 'border', btnClasses = '' } = $props();
16
+ import DucklakeIcon from './icons/DucklakeIcon.svelte';
17
+ const { asset, _resourceMetadata, s3FilePicker, dbManagerDrawer, onClick, class: className = '', noText = false, buttonVariant = 'border', btnClasses = '', disabled = false } = $props();
16
18
  const assetUri = $derived(formatAsset(asset));
17
19
  </script>
18
20
 
19
21
  <Button
20
- disabled={$userStore?.operator}
22
+ disabled={$userStore?.operator || disabled}
21
23
  size="xs"
22
24
  variant={buttonVariant}
23
25
  spacingSize="xs2"
@@ -25,9 +27,15 @@ const assetUri = $derived(formatAsset(asset));
25
27
  {btnClasses}
26
28
  on:click={async () => {
27
29
  if (asset.kind === 'resource' && isDbType(_resourceMetadata?.resource_type)) {
28
- dbManagerDrawer?.openDrawer(_resourceMetadata.resource_type, asset.path)
30
+ dbManagerDrawer?.openDrawer({
31
+ type: 'database',
32
+ resourceType: _resourceMetadata.resource_type,
33
+ resourcePath: asset.path
34
+ })
29
35
  } else if (asset.kind === 's3object' && isS3Uri(assetUri)) {
30
36
  s3FilePicker?.open(assetUri)
37
+ } else if (asset.kind === 'ducklake') {
38
+ dbManagerDrawer?.openDrawer({ type: 'ducklake', ducklake: asset.path })
31
39
  }
32
40
  onClick?.()
33
41
  }}
@@ -36,5 +44,7 @@ const assetUri = $derived(formatAsset(asset));
36
44
  <span class:hidden={noText}>Explore</span> <File size={18} />
37
45
  {:else if asset.kind === 'resource'}
38
46
  <span class:hidden={noText}>Manage</span> <Database size={18} />
47
+ {:else if asset.kind === 'ducklake'}
48
+ <span class:hidden={noText}>Manage</span> <DucklakeIcon size={18} />
39
49
  {/if}
40
50
  </Button>
@@ -17,6 +17,7 @@ type $$ComponentProps = {
17
17
  noText?: boolean;
18
18
  buttonVariant?: ButtonType.Variant;
19
19
  btnClasses?: string;
20
+ disabled?: boolean;
20
21
  };
21
22
  declare const ExploreAssetButton: import("svelte").Component<$$ComponentProps, {}, "">;
22
23
  type ExploreAssetButton = ReturnType<typeof ExploreAssetButton>;
@@ -7,7 +7,7 @@ import DrawerContent from './common/drawer/DrawerContent.svelte';
7
7
  import { Drawer } from './common';
8
8
  import AllFlowLogs from './AllFlowLogs.svelte';
9
9
  import { untrack } from 'svelte';
10
- let { waitingForExecutor = false, result, logs = $bindable(), col = false, noBorder = false, loading, filename = undefined, jobId = undefined, tag = undefined, workspaceId = undefined, refreshLog = false, durationStates, downloadLogs = true, tagLabel = undefined } = $props();
10
+ let { waitingForExecutor = false, result, result_stream, logs = $bindable(), col = false, noBorder = false, loading, filename = undefined, jobId = undefined, tag = undefined, workspaceId = undefined, refreshLog = false, durationStates, downloadLogs = true, tagLabel = undefined } = $props();
11
11
  let lastJobId = $state(undefined);
12
12
  let drawer = $state(undefined);
13
13
  let iteration = 0;
@@ -62,8 +62,8 @@ $effect(() => {
62
62
  >
63
63
  <div class="bg-surface {col ? '' : 'max-h-80'} p-1 overflow-auto relative">
64
64
  <span class="text-tertiary">Result</span>
65
- {#if result !== undefined}
66
- <DisplayResult {workspaceId} {jobId} {filename} {result} />
65
+ {#if result !== undefined || result_stream !== undefined}
66
+ <DisplayResult {workspaceId} {jobId} {filename} {result} {result_stream} />
67
67
  {:else if loading}
68
68
  <Loader2 class="animate-spin" />
69
69
  {:else}
@@ -3,6 +3,7 @@ import type { Writable } from 'svelte/store';
3
3
  interface Props {
4
4
  waitingForExecutor?: boolean;
5
5
  result: any;
6
+ result_stream?: string;
6
7
  logs: string | undefined;
7
8
  col?: boolean;
8
9
  noBorder?: boolean;
@@ -427,6 +427,14 @@ export function flowHasChanged() {
427
427
  savedArgs = previewArgs.val
428
428
  }}
429
429
  bind:isValid
430
+ helperScript={flowStore.val.schema?.['x-windmill-dyn-select-code'] &&
431
+ flowStore.val.schema?.['x-windmill-dyn-select-lang']
432
+ ? {
433
+ type: 'inline',
434
+ code: flowStore.val.schema['x-windmill-dyn-select-code'] as string,
435
+ lang: flowStore.val.schema['x-windmill-dyn-select-lang'] as ScriptLang
436
+ }
437
+ : undefined}
430
438
  />
431
439
  </div>
432
440
  {/key}
@@ -494,7 +502,7 @@ export function flowHasChanged() {
494
502
  bind:rightColumnSelect
495
503
  bind:isOwner
496
504
  {render}
497
- customUi={customUi}
505
+ {customUi}
498
506
  />
499
507
  {:else}
500
508
  <div class="italic text-tertiary h-full grow"> Flow status will be displayed here </div>
@@ -4,7 +4,7 @@ import FlowPreviewStatus from './preview/FlowPreviewStatus.svelte';
4
4
  import FlowStatusWaitingForEvents from './FlowStatusWaitingForEvents.svelte';
5
5
  import { emptyString } from '../utils';
6
6
  import Badge from './common/badge/Badge.svelte';
7
- let { job, workspaceId, isOwner, hideFlowResult, hideDownloadLogs, localDurationStatuses, innerModules, suspendStatus, hideJobId, extra } = $props();
7
+ let { job, workspaceId, isOwner, hideFlowResult, hideDownloadLogs, localDurationStatuses, innerModules, suspendStatus, hideJobId, extra, result_streams } = $props();
8
8
  </script>
9
9
 
10
10
  <FlowPreviewStatus {job} {hideJobId} {extra} />
@@ -76,6 +76,9 @@ let { job, workspaceId, isOwner, hideFlowResult, hideDownloadLogs, localDuration
76
76
  <Loader2 class="animate-spin mt-0.5" /></span
77
77
  ></div
78
78
  >
79
+ {#if mod.job && result_streams?.[mod.job]}
80
+ <pre class="text-xs text-primary">{result_streams?.[mod.job]}</pre>
81
+ {/if}
79
82
  {/if}
80
83
  {/each}
81
84
  </div>
@@ -15,6 +15,7 @@ interface Props {
15
15
  }>>;
16
16
  hideJobId?: boolean;
17
17
  extra?: import('svelte').Snippet;
18
+ result_streams?: Record<string, string | undefined>;
18
19
  }
19
20
  declare const FlowPreviewResult: import("svelte").Component<Props, {}, "">;
20
21
  type FlowPreviewResult = ReturnType<typeof FlowPreviewResult>;
@@ -27,7 +27,13 @@ import { createState } from '../svelte5Utils.svelte';
27
27
  import JobLoader from './JobLoader.svelte';
28
28
  const dispatch = createEventDispatcher();
29
29
  let { flowStateStore, retryStatus, suspendStatus, hideDownloadInGraph, hideTimeline, hideNodeDefinition, hideDownloadLogs, hideJobId } = getContext('FlowStatusViewer');
30
- let { jobId, initialJob = undefined, workspaceId = undefined, flowJobIds = undefined, innerModule = undefined, globalRefreshes = $bindable({}), render = true, isOwner = false, selectedNode = $bindable(undefined), globalModuleStates, globalDurationStatuses, childFlow = false, isSubflow = false, reducedPolling = false, wideResults = false, hideFlowResult = false, workspace = $workspaceStore, prefix = undefined, subflowParentsGlobalModuleStates = [], subflowParentsDurationStatuses = [], isForloopSelected = false, parentRecursiveRefresh = $bindable({}), job = $bindable(undefined), rightColumnSelect = $bindable('timeline'), localModuleStates = writable({}), localDurationStatuses = writable({}), customUi } = $props();
30
+ let { jobId, initialJob = undefined, workspaceId = undefined, flowJobIds = undefined, innerModule = undefined, globalRefreshes = $bindable({}), render = true, isOwner = false, selectedNode = $bindable(undefined), globalModuleStates, globalDurationStatuses, childFlow = false, isSubflow = false, reducedPolling = false, wideResults = false, hideFlowResult = false, workspace = $workspaceStore, prefix = undefined, subflowParentsGlobalModuleStates = [], subflowParentsDurationStatuses = [], isForloopSelected = false, parentRecursiveRefresh = $bindable({}), job = $bindable(undefined), rightColumnSelect = $bindable('timeline'), localModuleStates = writable({}), localDurationStatuses = writable({}), customUi, onResultStreamUpdate = undefined } = $props();
31
+ let resultStreams = $state({});
32
+ if (onResultStreamUpdate == undefined) {
33
+ onResultStreamUpdate = ({ jobId, result_stream }) => {
34
+ resultStreams[jobId] = result_stream;
35
+ };
36
+ }
31
37
  let recursiveRefresh = $state({});
32
38
  // Add support for the input args assets shown as an asset node
33
39
  const _flowGraphAssetsCtx = getContext('FlowGraphAssetContext');
@@ -76,7 +82,9 @@ function updateModuleStates(moduleState, key, newValue, keepType) {
76
82
  if (newValue.selectedForloop != undefined &&
77
83
  state[key]?.selectedForloop != undefined &&
78
84
  newValue.selectedForloop != state[key].selectedForloop) {
79
- if (newValue.type == 'InProgress' && state[key]?.type != 'InProgress') {
85
+ if (newValue.type == 'InProgress' &&
86
+ state[key]?.type != 'InProgress' &&
87
+ !(keepType && (state[key]?.type === 'Success' || state[key]?.type === 'Failure'))) {
80
88
  moduleState.update((state) => {
81
89
  state[key].type = 'InProgress';
82
90
  return state;
@@ -357,6 +365,9 @@ async function loadJobInProgress() {
357
365
  jobLoader?.watchJob(jobId, {
358
366
  change(newJob) {
359
367
  setJob(newJob, true);
368
+ },
369
+ resultStreamUpdate({ id, result_stream }) {
370
+ onResultStreamUpdate?.({ jobId: id, result_stream });
360
371
  }
361
372
  });
362
373
  }
@@ -685,7 +696,7 @@ $effect(() => {
685
696
  let selected = $derived(isListJob ? 'sequence' : 'graph');
686
697
  </script>
687
698
 
688
- <JobLoader noCode noLogs bind:this={jobLoader} />
699
+ <JobLoader workspaceOverride={workspaceId} noCode noLogs bind:this={jobLoader} />
689
700
  {#if notAnonynmous}
690
701
  <Alert type="error" title="Required Auth">
691
702
  As a non logged in user, you can only see jobs ran by anonymous users like you
@@ -728,6 +739,7 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
728
739
  <DisplayResult
729
740
  workspaceId={job?.workspace_id}
730
741
  {jobId}
742
+ result_stream={job?.result_stream}
731
743
  result={jobResults}
732
744
  language={job?.language}
733
745
  />
@@ -745,6 +757,7 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
745
757
  {innerModules}
746
758
  {suspendStatus}
747
759
  {hideJobId}
760
+ result_streams={resultStreams}
748
761
  />
749
762
  </div>
750
763
  {/if}
@@ -836,6 +849,7 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
836
849
  storedListJobs[j] = job
837
850
  innerJobLoaded(job, j, false, force)
838
851
  }}
852
+ {onResultStreamUpdate}
839
853
  />
840
854
  </div>
841
855
  {/if}
@@ -911,6 +925,7 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
911
925
  {reducedPolling}
912
926
  {workspaceId}
913
927
  jobId={failedRetry}
928
+ {onResultStreamUpdate}
914
929
  />
915
930
  </div>
916
931
  {/each}
@@ -943,6 +958,7 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
943
958
  let { force, job } = e.detail
944
959
  onJobsLoaded(mod, job, force)
945
960
  }}
961
+ {onResultStreamUpdate}
946
962
  />
947
963
  {:else if mod.flow_jobs?.length == 0 && mod.job == '00000000-0000-0000-0000-000000000000'}
948
964
  <div class="text-secondary">no subflow (empty loop?)</div>
@@ -974,6 +990,7 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
974
990
  let { job, force } = e.detail
975
991
  onJobsLoaded(mod, job, force)
976
992
  }}
993
+ {onResultStreamUpdate}
977
994
  />
978
995
  {/if}
979
996
  {:else}
@@ -1197,6 +1214,7 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
1197
1214
  waitingForExecutor={node.type == 'WaitingForExecutor'}
1198
1215
  refreshLog={node.type == 'InProgress'}
1199
1216
  col
1217
+ result_stream={resultStreams[node.job_id ?? '']}
1200
1218
  result={node.result}
1201
1219
  tag={node.tag}
1202
1220
  logs={node.logs}
@@ -31,10 +31,16 @@ interface Props {
31
31
  subflowParentsDurationStatuses?: Writable<Record<string, DurationStatus>>[];
32
32
  isForloopSelected?: boolean;
33
33
  parentRecursiveRefresh?: Record<string, (clear: any, root: any) => Promise<void>>;
34
- job?: Job | undefined;
34
+ job?: (Job & {
35
+ result_stream?: string;
36
+ }) | undefined;
35
37
  rightColumnSelect?: 'timeline' | 'node_status' | 'node_definition' | 'user_states';
36
38
  localModuleStates?: Writable<Record<string, GraphModuleState>>;
37
39
  localDurationStatuses?: Writable<Record<string, DurationStatus>>;
40
+ onResultStreamUpdate?: ({ jobId, result_stream }: {
41
+ jobId: string;
42
+ result_stream?: string;
43
+ }) => void;
38
44
  customUi?: {
39
45
  tagLabel?: string | undefined;
40
46
  };
@@ -250,7 +250,7 @@ run(() => {
250
250
  <div>
251
251
  <ToggleButtonGroup
252
252
  disabled={owner_name == 'u/' + $userStore?.username &&
253
- !$userStore?.is_admin}
253
+ !($userStore?.is_admin || $userStore?.is_super_admin)}
254
254
  selected={role}
255
255
  on:selected={async (e) => {
256
256
  const role = e.detail
@@ -1,25 +1,21 @@
1
- <script lang="ts">"use strict";
2
- let { previewResult } = $props();
1
+ <script lang="ts">let { previewResult } = $props();
2
+ let added = $derived(previewResult?.changes?.filter(c => c.type === 'added').map(c => c.path) || []);
3
+ let deleted = $derived(previewResult?.changes?.filter(c => c.type === 'deleted').map(c => c.path) || []);
4
+ let edited = $derived(previewResult?.changes?.filter(c => c.type === 'edited').map(c => c.path) || []);
5
+ export {};
3
6
  </script>
4
7
 
5
8
  <div class="border rounded p-2 text-xs max-h-40 overflow-y-auto bg-surface-secondary">
6
9
  <div class="font-semibold text-[11px] mb-1 text-tertiary">Preview of changes:</div>
7
- {#if !previewResult?.added?.length && !previewResult?.deleted?.length && !previewResult?.modified?.length && !previewResult?.yamlModified}
10
+
11
+ {#if !added.length && !deleted.length && !edited.length}
8
12
  <div class="mt-2 text-tertiary">No changes found! The workspace is up to date.</div>
9
13
  {:else}
10
- {#if previewResult?.yamlModified}
11
- <div class="mt-2">
12
- <div class="text-yellow-600">Modified:</div>
13
- <ul class="list-disc list-inside">
14
- <li>wmill.yaml (Git sync settings)</li>
15
- </ul>
16
- </div>
17
- {/if}
18
- {#if previewResult?.added?.length}
14
+ {#if added.length}
19
15
  <div class="mt-2">
20
16
  <div class="text-green-600">Added:</div>
21
17
  <ul class="list-disc list-inside">
22
- {#each previewResult.added as file}
18
+ {#each added as file}
23
19
  <li>
24
20
  {file}{!file.includes('.') ? ' (dir)' : ''}
25
21
  </li>
@@ -27,11 +23,11 @@ let { previewResult } = $props();
27
23
  </ul>
28
24
  </div>
29
25
  {/if}
30
- {#if previewResult?.deleted?.length}
26
+ {#if deleted.length}
31
27
  <div class="mt-2">
32
28
  <div class="text-red-600">Deleted:</div>
33
29
  <ul class="list-disc list-inside">
34
- {#each previewResult.deleted as file}
30
+ {#each deleted as file}
35
31
  <li>
36
32
  {file}{!file.includes('.') ? ' (dir)' : ''}
37
33
  </li>
@@ -39,11 +35,11 @@ let { previewResult } = $props();
39
35
  </ul>
40
36
  </div>
41
37
  {/if}
42
- {#if previewResult?.modified?.length}
38
+ {#if edited.length}
43
39
  <div class="mt-2">
44
- <div class="text-yellow-600">Modified:</div>
40
+ <div class="text-yellow-600">Edited:</div>
45
41
  <ul class="list-disc list-inside">
46
- {#each previewResult.modified as file}
42
+ {#each edited as file}
47
43
  <li>
48
44
  {file}{!file.includes('.') ? ' (dir)' : ''}
49
45
  </li>
@@ -1,12 +1,6 @@
1
- type DiffResult = {
2
- added: string[];
3
- deleted: string[];
4
- modified: string[];
5
- repoWmillYaml?: string;
6
- yamlModified?: boolean;
7
- };
1
+ import type { SyncResponse } from '../git-sync';
8
2
  type $$ComponentProps = {
9
- previewResult: DiffResult | undefined;
3
+ previewResult: SyncResponse | undefined;
10
4
  };
11
5
  declare const GitDiffPreview: import("svelte").Component<$$ComponentProps, {}, "">;
12
6
  type GitDiffPreview = ReturnType<typeof GitDiffPreview>;
@@ -12,7 +12,9 @@ let githubAppPopover = $state(null);
12
12
  let githubInstallationsNotInWorkspace = $derived(githubState.githubInstallations
13
13
  .filter((installation) => !githubState.workspaceGithubInstallations.some((workspaceInstallation) => workspaceInstallation.installation_id === installation.installation_id))
14
14
  .filter((installation, index, array) => array.findIndex((item) => item.installation_id === installation.installation_id) === index));
15
- let showGitHubApp = $derived(resourceType === 'git_repository' && $workspaceStore && $userStore?.is_admin);
15
+ let showGitHubApp = $derived(resourceType === 'git_repository' &&
16
+ $workspaceStore &&
17
+ ($userStore?.is_admin || $userStore?.is_super_admin));
16
18
  // Load GitHub installations when conditions are met
17
19
  $effect(() => {
18
20
  if (showGitHubApp && $enterpriseLicense && $workspaceStore) {
@@ -1,20 +1,13 @@
1
- <script lang="ts">import { ArrowRight } from 'lucide-svelte';
1
+ <script lang="ts">import { stopPropagation, createBubbler } from 'svelte/legacy';
2
+ const bubble = createBubbler();
3
+ import { ArrowRight } from 'lucide-svelte';
2
4
  import { Button } from './common';
3
- import { createEventDispatcher } from 'svelte';
4
5
  import { forbiddenIds } from './flows/idUtils';
5
6
  import { slide } from 'svelte/transition';
6
- export let initialId;
7
- export let reservedIds = [];
8
- export let label = 'Component ID';
9
- export let value = initialId;
10
- export let buttonText = '';
11
- export let btnClasses = '!p-1 !w-[34px] !ml-1';
12
- export let acceptUnderScores = false;
13
- let error = '';
14
- const dispatch = createEventDispatcher();
7
+ let { initialId, reservedIds = [], reservedPrefixes = [], label = 'Component ID', value = $bindable(initialId), buttonText = '', btnClasses = '!p-1 !w-[34px] !ml-1', acceptUnderScores = false, onSave, onClose } = $props();
8
+ let error = $state('');
15
9
  const regex = acceptUnderScores ? /^[a-zA-Z][a-zA-Z0-9_]*$/ : /^[a-zA-Z][a-zA-Z0-9]*$/;
16
- $: validateId(value, reservedIds);
17
- function validateId(id, reservedIds) {
10
+ function validateId(id, reservedIds, reservedPrefixes) {
18
11
  if (id == initialId) {
19
12
  error = '';
20
13
  return;
@@ -25,6 +18,9 @@ function validateId(id, reservedIds) {
25
18
  else if (forbiddenIds.includes(value)) {
26
19
  error = 'This ID is reserved';
27
20
  }
21
+ else if (reservedPrefixes.some((prefix) => value.startsWith(prefix))) {
22
+ error = 'This ID uses a reserved prefix';
23
+ }
28
24
  else if (reservedIds.some((rid) => rid === value)) {
29
25
  error = 'This ID is already in use';
30
26
  }
@@ -32,8 +28,13 @@ function validateId(id, reservedIds) {
32
28
  error = '';
33
29
  }
34
30
  }
35
- let inputDiv = undefined;
36
- $: inputDiv?.focus();
31
+ let inputDiv = $state(undefined);
32
+ $effect(() => {
33
+ validateId(value, reservedIds, reservedPrefixes);
34
+ });
35
+ $effect(() => {
36
+ inputDiv?.focus();
37
+ });
37
38
  </script>
38
39
 
39
40
  <label class="block text-primary">
@@ -46,15 +47,17 @@ $: inputDiv?.focus();
46
47
  type="text"
47
48
  bind:value
48
49
  class="!w-auto grow"
49
- on:click|stopPropagation={() => {}}
50
- on:keydown|stopPropagation={({ key }) => {
50
+ onclick={stopPropagation(() => {})}
51
+ onkeydown={(e) => {
52
+ e.stopPropagation()
53
+ let key = e.key
51
54
  if (key === 'Enter' && error === '' && value !== initialId) {
52
- dispatch('save', value)
55
+ onSave({ oldId: initialId, newId: value })
53
56
  } else if (key == 'Escape') {
54
- dispatch('close')
57
+ onClose?.()
55
58
  }
56
59
  }}
57
- on:keypress|stopPropagation
60
+ onkeypress={stopPropagation(bubble('keypress'))}
58
61
  />
59
62
  <Button
60
63
  size="xs"
@@ -63,8 +66,8 @@ $: inputDiv?.focus();
63
66
  {btnClasses}
64
67
  aria-label="Save ID"
65
68
  disabled={error != '' || value === initialId}
66
- on:click={() => {
67
- dispatch('save', value)
69
+ onclick={() => {
70
+ onSave({ oldId: initialId, newId: value })
68
71
  }}
69
72
  >
70
73
  {buttonText}<ArrowRight size={18} />