Add live eval of bindings
This commit is contained in:
parent
a880c5e62a
commit
daec133f79
|
@ -15,6 +15,7 @@
|
|||
decodeJSBinding,
|
||||
encodeJSBinding,
|
||||
convertToJS,
|
||||
processStringSync,
|
||||
} from "@budibase/string-templates"
|
||||
import {
|
||||
readableToRuntimeBinding,
|
||||
|
@ -59,15 +60,21 @@
|
|||
let hbsValue = initialValueJS ? null : value
|
||||
let sidebar = true
|
||||
let targetMode = null
|
||||
let expressionResult
|
||||
|
||||
$: usingJS = mode === "JavaScript"
|
||||
$: editorMode = mode == "JavaScript" ? EditorModes.JS : EditorModes.Handlebars
|
||||
$: editorMode =
|
||||
mode === "JavaScript" ? EditorModes.JS : EditorModes.Handlebars
|
||||
$: bindingCompletions = bindingsToCompletions(bindings, editorMode)
|
||||
$: runtimeExpression = readableToRuntimeBinding(bindings, value)
|
||||
$: expressionResult = processStringSync(runtimeExpression || "", context)
|
||||
|
||||
const updateValue = val => {
|
||||
valid = isValid(readableToRuntimeBinding(bindings, val))
|
||||
const runtimeExpression = readableToRuntimeBinding(bindings, val)
|
||||
valid = isValid(runtimeExpression)
|
||||
if (valid) {
|
||||
dispatch("change", val)
|
||||
expressionResult = processStringSync(runtimeExpression || "", context)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +121,7 @@
|
|||
}
|
||||
|
||||
const switchMode = () => {
|
||||
if (targetMode == "Text") {
|
||||
if (targetMode === "Text") {
|
||||
jsValue = null
|
||||
updateValue(jsValue)
|
||||
} else {
|
||||
|
@ -204,6 +211,11 @@
|
|||
autofocus={autofocusEditor}
|
||||
/>
|
||||
</div>
|
||||
{#if expressionResult}
|
||||
<div class="result">
|
||||
{expressionResult}
|
||||
</div>
|
||||
{/if}
|
||||
<div class="binding-footer">
|
||||
<div class="messaging">
|
||||
{#if !valid}
|
||||
|
@ -308,6 +320,11 @@
|
|||
autofocus={autofocusEditor}
|
||||
/>
|
||||
</div>
|
||||
{#if expressionResult}
|
||||
<div class="result">
|
||||
{expressionResult}
|
||||
</div>
|
||||
{/if}
|
||||
<div class="binding-footer">
|
||||
<div class="messaging">
|
||||
<Icon name="FlashOn" />
|
||||
|
@ -515,4 +532,18 @@
|
|||
.binding-drawer :global(.code-editor > div) {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.result {
|
||||
margin: 0;
|
||||
background: var(--spectrum-global-color-gray-200);
|
||||
font-size: 14px;
|
||||
padding: var(--spacing-l);
|
||||
border-radius: var(--border-radius-s);
|
||||
font-family: monospace;
|
||||
border: 1px solid var(--spectrum-global-color-gray-300);
|
||||
max-height: 200px;
|
||||
overflow: auto;
|
||||
white-space: pre;
|
||||
word-wrap: anywhere;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -16,12 +16,8 @@
|
|||
let popoverAnchor
|
||||
let hoverTarget
|
||||
let helpers = handlebarsCompletions()
|
||||
|
||||
let selectedCategory
|
||||
|
||||
$: searchRgx = new RegExp(search, "ig")
|
||||
|
||||
// Icons
|
||||
$: bindingIcons = bindings?.reduce((acc, ele) => {
|
||||
if (ele.icon) {
|
||||
acc[ele.category] = acc[ele.category] || ele.icon
|
||||
|
@ -29,10 +25,9 @@
|
|||
return acc
|
||||
}, {})
|
||||
$: categoryIcons = { ...bindingIcons, Helpers: "MagicWand" }
|
||||
|
||||
$: categories = Object.entries(groupBy("category", bindings))
|
||||
$: categoryNames = getCategoryNames(categories)
|
||||
|
||||
$: searchRgx = new RegExp(search, "ig")
|
||||
$: filteredCategories = categories
|
||||
.map(([name, categoryBindings]) => ({
|
||||
name,
|
||||
|
@ -73,38 +68,35 @@
|
|||
}
|
||||
return names
|
||||
}
|
||||
|
||||
const getBindingValue = binding => {
|
||||
const hbs = `{{ ${binding.runtimeBinding} }}`
|
||||
return processStringSync(hbs, context)
|
||||
}
|
||||
</script>
|
||||
|
||||
<span class="detailPopover">
|
||||
<Popover
|
||||
align="left-outside"
|
||||
bind:this={popover}
|
||||
anchor={popoverAnchor}
|
||||
maxWidth={300}
|
||||
maxHeight={300}
|
||||
dismissible={false}
|
||||
>
|
||||
<Popover
|
||||
align="left-outside"
|
||||
bind:this={popover}
|
||||
anchor={popoverAnchor}
|
||||
maxWidth={400}
|
||||
maxHeight={300}
|
||||
dismissible={false}
|
||||
>
|
||||
<div class="helper">
|
||||
<Layout gap="S">
|
||||
<div class="helper">
|
||||
{#if hoverTarget.title}
|
||||
<div class="helper__name">{hoverTarget.title}</div>
|
||||
{/if}
|
||||
{#if hoverTarget.description}
|
||||
<div class="helper__description">
|
||||
<!-- eslint-disable-next-line svelte/no-at-html-tags-->
|
||||
{@html hoverTarget.description}
|
||||
</div>
|
||||
{/if}
|
||||
{#if hoverTarget.example}
|
||||
<pre class="helper__example">{hoverTarget.example}</pre>
|
||||
{/if}
|
||||
{#if hoverTarget.val}
|
||||
<pre>{hoverTarget.val}</pre>
|
||||
{/if}
|
||||
</div>
|
||||
{#if hoverTarget.description}
|
||||
<div>
|
||||
<!-- eslint-disable-next-line svelte/no-at-html-tags-->
|
||||
{@html hoverTarget.description}
|
||||
</div>
|
||||
{/if}
|
||||
{#if hoverTarget.code}
|
||||
<pre>{hoverTarget.code}</pre>
|
||||
{/if}
|
||||
</Layout>
|
||||
</Popover>
|
||||
</span>
|
||||
</div>
|
||||
</Popover>
|
||||
|
||||
<Layout noPadding gap="S">
|
||||
{#if selectedCategory}
|
||||
|
@ -171,14 +163,13 @@
|
|||
<li
|
||||
class="binding"
|
||||
on:mouseenter={e => {
|
||||
const hbs = `{{ ${binding.runtimeBinding} }}`
|
||||
const val = processStringSync(hbs, context)
|
||||
console.log(binding.runtimeBinding, val)
|
||||
let val = getBindingValue(binding)
|
||||
if (val === "") {
|
||||
val = " "
|
||||
}
|
||||
popoverAnchor = e.target
|
||||
hoverTarget = {
|
||||
title: binding.display?.name || binding.fieldSchema?.name,
|
||||
description: binding.description,
|
||||
val,
|
||||
code: val,
|
||||
}
|
||||
popover.show()
|
||||
e.stopPropagation()
|
||||
|
@ -224,19 +215,15 @@
|
|||
{#each filteredHelpers as helper}
|
||||
<li
|
||||
class="binding"
|
||||
on:click={() => addHelper(helper, mode.name == "javascript")}
|
||||
on:click={() => addHelper(helper, mode.name === "javascript")}
|
||||
on:mouseenter={e => {
|
||||
popoverAnchor = e.target
|
||||
if (!helper.displayText && helper.description) {
|
||||
return
|
||||
}
|
||||
hoverTarget = {
|
||||
title: helper.displayText,
|
||||
description: helper.description,
|
||||
example: getHelperExample(
|
||||
helper,
|
||||
mode.name == "javascript"
|
||||
),
|
||||
code: getHelperExample(helper, mode.name === "javascript"),
|
||||
}
|
||||
popover.show()
|
||||
e.stopPropagation()
|
||||
|
@ -397,4 +384,16 @@
|
|||
margin-left: 2px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.helper pre {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
.helper :global(p) {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -150,8 +150,6 @@
|
|||
onMount(() => {
|
||||
store.actions.preview.sendEvent("request-context")
|
||||
})
|
||||
|
||||
$: console.log(context)
|
||||
</script>
|
||||
|
||||
{#each sections as section, idx (section.name)}
|
||||
|
|
Loading…
Reference in New Issue