From 10066bf3e045bd1236b4457f0c87f6a05b0de943 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 20 Aug 2021 09:27:38 +0100 Subject: [PATCH] Fix dependency loop in client stores --- .../client/src/components/Component.svelte | 1 - packages/client/src/store/builder.js | 44 +------------ packages/client/src/store/screens.js | 38 +++++++++++- packages/client/src/utils/components.js | 62 +++++++++++++++++++ .../src/forms/InnerForm.svelte | 2 +- 5 files changed, 103 insertions(+), 44 deletions(-) create mode 100644 packages/client/src/utils/components.js diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 8c7437e523..ed53a7eb32 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -74,7 +74,6 @@ styles: { ...instance._styles, id, empty, interactive }, empty, selected, - props: componentSettings, name, }) diff --git a/packages/client/src/store/builder.js b/packages/client/src/store/builder.js index 530f49843a..cf6e8afb95 100644 --- a/packages/client/src/store/builder.js +++ b/packages/client/src/store/builder.js @@ -1,5 +1,6 @@ import { writable, derived } from "svelte/store" import Manifest from "@budibase/standard-components/manifest.json" +import { findComponentById, findComponentPathById } from "../utils/components" const dispatchEvent = (type, data = {}) => { window.dispatchEvent( @@ -9,45 +10,6 @@ const dispatchEvent = (type, data = {}) => { ) } -const findComponentById = (component, componentId) => { - if (!component || !componentId) { - return null - } - if (component._id === componentId) { - return component - } - if (!component._children?.length) { - return null - } - for (let child of component._children) { - const result = findComponentById(child, componentId) - if (result) { - return result - } - } - return null -} - -const findComponentIdPath = (component, componentId, path = []) => { - if (!component || !componentId) { - return null - } - path = [...path, component._id] - if (component._id === componentId) { - return path - } - if (!component._children?.length) { - return null - } - for (let child of component._children) { - const result = findComponentIdPath(child, componentId, path) - if (result) { - return result - } - } - return null -} - const createBuilderStore = () => { const initialState = { inBuilder: false, @@ -75,13 +37,13 @@ const createBuilderStore = () => { const definition = type ? Manifest[type] : null // Derive the selected component path - const path = findComponentIdPath(asset.props, selectedComponentId) || [] + const path = findComponentPathById(asset.props, selectedComponentId) || [] return { ...$state, selectedComponent: component, selectedComponentDefinition: definition, - selectedComponentPath: path, + selectedComponentPath: path?.map(component => component._id), } }) diff --git a/packages/client/src/store/screens.js b/packages/client/src/store/screens.js index 367d9ecfea..702f662f8a 100644 --- a/packages/client/src/store/screens.js +++ b/packages/client/src/store/screens.js @@ -1,7 +1,12 @@ -import { derived } from "svelte/store" +import { derived, get } from "svelte/store" import { routeStore } from "./routes" import { builderStore } from "./builder" import { appStore } from "./app" +import { + findComponentPathById, + findChildrenByType, + findComponentById, +} from "../utils/components" const createScreenStore = () => { const store = derived( @@ -36,8 +41,39 @@ const createScreenStore = () => { } ) + // Utils to parse component definitions + const actions = { + findComponentById: componentId => { + const { activeScreen, activeLayout } = get(store) + let result = findComponentById(activeScreen?.props, componentId) + if (result) { + return result + } + return findComponentById(activeLayout?.props) + }, + findComponentPathById: componentId => { + const { activeScreen, activeLayout } = get(store) + let result = findComponentPathById(activeScreen?.props, componentId) + if (result) { + return result + } + return findComponentPathById(activeLayout?.props) + }, + findChildrenByType: (componentId, type) => { + const component = actions.findComponentById(componentId) + if (!component || !component._children) { + return null + } + let children = [] + findChildrenByType(component, type, children) + console.log(children) + return children + }, + } + return { subscribe: store.subscribe, + actions, } } diff --git a/packages/client/src/utils/components.js b/packages/client/src/utils/components.js new file mode 100644 index 0000000000..4b1b8a7ada --- /dev/null +++ b/packages/client/src/utils/components.js @@ -0,0 +1,62 @@ +/** + * Finds a component instance by ID + */ +export const findComponentById = (component, componentId) => { + if (!component || !componentId) { + return null + } + if (component._id === componentId) { + return component + } + if (!component._children?.length) { + return null + } + for (let child of component._children) { + const result = findComponentById(child, componentId) + if (result) { + return result + } + } + return null +} + +/** + * Finds the component path to a component + */ +export const findComponentPathById = (component, componentId, path = []) => { + if (!component || !componentId) { + return null + } + path = [...path, component] + if (component._id === componentId) { + return path + } + if (!component._children?.length) { + return null + } + for (let child of component._children) { + const result = findComponentPathById(child, componentId, path) + if (result) { + return result + } + } + return null +} + +/** + * Finds all children instances of a certain component type of a given component + */ +export const findChildrenByType = (component, type, children = []) => { + if (!component) { + return + } + if (component._component.endsWith(`/${type}`)) { + children.push(component) + } + if (!component._children?.length) { + return + } + component._children.forEach(child => { + findChildrenByType(child, type, children) + }) +} diff --git a/packages/standard-components/src/forms/InnerForm.svelte b/packages/standard-components/src/forms/InnerForm.svelte index 774419bbdc..3719de4750 100644 --- a/packages/standard-components/src/forms/InnerForm.svelte +++ b/packages/standard-components/src/forms/InnerForm.svelte @@ -27,7 +27,7 @@ $: errors = deriveFieldProperty(fields, f => f.fieldState.error) $: valid = !Object.values($errors).some(error => error != null) - // Derive which fields belong in which steps + // Derive whether the current form step is valid $: currentStepValid = derived( [currentStep, ...fields], ([currentStepValue, ...fieldsValue]) => {