feat: eval preview for apps

This commit is contained in:
Ruben Fiszel
2023-11-30 23:54:33 +01:00
parent fc5f054b94
commit d4374a0103
13 changed files with 67 additions and 13 deletions
@@ -7,7 +7,13 @@
TemplateV2Input,
UploadAppInput
} from '../../inputType'
import type { AppViewerContext, GroupContext, ListContext, RichConfiguration } from '../../types'
import type {
AppEditorContext,
AppViewerContext,
GroupContext,
ListContext,
RichConfiguration
} from '../../types'
import { accessPropertyByPath } from '../../utils'
import { computeGlobalContext, eval_like } from './eval'
import deepEqualWithOrderedArray from './deepEqualWithOrderedArray'
@@ -21,8 +27,10 @@
export let id: string | undefined = undefined
export let error: string = ''
export let key: string = ''
export let field: string = key
const { componentControl, runnableComponents } = getContext<AppViewerContext>('AppViewerContext')
const { evalPreview } = getContext<AppEditorContext>('AppEditorContext')
const iterContext = getContext<ListContext>('ListWrapperContext')
const rowContext = getContext<ListContext>('RowWrapperContext')
@@ -138,6 +146,12 @@
const debounceEval = async () => {
let nvalue = await evalExpr(lastInput as EvalAppInput)
if (field) {
evalPreview.update((x) => {
x[`${id}.${field}`] = nvalue
return x
})
}
if (!deepEqual(nvalue, value)) {
if (
typeof nvalue == 'string' ||
@@ -22,6 +22,7 @@
{#each Object.keys(configuration.configuration?.[choice] ?? {}) as nestedKey (nestedKey)}
{#if resolvedConfig.configuration?.[choice] != undefined}
<InputValue
field={key}
key={key + choice + nestedKey + extraKey}
{id}
input={configuration?.configuration?.[choice]?.[nestedKey]}
@@ -30,5 +31,11 @@
{/if}
{/each}
{:else}
<InputValue key={key + extraKey} {id} input={configuration} bind:value={resolvedConfig} />
<InputValue
field={key}
key={key + extraKey}
{id}
input={configuration}
bind:value={resolvedConfig}
/>
{/if}
@@ -53,6 +53,7 @@
{@const property = customCss[key]}
{#if property?.evalClass}
<InputValue
field={key}
key={key + extraKey + 'css'}
{id}
bind:value={evalClassValue}
@@ -65,6 +66,7 @@
{@const property = componentStyle[key]}
{#if property?.evalClass}
<InputValue
field={key}
key={key + extraKey + 'cssGlobal'}
{id}
bind:value={evalClassValueGlobal}
@@ -162,6 +162,7 @@
setContext<AppEditorContext>('AppEditorContext', {
yTop,
evalPreview: writable({}),
componentActive,
dndItem: writable({}),
refreshComponents: writable(undefined),
@@ -4,6 +4,7 @@
import InputsSpecEditor from '../settingsPanel/InputsSpecEditor.svelte'
export let evalClass: RichConfiguration
export let key: string
const { selectedComponent } = getContext<AppViewerContext>('AppViewerContext')
@@ -26,6 +27,6 @@
selectOptions={undefined}
subFieldType={undefined}
allowTypeChange={false}
key=""
{key}
/>
{/if}
@@ -246,7 +246,7 @@
/>
{#if value?.evalClass && dynamicClass}
<CssEval bind:evalClass={value.evalClass} />
<CssEval key={name} bind:evalClass={value.evalClass} />
{/if}
</div>
{/if}
@@ -221,14 +221,16 @@
<Button size="xs" color="light" startIcon={{ icon: Plus }} on:click={() => addElementByType()}>
Add
</Button>
{#if subFieldType === 'table-column'}
{#if subFieldType === 'table-column' || subFieldType == 'ag-grid'}
<QuickAddColumn
columns={componentInput.value?.map((item) => item.field)}
on:add={({ detail }) => {
if (!componentInput.value) componentInput.value = []
componentInput.value.push({ field: detail, headerName: detail, type: 'text' })
if (subFieldType === 'table-column') {
componentInput.value.push({ field: detail, headerName: detail, type: 'text' })
} else if (subFieldType === 'ag-grid') {
componentInput.value.push({ field: detail, headerName: detail, flex: 1 })
}
componentInput = componentInput
if (componentInput.value) {
@@ -263,6 +263,7 @@
/>
{:else if componentSettings.item.data.componentInput.type === 'evalv2' && component.componentInput !== undefined}
<EvalV2InputEditor
field="nonrunnable"
bind:this={evalV2editor}
id={component.id}
bind:componentInput={componentSettings.item.data.componentInput}
@@ -162,7 +162,7 @@
{:else if componentInput?.type === 'eval'}
<EvalInputEditor {id} bind:componentInput />
{:else if componentInput?.type === 'evalv2'}
<EvalV2InputEditor bind:this={evalV2editor} {id} bind:componentInput />
<EvalV2InputEditor field={key} bind:this={evalV2editor} {id} bind:componentInput />
{:else if componentInput?.type === 'upload'}
<UploadInputEditor bind:componentInput {fileUpload} />
{:else if componentInput?.type === 'user'}
@@ -33,7 +33,7 @@
}
function updateRemainingColumns(result: any[], columns: string[]) {
if (result?.length > 0) {
if (Array.isArray(result) && result?.length > 0) {
const allKeysSet: Set<string> = result.reduce((acc, obj) => {
Object.keys(obj).forEach((key) => acc.add(key))
return acc
@@ -2,17 +2,21 @@
import type { EvalV2AppInput } from '../../../inputType'
import { getContext } from 'svelte'
import type { AppViewerContext } from '$lib/components/apps/types'
import type { AppEditorContext, AppViewerContext } from '$lib/components/apps/types'
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
import { buildExtraLib } from '$lib/components/apps/utils'
import { inferDeps } from '../../appUtilsInfer'
import { Maximize2 } from 'lucide-svelte'
import { Drawer } from '$lib/components/common'
import { Highlight } from 'svelte-highlight'
import { json } from 'svelte-highlight/languages'
export let componentInput: EvalV2AppInput | undefined
export let id: string
export let field: string
const { onchange, worldStore, state, app } = getContext<AppViewerContext>('AppViewerContext')
const { evalPreview } = getContext<AppEditorContext>('AppEditorContext')
let editor: SimpleEditor
export function setCode(code: string) {
@@ -43,6 +47,7 @@
}
let fullscreen = false
let focus = false
</script>
{#if componentInput?.type === 'evalv2'}
@@ -75,6 +80,12 @@
shouldBindKey={false}
{extraLib}
autoHeight
on:focus={() => {
focus = true
}}
on:blur={() => {
focus = false
}}
on:change={async (e) => {
if (onchange) {
onchange()
@@ -86,10 +97,24 @@
class="border bg-surface absolute top-0.5 right-2 p-0.5"
on:click={() => (fullscreen = true)}><Maximize2 size={12} /></button
>
{#if focus}
<div class="relative w-full">
<div
class="p-1 !text-2xs absolute rounded-b border-b border-r border-l bg-surface w-full z-[5000] overflow-auto"
>
<Highlight
language={json}
code={JSON.stringify($evalPreview[`${id}.${field}`] ?? null, null, 4)}
/>
</div>
</div>
{/if}
{:else}
<pre class="text-small border px-2">{componentInput.expr}</pre>
{/if}
</div>
<!-- <div class="relative">
<div class="absolute top-0 left-0 z-[1000]"> -->
{#if componentInput?.expr && componentInput.expr != '' && componentInput.expr
.trim()
@@ -259,6 +259,7 @@ export type AppViewerContext = {
export type AppEditorContext = {
yTop: Writable<number>
evalPreview: Writable<Record<string, any>>
componentActive: Writable<boolean>
dndItem: Writable<Record<string, (x: number, y: number, topY: number) => void>>
refreshComponents: Writable<(() => void) | undefined>
+2 -2
View File
@@ -183,7 +183,7 @@ declare async function goto(path: string, newTab?: boolean): Promise<void>;
* @param id component's id
* @param index index of the tab to set
*/
declare function setTab(id: string, index: string): void;
declare function setTab(id: string, index: number): void;
/** recompute a component's runnable or background runnable
* @param id component's id
@@ -247,7 +247,7 @@ declare const state: ${JSON.stringify(state)};
declare const iter: {index: number, value: any};
/** The row within the context of a table */
declare const row: Record<string, any>;
declare const row: {index: number, value: Record<string, any>, disabled: boolean};
/** The group fields within the context of a container's group */
declare const group: Record<string, any>;