From 4d01063383f2aceda21c4d8f64b6b52b0e5df16f Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 14 Mar 2022 11:45:26 +0000 Subject: [PATCH 1/9] Convert marker popups to tooltips on hover --- .../components/app/embedded-map/EmbeddedMap.svelte | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/client/src/components/app/embedded-map/EmbeddedMap.svelte b/packages/client/src/components/app/embedded-map/EmbeddedMap.svelte index 200aaaaed9..342927252a 100644 --- a/packages/client/src/components/app/embedded-map/EmbeddedMap.svelte +++ b/packages/client/src/components/app/embedded-map/EmbeddedMap.svelte @@ -216,13 +216,10 @@ row[titleKey] ) - marker.bindPopup(markerContent).addTo(mapMarkerGroup) - - //https://github.com/Leaflet/Leaflet/issues/7331 - marker.on("click", function () { - this.openPopup() - }) - + marker.bindTooltip(markerContent, { + direction: "top", + offset: [0, -25] + }).addTo(mapMarkerGroup) mapMarkers = [...mapMarkers, marker] }) } From 9500203515deb47695f270bd749ecf4ded876f51 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 15 Mar 2022 11:16:51 +0000 Subject: [PATCH 2/9] Add event context to button actions to allow passing in params at run time and add corresponding data bindings --- .../builder/src/builderStore/dataBinding.js | 36 +- .../builder/src/builderStore/store/theme.js | 4 +- .../ButtonActionDrawer.svelte | 5 + .../ButtonActionEditor.svelte | 2 + .../PropertyControls/PropertyControl.svelte | 1 + packages/client/manifest.json | 439 ++++++++++-------- .../client/src/components/Component.svelte | 35 +- .../app/embedded-map/EmbeddedMap.svelte | 15 +- packages/client/src/utils/buttonActions.js | 8 +- packages/client/src/utils/componentProps.js | 6 +- 10 files changed, 344 insertions(+), 207 deletions(-) diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index 5b9bebcbf5..c4e14d2e5c 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -393,18 +393,45 @@ const getUrlBindings = asset => { /** * Gets all bindable properties exposed in a button actions flow up until - * the specified action ID. + * the specified action ID, as well as context provided for the action + * setting as a whole by the component. */ -export const getButtonContextBindings = (actions, actionId) => { +export const getButtonContextBindings = ( + asset, + componentId, + settingKey, + actions, + actionId +) => { + let bindings = [] + + // Check if any context bindings are provided by the component for this + // setting + const component = findComponent(asset.props, componentId) + const settings = getComponentSettings(component?._component) + const eventSetting = settings.find(setting => setting.key === settingKey) + if (!eventSetting) { + return bindings + } + if (eventSetting.context?.length) { + eventSetting.context.forEach(contextEntry => { + bindings.push({ + readableBinding: contextEntry.label, + runtimeBinding: `${makePropSafe("eventContext")}.${makePropSafe( + contextEntry.key + )}`, + }) + }) + } + // Get the steps leading up to this value const index = actions?.findIndex(action => action.id === actionId) if (index == null || index === -1) { - return [] + return bindings } const prevActions = actions.slice(0, index) // Generate bindings for any steps which provide context - let bindings = [] prevActions.forEach((action, idx) => { const def = ActionDefinitions.actions.find( x => x.name === action["##eventHandlerType"] @@ -418,6 +445,7 @@ export const getButtonContextBindings = (actions, actionId) => { }) } }) + return bindings } diff --git a/packages/builder/src/builderStore/store/theme.js b/packages/builder/src/builderStore/store/theme.js index d4d7460ed2..bd3a149d63 100644 --- a/packages/builder/src/builderStore/store/theme.js +++ b/packages/builder/src/builderStore/store/theme.js @@ -2,9 +2,10 @@ import { createLocalStorageStore } from "@budibase/frontend-core" export const getThemeStore = () => { const themeElement = document.documentElement + const initialValue = { theme: "darkest", - options: ["lightest", "light", "dark", "darkest"], + options: ["lightest", "light", "dark", "darkest", "nord"], } const store = createLocalStorageStore("bb-theme", initialValue) @@ -21,6 +22,7 @@ export const getThemeStore = () => { `spectrum--${option}`, option === state.theme ) + themeElement.classList.add("spectrum--darkest") }) }) diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/ButtonActionDrawer.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/ButtonActionDrawer.svelte index 8cf0f37f70..5b0ab4a6a3 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/ButtonActionDrawer.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/ButtonActionDrawer.svelte @@ -12,11 +12,13 @@ import { getAvailableActions } from "./index" import { generate } from "shortid" import { getButtonContextBindings } from "builderStore/dataBinding" + import { currentAsset, store } from "builderStore" const flipDurationMs = 150 const EVENT_TYPE_KEY = "##eventHandlerType" const actionTypes = getAvailableActions() + export let key export let actions export let bindings = [] @@ -24,6 +26,9 @@ // These are ephemeral bindings which only exist while executing actions $: buttonContextBindings = getButtonContextBindings( + $currentAsset, + $store.selectedComponentId, + key, actions, selectedAction?.id ) diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/ButtonActionEditor.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/ButtonActionEditor.svelte index 6a0e94cd4c..550d982013 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/ButtonActionEditor.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/ButtonActionEditor.svelte @@ -8,6 +8,7 @@ const dispatch = createEventDispatcher() + export let key export let value = [] export let name export let bindings @@ -81,5 +82,6 @@ bind:actions={tmpValue} eventType={name} {bindings} + {key} /> diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyControl.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyControl.svelte index 911688b30c..617b1c83ab 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyControl.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyControl.svelte @@ -79,6 +79,7 @@ bindings={allBindings} name={key} text={label} + {key} {type} {...props} /> diff --git a/packages/client/manifest.json b/packages/client/manifest.json index fff56f595d..1c7100192a 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -264,7 +264,8 @@ { "label": "Primary", "value": "primary" - }, { + }, + { "label": "Secondary", "value": "secondary" }, @@ -507,7 +508,7 @@ }, { "type": "static", - "values": [ + "values": [ { "label": "Row Index", "key": "index" @@ -626,28 +627,36 @@ "defaultValue": "M", "showInBar": true, "barStyle": "picker", - "options": [{ - "label": "Extra Small", - "value": "XS" - }, { - "label": "Small", - "value": "S" - }, { - "label": "Medium", - "value": "M" - }, { - "label": "Large", - "value": "L" - }, { - "label": "Extra Large", - "value": "XL" - }, { - "label": "2XL", - "value": "XXL" - }, { - "label": "3XL", - "value": "XXXL" - }] + "options": [ + { + "label": "Extra Small", + "value": "XS" + }, + { + "label": "Small", + "value": "S" + }, + { + "label": "Medium", + "value": "M" + }, + { + "label": "Large", + "value": "L" + }, + { + "label": "Extra Large", + "value": "XL" + }, + { + "label": "2XL", + "value": "XXL" + }, + { + "label": "3XL", + "value": "XXXL" + } + ] }, { "type": "color", @@ -689,27 +698,32 @@ "defaultValue": "left", "showInBar": true, "barStyle": "buttons", - "options": [{ - "label": "Left", - "value": "left", - "barIcon": "TextAlignLeft", - "barTitle": "Align left" - }, { - "label": "Center", - "value": "center", - "barIcon": "TextAlignCenter", - "barTitle": "Align center" - }, { - "label": "Right", - "value": "right", - "barIcon": "TextAlignRight", - "barTitle": "Align right" - }, { - "label": "Justify", - "value": "justify", - "barIcon": "TextAlignJustify", - "barTitle": "Justify text" - }] + "options": [ + { + "label": "Left", + "value": "left", + "barIcon": "TextAlignLeft", + "barTitle": "Align left" + }, + { + "label": "Center", + "value": "center", + "barIcon": "TextAlignCenter", + "barTitle": "Align center" + }, + { + "label": "Right", + "value": "right", + "barIcon": "TextAlignRight", + "barTitle": "Align right" + }, + { + "label": "Justify", + "value": "justify", + "barIcon": "TextAlignJustify", + "barTitle": "Justify text" + } + ] } ] }, @@ -733,28 +747,36 @@ "defaultValue": "M", "showInBar": true, "barStyle": "picker", - "options": [{ - "label": "Extra Small", - "value": "XS" - }, { - "label": "Small", - "value": "S" - }, { - "label": "Medium", - "value": "M" - }, { - "label": "Large", - "value": "L" - }, { - "label": "Extra Large", - "value": "XL" - }, { - "label": "2XL", - "value": "XXL" - }, { - "label": "3XL", - "value": "XXXL" - }] + "options": [ + { + "label": "Extra Small", + "value": "XS" + }, + { + "label": "Small", + "value": "S" + }, + { + "label": "Medium", + "value": "M" + }, + { + "label": "Large", + "value": "L" + }, + { + "label": "Extra Large", + "value": "XL" + }, + { + "label": "2XL", + "value": "XXL" + }, + { + "label": "3XL", + "value": "XXXL" + } + ] }, { "type": "color", @@ -796,27 +818,32 @@ "defaultValue": "left", "showInBar": true, "barStyle": "buttons", - "options": [{ - "label": "Left", - "value": "left", - "barIcon": "TextAlignLeft", - "barTitle": "Align left" - }, { - "label": "Center", - "value": "center", - "barIcon": "TextAlignCenter", - "barTitle": "Align center" - }, { - "label": "Right", - "value": "right", - "barIcon": "TextAlignRight", - "barTitle": "Align right" - }, { - "label": "Justify", - "value": "justify", - "barIcon": "TextAlignJustify", - "barTitle": "Justify text" - }] + "options": [ + { + "label": "Left", + "value": "left", + "barIcon": "TextAlignLeft", + "barTitle": "Align left" + }, + { + "label": "Center", + "value": "center", + "barIcon": "TextAlignCenter", + "barTitle": "Align center" + }, + { + "label": "Right", + "value": "right", + "barIcon": "TextAlignRight", + "barTitle": "Align right" + }, + { + "label": "Justify", + "value": "justify", + "barIcon": "TextAlignJustify", + "barTitle": "Justify text" + } + ] } ] }, @@ -837,16 +864,20 @@ "defaultValue": "M", "showInBar": true, "barStyle": "picker", - "options": [{ - "label": "Small", - "value": "S" - }, { - "label": "Medium", - "value": "M" - }, { - "label": "Large", - "value": "L" - }] + "options": [ + { + "label": "Small", + "value": "S" + }, + { + "label": "Medium", + "value": "M" + }, + { + "label": "Large", + "value": "L" + } + ] }, { "type": "color", @@ -1037,16 +1068,20 @@ "defaultValue": "M", "showInBar": true, "barStyle": "picker", - "options": [{ - "label": "Small", - "value": "S" - }, { - "label": "Medium", - "value": "M" - }, { - "label": "Large", - "value": "L" - }] + "options": [ + { + "label": "Small", + "value": "S" + }, + { + "label": "Medium", + "value": "M" + }, + { + "label": "Large", + "value": "L" + } + ] }, { "type": "color", @@ -1088,27 +1123,32 @@ "defaultValue": "left", "showInBar": true, "barStyle": "buttons", - "options": [{ - "label": "Left", - "value": "left", - "barIcon": "TextAlignLeft", - "barTitle": "Align left" - }, { - "label": "Center", - "value": "center", - "barIcon": "TextAlignCenter", - "barTitle": "Align center" - }, { - "label": "Right", - "value": "right", - "barIcon": "TextAlignRight", - "barTitle": "Align right" - }, { - "label": "Justify", - "value": "justify", - "barIcon": "TextAlignJustify", - "barTitle": "Justify text" - }] + "options": [ + { + "label": "Left", + "value": "left", + "barIcon": "TextAlignLeft", + "barTitle": "Align left" + }, + { + "label": "Center", + "value": "center", + "barIcon": "TextAlignCenter", + "barTitle": "Align center" + }, + { + "label": "Right", + "value": "right", + "barIcon": "TextAlignRight", + "barTitle": "Align right" + }, + { + "label": "Justify", + "value": "justify", + "barIcon": "TextAlignJustify", + "barTitle": "Justify text" + } + ] } ] }, @@ -1165,7 +1205,15 @@ "type": "select", "label": "Card Width", "key": "cardWidth", - "options": ["24rem", "28rem", "32rem", "40rem", "48rem", "60rem", "100%"], + "options": [ + "24rem", + "28rem", + "32rem", + "40rem", + "48rem", + "60rem", + "100%" + ], "defaultValue": "32rem" }, { @@ -1785,11 +1833,7 @@ "icon": "Form", "hasChildren": true, "illegalChildren": ["section", "form"], - "actions": [ - "ValidateForm", - "ClearForm", - "ChangeFormStep" - ], + "actions": ["ValidateForm", "ClearForm", "ChangeFormStep"], "styles": ["size"], "settings": [ { @@ -1816,7 +1860,8 @@ { "label": "Medium", "value": "spectrum--medium" - }, { + }, + { "label": "Large", "value": "spectrum--large" } @@ -1833,7 +1878,7 @@ "context": [ { "type": "static", - "values": [ + "values": [ { "label": "Value", "key": "__value" @@ -1947,27 +1992,32 @@ "defaultValue": "left", "showInBar": true, "barStyle": "buttons", - "options": [{ - "label": "Left", - "value": "left", - "barIcon": "TextAlignLeft", - "barTitle": "Align left" - }, { - "label": "Center", - "value": "center", - "barIcon": "TextAlignCenter", - "barTitle": "Align center" - }, { - "label": "Right", - "value": "right", - "barIcon": "TextAlignRight", - "barTitle": "Align right" - }, { - "label": "Justify", - "value": "justify", - "barIcon": "TextAlignJustify", - "barTitle": "Justify text" - }] + "options": [ + { + "label": "Left", + "value": "left", + "barIcon": "TextAlignLeft", + "barTitle": "Align left" + }, + { + "label": "Center", + "value": "center", + "barIcon": "TextAlignCenter", + "barTitle": "Align center" + }, + { + "label": "Right", + "value": "right", + "barIcon": "TextAlignRight", + "barTitle": "Align right" + }, + { + "label": "Justify", + "value": "justify", + "barIcon": "TextAlignJustify", + "barTitle": "Justify text" + } + ] } ] }, @@ -2480,15 +2530,42 @@ "styles": ["size"], "editable": true, "draggable": false, - "illegalChildren": [ - "section" - ], + "illegalChildren": ["section"], "settings": [ { "type": "dataProvider", "label": "Provider", "key": "dataProvider" }, + { + "type": "field", + "label": "Latitude Key", + "key": "latitudeKey", + "dependsOn": "dataProvider" + }, + { + "type": "field", + "label": "Longitude Key", + "key": "longitudeKey", + "dependsOn": "dataProvider" + }, + { + "type": "field", + "label": "Title Key", + "key": "titleKey", + "dependsOn": "dataProvider" + }, + { + "type": "event", + "label": "On marker click", + "key": "onMarkerClick", + "context": [ + { + "label": "Clicked marker", + "key": "marker" + } + ] + }, { "type": "boolean", "label": "Enable Fullscreen", @@ -2512,23 +2589,8 @@ "label": "Zoom Level (0-100)", "key": "zoomLevel", "defaultValue": 72, - "max" : 100, - "min" : 0 - }, - { - "type": "field", - "label": "Latitude Key", - "key": "latitudeKey" - }, - { - "type": "field", - "label": "Longitude Key", - "key": "longitudeKey" - }, - { - "type": "field", - "label": "Title Key", - "key": "titleKey" + "max": 100, + "min": 0 }, { "type": "text", @@ -2538,7 +2600,7 @@ }, { "type": "text", - "label": "Default Location (lat,lng)", + "label": "Default Location", "key": "defaultLocation", "defaultValue": "51.5072,-0.1276" }, @@ -2710,15 +2772,15 @@ ], "context": { "type": "static", - "values": [ + "values": [ { "label": "Rows", "key": "rows" }, - { - "label": "Extra Info", - "key": "info" - }, + { + "label": "Extra Info", + "key": "info" + }, { "label": "Rows Length", "key": "rowsLength" @@ -3192,7 +3254,6 @@ "key": "cardDescription", "label": "Description", "nested": true - }, { "type": "text", @@ -3457,12 +3518,12 @@ { "type": "static", "suffix": "provider", - "values": [ + "values": [ { "label": "Rows", "key": "rows" }, - { + { "label": "Extra Info", "key": "info" }, @@ -3483,12 +3544,12 @@ { "type": "static", "suffix": "repeater", - "values": [ + "values": [ { "label": "Row Index", "key": "index" } - ] + ] }, { "type": "schema", diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index e4176587ee..d9af295108 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -1,6 +1,7 @@
@@ -300,7 +351,14 @@
{error}
{/if} -
+
+ + {#if candidateMarkerPosition} +
+ + +
+ {/if}
diff --git a/packages/client/src/stores/confirmation.js b/packages/client/src/stores/confirmation.js index 497b021b04..bb9a54386f 100644 --- a/packages/client/src/stores/confirmation.js +++ b/packages/client/src/stores/confirmation.js @@ -4,30 +4,36 @@ const initialState = { showConfirmation: false, title: null, text: null, - callback: null, + onConfirm: null, + onCancel: null, } const createConfirmationStore = () => { const store = writable(initialState) - const showConfirmation = (title, text, callback) => { + const showConfirmation = (title, text, onConfirm, onCancel) => { store.set({ showConfirmation: true, title, text, - callback, + onConfirm, + onCancel, }) } const confirm = async () => { const state = get(store) - if (!state.showConfirmation || !state.callback) { + if (!state.showConfirmation || !state.onConfirm) { return } store.set(initialState) - await state.callback() + await state.onConfirm() } const cancel = () => { + const state = get(store) store.set(initialState) + if (state.onCancel) { + state.onCancel() + } } return { diff --git a/packages/client/src/utils/buttonActions.js b/packages/client/src/utils/buttonActions.js index d880455af0..d9d4dced71 100644 --- a/packages/client/src/utils/buttonActions.js +++ b/packages/client/src/utils/buttonActions.js @@ -331,33 +331,36 @@ export const enrichButtonActions = (actions, context) => { // If this action is confirmable, show confirmation and await a // callback to execute further actions if (action.parameters?.confirm) { - const defaultText = confirmTextMap[action["##eventHandlerType"]] - const confirmText = action.parameters?.confirmText || defaultText - confirmationStore.actions.showConfirmation( - action["##eventHandlerType"], - confirmText, - async () => { - // When confirmed, execute this action immediately, - // then execute the rest of the actions in the chain - const result = await callback() - if (result !== false) { - // Generate a new total context to pass into the next enrichment - buttonContext.push(result) - const newContext = { ...context, actions: buttonContext } + return new Promise(resolve => { + const defaultText = confirmTextMap[action["##eventHandlerType"]] + const confirmText = action.parameters?.confirmText || defaultText + confirmationStore.actions.showConfirmation( + action["##eventHandlerType"], + confirmText, + async () => { + // When confirmed, execute this action immediately, + // then execute the rest of the actions in the chain + const result = await callback() + if (result !== false) { + // Generate a new total context to pass into the next enrichment + buttonContext.push(result) + const newContext = { ...context, actions: buttonContext } - // Enrich and call the next button action - const next = enrichButtonActions( - actions.slice(i + 1), - newContext - ) - await next() + // Enrich and call the next button action + const next = enrichButtonActions( + actions.slice(i + 1), + newContext + ) + resolve(await next()) + } else { + resolve(false) + } + }, + () => { + resolve(false) } - } - ) - - // Stop enriching actions when encountering a confirmable action, - // as the callback continues the action chain - return + ) + }) } // For non-confirmable actions, execute the handler immediately From 4cf9d8612a450e61d0baf26eccb6d354e81b3906 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 16 Mar 2022 14:58:48 +0000 Subject: [PATCH 7/9] Update some settings text to be more consistent --- packages/client/manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 6c8ed8cbcc..ddea782ef0 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -2557,7 +2557,7 @@ }, { "type": "event", - "label": "On marker click", + "label": "On Click Marker", "key": "onClickMarker", "context": [ { @@ -2574,7 +2574,7 @@ }, { "type": "event", - "label": "On create marker", + "label": "On Create Marker", "key": "onCreateMarker", "dependsOn": "creationEnabled", "context": [ From d03dc54efd78751266f35aac1f59b0094c51b6ed Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 16 Mar 2022 15:03:13 +0000 Subject: [PATCH 8/9] Update default height of map component --- .../client/src/components/app/embedded-map/EmbeddedMap.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/client/src/components/app/embedded-map/EmbeddedMap.svelte b/packages/client/src/components/app/embedded-map/EmbeddedMap.svelte index b7eb516aa8..a6803ef5dd 100644 --- a/packages/client/src/components/app/embedded-map/EmbeddedMap.svelte +++ b/packages/client/src/components/app/embedded-map/EmbeddedMap.svelte @@ -364,6 +364,7 @@