Merge branch 'lts-2.50' into merge-lts-2.50.4-main

This commit is contained in:
Johnson Cherian 2024-06-07 09:36:25 +05:30
commit f461239dad
10 changed files with 128 additions and 47 deletions

View file

@ -1 +1 @@
2.61.0 2.61.0

View file

@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { computeCoercion, getCurrentNodeType, resolveReferences } from './utils'; import { computeCoercion, getCurrentNodeType, hasDeepChildren, resolveReferences } from './utils';
import CodeHinter from '.'; import CodeHinter from '.';
import { copyToClipboard } from '@/_helpers/appUtils'; import { copyToClipboard } from '@/_helpers/appUtils';
import { Alert } from '@/_ui/Alert/Alert'; import { Alert } from '@/_ui/Alert/Alert';
@ -17,6 +17,7 @@ export const PreviewBox = ({
setErrorStateActive, setErrorStateActive,
setErrorMessage, setErrorMessage,
customVariables, customVariables,
isWorkspaceVariable,
}) => { }) => {
const [resolvedValue, setResolvedValue] = useState(''); const [resolvedValue, setResolvedValue] = useState('');
const [error, setError] = useState(null); const [error, setError] = useState(null);
@ -68,7 +69,7 @@ export const PreviewBox = ({
useEffect(() => { useEffect(() => {
const [valid, _error, newValue, resolvedValue] = resolveReferences(currentValue, validationSchema, customVariables); const [valid, _error, newValue, resolvedValue] = resolveReferences(currentValue, validationSchema, customVariables);
if (!validationSchema || isEmpty(validationSchema)) { if (isWorkspaceVariable || !validationSchema || isEmpty(validationSchema)) {
return setResolvedValue(newValue); return setResolvedValue(newValue);
} }
@ -115,6 +116,7 @@ export const PreviewBox = ({
resolvedValue={content} resolvedValue={content}
coersionData={coersionData} coersionData={coersionData}
withValidation={!isEmpty(validationSchema)} withValidation={!isEmpty(validationSchema)}
isWorkspaceVariable={isWorkspaceVariable}
/> />
<CodeHinter.PopupIcon <CodeHinter.PopupIcon
callback={() => copyToClipboard(error ? error?.value : content)} callback={() => copyToClipboard(error ? error?.value : content)}
@ -125,7 +127,14 @@ export const PreviewBox = ({
); );
}; };
const RenderResolvedValue = ({ error, previewType, resolvedValue, coersionData, withValidation }) => { const RenderResolvedValue = ({
error,
previewType,
resolvedValue,
coersionData,
withValidation,
isWorkspaceVariable,
}) => {
const computeCoersionPreview = (resolvedValue, coersionData) => { const computeCoersionPreview = (resolvedValue, coersionData) => {
if (coersionData?.typeBeforeCoercion === coersionData?.typeAfterCoercion) return resolvedValue; if (coersionData?.typeBeforeCoercion === coersionData?.typeAfterCoercion) return resolvedValue;
@ -140,12 +149,13 @@ const RenderResolvedValue = ({ error, previewType, resolvedValue, coersionData,
return resolvedValue + coersionData?.coercionPreview; return resolvedValue + coersionData?.coercionPreview;
}; };
const previewValueType = const previewValueType = isWorkspaceVariable
withValidation || (coersionData && coersionData?.typeBeforeCoercion) ? previewType
? `${coersionData?.typeBeforeCoercion} ${ : withValidation || (coersionData && coersionData?.typeBeforeCoercion)
coersionData?.coercionPreview ? `${coersionData?.typeAfterCoercion}` : '' ? `${coersionData?.typeBeforeCoercion} ${
}` coersionData?.coercionPreview ? `${coersionData?.typeAfterCoercion}` : ''
: previewType; }`
: previewType;
const previewContent = !withValidation ? resolvedValue : computeCoersionPreview(resolvedValue, coersionData); const previewContent = !withValidation ? resolvedValue : computeCoersionPreview(resolvedValue, coersionData);
@ -341,6 +351,8 @@ const PreviewCodeBlock = ({ code, isExpectValue = false }) => {
if (showJSONTree) { if (showJSONTree) {
const darkMode = localStorage.getItem('darkMode') === 'true'; const darkMode = localStorage.getItem('darkMode') === 'true';
const hasDeepChild = hasDeepChildren(prettyPrintedJson);
return ( return (
<div className="preview-json"> <div className="preview-json">
<JsonViewer <JsonViewer
@ -351,7 +363,7 @@ const PreviewCodeBlock = ({ code, isExpectValue = false }) => {
enableClipboard={false} enableClipboard={false}
rootName={false} rootName={false}
theme={darkMode ? 'dark' : 'light'} theme={darkMode ? 'dark' : 'light'}
groupArraysAfterLength={500} groupArraysAfterLength={hasDeepChild ? 10 : 100}
/> />
</div> </div>
); );

View file

@ -193,6 +193,7 @@ const EditorInput = ({
class: 'cm-completionInfo-top cm-custom-completion-info', class: 'cm-completionInfo-top cm-custom-completion-info',
}; };
}, },
maxRenderedOptions: 10,
}); });
const customKeyMaps = [...defaultKeymap, ...completionKeymap]; const customKeyMaps = [...defaultKeymap, ...completionKeymap];

View file

@ -101,26 +101,25 @@ const resolveWorkspaceVariables = (query) => {
let resolvedStr = query; let resolvedStr = query;
let error = null; let error = null;
let valid = false; let valid = false;
// Resolve %%object%% // Resolve %%object%%
const serverRegex = /(%%.+?%%)/g; const serverRegex = /(%%.+?%%)/g;
const serverMatch = resolvedStr.match(serverRegex)?.[0]; const serverMatches = resolvedStr.match(serverRegex);
if (serverMatch) { if (serverMatches) {
const code = serverMatch.replace(/%%/g, ''); serverMatches.forEach((serverMatch) => {
const code = serverMatch.replace(/%%/g, '');
if (code.includes('server.')) { if (code.includes('server.') && !/^server\.[A-Za-z0-9]+$/.test(code)) {
resolvedStr = resolvedStr.replace(serverMatch, 'HiddenEnvironmentVariable'); resolvedStr = resolvedStr.replace(serverMatch, 'HiddenEnvironmentVariable');
error = 'Server variables cannot be resolved in the client.';
} else {
const [resolvedCode, err] = resolveCode(code);
if (!resolvedCode) {
error = err ? err : `Cannot resolve ${query}`;
} else { } else {
const resolvedCode = resolveCode(code);
resolvedStr = resolvedStr.replace(serverMatch, resolvedCode); resolvedStr = resolvedStr.replace(serverMatch, resolvedCode);
valid = true;
} }
} });
valid = true;
} }
return [valid, error, resolvedStr]; return [valid, error, resolvedStr];
@ -408,3 +407,19 @@ export const validateComponentProperty = (resolvedValue, validation) => {
return validate(resolvedValue, schema, defaultValue, true); return validate(resolvedValue, schema, defaultValue, true);
}; };
export function hasDeepChildren(obj, currentDepth = 1, maxDepth = 3) {
if (currentDepth > maxDepth) {
return true;
}
for (const key in obj) {
if (typeof obj[key] === 'object' && obj[key] !== null) {
if (hasDeepChildren(obj[key], currentDepth + 1, maxDepth)) {
return true;
}
}
}
return false;
}

View file

@ -360,6 +360,19 @@ const EditorComponent = (props) => {
() => { () => {
const components = appDefinition?.pages?.[currentPageId]?.components || {}; const components = appDefinition?.pages?.[currentPageId]?.components || {};
computeComponentState(components); computeComponentState(components);
const isPageSwitched = useResolveStore.getState().isPageSwitched;
if (isPageSwitched) {
const currentStateObj = useCurrentStateStore.getState();
useResolveStore.getState().actions.addAppSuggestions({
queries: currentStateObj.queries,
components: currentStateObj.components,
page: currentStateObj.page,
});
useResolveStore.getState().actions.pageSwitched(false);
}
}, },
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
[currentPageId] [currentPageId]
@ -745,7 +758,7 @@ const EditorComponent = (props) => {
user_id: userId, user_id: userId,
events, events,
} = appData; } = appData;
useResolveStore.getState().actions.updateJSHints();
const startingPageHandle = props.params.pageHandle; const startingPageHandle = props.params.pageHandle;
setWindowTitle({ page: pageTitles.EDITOR, appName }); setWindowTitle({ page: pageTitles.EDITOR, appName });
useAppVersionStore.getState().actions.updateEditingVersion(editing_version); useAppVersionStore.getState().actions.updateEditingVersion(editing_version);
@ -766,7 +779,7 @@ const EditorComponent = (props) => {
await processNewAppDefinition(appData, startingPageHandle, false, ({ homePageId }) => { await processNewAppDefinition(appData, startingPageHandle, false, ({ homePageId }) => {
handleLowPriorityWork(async () => { handleLowPriorityWork(async () => {
useResolveStore.getState().actions.updateLastUpdatedRefs(['constants']); useResolveStore.getState().actions.updateLastUpdatedRefs(['constants', 'client']);
await useDataSourcesStore.getState().actions.fetchGlobalDataSources(organizationId); await useDataSourcesStore.getState().actions.fetchGlobalDataSources(organizationId);
await fetchDataSources(editing_version?.id); await fetchDataSources(editing_version?.id);
commonLowPriorityActions(events, { homePageId }); commonLowPriorityActions(events, { homePageId });
@ -782,6 +795,7 @@ const EditorComponent = (props) => {
}; };
const processNewAppDefinition = async (data, startingPageHandle, versionSwitched = false, onComplete) => { const processNewAppDefinition = async (data, startingPageHandle, versionSwitched = false, onComplete) => {
useResolveStore.getState().actions.updateJSHints();
const appDefData = buildAppDefinition(data); const appDefData = buildAppDefinition(data);
const appJson = appDefData; const appJson = appDefData;
@ -1433,6 +1447,7 @@ const EditorComponent = (props) => {
useCurrentStateStore.getState().actions.setEditorReady(true); useCurrentStateStore.getState().actions.setEditorReady(true);
const currentComponents = appJson?.pages?.[pageId]?.components; const currentComponents = appJson?.pages?.[pageId]?.components;
const currentDataQueries = useDataQueriesStore.getState().dataQueries;
const referenceManager = useResolveStore.getState().referenceMapper; const referenceManager = useResolveStore.getState().referenceMapper;
@ -1446,8 +1461,17 @@ const EditorComponent = (props) => {
}; };
} }
}); });
const newDataQueries = currentDataQueries.map((dq) => {
if (!referenceManager.get(dq.id)) {
return {
id: dq.id,
name: dq.name,
};
}
});
useResolveStore.getState().actions.addEntitiesToMap(newComponents); useResolveStore.getState().actions.addEntitiesToMap([...newComponents, ...newDataQueries]);
// useResolveStore.getState().actions.addEntitiesToMap(newDataQueries);
}; };
const updateEntityReferences = (appJson, pageId) => { const updateEntityReferences = (appJson, pageId) => {
@ -1668,11 +1692,11 @@ const EditorComponent = (props) => {
switchPage: true, switchPage: true,
pageId: newPageId, pageId: newPageId,
}); });
props?.navigate(`/${getWorkspaceId()}/apps/${slug ?? appId}/${newHandle}`, { // props?.navigate(`/${getWorkspaceId()}/apps/${slug ?? appId}/${newHandle}`, {
state: { // state: {
isSwitchingPage: true, // isSwitchingPage: true,
}, // },
}); // });
const page = { const page = {
id: newPageId, id: newPageId,
@ -1707,14 +1731,15 @@ const EditorComponent = (props) => {
return; return;
} }
clearAllQueuedTasks(); await clearAllQueuedTasks();
useResolveStore.getState().actions.resetStore();
useEditorStore.getState().actions.setPageProgress(true); useEditorStore.getState().actions.setPageProgress(true);
useCurrentStateStore.getState().actions.setEditorReady(false); useCurrentStateStore.getState().actions.setEditorReady(false);
useResolveStore.getState().actions.resetStore();
// This are fetched from store to handle runQueriesOnAppLoad // This are fetched from store to handle runQueriesOnAppLoad
const currentPageId = useEditorStore.getState().currentPageId; const currentPageId = useEditorStore.getState().currentPageId;
const appDefinition = useEditorStore.getState().appDefinition; const appDefinition = useEditorStore.getState().appDefinition;
const pageHandle = getCurrentState().pageHandle;
const pageHandle = useCurrentStateStore.getState().page?.handle;
if (currentPageId === pageId && pageHandle === appDefinition?.pages[pageId]?.handle) { if (currentPageId === pageId && pageHandle === appDefinition?.pages[pageId]?.handle) {
return; return;
@ -1723,6 +1748,7 @@ const EditorComponent = (props) => {
if (!name || !handle) return; if (!name || !handle) return;
const copyOfAppDefinition = JSON.parse(JSON.stringify(appDefinition)); const copyOfAppDefinition = JSON.parse(JSON.stringify(appDefinition));
navigateToPage(queryParams, handle); navigateToPage(queryParams, handle);
const page = { const page = {
@ -1743,9 +1769,6 @@ const EditorComponent = (props) => {
await onEditorLoad(appDefinition, pageId, true); await onEditorLoad(appDefinition, pageId, true);
updateEntityReferences(appDefinition, pageId); updateEntityReferences(appDefinition, pageId);
handleLowPriorityWork(() => {
useResolveStore.getState().actions.updateJSHints();
});
setCurrentPageId(pageId); setCurrentPageId(pageId);
@ -1754,9 +1777,14 @@ const EditorComponent = (props) => {
.events.filter((event) => event.target === 'page' && event.sourceId === page.id); .events.filter((event) => event.target === 'page' && event.sourceId === page.id);
handleEvent('onPageLoad', currentPageEvents); handleEvent('onPageLoad', currentPageEvents);
handleLowPriorityWork(() => { handleLowPriorityWork(
useEditorStore.getState().actions.setPageProgress(false); () => {
}, 100); useEditorStore.getState().actions.setPageProgress(false);
useResolveStore.getState().actions.updateJSHints();
},
null,
true
);
}; };
const deletePageRequest = (pageId, isHomePage = false, pageName = '') => { const deletePageRequest = (pageId, isHomePage = false, pageName = '') => {

View file

@ -326,12 +326,14 @@ class ViewerComponent extends React.Component {
queryState[query.name] = { queryState[query.name] = {
...exposedVariables, ...exposedVariables,
...this.props.currentState.queries[query.name], ...this.props.currentState.queries[query.name],
id: query.id,
}; };
} else { } else {
const dataSourceTypeDetail = DataSourceTypes.find((source) => source.kind === query.kind); const dataSourceTypeDetail = DataSourceTypes.find((source) => source.kind === query.kind);
queryState[query.name] = { queryState[query.name] = {
...dataSourceTypeDetail.exposedVariables, ...dataSourceTypeDetail.exposedVariables,
...this.props.currentState.queries[query.name], ...this.props.currentState.queries[query.name],
id: query.id,
}; };
} }
}); });
@ -754,7 +756,7 @@ class ViewerComponent extends React.Component {
if (currentPageComponents && !_.isEmpty(currentPageComponents)) { if (currentPageComponents && !_.isEmpty(currentPageComponents)) {
const referenceManager = useResolveStore.getState().referenceMapper; const referenceManager = useResolveStore.getState().referenceMapper;
const currentDataQueries = useDataQueriesStore.getState().dataQueries;
const newComponents = Object.keys(currentPageComponents).map((componentId) => { const newComponents = Object.keys(currentPageComponents).map((componentId) => {
const component = currentPageComponents[componentId]; const component = currentPageComponents[componentId];
@ -765,9 +767,18 @@ class ViewerComponent extends React.Component {
}; };
} }
}); });
const newDataQueries = currentDataQueries.map((dq) => {
if (!referenceManager.get(dq.id)) {
return {
id: dq.id,
name: dq.name,
};
}
});
try { try {
useResolveStore.getState().actions.addEntitiesToMap(newComponents); useResolveStore.getState().actions.addEntitiesToMap(newComponents);
useResolveStore.getState().actions.addEntitiesToMap(newDataQueries);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
@ -1062,6 +1073,18 @@ const withStore = (Component) => (props) => {
flushComponentsToRender(updatedComponentIds); flushComponentsToRender(updatedComponentIds);
} }
React.useEffect(() => {
const currentComponentsDef = appDefinition?.pages?.[currentPageId]?.components || {};
const currentComponents = Object.keys(currentComponentsDef);
setTimeout(() => {
if (currentComponents.length > 0) {
batchUpdateComponents(currentComponents);
}
}, 400);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentPageId]);
React.useEffect(() => { React.useEffect(() => {
if (lastUpdatedRef.length > 0) { if (lastUpdatedRef.length > 0) {
const currentComponents = appDefinition?.pages?.[currentPageId]?.components || {}; const currentComponents = appDefinition?.pages?.[currentPageId]?.components || {};

View file

@ -149,7 +149,10 @@ function findReferenceInComponent(node, changedCurrentState) {
if (typeof node === 'object') { if (typeof node === 'object') {
for (let key in node) { for (let key in node) {
const value = node[key]; const value = node[key];
if (typeof value === 'string' && value.includes('{{') && value.includes('}}')) { if (
typeof value === 'string' &&
((value.includes('{{') && value.includes('}}')) || value.includes('%%client'))
) {
// Check if the referenced entity is in the state // Check if the referenced entity is in the state
if (changedCurrentState.some((state) => value.includes(state))) { if (changedCurrentState.some((state) => value.includes(state))) {
return true; return true;

View file

@ -105,7 +105,7 @@ useCurrentStateStore.subscribe((state) => {
() => { () => {
useResolveStore.getState().actions.updateAppSuggestions({ useResolveStore.getState().actions.updateAppSuggestions({
queries: state.queries, queries: state.queries,
components: state.components, components: !isPageSwitched ? state.components : {},
globals: state.globals, globals: state.globals,
page: state.page, page: state.page,
variables: state.variables, variables: state.variables,
@ -113,7 +113,6 @@ useCurrentStateStore.subscribe((state) => {
server: state.server, server: state.server,
constants: state.constants, constants: state.constants,
}); });
useResolveStore.getState().actions.pageSwitched(false);
}, },
null, null,
isPageSwitched isPageSwitched

View file

@ -71,7 +71,7 @@ export const useResolveStore = create(
set(() => ({ ...state, storeReady: true })); set(() => ({ ...state, storeReady: true }));
}, },
resetStore: () => { resetStore: () => {
set(() => initialState); set(() => ({ ...initialState, referenceMapper: new ReferencesBiMap() }));
}, },
pageSwitched: (bool) => set(() => ({ isPageSwitched: bool })), pageSwitched: (bool) => set(() => ({ isPageSwitched: bool })),
updateAppSuggestions: (refState) => { updateAppSuggestions: (refState) => {

View file

@ -1 +1 @@
2.61.0 2.61.0