diff --git a/frontend/src/Editor/BoxUI.jsx b/frontend/src/Editor/BoxUI.jsx index b8b8798e6f..be88f6504b 100644 --- a/frontend/src/Editor/BoxUI.jsx +++ b/frontend/src/Editor/BoxUI.jsx @@ -37,6 +37,10 @@ const BoxUI = (props) => { currentLayout, readOnly, currentPageId, + onOptionChanged, + onOptionsChanged, + isFromSubContainer, + childComponents, } = props; const darkMode = localStorage.getItem('darkMode') === 'true'; @@ -127,13 +131,25 @@ const BoxUI = (props) => { + isFromSubContainer + ? onOptionChanged(component, variable, value, id) + : onComponentOptionChanged(component, variable, value, id) + } + setExposedVariables={(variableSet) => { + if (isFromSubContainer) { + onOptionsChanged(component, Object.entries(variableSet), id); + } else { + onComponentOptionsChanged(component, Object.entries(variableSet), id); + } + }} height={height} component={component} containerProps={getContainerProps(id)} @@ -148,8 +164,6 @@ const BoxUI = (props) => { ? { boxShadow: generalStyles?.boxShadow } : {}), }} - setExposedVariable={(variable, value) => onComponentOptionChanged(component, variable, value, id)} - setExposedVariables={(variableSet) => onComponentOptionsChanged(component, Object.entries(variableSet), id)} fireEvent={fireEvent} validate={validate} parentId={parentId} @@ -166,6 +180,7 @@ const BoxUI = (props) => { currentState={currentState} currentPageId={currentPageId} getContainerProps={component.component === 'Form' ? getContainerProps : null} + childComponents={childComponents} /> diff --git a/frontend/src/Editor/CodeEditor/styles.scss b/frontend/src/Editor/CodeEditor/styles.scss index f032ee08b0..a5dd955ec0 100644 --- a/frontend/src/Editor/CodeEditor/styles.scss +++ b/frontend/src/Editor/CodeEditor/styles.scss @@ -245,7 +245,7 @@ .cm-tooltip-autocomplete { @extend .cm-base-autocomplete; - top: 0px !important; + top: content-box !important; } } diff --git a/frontend/src/Editor/CodeEditor/utils.js b/frontend/src/Editor/CodeEditor/utils.js index b068ddb487..dc0ea6811e 100644 --- a/frontend/src/Editor/CodeEditor/utils.js +++ b/frontend/src/Editor/CodeEditor/utils.js @@ -202,7 +202,7 @@ const resolveMultiDynamicReferences = (code, lookupTable) => { } else { const [resolvedCode] = resolveCode(variableToResolve, {}, true, [], true); - resolvedValue = resolvedCode; + resolvedValue = resolvedValue.replace(variable, resolvedCode); } }); } @@ -210,6 +210,14 @@ const resolveMultiDynamicReferences = (code, lookupTable) => { return resolvedValue; }; +const queryHasStringOtherThanVariable = (query) => { + if (query.startsWith('{{') && query.endsWith('}}')) { + return false; + } + + return true; +}; + export const resolveReferences = (query, validationSchema, customResolvers = {}) => { if (!query || typeof query !== 'string') return [false, null, null]; let resolvedValue = query; @@ -229,7 +237,7 @@ export const resolveReferences = (query, validationSchema, customResolvers = {}) return [valid, errors, newValue, resolvedValue]; } - const hasMultiDynamicVariables = getDynamicVariables(query)?.length > 1; + const hasMultiDynamicVariables = queryHasStringOtherThanVariable(query) || getDynamicVariables(query)?.length > 1; const { lookupTable } = useResolveStore.getState(); if (hasMultiDynamicVariables) { diff --git a/frontend/src/Editor/Components/Button.jsx b/frontend/src/Editor/Components/Button.jsx index 29bbb7ac49..aa49466759 100644 --- a/frontend/src/Editor/Components/Button.jsx +++ b/frontend/src/Editor/Components/Button.jsx @@ -1,11 +1,8 @@ import React, { useEffect, useState } from 'react'; import cx from 'classnames'; const tinycolor = require('tinycolor2'); -import useRenderCount from '@/_hooks/useRenderCount'; export const Button = function Button(props) { - useRenderCount(`Button Main component ${props.id}`); - const { height, properties, styles, fireEvent, id, dataCy, setExposedVariable, setExposedVariables } = props; const { backgroundColor, textColor, borderRadius, loaderColor, disabledState, borderColor, boxShadow } = styles; diff --git a/frontend/src/Editor/Components/Form/Form.jsx b/frontend/src/Editor/Components/Form/Form.jsx index 0a9e4615e6..b7441409a3 100644 --- a/frontend/src/Editor/Components/Form/Form.jsx +++ b/frontend/src/Editor/Components/Form/Form.jsx @@ -7,7 +7,12 @@ import _, { omit } from 'lodash'; import { Box } from '@/Editor/Box'; import { generateUIComponents } from './FormUtils'; import { useMounted } from '@/_hooks/use-mount'; -import { onComponentClick, onComponentOptionChanged, removeFunctionObjects } from '@/_helpers/appUtils'; +import { + onComponentClick, + onComponentOptionChanged, + onComponentOptionsChanged, + removeFunctionObjects, +} from '@/_helpers/appUtils'; import { useAppInfo } from '@/_stores/appDataStore'; export const Form = function Form(props) { const { @@ -31,12 +36,11 @@ export const Form = function Form(props) { mode, getContainerProps, containerProps, + childComponents, } = props; const { events: allAppEvents } = useAppInfo(); - const { childComponents } = containerProps; - const formEvents = allAppEvents.filter((event) => event.target === 'component' && event.sourceId === id); const { visibility, disabledState, borderRadius, borderColor, boxShadow } = styles; const { buttonToSubmit, loadingState, advanced, JSONSchema } = properties; @@ -76,7 +80,7 @@ export const Form = function Form(props) { }; setExposedVariables(exposedVariables); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isValid]); + }, [isValid, formEvents]); const extractData = (data) => { const result = {}; @@ -122,7 +126,7 @@ export const Form = function Form(props) { let formattedChildData = {}; let childValidation = true; - if (childComponents === null) { + if (!childComponents) { const exposedVariables = { data: formattedChildData, isValid: childValidation, @@ -179,7 +183,7 @@ export const Form = function Form(props) { document.addEventListener('submitForm', handleFormSubmission); return () => document.removeEventListener('submitForm', handleFormSubmission); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [buttonToSubmit, isValid, advanced, JSON.stringify(uiComponents)]); + }, [buttonToSubmit, isValid, advanced, JSON.stringify(uiComponents), formEvents]); const handleSubmit = (event) => { event.preventDefault(); @@ -282,7 +286,7 @@ export const Form = function Form(props) { ); diff --git a/frontend/src/Editor/Components/Text.jsx b/frontend/src/Editor/Components/Text.jsx index ef9a91808b..6cbd11e256 100644 --- a/frontend/src/Editor/Components/Text.jsx +++ b/frontend/src/Editor/Components/Text.jsx @@ -3,7 +3,6 @@ import DOMPurify from 'dompurify'; import Markdown from 'react-markdown'; import './text.scss'; import Loader from '@/ToolJetUI/Loader/Loader'; -import useRenderCount from '@/_hooks/useRenderCount'; const VERTICAL_ALIGNMENT_VS_CSS_VALUE = { top: 'flex-start', @@ -11,17 +10,7 @@ const VERTICAL_ALIGNMENT_VS_CSS_VALUE = { bottom: 'flex-end', }; -export const Text = function Text({ - height, - properties, - fireEvent, - styles, - darkMode, - setExposedVariable, - dataCy, - ...props -}) { - useRenderCount(`TextComponent Main component ${props.id}`); +export const Text = function Text({ height, properties, fireEvent, styles, darkMode, setExposedVariable, dataCy }) { let { textSize, textColor, diff --git a/frontend/src/Editor/Container.jsx b/frontend/src/Editor/Container.jsx index 03abfc68fd..d2d742209c 100644 --- a/frontend/src/Editor/Container.jsx +++ b/frontend/src/Editor/Container.jsx @@ -12,8 +12,8 @@ import { commentsService } from '@/_services'; import config from 'config'; import Spinner from '@/_ui/Spinner'; import { useHotkeys } from 'react-hotkeys-hook'; -import { addComponents, addNewWidgetToTheEditor } from '@/_helpers/appUtils'; -import { useCurrentState, useCurrentStateStore } from '@/_stores/currentStateStore'; +import { addComponents, addNewWidgetToTheEditor, isPDFSupported } from '@/_helpers/appUtils'; +import { useCurrentState } from '@/_stores/currentStateStore'; import { useAppVersionStore } from '@/_stores/appVersionStore'; import { useEditorStore } from '@/_stores/editorStore'; import { useAppInfo } from '@/_stores/appDataStore'; @@ -23,7 +23,6 @@ import _, { cloneDeep, isEmpty } from 'lodash'; import { diff } from 'deep-object-diff'; import DragContainer from './DragContainer'; import { compact, correctBounds } from './gridUtils'; -import { isPDFSupported } from '@/_stores/utils'; import toast from 'react-hot-toast'; import { isOnlyLayoutUpdate, handleLowPriorityWork } from '@/_helpers/editorHelpers'; import GhostWidget from './GhostWidget'; @@ -420,7 +419,7 @@ export const Container = ({ const newChildComponent = addNewWidgetToTheEditor( componentData, {}, - boxes, + { ...boxes, ...childrenBoxes }, {}, item.currentLayout, snapToGrid, @@ -754,28 +753,31 @@ export const Container = ({ return componentWithChildren; }, [components]); - const getContainerProps = React.useCallback((componentId) => { - return { - mode, - snapToGrid, - onComponentClick, - onEvent, - appDefinition, - appDefinitionChanged, - currentState, - appLoading, - zoomLevel, - setSelectedComponent, - removeComponent, - currentLayout, - selectedComponents, - darkMode, - currentPageId, - childComponents: childComponents[componentId], - parentGridWidth: gridWidth, - draggedSubContainer, - }; - }, []); + const getContainerProps = React.useCallback( + (componentId) => { + return { + mode, + snapToGrid, + onComponentClick, + onEvent, + appDefinition, + appDefinitionChanged, + currentState, + appLoading, + zoomLevel, + setSelectedComponent, + removeComponent, + currentLayout, + selectedComponents, + darkMode, + currentPageId, + childComponents: childComponents[componentId], + parentGridWidth: gridWidth, + draggedSubContainer, + }; + }, + [childComponents, selectedComponents, draggedSubContainer] + ); return ( ); diff --git a/frontend/src/Editor/ControlledComponentToRender.jsx b/frontend/src/Editor/ControlledComponentToRender.jsx index a13b27252d..b93d772683 100644 --- a/frontend/src/Editor/ControlledComponentToRender.jsx +++ b/frontend/src/Editor/ControlledComponentToRender.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState, useCallback } from 'react'; import { getComponentToRender } from '@/_helpers/editorHelpers'; import _ from 'lodash'; @@ -23,6 +23,9 @@ export const shouldUpdate = (prevProps, nextProps) => { } } + // Added to render the defaukt child components + if (prevProps?.childComponents === null && nextProps?.childComponents) return false; + return ( deepEqualityCheckusingLoDash(prevProps?.id, nextProps?.id) && deepEqualityCheckusingLoDash(prevProps?.component?.definition, nextProps?.component?.definition) && @@ -33,8 +36,19 @@ export const shouldUpdate = (prevProps, nextProps) => { }; const ComponentWrapper = React.memo(({ componentName, ...props }) => { + const [key, setKey] = useState(Math.random()); + + const resetComponent = useCallback(() => { + setKey(Math.random()); + }, []); + const ComponentToRender = getComponentToRender(componentName); + if (ComponentToRender === null) return; + if (componentName === 'Form') { + return ; + } + return ; }, shouldUpdate); diff --git a/frontend/src/Editor/DragContainer.jsx b/frontend/src/Editor/DragContainer.jsx index 8355f0a678..7a6d6ba9cd 100644 --- a/frontend/src/Editor/DragContainer.jsx +++ b/frontend/src/Editor/DragContainer.jsx @@ -433,7 +433,7 @@ export default function DragContainer({ // Adding the new updates to the macro task queue to unblock UI // setTimeout(() => { // }); - onResizeStop([newBoxs]); + onResizeStop(newBoxs); } else { events.forEach((ev) => { const currentWidget = boxes.find(({ id }) => { diff --git a/frontend/src/Editor/DraggableBox.jsx b/frontend/src/Editor/DraggableBox.jsx index d51387fa8c..19313f3d4e 100644 --- a/frontend/src/Editor/DraggableBox.jsx +++ b/frontend/src/Editor/DraggableBox.jsx @@ -53,6 +53,10 @@ const DraggableBox = React.memo( parentId, getContainerProps, currentPageId, + onComponentOptionChanged = null, + onComponentOptionsChanged = null, + isFromSubContainer = false, + childComponents = null, }) => { const isResizing = useGridStore((state) => state.resizingComponentId === id); const [canDrag, setCanDrag] = useState(true); @@ -222,6 +226,10 @@ const DraggableBox = React.memo( parentId={parentId} getContainerProps={getContainerProps} currentPageId={currentPageId} + onOptionChanged={onComponentOptionChanged} + onOptionsChanged={onComponentOptionsChanged} + isFromSubContainer={isFromSubContainer} + childComponents={childComponents} /> diff --git a/frontend/src/Editor/Editor.jsx b/frontend/src/Editor/Editor.jsx index 1f3af82f68..54c2e5f937 100644 --- a/frontend/src/Editor/Editor.jsx +++ b/frontend/src/Editor/Editor.jsx @@ -19,8 +19,6 @@ import { componentTypes } from './WidgetManager/components'; import { Inspector } from './Inspector/Inspector'; import QueryPanel from './QueryPanel/QueryPanel'; import { - onComponentOptionChanged, - onComponentOptionsChanged, onEvent, onQueryConfirmOrCancel, runQuery, @@ -213,8 +211,6 @@ const EditorComponent = (props) => { const prevAppDefinition = useRef(appDefinition); - const onAppLoadAndPageLoadEventsAreTriggered = useRef(false); - useLayoutEffect(() => { resetAllStores(); }, []); @@ -282,9 +278,9 @@ const EditorComponent = (props) => { } if (mounted && didAppDefinitionChanged && currentPageId) { - // const components = appDefinition?.pages[currentPageId]?.components || {}; + const components = appDefinition?.pages[currentPageId]?.components || {}; - // computeComponentState(components); + computeComponentState(components); if (appDiffOptions?.skipAutoSave === true || appDiffOptions?.entityReferenceUpdated === true) return; @@ -787,7 +783,6 @@ const EditorComponent = (props) => { handleLowPriorityWork(async () => { await runQueries(useDataQueriesStore.getState().dataQueries, editorRef, true); await handleEvent('onPageLoad', currentPageEvents, {}, true); - await handleLowPriorityWork(() => (onAppLoadAndPageLoadEventsAreTriggered.current = true)); }); }); }; @@ -1403,10 +1398,15 @@ const EditorComponent = (props) => { const updateEntityReferences = (appJson, pageId) => { const currentComponents = appJson?.pages?.[pageId]?.components; + const globalSettings = appJson['globalSettings']; let dataQueries = JSON.parse(JSON.stringify(useDataQueriesStore.getState().dataQueries)); let allEvents = JSON.parse(JSON.stringify(useAppDataStore.getState().events)); + const entittyReferencesInGlobalSettings = findAllEntityReferences(globalSettings, [])?.filter( + (entity) => entity && isValidUUID(entity) + ); + const entityReferencesInComponentDefinitions = findAllEntityReferences(currentComponents, [])?.filter( (entity) => entity && isValidUUID(entity) ); @@ -1421,6 +1421,27 @@ const EditorComponent = (props) => { const manager = useResolveStore.getState().referenceMapper; + if (Array.isArray(entittyReferencesInGlobalSettings) && entittyReferencesInGlobalSettings?.length > 0) { + let newGlobalSettings = JSON.parse(JSON.stringify(globalSettings)); + entittyReferencesInGlobalSettings.forEach((entity) => { + const entityrefExists = manager.has(entity); + + if (entityrefExists) { + const value = manager.get(entity); + newGlobalSettings = dfs(newGlobalSettings, entity, value); + } + }); + + const newAppDefinition = produce(appJson, (draft) => { + draft.globalSettings = newGlobalSettings; + }); + + updateEditorState({ + isUpdatingEditorStateInProcess: false, + appDefinition: newAppDefinition, + }); + } + if (Array.isArray(entityReferencesInComponentDefinitions) && entityReferencesInComponentDefinitions?.length > 0) { let newComponentDefinition = JSON.parse(JSON.stringify(currentComponents)); @@ -1433,7 +1454,8 @@ const EditorComponent = (props) => { } }); - const newAppDefinition = produce(appJson, (draft) => { + const appDefinition = useEditorStore.getState().appDefinition; + const newAppDefinition = produce(appDefinition, (draft) => { draft.pages[pageId].components = newComponentDefinition; }); diff --git a/frontend/src/Editor/SubContainer.jsx b/frontend/src/Editor/SubContainer.jsx index c664c87fea..eb999fa412 100644 --- a/frontend/src/Editor/SubContainer.jsx +++ b/frontend/src/Editor/SubContainer.jsx @@ -6,7 +6,12 @@ import { DraggableBox } from './DraggableBox'; import update from 'immutability-helper'; import _, { isEmpty } from 'lodash'; import { componentTypes } from './WidgetManager/components'; -import { addNewWidgetToTheEditor, onComponentOptionChanged, onComponentOptionsChanged } from '@/_helpers/appUtils'; +import { + addNewWidgetToTheEditor, + onComponentOptionChanged, + onComponentOptionsChanged, + isPDFSupported, +} from '@/_helpers/appUtils'; import { resolveWidgetFieldValue } from '@/_helpers/utils'; import { toast } from 'react-hot-toast'; import { restrictedWidgetsObj } from '@/Editor/WidgetManager/restrictedWidgetsConfig'; @@ -18,7 +23,6 @@ import { useEditorStore } from '@/_stores/editorStore'; import { diff } from 'deep-object-diff'; // eslint-disable-next-line import/namespace import { useGridStore, useResizingComponentId } from '@/_stores/gridStore'; -import { isPDFSupported } from '@/_stores/utils'; import GhostWidget from './GhostWidget'; export const SubContainer = ({ @@ -515,6 +519,7 @@ export const SubContainer = ({ isMultipleComponentsSelected={selectedComponents?.length > 1 ? true : false} exposedVariables={exposedVariables ?? {}} getContainerProps={getContainerProps} + isFromSubContainer={true} /> ); diff --git a/frontend/src/_helpers/appUtils.js b/frontend/src/_helpers/appUtils.js index e1ddd1bc2c..c9fb7d7a1f 100644 --- a/frontend/src/_helpers/appUtils.js +++ b/frontend/src/_helpers/appUtils.js @@ -622,7 +622,11 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) { const key = resolveReferences(event.key, getCurrentState(), undefined, customVariables); const customAppVariables = { ...getCurrentState().variables }; delete customAppVariables[key]; - // useResolveStore.getState().actions.removeAppSuggestions(key); + useResolveStore.getState().actions.removeAppSuggestions([`variables.${key}`]); + useResolveStore + .getState() + .actions.updateResolvedRefsOfHints([{ hint: 'variables', newRef: customAppVariables }]); + return useCurrentStateStore.getState().actions.setCurrentState({ variables: customAppVariables, }); @@ -635,9 +639,14 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) { ...getCurrentState().page.variables, [key]: value, }; + useResolveStore.getState().actions.addAppSuggestions({ - variables: customPageVariables, + page: { + ...getCurrentState().page, + variables: customPageVariables, + }, }); + return useCurrentStateStore.getState().actions.setCurrentState({ page: { ...getCurrentState().page, @@ -657,7 +666,23 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) { case 'unset-page-variable': { const key = resolveReferences(event.key, getCurrentState(), undefined, customVariables); const customPageVariables = _.omit(getCurrentState().page.variables, key); - // useResolveStore.getState().actions.removeAppSuggestions(key); + + useResolveStore.getState().actions.removeAppSuggestions([`page.variables.${key}`]); + + const pageRef = { + page: { + ...getCurrentState().page, + variables: customPageVariables, + }, + }; + + const toUpdateRefs = [ + { hint: 'page', newRef: pageRef }, + { hint: 'page.variables', newRef: customPageVariables }, + ]; + + useResolveStore.getState().actions.updateResolvedRefsOfHints(toUpdateRefs); + return useCurrentStateStore.getState().actions.setCurrentState({ page: { ...getCurrentState().page, @@ -2078,3 +2103,68 @@ export const removeFunctionObjects = (obj) => { } return obj; }; + +export function isPDFSupported() { + const browser = getBrowserUserAgent(); + + if (!browser) { + return true; + } + + const isChrome = browser.name === 'Chrome' && browser.major >= 92; + const isEdge = browser.name === 'Edge' && browser.major >= 92; + const isSafari = browser.name === 'Safari' && browser.major >= 15 && browser.minor >= 4; // Handle minor version check for Safari + const isFirefox = browser.name === 'Firefox' && browser.major >= 90; + + console.log('browser--', browser, isChrome || isEdge || isSafari || isFirefox); + + return isChrome || isEdge || isSafari || isFirefox; +} + +function getBrowserUserAgent(userAgent) { + var regexps = { + Chrome: [/Chrome\/(\S+)/], + Firefox: [/Firefox\/(\S+)/], + MSIE: [/MSIE (\S+);/], + Opera: [/Opera\/.*?Version\/(\S+)/ /* Opera 10 */, /Opera\/(\S+)/ /* Opera 9 and older */], + Safari: [/Version\/(\S+).*?Safari\//], + }, + re, + m, + browser, + version; + + if (userAgent === undefined) userAgent = navigator.userAgent; + + for (browser in regexps) + while ((re = regexps[browser].shift())) + if ((m = userAgent.match(re))) { + version = m[1].match(new RegExp('[^.]+(?:.[^.]+){0,1}'))[0]; + const { major, minor } = extractVersion(version); + return { + name: browser, + major, + minor, + }; + } + + return null; +} + +function extractVersion(versionStr) { + // Split the string by "." + const parts = versionStr.split('.'); + + // Check for valid input + if (parts.length === 0 || parts.some((part) => isNaN(part))) { + return { major: null, minor: null }; + } + + // Extract major version + const major = parseInt(parts[0], 10); + + // Handle minor version (default to 0) + const minor = parts.length > 1 ? parseInt(parts[1], 10) : 0; + + return { major, minor }; +} diff --git a/frontend/src/_helpers/editorHelpers.js b/frontend/src/_helpers/editorHelpers.js index 00649a0750..5ffbcb00a4 100644 --- a/frontend/src/_helpers/editorHelpers.js +++ b/frontend/src/_helpers/editorHelpers.js @@ -49,6 +49,7 @@ import { Icon } from '@/Editor/Components/Icon'; import { Link } from '@/Editor/Components/Link'; import { Form } from '@/Editor/Components/Form/Form'; import { BoundedBox } from '@/Editor/Components/BoundedBox/BoundedBox'; +import { isPDFSupported } from '@/_helpers/appUtils'; export function memoizeFunction(func) { const cache = new Map(); @@ -119,8 +120,13 @@ export const AllComponents = { Form, BoundedBox, }; +if (isPDFSupported()) { + AllComponents.PDF = await import('@/Editor/Components/PDF').then((module) => module.PDF); +} export const getComponentToRender = (componentName) => { + const shouldHideWidget = componentName === 'PDF' && !isPDFSupported(); + if (shouldHideWidget) return null; return AllComponents[componentName]; }; diff --git a/frontend/src/_helpers/utils.js b/frontend/src/_helpers/utils.js index 9ef51e0e57..bd63b34908 100644 --- a/frontend/src/_helpers/utils.js +++ b/frontend/src/_helpers/utils.js @@ -3,18 +3,17 @@ import moment from 'moment'; import _, { isEmpty } from 'lodash'; import axios from 'axios'; import JSON5 from 'json5'; -import { previewQuery, executeAction } from '@/_helpers/appUtils'; +import { executeAction } from '@/_helpers/appUtils'; import { toast } from 'react-hot-toast'; import { authenticationService } from '@/_services/authentication.service'; import { useDataQueriesStore } from '@/_stores/dataQueriesStore'; -import { getCurrentState, useCurrentState } from '@/_stores/currentStateStore'; +import { getCurrentState } from '@/_stores/currentStateStore'; import { getWorkspaceIdOrSlugFromURL, getSubpath, returnWorkspaceIdIfNeed } from './routes'; import { getCookie, eraseCookie } from '@/_helpers/cookie'; import { staticDataSources } from '@/Editor/QueryManager/constants'; -import { resolveReferences as newResolver } from '@/Editor/CodeEditor/utils'; -import { useResolveStore } from '@/_stores/resolverStore'; +const reservedKeyword = ['app', 'window']; //Keywords that slows down the app export function findProp(obj, prop, defval) { if (typeof defval === 'undefined') defval = null; prop = prop.split('.'); @@ -160,7 +159,7 @@ export function resolveReferences( forPreviewBox = false ) { if (object === '{{{}}}') return ''; - const reservedKeyword = ['app', 'window']; //Keywords that slows down the app + object = _.clone(object); const objectType = typeof object; let error; @@ -329,18 +328,7 @@ export const serializeNestedObjectToQueryParams = function (obj, prefix) { export function resolveWidgetFieldValue(prop, _default = [], customResolveObjects = {}) { const widgetFieldValue = prop; - const isStoreAndEditorReady = useResolveStore.getState().updateStoreState && useCurrentState.getState().isEditorReady; - try { - if (isStoreAndEditorReady) { - const [_, _error, resolveValue] = newResolver(widgetFieldValue?.value); - - if (_error) { - return _default; - } - - return resolveValue; - } const state = getCurrentState(); return resolveReferences(widgetFieldValue, state, _default, customResolveObjects); } catch (err) { @@ -435,6 +423,19 @@ export function validateEmail(email) { // eslint-disable-next-line no-unused-vars export async function executeMultilineJS(_ref, code, queryId, isPreview, mode = '', parameters = {}) { + if ([...reservedKeyword, 'this'].some((keyword) => code.includes(keyword))) { + const message = `Code contains ${reservedKeyword.join(' or ')} or this keywords`; + const description = 'Cannot resolve code with reserved keywords in it. Please remove them and try again.'; + + return { + status: 'failed', + data: { + message, + description, + }, + }; + } + const currentState = getCurrentState(); let result = {}, error = null; diff --git a/frontend/src/_hooks/useRenderCount.js b/frontend/src/_hooks/useRenderCount.js deleted file mode 100644 index c07b5734e3..0000000000 --- a/frontend/src/_hooks/useRenderCount.js +++ /dev/null @@ -1,11 +0,0 @@ -import { useRef, useEffect } from 'react'; - -function useRenderCount(componentName) { - const renderCountRef = useRef(0); - - renderCountRef.current++; - - return renderCountRef.current; -} - -export default useRenderCount; diff --git a/frontend/src/_stores/utils.js b/frontend/src/_stores/utils.js index 07899b3341..0f13001789 100644 --- a/frontend/src/_stores/utils.js +++ b/frontend/src/_stores/utils.js @@ -333,70 +333,6 @@ function toRemoveExposedvariablesFromComponentDiff(object) { return copy; } -export function isPDFSupported() { - const browser = getBrowserUserAgent(); - - if (!browser) { - return true; - } - - const isChrome = browser.name === 'Chrome' && browser.major >= 92; - const isEdge = browser.name === 'Edge' && browser.major >= 92; - const isSafari = browser.name === 'Safari' && browser.major >= 15 && browser.minor >= 4; // Handle minor version check for Safari - const isFirefox = browser.name === 'Firefox' && browser.major >= 90; - - console.log('browser--', browser, isChrome || isEdge || isSafari || isFirefox); - - return isChrome || isEdge || isSafari || isFirefox; -} - -export function getBrowserUserAgent(userAgent) { - var regexps = { - Chrome: [/Chrome\/(\S+)/], - Firefox: [/Firefox\/(\S+)/], - MSIE: [/MSIE (\S+);/], - Opera: [/Opera\/.*?Version\/(\S+)/ /* Opera 10 */, /Opera\/(\S+)/ /* Opera 9 and older */], - Safari: [/Version\/(\S+).*?Safari\//], - }, - re, - m, - browser, - version; - - if (userAgent === undefined) userAgent = navigator.userAgent; - - for (browser in regexps) - while ((re = regexps[browser].shift())) - if ((m = userAgent.match(re))) { - version = m[1].match(new RegExp('[^.]+(?:.[^.]+){0,1}'))[0]; - const { major, minor } = extractVersion(version); - return { - name: browser, - major, - minor, - }; - } - - return null; -} - -function extractVersion(versionStr) { - // Split the string by "." - const parts = versionStr.split('.'); - - // Check for valid input - if (parts.length === 0 || parts.some((part) => isNaN(part))) { - return { major: null, minor: null }; - } - - // Extract major version - const major = parseInt(parts[0], 10); - - // Handle minor version (default to 0) - const minor = parts.length > 1 ? parseInt(parts[1], 10) : 0; - - return { major, minor }; -} export function createReferencesLookup(refState, forQueryParams = false, initalLoad = false) { if (forQueryParams && _.isEmpty(refState['parameters'])) { return { suggestionList: [] }; @@ -466,7 +402,7 @@ export function createReferencesLookup(refState, forQueryParams = false, initalL if (_type === 'Array') { map.set(newPath, { type: _type }); - if (path.startsWith('queries') && key === 'data' && value.length > 2) { + if (path.startsWith('queries') && key === 'data' && value.length > 2000) { // do nothing } else { buildMap(value, newPath);