Skip to content

Commit

Permalink
Merge pull request #1397 from phac-nml/hotfix-sample-modal-cart
Browse files Browse the repository at this point in the history
Hotfix: Sample details modal add/remove to/from cart
  • Loading branch information
ericenns authored Nov 3, 2022
2 parents 3115d7f + aeede87 commit c87efff
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 66 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* [UI]: Fixed bug causing associated project samples to be added to the cart with the wrong project identifier. See [PR 1395](https://github.com/phac-nml/irida/pull/1395)
* [UI]: Fixed bug preventing the removal of locked samples within a project. See [PR 1396](https://github.com/phac-nml/irida/pull/1396)
* [Developer/UI]: Fixed bug preventing managers from sharing project samples. See [PR 1398](https://github.com/phac-nml/irida/pull/1398)
* [UI]: Fixed bug where a sample added to the cart from the sample detail viewer still had a `Add to Cart` button if the viewer was closed and relaunched. See [PR 1397](https://github.com/phac-nml/irida/pull/1397)

## [22.09.1] - 2022/10/21
* [UI]: Fixed when sharing or exporting sample on the project sample page, and other minor bugs. See [PR 1382](https://github.com/phac-nml/irida/pull/1382)
Expand Down
2 changes: 1 addition & 1 deletion src/main/webapp/resources/js/apis/cart/cart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export const {
useRemoveSampleMutation,
} = cartApi;

const updateCart = (data: CartUpdated) => {
export const updateCart = (data: CartUpdated) => {
data.notifications.forEach((n) => notification[n.type](n));
cartUpdated(data.count);
return data.count;
Expand Down
49 changes: 36 additions & 13 deletions src/main/webapp/resources/js/apis/samples/samples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import { setBaseUrl } from "../../utilities/url-utilities";
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

import { get, post } from "../requests";
import { AnalysisSubmission } from "../../types/irida";
import { AnalysisSubmission, Sample } from "../../types/irida";
import { CartUpdated, updateCart } from "../cart/cart";

const URL = setBaseUrl(`ajax/samples`);

const SEQUENCE_FILES_AJAX_URL = setBaseUrl("ajax/sequenceFiles");

const CART_URL = setBaseUrl("ajax/cart");

export type AnalysisState =
| "NEW"
| "PREPARING"
Expand Down Expand Up @@ -137,17 +140,15 @@ export interface SequencingObject {
*/
export const sampleApi = createApi({
reducerPath: `sampleApi`,
baseQuery: fetchBaseQuery({
baseUrl: setBaseUrl(URL),
}),
baseQuery: fetchBaseQuery({}),
tagTypes: ["SampleDetails", "SampleMetadata"],
endpoints: (build) => ({
/*
Get the default information about a sample
*/
getSampleDetails: build.query({
query: ({ sampleId, projectId }) => ({
url: `/${sampleId}/details?projectId=${projectId}`,
url: `${URL}/${sampleId}/details?projectId=${projectId}`,
}),
providesTags: ["SampleDetails"],
}),
Expand All @@ -156,7 +157,7 @@ export const sampleApi = createApi({
*/
updateSampleDetails: build.mutation({
query: ({ sampleId, field, value }) => ({
url: `/${sampleId}/details`,
url: `${URL}/${sampleId}/details`,
body: { field, value },
method: "PUT",
}),
Expand All @@ -170,15 +171,15 @@ export const sampleApi = createApi({
metadataEntry,
metadataRestriction,
}) => ({
url: `/${sampleId}/metadata`,
url: `${URL}/${sampleId}/metadata`,
body: { projectId, metadataField, metadataEntry, metadataRestriction },
method: "POST",
}),
invalidatesTags: ["SampleMetadata"],
}),
removeSampleMetadata: build.mutation({
query: ({ fieldId, entryId, projectId }) => ({
url: `/metadata?projectId=${projectId}&metadataFieldId=${fieldId}&metadataEntryId=${entryId}`,
url: `${URL}/metadata?projectId=${projectId}&metadataFieldId=${fieldId}&metadataEntryId=${entryId}`,
method: "DELETE",
}),
invalidatesTags: ["SampleMetadata"],
Expand All @@ -193,7 +194,7 @@ export const sampleApi = createApi({
metadataEntry,
metadataRestriction,
}) => ({
url: `/${sampleId}/metadata`,
url: `${URL}/${sampleId}/metadata`,
body: {
projectId,
metadataFieldId,
Expand All @@ -208,7 +209,7 @@ export const sampleApi = createApi({
}),
removeSampleFiles: build.mutation({
query: ({ sampleId, fileObjectId, type }) => ({
url: `/${sampleId}/files?fileObjectId=${fileObjectId}&fileType=${type}`,
url: `${URL}/${sampleId}/files?fileObjectId=${fileObjectId}&fileType=${type}`,
method: "DELETE",
}),
}),
Expand All @@ -219,24 +220,44 @@ export const sampleApi = createApi({
newFileName,
removeOriginals,
}) => ({
url: `/${sampleId}/files/concatenate?sequencingObjectIds=${sequencingObjectIds}&newFileName=${newFileName}&removeOriginals=${removeOriginals}`,
url: `${URL}/${sampleId}/files/concatenate?sequencingObjectIds=${sequencingObjectIds}&newFileName=${newFileName}&removeOriginals=${removeOriginals}`,
method: "POST",
}),
}),
updateDefaultSampleSequencingObject: build.mutation({
query: ({ sampleId, sequencingObjectId }) => ({
url: `/${sampleId}/default-sequencing-object?sequencingObjectId=${sequencingObjectId}`,
url: `${URL}/${sampleId}/default-sequencing-object?sequencingObjectId=${sequencingObjectId}`,
method: "PUT",
}),
invalidatesTags: ["SampleDetails"],
}),
updateDefaultSampleGenomeAssembly: build.mutation({
query: ({ sampleId, genomeAssemblyId }) => ({
url: `/${sampleId}/default-genome-assembly?genomeAssemblyId=${genomeAssemblyId}`,
url: `${URL}/${sampleId}/default-genome-assembly?genomeAssemblyId=${genomeAssemblyId}`,
method: "PUT",
}),
invalidatesTags: ["SampleDetails"],
}),
putSampleInCart: build.mutation({
query: ({ projectId, samples }) => ({
url: CART_URL,
body: {
projectId,
sampleIds: samples.map((s: Sample) => s.id || s.identifier),
},
method: "POST",
}),
transformResponse: (res: CartUpdated) => updateCart(res),
invalidatesTags: ["SampleDetails"],
}),
removeSampleFromCart: build.mutation({
query: ({ sampleId }) => ({
url: `${CART_URL}/sample?sampleId=${sampleId}`,
method: "DELETE",
}),
transformResponse: (res: CartUpdated) => updateCart(res),
invalidatesTags: ["SampleDetails"],
}),
}),
});

Expand All @@ -250,6 +271,8 @@ export const {
useConcatenateSequencingObjectsMutation,
useUpdateDefaultSampleGenomeAssemblyMutation,
useUpdateDefaultSampleSequencingObjectMutation,
usePutSampleInCartMutation,
useRemoveSampleFromCartMutation,
} = sampleApi;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface SampleDetailViewerProps {
projectId: number;
displayActions?: boolean;
children: React.ReactElement;
refetch?: () => void;
refetchCart?: () => void;
}

/**
Expand All @@ -26,7 +26,7 @@ export function SampleDetailViewer({
projectId,
displayActions = true,
children,
refetch,
refetchCart,
}: SampleDetailViewerProps): JSX.Element {
const [visible, setVisible] = useState(false);

Expand All @@ -41,7 +41,7 @@ export function SampleDetailViewer({
sampleId={sampleId}
projectId={projectId}
displayActions={displayActions}
refetchSample={refetch}
refetchCart={refetchCart}
setVisible={setVisible}
visible={visible}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface DisplaySampleDetailsProps {
sampleId: number;
projectId: number;
displayActions?: boolean;
refetch?: () => void;
refetchCart?: () => void;
visible: boolean;
setVisible: Dispatch<SetStateAction<boolean>>;
}
Expand All @@ -21,7 +21,7 @@ export default function SampleDetailsModal({
sampleId,
projectId,
displayActions,
refetch,
refetchCart,
visible,
setVisible,
}: DisplaySampleDetailsProps) {
Expand Down Expand Up @@ -55,6 +55,7 @@ export default function SampleDetailsModal({
details.projectId,
details.projectName,
details.sample,
details.inCart,
dispatch,
isLoading,
]);
Expand Down Expand Up @@ -85,7 +86,7 @@ export default function SampleDetailsModal({
tab={component}
onMenuChange={setComponent}
displayActions={!!displayActions}
refetch={refetch}
refetchCart={refetchCart}
/>
<div
style={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface SampleDetailsWrapperProps {
sampleId: number;
projectId: number;
displayActions: boolean;
refetchSample?: () => void;
refetchCart?: () => void;
visible: boolean;
setVisible: Dispatch<SetStateAction<boolean>>;
}
Expand All @@ -16,7 +16,7 @@ export default function SampleDetailsWrapper({
sampleId,
projectId,
displayActions,
refetchSample,
refetchCart,
visible,
setVisible,
}: SampleDetailsWrapperProps) {
Expand All @@ -26,7 +26,7 @@ export default function SampleDetailsWrapper({
sampleId={sampleId}
projectId={projectId}
displayActions={displayActions}
refetch={refetchSample}
refetchCart={refetchCart}
visible={visible}
setVisible={setVisible}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,26 @@ import { useAppDispatch, useAppSelector } from "../../../hooks/useState";
import { generateColourForItem } from "../../../utilities/colour-utilities";
import { ViewerTab } from "./SampleDetailsModal";

import { updateSampleInCart } from "../sampleSlice";
import {
addSampleToCartThunk,
removeSampleFromCartThunk,
} from "../sampleSlice";
usePutSampleInCartMutation,
useRemoveSampleFromCartMutation,
} from "../../../apis/samples/samples";

export const HEADER_HEIGHT = 90;
export const HEADER_HEIGHT_WITH_PADDING = 97;

export default function ViewerHeader({
displayActions,
projectId,
refetch,
refetchCart,
tab,
onMenuChange,
}: {
displayActions: boolean;
projectId: number;
sampleId: number;
refetch: undefined | (() => void);
refetchCart: undefined | (() => void);
tab: ViewerTab;
onMenuChange: Dispatch<SetStateAction<ViewerTab>>;
}): JSX.Element {
Expand All @@ -31,6 +32,9 @@ export default function ViewerHeader({
(state) => state.sampleReducer
);

const [removeSampleFromCart] = useRemoveSampleFromCartMutation();
const [addSampleToCart] = usePutSampleInCartMutation();

const projectColour = useMemo(
() =>
generateColourForItem({
Expand All @@ -54,7 +58,7 @@ export default function ViewerHeader({
display: "flex",
alignItems: "center",
justifyContent: "space-between",
margin: `10px 50px 0 20px`,
margin: `10px 56px 0 20px`,
}}
>
<Space>
Expand Down Expand Up @@ -83,8 +87,10 @@ export default function ViewerHeader({
className="t-remove-sample-from-cart"
danger
onClick={() => {
dispatch(removeSampleFromCartThunk());
if (typeof refetch !== "undefined") refetch();
removeSampleFromCart({ sampleId: sample.identifier }).then(() => {
dispatch(updateSampleInCart({ inCart: false }));
if (typeof refetchCart !== "undefined") refetchCart();
});
}}
>
{i18n("SampleDetailsViewer.removeFromCart")}
Expand All @@ -95,8 +101,10 @@ export default function ViewerHeader({
size="small"
className="t-add-sample-to-cart"
onClick={() => {
dispatch(addSampleToCartThunk());
if (typeof refetch !== "undefined") refetch();
addSampleToCart({ projectId, samples: [sample] }).then(() => {
dispatch(updateSampleInCart({ inCart: true }));
if (typeof refetchCart !== "undefined") refetchCart();
});
}}
>
{i18n("SampleDetailsViewer.addToCart")}
Expand Down
33 changes: 7 additions & 26 deletions src/main/webapp/resources/js/components/samples/sampleSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
SampleMetadataFieldEntry,
} from "../../apis/samples/samples";
import { Sample } from "../../types/irida";
import { putSampleInCart, removeSample } from "../../apis/cart/cart";

/**
* Action to set the target sample
Expand Down Expand Up @@ -119,25 +118,11 @@ export const updateDetails = createAction(
})
);

export const addSampleToCartThunk = createAsyncThunk(
"sample/addSampleToCartThunk",
async (_, { getState }) => {
const { sampleReducer } = getState();
await putSampleInCart(sampleReducer.projectId, [sampleReducer.sample]);
return {};
}
);

export const removeSampleFromCartThunk = createAsyncThunk(
"sample/removeSampleFromCartThunk",
async (_, { getState }) => {
const { sampleReducer } = getState();
await removeSample(
sampleReducer.projectId,
sampleReducer.sample.identifier
);
return {};
}
export const updateSampleInCart = createAction(
`sample/updateSampleInCart`,
({ inCart }) => ({
payload: { inCart },
})
);

/**
Expand Down Expand Up @@ -261,12 +246,8 @@ const sampleSlice = createSlice({
};
});

builder.addCase(addSampleToCartThunk.fulfilled, (state) => {
state.inCart = true;
});

builder.addCase(removeSampleFromCartThunk.fulfilled, (state) => {
state.inCart = false;
builder.addCase(updateSampleInCart, (state, action) => {
state.inCart = action.payload.inCart;
});
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class SampleRenderer extends React.Component {
<SampleDetailViewer
sampleId={sample.id}
projectId={this.props.data.project.id}
refetch={this.props.refetch}
refetchCart={this.props.refetch}
>
<Button
className="t-sample-details-btn"
Expand Down
Loading

0 comments on commit c87efff

Please sign in to comment.