mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-08 00:03:07 +00:00
app svelte 5 improvements
This commit is contained in:
@@ -164,7 +164,7 @@
|
||||
{#if data && resolvedConfig.type}
|
||||
{#key resolvedConfig.type}
|
||||
{#key options}
|
||||
<Chart type={resolvedConfig.type} {data} {options} />
|
||||
<Chart type={resolvedConfig.type} data={$state.snapshot(data)} {options} />
|
||||
{/key}
|
||||
{/key}
|
||||
{/if}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import { getContext, untrack } from 'svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { initConfig, initOutput } from '../../editor/appUtils'
|
||||
import { components } from '../../editor/component'
|
||||
@@ -13,17 +13,28 @@
|
||||
import ResolveStyle from '../helpers/ResolveStyle.svelte'
|
||||
import AlignWrapper from '../helpers/AlignWrapper.svelte'
|
||||
|
||||
export let id: string
|
||||
export let configuration: RichConfigurations
|
||||
export let customCss: ComponentCustomCSS<'downloadcomponent'> | undefined = undefined
|
||||
export let render: boolean
|
||||
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
|
||||
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
|
||||
export let noWFull = false
|
||||
interface Props {
|
||||
id: string
|
||||
configuration: RichConfigurations
|
||||
customCss?: ComponentCustomCSS<'downloadcomponent'> | undefined
|
||||
render: boolean
|
||||
horizontalAlignment?: 'left' | 'center' | 'right' | undefined
|
||||
verticalAlignment?: 'top' | 'center' | 'bottom' | undefined
|
||||
noWFull?: boolean
|
||||
}
|
||||
|
||||
const resolvedConfig = initConfig(
|
||||
components['downloadcomponent'].initialData.configuration,
|
||||
configuration
|
||||
let {
|
||||
id,
|
||||
configuration,
|
||||
customCss = undefined,
|
||||
render,
|
||||
horizontalAlignment = undefined,
|
||||
verticalAlignment = undefined,
|
||||
noWFull = false
|
||||
}: Props = $props()
|
||||
|
||||
const resolvedConfig = $state(
|
||||
initConfig(components['downloadcomponent'].initialData.configuration, configuration)
|
||||
)
|
||||
|
||||
const { app, worldStore } = getContext<AppViewerContext>('AppViewerContext')
|
||||
@@ -31,11 +42,8 @@
|
||||
//used so that we can count number of outputs setup for first refresh
|
||||
initOutput($worldStore, id, {})
|
||||
|
||||
let beforeIconComponent: any
|
||||
let afterIconComponent: any
|
||||
|
||||
$: resolvedConfig.beforeIcon && beforeIconComponent && handleBeforeIcon()
|
||||
$: resolvedConfig.afterIcon && afterIconComponent && handleAfterIcon()
|
||||
let beforeIconComponent: any = $state()
|
||||
let afterIconComponent: any = $state()
|
||||
|
||||
async function handleBeforeIcon() {
|
||||
if (resolvedConfig.beforeIcon) {
|
||||
@@ -61,7 +69,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
let css = initCss($app.css?.downloadcomponent, customCss)
|
||||
let css = $state(initCss($app.css?.downloadcomponent, customCss))
|
||||
$effect(() => {
|
||||
resolvedConfig.beforeIcon && beforeIconComponent && untrack(() => handleBeforeIcon())
|
||||
})
|
||||
$effect(() => {
|
||||
resolvedConfig.afterIcon && afterIconComponent && untrack(() => handleAfterIcon())
|
||||
})
|
||||
</script>
|
||||
|
||||
<InitializeComponent {id} />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import { getContext, untrack } from 'svelte'
|
||||
import { initConfig, initOutput } from '../../editor/appUtils'
|
||||
import {
|
||||
type AppViewerContext,
|
||||
@@ -14,19 +14,29 @@
|
||||
import RecomputeAllWrapper from '../../editor/RecomputeAllWrapper.svelte'
|
||||
import AlignWrapper from '../helpers/AlignWrapper.svelte'
|
||||
|
||||
export let id: string
|
||||
export let initializing: boolean | undefined = false
|
||||
export let customCss: ComponentCustomCSS<'jobiddisplaycomponent'> | undefined = undefined
|
||||
export let configuration: RichConfigurations
|
||||
export let render: boolean
|
||||
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
|
||||
interface Props {
|
||||
id: string
|
||||
initializing?: boolean | undefined
|
||||
customCss?: ComponentCustomCSS<'jobiddisplaycomponent'> | undefined
|
||||
configuration: RichConfigurations
|
||||
render: boolean
|
||||
horizontalAlignment?: 'left' | 'center' | 'right' | undefined
|
||||
}
|
||||
|
||||
let {
|
||||
id,
|
||||
initializing = $bindable(false),
|
||||
customCss = undefined,
|
||||
configuration,
|
||||
render,
|
||||
horizontalAlignment = undefined
|
||||
}: Props = $props()
|
||||
|
||||
const { app, worldStore, policy, recomputeAllContext } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let resolvedConfig = initConfig(
|
||||
components['recomputeallcomponent'].initialData.configuration,
|
||||
configuration
|
||||
let resolvedConfig = $state(
|
||||
initConfig(components['recomputeallcomponent'].initialData.configuration, configuration)
|
||||
)
|
||||
|
||||
initOutput($worldStore, id, {
|
||||
@@ -35,9 +45,7 @@
|
||||
|
||||
initializing = false
|
||||
|
||||
let css = initCss($app.css?.recomputeallcomponent, customCss)
|
||||
|
||||
$: resolvedConfig.defaultRefreshInterval && handleRefreshInterval()
|
||||
let css = $state(initCss($app.css?.recomputeallcomponent, customCss))
|
||||
|
||||
function handleRefreshInterval() {
|
||||
if (resolvedConfig.defaultRefreshInterval !== undefined) {
|
||||
@@ -51,6 +59,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
$effect(() => {
|
||||
resolvedConfig.defaultRefreshInterval && untrack(() => handleRefreshInterval())
|
||||
})
|
||||
</script>
|
||||
|
||||
{#each Object.keys(components['recomputeallcomponent'].initialData.configuration) as key (key)}
|
||||
|
||||
@@ -158,7 +158,10 @@
|
||||
if (!resolvedDatasetsValues) {
|
||||
return
|
||||
}
|
||||
const type = resolvedDatasetsValues[index].type
|
||||
const type = resolvedDatasetsValues?.[index]?.type
|
||||
if (!type) {
|
||||
return
|
||||
}
|
||||
if (type === 'range-bar' || type === 'range-area') {
|
||||
return {
|
||||
type: type,
|
||||
@@ -361,7 +364,7 @@
|
||||
bind:darkMode
|
||||
on:change={(e) => {
|
||||
tick().then(() => {
|
||||
updateChart()
|
||||
chartInstance && resolvedDatasetsValues && updateChart()
|
||||
})
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { getDeleteInput } from './queries/delete'
|
||||
|
||||
export let id: string
|
||||
interface Props {
|
||||
id: string
|
||||
}
|
||||
|
||||
let { id }: Props = $props()
|
||||
|
||||
const { worldStore } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
@@ -19,10 +23,10 @@
|
||||
jobId: undefined
|
||||
})
|
||||
|
||||
let runnableComponent: RunnableComponent
|
||||
let loading = false
|
||||
let runnableComponent: RunnableComponent | undefined = $state()
|
||||
let loading = $state(false)
|
||||
|
||||
let input: AppInput | undefined = undefined
|
||||
let input: AppInput | undefined = $state(undefined)
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
|
||||
+8
-4
@@ -9,7 +9,11 @@
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { getInsertInput } from './queries/insert'
|
||||
|
||||
export let id: string
|
||||
interface Props {
|
||||
id: string
|
||||
}
|
||||
|
||||
let { id }: Props = $props()
|
||||
|
||||
const { worldStore } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
@@ -19,9 +23,9 @@
|
||||
jobId: undefined
|
||||
})
|
||||
|
||||
let runnableComponent: RunnableComponent
|
||||
let loading = false
|
||||
let input: AppInput | undefined = undefined
|
||||
let runnableComponent: RunnableComponent | undefined = $state()
|
||||
let loading = $state(false)
|
||||
let input: AppInput | undefined = $state(undefined)
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import { getContext, onDestroy } from 'svelte'
|
||||
import { getContext, onDestroy, untrack } from 'svelte'
|
||||
import { initConfig, initOutput } from '../../editor/appUtils'
|
||||
import type {
|
||||
AppViewerContext,
|
||||
@@ -17,20 +17,35 @@
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import ResolveStyle from '../helpers/ResolveStyle.svelte'
|
||||
|
||||
export let id: string
|
||||
export let configuration: RichConfigurations
|
||||
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
|
||||
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
|
||||
export let recomputeIds: string[] | undefined = undefined
|
||||
export let customCss: ComponentCustomCSS<'checkboxcomponent'> | undefined = undefined
|
||||
export let render: boolean
|
||||
export let extraKey: string | undefined = undefined
|
||||
export let preclickAction: (() => Promise<void>) | undefined = undefined
|
||||
export let noInitialize = false
|
||||
export let onToggle: string[] | undefined = undefined
|
||||
interface Props {
|
||||
id: string
|
||||
configuration: RichConfigurations
|
||||
horizontalAlignment?: 'left' | 'center' | 'right' | undefined
|
||||
verticalAlignment?: 'top' | 'center' | 'bottom' | undefined
|
||||
recomputeIds?: string[] | undefined
|
||||
customCss?: ComponentCustomCSS<'checkboxcomponent'> | undefined
|
||||
render: boolean
|
||||
extraKey?: string | undefined
|
||||
preclickAction?: (() => Promise<void>) | undefined
|
||||
noInitialize?: boolean
|
||||
onToggle?: string[] | undefined
|
||||
controls?: { left: () => boolean; right: () => boolean | string } | undefined
|
||||
}
|
||||
|
||||
export let controls: { left: () => boolean; right: () => boolean | string } | undefined =
|
||||
undefined
|
||||
let {
|
||||
id,
|
||||
configuration,
|
||||
horizontalAlignment = undefined,
|
||||
verticalAlignment = undefined,
|
||||
recomputeIds = undefined,
|
||||
customCss = undefined,
|
||||
render,
|
||||
extraKey = undefined,
|
||||
preclickAction = undefined,
|
||||
noInitialize = false,
|
||||
onToggle = undefined,
|
||||
controls = undefined
|
||||
}: Props = $props()
|
||||
|
||||
const { app, worldStore, componentControl, runnableComponents } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
@@ -39,12 +54,11 @@
|
||||
const rowContext = getContext<ListContext>('RowWrapperContext')
|
||||
const rowInputs: ListInputs | undefined = getContext<ListInputs>('RowInputs')
|
||||
|
||||
let resolvedConfig = initConfig(
|
||||
components['checkboxcomponent'].initialData.configuration,
|
||||
configuration
|
||||
let resolvedConfig = $state(
|
||||
initConfig(components['checkboxcomponent'].initialData.configuration, configuration)
|
||||
)
|
||||
|
||||
let value: boolean = resolvedConfig.defaultValue ?? false
|
||||
let value: boolean = $state(resolvedConfig.defaultValue ?? false)
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: boolean) {
|
||||
@@ -89,11 +103,15 @@
|
||||
rowInputs?.remove(id)
|
||||
})
|
||||
|
||||
$: value != undefined && handleInput()
|
||||
$effect(() => {
|
||||
value != undefined && untrack(() => handleInput())
|
||||
})
|
||||
|
||||
$: resolvedConfig.defaultValue != undefined && handleDefault()
|
||||
$effect(() => {
|
||||
resolvedConfig.defaultValue != undefined && untrack(() => handleDefault())
|
||||
})
|
||||
|
||||
let css = initCss($app.css?.checkboxcomponent, customCss)
|
||||
let css = $state(initCss($app.css?.checkboxcomponent, customCss))
|
||||
</script>
|
||||
|
||||
{#each Object.keys(components['checkboxcomponent'].initialData.configuration) as key (key)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import { getContext, untrack } from 'svelte'
|
||||
|
||||
import type { AppViewerContext, ComponentCustomCSS, RichConfigurations } from '../../types'
|
||||
import AlignWrapper from '../helpers/AlignWrapper.svelte'
|
||||
@@ -12,27 +12,35 @@
|
||||
import { initCss } from '../../utils'
|
||||
import ResolveStyle from '../helpers/ResolveStyle.svelte'
|
||||
|
||||
export let id: string
|
||||
export let configuration: RichConfigurations
|
||||
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
|
||||
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
|
||||
export let render: boolean
|
||||
export let customCss: ComponentCustomCSS<'selectstepcomponent'> | undefined = undefined
|
||||
interface Props {
|
||||
id: string
|
||||
configuration: RichConfigurations
|
||||
horizontalAlignment?: 'left' | 'center' | 'right' | undefined
|
||||
verticalAlignment?: 'top' | 'center' | 'bottom' | undefined
|
||||
render: boolean
|
||||
customCss?: ComponentCustomCSS<'selectstepcomponent'> | undefined
|
||||
}
|
||||
|
||||
let {
|
||||
id,
|
||||
configuration,
|
||||
horizontalAlignment = undefined,
|
||||
verticalAlignment = undefined,
|
||||
render,
|
||||
customCss = undefined
|
||||
}: Props = $props()
|
||||
|
||||
const { app, worldStore, componentControl } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const resolvedConfig = initConfig(
|
||||
components['selectstepcomponent'].initialData.configuration,
|
||||
configuration
|
||||
const resolvedConfig = $state(
|
||||
initConfig(components['selectstepcomponent'].initialData.configuration, configuration)
|
||||
)
|
||||
const outputs = initOutput($worldStore, id, {
|
||||
result: undefined as string | undefined
|
||||
})
|
||||
|
||||
let selected: string = ''
|
||||
let selectedIndex: number = 0
|
||||
|
||||
$: resolvedConfig.defaultValue != undefined && setDefaultValue()
|
||||
let selected: string = $state('')
|
||||
let selectedIndex: number = $state(0)
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: string) {
|
||||
@@ -80,8 +88,13 @@
|
||||
return typeof item == 'string' ? item : item.label
|
||||
}
|
||||
|
||||
let css = initCss($app.css?.selectstepcomponent, customCss)
|
||||
$: selected && handleSelection(selected)
|
||||
let css = $state(initCss($app.css?.selectstepcomponent, customCss))
|
||||
$effect(() => {
|
||||
resolvedConfig.defaultValue != undefined && untrack(() => setDefaultValue())
|
||||
})
|
||||
$effect(() => {
|
||||
selected && untrack(() => handleSelection(selected))
|
||||
})
|
||||
</script>
|
||||
|
||||
{#each Object.keys(components['selectstepcomponent'].initialData.configuration) as key (key)}
|
||||
@@ -112,7 +125,7 @@
|
||||
class={twMerge(css?.container?.class, 'wm-select-step')}
|
||||
style={css?.container?.style}
|
||||
>
|
||||
<div class="w-full" on:pointerdown={onPointerDown}>
|
||||
<div class="w-full" onpointerdown={onPointerDown}>
|
||||
<Stepper
|
||||
tabs={(resolvedConfig?.items ?? []).map((item) => getLabel(item))}
|
||||
hasValidations={false}
|
||||
|
||||
@@ -17,17 +17,26 @@
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import LightweightResourcePicker from '$lib/components/LightweightResourcePicker.svelte'
|
||||
|
||||
export let id: string
|
||||
export let configuration: RichConfigurations
|
||||
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
|
||||
export let customCss: ComponentCustomCSS<'userresourcecomponent'> | undefined = undefined
|
||||
export let render: boolean
|
||||
interface Props {
|
||||
id: string
|
||||
configuration: RichConfigurations
|
||||
verticalAlignment?: 'top' | 'center' | 'bottom' | undefined
|
||||
customCss?: ComponentCustomCSS<'userresourcecomponent'> | undefined
|
||||
render: boolean
|
||||
}
|
||||
|
||||
let {
|
||||
id,
|
||||
configuration,
|
||||
verticalAlignment = undefined,
|
||||
customCss = undefined,
|
||||
render
|
||||
}: Props = $props()
|
||||
|
||||
const { app, worldStore, componentControl } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let resolvedConfig = initConfig(
|
||||
components['userresourcecomponent'].initialData.configuration,
|
||||
configuration
|
||||
let resolvedConfig = $state(
|
||||
initConfig(components['userresourcecomponent'].initialData.configuration, configuration)
|
||||
)
|
||||
|
||||
const iterContext = getContext<ListContext>('ListWrapperContext')
|
||||
@@ -37,16 +46,18 @@
|
||||
result: undefined as string | undefined
|
||||
})
|
||||
|
||||
let css = initCss($app.css?.['userresourcecomponent'], customCss)
|
||||
let css = $state(initCss($app.css?.['userresourcecomponent'], customCss))
|
||||
|
||||
$: classInput = twMerge(
|
||||
'windmillapp w-full px-2',
|
||||
css?.input?.class ?? '',
|
||||
'wm-input',
|
||||
'wm-user-resource-select'
|
||||
let classInput = $derived(
|
||||
twMerge(
|
||||
'windmillapp w-full px-2',
|
||||
css?.input?.class ?? '',
|
||||
'wm-input',
|
||||
'wm-user-resource-select'
|
||||
)
|
||||
)
|
||||
|
||||
let value: string | undefined = outputs.result.peak()?.replace('$res:', '')
|
||||
let value: string | undefined = $state(outputs.result.peak()?.replace('$res:', ''))
|
||||
|
||||
value && assignValue(outputs.result.peak())
|
||||
|
||||
@@ -76,7 +87,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
let resourcePicker: LightweightResourcePicker | undefined = undefined
|
||||
let resourcePicker: LightweightResourcePicker | undefined = $state(undefined)
|
||||
</script>
|
||||
|
||||
{#each Object.keys(components['userresourcecomponent'].initialData.configuration) as key (key)}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<script lang="ts">
|
||||
import { run } from 'svelte/legacy'
|
||||
|
||||
import { getContext } from 'svelte'
|
||||
import SubGridEditor from '../../editor/SubGridEditor.svelte'
|
||||
import type { AppViewerContext, ComponentCustomCSS, RichConfigurations } from '../../types'
|
||||
@@ -41,7 +39,7 @@
|
||||
}: Props = $props()
|
||||
|
||||
let everRender = $state(render)
|
||||
run(() => {
|
||||
$effect(() => {
|
||||
render && !everRender && (everRender = true)
|
||||
})
|
||||
|
||||
|
||||
@@ -62,12 +62,21 @@
|
||||
/>
|
||||
{/if}
|
||||
{#if (`recomputeIds` in item.data && Array.isArray(item.data.recomputeIds)) || item.data.type === 'buttoncomponent' || item.data.type === 'formbuttoncomponent'}
|
||||
<EventHandlerItem
|
||||
title="on success"
|
||||
tooltip="Select components to recompute after this runnable has successfully run"
|
||||
items={Object.keys($runnableComponents).filter((id) => id !== ownId)}
|
||||
bind:value={item.data.recomputeIds}
|
||||
/>
|
||||
{#if item.data.type == 'checkboxcomponent'}
|
||||
<EventHandlerItem
|
||||
title="on change"
|
||||
tooltip="When the value change, regardless of the source"
|
||||
items={Object.keys($runnableComponents).filter((id) => id !== ownId)}
|
||||
bind:value={item.data.recomputeIds}
|
||||
/>
|
||||
{:else}
|
||||
<EventHandlerItem
|
||||
title="on success"
|
||||
tooltip="Select components to recompute after this runnable has successfully run"
|
||||
items={Object.keys($runnableComponents).filter((id) => id !== ownId)}
|
||||
bind:value={item.data.recomputeIds}
|
||||
/>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if item.data.type === 'checkboxcomponent'}
|
||||
<EventHandlerItem
|
||||
|
||||
Reference in New Issue
Block a user