diff --git a/frontend/src/components/RecordsList.tsx b/frontend/src/components/RecordsList.tsx index b4aa00a4..fd070882 100644 --- a/frontend/src/components/RecordsList.tsx +++ b/frontend/src/components/RecordsList.tsx @@ -1,10 +1,8 @@ import AutoSizer from "react-virtualized-auto-sizer"; -import { Button, Col, Container, Form, Row, Modal } from "react-bootstrap"; +import { Button, Container, Modal } from "react-bootstrap"; import { FunctionComponent, useMemo } from "react"; import { useNavigate } from "react-router-dom"; -import classNames from "classnames"; import { DownloadModal } from "./DownloadModal"; -import Spinner from "react-spinkit"; import { CSVFormulate } from "../lib/CSVExport"; import { AgGridReact } from "ag-grid-react"; import { useState } from "react"; @@ -17,9 +15,8 @@ import { useHookGeneric } from "../shared/types"; import { SamplesList } from "./SamplesList"; import { SampleWhere } from "../generated/graphql"; import { defaultRecordsColDef } from "../shared/helpers"; -import InfoIcon from "@material-ui/icons/InfoOutlined"; -import { Tooltip } from "@material-ui/core"; import { PatientIdsTriplet } from "../pages/patients/PatientsPage"; +import { ErrorMessage, LoadingSpinner, Toolbar } from "../shared/tableElements"; export interface IRecordsListProps { lazyRecordsQuery: typeof useHookGeneric; @@ -119,14 +116,9 @@ const RecordsList: FunctionComponent = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [searchVal]); - if (loading) - return ( -
- -
- ); + if (loading) return ; - if (error) return

Error :(

; + if (error) return ; const remoteCount = data?.[totalCountNodeName]?.totalCount; @@ -224,76 +216,22 @@ const RecordsList: FunctionComponent = ({ )} - - - - - { - if (event.key === "Enter") { - handleSearch(); - } - }} - onInput={(event) => { - const newVal = event.currentTarget.value; - if (newVal === "") { - setCustomFilterVals && setCustomFilterVals([]); - setSearchVal([]); - } - setInputVal(newVal); - }} - /> - - - - - After inputting your search query, click on "Search" - or press "Enter" to get your results. To bulk search, - input a list of values separated by spaces or commas (e.g. - "value1 value2 value3") - - } - > - - - - - - - - - - {remoteCount?.toLocaleString()} matching{" "} - {remoteCount > 1 ? searchTerm : searchTerm.slice(0, -1)} - - - {customFilterUI} + { + setCustomFilterVals && setCustomFilterVals([]); + setSearchVal([]); + }} + matchingResultsCount={`${remoteCount?.toLocaleString()} matching ${ + remoteCount > 1 ? searchTerm : searchTerm.slice(0, -1) + }`} + handleDownload={handleDownload} + customUI={customFilterUI} + /> - - - - {({ width }) => (
= ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [searchVal]); - if (loading) - return ( -
- -
- ); + if (loading) return ; - if (error) return Error loading request details / request samples; + if (error) return ; const samples = data!.samplesConnection.edges.map((e) => e.node) as Sample[]; @@ -249,104 +241,50 @@ export const SamplesList: FunctionComponent = ({ } /> - - - - { - if (event.key === "Enter") { - setSearchVal(val); - } - }} - onInput={(event) => { - const newVal = event.currentTarget.value; - if (newVal === "") { - setSearchVal(""); - } - setVal(newVal); - }} - /> - - - - - After inputting your search query, click on "Search" - or press "Enter" to get your results. To bulk search, - input a list of values separated by spaces or commas (e.g. - "value1 value2 value3") - - } - > - - - - - - - - - - {remoteCount === max_rows + { + setSearchVal(val); + }} + clearInput={() => { + setSearchVal(""); + }} + matchingResultsCount={ + remoteCount === max_rows ? `${max_rows}+ matching samples` - : `${remoteCount} matching samples`} - - - {changes.length > 0 && ( - <> - - - - - - - - )} + : `${remoteCount} matching samples` + } + handleDownload={() => setShowDownloadModal(true)} + customUI={ + changes.length > 0 ? ( + <> + + + - - - - + + + + + ) : undefined + } + /> {({ width }) => ( diff --git a/frontend/src/shared/tableElements.tsx b/frontend/src/shared/tableElements.tsx new file mode 100644 index 00000000..eaac6367 --- /dev/null +++ b/frontend/src/shared/tableElements.tsx @@ -0,0 +1,110 @@ +import { ApolloError } from "@apollo/client"; +import classNames from "classnames"; +import { Button, Col, Form, Row } from "react-bootstrap"; +import Spinner from "react-spinkit"; +import InfoIcon from "@material-ui/icons/InfoOutlined"; +import { Tooltip } from "@material-ui/core"; + +export function LoadingSpinner() { + return ( +
+ +
+ ); +} + +export function ErrorMessage({ error }: { error: ApolloError }) { + return ( + + There was an error loading data ({error.name}: {error.message}). + + ); +} + +export function Toolbar({ + searchTerm, + input, + setInput, + handleSearch, + clearInput, + matchingResultsCount, + handleDownload, + customUI, +}: { + searchTerm: string; + input: string; + setInput: (input: string) => void; + handleSearch: () => void; + clearInput: () => void; + matchingResultsCount: string; + handleDownload: () => void; + customUI?: JSX.Element; +}) { + return ( + + + + + { + if (event.key === "Enter") { + handleSearch(); + } + }} + onInput={(event) => { + const currInput = event.currentTarget.value; + if (currInput === "") { + clearInput(); + } + setInput(currInput); + }} + /> + + + + + After inputting your search query, click on "Search" or + press "Enter" to get your results. To bulk search, input + a list of values separated by spaces or commas (e.g. "value1 + value2 value3") + + } + > + + + + + + + + + {matchingResultsCount} + + {customUI} + + + + + + ); +}