From c25b8a1448bf44b462fbf0a83268709c6dfdbab3 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 7 Nov 2023 14:10:16 +0000 Subject: [PATCH] Expose schema context from grid and allow usage in buttons --- .../ButtonActionEditor/actions/SaveRow.svelte | 3 ++- .../ButtonConfiguration.svelte | 2 ++ .../ButtonConfiguration/ButtonSetting.svelte | 18 ++++++++++++++++++ packages/client/manifest.json | 5 ++++- .../client/src/components/app/GridBlock.svelte | 6 +++++- .../components/grid/layout/ButtonColumn.svelte | 9 ++++++++- .../src/components/grid/stores/rows.js | 8 ++++++-- 7 files changed, 45 insertions(+), 6 deletions(-) diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/SaveRow.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/SaveRow.svelte index c1917ad90f..27b6463ffa 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/SaveRow.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/SaveRow.svelte @@ -21,7 +21,8 @@ $: schemaComponents = getContextProviderComponents( $currentAsset, $store.selectedComponentId, - "schema" + "schema", + { includeSelf: nested } ) $: providerOptions = getProviderOptions(formComponents, schemaComponents) $: schemaFields = getSchemaFields(parameters?.tableId) diff --git a/packages/builder/src/components/design/settings/controls/ButtonConfiguration/ButtonConfiguration.svelte b/packages/builder/src/components/design/settings/controls/ButtonConfiguration/ButtonConfiguration.svelte index 9126fa0f77..3f1ea83d8c 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonConfiguration/ButtonConfiguration.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonConfiguration/ButtonConfiguration.svelte @@ -11,6 +11,7 @@ export let bindings export let value export let key + export let nested const dispatch = createEventDispatcher() @@ -28,6 +29,7 @@ bindings: allBindings, removeButton, canRemove: true, + nested, } const sanitizeValue = val => { diff --git a/packages/builder/src/components/design/settings/controls/ButtonConfiguration/ButtonSetting.svelte b/packages/builder/src/components/design/settings/controls/ButtonConfiguration/ButtonSetting.svelte index a05fd9a39b..17c9667c26 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonConfiguration/ButtonSetting.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonConfiguration/ButtonSetting.svelte @@ -10,10 +10,27 @@ export let anchor export let removeButton export let canRemove + export let nested $: readableText = isJSBinding(item.text) ? "(JavaScript function)" : runtimeToReadableBinding([...bindings, componentBindings], item.text) + + // If this is a nested setting (for example inside a grid or form block) then + // we need to mark all the settings of the actual buttons as nested too, to + // allow up to reference context provided by the block + const updatedNestedFlags = settings => { + if (!nested) { + return settings + } + // Buttons do not currently have any sections, so this works. + // We will need to update this in future if the normal button component + // gets broken into multiple settings sections + return settings?.map(setting => ({ + ...setting, + nested: true, + })) + }
@@ -24,6 +41,7 @@ {componentBindings} {bindings} on:change + parseSettings={updatedNestedFlags} />
{readableText || "Button"}
diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 6bd1643756..d131cda8c3 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -6357,7 +6357,10 @@ } ] } - ] + ], + "context": { + "type": "schema" + } }, "bbreferencefield": { "devComment": "As bb reference is only used for user subtype for now, we are using user for icon and labels", diff --git a/packages/client/src/components/app/GridBlock.svelte b/packages/client/src/components/app/GridBlock.svelte index 490caa622f..847f1e0768 100644 --- a/packages/client/src/components/app/GridBlock.svelte +++ b/packages/client/src/components/app/GridBlock.svelte @@ -53,7 +53,11 @@ text: settings.text, type: settings.type, onClick: async row => { - const fn = enrichButtonActions(settings.onClick, get(context)) + // We add a fake context binding in here, which allows us to pretend + // that the grid provides a "schema" binding - that lets us use the + // clicked row in things like save row actions + const enrichedContext = { ...get(context), [$component.id]: row } + const fn = enrichButtonActions(settings.onClick, enrichedContext) return await fn?.({ row }) }, })) diff --git a/packages/frontend-core/src/components/grid/layout/ButtonColumn.svelte b/packages/frontend-core/src/components/grid/layout/ButtonColumn.svelte index 4acd8b6b70..65b9d212ca 100644 --- a/packages/frontend-core/src/components/grid/layout/ButtonColumn.svelte +++ b/packages/frontend-core/src/components/grid/layout/ButtonColumn.svelte @@ -9,6 +9,7 @@ hoveredRowId, props, width, + rows, focusedRow, selectedRows, visibleColumns, @@ -27,6 +28,12 @@ $: end = columnsWidth - 1 - $scroll.left $: left = Math.min($width - $buttonColumnWidth, end) + const handleClick = async (button, row) => { + await button.onClick?.(row) + // Refresh the row in case it changed + await rows.actions.refreshRow(row._id) + } + onMount(() => { const observer = new ResizeObserver(entries => { const width = entries?.[0]?.contentRect?.width ?? 0 @@ -81,7 +88,7 @@ secondary={button.type === "secondary"} warning={button.type === "warning"} overBackground={button.type === "overBackground"} - on:click={() => button.onClick?.(row)} + on:click={() => handleClick(button, row)} > {button.text || "Button"} diff --git a/packages/frontend-core/src/components/grid/stores/rows.js b/packages/frontend-core/src/components/grid/stores/rows.js index 82185d6b91..34ba77afa2 100644 --- a/packages/frontend-core/src/components/grid/stores/rows.js +++ b/packages/frontend-core/src/components/grid/stores/rows.js @@ -314,8 +314,12 @@ export const createActions = context => { // Refreshes a specific row const refreshRow = async id => { - const row = await datasource.actions.getRow(id) - replaceRow(id, row) + try { + const row = await datasource.actions.getRow(id) + replaceRow(id, row) + } catch { + // Do nothing - we probably just don't support refreshing individual rows + } } // Refreshes all data