fix(frontend): App form component (#1087)

* fix(frontend): Make app form usage more clear

* fix(frontend): Form orientation

* fix(frontend): Form message format

Co-authored-by: Ruben Fiszel <ruben@rubenfiszel.com>
This commit is contained in:
Ádám Kovács
2023-01-11 11:24:46 +01:00
committed by GitHub
parent 6bc0320bff
commit e93c511bb5
5 changed files with 116 additions and 71 deletions

View File

@@ -7,6 +7,7 @@
export let placement: `${typeof SIDE[number]}` | `${typeof SIDE[number]}-${typeof ALIGN[number]}` = 'auto'
export let notClickable = false
export let popupClass = ''
export let disapperTimoout = 100
const [popperRef, popperContent] = createPopperActions({ placement })
const betterPreventOverflow = (options) => ({
@@ -39,20 +40,30 @@
showTooltip = true
}
function close() {
timeout = setTimeout(() => (showTooltip = false), 100)
timeout = setTimeout(() => (showTooltip = false), disapperTimoout)
}
</script>
<button
class:cursor-default={notClickable}
use:popperRef
on:mouseenter={open}
on:mouseleave={close}
on:click
class={$$props.class}
>
<slot />
</button>
{#if notClickable}
<span
use:popperRef
on:mouseenter={open}
on:mouseleave={close}
class={$$props.class}
>
<slot />
</span>
{:else}
<button
use:popperRef
on:mouseenter={open}
on:mouseleave={close}
on:click
class={$$props.class}
>
<slot />
</button>
{/if}
{#if showTooltip}
<div
use:popperContent={extraOpts}

View File

@@ -1,6 +1,8 @@
<script lang="ts">
import { Button, type ButtonType } from '$lib/components/common'
import { faUser } from '@fortawesome/free-solid-svg-icons'
import { getContext } from 'svelte'
import { Icon } from 'svelte-awesome'
import type { AppInput } from '../../inputType'
import type { Output } from '../../rx'
import type { AppEditorContext } from '../../types'
@@ -27,6 +29,8 @@
let isLoading: boolean = false
$: noInputs = componentInput?.type != 'runnable' || Object.values(componentInput?.fields ?? {}).filter((x) => x.type == 'user').length == 0
$: outputs = $worldStore?.outputsById[id] as {
result: Output<Array<any>>
loading: Output<boolean>
@@ -56,39 +60,47 @@
{extraQueryParams}
autoRefresh={false}
forceSchemaDisplay={true}
runnableClass="!flex-col"
>
<AlignWrapper {horizontalAlignment}>
<div class="flex flex-col gap-2 px-4 w-full ">
<div>
{#if componentInput?.type != 'runnable' || Object.values(componentInput?.fields ?? {}).filter((x) => x.type == 'user').length == 0}
<span class="text-gray-600 italic text-sm py-2">
Run forms are associated with a runnable that has user inputs. Once a runnable is
chosen, set some 'Runnable Inputs' to 'User Input'
</span>
{#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">
<Button
loading={isLoading}
btnClasses="my-1"
on:pointerdown={(e) => {
e?.stopPropagation()
window.dispatchEvent(new Event('pointerup'))
}}
on:click={() => {
runnableComponent?.runComponent()
{#if !noInputs}
<Button
loading={isLoading}
btnClasses="my-1"
on:pointerdown={(e) => {
e?.stopPropagation()
window.dispatchEvent(new Event('pointerup'))
}}
on:click={() => {
runnableComponent?.runComponent()
if (recomputeIds) {
recomputeIds.forEach((id) => {
$runnableComponents[id]?.()
})
}
}}
{size}
{color}
>
{labelValue}
</Button>
if (recomputeIds) {
recomputeIds.forEach((id) => {
$runnableComponents[id]?.()
})
}
}}
{size}
{color}
>
{labelValue}
</Button>
{/if}
</div>
</div>
</AlignWrapper>

View File

@@ -24,6 +24,7 @@
export let noMinH = false
export let defaultUserInput = false
export let flexWrap = false
export let wrapperClass = ''
const { worldStore, runnableComponents, workspace, appPath, isEditor, jobs, noBackend } =
getContext<AppEditorContext>('AppEditorContext')
@@ -271,7 +272,7 @@
bind:this={testJobLoader}
/>
<div class="h-full flex relative flex-row flex-wrap">
<div class="h-full flex relative flex-row flex-wrap {wrapperClass}">
{#if autoRefresh === true}
<div class="flex absolute top-1 right-1">
<RefreshButton componentId={id} />

View File

@@ -17,6 +17,7 @@
export let forceSchemaDisplay: boolean = false
export let defaultUserInput = false
export let flexWrap = false
export let runnableClass = ''
const { staticExporter, noBackend } = getContext<AppEditorContext>('AppEditorContext')
@@ -47,6 +48,7 @@
{extraQueryParams}
{forceSchemaDisplay}
{noMinH}
wrapperClass={runnableClass}
>
<slot />
</RunnableComponent>

View File

@@ -13,6 +13,8 @@
import { getContext } from 'svelte'
import type { AppEditorContext } from '../../types'
import Tooltip from '$lib/components/Tooltip.svelte'
import Popup from '../../../common/popup/Popup.svelte'
import Popover from '../../../Popover.svelte'
export let inputSpecs: Record<
string,
@@ -36,7 +38,7 @@
{shouldCapitalize ? capitalize(inputSpecKey) : inputSpecKey}
</span>
<div class="flex gap-2 flex-wrap items-center">
<div class="flex gap-x-2 gap-y-1 flex-wrap justify-end items-center">
<Badge color="blue">
{input.fieldType === 'array' && input.subFieldType
? `${capitalize(fieldTypeToTsType(input.subFieldType))}[]`
@@ -57,47 +59,64 @@
}
}}
>
<ToggleButton
title="Static"
position="left"
value="static"
startIcon={{ icon: faPen }}
size="xs"
iconOnly
/>
{#if rowColumns}
<Popover placement="bottom" notClickable disapperTimoout={0}>
<ToggleButton
title="Column"
position="center"
value="row"
startIcon={{ icon: faTableCells }}
position="left"
value="static"
startIcon={{ icon: faPen }}
size="xs"
disabled={staticOnly}
><Tooltip
>Use the column name to have the value of the cell be passed to the action</Tooltip
></ToggleButton
>
iconOnly
/>
<svelte:fragment slot="text">
Static
</svelte:fragment>
</Popover>
{#if rowColumns}
<Popover placement="bottom" notClickable disapperTimoout={0}>
<ToggleButton
position="center"
value="row"
startIcon={{ icon: faTableCells }}
size="xs"
disabled={staticOnly}
>
<Tooltip>
Use the column name to have the value of the cell be passed to the action
</Tooltip>
</ToggleButton>
<svelte:fragment slot="text">
Column
</svelte:fragment>
</Popover>
{/if}
{#if userInputEnabled && !input.format?.startsWith('resource-')}
{#if userInputEnabled && (!input.format?.startsWith('resource-'))}
<Popover placement="bottom" notClickable disapperTimoout={0}>
<ToggleButton
position="center"
value="user"
startIcon={{ icon: faUser }}
size="xs"
iconOnly
disabled={staticOnly}
/>
<svelte:fragment slot="text">
User Input
</svelte:fragment>
</Popover>
{/if}
<Popover placement="bottom" notClickable disapperTimoout={0}>
<ToggleButton
title="User Input"
position="center"
value="user"
startIcon={{ icon: faUser }}
position="right"
value="connected"
startIcon={{ icon: faArrowRight }}
size="xs"
iconOnly
disabled={staticOnly}
/>
{/if}
<ToggleButton
title="Connect"
position="right"
value="connected"
startIcon={{ icon: faArrowRight }}
size="xs"
iconOnly
disabled={staticOnly}
/>
<svelte:fragment slot="text">
Connect
</svelte:fragment>
</Popover>
</ToggleButtonGroup>
{/if}
</div>