Add loading indicator and debounce evaluations to fix performance issues with large JSON payloads

This commit is contained in:
Andrew Kingston 2024-02-24 18:17:08 +00:00
parent a27529eca5
commit d666d03328
2 changed files with 37 additions and 9 deletions

View File

@ -1,5 +1,5 @@
<script>
import { DrawerContent, ActionButton, Icon } from "@budibase/bbui"
import { DrawerContent, ActionButton, Icon, Helpers } from "@budibase/bbui"
import { createEventDispatcher, getContext, onMount } from "svelte"
import {
isValid,
@ -26,6 +26,7 @@
import formatHighlight from "json-format-highlight"
import { capitalise } from "helpers"
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
import { Utils } from "@budibase/frontend-core"
const dispatch = createEventDispatcher()
@ -57,6 +58,7 @@
let targetMode = null
let expressionResult
let drawerIsModal
let evaluating = false
$: drawerContext?.modal.subscribe(val => (drawerIsModal = val))
$: editorTabs = allowJS ? [Modes.Text, Modes.JavaScript] : [Modes.Text]
@ -67,9 +69,21 @@
mode === Modes.JavaScript ? EditorModes.JS : EditorModes.Handlebars
$: bindingCompletions = bindingsToCompletions(enrichedBindings, editorMode)
$: runtimeExpression = readableToRuntimeBinding(enrichedBindings, value)
$: expressionResult = processStringSync(runtimeExpression || "", context)
$: requestUpdateEvaluation(runtimeExpression, context)
$: bindingHelpers = new BindingHelpers(getCaretPosition, insertAtPos)
const updateEvaluation = (expression, context) => {
expressionResult = processStringSync(expression || "", context)
evaluating = false
}
const debouncedUpdateEvaluation = Utils.debounce(updateEvaluation, 260)
const requestUpdateEvaluation = (expression, context) => {
evaluating = true
debouncedUpdateEvaluation(expression, context)
}
const getBindingValue = (binding, context) => {
const hbs = `{{ literal ${binding.runtimeBinding} }}`
const res = processStringSync(hbs, context)
@ -103,7 +117,7 @@
valid = isValid(runtimeExpression)
if (valid) {
dispatch("change", val)
expressionResult = processStringSync(runtimeExpression || "", context)
requestUpdateEvaluation(runtimeExpression, context)
}
}
@ -249,7 +263,7 @@
mode={editorMode}
/>
{:else if sidePanel === SidePanels.Evaluation}
<EvaluationSidePanel {expressionResult} />
<EvaluationSidePanel {expressionResult} {evaluating} />
{/if}
</div>
</div>

View File

@ -1,13 +1,16 @@
<script>
import formatHighlight from "json-format-highlight"
import { Icon, notifications } from "@budibase/bbui"
import { Icon, ProgressCircle, notifications } from "@budibase/bbui"
import { copyToClipboard } from "@budibase/bbui/helpers"
import { fade } from "svelte/transition"
export let expressionResult
export let evaluating = false
$: error = expressionResult === "Error while executing JS"
$: empty = expressionResult == null || expressionResult === ""
$: success = !error && !empty
$: highlightedResult = highlight(expressionResult)
const highlight = json => {
// Attempt to parse and then stringify, in case this is valid JSON
@ -16,7 +19,6 @@
} catch (err) {
// Ignore
}
return formatHighlight(json, {
keyColor: "#e06c75",
numberColor: "#e5c07b",
@ -42,10 +44,22 @@
<div class="header-content">
{#if error}
<Icon name="Alert" color="var(--spectrum-global-color-red-600)" />
<span> Error </span>
<div>Error</div>
{#if evaluating}
<div transition:fade|local={{ duration: 130 }}>
<ProgressCircle size="S" />
</div>
{/if}
<span />
<Icon name="Copy" hoverable on:click={copy} />
{:else}
<span>Preview</span>
<div>Preview</div>
{#if evaluating}
<div transition:fade|local={{ duration: 130 }}>
<ProgressCircle size="S" />
</div>
{/if}
<span />
{#if !empty}
<Icon name="Copy" hoverable on:click={copy} />
{/if}
@ -54,7 +68,7 @@
</div>
<div class="body">
{#if expressionResult}
{@html highlight(expressionResult)}
{@html highlightedResult}
{:else}
Your expression will be evaluated here
{/if}