diff --git a/.version b/.version
index 3a2b37ff57..bc2e849859 100644
--- a/.version
+++ b/.version
@@ -1 +1 @@
-2.50.6
+2.50.7
diff --git a/frontend/.version b/frontend/.version
index 3a2b37ff57..bc2e849859 100644
--- a/frontend/.version
+++ b/frontend/.version
@@ -1 +1 @@
-2.50.6
+2.50.7
diff --git a/frontend/src/Editor/Components/Form/Form.jsx b/frontend/src/Editor/Components/Form/Form.jsx
index 1c861bf8e7..3a592dfc9a 100644
--- a/frontend/src/Editor/Components/Form/Form.jsx
+++ b/frontend/src/Editor/Components/Form/Form.jsx
@@ -3,7 +3,7 @@ import { SubCustomDragLayer } from '@/Editor/SubCustomDragLayer';
import { SubContainer } from '@/Editor/SubContainer';
// eslint-disable-next-line import/no-unresolved
import { diff } from 'deep-object-diff';
-import _, { omit } from 'lodash';
+import _, { debounce, omit } from 'lodash';
import { Box } from '@/Editor/Box';
import { generateUIComponents } from './FormUtils';
import { useMounted } from '@/_hooks/use-mount';
@@ -189,7 +189,9 @@ export const Form = function Form(props) {
};
const fireSubmissionEvent = () => {
if (isValid) {
- onEvent('onSubmit', formEvents).then(() => resetComponent());
+ onEvent('onSubmit', formEvents).then(() => {
+ debounce(() => resetComponent(), 100)();
+ });
} else {
fireEvent('onInvalid');
}
diff --git a/frontend/src/Editor/Container.jsx b/frontend/src/Editor/Container.jsx
index 000dd67328..212221bf50 100644
--- a/frontend/src/Editor/Container.jsx
+++ b/frontend/src/Editor/Container.jsx
@@ -258,16 +258,18 @@ export const Container = ({
return;
}
- if (!appDefinition.pages[currentPageId]?.components) return;
+ const definition = useEditorStore.getState().appDefinition;
+
+ if (!definition.pages[currentPageId]?.components) return;
const newDefinition = {
- ...appDefinition,
+ ...definition,
pages: {
- ...appDefinition.pages,
+ ...definition.pages,
[currentPageId]: {
- ...appDefinition.pages[currentPageId],
+ ...definition.pages[currentPageId],
components: {
- ...appDefinition.pages[currentPageId]?.components,
+ ...definition.pages[currentPageId]?.components,
...boxes,
},
},
@@ -276,7 +278,7 @@ export const Container = ({
//need to check if a new component is added or deleted
- const oldComponents = appDefinition.pages[currentPageId]?.components ?? {};
+ const oldComponents = definition.pages[currentPageId]?.components ?? {};
const newComponents = boxes;
const componendAdded = Object.keys(newComponents).length > Object.keys(oldComponents).length;
@@ -289,7 +291,8 @@ export const Container = ({
opts.componentAdded = true;
}
- const shouldUpdate = !_.isEmpty(diff(appDefinition, newDefinition));
+ const shouldUpdate = !_.isEmpty(diff(definition, newDefinition));
+
if (shouldUpdate) {
appDefinitionChanged(newDefinition, opts);
}
@@ -1045,15 +1048,16 @@ const WidgetWrapper = ({
const isWidgetActive = (isSelected || isDragging) && mode !== 'view';
const { label = { value: null } } = propertiesDefinition ?? {};
+ const visibility = propertiesDefinition?.visibility?.value ?? stylesDefinition?.visibility?.value ?? null;
+ const resolvedVisibility = resolveWidgetFieldValue(visibility);
const styles = {
width: width + 'px',
- height: calculateMoveableBoxHeight() + 'px',
+ height: resolvedVisibility ? calculateMoveableBoxHeight() + 'px' : '10px',
transform: `translate(${layoutData.left * gridWidth}px, ${layoutData.top}px)`,
...(isGhostComponent ? { opacity: 0.5 } : {}),
...(isWidgetActive ? { zIndex: 3 } : {}),
};
-
return (
<>
{
return (
deepEqualityCheckusingLoDash(prevProps?.id, nextProps?.id) &&
deepEqualityCheckusingLoDash(prevProps?.component?.definition, nextProps?.component?.definition) &&
+ deepEqualityCheckusingLoDash(prevProps?.customResolvables, nextProps?.customResolvables) &&
prevProps?.width === nextProps?.width &&
prevProps?.height === nextProps?.height &&
prevProps?.darkMode === nextProps?.darkMode &&
diff --git a/frontend/src/Editor/SubContainer.jsx b/frontend/src/Editor/SubContainer.jsx
index bacce01b9e..fd7af6a003 100644
--- a/frontend/src/Editor/SubContainer.jsx
+++ b/frontend/src/Editor/SubContainer.jsx
@@ -190,22 +190,24 @@ export const SubContainer = ({
}, [containerWidth]);
useEffect(() => {
- if (appDefinitionChanged) {
+ const definition = useEditorStore.getState().appDefinition;
+
+ if (definition) {
const newDefinition = {
- ...appDefinition,
+ ...definition,
pages: {
- ...appDefinition.pages,
+ ...definition.pages,
[currentPageId]: {
- ...appDefinition.pages[currentPageId],
+ ...definition.pages[currentPageId],
components: {
- ...appDefinition.pages[currentPageId].components,
+ ...definition.pages[currentPageId].components,
...childWidgets,
},
},
},
};
- const oldComponents = appDefinition.pages[currentPageId]?.components ?? {};
+ const oldComponents = definition.pages[currentPageId]?.components ?? {};
const newComponents = newDefinition.pages[currentPageId]?.components ?? {};
const componendAdded = Object.keys(newComponents).length > Object.keys(oldComponents).length;
@@ -216,7 +218,7 @@ export const SubContainer = ({
opts.componentAdded = true;
}
- const shouldUpdate = !_.isEmpty(diff(appDefinition, newDefinition));
+ const shouldUpdate = !_.isEmpty(diff(definition, newDefinition));
if (shouldUpdate) {
appDefinitionChanged(newDefinition, opts);
@@ -716,11 +718,19 @@ const SubWidgetWrapper = ({
const isDragging = useGridStore((state) => state?.draggingComponentId === id);
+ const isComponentVisible = () => {
+ const visibility =
+ widget.component.definition?.properties?.visibility?.value ??
+ widget.component.definition?.styles?.visibility?.value ??
+ null;
+ return resolveWidgetFieldValue(visibility);
+ };
+
let width = (canvasWidth * layoutData.width) / 43;
width = width > canvasWidth ? canvasWidth : width; //this handles scenarios where the width is set more than canvas for older components
const styles = {
width: width + 'px',
- height: layoutData.height + 'px',
+ height: isComponentVisible() ? layoutData.height + 'px' : '10px',
transform: `translate(${layoutData.left * gridWidth}px, ${layoutData.top}px)`,
...(isGhostComponent ? { opacity: 0.5 } : {}),
};
diff --git a/frontend/src/_helpers/appUtils.js b/frontend/src/_helpers/appUtils.js
index 922b1f2e01..12afe5f831 100644
--- a/frontend/src/_helpers/appUtils.js
+++ b/frontend/src/_helpers/appUtils.js
@@ -105,15 +105,22 @@ export function onComponentOptionsChanged(component, options, id) {
componentData = deepClone(componentData) || {};
const shouldUpdateResolvedRefsOfHints = [];
-
+ const isListviewOrKanbaComponent = component.component === 'Listview' || component.component === 'Kanban';
+ const isFromComponent = component.component === 'Form';
for (const option of options) {
componentData[option[0]] = option[1];
- const isListviewOrKanbaComponent = component.component === 'Listview' || component.component === 'Kanban';
-
let path = null;
if (isListviewOrKanbaComponent) {
path = `components.${componentName}`;
+ } else if (isFromComponent) {
+ const basePath = `components.${componentName}.${option[0]}`;
+
+ useResolveStore.getState().actions.addAppSuggestions({
+ [basePath]: option[1],
+ });
+
+ shouldUpdateResolvedRefsOfHints.push({ hint: basePath, newRef: componentData[option[1]] });
} else {
path = `components.${componentName}.${option[0]}`;
}
@@ -405,7 +412,7 @@ export async function executeActionsForEventId(_ref, eventId, events = [], mode,
const filteredEvents = events?.filter((event) => event?.event.eventId === eventId)?.sort((a, b) => a.index - b.index);
for (const event of filteredEvents) {
- await executeAction(_ref, event.event, mode, customVariables); // skipcq: JS-0032
+ await executeActionWithDebounce(_ref, event.event, mode, customVariables);
}
}
@@ -745,9 +752,8 @@ export async function onEvent(_ref, eventName, events, options = {}, mode = 'edi
const { customVariables } = options;
if (eventName === 'onPageLoad') {
- return _.debounce(async () => {
- await executeActionsForEventId(_ref, 'onPageLoad', events, mode, customVariables);
- }, 10);
+ // for onPageLoad events, we need to execute the actions after the page is loaded
+ handleLowPriorityWork(() => executeActionsForEventId(_ref, 'onPageLoad', events, mode, customVariables));
}
if (eventName === 'onTrigger') {
@@ -1221,6 +1227,16 @@ export function runQuery(
});
resolve(data);
onEvent(_self, 'onDataQueryFailure', queryEvents);
+
+ const toUpdateRefs = [
+ { hint: `queries.${queryName}.isLoading`, newRef: false },
+ {
+ hint: `queries.${queryName}.data`,
+ newRef: [],
+ },
+ ];
+
+ useResolveStore.getState().actions.updateResolvedRefsOfHints(toUpdateRefs);
if (mode !== 'view') {
const err = query.kind == 'tooljetdb' ? data?.error || data : data;
toast.error(err?.message ? err?.message : 'Something went wrong');
@@ -1652,7 +1668,7 @@ export const cloneComponents = (
});
};
-const getAllChildComponents = (allComponents, parentId) => {
+export const getAllChildComponents = (allComponents, parentId) => {
const childComponents = [];
Object.keys(allComponents).forEach((componentId) => {
@@ -1660,7 +1676,8 @@ const getAllChildComponents = (allComponents, parentId) => {
const isParentTabORCalendar =
allComponents[parentId]?.component?.component === 'Tabs' ||
- allComponents[parentId]?.component?.component === 'Calendar';
+ allComponents[parentId]?.component?.component === 'Calendar' ||
+ allComponents[parentId]?.component?.component === 'Kanban';
if (componentParentId && isParentTabORCalendar) {
const childComponent = allComponents[componentId];
diff --git a/frontend/src/_helpers/utility.js b/frontend/src/_helpers/utility.js
index 3906f25460..ea1c6e34ee 100644
--- a/frontend/src/_helpers/utility.js
+++ b/frontend/src/_helpers/utility.js
@@ -2,7 +2,7 @@ import { useResolveStore } from '@/_stores/resolverStore';
import _ from 'lodash';
export function validateMultilineCode(code) {
- const reservedKeyword = ['app', 'window', 'this']; // Case-sensitive reserved keywords
+ const reservedKeyword = ['app', 'this']; // Case-sensitive reserved keywords except 'window'
const keywordRegex = new RegExp(`\\b(${reservedKeyword.join('|')})\\b`, 'i');
let inString = false;
let inComment = false;
@@ -33,6 +33,18 @@ export function validateMultilineCode(code) {
// If we are not within a string or a comment, check for keywords
if (!inString && !inComment) {
+ // Special handling for 'window'
+ if (code.substring(i, i + 6) === 'window' && (code[i + 6] === undefined || code[i + 6] !== '.')) {
+ return {
+ status: 'failed',
+ data: {
+ message: `Code contains reserved keyword 'window'`,
+ description:
+ 'Cannot resolve code with reserved keyword "window" in it unless it is followed by a dot. Please remove it and try again.',
+ },
+ };
+ }
+
const restOfCode = code.substring(i);
const match = restOfCode.match(keywordRegex);
diff --git a/server/.version b/server/.version
index 3a2b37ff57..bc2e849859 100644
--- a/server/.version
+++ b/server/.version
@@ -1 +1 @@
-2.50.6
+2.50.7
diff --git a/server/src/services/components.service.ts b/server/src/services/components.service.ts
index 35f51a314a..8193b4d9ed 100644
--- a/server/src/services/components.service.ts
+++ b/server/src/services/components.service.ts
@@ -108,13 +108,12 @@ export class ComponentsService {
return acc;
}, {});
+ // Update the component with merged data
await manager.update(Component, componentId, newComponentsData);
- return;
+ } else {
+ // Update the component directly if definition is not changed
+ await manager.update(Component, componentId, component);
}
-
- await manager.update(Component, componentId, component);
-
- return;
}
}, appVersionId);
}