Improve how snippets are handled in client apps
This commit is contained in:
parent
1a9843fcc8
commit
b3cf3fa636
|
@ -37,6 +37,7 @@
|
||||||
import DevTools from "components/devtools/DevTools.svelte"
|
import DevTools from "components/devtools/DevTools.svelte"
|
||||||
import FreeFooter from "components/FreeFooter.svelte"
|
import FreeFooter from "components/FreeFooter.svelte"
|
||||||
import licensing from "../licensing"
|
import licensing from "../licensing"
|
||||||
|
import SnippetsProvider from "./context/SnippetsProvider.svelte"
|
||||||
|
|
||||||
// Provide contexts
|
// Provide contexts
|
||||||
setContext("sdk", SDK)
|
setContext("sdk", SDK)
|
||||||
|
@ -116,112 +117,116 @@
|
||||||
<StateBindingsProvider>
|
<StateBindingsProvider>
|
||||||
<RowSelectionProvider>
|
<RowSelectionProvider>
|
||||||
<QueryParamsProvider>
|
<QueryParamsProvider>
|
||||||
<!-- Settings bar can be rendered outside of device preview -->
|
<SnippetsProvider>
|
||||||
<!-- Key block needs to be outside the if statement or it breaks -->
|
<!-- Settings bar can be rendered outside of device preview -->
|
||||||
{#key $builderStore.selectedComponentId}
|
<!-- Key block needs to be outside the if statement or it breaks -->
|
||||||
{#if $builderStore.inBuilder}
|
{#key $builderStore.selectedComponentId}
|
||||||
<SettingsBar />
|
{#if $builderStore.inBuilder}
|
||||||
{/if}
|
<SettingsBar />
|
||||||
{/key}
|
|
||||||
|
|
||||||
<!-- Clip boundary for selection indicators -->
|
|
||||||
<div
|
|
||||||
id="clip-root"
|
|
||||||
class:preview={$builderStore.inBuilder}
|
|
||||||
class:tablet-preview={$builderStore.previewDevice === "tablet"}
|
|
||||||
class:mobile-preview={$builderStore.previewDevice === "mobile"}
|
|
||||||
>
|
|
||||||
<!-- Actual app -->
|
|
||||||
<div id="app-root">
|
|
||||||
{#if showDevTools}
|
|
||||||
<DevToolsHeader />
|
|
||||||
{/if}
|
{/if}
|
||||||
|
{/key}
|
||||||
|
|
||||||
<div id="app-body">
|
<!-- Clip boundary for selection indicators -->
|
||||||
{#if permissionError}
|
<div
|
||||||
<div class="error">
|
id="clip-root"
|
||||||
<Layout justifyItems="center" gap="S">
|
class:preview={$builderStore.inBuilder}
|
||||||
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
class:tablet-preview={$builderStore.previewDevice ===
|
||||||
{@html ErrorSVG}
|
"tablet"}
|
||||||
<Heading size="L">
|
class:mobile-preview={$builderStore.previewDevice ===
|
||||||
You don't have permission to use this app
|
"mobile"}
|
||||||
</Heading>
|
>
|
||||||
<Body size="S">
|
<!-- Actual app -->
|
||||||
Ask your administrator to grant you access
|
<div id="app-root">
|
||||||
</Body>
|
{#if showDevTools}
|
||||||
</Layout>
|
<DevToolsHeader />
|
||||||
</div>
|
{/if}
|
||||||
{:else if !$screenStore.activeLayout}
|
|
||||||
<div class="error">
|
|
||||||
<Layout justifyItems="center" gap="S">
|
|
||||||
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
||||||
{@html ErrorSVG}
|
|
||||||
<Heading size="L">
|
|
||||||
Something went wrong rendering your app
|
|
||||||
</Heading>
|
|
||||||
<Body size="S">
|
|
||||||
Get in touch with support if this issue persists
|
|
||||||
</Body>
|
|
||||||
</Layout>
|
|
||||||
</div>
|
|
||||||
{:else if embedNoScreens}
|
|
||||||
<div class="error">
|
|
||||||
<Layout justifyItems="center" gap="S">
|
|
||||||
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
||||||
{@html ErrorSVG}
|
|
||||||
<Heading size="L">
|
|
||||||
This Budibase app is not publicly accessible
|
|
||||||
</Heading>
|
|
||||||
</Layout>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<CustomThemeWrapper>
|
|
||||||
{#key $screenStore.activeLayout._id}
|
|
||||||
<Component
|
|
||||||
isLayout
|
|
||||||
instance={$screenStore.activeLayout.props}
|
|
||||||
/>
|
|
||||||
{/key}
|
|
||||||
|
|
||||||
<!--
|
<div id="app-body">
|
||||||
|
{#if permissionError}
|
||||||
|
<div class="error">
|
||||||
|
<Layout justifyItems="center" gap="S">
|
||||||
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
||||||
|
{@html ErrorSVG}
|
||||||
|
<Heading size="L">
|
||||||
|
You don't have permission to use this app
|
||||||
|
</Heading>
|
||||||
|
<Body size="S">
|
||||||
|
Ask your administrator to grant you access
|
||||||
|
</Body>
|
||||||
|
</Layout>
|
||||||
|
</div>
|
||||||
|
{:else if !$screenStore.activeLayout}
|
||||||
|
<div class="error">
|
||||||
|
<Layout justifyItems="center" gap="S">
|
||||||
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
||||||
|
{@html ErrorSVG}
|
||||||
|
<Heading size="L">
|
||||||
|
Something went wrong rendering your app
|
||||||
|
</Heading>
|
||||||
|
<Body size="S">
|
||||||
|
Get in touch with support if this issue persists
|
||||||
|
</Body>
|
||||||
|
</Layout>
|
||||||
|
</div>
|
||||||
|
{:else if embedNoScreens}
|
||||||
|
<div class="error">
|
||||||
|
<Layout justifyItems="center" gap="S">
|
||||||
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
||||||
|
{@html ErrorSVG}
|
||||||
|
<Heading size="L">
|
||||||
|
This Budibase app is not publicly accessible
|
||||||
|
</Heading>
|
||||||
|
</Layout>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<CustomThemeWrapper>
|
||||||
|
{#key $screenStore.activeLayout._id}
|
||||||
|
<Component
|
||||||
|
isLayout
|
||||||
|
instance={$screenStore.activeLayout.props}
|
||||||
|
/>
|
||||||
|
{/key}
|
||||||
|
|
||||||
|
<!--
|
||||||
Flatpickr needs to be inside the theme wrapper.
|
Flatpickr needs to be inside the theme wrapper.
|
||||||
It also needs its own container because otherwise it hijacks
|
It also needs its own container because otherwise it hijacks
|
||||||
key events on the whole page. It is painful to work with.
|
key events on the whole page. It is painful to work with.
|
||||||
-->
|
-->
|
||||||
<div id="flatpickr-root" />
|
<div id="flatpickr-root" />
|
||||||
|
|
||||||
<!-- Modal container to ensure they sit on top -->
|
<!-- Modal container to ensure they sit on top -->
|
||||||
<div class="modal-container" />
|
<div class="modal-container" />
|
||||||
|
|
||||||
<!-- Layers on top of app -->
|
<!-- Layers on top of app -->
|
||||||
<NotificationDisplay />
|
<NotificationDisplay />
|
||||||
<ConfirmationDisplay />
|
<ConfirmationDisplay />
|
||||||
<PeekScreenDisplay />
|
<PeekScreenDisplay />
|
||||||
</CustomThemeWrapper>
|
</CustomThemeWrapper>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if showDevTools}
|
{#if showDevTools}
|
||||||
<DevTools />
|
<DevTools />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if !$builderStore.inBuilder && licensing.logoEnabled()}
|
||||||
|
<FreeFooter />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if !$builderStore.inBuilder && licensing.logoEnabled()}
|
<!-- Preview and dev tools utilities -->
|
||||||
<FreeFooter />
|
{#if $appStore.isDevApp}
|
||||||
|
<SelectionIndicator />
|
||||||
|
{/if}
|
||||||
|
{#if $builderStore.inBuilder || $devToolsStore.allowSelection}
|
||||||
|
<HoverIndicator />
|
||||||
|
{/if}
|
||||||
|
{#if $builderStore.inBuilder}
|
||||||
|
<DNDHandler />
|
||||||
|
<GridDNDHandler />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
</SnippetsProvider>
|
||||||
<!-- Preview and dev tools utilities -->
|
|
||||||
{#if $appStore.isDevApp}
|
|
||||||
<SelectionIndicator />
|
|
||||||
{/if}
|
|
||||||
{#if $builderStore.inBuilder || $devToolsStore.allowSelection}
|
|
||||||
<HoverIndicator />
|
|
||||||
{/if}
|
|
||||||
{#if $builderStore.inBuilder}
|
|
||||||
<DNDHandler />
|
|
||||||
<GridDNDHandler />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</QueryParamsProvider>
|
</QueryParamsProvider>
|
||||||
</RowSelectionProvider>
|
</RowSelectionProvider>
|
||||||
</StateBindingsProvider>
|
</StateBindingsProvider>
|
||||||
|
|
|
@ -565,7 +565,8 @@
|
||||||
|
|
||||||
// If we don't know, check and cache
|
// If we don't know, check and cache
|
||||||
if (used == null) {
|
if (used == null) {
|
||||||
used = bindingString.indexOf(`[${key}]`) !== -1
|
const searchString = key === "snippets" ? key : `[${key}]`
|
||||||
|
used = bindingString.indexOf(searchString) !== -1
|
||||||
knownContextKeyMap[key] = used
|
knownContextKeyMap[key] = used
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<script>
|
||||||
|
import Provider from "./Provider.svelte"
|
||||||
|
import { snippets } from "stores"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Provider key="snippets" data={$snippets}>
|
||||||
|
<slot />
|
||||||
|
</Provider>
|
|
@ -1,8 +1,8 @@
|
||||||
import { derived } from "svelte/store"
|
|
||||||
import { appStore } from "../app.js"
|
import { appStore } from "../app.js"
|
||||||
import { builderStore } from "../builder.js"
|
import { builderStore } from "../builder.js"
|
||||||
|
import { derivedMemo } from "@budibase/frontend-core"
|
||||||
|
|
||||||
export const snippets = derived(
|
export const snippets = derivedMemo(
|
||||||
[appStore, builderStore],
|
[appStore, builderStore],
|
||||||
([$appStore, $builderStore]) => {
|
([$appStore, $builderStore]) => {
|
||||||
return $builderStore?.snippets || $appStore?.application?.snippets || []
|
return $builderStore?.snippets || $appStore?.application?.snippets || []
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
import { Helpers } from "@budibase/bbui"
|
import { Helpers } from "@budibase/bbui"
|
||||||
import { processObjectSync } from "@budibase/string-templates"
|
import { processObjectSync } from "@budibase/string-templates"
|
||||||
import { snippets } from "../stores"
|
|
||||||
import { get } from "svelte/store"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively enriches all props in a props object and returns the new props.
|
* Recursively enriches all props in a props object and returns the new props.
|
||||||
* Props are deeply cloned so that no mutation is done to the source object.
|
* Props are deeply cloned so that no mutation is done to the source object.
|
||||||
*/
|
*/
|
||||||
export const enrichDataBindings = (props, context) => {
|
export const enrichDataBindings = (props, context) => {
|
||||||
const totalContext = { ...context, snippets: get(snippets) }
|
return processObjectSync(Helpers.cloneDeep(props), context, { cache: true })
|
||||||
const opts = { cache: true }
|
|
||||||
return processObjectSync(Helpers.cloneDeep(props), totalContext, opts)
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue