Skip to content

Commit

Permalink
Merge branch 'mvp-2.1.0' into CRDCDH-730
Browse files Browse the repository at this point in the history
  • Loading branch information
Alejandro-Vega authored Jan 17, 2024
2 parents b9509f2 + c752c6e commit 45ca65e
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 27 deletions.
7 changes: 7 additions & 0 deletions src/components/DataSubmissions/GenericTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export type FetchListing<T> = {

export type TableMethods = {
refresh: () => void;
setPage: (page: number, forceRefetch?: boolean) => void;
};

type Props<T> = {
Expand Down Expand Up @@ -193,6 +194,12 @@ const GenericTable = <T,>({
useImperativeHandle(ref, () => ({
refresh: () => {
fetchData(true);
},
setPage: (newPage: number, forceRefetch = false) => {
setPage(newPage);
if (forceRefetch) {
fetchData(true);
}
}
}));

Expand Down
170 changes: 163 additions & 7 deletions src/content/dataSubmissions/QualityControl.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { useMemo, useRef, useState } from "react";
import { useLazyQuery } from "@apollo/client";
import { FC, useEffect, useMemo, useRef, useState } from "react";
import { useLazyQuery, useQuery } from "@apollo/client";
import { useParams } from "react-router-dom";
import { isEqual } from "lodash";
import { Box, Button, styled } from "@mui/material";
import { SUBMISSION_QC_RESULTS, submissionQCResultsResp } from "../../graphql";
import { Box, Button, FormControl, MenuItem, Select, styled } from "@mui/material";
import { Controller, useForm } from 'react-hook-form';
import { LIST_BATCHES, LIST_NODE_TYPES, ListBatchesResp, ListNodeTypesResp, SUBMISSION_QC_RESULTS, submissionQCResultsResp } from "../../graphql";
import GenericTable, { Column, FetchListing, TableMethods } from "../../components/DataSubmissions/GenericTable";
import { FormatDate } from "../../utils";
import ErrorDialog from "./ErrorDialog";
import QCResultsContext from "./Contexts/QCResultsContext";

type FilterForm = {
nodeType: string | "All";
batchID: number | "All";
severity: QCResult["severity"] | "All";
};

const StyledErrorDetailsButton = styled(Button)({
display: "inline",
color: "#0D78C5",
Expand Down Expand Up @@ -42,6 +49,58 @@ const StyledBreakAll = styled(Box)({
wordBreak: "break-all"
});

const StyledFilterContainer = styled(Box)({
display: "flex",
alignItems: "center",
justifyContent: "flex-start",
marginBottom: "19px",
paddingLeft: "24px",
});

const StyledFormControl = styled(FormControl)({
margin: "10px",
marginRight: "15px",
minWidth: "250px",
});

const StyledInlineLabel = styled('label')({
padding: "0 10px",
fontWeight: "700"
});

const baseTextFieldStyles = {
borderRadius: "8px",
"& .MuiInputBase-input": {
fontWeight: 400,
fontSize: "16px",
fontFamily: "'Nunito', 'Rubik', sans-serif",
padding: "10px",
height: "20px",
},
"& .MuiOutlinedInput-notchedOutline": {
borderColor: "#6B7294",
},
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
border: "1px solid #209D7D",
boxShadow: "2px 2px 4px 0px rgba(38, 184, 147, 0.10), -1px -1px 6px 0px rgba(38, 184, 147, 0.20)",
},
"& .Mui-disabled": {
cursor: "not-allowed",
},
"& .MuiList-root": {
padding: "0 !important",
},
"& .MuiMenuItem-root.Mui-selected": {
background: "#3E7E6D !important",
color: "#FFFFFF !important",
},
"& .MuiMenuItem-root:hover": {
background: "#D5EDE5",
},
};

const StyledSelect = styled(Select)(baseTextFieldStyles);

const columns: Column<QCResult>[] = [
{
label: "Type",
Expand Down Expand Up @@ -100,8 +159,9 @@ const columns: Column<QCResult>[] = [
},
];

const QualityControl = () => {
const QualityControl: FC = () => {
const { submissionId } = useParams();
const { watch, control } = useForm<FilterForm>();

const [loading, setLoading] = useState<boolean>(false);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -116,7 +176,26 @@ const QualityControl = () => {
const [submissionQCResults] = useLazyQuery<submissionQCResultsResp>(SUBMISSION_QC_RESULTS, {
variables: { id: submissionId },
context: { clientName: 'backend' },
fetchPolicy: 'no-cache'
fetchPolicy: 'cache-and-network',
});

const { data: batchData } = useQuery<ListBatchesResp>(LIST_BATCHES, {
variables: {
submissionID: submissionId,
first: -1,
offset: 0,
partial: true,
orderBy: "displayID",
sortDirection: "asc",
},
context: { clientName: 'backend' },
fetchPolicy: 'cache-and-network',
});

const { data: nodeTypes } = useQuery<ListNodeTypesResp>(LIST_NODE_TYPES, {
variables: { _id: submissionId, },
context: { clientName: 'backend' },
fetchPolicy: 'cache-and-network',
});

const handleFetchQCResults = async (fetchListing: FetchListing<QCResult>, force: boolean) => {
Expand All @@ -133,13 +212,19 @@ const QualityControl = () => {

try {
setLoading(true);

const nodeType = watch("nodeType");
const batchID = watch("batchID");
const { data: d, error } = await submissionQCResults({
variables: {
submissionID: submissionId,
first,
offset,
sortDirection,
orderBy
orderBy,
nodeTypes: !nodeType || nodeType === "All" ? undefined : [watch("nodeType")],
batchIDs: !batchID || batchID === "All" ? undefined : [watch("batchID")],
severities: watch("severity") || "All",
},
context: { clientName: 'backend' },
fetchPolicy: 'no-cache'
Expand All @@ -166,8 +251,79 @@ const QualityControl = () => {
handleOpenErrorDialog
}), [handleOpenErrorDialog]);

useEffect(() => {
tableRef.current?.setPage(0, true);
}, [watch("nodeType"), watch("batchID"), watch("severity")]);

return (
<>
<StyledFilterContainer>
<StyledInlineLabel htmlFor="nodeType-filter">Node Type</StyledInlineLabel>
<StyledFormControl>
<Controller
name="nodeType"
control={control}
render={({ field }) => (
<StyledSelect
{...field}
defaultValue="All"
value={field.value || "All"}
MenuProps={{ disablePortal: true }}
inputProps={{ id: "nodeType-filter" }}
>
<MenuItem value="All">All</MenuItem>
{nodeTypes?.listSubmissionNodeTypes?.map((nodeType) => (
<MenuItem key={nodeType} value={nodeType}>{nodeType}</MenuItem>
))}
</StyledSelect>
)}
/>
</StyledFormControl>
<StyledInlineLabel htmlFor="batchID-filter">Batch ID</StyledInlineLabel>
<StyledFormControl>
<Controller
name="batchID"
control={control}
render={({ field }) => (
<StyledSelect
{...field}
defaultValue="All"
value={field.value || "All"}
MenuProps={{ disablePortal: true }}
inputProps={{ id: "batchID-filter" }}
>
<MenuItem value="All">All</MenuItem>
{batchData?.listBatches?.batches?.map((batch) => (
<MenuItem key={batch._id} value={batch._id}>
{batch.displayID}
{` (${FormatDate(batch.createdAt, "MM/DD/YYYY")})`}
</MenuItem>
))}
</StyledSelect>
)}
/>
</StyledFormControl>
<StyledInlineLabel htmlFor="severity-filter">Severity</StyledInlineLabel>
<StyledFormControl>
<Controller
name="severity"
control={control}
render={({ field }) => (
<StyledSelect
{...field}
defaultValue="All"
value={field.value || "All"}
MenuProps={{ disablePortal: true }}
inputProps={{ id: "severity-filter" }}
>
<MenuItem value="All">All</MenuItem>
<MenuItem value="Error">Error</MenuItem>
<MenuItem value="Warning">Warning</MenuItem>
</StyledSelect>
)}
/>
</StyledFormControl>
</StyledFilterContainer>
<QCResultsContext.Provider value={providerValue}>
<GenericTable
ref={tableRef}
Expand Down
3 changes: 3 additions & 0 deletions src/graphql/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export type { Response as submissionQCResultsResp } from "./submissionQCResults"
export { mutation as VALIDATE_SUBMISSION } from "./validateSubmission";
export type { Response as ValidateSubmissionResp } from "./validateSubmission";

export { query as LIST_NODE_TYPES } from "./listSubmissionNodeTypes";
export type { Response as ListNodeTypesResp } from "./listSubmissionNodeTypes";

// User Profile
export { query as GET_USER } from "./getUser";
export type { Response as GetUserResp } from "./getUser";
Expand Down
57 changes: 37 additions & 20 deletions src/graphql/listBatches.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,45 @@
import gql from 'graphql-tag';

// The base Batch model used for all listBatches queries
const BaseBatchFragment = gql`
fragment BaseBatchFragment on Batch {
_id
displayID
createdAt
updatedAt
}
`;

// The extended batch model which includes all fields
const FullBatchFragment = gql`
fragment BatchFragment on Batch {
submissionID
type
metadataIntention
fileCount
files {
nodeType
filePrefix
fileName
size
status
errors
createdAt
updatedAt
}
status
errors
}
`;

export const query = gql`
query listBatches(
$submissionID: ID!
$first: Int
$offset: Int
$orderBy: String
$sortDirection: String
$partial: Boolean = false
) {
listBatches(
submissionID: $submissionID
Expand All @@ -17,29 +50,13 @@ export const query = gql`
) {
total
batches {
_id
displayID
submissionID
type
metadataIntention
fileCount
files {
nodeType
filePrefix
fileName
size
status
errors
createdAt
updatedAt
}
status
errors
createdAt
updatedAt
...BaseBatchFragment
...BatchFragment @skip(if: $partial)
}
}
}
${FullBatchFragment}
${BaseBatchFragment}
`;

export type Response = {
Expand Down
11 changes: 11 additions & 0 deletions src/graphql/listSubmissionNodeTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import gql from "graphql-tag";

export const query = gql`
query listSubmissionNodeTypes($_id: ID!) {
listSubmissionNodeTypes(_id: $_id)
}
`;

export type Response = {
listSubmissionNodeTypes: string[];
};
6 changes: 6 additions & 0 deletions src/graphql/submissionQCResults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@ import gql from "graphql-tag";
export const query = gql`
query submissionQCResults(
$id: ID!
$nodeTypes: [String]
$batchIDs: [ID]
$severities: String
$first: Int
$offset: Int
$orderBy: String
$sortDirection: String
) {
submissionQCResults(
_id: $id
nodeTypes: $nodeTypes
batchIDs: $batchIDs
severities: $severities
first: $first
offset: $offset
orderBy: $orderBy
Expand Down

0 comments on commit 45ca65e

Please sign in to comment.