mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-12 16:05:43 +00:00
feat(frontend): app static and user resource picker default values (#6179)
This commit is contained in:
@@ -1,40 +1,37 @@
|
||||
<script lang="ts">
|
||||
import { ResourceService } from '$lib/gen'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
import { getContext, untrack } from 'svelte'
|
||||
import DarkModeObserver from './DarkModeObserver.svelte'
|
||||
import { Button, Drawer, DrawerContent } from './common'
|
||||
import { Plus, Loader2, Link2Off } from 'lucide-svelte'
|
||||
import type { AppViewerContext } from './apps/types'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { createDispatcherIfMounted } from '$lib/createDispatcherIfMounted'
|
||||
import Select from './select/Select.svelte'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const dispatchIfMounted = createDispatcherIfMounted(dispatch)
|
||||
interface Props {
|
||||
value: string | undefined
|
||||
resourceType?: string | undefined
|
||||
disablePortal?: boolean
|
||||
expressOAuthSetup?: boolean
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
export let initialValue: string | undefined = undefined
|
||||
export let value: string | undefined = initialValue
|
||||
export let resourceType: string | undefined = undefined
|
||||
export let disablePortal = false
|
||||
export let expressOAuthSetup = false
|
||||
export let disabled = false
|
||||
let {
|
||||
value = $bindable(),
|
||||
resourceType = undefined,
|
||||
disablePortal = false,
|
||||
expressOAuthSetup = false,
|
||||
disabled = false
|
||||
}: Props = $props()
|
||||
|
||||
let open = false
|
||||
let refreshCount = 0
|
||||
let open = $state(false)
|
||||
let refreshCount = $state(0)
|
||||
const appViewerContext = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let valueSelect =
|
||||
initialValue || value
|
||||
? {
|
||||
value: value ?? initialValue,
|
||||
label: value ?? initialValue
|
||||
}
|
||||
: undefined
|
||||
let collection = $state(value ? [{ value, label: value }] : [])
|
||||
|
||||
let collection = valueSelect ? [valueSelect] : []
|
||||
|
||||
let loading = true
|
||||
let loading = $state(true)
|
||||
async function loadResources(resourceType: string | undefined) {
|
||||
loading = true
|
||||
try {
|
||||
@@ -49,26 +46,25 @@
|
||||
}))
|
||||
|
||||
// TODO check if this is needed
|
||||
if (!nc.find((x) => x.value == value) && (initialValue || value)) {
|
||||
nc.push({ value: value ?? initialValue!, label: value ?? initialValue! })
|
||||
if (!nc.find((x) => x.value == value) && value) {
|
||||
nc.push({ value: value, label: value })
|
||||
}
|
||||
collection = nc
|
||||
if (expressOAuthSetup && nc.length > 0) {
|
||||
value = nc[0].value
|
||||
valueSelect = nc[0]
|
||||
}
|
||||
} finally {
|
||||
loading = false
|
||||
}
|
||||
}
|
||||
|
||||
$: $workspaceStore && loadResources(resourceType)
|
||||
$effect(() => {
|
||||
$workspaceStore && resourceType && untrack(() => loadResources(resourceType))
|
||||
})
|
||||
|
||||
$: dispatchIfMounted('change', value)
|
||||
let darkMode: boolean = $state(false)
|
||||
|
||||
let darkMode: boolean = false
|
||||
|
||||
let drawer: Drawer | undefined = undefined
|
||||
let drawer: Drawer | undefined = $state(undefined)
|
||||
|
||||
export function askNewResource() {
|
||||
refreshCount += 1
|
||||
@@ -93,7 +89,6 @@
|
||||
on:refresh={async (e) => {
|
||||
await loadResources(resourceType)
|
||||
value = e.detail
|
||||
valueSelect = { value, label: value }
|
||||
open = false
|
||||
}}
|
||||
/>
|
||||
@@ -121,7 +116,6 @@
|
||||
on:refresh={async (e) => {
|
||||
await loadResources(resourceType)
|
||||
value = e.detail
|
||||
valueSelect = { value, label: value }
|
||||
drawer?.closeDrawer?.()
|
||||
open = false
|
||||
}}
|
||||
@@ -157,7 +151,6 @@
|
||||
const item = collection[0]
|
||||
if (item) {
|
||||
value = item.value
|
||||
valueSelect = item
|
||||
}
|
||||
}}>Use existing</Button
|
||||
>
|
||||
@@ -167,15 +160,13 @@
|
||||
{disabled}
|
||||
{disablePortal}
|
||||
bind:value={
|
||||
() => valueSelect?.value,
|
||||
() => value,
|
||||
(v) => {
|
||||
value = v
|
||||
valueSelect = collection.find((x) => x.value === v)
|
||||
}
|
||||
}
|
||||
onClear={() => {
|
||||
value = undefined
|
||||
valueSelect = undefined
|
||||
}}
|
||||
clearable
|
||||
items={collection}
|
||||
@@ -184,7 +175,7 @@
|
||||
/>
|
||||
{/if}
|
||||
<div class="flex gap-1 items-center">
|
||||
{#if valueSelect && expressOAuthSetup}
|
||||
{#if value && expressOAuthSetup}
|
||||
<Button
|
||||
{disabled}
|
||||
color="light"
|
||||
@@ -193,15 +184,13 @@
|
||||
btnClasses="w-8 px-0.5 py-1.5"
|
||||
iconOnly
|
||||
on:click={async () => {
|
||||
if (valueSelect && valueSelect.label) {
|
||||
value = undefined
|
||||
if (value) {
|
||||
await ResourceService.deleteResource({
|
||||
workspace: appViewerContext?.workspace ?? $workspaceStore,
|
||||
path: valueSelect.label
|
||||
path: value
|
||||
})
|
||||
await loadResources(resourceType)
|
||||
value = undefined
|
||||
valueSelect = undefined
|
||||
await loadResources(resourceType)
|
||||
}
|
||||
}}
|
||||
startIcon={{ icon: Link2Off }}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { getContext, onDestroy } from 'svelte'
|
||||
import { getContext, onDestroy, untrack } from 'svelte'
|
||||
import { initConfig, initOutput } from '../../editor/appUtils'
|
||||
import type {
|
||||
AppViewerContext,
|
||||
@@ -33,7 +33,8 @@
|
||||
render
|
||||
}: Props = $props()
|
||||
|
||||
const { app, worldStore, componentControl } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { app, worldStore, componentControl, isEditor, mode } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let resolvedConfig = $state(
|
||||
initConfig(components['userresourcecomponent'].initialData.configuration, configuration)
|
||||
@@ -57,9 +58,34 @@
|
||||
)
|
||||
)
|
||||
|
||||
let value: string | undefined = $state(outputs.result.peak()?.replace('$res:', ''))
|
||||
function getDefaultValue(): string | undefined {
|
||||
if (resolvedConfig.defaultValue && typeof resolvedConfig.defaultValue === 'string') {
|
||||
const nval = resolvedConfig.defaultValue as string
|
||||
return nval.replace('$res:', '')
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
value && assignValue(outputs.result.peak())
|
||||
let value: string | undefined = $state(
|
||||
outputs.result.peak()?.replace('$res:', '') ?? getDefaultValue()
|
||||
)
|
||||
|
||||
$effect(() => {
|
||||
value
|
||||
untrack(() => assignValue(value))
|
||||
})
|
||||
|
||||
let lastDefaultValue = $state(getDefaultValue())
|
||||
$effect(() => {
|
||||
// when in dnd mode, we react to the default value being changed for better UX
|
||||
if (isEditor && $mode === 'dnd') {
|
||||
const currentDefaultValue = getDefaultValue() // reactive
|
||||
if (lastDefaultValue !== currentDefaultValue) {
|
||||
value = currentDefaultValue
|
||||
lastDefaultValue = currentDefaultValue
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
listInputs?.remove(id)
|
||||
@@ -74,7 +100,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
function assignValue(value: string) {
|
||||
function assignValue(value: string | undefined) {
|
||||
let nval
|
||||
if (!value || value === '') {
|
||||
nval = undefined
|
||||
@@ -119,10 +145,7 @@
|
||||
<LightweightResourcePicker
|
||||
expressOAuthSetup={resolvedConfig.expressOauthSetup}
|
||||
bind:this={resourcePicker}
|
||||
{value}
|
||||
on:change={(e) => {
|
||||
assignValue(e.detail)
|
||||
}}
|
||||
bind:value
|
||||
disabled={resolvedConfig.disabled}
|
||||
resourceType={resolvedConfig.resourceType}
|
||||
/>
|
||||
|
||||
@@ -1648,8 +1648,8 @@ export const components = {
|
||||
backgroundColor: ['#FF6384', '#4BC0C0', '#FFCE56']
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
chartjscomponentv2: {
|
||||
@@ -1687,9 +1687,8 @@ export const components = {
|
||||
backgroundColor: ['#FF6384', '#4BC0C0', '#FFCE56']
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
barchartcomponent: {
|
||||
@@ -1859,8 +1858,7 @@ This is a paragraph.
|
||||
width: 2.5
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
configuration: {
|
||||
layout: {
|
||||
@@ -1893,7 +1891,7 @@ This is a paragraph.
|
||||
width: 2.5
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
configuration: {
|
||||
layout: {
|
||||
@@ -1904,8 +1902,7 @@ This is a paragraph.
|
||||
'Layout options for the plot. See https://plotly.com/javascript/reference/layout/ for more information'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
timeseriescomponent: {
|
||||
name: 'Timeseries',
|
||||
@@ -2431,6 +2428,12 @@ This is a paragraph.
|
||||
allowTypeChange: false,
|
||||
value: []
|
||||
} as StaticAppInput,
|
||||
defaultValue: {
|
||||
type: 'static',
|
||||
fieldType: 'text',
|
||||
value: undefined,
|
||||
tooltip: 'Format: $res:path/to/resource'
|
||||
},
|
||||
placeholder: {
|
||||
type: 'static',
|
||||
fieldType: 'text',
|
||||
@@ -2468,6 +2471,12 @@ This is a paragraph.
|
||||
fieldType: 'text',
|
||||
value: 'postgresql'
|
||||
},
|
||||
defaultValue: {
|
||||
type: 'static',
|
||||
fieldType: 'text',
|
||||
value: undefined,
|
||||
tooltip: 'Format: $res:path/to/resource'
|
||||
},
|
||||
expressOauthSetup: {
|
||||
type: 'static',
|
||||
fieldType: 'boolean',
|
||||
|
||||
@@ -156,8 +156,8 @@
|
||||
<div class="h-screen">
|
||||
{#key value}
|
||||
<AppEditor
|
||||
on:savedNewAppPath={(event) => {
|
||||
goto(`/apps/edit/${event.detail}`)
|
||||
onSavedNewAppPath={(path) => {
|
||||
goto(`/apps/edit/${path}`)
|
||||
}}
|
||||
{summary}
|
||||
app={value}
|
||||
|
||||
Reference in New Issue
Block a user