windmill-components 1.542.5 → 1.550.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 (188) hide show
  1. package/package/common.d.ts +4 -1
  2. package/package/components/AIAgentLogViewer.svelte +1 -1
  3. package/package/components/ArgEnum.svelte +14 -5
  4. package/package/components/ArgInput.svelte +23 -15
  5. package/package/components/ArgInput.svelte.d.ts +1 -1
  6. package/package/components/ChannelSelector.svelte +92 -18
  7. package/package/components/ChannelSelector.svelte.d.ts +2 -0
  8. package/package/components/ConnectionSection.svelte +12 -1
  9. package/package/components/Dev.svelte +18 -5
  10. package/package/components/Dev.svelte.d.ts +23 -1
  11. package/package/components/DisplayResult.svelte +36 -23
  12. package/package/components/DropdownV2.svelte +8 -2
  13. package/package/components/DropdownV2.svelte.d.ts +1 -0
  14. package/package/components/DynamicInput.svelte +10 -10
  15. package/package/components/EditableSchemaForm.svelte +21 -7
  16. package/package/components/ErrorOrRecoveryHandler.svelte +14 -20
  17. package/package/components/FlowHistoryJobPicker.svelte +3 -0
  18. package/package/components/FlowHistoryJobPicker.svelte.d.ts +1 -0
  19. package/package/components/FlowJobResult.svelte +5 -5
  20. package/package/components/FlowLogRow.svelte +2 -2
  21. package/package/components/FlowLogViewer.svelte +228 -57
  22. package/package/components/FlowLogViewer.svelte.d.ts +16 -5
  23. package/package/components/FlowLogViewerWrapper.svelte +56 -3
  24. package/package/components/FlowLogViewerWrapper.svelte.d.ts +4 -3
  25. package/package/components/FlowLoopIterationPreview.svelte +4 -4
  26. package/package/components/FlowMetadata.svelte +3 -4
  27. package/package/components/FlowMetadata.svelte.d.ts +4 -18
  28. package/package/components/FlowPreviewContent.svelte +9 -3
  29. package/package/components/FlowPreviewContent.svelte.d.ts +1 -1
  30. package/package/components/FlowStatusViewer.svelte +62 -59
  31. package/package/components/FlowStatusViewer.svelte.d.ts +2 -2
  32. package/package/components/FlowStatusViewerInner.svelte +186 -94
  33. package/package/components/FlowStatusViewerInner.svelte.d.ts +10 -3
  34. package/package/components/FlowTimeline.svelte +110 -131
  35. package/package/components/FlowTimeline.svelte.d.ts +13 -4
  36. package/package/components/FlowTimelineBar.svelte +227 -0
  37. package/package/components/FlowTimelineBar.svelte.d.ts +24 -0
  38. package/package/components/InputTransformForm.svelte +119 -3
  39. package/package/components/InputTransformForm.svelte.d.ts +3 -0
  40. package/package/components/InputTransformSchemaForm.svelte +5 -1
  41. package/package/components/InputTransformSchemaForm.svelte.d.ts +2 -0
  42. package/package/components/InstanceSetting.svelte +17 -42
  43. package/package/components/InstanceSettings.svelte +12 -21
  44. package/package/components/JobArgs.svelte +15 -16
  45. package/package/components/JobArgs.svelte.d.ts +4 -18
  46. package/package/components/JobLoader.svelte +23 -42
  47. package/package/components/JobLoader.svelte.d.ts +2 -0
  48. package/package/components/JobStatus.svelte +1 -1
  49. package/package/components/JobStatus.svelte.d.ts +4 -18
  50. package/package/components/ModulePreviewResultViewer.svelte +1 -7
  51. package/package/components/NextcloudSetting.svelte +6 -1
  52. package/package/components/Password.svelte +7 -11
  53. package/package/components/Password.svelte.d.ts +5 -20
  54. package/package/components/PasswordArgInput.svelte +35 -15
  55. package/package/components/PasswordArgInput.svelte.d.ts +4 -18
  56. package/package/components/QueuePosition.svelte +6 -2
  57. package/package/components/RunForm.svelte +5 -14
  58. package/package/components/S3ArrayHelperButton.svelte +12 -0
  59. package/package/components/S3ArrayHelperButton.svelte.d.ts +8 -0
  60. package/package/components/ScriptEditor.svelte +5 -6
  61. package/package/components/StringTypeNarrowing.svelte +39 -24
  62. package/package/components/StringTypeNarrowing.svelte.d.ts +1 -1
  63. package/package/components/TeamSelector.svelte +83 -37
  64. package/package/components/TeamSelector.svelte.d.ts +0 -1
  65. package/package/components/apps/components/buttons/AppButton.svelte +11 -1
  66. package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte +13 -4
  67. package/package/components/apps/components/display/table/SyncColumnDefs.svelte +2 -2
  68. package/package/components/apps/components/display/table/utils.js +1 -1
  69. package/package/components/apps/components/helpers/RefreshButton.svelte +5 -1
  70. package/package/components/apps/components/helpers/RunnableComponent.svelte +0 -2
  71. package/package/components/apps/components/helpers/RunnableWrapper.svelte.d.ts +1 -0
  72. package/package/components/apps/components/layout/AppTabs.svelte +116 -71
  73. package/package/components/apps/components/layout/AppTabs.svelte.d.ts +1 -0
  74. package/package/components/apps/editor/component/ComponentInner.svelte +1 -0
  75. package/package/components/apps/editor/component/components.d.ts +16 -1
  76. package/package/components/apps/editor/component/components.js +22 -2
  77. package/package/components/apps/editor/settingsPanel/ComponentPanel.svelte +2 -0
  78. package/package/components/apps/editor/settingsPanel/GridTab.svelte +19 -1
  79. package/package/components/apps/editor/settingsPanel/GridTab.svelte.d.ts +3 -1
  80. package/package/components/apps/editor/settingsPanel/GridTabHidden.svelte +52 -0
  81. package/package/components/apps/editor/settingsPanel/GridTabHidden.svelte.d.ts +9 -0
  82. package/package/components/auditLogs/AuditLogsFilters.svelte +6 -0
  83. package/package/components/auditLogs/AuditLogsTable.svelte +17 -7
  84. package/package/components/auditLogs/AuditLogsTable.svelte.d.ts +1 -0
  85. package/package/components/common/CloseButton.svelte +2 -2
  86. package/package/components/common/CloseButton.svelte.d.ts +1 -0
  87. package/package/components/common/layout/List.svelte +3 -7
  88. package/package/components/common/layout/List.svelte.d.ts +7 -29
  89. package/package/components/common/popup/PopupV2.svelte +8 -25
  90. package/package/components/common/popup/PopupV2.svelte.d.ts +4 -2
  91. package/package/components/common/table/ScriptRow.svelte +22 -2
  92. package/package/components/copilot/FlowCopilotInputsModal.svelte +26 -23
  93. package/package/components/copilot/chat/AIChatManager.svelte.js +3 -2
  94. package/package/components/copilot/chat/ProviderModelSelector.svelte +1 -1
  95. package/package/components/copilot/chat/flow/FlowAIChat.svelte +4 -2
  96. package/package/components/copilot/chat/script/core.d.ts +4 -4
  97. package/package/components/copilot/chat/script/core.js +93 -34
  98. package/package/components/copilot/lib.d.ts +1 -0
  99. package/package/components/copilot/lib.js +6 -3
  100. package/package/components/custom_ui.d.ts +1 -0
  101. package/package/components/flows/FlowProgressBar.svelte +16 -16
  102. package/package/components/flows/FlowProgressBar.svelte.d.ts +7 -22
  103. package/package/components/flows/content/FlowInputsQuick.svelte +3 -2
  104. package/package/components/flows/content/FlowInputsQuick.svelte.d.ts +1 -0
  105. package/package/components/flows/content/FlowModuleComponent.svelte +24 -1
  106. package/package/components/flows/flowInfers.js +34 -8
  107. package/package/components/flows/flowStore.d.ts +4 -1
  108. package/package/components/flows/map/FlowJobsMenu.svelte +3 -3
  109. package/package/components/flows/map/FlowJobsMenu.svelte.d.ts +1 -1
  110. package/package/components/flows/map/InsertModuleButton.svelte +4 -14
  111. package/package/components/flows/map/InsertModuleButton.svelte.d.ts +0 -1
  112. package/package/components/flows/map/InsertModuleInner.svelte +17 -20
  113. package/package/components/flows/map/MapItem.svelte +1 -1
  114. package/package/components/flows/pickers/PickHubScriptQuick.svelte +38 -52
  115. package/package/components/flows/pickers/PickHubScriptQuick.svelte.d.ts +1 -0
  116. package/package/components/flows/pickers/WorkspaceScriptPickerQuick.svelte +27 -15
  117. package/package/components/flows/pickers/WorkspaceScriptPickerQuick.svelte.d.ts +1 -0
  118. package/package/components/flows/propPicker/OutputPicker.svelte +2 -0
  119. package/package/components/git_sync/DetectionFlow.svelte +33 -44
  120. package/package/components/git_sync/DetectionFlow.svelte.d.ts +1 -0
  121. package/package/components/git_sync/GitSyncContext.svelte.d.ts +22 -0
  122. package/package/components/git_sync/GitSyncContext.svelte.js +145 -5
  123. package/package/components/git_sync/GitSyncModeDisplay.svelte +14 -0
  124. package/package/components/git_sync/GitSyncModeDisplay.svelte.d.ts +9 -0
  125. package/package/components/git_sync/GitSyncRepositoryCard.svelte +365 -253
  126. package/package/components/git_sync/GitSyncRepositoryCard.svelte.d.ts +10 -1
  127. package/package/components/git_sync/GitSyncSection.svelte +134 -14
  128. package/package/components/git_sync/PullWorkspaceModal.svelte +24 -32
  129. package/package/components/git_sync/PushWorkspaceModal.svelte +24 -32
  130. package/package/components/graph/model.d.ts +5 -5
  131. package/package/components/graph/renderers/edges/EmptyEdge.svelte +3 -10
  132. package/package/components/graph/renderers/edges/EmptyEdge.svelte.d.ts +4 -18
  133. package/package/components/graph/renderers/nodes/AIToolNode.svelte +2 -2
  134. package/package/components/graph/renderers/nodes/NewAIToolNode.svelte +5 -10
  135. package/package/components/home/ItemsList.svelte +1 -1
  136. package/package/components/jobs/JobProgressBar.svelte +27 -21
  137. package/package/components/jobs/JobProgressBar.svelte.d.ts +9 -24
  138. package/package/components/meltComponents/MenuSingleItem.svelte +3 -8
  139. package/package/components/meltComponents/MenuSingleItem.svelte.d.ts +0 -3
  140. package/package/components/meltComponents/Popover.svelte +3 -2
  141. package/package/components/meltComponents/Popover.svelte.d.ts +1 -0
  142. package/package/components/meltComponents/Tooltip.svelte +1 -1
  143. package/package/components/progressBar/ProgressBar.svelte +39 -53
  144. package/package/components/progressBar/ProgressBar.svelte.d.ts +11 -26
  145. package/package/components/runs/JobsLoader.svelte +1 -1
  146. package/package/components/runs/NoWorkerWithTagWarning.svelte +3 -3
  147. package/package/components/runs/NoWorkerWithTagWarning.svelte.d.ts +1 -1
  148. package/package/components/schema/AddPropertyV2.svelte +7 -4
  149. package/package/components/schema/PropertyEditor.svelte.d.ts +1 -1
  150. package/package/components/select/MultiSelect.svelte +2 -2
  151. package/package/components/select/MultiSelect.svelte.d.ts +1 -0
  152. package/package/components/settings/WorkspaceUserSettings.svelte +92 -1
  153. package/package/components/sidebar/MenuLink.svelte +2 -1
  154. package/package/components/sidebar/MenuLink.svelte.d.ts +1 -0
  155. package/package/components/sidebar/SidebarContent.svelte +27 -27
  156. package/package/components/table/Cell.svelte +7 -14
  157. package/package/components/table/Cell.svelte.d.ts +13 -35
  158. package/package/components/triggers/AddTriggersButton.svelte +1 -0
  159. package/package/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte +1 -1
  160. package/package/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte.d.ts +2 -1
  161. package/package/components/triggers/gcp/GcpTriggerEditorInner.svelte +28 -5
  162. package/package/components/triggers/gcp/utils.js +1 -0
  163. package/package/components/triggers/schedules/ScheduleEditorInner.svelte +1 -0
  164. package/package/components/triggers/webhook/WebhooksConfigSection.svelte +143 -63
  165. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +22 -0
  166. package/package/components/triggers/websocket/utils.js +1 -0
  167. package/package/components/workspaceSettings/AISettings.svelte +8 -2
  168. package/package/components/workspaceSettings/AISettings.svelte.d.ts +2 -1
  169. package/package/components/workspaceSettings/ModelTokenLimits.svelte +165 -0
  170. package/package/components/workspaceSettings/ModelTokenLimits.svelte.d.ts +8 -0
  171. package/package/components/workspaceSettings/StorageSettings.svelte +123 -51
  172. package/package/gen/core/OpenAPI.js +1 -1
  173. package/package/gen/schemas.gen.d.ts +141 -16
  174. package/package/gen/schemas.gen.js +144 -16
  175. package/package/gen/services.gen.d.ts +62 -42
  176. package/package/gen/services.gen.js +131 -82
  177. package/package/gen/types.gen.d.ts +218 -144
  178. package/package/hubPaths.json +2 -1
  179. package/package/services/JobManager.js +10 -7
  180. package/package/stores.d.ts +1 -0
  181. package/package/stores.js +6 -3
  182. package/package/timelineCompute.svelte.d.ts +21 -0
  183. package/package/timelineCompute.svelte.js +113 -0
  184. package/package/utils.d.ts +15 -8
  185. package/package/utils.js +62 -12
  186. package/package/workspace_settings.d.ts +13 -8
  187. package/package/workspace_settings.js +46 -11
  188. package/package.json +2 -2
@@ -2,71 +2,117 @@
2
2
  import { RefreshCcw } from 'lucide-svelte';
3
3
  import { WorkspaceService } from '../gen';
4
4
  import Select from './select/Select.svelte';
5
- import { onMount } from 'svelte';
6
- let { disabled = false, placeholder = 'Select a team', selectedTeam = $bindable(), containerClass = 'w-64', showRefreshButton = true, teams = undefined, minWidth = '160px', onError } = $props();
5
+ import { debounce } from '../utils';
6
+ let { disabled = false, selectedTeam = $bindable(), containerClass = 'w-64', showRefreshButton = true, teams = undefined, minWidth = '160px', onError } = $props();
7
7
  let isFetching = $state(false);
8
- onMount(() => {
9
- if (!teams)
10
- loadTeams();
8
+ let searchResults = $state([]);
9
+ // Only enable search mode if no teams are provided
10
+ const searchMode = !teams;
11
+ // Determine which teams to show: provided teams or search results
12
+ // In search mode, include the selected team if it exists
13
+ let displayTeams = $derived(() => {
14
+ const baseTeams = teams || searchResults;
15
+ if (searchMode && selectedTeam && !baseTeams.find(t => t.team_id === selectedTeam?.team_id)) {
16
+ return [selectedTeam, ...baseTeams];
17
+ }
18
+ return baseTeams;
19
+ });
20
+ // Create separate filter text for search mode
21
+ let searchFilterText = $state('');
22
+ // Debounced search function
23
+ const debouncedSearch = debounce(async (query) => {
24
+ await searchTeams(query);
25
+ }, 500);
26
+ // Watch for search filter text changes (only in search mode)
27
+ $effect(() => {
28
+ if (searchMode) {
29
+ if (searchFilterText.length >= 1) {
30
+ debouncedSearch.debounced(searchFilterText);
31
+ }
32
+ else if (searchFilterText.length === 0) {
33
+ searchResults = [];
34
+ }
35
+ }
11
36
  });
12
- async function loadTeams() {
37
+ async function searchTeams(query) {
38
+ if (!query)
39
+ return;
13
40
  isFetching = true;
14
41
  try {
15
42
  const response = (await WorkspaceService.listAvailableTeamsIds({
16
- workspace: $workspaceStore
43
+ workspace: $workspaceStore,
44
+ search: query
17
45
  }));
18
- teams = response || [];
46
+ searchResults = response || [];
19
47
  isFetching = false;
20
- console.log('Teams loaded:', teams.length);
21
- return teams;
48
+ return searchResults;
22
49
  }
23
50
  catch (error) {
24
51
  isFetching = false;
25
52
  onError?.(error);
26
- console.error('Error loading teams:', error);
53
+ console.error('Error searching teams:', error);
54
+ searchResults = [];
27
55
  return [];
28
56
  }
29
57
  }
58
+ async function refreshSearch() {
59
+ if (searchMode && searchFilterText.length >= 2) {
60
+ await searchTeams(searchFilterText);
61
+ }
62
+ }
30
63
  </script>
31
64
 
32
65
  <div class={containerClass}>
33
66
  <div class="flex items-center gap-2">
34
67
  <div class="flex-grow" style="min-width: {minWidth};">
35
- <Select
36
- containerStyle={'min-width: ' + minWidth}
37
- items={teams?.map((team) => ({
38
- label: team.team_name,
39
- value: team.team_id
40
- })) ?? []}
41
- {placeholder}
42
- clearable
43
- disabled={disabled || isFetching}
44
- bind:value={
45
- () => selectedTeam?.team_id,
46
- (value) => (selectedTeam = teams?.find((team) => team.team_id === value))
47
- }
48
- />
68
+ {#if searchMode}
69
+ <Select
70
+ containerStyle={'min-width: ' + minWidth}
71
+ items={searchFilterText.length >= 1 || (searchFilterText.length === 0 && selectedTeam) ? displayTeams().map((team) => ({
72
+ label: team.team_name,
73
+ value: team.team_id
74
+ })) : []}
75
+ placeholder={isFetching ? "Searching..." : "Search teams..."}
76
+ clearable
77
+ disabled={disabled || isFetching}
78
+ bind:filterText={searchFilterText}
79
+ bind:value={
80
+ () => selectedTeam?.team_id,
81
+ (value) => {
82
+ selectedTeam = value ? displayTeams().find((team) => team.team_id === value) : undefined
83
+ }
84
+ }
85
+ />
86
+ {:else}
87
+ <Select
88
+ containerStyle={'min-width: ' + minWidth}
89
+ items={displayTeams().map((team) => ({
90
+ label: team.team_name,
91
+ value: team.team_id
92
+ }))}
93
+ placeholder="Select a team"
94
+ clearable
95
+ disabled={disabled || isFetching}
96
+ bind:value={
97
+ () => selectedTeam?.team_id,
98
+ (value) => {
99
+ selectedTeam = value ? displayTeams().find((team) => team.team_id === value) : undefined
100
+ }
101
+ }
102
+ />
103
+ {/if}
49
104
  </div>
50
105
 
51
106
  {#if showRefreshButton}
52
107
  <button
53
- onclick={loadTeams}
54
- disabled={isFetching || disabled}
108
+ onclick={refreshSearch}
109
+ disabled={isFetching || disabled || (searchMode && searchFilterText.length < 2)}
55
110
  class="flex items-center justify-center p-1.5 rounded hover:bg-surface-hover focus:bg-surface-hover disabled:opacity-50"
56
- title="Refresh teams from Microsoft"
111
+ title={searchMode ? "Refresh search results" : "Refresh teams from Microsoft"}
57
112
  >
58
113
  <RefreshCcw size={16} class={isFetching ? 'animate-spin' : ''} />
59
114
  </button>
60
115
  {/if}
61
116
  </div>
62
117
 
63
- {#if isFetching || ((!teams || teams.length === 0) && !isFetching)}
64
- <div class="text-xs text-tertiary mt-1">
65
- {#if isFetching}
66
- Fetching teams from Microsoft...
67
- {:else}
68
- No available teams found
69
- {/if}
70
- </div>
71
- {/if}
72
118
  </div>
@@ -4,7 +4,6 @@ interface TeamItem {
4
4
  }
5
5
  interface Props {
6
6
  disabled?: boolean;
7
- placeholder?: string;
8
7
  selectedTeam?: TeamItem | undefined;
9
8
  containerClass?: string;
10
9
  showRefreshButton?: boolean;
@@ -70,6 +70,13 @@ async function handleClick(event) {
70
70
  event?.stopPropagation();
71
71
  event?.preventDefault();
72
72
  $selectedComponent = [id];
73
+ // Show brief feedback for background mode
74
+ if (resolvedConfig.runInBackground) {
75
+ backgroundClickFeedback = true;
76
+ setTimeout(() => {
77
+ backgroundClickFeedback = false;
78
+ }, 300);
79
+ }
73
80
  const action = async () => {
74
81
  const inputOutput = { result: outputs.result.peak(), loading: true };
75
82
  if (rowContext && rowInputs) {
@@ -96,6 +103,7 @@ async function handleClick(event) {
96
103
  }
97
104
  }
98
105
  let loading = $state(false);
106
+ let backgroundClickFeedback = $state(false);
99
107
  let css = $state(initCss($app.css?.buttoncomponent, customCss));
100
108
  $effect(() => {
101
109
  errorHandledByComponent = resolvedConfig?.onError?.selected !== 'errorOverlay';
@@ -150,6 +158,7 @@ let errorsMessage = $derived(Object.values(errors)
150
158
  {render}
151
159
  {outputs}
152
160
  {extraKey}
161
+ allowConcurentRequests={resolvedConfig.runInBackground}
153
162
  onSuccess={(r) => {
154
163
  let inputOutput = { result: r, loading: false }
155
164
  if (rowContext && rowInputs) {
@@ -196,7 +205,8 @@ let errorsMessage = $derived(Object.values(errors)
196
205
  on:click={handleClick}
197
206
  size={resolvedConfig.size}
198
207
  color={resolvedConfig.color}
199
- {loading}
208
+ title={resolvedConfig.tooltip && String(resolvedConfig.tooltip).length > 0 ? String(resolvedConfig.tooltip) : undefined}
209
+ loading={resolvedConfig.runInBackground ? backgroundClickFeedback : loading}
200
210
  >
201
211
  {#if resolvedConfig.beforeIcon}
202
212
  {#key resolvedConfig.beforeIcon}
@@ -13,6 +13,7 @@ import { getPrimaryKeys } from '../dbtable/utils';
13
13
  import InitializeComponent from '../../helpers/InitializeComponent.svelte';
14
14
  import DebouncedInput from '../../helpers/DebouncedInput.svelte';
15
15
  import RunnableComponent from '../../helpers/RunnableComponent.svelte';
16
+ import { CancelablePromise } from '../../../../../gen';
16
17
  let { id, componentInput, configuration, initializing = $bindable(undefined), render, customCss = undefined, actions = undefined } = $props();
17
18
  let runnableComponent = $state(undefined);
18
19
  function clear() {
@@ -113,6 +114,7 @@ function updateSearchInOutputs() {
113
114
  $effect(() => {
114
115
  searchValue !== undefined && untrack(() => updateSearchInOutputs());
115
116
  });
117
+ let ignoreFirst = true;
116
118
  </script>
117
119
 
118
120
  {#each Object.keys(components['aggridinfinitecomponent'].initialData.configuration) as key (key)}
@@ -144,10 +146,17 @@ $effect(() => {
144
146
  bind:result
145
147
  bind:loading
146
148
  bind:runnableComponent
147
- on:recompute={() => {
148
- console.log('recompute')
149
- clear()
150
- }}
149
+ preventDefaultRefresh
150
+ overrideCallback={() =>
151
+ new CancelablePromise(async (resolve) => {
152
+ if (ignoreFirst) {
153
+ ignoreFirst = false
154
+ resolve()
155
+ return
156
+ }
157
+ clear()
158
+ resolve()
159
+ })}
151
160
  {render}
152
161
  autoRefresh={true}
153
162
  allowConcurentRequests
@@ -88,10 +88,10 @@ $effect(() => {
88
88
  });
89
89
  }
90
90
  });
91
+ let keys = $derived(Object.keys(result[0] ?? []).filter((x) => x !== '__index'));
91
92
  async function syncColumns() {
92
93
  const gridItem = findGridItem($app, id);
93
94
  if (gridItem && result) {
94
- const keys = Object.keys(result[0] ?? {}) ?? [];
95
95
  const conf = gridItem.data.configuration.columnDefs;
96
96
  const newColumns = keys.map((key) => ({
97
97
  field: key,
@@ -136,7 +136,7 @@ async function updateConfiguration() {
136
136
  <div class="flex flex-col items-start gap-2">
137
137
  <div class="text-xs"> No columns definition found. Columns found in data: </div>
138
138
  <div class="text-sm flex flex-row gap-2">
139
- {#each Object.keys(result[0] ?? []) as key}
139
+ {#each keys as key}
140
140
  <Badge small color="dark-gray">{key}</Badge>
141
141
  {/each}
142
142
  </div>
@@ -182,7 +182,7 @@ export function validateColumnDefs(columnDefs) {
182
182
  colDef.hideInsert = true;
183
183
  }
184
184
  // Check if 'field' property exists and is a non-empty string
185
- if (noField && !(colDef.children && Array.isArray(colDef.children))) {
185
+ if (noField && !(colDef.children && Array.isArray(colDef.children)) && !colDef.cellRenderer) {
186
186
  isValid = false;
187
187
  errors.push(`Column at index ${index} is missing a valid 'field' property nor having any children.`);
188
188
  }
@@ -23,13 +23,17 @@ let cancelCallbacks = $state(undefined);
23
23
  color="light"
24
24
  size="xs2"
25
25
  btnClasses={twMerge(loading ? ' bg-blue-100 dark:bg-blue-400' : '', 'transition-all')}
26
- on:click={() => {
26
+ on:click={(e) => {
27
27
  if (buttonHover && loading) {
28
28
  cancelCallbacks?.forEach((cb) => cb.cancel())
29
29
  } else {
30
30
  cancelCallbacks = $runnableComponents[id]?.cb?.map((cb) => cb())
31
31
  }
32
32
  }}
33
+ on:pointerdown={(e) => {
34
+ e.preventDefault()
35
+ e.stopPropagation()
36
+ }}
33
37
  iconOnly
34
38
  />
35
39
  {#snippet text()}
@@ -53,8 +53,6 @@ function refreshOnStaticChange() {
53
53
  refreshIfAutoRefresh('static changed');
54
54
  }
55
55
  }
56
- // $: sendUserToast('args' + JSON.stringify(runnableInputValues) + Boolean(extraQueryParams) || args)
57
- // $: console.log(runnableInputValues)
58
56
  let firstRefresh = true;
59
57
  function genCallbacks({ onDone, onCancel, onError }) {
60
58
  const callbacks = {
@@ -75,6 +75,7 @@ interface Props {
75
75
  onSuccess?: (result: any) => void;
76
76
  children?: import('svelte').Snippet;
77
77
  nonRenderedPlaceholder?: import('svelte').Snippet;
78
+ preventDefaultRefresh?: boolean;
78
79
  }
79
80
  interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
80
81
  new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
@@ -11,7 +11,7 @@ import InitializeComponent from '../helpers/InitializeComponent.svelte';
11
11
  import { twMerge } from 'tailwind-merge';
12
12
  import ResolveStyle from '../helpers/ResolveStyle.svelte';
13
13
  import { deepEqual } from 'fast-equals';
14
- let { id, configuration, componentContainerHeight, tabs, customCss = undefined, render, disabledTabs, onTabChange = undefined } = $props();
14
+ let { id, configuration, componentContainerHeight, tabs, customCss = undefined, render, disabledTabs, hiddenTabs, onTabChange = undefined } = $props();
15
15
  let resolvedConfig = $state(initConfig(components['tabscomponent'].initialData.configuration, configuration));
16
16
  let everRender = $state(render);
17
17
  $effect.pre(() => {
@@ -51,18 +51,28 @@ $componentControl[id] = {
51
51
  }
52
52
  },
53
53
  left: () => {
54
- const index = tabs.indexOf(selected);
55
- if (index > 0) {
56
- selected = tabs[index - 1];
57
- return true;
54
+ const currentIndex = tabs.indexOf(selected);
55
+ if (currentIndex > 0) {
56
+ // Find the next visible tab to the left
57
+ for (let i = currentIndex - 1; i >= 0; i--) {
58
+ if (!resolvedHiddenTabs[i]) {
59
+ selected = tabs[i];
60
+ return true;
61
+ }
62
+ }
58
63
  }
59
64
  return false;
60
65
  },
61
66
  right: () => {
62
- const index = tabs.indexOf(selected);
63
- if (index < tabs.length - 1) {
64
- selected = tabs[index + 1];
65
- return true;
67
+ const currentIndex = tabs.indexOf(selected);
68
+ if (currentIndex < tabs.length - 1) {
69
+ // Find the next visible tab to the right
70
+ for (let i = currentIndex + 1; i < tabs.length; i++) {
71
+ if (!resolvedHiddenTabs[i]) {
72
+ selected = tabs[i];
73
+ return true;
74
+ }
75
+ }
66
76
  }
67
77
  return false;
68
78
  },
@@ -88,6 +98,26 @@ $effect.pre(() => {
88
98
  selected != undefined && untrack(() => handleTabSelection());
89
99
  });
90
100
  let resolvedDisabledTabs = $state([]);
101
+ let resolvedHiddenTabs = $state([]);
102
+ // Filter visible tabs based on hiddenTabs configuration
103
+ let visibleTabsIndices = $derived((tabs ?? []).map((_, index) => index).filter((index) => !resolvedHiddenTabs[index]));
104
+ // Auto-select first visible tab if current selection is hidden or invalid
105
+ $effect(() => {
106
+ if (visibleTabsIndices.length === 0) {
107
+ // Handle case where all tabs are hidden
108
+ selected = '';
109
+ selectedIndex = -1;
110
+ return;
111
+ }
112
+ const currentIndex = tabs?.indexOf(selected) ?? -1;
113
+ if (currentIndex === -1 || resolvedHiddenTabs[currentIndex]) {
114
+ const firstVisibleTab = tabs[visibleTabsIndices[0]];
115
+ if (selected !== firstVisibleTab) {
116
+ // Current selection is hidden or invalid, select first visible tab
117
+ selected = firstVisibleTab;
118
+ }
119
+ }
120
+ });
91
121
  </script>
92
122
 
93
123
  <InputValue key="kind" {id} input={configuration.tabsKind} bind:value={resolvedConfig.tabsKind} />
@@ -113,6 +143,15 @@ let resolvedDisabledTabs = $state([]);
113
143
  />
114
144
  {/each}
115
145
 
146
+ {#each hiddenTabs ?? [] as hideTab, index}
147
+ <InputValue
148
+ key="tabHidden {index}"
149
+ {id}
150
+ input={hideTab}
151
+ bind:value={resolvedHiddenTabs[index]}
152
+ />
153
+ {/each}
154
+
116
155
  {#if everRender}
117
156
  <div class={resolvedConfig.tabsKind == 'sidebar' ? 'flex gap-4 w-full h-full' : 'w-full'}>
118
157
  {#if !resolvedConfig.tabsKind || resolvedConfig.tabsKind == 'tabs' || (resolvedConfig.tabsKind == 'invisibleOnView' && $mode == 'dnd')}
@@ -123,16 +162,18 @@ let resolvedDisabledTabs = $state([]);
123
162
  style={css?.tabRow?.style}
124
163
  >
125
164
  {#each tabs ?? [] as res, index}
126
- <Tab
127
- value={res}
128
- class={twMerge(css?.allTabs?.class, 'wm-tabs-alltabs')}
129
- style={css?.allTabs?.style}
130
- selectedClass={twMerge(css?.selectedTab?.class, 'wm-tabs-selectedTab')}
131
- selectedStyle={css?.selectedTab?.style}
132
- disabled={resolvedDisabledTabs[index]}
133
- >
134
- <span class="font-semibold">{res}</span>
135
- </Tab>
165
+ {#if !resolvedHiddenTabs[index]}
166
+ <Tab
167
+ value={res}
168
+ class={twMerge(css?.allTabs?.class, 'wm-tabs-alltabs')}
169
+ style={css?.allTabs?.style}
170
+ selectedClass={twMerge(css?.selectedTab?.class, 'wm-tabs-selectedTab')}
171
+ selectedStyle={css?.selectedTab?.style}
172
+ disabled={resolvedDisabledTabs[index]}
173
+ >
174
+ <span class="font-semibold">{res}</span>
175
+ </Tab>
176
+ {/if}
136
177
  {/each}
137
178
  </Tabs>
138
179
  </div>
@@ -146,78 +187,82 @@ let resolvedDisabledTabs = $state([]);
146
187
  style={css?.tabRow?.style}
147
188
  >
148
189
  {#each tabs ?? [] as res, index}
149
- <button
150
- onpointerdown={stopPropagation(bubble('pointerdown'))}
151
- onclick={() => !resolvedDisabledTabs[index] && (selected = res)}
152
- disabled={resolvedDisabledTabs[index]}
153
- class={twMerge(
154
- 'rounded-sm !truncate text-sm hover:text-primary px-1 py-2',
155
- css?.allTabs?.class,
156
- 'wm-tabs-alltabs',
157
- selected == res
158
- ? twMerge(
159
- 'border-r border-primary border-l bg-surface text-primary',
160
- css?.selectedTab?.class,
161
- 'wm-tabs-selectedTab'
162
- )
163
- : '',
164
- resolvedDisabledTabs[index]
165
- ? 'opacity-50 cursor-not-allowed hover:text-secondary'
166
- : ''
167
- )}
168
- style={selected == res
169
- ? [css?.allTabs?.style, css?.selectedTab?.style].filter(Boolean).join(';')
170
- : css?.allTabs?.style}
171
- >
172
- {res}
173
- </button>
174
- {/each}
175
- </div>
176
- {/if}
177
- {#if resolvedConfig.tabsKind == 'accordion'}
178
- <div class="flex flex-col w-full">
179
- {#each tabs ?? [] as res, index}
180
- <div class="border-b">
190
+ {#if !resolvedHiddenTabs[index]}
181
191
  <button
182
192
  onpointerdown={stopPropagation(bubble('pointerdown'))}
183
193
  onclick={() => !resolvedDisabledTabs[index] && (selected = res)}
184
194
  disabled={resolvedDisabledTabs[index]}
185
195
  class={twMerge(
186
- 'w-full text-left bg-surface !truncate text-sm hover:text-primary px-1 py-2',
196
+ 'rounded-sm !truncate text-sm hover:text-primary px-1 py-2',
187
197
  css?.allTabs?.class,
188
198
  'wm-tabs-alltabs',
189
199
  selected == res
190
200
  ? twMerge(
191
- 'bg-surface text-primary ',
201
+ 'border-r border-primary border-l bg-surface text-primary',
192
202
  css?.selectedTab?.class,
193
203
  'wm-tabs-selectedTab'
194
204
  )
195
- : 'text-secondary',
205
+ : '',
196
206
  resolvedDisabledTabs[index]
197
207
  ? 'opacity-50 cursor-not-allowed hover:text-secondary'
198
208
  : ''
199
209
  )}
210
+ style={selected == res
211
+ ? [css?.allTabs?.style, css?.selectedTab?.style].filter(Boolean).join(';')
212
+ : css?.allTabs?.style}
200
213
  >
201
- <span class="mr-2 w-8 font-mono">{selected == res ? '-' : '+'}</span>
202
214
  {res}
203
215
  </button>
204
- <div class={selected == res ? 'border-t' : ''}>
205
- <SubGridEditor
206
- {id}
207
- visible={render && index === selectedIndex}
208
- subGridId={`${id}-${index}`}
209
- class={twMerge(css?.container?.class, 'wm-tabs-container')}
210
- style={css?.container?.style}
211
- containerHeight={componentContainerHeight - (titleBarHeight * tabs.length + 40)}
212
- onFocus={() => {
213
- if (!$connectingInput.opened) {
214
- $selectedComponent = [id]
215
- handleTabSelection()
216
- }
217
- }}
218
- />
216
+ {/if}
217
+ {/each}
218
+ </div>
219
+ {/if}
220
+ {#if resolvedConfig.tabsKind == 'accordion'}
221
+ <div class="flex flex-col w-full">
222
+ {#each tabs ?? [] as res, index}
223
+ {#if !resolvedHiddenTabs[index]}
224
+ <div class="border-b">
225
+ <button
226
+ onpointerdown={stopPropagation(bubble('pointerdown'))}
227
+ onclick={() => !resolvedDisabledTabs[index] && (selected = res)}
228
+ disabled={resolvedDisabledTabs[index]}
229
+ class={twMerge(
230
+ 'w-full text-left bg-surface !truncate text-sm hover:text-primary px-1 py-2',
231
+ css?.allTabs?.class,
232
+ 'wm-tabs-alltabs',
233
+ selected == res
234
+ ? twMerge(
235
+ 'bg-surface text-primary ',
236
+ css?.selectedTab?.class,
237
+ 'wm-tabs-selectedTab'
238
+ )
239
+ : 'text-secondary',
240
+ resolvedDisabledTabs[index]
241
+ ? 'opacity-50 cursor-not-allowed hover:text-secondary'
242
+ : ''
243
+ )}
244
+ >
245
+ <span class="mr-2 w-8 font-mono">{selected == res ? '-' : '+'}</span>
246
+ {res}
247
+ </button>
248
+ <div class={selected == res ? 'border-t' : ''}>
249
+ <SubGridEditor
250
+ {id}
251
+ visible={render && index === selectedIndex}
252
+ subGridId={`${id}-${index}`}
253
+ class={twMerge(css?.container?.class, 'wm-tabs-container')}
254
+ style={css?.container?.style}
255
+ containerHeight={componentContainerHeight - (titleBarHeight * tabs.length + 40)}
256
+ onFocus={() => {
257
+ if (!$connectingInput.opened) {
258
+ $selectedComponent = [id]
259
+ handleTabSelection()
260
+ }
261
+ }}
262
+ />
263
+ </div>
219
264
  </div>
220
- </div>
265
+ {/if}
221
266
  {/each}
222
267
  </div>
223
268
  {:else}
@@ -7,6 +7,7 @@ interface Props {
7
7
  customCss?: ComponentCustomCSS<'tabscomponent'> | undefined;
8
8
  render: boolean;
9
9
  disabledTabs: RichConfiguration[];
10
+ hiddenTabs: RichConfiguration[];
10
11
  onTabChange?: string[] | undefined;
11
12
  }
12
13
  declare const AppTabs: import("svelte").Component<Props, {}, "">;
@@ -833,6 +833,7 @@ const chunk9Components = new Set(['verticalsplitpanescomponent']);
833
833
  id={component.id}
834
834
  tabs={component.tabs}
835
835
  disabledTabs={component.disabledTabs}
836
+ hiddenTabs={component.hiddenTabs}
836
837
  onTabChange={component.onTabChange}
837
838
  customCss={component.customCss}
838
839
  {componentContainerHeight}
@@ -150,6 +150,7 @@ export type FileInputComponent = BaseComponent<'fileinputcomponent'> & {
150
150
  export type TabsComponent = BaseComponent<'tabscomponent'> & {
151
151
  tabs: string[];
152
152
  disabledTabs: RichConfiguration[];
153
+ hiddenTabs: RichConfiguration[];
153
154
  onTabChange?: string[];
154
155
  };
155
156
  export type ListComponent = BaseComponent<'listcomponent'>;
@@ -706,11 +707,23 @@ export declare const components: {
706
707
  readonly value: undefined;
707
708
  readonly fieldType: "icon-select";
708
709
  };
710
+ readonly tooltip: {
711
+ readonly type: "static";
712
+ readonly value: "";
713
+ readonly fieldType: "text";
714
+ readonly tooltip: "Tooltip text to show on hover";
715
+ };
709
716
  readonly triggerOnAppLoad: {
710
717
  readonly type: "static";
711
718
  readonly value: false;
712
719
  readonly fieldType: "boolean";
713
720
  };
721
+ readonly runInBackground: {
722
+ readonly type: "static";
723
+ readonly value: false;
724
+ readonly fieldType: "boolean";
725
+ readonly tooltip: "Run the job in the background without blocking the button. Multiple clicks will trigger multiple jobs.";
726
+ };
714
727
  readonly onSuccess: {
715
728
  readonly type: "oneOf";
716
729
  readonly tooltip: "Action to perform on success";
@@ -3276,6 +3289,8 @@ export declare const components: {
3276
3289
  readonly componentInput: undefined;
3277
3290
  readonly numberOfSubgrids: 2;
3278
3291
  readonly tabs: string[];
3292
+ readonly disabledTabs: RichConfiguration[];
3293
+ readonly hiddenTabs: RichConfiguration[];
3279
3294
  };
3280
3295
  };
3281
3296
  readonly steppercomponent: {
@@ -3857,7 +3872,7 @@ export declare const components: {
3857
3872
  readonly type: "static";
3858
3873
  readonly fieldType: "object";
3859
3874
  readonly value: {};
3860
- readonly tooltip: "This enables setting form enum values dynamically using an object: keys are field names, and values are arrays of strings.";
3875
+ readonly tooltip: "This enables setting form enum values dynamically using an object: keys are field names, and values are arrays of strings or { \"label\": \"myLabel\", \"value\": \"myValue\" }.";
3861
3876
  };
3862
3877
  readonly displayType: {
3863
3878
  readonly fieldType: "boolean";