mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-24 09:28:31 +00:00
Merge branch 'feat/grid-appbuilder-improvement' into builder-performance-platform-part/release
This commit is contained in:
commit
caac572341
17 changed files with 252 additions and 162 deletions
|
|
@ -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) => {
|
|||
<ControlledComponentToRender
|
||||
componentName={component.component}
|
||||
onComponentClick={onComponentClick}
|
||||
onComponentOptionChanged={onComponentOptionChanged}
|
||||
onEvent={onEvent}
|
||||
id={id}
|
||||
paramUpdated={paramUpdated}
|
||||
width={width}
|
||||
changeCanDrag={changeCanDrag}
|
||||
onComponentOptionsChanged={onComponentOptionsChanged}
|
||||
onComponentOptionChanged={isFromSubContainer ? onOptionChanged : onComponentOptionChanged}
|
||||
onComponentOptionsChanged={isFromSubContainer ? onOptionsChanged : onComponentOptionsChanged}
|
||||
setExposedVariable={(variable, value) =>
|
||||
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}
|
||||
/>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@
|
|||
|
||||
.cm-tooltip-autocomplete {
|
||||
@extend .cm-base-autocomplete;
|
||||
top: 0px !important;
|
||||
top: content-box !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
|||
<Box
|
||||
{...props}
|
||||
component={item}
|
||||
id={id}
|
||||
id={index}
|
||||
width={width}
|
||||
height={item.defaultSize.height}
|
||||
mode={mode}
|
||||
|
|
@ -297,6 +301,9 @@ export const Form = function Form(props) {
|
|||
// customResolvables={customResolvables}
|
||||
parentId={id}
|
||||
getContainerProps={getContainerProps}
|
||||
onOptionChanged={onComponentOptionChangedForSubcontainer}
|
||||
onOptionsChanged={onComponentOptionsChanged}
|
||||
isFromSubContainer={true}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<ContainerWrapper
|
||||
|
|
@ -860,6 +862,7 @@ export const Container = ({
|
|||
getContainerProps={getContainerProps}
|
||||
isVersionReleased={isVersionReleased}
|
||||
currentPageId={currentPageId}
|
||||
childComponents={childComponents[id]}
|
||||
/>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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 <ComponentToRender key={key} resetComponent={resetComponent} {...props} />;
|
||||
}
|
||||
|
||||
return <ComponentToRender {...props} />;
|
||||
}, shouldUpdate);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }) => {
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
/>
|
||||
</Sentry.ErrorBoundary>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
/>
|
||||
</SubWidgetWrapper>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
import { useRef, useEffect } from 'react';
|
||||
|
||||
function useRenderCount(componentName) {
|
||||
const renderCountRef = useRef(0);
|
||||
|
||||
renderCountRef.current++;
|
||||
|
||||
return renderCountRef.current;
|
||||
}
|
||||
|
||||
export default useRenderCount;
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue