From aa4cd1fc2e2279f9fd6e3c0a35b5366334faa705 Mon Sep 17 00:00:00 2001 From: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com> Date: Wed, 4 Dec 2024 00:26:38 -0800 Subject: [PATCH] chore: Exposes CSAs for Container widget (#11229) * chore: Exposes CSAs for Container widget * Introduces hook to expose variables * Updates hook to expose variable after setting the state * Update frontend/src/AppBuilder/_hooks/useExposeVariables.js Co-authored-by: Kavin Venkatachalam <50441969+kavinvenkatachalam@users.noreply.github.com> * Removes unwanted imports * Exposing CSA to control component actions * Moves CSA's to additional actions section * Fixes wrong handle param --------- Co-authored-by: Kavin Venkatachalam <50441969+kavinvenkatachalam@users.noreply.github.com> --- .../Inspector/Components/DefaultComponent.jsx | 1 + .../WidgetManager/widgets/container.js | 63 +++++++++++++------ frontend/src/AppBuilder/Widgets/Container.jsx | 31 +++++++-- .../AppBuilder/_hooks/useExposeVariables.js | 51 +++++++++++++++ .../Editor/WidgetManager/configs/container.js | 61 ++++++++++++------ server/src/helpers/widget-config/container.js | 63 +++++++++++++------ 6 files changed, 206 insertions(+), 64 deletions(-) create mode 100644 frontend/src/AppBuilder/_hooks/useExposeVariables.js diff --git a/frontend/src/AppBuilder/RightSideBar/Inspector/Components/DefaultComponent.jsx b/frontend/src/AppBuilder/RightSideBar/Inspector/Components/DefaultComponent.jsx index 74ae7c6e47..c183a644c0 100644 --- a/frontend/src/AppBuilder/RightSideBar/Inspector/Components/DefaultComponent.jsx +++ b/frontend/src/AppBuilder/RightSideBar/Inspector/Components/DefaultComponent.jsx @@ -12,6 +12,7 @@ import { shallow } from 'zustand/shallow'; const SHOW_ADDITIONAL_ACTIONS = [ 'Text', + 'Container', 'TextInput', 'NumberInput', 'PasswordInput', diff --git a/frontend/src/AppBuilder/WidgetManager/widgets/container.js b/frontend/src/AppBuilder/WidgetManager/widgets/container.js index 32d4158ffc..dc2dcf34ec 100644 --- a/frontend/src/AppBuilder/WidgetManager/widgets/container.js +++ b/frontend/src/AppBuilder/WidgetManager/widgets/container.js @@ -15,6 +15,25 @@ export const containerConfig = { loadingState: { type: 'toggle', displayName: 'Loading state', + section: 'additionalActions', + validation: { + schema: { type: 'boolean' }, + defaultValue: false, + }, + }, + visibility: { + type: 'toggle', + displayName: 'Visibility', + section: 'additionalActions', + validation: { + schema: { type: 'boolean' }, + defaultValue: true, + }, + }, + disabledState: { + type: 'toggle', + displayName: 'Disable', + section: 'additionalActions', validation: { schema: { type: 'boolean' }, defaultValue: false, @@ -50,40 +69,44 @@ export const containerConfig = { defaultValue: '#fff', }, }, - visibility: { - type: 'toggle', - displayName: 'Visibility', - validation: { - schema: { type: 'boolean' }, - defaultValue: true, - }, - }, - disabledState: { - type: 'toggle', - displayName: 'Disable', - validation: { - schema: { type: 'boolean' }, - }, - defaultValue: false, - }, }, - exposedVariables: {}, + exposedVariables: { + isVisible: true, + isDisabled: false, + isLoading: false, + }, + actions: [ + { + handle: 'setVisibility', + displayName: 'Set visibility', + params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }], + }, + { + handle: 'setDisable', + displayName: 'Set disable', + params: [{ handle: 'setDisable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }], + }, + { + handle: 'setLoading', + displayName: 'Set loading', + params: [{ handle: 'setLoading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }], + }, + ], definition: { others: { showOnDesktop: { value: '{{true}}' }, showOnMobile: { value: '{{false}}' }, }, properties: { - visible: { value: '{{true}}' }, loadingState: { value: `{{false}}` }, + visibility: { value: '{{true}}' }, + disabledState: { value: '{{false}}' }, }, events: [], styles: { backgroundColor: { value: '#fff' }, borderRadius: { value: '4' }, borderColor: { value: '#fff' }, - visibility: { value: '{{true}}' }, - disabledState: { value: '{{false}}' }, }, }, }; diff --git a/frontend/src/AppBuilder/Widgets/Container.jsx b/frontend/src/AppBuilder/Widgets/Container.jsx index b54b94c9a3..2b6f8008ed 100644 --- a/frontend/src/AppBuilder/Widgets/Container.jsx +++ b/frontend/src/AppBuilder/Widgets/Container.jsx @@ -1,9 +1,28 @@ import React, { useMemo } from 'react'; import { Container as ContainerComponent } from '@/AppBuilder/AppCanvas/Container'; import Spinner from '@/_ui/Spinner'; +import { useExposeState } from '@/AppBuilder/_hooks/useExposeVariables'; + +export const Container = ({ + id, + properties, + styles, + darkMode, + height, + width, + setExposedVariables, + setExposedVariable, +}) => { + const { borderRadius, borderColor, boxShadow } = styles; + + const { isDisabled, isVisible, isLoading } = useExposeState( + properties.loadingState, + properties.visibility, + properties.disabledState, + setExposedVariables, + setExposedVariable + ); -export const Container = ({ id, properties, styles, darkMode, height, width }) => { - const { visibility, disabledState, borderRadius, borderColor, boxShadow } = styles; const bgColor = useMemo(() => { return { backgroundColor: @@ -16,19 +35,19 @@ export const Container = ({ id, properties, styles, darkMode, height, width }) = borderRadius: borderRadius ? parseFloat(borderRadius) : 0, border: `1px solid ${borderColor}`, height, - display: visibility ? 'flex' : 'none', + display: isVisible ? 'flex' : 'none', overflow: 'hidden auto', position: 'relative', boxShadow, }; return (
- {properties.loadingState ? ( + {isLoading ? ( ) : ( diff --git a/frontend/src/AppBuilder/_hooks/useExposeVariables.js b/frontend/src/AppBuilder/_hooks/useExposeVariables.js new file mode 100644 index 0000000000..3c929f829b --- /dev/null +++ b/frontend/src/AppBuilder/_hooks/useExposeVariables.js @@ -0,0 +1,51 @@ +import { useEffect, useState } from 'react'; + +export const useExposeState = (loadingState, visibleState, disabledState, setExposedVariables, setExposedVariable) => { + const [isDisabled, setDisable] = useState(disabledState || false); + const [isVisible, setVisibility] = useState(visibleState || true); + const [isLoading, setLoading] = useState(loadingState || false); + + // Effect to conditionally update state from properties passed to widget + useEffect(() => { + setDisable(disabledState); + }, [disabledState]); + + useEffect(() => { + setVisibility(visibleState); + }, [visibleState]); + + useEffect(() => { + setLoading(loadingState); + }, [loadingState]); + + // exposed variables with state and async setters, happens on first time load + useEffect(() => { + setExposedVariables({ + setDisable: async (value) => setDisable(value), + setVisibility: async (value) => setVisibility(value), + setLoading: async (value) => setLoading(value), + }); + }, [setExposedVariables]); + + //Side effect to state variables, these will run after the state is set and the values will be exposed + useEffect(() => { + setExposedVariable('isDisabled', isDisabled); + }, [isDisabled, setExposedVariable]); + + useEffect(() => { + setExposedVariable('isVisible', isVisible); + }, [isVisible, setExposedVariable]); + + useEffect(() => { + setExposedVariable('isLoading', isLoading); + }, [isLoading, setExposedVariable]); + + return { + isDisabled, + setDisable, + isVisible, + setVisibility, + isLoading, + setLoading, + }; +}; diff --git a/frontend/src/Editor/WidgetManager/configs/container.js b/frontend/src/Editor/WidgetManager/configs/container.js index 32d4158ffc..062b2791c4 100644 --- a/frontend/src/Editor/WidgetManager/configs/container.js +++ b/frontend/src/Editor/WidgetManager/configs/container.js @@ -15,6 +15,25 @@ export const containerConfig = { loadingState: { type: 'toggle', displayName: 'Loading state', + section: 'additionalActions', + validation: { + schema: { type: 'boolean' }, + defaultValue: false, + }, + }, + visibility: { + type: 'toggle', + displayName: 'Visibility', + section: 'additionalActions', + validation: { + schema: { type: 'boolean' }, + defaultValue: true, + }, + }, + disabledState: { + type: 'toggle', + section: 'additionalActions', + displayName: 'Disable', validation: { schema: { type: 'boolean' }, defaultValue: false, @@ -50,32 +69,38 @@ export const containerConfig = { defaultValue: '#fff', }, }, - visibility: { - type: 'toggle', - displayName: 'Visibility', - validation: { - schema: { type: 'boolean' }, - defaultValue: true, - }, - }, - disabledState: { - type: 'toggle', - displayName: 'Disable', - validation: { - schema: { type: 'boolean' }, - }, - defaultValue: false, - }, }, - exposedVariables: {}, + exposedVariables: { + isVisible: true, + isDisabled: false, + isLoading: false, + }, + actions: [ + { + handle: 'setVisibility', + displayName: 'Set visibility', + params: [{ handle: 'setVisibility', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }], + }, + { + handle: 'setLoading', + displayName: 'Set disable', + params: [{ handle: 'setLoading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }], + }, + { + handle: 'setLoading', + displayName: 'Set loading', + params: [{ handle: 'setLoading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }], + }, + ], definition: { others: { showOnDesktop: { value: '{{true}}' }, showOnMobile: { value: '{{false}}' }, }, properties: { - visible: { value: '{{true}}' }, loadingState: { value: `{{false}}` }, + visibility: { value: '{{true}}' }, + disabledState: { value: '{{false}}' }, }, events: [], styles: { diff --git a/server/src/helpers/widget-config/container.js b/server/src/helpers/widget-config/container.js index 32d4158ffc..ef7f60855d 100644 --- a/server/src/helpers/widget-config/container.js +++ b/server/src/helpers/widget-config/container.js @@ -15,6 +15,25 @@ export const containerConfig = { loadingState: { type: 'toggle', displayName: 'Loading state', + section: 'additionalActions', + validation: { + schema: { type: 'boolean' }, + defaultValue: false, + }, + }, + visibility: { + type: 'toggle', + displayName: 'Visibility', + section: 'additionalActions', + validation: { + schema: { type: 'boolean' }, + defaultValue: true, + }, + }, + disabledState: { + type: 'toggle', + displayName: 'Disable', + section: 'additionalActions', validation: { schema: { type: 'boolean' }, defaultValue: false, @@ -50,40 +69,44 @@ export const containerConfig = { defaultValue: '#fff', }, }, - visibility: { - type: 'toggle', - displayName: 'Visibility', - validation: { - schema: { type: 'boolean' }, - defaultValue: true, - }, - }, - disabledState: { - type: 'toggle', - displayName: 'Disable', - validation: { - schema: { type: 'boolean' }, - }, - defaultValue: false, - }, }, - exposedVariables: {}, + exposedVariables: { + isVisible: true, + isDisabled: false, + isLoading: false, + }, + actions: [ + { + handle: 'setVisibility', + displayName: 'Set visibility', + params: [{ handle: 'setVisibility', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }], + }, + { + handle: 'setDisable', + displayName: 'Set disable', + params: [{ handle: 'setDisable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }], + }, + { + handle: 'setLoading', + displayName: 'Set loading', + params: [{ handle: 'setLoading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }], + }, + ], definition: { others: { showOnDesktop: { value: '{{true}}' }, showOnMobile: { value: '{{false}}' }, }, properties: { - visible: { value: '{{true}}' }, loadingState: { value: `{{false}}` }, + visibility: { value: '{{true}}' }, + disabledState: { value: '{{false}}' }, }, events: [], styles: { backgroundColor: { value: '#fff' }, borderRadius: { value: '4' }, borderColor: { value: '#fff' }, - visibility: { value: '{{true}}' }, - disabledState: { value: '{{false}}' }, }, }, };