Skip to content

Commit

Permalink
adding new camera image count thunk
Browse files Browse the repository at this point in the history
  • Loading branch information
jue-henry committed Dec 11, 2024
1 parent 132ba93 commit 811b97d
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 40 deletions.
29 changes: 22 additions & 7 deletions src/features/cameras/DeleteCameraForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ import { FormWrapper, ButtonRow, HelperText } from '../../components/Form.jsx';
import { deleteCamera, fetchTask, selectDeleteCameraLoading } from '../tasks/tasksSlice.js';
import { SimpleSpinner, SpinnerOverlay } from '../../components/Spinner.jsx';
import { selectSelectedCamera } from '../projects/projectsSlice.js';
import {
fetchCameraImageCount,
selectCameraImageCount,
selectCameraImageCountLoading,
} from '../cameras/wirelessCamerasSlice.js';

const CameraId = styled('span', {
const BoldText = styled('span', {
fontWeight: '$5',
});

Expand All @@ -21,12 +26,19 @@ const DeleteCameraForm = ({ handleClose }) => {
const [queuedForClose, setQueuedForClose] = useState(false);
const deleteCameraLoading = useSelector(selectDeleteCameraLoading);
const selectedCamera = useSelector(selectSelectedCamera);
const imageCount = useSelector(selectCameraImageCount);
const imageCountLoading = useSelector(selectCameraImageCountLoading);
const dispatch = useDispatch();

// TODO: extract into hook?
useEffect(() => {
if (queuedForClose) handleClose();
}, [queuedForClose, handleClose]);
if (imageCount === null && selectedCamera !== null && !imageCountLoading) {
dispatch(fetchCameraImageCount({ cameraId: selectedCamera }));
}
}, [imageCount, selectedCamera, dispatch]);

useEffect(() => {
if (queuedForClose && !deleteCameraLoading.isLoading) handleClose();
}, [deleteCameraLoading, queuedForClose, handleClose]);

const handleDeleteCameraSubmit = (formVals) => {
dispatch(deleteCamera(formVals));
Expand All @@ -41,9 +53,11 @@ const DeleteCameraForm = ({ handleClose }) => {
}
}, [deleteCameraLoading, dispatch]);

const imagesText = `${imageCount} ${imageCount === 1 ? ' image' : ' images'}`;

return (
<div>
{deleteCameraLoading.isLoading && (
{(deleteCameraLoading.isLoading || imageCountLoading) && (
<SpinnerOverlay>
<SimpleSpinner />
</SpinnerOverlay>
Expand All @@ -59,9 +73,10 @@ const DeleteCameraForm = ({ handleClose }) => {
{() => (
<Form>
<HelperText>
Are you sure you&apos;d like to delete Camera <CameraId>{selectedCamera}</CameraId>?
Are you sure you&apos;d like to delete Camera <BoldText>{selectedCamera}</BoldText>?
This will remove the camera from the project, remove all deployments associated with
it, and delete all images. This action cannot be undone.
it, and <BoldText>{imagesText}</BoldText> will be deleted.{' '}
<BoldText>This action cannot be undone.</BoldText>
</HelperText>
<Field name="cameraId" type="hidden" />
<Field name="deploymentId" type="hidden" />
Expand Down
108 changes: 78 additions & 30 deletions src/features/cameras/wirelessCamerasSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ import { setSelectedProjAndView } from '../projects/projectsSlice';

const initialState = {
wirelessCameras: [],
cameraImageCount: {
isLoading: false,
currentCameraId: null,
count: null,
},
loadingState: {
isLoading: false,
operation: null, /* 'fetching', 'updating', 'deleting' */
operation: null /* 'fetching', 'updating', 'deleting' */,
errors: null,
noneFound: false,
},
Expand All @@ -17,7 +22,6 @@ export const wirelessCamerasSlice = createSlice({
name: 'wirelessCameras',
initialState,
reducers: {

getWirelessCamerasStart: (state) => {
state.loadingState.isLoading = true;
state.loadingState.operation = 'fetching';
Expand All @@ -35,7 +39,7 @@ export const wirelessCamerasSlice = createSlice({
isLoading: false,
operation: null,
errors: null,
noneFound: (payload.length === 0),
noneFound: payload.length === 0,
};
},

Expand All @@ -58,13 +62,13 @@ export const wirelessCamerasSlice = createSlice({
isLoading: false,
operation: null,
errors: null,
noneFound: (payload.wirelessCameras.length === 0),
noneFound: payload.wirelessCameras.length === 0,
};
// TODO: make the cameras update update more surgical?
// i.e. ONLY return the new/updated Camera source record and merge it
// into existing cameras (like we do with Views), and only return the
// new cameraConfig & merge that with Project.cameras array.
// Advantages: don't have to do getCameras() on backend before returning,
// i.e. ONLY return the new/updated Camera source record and merge it
// into existing cameras (like we do with Views), and only return the
// new cameraConfig & merge that with Project.cameras array.
// Advantages: don't have to do getCameras() on backend before returning,
// less data in payload
},

Expand All @@ -87,36 +91,53 @@ export const wirelessCamerasSlice = createSlice({
isLoading: false,
operation: null,
errors: null,
noneFound: (payload.wirelessCameras.length === 0),
noneFound: payload.wirelessCameras.length === 0,
};
},

dismissWirelessCamerasError: (state, { payload }) => {
const index = payload;
state.loadingState.errors.splice(index, 1);
},


/* Fetch image count for specific camera, so as to not clash with imageCount in imagesSlice */

cameraImageCountStart: (state, { payload }) => {
state.cameraImageCount.isLoading = true;
state.cameraImageCount.currentCameraId = payload.cameraId;
state.cameraImageCount.count = null;
},

cameraImageCountSuccess(state, { payload }) {
state.cameraImageCount.isLoading = false;
state.cameraImageCount.currentCameraId = null;
state.cameraImageCount.count = payload.imagesCount.count;
},

cameraImageCountError(state) {
state.cameraImageCount.isLoading = false;
state.cameraImageCount.currentCameraId = null;
state.cameraImageCount.count = null;
},
},

extraReducers: (builder) => {
builder
.addCase(setSelectedProjAndView, (state, { payload }) => {
if (payload.newProjSelected) {
state.wirelessCameras = [];
state.loadingState = {
isLoading: false,
operation: null,
errors: null,
noneFound: null,
};
}
})
builder.addCase(setSelectedProjAndView, (state, { payload }) => {
if (payload.newProjSelected) {
state.wirelessCameras = [];
state.loadingState = {
isLoading: false,
operation: null,
errors: null,
noneFound: null,
};
}
});
},
});

// export actions from slice
export const {

getWirelessCamerasStart,
getWirelessCamerasFailure,
getWirelessCamerasSuccess,
Expand All @@ -131,6 +152,9 @@ export const {

dismissWirelessCamerasError,

cameraImageCountStart,
cameraImageCountSuccess,
cameraImageCountError,
} = wirelessCamerasSlice.actions;

// fetchWirelessCameras thunk
Expand Down Expand Up @@ -169,17 +193,16 @@ export const registerCamera = (payload) => {
request: 'registerCamera',
input: payload,
});
dispatch(registerCameraSuccess(res.registerCamera))
dispatch(registerCameraSuccess(res.registerCamera));
}

} catch (err) {
console.log(`error(s) attempting to register camera: `, err);
dispatch(registerCameraFailure(err));
}
};
};

// unregisger camera thunk
// unregister camera thunk
export const unregisterCamera = (payload) => async (dispatch, getState) => {
try {
dispatch(unregisterCameraStart());
Expand All @@ -192,7 +215,7 @@ export const unregisterCamera = (payload) => async (dispatch, getState) => {
const res = await call({
projId: selectedProj._id,
request: 'unregisterCamera',
input: payload
input: payload,
});
dispatch(unregisterCameraSuccess(res.unregisterCamera));
}
Expand All @@ -201,10 +224,35 @@ export const unregisterCamera = (payload) => async (dispatch, getState) => {
}
};

// fetchCameraImageCount thunk
export const fetchCameraImageCount = (payload) => async (dispatch, getState) => {
try {
dispatch(cameraImageCountStart(payload));
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 res = await call({
projId: selectedProj._id,
request: 'getImagesCount',
input: { filters: { cameras: [payload.cameraId] } },
});
dispatch(cameraImageCountSuccess(res));
}
} catch (err) {
console.log(`error(s) attempting to fetch image count for camera ${payload.cameraId}: `, err);
dispatch(cameraImageCountError(err));
}
};

// Selectors
export const selectWirelessCameras = state => state.wirelessCameras.wirelessCameras;
export const selectWirelessCamerasLoading = state => state.wirelessCameras.loadingState;
export const selectWirelessCamerasErrors = state => state.wirelessCameras.loadingState.errors;
export const selectWirelessCameras = (state) => state.wirelessCameras.wirelessCameras;
export const selectWirelessCamerasLoading = (state) => state.wirelessCameras.loadingState;
export const selectWirelessCamerasErrors = (state) => state.wirelessCameras.loadingState.errors;
export const selectCameraImageCount = (state) => state.wirelessCameras.cameraImageCount.count;
export const selectCameraImageCountLoading = (state) =>
state.wirelessCameras.cameraImageCount.isLoading;

export default wirelessCamerasSlice.reducer;
10 changes: 8 additions & 2 deletions src/features/images/DeleteImagesAlert.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,14 @@ const DeleteImagesAlert = () => {
(alertState.deleteImagesAlertByFilter && imageCountIsLoading.isLoading) ||
imagesLoading.isLoading;

const filterTitle = `Are you sure you'd like to delete ${imageCount === 1 ? 'this image' : `these ${imageCount && imageCount.toLocaleString()} images`}?`;
const selectionTitle = `Are you sure you'd like to delete ${selectedImages.length === 1 ? 'this image' : `these ${selectedImages && selectedImages.length.toLocaleString()} images`}?`;
const filterTitle = `Are you sure you'd like to delete ${
imageCount === 1 ? 'this image' : `these ${imageCount && imageCount.toLocaleString()} images`
}?`;
const selectionTitle = `Are you sure you'd like to delete ${
selectedImages.length === 1
? 'this image'
: `these ${selectedImages && selectedImages.length.toLocaleString()} images`
}?`;
const filterText = (
<div>
<p>
Expand Down
2 changes: 1 addition & 1 deletion src/features/tasks/tasksSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ export const deleteCamera = (payload) => {
input: payload,
});
console.log('deleteCamera - res: ', res);
dispatch(updateDeleteCameraUpdate({ taskId: res.deleteCamera._id }));
dispatch(updateDeleteCameraUpdate({ taskId: res.deleteCameraConfig._id }));
}
} catch (err) {
console.log('error attempting to delete camera: ', err);
Expand Down

0 comments on commit 811b97d

Please sign in to comment.