-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Added Index Assignment tab - Implemented Assign by table to fit usage of MetagenimicsBatchItem and PcrBatchItem - Assign by table correctly loads Well Coordinates and Material Sample Name - Can assign, save, and load Index i5 and Index i7
- Loading branch information
1 parent
e177a35
commit dad62c3
Showing
6 changed files
with
911 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 99 additions & 2 deletions
101
packages/dina-ui/components/seqdb/metagenomics-workflow/MetagenomicsIndexAssignmentStep.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,100 @@ | ||
export function MetagenomicsIndexAssignmentStep() { | ||
return <></>; | ||
import { PersistedResource } from "kitsu"; | ||
import { PcrBatch } from "packages/dina-ui/types/seqdb-api"; | ||
import { Dispatch, SetStateAction } from "react"; | ||
import Col from "react-bootstrap/Col"; | ||
import Nav from "react-bootstrap/Nav"; | ||
import Row from "react-bootstrap/Row"; | ||
import Tab from "react-bootstrap/Tab"; | ||
import { useSeqdbIntl } from "packages/dina-ui/intl/seqdb-intl"; | ||
import { useLocalStorage } from "@rehooks/local-storage"; | ||
import { MetagenomicsBatch } from "packages/dina-ui/types/seqdb-api/resources/metagenomics/MetagenomicsBatch"; | ||
import { useMetagenomicsIndexAssignmentAPI } from "../ngs-workflow/useMetagenomicsIndexAssignmentAPI"; | ||
import { MetagenomicsIndexGrid } from "../ngs-workflow/index-grid/MetagenomicsIndexGrid"; | ||
import { MetagenomicsIndexAssignmentTable } from "../ngs-workflow/MetagenomicsIndexAssignmentTable"; | ||
|
||
export interface MetagenomicsIndexAssignmentStepProps { | ||
pcrBatchId: string; | ||
pcrBatch: PcrBatch; | ||
metagenomicsBatchId: string; | ||
metagenomicsBatch: MetagenomicsBatch; | ||
onSaved: ( | ||
nextStep: number, | ||
batchSaved?: PersistedResource<MetagenomicsBatch> | ||
) => Promise<void>; | ||
editMode: boolean; | ||
setEditMode: Dispatch<SetStateAction<boolean>>; | ||
performSave: boolean; | ||
setPerformSave: (newValue: boolean) => void; | ||
} | ||
|
||
export function MetagenomicsIndexAssignmentStep( | ||
props: MetagenomicsIndexAssignmentStepProps | ||
) { | ||
const { formatMessage } = useSeqdbIntl(); | ||
// Get the last active tab from local storage (defaults to "assignByGrid") | ||
const [activeKey, setActiveKey] = useLocalStorage( | ||
"metagenomicsIndexAssignmentStep_activeTab", | ||
"assignByGrid" | ||
); | ||
|
||
// Data required for both options is pretty much the same so share the data between both. | ||
const metagenomicsIndexAssignmentApiProps = | ||
useMetagenomicsIndexAssignmentAPI(props); | ||
|
||
const handleSelect = (eventKey) => { | ||
// Do not switch modes if in edit mode. This is used to prevent data from being mixed up. | ||
if (props.editMode) { | ||
return; | ||
} | ||
|
||
setActiveKey(eventKey); | ||
}; | ||
return ( | ||
<Tab.Container | ||
id="left-tabs-example" | ||
activeKey={activeKey} | ||
onSelect={handleSelect} | ||
> | ||
<Row> | ||
<Col sm={2}> | ||
<Nav variant="pills" className="flex-column"> | ||
<Nav.Item> | ||
<Nav.Link | ||
eventKey="assignByGrid" | ||
style={{ cursor: props.editMode ? "default" : "pointer" }} | ||
disabled={props.editMode} | ||
> | ||
{formatMessage("assignByGrid")} | ||
</Nav.Link> | ||
</Nav.Item> | ||
<Nav.Item> | ||
<Nav.Link | ||
eventKey="assignByTable" | ||
style={{ cursor: props.editMode ? "default" : "pointer" }} | ||
disabled={props.editMode} | ||
> | ||
{formatMessage("assignByTable")} | ||
</Nav.Link> | ||
</Nav.Item> | ||
</Nav> | ||
</Col> | ||
<Col sm={10}> | ||
<Tab.Content> | ||
<Tab.Pane eventKey="assignByGrid"> | ||
<MetagenomicsIndexGrid | ||
{...props} | ||
{...metagenomicsIndexAssignmentApiProps} | ||
/> | ||
</Tab.Pane> | ||
<Tab.Pane eventKey="assignByTable"> | ||
<MetagenomicsIndexAssignmentTable | ||
{...props} | ||
{...metagenomicsIndexAssignmentApiProps} | ||
/> | ||
</Tab.Pane> | ||
</Tab.Content> | ||
</Col> | ||
</Row> | ||
</Tab.Container> | ||
); | ||
} |
213 changes: 213 additions & 0 deletions
213
packages/dina-ui/components/seqdb/ngs-workflow/MetagenomicsIndexAssignmentTable.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
import { | ||
DinaForm, | ||
LoadingSpinner, | ||
ReactTable, | ||
SelectField, | ||
SelectOption, | ||
SubmitButton, | ||
useStringComparator | ||
} from "packages/common-ui/lib"; | ||
import { IndexAssignmentStepProps } from "./IndexAssignmentStep"; | ||
import { useMemo } from "react"; | ||
import { PcrBatchItem } from "packages/dina-ui/types/seqdb-api"; | ||
import { ColumnDef } from "@tanstack/react-table"; | ||
import { MaterialSampleSummary } from "packages/dina-ui/types/collection-api"; | ||
import { UseIndexAssignmentReturn } from "./useIndexAssignmentAPI"; | ||
import { useSeqdbIntl } from "packages/dina-ui/intl/seqdb-intl"; | ||
import { MetagenomicsBatchItem } from "packages/dina-ui/types/seqdb-api/resources/metagenomics/MetagenomicsBatchItem"; | ||
import { MetagenomicsIndexAssignmentStepProps } from "../metagenomics-workflow/MetagenomicsIndexAssignmentStep"; | ||
import { | ||
MetagenomicsIndexAssignmentResource, | ||
UseMetagenomicsIndexAssignmentReturn | ||
} from "./useMetagenomicsIndexAssignmentAPI"; | ||
|
||
interface MetagenomicsIndexAssignmentRow { | ||
materialSample?: MaterialSampleSummary; | ||
metagenomicsIndexAssignmentResource?: MetagenomicsIndexAssignmentResource; | ||
pcrBatchItem?: PcrBatchItem; | ||
} | ||
|
||
interface MetagenomicsIndexAssignmentTableProps | ||
extends MetagenomicsIndexAssignmentStepProps, | ||
UseMetagenomicsIndexAssignmentReturn {} | ||
|
||
export function MetagenomicsIndexAssignmentTable( | ||
props: MetagenomicsIndexAssignmentTableProps | ||
) { | ||
const { | ||
editMode, | ||
metagenomicsBatch, | ||
performSave, | ||
setPerformSave, | ||
loading, | ||
metagenomicsIndexAssignmentResources, | ||
materialSamples, | ||
ngsIndexes, | ||
onSubmitTable | ||
} = props; | ||
|
||
const { compareByStringAndNumber } = useStringComparator(); | ||
const { formatMessage } = useSeqdbIntl(); | ||
|
||
// Hidden button bar is used to submit the page from the button bar in a parent component. | ||
const hiddenButtonBar = ( | ||
<SubmitButton | ||
className="hidden" | ||
performSave={performSave} | ||
setPerformSave={setPerformSave} | ||
/> | ||
); | ||
|
||
const COLUMNS: ColumnDef<MetagenomicsIndexAssignmentRow>[] = [ | ||
{ | ||
cell: ({ row: { original: sr } }) => { | ||
const { metagenomicsIndexAssignmentResource } = | ||
sr as MetagenomicsIndexAssignmentRow; | ||
if ( | ||
!metagenomicsIndexAssignmentResource || | ||
!metagenomicsIndexAssignmentResource.storageUnitUsage | ||
) { | ||
return ""; | ||
} | ||
|
||
const { wellRow, wellColumn } = | ||
metagenomicsIndexAssignmentResource.storageUnitUsage; | ||
const wellCoordinates = | ||
wellColumn === null || !wellRow ? "" : `${wellRow}${wellColumn}`; | ||
|
||
return wellCoordinates; | ||
}, | ||
header: "Well Coordinates", | ||
accessorKey: "wellCoordinates", | ||
sortingFn: (a: any, b: any): number => { | ||
const aStorageUnit = | ||
a.original?.metagenomicsIndexAssignmentResource?.storageUnitUsage; | ||
const bStorageUnit = | ||
b.original?.metagenomicsIndexAssignmentResource?.storageUnitUsage; | ||
|
||
const aString = | ||
!aStorageUnit || | ||
aStorageUnit?.wellRow === null || | ||
aStorageUnit?.wellColumn === null | ||
? "" | ||
: `${aStorageUnit?.wellRow}${aStorageUnit?.wellColumn}`; | ||
const bString = | ||
!bStorageUnit || | ||
bStorageUnit?.wellRow === null || | ||
bStorageUnit?.wellColumn === null | ||
? "" | ||
: `${bStorageUnit?.wellRow}${bStorageUnit?.wellColumn}`; | ||
return compareByStringAndNumber(aString, bString); | ||
}, | ||
enableSorting: true, | ||
size: 150 | ||
}, | ||
{ | ||
header: "Material Sample Name", | ||
accessorKey: "materialSample.materialSampleName" | ||
}, | ||
{ | ||
header: "Index i5", | ||
cell: ({ row: { index } }) => | ||
metagenomicsBatch.indexSet && ( | ||
<SelectField | ||
hideLabel={true} | ||
name={`indexAssignment[${index}].indexI5`} | ||
options={ngsIndexes | ||
?.filter((ngsIndex) => ngsIndex.direction === "I5") | ||
?.map<SelectOption<string>>((ngsIndex) => ({ | ||
label: ngsIndex.name, | ||
value: ngsIndex.id | ||
}))} | ||
selectProps={{ | ||
isClearable: true | ||
}} | ||
/> | ||
) | ||
}, | ||
{ | ||
header: "Index i7", | ||
cell: ({ row: { index } }) => | ||
metagenomicsBatch.indexSet && ( | ||
<SelectField | ||
hideLabel={true} | ||
name={`indexAssignment[${index}].indexI7`} | ||
options={ngsIndexes | ||
?.filter((ngsIndex) => ngsIndex.direction === "I7") | ||
?.map<SelectOption<string>>((ngsIndex) => ({ | ||
label: ngsIndex.name, | ||
value: ngsIndex.id | ||
}))} | ||
selectProps={{ | ||
isClearable: true | ||
}} | ||
/> | ||
) | ||
} | ||
]; | ||
|
||
const tableData = useMemo( | ||
() => | ||
metagenomicsIndexAssignmentResources && | ||
metagenomicsIndexAssignmentResources.length !== 0 | ||
? metagenomicsIndexAssignmentResources.map<MetagenomicsIndexAssignmentRow>( | ||
(prep) => ({ | ||
metagenomicsIndexAssignmentResource: prep, | ||
materialSample: materialSamples?.find( | ||
(samp) => samp.id === prep?.materialSampleSummary?.id | ||
) | ||
}) | ||
) | ||
: [], | ||
[metagenomicsIndexAssignmentResources, materialSamples] | ||
); | ||
|
||
const initialValues = useMemo(() => { | ||
if ( | ||
!metagenomicsIndexAssignmentResources || | ||
metagenomicsIndexAssignmentResources.length === 0 | ||
) { | ||
return {}; | ||
} | ||
|
||
return { | ||
indexAssignment: metagenomicsIndexAssignmentResources.map((resource) => ({ | ||
...(resource.indexI5 ? { indexI5: resource?.indexI5?.id } : {}), | ||
...(resource.indexI7 ? { indexI7: resource?.indexI7?.id } : {}) | ||
})) | ||
}; | ||
}, [metagenomicsIndexAssignmentResources]); | ||
|
||
if (loading) { | ||
return <LoadingSpinner loading={true} />; | ||
} | ||
|
||
if (!metagenomicsBatch?.indexSet?.id) { | ||
return ( | ||
<div className="alert alert-warning mt-2"> | ||
{formatMessage("missingIndexForAssignment")} | ||
</div> | ||
); | ||
} | ||
|
||
return ( | ||
<DinaForm | ||
initialValues={initialValues} | ||
onSubmit={onSubmitTable} | ||
readOnly={editMode === false} | ||
enableReinitialize={true} | ||
> | ||
{hiddenButtonBar} | ||
<ReactTable<MetagenomicsIndexAssignmentRow> | ||
className="-striped react-table-overflow" | ||
columns={COLUMNS} | ||
data={tableData} | ||
loading={loading} | ||
manualPagination={true} | ||
showPagination={false} | ||
pageSize={tableData.length} | ||
sort={[{ id: "wellCoordinates", desc: false }]} | ||
/> | ||
</DinaForm> | ||
); | ||
} |
Oops, something went wrong.