mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-24 09:28:31 +00:00
Merge branch 'fix/appbuilder-stability-and-ui' of https://github.com/ToolJet/ToolJet into fix/appbuilder-stability-and-ui
This commit is contained in:
commit
966d515718
30 changed files with 359 additions and 218 deletions
|
|
@ -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 } from '@/_stores/currentStateStore';
|
||||
import { useCurrentState, useCurrentStateStore } from '@/_stores/currentStateStore';
|
||||
import { useAppDataStore } from '@/_stores/appDataStore';
|
||||
import _ from 'lodash';
|
||||
|
||||
|
|
@ -97,6 +97,8 @@ const BoxUI = (props) => {
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const isEditorReady = useCurrentStateStore((state) => state.isEditorReady);
|
||||
|
||||
return (
|
||||
<OverlayTrigger
|
||||
placement={inCanvas ? 'auto' : 'top'}
|
||||
|
|
@ -183,6 +185,7 @@ const BoxUI = (props) => {
|
|||
currentPageId={currentPageId}
|
||||
getContainerProps={component.component === 'Form' ? getContainerProps : null}
|
||||
childComponents={childComponents}
|
||||
isEditorReady={isEditorReady}
|
||||
/>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import CodeHinter from './CodeHinter';
|
|||
import { CodeHinterContext } from '../CodeBuilder/CodeHinterContext';
|
||||
import { createReferencesLookup } from '@/_stores/utils';
|
||||
import { PreviewBox } from './PreviewBox';
|
||||
import { removeNestedDoubleCurlyBraces } from '@/_helpers/utils';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
const langSupport = Object.freeze({
|
||||
|
|
@ -87,7 +88,7 @@ const MultiLineCodeEditor = (props) => {
|
|||
|
||||
const inputStr = currentString.join(' ');
|
||||
const currentCurosorPos = currentCursor;
|
||||
const nearestSubstring = findNearestSubstring(inputStr, currentCurosorPos).replace(/{{|}}/g, '');
|
||||
const nearestSubstring = removeNestedDoubleCurlyBraces(findNearestSubstring(inputStr, currentCurosorPos));
|
||||
|
||||
let JSLangHints = [];
|
||||
if (lang === 'javascript') {
|
||||
|
|
|
|||
|
|
@ -431,8 +431,6 @@ const PreviewCodeBlock = ({ code, isExpectValue = false, isLargeDataset }) => {
|
|||
value={prettyPrintedJson}
|
||||
displayDataTypes={false}
|
||||
displaySize={false}
|
||||
maxDisplayLength={50}
|
||||
// defaultInspectDepth={isLargeDataset ? 1 : 2}
|
||||
displayObjectSize={false}
|
||||
enableClipboard={false}
|
||||
rootName={false}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import { getAutocompletion } from './autocompleteExtensionConfig';
|
|||
import ErrorBoundary from '../ErrorBoundary';
|
||||
import CodeHinter from './CodeHinter';
|
||||
import { EditorContext } from '../Context/EditorContextWrapper';
|
||||
import { removeNestedDoubleCurlyBraces } from '@/_helpers/utils';
|
||||
|
||||
const SingleLineCodeEditor = ({ suggestions, componentName, fieldMeta = {}, componentId, ...restProps }) => {
|
||||
const { initialValue, onChange, enablePreview = true, portalProps } = restProps;
|
||||
|
|
@ -156,7 +157,7 @@ const EditorInput = ({
|
|||
const lastBracesFromPos = queryInput.lastIndexOf('{{', currentCursorPos);
|
||||
currentWord = queryInput.substring(lastBracesFromPos, currentCursorPos);
|
||||
//remove curly braces from the current word as will append it later
|
||||
currentWord = currentWord.replace(/{{|}}/g, '');
|
||||
currentWord = removeNestedDoubleCurlyBraces(currentWord);
|
||||
}
|
||||
|
||||
if (currentWord.includes(' ')) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { removeNestedDoubleCurlyBraces } from '@/_helpers/utils';
|
||||
import { getLastDepth, getLastSubstring } from './autocompleteUtils';
|
||||
|
||||
export const getAutocompletion = (input, fieldType, hints, totalReferences = 1, originalQueryInput = null) => {
|
||||
if (!input.startsWith('{{') || !input.endsWith('}}')) return [];
|
||||
|
||||
const actualInput = input.replace(/{{|}}/g, '');
|
||||
const actualInput = removeNestedDoubleCurlyBraces(input);
|
||||
|
||||
let JSLangHints = [];
|
||||
|
||||
|
|
@ -58,7 +59,7 @@ export const getAutocompletion = (input, fieldType, hints, totalReferences = 1,
|
|||
if (autoSuggestionList.length === 0 && !cm.hint.includes(actualInput)) return true;
|
||||
});
|
||||
|
||||
const searchInput = input.replace(/{{|}}/g, '');
|
||||
const searchInput = removeNestedDoubleCurlyBraces(input);
|
||||
const suggestions = generateHints(
|
||||
[...jsHints, ...autoSuggestionList],
|
||||
totalReferences,
|
||||
|
|
@ -137,7 +138,7 @@ export const generateHints = (hints, totalReferences = 1, input, searchText) =>
|
|||
changes: pickedCompletionConfig,
|
||||
};
|
||||
|
||||
const actualInput = doc.toString().replace(/{{|}}/g, '');
|
||||
const actualInput = removeNestedDoubleCurlyBraces(doc.toString());
|
||||
|
||||
if (actualInput.length === 0) {
|
||||
dispatchConfig.selection = {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,11 @@ import _, { isEmpty } from 'lodash';
|
|||
import { useCurrentStateStore } from '@/_stores/currentStateStore';
|
||||
import { any } from 'superstruct';
|
||||
import { generateSchemaFromValidationDefinition, validate } from '../component-properties-validation';
|
||||
import { hasCircularDependency, resolveReferences as olderResolverMethod } from '@/_helpers/utils';
|
||||
import {
|
||||
hasCircularDependency,
|
||||
resolveReferences as olderResolverMethod,
|
||||
removeNestedDoubleCurlyBraces,
|
||||
} from '@/_helpers/utils';
|
||||
import { validateMultilineCode } from '@/_helpers/utility';
|
||||
|
||||
const acorn = require('acorn');
|
||||
|
|
@ -191,7 +195,7 @@ const resolveMultiDynamicReferences = (code, lookupTable, queryHasJSCode) => {
|
|||
|
||||
if (!isJSCodeResolver) {
|
||||
allDynamicVariables.forEach((variable) => {
|
||||
const variableToResolve = variable.replace(/{{|}}/g, '').trim();
|
||||
const variableToResolve = removeNestedDoubleCurlyBraces(variable);
|
||||
|
||||
const { toResolveReference } = inferJSExpAndReferences(variableToResolve, lookupTable.hints);
|
||||
|
||||
|
|
@ -207,8 +211,7 @@ const resolveMultiDynamicReferences = (code, lookupTable, queryHasJSCode) => {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
const variableToResolve = code.replace(/{{|}}/g, '').trim();
|
||||
|
||||
const variableToResolve = removeNestedDoubleCurlyBraces(code);
|
||||
const [resolvedCode] = resolveCode(variableToResolve, {}, true, [], true);
|
||||
|
||||
resolvedValue = typeof resolvedCode === 'string' ? resolvedValue.replace(code, resolvedCode) : resolvedCode;
|
||||
|
|
@ -272,7 +275,7 @@ export const resolveReferences = (query, validationSchema, customResolvers = {})
|
|||
if (useJSResolvers) {
|
||||
resolvedValue = resolveMultiDynamicReferences(query, lookupTable, queryHasJSCode);
|
||||
} else {
|
||||
let value = query?.replace(/{{|}}/g, '').trim();
|
||||
let value = removeNestedDoubleCurlyBraces(query);
|
||||
|
||||
if (value.startsWith('#') || value.includes('table-')) {
|
||||
value = JSON.stringify(value);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ 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 } = props;
|
||||
const { height, properties, styles, fireEvent, id, dataCy, setExposedVariable, setExposedVariables, isEditorReady } =
|
||||
props;
|
||||
|
||||
const {
|
||||
backgroundColor,
|
||||
textColor,
|
||||
|
|
@ -93,31 +95,33 @@ export const Button = function Button(props) {
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
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);
|
||||
},
|
||||
};
|
||||
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);
|
||||
},
|
||||
};
|
||||
|
||||
setExposedVariables(exposedVariables);
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disable]);
|
||||
}, [disable, isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setLoading', async function (loading) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export const Chart = function Chart({
|
|||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
dataCy,
|
||||
isEditorReady,
|
||||
}) {
|
||||
const [loadingState, setLoadingState] = useState(false);
|
||||
|
||||
|
|
@ -80,8 +81,9 @@ export const Chart = function Chart({
|
|||
xAxisTitle: xAxisTitle,
|
||||
yAxisTitle: yAxisTitle,
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
}, [JSON.stringify(chartLayout, chartTitle)]);
|
||||
if (isEditorReady) setExposedVariables(exposedVariables);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify(chartLayout, chartTitle), isEditorReady]);
|
||||
|
||||
const layout = {
|
||||
width: width - 4,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ export const Checkbox = ({
|
|||
component,
|
||||
validate,
|
||||
width,
|
||||
isEditorReady,
|
||||
}) => {
|
||||
const defaultValueFromProperties = properties.defaultValue ?? false;
|
||||
const [defaultValue, setDefaultValue] = useState(defaultValueFromProperties);
|
||||
|
|
@ -68,10 +69,10 @@ export const Checkbox = ({
|
|||
setDefaultValue(defaultValueFromProperties);
|
||||
setChecked(defaultValueFromProperties);
|
||||
setValue(defaultValueFromProperties);
|
||||
setExposedVariables(exposedVariables);
|
||||
if (isEditorReady) setExposedVariables(exposedVariables);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [defaultValueFromProperties]);
|
||||
}, [defaultValueFromProperties, isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
if (disable !== disabledState) setDisable(properties.disabledState);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export const ColorPicker = function ({
|
|||
height,
|
||||
fireEvent,
|
||||
dataCy,
|
||||
isEditorReady,
|
||||
}) {
|
||||
const { visibility, boxShadow } = styles;
|
||||
const defaultColor = properties.defaultColor;
|
||||
|
|
@ -57,8 +58,9 @@ export const ColorPicker = function ({
|
|||
selectedColorRGB: hexToRgb(colorCode),
|
||||
selectedColorRGBA: hexToRgba(colorCode),
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
fireEvent('onChange');
|
||||
}
|
||||
} else {
|
||||
|
|
@ -67,14 +69,15 @@ export const ColorPicker = function ({
|
|||
selectedColorRGB: undefined,
|
||||
selectedColorRGBA: undefined,
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
fireEvent('onChange');
|
||||
setColor('Invalid Color');
|
||||
}
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setColor]);
|
||||
}, [setColor, isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
let exposedVariables = {};
|
||||
|
|
@ -85,8 +88,9 @@ export const ColorPicker = function ({
|
|||
selectedColorRGB: hexToRgb(defaultColor),
|
||||
selectedColorRGBA: hexToRgba(defaultColor),
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
setColor(defaultColor);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -95,12 +99,13 @@ export const ColorPicker = function ({
|
|||
selectedColorRGB: undefined,
|
||||
selectedColorRGBA: undefined,
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
setColor(`Invalid Color`);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [defaultColor]);
|
||||
}, [defaultColor, isEditorReady]);
|
||||
|
||||
const handleColorChange = (colorCode) => {
|
||||
let exposedVariables = {};
|
||||
|
|
@ -113,7 +118,9 @@ export const ColorPicker = function ({
|
|||
selectedColorRGB: `rgb(${r},${g},${b})`,
|
||||
selectedColorRGBA: `rgb(${r},${g},${b},${a})`,
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
fireEvent('onChange');
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ export const DropdownV2 = ({
|
|||
component,
|
||||
exposedVariables,
|
||||
dataCy,
|
||||
isEditorReady,
|
||||
}) => {
|
||||
const {
|
||||
label,
|
||||
|
|
@ -225,8 +226,11 @@ export const DropdownV2 = ({
|
|||
setIsDropdownDisabled(value);
|
||||
},
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
}, []);
|
||||
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
}, [isEditorReady]);
|
||||
|
||||
const customStyles = {
|
||||
container: (base) => ({
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ export const Form = function Form(props) {
|
|||
getContainerProps,
|
||||
containerProps,
|
||||
childComponents,
|
||||
isEditorReady,
|
||||
} = props;
|
||||
|
||||
const { events: allAppEvents } = useAppInfo();
|
||||
|
|
@ -132,7 +133,9 @@ export const Form = function Form(props) {
|
|||
...(!advanced && { children: formattedChildData }),
|
||||
};
|
||||
|
||||
setExposedVariables(exposedVariables);
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
return setValidation(childValidation);
|
||||
}
|
||||
|
||||
|
|
@ -158,9 +161,10 @@ export const Form = function Form(props) {
|
|||
isValid: childValidation,
|
||||
};
|
||||
setValidation(childValidation);
|
||||
setExposedVariables(exposedVariables);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [childrenData, childComponents, advanced, JSON.stringify(JSONSchema)]);
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
} // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [childrenData, childComponents, advanced, JSON.stringify(JSONSchema), isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
const childIds = Object.keys(childrenData);
|
||||
|
|
|
|||
|
|
@ -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,9 +40,11 @@ export const Icon = ({
|
|||
fireEvent('onClick');
|
||||
},
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setIconVisibility]);
|
||||
}, [setIconVisibility, isEditorReady]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import React, { useRef } from 'react';
|
|||
import { KanbanBoard } from './KanbanBoard';
|
||||
|
||||
export const Kanban = (props) => {
|
||||
const { height, width, properties, styles, id, mode } = props;
|
||||
const { height, width, properties, styles, id, mode, isEditorReady } = props;
|
||||
const { showDeleteButton } = properties;
|
||||
const { visibility, disabledState, boxShadow } = styles;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ const dropAnimation = {
|
|||
const TRASH_ID = 'void';
|
||||
|
||||
export function KanbanBoard({ widgetHeight, kanbanProps, parentRef, mode, id }) {
|
||||
const { properties, fireEvent, setExposedVariable, setExposedVariables, styles } = kanbanProps;
|
||||
const { properties, fireEvent, setExposedVariable, setExposedVariables, styles, isEditorReady } = kanbanProps;
|
||||
const { columnData, cardData, cardWidth, cardHeight, showDeleteButton, enableAddCard } = properties;
|
||||
const { accentColor } = styles;
|
||||
const [lastSelectedCard, setLastSelectedCard] = useState({});
|
||||
|
|
@ -112,17 +112,20 @@ export function KanbanBoard({ widgetHeight, kanbanProps, parentRef, mode, id })
|
|||
cardDataAsObj[cardId] = value;
|
||||
const diffKeys = Object.keys(diff(cardToBeUpdated, value));
|
||||
if (lastSelectedCard?.id === cardId) {
|
||||
setExposedVariables({
|
||||
lastSelectedCard: cardDataAsObj[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),
|
||||
});
|
||||
}
|
||||
|
||||
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));
|
||||
|
|
@ -130,7 +133,7 @@ export function KanbanBoard({ widgetHeight, kanbanProps, parentRef, mode, id })
|
|||
}
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [lastSelectedCard, JSON.stringify(cardDataAsObj)]);
|
||||
}, [lastSelectedCard, JSON.stringify(cardDataAsObj), isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('moveCard', async function (cardId, columnId) {
|
||||
|
|
@ -169,11 +172,13 @@ export function KanbanBoard({ widgetHeight, kanbanProps, parentRef, mode, id })
|
|||
...items,
|
||||
[columnId]: [...items[columnId], cardDetails.id],
|
||||
}));
|
||||
setExposedVariables({ lastAddedCard: { ...cardDetails }, updatedCardData: getData(cardDataAsObj) });
|
||||
if (isEditorReady) {
|
||||
setExposedVariables({ lastAddedCard: { ...cardDetails }, updatedCardData: getData(cardDataAsObj) });
|
||||
}
|
||||
fireEvent('onCardAdded');
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [items, JSON.stringify(cardDataAsObj)]);
|
||||
}, [items, JSON.stringify(cardDataAsObj), isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('deleteCard', async function (cardId) {
|
||||
|
|
@ -186,11 +191,13 @@ export function KanbanBoard({ widgetHeight, kanbanProps, parentRef, mode, id })
|
|||
...items,
|
||||
[columnId]: items[columnId].filter((id) => id !== cardId),
|
||||
}));
|
||||
setExposedVariables({ lastRemovedCard: { ...deletedCard }, updatedCardData: getData(cardDataAsObj) });
|
||||
if (isEditorReady) {
|
||||
setExposedVariables({ lastRemovedCard: { ...deletedCard }, updatedCardData: getData(cardDataAsObj) });
|
||||
}
|
||||
fireEvent('onCardRemoved');
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [showModal, JSON.stringify(cardDataAsObj)]);
|
||||
}, [showModal, JSON.stringify(cardDataAsObj), isEditorReady]);
|
||||
|
||||
const [clonedItems, setClonedItems] = useState(null);
|
||||
const sensors = useSensors(
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ export const Listview = function Listview({
|
|||
darkMode,
|
||||
dataCy,
|
||||
childComponents,
|
||||
isEditorReady,
|
||||
}) {
|
||||
const fallbackProperties = { height: 100, showBorder: false, data: [] };
|
||||
const fallbackStyles = { visibility: true, disabledState: false };
|
||||
|
|
@ -58,7 +59,9 @@ export const Listview = function Listview({
|
|||
selectedRecordId: index,
|
||||
selectedRecord: childrenData[index],
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
fireEvent('onRecordClicked');
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}
|
||||
|
|
@ -68,7 +71,9 @@ export const Listview = function Listview({
|
|||
selectedRowId: index,
|
||||
selectedRow: childrenData[index],
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
fireEvent('onRowClicked');
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}
|
||||
|
|
@ -85,16 +90,20 @@ export const Listview = function Listview({
|
|||
data: removeFunctionObjects(childrenDataClone),
|
||||
children: childrenData,
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
if (selectedRowIndex != undefined) {
|
||||
const exposedVariables = {
|
||||
selectedRowId: selectedRowIndex,
|
||||
selectedRow: childrenData[selectedRowIndex],
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [childrenData, childComponents]);
|
||||
}, [childrenData, childComponents, isEditorReady]);
|
||||
|
||||
function filterComponents() {
|
||||
if (!childrenData || childrenData.length === 0) {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export const Modal = function Modal({
|
|||
dataCy,
|
||||
height,
|
||||
mode,
|
||||
isEditorReady,
|
||||
}) {
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
|
||||
|
|
@ -45,7 +46,6 @@ export const Modal = function Modal({
|
|||
} = styles;
|
||||
const parentRef = useRef(null);
|
||||
const controlBoxRef = useRef(null);
|
||||
const isInitialRender = useRef(true);
|
||||
|
||||
const title = properties.title ?? '';
|
||||
const size = properties.size ?? 'lg';
|
||||
|
|
@ -77,31 +77,43 @@ export const Modal = function Modal({
|
|||
setExposedVariable('show', false);
|
||||
},
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setShowModal]);
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
} // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setShowModal, isEditorReady]);
|
||||
|
||||
const isInitialRender = useRef(true);
|
||||
const prevShowValue = useRef(exposedVariables.show);
|
||||
const shouldFireCloseEvent = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
const canShowModal = exposedVariables.show ?? false;
|
||||
|
||||
if (isInitialRender.current) {
|
||||
isInitialRender.current = false;
|
||||
return;
|
||||
} else if (!canShowModal && prevShowValue.current) {
|
||||
shouldFireCloseEvent.current = true;
|
||||
}
|
||||
const canShowModal = exposedVariables.show ?? false;
|
||||
fireEvent(!canShowModal && 'onClose');
|
||||
setShowModal(exposedVariables.show ?? false);
|
||||
const inputRef = document?.getElementsByClassName('tj-text-input-widget')?.[0];
|
||||
inputRef?.blur();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [exposedVariables.show]);
|
||||
|
||||
setShowModal(canShowModal);
|
||||
prevShowValue.current = canShowModal;
|
||||
|
||||
// return () => {
|
||||
// if (shouldFireCloseEvent.current) {
|
||||
// fireEvent('onClose');
|
||||
// shouldFireCloseEvent.current = false;
|
||||
// }
|
||||
// };
|
||||
}, [exposedVariables.show]);
|
||||
function hideModal() {
|
||||
setShowModal(false);
|
||||
setExposedVariable('show', false);
|
||||
fireEvent('onClose');
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const handleModalOpen = () => {
|
||||
fireEvent('onOpen');
|
||||
setExposedVariable('show', true);
|
||||
const canvasElement = document.getElementsByClassName('canvas-area')[0];
|
||||
const modalBackdropEl = document.getElementsByClassName('modal-backdrop')[0];
|
||||
const realCanvasEl = document.getElementsByClassName('real-canvas')[0];
|
||||
|
|
@ -222,8 +234,8 @@ export const Modal = function Modal({
|
|||
|
||||
event.stopPropagation();
|
||||
setShowModal(true);
|
||||
setExposedVariable('show', true);
|
||||
fireEvent('onOpen');
|
||||
// setExposedVariable('show', true);
|
||||
// fireEvent('onOpen');
|
||||
}}
|
||||
data-cy={`${dataCy}-launch-button`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export const Multiselect = function Multiselect({
|
|||
darkMode,
|
||||
fireEvent,
|
||||
dataCy,
|
||||
isEditorReady,
|
||||
}) {
|
||||
const { label, value, values, display_values, showAllOption } = properties;
|
||||
const { borderRadius, visibility, disabledState, boxShadow } = styles;
|
||||
|
|
@ -124,10 +125,11 @@ export const Multiselect = function Multiselect({
|
|||
},
|
||||
};
|
||||
|
||||
setExposedVariables(exposedVariables);
|
||||
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selected, setSelected]);
|
||||
}, [selected, setSelected, isEditorReady]);
|
||||
|
||||
const filterOptions = (options, filter) => {
|
||||
setSearched(filter);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export const MultiselectV2 = ({
|
|||
darkMode,
|
||||
fireEvent,
|
||||
validate,
|
||||
width,
|
||||
isEditorReady,
|
||||
}) => {
|
||||
let {
|
||||
label,
|
||||
|
|
@ -177,8 +177,10 @@ export const MultiselectV2 = ({
|
|||
setIsMultiSelectDisabled(value);
|
||||
},
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
}, []);
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
}, [isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
// Expose selectOption
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export const RadioButton = function RadioButton({
|
|||
setExposedVariables,
|
||||
darkMode,
|
||||
dataCy,
|
||||
isEditorReady,
|
||||
}) {
|
||||
const { label, value, values, display_values } = properties;
|
||||
const { visibility, disabledState, activeColor, boxShadow } = styles;
|
||||
|
|
@ -43,9 +44,10 @@ export const RadioButton = function RadioButton({
|
|||
onSelect(option);
|
||||
},
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [value, setValue]);
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
} // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [value, setValue, isEditorReady]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ export function Table({
|
|||
setProperty,
|
||||
mode,
|
||||
exposedVariables,
|
||||
isEditorReady,
|
||||
}) {
|
||||
const {
|
||||
color,
|
||||
|
|
@ -510,11 +511,13 @@ export function Table({
|
|||
}, [JSON.stringify([tableData, transformations, currentState])]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariables({
|
||||
currentData: tableData,
|
||||
updatedData: tableData,
|
||||
});
|
||||
}, [JSON.stringify(tableData)]);
|
||||
if (isEditorReady) {
|
||||
setExposedVariables({
|
||||
currentData: tableData,
|
||||
updatedData: tableData,
|
||||
});
|
||||
}
|
||||
}, [JSON.stringify(tableData), isEditorReady]);
|
||||
|
||||
const columnDataForAddNewRows = generateColumnsData({
|
||||
columnProperties: useDynamicColumn ? generatedColumn : component.definition.properties.columns.value,
|
||||
|
|
@ -775,7 +778,7 @@ export function Table({
|
|||
fireEvent('onRowClicked');
|
||||
}
|
||||
});
|
||||
}, [JSON.stringify(tableData), JSON.stringify(tableDetails.selectedRow)]);
|
||||
}, [JSON.stringify(tableData), JSON.stringify(tableDetails.selectedRow), isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('deselectRow', async function () {
|
||||
|
|
@ -787,7 +790,7 @@ export function Table({
|
|||
}
|
||||
return;
|
||||
});
|
||||
}, [JSON.stringify(tableData), JSON.stringify(tableDetails.selectedRow)]);
|
||||
}, [JSON.stringify(tableData), JSON.stringify(tableDetails.selectedRow), isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('discardChanges', async function () {
|
||||
|
|
@ -799,7 +802,7 @@ export function Table({
|
|||
mergeToTableDetails({ dataUpdates: {}, changeSet: {} });
|
||||
}
|
||||
});
|
||||
}, [JSON.stringify(tableData), JSON.stringify(tableDetails.changeSet)]);
|
||||
}, [JSON.stringify(tableData), JSON.stringify(tableDetails.changeSet), isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('discardNewlyAddedRows', async function () {
|
||||
|
|
@ -818,6 +821,7 @@ export function Table({
|
|||
JSON.stringify(tableDetails.addNewRowsDetails.newRowsChangeSet),
|
||||
tableDetails.addNewRowsDetails.addingNewRows,
|
||||
JSON.stringify(tableDetails.addNewRowsDetails.newRowsDataUpdates),
|
||||
isEditorReady,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -841,7 +845,7 @@ export function Table({
|
|||
setExposedVariables({ selectedRow, selectedRowId });
|
||||
mergeToTableDetails({ selectedRow, selectedRowId });
|
||||
}
|
||||
}, [selectedFlatRows.length, selectedFlatRows]);
|
||||
}, [selectedFlatRows.length, selectedFlatRows, isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('downloadTableData', async function (format) {
|
||||
|
|
@ -855,7 +859,7 @@ export function Table({
|
|||
mergeToTableDetails({ selectedRowsDetails: [], selectedRow: {}, selectedRowId: null });
|
||||
toggleAllRowsSelected(false);
|
||||
}
|
||||
}, [showBulkSelector, highlightSelectedRow, allowSelection]);
|
||||
}, [showBulkSelector, highlightSelectedRow, allowSelection, isEditorReady]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (enablePagination) {
|
||||
|
|
@ -971,7 +975,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)]);
|
||||
}, [JSON.stringify(defaultSelectedRow), JSON.stringify(data), isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
// csa for select all rows in table
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ export const Tabs = function Tabs({
|
|||
styles,
|
||||
darkMode,
|
||||
dataCy,
|
||||
isEditorReady,
|
||||
}) {
|
||||
const { tabWidth, boxShadow } = styles;
|
||||
|
||||
|
|
@ -103,10 +104,11 @@ export const Tabs = function Tabs({
|
|||
},
|
||||
currentTab: currentTab,
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setCurrentTab, currentTab]);
|
||||
}, [setCurrentTab, currentTab, isEditorReady]);
|
||||
|
||||
const renderTabContent = (id, tab) => (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -7,26 +7,32 @@ export const TextArea = function TextArea({
|
|||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
dataCy,
|
||||
isEditorReady,
|
||||
}) {
|
||||
const [value, setValue] = useState(properties.value);
|
||||
|
||||
useEffect(() => {
|
||||
setValue(properties.value);
|
||||
setExposedVariable('value', properties.value);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.value]);
|
||||
|
||||
useEffect(() => {
|
||||
const exposedVariables = {
|
||||
value: properties.value,
|
||||
setText: async function (text) {
|
||||
setValue(text);
|
||||
setExposedVariable('value', text);
|
||||
},
|
||||
clear: async function (text) {
|
||||
clear: async function () {
|
||||
setValue('');
|
||||
setExposedVariable('value', '');
|
||||
},
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.value, setValue]);
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
} // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.value, setValue, isEditorReady]);
|
||||
|
||||
return (
|
||||
<textarea
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { resolveWidgetFieldValue } from '@/_helpers/utils';
|
||||
|
||||
import * as Icons from '@tabler/icons-react';
|
||||
import Loader from '@/ToolJetUI/Loader/Loader';
|
||||
const tinycolor = require('tinycolor2');
|
||||
|
|
@ -18,6 +17,7 @@ export const TextInput = function TextInput({
|
|||
darkMode,
|
||||
dataCy,
|
||||
isResizing,
|
||||
isEditorReady,
|
||||
}) {
|
||||
const textInputRef = useRef();
|
||||
const labelRef = useRef();
|
||||
|
|
@ -172,9 +172,9 @@ export const TextInput = function TextInput({
|
|||
setVisibility(value);
|
||||
},
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
if (isEditorReady) setExposedVariables(exposedVariables);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
}, [isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
const exposedVariables = {
|
||||
|
|
@ -189,9 +189,9 @@ export const TextInput = function TextInput({
|
|||
fireEvent('onChange');
|
||||
},
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
if (isEditorReady) setExposedVariables(exposedVariables);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setValue]);
|
||||
}, [setValue, isEditorReady]);
|
||||
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];
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ export const TreeSelect = ({
|
|||
fireEvent,
|
||||
darkMode,
|
||||
dataCy,
|
||||
isEditorReady,
|
||||
}) => {
|
||||
const { label } = properties;
|
||||
const { visibility, disabledState, checkboxColor, boxShadow } = styles;
|
||||
|
|
@ -51,10 +52,11 @@ export const TreeSelect = ({
|
|||
checkedPathStrings: checkedPathString,
|
||||
checked: checkedArr,
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify(checkedData), JSON.stringify(data)]);
|
||||
}, [JSON.stringify(checkedData), JSON.stringify(data), isEditorReady]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('expanded', expandedData);
|
||||
|
|
@ -90,8 +92,9 @@ export const TreeSelect = ({
|
|||
checkedPathStrings: checkedPathString,
|
||||
checked: checked,
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
|
||||
if (isEditorReady) {
|
||||
setExposedVariables(exposedVariables);
|
||||
}
|
||||
updatedNode.checked ? fireEvent('onCheck') : fireEvent('onUnCheck');
|
||||
fireEvent('onChange');
|
||||
setChecked(checked);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ 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);
|
||||
|
|
@ -26,7 +25,7 @@ export const shouldUpdate = (prevProps, nextProps) => {
|
|||
}
|
||||
}
|
||||
|
||||
// Added to render the defaukt child components
|
||||
// Added to render the default child components
|
||||
if (prevProps?.childComponents === null && nextProps?.childComponents) return false;
|
||||
|
||||
return (
|
||||
|
|
@ -39,6 +38,7 @@ export const shouldUpdate = (prevProps, nextProps) => {
|
|||
prevProps?.height === nextProps?.height &&
|
||||
prevProps?.darkMode === nextProps?.darkMode &&
|
||||
prevProps?.childComponents === nextProps?.childComponents &&
|
||||
prevProps?.isEditorReady === nextProps?.isEditorReady &&
|
||||
!needToRender
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -89,7 +89,8 @@ export const chartConfig = {
|
|||
displayName: 'Json Description',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'string',
|
||||
type: 'union',
|
||||
schemas: [{ type: 'string' }, { type: 'object' }],
|
||||
},
|
||||
defaultValue: '{ "data": [ { "x": [ "Jan", "Feb", "Mar" ], "y": [ 100, 80, 40 ], "type": "bar" } ] }',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {
|
|||
resolveWidgetFieldValue,
|
||||
} from '@/_helpers/utils';
|
||||
import { dataqueryService } from '@/_services';
|
||||
import _, { isArray, isEmpty, set } from 'lodash';
|
||||
import _, { isArray, isEmpty } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import Tooltip from 'react-bootstrap/Tooltip';
|
||||
import { componentTypes } from '@/Editor/WidgetManager/components';
|
||||
|
|
@ -1854,88 +1854,84 @@ const isChildOfTabsOrCalendar = (component, allComponents = [], componentParentI
|
|||
return false;
|
||||
};
|
||||
|
||||
export const addComponents = (
|
||||
pageId,
|
||||
appDefinition,
|
||||
appDefinitionChanged,
|
||||
parentId = undefined,
|
||||
newComponentObj,
|
||||
fromClipboard = false
|
||||
) => {
|
||||
const finalComponents = {};
|
||||
const componentMap = {};
|
||||
let newComponent = {};
|
||||
let parentComponent = undefined;
|
||||
const { isCloning, isCut, newComponents: pastedComponents = [], currentPageId } = newComponentObj;
|
||||
export const addComponents = _.debounce(
|
||||
(pageId, appDefinition, appDefinitionChanged, parentId = undefined, newComponentObj, fromClipboard = false) => {
|
||||
const finalComponents = {};
|
||||
const componentMap = {};
|
||||
let newComponent = {};
|
||||
let parentComponent = undefined;
|
||||
const { isCloning, isCut, newComponents: pastedComponents = [], currentPageId } = newComponentObj;
|
||||
|
||||
if (parentId) {
|
||||
const id = Object.keys(appDefinition.pages[pageId].components).filter((key) => parentId.startsWith(key));
|
||||
parentComponent = JSON.parse(JSON.stringify(appDefinition.pages[pageId].components[id[0]]));
|
||||
}
|
||||
if (parentId) {
|
||||
const id = Object.keys(appDefinition.pages[pageId].components).filter((key) => parentId.startsWith(key));
|
||||
parentComponent = JSON.parse(JSON.stringify(appDefinition.pages[pageId].components[id[0]]));
|
||||
}
|
||||
|
||||
pastedComponents.forEach((component) => {
|
||||
const newComponentId = isCut ? component.componentId : uuidv4();
|
||||
const componentName = computeComponentName(component.component.component, {
|
||||
...appDefinition.pages[pageId].components,
|
||||
...finalComponents,
|
||||
pastedComponents.forEach((component) => {
|
||||
const newComponentId = isCut ? component.componentId : uuidv4();
|
||||
const componentName = computeComponentName(component.component.component, {
|
||||
...appDefinition.pages[pageId].components,
|
||||
...finalComponents,
|
||||
});
|
||||
|
||||
const isParentTabOrCalendar = isChildOfTabsOrCalendar(component, pastedComponents, parentId);
|
||||
const parentRef = isParentTabOrCalendar
|
||||
? component.component.parent.split('-').slice(0, -1).join('-')
|
||||
: component.component.parent;
|
||||
const isParentAlsoCopied = parentRef && componentMap[parentRef];
|
||||
|
||||
componentMap[component.componentId] = newComponentId;
|
||||
let isChild = isParentAlsoCopied ? component.component.parent : parentId;
|
||||
const componentData = JSON.parse(JSON.stringify(component.component));
|
||||
|
||||
if (isCloning && parentId && !componentData.parent) {
|
||||
isChild = component.component.parent;
|
||||
}
|
||||
|
||||
if (!parentComponent && !isParentAlsoCopied && fromClipboard) {
|
||||
isChild = undefined;
|
||||
componentData.parent = undefined;
|
||||
}
|
||||
|
||||
if (!isCloning && parentComponent && fromClipboard) {
|
||||
componentData.parent = isParentAlsoCopied ?? parentId;
|
||||
} else if (isChild && isChildOfTabsOrCalendar(component, pastedComponents, parentId)) {
|
||||
const parentId = component.component.parent.split('-').slice(0, -1).join('-');
|
||||
const childTabId = component.component.parent.split('-').at(-1);
|
||||
|
||||
componentData.parent = `${componentMap[parentId]}-${childTabId}`;
|
||||
} else if (isChild) {
|
||||
const isParentInMap = componentMap[isChild] !== undefined;
|
||||
|
||||
componentData.parent = isParentInMap ? componentMap[isChild] : isChild;
|
||||
}
|
||||
|
||||
newComponent = {
|
||||
component: {
|
||||
...componentData,
|
||||
name: componentName,
|
||||
},
|
||||
layouts: component.layouts,
|
||||
id: newComponentId,
|
||||
};
|
||||
|
||||
finalComponents[newComponentId] = newComponent;
|
||||
|
||||
// const doesComponentHaveChildren = getAllChildComponents
|
||||
});
|
||||
|
||||
const isParentTabOrCalendar = isChildOfTabsOrCalendar(component, pastedComponents, parentId);
|
||||
const parentRef = isParentTabOrCalendar
|
||||
? component.component.parent.split('-').slice(0, -1).join('-')
|
||||
: component.component.parent;
|
||||
const isParentAlsoCopied = parentRef && componentMap[parentRef];
|
||||
|
||||
componentMap[component.componentId] = newComponentId;
|
||||
let isChild = isParentAlsoCopied ? component.component.parent : parentId;
|
||||
const componentData = JSON.parse(JSON.stringify(component.component));
|
||||
|
||||
if (isCloning && parentId && !componentData.parent) {
|
||||
isChild = component.component.parent;
|
||||
if (currentPageId === pageId) {
|
||||
updateComponentLayout(pastedComponents, parentId, isCut);
|
||||
}
|
||||
|
||||
if (!parentComponent && !isParentAlsoCopied && fromClipboard) {
|
||||
isChild = undefined;
|
||||
componentData.parent = undefined;
|
||||
updateNewComponents(pageId, appDefinition, finalComponents, appDefinitionChanged, componentMap, isCut);
|
||||
if (!isCloning) {
|
||||
toast.success('Component pasted succesfully');
|
||||
}
|
||||
|
||||
if (!isCloning && parentComponent && fromClipboard) {
|
||||
componentData.parent = isParentAlsoCopied ?? parentId;
|
||||
} else if (isChild && isChildOfTabsOrCalendar(component, pastedComponents, parentId)) {
|
||||
const parentId = component.component.parent.split('-').slice(0, -1).join('-');
|
||||
const childTabId = component.component.parent.split('-').at(-1);
|
||||
|
||||
componentData.parent = `${componentMap[parentId]}-${childTabId}`;
|
||||
} else if (isChild) {
|
||||
const isParentInMap = componentMap[isChild] !== undefined;
|
||||
|
||||
componentData.parent = isParentInMap ? componentMap[isChild] : isChild;
|
||||
}
|
||||
|
||||
newComponent = {
|
||||
component: {
|
||||
...componentData,
|
||||
name: componentName,
|
||||
},
|
||||
layouts: component.layouts,
|
||||
id: newComponentId,
|
||||
};
|
||||
|
||||
finalComponents[newComponentId] = newComponent;
|
||||
|
||||
// const doesComponentHaveChildren = getAllChildComponents
|
||||
});
|
||||
|
||||
if (currentPageId === pageId) {
|
||||
updateComponentLayout(pastedComponents, parentId, isCut);
|
||||
}
|
||||
|
||||
updateNewComponents(pageId, appDefinition, finalComponents, appDefinitionChanged, componentMap, isCut);
|
||||
if (!isCloning) {
|
||||
toast.success('Component pasted succesfully');
|
||||
}
|
||||
return newComponent;
|
||||
};
|
||||
return newComponent;
|
||||
},
|
||||
100
|
||||
);
|
||||
|
||||
export const addNewWidgetToTheEditor = (
|
||||
componentMeta,
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ export const pluralize = (count, noun, suffix = 's') => `${count} ${noun}${count
|
|||
|
||||
export function resolve(data, state) {
|
||||
if (data.startsWith('{{queries.') || data.startsWith('{{globals.') || data.startsWith('{{components.')) {
|
||||
let prop = data.replace('{{', '').replace('}}', '');
|
||||
let prop = removeNestedDoubleCurlyBraces(data);
|
||||
return findProp(state, prop, '');
|
||||
}
|
||||
}
|
||||
|
|
@ -114,7 +114,7 @@ export function resolveString(str, state, customObjects, reservedKeyword, withEr
|
|||
|
||||
if (codeMatches) {
|
||||
codeMatches.forEach((codeMatch) => {
|
||||
const code = codeMatch.replace('{{', '').replace('}}', '');
|
||||
const code = removeNestedDoubleCurlyBraces(codeMatch);
|
||||
|
||||
if (reservedKeyword.includes(code)) {
|
||||
resolvedStr = resolvedStr.replace(codeMatch, '');
|
||||
|
|
@ -181,7 +181,7 @@ export function resolveReferences(
|
|||
|
||||
if (object.startsWith('{{') && object.endsWith('}}')) {
|
||||
if ((object.match(/{{/g) || []).length === 1) {
|
||||
const code = object.replace('{{', '').replace('}}', '');
|
||||
const code = removeNestedDoubleCurlyBraces(object);
|
||||
|
||||
//Will be remove in next release
|
||||
|
||||
|
|
@ -1340,3 +1340,66 @@ export const triggerKeyboardShortcut = (keyCallbackFnArray, initiator) => {
|
|||
export function decodeEntities(encodedString) {
|
||||
return encodedString?.replace(/</gi, '<')?.replace(/>/gi, '>')?.replace(/&/gi, '&');
|
||||
}
|
||||
|
||||
export const removeNestedDoubleCurlyBraces = (str) => {
|
||||
const transformedInput = str.split('');
|
||||
let iter = 0;
|
||||
const stack = [];
|
||||
|
||||
while (iter < str.length - 1) {
|
||||
if (transformedInput[iter] === '{' && transformedInput[iter + 1] === '{') {
|
||||
transformedInput[iter] = 'le';
|
||||
transformedInput[iter + 1] = 'le';
|
||||
stack.push(2);
|
||||
iter += 2;
|
||||
} else if (transformedInput[iter] === '{') {
|
||||
stack.push(1);
|
||||
iter++;
|
||||
} else if (transformedInput[iter] === '}' && stack.length > 0 && stack[stack.length - 1] === 1) {
|
||||
stack.pop();
|
||||
iter++;
|
||||
} else if (
|
||||
transformedInput[iter] === '}' &&
|
||||
stack.length > 0 &&
|
||||
transformedInput[iter + 1] === '}' &&
|
||||
stack[stack.length - 1] === 2
|
||||
) {
|
||||
stack.pop();
|
||||
transformedInput[iter] = 'ri';
|
||||
transformedInput[iter + 1] = 'ri';
|
||||
iter += 2;
|
||||
} else {
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
iter = 0;
|
||||
let shouldRemoveSpace = true;
|
||||
while (iter < str.length) {
|
||||
if (transformedInput[iter] === ' ' && shouldRemoveSpace) {
|
||||
transformedInput[iter] = '';
|
||||
} else if (transformedInput[iter] === 'le') {
|
||||
shouldRemoveSpace = true;
|
||||
transformedInput[iter] = '';
|
||||
} else {
|
||||
shouldRemoveSpace = false;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
iter = str.length - 1;
|
||||
shouldRemoveSpace = true;
|
||||
while (iter >= 0) {
|
||||
if (transformedInput[iter] === ' ' && shouldRemoveSpace) {
|
||||
transformedInput[iter] = '';
|
||||
} else if (transformedInput[iter] === 'ri') {
|
||||
shouldRemoveSpace = true;
|
||||
transformedInput[iter] = '';
|
||||
} else {
|
||||
shouldRemoveSpace = false;
|
||||
}
|
||||
iter--;
|
||||
}
|
||||
|
||||
return transformedInput.join('');
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { diff } from 'deep-object-diff';
|
|||
import { componentTypes } from '@/Editor/WidgetManager/components';
|
||||
import _ from 'lodash';
|
||||
import { deepClone } from '@/_helpers/utilities/utils.helpers';
|
||||
import { removeNestedDoubleCurlyBraces } from '@/_helpers/utils';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
export const zustandDevTools = (fn, options = {}) =>
|
||||
|
|
|
|||
Loading…
Reference in a new issue