mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-24 09:28:31 +00:00
Merge branch 'feat/grid-appbuilder-improvement' of https://github.com/ToolJet/ToolJet into feat/grid-appbuilder-improvement
This commit is contained in:
commit
2044bf539f
11 changed files with 73 additions and 64 deletions
|
|
@ -88,8 +88,7 @@ const Portal = ({ children, ...restProps }) => {
|
|||
const PopupIcon = ({ callback, icon, tip, position, isMultiEditor = false }) => {
|
||||
const size = 16;
|
||||
const topRef = isNumber(position?.height) ? Math.floor(position?.height) - 30 : 32;
|
||||
let top = isMultiEditor ? 370 : topRef > 32 ? topRef : 0;
|
||||
|
||||
let top = isMultiEditor ? 270 : topRef > 32 ? topRef : 0;
|
||||
return (
|
||||
<div className="d-flex justify-content-end w-100 position-absolute codehinter-popup-icon" style={{ top: top }}>
|
||||
<OverlayTrigger
|
||||
|
|
|
|||
|
|
@ -12,14 +12,7 @@ import Card from 'react-bootstrap/Card';
|
|||
// eslint-disable-next-line import/no-unresolved
|
||||
import { JsonViewer } from '@textea/json-viewer';
|
||||
|
||||
export const PreviewBox = ({
|
||||
currentValue,
|
||||
validationSchema,
|
||||
setErrorStateActive,
|
||||
componentId,
|
||||
fxActive,
|
||||
setErrorMessage,
|
||||
}) => {
|
||||
export const PreviewBox = ({ currentValue, validationSchema, setErrorStateActive, componentId, setErrorMessage }) => {
|
||||
const { variablesExposedForPreview } = useContext(EditorContext);
|
||||
|
||||
const customVariables = variablesExposedForPreview?.[componentId] ?? {};
|
||||
|
|
@ -27,10 +20,8 @@ export const PreviewBox = ({
|
|||
const [resolvedValue, setResolvedValue] = useState('');
|
||||
const [error, setError] = useState(null);
|
||||
const [coersionData, setCoersionData] = useState(null);
|
||||
|
||||
const getPreviewContent = (content, type) => {
|
||||
if (!content) return currentValue;
|
||||
|
||||
try {
|
||||
switch (type) {
|
||||
case 'Object':
|
||||
|
|
@ -75,12 +66,7 @@ export const PreviewBox = ({
|
|||
}, [error]);
|
||||
|
||||
useEffect(() => {
|
||||
const [valid, _error, newValue, resolvedValue] = resolveReferences(
|
||||
currentValue,
|
||||
validationSchema,
|
||||
customVariables,
|
||||
fxActive
|
||||
);
|
||||
const [valid, _error, newValue, resolvedValue] = resolveReferences(currentValue, validationSchema, customVariables);
|
||||
|
||||
if (!validationSchema || isEmpty(validationSchema)) {
|
||||
return setResolvedValue(newValue);
|
||||
|
|
@ -345,7 +331,6 @@ const PreviewCodeBlock = ({ code, isExpectValue = false }) => {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="p-2 pt-0">
|
||||
<pre
|
||||
|
|
@ -366,7 +351,9 @@ const PreviewCodeBlock = ({ code, isExpectValue = false }) => {
|
|||
padding: '0',
|
||||
}}
|
||||
>
|
||||
{prettyPrintedJson}
|
||||
{prettyPrintedJson?.startsWith('{{')
|
||||
? prettyPrintedJson?.replace(/{{/g, '').replace(/}}/g, '')
|
||||
: prettyPrintedJson}
|
||||
</pre>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -34,15 +34,9 @@ const SingleLineCodeEditor = ({ suggestions, componentName, fieldMeta = {}, fxAc
|
|||
|
||||
useEffect(() => {
|
||||
if (typeof initialValue !== 'string') return;
|
||||
|
||||
if (fxActive && initialValue?.startsWith('{{')) {
|
||||
const _value = initialValue?.replace(/{{/g, '').replace(/}}/g, '');
|
||||
return setCurrentValue(_value);
|
||||
}
|
||||
|
||||
setCurrentValue(initialValue);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [componentName, initialValue, fxActive]);
|
||||
}, [componentName, initialValue]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event) => {
|
||||
|
|
@ -80,7 +74,7 @@ const SingleLineCodeEditor = ({ suggestions, componentName, fieldMeta = {}, fxAc
|
|||
setErrorStateActive={setErrorStateActive}
|
||||
ignoreValidation={restProps?.ignoreValidation || isEmpty(validation)}
|
||||
componentId={restProps?.componentId ?? null}
|
||||
fxActive={fxActive}
|
||||
// fxActive={fxActive}
|
||||
isWorkspaceVariable={isWorkspaceVariable}
|
||||
errorStateActive={errorStateActive}
|
||||
previewPlacement={restProps?.cyLabel === 'canvas-bg-colour' ? 'top' : 'left-start'}
|
||||
|
|
@ -99,7 +93,6 @@ const SingleLineCodeEditor = ({ suggestions, componentName, fieldMeta = {}, fxAc
|
|||
cyLabel={restProps.cyLabel}
|
||||
portalProps={portalProps}
|
||||
componentName={componentName}
|
||||
fxActive={fxActive}
|
||||
{...restProps}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -124,7 +117,6 @@ const EditorInput = ({
|
|||
renderPreview,
|
||||
portalProps,
|
||||
ignoreValidation,
|
||||
fxActive,
|
||||
lang,
|
||||
isFocused,
|
||||
componentId,
|
||||
|
|
@ -138,15 +130,15 @@ const EditorInput = ({
|
|||
|
||||
if (totalReferences > 1) {
|
||||
const currentWord = queryInput.split('{{').pop().split('}}')[0];
|
||||
queryInput = fxActive ? currentWord : `{{${currentWord}}}`;
|
||||
queryInput = currentWord;
|
||||
}
|
||||
|
||||
let completions = getAutocompletion(queryInput, validationType, hints, fxActive, totalReferences);
|
||||
let completions = getAutocompletion(queryInput, validationType, hints, totalReferences);
|
||||
|
||||
return {
|
||||
from: word.from,
|
||||
options: completions,
|
||||
validFor: !fxActive ? /^\{\{.*\}\}$/ : '',
|
||||
validFor: /^\{\{.*\}\}$/,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -168,18 +160,17 @@ const EditorInput = ({
|
|||
setCurrentValue(val);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const handleOnBlur = React.useCallback(() => {
|
||||
setFirstTimeFocus(false);
|
||||
if (ignoreValidation) {
|
||||
return onBlurUpdate(currentValue);
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
const _value = fxActive ? `{{${currentValue}}}` : currentValue;
|
||||
|
||||
onBlurUpdate(_value);
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (!error || currentValue == '') {
|
||||
const _value = currentValue;
|
||||
onBlurUpdate(_value);
|
||||
}
|
||||
}, 0);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currentValue, error]);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
export const getAutocompletion = (input, fieldType, hints, fxActive = false, totalReferences = 1) => {
|
||||
if (!fxActive && (!input.startsWith('{{') || !input.endsWith('}}'))) return [];
|
||||
|
||||
const actualInput = !fxActive ? input.replace(/{{|}}/g, '') : input;
|
||||
export const getAutocompletion = (input, fieldType, hints, totalReferences = 1) => {
|
||||
if (!input.startsWith('{{') || !input.endsWith('}}')) return [];
|
||||
|
||||
const actualInput = input.replace(/{{|}}/g, '');
|
||||
let JSLangHints = [];
|
||||
|
||||
if (fieldType) {
|
||||
|
|
@ -50,7 +49,7 @@ export const getAutocompletion = (input, fieldType, hints, fxActive = false, tot
|
|||
if (autoSuggestionList.length === 0 && !cm.hint.includes(actualInput)) return true;
|
||||
});
|
||||
|
||||
const suggestions = generateHints([...jsHints, ...autoSuggestionList], fxActive, totalReferences);
|
||||
const suggestions = generateHints([...jsHints, ...autoSuggestionList], totalReferences);
|
||||
return orderSuggestions(suggestions, fieldType).map((cm, index) => ({ ...cm, boost: 100 - index }));
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.cm-widgetBuffer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.cm-base-autocomplete {
|
||||
|
|
@ -153,18 +157,35 @@
|
|||
}
|
||||
}
|
||||
|
||||
.query-manager-sort-filter-popup {
|
||||
.cm-base-autocomplete {
|
||||
position: fixed !important;
|
||||
top: 130px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.canvas-codehinter-container {
|
||||
.cm-base-autocomplete {
|
||||
position: fixed !important;
|
||||
top: 500px !important;
|
||||
left: 38px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.widget-code-editor {
|
||||
height: 100%;
|
||||
|
||||
.cm-content {
|
||||
max-width: 220px !important;
|
||||
max-width: 100% !important;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
|
||||
.cm-placeholder {
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.code-hinter-wrapper {
|
||||
.cm-editor {
|
||||
min-height: 32px;
|
||||
|
|
@ -224,6 +245,7 @@
|
|||
|
||||
.cm-tooltip-autocomplete {
|
||||
@extend .cm-base-autocomplete;
|
||||
top: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -277,6 +299,7 @@
|
|||
overflow-y: auto !important;
|
||||
overflow-x: hidden !important;
|
||||
padding: 2px !important;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
.cm-focused {
|
||||
|
|
@ -315,8 +338,6 @@
|
|||
|
||||
.code-hinter-preview-card-body::-webkit-scrollbar {
|
||||
width: 4px !important;
|
||||
/* for vertical scrollbars */
|
||||
;
|
||||
}
|
||||
|
||||
.code-hinter-preview-card-body::-webkit-scrollbar-track {
|
||||
|
|
|
|||
|
|
@ -211,9 +211,8 @@ const resolveMultiDynamicReferences = (code, lookupTable) => {
|
|||
return resolvedValue;
|
||||
};
|
||||
|
||||
export const resolveReferences = (query, validationSchema, customResolvers = {}, fxActive = false) => {
|
||||
export const resolveReferences = (query, validationSchema, customResolvers = {}) => {
|
||||
if (!query || typeof query !== 'string') return [false, null, null];
|
||||
|
||||
let resolvedValue = query;
|
||||
let error = null;
|
||||
|
||||
|
|
@ -226,20 +225,20 @@ export const resolveReferences = (query, validationSchema, customResolvers = {},
|
|||
return [true, error, resolvedValue];
|
||||
}
|
||||
|
||||
if (validationSchema && !fxActive && !query?.includes('{{') && !query?.includes('}}')) {
|
||||
if (validationSchema && !query?.includes('{{') && !query?.includes('}}')) {
|
||||
const [valid, errors, newValue] = validateComponentProperty(query, validationSchema);
|
||||
return [valid, errors, newValue, resolvedValue];
|
||||
}
|
||||
|
||||
const hasMultiDynamicVariables = getDynamicVariables(query);
|
||||
const hasMultiDynamicVariables = getDynamicVariables(query)?.length > 1;
|
||||
|
||||
const { lookupTable } = useResolveStore.getState();
|
||||
if (isEmpty(validationSchema) && hasMultiDynamicVariables) {
|
||||
if (hasMultiDynamicVariables) {
|
||||
resolvedValue = resolveMultiDynamicReferences(query, lookupTable);
|
||||
} else {
|
||||
let value = !fxActive ? query?.replace(/{{|}}/g, '').trim() : query;
|
||||
let value = query?.replace(/{{|}}/g, '').trim();
|
||||
|
||||
if (fxActive && (value.startsWith('#') || value.includes('table-'))) {
|
||||
if (value.startsWith('#') || value.includes('table-')) {
|
||||
value = JSON.stringify(value);
|
||||
}
|
||||
const { toResolveReference, jsExpression, jsExpMatch } = inferJSExpAndReferences(value, lookupTable.hints);
|
||||
|
|
|
|||
|
|
@ -108,10 +108,10 @@ export const EventManager = ({
|
|||
return { name: action.name, value: action.id };
|
||||
});
|
||||
|
||||
let checkIfClicksAreInsideOf = document.querySelector('#cm-complete-0');
|
||||
let checkIfClicksAreInsideOf = document.querySelector('.cm-completionListIncompleteBottom');
|
||||
// Listen for click events on body
|
||||
if (checkIfClicksAreInsideOf) {
|
||||
document.body.addEventListener('click', function (event) {
|
||||
document.body.addEventListener('mousedown', function (event) {
|
||||
if (checkIfClicksAreInsideOf.contains(event.target)) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,19 +21,19 @@ const ParameterDetails = ({ darkMode, onSubmit, isEdit, name, defaultValue, onRe
|
|||
if (
|
||||
showModal &&
|
||||
event.target.closest('#parameter-form-popover') === null &&
|
||||
event.target.closest('#cm-complete-0') === null
|
||||
event.target.closest('.cm-completionListIncompleteBottom') === null
|
||||
) {
|
||||
closeMenu();
|
||||
}
|
||||
};
|
||||
|
||||
if (showModal) {
|
||||
document.addEventListener('mouseup', handleClickOutside);
|
||||
document.addEventListener('click', handleClickOutside);
|
||||
} else {
|
||||
document.removeEventListener('mouseup', handleClickOutside);
|
||||
document.removeEventListener('click', handleClickOutside);
|
||||
}
|
||||
return () => {
|
||||
document.removeEventListener('mouseup', handleClickOutside);
|
||||
document.removeEventListener('click', handleClickOutside);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [showModal]);
|
||||
|
|
|
|||
|
|
@ -604,6 +604,9 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) {
|
|||
const value = resolveReferences(event.value, getCurrentState(), undefined, customVariables);
|
||||
const customAppVariables = { ...getCurrentState().variables };
|
||||
customAppVariables[key] = value;
|
||||
useResolveStore.getState().actions.addAppSuggestions({
|
||||
variables: customAppVariables,
|
||||
});
|
||||
return useCurrentStateStore.getState().actions.setCurrentState({
|
||||
variables: customAppVariables,
|
||||
});
|
||||
|
|
@ -619,6 +622,7 @@ 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);
|
||||
return useCurrentStateStore.getState().actions.setCurrentState({
|
||||
variables: customAppVariables,
|
||||
});
|
||||
|
|
@ -631,6 +635,9 @@ function executeActionWithDebounce(_ref, event, mode, customVariables) {
|
|||
...getCurrentState().page.variables,
|
||||
[key]: value,
|
||||
};
|
||||
useResolveStore.getState().actions.addAppSuggestions({
|
||||
variables: customPageVariables,
|
||||
});
|
||||
return useCurrentStateStore.getState().actions.setCurrentState({
|
||||
page: {
|
||||
...getCurrentState().page,
|
||||
|
|
@ -650,6 +657,7 @@ 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);
|
||||
return useCurrentStateStore.getState().actions.setCurrentState({
|
||||
page: {
|
||||
...getCurrentState().page,
|
||||
|
|
|
|||
|
|
@ -136,13 +136,13 @@ export const useResolveStore = create(
|
|||
},
|
||||
|
||||
removeAppSuggestions: (suggestionsArray) => {
|
||||
if (suggestionsArray.length === 0) return new Promise((resolve) => resolve({ status: '' }));
|
||||
if (suggestionsArray?.length === 0) return new Promise((resolve) => resolve({ status: '' }));
|
||||
|
||||
const lookupHintsMap = new Map([...get().lookupTable.hints]);
|
||||
const lookupResolvedRefs = new Map([...get().lookupTable.resolvedRefs]);
|
||||
const currentSuggestions = get().suggestions.appHints;
|
||||
|
||||
suggestionsArray.forEach((suggestion) => {
|
||||
suggestionsArray?.forEach((suggestion) => {
|
||||
const index = currentSuggestions.findIndex((s) => s.hint === suggestion);
|
||||
|
||||
if (index === -1) return;
|
||||
|
|
|
|||
|
|
@ -505,7 +505,12 @@ export function findAllEntityReferences(node, allRefs) {
|
|||
if (typeof node === 'object') {
|
||||
for (let key in node) {
|
||||
const value = node[key];
|
||||
if (typeof value === 'string' && value.includes('{{') && value.includes('}}')) {
|
||||
if (
|
||||
typeof value === 'string' &&
|
||||
value.includes('{{') &&
|
||||
value.includes('}}') &&
|
||||
(value.startsWith('{{components') || value.startsWith('queries'))
|
||||
) {
|
||||
const referenceExists = value;
|
||||
|
||||
if (referenceExists) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue