windmill-components 1.531.1 → 1.537.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/package/components/ArgInput.svelte +69 -19
  2. package/package/components/Auth0Setting.svelte +8 -3
  3. package/package/components/Dev.svelte +5 -4
  4. package/package/components/DiffDrawer.svelte +2 -2
  5. package/package/components/DiffEditor.svelte +34 -37
  6. package/package/components/DiffEditor.svelte.d.ts +23 -39
  7. package/package/components/EditableSchemaForm.svelte +67 -67
  8. package/package/components/EditableSchemaForm.svelte.d.ts +3 -3
  9. package/package/components/Editor.svelte +32 -11
  10. package/package/components/Editor.svelte.d.ts +6 -0
  11. package/package/components/EditorBar.svelte +2 -2
  12. package/package/components/EditorBar.svelte.d.ts +1 -0
  13. package/package/components/FieldHeader.svelte +1 -1
  14. package/package/components/FlowBuilder.svelte +7 -4
  15. package/package/components/FlowPreviewContent.svelte +3 -3
  16. package/package/components/FlowStatusViewer.svelte +28 -0
  17. package/package/components/FlowStatusViewerInner.svelte +72 -20
  18. package/package/components/FlowStatusViewerInner.svelte.d.ts +7 -0
  19. package/package/components/ModulePreview.svelte +2 -1
  20. package/package/components/ModulePreview.svelte.d.ts +1 -0
  21. package/package/components/ModulePreviewForm.svelte +72 -65
  22. package/package/components/ModulePreviewResultViewer.svelte +13 -18
  23. package/package/components/ModuleTest.svelte +10 -6
  24. package/package/components/ModuleTest.svelte.d.ts +1 -0
  25. package/package/components/OktaSetting.svelte +8 -3
  26. package/package/components/Portal.svelte +11 -7
  27. package/package/components/Portal.svelte.d.ts +19 -39
  28. package/package/components/ResourceEditor.svelte +4 -0
  29. package/package/components/RunForm.svelte +2 -2
  30. package/package/components/RunForm.svelte.d.ts +1 -1
  31. package/package/components/RunFormAdvancedPopup.svelte +13 -1
  32. package/package/components/SchemaForm.svelte +1 -2
  33. package/package/components/ScriptBuilder.svelte +1 -1
  34. package/package/components/ScriptEditor.svelte +22 -7
  35. package/package/components/SimpleEditor.svelte +0 -1
  36. package/package/components/StringTypeNarrowing.svelte.d.ts +1 -1
  37. package/package/components/apps/components/layout/AppModal.svelte +2 -2
  38. package/package/components/apps/editor/component/ComponentNavigation.svelte +3 -2
  39. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +1 -1
  40. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptRunnableByPath.svelte +0 -1
  41. package/package/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte +3 -1
  42. package/package/components/apps/editor/settingsPanel/GridCondition.svelte +3 -1
  43. package/package/components/apps/editor/settingsPanel/GridNavbar.svelte +3 -1
  44. package/package/components/apps/editor/settingsPanel/GridTab.svelte +3 -1
  45. package/package/components/apps/editor/settingsPanel/OneOfInputSpecsEditor.svelte +55 -53
  46. package/package/components/apps/editor/settingsPanel/TableActions.svelte +3 -1
  47. package/package/components/common/button/model.d.ts +1 -1
  48. package/package/components/common/drawer/Disposable.svelte +51 -30
  49. package/package/components/common/drawer/Disposable.svelte.d.ts +12 -44
  50. package/package/components/common/drawer/Drawer.svelte +15 -11
  51. package/package/components/copilot/FlowInlineScriptAIButton.svelte +4 -2
  52. package/package/components/copilot/FlowInlineScriptAIButton.svelte.d.ts +4 -1
  53. package/package/components/copilot/MetadataGen.svelte +14 -3
  54. package/package/components/copilot/autocomplete/Autocompletor.js +0 -2
  55. package/package/components/copilot/chat/AIChat.svelte +2 -4
  56. package/package/components/copilot/chat/AIChatInput.svelte +3 -3
  57. package/package/components/copilot/chat/AIChatManager.svelte.js +24 -12
  58. package/package/components/copilot/chat/AvailableContextList.svelte +243 -26
  59. package/package/components/copilot/chat/AvailableContextList.svelte.d.ts +2 -1
  60. package/package/components/copilot/chat/ContextElementBadge.svelte +31 -15
  61. package/package/components/copilot/chat/ContextElementBadge.svelte.d.ts +5 -20
  62. package/package/components/copilot/chat/ContextManager.svelte.d.ts +15 -2
  63. package/package/components/copilot/chat/ContextManager.svelte.js +134 -24
  64. package/package/components/copilot/chat/ContextTextarea.svelte +22 -49
  65. package/package/components/copilot/chat/ToolContentDisplay.svelte +10 -1
  66. package/package/components/copilot/chat/ToolExecutionDisplay.svelte +3 -3
  67. package/package/components/copilot/chat/context.d.ts +19 -1
  68. package/package/components/copilot/chat/context.js +1 -0
  69. package/package/components/copilot/chat/flow/FlowAIChat.svelte +109 -7
  70. package/package/components/copilot/chat/flow/core.d.ts +13 -1
  71. package/package/components/copilot/chat/flow/core.js +171 -19
  72. package/package/components/copilot/chat/flow/uiIntents.d.ts +8 -0
  73. package/package/components/copilot/chat/flow/uiIntents.js +5 -0
  74. package/package/components/copilot/chat/flow/useUiIntent.d.ts +5 -0
  75. package/package/components/copilot/chat/flow/useUiIntent.js +12 -0
  76. package/package/components/copilot/chat/monaco-adapter.d.ts +22 -4
  77. package/package/components/copilot/chat/monaco-adapter.js +55 -16
  78. package/package/components/copilot/chat/script/core.d.ts +2 -2
  79. package/package/components/copilot/chat/script/core.js +54 -124
  80. package/package/components/copilot/chat/shared.d.ts +14 -2
  81. package/package/components/copilot/chat/shared.js +170 -7
  82. package/package/components/copilot/lib.js +12 -7
  83. package/package/components/copilot/shared.d.ts +1 -1
  84. package/package/components/copilot/shared.js +16 -10
  85. package/package/components/flows/FlowEditor.svelte +15 -1
  86. package/package/components/flows/FlowEditor.svelte.d.ts +1 -0
  87. package/package/components/flows/FlowModuleIcon.svelte +39 -0
  88. package/package/components/flows/FlowModuleIcon.svelte.d.ts +10 -0
  89. package/package/components/flows/common/FlowCardHeader.svelte +4 -1
  90. package/package/components/flows/content/FlowBranchesAllWrapper.svelte +6 -0
  91. package/package/components/flows/content/FlowBranchesOneWrapper.svelte +6 -0
  92. package/package/components/flows/content/FlowEditorPanel.svelte +2 -1
  93. package/package/components/flows/content/FlowEditorPanel.svelte.d.ts +1 -0
  94. package/package/components/flows/content/FlowInput.svelte +31 -34
  95. package/package/components/flows/content/FlowInput.svelte.d.ts +1 -0
  96. package/package/components/flows/content/FlowLoop.svelte +7 -0
  97. package/package/components/flows/content/FlowModuleComponent.svelte +39 -44
  98. package/package/components/flows/content/FlowModuleScript.svelte +1 -1
  99. package/package/components/flows/content/FlowModuleSuspend.svelte +16 -18
  100. package/package/components/flows/content/FlowWhileLoop.svelte +6 -0
  101. package/package/components/flows/content/ScriptEditorDrawer.svelte +9 -11
  102. package/package/components/flows/dfs.d.ts +1 -1
  103. package/package/components/flows/dfs.js +6 -6
  104. package/package/components/flows/flowInfers.js +7 -7
  105. package/package/components/flows/flowStateUtils.svelte.js +1 -2
  106. package/package/components/flows/map/FlowModuleSchemaItem.svelte +12 -26
  107. package/package/components/flows/map/MapItem.svelte +12 -39
  108. package/package/components/flows/map/VirtualItem.svelte +1 -1
  109. package/package/components/flows/pickers/TopLevelNode.svelte +1 -1
  110. package/package/components/flows/propPicker/InputPickerInner.svelte +5 -5
  111. package/package/components/flows/propPicker/OutputPickerInner.svelte +143 -118
  112. package/package/components/flows/propPicker/OutputPickerInner.svelte.d.ts +7 -16
  113. package/package/components/flows/{testSteps.svelte.d.ts → stepsInputArgs.svelte.d.ts} +2 -1
  114. package/package/components/flows/{testSteps.svelte.js → stepsInputArgs.svelte.js} +15 -3
  115. package/package/components/flows/types.d.ts +16 -3
  116. package/package/components/flows/utils.js +3 -0
  117. package/package/components/graph/FlowGraphV2.svelte +1 -1
  118. package/package/components/graph/renderers/nodes/AIToolNode.svelte +4 -4
  119. package/package/components/graph/renderers/nodes/NewAIToolNode.svelte +71 -54
  120. package/package/components/propertyPicker/ObjectViewer.svelte +11 -3
  121. package/package/components/raw_apps/RawAppInlineScriptEditor.svelte +1 -1
  122. package/package/components/schema/AddPropertyV2.svelte +2 -7
  123. package/package/components/schema/AddPropertyV2.svelte.d.ts +3 -20
  124. package/package/components/schema/EditableSchemaDrawer.svelte +109 -115
  125. package/package/components/schema/EditableSchemaDrawer.svelte.d.ts +2 -1
  126. package/package/components/schema/EditableSchemaSdkWrapper.svelte +16 -3
  127. package/package/components/schema/EditableSchemaSdkWrapper.svelte.d.ts +4 -1
  128. package/package/components/schema/EditableSchemaWrapper.svelte +3 -10
  129. package/package/components/schema/FlowPropertyEditor.svelte +83 -57
  130. package/package/components/schema/FlowPropertyEditor.svelte.d.ts +1 -1
  131. package/package/components/schema/PropertyEditor.svelte.d.ts +1 -1
  132. package/package/components/schema/SchemaFormDND.svelte +11 -10
  133. package/package/components/schema/SchemaFormDND.svelte.d.ts +3 -2
  134. package/package/components/schema/editable_schema_wrapper.d.ts +0 -3
  135. package/package/components/schema/jsonSchemaResource.svelte.d.ts +2 -0
  136. package/package/components/schema/jsonSchemaResource.svelte.js +40 -0
  137. package/package/components/settings/PremiumInfo.svelte +7 -2
  138. package/package/components/triggers/CaptureWrapper.svelte +2 -13
  139. package/package/components/triggers/CaptureWrapper.svelte.d.ts +1 -1
  140. package/package/components/triggers/TriggersWrapper.svelte +1 -0
  141. package/package/components/triggers/http/RouteEditorInner.svelte +1 -1
  142. package/package/components/triggers/nats/NatsTriggerEditorInner.svelte +23 -20
  143. package/package/components/triggers/nats/NatsTriggersConfigSection.svelte +15 -27
  144. package/package/components/triggers/nats/NatsTriggersConfigSection.svelte.d.ts +7 -5
  145. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +16 -16
  146. package/package/hubPaths.json +3 -1
  147. package/package/script_helpers.d.ts +2 -2
  148. package/package/script_helpers.js +2 -0
  149. package/package/stores.d.ts +1 -0
  150. package/package/stores.js +8 -1
  151. package/package/utils.d.ts +1 -1
  152. package/package.json +14 -14
  153. package/package/components/ModulePreviewResultViewer.svelte.d.ts +0 -28
@@ -1,40 +1,257 @@
1
- <script lang="ts">import { ContextIconMap } from './context';
2
- const { availableContext, selectedContext, onSelect, showAllAvailable = false, stringSearch = '', selectedIndex = 0 } = $props();
3
- // Define priority map for context types
4
- const typePriority = {
5
- code: 1,
6
- diff: 2,
7
- default: 3
8
- };
9
- const actualAvailableContext = $derived(availableContext
10
- .filter((c) => (showAllAvailable ||
11
- !selectedContext.some((sc) => sc.type === c.type && sc.title === c.title)) &&
12
- (!stringSearch || c.title.toLowerCase().includes(stringSearch.toLowerCase())))
13
- .sort((a, b) => {
14
- const priorityA = typePriority[a.type] || typePriority.default;
15
- const priorityB = typePriority[b.type] || typePriority.default;
16
- return priorityA - priorityB;
1
+ <script lang="ts">import FlowModuleIcon from '../../flows/FlowModuleIcon.svelte';
2
+ import BarsStaggered from '../../icons/BarsStaggered.svelte';
3
+ import { ContextIconMap } from './context';
4
+ import { ArrowLeft, Diff, Database, ChevronRight } from 'lucide-svelte';
5
+ const { availableContext, selectedContext, onSelect, setShowing, showAllAvailable = false, stringSearch = '', onViewChange } = $props();
6
+ // Current view state: 'categories' or specific category type
7
+ let currentView = $state('categories');
8
+ // Selected index for keyboard navigation
9
+ let itemSelectedIndex = $state(0);
10
+ let categorySelectedIndex = $state(0);
11
+ // Category definitions
12
+ const categories = [
13
+ { id: 'diffs', label: 'Diffs', icon: Diff },
14
+ { id: 'modules', label: 'Modules', icon: BarsStaggered },
15
+ { id: 'databases', label: 'Databases', icon: Database }
16
+ ];
17
+ const filteredAvailableContext = $derived(availableContext.filter((context) => {
18
+ const filtered = (showAllAvailable ||
19
+ !selectedContext.some((sc) => sc.type === context.type && sc.title === context.title)) &&
20
+ (!stringSearch || context.title.toLowerCase().includes(stringSearch.toLowerCase()));
21
+ return filtered;
17
22
  }));
23
+ // Group context by category
24
+ const contextByCategory = $derived.by(() => {
25
+ const grouped = {
26
+ diffs: [],
27
+ modules: [],
28
+ databases: []
29
+ };
30
+ filteredAvailableContext.forEach((context) => {
31
+ if (context.type === 'diff')
32
+ grouped.diffs.push(context);
33
+ else if (context.type === 'flow_module')
34
+ grouped.modules.push(context);
35
+ else if (context.type === 'db')
36
+ grouped.databases.push(context);
37
+ });
38
+ return grouped;
39
+ });
40
+ const currentCategoryItems = $derived(currentView !== 'categories' ? contextByCategory[currentView] : []);
41
+ // Filter to only show categories with items
42
+ const availableCategories = $derived(categories.filter((cat) => contextByCategory[cat.id].length > 0));
43
+ // Report view changes
44
+ $effect(() => {
45
+ if (onViewChange) {
46
+ if (currentView === 'categories') {
47
+ onViewChange(availableCategories.length);
48
+ }
49
+ else {
50
+ onViewChange(currentCategoryItems.length + 1);
51
+ }
52
+ }
53
+ });
54
+ function handleCategoryClick(categoryId) {
55
+ currentView = categoryId;
56
+ }
57
+ function handleBackClick() {
58
+ currentView = 'categories';
59
+ itemSelectedIndex = 0;
60
+ }
61
+ function handleKeyDown(e) {
62
+ if (stringSearch.length > 0) {
63
+ // Navigation in search view (flat list)
64
+ if (e.key === 'ArrowDown') {
65
+ e.preventDefault();
66
+ e.stopPropagation();
67
+ if (filteredAvailableContext.length > 0) {
68
+ itemSelectedIndex = (itemSelectedIndex + 1) % filteredAvailableContext.length;
69
+ }
70
+ }
71
+ else if (e.key === 'ArrowUp') {
72
+ e.preventDefault();
73
+ e.stopPropagation();
74
+ if (filteredAvailableContext.length > 0) {
75
+ itemSelectedIndex =
76
+ (itemSelectedIndex - 1 + filteredAvailableContext.length) %
77
+ filteredAvailableContext.length;
78
+ }
79
+ }
80
+ else if (e.key === 'Enter' || e.key === 'Tab') {
81
+ if (e.key === 'Tab')
82
+ e.preventDefault();
83
+ e.stopPropagation();
84
+ const selectedItem = filteredAvailableContext[itemSelectedIndex];
85
+ if (selectedItem) {
86
+ onSelect(selectedItem);
87
+ }
88
+ }
89
+ }
90
+ else if (currentView === 'categories') {
91
+ // Navigation in categories view
92
+ if (e.key === 'ArrowDown') {
93
+ e.preventDefault();
94
+ e.stopPropagation();
95
+ categorySelectedIndex = (categorySelectedIndex + 1) % availableCategories.length;
96
+ }
97
+ else if (e.key === 'ArrowUp') {
98
+ e.preventDefault();
99
+ e.stopPropagation();
100
+ categorySelectedIndex =
101
+ (categorySelectedIndex - 1 + availableCategories.length) % availableCategories.length;
102
+ }
103
+ else if (e.key === 'Enter' || e.key === 'ArrowRight' || e.key === 'Tab') {
104
+ e.preventDefault();
105
+ e.stopPropagation();
106
+ const selectedCategory = availableCategories[categorySelectedIndex];
107
+ if (selectedCategory) {
108
+ handleCategoryClick(selectedCategory.id);
109
+ }
110
+ }
111
+ else if (e.key === 'Escape' || e.key === 'ArrowLeft') {
112
+ e.preventDefault();
113
+ e.stopPropagation();
114
+ setShowing?.(false);
115
+ }
116
+ }
117
+ else {
118
+ // Navigation in category items view
119
+ if (e.key === 'ArrowDown') {
120
+ e.preventDefault();
121
+ e.stopPropagation();
122
+ if (currentCategoryItems.length > 0) {
123
+ itemSelectedIndex = (itemSelectedIndex + 1) % currentCategoryItems.length;
124
+ }
125
+ }
126
+ else if (e.key === 'ArrowUp') {
127
+ e.preventDefault();
128
+ e.stopPropagation();
129
+ if (currentCategoryItems.length > 0) {
130
+ itemSelectedIndex =
131
+ (itemSelectedIndex - 1 + currentCategoryItems.length) % currentCategoryItems.length;
132
+ }
133
+ }
134
+ else if (e.key === 'Enter' || e.key === 'Tab') {
135
+ if (e.key === 'Tab')
136
+ e.preventDefault();
137
+ e.stopPropagation();
138
+ const selectedItem = currentCategoryItems[itemSelectedIndex];
139
+ if (selectedItem) {
140
+ onSelect(selectedItem);
141
+ currentView = 'categories'; // Go back to categories after selection
142
+ }
143
+ }
144
+ else if (e.key === 'ArrowLeft' || e.key === 'Escape') {
145
+ e.preventDefault();
146
+ e.stopPropagation();
147
+ handleBackClick();
148
+ }
149
+ }
150
+ }
151
+ // Listen for keyboard events
152
+ $effect(() => {
153
+ document.addEventListener('keydown', handleKeyDown);
154
+ return () => {
155
+ document.removeEventListener('keydown', handleKeyDown);
156
+ };
157
+ });
158
+ $effect(() => {
159
+ if (stringSearch.length > 0) {
160
+ itemSelectedIndex = 0;
161
+ }
162
+ });
18
163
  </script>
19
164
 
20
- <div class="flex flex-col gap-1 text-tertiary text-xs p-1 min-w-24 max-h-48 overflow-y-scroll">
21
- {#if actualAvailableContext.length === 0}
22
- <div class="text-center text-tertiary text-xs">No available context</div>
23
- {:else}
24
- {#each actualAvailableContext as element, i}
165
+ <div
166
+ class="flex flex-col gap-1 text-tertiary text-xs p-1 pr-0 min-w-24 max-h-48 overflow-y-scroll"
167
+ onmousedown={(e) =>
168
+ // avoids triggering onblur on the textinput and closing the tooltip
169
+ e.preventDefault()}
170
+ role="listbox"
171
+ tabindex={0}
172
+ >
173
+ {#if stringSearch.length > 0}
174
+ <!-- Search view - show flat list -->
175
+ {#each filteredAvailableContext as element, i}
25
176
  {@const Icon = ContextIconMap[element.type]}
26
177
  <button
27
- class="hover:bg-surface-hover rounded-md p-1 text-left flex flex-row gap-1 items-center font-normal {i ===
28
- selectedIndex
178
+ class="hover:bg-surface-hover rounded-md p-1 text-left flex flex-row gap-1 items-center font-normal transition-colors {i ===
179
+ itemSelectedIndex
29
180
  ? 'bg-surface-hover'
30
181
  : ''}"
31
- onclick={() => onSelect(element)}
182
+ onclick={() => {
183
+ onSelect(element)
184
+ }}
32
185
  >
33
- {#if Icon}
186
+ {#if element.type === 'flow_module'}
187
+ <FlowModuleIcon module={element as FlowModule} size={16} />
188
+ {:else if Icon}
34
189
  <Icon size={16} />
35
190
  {/if}
36
- {element.type === 'diff' ? element.title.replace(/_/g, ' ') : element.title}
191
+ <span class="truncate">
192
+ {element.type === 'diff' || element.type === 'flow_module'
193
+ ? element.title.replace(/_/g, ' ')
194
+ : element.title}
195
+ </span>
37
196
  </button>
38
197
  {/each}
198
+ {#if filteredAvailableContext.length === 0}
199
+ <div class="text-center text-tertiary text-xs py-2">No matching context</div>
200
+ {/if}
201
+ {:else if currentView === 'categories'}
202
+ <!-- Categories view -->
203
+ {#each availableCategories as category, i}
204
+ {@const Icon = category.icon}
205
+ <button
206
+ class="hover:bg-surface-hover rounded-md p-1 pr-0 text-left flex flex-row gap-1 items-center font-normal transition-colors {i ===
207
+ categorySelectedIndex
208
+ ? 'bg-surface-hover'
209
+ : ''}"
210
+ onclick={() => handleCategoryClick(category.id)}
211
+ >
212
+ <Icon size={16} />
213
+ <span class="flex-1">{category.label}</span>
214
+ <ChevronRight size={16} />
215
+ </button>
216
+ {/each}
217
+ {#if availableCategories.length === 0}
218
+ <div class="text-center text-tertiary text-xs py-2">No available context</div>
219
+ {/if}
220
+ {:else}
221
+ <!-- Category items view -->
222
+ <button
223
+ class="hover:bg-surface-hover rounded-md text-left flex flex-row gap-1 items-center font-normal transition-colors mb-1"
224
+ onclick={handleBackClick}
225
+ >
226
+ <ArrowLeft size={12} />
227
+ <span class="text-xs">Go back</span>
228
+ </button>
229
+
230
+ {#if currentCategoryItems.length === 0}
231
+ <div class="text-center text-tertiary text-xs py-2">No items in this category</div>
232
+ {:else}
233
+ {#each currentCategoryItems as element, i}
234
+ {@const Icon = ContextIconMap[element.type]}
235
+ <button
236
+ class="hover:bg-surface-hover rounded-md p-1 text-left flex flex-row gap-1 items-center font-normal transition-colors {i ===
237
+ itemSelectedIndex
238
+ ? 'bg-surface-hover'
239
+ : ''}"
240
+ onclick={() => {
241
+ onSelect(element)
242
+ currentView = 'categories' // Go back to categories after selection
243
+ }}
244
+ >
245
+ {#if element.type === 'flow_module'}
246
+ <FlowModuleIcon module={element as FlowModule} size={16} />
247
+ {:else if Icon}
248
+ <Icon size={16} />
249
+ {/if}
250
+ <span class="truncate">
251
+ {element.type === 'diff' ? element.title.replace(/_/g, ' ') : element.title}
252
+ </span>
253
+ </button>
254
+ {/each}
255
+ {/if}
39
256
  {/if}
40
257
  </div>
@@ -3,9 +3,10 @@ interface Props {
3
3
  availableContext: ContextElement[];
4
4
  selectedContext: ContextElement[];
5
5
  onSelect: (element: ContextElement) => void;
6
+ setShowing?: (showing: boolean) => void;
6
7
  showAllAvailable?: boolean;
7
8
  stringSearch?: string;
8
- selectedIndex?: number;
9
+ onViewChange?: (newNumber: number) => void;
9
10
  }
10
11
  declare const AvailableContextList: import("svelte").Component<Props, {}, "">;
11
12
  type AvailableContextList = ReturnType<typeof AvailableContextList>;
@@ -6,32 +6,34 @@ import { json } from 'svelte-highlight/languages';
6
6
  import { twMerge } from 'tailwind-merge';
7
7
  import { formatGraphqlSchema, formatSchema } from '../../apps/components/display/dbtable/utils';
8
8
  import ObjectViewer from '../../propertyPicker/ObjectViewer.svelte';
9
- import { createEventDispatcher } from 'svelte';
10
9
  import HighlightCode from '../../HighlightCode.svelte';
11
- export let contextElement;
12
- export let deletable = false;
10
+ import FlowModuleIcon from '../../flows/FlowModuleIcon.svelte';
11
+ let { contextElement, deletable = false, onDelete } = $props();
13
12
  const icon = ContextIconMap[contextElement.type];
14
- let showDelete = false;
15
- const dispatch = createEventDispatcher();
13
+ let showDelete = $state(false);
14
+ const isDeletable = $derived(deletable && contextElement.deletable !== false);
16
15
  </script>
17
16
 
18
17
  <Popover>
19
- <svelte:fragment slot="trigger">
18
+ {#snippet trigger()}
20
19
  <div
21
20
  class={twMerge(
22
21
  'border rounded-md px-1 py-0.5 flex flex-row items-center gap-1 text-tertiary text-xs cursor-default hover:bg-surface-hover hover:cursor-pointer max-w-48 bg-surface'
23
22
  )}
24
- on:mouseenter={() => (showDelete = true)}
25
- on:mouseleave={() => (showDelete = false)}
23
+ onmouseenter={() => (showDelete = true)}
24
+ onmouseleave={() => (showDelete = false)}
26
25
  aria-label="Context element"
27
26
  role="button"
28
27
  tabindex={0}
29
28
  >
30
- <button on:click={() => dispatch('delete')} class:cursor-default={!deletable}>
31
- {#if showDelete && deletable}
29
+ <button onclick={isDeletable ? onDelete : undefined} class:cursor-default={!isDeletable}>
30
+ {#if showDelete && isDeletable}
32
31
  <X size={16} />
32
+ {:else if contextElement.type === 'flow_module' || contextElement.type === 'flow_module_code_piece'}
33
+ <FlowModuleIcon module={contextElement as FlowModule} size={16} />
33
34
  {:else}
34
- <svelte:component this={icon} size={16} />
35
+ {@const SvelteComponent = icon}
36
+ <SvelteComponent size={16} />
35
37
  {/if}
36
38
  </button>
37
39
  <span class="truncate">
@@ -40,8 +42,8 @@ const dispatch = createEventDispatcher();
40
42
  : contextElement.title}
41
43
  </span>
42
44
  </div>
43
- </svelte:fragment>
44
- <svelte:fragment slot="content">
45
+ {/snippet}
46
+ {#snippet content()}
45
47
  {#if contextElement.type === 'error'}
46
48
  <div class="max-w-96 max-h-[300px] text-xs overflow-auto">
47
49
  <Highlight language={json} code={contextElement.content} class="w-full p-2" />
@@ -63,7 +65,7 @@ const dispatch = createEventDispatcher();
63
65
  <div class="text-tertiary">Not loaded yet</div>
64
66
  {/if}
65
67
  </div>
66
- {:else if contextElement.type === 'code' || contextElement.type === 'code_piece' || contextElement.type === 'diff'}
68
+ {:else if contextElement.type === 'code' || contextElement.type === 'code_piece' || contextElement.type === 'diff' || contextElement.type === 'flow_module_code_piece'}
67
69
  <div class="max-w-96 max-h-[300px] text-xs overflow-auto">
68
70
  <HighlightCode
69
71
  language={contextElement.lang}
@@ -71,6 +73,20 @@ const dispatch = createEventDispatcher();
71
73
  class="w-full p-2 "
72
74
  />
73
75
  </div>
76
+ {:else if contextElement.type === 'flow_module'}
77
+ {#if contextElement.value.content}
78
+ <div class="p-2 max-w-96 max-h-[300px] text-xs overflow-auto">
79
+ <HighlightCode
80
+ language={contextElement.value.language}
81
+ code={contextElement.value.content}
82
+ class="w-full p-2 "
83
+ />
84
+ </div>
85
+ {:else}
86
+ <div class="p-2 max-w-96 max-h-[300px] text-xs overflow-auto">
87
+ <div class="text-tertiary">{contextElement.title}</div>
88
+ </div>
89
+ {/if}
74
90
  {/if}
75
- </svelte:fragment>
91
+ {/snippet}
76
92
  </Popover>
@@ -1,24 +1,9 @@
1
1
  import { type ContextElement } from './context';
2
- 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> {
3
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
- $$bindings?: Bindings;
5
- } & Exports;
6
- (internal: unknown, props: Props & {
7
- $$events?: Events;
8
- $$slots?: Slots;
9
- }): Exports & {
10
- $set?: any;
11
- $on?: any;
12
- };
13
- z_$$bindings?: Bindings;
14
- }
15
- declare const ContextElementBadge: $$__sveltets_2_IsomorphicComponent<{
2
+ interface Props {
16
3
  contextElement: ContextElement;
17
4
  deletable?: boolean;
18
- }, {
19
- delete: CustomEvent<void>;
20
- } & {
21
- [evt: string]: CustomEvent<any>;
22
- }, {}, {}, string>;
23
- type ContextElementBadge = InstanceType<typeof ContextElementBadge>;
5
+ onDelete?: () => void;
6
+ }
7
+ declare const ContextElementBadge: import("svelte").Component<Props, {}, "">;
8
+ type ContextElementBadge = ReturnType<typeof ContextElementBadge>;
24
9
  export default ContextElementBadge;
@@ -1,7 +1,9 @@
1
- import { type ScriptLang } from '../../../gen';
1
+ import { type Flow, type ScriptLang } from '../../../gen';
2
2
  import { type DBSchemas } from '../../../stores';
3
3
  import type { ContextElement } from './context';
4
+ import type { FlowModule } from '../../../gen';
4
5
  import type { DisplayMessage } from './shared';
6
+ import type { ExtendedOpenFlow } from '../../flows/types';
5
7
  export interface ScriptOptions {
6
8
  lang: ScriptLang | 'bunnative';
7
9
  code: string;
@@ -12,6 +14,13 @@ export interface ScriptOptions {
12
14
  lastDeployedCode?: string;
13
15
  diffMode: boolean;
14
16
  }
17
+ export interface FlowOptions {
18
+ currentFlow: ExtendedOpenFlow;
19
+ lastDeployedFlow?: Flow;
20
+ path: string | undefined;
21
+ modules: FlowModule[];
22
+ lastSavedFlow?: Flow;
23
+ }
15
24
  export default class ContextManager {
16
25
  private selectedContext;
17
26
  private availableContext;
@@ -21,11 +30,13 @@ export default class ContextManager {
21
30
  private refreshDbResources;
22
31
  private getSelectedDBSchema;
23
32
  private getContextCodePath;
33
+ updateAvailableContextForFlow(flowOptions: FlowOptions, dbSchemas: DBSchemas, workspace: string, toolSupport: boolean, currentlySelectedContext: ContextElement[]): Promise<void>;
24
34
  updateAvailableContext(scriptOptions: ScriptOptions, dbSchemas: DBSchemas, workspace: string, toolSupport: boolean, currentlySelectedContext: ContextElement[]): Promise<void>;
25
35
  getSelectedContext(): ContextElement[];
26
36
  setSelectedContext(newSelectedContext: ContextElement[]): void;
27
37
  getAvailableContext(): ContextElement[];
28
- addSelectedLinesToContext(lines: string, startLine: number, endLine: number): void;
38
+ setScriptOptions(scriptOptions: ScriptOptions): void;
39
+ addSelectedLinesToContext(lines: string, startLine: number, endLine: number, moduleId?: string): void;
29
40
  setFixContext(): void;
30
41
  setAskAiContext(options: {
31
42
  withCode?: boolean;
@@ -36,4 +47,6 @@ export default class ContextManager {
36
47
  addBackCode?: boolean;
37
48
  }): void;
38
49
  static updateDisplayMessages(displayMessages: DisplayMessage[], dbSchemas: DBSchemas): DisplayMessage[];
50
+ setSelectedModuleContext(moduleId: string | undefined, availableContext: ContextElement[] | undefined): void;
51
+ clearContext(): void;
39
52
  }
@@ -33,14 +33,82 @@ export default class ContextManager {
33
33
  '.' +
34
34
  langToExt(scriptLangToEditorLang(scriptOptions.lang)));
35
35
  }
36
+ async updateAvailableContextForFlow(flowOptions, dbSchemas, workspace, toolSupport, currentlySelectedContext) {
37
+ try {
38
+ if (this.workspace !== workspace) {
39
+ await this.refreshDbResources(workspace);
40
+ this.workspace = workspace;
41
+ }
42
+ let newAvailableContext = [];
43
+ // Add diff context if we have a deployed flow version
44
+ const deployedFlowString = JSON.stringify(flowOptions.lastDeployedFlow, null, 2);
45
+ const savedFlowString = JSON.stringify(flowOptions.lastSavedFlow, null, 2);
46
+ const currentFlowString = JSON.stringify(flowOptions.currentFlow, null, 2);
47
+ if (currentFlowString && deployedFlowString && deployedFlowString !== currentFlowString) {
48
+ newAvailableContext.push({
49
+ type: 'diff',
50
+ title: 'diff_with_last_deployed_version',
51
+ content: deployedFlowString,
52
+ diff: diffLines(deployedFlowString, currentFlowString),
53
+ lang: 'graphql' // irrelevant, but needed for the diff component
54
+ });
55
+ }
56
+ if (currentFlowString && savedFlowString && savedFlowString !== currentFlowString) {
57
+ newAvailableContext.push({
58
+ type: 'diff',
59
+ title: 'diff_with_last_saved_draft',
60
+ content: savedFlowString,
61
+ diff: diffLines(savedFlowString, currentFlowString),
62
+ lang: 'graphql' // irrelevant, but needed for the diff component
63
+ });
64
+ }
65
+ for (const module of flowOptions.modules) {
66
+ newAvailableContext.push({
67
+ type: 'flow_module',
68
+ id: module.id,
69
+ title: `${module.id}`,
70
+ value: {
71
+ language: 'language' in module.value ? module.value.language : 'bunnative',
72
+ path: 'path' in module.value ? module.value.path : '',
73
+ content: 'content' in module.value ? module.value.content : '',
74
+ type: module.value.type
75
+ }
76
+ });
77
+ }
78
+ if (toolSupport) {
79
+ for (const d of this.dbResources) {
80
+ const loadedSchema = dbSchemas[d.path];
81
+ newAvailableContext.push({
82
+ type: 'db',
83
+ title: d.path,
84
+ // If the db is already fetched, add the schema to the context
85
+ ...(loadedSchema ? { schema: loadedSchema } : {})
86
+ });
87
+ }
88
+ }
89
+ let newSelectedContext = [...currentlySelectedContext];
90
+ // Filter selected context to only include available items
91
+ newSelectedContext = newSelectedContext
92
+ .filter((c) => newAvailableContext.some((ac) => ac.type === c.type && ac.title === c.title))
93
+ .map((c) => c.type === 'db' && dbSchemas[c.title]
94
+ ? {
95
+ ...c,
96
+ schema: dbSchemas[c.title]
97
+ }
98
+ : c);
99
+ this.availableContext = newAvailableContext;
100
+ this.selectedContext = newSelectedContext;
101
+ }
102
+ catch (err) {
103
+ console.error('Could not update available context for flow', err);
104
+ }
105
+ }
36
106
  async updateAvailableContext(scriptOptions, dbSchemas, workspace, toolSupport, currentlySelectedContext) {
37
107
  try {
38
- let firstTime = !this.workspace;
39
108
  if (this.workspace !== workspace) {
40
109
  await this.refreshDbResources(workspace);
41
110
  this.workspace = workspace;
42
111
  }
43
- this.scriptOptions = scriptOptions;
44
112
  let newAvailableContext = [
45
113
  {
46
114
  type: 'code',
@@ -89,16 +157,15 @@ export default class ContextManager {
89
157
  ];
90
158
  }
91
159
  let newSelectedContext = [...currentlySelectedContext];
92
- if (firstTime) {
93
- newSelectedContext = [
94
- {
95
- type: 'code',
96
- title: this.getContextCodePath(scriptOptions) ?? '',
97
- content: scriptOptions.code,
98
- lang: scriptOptions.lang
99
- }
100
- ];
101
- }
160
+ newSelectedContext = [
161
+ {
162
+ type: 'code',
163
+ title: this.getContextCodePath(scriptOptions) ?? '',
164
+ content: scriptOptions.code,
165
+ lang: scriptOptions.lang,
166
+ deletable: false
167
+ }
168
+ ];
102
169
  const db = this.getSelectedDBSchema(scriptOptions, dbSchemas);
103
170
  if (db &&
104
171
  !newSelectedContext.find((c) => c.type === 'db' && db && c.title === db.resource) &&
@@ -144,22 +211,49 @@ export default class ContextManager {
144
211
  getAvailableContext() {
145
212
  return this.availableContext;
146
213
  }
147
- addSelectedLinesToContext(lines, startLine, endLine) {
214
+ setScriptOptions(scriptOptions) {
215
+ this.scriptOptions = scriptOptions;
216
+ }
217
+ addSelectedLinesToContext(lines, startLine, endLine, moduleId) {
218
+ const title = moduleId ? `${moduleId} L${startLine}-L${endLine}` : `L${startLine}-L${endLine}`;
148
219
  if (!this.scriptOptions ||
149
- this.selectedContext.find((c) => c.type === 'code_piece' && c.title === `L${startLine}-L${endLine}`)) {
220
+ this.selectedContext.find((c) => (c.type === 'code_piece' && c.title === title) ||
221
+ (c.type === 'flow_module_code_piece' && c.id === moduleId && c.title === title))) {
150
222
  return;
151
223
  }
152
- this.selectedContext = [
153
- ...this.selectedContext,
154
- {
155
- type: 'code_piece',
156
- title: `L${startLine}-L${endLine}`,
157
- startLine,
158
- endLine,
159
- content: lines,
160
- lang: this.scriptOptions.lang
224
+ if (moduleId) {
225
+ const module = [...this.availableContext, ...this.selectedContext].find((c) => c.type === 'flow_module' && c.id === moduleId);
226
+ if (!module) {
227
+ console.error('Module not found', moduleId);
228
+ return;
161
229
  }
162
- ];
230
+ this.selectedContext = [
231
+ ...this.selectedContext,
232
+ {
233
+ type: 'flow_module_code_piece',
234
+ id: moduleId,
235
+ title: title,
236
+ startLine,
237
+ endLine,
238
+ content: lines,
239
+ lang: this.scriptOptions.lang,
240
+ value: module.value
241
+ }
242
+ ];
243
+ }
244
+ else {
245
+ this.selectedContext = [
246
+ ...this.selectedContext,
247
+ {
248
+ type: 'code_piece',
249
+ title: title,
250
+ startLine,
251
+ endLine,
252
+ content: lines,
253
+ lang: this.scriptOptions.lang
254
+ }
255
+ ];
256
+ }
163
257
  }
164
258
  setFixContext() {
165
259
  const codeContext = this.availableContext.find((c) => c.type === 'code');
@@ -217,4 +311,20 @@ export default class ContextManager {
217
311
  : undefined
218
312
  }));
219
313
  }
314
+ setSelectedModuleContext(moduleId, availableContext) {
315
+ if (availableContext && moduleId) {
316
+ const module = availableContext.find((c) => c.type === 'flow_module' && c.id === moduleId);
317
+ if (module &&
318
+ !this.selectedContext.find((c) => c.type === 'flow_module' && c.id === moduleId)) {
319
+ this.selectedContext = this.selectedContext.filter((c) => c.type !== 'flow_module');
320
+ this.selectedContext = [module, ...this.selectedContext];
321
+ }
322
+ }
323
+ else if (!moduleId) {
324
+ this.selectedContext = this.selectedContext.filter((c) => c.type !== 'flow_module');
325
+ }
326
+ }
327
+ clearContext() {
328
+ this.selectedContext = [];
329
+ }
220
330
  }