fix(frontend): fix refresh with manual dependencies (#1319)

* fix(frontend): fix refresh with manual dependencies

* fix(frontend): fix id generation

* fix(frontend): wip

* fix(frontend): wip

* fix(frontend): Fix binding + hide toggle for frontend scripts
This commit is contained in:
Faton Ramadani
2023-03-22 18:27:38 +01:00
committed by GitHub
parent 558af187c9
commit 71d51a6981
15 changed files with 68 additions and 15 deletions
+1 -1
View File
@@ -26,7 +26,7 @@
{#if Boolean(options?.left)}
<span
class={twMerge(
'ml-2 font-medium duration-200',
'mr-2 font-medium duration-200',
disabled ? 'text-gray-500' : 'text-gray-900',
size === 'xs' ? 'text-xs' : 'text-sm',
textClass
@@ -15,6 +15,7 @@
export let inlineScript: InlineScript | undefined
export let fields: Record<string, StaticAppInput | ConnectedAppInput | RowAppInput | UserAppInput>
export let autoRefresh: boolean
export let doNotRecomputeOnInputChanged: boolean = false
let result: any = undefined
@@ -31,6 +32,7 @@
{id}
{fields}
{autoRefresh}
{doNotRecomputeOnInputChanged}
bind:result
transformer={undefined}
runnable={{
@@ -1,5 +1,4 @@
<script lang="ts">
import { goto } from '$app/navigation'
import type { Schema } from '$lib/common'
import Alert from '$lib/components/common/alert/Alert.svelte'
import LightweightSchemaForm from '$lib/components/LightweightSchemaForm.svelte'
@@ -33,6 +32,7 @@
export let recomputable: boolean = false
export let outputs: { result: Output<any>; loading: Output<boolean> }
export let extraKey = ''
export let doNotRecomputeOnInputChanged: boolean = false
const {
worldStore,
@@ -51,7 +51,7 @@
const dispatch = createEventDispatcher()
if (recomputable || autoRefresh) {
if ((recomputable || autoRefresh) && !doNotRecomputeOnInputChanged) {
$runnableComponents[id] = async (inlineScript?: InlineScript) => {
await executeComponent(true, inlineScript)
}
@@ -91,8 +91,12 @@
testJobLoader &&
refreshIfAutoRefresh('arg changed')
$: refreshOn =
runnable && runnable.type === 'runnableByName' ? runnable.inlineScript?.refreshOn ?? [] : []
function refreshIfAutoRefresh(_src: string) {
if (autoRefresh && $worldStore.initialized) {
const refreshEnabled = !doNotRecomputeOnInputChanged && (autoRefresh || refreshOn.length > 0)
if (refreshEnabled && $worldStore.initialized) {
setDebouncedExecute()
}
}
@@ -107,6 +107,7 @@
runnable={componentInput.runnable}
transformer={componentInput.transformer}
{autoRefresh}
bind:doNotRecomputeOnInputChanged={componentInput.doNotRecomputeOnInputChanged}
{id}
{extraQueryParams}
{forceSchemaDisplay}
@@ -177,6 +177,7 @@
name={script.name}
fields={script.fields}
autoRefresh={script.autoRefresh ?? true}
doNotRecomputeOnInputChanged={script.doNotRecomputeOnInputChanged}
/>
{/if}
{/each}
@@ -30,10 +30,10 @@
bind:checked={script.autoRefresh}
options={{ right: 'Run on start and app refresh' }}
/>
<Tooltip
>You may want to disable this so that the background script is only triggered by changes
to other values or triggered by another computation on a button (See 'Recompute Others')</Tooltip
>
<Tooltip>
You may want to disable this so that the background script is only triggered by changes
to other values or triggered by another computation on a button (See 'Recompute Others')
</Tooltip>
</div>
</PanelSection>
@@ -43,6 +43,7 @@
fields={script.fields}
autoRefresh={script.autoRefresh}
id={`bg_${index}`}
bind:doNotRecomputeOnInputChanged={script.doNotRecomputeOnInputChanged}
bind:inlineScript={script.inlineScript}
/>
{:else}
@@ -71,7 +71,7 @@ export function findGridItem(app: App, id: string): GridItem | undefined {
export function getNextGridItemId(app: App): string {
const subgridsKeys = allItems(app.grid, app.subgrids).map((x) => x.id)
const withoutDash = subgridsKeys.map((element) => element.split('-')[0])
const id = getNextId([...new Set(withoutDash), 'do'])
const id = getNextId([...new Set(withoutDash)])
return id
}
@@ -49,6 +49,7 @@
name: newScriptPath,
inlineScript: undefined,
autoRefresh: true,
fields: {}
})
$app.hiddenInlineScripts = $app.hiddenInlineScripts
@@ -1,7 +1,9 @@
<script lang="ts">
import Button from '$lib/components/common/button/Button.svelte'
import Toggle from '$lib/components/Toggle.svelte'
import Tooltip from '$lib/components/Tooltip.svelte'
import { faClose, faEdit } from '@fortawesome/free-solid-svg-icons'
import { includes } from 'lodash'
import { getContext } from 'svelte'
import type { ResultAppInput } from '../../inputType'
import type { AppEditorContext, AppViewerContext } from '../../types'
@@ -97,11 +99,22 @@
</div>
{#if appInput.runnable?.type === 'runnableByName' && appInput.runnable.inlineScript}
{#if !['buttoncomponent', 'formbuttoncomponent', 'formcomponent'].includes(appComponent.type)}
<div class="flex items-center">
<Toggle
bind:checked={appInput.doNotRecomputeOnInputChanged}
options={{ right: "Don't recompute on input changed" }}
/>
<Tooltip>Whenever an input is changed, the script will be re-run.</Tooltip>
</div>
{/if}
<div>
<ComponentTriggerList
bind:runnable={appInput.runnable}
{appComponent}
fields={appInput.fields}
doNotRecomputeOnInputChanged={appInput.doNotRecomputeOnInputChanged}
/>
</div>
{/if}
@@ -6,6 +6,8 @@
UserAppInput
} from '$lib/components/apps/inputType'
import type { InlineScript } from '$lib/components/apps/types'
import Toggle from '$lib/components/Toggle.svelte'
import Tooltip from '$lib/components/Tooltip.svelte'
import TriggerBadgesList from './TriggerBadgesList.svelte'
import { getDependencies } from './triggerListUtils'
@@ -14,11 +16,25 @@
export let autoRefresh: boolean = false
export let id: string
export let inlineScript: InlineScript
export let doNotRecomputeOnInputChanged: boolean = false
$: dependencies = getDependencies(fields)
</script>
{#if inlineScript.language !== 'frontend'}
<div class="flex items-center px-1">
<Toggle
bind:checked={doNotRecomputeOnInputChanged}
options={{ right: "Don't recompute on input changed" }}
/>
<Tooltip>Whenever an input is changed, the script will be re-run.</Tooltip>
</div>
{/if}
<TriggerBadgesList
bind:inlineScript
{id}
inputDependencies={getDependencies(fields)}
inputDependencies={dependencies}
onLoad={autoRefresh}
{doNotRecomputeOnInputChanged}
/>
@@ -16,6 +16,7 @@
export let fields: Record<string, StaticAppInput | ConnectedAppInput | RowAppInput | UserAppInput>
export let appComponent: AppComponent
export let runnable: RunnableByName
export let doNotRecomputeOnInputChanged: boolean = false
const onClick = ['buttoncomponent', 'formbuttoncomponent', 'formcomponent'].includes(
appComponent.type
@@ -32,6 +33,7 @@
inputDependencies={onClick ? [] : getDependencies(fields)}
bind:inlineScript={runnable.inlineScript}
{onLoad}
{doNotRecomputeOnInputChanged}
id={$selectedComponent}
{onClick}
/>
@@ -11,6 +11,7 @@
export let onClick: boolean = false
export let onLoad: boolean = false
export let id: string | undefined = undefined
export let doNotRecomputeOnInputChanged: boolean = false
const colors = {
red: 'text-red-800 border-red-600 bg-red-100',
@@ -102,7 +103,9 @@
<div class="flex flex-row gap-2 flex-wrap">
{#if onLoad}
<span class={classNames(badgeClass, colors['green'])}>Start</span>
<span class={classNames(badgeClass, colors['green'])}>Refresh</span>
{#if !doNotRecomputeOnInputChanged}
<span class={classNames(badgeClass, colors['green'])}>Refresh</span>
{/if}
{/if}
{#if onClick}
<span class={classNames(badgeClass, colors['green'])}>Click</span>
@@ -110,7 +113,7 @@
</div>
</div>
{/if}
{#if inputDependencies.length > 0}
{#if inputDependencies.length > 0 && !doNotRecomputeOnInputChanged}
<div class="w-full">
<div class="flex justify-between items-center mb-1">
<div class="text-xs font-semibold text-slate-800">Change on values</div>
@@ -136,7 +139,7 @@
</div>
{/if}
{/if}
{#if frontendDependencies}
{#if frontendDependencies && !doNotRecomputeOnInputChanged}
<div class="w-full">
<div class="flex justify-between items-center">
<div class="text-xs font-semibold text-slate-800 mb-1">Change on values</div>
@@ -87,6 +87,7 @@ export type ResultInput = {
fields: Record<string, StaticAppInput | ConnectedAppInput | RowAppInput | UserAppInput>
type: 'runnable'
value?: any
doNotRecomputeOnInputChanged?: boolean
}
type AppInputSpec<T extends InputType, U, V extends InputType = never> = (
@@ -112,6 +112,7 @@ export type App = {
inlineScript: InlineScript | undefined
fields: Record<string, StaticAppInput | ConnectedAppInput | RowAppInput | UserAppInput>
autoRefresh?: boolean
doNotRecomputeOnInputChanged?: boolean
}>
css?: Partial<
Record<'viewer' | 'grid' | AppComponent['type'], Record<string, ComponentCssProperty>>
@@ -43,6 +43,8 @@ export async function loadFlowModuleState(flowModule: FlowModule): Promise<FlowM
export const idMutex = new Mutex()
const forbiddenIds: string[] = ['do']
export function getNextId(currentKeys: string[]): string {
const max = currentKeys.reduce((acc, key) => {
if (key === 'failure' || key.includes('branch') || key.includes('loop')) {
@@ -52,12 +54,17 @@ export function getNextId(currentKeys: string[]): string {
return Math.max(acc, num + 1)
}
}, 0)
return numberToChars(max)
const char = numberToChars(max)
if (forbiddenIds.includes(char)) {
return getNextId(currentKeys.concat(char))
} else {
return char
}
}
// Computes the next available id
export function nextId(flowState: FlowState): string {
const max = Object.keys(flowState).reduce((acc, key) => {
if (key === 'failure' || key.includes('branch') || key.includes('loop')) {
return acc