Skip to content

Commit

Permalink
Merge pull request #153 from tnc-ca-geo/delete-images
Browse files Browse the repository at this point in the history
Delete images
  • Loading branch information
nathanielrindlaub authored Oct 24, 2023
2 parents efc0acc + 36ab324 commit 8e7fb8c
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 24 deletions.
15 changes: 15 additions & 0 deletions src/api/buildQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,21 @@ const queries = {
}
},

deleteImages: (input) => {
return {
template: `
mutation DeleteImages($input: DeleteImagesInput!) {
deleteImages(input: $input) {
message
}
}
`,
variables: {
input
}
}
},

getImages: ({ filters, pageInfo, page }) => ({
template: `
query GetImages($input: QueryImagesInput!) {
Expand Down
1 change: 1 addition & 0 deletions src/auth/roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const WRITE_DEPLOYMENTS_ROLES = [MANAGER];
export const WRITE_AUTOMATION_RULES_ROLES = [MANAGER];
export const WRITE_CAMERA_REGISTRATION_ROLES = [MANAGER];
export const QUERY_WITH_CUSTOM_FILTER = [MANAGER];
export const DELETE_IMAGES = [MANAGER, MEMBER];
export const MANAGE_USERS_ROLES = [MANAGER];

export const hasRole = (currRoles, targetRoles = []) => (
Expand Down
2 changes: 1 addition & 1 deletion src/components/ErrorAlerts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const ErrorAlerts = () => {
enrichErrors(depsErrors, 'Deployment Error', 'deployments'),
enrichErrors(modelsErrors, 'Model Error', 'models'),
enrichErrors(camerasErrors, 'Camera Error', 'cameras'),
enrichErrors(imagesErrors, 'Error Fetching Images', 'images'),
enrichErrors(imagesErrors, 'Image Error', 'images'),
enrichErrors(imageContextErrors, 'Image Error', 'imageContext'),
enrichErrors(statsErrors, 'Error Getting Stats', 'stats'),
enrichErrors(exportErrors, 'Error Exporting Data', 'data'),
Expand Down
44 changes: 43 additions & 1 deletion src/features/images/imagesSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const imagesSlice = createSlice({

dismissImagesError: (state, { payload }) => {
const index = payload;
state.loadingStates.image.errors.splice(index, 1);
state.loadingStates.images.errors.splice(index, 1);
},

preFocusImageStart: (state, { payload }) => {
Expand Down Expand Up @@ -240,6 +240,22 @@ export const imagesSlice = createSlice({
const index = payload;
state.loadingStates.export.errors.splice(index, 1);
},

deleteImagesStart: (state) => {
state.loadingStates.images.isLoading = true;
state.loadingStates.images.operation = 'deleting';
state.loadingStates.images.error = null;
},

deleteImagesSuccess: (state, { payload }) => {
state.loadingStates.images.isLoading = false;
state.loadingStates.images.operation = null;
},

deleteImagesError: (state, { payload }) => {
state.loadingStates.images.isLoading = false;
state.loadingStates.images.errors = payload;
},
},
});

Expand Down Expand Up @@ -268,6 +284,9 @@ export const {
exportFailure,
clearExport,
dismissExportError,
deleteImagesStart,
deleteImagesSuccess,
deleteImagesError,
} = imagesSlice.actions;

// fetchImages thunk
Expand Down Expand Up @@ -451,6 +470,29 @@ export const getExportStatus = (documentId) => {
};
};

export const deleteImages = (imageIds) => async (dispatch, getState) => {
dispatch(deleteImagesStart(imageIds));
try {
const currentUser = await Auth.currentAuthenticatedUser();
const token = currentUser.getSignInUserSession().getIdToken().getJwtToken();

const projects = getState().projects.projects;
const selectedProj = projects.find((proj) => proj.selected);

if (token && selectedProj) {
const r = await call({
projId: selectedProj._id,
request: 'deleteImages',
input: { imageIds },
});
}
dispatch(deleteImagesSuccess(imageIds));
} catch (err) {
console.log(`error attempting to delete image: `, err);
dispatch(deleteImagesError(err));
}
}

export const selectPageInfo = state => state.images.pageInfo;
export const selectPaginatedField = state => state.images.pageInfo.paginatedField;
export const selectSortAscending = state => state.images.pageInfo.sortAscending;
Expand Down
53 changes: 34 additions & 19 deletions src/features/loupe/FullSizeImage.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React, { useState, useRef, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Cross2Icon, PlusIcon } from '@radix-ui/react-icons';
import { Cross2Icon, PlusIcon, TrashIcon } from '@radix-ui/react-icons';
import { useResizeObserver } from '../../app/utils';
import { styled } from '../../theme/stitches.config';
// import { CircleSpinner, SpinnerOverlay } from '../../components/Spinner';
import { selectUserUsername, selectUserCurrentRoles } from '../user/userSlice';
import { hasRole, WRITE_OBJECTS_ROLES } from '../../auth/roles';
import { hasRole, WRITE_OBJECTS_ROLES, DELETE_IMAGES } from '../../auth/roles';
import { drawBboxStart, selectIsDrawingBbox} from './loupeSlice';
import { selectWorkingImages, labelsValidated, markedEmpty } from '../review/reviewSlice';
import { deleteImages } from '../images/imagesSlice';
import { Image } from '../../components/Image';
import BoundingBox from './BoundingBox';
import DrawBboxOverlay from './DrawBboxOverlay';
Expand Down Expand Up @@ -145,6 +146,8 @@ const FullSizeImage = ({ image, focusIndex }) => {

const handleAddObjectButtonClick = () => dispatch(drawBboxStart());

const handleDeleteButtonClick = () => dispatch(deleteImages([image._id]));

return (
<ImageWrapper ref={containerEl} className='full-size-image'>
{isDrawingBbox &&
Expand Down Expand Up @@ -192,29 +195,41 @@ const FullSizeImage = ({ image, focusIndex }) => {
</ContextMenuItemIconLeft>
Mark empty
</ContextMenuItem>
{hasRole(userRoles, DELETE_IMAGES) &&
<ContextMenuItem
onSelect={handleDeleteButtonClick}
>
<ContextMenuItemIconLeft>
<TrashIcon />
</ContextMenuItemIconLeft>
Delete
</ContextMenuItem>
}
</ContextMenuContent>
</ContextMenu>
<ShareImage>
<ShareImageButton imageId={image._id}/>
</ShareImage>
{hasRole(userRoles, WRITE_OBJECTS_ROLES) &&
<EditObjectButtons>
<EditObjectButton onClick={handleMarkEmptyButtonClick}>
<Cross2Icon /> Mark empty
</EditObjectButton>
<EditObjectButton
onClick={handleAddObjectButtonClick}
css={{
color: '$loContrast',
backgroundColor: '$hiContrast',
}}
>
<PlusIcon /> Add object
</EditObjectButton>
</EditObjectButtons>
}
<EditObjectButtons>
{hasRole(userRoles, WRITE_OBJECTS_ROLES) &&
<>
<EditObjectButton onClick={handleMarkEmptyButtonClick}>
<Cross2Icon /> Mark empty
</EditObjectButton>
<EditObjectButton
onClick={handleAddObjectButtonClick}
css={{
color: '$loContrast',
backgroundColor: '$hiContrast',
}}
>
<PlusIcon /> Add object
</EditObjectButton>
</>
}
</EditObjectButtons>
</ImageWrapper>
);
};

export default FullSizeImage;
export default FullSizeImage;
10 changes: 7 additions & 3 deletions src/features/review/reviewSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createSlice, createAction } from '@reduxjs/toolkit';
import { Auth } from 'aws-amplify';
import { call } from '../../api';
import { findImage, findObject, findLabel } from '../../app/utils';
import { getImagesSuccess, clearImages } from '../images/imagesSlice';
import { getImagesSuccess, clearImages, deleteImagesSuccess } from '../images/imagesSlice';

const initialState = {
workingImages: [],
Expand Down Expand Up @@ -134,8 +134,7 @@ export const reviewSlice = createSlice({
dismissLabelsError: (state, { payload }) => {
const index = payload;
state.loadingStates.labels.errors.splice(index, 1);
},

}
},

extraReducers: (builder) => {
Expand All @@ -147,6 +146,11 @@ export const reviewSlice = createSlice({
.addCase(clearImages, (state) => {
state.workingImages = [];
})
.addCase(deleteImagesSuccess, (state, { payload }) => {
state.workingImages = state.workingImages.filter(
({ _id }) => !payload.includes(_id)
);
})
},

});
Expand Down

0 comments on commit 8e7fb8c

Please sign in to comment.