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

View File

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