Skip to content

Commit

Permalink
Implement client viewers architecture (#132)
Browse files Browse the repository at this point in the history
  • Loading branch information
allyoucanmap authored Apr 20, 2021
1 parent 752f8d3 commit 9db0daa
Show file tree
Hide file tree
Showing 24 changed files with 2,144 additions and 48 deletions.
2 changes: 2 additions & 0 deletions geonode_mapstore_client/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#########################################################################
import os
from django.apps import AppConfig as BaseAppConfig
from django.views.generic import TemplateView

def run_setup_hooks(*args, **kwargs):
from geonode.urls import urlpatterns
Expand All @@ -22,6 +23,7 @@ def run_setup_hooks(*args, **kwargs):
urlpatterns += [
url(r'^mapstore/', include('mapstore2_adapter.urls')),
url(r'^', include('mapstore2_adapter.geoapps.geostories.api.urls')),
url(r'^viewer/', TemplateView.as_view(template_name='geonode-mapstore-client/viewer.html')),
]


Expand Down
41 changes: 41 additions & 0 deletions geonode_mapstore_client/client/js/actions/gnviewer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2021, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

export const REQUEST_LAYER_CONFIG = 'GEONODE_VIEWER:REQUEST_LAYER_CONFIG';
export const REQUEST_MAP_CONFIG = 'GEONODE_VIEWER:REQUEST_MAP_CONFIG';
export const REQUEST_GEOSTORY_CONFIG = 'GEONODE_VIEWER:REQUEST_GEOSTORY_CONFIG';
export const REQUEST_DOCUMENT_CONFIG = 'GEONODE_VIEWER:REQUEST_DOCUMENT_CONFIG';

export function requestLayerConfig(pk) {
return {
type: REQUEST_LAYER_CONFIG,
pk
};
}

export function requestMapConfig(pk) {
return {
type: REQUEST_MAP_CONFIG,
pk
};
}

export function requestGeoStoryConfig(pk) {
return {
type: REQUEST_GEOSTORY_CONFIG,
pk
};
}

export function requestDocumentConfig(pk) {
return {
type: REQUEST_DOCUMENT_CONFIG,
pk
};
}

18 changes: 18 additions & 0 deletions geonode_mapstore_client/client/js/api/geonode/config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright 2021, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

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

export const getBaseMapConfiguration = (baseMapUrl = '/static/mapstore/configs/map.json') => {
return axios.get(baseMapUrl)
.then(({ data }) => data);
};

export default {
getBaseMapConfiguration
};
34 changes: 33 additions & 1 deletion geonode_mapstore_client/client/js/api/geonode/v2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,16 @@ export const getResourceByPk = (pk) => {
.then(({ data }) => data.resource);
};

export const getLayerByPk = (pk) => {
return axios.get(parseDevHostname(`${endpoints[LAYERS]}/${pk}`))
.then(({ data }) => data.layer);
};

export const getDocumentByPk = (pk) => {
return axios.get(parseDevHostname(`${endpoints[DOCUMENTS]}/${pk}`))
.then(({ data }) => data.document);
};

export const createGeoApp = (body) => {
return axios.post(parseDevHostname(`${endpoints[GEOAPPS]}`), body, {
params: {
Expand All @@ -240,6 +250,15 @@ export const createGeoApp = (body) => {
.then(({ data }) => data.resource);
};

export const getGeoAppByPk = (pk) => {
return axios.get(parseDevHostname(`${endpoints[GEOAPPS]}/${pk}`), {
params: {
full: true
}
})
.then(({ data }) => data.geoapp);
};

export const createGeoStory = (body) => {
return axios.post(parseDevHostname(`${endpoints[GEOSTORIES]}`), body, {
params: {
Expand All @@ -249,6 +268,15 @@ export const createGeoStory = (body) => {
.then(({ data }) => data.geostory);
};

export const getGeoStoryByPk = (pk) => {
return axios.get(parseDevHostname(`${endpoints[GEOSTORIES]}/${pk}`), {
params: {
include: ['data']
}
})
.then(({ data }) => data.geostory);
};

export const updateGeoStory = (pk, body) => {
return axios.patch(parseDevHostname(`${endpoints[GEOSTORIES]}/${pk}`), body, {
params: {
Expand Down Expand Up @@ -371,13 +399,17 @@ export default {
getResources,
getResourceByPk,
createGeoApp,
getGeoAppByPk,
createGeoStory,
getGeoStoryByPk,
updateGeoStory,
getMaps,
getDocumentsByDocType,
getUserByPk,
getAccountInfo,
getConfiguration,
getResourceTypes,
getResourcesTotalCount
getResourcesTotalCount,
getLayerByPk,
getDocumentByPk
};
232 changes: 232 additions & 0 deletions geonode_mapstore_client/client/js/apps/gn-viewer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
/*
* Copyright 2021, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

import main from '@mapstore/framework/components/app/main';
import Router, { withRoutes } from '@js/components/app/Router';
import MainLoader from '@js/components/app/MainLoader';
import { connect } from 'react-redux';
import { getConfigProp, setConfigProp } from '@mapstore/framework/utils/ConfigUtils';
import { loadPrintCapabilities } from '@mapstore/framework/actions/print';
import StandardApp from '@mapstore/framework/components/app/StandardApp';
import geostory from '@mapstore/framework/reducers/geostory';
import withExtensions from '@mapstore/framework/components/app/withExtensions';

// the app needs this epics and reducers from mapstore to correctly initialize some functionalities
import controls from '@mapstore/framework/reducers/controls';
import maptype from '@mapstore/framework/reducers/maptype';
import security from '@mapstore/framework/reducers/security';
import print from '@mapstore/framework/reducers/print';
import {
standardReducers,
standardEpics,
standardRootReducerFunc
} from '@mapstore/framework/stores/defaultOptions';

import timeline from '@mapstore/framework/reducers/timeline';
import dimension from '@mapstore/framework/reducers/dimension';
import playback from '@mapstore/framework/reducers/playback';
import mapPopups from '@mapstore/framework/reducers/mapPopups';
import catalog from '@mapstore/framework/reducers/catalog';
import searchconfig from '@mapstore/framework/reducers/searchconfig';
import widgets from '@mapstore/framework/reducers/widgets';
// end

import LayerViewerRoute from '@js/routes/LayerViewer';
import MapViewerRoute from '@js/routes/MapViewer';
import GeoStoryViewerRoute from '@js/routes/GeoStoryViewer';
import DocumentViewerRoute from '@js/routes/DocumentViewer';

import gnresource from '@js/reducers/gnresource';
import gnsettings from '@js/reducers/gnsettings';

import {
getConfiguration,
getEndpoints,
getAccountInfo
} from '@js/api/geonode/v2';

import {
setupConfiguration,
getVersion,
initializeApp,
getPluginsConfiguration
} from '@js/utils/AppUtils';

import { updateGeoNodeSettings } from '@js/actions/gnsettings';

import {
updateMapLayoutEpic,
_setFeatureEditPermission,
_setStyleEditorPermission
} from '@js/epics';
import gnviewerEpics from '@js/epics/gnviewer';
import maplayout from '@mapstore/framework/reducers/maplayout';
import 'react-widgets/dist/css/react-widgets.css';
import 'react-select/dist/react-select.css';

import pluginsDefinition from '@js/plugins/index';
import ReactSwipe from 'react-swipeable-views';
import SwipeHeader from '@mapstore/framework/components/data/identify/SwipeHeader';
const requires = {
ReactSwipe,
SwipeHeader
};

const DEFAULT_LOCALE = {};
const ConnectedRouter = connect((state) => ({
locale: state?.locale || DEFAULT_LOCALE
}))(Router);

const routes = [
{
name: 'layer_viewer',
path: [
'/layer/:pk'
],
component: LayerViewerRoute
},
{
name: 'layer_edit_data_viewer',
path: [
'/layer/:pk/edit/data'
],
component: LayerViewerRoute
},
{
name: 'layer_edit_style_viewer',
path: [
'/layer/:pk/edit/style'
],
component: LayerViewerRoute
},
{
name: 'map_viewer',
path: [
'/map/:pk'
],
component: MapViewerRoute
},
{
name: 'geostory_viewer',
path: [
'/geostory/:pk'
],
component: GeoStoryViewerRoute
},
{
name: 'document_viewer',
path: [
'/document/:pk'
],
component: DocumentViewerRoute
}
];

initializeApp();

Promise.all([
getConfiguration(),
getAccountInfo(),
getEndpoints()
])
.then(([localConfig, user]) => {
const {
securityState,
geoNodeConfiguration,
pluginsConfigKey,
query,
configEpics,
mapType = 'openlayers',
onStoreInit,
targetId = 'ms-container',
settings
} = setupConfiguration({
localConfig,
user
});

// get the correct map layout
const mapLayout = getConfigProp('mapLayout') || {};
setConfigProp('mapLayout', mapLayout[query.theme] || mapLayout.viewer);

// register custom arcgis layer
import('@js/components/' + mapType + '/ArcGisMapServer')
.then(() => {
main({
targetId,
enableExtensions: true,
appComponent: withRoutes(routes)(ConnectedRouter),
loaderComponent: MainLoader,
initialState: {
defaultState: {
...securityState,
maptype: {
mapType
}
}
},
themeCfg: {
path: '/static/mapstore/dist/themes',
prefixContainer: '#' + targetId,
version: getVersion(),
prefix: 'msgapi',
theme: query.theme
},
pluginsConfig: getPluginsConfiguration(localConfig.plugins, pluginsConfigKey),
lazyPlugins: pluginsDefinition.lazyPlugins,
pluginsDef: {
plugins: {
...pluginsDefinition.plugins
},
requires: {
...requires,
...pluginsDefinition.requires
}
},
printEnabled: true,
rootReducerFunc: standardRootReducerFunc,
onStoreInit,
appReducers: {
...standardReducers,
gnresource,
gnsettings,
security,
maptype,
print,
maplayout,
controls,
timeline,
dimension,
playback,
mapPopups,
catalog,
searchconfig,
widgets,
geostory,
...pluginsDefinition.reducers
},
appEpics: {
...standardEpics,
...configEpics,
updateMapLayoutEpic,
_setFeatureEditPermission,
_setStyleEditorPermission,
...pluginsDefinition.epics,
...gnviewerEpics
},
geoNodeConfiguration,
initialActions: [
// add some settings in the global state to make them accessible in the monitor state
// later we could use expression in localConfig
updateGeoNodeSettings.bind(null, settings),
loadPrintCapabilities.bind(null, getConfigProp('printUrl'))
]
},
withExtensions(StandardApp));
});
});
Loading

0 comments on commit 9db0daa

Please sign in to comment.