diff --git a/frontend/src/Editor/BoxUI.jsx b/frontend/src/Editor/BoxUI.jsx
index e6dd2dda75..1272302ce5 100644
--- a/frontend/src/Editor/BoxUI.jsx
+++ b/frontend/src/Editor/BoxUI.jsx
@@ -6,7 +6,7 @@ import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
import '@/_styles/custom.scss';
import { EditorContext } from './Context/EditorContextWrapper';
import { validateWidget } from '@/_helpers/utils';
-import { useCurrentState, useCurrentStateStore } from '@/_stores/currentStateStore';
+import { useCurrentState } from '@/_stores/currentStateStore';
import { useAppDataStore } from '@/_stores/appDataStore';
import _ from 'lodash';
@@ -186,7 +186,6 @@ const BoxUI = (props) => {
currentPageId={currentPageId}
getContainerProps={component.component === 'Form' ? getContainerProps : null}
childComponents={childComponents}
- isEditorReady={isEditorReady}
/>
diff --git a/frontend/src/Editor/CodeEditor/utils.js b/frontend/src/Editor/CodeEditor/utils.js
index 3ce951f644..26762fcaa1 100644
--- a/frontend/src/Editor/CodeEditor/utils.js
+++ b/frontend/src/Editor/CodeEditor/utils.js
@@ -188,7 +188,7 @@ function getDynamicVariables(text) {
const resolveMultiDynamicReferences = (code, lookupTable, queryHasJSCode) => {
let resolvedValue = code;
- const isComponentValue = code.includes('components.') || false;
+ const isComponentValue = code.includes('components.') || code.includes('queries.') || false;
const allDynamicVariables = getDynamicVariables(code) || [];
let isJSCodeResolver = queryHasJSCode && (allDynamicVariables.length === 1 || allDynamicVariables.length === 0);
@@ -301,10 +301,16 @@ export const resolveReferences = (query, validationSchema, customResolvers = {})
resolvedValue = lookupTable.resolvedRefs.get(idToLookUp);
if (jsExpression) {
- let jscode = value.replace(toResolveReference, resolvedValue);
- jscode = value.replace(toResolveReference, `'${resolvedValue}'`);
+ let jscode = value;
+ if (!Array.isArray(resolvedValue) && typeof resolvedValue !== 'object' && resolvedValue !== null) {
+ jscode = value.replace(toResolveReference, resolvedValue).replace(toResolveReference, `'${resolvedValue}'`);
+ resolvedValue = resolveCode(jscode, customResolvers);
+ } else {
+ const [resolvedCode, errorRef] = resolveCode(value, customResolvers, true, [], true);
- resolvedValue = resolveCode(jscode, customResolvers);
+ resolvedValue = resolvedCode;
+ error = errorRef || null;
+ }
}
} else {
const [resolvedCode, errorRef] = resolveCode(value, customResolvers, true, [], true);
diff --git a/frontend/src/Editor/Components/Button.jsx b/frontend/src/Editor/Components/Button.jsx
index 040b329544..ab32b219f3 100644
--- a/frontend/src/Editor/Components/Button.jsx
+++ b/frontend/src/Editor/Components/Button.jsx
@@ -5,9 +5,7 @@ import * as Icons from '@tabler/icons-react';
import Loader from '@/ToolJetUI/Loader/Loader';
export const Button = function Button(props) {
- const { height, properties, styles, fireEvent, id, dataCy, setExposedVariable, setExposedVariables, isEditorReady } =
- props;
-
+ const { height, properties, styles, fireEvent, id, dataCy, setExposedVariable, setExposedVariables } = props;
const {
backgroundColor,
textColor,
@@ -95,33 +93,31 @@ export const Button = function Button(props) {
};
useEffect(() => {
- if (isEditorReady) {
- const exposedVariables = {
- click: async function () {
- if (!disable) {
- fireEvent('onClick');
- }
- },
- setText: async function (text) {
- setLabel(text);
- setExposedVariable('buttonText', text);
- },
- disable: async function (value) {
- setDisable(value);
- },
- visibility: async function (value) {
- setVisibility(value);
- },
- loading: async function (value) {
- setLoading(value);
- },
- };
+ const exposedVariables = {
+ click: async function () {
+ if (!disable) {
+ fireEvent('onClick');
+ }
+ },
+ setText: async function (text) {
+ setLabel(text);
+ setExposedVariable('buttonText', text);
+ },
+ disable: async function (value) {
+ setDisable(value);
+ },
+ visibility: async function (value) {
+ setVisibility(value);
+ },
+ loading: async function (value) {
+ setLoading(value);
+ },
+ };
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [disable, isEditorReady]);
+ }, [disable]);
useEffect(() => {
setExposedVariable('setLoading', async function (loading) {
diff --git a/frontend/src/Editor/Components/Chart.jsx b/frontend/src/Editor/Components/Chart.jsx
index e77000cd85..3b83b0f3e4 100644
--- a/frontend/src/Editor/Components/Chart.jsx
+++ b/frontend/src/Editor/Components/Chart.jsx
@@ -18,7 +18,6 @@ export const Chart = function Chart({
setExposedVariable,
setExposedVariables,
dataCy,
- isEditorReady,
}) {
const [loadingState, setLoadingState] = useState(false);
@@ -81,9 +80,8 @@ export const Chart = function Chart({
xAxisTitle: xAxisTitle,
yAxisTitle: yAxisTitle,
};
- if (isEditorReady) setExposedVariables(exposedVariables);
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [JSON.stringify(chartLayout, chartTitle), isEditorReady]);
+ setExposedVariables(exposedVariables);
+ }, [JSON.stringify(chartLayout, chartTitle)]);
const layout = {
width: width - 4,
diff --git a/frontend/src/Editor/Components/Checkbox.jsx b/frontend/src/Editor/Components/Checkbox.jsx
index 9e7842d976..bce29bad1f 100644
--- a/frontend/src/Editor/Components/Checkbox.jsx
+++ b/frontend/src/Editor/Components/Checkbox.jsx
@@ -14,7 +14,6 @@ export const Checkbox = ({
component,
validate,
width,
- isEditorReady,
}) => {
const defaultValueFromProperties = properties.defaultValue ?? false;
const [defaultValue, setDefaultValue] = useState(defaultValueFromProperties);
@@ -69,10 +68,10 @@ export const Checkbox = ({
setDefaultValue(defaultValueFromProperties);
setChecked(defaultValueFromProperties);
setValue(defaultValueFromProperties);
- if (isEditorReady) setExposedVariables(exposedVariables);
+ setExposedVariables(exposedVariables);
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [defaultValueFromProperties, isEditorReady]);
+ }, [defaultValueFromProperties]);
useEffect(() => {
if (disable !== disabledState) setDisable(properties.disabledState);
diff --git a/frontend/src/Editor/Components/ColorPicker.jsx b/frontend/src/Editor/Components/ColorPicker.jsx
index eeadc3c339..6e4c3d682a 100644
--- a/frontend/src/Editor/Components/ColorPicker.jsx
+++ b/frontend/src/Editor/Components/ColorPicker.jsx
@@ -11,7 +11,6 @@ export const ColorPicker = function ({
height,
fireEvent,
dataCy,
- isEditorReady,
}) {
const { visibility, boxShadow } = styles;
const defaultColor = properties.defaultColor;
@@ -58,9 +57,8 @@ export const ColorPicker = function ({
selectedColorRGB: hexToRgb(colorCode),
selectedColorRGBA: hexToRgba(colorCode),
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
+
fireEvent('onChange');
}
} else {
@@ -69,15 +67,14 @@ export const ColorPicker = function ({
selectedColorRGB: undefined,
selectedColorRGBA: undefined,
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
+
fireEvent('onChange');
setColor('Invalid Color');
}
});
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [setColor, isEditorReady]);
+ }, [setColor]);
useEffect(() => {
let exposedVariables = {};
@@ -88,9 +85,8 @@ export const ColorPicker = function ({
selectedColorRGB: hexToRgb(defaultColor),
selectedColorRGBA: hexToRgba(defaultColor),
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
+
setColor(defaultColor);
}
} else {
@@ -99,13 +95,12 @@ export const ColorPicker = function ({
selectedColorRGB: undefined,
selectedColorRGBA: undefined,
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
+
setColor(`Invalid Color`);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [defaultColor, isEditorReady]);
+ }, [defaultColor]);
const handleColorChange = (colorCode) => {
let exposedVariables = {};
@@ -118,9 +113,7 @@ export const ColorPicker = function ({
selectedColorRGB: `rgb(${r},${g},${b})`,
selectedColorRGBA: `rgb(${r},${g},${b},${a})`,
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
fireEvent('onChange');
}
};
diff --git a/frontend/src/Editor/Components/DropdownV2/DropdownV2.jsx b/frontend/src/Editor/Components/DropdownV2/DropdownV2.jsx
index 0699eb34a6..c0a922b0a2 100644
--- a/frontend/src/Editor/Components/DropdownV2/DropdownV2.jsx
+++ b/frontend/src/Editor/Components/DropdownV2/DropdownV2.jsx
@@ -58,7 +58,6 @@ export const DropdownV2 = ({
component,
exposedVariables,
dataCy,
- isEditorReady,
}) => {
const { label, value, advanced, schema, placeholder, loadingState: dropdownLoadingState, disabledState } = properties;
const {
@@ -218,11 +217,8 @@ export const DropdownV2 = ({
setIsDropdownDisabled(value);
},
};
-
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
- }, [isEditorReady]);
+ setExposedVariables(exposedVariables);
+ }, []);
const customStyles = {
container: (base) => ({
diff --git a/frontend/src/Editor/Components/Form/Form.jsx b/frontend/src/Editor/Components/Form/Form.jsx
index 51babaa340..7426dd365d 100644
--- a/frontend/src/Editor/Components/Form/Form.jsx
+++ b/frontend/src/Editor/Components/Form/Form.jsx
@@ -38,7 +38,6 @@ export const Form = function Form(props) {
getContainerProps,
containerProps,
childComponents,
- isEditorReady,
} = props;
const { events: allAppEvents } = useAppInfo();
@@ -133,9 +132,7 @@ export const Form = function Form(props) {
...(!advanced && { children: formattedChildData }),
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
return setValidation(childValidation);
}
@@ -161,10 +158,9 @@ export const Form = function Form(props) {
isValid: childValidation,
};
setValidation(childValidation);
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- } // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [childrenData, childComponents, advanced, JSON.stringify(JSONSchema), isEditorReady]);
+ setExposedVariables(exposedVariables);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [childrenData, childComponents, advanced, JSON.stringify(JSONSchema)]);
useEffect(() => {
const childIds = Object.keys(childrenData);
diff --git a/frontend/src/Editor/Components/Icon.jsx b/frontend/src/Editor/Components/Icon.jsx
index 6edcf75477..cec0bbb348 100644
--- a/frontend/src/Editor/Components/Icon.jsx
+++ b/frontend/src/Editor/Components/Icon.jsx
@@ -9,11 +9,11 @@ export const Icon = ({
fireEvent,
width,
height,
+ setExposedVariable,
setExposedVariables,
darkMode,
dataCy,
component,
- isEditorReady,
}) => {
const { icon } = properties;
const { iconColor, visibility, boxShadow } = styles;
@@ -40,11 +40,9 @@ export const Icon = ({
fireEvent('onClick');
},
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [setIconVisibility, isEditorReady]);
+ }, [setIconVisibility]);
return (
{
- const { height, width, properties, styles, id, mode, isEditorReady } = props;
+ const { height, width, properties, styles, id, mode } = props;
const { showDeleteButton } = properties;
const { visibility, disabledState, boxShadow } = styles;
diff --git a/frontend/src/Editor/Components/Kanban/KanbanBoard.jsx b/frontend/src/Editor/Components/Kanban/KanbanBoard.jsx
index 9f9beb7265..433eca7ac3 100644
--- a/frontend/src/Editor/Components/Kanban/KanbanBoard.jsx
+++ b/frontend/src/Editor/Components/Kanban/KanbanBoard.jsx
@@ -38,7 +38,7 @@ const dropAnimation = {
const TRASH_ID = 'void';
export function KanbanBoard({ widgetHeight, kanbanProps, parentRef, mode, id }) {
- const { properties, fireEvent, setExposedVariable, setExposedVariables, styles, isEditorReady } = kanbanProps;
+ const { properties, fireEvent, setExposedVariable, setExposedVariables, styles } = kanbanProps;
const { columnData, cardData, cardWidth, cardHeight, showDeleteButton, enableAddCard } = properties;
const { accentColor } = styles;
const [lastSelectedCard, setLastSelectedCard] = useState({});
@@ -112,20 +112,17 @@ export function KanbanBoard({ widgetHeight, kanbanProps, parentRef, mode, id })
cardDataAsObj[cardId] = value;
const diffKeys = Object.keys(diff(cardToBeUpdated, value));
if (lastSelectedCard?.id === cardId) {
- if (isEditorReady) {
- setExposedVariables({
- lastSelectedCard: cardDataAsObj[cardId],
-
- lastUpdatedCard: cardDataAsObj[cardId],
- lastCardUpdate: diffKeys.map((key) => {
- return {
- [key]: { oldValue: cardToBeUpdated[key], newValue: value[key] },
- };
- }),
- updatedCardData: getData(cardDataAsObj),
- });
- }
+ setExposedVariables({
+ lastSelectedCard: cardDataAsObj[cardId],
+ lastUpdatedCard: cardDataAsObj[cardId],
+ lastCardUpdate: diffKeys.map((key) => {
+ return {
+ [key]: { oldValue: cardToBeUpdated[key], newValue: value[key] },
+ };
+ }),
+ updatedCardData: getData(cardDataAsObj),
+ });
fireEvent('onUpdate');
} else {
setExposedVariable('updatedCardData', getData(cardDataAsObj));
@@ -133,7 +130,7 @@ export function KanbanBoard({ widgetHeight, kanbanProps, parentRef, mode, id })
}
});
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [lastSelectedCard, JSON.stringify(cardDataAsObj), isEditorReady]);
+ }, [lastSelectedCard, JSON.stringify(cardDataAsObj)]);
useEffect(() => {
setExposedVariable('moveCard', async function (cardId, columnId) {
@@ -172,13 +169,11 @@ export function KanbanBoard({ widgetHeight, kanbanProps, parentRef, mode, id })
...items,
[columnId]: [...items[columnId], cardDetails.id],
}));
- if (isEditorReady) {
- setExposedVariables({ lastAddedCard: { ...cardDetails }, updatedCardData: getData(cardDataAsObj) });
- }
+ setExposedVariables({ lastAddedCard: { ...cardDetails }, updatedCardData: getData(cardDataAsObj) });
fireEvent('onCardAdded');
});
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [items, JSON.stringify(cardDataAsObj), isEditorReady]);
+ }, [items, JSON.stringify(cardDataAsObj)]);
useEffect(() => {
setExposedVariable('deleteCard', async function (cardId) {
@@ -191,13 +186,11 @@ export function KanbanBoard({ widgetHeight, kanbanProps, parentRef, mode, id })
...items,
[columnId]: items[columnId].filter((id) => id !== cardId),
}));
- if (isEditorReady) {
- setExposedVariables({ lastRemovedCard: { ...deletedCard }, updatedCardData: getData(cardDataAsObj) });
- }
+ setExposedVariables({ lastRemovedCard: { ...deletedCard }, updatedCardData: getData(cardDataAsObj) });
fireEvent('onCardRemoved');
});
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [showModal, JSON.stringify(cardDataAsObj), isEditorReady]);
+ }, [showModal, JSON.stringify(cardDataAsObj)]);
const [clonedItems, setClonedItems] = useState(null);
const sensors = useSensors(
diff --git a/frontend/src/Editor/Components/Listview.jsx b/frontend/src/Editor/Components/Listview.jsx
index f7f4673ab3..99efcf9cca 100644
--- a/frontend/src/Editor/Components/Listview.jsx
+++ b/frontend/src/Editor/Components/Listview.jsx
@@ -19,7 +19,6 @@ export const Listview = function Listview({
darkMode,
dataCy,
childComponents,
- isEditorReady,
}) {
const fallbackProperties = { height: 100, showBorder: false, data: [] };
const fallbackStyles = { visibility: true, disabledState: false };
@@ -59,9 +58,7 @@ export const Listview = function Listview({
selectedRecordId: index,
selectedRecord: childrenData[index],
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
fireEvent('onRecordClicked');
// eslint-disable-next-line react-hooks/exhaustive-deps
}
@@ -71,9 +68,7 @@ export const Listview = function Listview({
selectedRowId: index,
selectedRow: childrenData[index],
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
fireEvent('onRowClicked');
// eslint-disable-next-line react-hooks/exhaustive-deps
}
@@ -90,20 +85,16 @@ export const Listview = function Listview({
data: removeFunctionObjects(childrenDataClone),
children: childrenData,
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
if (selectedRowIndex != undefined) {
const exposedVariables = {
selectedRowId: selectedRowIndex,
selectedRow: childrenData[selectedRowIndex],
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [childrenData, childComponents, isEditorReady]);
+ }, [childrenData, childComponents]);
function filterComponents() {
if (!childrenData || childrenData.length === 0) {
diff --git a/frontend/src/Editor/Components/Modal.jsx b/frontend/src/Editor/Components/Modal.jsx
index 66f6565343..e63f25a141 100644
--- a/frontend/src/Editor/Components/Modal.jsx
+++ b/frontend/src/Editor/Components/Modal.jsx
@@ -20,7 +20,6 @@ export const Modal = function Modal({
dataCy,
height,
mode,
- isEditorReady,
}) {
const [showModal, setShowModal] = useState(false);
@@ -77,10 +76,9 @@ export const Modal = function Modal({
setExposedVariable('show', false);
},
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- } // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [setShowModal, isEditorReady]);
+ setExposedVariables(exposedVariables);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [setShowModal]);
const isInitialRender = useRef(true);
const prevShowValue = useRef(exposedVariables.show);
@@ -108,6 +106,7 @@ export const Modal = function Modal({
function hideModal() {
setShowModal(false);
setExposedVariable('show', false);
+ console.log('Trigger close event =>', exposedVariables.show);
fireEvent('onClose');
}
useEffect(() => {
diff --git a/frontend/src/Editor/Components/Multiselect.jsx b/frontend/src/Editor/Components/Multiselect.jsx
index 8b2db437ca..2c57edf8aa 100644
--- a/frontend/src/Editor/Components/Multiselect.jsx
+++ b/frontend/src/Editor/Components/Multiselect.jsx
@@ -22,7 +22,6 @@ export const Multiselect = function Multiselect({
darkMode,
fireEvent,
dataCy,
- isEditorReady,
}) {
const { label, value, values, display_values, showAllOption } = properties;
const { borderRadius, visibility, disabledState, boxShadow } = styles;
@@ -125,11 +124,10 @@ export const Multiselect = function Multiselect({
},
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
+
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [selected, setSelected, isEditorReady]);
+ }, [selected, setSelected]);
const filterOptions = (options, filter) => {
setSearched(filter);
diff --git a/frontend/src/Editor/Components/MultiselectV2/MultiselectV2.jsx b/frontend/src/Editor/Components/MultiselectV2/MultiselectV2.jsx
index 1049532c4b..abd3de16ed 100644
--- a/frontend/src/Editor/Components/MultiselectV2/MultiselectV2.jsx
+++ b/frontend/src/Editor/Components/MultiselectV2/MultiselectV2.jsx
@@ -27,7 +27,7 @@ export const MultiselectV2 = ({
darkMode,
fireEvent,
validate,
- isEditorReady,
+ width,
}) => {
let {
label,
@@ -179,10 +179,8 @@ export const MultiselectV2 = ({
setIsMultiSelectDisabled(value);
},
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
- }, [isEditorReady]);
+ setExposedVariables(exposedVariables);
+ }, []);
useEffect(() => {
// Expose selectOption
diff --git a/frontend/src/Editor/Components/RadioButton.jsx b/frontend/src/Editor/Components/RadioButton.jsx
index a5f74cde19..51d19d8cbb 100644
--- a/frontend/src/Editor/Components/RadioButton.jsx
+++ b/frontend/src/Editor/Components/RadioButton.jsx
@@ -11,7 +11,6 @@ export const RadioButton = function RadioButton({
setExposedVariables,
darkMode,
dataCy,
- isEditorReady,
}) {
const { label, value, values, display_values } = properties;
const { visibility, disabledState, activeColor, boxShadow } = styles;
@@ -44,10 +43,9 @@ export const RadioButton = function RadioButton({
onSelect(option);
},
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- } // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [value, setValue, isEditorReady]);
+ setExposedVariables(exposedVariables);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [value, setValue]);
return (
{
- if (isEditorReady) {
- setExposedVariables({
- currentData: tableData,
- updatedData: tableData,
- });
- }
- }, [JSON.stringify(tableData), isEditorReady]);
+ setExposedVariables({
+ currentData: tableData,
+ updatedData: tableData,
+ });
+ }, [JSON.stringify(tableData)]);
const columnDataForAddNewRows = generateColumnsData({
columnProperties: useDynamicColumn ? generatedColumn : component.definition.properties.columns.value,
@@ -778,7 +775,7 @@ export function Table({
fireEvent('onRowClicked');
}
});
- }, [JSON.stringify(tableData), JSON.stringify(tableDetails.selectedRow), isEditorReady]);
+ }, [JSON.stringify(tableData), JSON.stringify(tableDetails.selectedRow)]);
useEffect(() => {
setExposedVariable('deselectRow', async function () {
@@ -790,7 +787,7 @@ export function Table({
}
return;
});
- }, [JSON.stringify(tableData), JSON.stringify(tableDetails.selectedRow), isEditorReady]);
+ }, [JSON.stringify(tableData), JSON.stringify(tableDetails.selectedRow)]);
useEffect(() => {
setExposedVariable('discardChanges', async function () {
@@ -802,7 +799,7 @@ export function Table({
mergeToTableDetails({ dataUpdates: {}, changeSet: {} });
}
});
- }, [JSON.stringify(tableData), JSON.stringify(tableDetails.changeSet), isEditorReady]);
+ }, [JSON.stringify(tableData), JSON.stringify(tableDetails.changeSet)]);
useEffect(() => {
setExposedVariable('discardNewlyAddedRows', async function () {
@@ -821,7 +818,6 @@ export function Table({
JSON.stringify(tableDetails.addNewRowsDetails.newRowsChangeSet),
tableDetails.addNewRowsDetails.addingNewRows,
JSON.stringify(tableDetails.addNewRowsDetails.newRowsDataUpdates),
- isEditorReady,
]);
useEffect(() => {
@@ -845,7 +841,7 @@ export function Table({
setExposedVariables({ selectedRow, selectedRowId });
mergeToTableDetails({ selectedRow, selectedRowId });
}
- }, [selectedFlatRows.length, selectedFlatRows, isEditorReady]);
+ }, [selectedFlatRows.length, selectedFlatRows]);
useEffect(() => {
setExposedVariable('downloadTableData', async function (format) {
@@ -859,7 +855,7 @@ export function Table({
mergeToTableDetails({ selectedRowsDetails: [], selectedRow: {}, selectedRowId: null });
toggleAllRowsSelected(false);
}
- }, [showBulkSelector, highlightSelectedRow, allowSelection, isEditorReady]);
+ }, [showBulkSelector, highlightSelectedRow, allowSelection]);
React.useEffect(() => {
if (enablePagination) {
@@ -975,7 +971,7 @@ export function Table({
}
//hack : in the initial render, data is undefined since, upon feeding data to the table from some query, query inside current state is {}. Hence we added data in the dependency array, now question is should we add data or rows?
- }, [JSON.stringify(defaultSelectedRow), JSON.stringify(data), isEditorReady]);
+ }, [JSON.stringify(defaultSelectedRow), JSON.stringify(data)]);
useEffect(() => {
// csa for select all rows in table
diff --git a/frontend/src/Editor/Components/Tabs.jsx b/frontend/src/Editor/Components/Tabs.jsx
index 716cb9b66e..6d67108d89 100644
--- a/frontend/src/Editor/Components/Tabs.jsx
+++ b/frontend/src/Editor/Components/Tabs.jsx
@@ -17,7 +17,6 @@ export const Tabs = function Tabs({
styles,
darkMode,
dataCy,
- isEditorReady,
}) {
const { tabWidth, boxShadow } = styles;
@@ -104,11 +103,10 @@ export const Tabs = function Tabs({
},
currentTab: currentTab,
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
+
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [setCurrentTab, currentTab, isEditorReady]);
+ }, [setCurrentTab, currentTab]);
const renderTabContent = (id, tab) => (
{
const exposedVariables = {
@@ -189,9 +189,9 @@ export const TextInput = function TextInput({
fireEvent('onChange');
},
};
- if (isEditorReady) setExposedVariables(exposedVariables);
+ setExposedVariables(exposedVariables);
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [setValue, isEditorReady]);
+ }, [setValue]);
const iconName = styles.icon; // Replace with the name of the icon you want
// eslint-disable-next-line import/namespace
const IconElement = Icons[iconName] == undefined ? Icons['IconHome2'] : Icons[iconName];
diff --git a/frontend/src/Editor/Components/TreeSelect.jsx b/frontend/src/Editor/Components/TreeSelect.jsx
index 08f7456bb1..c66202637b 100644
--- a/frontend/src/Editor/Components/TreeSelect.jsx
+++ b/frontend/src/Editor/Components/TreeSelect.jsx
@@ -14,7 +14,6 @@ export const TreeSelect = ({
fireEvent,
darkMode,
dataCy,
- isEditorReady,
}) => {
const { label } = properties;
const { visibility, disabledState, checkboxColor, boxShadow } = styles;
@@ -52,11 +51,10 @@ export const TreeSelect = ({
checkedPathStrings: checkedPathString,
checked: checkedArr,
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
+
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [JSON.stringify(checkedData), JSON.stringify(data), isEditorReady]);
+ }, [JSON.stringify(checkedData), JSON.stringify(data)]);
useEffect(() => {
setExposedVariable('expanded', expandedData);
@@ -92,9 +90,8 @@ export const TreeSelect = ({
checkedPathStrings: checkedPathString,
checked: checked,
};
- if (isEditorReady) {
- setExposedVariables(exposedVariables);
- }
+ setExposedVariables(exposedVariables);
+
updatedNode.checked ? fireEvent('onCheck') : fireEvent('onUnCheck');
fireEvent('onChange');
setChecked(checked);
diff --git a/frontend/src/Editor/Container.jsx b/frontend/src/Editor/Container.jsx
index 6cc2efa620..7a0a9804eb 100644
--- a/frontend/src/Editor/Container.jsx
+++ b/frontend/src/Editor/Container.jsx
@@ -19,7 +19,7 @@ import {
calculateMoveableBoxHeight,
} from '@/_helpers/appUtils';
import { useAppVersionStore } from '@/_stores/appVersionStore';
-import { useEditorStore } from '@/_stores/editorStore';
+import { useEditorStore, flushComponentsToRender } from '@/_stores/editorStore';
import { useAppInfo } from '@/_stores/appDataStore';
import { shallow } from 'zustand/shallow';
import _, { isEmpty } from 'lodash';
@@ -878,12 +878,6 @@ export const Container = ({
})
.filter(([, box]) => isEmpty(box?.component?.parent))
.map(([id, box]) => {
- const canShowInCurrentLayout =
- box.component.definition.others[currentLayout === 'mobile' ? 'showOnMobile' : 'showOnDesktop'].value;
-
- if (box.parent || !resolveWidgetFieldValue(canShowInCurrentLayout)) {
- return '';
- }
return (
{
const isGhostComponent = id === 'resizingComponentId';
const {
component: { parent },
layouts,
} = widget;
- const { isSelected, isHovered } = useEditorStore((state) => {
+ const { isSelected, isHovered, shouldRerender } = useEditorStore((state) => {
const isSelected = !!(state.selectedComponents || []).find((selected) => selected?.id === id);
const isHovered = state?.hoveredComponent == id;
- return { isSelected, isHovered };
+ /*
+ `shouldRerender` is added only for re-rendering the component when visibility/showOnMobile/showOnDesktop
+ updates since these attributes need update or WidgetWrapper rather than actual Widget itself
+ */
+ const shouldRerender = state.componentsNeedsUpdateOnNextRender.some((compId) => compId === id);
+ return { isSelected, isHovered, shouldRerender };
}, shallow);
const isDragging = useGridStore((state) => state?.draggingComponentId === id);
+ const canShowInCurrentLayout = otherDefinition[currentLayout === 'mobile' ? 'showOnMobile' : 'showOnDesktop'].value;
+
+ if (parent || !resolveWidgetFieldValue(canShowInCurrentLayout)) {
+ /*
+ Remove the component from the re-render queue
+ This is necessary because child components are not rendered,
+ so their flush functions won't be called from ControlledComponentToRender
+ */
+ shouldRerender && flushComponentsToRender(id);
+ return '';
+ }
+
let layoutData = layouts?.[currentLayout];
if (isEmpty(layoutData)) {
layoutData = layouts?.['desktop'];
diff --git a/frontend/src/Editor/ControlledComponentToRender.jsx b/frontend/src/Editor/ControlledComponentToRender.jsx
index 0471bef462..226bdcd5a9 100644
--- a/frontend/src/Editor/ControlledComponentToRender.jsx
+++ b/frontend/src/Editor/ControlledComponentToRender.jsx
@@ -1,7 +1,7 @@
import React, { useState, useCallback } from 'react';
import { getComponentToRender } from '@/_helpers/editorHelpers';
import _ from 'lodash';
-import { getComponentsToRenders } from '@/_stores/editorStore';
+import { getComponentsToRenders, flushComponentsToRender } from '@/_stores/editorStore';
function deepEqualityCheckusingLoDash(obj1, obj2) {
return _.isEqual(obj1, obj2);
@@ -16,6 +16,7 @@ export const shouldUpdate = (prevProps, nextProps) => {
if (componentId) {
const componentToRender = listToRender.find((item) => item === componentId);
+
const parentReRendered = listToRender.find((item) => item === prevProps?.parentId);
const grandParentReRendered = listToRender.find((item) => item === prevProps?.grandParentId);
@@ -25,6 +26,9 @@ export const shouldUpdate = (prevProps, nextProps) => {
}
}
+ // Flushing the component after the function is called from ControlledComponentToRender component
+ if (nextProps?.componentName) flushComponentsToRender([prevProps?.id]);
+
// Added to render the default child components
if (prevProps?.childComponents === null && nextProps?.childComponents) return false;
@@ -38,7 +42,6 @@ export const shouldUpdate = (prevProps, nextProps) => {
prevProps?.height === nextProps?.height &&
prevProps?.darkMode === nextProps?.darkMode &&
prevProps?.childComponents === nextProps?.childComponents &&
- prevProps?.isEditorReady === nextProps?.isEditorReady &&
!needToRender
);
};
diff --git a/frontend/src/Editor/Editor.jsx b/frontend/src/Editor/Editor.jsx
index fc20c1caa1..75799e827d 100644
--- a/frontend/src/Editor/Editor.jsx
+++ b/frontend/src/Editor/Editor.jsx
@@ -28,6 +28,7 @@ import {
buildComponentMetaDefinition,
getAllChildComponents,
runQueries,
+ updateSuggestionsFromCurrentState,
} from '@/_helpers/appUtils';
import { Confirm } from './Viewer/Confirm';
// eslint-disable-next-line import/no-unresolved
@@ -308,14 +309,8 @@ const EditorComponent = (props) => {
const isPageSwitched = useResolveStore.getState().isPageSwitched;
if (isPageSwitched) {
- const currentStateObj = useCurrentStateStore.getState();
-
handleLowPriorityWork(() => {
- useResolveStore.getState().actions.addAppSuggestions({
- queries: currentStateObj.queries,
- components: currentStateObj.components,
- page: currentStateObj.page,
- });
+ updateSuggestionsFromCurrentState();
useResolveStore.getState().actions.pageSwitched(false);
});
}
@@ -733,6 +728,7 @@ const EditorComponent = (props) => {
await processNewAppDefinition(appData, startingPageHandle, false, ({ homePageId }) => {
handleLowPriorityWork(() => {
+ updateSuggestionsFromCurrentState();
useResolveStore.getState().actions.updateLastUpdatedRefs(['constants', 'client']);
commonLowPriorityActions(events, { homePageId });
});
@@ -825,6 +821,7 @@ const EditorComponent = (props) => {
});
processNewAppDefinition(appData, null, true, ({ homePageId }) => {
handleLowPriorityWork(async () => {
+ updateSuggestionsFromCurrentState();
await fetchDataSources(editing_version?.id);
commonLowPriorityActions(events, homePageId);
});
diff --git a/frontend/src/Editor/Viewer.jsx b/frontend/src/Editor/Viewer.jsx
index 841fc95cd4..1989261728 100644
--- a/frontend/src/Editor/Viewer.jsx
+++ b/frontend/src/Editor/Viewer.jsx
@@ -21,6 +21,7 @@ import {
runQuery,
computeComponentState,
buildAppDefinition,
+ updateSuggestionsFromCurrentState,
} from '@/_helpers/appUtils';
import queryString from 'query-string';
import ViewerLogoIcon from './Icons/viewer-logo.svg';
@@ -45,7 +46,7 @@ import MobileHeader from './Viewer/MobileHeader';
import DesktopHeader from './Viewer/DesktopHeader';
import './Viewer/viewer.scss';
import { useResolveStore } from '@/_stores/resolverStore';
-import { findComponentsWithReferences } from '@/_helpers/editorHelpers';
+import { findComponentsWithReferences, handleLowPriorityWork } from '@/_helpers/editorHelpers';
import { findAllEntityReferences } from '@/_stores/utils';
import { dfs } from '@/_stores/handleReferenceTransactions';
import useAppDarkMode from '@/_hooks/useAppDarkMode';
@@ -265,6 +266,7 @@ class ViewerComponent extends React.Component {
useCurrentStateStore.getState().actions.setEditorReady(true);
if (loadType === 'appload') {
+ updateSuggestionsFromCurrentState();
this.runQueries(dataQueries);
}
@@ -807,6 +809,8 @@ class ViewerComponent extends React.Component {
isSwitchingPage: true,
},
});
+
+ useResolveStore.getState().actions.pageSwitched(true);
this.onViewerLoadUpdateEntityReferences(id, 'page-switch');
};
@@ -1093,6 +1097,10 @@ const withStore = (Component) => (props) => {
if (isPageSwitched) {
const currentComponentsDef = appDefinition?.pages?.[currentPageId]?.components || {};
const currentComponents = Object.keys(currentComponentsDef);
+ handleLowPriorityWork(() => {
+ updateSuggestionsFromCurrentState();
+ useResolveStore.getState().actions.pageSwitched(false);
+ });
setTimeout(() => {
if (currentComponents.length > 0) {
diff --git a/frontend/src/_helpers/appUtils.js b/frontend/src/_helpers/appUtils.js
index a111e434b0..335785cf2a 100644
--- a/frontend/src/_helpers/appUtils.js
+++ b/frontend/src/_helpers/appUtils.js
@@ -89,6 +89,8 @@ const debouncedChange = _.debounce((duplicateCurrentState) => {
}, 100);
export function onComponentOptionsChanged(component, options, id) {
+ const resolveStoreActions = useResolveStore.getState().actions;
+ options.forEach((option) => resolveStoreActions.resetHintsByKey([`components.${component?.name}.${option[0]}`]));
let componentName = component.name;
const { isEditorReady, page } = useCurrentStateStore.getState();
@@ -183,6 +185,8 @@ export function onComponentOptionsChanged(component, options, id) {
}
export function onComponentOptionChanged(component, option_name, value, id) {
+ const resolveStoreActions = useResolveStore.getState().actions;
+ resolveStoreActions.resetHintsByKey(`components.${component?.name}.${option_name}`);
if (!useEditorStore.getState()?.appDefinition?.pages[getCurrentState()?.page?.id]?.components) return;
let componentName = component.name;
@@ -633,12 +637,15 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) {
const value = resolveReferences(event.value, state, undefined, customVariables);
const customAppVariables = { ...state.variables };
customAppVariables[key] = value;
+ const resp = useCurrentStateStore.getState().actions.setCurrentState({
+ variables: customAppVariables,
+ });
+
useResolveStore.getState().actions.addAppSuggestions({
variables: customAppVariables,
});
- return useCurrentStateStore.getState().actions.setCurrentState({
- variables: customAppVariables,
- });
+
+ return resp;
}
case 'get-custom-variable': {
@@ -1144,7 +1151,7 @@ export function runQuery(
//for resetting the hints when the query is run for large number of items
if (mode == 'edit') {
const resolveStoreActions = useResolveStore.getState().actions;
- resolveStoreActions.resetHintsByQueryName(queryName);
+ resolveStoreActions.resetHintsByKey(`queries.${queryName}`);
}
let parameters = userSuppliedParameters;
@@ -2342,3 +2349,12 @@ export const calculateMoveableBoxHeight = (componentType, layoutData, stylesDefi
return newHeight;
};
+
+export const updateSuggestionsFromCurrentState = () => {
+ const currentStateObj = useCurrentStateStore.getState();
+ useResolveStore.getState().actions.addAppSuggestions({
+ queries: currentStateObj.queries,
+ components: currentStateObj.components,
+ page: currentStateObj.page,
+ });
+};
diff --git a/frontend/src/_helpers/editorHelpers.js b/frontend/src/_helpers/editorHelpers.js
index 2869a072ac..ddc7604bd7 100644
--- a/frontend/src/_helpers/editorHelpers.js
+++ b/frontend/src/_helpers/editorHelpers.js
@@ -166,6 +166,19 @@ function convertToBracketNotation(base, accessors) {
}
function verifyDotAndBracketNotations(jsString) {
+ if (
+ !(
+ jsString.includes('components.') ||
+ jsString.includes('globals.') ||
+ jsString.includes('queries.') ||
+ jsString.includes('page.') ||
+ jsString.includes('variables.') ||
+ jsString.includes('constants.')
+ )
+ ) {
+ return false;
+ }
+
const notations = findNotations(jsString);
for (const { base, accessors } of notations) {
diff --git a/frontend/src/_stores/resolverStore.js b/frontend/src/_stores/resolverStore.js
index 57b4533a81..ce4b03d1d1 100644
--- a/frontend/src/_stores/resolverStore.js
+++ b/frontend/src/_stores/resolverStore.js
@@ -79,19 +79,21 @@ export const useResolveStore = create(
resetStore: () => {
set(() => ({ ...initialState, referenceMapper: new ReferencesBiMap() }));
},
- resetHintsByQueryName: (queryName) => {
+ resetHintsByKey: (hintKey) => {
set((state) => {
// Filter out app hints related to the specified query
- const newAppHints = state.suggestions.appHints.filter(
- (hint) => !hint.hint.startsWith(`queries.${queryName}.`)
- );
+ const newAppHints = state.suggestions.appHints.filter((hint) => !hint.hint.startsWith(`${hintKey}.`));
+
+ if (!isIterable(state.lookupTable.hints) || !isIterable(state.lookupTable.resolvedRefs)) {
+ return { ...state };
+ }
const newHints = new Map(state.lookupTable.hints);
const newResolvedRefs = new Map(state.lookupTable.resolvedRefs);
// Remove entries from hints and resolvedRefs
for (const [key, value] of newHints) {
- if (key.startsWith(`queries.${queryName}.`)) {
+ if (key.startsWith(`${hintKey}.`)) {
newHints.delete(key);
newResolvedRefs.delete(value);
}
@@ -106,7 +108,7 @@ export const useResolveStore = create(
hints: newHints,
resolvedRefs: newResolvedRefs,
},
- lastUpdatedRefs: state.lastUpdatedRefs.filter((ref) => !ref.startsWith(`queries.${queryName}.`)),
+ lastUpdatedRefs: state.lastUpdatedRefs.filter((ref) => !ref.startsWith(`${hintKey}.`)),
};
});
},
@@ -425,10 +427,14 @@ async function batchUpdateComponents(componentIds) {
useEditorStore.getState().actions.updateComponentsNeedsUpdateOnNextRender(batch);
}
-
- // Flush only updated components
-
- flushComponentsToRender(updatedComponentIds);
}
export const useResolverStoreActions = () => useResolveStore.getState().actions;
+
+function isIterable(obj) {
+ // checks for null and undefined
+ if (obj == null) {
+ return false;
+ }
+ return typeof obj[Symbol.iterator] === 'function';
+}