@@ -10,6 +10,7 @@ import axios from '@mapstore/framework/libs/ajax';
10
10
import { Observable } from 'rxjs' ;
11
11
import get from 'lodash/get' ;
12
12
import castArray from 'lodash/castArray' ;
13
+ import isEqual from 'lodash/isEqual' ;
13
14
14
15
import { mapInfoSelector } from '@mapstore/framework/selectors/map' ;
15
16
import { userSelector } from '@mapstore/framework/selectors/security' ;
@@ -76,17 +77,18 @@ import {
76
77
cleanCompactPermissions ,
77
78
toGeoNodeMapConfig ,
78
79
RESOURCE_MANAGEMENT_PROPERTIES ,
79
- getDimensions
80
+ getDimensions ,
81
+ GROUP_OWNER_PROPERTIES
80
82
} from '@js/utils/ResourceUtils' ;
81
83
import {
82
84
ProcessTypes ,
83
85
ProcessStatus
84
86
} from '@js/utils/ResourceServiceUtils' ;
85
- import { updateDatasetTimeSeries } from '@js/api/geonode/v2/index' ;
87
+ import { transferResource , updateDatasetTimeSeries } from '@js/api/geonode/v2/index' ;
86
88
import { updateNode } from '@mapstore/framework/actions/layers' ;
87
89
import { layersSelector } from '@mapstore/framework/selectors/layers' ;
88
90
89
- const RESOURCE_MANAGEMENT_PROPERTIES_KEYS = Object . keys ( RESOURCE_MANAGEMENT_PROPERTIES ) ;
91
+ const RESOURCE_MANAGEMENT_PROPERTIES_KEYS = Object . keys ( { ... RESOURCE_MANAGEMENT_PROPERTIES , ... GROUP_OWNER_PROPERTIES } ) ;
90
92
91
93
function parseMapBody ( body ) {
92
94
const geoNodeMap = toGeoNodeMapConfig ( body . data ) ;
@@ -169,11 +171,13 @@ export const gnSaveContent = (action$, store) =>
169
171
const contentType = state . gnresource ?. type || currentResource ?. resource_type ;
170
172
const data = ! currentResource ?. [ '@ms-detail' ] ? getDataPayload ( state , contentType ) : null ;
171
173
const extent = getExtentPayload ( state , contentType ) ;
174
+ const { compactPermissions } = getPermissionsPayload ( state ) ;
172
175
const body = {
173
176
'title' : action . metadata . name ,
174
177
...( RESOURCE_MANAGEMENT_PROPERTIES_KEYS . reduce ( ( acc , key ) => {
175
178
if ( currentResource ?. [ key ] !== undefined ) {
176
- acc [ key ] = ! ! currentResource [ key ] ;
179
+ const value = typeof currentResource [ key ] === 'boolean' ? ! ! currentResource [ key ] : currentResource [ key ] ;
180
+ acc [ key ] = value ;
177
181
}
178
182
return acc ;
179
183
} , { } ) ) ,
@@ -193,22 +197,34 @@ export const gnSaveContent = (action$, store) =>
193
197
window . location . reload ( ) ;
194
198
return Observable . empty ( ) ;
195
199
}
196
- return Observable . of (
197
- saveSuccess ( resource ) ,
198
- setResource ( {
199
- ...currentResource ,
200
- ...body ,
201
- ...resource
202
- } ) ,
203
- updateResource ( resource ) ,
204
- ...( action . showNotifications
205
- ? [
206
- action . showNotifications === true
207
- ? successNotification ( { title : "saveDialog.saveSuccessTitle" , message : "saveDialog.saveSuccessMessage" } )
208
- : warningNotification ( action . showNotifications )
209
- ]
210
- : [ ] ) ,
211
- ...actions // additional actions to be dispatched
200
+ return Observable . merge (
201
+ Observable . of (
202
+ saveSuccess ( resource ) ,
203
+ setResource ( {
204
+ ...currentResource ,
205
+ ...body ,
206
+ ...resource
207
+ } ) ,
208
+ updateResource ( resource ) ,
209
+ ...( action . showNotifications
210
+ ? [
211
+ action . showNotifications === true
212
+ ? successNotification ( { title : "saveDialog.saveSuccessTitle" , message : "saveDialog.saveSuccessMessage" } )
213
+ : warningNotification ( action . showNotifications )
214
+ ]
215
+ : [ ] ) ,
216
+ ...actions // additional actions to be dispatched
217
+ ) ,
218
+ ...( compactPermissions ? [
219
+ Observable . defer ( ( ) =>
220
+ updateCompactPermissionsByPk ( action . id , cleanCompactPermissions ( compactPermissions ) )
221
+ . then ( output => ( { resource : currentResource , output, processType : ProcessTypes . PERMISSIONS_RESOURCE } ) )
222
+ . catch ( ( error ) => ( { resource : currentResource , error : error ?. data ?. detail || error ?. statusText || error ?. message || true , processType : ProcessTypes . PERMISSIONS_RESOURCE } ) )
223
+ )
224
+ . switchMap ( ( payload ) => {
225
+ return Observable . of ( startAsyncProcess ( payload ) ) ;
226
+ } )
227
+ ] : [ ] )
212
228
) ;
213
229
} )
214
230
. catch ( ( error ) => {
@@ -264,22 +280,35 @@ export const gnSaveDirectContent = (action$, store) =>
264
280
const state = store . getState ( ) ;
265
281
const mapInfo = mapInfoSelector ( state ) ;
266
282
const resourceId = mapInfo ?. id || getResourceId ( state ) ;
267
- const { compactPermissions , geoLimits } = getPermissionsPayload ( state ) ;
283
+ const { geoLimits } = getPermissionsPayload ( state ) ;
268
284
const currentResource = getResourceData ( state ) ;
269
285
270
- return Observable . defer ( ( ) => axios . all ( [
271
- getResourceByPk ( resourceId ) ,
272
- ...( geoLimits
273
- ? geoLimits . map ( ( limits ) =>
274
- limits . features . length === 0
275
- ? deleteGeoLimits ( resourceId , limits . id , limits . type )
276
- . catch ( ( ) => ( { error : true , resourceId, limits } ) )
277
- : updateGeoLimits ( resourceId , limits . id , limits . type , { features : limits . features } )
278
- . catch ( ( ) => ( { error : true , resourceId, limits } ) )
279
- )
280
- : [ ] )
281
- ] ) )
282
- . switchMap ( ( [ resource , ...geoLimitsResponses ] ) => {
286
+ const newOwner = get ( currentResource , 'owner.pk' , null ) ;
287
+ const currentOwner = get ( state , 'gnresource.initialResource.owner.pk' , null ) ;
288
+ const userId = userSelector ( state ) ?. pk ;
289
+ let transferOwnership ;
290
+ if ( newOwner && userId && ! isEqual ( currentOwner , newOwner ) ) {
291
+ transferOwnership = { currentOwner, newOwner, resources : [ Number ( resourceId ) ] } ;
292
+ }
293
+
294
+ // resource information should be saved in a synchronous manner
295
+ // i.e transfer ownership (if any) followed by resource data and finally permissions
296
+ return Observable . concat (
297
+ transferOwnership ? Observable . defer ( ( ) => transferResource ( userId , transferOwnership ) ) : Promise . resolve ( ) ,
298
+ Observable . defer ( ( ) => axios . all ( [
299
+ getResourceByPk ( resourceId ) ,
300
+ ...( geoLimits
301
+ ? geoLimits . map ( ( limits ) =>
302
+ limits . features . length === 0
303
+ ? deleteGeoLimits ( resourceId , limits . id , limits . type )
304
+ . catch ( ( ) => ( { error : true , resourceId, limits } ) )
305
+ : updateGeoLimits ( resourceId , limits . id , limits . type , { features : limits . features } )
306
+ . catch ( ( ) => ( { error : true , resourceId, limits } ) )
307
+ )
308
+ : [ ] )
309
+ ] ) ) ) . toArray ( )
310
+ . switchMap ( ( [ , responses ] ) => {
311
+ const [ resource , ...geoLimitsResponses ] = responses ;
283
312
const geoLimitsErrors = geoLimitsResponses . filter ( ( { error } ) => error ) ;
284
313
const name = getResourceName ( state ) ;
285
314
const description = getResourceDescription ( state ) ;
@@ -290,16 +319,6 @@ export const gnSaveDirectContent = (action$, store) =>
290
319
href : resource ?. href
291
320
} ;
292
321
return Observable . concat (
293
- ...( compactPermissions ? [
294
- Observable . defer ( ( ) =>
295
- updateCompactPermissionsByPk ( resourceId , cleanCompactPermissions ( compactPermissions ) )
296
- . then ( output => ( { resource : currentResource , output, processType : ProcessTypes . PERMISSIONS_RESOURCE } ) )
297
- . catch ( ( error ) => ( { resource : currentResource , error : error ?. data ?. detail || error ?. statusText || error ?. message || true , processType : ProcessTypes . PERMISSIONS_RESOURCE } ) )
298
- )
299
- . switchMap ( ( payload ) => {
300
- return Observable . of ( startAsyncProcess ( payload ) ) ;
301
- } )
302
- ] : [ ] ) ,
303
322
Observable . of (
304
323
saveContent (
305
324
resourceId ,
@@ -313,6 +332,7 @@ export const gnSaveDirectContent = (action$, store) =>
313
332
: true /* showNotification */ ) ,
314
333
resetGeoLimits ( )
315
334
)
335
+
316
336
) ;
317
337
} )
318
338
. catch ( ( error ) => {
0 commit comments