Skip to content

Commit

Permalink
Merge pull request #256 from CBIIT/CRDCDH-603
Browse files Browse the repository at this point in the history
CRDCDH-603 Batch File List
  • Loading branch information
amattu2 authored Jan 12, 2024
2 parents a803d49 + ad64f6d commit 842267a
Show file tree
Hide file tree
Showing 9 changed files with 424 additions and 44 deletions.
84 changes: 51 additions & 33 deletions src/components/DataSubmissions/GenericTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
TableCell,
TableCellProps,
TableContainer,
TableContainerProps,
TableHead,
TablePagination,
TablePaginationProps,
Expand All @@ -13,20 +14,22 @@ import {
Typography,
styled,
} from "@mui/material";
import { ElementType, forwardRef, useEffect, useImperativeHandle, useMemo, useState } from "react";
import { CSSProperties, ElementType, forwardRef, useEffect, useImperativeHandle, useMemo, useState } from "react";
import { useAuthContext } from "../Contexts/AuthContext";
import PaginationActions from "./PaginationActions";
import SuspenseLoader from '../SuspenseLoader';

const StyledTableContainer = styled(TableContainer)({
borderRadius: "8px",
border: 0,
border: "1px solid #6CACDA",
marginBottom: "25px",
position: "relative",
overflowX: "auto",
overflowY: "hidden",
"& .MuiTableRow-root:nth-of-type(2n)": {
background: "#E3EEF9",
},
" .MuiTableCell-root:first-of-type": {
"& .MuiTableCell-root:first-of-type": {
paddingLeft: "40.44px",
},
"& .MuiTableCell-root:last-of-type": {
Expand Down Expand Up @@ -74,11 +77,11 @@ const StyledTableCell = styled(TableCell)({
},
});

const StyledTablePagination = styled(TablePagination)<
TablePaginationProps & { component: ElementType }
>({
"& .MuiTablePagination-displayedRows, & .MuiTablePagination-selectLabel, & .MuiTablePagination-select":
{
const StyledTablePagination = styled(TablePagination, {
shouldForwardProp: (prop) => prop !== "placement"
})<TablePaginationProps & { component: ElementType; placement: CSSProperties["justifyContent"]; }>(
({ placement }) => ({
"& .MuiTablePagination-displayedRows, & .MuiTablePagination-selectLabel, & .MuiTablePagination-select": {
height: "27px",
display: "flex",
alignItems: "center",
Expand All @@ -93,24 +96,31 @@ const StyledTablePagination = styled(TablePagination)<
lineHeight: "14.913px",
letterSpacing: "0.14px",
},
"& .MuiToolbar-root .MuiInputBase-root": {
height: "27px",
marginLeft: 0,
marginRight: "16px",
},
"& .MuiToolbar-root p": {
marginTop: 0,
marginBottom: 0,
},
"& .MuiToolbar-root": {
minHeight: "45px",
height: "fit-content",
paddingTop: "7px",
paddingBottom: "6px",
borderTop: "2px solid #083A50",
background: "#F5F7F8",
},
});
"& .MuiToolbar-root .MuiInputBase-root": {
height: "27px",
marginLeft: 0,
marginRight: "16px",
},
"& .MuiToolbar-root p": {
marginTop: 0,
marginBottom: 0,
},
"& .MuiToolbar-root": {
minHeight: "45px",
height: "fit-content",
paddingTop: "7px",
paddingBottom: "6px",
borderTop: "2px solid #083A50",
background: "#F5F7F8",
...(placement && {
justifyContent: placement,
"& .MuiTablePagination-spacer": {
display: "none"
}
})
},
})
);

export type Order = "asc" | "desc";

Expand Down Expand Up @@ -140,34 +150,41 @@ type Props<T> = {
total: number;
loading?: boolean;
noContentText?: string;
defaultOrder?: Order;
defaultRowsPerPage?: number;
paginationPlacement?: CSSProperties["justifyContent"];
containerProps?: TableContainerProps;
setItemKey?: (item: T, index: number) => string;
onFetchData?: (params: FetchListing<T>, force: boolean) => void;
onOrderChange?: (order: Order) => void;
onOrderByChange?: (orderBy: Column<T>) => void;
onPerPageChange?: (perPage: number) => void;
};

const DataSubmissionBatchTable = <T,>({
const GenericTable = <T,>({
columns,
data,
total = 0,
loading,
noContentText,
defaultOrder = "desc",
defaultRowsPerPage = 10,
paginationPlacement,
containerProps,
setItemKey,
onFetchData,
onOrderChange,
onOrderByChange,
onPerPageChange,
}: Props<T>, ref: React.Ref<TableMethods>) => {
const { user } = useAuthContext();
const [order, setOrder] = useState<Order>("desc");
const [order, setOrder] = useState<Order>(defaultOrder);
const [orderBy, setOrderBy] = useState<Column<T>>(
columns.find((c) => c.default) || columns.find((c) => c.field)
);
const [page, setPage] = useState<number>(0);
const [perPage, setPerPage] = useState<number>(defaultRowsPerPage);
const numRowsNoContent = 10;

useEffect(() => {
fetchData();
Expand Down Expand Up @@ -219,7 +236,7 @@ const DataSubmissionBatchTable = <T,>({
};

return (
<StyledTableContainer>
<StyledTableContainer {...containerProps}>
{loading && (<SuspenseLoader fullscreen={false} />)}
<Table>
<StyledTableHead>
Expand All @@ -242,7 +259,7 @@ const DataSubmissionBatchTable = <T,>({
</TableRow>
</StyledTableHead>
<TableBody>
{loading ? Array.from(Array(perPage).keys())?.map((_, idx) => (
{loading && total === 0 ? Array.from(Array(numRowsNoContent).keys())?.map((_, idx) => (
<StyledTableRow key={`loading_row_${idx}`}>
<TableCell colSpan={columns.length} />
</StyledTableRow>
Expand Down Expand Up @@ -271,7 +288,7 @@ const DataSubmissionBatchTable = <T,>({

{/* No content message */}
{!loading && (!total || total === 0) && (
<TableRow style={{ height: 46 * 10 }}>
<TableRow style={{ height: 46 * numRowsNoContent }}>
<TableCell colSpan={columns.length}>
<Typography
variant="h6"
Expand All @@ -294,6 +311,7 @@ const DataSubmissionBatchTable = <T,>({
page={page}
onPageChange={(e, newPage) => setPage(newPage - 1)}
onRowsPerPageChange={handleChangeRowsPerPage}
placement={paginationPlacement}
nextIconButtonProps={{
disabled: perPage === -1
|| !data
Expand All @@ -310,6 +328,6 @@ const DataSubmissionBatchTable = <T,>({
);
};

const BatchTableWithRef = forwardRef(DataSubmissionBatchTable) as <T>(props: Props<T> & { ref?: React.Ref<TableMethods> }) => ReturnType<typeof DataSubmissionBatchTable>;
const TableWithRef = forwardRef(GenericTable) as <T>(props: Props<T> & { ref?: React.Ref<TableMethods> }) => ReturnType<typeof GenericTable>;

export default BatchTableWithRef;
export default TableWithRef;
11 changes: 11 additions & 0 deletions src/config/TableConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Order } from "../components/DataSubmissions/GenericTable";

export const SORT: { [key in Order as Uppercase<Order>]: Order } = {
ASC: "asc",
DESC: "desc",
};

export const DIRECTION: { [key in Order as Uppercase<Order>]: number } = {
ASC: 1,
DESC: -1,
};
1 change: 1 addition & 0 deletions src/content/dataSubmissions/Contexts/BatchTableContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";

const BatchTableContext = React.createContext<{
handleOpenErrorDialog?:(data: Batch) => void;
handleOpenFileListDialog?:(data: Batch) => void;
}>({});

export default BatchTableContext;
68 changes: 57 additions & 11 deletions src/content/dataSubmissions/DataSubmission.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import BatchTableContext from "./Contexts/BatchTableContext";
import DataSubmissionStatistics from '../../components/DataSubmissions/ValidationStatistics';
import ValidationControls from '../../components/DataSubmissions/ValidationControls';
import { useAuthContext } from "../../components/Contexts/AuthContext";
import FileListDialog from "./FileListDialog";
import { shouldDisableSubmit } from "../../utils/dataSubmissionUtils";

const StyledBanner = styled("div")(({ bannerSrc }: { bannerSrc: string }) => ({
Expand Down Expand Up @@ -224,6 +225,23 @@ const StyledErrorDetailsButton = styled(Button)(() => ({
},
}));

const StyledFileCountButton = styled(Button)(() => ({
color: "#0D78C5",
fontFamily: "Inter",
fontSize: "16px",
fontStyle: "normal",
fontWeight: 600,
lineHeight: "19px",
textDecorationLine: "underline",
textTransform: "none",
padding: 0,
justifyContent: "flex-start",
"&:hover": {
background: "transparent",
textDecorationLine: "underline",
},
}));

const columns: Column<Batch>[] = [
{
label: "Batch ID",
Expand All @@ -242,7 +260,23 @@ const columns: Column<Batch>[] = [
},
{
label: "File Count",
renderValue: (data) => Intl.NumberFormat("en-US", { maximumFractionDigits: 0 }).format(data?.fileCount || 0),
renderValue: (data) => (
<BatchTableContext.Consumer>
{({ handleOpenFileListDialog }) => (
<StyledFileCountButton
onClick={() => handleOpenFileListDialog && handleOpenFileListDialog(data)}
variant="text"
disableRipple
disableTouchRipple
disableFocusRipple
>
{Intl.NumberFormat("en-US", { maximumFractionDigits: 0 }).format(
data?.fileCount || 0
)}
</StyledFileCountButton>
)}
</BatchTableContext.Consumer>
),
field: "fileCount",
},
{
Expand Down Expand Up @@ -298,13 +332,14 @@ const DataSubmission = () => {
const { submissionId, tab } = useParams();
const { user } = useAuthContext();

const [batchFiles, setBatchFiles] = useState<Batch[]>([]);
const [totalBatchFiles, setTotalBatchFiles] = useState<number>(0);
const [batches, setBatches] = useState<Batch[]>([]);
const [totalBatches, setTotalBatches] = useState<number>(0);
const [prevBatchFetch, setPrevBatchFetch] = useState<FetchListing<Batch>>(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
const [changesAlert, setChangesAlert] = useState<AlertState>(null);
const [openErrorDialog, setOpenErrorDialog] = useState<boolean>(false);
const [openFileListDialog, setOpenFileListDialog] = useState<boolean>(false);
const [selectedRow, setSelectedRow] = useState<Batch | null>(null);

const {
Expand Down Expand Up @@ -344,13 +379,13 @@ const DataSubmission = () => {
fetchPolicy: 'no-cache'
});

const handleFetchBatchFiles = async (fetchListing: FetchListing<Batch>, force: boolean) => {
const handleFetchBatches = async (fetchListing: FetchListing<Batch>, force: boolean) => {
const { first, offset, sortDirection, orderBy } = fetchListing || {};
if (!submissionId) {
setError("Invalid submission ID provided.");
return;
}
if (!force && batchFiles?.length > 0 && isEqual(fetchListing, prevBatchFetch)) {
if (!force && batches?.length > 0 && isEqual(fetchListing, prevBatchFetch)) {
return;
}

Expand All @@ -373,8 +408,8 @@ const DataSubmission = () => {
setError("Unable to retrieve batch data.");
return;
}
setBatchFiles(newBatchFiles.listBatches.batches);
setTotalBatchFiles(newBatchFiles.listBatches.total);
setBatches(newBatchFiles.listBatches.batches);
setTotalBatches(newBatchFiles.listBatches.total);
} catch (err) {
setError("Unable to retrieve batch data.");
} finally {
Expand Down Expand Up @@ -431,6 +466,11 @@ const DataSubmission = () => {
setSelectedRow(data);
};

const handleOpenFileListDialog = (data: Batch) => {
setOpenFileListDialog(true);
setSelectedRow(data);
};

const handleOnValidate = (status: boolean) => {
if (!status) {
return;
Expand All @@ -440,7 +480,8 @@ const DataSubmission = () => {
};

const providerValue = useMemo(() => ({
handleOpenErrorDialog
handleOpenErrorDialog,
handleOpenFileListDialog
}), [handleOpenErrorDialog]);

useEffect(() => {
Expand Down Expand Up @@ -515,11 +556,11 @@ const DataSubmission = () => {
<GenericTable
ref={tableRef}
columns={columns}
data={batchFiles || []}
total={totalBatchFiles || 0}
data={batches || []}
total={totalBatches || 0}
loading={loading}
defaultRowsPerPage={20}
onFetchData={handleFetchBatchFiles}
onFetchData={handleFetchBatches}
/>
</BatchTableContext.Provider>
) : <QualityControl />}
Expand All @@ -545,6 +586,11 @@ const DataSubmission = () => {
errors={selectedRow?.errors}
uploadedDate={data?.getSubmission?.createdAt}
/>
<FileListDialog
open={openFileListDialog}
batch={selectedRow}
onClose={() => setOpenFileListDialog(false)}
/>
</StyledWrapper>
);
};
Expand Down
Loading

0 comments on commit 842267a

Please sign in to comment.