diff --git a/geonode_mapstore_client/client/MapStore2 b/geonode_mapstore_client/client/MapStore2 index 16008b14d2..c7a5ee21f1 160000 --- a/geonode_mapstore_client/client/MapStore2 +++ b/geonode_mapstore_client/client/MapStore2 @@ -1 +1 @@ -Subproject commit 16008b14d275b1f816e1641fa540f6230dde2f24 +Subproject commit c7a5ee21f10b36805cc7e07fc50b95a349ec3c05 diff --git a/geonode_mapstore_client/client/js/api/geonode/v2/index.js b/geonode_mapstore_client/client/js/api/geonode/v2/index.js index 0362f2ccd9..ae1ad3ee8d 100644 --- a/geonode_mapstore_client/client/js/api/geonode/v2/index.js +++ b/geonode_mapstore_client/client/js/api/geonode/v2/index.js @@ -382,11 +382,13 @@ export const getUsers = ({ q, page = 1, pageSize = 20, + config, ...params } = {}) => { return axios.get( getEndpointUrl(USERS), { + ...config, params: { ...params, ...(q && { @@ -411,11 +413,13 @@ export const getGroups = ({ q, page = 1, pageSize = 20, + config, ...params } = {}) => { return axios.get( getEndpointUrl(GROUPS), { + ...config, params: { ...params, ...(q && { diff --git a/geonode_mapstore_client/client/js/epics/__tests__/gnsave-test.js b/geonode_mapstore_client/client/js/epics/__tests__/gnsave-test.js index 4ddefa3268..d75436f0db 100644 --- a/geonode_mapstore_client/client/js/epics/__tests__/gnsave-test.js +++ b/geonode_mapstore_client/client/js/epics/__tests__/gnsave-test.js @@ -33,6 +33,7 @@ import { SET_EDIT_PERMISSION } from '@mapstore/framework/actions/styleeditor'; import { configureMap } from '@mapstore/framework/actions/config'; import { selectNode, addLayer } from '@mapstore/framework/actions/layers'; +import { START_ASYNC_PROCESS } from '@js/actions/resourceservice'; let mockAxios; @@ -49,6 +50,93 @@ describe('gnsave epics', () => { setTimeout(done); }); it('should create new map with success (gnSaveContent)', (done) => { + const NUM_ACTIONS = 5; + const metadata = { + title: 'Title', + description: 'Description', + thumbnail: 'thumbnail.jpeg' + }; + mockAxios.onPost().reply(() => [200, { map: {} }]); + mockAxios.onPut().reply(() => [200, { output: {} }]); + testEpic( + gnSaveContent, + NUM_ACTIONS, + saveContent(undefined, metadata, false), + (actions) => { + try { + expect(actions.map(({ type }) => type)) + .toEqual([ + SAVING_RESOURCE, + SAVE_SUCCESS, + SET_RESOURCE, + UPDATE_SINGLE_RESOURCE, + START_ASYNC_PROCESS + ]); + } catch (e) { + done(e); + } + done(); + }, + { + gnresource: { + data: { + resource_type: "map" + }, + isCompactPermissionsChanged: true, + compactPermissions: { + users: [], + organizations: [], + groups: [] + } + } + } + ); + }); + it('should update existing map with success (gnSaveContent)', (done) => { + const NUM_ACTIONS = 5; + const id = 1; + const metadata = { + title: 'Title', + description: 'Description', + thumbnail: 'thumbnail.jpeg' + }; + mockAxios.onPatch().reply(() => [200, {}]); + mockAxios.onPut().reply(() => [200, { output: {} }]); + testEpic( + gnSaveContent, + NUM_ACTIONS, + saveContent(id, metadata, false, false), + (actions) => { + try { + expect(actions.map(({ type }) => type)) + .toEqual([ + SAVING_RESOURCE, + SAVE_SUCCESS, + SET_RESOURCE, + UPDATE_SINGLE_RESOURCE, + START_ASYNC_PROCESS + ]); + } catch (e) { + done(e); + } + done(); + }, + { + gnresource: { + data: { + resource_type: "map" + }, + isCompactPermissionsChanged: true, + compactPermissions: { + users: [], + organizations: [], + groups: [] + } + } + } + ); + }); + it('should skip permission update when permission is unchanged', (done) => { const NUM_ACTIONS = 4; const metadata = { title: 'Title', @@ -56,6 +144,7 @@ describe('gnsave epics', () => { thumbnail: 'thumbnail.jpeg' }; mockAxios.onPost().reply(() => [200, { map: {} }]); + mockAxios.onPut().reply(() => [200, { output: {} }]); testEpic( gnSaveContent, NUM_ACTIONS, @@ -110,7 +199,15 @@ describe('gnsave epics', () => { }, { gnresource: { - type: "map" + data: { + resource_type: "map" + }, + isCompactPermissionsChanged: false, + compactPermissions: { + users: [], + organizations: [], + groups: [] + } } } ); @@ -170,7 +267,7 @@ describe('gnsave epics', () => { 'thumbnail_url': 'thumbnail.jpeg' }; mockAxios.onGet(new RegExp(`resources/${pk}`)) - .reply(200, resource); + .reply(200, {resource}); testEpic( gnSaveDirectContent, NUM_ACTIONS, diff --git a/geonode_mapstore_client/client/js/epics/gnsave.js b/geonode_mapstore_client/client/js/epics/gnsave.js index 98a936bb08..30e9b7d49b 100644 --- a/geonode_mapstore_client/client/js/epics/gnsave.js +++ b/geonode_mapstore_client/client/js/epics/gnsave.js @@ -204,9 +204,10 @@ export const gnSaveContent = (action$, store) => const extent = getExtentPayload(state, contentType); const body = { 'title': action.metadata.name, - ...(RESOURCE_MANAGEMENT_PROPERTIES_KEYS.reduce((acc, key) => { + ...([...RESOURCE_MANAGEMENT_PROPERTIES_KEYS, 'group'].reduce((acc, key) => { if (currentResource?.[key] !== undefined) { - acc[key] = !!currentResource[key]; + const value = typeof currentResource[key] === 'boolean' ? !!currentResource[key] : currentResource[key]; + acc[key] = value; } return acc; }, {})), @@ -312,6 +313,8 @@ export const gnSaveDirectContent = (action$, store) => const resourceId = mapInfo?.id || getResourceId(state); const { geoLimits } = getPermissionsPayload(state); + // resource information should be saved in a synchronous manner + // i.e update resource data followed by permissions return Observable.defer(() => axios.all([ getResourceByPk(resourceId), ...(geoLimits diff --git a/geonode_mapstore_client/client/js/plugins/ResourceDetails/components/DetailsSettings.jsx b/geonode_mapstore_client/client/js/plugins/ResourceDetails/components/DetailsSettings.jsx index c88cda7545..ba227b3d97 100644 --- a/geonode_mapstore_client/client/js/plugins/ResourceDetails/components/DetailsSettings.jsx +++ b/geonode_mapstore_client/client/js/plugins/ResourceDetails/components/DetailsSettings.jsx @@ -1,10 +1,13 @@ import React, { forwardRef } from 'react'; -import { Checkbox } from 'react-bootstrap'; +import { Checkbox, FormGroup, ControlLabel } from 'react-bootstrap'; + import Message from '@mapstore/framework/components/I18N/Message'; import tooltip from '@mapstore/framework/components/misc/enhancers/tooltip'; -import { canAccessPermissions, canManageResourceSettings, RESOURCE_MANAGEMENT_PROPERTIES } from '@js/utils/ResourceUtils'; import FlexBox from '@mapstore/framework/components/layout/FlexBox'; import Text from '@mapstore/framework/components/layout/Text'; +import SelectInfiniteScroll from '@mapstore/framework/plugins/ResourcesCatalog/components/SelectInfiniteScroll'; +import { getGroups } from '@js/api/geonode/v2'; +import { canAccessPermissions, canManageResourceSettings, RESOURCE_MANAGEMENT_PROPERTIES } from '@js/utils/ResourceUtils'; import DetailsPermissions from '@js/plugins/ResourceDetails/containers/Permissions'; const MessageTooltip = tooltip(forwardRef(({children, msgId, ...props}, ref) => { @@ -20,6 +23,30 @@ const MessageTooltip = tooltip(forwardRef(({children, msgId, ...props}, ref) => function DetailsSettings({ resource, onChange }) { return ( + + + + onChange({ group: selected?.value ?? null})} + loadOptions={({ q, ...params }) => getGroups({q, ...params}) + .then((response) => { + return { + ...response, + results: (response?.groups ?? []) + .map((item) => ({...item, selectOption: { + value: item.group, + label: item.group.name + }})) + }; + }) + } + /> + + {canAccessPermissions(resource) && } {canManageResourceSettings(resource) && ( diff --git a/geonode_mapstore_client/client/js/selectors/resource.js b/geonode_mapstore_client/client/js/selectors/resource.js index a50f3e950a..56cb720f21 100644 --- a/geonode_mapstore_client/client/js/selectors/resource.js +++ b/geonode_mapstore_client/client/js/selectors/resource.js @@ -334,7 +334,7 @@ export const getResourceDirtyState = (state) => { return null; } const resourceType = state?.gnresource?.type; - let metadataKeys = ['title', 'abstract', 'data', 'extent', ...RESOURCE_MANAGEMENT_PROPERTIES_KEYS]; + let metadataKeys = ['title', 'abstract', 'data', 'extent', 'group', ...RESOURCE_MANAGEMENT_PROPERTIES_KEYS]; if (resourceType === ResourceTypes.DATASET) { metadataKeys = metadataKeys.concat('timeseries'); } diff --git a/geonode_mapstore_client/client/js/utils/ResourceUtils.js b/geonode_mapstore_client/client/js/utils/ResourceUtils.js index 07c65e9cc7..afaf89462a 100644 --- a/geonode_mapstore_client/client/js/utils/ResourceUtils.js +++ b/geonode_mapstore_client/client/js/utils/ResourceUtils.js @@ -8,15 +8,15 @@ import uuid from 'uuid'; import url from 'url'; -import isEmpty from 'lodash/isEmpty'; -import omit from 'lodash/omit'; +import { isEmpty, uniqBy, omit, orderBy, isString, isObject } from 'lodash'; + +import { isImageServerUrl } from '@mapstore/framework/utils/ArcGISUtils'; import { getConfigProp, convertFromLegacy, normalizeConfig } from '@mapstore/framework/utils/ConfigUtils'; +import { excludeGoogleBackground, extractTileMatrixFromSources, ServerTypes } from '@mapstore/framework/utils/LayersUtils'; + import { getGeoNodeLocalConfig, parseDevHostname } from '@js/utils/APIUtils'; import { ProcessTypes, ProcessStatus } from '@js/utils/ResourceServiceUtils'; -import { uniqBy, orderBy, isString, isObject } from 'lodash'; -import { excludeGoogleBackground, extractTileMatrixFromSources, ServerTypes } from '@mapstore/framework/utils/LayersUtils'; import { determineResourceType } from '@js/utils/FileUtils'; -import { isImageServerUrl } from '@mapstore/framework/utils/ArcGISUtils'; /** * @module utils/ResourceUtils diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.de-DE.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.de-DE.json index 4602b5ff1f..4a82ebb70a 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.de-DE.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.de-DE.json @@ -202,6 +202,8 @@ "filterBy": "Filtern...", "addPermissionsEntry": "Benutzer / Gruppen hinzufügen", "groups": "Gruppen", + "group": "Gruppe", + "groupPlaceholder": "Gruppe auswählen", "users": "Benutzer", "nonePermission": "Keiner", "viewPermission": "Ansicht", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.en-US.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.en-US.json index 14370eebde..8ce157bc23 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.en-US.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.en-US.json @@ -201,6 +201,8 @@ "data": "Data", "filterBy": "Filter...", "addPermissionsEntry": "Add Users / Groups", + "group": "Group", + "groupPlaceholder": "Select group", "groups": "Groups", "users": "Users", "nonePermission": "None", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.es-ES.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.es-ES.json index 82e77799ff..696e7d7750 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.es-ES.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.es-ES.json @@ -202,6 +202,8 @@ "filterBy": "Filtro ...", "addPermissionsEntry": "Agregar usuarios / grupos", "groups": "Grupos", + "group": "Grupo", + "groupPlaceholder": "Seleccionar grupo", "users": "Usuarios", "nonePermission": "Ninguno", "viewPermission": "Ver", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.fi-FI.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.fi-FI.json index fe951b1492..3e54cbef53 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.fi-FI.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.fi-FI.json @@ -200,6 +200,8 @@ "filterBy": "Filter...", "addPermissionsEntry": "Add Users / Groups", "groups": "Groups", + "group": "Group", + "groupPlaceholder": "Select group", "users": "Users", "nonePermission": "None", "viewPermission": "View", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.fr-FR.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.fr-FR.json index 26d14bba93..593e36f544 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.fr-FR.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.fr-FR.json @@ -202,6 +202,8 @@ "filterBy": "Filtrer...", "addPermissionsEntry": "Ajouter des utilisateurs/groupes", "groups": "Groupes", + "group": "Groupe", + "groupPlaceholder": "Sélectionner un groupe", "users": "Utilisateurs", "nonePermission": "Rien", "viewPermission": "View", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.hr-HR.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.hr-HR.json index 98d4d03529..d9ee519401 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.hr-HR.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.hr-HR.json @@ -200,6 +200,8 @@ "filterBy": "Filter...", "addPermissionsEntry": "Add Users / Groups", "groups": "Groups", + "group": "Group", + "groupPlaceholder": "Select group", "users": "Users", "nonePermission": "None", "viewPermission": "View", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.it-IT.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.it-IT.json index 1e21f2818c..f650fa0ba0 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.it-IT.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.it-IT.json @@ -204,6 +204,8 @@ "filterBy": "Filtra...", "addPermissionsEntry": "Aggiungi utenti/gruppi", "groups": "Gruppi", + "group": "Gruppo", + "groupPlaceholder": "Seleziona gruppo", "users": "Utenti", "nonePermission": "Nessuno", "viewPermission": "Visualizza", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.nl-NL.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.nl-NL.json index a2984dcf75..656a6cc0cd 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.nl-NL.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.nl-NL.json @@ -200,6 +200,8 @@ "filterBy": "Filter...", "addPermissionsEntry": "Add Users / Groups", "groups": "Groups", + "group": "Group", + "groupPlaceholder": "Select group", "users": "Users", "nonePermission": "None", "viewPermission": "View", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.pt-PT.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.pt-PT.json index 44e3a0decf..053ab40c22 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.pt-PT.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.pt-PT.json @@ -200,6 +200,8 @@ "filterBy": "Filter...", "addPermissionsEntry": "Add Users / Groups", "groups": "Groups", + "group": "Group", + "groupPlaceholder": "Select group", "users": "Users", "nonePermission": "None", "viewPermission": "View", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.sk-SK.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.sk-SK.json index f10bb39317..4c50af2d1a 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.sk-SK.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.sk-SK.json @@ -200,6 +200,8 @@ "filterBy": "Filter...", "addPermissionsEntry": "Add Users / Groups", "groups": "Groups", + "group": "Group", + "groupPlaceholder": "Select group", "users": "Users", "nonePermission": "None", "viewPermission": "View", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.sv-SE.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.sv-SE.json index cf74e49de9..f22267c045 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.sv-SE.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.sv-SE.json @@ -201,6 +201,8 @@ "filterBy": "Filter...", "addPermissionsEntry": "Add Users / Groups", "groups": "Groups", + "group": "Group", + "groupPlaceholder": "Select group", "users": "Users", "nonePermission": "None", "viewPermission": "View", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.vi-VN.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.vi-VN.json index 1668849e71..cbc38237b4 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.vi-VN.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.vi-VN.json @@ -200,6 +200,8 @@ "filterBy": "Filter...", "addPermissionsEntry": "Add Users / Groups", "groups": "Groups", + "group": "Group", + "groupPlaceholder": "Select group", "users": "Users", "nonePermission": "None", "viewPermission": "View", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.zh-ZH.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.zh-ZH.json index 6c5c8cfa20..0eb0523820 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.zh-ZH.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.zh-ZH.json @@ -200,6 +200,8 @@ "filterBy": "Filter...", "addPermissionsEntry": "Add Users / Groups", "groups": "Groups", + "group": "Group", + "groupPlaceholder": "Select group", "users": "Users", "nonePermission": "None", "viewPermission": "View",