more svelte 5 migrations

This commit is contained in:
Ruben Fiszel
2025-06-13 08:47:27 +02:00
parent 7cb717ed70
commit 91f5e55f41
8 changed files with 369 additions and 282 deletions
@@ -6,7 +6,11 @@
import type { DurationStatus } from './graph'
import type { Writable } from 'svelte/store'
export let states: Writable<Record<string, DurationStatus>> | undefined
interface Props {
states: Writable<Record<string, DurationStatus>> | undefined
}
let { states }: Props = $props()
</script>
<div class="flex flex-col">
@@ -5,17 +5,21 @@
import { workspaceStore } from '$lib/stores'
import { onMount } from 'svelte'
export let resourceType: string | undefined = undefined
export let workspace: string
export let express = false
interface Props {
resourceType?: string | undefined
workspace: string
express?: boolean
}
let step = 1
let disabled = false
let manual = true
let { resourceType = $bindable(undefined), workspace, express = false }: Props = $props()
let appConnect: AppConnectInner | undefined = undefined
let step = $state(1)
let disabled = $state(false)
let manual = $state(true)
let darkMode: boolean = false
let appConnect: AppConnectInner | undefined = $state(undefined)
let darkMode: boolean = $state(false)
if (workspace) {
$workspaceStore = workspace
@@ -9,17 +9,25 @@
import EditableSchemaDrawer from './schema/EditableSchemaDrawer.svelte'
import type { SchemaProperty } from '$lib/common'
export let canEditResourceType: boolean = false
export let originalType: string | undefined = undefined
export let itemsType:
| {
type?: 'string' | 'number' | 'bytes' | 'object' | 'resource'
contentEncoding?: 'base64'
enum?: string[]
resourceType?: string
properties?: { [name: string]: SchemaProperty }
}
| undefined
interface Props {
canEditResourceType?: boolean
originalType?: string | undefined
itemsType:
| {
type?: 'string' | 'number' | 'bytes' | 'object' | 'resource'
contentEncoding?: 'base64'
enum?: string[]
resourceType?: string
properties?: { [name: string]: SchemaProperty }
}
| undefined
}
let {
canEditResourceType = false,
originalType = undefined,
itemsType = $bindable()
}: Props = $props()
let selected:
| 'string'
@@ -29,7 +37,7 @@
| 'enum'
| 'resource'
| 's3object'
| undefined =
| undefined = $state(
itemsType?.type != 'string'
? itemsType?.type == 'object' && itemsType?.resourceType == 's3object'
? 's3object'
@@ -39,12 +47,13 @@
: itemsType?.contentEncoding == 'base64'
? 'bytes'
: 'string'
)
let schema = {
let schema = $state({
properties: itemsType?.properties || {},
order: Object.keys(itemsType?.properties || {}),
required: Object.values(itemsType?.properties || {}).map((p) => p.required)
}
})
function updateItemsType() {
itemsType = {
@@ -59,7 +68,7 @@
<Label label="Items type">
<select
bind:value={selected}
on:change={() => {
onchange={() => {
if (selected == 'enum') {
itemsType = { type: 'string', enum: [] }
} else if (selected == 'string') {
@@ -127,7 +136,7 @@
<button
transition:fade|local={{ duration: 100 }}
class="rounded-full p-1 bg-surface-secondary duration-200 hover:bg-surface-hover ml-2"
on:click={() => {
onclick={() => {
if (itemsType && itemsType.enum) {
const enumValue = itemsType.enum[index]
itemsType.enum = itemsType.enum.filter((el) => el !== enumValue)
@@ -6,10 +6,19 @@
import Tooltip from './Tooltip.svelte'
import AssignableTagsInner from './AssignableTagsInner.svelte'
export let placement: 'bottom-end' | 'top-end' = 'bottom-end'
export let color: 'nord' | 'dark' = 'dark'
export let disabled = false
export let showWorkspaceRestriction = false
interface Props {
placement?: 'bottom-end' | 'top-end'
color?: 'nord' | 'dark'
disabled?: boolean
showWorkspaceRestriction?: boolean
}
let {
placement = 'bottom-end',
color = 'dark',
disabled = false,
showWorkspaceRestriction = false
}: Props = $props()
</script>
<Popover
@@ -18,7 +27,7 @@
closeButton
usePointerDownOutside
>
<svelte:fragment slot="trigger">
{#snippet trigger()}
<Button {color} size="xs" nonCaptureEvent={true} {disabled}>
<div class="flex flex-row gap-1 items-center"
><Pen size={14} /> Custom tags&nbsp;<Tooltip light
@@ -29,8 +38,8 @@
></div
>
</Button>
</svelte:fragment>
<svelte:fragment slot="content">
{/snippet}
{#snippet content()}
<AssignableTagsInner {showWorkspaceRestriction} on:refresh />
</svelte:fragment>
{/snippet}
</Popover>
@@ -1,4 +1,6 @@
<script lang="ts">
import { preventDefault, stopPropagation } from 'svelte/legacy'
import { Button } from './common'
import { ExternalLink, Loader2, X } from 'lucide-svelte'
import { SettingService, WorkerService } from '$lib/gen'
@@ -9,9 +11,13 @@
import { base } from '$lib/base'
import { createEventDispatcher } from 'svelte'
export let showWorkspaceRestriction = false
let newTag: string = ''
let customTags: string[] | undefined = undefined
interface Props {
showWorkspaceRestriction?: boolean
}
let { showWorkspaceRestriction = false }: Props = $props()
let newTag: string = $state('')
let customTags: string[] | undefined = $state(undefined)
async function loadCustomTags() {
try {
@@ -40,15 +46,17 @@
<button
class="z-10 rounded-full p-1 duration-200 hover:bg-gray-200"
aria-label="Remove item"
on:click|preventDefault|stopPropagation={async () => {
await SettingService.setGlobal({
key: CUSTOM_TAGS_SETTING,
requestBody: { value: customTags?.filter((x) => x != customTag) }
onclick={stopPropagation(
preventDefault(async () => {
await SettingService.setGlobal({
key: CUSTOM_TAGS_SETTING,
requestBody: { value: customTags?.filter((x) => x != customTag) }
})
dispatch('refresh')
loadCustomTags()
sendUserToast('Tag removed')
})
dispatch('refresh')
loadCustomTags()
sendUserToast('Tag removed')
}}
)}
>
<X size={12} />
</button><NoWorkerWithTagWarning tag={customTag} />
@@ -74,7 +82,9 @@
}}
disabled={newTag.trim() == '' || !$superadmin}
>
Add {#if !$superadmin} <span class="text-2xs text-tertiary">superadmin only</span> {/if}
Add {#if !$superadmin}
<span class="text-2xs text-tertiary">superadmin only</span>
{/if}
</Button>
<span class="text-sm text-primary"
>Configure <a href="{base}/workers" target="_blank" class="inline-flex gap-1 items-baseline"
+214 -178
View File
@@ -18,9 +18,31 @@
import { ExternalLink, Plus } from 'lucide-svelte'
import AzureOauthSettings from './AzureOauthSettings.svelte'
export let snowflakeAccountIdentifier = ''
export let oauths: Record<string, any> = {}
export let requirePreexistingUserForOauth: boolean = false
interface Props {
snowflakeAccountIdentifier?: string
oauths?: Record<string, any>
requirePreexistingUserForOauth?: boolean
scim?: import('svelte').Snippet
}
let {
snowflakeAccountIdentifier = $bindable(),
oauths = $bindable(),
requirePreexistingUserForOauth = $bindable(),
scim
}: Props = $props()
$effect(() => {
if (snowflakeAccountIdentifier == undefined) {
snowflakeAccountIdentifier = ''
}
if (oauths == undefined) {
oauths = {}
}
if (requirePreexistingUserForOauth == undefined) {
requirePreexistingUserForOauth = false
}
})
const windmillBuiltins = [
'azure_oauth',
@@ -45,12 +67,12 @@
'xero'
]
let oauth_name = undefined
let oauth_name = $state(undefined)
let clientName = ''
let resourceName = ''
let clientName = $state('')
let resourceName = $state('')
let tab: 'sso' | 'oauth' | 'scim' = 'sso'
let tab: 'sso' | 'oauth' | 'scim' = $state('sso')
</script>
<div>
@@ -62,60 +84,147 @@
</div>
<div class="mb-6">
{#if tab === 'sso'}
{#if !$enterpriseLicense || $enterpriseLicense.endsWith('_pro')}
<Alert type="warning" title="Limited to 10 SSO users">
Without EE, the number of SSO users is limited to 10. SCIM/SAML is available on EE
</Alert>
{/if}
{#if oauths}
{#if tab === 'sso'}
{#if !$enterpriseLicense || $enterpriseLicense.endsWith('_pro')}
<Alert type="warning" title="Limited to 10 SSO users">
Without EE, the number of SSO users is limited to 10. SCIM/SAML is available on EE
</Alert>
{/if}
<div class="py-1"></div>
<div class="mb-2">
<span class="text-primary text-sm"
>When at least one of the below options is set, users will be able to login to Windmill
via their third-party account.
<br /> To test SSO, the recommended workflow is to to save the settings and try to login
in an incognito window.
<a target="_blank" href="https://www.windmill.dev/docs/misc/setup_oauth#sso">Learn more</a
></span
>
</div>
<div class="flex flex-col gap-3 py-4">
<OAuthSetting name="google" bind:value={oauths['google']} />
<OAuthSetting name="microsoft" bind:value={oauths['microsoft']} />
<OktaSetting bind:value={oauths['okta']} />
<Auth0Setting bind:value={oauths['auth0']} />
<OAuthSetting name="github" bind:value={oauths['github']} />
<OAuthSetting name="gitlab" bind:value={oauths['gitlab']} />
<OAuthSetting name="jumpcloud" bind:value={oauths['jumpcloud']} />
<KeycloakSetting bind:value={oauths['keycloak']} />
<AuthentikSetting bind:value={oauths['authentik']} />
<AutheliaSetting bind:value={oauths['authelia']} />
<KanidmSetting bind:value={oauths['kanidm']} />
<ZitadelSetting bind:value={oauths['zitadel']} />
{#each Object.keys(oauths) as k}
{#if !['authelia', 'authentik', 'google', 'microsoft', 'github', 'gitlab', 'jumpcloud', 'okta', 'auth0', 'keycloak', 'slack', 'kanidm', 'zitadel'].includes(k) && 'login_config' in oauths[k]}
{#if oauths[k]}
<div class="flex flex-col gap-2 pb-4">
<div class="flex flex-row items-center gap-2">
<!-- svelte-ignore a11y_label_has_associated_control -->
<label class="text-md font-medium text-primary">{k}</label>
<CloseButton
on:close={() => {
if (oauths) {
delete oauths[k]
oauths = { ...oauths }
}
}}
/>
</div>
<div class="p-2 border rounded">
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">Custom Name</span>
<input
type="text"
placeholder="Custom Name"
bind:value={oauths[k]['display_name']}
/>
</label>
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">Client Id</span>
<input type="text" placeholder="Client Id" bind:value={oauths[k]['id']} />
</label>
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">Client Secret</span>
<input
type="text"
placeholder="Client Secret"
bind:value={oauths[k]['secret']}
/>
</label>
{#if !windmillBuiltins.includes(k) && k != 'slack'}
<CustomSso bind:login_config={oauths[k]['login_config']} />
{/if}
</div>
</div>
{/if}
{/if}
{/each}
</div>
<div class="flex gap-2 py-4">
<input type="text" placeholder="client_id" bind:value={clientName} />
<Button
variant="border"
color="blue"
hover="yo"
size="sm"
endIcon={{ icon: Plus }}
disabled={clientName == ''}
on:click={() => {
if (oauths) {
oauths[clientName] = { id: '', secret: '', login_config: {} }
}
clientName = ''
}}
>
Add custom SSO client {!$enterpriseLicense ? '(requires ee)' : ''}
</Button>
</div>
<div class="flex gap-2 py-4">
<Toggle
options={{
right: 'Require users to have been added manually to Windmill to sign in through OAuth'
}}
bind:checked={requirePreexistingUserForOauth}
/>
</div>
{:else if tab === 'oauth'}
<div class="mb-2">
<span class="text-primary text-sm"
>When one of the below options is set, you will be able to create a specific resource
containing a token automatically generated by the third-party provider.
<br />
To test it after setting an oauth client, go to the Resources menu and create a new one of
the type of your oauth client (i.e. a 'github' resource if you set Github OAuth).
<br /><a target="_blank" href="https://www.windmill.dev/docs/misc/setup_oauth#oauth"
>Learn more</a
></span
>
</div>
<div class="py-1"></div>
<OAuthSetting login={false} name="slack" bind:value={oauths['slack']} />
<div class="py-1"></div>
<OAuthSetting login={false} name="teams" eeOnly={true} bind:value={oauths['teams']} />
<div class="py-1"></div>
<div class="py-1"></div>
<div class="mb-2">
<span class="text-primary text-sm"
>When at least one of the below options is set, users will be able to login to Windmill via
their third-party account.
<br /> To test SSO, the recommended workflow is to to save the settings and try to login in
an incognito window.
<a target="_blank" href="https://www.windmill.dev/docs/misc/setup_oauth#sso">Learn more</a
></span
>
</div>
<div class="flex flex-col gap-3 py-4">
<OAuthSetting name="google" bind:value={oauths['google']} />
<OAuthSetting name="microsoft" bind:value={oauths['microsoft']} />
<OktaSetting bind:value={oauths['okta']} />
<Auth0Setting bind:value={oauths['auth0']} />
<OAuthSetting name="github" bind:value={oauths['github']} />
<OAuthSetting name="gitlab" bind:value={oauths['gitlab']} />
<OAuthSetting name="jumpcloud" bind:value={oauths['jumpcloud']} />
<KeycloakSetting bind:value={oauths['keycloak']} />
<AuthentikSetting bind:value={oauths['authentik']} />
<AutheliaSetting bind:value={oauths['authelia']} />
<KanidmSetting bind:value={oauths['kanidm']} />
<ZitadelSetting bind:value={oauths['zitadel']} />
{#each Object.keys(oauths) as k}
{#if !['authelia', 'authentik', 'google', 'microsoft', 'github', 'gitlab', 'jumpcloud', 'okta', 'auth0', 'keycloak', 'slack', 'kanidm', 'zitadel'].includes(k) && 'login_config' in oauths[k]}
{#if oauths[k]}
{#if oauths[k] && !('login_config' in oauths[k])}
{#if !['slack', 'teams'].includes(k) && oauths[k]}
<div class="flex flex-col gap-2 pb-4">
<div class="flex flex-row items-center gap-2">
<!-- svelte-ignore a11y-label-has-associated-control -->
<!-- svelte-ignore a11y_label_has_associated_control -->
<label class="text-md font-medium text-primary">{k}</label>
<CloseButton
on:close={() => {
delete oauths[k]
oauths = { ...oauths }
if (oauths) {
delete oauths[k]
oauths = { ...oauths }
}
}}
/>
</div>
<div class="p-2 border rounded">
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">Custom Name</span>
<input
type="text"
placeholder="Custom Name"
bind:value={oauths[k]['display_name']}
/>
</label>
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">Client Id</span>
<input type="text" placeholder="Client Id" bind:value={oauths[k]['id']} />
@@ -124,141 +233,68 @@
<span class="text-primary font-semibold text-sm">Client Secret</span>
<input type="text" placeholder="Client Secret" bind:value={oauths[k]['secret']} />
</label>
{#if !windmillBuiltins.includes(k) && k != 'slack'}
<CustomSso bind:login_config={oauths[k]['login_config']} />
{#if k === 'azure_oauth'}
<AzureOauthSettings bind:connect_config={oauths[k]['connect_config']} />
{:else if !windmillBuiltins.includes(k) && k != 'slack'}
<CustomOauth bind:connect_config={oauths[k]['connect_config']} />
{/if}
{#if k == 'snowflake_oauth'}
<label class="block pb-2">
<span class="text-primary font-semibold text-sm flex gap-2 items-center"
><a
href="https://docs.snowflake.com/en/user-guide/admin-account-identifier#using-an-account-name-as-an-identifier"
target="_blank">Snowflake Account Identifier</a
><ExternalLink size={12} /></span
>
<input
type="text"
placeholder="<orgname>-<account_name>"
required={true}
bind:value={snowflakeAccountIdentifier}
/>
</label>
{/if}
</div>
</div>
{/if}
{/if}
{/each}
</div>
<div class="flex gap-2 py-4">
<input type="text" placeholder="client_id" bind:value={clientName} />
<Button
variant="border"
color="blue"
hover="yo"
size="sm"
endIcon={{ icon: Plus }}
disabled={clientName == ''}
on:click={() => {
oauths[clientName] = { id: '', secret: '', login_config: {} }
clientName = ''
}}
>
Add custom SSO client {!$enterpriseLicense ? '(requires ee)' : ''}
</Button>
</div>
<div class="flex gap-2 py-4">
<Toggle
options={{
right: 'Require users to have been added manually to Windmill to sign in through OAuth'
}}
bind:checked={requirePreexistingUserForOauth}
/>
</div>
{:else if tab === 'oauth'}
<div class="mb-2">
<span class="text-primary text-sm"
>When one of the below options is set, you will be able to create a specific resource
containing a token automatically generated by the third-party provider.
<br />
To test it after setting an oauth client, go to the Resources menu and create a new one of the
type of your oauth client (i.e. a 'github' resource if you set Github OAuth).
<br /><a target="_blank" href="https://www.windmill.dev/docs/misc/setup_oauth#oauth"
>Learn more</a
></span
>
</div>
<div class="py-1"></div>
<OAuthSetting login={false} name="slack" bind:value={oauths['slack']} />
<div class="py-1"></div>
<OAuthSetting login={false} name="teams" eeOnly={true} bind:value={oauths['teams']} />
<div class="py-1"></div>
{#each Object.keys(oauths) as k}
{#if oauths[k] && !('login_config' in oauths[k])}
{#if !['slack', 'teams'].includes(k) && oauths[k]}
<div class="flex flex-col gap-2 pb-4">
<div class="flex flex-row items-center gap-2">
<!-- svelte-ignore a11y-label-has-associated-control -->
<label class="text-md font-medium text-primary">{k}</label>
<CloseButton
on:close={() => {
delete oauths[k]
oauths = { ...oauths }
}}
/>
</div>
<div class="p-2 border rounded">
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">Client Id</span>
<input type="text" placeholder="Client Id" bind:value={oauths[k]['id']} />
</label>
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">Client Secret</span>
<input type="text" placeholder="Client Secret" bind:value={oauths[k]['secret']} />
</label>
{#if k === 'azure_oauth'}
<AzureOauthSettings bind:connect_config={oauths[k]['connect_config']} />
{:else if !windmillBuiltins.includes(k) && k != 'slack'}
<CustomOauth bind:connect_config={oauths[k]['connect_config']} />
{/if}
{#if k == 'snowflake_oauth'}
<label class="block pb-2">
<span class="text-primary font-semibold text-sm flex gap-2 items-center"
><a
href="https://docs.snowflake.com/en/user-guide/admin-account-identifier#using-an-account-name-as-an-identifier"
target="_blank">Snowflake Account Identifier</a
><ExternalLink size={12} /></span
>
<input
type="text"
placeholder="<orgname>-<account_name>"
required={true}
bind:value={snowflakeAccountIdentifier}
/>
</label>
{/if}
</div>
</div>
<div class="flex gap-2">
<select name="oauth_name" id="oauth_name" bind:value={oauth_name}>
<option value={undefined}>Select an OAuth client</option>
<option value="custom">Fully Custom (requires ee)</option>
{#each windmillBuiltins as name}
<option value={name}>{capitalize(name)}</option>
{/each}
</select>
{#if oauth_name == 'custom'}
<input type="text" placeholder="client_id" bind:value={resourceName} />
{:else}
<input type="text" value={oauth_name ?? ''} disabled />
{/if}
{/if}
{/each}
<div class="flex gap-2">
<select name="oauth_name" id="oauth_name" bind:value={oauth_name}>
<option value={undefined}>Select an OAuth client</option>
<option value="custom">Fully Custom (requires ee)</option>
{#each windmillBuiltins as name}
<option value={name}>{capitalize(name)}</option>
{/each}
</select>
{#if oauth_name == 'custom'}
<input type="text" placeholder="client_id" bind:value={resourceName} />
{:else}
<input type="text" value={oauth_name ?? ''} disabled />
{/if}
<Button
variant="border"
color="blue"
hover="yo"
size="sm"
endIcon={{ icon: Plus }}
disabled={!oauth_name ||
(oauth_name == 'custom' && resourceName == '') ||
(oauth_name == 'custom' && !$enterpriseLicense)}
on:click={() => {
let name = oauth_name == 'custom' ? resourceName : oauth_name
oauths[name ?? ''] = { id: '', secret: '' }
resourceName = ''
}}
>
Add OAuth client {oauth_name == 'custom' && !$enterpriseLicense ? '(requires ee)' : ''}
</Button>
</div>
{:else if tab == 'scim'}
<slot name="scim" />
<Button
variant="border"
color="blue"
hover="yo"
size="sm"
endIcon={{ icon: Plus }}
disabled={!oauth_name ||
(oauth_name == 'custom' && resourceName == '') ||
(oauth_name == 'custom' && !$enterpriseLicense)}
on:click={() => {
if (oauths) {
let name = oauth_name == 'custom' ? resourceName : oauth_name
oauths[name ?? ''] = { id: '', secret: '' }
}
resourceName = ''
}}
>
Add OAuth client {oauth_name == 'custom' && !$enterpriseLicense ? '(requires ee)' : ''}
</Button>
</div>
{:else if tab == 'scim'}
{@render scim?.()}
{/if}
{/if}
</div>
@@ -41,10 +41,14 @@
import TeamSelector from './TeamSelector.svelte'
import ChannelSelector from './ChannelSelector.svelte'
export let setting: Setting
export let version: string
export let values: Writable<Record<string, any>>
export let loading = true
interface Props {
setting: Setting
version: string
values: Writable<Record<string, any>>
loading?: boolean
}
let { setting, version, values, loading = true }: Props = $props()
const dispatch = createEventDispatcher()
if (
@@ -57,9 +61,9 @@
let latestKeyRenewalAttempt: {
result: string
attempted_at: string
} | null
} | null = $state(null)
let isFetching = false
let isFetching = $state(false)
function showSetting(setting: string, values: Record<string, any>) {
if (setting == 'dev_instance') {
@@ -70,11 +74,11 @@
return true
}
let licenseKeyChanged = false
let renewing = false
let opening = false
let licenseKeyChanged = $state(false)
let renewing = $state(false)
let opening = $state(false)
let to: string = ''
let to: string = $state('')
async function reloadKeyrenewalAttemptInfo() {
latestKeyRenewalAttempt = await SettingService.getLatestKeyRenewalAttempt()
@@ -135,9 +139,9 @@
}
}
let pythonAvailableVersions: ListAvailablePythonVersionsResponse = []
let pythonAvailableVersions: ListAvailablePythonVersionsResponse = $state([])
let isPyFetching = false
let isPyFetching = $state(false)
async function fetch_available_python_versions() {
if (isPyFetching) return
isPyFetching = true
@@ -209,7 +213,7 @@
{/if}
{#if setting.fieldType == 'select'}
<div>
<!-- svelte-ignore a11y-label-has-associated-control -->
<!-- svelte-ignore a11y_label_has_associated_control -->
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">{setting.label}</span>
{#if setting.description}
@@ -233,7 +237,7 @@
</div>
{:else if setting.fieldType == 'select_python'}
<div>
<!-- svelte-ignore a11y-label-has-associated-control -->
<!-- svelte-ignore a11y_label_has_associated_control -->
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">{setting.label}</span>
{#if setting.description}
@@ -254,7 +258,7 @@
/>
{/each}
<PopoverMelt closeButton={!isPyFetching}>
<svelte:fragment slot="trigger">
{#snippet trigger()}
{#if setting.select_items?.some((e) => e.label == $values[setting.key] || e.value == $values[setting.key])}
<Button
variant="border"
@@ -270,8 +274,8 @@
nonCaptureEvent={true}>Custom | {$values[setting.key]}</Button
>
{/if}
</svelte:fragment>
<svelte:fragment slot="content">
{/snippet}
{#snippet content()}
{#if isPyFetching}
<div class="p-4">
<LoadingIcon />
@@ -289,13 +293,13 @@
{/snippet}
</ToggleButtonGroup>
{/if}
</svelte:fragment>
{/snippet}
</PopoverMelt>
{/snippet}
</ToggleButtonGroup>
</div>
{:else}
<!-- svelte-ignore a11y-label-has-associated-control -->
<!-- svelte-ignore a11y_label_has_associated_control -->
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">{setting.label}</span>
{#if setting.description}
@@ -444,27 +448,29 @@
on {attemptedAt}
</span>
</div>
<div slot="text">
{#if latestKeyRenewalAttempt.result === 'success'}
<span class="text-green-300">
Latest key renewal succeeded on {attemptedAt}
</span>
{:else if isTrial}
<span class="text-yellow-300">
License key cannot be renewed during trial ({attemptedAt})
</span>
{:else}
<span class="text-red-300">
Latest key renewal failed on {attemptedAt}: {latestKeyRenewalAttempt.result.replace(
'error: ',
''
)}
</span>
{/if}
<br />
As long as invoices are paid and usage corresponds to the subscription, the key is
renewed daily with a validity of 35 days (grace period).
</div>
{#snippet text()}
<div>
{#if latestKeyRenewalAttempt?.result === 'success'}
<span class="text-green-300">
Latest key renewal succeeded on {attemptedAt}
</span>
{:else if isTrial}
<span class="text-yellow-300">
License key cannot be renewed during trial ({attemptedAt})
</span>
{:else}
<span class="text-red-300">
Latest key renewal failed on {attemptedAt}: {latestKeyRenewalAttempt?.result.replace(
'error: ',
''
)}
</span>
{/if}
<br />
As long as invoices are paid and usage corresponds to the subscription, the key
is renewed daily with a validity of 35 days (grace period).
</div>
{/snippet}
</Popover>
</div>
{/if}
@@ -520,7 +526,7 @@
<div class="flex w-full max-w-lg mt-1 gap-2 items-center">
<select
class="max-w-24"
on:change={(e) => {
onchange={(e) => {
if (e.target?.['value']) {
$values[setting.key][i] = {
[e.target['value']]: ''
@@ -545,7 +551,7 @@
<input
type="text"
placeholder="Slack channel"
on:input={(e) => {
oninput={(e) => {
if (e.target?.['value']) {
$values[setting.key][i] = {
slack_channel: e.target['value']
@@ -603,7 +609,7 @@
/>
{/if}
<div>
<button on:click={fetchTeams} class="flex items-center gap-1 mt-2">
<button onclick={fetchTeams} class="flex items-center gap-1 mt-2">
<RefreshCcw size={16} class={isFetching ? 'animate-spin' : ''} />
</button>
</div>
@@ -612,7 +618,7 @@
<input
type="email"
placeholder="Email address"
on:input={(e) => {
oninput={(e) => {
if (e.target?.['value']) {
$values[setting.key][i] = {
email: e.target['value']
@@ -626,7 +632,7 @@
transition:fade|local={{ duration: 100 }}
class="rounded-full p-1 bg-surface-secondary duration-200 hover:bg-surface-hover"
aria-label="Clear"
on:click={() => {
onclick={() => {
$values[setting.key] = $values[setting.key].filter(
(_, index) => index !== i
)
@@ -723,7 +729,7 @@
type="number"
id="writer_memory_budget"
placeholder="300"
on:input={(e) => {
oninput={(e) => {
if (e.target instanceof HTMLInputElement) {
if (e.target.valueAsNumber) {
$values[setting.key].writer_memory_budget =
@@ -781,7 +787,7 @@
type="number"
id="max_indexed_job_log_size"
placeholder="1024"
on:input={(e) => {
oninput={(e) => {
if (e.target instanceof HTMLInputElement) {
if (e.target.valueAsNumber) {
$values[setting.key].max_indexed_job_log_size =
@@ -16,20 +16,29 @@
import InstanceSetting from './InstanceSetting.svelte'
import { writable, type Writable } from 'svelte/store'
export let tab: string = 'Core'
export let hideTabs: boolean = false
export let hideSave: boolean = false
export let closeDrawer: (() => void) | undefined = () => {}
interface Props {
tab?: string
hideTabs?: boolean
hideSave?: boolean
closeDrawer?: (() => void) | undefined
}
let {
tab = $bindable('Core'),
hideTabs = false,
hideSave = false,
closeDrawer = () => {}
}: Props = $props()
let values: Writable<Record<string, any>> = writable({})
let initialOauths: Record<string, any> = {}
let initialRequirePreexistingUserForOauth: boolean = false
let requirePreexistingUserForOauth: boolean = false
let requirePreexistingUserForOauth: boolean = $state(false)
let initialValues: Record<string, any> = {}
let snowflakeAccountIdentifier = ''
let version: string = ''
let loading = true
let snowflakeAccountIdentifier = $state('')
let version: string = $state('')
let loading = $state(true)
loadSettings()
loadVersion()
@@ -39,7 +48,7 @@
async function loadVersion() {
version = await SettingsService.backendVersion()
}
let oauths: Record<string, any> = {}
let oauths: Record<string, any> = $state({})
async function loadSettings() {
loading = true
@@ -240,7 +249,7 @@
</script>
<div class="pb-8">
<!-- svelte-ignore a11y-label-has-associated-control -->
<!-- svelte-ignore a11y_label_has_associated_control -->
<Tabs {hideTabs} bind:selected={tab}>
{#each settingsKeys as category}
<Tab value={category}>{category}</Tab>
@@ -332,7 +341,7 @@
bind:snowflakeAccountIdentifier
bind:requirePreexistingUserForOauth
>
<svelte:fragment slot="scim">
{#snippet scim()}
<div class="flex-col flex gap-2 pb-4">
{#each scimSamlSetting as setting}
<InstanceSetting
@@ -344,7 +353,7 @@
/>
{/each}
</div>
</svelte:fragment>
{/snippet}
</AuthSettings>
{/if}
<div>