windmill-components 1.542.4 → 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 (189) 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/EditorSettings.svelte +11 -9
  17. package/package/components/ErrorOrRecoveryHandler.svelte +14 -20
  18. package/package/components/FlowHistoryJobPicker.svelte +3 -0
  19. package/package/components/FlowHistoryJobPicker.svelte.d.ts +1 -0
  20. package/package/components/FlowJobResult.svelte +5 -5
  21. package/package/components/FlowLogRow.svelte +2 -2
  22. package/package/components/FlowLogViewer.svelte +228 -57
  23. package/package/components/FlowLogViewer.svelte.d.ts +16 -5
  24. package/package/components/FlowLogViewerWrapper.svelte +56 -3
  25. package/package/components/FlowLogViewerWrapper.svelte.d.ts +4 -3
  26. package/package/components/FlowLoopIterationPreview.svelte +4 -4
  27. package/package/components/FlowMetadata.svelte +3 -4
  28. package/package/components/FlowMetadata.svelte.d.ts +4 -18
  29. package/package/components/FlowPreviewContent.svelte +9 -3
  30. package/package/components/FlowPreviewContent.svelte.d.ts +1 -1
  31. package/package/components/FlowStatusViewer.svelte +62 -59
  32. package/package/components/FlowStatusViewer.svelte.d.ts +2 -2
  33. package/package/components/FlowStatusViewerInner.svelte +186 -94
  34. package/package/components/FlowStatusViewerInner.svelte.d.ts +10 -3
  35. package/package/components/FlowTimeline.svelte +110 -131
  36. package/package/components/FlowTimeline.svelte.d.ts +13 -4
  37. package/package/components/FlowTimelineBar.svelte +227 -0
  38. package/package/components/FlowTimelineBar.svelte.d.ts +24 -0
  39. package/package/components/InputTransformForm.svelte +119 -3
  40. package/package/components/InputTransformForm.svelte.d.ts +3 -0
  41. package/package/components/InputTransformSchemaForm.svelte +5 -1
  42. package/package/components/InputTransformSchemaForm.svelte.d.ts +2 -0
  43. package/package/components/InstanceSetting.svelte +17 -42
  44. package/package/components/InstanceSettings.svelte +12 -21
  45. package/package/components/JobArgs.svelte +15 -16
  46. package/package/components/JobArgs.svelte.d.ts +4 -18
  47. package/package/components/JobLoader.svelte +23 -42
  48. package/package/components/JobLoader.svelte.d.ts +2 -0
  49. package/package/components/JobStatus.svelte +1 -1
  50. package/package/components/JobStatus.svelte.d.ts +4 -18
  51. package/package/components/ModulePreviewResultViewer.svelte +1 -7
  52. package/package/components/NextcloudSetting.svelte +6 -1
  53. package/package/components/Password.svelte +7 -11
  54. package/package/components/Password.svelte.d.ts +5 -20
  55. package/package/components/PasswordArgInput.svelte +35 -15
  56. package/package/components/PasswordArgInput.svelte.d.ts +4 -18
  57. package/package/components/QueuePosition.svelte +6 -2
  58. package/package/components/RunForm.svelte +5 -14
  59. package/package/components/S3ArrayHelperButton.svelte +12 -0
  60. package/package/components/S3ArrayHelperButton.svelte.d.ts +8 -0
  61. package/package/components/ScriptEditor.svelte +5 -6
  62. package/package/components/StringTypeNarrowing.svelte +39 -24
  63. package/package/components/StringTypeNarrowing.svelte.d.ts +1 -1
  64. package/package/components/TeamSelector.svelte +83 -37
  65. package/package/components/TeamSelector.svelte.d.ts +0 -1
  66. package/package/components/apps/components/buttons/AppButton.svelte +11 -1
  67. package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte +13 -4
  68. package/package/components/apps/components/display/table/SyncColumnDefs.svelte +2 -2
  69. package/package/components/apps/components/display/table/utils.js +1 -1
  70. package/package/components/apps/components/helpers/RefreshButton.svelte +5 -1
  71. package/package/components/apps/components/helpers/RunnableComponent.svelte +0 -2
  72. package/package/components/apps/components/helpers/RunnableWrapper.svelte.d.ts +1 -0
  73. package/package/components/apps/components/layout/AppTabs.svelte +116 -71
  74. package/package/components/apps/components/layout/AppTabs.svelte.d.ts +1 -0
  75. package/package/components/apps/editor/component/ComponentInner.svelte +1 -0
  76. package/package/components/apps/editor/component/components.d.ts +16 -1
  77. package/package/components/apps/editor/component/components.js +22 -2
  78. package/package/components/apps/editor/settingsPanel/ComponentPanel.svelte +2 -0
  79. package/package/components/apps/editor/settingsPanel/GridTab.svelte +19 -1
  80. package/package/components/apps/editor/settingsPanel/GridTab.svelte.d.ts +3 -1
  81. package/package/components/apps/editor/settingsPanel/GridTabHidden.svelte +52 -0
  82. package/package/components/apps/editor/settingsPanel/GridTabHidden.svelte.d.ts +9 -0
  83. package/package/components/auditLogs/AuditLogsFilters.svelte +6 -0
  84. package/package/components/auditLogs/AuditLogsTable.svelte +17 -7
  85. package/package/components/auditLogs/AuditLogsTable.svelte.d.ts +1 -0
  86. package/package/components/common/CloseButton.svelte +2 -2
  87. package/package/components/common/CloseButton.svelte.d.ts +1 -0
  88. package/package/components/common/layout/List.svelte +3 -7
  89. package/package/components/common/layout/List.svelte.d.ts +7 -29
  90. package/package/components/common/popup/PopupV2.svelte +8 -25
  91. package/package/components/common/popup/PopupV2.svelte.d.ts +4 -2
  92. package/package/components/common/table/ScriptRow.svelte +22 -2
  93. package/package/components/copilot/FlowCopilotInputsModal.svelte +26 -23
  94. package/package/components/copilot/chat/AIChatManager.svelte.js +3 -2
  95. package/package/components/copilot/chat/ProviderModelSelector.svelte +1 -1
  96. package/package/components/copilot/chat/flow/FlowAIChat.svelte +4 -2
  97. package/package/components/copilot/chat/script/core.d.ts +4 -4
  98. package/package/components/copilot/chat/script/core.js +93 -34
  99. package/package/components/copilot/lib.d.ts +1 -0
  100. package/package/components/copilot/lib.js +6 -3
  101. package/package/components/custom_ui.d.ts +2 -0
  102. package/package/components/flows/FlowProgressBar.svelte +16 -16
  103. package/package/components/flows/FlowProgressBar.svelte.d.ts +7 -22
  104. package/package/components/flows/content/FlowInputsQuick.svelte +3 -2
  105. package/package/components/flows/content/FlowInputsQuick.svelte.d.ts +1 -0
  106. package/package/components/flows/content/FlowModuleComponent.svelte +24 -1
  107. package/package/components/flows/flowInfers.js +34 -8
  108. package/package/components/flows/flowStore.d.ts +4 -1
  109. package/package/components/flows/map/FlowJobsMenu.svelte +3 -3
  110. package/package/components/flows/map/FlowJobsMenu.svelte.d.ts +1 -1
  111. package/package/components/flows/map/InsertModuleButton.svelte +4 -14
  112. package/package/components/flows/map/InsertModuleButton.svelte.d.ts +0 -1
  113. package/package/components/flows/map/InsertModuleInner.svelte +17 -20
  114. package/package/components/flows/map/MapItem.svelte +1 -1
  115. package/package/components/flows/pickers/PickHubScriptQuick.svelte +38 -52
  116. package/package/components/flows/pickers/PickHubScriptQuick.svelte.d.ts +1 -0
  117. package/package/components/flows/pickers/WorkspaceScriptPickerQuick.svelte +27 -15
  118. package/package/components/flows/pickers/WorkspaceScriptPickerQuick.svelte.d.ts +1 -0
  119. package/package/components/flows/propPicker/OutputPicker.svelte +2 -0
  120. package/package/components/git_sync/DetectionFlow.svelte +33 -44
  121. package/package/components/git_sync/DetectionFlow.svelte.d.ts +1 -0
  122. package/package/components/git_sync/GitSyncContext.svelte.d.ts +22 -0
  123. package/package/components/git_sync/GitSyncContext.svelte.js +145 -5
  124. package/package/components/git_sync/GitSyncModeDisplay.svelte +14 -0
  125. package/package/components/git_sync/GitSyncModeDisplay.svelte.d.ts +9 -0
  126. package/package/components/git_sync/GitSyncRepositoryCard.svelte +365 -253
  127. package/package/components/git_sync/GitSyncRepositoryCard.svelte.d.ts +10 -1
  128. package/package/components/git_sync/GitSyncSection.svelte +134 -14
  129. package/package/components/git_sync/PullWorkspaceModal.svelte +24 -32
  130. package/package/components/git_sync/PushWorkspaceModal.svelte +24 -32
  131. package/package/components/graph/model.d.ts +5 -5
  132. package/package/components/graph/renderers/edges/EmptyEdge.svelte +3 -10
  133. package/package/components/graph/renderers/edges/EmptyEdge.svelte.d.ts +4 -18
  134. package/package/components/graph/renderers/nodes/AIToolNode.svelte +2 -2
  135. package/package/components/graph/renderers/nodes/NewAIToolNode.svelte +5 -10
  136. package/package/components/home/ItemsList.svelte +1 -1
  137. package/package/components/jobs/JobProgressBar.svelte +27 -21
  138. package/package/components/jobs/JobProgressBar.svelte.d.ts +9 -24
  139. package/package/components/meltComponents/MenuSingleItem.svelte +3 -8
  140. package/package/components/meltComponents/MenuSingleItem.svelte.d.ts +0 -3
  141. package/package/components/meltComponents/Popover.svelte +3 -2
  142. package/package/components/meltComponents/Popover.svelte.d.ts +1 -0
  143. package/package/components/meltComponents/Tooltip.svelte +1 -1
  144. package/package/components/progressBar/ProgressBar.svelte +39 -53
  145. package/package/components/progressBar/ProgressBar.svelte.d.ts +11 -26
  146. package/package/components/runs/JobsLoader.svelte +1 -1
  147. package/package/components/runs/NoWorkerWithTagWarning.svelte +3 -3
  148. package/package/components/runs/NoWorkerWithTagWarning.svelte.d.ts +1 -1
  149. package/package/components/schema/AddPropertyV2.svelte +7 -4
  150. package/package/components/schema/PropertyEditor.svelte.d.ts +1 -1
  151. package/package/components/select/MultiSelect.svelte +2 -2
  152. package/package/components/select/MultiSelect.svelte.d.ts +1 -0
  153. package/package/components/settings/WorkspaceUserSettings.svelte +92 -1
  154. package/package/components/sidebar/MenuLink.svelte +2 -1
  155. package/package/components/sidebar/MenuLink.svelte.d.ts +1 -0
  156. package/package/components/sidebar/SidebarContent.svelte +27 -27
  157. package/package/components/table/Cell.svelte +7 -14
  158. package/package/components/table/Cell.svelte.d.ts +13 -35
  159. package/package/components/triggers/AddTriggersButton.svelte +1 -0
  160. package/package/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte +1 -1
  161. package/package/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte.d.ts +2 -1
  162. package/package/components/triggers/gcp/GcpTriggerEditorInner.svelte +28 -5
  163. package/package/components/triggers/gcp/utils.js +1 -0
  164. package/package/components/triggers/schedules/ScheduleEditorInner.svelte +1 -0
  165. package/package/components/triggers/webhook/WebhooksConfigSection.svelte +143 -63
  166. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +22 -0
  167. package/package/components/triggers/websocket/utils.js +1 -0
  168. package/package/components/workspaceSettings/AISettings.svelte +8 -2
  169. package/package/components/workspaceSettings/AISettings.svelte.d.ts +2 -1
  170. package/package/components/workspaceSettings/ModelTokenLimits.svelte +165 -0
  171. package/package/components/workspaceSettings/ModelTokenLimits.svelte.d.ts +8 -0
  172. package/package/components/workspaceSettings/StorageSettings.svelte +123 -51
  173. package/package/gen/core/OpenAPI.js +1 -1
  174. package/package/gen/schemas.gen.d.ts +141 -16
  175. package/package/gen/schemas.gen.js +144 -16
  176. package/package/gen/services.gen.d.ts +62 -42
  177. package/package/gen/services.gen.js +131 -82
  178. package/package/gen/types.gen.d.ts +218 -144
  179. package/package/hubPaths.json +2 -1
  180. package/package/services/JobManager.js +10 -7
  181. package/package/stores.d.ts +1 -0
  182. package/package/stores.js +6 -3
  183. package/package/timelineCompute.svelte.d.ts +21 -0
  184. package/package/timelineCompute.svelte.js +113 -0
  185. package/package/utils.d.ts +15 -8
  186. package/package/utils.js +62 -12
  187. package/package/workspace_settings.d.ts +13 -8
  188. package/package/workspace_settings.js +46 -11
  189. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- <script lang="ts">import { Save, Trash, XCircle, CheckCircle2, RotateCw, RotateCcw, Download, Upload } from 'lucide-svelte';
1
+ <script lang="ts">import { Save, Trash, XCircle, CheckCircle2, RotateCw, RotateCcw, Download, Upload, Plus } from 'lucide-svelte';
2
2
  import { Button, Alert } from '../common';
3
3
  import { getGitSyncContext } from './GitSyncContext.svelte';
4
4
  import ResourcePicker from '../ResourcePicker.svelte';
@@ -8,18 +8,51 @@ import { sendUserToast } from '../../toast';
8
8
  import { fade } from 'svelte/transition';
9
9
  import { workspaceStore } from '../../stores';
10
10
  import hubPaths from '../../hubPaths.json';
11
- let { idx } = $props();
11
+ import GitSyncModeDisplay from './GitSyncModeDisplay.svelte';
12
+ let { idx = null, isSecondary = false, isLegacy = false, variant = 'standard', mode = null, repository = null, onAdd = null, isCollapsible = true, showEmptyState = false } = $props();
12
13
  const gitSyncContext = getGitSyncContext();
13
- const repo = $derived(gitSyncContext.getRepository(idx));
14
- const validation = $derived(gitSyncContext.getValidation(idx));
15
- const gitSyncTestJob = $derived(gitSyncContext.gitSyncTestJobs?.[idx]);
14
+ const repo = $derived(repository || (idx !== null ? gitSyncContext.getRepository(idx) : null));
15
+ const validation = $derived(idx !== null ? gitSyncContext.getValidation(idx) : null);
16
+ const gitSyncTestJob = $derived(idx !== null ? gitSyncContext.gitSyncTestJobs?.[idx] : null);
16
17
  let confirmingDelete = $state(false);
18
+ let targetBranch = $state('main'); // Default to main, will be updated when resource is available
19
+ // Update target branch when repository changes
20
+ $effect(() => {
21
+ const abortController = new AbortController();
22
+ if (repo?.git_repo_resource_path) {
23
+ gitSyncContext.getTargetBranch(repo).then(branch => {
24
+ if (!abortController.signal.aborted) {
25
+ targetBranch = branch;
26
+ }
27
+ }).catch(error => {
28
+ if (!abortController.signal.aborted) {
29
+ console.warn('Failed to get target branch:', error);
30
+ }
31
+ });
32
+ }
33
+ return () => {
34
+ abortController.abort();
35
+ };
36
+ });
17
37
  // Compute already-used repository paths to exclude from picker
18
38
  const usedRepositoryPaths = $derived(gitSyncContext.repositories
19
39
  .map((r, i) => i !== idx ? r.git_repo_resource_path : null)
20
40
  .filter((path) => Boolean(path?.trim())));
41
+ // Determine display title based on variant and legacy status
42
+ const displayTitle = $derived(variant === 'primary-sync' ? (mode === 'sync' ? 'Sync mode' : 'Promotion mode') :
43
+ variant === 'primary-promotion' ? 'Promotion mode' :
44
+ isLegacy ? 'Legacy promotion repository' :
45
+ isSecondary ? 'Secondary sync repository' :
46
+ `Repository #${(idx ?? 0) + 1}`);
47
+ // Determine display description based on variant and mode
48
+ const displayDescription = $derived((variant === 'primary-sync' || variant === 'primary-promotion') ?
49
+ (mode === 'sync' ? `Changes will be committed directly to the ${targetBranch} branch` :
50
+ mode === 'promotion' ? `Changes will be made to new branches whose promotion target is ${targetBranch}` :
51
+ null) :
52
+ null);
53
+ const shouldShowEmptyState = $derived(showEmptyState || (!repo && (variant === 'primary-sync' || variant === 'primary-promotion')));
21
54
  async function handleSave() {
22
- if (!repo)
55
+ if (!repo || idx === null)
23
56
  return;
24
57
  try {
25
58
  await gitSyncContext.saveRepository(idx);
@@ -31,7 +64,7 @@ async function handleSave() {
31
64
  }
32
65
  }
33
66
  function handleRevert() {
34
- if (!repo)
67
+ if (!repo || idx === null)
35
68
  return;
36
69
  try {
37
70
  gitSyncContext.revertRepository?.(idx);
@@ -46,6 +79,8 @@ function initiateDelete() {
46
79
  confirmingDelete = true;
47
80
  }
48
81
  async function confirmDelete() {
82
+ if (idx === null)
83
+ return;
49
84
  try {
50
85
  await gitSyncContext.removeRepository(idx);
51
86
  sendUserToast('Repository connection removed successfully');
@@ -62,7 +97,7 @@ function cancelDelete() {
62
97
  confirmingDelete = false;
63
98
  }
64
99
  function runGitSyncTestJob() {
65
- if (gitSyncContext.runTestJob) {
100
+ if (idx !== null && gitSyncContext.runTestJob) {
66
101
  gitSyncContext.runTestJob(idx);
67
102
  }
68
103
  }
@@ -70,269 +105,346 @@ function emptyString(str) {
70
105
  return !str || str.trim() === '';
71
106
  }
72
107
  function handlePullSettings() {
73
- gitSyncContext.showPullModal(idx, true); // true for settingsOnly
108
+ if (idx !== null) {
109
+ gitSyncContext.showPullModal(idx, true);
110
+ }
74
111
  }
75
112
  </script>
76
113
 
77
- {#if repo}
78
- <div class="rounded-lg shadow-sm border p-0 w-full mb-4">
79
- <!-- Card Header -->
80
- <div class="flex items-center justify-between min-h-10 px-4 py-1 border-b">
81
- <div class="flex items-center gap-2">
82
- <span class="font-semibold">Repository #{idx + 1}</span>
83
- {#if repo.legacyImported}
84
- <span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-orange-100 text-orange-800 border border-orange-200">
85
- Legacy Configuration
86
- </span>
87
- {/if}
88
- <span class="text-xs text-tertiary pt-1 pl-8">
89
- {repo.git_repo_resource_path}
90
- </span>
114
+ <!-- Shared snippets for reusable content -->
115
+
116
+ {#snippet headerActions()}
117
+ {#if !isLegacy}
118
+ {#if validation?.hasChanges && validation?.isValid && !repo.isUnsavedConnection}
119
+ <Button
120
+ size="xs"
121
+ onclick={handleSave}
122
+ startIcon={{ icon: Save }}
123
+ >
124
+ {repo.legacyImported ? 'Migrate and save' : 'Save changes'}
125
+ </Button>
126
+ {#if idx !== null && gitSyncContext.initialRepositories[idx] && !repo.legacyImported}
127
+ <Button
128
+ color="light"
129
+ size="xs"
130
+ onclick={handleRevert}
131
+ startIcon={{ icon: RotateCcw }}
132
+ >
133
+ Revert
134
+ </Button>
135
+ {/if}
136
+ {/if}
137
+ {/if}
138
+ {#if isCollapsible}
139
+ <button
140
+ class="text-secondary hover:text-primary focus:outline-none"
141
+ onclick={() => (repo.collapsed = !repo.collapsed)}
142
+ aria-label="Toggle collapse"
143
+ >
144
+ {#if repo.collapsed}
145
+ <svg
146
+ xmlns="http://www.w3.org/2000/svg"
147
+ class="h-5 w-5"
148
+ fill="none"
149
+ viewBox="0 0 24 24"
150
+ stroke="currentColor"
151
+ >
152
+ <path
153
+ stroke-linecap="round"
154
+ stroke-linejoin="round"
155
+ stroke-width="2"
156
+ d="M19 9l-7 7-7-7"
157
+ />
158
+ </svg>
159
+ {:else}
160
+ <svg
161
+ xmlns="http://www.w3.org/2000/svg"
162
+ class="h-5 w-5"
163
+ fill="none"
164
+ viewBox="0 0 24 24"
165
+ stroke="currentColor"
166
+ >
167
+ <path
168
+ stroke-linecap="round"
169
+ stroke-linejoin="round"
170
+ stroke-width="2"
171
+ d="M5 15l7-7 7 7"
172
+ />
173
+ </svg>
174
+ {/if}
175
+ </button>
176
+ {/if}
177
+ {#if !confirmingDelete}
178
+ <div transition:fade|local={{ duration: 100 }}>
179
+ <Button
180
+ size="xs"
181
+ color="light"
182
+ variant="border"
183
+ onclick={initiateDelete}
184
+ startIcon={{ icon: Trash }}
185
+ >
186
+ Delete
187
+ </Button>
188
+ </div>
189
+ {:else}
190
+ <div class="flex gap-1">
191
+ <button
192
+ transition:fade|local={{ duration: 100 }}
193
+ class="px-3 py-1 text-xs bg-red-500 text-white rounded duration-200 hover:bg-red-600"
194
+ onclick={confirmDelete}
195
+ >
196
+ Confirm delete
197
+ </button>
198
+ <button
199
+ transition:fade|local={{ duration: 100 }}
200
+ class="px-2 py-1 text-xs bg-surface-secondary rounded duration-200 hover:bg-surface-hover"
201
+ onclick={cancelDelete}
202
+ >
203
+ <XCircle size={12} />
204
+ </button>
205
+ </div>
206
+ {/if}
207
+ {/snippet}
208
+
209
+ {#snippet repositoryContent()}
210
+ <div class="space-y-4">
211
+ <!-- Resource Picker -->
212
+ <div class="flex gap-2 items-center">
213
+ <div class="font-medium">Resource:</div>
214
+ <div class="flex-1">
215
+ <ResourcePicker
216
+ bind:value={repo.git_repo_resource_path}
217
+ resourceType={'git_repository'}
218
+ disabled={!repo.isUnsavedConnection}
219
+ excludedValues={usedRepositoryPaths}
220
+ />
91
221
  </div>
92
- <div class="flex items-center gap-2">
93
- {#if validation.hasChanges && validation.isValid && !repo.isUnsavedConnection}
94
- <Button
95
- size="xs"
96
- onclick={handleSave}
97
- startIcon={{ icon: Save }}
222
+ {#if !emptyString(repo.git_repo_resource_path)}
223
+ <Button
224
+ disabled={emptyString(repo.script_path)}
225
+ color="dark"
226
+ onclick={runGitSyncTestJob}
227
+ size="xs"
228
+ >
229
+ Test connection
230
+ </Button>
231
+ {/if}
232
+ </div>
233
+
234
+ {#if !emptyString(repo.git_repo_resource_path)}
235
+ <!-- Validation and Test Status -->
236
+ {#if validation?.isDuplicate}
237
+ <div class="text-red-600 text-sm">
238
+ This resource is already used by another repository.
239
+ </div>
240
+ {/if}
241
+ {#if gitSyncTestJob && gitSyncTestJob.status !== undefined}
242
+ <div class="flex text-sm gap-1 items-center">
243
+ {#if gitSyncTestJob.status === 'running'}
244
+ <RotateCw size={14} class="animate-spin" />
245
+ {:else if gitSyncTestJob.status === 'success'}
246
+ <CheckCircle2 size={14} class="text-green-600" />
247
+ {:else}
248
+ <XCircle size={14} class="text-red-700" />
249
+ {/if}
250
+ Git sync resource checked via Windmill job
251
+ <a
252
+ target="_blank"
253
+ href={`/run/${gitSyncTestJob.jobId}?workspace=${$workspaceStore}`}
254
+ class="text-blue-500 hover:underline"
98
255
  >
99
- {repo.legacyImported ? 'Migrate and save' : 'Save changes'}
100
- </Button>
101
- {#if gitSyncContext.initialRepositories[idx] && !repo.legacyImported}
256
+ {gitSyncTestJob.jobId}
257
+ </a>
258
+ <span class="text-secondary">WARNING: Only read permissions are verified.</span>
259
+ </div>
260
+ {/if}
261
+
262
+ <!-- Warnings -->
263
+ {#if repo.legacyImported}
264
+ <Alert type="warning" title="Legacy git sync settings imported">
265
+ This repository was initialized from workspace-level legacy Git-Sync settings. Review the filters and press <b>Save</b> to migrate.
266
+ </Alert>
267
+ {/if}
268
+
269
+ {#if repo.script_path != hubPaths.gitSync}
270
+ <Alert type="warning" title="Script version mismatch">
271
+ The git sync version for this repository is not latest. Current: <a
272
+ target="_blank"
273
+ href="https://hub.windmill.dev/scripts/windmill/6943/sync-script-to-git-repo-windmill/9014/versions"
274
+ >{repo.script_path}</a>, latest:
275
+ <a
276
+ target="_blank"
277
+ href="https://hub.windmill.dev/scripts/windmill/6943/sync-script-to-git-repo-windmill/9014/versions"
278
+ >{hubPaths.gitSync}</a>
279
+ <div class="flex mt-2">
102
280
  <Button
103
- color="light"
104
281
  size="xs"
105
- onclick={handleRevert}
106
- startIcon={{ icon: RotateCcw }}
282
+ color="dark"
283
+ onclick={() => {
284
+ if (repo) {
285
+ repo.script_path = hubPaths.gitSync
286
+ }
287
+ }}
107
288
  >
108
- Revert
289
+ Update git sync script (require save git settings to be applied)
109
290
  </Button>
110
- {/if}
111
- {/if}
112
- <button
113
- class="text-secondary hover:text-primary focus:outline-none"
114
- onclick={() => (repo.collapsed = !repo.collapsed)}
115
- aria-label="Toggle collapse"
291
+ </div>
292
+ </Alert>
293
+ {/if}
294
+
295
+ <!-- Configuration -->
296
+ {#if repo.isUnsavedConnection && !emptyString(repo.git_repo_resource_path) && idx !== null}
297
+ <DetectionFlow {idx} mode={variant === 'primary-promotion' || variant === 'legacy' ? 'promotion' : 'sync'} />
298
+ {:else}
299
+ <GitSyncFilterSettings
300
+ bind:git_repo_resource_path={repo.git_repo_resource_path}
301
+ bind:include_path={repo.settings.include_path}
302
+ bind:include_type={repo.settings.include_type}
303
+ bind:exclude_types_override={repo.exclude_types_override}
304
+ isLegacyRepo={repo.legacyImported}
305
+ bind:excludes={repo.settings.exclude_path}
306
+ bind:extraIncludes={repo.settings.extra_include_path}
307
+ isInitialSetup={false}
308
+ requiresMigration={repo.legacyImported}
309
+ useIndividualBranch={repo.use_individual_branch}
116
310
  >
117
- {#if repo.collapsed}
118
- <svg
119
- xmlns="http://www.w3.org/2000/svg"
120
- class="h-5 w-5"
121
- fill="none"
122
- viewBox="0 0 24 24"
123
- stroke="currentColor"
124
- >
125
- <path
126
- stroke-linecap="round"
127
- stroke-linejoin="round"
128
- stroke-width="2"
129
- d="M19 9l-7 7-7-7"
130
- />
131
- </svg>
132
- {:else}
133
- <svg
134
- xmlns="http://www.w3.org/2000/svg"
135
- class="h-5 w-5"
136
- fill="none"
137
- viewBox="0 0 24 24"
138
- stroke="currentColor"
139
- >
140
- <path
141
- stroke-linecap="round"
142
- stroke-linejoin="round"
143
- stroke-width="2"
144
- d="M5 15l7-7 7 7"
145
- />
146
- </svg>
147
- {/if}
148
- </button>
149
- {#if !confirmingDelete}
150
- <button
151
- transition:fade|local={{ duration: 100 }}
152
- class="rounded-full p-2 bg-surface-secondary duration-200 hover:bg-surface-hover"
153
- aria-label="Remove repository"
154
- onclick={initiateDelete}
155
- >
156
- <Trash size={14} />
157
- </button>
158
- {:else}
159
- <div class="flex gap-1">
160
- <button
161
- transition:fade|local={{ duration: 100 }}
162
- class="px-3 py-1 text-xs bg-red-500 text-white rounded duration-200 hover:bg-red-600"
163
- onclick={confirmDelete}
164
- >
165
- Confirm delete
166
- </button>
167
- <button
168
- transition:fade|local={{ duration: 100 }}
169
- class="px-2 py-1 text-xs bg-surface-secondary rounded duration-200 hover:bg-surface-hover"
170
- onclick={cancelDelete}
311
+ {#snippet actions()}
312
+ <Button
313
+ size="md"
314
+ onclick={handlePullSettings}
315
+ startIcon={{ icon: Download }}
171
316
  >
172
- <XCircle size={12} />
173
- </button>
174
- </div>
175
- {/if}
176
- </div>
177
- </div>
178
- {#if !repo.collapsed}
179
- <div class="px-4 py-2">
180
- <div class="flex mt-5 mb-1 gap-1">
181
- {#key repo}
182
- <div class="pt-1 font-semibold">Resource: </div>
183
- <ResourcePicker
184
- bind:value={repo.git_repo_resource_path}
185
- resourceType={'git_repository'}
186
- disabled={!repo.isUnsavedConnection}
187
- excludedValues={usedRepositoryPaths}
188
- />
189
- {#if !emptyString(repo.git_repo_resource_path)}
190
- <Button
191
- disabled={emptyString(repo.script_path)}
192
- color="dark"
193
- onclick={runGitSyncTestJob}
194
- size="xs">Test connection</Button
195
- >
196
- {/if}
197
- {/key}
198
- </div>
317
+ Pull settings
318
+ </Button>
319
+ {/snippet}
320
+ </GitSyncFilterSettings>
199
321
 
200
- {#if !emptyString(repo.git_repo_resource_path)}
201
- <div class="flex text-normal text-2xs gap-1">
202
- {#if validation.isDuplicate}
203
- <span class="text-red-600">This resource is already used by another repository.</span>
204
- {/if}
205
- {#if gitSyncTestJob && gitSyncTestJob.status !== undefined}
206
- {#if gitSyncTestJob.status === 'running'}
207
- <RotateCw size={14} class="animate-spin" />
208
- {:else if gitSyncTestJob.status === 'success'}
209
- <CheckCircle2 size={14} class="text-green-600" />
210
- {:else}
211
- <XCircle size={14} class="text-red-700" />
212
- {/if}
213
- Git sync resource checked via Windmill job
214
- <a
215
- target="_blank"
216
- href={`/run/${gitSyncTestJob.jobId}?workspace=${$workspaceStore}`}
217
- >
218
- {gitSyncTestJob.jobId}
219
- </a>WARNING: Only read permissions are verified.
220
- {/if}
322
+ {#if !repo.isUnsavedConnection}
323
+ <div class="flex justify-between items-start">
324
+ <!-- Display mode settings as prominent text -->
325
+ <div class="flex-1 mr-4">
326
+ <GitSyncModeDisplay
327
+ mode={variant === 'primary-promotion' || variant === 'legacy' ? 'promotion' : 'sync'}
328
+ {targetBranch}
329
+ repository={repo}
330
+ />
221
331
  </div>
222
332
 
223
- {#if repo.legacyImported}
224
- <Alert type="warning" title="Legacy git sync settings imported">
225
- This repository was initialized from workspace-level legacy Git-Sync settings. Review the filters and press <b>Save</b> to migrate.
226
- </Alert>
227
- {/if}
228
- <div class="flex flex-col mb-1 gap-4">
229
- {#if repo}
230
- {#if repo.script_path != hubPaths.gitSync}
231
- <Alert type="warning" title="Script version mismatch">
232
- The git sync version for this repository is not latest. Current: <a
233
- target="_blank"
234
- href="https://hub.windmill.dev/scripts/windmill/6943/sync-script-to-git-repo-windmill/9014/versions"
235
- >{repo.script_path}</a
236
- >, latest:
237
- <a
238
- target="_blank"
239
- href="https://hub.windmill.dev/scripts/windmill/6943/sync-script-to-git-repo-windmill/9014/versions"
240
- >{hubPaths.gitSync}</a
333
+ <!-- Manual sync section for existing repos -->
334
+ {#if !emptyString(repo.git_repo_resource_path) && !repo.legacyImported}
335
+ <div class="flex flex-col">
336
+ <div class="text-sm text-secondary mb-2">Manual workspace content sync</div>
337
+ <div class="flex gap-2">
338
+ <Button
339
+ size="xs"
340
+ color="dark"
341
+ variant="border"
342
+ onclick={() => idx !== null && gitSyncContext.showPullModal(idx)}
343
+ startIcon={{ icon: Download }}
241
344
  >
242
- <div class="flex mt-2">
243
- <Button
244
- size="xs"
245
- color="dark"
246
- onclick={() => {
247
- if (repo) {
248
- repo.script_path = hubPaths.gitSync
249
- }
250
- }}
251
- >Update git sync script (require save git settings to be applied)</Button
252
- >
253
- </div>
254
- </Alert>
255
- {/if}
256
- {#if repo.isUnsavedConnection && !emptyString(repo.git_repo_resource_path)}
257
- <!-- Use DetectionFlow component -->
258
- <div class="mt-4">
259
- <DetectionFlow {idx} />
260
- </div>
261
- {:else}
262
- <!-- Existing saved connection flow -->
263
- <GitSyncFilterSettings
264
- bind:git_repo_resource_path={repo.git_repo_resource_path}
265
- bind:include_path={repo.settings.include_path}
266
- bind:include_type={repo.settings.include_type}
267
- bind:exclude_types_override={repo.exclude_types_override}
268
- isLegacyRepo={repo.legacyImported}
269
- bind:excludes={repo.settings.exclude_path}
270
- bind:extraIncludes={repo.settings.extra_include_path}
271
- isInitialSetup={false}
272
- requiresMigration={repo.legacyImported}
273
- useIndividualBranch={repo.use_individual_branch}
274
- >
275
- {#snippet actions()}
276
- <Button
277
- size="md"
278
- onclick={handlePullSettings}
279
- startIcon={{ icon: Download }}
280
- >
281
- Pull settings
282
- </Button>
283
- {/snippet}
284
- </GitSyncFilterSettings>
285
- {/if}
286
- {#if !repo.isUnsavedConnection}
287
- <div class="flex justify-between items-start">
288
- <!-- Display mode settings as prominent text -->
289
- <div class="text-base flex-1 mr-4">
290
- {#if repo.use_individual_branch}
291
- <div><span class="font-bold">Promotion:</span> Creating branches whose promotion target is main</div>
292
- {#if repo.group_by_folder}
293
- <div class="text-sm text-tertiary mt-1">Grouped by folder</div>
294
- {/if}
295
- {:else}
296
- <div>Sync: <span class="font-bold">Syncing back to branch main</span></div>
297
- {/if}
298
- </div>
299
-
300
- <!-- Manual sync section for existing repos -->
301
- {#if !emptyString(repo.git_repo_resource_path) && !repo.legacyImported}
302
- <div class="flex flex-col">
303
- <div class="text-sm text-secondary mb-2">Manual workspace content sync</div>
304
- <div class="flex gap-2">
305
- <Button
306
- size="xs"
307
- color="dark"
308
- variant="border"
309
- onclick={() => gitSyncContext.showPullModal(idx)}
310
- startIcon={{ icon: Download }}
311
- >
312
- Pull from repo
313
- </Button>
314
- <Button
315
- size="xs"
316
- color="dark"
317
- variant="border"
318
- onclick={() => gitSyncContext.showPushModal(idx)}
319
- startIcon={{ icon: Upload }}
320
- >
321
- Push to repo
322
- </Button>
323
- </div>
324
- </div>
325
- {/if}
345
+ Pull from repo
346
+ </Button>
347
+ <Button
348
+ size="xs"
349
+ color="dark"
350
+ variant="border"
351
+ onclick={() => idx !== null && gitSyncContext.showPushModal(idx)}
352
+ startIcon={{ icon: Upload }}
353
+ >
354
+ Push to repo
355
+ </Button>
326
356
  </div>
327
-
328
- {/if}
329
-
357
+ </div>
330
358
  {/if}
331
359
  </div>
332
- {:else}
333
- <div class="text-xs text-tertiary pt-1 pl-8">Please select a Git repository resource.</div>
334
360
  {/if}
335
- </div>
361
+ {/if}
362
+ {:else}
363
+ <div class="text-xs text-tertiary">Please select a Git repository resource.</div>
336
364
  {/if}
337
365
  </div>
338
- {/if}
366
+ {/snippet}
367
+
368
+ <!-- Main component rendering -->
369
+
370
+ {#if shouldShowEmptyState}
371
+ <!-- Empty State for Primary Variants -->
372
+ <div class="rounded-lg border bg-surface p-4 mb-4">
373
+ <div class="flex items-center justify-between mb-4">
374
+ <div class="flex flex-col">
375
+ <h3 class="text-xl font-semibold">{displayTitle}</h3>
376
+ {#if displayDescription}
377
+ <p class="text-sm text-secondary">{displayDescription}</p>
378
+ {/if}
379
+ </div>
380
+ </div>
381
+
382
+ <div class="flex flex-col items-center justify-center py-8 px-4 border-2 border-dashed rounded-md">
383
+ <div class="text-center mb-4">
384
+ <p class="text-secondary mb-2">
385
+ {#if mode === 'sync'}
386
+ No sync repository configured. Add one to enable direct synchronization.
387
+ {:else if mode === 'promotion'}
388
+ No promotion repository configured. Add one to enable branch-based workflows.
389
+ {:else}
390
+ No repository configured.
391
+ {/if}
392
+ </p>
393
+ </div>
394
+ {#if onAdd}
395
+ <Button
396
+ size="md"
397
+ color="dark"
398
+ variant="border"
399
+ startIcon={{ icon: Plus }}
400
+ onclick={onAdd}
401
+ >
402
+ Add {mode || 'repository'} repository
403
+ </Button>
404
+ {/if}
405
+ </div>
406
+ </div>
407
+ {:else if repo}
408
+ {#if variant === 'primary-sync' || variant === 'primary-promotion'}
409
+ <!-- Primary Repository Layout -->
410
+ <div class="rounded-lg border bg-surface p-4 mb-4">
411
+ <div class="flex items-center justify-between mb-4">
412
+ <div class="flex flex-col">
413
+ <h3 class="text-xl font-semibold">{displayTitle}</h3>
414
+ {#if displayDescription}
415
+ <p class="text-sm text-secondary">{displayDescription}</p>
416
+ {/if}
417
+ </div>
418
+ <div class="flex items-center gap-2">
419
+ {@render headerActions()}
420
+ </div>
421
+ </div>
422
+ {@render repositoryContent()}
423
+ </div>
424
+ {:else}
425
+ <!-- Standard Repository Card Layout -->
426
+ <div class="rounded-lg shadow-sm border p-0 w-full mb-4">
427
+ <div class="flex items-center justify-between min-h-10 px-4 py-1 border-b">
428
+ <div class="flex items-center gap-2">
429
+ <span class="text-lg font-semibold">{displayTitle}</span>
430
+ {#if repo.legacyImported}
431
+ <span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-orange-100 text-orange-800 border border-orange-200">
432
+ Legacy Configuration
433
+ </span>
434
+ {/if}
435
+ <span class="text-xs text-tertiary pt-1 pl-8">
436
+ {repo.git_repo_resource_path}
437
+ </span>
438
+ </div>
439
+ <div class="flex items-center gap-2">
440
+ {@render headerActions()}
441
+ </div>
442
+ </div>
443
+ {#if !repo.collapsed}
444
+ <div class="px-4 py-2">
445
+ {@render repositoryContent()}
446
+ </div>
447
+ {/if}
448
+ </div>
449
+ {/if}
450
+ {/if}