windmill-components 1.699.0 → 1.700.2

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.
@@ -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
- <TextInput
104
- inputProps={{ type: 'text', placeholder: 'Client Secret' }}
105
- bind:value={value['secret']}
106
- class="max-w-lg"
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
- <input
265
- type="text"
265
+ <Password
266
+ id="{k}_client_secret_sso"
266
267
  placeholder="Client Secret"
267
- bind:value={oauths[k]['secret']}
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
- <input type="text" placeholder="Client Secret" bind:value={oauths[k]['secret']} />
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
- <TextInput
72
- inputProps={{ type: 'text', placeholder: 'Client Secret' }}
73
- bind:value={value['secret']}
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
- <input type="text" placeholder="Client Secret" bind:value={value['secret']} />
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}
@@ -82,12 +82,6 @@ let resultDownloadHref = $derived(resultApiPath
82
82
  ? `${base}/api${resultApiPath}`
83
83
  : `data:text/json;charset=utf-8,${encodeURIComponent(toJsonStr(result))}`);
84
84
  let resultDownloadName = $derived(`${filename ?? 'result'}.json`);
85
- async function onResultDownload(e) {
86
- if (!resultApiPath || !shouldDownloadViaClient())
87
- return;
88
- e.preventDefault();
89
- await downloadViaClient(resultApiPath, resultDownloadName);
90
- }
91
85
  function checkIfS3(result, keys) {
92
86
  return keys.includes('s3') && typeof result.s3 === 'string';
93
87
  }
@@ -875,13 +869,17 @@ $effect(() => {
875
869
  {:else}
876
870
  {#if largeObject}
877
871
  <div class="text-xs text-emphasis"
878
- ><a
879
- download={resultDownloadName}
880
- href={resultDownloadHref}
881
- onclick={onResultDownload}
882
- >
883
- Download {filename ? '' : 'as JSON'}
884
- </a>
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}
885
883
  {#if download_as_csv}
886
884
  <DownloadCsv
887
885
  getContent={() => convertJsonToCsv(result)}
@@ -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
- <TextInput
78
- inputProps={{ type: 'text', placeholder: 'Client Secret' }}
79
- bind:value={value['secret']}
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
- <TextInput
78
- inputProps={{ type: 'text', placeholder: 'Client Secret' }}
79
- bind:value={value['secret']}
78
+ <Password
79
+ id="keycloak_client_secret"
80
+ placeholder="Client Secret"
81
+ bind:password={value['secret']}
80
82
  />
81
83
  </label>
82
84
  </SettingCard>
@@ -136,12 +136,6 @@ $effect.pre(() => {
136
136
  let logsApiPath = $derived(`/w/${$workspaceStore}/jobs_u/get_logs/${jobId}`);
137
137
  let downloadHref = $derived(withExternalDomain(`${base}/api${logsApiPath}`));
138
138
  let downloadName = $derived(`windmill_logs_${jobId}.txt`);
139
- async function onDownloadClick(e) {
140
- if (!shouldDownloadViaClient())
141
- return;
142
- e.preventDefault();
143
- await downloadViaClient(logsApiPath, downloadName);
144
- }
145
139
  let truncatedContent = $derived(truncateContent(content, loadedFromObjectStore, LOG_LIMIT));
146
140
  let prefixInfo = $derived(findPrefixInfo(truncatedContent));
147
141
  let downloadStartUrl = $derived(findStartUrl(truncatedContent, prefixInfo));
@@ -284,14 +278,21 @@ let html = $derived.by(() => {
284
278
  <div class="flex gap-2 justify-end flex-1">
285
279
  {#if jobId && download}
286
280
  <div class="flex items-center">
287
- <a
288
- class="text-primary pb-0.5"
289
- target="_blank"
290
- href={downloadHref}
291
- download={downloadName}
292
- onclick={onDownloadClick}
293
- ><Download size="14" />
294
- </a>
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}
295
296
  </div>
296
297
  {/if}
297
298
  <button onclick={logViewer.openDrawer}><Expand size="12" /></button>
@@ -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
- <TextInput
85
- inputProps={{ type: 'password', placeholder: 'Client Secret' }}
86
- bind:value={value['secret']}
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
- <TextInput
116
- inputProps={{ type: 'text', placeholder: 'Client Secret' }}
117
- bind:value={value['secret']}
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
- <input type="text" placeholder="Client Secret" bind:value={value['secret']} />
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">
@@ -174,16 +174,24 @@ run(() => {
174
174
  {#if !disable_download && !s3resource.endsWith('.csv')}
175
175
  {@const csvApiPath = `/w/${workspaceId}/job_helpers/download_s3_parquet_file_as_csv?file_key=${encodeURIComponent(s3resource)}${storage ? `&storage=${storage}` : ''}`}
176
176
  {@const csvName = (s3resource.split('/').pop() ?? 'download') + '.csv'}
177
- <a
178
- target="_blank"
179
- href="{base}/api{csvApiPath}"
180
- class="text-secondary w-full text-right underline text-2xs whitespace-nowrap"
181
- onclick={async (e) => {
182
- if (!shouldDownloadViaClient()) return
183
- e.preventDefault()
184
- await downloadViaClient(csvApiPath, csvName)
185
- }}><div class="flex flex-row-reverse gap-2 items-center"><Download size={12} /> CSV</div></a
186
- >
177
+ {#if shouldDownloadViaClient()}
178
+ <button
179
+ class="text-secondary w-full text-right underline text-2xs whitespace-nowrap"
180
+ onclick={() => downloadViaClient(csvApiPath, csvName)}
181
+ ><div class="flex flex-row-reverse gap-2 items-center"
182
+ ><Download size={12} /> CSV</div
183
+ ></button
184
+ >
185
+ {:else}
186
+ <a
187
+ target="_blank"
188
+ href="{base}/api{csvApiPath}"
189
+ class="text-secondary w-full text-right underline text-2xs whitespace-nowrap"
190
+ ><div class="flex flex-row-reverse gap-2 items-center"
191
+ ><Download size={12} /> CSV</div
192
+ ></a
193
+ >
194
+ {/if}
187
195
  {/if}
188
196
 
189
197
  {#if nbRows != undefined}
@@ -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();
@@ -71,11 +72,12 @@ function handleToggle(e) {
71
72
  bind:value={value['id']}
72
73
  />
73
74
  </label>
74
- <label class="flex flex-col gap-1">
75
+ <label for="pocketid_client_secret" class="flex flex-col gap-1">
75
76
  <span class="text-emphasis font-semibold text-xs">Client Secret</span>
76
- <TextInput
77
- inputProps={{ type: 'text', placeholder: 'Client Secret' }}
78
- bind:value={value['secret']}
77
+ <Password
78
+ id="pocketid_client_secret"
79
+ placeholder="Client Secret"
80
+ bind:password={value['secret']}
79
81
  />
80
82
  </label>
81
83
  </SettingCard>
@@ -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();
@@ -64,11 +65,12 @@ run(() => {
64
65
  bind:value={value['id']}
65
66
  />
66
67
  </label>
67
- <label>
68
+ <label for="zitadel_client_secret">
68
69
  <span class="text-emphasis font-semibold text-xs">Client Secret </span>
69
- <TextInput
70
- inputProps={{ type: 'text', placeholder: 'Client Secret' }}
71
- bind:value={value['secret']}
70
+ <Password
71
+ id="zitadel_client_secret"
72
+ placeholder="Client Secret"
73
+ bind:password={value['secret']}
72
74
  />
73
75
  </label>
74
76
  </SettingCard>
@@ -9,27 +9,26 @@ let apiPath = $derived(`${appPath
9
9
  ? `/w/${workspace}/apps_u/download_s3_file/${appPath}`
10
10
  : `/w/${workspace}/job_helpers/download_s3_file`}?${appPath ? 's3' : 'file_key'}=${encodeURIComponent(s3object?.s3 ?? '')}${s3object?.storage ? `&storage=${s3object.storage}` : ''}${appPath && s3object?.presigned ? `&${s3object?.presigned}` : ''}`);
11
11
  let href = $derived(`${base}/api${apiPath}`);
12
- async function onclick(e) {
13
- if (!shouldDownloadViaClient())
14
- return;
15
- e.preventDefault();
16
- await downloadViaClient(apiPath, filename);
17
- }
12
+ const sharedClass = `relative center-center flex w-full text-center font-normal text-primary text-sm
13
+ border border-dashed border-gray-400 hover:border-blue-500
14
+ focus-within:border-blue-500 hover:bg-blue-50 dark:hover:bg-frost-900 focus-within:bg-blue-50
15
+ duration-200 rounded-lg p-1 gap-2`;
18
16
  </script>
19
17
 
20
18
  {#if s3object && s3object?.s3}
21
- <a
22
- class="relative center-center flex w-full text-center font-normal text-primary text-sm
23
- border border-dashed border-gray-400 hover:border-blue-500
24
- focus-within:border-blue-500 hover:bg-blue-50 dark:hover:bg-frost-900 focus-within:bg-blue-50
25
- duration-200 rounded-lg p-1 gap-2"
26
- {href}
27
- download={filename}
28
- {onclick}
29
- >
30
- <Download />
31
- <span>
32
- {s3object?.storage ? `s3://${s3object.storage}/${s3object.s3}` : `s3:///${s3object.s3}`}
33
- </span>
34
- </a>
19
+ {#if shouldDownloadViaClient()}
20
+ <button class={sharedClass} onclick={() => downloadViaClient(apiPath, filename)}>
21
+ <Download />
22
+ <span>
23
+ {s3object?.storage ? `s3://${s3object.storage}/${s3object.s3}` : `s3:///${s3object.s3}`}
24
+ </span>
25
+ </button>
26
+ {:else}
27
+ <a class={sharedClass} {href} download={filename}>
28
+ <Download />
29
+ <span>
30
+ {s3object?.storage ? `s3://${s3object.storage}/${s3object.s3}` : `s3:///${s3object.s3}`}
31
+ </span>
32
+ </a>
33
+ {/if}
35
34
  {/if}
@@ -338,18 +338,26 @@ let menuItems = $derived([
338
338
  {#if getTypeAsString(jsonFiltered) === 's3object'}
339
339
  {@const s3DownloadApiPath = `/w/${$workspaceStore}/job_helpers/download_s3_file?file_key=${encodeURIComponent(jsonFiltered?.s3 ?? '')}${jsonFiltered?.storage ? `&storage=${jsonFiltered.storage}` : ''}`}
340
340
  {@const s3DownloadName = jsonFiltered?.s3.split('/').pop() ?? 'unnamed_download.file'}
341
- <a
342
- class="text-secondary underline font-semibold text-2xs whitespace-nowrap ml-1 w-fit"
343
- href={`/api${s3DownloadApiPath}`}
344
- download={s3DownloadName}
345
- onclick={async (e) => {
346
- if (!shouldDownloadViaClient()) return
347
- e.preventDefault()
348
- await downloadViaClient(s3DownloadApiPath, s3DownloadName)
349
- }}
350
- >
351
- <span class="flex items-center gap-1"><Download size={12} />download</span>
352
- </a>
341
+ {#if shouldDownloadViaClient()}
342
+ <button
343
+ class="text-secondary underline font-semibold text-2xs whitespace-nowrap ml-1 w-fit"
344
+ onclick={() => downloadViaClient(s3DownloadApiPath, s3DownloadName)}
345
+ >
346
+ <span class="flex items-center gap-1"
347
+ ><Download size={12} />download</span
348
+ >
349
+ </button>
350
+ {:else}
351
+ <a
352
+ class="text-secondary underline font-semibold text-2xs whitespace-nowrap ml-1 w-fit"
353
+ href={`/api${s3DownloadApiPath}`}
354
+ download={s3DownloadName}
355
+ >
356
+ <span class="flex items-center gap-1"
357
+ ><Download size={12} />download</span
358
+ >
359
+ </a>
360
+ {/if}
353
361
  <button
354
362
  class="text-secondary underline text-2xs whitespace-nowrap ml-1"
355
363
  onclick={() => {