Skip to content

Commit

Permalink
CPF-492 Add "Only Treasury Uploads" filter (#504)
Browse files Browse the repository at this point in the history
* CPF-492 add treasury uploads filter, add global filter option to table builder component

* sort uploads in desc order, by createdAt date

* remove lodash import

* remove interface

* add id to treasury checkbox to make the label clickable
  • Loading branch information
Vikariusu authored Nov 15, 2024
1 parent 199b883 commit 8a8bdd9
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 21 deletions.
1 change: 1 addition & 0 deletions api/src/graphql/uploads.sdl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const schema = gql`
type Query {
uploads: [Upload!]! @requireAuth
upload(id: Int!): Upload @requireAuth
getValidUploadsInCurrentPeriod: [Upload!]! @requireAuth
}
input CreateUploadInput {
Expand Down
1 change: 1 addition & 0 deletions api/src/services/uploads/uploads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const uploads: QueryResolvers['uploads'] = () => {

return db.upload.findMany({
where: whereInputs,
orderBy: { createdAt: 'desc' },
})
}

Expand Down
66 changes: 47 additions & 19 deletions web/src/components/TableBuilder/TableBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
getFilteredRowModel,
ColumnFiltersState,
} from '@tanstack/react-table'
import { Button } from 'react-bootstrap'
import { Button, Form } from 'react-bootstrap'
import Table from 'react-bootstrap/Table'

import TableHeader from './TableHeader'
Expand All @@ -16,9 +16,9 @@ import TableRow from './TableRow'
/*
This component uses TanStack Table to add filtering
and sorting functionality.
For documentation, visit: https://tanstack.com/table/v8/docs/guide/introduction
For documentation, visit: https://tanstack.com/table/v8/docs/introduction
*/
function TableBuilder({ data, columns, filterableInputs = [] }) {
function TableBuilder({ data, columns, filterableInputs = [], globalFilter }) {
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
const [sorting, setSorting] = useState([])

Expand All @@ -36,25 +36,57 @@ function TableBuilder({ data, columns, filterableInputs = [] }) {
getFilteredRowModel: getFilteredRowModel(),
})

const resetColumnFilters = () => {
const resetFilters = () => {
table.resetColumnFilters()
if (globalFilter) {
globalFilter.onChange()
}
}

const renderTableBody = () => {
const rows = table.getRowModel().rows

if (!rows.length) {
return (
<tr className="border">
<td colSpan={100} className="text-center py-4">
<span className="text-muted">No results found</span>
</td>
</tr>
)
}

return rows.map((row) => <TableRow row={row} key={row.id} />)
}

return (
<div className="p-2">
<Table striped borderless>
<thead>
{!!filterableInputs.length && (
{(!!filterableInputs.length || globalFilter) && (
<tr className="border">
<th className="text-end" colSpan={100}>
<Button
className="btn btn-secondary"
size="sm"
onClick={resetColumnFilters}
>
Reset filters
</Button>
</th>
<td colSpan={100} className="text-end pe-2">
<div className="d-inline-flex align-items-center gap-3">
{globalFilter && (
<Form.Check
type="checkbox"
id="treasury-files-filter"
label={globalFilter.label}
checked={globalFilter.checked}
onChange={globalFilter.onChange}
disabled={globalFilter.loading}
className="mb-0"
/>
)}
<Button
className="btn btn-secondary"
size="sm"
onClick={resetFilters}
>
Reset filters
</Button>
</div>
</td>
</tr>
)}
{table.getHeaderGroups().map((headerGroup) => (
Expand All @@ -65,11 +97,7 @@ function TableBuilder({ data, columns, filterableInputs = [] }) {
/>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<TableRow row={row} key={row.id} />
))}
</tbody>
<tbody>{renderTableBody()}</tbody>
</Table>
</div>
)
Expand Down
20 changes: 19 additions & 1 deletion web/src/components/Upload/Uploads/Uploads.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,19 @@ import TableBuilder from 'src/components/TableBuilder/TableBuilder'

import { columnDefs } from './columns'

const UploadsList = ({ uploads }: FindUploads) => {
interface UploadsListProps {
uploads: FindUploads['uploads']
showTreasuryFiles: boolean
onTreasuryFilesChange: () => void
isLoading?: boolean
}

const UploadsList = ({
uploads,
showTreasuryFiles,
onTreasuryFilesChange,
isLoading,
}: UploadsListProps) => {
const filterableInputs = [
'agency_code',
'expenditureCategory_code',
Expand All @@ -18,6 +30,12 @@ const UploadsList = ({ uploads }: FindUploads) => {
data={uploads}
columns={columnDefs}
filterableInputs={filterableInputs}
globalFilter={{
label: 'Only Treasury Files',
checked: showTreasuryFiles,
onChange: onTreasuryFilesChange,
loading: isLoading,
}}
/>
)
}
Expand Down
59 changes: 58 additions & 1 deletion web/src/components/Upload/UploadsCell/UploadsCell.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { useState } from 'react'

import type { FindUploads } from 'types/graphql'

import { Link, routes } from '@redwoodjs/router'
import type { CellSuccessProps, CellFailureProps } from '@redwoodjs/web'
import { useQuery } from '@redwoodjs/web'

import Uploads from 'src/components/Upload/Uploads'

Expand Down Expand Up @@ -39,6 +42,40 @@ export const QUERY = gql`
}
`

export const VALID_UPLOADS_QUERY = gql`
query GetValidUploadsInCurrentPeriod {
getValidUploadsInCurrentPeriod {
id
filename
uploadedBy {
id
email
}
agency {
id
code
}
expenditureCategory {
id
code
}
reportingPeriod {
id
name
}
latestValidation {
id
createdAt
passed
isManual
results
}
createdAt
updatedAt
}
}
`

export const Loading = () => <div>Loading...</div>

export const Empty = () => {
Expand All @@ -57,5 +94,25 @@ export const Failure = ({ error }: CellFailureProps) => (
)

export const Success = ({ uploads }: CellSuccessProps<FindUploads>) => {
return <Uploads uploads={uploads} />
const [showTreasuryFiles, setShowTreasuryFiles] = useState(false)
const { data: validUploadsData, loading: validUploadsLoading } = useQuery(
VALID_UPLOADS_QUERY,
{
skip: !showTreasuryFiles,
}
)

const displayedUploads =
showTreasuryFiles && validUploadsData
? validUploadsData.getValidUploadsInCurrentPeriod
: uploads

return (
<Uploads
uploads={displayedUploads}
showTreasuryFiles={showTreasuryFiles}
onTreasuryFilesChange={() => setShowTreasuryFiles(!showTreasuryFiles)}
isLoading={validUploadsLoading}
/>
)
}

0 comments on commit 8a8bdd9

Please sign in to comment.