Make binding viewer a more generic JSON viewer

This commit is contained in:
Andrew Kingston 2025-01-21 10:57:51 +00:00
parent c185e806b6
commit 3bd8becab1
No known key found for this signature in database
2 changed files with 45 additions and 20 deletions

View File

@ -1,11 +1,24 @@
<script context="module" lang="ts">
export interface JSONViewerClickEvent {
detail: {
label: string | undefined
value: any
path: (string | number)[]
}
}
</script>
<script lang="ts">
import { Icon, notifications, Helpers } from "@budibase/bbui"
import { Icon } from "@budibase/bbui"
import { createEventDispatcher } from "svelte"
export let label: string | undefined = undefined
export let value: any = undefined
export let root: boolean = true
export let path: (string | number)[] = []
export let showCopyIcon: boolean = false
const dispatch = createEventDispatcher()
const Colors = {
Array: "var(--spectrum-global-color-gray-600)",
Object: "var(--spectrum-global-color-gray-600)",
@ -21,6 +34,7 @@
let expanded = false
let valueExpanded = false
let clickContext: JSONViewerClickContext
$: isArray = Array.isArray(value)
$: isObject = value?.toString?.() === "[object Object]"
@ -29,7 +43,7 @@
$: expandable = keys.length > 0
$: displayValue = getDisplayValue(isArray, isObject, keys, value)
$: style = getStyle(isArray, isObject, value)
$: readableBinding = `{{ ${path.join(".")} }}`
$: clickContext = { value, label, path }
const getKeys = (isArray: boolean, isObject: boolean, value: any) => {
if (isArray) {
@ -96,11 +110,6 @@
}
return Colors.Other
}
const copyBinding = () => {
Helpers.copyToClipboard(readableBinding)
notifications.success("Binding copied to clipboard")
}
</script>
<!-- svelte-ignore a11y-no-static-element-interactions -->
@ -124,6 +133,7 @@
class:primitive
class:expandable
on:click={() => (expanded = !expanded)}
on:click={() => dispatch("click-label", clickContext)}
>
{label}
</div>
@ -133,19 +143,22 @@
class:expanded={valueExpanded}
{style}
on:click={() => (valueExpanded = !valueExpanded)}
on:click={() => dispatch("click-value", clickContext)}
>
{displayValue}
</div>
<div class="copy-value-icon">
<Icon
name="Copy"
size="XS"
hoverable
color="var(--spectrum-global-color-gray-600)"
hoverColor="var(--spectrum-global-color-gray-900)"
on:click={copyBinding}
/>
</div>
{#if showCopyIcon}
<div class="copy-value-icon">
<Icon
name="Copy"
size="XS"
hoverable
color="var(--spectrum-global-color-gray-600)"
hoverColor="var(--spectrum-global-color-gray-900)"
on:click={() => dispatch("click-copy", clickContext)}
/>
</div>
{/if}
</div>
{/if}
{#if expandable && (expanded || label == null)}
@ -156,6 +169,10 @@
value={value[key]}
root={false}
path={[...path, key]}
{showCopyIcon}
on:click-label
on:click-value
on:click-copy
/>
{/each}
</div>

View File

@ -1,6 +1,6 @@
<script lang="ts">
import { onMount } from "svelte"
import { Link, Body, Helpers, Layout } from "@budibase/bbui"
import { Link, Body, Helpers, Layout, notifications } from "@budibase/bbui"
import { processObjectSync } from "@budibase/string-templates"
import {
previewStore,
@ -9,7 +9,9 @@
snippets,
} from "@/stores/builder"
import { getBindableProperties } from "@/dataBinding"
import BindingNode from "./BindingNode.svelte"
import JSONViewer, {
type JSONViewerClickEvent,
} from "@/components/common/JSONViewer.svelte"
// Minimal typing for the real data binding structure, as none exists
type DataBinding = {
@ -56,6 +58,12 @@
return context
}
const copyBinding = (e: JSONViewerClickEvent) => {
const readableBinding = `{{ ${e.detail.path.join(".")} }}`
Helpers.copyToClipboard(readableBinding)
notifications.success("Binding copied to clipboard")
}
onMount(previewStore.requestComponentContext)
</script>
@ -70,7 +78,7 @@
Learn more.
</Link>
</div>
<BindingNode value={context} />
<JSONViewer value={context} showCopyIcon on:click-copy={copyBinding} />
</Layout>
</div>