windmill-components 1.504.6 → 1.510.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.
- package/package/ata/index.js +1 -1
- package/package/components/AppConnectInner.svelte +161 -29
- package/package/components/ArgInput.svelte +33 -103
- package/package/components/AuthSettings.svelte +45 -1
- package/package/components/Dev.svelte +31 -24
- package/package/components/DisplayResult.svelte +53 -26
- package/package/components/DisplayResult.svelte.d.ts +1 -1
- package/package/components/DynSelect.svelte +3 -3
- package/package/components/Editor.svelte +7 -4
- package/package/components/EditorBar.svelte +2 -2
- package/package/components/ErrorOrRecoveryHandler.svelte +73 -67
- package/package/components/ErrorOrRecoveryHandler.svelte.d.ts +8 -24
- package/package/components/FlowBuilder.svelte +11 -2
- package/package/components/FlowJobResult.svelte +12 -17
- package/package/components/FlowJobResult.svelte.d.ts +5 -18
- package/package/components/FlowPreviewContent.svelte +13 -10
- package/package/components/FlowPreviewContent.svelte.d.ts +1 -1
- package/package/components/FlowPreviewResult.svelte +14 -6
- package/package/components/FlowStatusViewer.svelte +11 -24
- package/package/components/FlowStatusViewer.svelte.d.ts +19 -18
- package/package/components/FlowStatusViewerInner.svelte +110 -131
- package/package/components/FlowStatusViewerInner.svelte.d.ts +20 -18
- package/package/components/GitDiffPreview.svelte +55 -0
- package/package/components/GitDiffPreview.svelte.d.ts +13 -0
- package/package/components/HistoricInputs.svelte +2 -2
- package/package/components/InitGitRepoPopover.svelte +410 -0
- package/package/components/InitGitRepoPopover.svelte.d.ts +13 -0
- package/package/components/InstanceSetting.svelte +21 -9
- package/package/components/InstanceSettings.svelte +16 -3
- package/package/components/JobLoader.svelte +567 -0
- package/package/components/JobLoader.svelte.d.ts +53 -0
- package/package/components/JobLogs.svelte +6 -4
- package/package/components/JobLogs.svelte.d.ts +5 -18
- package/package/components/LightweightResourcePicker.svelte +18 -39
- package/package/components/LightweightResourcePicker.svelte.d.ts +6 -22
- package/package/components/LogViewer.svelte +35 -41
- package/package/components/LogViewer.svelte.d.ts +6 -20
- package/package/components/ModulePreviewResultViewer.svelte +3 -1
- package/package/components/ModulePreviewResultViewer.svelte.d.ts +1 -0
- package/package/components/ModuleTest.svelte +16 -11
- package/package/components/PullGitRepoPopover.svelte +355 -0
- package/package/components/PullGitRepoPopover.svelte.d.ts +18 -0
- package/package/components/S3FilePicker.svelte +5 -3
- package/package/components/SavedInputs.svelte +2 -2
- package/package/components/ScriptBuilder.svelte +4 -3
- package/package/components/ScriptEditor.svelte +34 -31
- package/package/components/ScriptEditor.svelte.d.ts +3 -3
- package/package/components/ServiceLogsInner.svelte +2 -1
- package/package/components/ServiceLogsInner.svelte.d.ts +1 -0
- package/package/components/UserSettings.svelte +1 -1
- package/package/components/WorkerTagSelect.svelte +32 -3
- package/package/components/apps/components/buttons/AppButton.svelte +7 -1
- package/package/components/apps/components/buttons/AppButton.svelte.d.ts +1 -0
- package/package/components/apps/components/display/AppCustomComponent.svelte +1 -1
- package/package/components/apps/components/display/AppDisplayComponentByJobId.svelte +16 -11
- package/package/components/apps/components/display/AppJobIdLogComponent.svelte +13 -10
- package/package/components/apps/components/display/AppMenu.svelte +5 -0
- package/package/components/apps/components/display/dbtable/AppDbExplorer.svelte +3 -3
- package/package/components/apps/components/display/dbtable/DeleteRow.svelte +3 -3
- package/package/components/apps/components/display/dbtable/InsertRowRunnable.svelte +3 -3
- package/package/components/apps/components/display/dbtable/UpdateCell.svelte +3 -3
- package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte +3 -3
- package/package/components/apps/components/helpers/RunnableComponent.svelte +65 -54
- package/package/components/apps/components/helpers/RunnableComponent.svelte.d.ts +5 -5
- package/package/components/apps/components/inputs/AppUserResource.svelte +26 -8
- package/package/components/apps/editor/AppEditorHeader.svelte +11 -5
- package/package/components/apps/editor/AppJobsDrawer.svelte +5 -5
- package/package/components/apps/editor/RunnableJobPanel.svelte +4 -4
- package/package/components/apps/editor/component/components.d.ts +12 -0
- package/package/components/apps/editor/component/components.js +19 -7
- package/package/components/assets/AssetButtons.svelte +38 -0
- package/package/components/assets/AssetButtons.svelte.d.ts +15 -0
- package/package/components/assets/AssetsDropdownButton.svelte +60 -72
- package/package/components/assets/AssetsDropdownButton.svelte.d.ts +3 -4
- package/package/components/assets/AssetsUsageDrawer.svelte +10 -10
- package/package/components/assets/JobAssetsViewer.svelte +79 -0
- package/package/components/assets/JobAssetsViewer.svelte.d.ts +7 -0
- package/package/components/assets/README_DEV.md +0 -0
- package/package/components/assets/lib.d.ts +9 -1
- package/package/components/assets/lib.js +48 -7
- package/package/components/common/fileUpload/FileUpload.svelte +126 -84
- package/package/components/common/fileUpload/FileUpload.svelte.d.ts +13 -3
- package/package/components/common/fileUpload/S3ArgInput.svelte +111 -0
- package/package/components/common/fileUpload/S3ArgInput.svelte.d.ts +21 -0
- package/package/components/common/table/ScriptRow.svelte +3 -1
- package/package/components/copilot/autocomplete/Autocompletor.js +23 -5
- package/package/components/copilot/chat/AIChatDisplay.svelte +8 -0
- package/package/components/copilot/chat/AIChatManager.svelte.js +13 -8
- package/package/components/copilot/chat/flow/ModuleAcceptReject.svelte +5 -5
- package/package/components/copilot/chat/flow/core.d.ts +1 -1
- package/package/components/copilot/chat/flow/core.js +2 -38
- package/package/components/copilot/chat/navigator/apiTools.d.ts +8 -0
- package/package/components/copilot/chat/navigator/apiTools.js +95 -15
- package/package/components/copilot/chat/navigator/core.d.ts +1 -1
- package/package/components/copilot/chat/navigator/core.js +2 -1
- package/package/components/copilot/chat/script/core.d.ts +11 -2
- package/package/components/copilot/chat/script/core.js +135 -1
- package/package/components/copilot/chat/shared.d.ts +10 -0
- package/package/components/copilot/chat/shared.js +56 -0
- package/package/components/copilot/lib.d.ts +1 -0
- package/package/components/copilot/lib.js +27 -9
- package/package/components/custom_ui.d.ts +1 -0
- package/package/components/flows/FlowAssetsHandler.svelte +133 -0
- package/package/components/flows/FlowAssetsHandler.svelte.d.ts +14 -0
- package/package/components/flows/content/FlowModuleComponent.svelte +16 -18
- package/package/components/flows/flowStore.d.ts +1 -1
- package/package/components/flows/map/FlowModuleSchemaItem.svelte +1 -0
- package/package/components/flows/propPicker/OutputPicker.svelte +9 -4
- package/package/components/flows/scheduleUtils.js +1 -1
- package/package/components/flows/types.d.ts +2 -1
- package/package/components/graph/FlowGraphV2.svelte +8 -104
- package/package/components/graph/FlowGraphV2.svelte.d.ts +0 -2
- package/package/components/graph/graphBuilder.svelte.d.ts +6 -3
- package/package/components/graph/graphBuilder.svelte.js +35 -9
- package/package/components/graph/renderers/edges/BaseEdge.svelte +2 -5
- package/package/components/graph/renderers/edges/BaseEdge.svelte.d.ts +1 -0
- package/package/components/graph/renderers/nodes/AssetNode.svelte +23 -20
- package/package/components/graph/renderers/nodes/AssetNode.svelte.d.ts +5 -10
- package/package/components/graph/renderers/nodes/AssetsOverflowedNode.svelte +1 -1
- package/package/components/graph/util.js +1 -1
- package/package/components/home/ItemsList.svelte +2 -0
- package/package/components/icons/AssetGenericIcon.svelte +0 -3
- package/package/components/jobs/JobPreview.svelte +10 -6
- package/package/components/raw_apps/RawAppInlineScriptRunnable.svelte +13 -12
- package/package/components/runs/BatchReRunOptionsPane.svelte +5 -1
- package/package/components/runs/JobPreview.svelte +26 -16
- package/package/components/runs/{JobLoader.svelte.d.ts → JobsLoader.svelte.d.ts} +3 -3
- package/package/components/runs/NoWorkerWithTagWarning.svelte +2 -2
- package/package/components/runs/NoWorkerWithTagWarning.svelte.d.ts +1 -0
- package/package/components/runs/RunsFilter.svelte.d.ts +1 -1
- package/package/components/scriptEditor/LogPanel.svelte +3 -2
- package/package/components/script_builder.d.ts +2 -2
- package/package/components/settings/CreateToken.svelte +76 -41
- package/package/components/settings/CreateToken.svelte.d.ts +1 -1
- package/package/components/settings/ScopeSelector.svelte +613 -0
- package/package/components/settings/ScopeSelector.svelte.d.ts +8 -0
- package/package/components/settings/TokenDisplay.svelte +103 -0
- package/package/components/settings/TokenDisplay.svelte.d.ts +10 -0
- package/package/components/settings/TokensTable.svelte +70 -349
- package/package/components/sidebar/CriticalAlertModal.svelte +3 -0
- package/package/components/triggers/DeleteTriggerButton.svelte +1 -1
- package/package/components/triggers/TriggerEditorToolbar.svelte +3 -3
- package/package/components/triggers/TriggerRetriesAndErrorHandler.svelte +55 -0
- package/package/components/triggers/TriggerRetriesAndErrorHandler.svelte.d.ts +13 -0
- package/package/components/triggers/TriggersEditor.svelte +45 -3
- package/package/components/triggers/TriggersWrapper.svelte +2 -2
- package/package/components/triggers/gcp/GcpTriggerEditorInner.svelte +43 -2
- package/package/components/triggers/gcp/utils.js +9 -1
- package/package/components/triggers/http/OpenAPISpecGenerator.svelte +1 -0
- package/package/components/triggers/http/RouteEditorInner.svelte +208 -164
- package/package/components/triggers/http/RouteEditorInner.svelte.d.ts +6 -2
- package/package/components/triggers/http/utils.js +9 -3
- package/package/components/triggers/kafka/KafkaTriggerEditorInner.svelte +43 -2
- package/package/components/triggers/kafka/utils.js +9 -1
- package/package/components/triggers/mqtt/MqttEditorConfigSection.svelte +4 -132
- package/package/components/triggers/mqtt/MqttEditorConfigSection.svelte.d.ts +2 -5
- package/package/components/triggers/mqtt/MqttTriggerEditorInner.svelte +178 -9
- package/package/components/triggers/mqtt/utils.js +9 -1
- package/package/components/triggers/nats/NatsTriggerEditorInner.svelte +43 -2
- package/package/components/triggers/nats/utils.js +9 -1
- package/package/components/triggers/postgres/PostgresTriggerEditorInner.svelte +41 -2
- package/package/components/triggers/postgres/utils.js +9 -1
- package/package/components/triggers/schedules/ScheduleEditorInner.svelte +34 -88
- package/package/components/triggers/sqs/SqsTriggerEditorInner.svelte +43 -2
- package/package/components/triggers/sqs/utils.js +9 -1
- package/package/components/triggers/utils.js +12 -0
- package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +43 -2
- package/package/components/triggers/websocket/utils.js +11 -1
- package/package/components/workspaceSettings/AISettings.svelte +0 -2
- package/package/components/workspaceSettings/FilterList.svelte +56 -0
- package/package/components/workspaceSettings/FilterList.svelte.d.ts +8 -0
- package/package/components/workspaceSettings/GitSyncFilterSettings.svelte +785 -0
- package/package/components/workspaceSettings/GitSyncFilterSettings.svelte.d.ts +18 -0
- package/package/gen/core/OpenAPI.js +1 -1
- package/package/gen/schemas.gen.d.ts +305 -23
- package/package/gen/schemas.gen.js +305 -23
- package/package/gen/services.gen.d.ts +33 -1
- package/package/gen/services.gen.js +66 -2
- package/package/gen/types.gen.d.ts +216 -11
- package/package/history.svelte.js +0 -2
- package/package/hub.d.ts +1 -0
- package/package/hubPaths.json +5 -2
- package/package/infer.js +16 -10
- package/package/svelte5Utils.svelte.d.ts +1 -0
- package/package/svelte5Utils.svelte.js +25 -18
- package/package/toast.js +10 -0
- package/package/utils.d.ts +3 -2
- package/package/utils.js +20 -5
- package/package.json +11 -11
- package/package/components/ResultJobLoader.svelte +0 -219
- package/package/components/ResultJobLoader.svelte.d.ts +0 -52
- package/package/components/TestJobLoader.svelte +0 -274
- package/package/components/TestJobLoader.svelte.d.ts +0 -43
- package/package/components/icons/AssetVarIcon.svelte +0 -31
- package/package/components/icons/AssetVarIcon.svelte.d.ts +0 -9
- /package/package/components/runs/{JobLoader.svelte → JobsLoader.svelte} +0 -0
|
@@ -0,0 +1,785 @@
|
|
|
1
|
+
<script lang="ts">import Toggle from '../Toggle.svelte';
|
|
2
|
+
import { Filter, Save, Eye, Loader2, CheckCircle2, XCircle, Check } from 'lucide-svelte';
|
|
3
|
+
import Tooltip from '../Tooltip.svelte';
|
|
4
|
+
import yaml from 'js-yaml';
|
|
5
|
+
import hubPaths from '../../hubPaths.json';
|
|
6
|
+
import { JobService } from '../../gen';
|
|
7
|
+
import { workspaceStore } from '../../stores';
|
|
8
|
+
import { Button } from '../common';
|
|
9
|
+
import { sendUserToast } from '../../toast';
|
|
10
|
+
import FilterList from './FilterList.svelte';
|
|
11
|
+
import { Tabs, Tab } from '../common';
|
|
12
|
+
let { git_repo_resource_path = $bindable(''), include_path = $bindable(['f/**']), include_type = $bindable(['script', 'flow', 'app', 'folder']), exclude_types_override = $bindable([]), isLegacyRepo = false, yamlText = $bindable(''), onSettingsChange = (settings) => { }, excludes = $bindable([]), extraIncludes = $bindable([]) } = $props();
|
|
13
|
+
// Component state
|
|
14
|
+
let collapsed = $state(false);
|
|
15
|
+
let editAsYaml = $state(false);
|
|
16
|
+
let yamlError = $state('');
|
|
17
|
+
let isPullMode = $state(false);
|
|
18
|
+
// Preview/Push state
|
|
19
|
+
let previewResult = $state(null);
|
|
20
|
+
let previewJobId = $state(null);
|
|
21
|
+
let previewJobStatus = $state(undefined);
|
|
22
|
+
let pushJobId = $state(null);
|
|
23
|
+
let pushJobStatus = $state(undefined);
|
|
24
|
+
let isPreviewLoading = $state(false);
|
|
25
|
+
let isPushing = $state(false);
|
|
26
|
+
let previewError = $state('');
|
|
27
|
+
let previewSettingsSnapshot = $state(null);
|
|
28
|
+
// Compute effective include types (include_type minus exclude_types_override for legacy repos only)
|
|
29
|
+
const effectiveIncludeTypes = $derived(isLegacyRepo
|
|
30
|
+
? include_type.filter((type) => !exclude_types_override.includes(type))
|
|
31
|
+
: include_type);
|
|
32
|
+
// Compute type toggles from effective include types
|
|
33
|
+
const typeToggles = $derived({
|
|
34
|
+
scripts: effectiveIncludeTypes.includes('script'),
|
|
35
|
+
flows: effectiveIncludeTypes.includes('flow'),
|
|
36
|
+
apps: effectiveIncludeTypes.includes('app'),
|
|
37
|
+
folders: effectiveIncludeTypes.includes('folder'),
|
|
38
|
+
resourceTypes: effectiveIncludeTypes.includes('resourcetype'),
|
|
39
|
+
resources: effectiveIncludeTypes.includes('resource'),
|
|
40
|
+
variables: effectiveIncludeTypes.includes('variable'),
|
|
41
|
+
secrets: effectiveIncludeTypes.includes('secret'),
|
|
42
|
+
schedules: effectiveIncludeTypes.includes('schedule'),
|
|
43
|
+
users: effectiveIncludeTypes.includes('user'),
|
|
44
|
+
groups: effectiveIncludeTypes.includes('group'),
|
|
45
|
+
triggers: effectiveIncludeTypes.includes('trigger'),
|
|
46
|
+
settings: effectiveIncludeTypes.includes('settings'),
|
|
47
|
+
key: effectiveIncludeTypes.includes('key')
|
|
48
|
+
});
|
|
49
|
+
// Tab selection for filter kinds
|
|
50
|
+
let filtersTab = $state('includes');
|
|
51
|
+
function updateIncludeType(key, value) {
|
|
52
|
+
const newTypes = new Set(include_type);
|
|
53
|
+
const typeMap = {
|
|
54
|
+
scripts: 'script',
|
|
55
|
+
flows: 'flow',
|
|
56
|
+
apps: 'app',
|
|
57
|
+
folders: 'folder',
|
|
58
|
+
resourceTypes: 'resourcetype',
|
|
59
|
+
resources: 'resource',
|
|
60
|
+
variables: 'variable',
|
|
61
|
+
secrets: 'secret',
|
|
62
|
+
schedules: 'schedule',
|
|
63
|
+
users: 'user',
|
|
64
|
+
groups: 'group',
|
|
65
|
+
triggers: 'trigger',
|
|
66
|
+
settings: 'settings',
|
|
67
|
+
key: 'key'
|
|
68
|
+
};
|
|
69
|
+
if (value) {
|
|
70
|
+
newTypes.add(typeMap[key]);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
newTypes.delete(typeMap[key]);
|
|
74
|
+
if (key === 'variables') {
|
|
75
|
+
newTypes.delete('secret');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
include_type = Array.from(newTypes);
|
|
79
|
+
}
|
|
80
|
+
function capitalize(str) {
|
|
81
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
82
|
+
}
|
|
83
|
+
// Simple JSON-based UI state helper
|
|
84
|
+
function getUIState() {
|
|
85
|
+
return {
|
|
86
|
+
include_path,
|
|
87
|
+
exclude_path: excludes,
|
|
88
|
+
extra_include_path: extraIncludes,
|
|
89
|
+
include_type
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Apply settings from backend format (used by both local git repo and backend settings)
|
|
93
|
+
function fromBackendFormat(settings) {
|
|
94
|
+
include_path = settings.include_path || [];
|
|
95
|
+
excludes = settings.exclude_path || [];
|
|
96
|
+
extraIncludes = settings.extra_include_path || [];
|
|
97
|
+
include_type = settings.include_type || [];
|
|
98
|
+
}
|
|
99
|
+
// Simplified YAML parsing for manual editing
|
|
100
|
+
function fromYaml(yamlStr) {
|
|
101
|
+
yamlError = '';
|
|
102
|
+
try {
|
|
103
|
+
const parsed = yaml.load(yamlStr);
|
|
104
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
105
|
+
throw new Error('Invalid YAML structure');
|
|
106
|
+
}
|
|
107
|
+
const obj = parsed;
|
|
108
|
+
yamlText = yamlStr;
|
|
109
|
+
// Extract includes - reset to default if not present
|
|
110
|
+
if (obj.includes && Array.isArray(obj.includes)) {
|
|
111
|
+
include_path = obj.includes.map((p) => {
|
|
112
|
+
if (typeof p !== 'string') {
|
|
113
|
+
throw new Error('includes must contain only strings');
|
|
114
|
+
}
|
|
115
|
+
// Handle quoted strings
|
|
116
|
+
if (/^['"].*['"]$/.test(p)) {
|
|
117
|
+
return p.slice(1, -1).replace(/''/g, "'");
|
|
118
|
+
}
|
|
119
|
+
return p;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
// Reset to default if includes is not present
|
|
124
|
+
include_path = ['f/**'];
|
|
125
|
+
}
|
|
126
|
+
// Build the type set based on the YAML flags
|
|
127
|
+
const newTypes = new Set();
|
|
128
|
+
// Always include core types (these are fundamental and not controlled by flags)
|
|
129
|
+
newTypes.add('script');
|
|
130
|
+
newTypes.add('flow');
|
|
131
|
+
newTypes.add('app');
|
|
132
|
+
newTypes.add('folder');
|
|
133
|
+
// Handle skip flags (if skipX is false or undefined, include the type)
|
|
134
|
+
if (obj.skipResourceTypes !== true)
|
|
135
|
+
newTypes.add('resourcetype');
|
|
136
|
+
if (obj.skipResources !== true)
|
|
137
|
+
newTypes.add('resource');
|
|
138
|
+
if (obj.skipVariables !== true)
|
|
139
|
+
newTypes.add('variable');
|
|
140
|
+
if (obj.skipSecrets !== true)
|
|
141
|
+
newTypes.add('secret');
|
|
142
|
+
// Handle include flags (if includeX is true, include the type)
|
|
143
|
+
if (obj.includeSchedules === true)
|
|
144
|
+
newTypes.add('schedule');
|
|
145
|
+
if (obj.includeTriggers === true)
|
|
146
|
+
newTypes.add('trigger');
|
|
147
|
+
if (obj.includeUsers === true)
|
|
148
|
+
newTypes.add('user');
|
|
149
|
+
if (obj.includeGroups === true)
|
|
150
|
+
newTypes.add('group');
|
|
151
|
+
if (obj.includeSettings === true)
|
|
152
|
+
newTypes.add('settings');
|
|
153
|
+
if (obj.includeKey === true)
|
|
154
|
+
newTypes.add('key');
|
|
155
|
+
// Apply business rule: secrets can only be included if variables are included
|
|
156
|
+
// This matches the UI behavior where turning off variables also turns off secrets
|
|
157
|
+
if (!newTypes.has('variable')) {
|
|
158
|
+
newTypes.delete('secret');
|
|
159
|
+
}
|
|
160
|
+
include_type = Array.from(newTypes);
|
|
161
|
+
}
|
|
162
|
+
catch (e) {
|
|
163
|
+
yamlError = e.message || 'Invalid YAML';
|
|
164
|
+
console.error('Error parsing YAML:', e);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Simple YAML generation for manual editing mode
|
|
168
|
+
function generateYamlFromUI() {
|
|
169
|
+
try {
|
|
170
|
+
const validIncludePath = include_path;
|
|
171
|
+
const validExcludePath = excludes;
|
|
172
|
+
const validExtraInclude = extraIncludes;
|
|
173
|
+
// Basic YAML structure - let the CLI handle the proper normalization
|
|
174
|
+
let config = {
|
|
175
|
+
includes: validIncludePath,
|
|
176
|
+
excludes: validExcludePath,
|
|
177
|
+
extraIncludes: validExtraInclude,
|
|
178
|
+
codebases: []
|
|
179
|
+
};
|
|
180
|
+
// Let the CLI handle the optimization of skip/include flags
|
|
181
|
+
// Just convert the UI state directly
|
|
182
|
+
if (!include_type.includes('variable'))
|
|
183
|
+
config.skipVariables = true;
|
|
184
|
+
if (!include_type.includes('resource'))
|
|
185
|
+
config.skipResources = true;
|
|
186
|
+
if (!include_type.includes('secret'))
|
|
187
|
+
config.skipSecrets = true;
|
|
188
|
+
if (!include_type.includes('resourcetype'))
|
|
189
|
+
config.skipResourceTypes = true;
|
|
190
|
+
if (include_type.includes('schedule'))
|
|
191
|
+
config.includeSchedules = true;
|
|
192
|
+
if (include_type.includes('trigger'))
|
|
193
|
+
config.includeTriggers = true;
|
|
194
|
+
if (include_type.includes('user'))
|
|
195
|
+
config.includeUsers = true;
|
|
196
|
+
if (include_type.includes('group'))
|
|
197
|
+
config.includeGroups = true;
|
|
198
|
+
if (include_type.includes('settings'))
|
|
199
|
+
config.includeSettings = true;
|
|
200
|
+
if (include_type.includes('key'))
|
|
201
|
+
config.includeKey = true;
|
|
202
|
+
return yaml.dump(config, {
|
|
203
|
+
indent: 2,
|
|
204
|
+
lineWidth: -1,
|
|
205
|
+
quotingType: '"',
|
|
206
|
+
forceQuotes: false,
|
|
207
|
+
noRefs: true
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
catch (e) {
|
|
211
|
+
console.warn('Failed to generate YAML:', e);
|
|
212
|
+
yamlError = e.message || 'Failed to generate YAML';
|
|
213
|
+
return `includes:
|
|
214
|
+
- f/**
|
|
215
|
+
excludes: []
|
|
216
|
+
extraIncludes: []
|
|
217
|
+
codebases: []`;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function switchToYaml() {
|
|
221
|
+
yamlText = generateYamlFromUI();
|
|
222
|
+
yamlError = '';
|
|
223
|
+
editAsYaml = true;
|
|
224
|
+
}
|
|
225
|
+
function switchToUI() {
|
|
226
|
+
fromYaml(yamlText);
|
|
227
|
+
if (!yamlError) {
|
|
228
|
+
editAsYaml = false;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Simplified preview function - always uses JSON approach
|
|
232
|
+
async function previewFiltersToGitRepo() {
|
|
233
|
+
isPreviewLoading = true;
|
|
234
|
+
previewError = '';
|
|
235
|
+
previewResult = null;
|
|
236
|
+
previewJobId = null;
|
|
237
|
+
previewJobStatus = undefined;
|
|
238
|
+
// Take a snapshot of current settings
|
|
239
|
+
previewSettingsSnapshot = JSON.stringify({
|
|
240
|
+
include_path,
|
|
241
|
+
excludes,
|
|
242
|
+
extraIncludes,
|
|
243
|
+
include_type
|
|
244
|
+
});
|
|
245
|
+
try {
|
|
246
|
+
const workspace = $workspaceStore;
|
|
247
|
+
if (!workspace)
|
|
248
|
+
return;
|
|
249
|
+
// Always pass UI state as JSON - the backend now handles this uniformly
|
|
250
|
+
const payloadObj = {
|
|
251
|
+
workspace_id: workspace,
|
|
252
|
+
repo_url_resource_path: git_repo_resource_path,
|
|
253
|
+
only_wmill_yaml: true,
|
|
254
|
+
dry_run: true,
|
|
255
|
+
pull: isPullMode,
|
|
256
|
+
settings_json: JSON.stringify(getUIState())
|
|
257
|
+
};
|
|
258
|
+
const jobId = await JobService.runScriptByPath({
|
|
259
|
+
workspace,
|
|
260
|
+
path: hubPaths.gitInitRepo,
|
|
261
|
+
requestBody: payloadObj,
|
|
262
|
+
skipPreprocessor: true
|
|
263
|
+
});
|
|
264
|
+
previewJobId = jobId;
|
|
265
|
+
previewJobStatus = 'running';
|
|
266
|
+
let jobSuccess = false;
|
|
267
|
+
let result = {};
|
|
268
|
+
await (await import('../../utils')).tryEvery({
|
|
269
|
+
tryCode: async () => {
|
|
270
|
+
const testResult = await JobService.getCompletedJob({ workspace, id: jobId });
|
|
271
|
+
jobSuccess = !!testResult.success;
|
|
272
|
+
if (jobSuccess) {
|
|
273
|
+
const jobResult = await JobService.getCompletedJobResult({ workspace, id: jobId });
|
|
274
|
+
result = jobResult;
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
timeoutCode: async () => {
|
|
278
|
+
try {
|
|
279
|
+
await JobService.cancelQueuedJob({
|
|
280
|
+
workspace,
|
|
281
|
+
id: jobId,
|
|
282
|
+
requestBody: { reason: 'Preview job timed out after 5s' }
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
catch (err) { }
|
|
286
|
+
},
|
|
287
|
+
interval: 500,
|
|
288
|
+
timeout: 10000
|
|
289
|
+
});
|
|
290
|
+
previewJobStatus = jobSuccess ? 'success' : 'failure';
|
|
291
|
+
if (jobSuccess) {
|
|
292
|
+
previewResult = result;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
previewError = 'Preview failed';
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
catch (e) {
|
|
299
|
+
previewJobStatus = 'failure';
|
|
300
|
+
previewError = e?.message || 'Preview failed';
|
|
301
|
+
previewResult = null;
|
|
302
|
+
}
|
|
303
|
+
finally {
|
|
304
|
+
isPreviewLoading = false;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// Simplified push function - always uses JSON approach
|
|
308
|
+
async function pushFiltersToGitRepo() {
|
|
309
|
+
if (isPullMode) {
|
|
310
|
+
// In pull mode, apply the local settings (from git repo) to UI
|
|
311
|
+
if (previewResult?.local) {
|
|
312
|
+
try {
|
|
313
|
+
fromBackendFormat(previewResult.local);
|
|
314
|
+
yamlText = generateYamlFromUI();
|
|
315
|
+
onSettingsChange({ yaml: yamlText });
|
|
316
|
+
sendUserToast('Changes applied - remember to save repository settings to persist changes');
|
|
317
|
+
// Clear the preview state after applying settings
|
|
318
|
+
previewResult = null;
|
|
319
|
+
previewJobId = null;
|
|
320
|
+
previewJobStatus = undefined;
|
|
321
|
+
previewError = '';
|
|
322
|
+
}
|
|
323
|
+
catch (e) {
|
|
324
|
+
previewError = 'Failed to apply pulled settings: ' + e.message;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
// Push mode - send current UI state as JSON
|
|
330
|
+
isPushing = true;
|
|
331
|
+
pushJobId = null;
|
|
332
|
+
pushJobStatus = undefined;
|
|
333
|
+
try {
|
|
334
|
+
const workspace = $workspaceStore;
|
|
335
|
+
if (!workspace)
|
|
336
|
+
return;
|
|
337
|
+
const payloadObj = {
|
|
338
|
+
workspace_id: workspace,
|
|
339
|
+
repo_url_resource_path: git_repo_resource_path,
|
|
340
|
+
dry_run: false,
|
|
341
|
+
pull: isPullMode,
|
|
342
|
+
only_wmill_yaml: true,
|
|
343
|
+
settings_json: JSON.stringify(getUIState())
|
|
344
|
+
};
|
|
345
|
+
const jobId = await JobService.runScriptByPath({
|
|
346
|
+
workspace,
|
|
347
|
+
path: hubPaths.gitInitRepo,
|
|
348
|
+
requestBody: payloadObj,
|
|
349
|
+
skipPreprocessor: true
|
|
350
|
+
});
|
|
351
|
+
pushJobId = jobId;
|
|
352
|
+
pushJobStatus = 'running';
|
|
353
|
+
let jobSuccess = false;
|
|
354
|
+
await (await import('../../utils')).tryEvery({
|
|
355
|
+
tryCode: async () => {
|
|
356
|
+
const testResult = await JobService.getCompletedJob({ workspace, id: jobId });
|
|
357
|
+
jobSuccess = !!testResult.success;
|
|
358
|
+
},
|
|
359
|
+
timeoutCode: async () => {
|
|
360
|
+
try {
|
|
361
|
+
await JobService.cancelQueuedJob({
|
|
362
|
+
workspace,
|
|
363
|
+
id: jobId,
|
|
364
|
+
requestBody: { reason: 'Push job timed out after 5s' }
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
catch (err) { }
|
|
368
|
+
},
|
|
369
|
+
interval: 500,
|
|
370
|
+
timeout: 10000
|
|
371
|
+
});
|
|
372
|
+
pushJobStatus = jobSuccess ? 'success' : 'failure';
|
|
373
|
+
if (jobSuccess) {
|
|
374
|
+
// Reset preview state after successful push
|
|
375
|
+
previewResult = null;
|
|
376
|
+
previewJobId = null;
|
|
377
|
+
previewJobStatus = undefined;
|
|
378
|
+
previewError = '';
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
catch (e) {
|
|
382
|
+
pushJobStatus = 'failure';
|
|
383
|
+
}
|
|
384
|
+
finally {
|
|
385
|
+
isPushing = false;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// Simplified export function for backward compatibility
|
|
389
|
+
export function toYaml() {
|
|
390
|
+
return generateYamlFromUI();
|
|
391
|
+
}
|
|
392
|
+
export function setSettings(settings) {
|
|
393
|
+
yamlText = settings.yaml;
|
|
394
|
+
fromYaml(settings.yaml);
|
|
395
|
+
}
|
|
396
|
+
$effect(() => {
|
|
397
|
+
// Reset preview state when switching modes
|
|
398
|
+
if (isPullMode !== undefined) {
|
|
399
|
+
previewResult = null;
|
|
400
|
+
previewJobId = null;
|
|
401
|
+
previewJobStatus = undefined;
|
|
402
|
+
pushJobId = null;
|
|
403
|
+
pushJobStatus = undefined;
|
|
404
|
+
isPreviewLoading = false;
|
|
405
|
+
isPushing = false;
|
|
406
|
+
previewError = '';
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
// Reset preview state when settings change (making preview stale)
|
|
410
|
+
$effect(() => {
|
|
411
|
+
// Track all the settings that affect the preview
|
|
412
|
+
const currentSettings = JSON.stringify({
|
|
413
|
+
include_path,
|
|
414
|
+
excludes,
|
|
415
|
+
extraIncludes,
|
|
416
|
+
include_type
|
|
417
|
+
});
|
|
418
|
+
// If we have an existing preview result and settings have changed from snapshot, clear it
|
|
419
|
+
if (previewResult !== null &&
|
|
420
|
+
previewSettingsSnapshot !== null &&
|
|
421
|
+
currentSettings !== previewSettingsSnapshot) {
|
|
422
|
+
previewResult = null;
|
|
423
|
+
previewJobId = null;
|
|
424
|
+
previewJobStatus = undefined;
|
|
425
|
+
previewError = '';
|
|
426
|
+
previewSettingsSnapshot = null;
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
</script>
|
|
430
|
+
|
|
431
|
+
<div class="rounded-lg shadow-sm border p-0 w-full">
|
|
432
|
+
<!-- Card Header -->
|
|
433
|
+
<div class="flex items-center justify-between min-h-10 px-4 py-1 border-b">
|
|
434
|
+
<div class="flex items-center gap-2">
|
|
435
|
+
<Filter size={18} class="text-primary" />
|
|
436
|
+
<span class="font-semibold text-sm">Git Sync filter settings</span>
|
|
437
|
+
</div>
|
|
438
|
+
<div class="flex items-center gap-2">
|
|
439
|
+
{#if !collapsed}
|
|
440
|
+
<button
|
|
441
|
+
class="text-xs px-2 py-1 rounded border border-gray-300 bg-surface-primary hover:bg-surface-secondary"
|
|
442
|
+
onclick={editAsYaml ? switchToUI : switchToYaml}
|
|
443
|
+
>
|
|
444
|
+
{editAsYaml ? 'Edit in UI' : 'Edit as YAML'}
|
|
445
|
+
</button>
|
|
446
|
+
{/if}
|
|
447
|
+
<button
|
|
448
|
+
class="text-gray-500 hover:text-primary focus:outline-none"
|
|
449
|
+
onclick={() => (collapsed = !collapsed)}
|
|
450
|
+
aria-label="Toggle collapse"
|
|
451
|
+
>
|
|
452
|
+
{#if collapsed}
|
|
453
|
+
<svg
|
|
454
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
455
|
+
class="h-5 w-5"
|
|
456
|
+
fill="none"
|
|
457
|
+
viewBox="0 0 24 24"
|
|
458
|
+
stroke="currentColor"
|
|
459
|
+
>
|
|
460
|
+
<path
|
|
461
|
+
stroke-linecap="round"
|
|
462
|
+
stroke-linejoin="round"
|
|
463
|
+
stroke-width="2"
|
|
464
|
+
d="M19 9l-7 7-7-7"
|
|
465
|
+
/>
|
|
466
|
+
</svg>
|
|
467
|
+
{:else}
|
|
468
|
+
<svg
|
|
469
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
470
|
+
class="h-5 w-5"
|
|
471
|
+
fill="none"
|
|
472
|
+
viewBox="0 0 24 24"
|
|
473
|
+
stroke="currentColor"
|
|
474
|
+
>
|
|
475
|
+
<path
|
|
476
|
+
stroke-linecap="round"
|
|
477
|
+
stroke-linejoin="round"
|
|
478
|
+
stroke-width="2"
|
|
479
|
+
d="M5 15l7-7 7 7"
|
|
480
|
+
/>
|
|
481
|
+
</svg>
|
|
482
|
+
{/if}
|
|
483
|
+
</button>
|
|
484
|
+
</div>
|
|
485
|
+
</div>
|
|
486
|
+
{#if !collapsed}
|
|
487
|
+
{#if editAsYaml}
|
|
488
|
+
<div class="px-4 py-4">
|
|
489
|
+
<textarea
|
|
490
|
+
class="w-full h-64 font-mono text-xs border rounded p-2 bg-gray-50 focus:outline-none focus:ring-2 focus:ring-primary"
|
|
491
|
+
spellcheck="false"
|
|
492
|
+
bind:value={yamlText}
|
|
493
|
+
></textarea>
|
|
494
|
+
{#if yamlError}
|
|
495
|
+
<div class="text-xs text-red-600 mt-2">{yamlError}</div>
|
|
496
|
+
{/if}
|
|
497
|
+
</div>
|
|
498
|
+
{:else}
|
|
499
|
+
<div class="px-4 py-2">
|
|
500
|
+
<div class="grid grid-cols-1 md:grid-cols-2 md:gap-32">
|
|
501
|
+
<div class="flex flex-col gap-2">
|
|
502
|
+
<Tabs bind:selected={filtersTab}>
|
|
503
|
+
<Tab value="includes">Includes</Tab>
|
|
504
|
+
<Tab value="excludes">Excludes</Tab>
|
|
505
|
+
</Tabs>
|
|
506
|
+
|
|
507
|
+
{#if filtersTab === 'includes'}
|
|
508
|
+
<FilterList
|
|
509
|
+
title="Include path filters"
|
|
510
|
+
bind:items={include_path}
|
|
511
|
+
placeholder="Add filter (e.g. f/**)"
|
|
512
|
+
>
|
|
513
|
+
{#snippet tooltip()}
|
|
514
|
+
<Tooltip>
|
|
515
|
+
Only scripts, flows and apps with their path matching one of those filters will
|
|
516
|
+
be synced to the Git repositories below. The filters allow '*' and '**'
|
|
517
|
+
characters, with '*' matching any character allowed in paths until the next
|
|
518
|
+
slash (/) and '**' matching anything including slashes. By default everything in
|
|
519
|
+
folders will be synced.
|
|
520
|
+
</Tooltip>
|
|
521
|
+
{/snippet}
|
|
522
|
+
</FilterList>
|
|
523
|
+
{:else if filtersTab === 'excludes'}
|
|
524
|
+
<FilterList
|
|
525
|
+
title="Exclude path filters"
|
|
526
|
+
bind:items={excludes}
|
|
527
|
+
placeholder="Add filter (e.g. f/**)"
|
|
528
|
+
>
|
|
529
|
+
{#snippet tooltip()}
|
|
530
|
+
<Tooltip>
|
|
531
|
+
After the include / extra include checks, if a file matches any of these
|
|
532
|
+
patterns it will be skipped.
|
|
533
|
+
</Tooltip>
|
|
534
|
+
{/snippet}
|
|
535
|
+
</FilterList>
|
|
536
|
+
{/if}
|
|
537
|
+
</div>
|
|
538
|
+
<!-- Type Filters Section (Right) -->
|
|
539
|
+
<div>
|
|
540
|
+
<div class="flex items-center gap-2 mb-3">
|
|
541
|
+
<h4 class="font-semibold text-sm">Type filters</h4>
|
|
542
|
+
<Tooltip>
|
|
543
|
+
On top of the filter path above, you can include only certain type of object to be
|
|
544
|
+
synced with the Git repository. By default everything is synced.
|
|
545
|
+
</Tooltip>
|
|
546
|
+
</div>
|
|
547
|
+
<div class="grid grid-cols-2 gap-x-4 gap-y-2">
|
|
548
|
+
<div class="flex items-center gap-2">
|
|
549
|
+
<Toggle
|
|
550
|
+
size="xs"
|
|
551
|
+
checked={typeToggles.scripts}
|
|
552
|
+
on:change={(e) => updateIncludeType('scripts', e.detail)}
|
|
553
|
+
options={{ right: capitalize('scripts') }}
|
|
554
|
+
/>
|
|
555
|
+
</div>
|
|
556
|
+
<div class="flex items-center gap-2">
|
|
557
|
+
<Toggle
|
|
558
|
+
size="xs"
|
|
559
|
+
checked={typeToggles.flows}
|
|
560
|
+
on:change={(e) => updateIncludeType('flows', e.detail)}
|
|
561
|
+
options={{ right: capitalize('flows') }}
|
|
562
|
+
/>
|
|
563
|
+
</div>
|
|
564
|
+
<div class="flex items-center gap-2">
|
|
565
|
+
<Toggle
|
|
566
|
+
size="xs"
|
|
567
|
+
checked={typeToggles.apps}
|
|
568
|
+
on:change={(e) => updateIncludeType('apps', e.detail)}
|
|
569
|
+
options={{ right: capitalize('apps') }}
|
|
570
|
+
/>
|
|
571
|
+
</div>
|
|
572
|
+
<div class="flex items-center gap-2">
|
|
573
|
+
<Toggle
|
|
574
|
+
size="xs"
|
|
575
|
+
checked={typeToggles.folders}
|
|
576
|
+
on:change={(e) => updateIncludeType('folders', e.detail)}
|
|
577
|
+
options={{ right: capitalize('folders') }}
|
|
578
|
+
/>
|
|
579
|
+
</div>
|
|
580
|
+
<div class="flex items-center gap-2">
|
|
581
|
+
<Toggle
|
|
582
|
+
size="xs"
|
|
583
|
+
checked={typeToggles.resourceTypes}
|
|
584
|
+
on:change={(e) => updateIncludeType('resourceTypes', e.detail)}
|
|
585
|
+
options={{ right: capitalize('resourceTypes') }}
|
|
586
|
+
/>
|
|
587
|
+
</div>
|
|
588
|
+
<div class="flex items-center gap-2">
|
|
589
|
+
<Toggle
|
|
590
|
+
size="xs"
|
|
591
|
+
checked={typeToggles.resources}
|
|
592
|
+
on:change={(e) => updateIncludeType('resources', e.detail)}
|
|
593
|
+
options={{ right: capitalize('resources') }}
|
|
594
|
+
/>
|
|
595
|
+
</div>
|
|
596
|
+
<div class="col-span-2 flex items-center gap-2">
|
|
597
|
+
<Toggle
|
|
598
|
+
size="xs"
|
|
599
|
+
checked={typeToggles.variables}
|
|
600
|
+
on:change={(e) => updateIncludeType('variables', e.detail)}
|
|
601
|
+
options={{ right: 'Variables' }}
|
|
602
|
+
/>
|
|
603
|
+
<span class="text-gray-400">-</span>
|
|
604
|
+
<Toggle
|
|
605
|
+
size="xs"
|
|
606
|
+
disabled={!typeToggles.variables}
|
|
607
|
+
checked={typeToggles.secrets}
|
|
608
|
+
on:change={(e) => updateIncludeType('secrets', e.detail)}
|
|
609
|
+
options={{ left: 'Include secrets' }}
|
|
610
|
+
/>
|
|
611
|
+
</div>
|
|
612
|
+
<div class="flex items-center gap-2">
|
|
613
|
+
<Toggle
|
|
614
|
+
size="xs"
|
|
615
|
+
checked={typeToggles.schedules}
|
|
616
|
+
on:change={(e) => updateIncludeType('schedules', e.detail)}
|
|
617
|
+
options={{ right: capitalize('schedules') }}
|
|
618
|
+
/>
|
|
619
|
+
</div>
|
|
620
|
+
<div class="flex items-center gap-2">
|
|
621
|
+
<Toggle
|
|
622
|
+
size="xs"
|
|
623
|
+
checked={typeToggles.users}
|
|
624
|
+
on:change={(e) => updateIncludeType('users', e.detail)}
|
|
625
|
+
options={{ right: capitalize('users') }}
|
|
626
|
+
/>
|
|
627
|
+
</div>
|
|
628
|
+
<div class="flex items-center gap-2">
|
|
629
|
+
<Toggle
|
|
630
|
+
size="xs"
|
|
631
|
+
checked={typeToggles.groups}
|
|
632
|
+
on:change={(e) => updateIncludeType('groups', e.detail)}
|
|
633
|
+
options={{ right: capitalize('groups') }}
|
|
634
|
+
/>
|
|
635
|
+
</div>
|
|
636
|
+
<div class="flex items-center gap-2">
|
|
637
|
+
<Toggle
|
|
638
|
+
size="xs"
|
|
639
|
+
checked={typeToggles.triggers}
|
|
640
|
+
on:change={(e) => updateIncludeType('triggers', e.detail)}
|
|
641
|
+
options={{ right: capitalize('triggers') }}
|
|
642
|
+
/>
|
|
643
|
+
</div>
|
|
644
|
+
<div class="flex items-center gap-2">
|
|
645
|
+
<Toggle
|
|
646
|
+
size="xs"
|
|
647
|
+
checked={typeToggles.settings}
|
|
648
|
+
on:change={(e) => updateIncludeType('settings', e.detail)}
|
|
649
|
+
options={{ right: 'Workspace settings' }}
|
|
650
|
+
/>
|
|
651
|
+
</div>
|
|
652
|
+
<div class="flex items-center gap-2">
|
|
653
|
+
<Toggle
|
|
654
|
+
size="xs"
|
|
655
|
+
checked={typeToggles.key}
|
|
656
|
+
on:change={(e) => updateIncludeType('key', e.detail)}
|
|
657
|
+
options={{ right: 'Encryption key' }}
|
|
658
|
+
/>
|
|
659
|
+
</div>
|
|
660
|
+
</div>
|
|
661
|
+
</div>
|
|
662
|
+
</div>
|
|
663
|
+
</div>
|
|
664
|
+
<div class="mt-6 flex flex-col gap-2 p-2">
|
|
665
|
+
<div class="flex flex-col gap-2 mb-2">
|
|
666
|
+
<Toggle
|
|
667
|
+
size="sm"
|
|
668
|
+
bind:checked={isPullMode}
|
|
669
|
+
options={{
|
|
670
|
+
left: 'Push',
|
|
671
|
+
right: 'Pull'
|
|
672
|
+
}}
|
|
673
|
+
/>
|
|
674
|
+
<span class="text-xs text-tertiary">
|
|
675
|
+
{isPullMode ? 'Pull settings from Git repository' : 'Push settings to Git repository'}
|
|
676
|
+
</span>
|
|
677
|
+
</div>
|
|
678
|
+
<div class="flex gap-2 items-center">
|
|
679
|
+
<Button
|
|
680
|
+
size="sm"
|
|
681
|
+
on:click={previewFiltersToGitRepo}
|
|
682
|
+
disabled={isPreviewLoading || isPushing}
|
|
683
|
+
startIcon={{
|
|
684
|
+
icon: isPreviewLoading ? Loader2 : Eye,
|
|
685
|
+
classes: isPreviewLoading ? 'animate-spin' : ''
|
|
686
|
+
}}
|
|
687
|
+
>
|
|
688
|
+
{isPreviewLoading ? 'Previewing...' : 'Preview'}
|
|
689
|
+
</Button>
|
|
690
|
+
{#if previewResult?.hasChanges && (previewResult?.isInitialSetup || (previewResult?.diff && Object.keys(previewResult.diff).length > 0))}
|
|
691
|
+
<Button
|
|
692
|
+
size="sm"
|
|
693
|
+
on:click={pushFiltersToGitRepo}
|
|
694
|
+
disabled={isPushing || isPreviewLoading}
|
|
695
|
+
color={isPullMode ? 'dark' : 'red'}
|
|
696
|
+
startIcon={{
|
|
697
|
+
icon: isPushing ? Loader2 : isPullMode ? Check : Save,
|
|
698
|
+
classes: isPushing ? 'animate-spin' : ''
|
|
699
|
+
}}
|
|
700
|
+
>
|
|
701
|
+
{isPushing
|
|
702
|
+
? isPullMode
|
|
703
|
+
? 'Applying...'
|
|
704
|
+
: 'Pushing...'
|
|
705
|
+
: isPullMode
|
|
706
|
+
? 'Apply'
|
|
707
|
+
: 'Push Settings to Git'}
|
|
708
|
+
</Button>
|
|
709
|
+
{/if}
|
|
710
|
+
</div>
|
|
711
|
+
{#if previewError}
|
|
712
|
+
<div class="text-xs text-red-600 mt-2">{previewError}</div>
|
|
713
|
+
{/if}
|
|
714
|
+
{#if previewJobId}
|
|
715
|
+
<div class="flex items-center gap-2 text-xs text-tertiary mt-1">
|
|
716
|
+
{#if previewJobStatus === 'running'}
|
|
717
|
+
<Loader2 class="animate-spin" size={14} />
|
|
718
|
+
{:else if previewJobStatus === 'success'}
|
|
719
|
+
<CheckCircle2 size={14} class="text-green-600" />
|
|
720
|
+
{:else if previewJobStatus === 'failure'}
|
|
721
|
+
<XCircle size={14} class="text-red-700" />
|
|
722
|
+
{/if}
|
|
723
|
+
Preview job:
|
|
724
|
+
<a
|
|
725
|
+
target="_blank"
|
|
726
|
+
class="underline"
|
|
727
|
+
href={`/run/${previewJobId}?workspace=${$workspaceStore}`}>{previewJobId}</a
|
|
728
|
+
>
|
|
729
|
+
</div>
|
|
730
|
+
{/if}
|
|
731
|
+
{#if previewResult}
|
|
732
|
+
<div
|
|
733
|
+
class="border rounded p-2 text-xs max-h-40 overflow-y-auto bg-surface-secondary mt-2"
|
|
734
|
+
>
|
|
735
|
+
<div class="font-semibold text-[11px] mb-1 text-tertiary">Preview of changes:</div>
|
|
736
|
+
{#if previewResult.isInitialSetup}
|
|
737
|
+
<div class="mt-2 text-green-600">
|
|
738
|
+
{previewResult.message || 'wmill.yaml will be created with repository settings'}
|
|
739
|
+
</div>
|
|
740
|
+
{:else if previewResult.hasChanges && previewResult.diff && Object.keys(previewResult.diff).length > 0}
|
|
741
|
+
<div class="mt-2 space-y-1">
|
|
742
|
+
{#each Object.entries(previewResult.diff) as [field, change]}
|
|
743
|
+
<div class="flex items-start gap-2 text-2xs">
|
|
744
|
+
<span class="font-mono text-tertiary min-w-0 flex-shrink-0">{field}:</span>
|
|
745
|
+
<div class="min-w-0 flex-1">
|
|
746
|
+
{#if Array.isArray(change.from) || Array.isArray(change.to)}
|
|
747
|
+
<div class="space-y-0.5">
|
|
748
|
+
<div class="text-red-600">- {JSON.stringify(change.from)}</div>
|
|
749
|
+
<div class="text-green-600">+ {JSON.stringify(change.to)}</div>
|
|
750
|
+
</div>
|
|
751
|
+
{:else}
|
|
752
|
+
<span class="text-red-600">{JSON.stringify(change.from)}</span>
|
|
753
|
+
<span class="text-tertiary"> → </span>
|
|
754
|
+
<span class="text-green-600">{JSON.stringify(change.to)}</span>
|
|
755
|
+
{/if}
|
|
756
|
+
</div>
|
|
757
|
+
</div>
|
|
758
|
+
{/each}
|
|
759
|
+
</div>
|
|
760
|
+
{:else}
|
|
761
|
+
<div class="mt-2 text-tertiary">No changes found! The file is up to date.</div>
|
|
762
|
+
{/if}
|
|
763
|
+
</div>
|
|
764
|
+
{/if}
|
|
765
|
+
{#if pushJobId}
|
|
766
|
+
<div class="flex items-center gap-2 text-xs text-tertiary mt-1">
|
|
767
|
+
{#if pushJobStatus === 'running'}
|
|
768
|
+
<Loader2 class="animate-spin" size={14} />
|
|
769
|
+
{:else if pushJobStatus === 'success'}
|
|
770
|
+
<CheckCircle2 size={14} class="text-green-600" />
|
|
771
|
+
{:else if pushJobStatus === 'failure'}
|
|
772
|
+
<XCircle size={14} class="text-red-700" />
|
|
773
|
+
{/if}
|
|
774
|
+
Push job:
|
|
775
|
+
<a
|
|
776
|
+
target="_blank"
|
|
777
|
+
class="underline"
|
|
778
|
+
href={`/run/${pushJobId}?workspace=${$workspaceStore}`}>{pushJobId}</a
|
|
779
|
+
>
|
|
780
|
+
</div>
|
|
781
|
+
{/if}
|
|
782
|
+
</div>
|
|
783
|
+
{/if}
|
|
784
|
+
{/if}
|
|
785
|
+
</div>
|