windmill-components 1.698.0 → 1.700.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/components/Auth0Setting.svelte +7 -5
- package/package/components/AuthSettings.svelte +11 -6
- package/package/components/AutheliaSetting.svelte +6 -4
- package/package/components/AuthentikSetting.svelte +7 -2
- package/package/components/DisplayResult.svelte +41 -23
- package/package/components/FlowStatusViewerInner.svelte +23 -9
- package/package/components/HistoricInputs.svelte +2 -1
- package/package/components/InstanceSetting.svelte +47 -5
- package/package/components/KanidmSetting.svelte +6 -4
- package/package/components/KeycloakSetting.svelte +6 -4
- package/package/components/LogViewer.svelte +69 -29
- package/package/components/NextcloudSetting.svelte +6 -4
- package/package/components/OAuthSetting.svelte +6 -4
- package/package/components/OktaSetting.svelte +7 -2
- package/package/components/ParqetCsvTableRenderer.svelte +21 -8
- package/package/components/Path.svelte +10 -0
- package/package/components/PocketIdSetting.svelte +6 -4
- package/package/components/S3FilePickerInner.svelte +22 -8
- package/package/components/ScriptEditor.svelte +34 -4
- package/package/components/ShareModal.svelte.d.ts +1 -1
- package/package/components/VariableForm.svelte +1 -1
- package/package/components/ZitadelSetting.svelte +6 -4
- package/package/components/apps/components/helpers/RunnableComponent.svelte.d.ts +1 -0
- package/package/components/common/fileDownload/FileDownload.svelte +26 -17
- package/package/components/flows/idUtils.js +4 -1
- package/package/components/flows/stepsInputArgs.svelte.js +6 -1
- package/package/components/instanceSettings/SecretBackendConfig.svelte +36 -11
- package/package/components/propertyPicker/ObjectViewer.svelte +23 -9
- package/package/components/runs/runsFilter.d.ts +1 -1
- package/package/components/runs/useJobsLoader.svelte.d.ts +1 -0
- package/package/components/runs/useJobsLoader.svelte.js +3 -1
- package/package/components/scriptEditor/LogPanel.svelte +4 -1
- package/package/components/scriptEditor/LogPanel.svelte.d.ts +1 -0
- package/package/components/settings/WorkspaceOperatorSettings.svelte +1 -1
- package/package/components/sidebar/SidebarContent.svelte +40 -2
- package/package/gen/core/OpenAPI.js +1 -1
- package/package/gen/schemas.gen.d.ts +33 -4
- package/package/gen/schemas.gen.js +33 -4
- package/package/gen/services.gen.d.ts +20 -1
- package/package/gen/services.gen.js +40 -0
- package/package/gen/types.gen.d.ts +182 -3
- package/package/system_prompts/prompts.d.ts +2 -2
- package/package/system_prompts/prompts.js +2 -2
- package/package/utils/downloadFile.d.ts +11 -0
- package/package/utils/downloadFile.js +48 -0
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@ import Tooltip from './Tooltip.svelte';
|
|
|
6
6
|
import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte';
|
|
7
7
|
import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte';
|
|
8
8
|
import TextInput from './text_input/TextInput.svelte';
|
|
9
|
+
import Password from './Password.svelte';
|
|
9
10
|
import SettingCard from './instanceSettings/SettingCard.svelte';
|
|
10
11
|
let { value = $bindable() } = $props();
|
|
11
12
|
function changeDomain(domain, custom) {
|
|
@@ -96,14 +97,15 @@ $effect.pre(() => {
|
|
|
96
97
|
class="max-w-lg"
|
|
97
98
|
/>
|
|
98
99
|
</label>
|
|
99
|
-
<label class="flex flex-col gap-1">
|
|
100
|
+
<label for="auth0_client_secret" class="flex flex-col gap-1">
|
|
100
101
|
<span class="text-emphasis font-semibold text-xs"
|
|
101
102
|
>Client Secret <Tooltip>Client Secret of the auth0 service configuration</Tooltip></span
|
|
102
103
|
>
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
<Password
|
|
105
|
+
id="auth0_client_secret"
|
|
106
|
+
small
|
|
107
|
+
placeholder="Client Secret"
|
|
108
|
+
bind:password={value['secret']}
|
|
107
109
|
/>
|
|
108
110
|
</label>
|
|
109
111
|
<CollapseLink text="Instructions">
|
|
@@ -12,6 +12,7 @@ import KanidmSetting from './KanidmSetting.svelte';
|
|
|
12
12
|
import ZitadelSetting from './ZitadelSetting.svelte';
|
|
13
13
|
import NextcloudSetting from './NextcloudSetting.svelte';
|
|
14
14
|
import CustomOauth from './CustomOauth.svelte';
|
|
15
|
+
import Password from './Password.svelte';
|
|
15
16
|
import { capitalize } from '../utils';
|
|
16
17
|
import ClipboardPanel from './details/ClipboardPanel.svelte';
|
|
17
18
|
import Toggle from './Toggle.svelte';
|
|
@@ -259,12 +260,12 @@ function generateOAuthDropdownItems() {
|
|
|
259
260
|
<span class="text-primary font-semibold text-xs">Client Id</span>
|
|
260
261
|
<input type="text" placeholder="Client Id" bind:value={oauths[k]['id']} />
|
|
261
262
|
</label>
|
|
262
|
-
<label class="block pb-6">
|
|
263
|
+
<label for="{k}_client_secret_sso" class="block pb-6">
|
|
263
264
|
<span class="text-primary font-semibold text-xs">Client Secret</span>
|
|
264
|
-
<
|
|
265
|
-
|
|
265
|
+
<Password
|
|
266
|
+
id="{k}_client_secret_sso"
|
|
266
267
|
placeholder="Client Secret"
|
|
267
|
-
bind:
|
|
268
|
+
bind:password={oauths[k]['secret']}
|
|
268
269
|
/>
|
|
269
270
|
</label>
|
|
270
271
|
{#if !windmillBuiltins.includes(k) && k != 'slack'}
|
|
@@ -356,9 +357,13 @@ function generateOAuthDropdownItems() {
|
|
|
356
357
|
<span class="text-primary font-semibold text-xs">Client Id</span>
|
|
357
358
|
<input type="text" placeholder="Client Id" bind:value={oauths[k]['id']} />
|
|
358
359
|
</label>
|
|
359
|
-
<label>
|
|
360
|
+
<label for="{k}_client_secret_oauth">
|
|
360
361
|
<span class="text-primary font-semibold text-xs">Client Secret</span>
|
|
361
|
-
<
|
|
362
|
+
<Password
|
|
363
|
+
id="{k}_client_secret_oauth"
|
|
364
|
+
placeholder="Client Secret"
|
|
365
|
+
bind:password={oauths[k]['secret']}
|
|
366
|
+
/>
|
|
362
367
|
</label>
|
|
363
368
|
{#if k === 'visma' || !windmillBuiltins.includes(k)}
|
|
364
369
|
<div class="mb-8">
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">import { run } from 'svelte/legacy';
|
|
2
2
|
import IconedResourceType from './IconedResourceType.svelte';
|
|
3
3
|
import TextInput from './text_input/TextInput.svelte';
|
|
4
|
+
import Password from './Password.svelte';
|
|
4
5
|
import Toggle from './Toggle.svelte';
|
|
5
6
|
import SettingCard from './instanceSettings/SettingCard.svelte';
|
|
6
7
|
let { value = $bindable() } = $props();
|
|
@@ -66,11 +67,12 @@ run(() => {
|
|
|
66
67
|
bind:value={value['id']}
|
|
67
68
|
/>
|
|
68
69
|
</label>
|
|
69
|
-
<label class="flex flex-col gap-1">
|
|
70
|
+
<label for="authelia_client_secret" class="flex flex-col gap-1">
|
|
70
71
|
<span class="text-emphasis font-semibold text-xs">Client Secret </span>
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
<Password
|
|
73
|
+
id="authelia_client_secret"
|
|
74
|
+
placeholder="Client Secret"
|
|
75
|
+
bind:password={value['secret']}
|
|
74
76
|
/>
|
|
75
77
|
</label>
|
|
76
78
|
</SettingCard>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">import { run } from 'svelte/legacy';
|
|
2
2
|
import IconedResourceType from './IconedResourceType.svelte';
|
|
3
|
+
import Password from './Password.svelte';
|
|
3
4
|
import Toggle from './Toggle.svelte';
|
|
4
5
|
import SettingCard from './instanceSettings/SettingCard.svelte';
|
|
5
6
|
let { value = $bindable() } = $props();
|
|
@@ -60,9 +61,13 @@ run(() => {
|
|
|
60
61
|
<span class="text-emphasis font-semibold text-xs">Client Id</span>
|
|
61
62
|
<input type="text" placeholder="Client Id" bind:value={value['id']} />
|
|
62
63
|
</label>
|
|
63
|
-
<label>
|
|
64
|
+
<label for="authentik_client_secret">
|
|
64
65
|
<span class="text-emphasis font-semibold text-xs">Client Secret </span>
|
|
65
|
-
<
|
|
66
|
+
<Password
|
|
67
|
+
id="authentik_client_secret"
|
|
68
|
+
placeholder="Client Secret"
|
|
69
|
+
bind:password={value['secret']}
|
|
70
|
+
/>
|
|
66
71
|
</label>
|
|
67
72
|
</SettingCard>
|
|
68
73
|
{/if}
|
|
@@ -3,6 +3,7 @@ import { Highlight } from 'svelte-highlight';
|
|
|
3
3
|
import { json } from 'svelte-highlight/languages';
|
|
4
4
|
import { copyToClipboard, parseS3Object, roughSizeOfObject } from '../utils';
|
|
5
5
|
import { base } from '../base';
|
|
6
|
+
import { downloadViaClient, shouldDownloadViaClient } from '../utils/downloadFile';
|
|
6
7
|
import { Button, Drawer, DrawerContent } from './common';
|
|
7
8
|
import { ClipboardCopy, Download, PanelRightOpen, Table2, Braces, Highlighter, ArrowDownFromLine, Loader2 } from 'lucide-svelte';
|
|
8
9
|
import Portal from './Portal.svelte';
|
|
@@ -72,6 +73,15 @@ function isTableRowObjectInner(json, hasHeaders) {
|
|
|
72
73
|
}));
|
|
73
74
|
}
|
|
74
75
|
let largeObject = $state(undefined);
|
|
76
|
+
let resultApiPath = $derived(workspaceId && jobId
|
|
77
|
+
? nodeId
|
|
78
|
+
? `/w/${workspaceId}/jobs/result_by_id/${jobId}/${nodeId}`
|
|
79
|
+
: `/w/${workspaceId}/jobs_u/completed/get_result/${jobId}`
|
|
80
|
+
: undefined);
|
|
81
|
+
let resultDownloadHref = $derived(resultApiPath
|
|
82
|
+
? `${base}/api${resultApiPath}`
|
|
83
|
+
: `data:text/json;charset=utf-8,${encodeURIComponent(toJsonStr(result))}`);
|
|
84
|
+
let resultDownloadName = $derived(`${filename ?? 'result'}.json`);
|
|
75
85
|
function checkIfS3(result, keys) {
|
|
76
86
|
return keys.includes('s3') && typeof result.s3 === 'string';
|
|
77
87
|
}
|
|
@@ -859,16 +869,17 @@ $effect(() => {
|
|
|
859
869
|
{:else}
|
|
860
870
|
{#if largeObject}
|
|
861
871
|
<div class="text-xs text-emphasis"
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
+
>{#if resultApiPath && shouldDownloadViaClient()}
|
|
873
|
+
<button
|
|
874
|
+
onclick={() => downloadViaClient(resultApiPath!, resultDownloadName)}
|
|
875
|
+
>
|
|
876
|
+
Download {filename ? '' : 'as JSON'}
|
|
877
|
+
</button>
|
|
878
|
+
{:else}
|
|
879
|
+
<a download={resultDownloadName} href={resultDownloadHref}>
|
|
880
|
+
Download {filename ? '' : 'as JSON'}
|
|
881
|
+
</a>
|
|
882
|
+
{/if}
|
|
872
883
|
{#if download_as_csv}
|
|
873
884
|
<DownloadCsv
|
|
874
885
|
getContent={() => convertJsonToCsv(result)}
|
|
@@ -933,19 +944,26 @@ $effect(() => {
|
|
|
933
944
|
<DrawerContent title="Expanded Result" on:close={jsonViewer.closeDrawer}>
|
|
934
945
|
{#snippet actions()}
|
|
935
946
|
{#if customUi?.disableDownload !== true}
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
947
|
+
{#if resultApiPath && shouldDownloadViaClient()}
|
|
948
|
+
<Button
|
|
949
|
+
on:click={() => downloadViaClient(resultApiPath!, resultDownloadName)}
|
|
950
|
+
startIcon={{ icon: Download }}
|
|
951
|
+
variant="subtle"
|
|
952
|
+
unifiedSize="md"
|
|
953
|
+
>
|
|
954
|
+
Download
|
|
955
|
+
</Button>
|
|
956
|
+
{:else}
|
|
957
|
+
<Button
|
|
958
|
+
download={resultDownloadName}
|
|
959
|
+
href={resultDownloadHref}
|
|
960
|
+
startIcon={{ icon: Download }}
|
|
961
|
+
variant="subtle"
|
|
962
|
+
unifiedSize="md"
|
|
963
|
+
>
|
|
964
|
+
Download
|
|
965
|
+
</Button>
|
|
966
|
+
{/if}
|
|
949
967
|
{/if}
|
|
950
968
|
<Button
|
|
951
969
|
on:click={() => copyToClipboard(toJsonStr(result))}
|
|
@@ -12,6 +12,7 @@ import Tabs from './common/tabs/Tabs.svelte';
|
|
|
12
12
|
import {} from './graph';
|
|
13
13
|
import ModuleStatus from './ModuleStatus.svelte';
|
|
14
14
|
import { clone, isScriptPreview, msToSec, readFieldsRecursively, truncateRev } from '../utils';
|
|
15
|
+
import { downloadViaClient, shouldDownloadViaClient } from '../utils/downloadFile';
|
|
15
16
|
import JobArgs from './JobArgs.svelte';
|
|
16
17
|
import { ChevronDown, Download, ExternalLink, Hourglass } from 'lucide-svelte';
|
|
17
18
|
import { deepEqual } from 'fast-equals';
|
|
@@ -1481,16 +1482,29 @@ let totalEventsWaiting = $derived(Object.values(suspendStatus?.val ?? {}).reduce
|
|
|
1481
1482
|
style="min-height: {minTabHeight}px"
|
|
1482
1483
|
>
|
|
1483
1484
|
{#if !hideDownloadLogs && !isReplay && job?.id}
|
|
1485
|
+
{@const logsApiPath = `/w/${workspace}/jobs_u/get_flow_all_logs/${job.id}`}
|
|
1486
|
+
{@const logsName = `windmill_flow_logs_${job.id}.txt`}
|
|
1484
1487
|
<div class="flex justify-end p-1">
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1488
|
+
{#if shouldDownloadViaClient()}
|
|
1489
|
+
<Button
|
|
1490
|
+
on:click={() => downloadViaClient(logsApiPath, logsName)}
|
|
1491
|
+
color="light"
|
|
1492
|
+
size="xs"
|
|
1493
|
+
startIcon={{ icon: Download }}
|
|
1494
|
+
>
|
|
1495
|
+
Download all logs
|
|
1496
|
+
</Button>
|
|
1497
|
+
{:else}
|
|
1498
|
+
<Button
|
|
1499
|
+
href="{base}/api{logsApiPath}"
|
|
1500
|
+
download={logsName}
|
|
1501
|
+
color="light"
|
|
1502
|
+
size="xs"
|
|
1503
|
+
startIcon={{ icon: Download }}
|
|
1504
|
+
>
|
|
1505
|
+
Download all logs
|
|
1506
|
+
</Button>
|
|
1507
|
+
{/if}
|
|
1494
1508
|
</div>
|
|
1495
1509
|
{/if}
|
|
1496
1510
|
<FlowLogViewerWrapper
|
|
@@ -81,7 +81,8 @@ let jobsLoader = useJobsLoader(() => ({
|
|
|
81
81
|
syncQueuedRunsCount: false,
|
|
82
82
|
refreshRate: 10000,
|
|
83
83
|
currentWorkspace: $workspaceStore ?? '',
|
|
84
|
-
skip: !runnableId
|
|
84
|
+
skip: !runnableId,
|
|
85
|
+
excludesEntrypointOverride: true
|
|
85
86
|
}));
|
|
86
87
|
let jobs = $derived(jobsLoader?.jobs ?? []);
|
|
87
88
|
</script>
|
|
@@ -29,6 +29,7 @@ import SettingCard from './instanceSettings/SettingCard.svelte';
|
|
|
29
29
|
let { setting, version, values, loading = true, openSmtpSettings, oauths, warning } = $props();
|
|
30
30
|
const dispatch = createEventDispatcher();
|
|
31
31
|
let latestKeyRenewalAttempt = $state(null);
|
|
32
|
+
let offlineCapStatus = $state(null);
|
|
32
33
|
function showSetting(setting, values) {
|
|
33
34
|
if (setting == 'dev_instance') {
|
|
34
35
|
if (values['license_key'] == undefined) {
|
|
@@ -42,6 +43,14 @@ let opening = $state(false);
|
|
|
42
43
|
async function reloadKeyrenewalAttemptInfo() {
|
|
43
44
|
latestKeyRenewalAttempt = await SettingService.getLatestKeyRenewalAttempt();
|
|
44
45
|
}
|
|
46
|
+
async function reloadLicenseStatus() {
|
|
47
|
+
try {
|
|
48
|
+
offlineCapStatus = (await SettingService.getOfflineLicenseStatus());
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
offlineCapStatus = null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
45
54
|
async function reloadLicenseKey() {
|
|
46
55
|
$values['license_key'] = await SettingService.getGlobal({
|
|
47
56
|
key: 'license_key'
|
|
@@ -49,7 +58,10 @@ async function reloadLicenseKey() {
|
|
|
49
58
|
}
|
|
50
59
|
$effect(() => {
|
|
51
60
|
if (setting.key == 'license_key') {
|
|
52
|
-
untrack(() =>
|
|
61
|
+
untrack(() => {
|
|
62
|
+
reloadKeyrenewalAttemptInfo();
|
|
63
|
+
reloadLicenseStatus();
|
|
64
|
+
});
|
|
53
65
|
}
|
|
54
66
|
});
|
|
55
67
|
export async function renewLicenseKey() {
|
|
@@ -393,7 +405,7 @@ $effect(() => {
|
|
|
393
405
|
</div>
|
|
394
406
|
{/if}
|
|
395
407
|
{/if}
|
|
396
|
-
{#if latestKeyRenewalAttempt}
|
|
408
|
+
{#if latestKeyRenewalAttempt && !offlineCapStatus}
|
|
397
409
|
{@const attemptedAt = new Date(latestKeyRenewalAttempt.attempted_at).toLocaleString()}
|
|
398
410
|
{@const isTrial = latestKeyRenewalAttempt.result.startsWith('error: trial:')}
|
|
399
411
|
<div class="relative">
|
|
@@ -463,11 +475,41 @@ $effect(() => {
|
|
|
463
475
|
</div>
|
|
464
476
|
{/if}
|
|
465
477
|
|
|
478
|
+
{#if offlineCapStatus}
|
|
479
|
+
{@const cap = offlineCapStatus}
|
|
480
|
+
{@const seatsOver = cap.seats_used > cap.seats_cap}
|
|
481
|
+
{@const cuOver = cap.cu_over_cap}
|
|
482
|
+
<div class="mt-1 flex flex-row items-center gap-2 text-xs">
|
|
483
|
+
<div class="flex flex-row items-center gap-1">
|
|
484
|
+
{#if seatsOver}
|
|
485
|
+
<BadgeX class="text-red-600" size={12} />
|
|
486
|
+
{:else}
|
|
487
|
+
<BadgeCheck class="text-green-600" size={12} />
|
|
488
|
+
{/if}
|
|
489
|
+
<span class={seatsOver ? 'text-red-600' : 'text-green-600'}>
|
|
490
|
+
Seats: {cap.seats_used.toFixed(1)} / {cap.seats_cap}
|
|
491
|
+
</span>
|
|
492
|
+
</div>
|
|
493
|
+
<div class="flex flex-row items-center gap-1">
|
|
494
|
+
{#if cuOver}
|
|
495
|
+
<BadgeX class="text-red-600" size={12} />
|
|
496
|
+
{:else}
|
|
497
|
+
<BadgeCheck class="text-green-600" size={12} />
|
|
498
|
+
{/if}
|
|
499
|
+
<span class={cuOver ? 'text-red-600' : 'text-green-600'}>
|
|
500
|
+
CUs: {cap.current_cu.toFixed(2)} / {cap.cu_cap.toFixed(2)}
|
|
501
|
+
</span>
|
|
502
|
+
</div>
|
|
503
|
+
</div>
|
|
504
|
+
{/if}
|
|
505
|
+
|
|
466
506
|
{#if valid || expiration}
|
|
467
507
|
<div class="flex flex-row gap-2 mt-1">
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
508
|
+
{#if !offlineCapStatus}
|
|
509
|
+
<Button on:click={renewLicenseKey} loading={renewing} size="xs" variant="accent"
|
|
510
|
+
>Renew key
|
|
511
|
+
</Button>
|
|
512
|
+
{/if}
|
|
471
513
|
<Button variant="accent" size="xs" loading={opening} on:click={openCustomerPortal}>
|
|
472
514
|
Open customer portal
|
|
473
515
|
</Button>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">import { run } from 'svelte/legacy';
|
|
2
2
|
import IconedResourceType from './IconedResourceType.svelte';
|
|
3
3
|
import TextInput from './text_input/TextInput.svelte';
|
|
4
|
+
import Password from './Password.svelte';
|
|
4
5
|
import Toggle from './Toggle.svelte';
|
|
5
6
|
import SettingCard from './instanceSettings/SettingCard.svelte';
|
|
6
7
|
let { value = $bindable() } = $props();
|
|
@@ -72,11 +73,12 @@ run(() => {
|
|
|
72
73
|
bind:value={value['id']}
|
|
73
74
|
/>
|
|
74
75
|
</label>
|
|
75
|
-
<label class="flex flex-col gap-1">
|
|
76
|
+
<label for="kanidm_client_secret" class="flex flex-col gap-1">
|
|
76
77
|
<span class="text-emphasis font-semibold text-xs">Client Secret </span>
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
<Password
|
|
79
|
+
id="kanidm_client_secret"
|
|
80
|
+
placeholder="Client Secret"
|
|
81
|
+
bind:password={value['secret']}
|
|
80
82
|
/>
|
|
81
83
|
</label>
|
|
82
84
|
</SettingCard>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">import { untrack } from 'svelte';
|
|
2
2
|
import IconedResourceType from './IconedResourceType.svelte';
|
|
3
3
|
import TextInput from './text_input/TextInput.svelte';
|
|
4
|
+
import Password from './Password.svelte';
|
|
4
5
|
import Toggle from './Toggle.svelte';
|
|
5
6
|
import SettingCard from './instanceSettings/SettingCard.svelte';
|
|
6
7
|
let { value = $bindable() } = $props();
|
|
@@ -72,11 +73,12 @@ $effect.pre(() => {
|
|
|
72
73
|
bind:value={value['id']}
|
|
73
74
|
/>
|
|
74
75
|
</label>
|
|
75
|
-
<label class="flex flex-col gap-1">
|
|
76
|
+
<label for="keycloak_client_secret" class="flex flex-col gap-1">
|
|
76
77
|
<span class="text-emphasis font-semibold text-xs">Client Secret </span>
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
<Password
|
|
79
|
+
id="keycloak_client_secret"
|
|
80
|
+
placeholder="Client Secret"
|
|
81
|
+
bind:password={value['secret']}
|
|
80
82
|
/>
|
|
81
83
|
</label>
|
|
82
84
|
</SettingCard>
|
|
@@ -8,11 +8,12 @@ const s3LogPrefixes = [
|
|
|
8
8
|
const S3_LOG_SEARCH_LIMIT = 2000;
|
|
9
9
|
</script>
|
|
10
10
|
|
|
11
|
-
<script lang="ts">import { ClipboardCopy, Download, Expand, Loader2 } from 'lucide-svelte';
|
|
11
|
+
<script lang="ts">import { ClipboardCopy, Download, Expand, Loader2, Timer, Cpu } from 'lucide-svelte';
|
|
12
12
|
import { Button, Drawer, DrawerContent } from './common';
|
|
13
13
|
import { copyToClipboard } from '../utils';
|
|
14
14
|
import { base } from '../base';
|
|
15
15
|
import { withExternalDomain } from '../externalDomain';
|
|
16
|
+
import { downloadViaClient, shouldDownloadViaClient } from '../utils/downloadFile';
|
|
16
17
|
import { workspaceStore } from '../stores';
|
|
17
18
|
import { AnsiUp } from 'ansi_up';
|
|
18
19
|
import NoWorkerWithTagWarning from './runs/NoWorkerWithTagWarning.svelte';
|
|
@@ -96,8 +97,7 @@ function truncateContent(jobContent, loadedFromObjectStore, limit) {
|
|
|
96
97
|
return content;
|
|
97
98
|
}
|
|
98
99
|
export function scrollToBottom() {
|
|
99
|
-
scroll &&
|
|
100
|
-
setTimeout(() => preEl?.scroll({ top: preEl?.scrollHeight, behavior: 'smooth' }), 100);
|
|
100
|
+
scroll && setTimeout(() => preEl?.scroll({ top: preEl?.scrollHeight, behavior: 'smooth' }), 100);
|
|
101
101
|
}
|
|
102
102
|
let logViewer = $state();
|
|
103
103
|
async function getStoreLogs() {
|
|
@@ -133,7 +133,9 @@ $effect.pre(() => {
|
|
|
133
133
|
scroll = true;
|
|
134
134
|
}
|
|
135
135
|
});
|
|
136
|
-
let
|
|
136
|
+
let logsApiPath = $derived(`/w/${$workspaceStore}/jobs_u/get_logs/${jobId}`);
|
|
137
|
+
let downloadHref = $derived(withExternalDomain(`${base}/api${logsApiPath}`));
|
|
138
|
+
let downloadName = $derived(`windmill_logs_${jobId}.txt`);
|
|
137
139
|
let truncatedContent = $derived(truncateContent(content, loadedFromObjectStore, LOG_LIMIT));
|
|
138
140
|
let prefixInfo = $derived(findPrefixInfo(truncatedContent));
|
|
139
141
|
let downloadStartUrl = $derived(findStartUrl(truncatedContent, prefixInfo));
|
|
@@ -171,17 +173,30 @@ let html = $derived.by(() => {
|
|
|
171
173
|
<DrawerContent title="Expanded Logs" on:close={logViewer.closeDrawer}>
|
|
172
174
|
{#snippet actions()}
|
|
173
175
|
{#if jobId && download}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
176
|
+
{#if shouldDownloadViaClient()}
|
|
177
|
+
<Button
|
|
178
|
+
on:click={() => downloadViaClient(logsApiPath, downloadName)}
|
|
179
|
+
color="light"
|
|
180
|
+
size="xs"
|
|
181
|
+
startIcon={{
|
|
182
|
+
icon: Download
|
|
183
|
+
}}
|
|
184
|
+
>
|
|
185
|
+
Download
|
|
186
|
+
</Button>
|
|
187
|
+
{:else}
|
|
188
|
+
<Button
|
|
189
|
+
href={downloadHref}
|
|
190
|
+
download={downloadName}
|
|
191
|
+
color="light"
|
|
192
|
+
size="xs"
|
|
193
|
+
startIcon={{
|
|
194
|
+
icon: Download
|
|
195
|
+
}}
|
|
196
|
+
>
|
|
197
|
+
Download
|
|
198
|
+
</Button>
|
|
199
|
+
{/if}
|
|
185
200
|
{/if}
|
|
186
201
|
|
|
187
202
|
<Button
|
|
@@ -220,7 +235,9 @@ let html = $derived.by(() => {
|
|
|
220
235
|
class="w-full h-full bg-surface-secondary flex flex-col {noMaxH ? '' : 'max-h-screen'}"
|
|
221
236
|
data-nav-id={navigationId}
|
|
222
237
|
>
|
|
223
|
-
<div
|
|
238
|
+
<div
|
|
239
|
+
class="flex gap-2 ml-2 {small ? 'py-1' : 'py-2'} border-b overflow-x-auto overflow-y-hidden"
|
|
240
|
+
>
|
|
224
241
|
{#if isLoading}
|
|
225
242
|
<div class="flex gap-2 items-center">
|
|
226
243
|
<Loader2 class="animate-spin" />
|
|
@@ -236,31 +253,54 @@ let html = $derived.by(() => {
|
|
|
236
253
|
</div>
|
|
237
254
|
{:else if duration}
|
|
238
255
|
<span
|
|
239
|
-
class={twMerge(
|
|
240
|
-
|
|
256
|
+
class={twMerge(
|
|
257
|
+
'flex items-center gap-1 text-secondary dark:text-gray-400',
|
|
258
|
+
small ? '!text-2xs' : '!text-xs'
|
|
259
|
+
)}
|
|
260
|
+
title="Duration"
|
|
241
261
|
>
|
|
262
|
+
<Timer size={small ? 10 : 12} />
|
|
263
|
+
{duration}ms
|
|
264
|
+
</span>
|
|
242
265
|
{/if}
|
|
243
266
|
{#if mem}
|
|
244
|
-
<span
|
|
245
|
-
|
|
267
|
+
<span
|
|
268
|
+
class={twMerge(
|
|
269
|
+
'flex items-center gap-1 text-secondary dark:text-gray-400',
|
|
270
|
+
small ? '!text-2xs' : '!text-xs'
|
|
271
|
+
)}
|
|
272
|
+
title="Memory peak"
|
|
246
273
|
>
|
|
274
|
+
<Cpu size={small ? 10 : 12} />
|
|
275
|
+
{(mem / 1024).toPrecision(4)}MB
|
|
276
|
+
</span>
|
|
247
277
|
{/if}
|
|
248
278
|
<div class="flex gap-2 justify-end flex-1">
|
|
249
279
|
{#if jobId && download}
|
|
250
280
|
<div class="flex items-center">
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
281
|
+
{#if shouldDownloadViaClient()}
|
|
282
|
+
<button
|
|
283
|
+
class="text-primary pb-0.5"
|
|
284
|
+
onclick={() => downloadViaClient(logsApiPath, downloadName)}
|
|
285
|
+
><Download size="14" />
|
|
286
|
+
</button>
|
|
287
|
+
{:else}
|
|
288
|
+
<a
|
|
289
|
+
class="text-primary pb-0.5"
|
|
290
|
+
target="_blank"
|
|
291
|
+
href={downloadHref}
|
|
292
|
+
download={downloadName}
|
|
293
|
+
><Download size="14" />
|
|
294
|
+
</a>
|
|
295
|
+
{/if}
|
|
258
296
|
</div>
|
|
259
297
|
{/if}
|
|
260
298
|
<button onclick={logViewer.openDrawer}><Expand size="12" /></button>
|
|
261
299
|
{#if !noAutoScroll}
|
|
262
|
-
<label
|
|
263
|
-
|
|
300
|
+
<label
|
|
301
|
+
class="pr-2 text-2xs flex gap-2 font-normal text-primary items-center whitespace-nowrap"
|
|
302
|
+
>
|
|
303
|
+
auto-scroll
|
|
264
304
|
<input class="windmillapp" type="checkbox" bind:checked={scroll} />
|
|
265
305
|
</label>
|
|
266
306
|
{/if}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">import CollapseLink from './CollapseLink.svelte';
|
|
2
2
|
import IconedResourceType from './IconedResourceType.svelte';
|
|
3
3
|
import TextInput from './text_input/TextInput.svelte';
|
|
4
|
+
import Password from './Password.svelte';
|
|
4
5
|
import Toggle from './Toggle.svelte';
|
|
5
6
|
import SettingCard from './instanceSettings/SettingCard.svelte';
|
|
6
7
|
let { value = $bindable(), baseUrl } = $props();
|
|
@@ -76,14 +77,15 @@ $effect(() => {
|
|
|
76
77
|
bind:value={value['id']}
|
|
77
78
|
/>
|
|
78
79
|
</label>
|
|
79
|
-
<label class="flex flex-col gap-1">
|
|
80
|
+
<label for="nextcloud_client_secret" class="flex flex-col gap-1">
|
|
80
81
|
<span class="text-emphasis font-semibold text-xs">Client Secret </span>
|
|
81
82
|
<span class="text-secondary font-normal text-xs"
|
|
82
83
|
>Client Secret from your Nextcloud OAuth2 app configuration</span
|
|
83
84
|
>
|
|
84
|
-
<
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
<Password
|
|
86
|
+
id="nextcloud_client_secret"
|
|
87
|
+
placeholder="Client Secret"
|
|
88
|
+
bind:password={value['secret']}
|
|
87
89
|
/>
|
|
88
90
|
</label>
|
|
89
91
|
<CollapseLink text="Instructions">
|
|
@@ -6,6 +6,7 @@ import { untrack } from 'svelte';
|
|
|
6
6
|
import { enterpriseLicense } from '../stores';
|
|
7
7
|
import Button from './common/button/Button.svelte';
|
|
8
8
|
import TextInput from './text_input/TextInput.svelte';
|
|
9
|
+
import Password from './Password.svelte';
|
|
9
10
|
import SettingCard from './instanceSettings/SettingCard.svelte';
|
|
10
11
|
let { name, value = $bindable(), login = true, eeOnly = false } = $props();
|
|
11
12
|
// For Microsoft SSO, tenant is embedded in the login_config URLs, so we need
|
|
@@ -110,11 +111,12 @@ let enabled = $derived(value != undefined && !(eeOnly && !$enterpriseLicense));
|
|
|
110
111
|
bind:value={value['id']}
|
|
111
112
|
/>
|
|
112
113
|
</label>
|
|
113
|
-
<label class="flex flex-col gap-1">
|
|
114
|
+
<label for="{name}_client_secret" class="flex flex-col gap-1">
|
|
114
115
|
<span class="text-emphasis font-semibold text-xs">Client Secret</span>
|
|
115
|
-
<
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
<Password
|
|
117
|
+
id="{name}_client_secret"
|
|
118
|
+
placeholder="Client Secret"
|
|
119
|
+
bind:password={value['secret']}
|
|
118
120
|
/>
|
|
119
121
|
</label>
|
|
120
122
|
{#if name == 'microsoft' || name == 'teams'}
|
|
@@ -4,6 +4,7 @@ import IconedResourceType from './IconedResourceType.svelte';
|
|
|
4
4
|
import Toggle from './Toggle.svelte';
|
|
5
5
|
import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte';
|
|
6
6
|
import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte';
|
|
7
|
+
import Password from './Password.svelte';
|
|
7
8
|
import SettingCard from './instanceSettings/SettingCard.svelte';
|
|
8
9
|
let { value = $bindable() } = $props();
|
|
9
10
|
let lastValues = { domain: undefined, custom: undefined };
|
|
@@ -87,12 +88,16 @@ $effect.pre(() => {
|
|
|
87
88
|
>
|
|
88
89
|
<input type="text" placeholder="Client Id" bind:value={value['id']} />
|
|
89
90
|
</label>
|
|
90
|
-
<label class="flex flex-col gap-1">
|
|
91
|
+
<label for="okta_client_secret" class="flex flex-col gap-1">
|
|
91
92
|
<span class="text-emphasis font-semibold text-xs">Client Secret </span>
|
|
92
93
|
<span class="text-secondary font-normal text-xs"
|
|
93
94
|
>from the CLIENT SECRETS section of the okta service configuration</span
|
|
94
95
|
>
|
|
95
|
-
<
|
|
96
|
+
<Password
|
|
97
|
+
id="okta_client_secret"
|
|
98
|
+
placeholder="Client Secret"
|
|
99
|
+
bind:password={value['secret']}
|
|
100
|
+
/>
|
|
96
101
|
</label>
|
|
97
102
|
<CollapseLink text="Instructions">
|
|
98
103
|
<div class="text-xs text-primary border rounded-md p-4 space-y-3">
|