Skip to content

Commit

Permalink
Merge pull request #686 from sanger/update-roi-table-columns
Browse files Browse the repository at this point in the history
Update roi table columns
  • Loading branch information
khelwood authored May 24, 2024
2 parents e9c3acc + 2df5223 commit bb99cc5
Show file tree
Hide file tree
Showing 8 changed files with 1,871 additions and 1,833 deletions.
76 changes: 76 additions & 0 deletions src/components/xeniumMetrics/RoiTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import DataTable from '../DataTable';
import { Column, Row } from 'react-table';
import React from 'react';
import { RoiFieldsFragment } from '../../types/sdk';

type RoiTableRow = {
roi: string;
externalIdAddress: Array<{ externalId: string; address: string }>;
};

type RoiTableProps<T extends RoiFieldsFragment> = {
actionColumn: Column<T>;
data: RoiTableRow[];
};

export const groupByRoi = (rois: RoiFieldsFragment[]): Record<string, RoiFieldsFragment[]> => {
const grouped = rois.reduce(
(acc, data) => {
if (!acc[data.roi]) {
acc[data.roi] = [];
}
acc[data.roi].push(data);
return acc;
},
{} as Record<string, RoiFieldsFragment[]>
);
return grouped;
};
const RoiTable = ({ actionColumn, data }: RoiTableProps<any>) => {
return (
<DataTable
columns={[
{
Header: 'Region of interest',
accessor: 'roi'
},
{
Header: 'External ID',
Cell: ({ row }: { row: Row<RoiTableRow> }) => {
return (
<div className="grid grid-cols-1 text-wrap">
{row.original.externalIdAddress.map((data, index) => {
return (
<label className="py-1" key={`${data.externalId}-${index}`}>
{data.externalId}
</label>
);
})}
</div>
);
}
},
{
Header: 'Address',
Cell: ({ row }: { row: Row<RoiTableRow> }) => {
return (
<div className="grid grid-cols-1 text-wrap">
{row.original.externalIdAddress.map((data, index) => {
return (
<label className="py-1" key={`${data.address}-${index}`}>
{data.address}
</label>
);
})}
</div>
);
}
},
actionColumn
]}
data={data}
/>
);
};

export default RoiTable;
43 changes: 21 additions & 22 deletions src/components/xeniumQC/XeniumLabwareQC.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import CustomReactSelect, { OptionType } from '../forms/CustomReactSelect';
import { selectOptionValues } from '../forms';
import { FieldArray, useFormikContext } from 'formik';
import { SampleComment, XeniumQCFormData } from '../../pages/XeniumQC';
import DataTable from '../DataTable';
import { CellProps } from 'react-table';
import StyledLink from '../StyledLink';
import Warning from '../notifications/Warning';
import { FlaggedBarcodeLink } from '../dataTableColumns/labwareColumns';
import RoiTable from '../xeniumMetrics/RoiTable';

type XeniumLabwareQCProps = {
comments: CommentFieldsFragment[];
Expand All @@ -20,6 +20,7 @@ type XeniumLabwareQCProps = {
removeLabware: (barcode: string) => void;
cleanedOutAddress?: string[];
};

export const XeniumLabwareQC = ({ labware, comments, index, removeLabware }: XeniumLabwareQCProps) => {
const { values, setFieldValue, setValues } = useFormikContext<XeniumQCFormData>();
return (
Expand Down Expand Up @@ -119,22 +120,21 @@ export const XeniumLabwareQC = ({ labware, comments, index, removeLabware }: Xen
)}
/>
</div>
<div className={'col-span-4'}>
<DataTable
columns={[
{
Header: 'Sample ID',
accessor: 'sampleId'
},
{
Header: 'Address',
accessor: 'address'
},
{
Header: 'Region',
accessor: 'roi'
},
{
{values.labware[index]?.sampleComments.length > 0 && (
<div className={'col-span-4'}>
<RoiTable
data={values.labware[index]?.sampleComments.map((data) => {
return {
roi: data.roi,
externalIdAddress: data.sampleAddress.map((sampleAddress) => {
return {
externalId: sampleAddress.sample.tissue.externalName ?? '',
address: sampleAddress.address
};
})
};
})}
actionColumn={{
Header: 'Comment',
accessor: 'comments',
Cell: (props: CellProps<SampleComment>) => {
Expand All @@ -151,11 +151,10 @@ export const XeniumLabwareQC = ({ labware, comments, index, removeLabware }: Xen
/>
);
}
}
]}
data={values.labware[index]?.sampleComments}
/>
</div>
}}
/>
</div>
)}
</div>
)}
</Panel>
Expand Down
4 changes: 3 additions & 1 deletion src/graphql/fragments/RoiFields.graphql
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
fragment RoiFields on Roi {
sampleId
sample {
...SampleFields
}
address
roi
}
2 changes: 1 addition & 1 deletion src/mocks/handlers/regionOfInterestHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const regionOfInterestHandlers = [
slot.samples.map((sample) => ({
slotId: slot.id,
operationId: faker.number.int(19),
sampleId: sample.id,
sample,
address: slot.address,
roi: faker.helpers.arrayElement(['top left', 'top right', 'bottom left', 'bottom right', 'center'])
}))
Expand Down
87 changes: 19 additions & 68 deletions src/pages/XeniumMetrics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,12 @@ import Heading from '../components/Heading';
import LabwareScanner from '../components/labwareScanner/LabwareScanner';
import React, { SetStateAction, useCallback, useContext } from 'react';
import { Form, Formik } from 'formik';
import {
LabwareFlaggedFieldsFragment,
RecordMetricsMutation,
RoiFieldsFragment,
SampleMetricsRequest
} from '../types/sdk';
import { LabwareFlaggedFieldsFragment, RecordMetricsMutation, SampleMetricsRequest } from '../types/sdk';
import { StanCoreContext } from '../lib/sdk';
import Panel from '../components/Panel';
import RemoveButton from '../components/buttons/RemoveButton';
import { FlaggedBarcodeLink } from '../components/dataTableColumns/labwareColumns';
import StyledLink from '../components/StyledLink';
import DataTable from '../components/DataTable';
import { Row } from 'react-table';
import { UploadProgress, UploadResult } from '../components/upload/useUpload';
import MetricsReader from '../components/xeniumMetrics/MetricsReader';
Expand All @@ -26,14 +20,15 @@ import { fromPromise } from 'xstate';
import { useMachine } from '@xstate/react';
import OperationCompleteModal from '../components/modal/OperationCompleteModal';
import Warning from '../components/notifications/Warning';
import RoiTable, { groupByRoi } from '../components/xeniumMetrics/RoiTable';

export type Metric = {
name: string;
value: string;
};

export type SampleMetricData = {
sampleIdAddress: Array<{ sampleId: number; address: string }>;
externalIdAddress: Array<{ externalId: string; address: string }>;
roi: string;
metrics: Array<Metric>;
file?: File;
Expand Down Expand Up @@ -76,19 +71,6 @@ const validationSchema = Yup.object().shape({
})
});

export const groupByRoi = (rois: RoiFieldsFragment[]): Record<string, RoiFieldsFragment[]> => {
const grouped = rois.reduce(
(acc, data) => {
if (!acc[data.roi]) {
acc[data.roi] = [];
}
acc[data.roi].push(data);
return acc;
},
{} as Record<string, RoiFieldsFragment[]>
);
return grouped;
};
const XeniumMetrics = () => {
const stanCore = useContext(StanCoreContext);

Expand All @@ -108,8 +90,8 @@ const XeniumMetrics = () => {
labware: foundLabware,
sampleMetricData: Object.keys(groupedByRoi).map((roi) => {
return {
sampleIdAddress: groupedByRoi[roi].map((data) => {
return { sampleId: data.sampleId, address: data.address };
externalIdAddress: groupedByRoi[roi].map((data) => {
return { externalId: data.sample.tissue.externalName ?? '', address: data.address };
}),
roi,
metrics: []
Expand Down Expand Up @@ -212,55 +194,24 @@ const XeniumMetrics = () => {
/>
</div>
</div>
<div className="my-4">
<DataTable
columns={[
{
Header: 'Region of interest',
accessor: 'roi'
},
{
Header: 'Sample ID',
Cell: ({ row }: { row: Row<SampleMetricData> }) => {
return (
<div className="grid grid-cols-1 text-wrap">
{row.original.sampleIdAddress.map((data, index) => {
return (
<label className="py-1" key={`${data.sampleId}-${index}`}>
{data.sampleId}
</label>
);
})}
</div>
);
}
},
{
Header: 'Address',
Cell: ({ row }: { row: Row<SampleMetricData> }) => {
return (
<div className="grid grid-cols-1 text-wrap">
{row.original.sampleIdAddress.map((data, index) => {
return (
<label className="py-1" key={`${data.address}-${index}`}>
{data.address}
</label>
);
})}
</div>
);
}
},
{
{values.sampleMetricData.length > 0 && (
<div className="my-4">
<RoiTable
data={values.sampleMetricData.map((data) => {
return {
roi: data.roi,
externalIdAddress: data.externalIdAddress
};
})}
actionColumn={{
Header: 'File Metrics',
Cell: ({ row }: { row: Row<SampleMetricData> }) => {
return <MetricsReader rowIndex={row.index} />;
}
}
]}
data={values.sampleMetricData}
/>
</div>
}}
/>
</div>
)}
</Panel>
))
}
Expand Down
37 changes: 22 additions & 15 deletions src/pages/XeniumQC.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import {
CommentFieldsFragment,
LabwareFlaggedFieldsFragment,
QcLabwareRequest,
RecordQcLabwareMutation
RecordQcLabwareMutation,
SampleFieldsFragment
} from '../types/sdk';
import * as Yup from 'yup';
import { StanCoreContext } from '../lib/sdk';
Expand All @@ -22,11 +23,11 @@ import { getCurrentDateTime } from '../types/stan';
import OperationCompleteModal from '../components/modal/OperationCompleteModal';
import { useLoaderData } from 'react-router-dom';
import { fromPromise } from 'xstate';
import { groupByRoi } from '../components/xeniumMetrics/RoiTable';

export type SampleComment = {
roi: string;
address: string;
sampleId: number;
sampleAddress: Array<{ sample: SampleFieldsFragment; address: string }>;
comments: string[];
};

Expand Down Expand Up @@ -110,6 +111,7 @@ const XeniumQC = () => {
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({
Expand All @@ -118,12 +120,15 @@ const XeniumQC = () => {
completion: prev.completion,
comments: [],
roiComments: [],
sampleComments: response.rois[0].rois.map((regionOfInterest) => ({
roi: regionOfInterest.roi,
address: regionOfInterest.address,
sampleId: regionOfInterest.sampleId,
comments: []
}))
sampleComments: Object.keys(groupedByRoi).map((roi) => {
return {
sampleAddress: groupedByRoi[roi].map((data) => {
return { sample: data.sample ?? '', address: data.address };
}),
roi,
comments: []
};
})
});
return prev;
});
Expand Down Expand Up @@ -158,12 +163,14 @@ const XeniumQC = () => {
workNumber: lw.workNumber,
comments: lw.comments.map((comment) => Number(comment)),
sampleComments: lw.sampleComments?.flatMap((sampleComment) => {
return sampleComment.comments.map((comment) => {
return {
address: sampleComment.address,
sampleId: sampleComment.sampleId,
commentId: Number(comment)
};
return sampleComment.sampleAddress.flatMap((sampleAdress) => {
return sampleComment.comments.map((commentId) => {
return {
sampleId: sampleAdress.sample.id,
address: sampleAdress.address,
commentId: Number(commentId)
};
});
});
})
};
Expand Down
Loading

0 comments on commit bb99cc5

Please sign in to comment.