diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ea29212..2325b266 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -45,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Load boundary details in draw page [#139](https://github.com/azavea/iow-boundary-tool/pull/139)
- Let users select utility at login [#142](https://github.com/azavea/iow-boundary-tool/pull/142)
- Add Activity Log Serializer [#140](https://github.com/azavea/iow-boundary-tool/pull/140)
+- Save shape updates on draw page [#141](https://github.com/azavea/iow-boundary-tool/pull/141)
### Changed
diff --git a/src/app/src/App.js b/src/app/src/App.js
index 548fbd5e..a092aa16 100644
--- a/src/app/src/App.js
+++ b/src/app/src/App.js
@@ -28,7 +28,7 @@ const privateRoutes = (
} />
} />
- } />
+ } />
} />
} />
diff --git a/src/app/src/api/boundaries.js b/src/app/src/api/boundaries.js
index c362afdc..0e54cefa 100644
--- a/src/app/src/api/boundaries.js
+++ b/src/app/src/api/boundaries.js
@@ -28,11 +28,19 @@ const boundaryApi = api.injectEndpoints({
query: newBoundary => ({
url: '/boundaries/',
method: 'POST',
- body: newBoundary,
+ data: newBoundary,
}),
invalidatesTags: getNewItemTagInvalidator(TAGS.BOUNDARY),
}),
+ updateBoundaryShape: build.mutation({
+ query: ({ id, shape }) => ({
+ url: `/boundaries/${id}/shape/`,
+ method: 'PUT',
+ data: shape,
+ }),
+ }),
+
submitBoundary: build.mutation({
query: id => ({
url: `/boundaries/${id}/submit/`,
@@ -47,5 +55,6 @@ export const {
useGetBoundariesQuery,
useGetBoundaryDetailsQuery,
useStartNewBoundaryMutation,
+ useUpdateBoundaryShapeMutation,
useSubmitBoundaryMutation,
} = boundaryApi;
diff --git a/src/app/src/components/DrawTools/DrawTools.js b/src/app/src/components/DrawTools/DrawTools.js
index eff2f84e..ead6ee54 100644
--- a/src/app/src/components/DrawTools/DrawTools.js
+++ b/src/app/src/components/DrawTools/DrawTools.js
@@ -1,5 +1,5 @@
import { useEffect } from 'react';
-import { useDispatch } from 'react-redux';
+import { useDispatch, useSelector } from 'react-redux';
import { Button, Icon } from '@chakra-ui/react';
import { ArrowRightIcon } from '@heroicons/react/outline';
@@ -7,14 +7,45 @@ import { ArrowRightIcon } from '@heroicons/react/outline';
import EditToolbar from './EditToolbar';
import MapControlButtons from './MapControlButtons';
+import { useGetBoundaryDetailsQuery } from '../../api/boundaries';
+import { useBoundaryId, useEndpointToastError } from '../../hooks';
+
import useAddPolygonCursor from './useAddPolygonCursor';
import useEditingPolygon from './useEditingPolygon';
import useGeocoderResult from './useGeocoderResult';
import useTrackMapZoom from './useTrackMapZoom';
import { setPolygon } from '../../store/mapSlice';
+import { BOUNDARY_STATUS, ROLES } from '../../constants';
+import LoadingModal from '../LoadingModal';
+
+const DRAW_MODES = {
+ FULLY_EDITABLE: 'fully_editable',
+ ANNOTATIONS_ONLY: 'annotations_only',
+ READ_ONLY: 'read_only',
+};
+
+export default function LoadBoundaryDetails() {
+ const user = useSelector(state => state.auth.user);
+ const id = useBoundaryId();
+
+ const { isFetching, data: details, error } = useGetBoundaryDetailsQuery(id);
+ useEndpointToastError(error);
+
+ if (isFetching) {
+ return ;
+ }
+
+ if (error || typeof details !== 'object') {
+ return null;
+ }
+
+ const mode = getDrawMode({ status: details.status, userRole: user.role });
-export default function DrawTools({ details }) {
+ return ;
+}
+
+function DrawTools({ mode, details }) {
const dispatch = useDispatch();
// Add the polygon indicated by `details` to the state
@@ -22,11 +53,7 @@ export default function DrawTools({ details }) {
if (details) {
dispatch(
setPolygon({
- // endpoint returns lngLat, leaflet needs latLng
- points: details.submission.shape.coordinates[0].map(p => [
- p[1],
- p[0],
- ]),
+ points: details.submission.shape.coordinates[0],
visible: true,
label: details.utility.name,
})
@@ -49,6 +76,18 @@ export default function DrawTools({ details }) {
);
}
+function getDrawMode({ status, userRole }) {
+ if (userRole === ROLES.VALIDATOR && status === BOUNDARY_STATUS.IN_REVIEW) {
+ return DRAW_MODES.ANNOTATIONS_ONLY;
+ }
+
+ if (status === BOUNDARY_STATUS.DRAFT && userRole === ROLES.CONTRIBUTOR) {
+ return DRAW_MODES.FULLY_EDITABLE;
+ }
+
+ return DRAW_MODES.READ_ONLY;
+}
+
function SaveAndBackButton() {
return (