fix: fix app button form modal
This commit is contained in:
@@ -311,7 +311,7 @@
|
||||
/>
|
||||
{:else if inputCat == 'string'}
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="flex flex-row w-full items- justify-between">
|
||||
<div class="flex flex-row w-full items-center justify-between">
|
||||
<textarea
|
||||
rows="1"
|
||||
bind:this={el}
|
||||
|
||||
@@ -21,30 +21,30 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class={twMerge('w-full flex flex-col overflow-auto', largeGap ? 'gap-8' : 'gap-2')}>
|
||||
<div
|
||||
class={twMerge('w-full flex flex-col overflow-auto px-0.5 pb-2', largeGap ? 'gap-8' : 'gap-2')}
|
||||
>
|
||||
{#each Object.keys(schema.properties ?? {}) as argName (argName)}
|
||||
<div>
|
||||
{#if typeof args == 'object' && schema?.properties[argName] && args}
|
||||
<LightweightArgInput
|
||||
label={argName}
|
||||
description={schema.properties[argName].description}
|
||||
bind:value={args[argName]}
|
||||
bind:valid={inputCheck[argName]}
|
||||
type={schema.properties[argName].type}
|
||||
required={schema.required?.includes(argName) ?? false}
|
||||
pattern={schema.properties[argName].pattern}
|
||||
defaultValue={schema.properties[argName].default}
|
||||
enum_={schema.properties[argName].enum}
|
||||
format={schema.properties[argName].format}
|
||||
contentEncoding={schema.properties[argName].contentEncoding}
|
||||
properties={schema.properties[argName].properties}
|
||||
itemsType={schema.properties[argName].items}
|
||||
extra={schema.properties[argName]}
|
||||
on:inputClicked
|
||||
{displayType}
|
||||
{css}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{#if typeof args == 'object' && schema?.properties[argName] && args}
|
||||
<LightweightArgInput
|
||||
label={argName}
|
||||
description={schema.properties[argName].description}
|
||||
bind:value={args[argName]}
|
||||
bind:valid={inputCheck[argName]}
|
||||
type={schema.properties[argName].type}
|
||||
required={schema.required?.includes(argName) ?? false}
|
||||
pattern={schema.properties[argName].pattern}
|
||||
defaultValue={schema.properties[argName].default}
|
||||
enum_={schema.properties[argName].enum}
|
||||
format={schema.properties[argName].format}
|
||||
contentEncoding={schema.properties[argName].contentEncoding}
|
||||
properties={schema.properties[argName].properties}
|
||||
itemsType={schema.properties[argName].items}
|
||||
extra={schema.properties[argName]}
|
||||
on:inputClicked
|
||||
{displayType}
|
||||
{css}
|
||||
/>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
)
|
||||
|
||||
let runnableComponent: RunnableComponent
|
||||
let isLoading: boolean = false
|
||||
let loading = false
|
||||
|
||||
$: noInputs =
|
||||
@@ -97,7 +96,7 @@
|
||||
<div class="flex justify-end my-1">
|
||||
{#if !noInputs}
|
||||
<Button
|
||||
loading={isLoading}
|
||||
{loading}
|
||||
btnClasses={css?.button?.class}
|
||||
style={css?.button?.style ?? ''}
|
||||
on:pointerdown={(e) => {
|
||||
|
||||
@@ -56,10 +56,6 @@
|
||||
$: noInputs =
|
||||
componentInput?.type != 'runnable' || Object.keys(componentInput?.fields ?? {}).length == 0
|
||||
|
||||
$: if (outputs?.loading != undefined) {
|
||||
outputs.loading.set(false, true)
|
||||
}
|
||||
|
||||
$: css = concatCustomCss($app?.css?.formbuttoncomponent, customCss)
|
||||
let runnableWrapper: RunnableWrapper
|
||||
let loading = false
|
||||
@@ -75,38 +71,37 @@
|
||||
/>
|
||||
{/each}
|
||||
|
||||
<AlwaysMountedModal title={resolvedConfig.label ?? ''} bind:this={modal}>
|
||||
<RunnableWrapper
|
||||
bind:this={runnableWrapper}
|
||||
{recomputeIds}
|
||||
{render}
|
||||
bind:runnableComponent
|
||||
{componentInput}
|
||||
{id}
|
||||
{extraQueryParams}
|
||||
autoRefresh={false}
|
||||
forceSchemaDisplay={true}
|
||||
runnableClass="!block"
|
||||
{outputs}
|
||||
doOnSuccess={resolvedConfig.onSuccess}
|
||||
doOnError={resolvedConfig.onError}
|
||||
{errorHandledByComponent}
|
||||
>
|
||||
<div class="flex flex-col gap-2 px-4 w-full">
|
||||
<div>
|
||||
{#if noInputs}
|
||||
<div class="text-gray-600 italic text-sm my-4">
|
||||
Run forms are associated with a runnable that has user inputs.
|
||||
<br />
|
||||
Once a script or flow is chosen, set some <strong>Runnable Inputs</strong> to
|
||||
<strong>
|
||||
User Input
|
||||
<Icon data={faUser} scale={1.3} class="rounded-sm bg-gray-200 p-1 ml-0.5" />
|
||||
</strong>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex justify-end">
|
||||
<AlwaysMountedModal {css} title={resolvedConfig.modalTitle ?? ''} bind:this={modal}>
|
||||
<div class="flex flex-col gap-2 px-4 w-full pt-2">
|
||||
<RunnableWrapper
|
||||
bind:this={runnableWrapper}
|
||||
bind:loading
|
||||
{recomputeIds}
|
||||
{render}
|
||||
bind:runnableComponent
|
||||
{componentInput}
|
||||
{id}
|
||||
{extraQueryParams}
|
||||
autoRefresh={false}
|
||||
forceSchemaDisplay={true}
|
||||
runnableClass="!block"
|
||||
{outputs}
|
||||
doOnSuccess={resolvedConfig.onSuccess}
|
||||
doOnError={resolvedConfig.onError}
|
||||
{errorHandledByComponent}
|
||||
>
|
||||
{#if noInputs}
|
||||
<div class="text-gray-600 italic text-sm my-4">
|
||||
Run forms are associated with a runnable that has user inputs.
|
||||
<br />
|
||||
Once a script or flow is chosen, set some <strong>Runnable Inputs</strong> to
|
||||
<strong>
|
||||
User Input
|
||||
<Icon data={faUser} scale={1.3} class="rounded-sm bg-gray-200 p-1 ml-0.5" />
|
||||
</strong>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="flex justify-end gap-3 p-2">
|
||||
<Button
|
||||
{loading}
|
||||
btnClasses="my-1"
|
||||
@@ -119,6 +114,7 @@
|
||||
} else {
|
||||
await runnableComponent?.runComponent()
|
||||
}
|
||||
console.log('close')
|
||||
modal?.close()
|
||||
}}
|
||||
size="xs"
|
||||
@@ -127,11 +123,11 @@
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</RunnableWrapper>
|
||||
</RunnableWrapper>
|
||||
</div>
|
||||
</AlwaysMountedModal>
|
||||
|
||||
<AlignWrapper {horizontalAlignment} {verticalAlignment}>
|
||||
<AlignWrapper {render} {horizontalAlignment} {verticalAlignment}>
|
||||
{#if errorsMessage}
|
||||
<div class="text-red-500 text-xs">{errorsMessage}</div>
|
||||
{/if}
|
||||
|
||||
@@ -265,7 +265,11 @@
|
||||
|
||||
export async function runComponent() {
|
||||
try {
|
||||
await executeComponent()
|
||||
if (cancellableRun) {
|
||||
await cancellableRun()
|
||||
} else {
|
||||
executeComponent()
|
||||
}
|
||||
} catch (e) {
|
||||
setResult({ error: e.body ?? e.message }, undefined)
|
||||
}
|
||||
@@ -345,10 +349,11 @@
|
||||
!$connectingInput.opened && selectId(event, id, selectedComponent, $app)
|
||||
}
|
||||
|
||||
let cancellableRun: ((inlineScript?: InlineScript) => CancelablePromise<void>) | undefined =
|
||||
undefined
|
||||
|
||||
onMount(() => {
|
||||
const cancellableRun: (inlineScript?: InlineScript) => CancelablePromise<void> = (
|
||||
inlineScript?: InlineScript
|
||||
) => {
|
||||
cancellableRun = (inlineScript?: InlineScript) => {
|
||||
let rejectCb: (err: Error) => void
|
||||
let p: Partial<CancelablePromise<void>> = new Promise<void>((resolve, reject) => {
|
||||
rejectCb = reject
|
||||
|
||||
@@ -52,9 +52,8 @@
|
||||
<InputValue {id} input={configuration.defaultValue} bind:value={defaultValue} />
|
||||
|
||||
<InitializeComponent {id} />
|
||||
|
||||
{#if inputType === 'textarea'}
|
||||
{#if render}
|
||||
{#if render}
|
||||
{#if inputType === 'textarea'}
|
||||
<textarea
|
||||
class={twMerge(
|
||||
'windmillapp w-full h-full py-1.5 text-sm focus:ring-indigo-100 px-2 ',
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
/>
|
||||
{/each}
|
||||
|
||||
<InitializeComponent {id} />
|
||||
|
||||
<div class="h-full w-full">
|
||||
<AlignWrapper {noWFull} {horizontalAlignment} {verticalAlignment}>
|
||||
<Button
|
||||
@@ -74,8 +76,6 @@
|
||||
</AlignWrapper>
|
||||
</div>
|
||||
|
||||
<InitializeComponent {id} />
|
||||
|
||||
<Portal target="#app-editor-top-level-drawer">
|
||||
<Drawer
|
||||
let:open
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
)
|
||||
</script>
|
||||
|
||||
<svelte:window on:keyup={handleKeyUp} />
|
||||
|
||||
<InitializeComponent {id} />
|
||||
|
||||
{#each Object.keys(components['modalcomponent'].initialData.configuration) as key (key)}
|
||||
@@ -61,35 +63,35 @@
|
||||
configuration={configuration[key]}
|
||||
/>
|
||||
{/each}
|
||||
<svelte:window on:keyup={handleKeyUp} />
|
||||
|
||||
<div class="h-full w-full">
|
||||
<AlignWrapper {noWFull} {horizontalAlignment} {verticalAlignment}>
|
||||
<Button
|
||||
btnClasses={css?.button?.class}
|
||||
wrapperClasses={twMerge(
|
||||
resolvedConfig?.buttonFillContainer ? 'w-full h-full' : '',
|
||||
css?.buttonContainer?.class
|
||||
)}
|
||||
wrapperStyle={css?.buttonContainer?.style}
|
||||
disabled={resolvedConfig.buttonDisabled}
|
||||
on:pointerdown={(e) => {
|
||||
e?.stopPropagation()
|
||||
}}
|
||||
on:click={async (e) => {
|
||||
$focusedGrid = {
|
||||
parentComponentId: id,
|
||||
subGridIndex: 0
|
||||
}
|
||||
open = true
|
||||
}}
|
||||
size={resolvedConfig.buttonSize}
|
||||
color={resolvedConfig.buttonColor}
|
||||
>
|
||||
<div>{resolvedConfig.buttonLabel}</div>
|
||||
</Button>
|
||||
</AlignWrapper>
|
||||
</div>
|
||||
{#if render}
|
||||
<div class="h-full w-full">
|
||||
<AlignWrapper {noWFull} {horizontalAlignment} {verticalAlignment}>
|
||||
<Button
|
||||
btnClasses={css?.button?.class}
|
||||
wrapperClasses={twMerge(
|
||||
resolvedConfig?.buttonFillContainer ? 'w-full h-full' : '',
|
||||
css?.buttonContainer?.class
|
||||
)}
|
||||
wrapperStyle={css?.buttonContainer?.style}
|
||||
disabled={resolvedConfig.buttonDisabled}
|
||||
on:pointerdown={(e) => {
|
||||
e?.stopPropagation()
|
||||
}}
|
||||
on:click={async (e) => {
|
||||
$focusedGrid = {
|
||||
parentComponentId: id,
|
||||
subGridIndex: 0
|
||||
}
|
||||
open = true
|
||||
}}
|
||||
size={resolvedConfig.buttonSize}
|
||||
color={resolvedConfig.buttonColor}
|
||||
>
|
||||
<div>{resolvedConfig.buttonLabel}</div>
|
||||
</Button>
|
||||
</AlignWrapper>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<Portal target="#app-editor-top-level-drawer">
|
||||
<div
|
||||
@@ -113,7 +115,7 @@
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div class="p-4 border-b flex justify-between items-center">
|
||||
<div class="px-4 py-2 border-b flex justify-between items-center">
|
||||
<div>{resolvedConfig.modalTitle}</div>
|
||||
<div class="w-8">
|
||||
<button
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
pickVariableCallback,
|
||||
movingcomponents: writable(undefined),
|
||||
selectedComponentInEditor: writable(undefined),
|
||||
jobsDrawerOpen: writable(false),
|
||||
jobsDrawerOpen: writable(false)
|
||||
})
|
||||
|
||||
let timeout: NodeJS.Timeout | undefined = undefined
|
||||
|
||||
@@ -106,9 +106,9 @@
|
||||
|
||||
<svelte:window on:hashchange={hashchange} on:resize={resizeWindow} />
|
||||
|
||||
<div id="app-editor-top-level-drawer" />
|
||||
|
||||
<div class="relative">
|
||||
<div id="app-editor-top-level-drawer" />
|
||||
|
||||
<div
|
||||
class="{$$props.class} {lockedClasses} {width} h-full {app.fullscreen
|
||||
? ''
|
||||
|
||||
@@ -709,6 +709,12 @@ export const components = {
|
||||
},
|
||||
recomputeIds: true,
|
||||
configuration: {
|
||||
modalTitle: {
|
||||
type: 'static',
|
||||
fieldType: 'text',
|
||||
value: 'Modal title',
|
||||
onlyStatic: true
|
||||
},
|
||||
label: {
|
||||
type: 'static',
|
||||
value: 'Open popup',
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
Dialog,
|
||||
DialogOverlay,
|
||||
DialogTitle,
|
||||
Transition,
|
||||
TransitionChild
|
||||
} from '@rgossiaux/svelte-headlessui'
|
||||
import Portal from 'svelte-portal'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import Button from '../button/Button.svelte'
|
||||
import Badge from '../badge/Badge.svelte'
|
||||
import { clickOutside } from '$lib/utils'
|
||||
import { X } from 'lucide-svelte'
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppViewerContext } from '$lib/components/apps/types'
|
||||
|
||||
export let title: string
|
||||
export let style: string = ''
|
||||
export let css: any = {}
|
||||
|
||||
const { mode } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let isOpen = false
|
||||
|
||||
@@ -26,58 +24,54 @@
|
||||
</script>
|
||||
|
||||
<Portal target="#app-editor-top-level-drawer">
|
||||
<Transition show={isOpen}>
|
||||
<Dialog as="div" class="absolute inset-0 overflow-y-auto z-50" on:close={close}>
|
||||
<div class="min-h-screen px-4 text-center">
|
||||
<TransitionChild
|
||||
enter="ease-out duration-100"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="ease-in duration-100"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<DialogOverlay class="fixed inset-0 bg-gray-800/50 " />
|
||||
</TransitionChild>
|
||||
|
||||
<TransitionChild
|
||||
enter="ease-out duration-[50ms]"
|
||||
enterFrom="opacity-0 scale-95"
|
||||
enterTo="opacity-100 scale-100"
|
||||
leave="ease-in dduration-[50ms]"
|
||||
leaveFrom="opacity-100 scale-100"
|
||||
leaveTo="opacity-0 scale-95"
|
||||
>
|
||||
<!-- This element is to trick the browser into centering the modal contents. -->
|
||||
<span class="inline-block h-screen align-middle" aria-hidden="true"> ​ </span>
|
||||
<div
|
||||
class="inline-block w-full max-w-md p-6 text-left align-middle transition-all transform bg-white shadow-xl rounded-md"
|
||||
>
|
||||
<DialogTitle class="text-lg font-medium leading-6 text-gray-900">
|
||||
{title}
|
||||
</DialogTitle>
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="relative bg-white rounded-md" on:click|stopPropagation={() => {}}>
|
||||
<div
|
||||
class={twMerge(
|
||||
'max-w-screen-lg max-h-screen-80 overflow-auto flex flex-col',
|
||||
$$props.class
|
||||
)}
|
||||
{style}
|
||||
>
|
||||
<div class="flex-1">
|
||||
<slot />
|
||||
</div>
|
||||
<div class="flex items-center space-x-2 flex-row-reverse space-x-reverse mt-4">
|
||||
<Button on:click={close} color="light" size="sm">
|
||||
<span class="gap-2">Cancel <Badge color="dark-gray">Escape</Badge></span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class={twMerge(
|
||||
`${
|
||||
$mode == 'dnd' ? 'absolute' : 'fixed'
|
||||
} top-0 bottom-0 left-0 right-0 transition-all duration-50 overflow-hidden`,
|
||||
isOpen ? 'z-[1100] bg-black bg-opacity-60' : 'hidden'
|
||||
)}
|
||||
>
|
||||
<div class="flex min-h-full items-center justify-center p-4">
|
||||
<div
|
||||
style={css?.popup?.style}
|
||||
class={twMerge(
|
||||
'bg-white max-w-5xl m-24 overflow-y-auto rounded-lg relative',
|
||||
css?.popup?.class
|
||||
)}
|
||||
use:clickOutside
|
||||
on:click_outside={() => {
|
||||
close()
|
||||
}}
|
||||
>
|
||||
<div class="px-4 py-2 border-b flex justify-between items-center">
|
||||
<div>{title}</div>
|
||||
<div class="w-8">
|
||||
<button
|
||||
on:click={() => {
|
||||
isOpen = false
|
||||
}}
|
||||
style={css?.button?.style}
|
||||
class="hover:bg-gray-200 bg-gray-100 rounded-full w-8 h-8 flex items-center justify-center transition-all"
|
||||
>
|
||||
<X class="text-gray-500" />
|
||||
</button>
|
||||
</div>
|
||||
</TransitionChild>
|
||||
</div>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="relative bg-white rounded-md" on:click|stopPropagation={() => {}}>
|
||||
<div
|
||||
class={twMerge(
|
||||
'max-w-screen-lg max-h-screen-80 overflow-auto flex flex-col',
|
||||
$$props.class
|
||||
)}
|
||||
{style}
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition>
|
||||
</Portal>
|
||||
</div>
|
||||
</div></Portal
|
||||
>
|
||||
|
||||
@@ -390,14 +390,14 @@
|
||||
>{curlCommand(true)} <span
|
||||
on:click={() => copyToClipboard(curlCommand(true))}
|
||||
class="cursor-pointer ml-2"><Icon data={faClipboard} /></span
|
||||
></TabContent
|
||||
><br /><br />//^ returns an UUID. Fetch result until completed == true<br
|
||||
/>curl -H "Authorization: Bearer $TOKEN" {$page.url.protocol}//{$page.url
|
||||
.hostname}/api/w/{$workspaceStore}/jobs_u/completed/get_result_maybe/$UUID</TabContent
|
||||
><TabContent value="sync"
|
||||
>{curlCommand(false)} <span
|
||||
on:click={() => copyToClipboard(curlCommand(false))}
|
||||
class="cursor-pointer ml-2"><Icon data={faClipboard} /></span
|
||||
><br /><br />//^ returns an UUID. Fetch result until completed == true<br
|
||||
/>curl -H "Authorization: Bearer $TOKEN" {$page.url.protocol}//{$page.url
|
||||
.hostname}/api/w/{$workspaceStore}/jobs_u/completed/get_result_maybe/$UUID</TabContent
|
||||
></TabContent
|
||||
></pre
|
||||
>
|
||||
</svelte:fragment>
|
||||
|
||||
@@ -317,9 +317,3 @@
|
||||
loadSchedules()
|
||||
}}
|
||||
/>
|
||||
|
||||
<style lang="postcss">
|
||||
td {
|
||||
@apply px-2;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user