fix: fix app button form modal

This commit is contained in:
Ruben Fiszel
2023-06-12 14:11:41 +02:00
parent 06b64aa176
commit edf62764e5
14 changed files with 175 additions and 180 deletions

View File

@@ -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}

View File

@@ -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>

View File

@@ -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) => {

View File

@@ -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}

View File

@@ -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

View File

@@ -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 ',

View File

@@ -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

View File

@@ -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

View File

@@ -113,7 +113,7 @@
pickVariableCallback,
movingcomponents: writable(undefined),
selectedComponentInEditor: writable(undefined),
jobsDrawerOpen: writable(false),
jobsDrawerOpen: writable(false)
})
let timeout: NodeJS.Timeout | undefined = undefined

View File

@@ -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
? ''

View File

@@ -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',

View File

@@ -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"> &#8203; </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
>

View File

@@ -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>

View File

@@ -317,9 +317,3 @@
loadSchedules()
}}
/>
<style lang="postcss">
td {
@apply px-2;
}
</style>