Skip to content

Commit

Permalink
Merge pull request #724 from sanger/x1219-xeniumQC-runName
Browse files Browse the repository at this point in the history
x1219 - link the run name of the Xenium Analyser to the QC step
  • Loading branch information
sabrine33 authored Jul 10, 2024
2 parents bea923d + 1004a6c commit b26ff43
Show file tree
Hide file tree
Showing 6 changed files with 1,604 additions and 1,521 deletions.
1 change: 1 addition & 0 deletions cypress/e2e/pages/xeniumQC.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ describe('Xenium QC', () => {
//display work number for all labware
cy.findByTestId('workNumberAll').should('be.visible');
cy.findByTestId('completion').should('be.visible');
cy.findByTestId('runName').should('be.visible');
});
});
describe('When two labware is scanned ', () => {
Expand Down
19 changes: 18 additions & 1 deletion src/components/xeniumQC/XeniumLabwareQC.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ type XeniumLabwareQCProps = {

export const XeniumLabwareQC = ({ labware, comments, index, removeLabware }: XeniumLabwareQCProps) => {
const { values, setFieldValue, setValues } = useFormikContext<XeniumQCFormData>();
const runNamesSelectOption: OptionType[] = values.labware[index]
? values.labware[index].runNames!.map((runName) => {
return { value: runName, label: runName } as OptionType;
})
: ([] as OptionType[]);

return (
<div className="max-w-screen-xl mx-auto" data-testid={'xenium-labware-qc'}>
{labware && (
Expand All @@ -47,7 +53,7 @@ export const XeniumLabwareQC = ({ labware, comments, index, removeLabware }: Xen
</div>
</div>
<div className="flex flex-row items-center justify-start"></div>
<div className={'grid grid-cols-2 gap-4'}>
<div className={'grid grid-cols-3 gap-4'}>
<WorkNumberSelect
label={'SGP Number'}
name={`labware.${index}.workNumber`}
Expand All @@ -58,6 +64,17 @@ export const XeniumLabwareQC = ({ labware, comments, index, removeLabware }: Xen
workNumber={values.labware[index]?.workNumber}
/>

<CustomReactSelect
label={'Run Name'}
dataTestId={'runName'}
name={`labware.${index}.selectedRunName`}
emptyOption={true}
options={runNamesSelectOption}
handleChange={async (val) => {
await setFieldValue(`labware.${index}.selectedRunName`, val ? (val as OptionType).value : '');
}}
/>

<CustomReactSelect
label={'Comments'}
dataTestId={`${labware.barcode}-comments`}
Expand Down
3 changes: 3 additions & 0 deletions src/graphql/queries/GetRunNames.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
query GetRunNames($barcode: String!) {
runNames(barcode: $barcode)
}
13 changes: 13 additions & 0 deletions src/mocks/handlers/xeniumHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import commentRepository from '../repositories/commentRepository';
import {
GetAnalyserScanDataQuery,
GetAnalyserScanDataQueryVariables,
GetRunNamesQuery,
RecordAnalyserMutation,
RecordAnalyserMutationVariables
} from '../../types/sdk';
Expand Down Expand Up @@ -43,6 +44,18 @@ const xeniumHandlers = [
},
{ status: 200 }
);
}),

graphql.query<GetRunNamesQuery, GetAnalyserScanDataQueryVariables>('GetRunNames', () => {
return HttpResponse.json({
data: {
runNames: [
faker.string.alphanumeric({ length: { min: 5, max: 8 } }),
faker.string.alphanumeric({ length: { min: 5, max: 8 } }),
faker.string.alphanumeric({ length: { min: 5, max: 8 } })
]
}
});
})
];

Expand Down
81 changes: 51 additions & 30 deletions src/pages/XeniumQC.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import {
LabwareFlaggedFieldsFragment,
QcLabwareRequest,
RecordQcLabwareMutation,
RoiFieldsFragment,
SampleFieldsFragment
} from '../types/sdk';
import * as Yup from 'yup';
import { StanCoreContext } from '../lib/sdk';
import { stanCore, StanCoreContext } from '../lib/sdk';
import createFormMachine from '../lib/machines/form/formMachine';
import { useMachine } from '@xstate/react';
import AppShell from '../components/AppShell';
Expand Down Expand Up @@ -38,6 +39,8 @@ type QcFormLabware = {
comments: string[];
roiComments: string[];
sampleComments: Array<SampleComment>;
runNames?: string[];
selectedRunName?: string;
};

export type XeniumQCFormData = {
Expand All @@ -46,6 +49,22 @@ export type XeniumQCFormData = {
completion: string;
};

const getRegionsOfInterestGroupedByRoi = async (barcode: string): Promise<Record<string, RoiFieldsFragment[]>> => {
const response = await stanCore.GetRegionsOfInterest({
barcodes: [barcode]
});
if (response.rois.length === 0 || response.rois[0]!.rois.length === 0) return {};
return groupByRoi(response.rois[0]!.rois!);
};

const getRunNames = async (barcode: string): Promise<string[]> => {
return await stanCore
.GetRunNames({
barcode: barcode
})
.then((response) => response.runNames);
};

const XeniumQC = () => {
const comments = useLoaderData() as CommentFieldsFragment[];
const stanCore = useContext(StanCoreContext);
Expand Down Expand Up @@ -79,6 +98,8 @@ const XeniumQC = () => {
barcode: Yup.string().required(),
workNumber: Yup.string().required().label('SGP Number'),
comments: Yup.array().min(0).optional(),
runNames: Yup.array().min(0).optional(),
selectedRunName: Yup.string().optional(),
roiComments: Yup.array().min(0).optional(),
sampleComments: Yup.array()
.of(
Expand All @@ -102,44 +123,43 @@ const XeniumQC = () => {
completion: currentTime
};

const getRegionsOfInterest = useCallback(
const getRelatedLabwareData = useCallback(
async (
foundLabware: LabwareFlaggedFieldsFragment,
barcode: string,
setValues: (values: SetStateAction<XeniumQCFormData>, shouldValidate?: boolean) => {}
): Promise<string[]> => {
try {
const response = await stanCore.GetRegionsOfInterest({
barcodes: [foundLabware.barcode]
});
const groupedByRoi = groupByRoi(response.rois[0]!.rois!);
if (response.rois.length > 0) {
setValues((prev) => {
prev.labware.push({
barcode: foundLabware.barcode,
workNumber: prev.workNumberAll,
completion: prev.completion,
comments: [],
roiComments: [],
sampleComments: Object.keys(groupedByRoi).map((roi) => {
return {
sampleAddress: groupedByRoi[roi].map((data) => {
return { sample: data.sample ?? '', address: data.address };
}),
roi,
comments: []
};
})
});
return prev;
const groupedByRoi = await getRegionsOfInterestGroupedByRoi(barcode);
if (Object.keys(groupedByRoi).length === 0)
return [`No region of interest is recorded against the scanned labware ${barcode}.`];
const runNames = await getRunNames(barcode);
setValues((prev) => {
prev.labware.push({
barcode: barcode,
workNumber: prev.workNumberAll,
completion: prev.completion,
comments: [],
roiComments: [],
runNames,
sampleComments: Object.keys(groupedByRoi).map((roi) => {
return {
sampleAddress: groupedByRoi[roi].map((data) => {
return { sample: data.sample ?? '', address: data.address };
}),
roi,
comments: []
};
})
});
}
return prev;
});

return [];
} catch (error) {
return ['Error fetching the regions of interests related to the labware ' + foundLabware.barcode];
return [`There was an error fetching the related data for the labware ${barcode}.`];
}
},
[stanCore]
[]
);

return (
Expand All @@ -162,6 +182,7 @@ const XeniumQC = () => {
barcode: lw.barcode,
workNumber: lw.workNumber,
comments: lw.comments.map((comment) => Number(comment)),
runName: lw.selectedRunName,
sampleComments: lw.sampleComments?.flatMap((sampleComment) => {
return sampleComment.sampleAddress.flatMap((sampleAdress) => {
return sampleComment.comments.map((commentId) => {
Expand Down Expand Up @@ -204,7 +225,7 @@ const XeniumQC = () => {
labwares: LabwareFlaggedFieldsFragment[],
foundLabware: LabwareFlaggedFieldsFragment
) => {
return getRegionsOfInterest(foundLabware, setValues);
return getRelatedLabwareData(foundLabware.barcode, setValues);
}}
>
{({ labwares, removeLabware }) => (
Expand Down
Loading

0 comments on commit b26ff43

Please sign in to comment.