Skip to content

Commit

Permalink
optimize request while routing (#545)
Browse files Browse the repository at this point in the history
  • Loading branch information
allyoucanmap authored Oct 22, 2021
1 parent 8b89c61 commit c0e52e6
Show file tree
Hide file tree
Showing 7 changed files with 350 additions and 108 deletions.
26 changes: 22 additions & 4 deletions geonode_mapstore_client/client/js/api/geonode/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,32 @@

import axios from '@mapstore/framework/libs/ajax';

let cache = {};

export const getNewMapConfiguration = (newMapUrl = '/static/mapstore/configs/map.json') => {
return axios.get(newMapUrl)
.then(({ data }) => window.overrideNewMapConfig ? window.overrideNewMapConfig(data) : data);
return cache.newMapConfig
? new Promise((resolve) => resolve(cache.newMapConfig))
: axios.get(newMapUrl).then(({ data }) => {
cache.newMapConfig = data;
return data;
})
.then((newMapConfig) => window.overrideNewMapConfig
? window.overrideNewMapConfig(newMapConfig)
: newMapConfig
);
};

export const getNewGeoStoryConfig = (newGeoStoryUrl = '/static/mapstore/configs/geostory.json') => {
return axios.get(newGeoStoryUrl)
.then(({ data }) => window.overrideNewGeoStoryConfig ? window.overrideNewGeoStoryConfig(data) : data);
return cache.newGeoStoryConfig
? new Promise((resolve) => resolve(cache.newGeoStoryConfig))
: axios.get(newGeoStoryUrl).then(({ data }) => {
cache.newGeoStoryConfig = data;
return data;
})
.then((newGeoStoryConfig) => window.overrideNewGeoStoryConfig
? window.overrideNewGeoStoryConfig(newGeoStoryConfig)
: newGeoStoryConfig
);
};

export default {
Expand Down
39 changes: 26 additions & 13 deletions geonode_mapstore_client/client/js/epics/gnresource.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ import {
resourceToLayerConfig,
ResourceTypes
} from '@js/utils/ResourceUtils';
import { canAddResource } from '@js/selectors/resource';
import {
canAddResource,
getResourceData
} from '@js/selectors/resource';
import { updateAdditionalLayer } from '@mapstore/framework/actions/additionallayers';
import { STYLE_OWNER_NAME } from '@mapstore/framework/utils/StyleEditorUtils';
import StylesAPI from '@mapstore/framework/api/geoserver/Styles';
Expand All @@ -74,7 +77,9 @@ const resourceTypes = {
return Observable.defer(() =>
axios.all([
getNewMapConfiguration(),
getDatasetByPk(pk)
options?.isSamePreviousResource
? new Promise(resolve => resolve(options.resourceData))
: getDatasetByPk(pk)
])
.then((response) => {
const [mapConfig, gnLayer] = response;
Expand Down Expand Up @@ -229,9 +234,9 @@ const resourceTypes = {
};

// collect all the reset action needed before changing a viewer
const getResetActions = () => [
const getResetActions = (isSameResource) => [
resetControls(),
resetResourceState(),
...(!isSameResource ? [ resetResourceState() ] : []),
setControlProperty('rightOverlay', 'enabled', false)
];

Expand Down Expand Up @@ -301,19 +306,25 @@ export const gnViewerRequestResourceConfig = (action$, store) =>
);
}
const styleService = styleServiceSelector(state);
const resourceData = getResourceData(state);
const isSamePreviousResource = !resourceData?.['@ms-detail'] && resourceData?.pk === action.pk;
return Observable.concat(
Observable.of(
...getResetActions(),
...getResetActions(isSamePreviousResource),
loadingResourceConfig(true),
setResourceType(action.resourceType)
),
Observable.defer(() => getCompactPermissionsByPk(action.pk))
.switchMap((compactPermissions) => {
return Observable.of(setResourceCompactPermissions(compactPermissions));
})
.catch(() => {
return Observable.empty();
}),
...(!isSamePreviousResource
? [
Observable.defer(() => getCompactPermissionsByPk(action.pk))
.switchMap((compactPermissions) => {
return Observable.of(setResourceCompactPermissions(compactPermissions));
})
.catch(() => {
return Observable.empty();
})
]
: []),
...(styleService?.baseUrl
? [Observable.defer(() => updateStyleService({
styleService
Expand All @@ -327,7 +338,9 @@ export const gnViewerRequestResourceConfig = (action$, store) =>
// set the pending changes as the new data fro maps, dashboards and geostories
// if undefined the returned data will be used
data: pendingChanges?.data,
styleService: styleServiceSelector(state)
styleService: styleServiceSelector(state),
isSamePreviousResource,
resourceData
}),
Observable.of(
...(pendingChanges?.resource ? [updateResourceProperties(pendingChanges.resource)] : []),
Expand Down
12 changes: 10 additions & 2 deletions geonode_mapstore_client/client/js/epics/gnsearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,15 +214,23 @@ export const gnsSelectResourceEpic = (action$, store) =>
pk === action.pk && action.ctype === resourceType);
return Observable.defer(() => getResourceByPk(action.pk))
.switchMap((resource) => {
return Observable.of(setResource(resource));
return Observable.of(setResource({
...resource,
/* store information related to detail */
'@ms-detail': true
}));
})
.catch((error) => {
return Observable.of(resourceError(error.data || error.message));
})
.startWith(
// preload the resource if available
...(selectedResource
? [ setResource(selectedResource) ]
? [ setResource({
...selectedResource,
/* store information related to detail */
'@ms-detail': true
}) ]
: [ resourceLoading() ])
);
});
Expand Down
59 changes: 22 additions & 37 deletions geonode_mapstore_client/client/js/hooks/useLazyPlugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import { useEffect, useState } from 'react';
import isEmpty from 'lodash/isEmpty';
import { getPlugins } from '@mapstore/framework/utils/PluginsUtils';
import { getPlugins, createPlugin } from '@mapstore/framework/utils/PluginsUtils';
import { augmentStore } from '@mapstore/framework/utils/StateUtils';
import join from 'lodash/join';

Expand All @@ -24,6 +24,7 @@ function filterRemoved(registry, removed = []) {
}, {});
}

let storedPlugins = {};
const pluginsCache = {};
const epicsCache = {};
const reducersCache = {};
Expand All @@ -43,18 +44,20 @@ function useLazyPlugins({
const pluginsString = join(pluginsKeys, ',');

useEffect(() => {
if (!pluginsCache[pluginsString]) {
const filteredPluginsKeys = pluginsKeys
.filter((pluginName) => !pluginsCache[pluginName]);
if (filteredPluginsKeys.length > 0) {
setPending(true);
Promise.all(
pluginsKeys.map(pluginName => {
const loadPlugins = filteredPluginsKeys
.map(pluginName => {
return pluginsEntries[pluginName]().then((mod) => {
const impl = mod.default;
return impl;
});
})
)
});
Promise.all(loadPlugins)
.then((impls) => {
const { reducers, epics } = pluginsKeys.reduce((acc, pluginName, idx) => {
const { reducers, epics } = filteredPluginsKeys.reduce((acc, pluginName, idx) => {
const impl = impls[idx];
return {
reducers: {
Expand Down Expand Up @@ -104,45 +107,27 @@ function useLazyPlugins({
epics: filterOutExistingEpics
});
}

return pluginsKeys.map((pluginName, idx) => {
const { loadPlugin, enabler, ...impl } = impls[idx];
const pluginDef = {
[pluginName]: {
[pluginName]: {
...impl.containers,
...(enabler && { enabler }),
loadPlugin: loadPlugin
? (resolve) => loadPlugin((component) => {
resolve({ ...impl, component });
})
: (resolve) => {
resolve(impl);
}
}
}
};
return { plugin: pluginDef };
return getPlugins({
...filterRemoved(impls.map(impl => createPlugin(impl.name, impl)), removed)
});
})
.then((loaded) => {
pluginsCache[pluginsString] = getPlugins(
{
...filterRemoved(
loaded.reduce((previous, current) => ({ ...previous, ...current.plugin }), {}),
removed
)
}
);
setPlugins(pluginsCache[pluginsString]);
.then((newPlugins) => {
Object.keys(newPlugins).forEach(pluginName => {
pluginsCache[pluginName] = true;
});
storedPlugins = {
...storedPlugins,
...newPlugins
};
setPlugins(storedPlugins);
setPending(false);
})
.catch(() => {
setPlugins({});
setPending(false);
});
} else {
setPlugins(pluginsCache[pluginsString]);
setPlugins(storedPlugins);
}
}, [ pluginsString ]);

Expand Down
47 changes: 27 additions & 20 deletions geonode_mapstore_client/client/js/routes/Viewer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
* LICENSE file in the root directory of this source tree.
*/

import React, { useEffect, useState } from 'react';
import React, { useEffect, useMemo } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import url from 'url';
import isArray from 'lodash/isArray';
import { createSelector } from 'reselect';
import BorderLayout from '@mapstore/framework/components/layout/BorderLayout';
import { getMonitoredState } from '@mapstore/framework/utils/PluginsUtils';
import { getConfigProp } from '@mapstore/framework/utils/ConfigUtils';
Expand All @@ -20,17 +20,24 @@ import useLazyPlugins from '@js/hooks/useLazyPlugins';
import { requestResourceConfig, requestNewResourceConfig } from '@js/actions/gnresource';
import MetaTags from '@js/components/MetaTags';
import MainErrorView from '@js/components/MainErrorView';
import { createShallowSelector } from '@mapstore/framework/utils/ReselectUtils';

const urlQuery = url.parse(window.location.href, true).query;

const ConnectedPluginsContainer = connect((state) => ({
mode: urlQuery.mode || (urlQuery.mobile || state.browser && state.browser.mobile ? 'mobile' : 'desktop'),
monitoredState: getMonitoredState(state, getConfigProp('monitorState')),
pluginsState: {
...state.controls
}
}))(PluginsContainer);
const ConnectedPluginsContainer = connect(
createShallowSelector(
state => urlQuery.mode || (urlQuery.mobile || state.browser && state.browser.mobile ? 'mobile' : 'desktop'),
state => getMonitoredState(state, getConfigProp('monitorState')),
state => state?.controls,
(mode, monitoredState, controls) => ({
mode,
monitoredState,
pluginsState: controls
})
)
)(PluginsContainer);

const DEFAULT_PLUGINS_CONFIG = [];
function ViewerRoute({
name,
pluginsConfig: propPluginsConfig,
Expand All @@ -51,15 +58,15 @@ function ViewerRoute({
const { pk } = match.params || {};
const pluginsConfig = isArray(propPluginsConfig)
? propPluginsConfig
: propPluginsConfig && propPluginsConfig[name] || [];
: propPluginsConfig && propPluginsConfig[name] || DEFAULT_PLUGINS_CONFIG;

const [loading, setLoading] = useState(true);
const { plugins: loadedPlugins } = useLazyPlugins({

const { plugins: loadedPlugins, pending } = useLazyPlugins({
pluginsEntries: lazyPlugins,
pluginsConfig
});
useEffect(() => {
if (!loading && pk !== undefined) {
if (!pending && pk !== undefined) {
if (pk === 'new') {
onCreate(resourceType);
} else {
Expand All @@ -68,30 +75,30 @@ function ViewerRoute({
});
}
}
}, [loading, pk]);
}, [pending, pk]);

const parsedPlugins = useMemo(() => ({ ...loadedPlugins, ...plugins }), [loadedPlugins]);
const Loader = loaderComponent;

return (
<>
{resource && <MetaTags
{resource && <MetaTags
logo={resource.thumbnail_url}
title={(resource?.title) ? `${resource?.title} - ${siteName}` : siteName }
siteName={siteName}
contentURL={resource?.detail_url}
content={resource?.abstract}
/>}
<ConnectedPluginsContainer
{(!pending) && <ConnectedPluginsContainer
key={`page-${resourceType}-viewer`}
id={`page-${resourceType}-viewer`}
className={`page page-${resourceType}-viewer`}
component={BorderLayout}
pluginsConfig={pluginsConfig}
plugins={{ ...loadedPlugins, ...plugins }}
plugins={parsedPlugins}
params={params}
onPluginsLoaded={() => setLoading(false)}
/>
{( loading || loadingConfig ) && Loader && <Loader />}
/>}
{( loadingConfig || pending ) && Loader && <Loader />}
{configError && <MainErrorView msgId={configError}/>}
</>
);
Expand Down
Loading

0 comments on commit c0e52e6

Please sign in to comment.