From 9535bc7c244289d68db1a3863530d145dc0a3a8d Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 1 Mar 2022 09:51:48 +0000 Subject: [PATCH 1/3] Update option picker logic to only hide nullish rather than falsey values when using a dynamic options source --- packages/client/src/components/app/forms/optionsParser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/components/app/forms/optionsParser.js b/packages/client/src/components/app/forms/optionsParser.js index dd37989be7..c6132ab1bb 100644 --- a/packages/client/src/components/app/forms/optionsParser.js +++ b/packages/client/src/components/app/forms/optionsParser.js @@ -17,7 +17,7 @@ export const getOptions = ( dataProvider?.rows?.forEach(row => { const value = row?.[valueColumn] - if (value) { + if (value != null) { const label = row[labelColumn] || value optionsSet[value] = { value, label } } From 1d38486bb7a6dcf9845547165e494507756ccaf4 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 1 Mar 2022 10:00:08 +0000 Subject: [PATCH 2/3] Update more option picker logic to only hide nullish rather than falsey values when using a dynamic options source --- packages/client/src/components/app/forms/optionsParser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/components/app/forms/optionsParser.js b/packages/client/src/components/app/forms/optionsParser.js index c6132ab1bb..e670ccb076 100644 --- a/packages/client/src/components/app/forms/optionsParser.js +++ b/packages/client/src/components/app/forms/optionsParser.js @@ -30,7 +30,7 @@ export const getOptions = ( let optionsSet = {} dataProvider?.rows?.forEach(row => { const value = row?.[valueColumn] - if (value) { + if (value != null) { const label = row[labelColumn] || value optionsSet[value] = { value, label } } From 0f295afb04d19ec63b96b631d31da23f411c7ade Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 1 Mar 2022 11:11:56 +0000 Subject: [PATCH 3/3] Make component setting updates sequential to prevent 409s --- .../ComponentSettingsSection.svelte | 5 +++-- packages/frontend-core/src/index.js | 6 ++---- packages/frontend-core/src/stores/index.js | 1 + packages/frontend-core/src/utils/index.js | 4 ++++ packages/frontend-core/src/utils/utils.js | 17 +++++++++++++++++ 5 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 packages/frontend-core/src/stores/index.js create mode 100644 packages/frontend-core/src/utils/index.js create mode 100644 packages/frontend-core/src/utils/utils.js diff --git a/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte b/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte index f9fa56f739..399ec05b16 100644 --- a/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte @@ -7,6 +7,7 @@ import RoleSelect from "./PropertyControls/RoleSelect.svelte" import ResetFieldsButton from "./PropertyControls/ResetFieldsButton.svelte" import { getComponentForSettingType } from "./PropertyControls/componentSettings" + import { Utils } from "@budibase/frontend-core" export let componentDefinition export let componentInstance @@ -40,13 +41,13 @@ ] } - const updateProp = async (key, value) => { + const updateProp = Utils.sequential(async (key, value) => { try { await store.actions.components.updateProp(key, value) } catch (error) { notifications.error("Error updating component prop") } - } + }) const canRenderControl = setting => { const control = getComponentForSettingType(setting?.type) diff --git a/packages/frontend-core/src/index.js b/packages/frontend-core/src/index.js index 53822fdfb4..aecca81cda 100644 --- a/packages/frontend-core/src/index.js +++ b/packages/frontend-core/src/index.js @@ -1,7 +1,5 @@ export { createAPIClient } from "./api" -export { createLocalStorageStore } from "./stores/localStorage" export { fetchData } from "./fetch/fetchData" export * as Constants from "./constants" -export * as LuceneUtils from "./utils/lucene" -export * as JSONUtils from "./utils/json" -export * as CookieUtils from "./utils/cookies" +export * from "./stores" +export * from "./utils" diff --git a/packages/frontend-core/src/stores/index.js b/packages/frontend-core/src/stores/index.js new file mode 100644 index 0000000000..9766da43e3 --- /dev/null +++ b/packages/frontend-core/src/stores/index.js @@ -0,0 +1 @@ +export { createLocalStorageStore } from "./localStorage" diff --git a/packages/frontend-core/src/utils/index.js b/packages/frontend-core/src/utils/index.js new file mode 100644 index 0000000000..6755940289 --- /dev/null +++ b/packages/frontend-core/src/utils/index.js @@ -0,0 +1,4 @@ +export * as LuceneUtils from "./lucene" +export * as JSONUtils from "./json" +export * as CookieUtils from "./cookies" +export * as Utils from "./utils" diff --git a/packages/frontend-core/src/utils/utils.js b/packages/frontend-core/src/utils/utils.js new file mode 100644 index 0000000000..afa88a0624 --- /dev/null +++ b/packages/frontend-core/src/utils/utils.js @@ -0,0 +1,17 @@ +/** + * Utility to wrap an async function and ensure all invocations happen + * sequentially. + * @param fn the async function to run + * @return {Promise} a sequential version of the function + */ +export const sequential = fn => { + let promise + return async (...params) => { + if (promise) { + await promise + } + promise = fn(...params) + await promise + promise = null + } +}