Skip to content

Commit

Permalink
feat: implement filtering from backend
Browse files Browse the repository at this point in the history
  • Loading branch information
stampaaaron committed Jun 21, 2022
1 parent ae4a0af commit 2a7136e
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 19 deletions.
6 changes: 6 additions & 0 deletions graphql-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ export type DossierCollection = {
metadata: CollectionMetadata;
};

export type DossierFilterInput = {
tenantName: Array<Scalars['String']>;
};

export type DossierInput = {
affiliation: AffiliationInput;
candidate: PersonInput;
Expand Down Expand Up @@ -267,6 +271,7 @@ export type QueryConferencesArgs = {


export type QueryDossiersArgs = {
filter?: InputMaybe<DossierFilterInput>;
id?: InputMaybe<Scalars['Int']>;
ids?: InputMaybe<Array<Scalars['Int']>>;
page?: InputMaybe<Scalars['Int']>;
Expand Down Expand Up @@ -457,6 +462,7 @@ export type CreateUserMutation = { __typename?: 'Mutation', users?: { __typename

export type IndexDossiersQueryVariables = Exact<{
page?: InputMaybe<Scalars['Int']>;
filter?: InputMaybe<DossierFilterInput>;
}>;


Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"history": "^5.3.0",
"jsonexport": "^3.2.0",
"os-browserify": "^0.3.0",
"query-string": "^7.1.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-intl": "^6.0.4",
Expand All @@ -58,6 +59,7 @@
"react-scripts": "5.0.1",
"stream-browserify": "^3.0.0",
"typescript": "4.7.3",
"use-query-params": "^1.2.3",
"web-vitals": "^2.1.4"
},
"devDependencies": {
Expand Down
34 changes: 30 additions & 4 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { ApolloClient, ApolloProvider, createHttpLink, from } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
import React from 'react';
import React, { PropsWithChildren, useMemo } from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
import CONFIGURATION from './configuration';
import { css, Global } from '@emotion/react';
import { BrowserRouter } from 'react-router-dom';
import { BrowserRouter, useLocation, useNavigate } from 'react-router-dom';
import { Location } from 'history';
import { QueryParamProvider } from 'use-query-params';
import './index.less';
import { cacheInstance, sessionVar } from './cache';

Expand Down Expand Up @@ -53,13 +55,37 @@ const httpLink = createHttpLink({

const client = new ApolloClient({ link: from([authLink, httpLink]), cache: cacheInstance });

const RouteAdapter: React.FC<PropsWithChildren> = ({ children }) => {
const navigate = useNavigate();
const location = useLocation();

const adaptedHistory = useMemo(
() => ({
replace(location: Location) {
navigate(location, { replace: true, state: location.state });
},
push(location: Location) {
navigate(location, {
replace: false,
state: location.state
});
}
}),
[navigate]
);
// @ts-ignore
return children({ history: adaptedHistory, location });
};

function AppShell() {
return (
<React.StrictMode>
<ApolloProvider client={client}>
<BrowserRouter>
{globalStyles}
<App />
<QueryParamProvider ReactRouterRoute={RouteAdapter}>
{globalStyles}
<App />
</QueryParamProvider>
</BrowserRouter>
</ApolloProvider>
</React.StrictMode>
Expand Down
7 changes: 6 additions & 1 deletion src/utils/pagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@ export const usePagination = (totalCount?: number, options?: PaginationOptions):
const pageParams = searchParams.get(searchParamKey);
const currentPage = pageParams ? parseInt(pageParams) : undefined;

const updatePageParam = (page: number) => {
searchParams.set(searchParamKey, `${page}`);
setSearchParams(searchParams);
};

return {
paginationConfig: {
current: currentPage,
onChange: (page) => setSearchParams({ [searchParamKey]: `${page}` }),
onChange: updatePageParam,
pageSize,
total: totalCount,
showSizeChanger: false,
Expand Down
64 changes: 50 additions & 14 deletions src/views/verification/VerificationAssignment.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { gql, useLazyQuery } from '@apollo/client';
import { Button, PageHeader, Table, TableColumnsType, Tag, TagProps } from 'antd';
import { Button, PageHeader, Table, TableColumnsType, TableProps, Tag, TagProps } from 'antd';
import { CloudDownloadOutlined } from '@ant-design/icons';
import { Fragment, useEffect, useState } from 'react';
import { FormattedMessage, useIntl } from 'react-intl';
Expand All @@ -10,10 +10,11 @@ import { Unarray } from '../../utils/types';
import VerificationList from './assignment/VerificationList';
import MultiAssignmentModal from './assignment/MultiAssignmentModal';
import { usePagination } from '../../utils/pagination';
import { ArrayParam, BooleanParam, NumberParam, StringParam, useQueryParams } from 'use-query-params';

const INDEX_DOSSIERS = gql`
query IndexDossiers($page: Int) {
dossiers(page: $page) {
query IndexDossiers($page: Int, $filter: DossierFilterInput) {
dossiers(page: $page, filter: $filter) {
collection {
id
affiliation {
Expand Down Expand Up @@ -43,15 +44,36 @@ const INDEX_DOSSIERS = gql`

type AssignmentTable = Unarray<NonNullable<NonNullable<IndexDossiersQuery['dossiers']>['collection']>>;

enum DossierTag {
verified = 'verified',
notVerified = 'not-verified',
noInvitation = 'no-invitation',
verifiedWithChanges = 'verified-with-change',
noFinalMark = 'no-final-mark',
insufficient = 'insufficient',
justEnough = 'just-enough',
veryGood = 'very-good'
}

const KEYS_WITH_SINGLE_SELECTION_FILTER = ['markDeduction', 'tags'];

export default function VerificationAssignment() {
const intl = useIntl();
const [indexDossiers, { loading, data }] = useLazyQuery<IndexDossiersQuery>(INDEX_DOSSIERS, { fetchPolicy: 'cache-and-network' });
const [selection, setSelection] = useState<number[]>([]);
const { paginationConfig, currentPage } = usePagination(data?.dossiers?.metadata.totalCount);

const [queryParams, setQueryParams] = useQueryParams({
tenantName: ArrayParam,
markDeduction: BooleanParam,
tags: StringParam,
page: NumberParam
});

useEffect(() => {
indexDossiers({ variables: { page: currentPage } });
}, [indexDossiers, currentPage]);
delete queryParams.page;
indexDossiers({ variables: { page: currentPage, filter: queryParams } });
}, [indexDossiers, currentPage, queryParams]);

const columns: TableColumnsType<AssignmentTable> = [
{
Expand All @@ -61,10 +83,10 @@ export default function VerificationAssignment() {
},
{
dataIndex: ['affiliation', 'tenantName'],
key: 'affiliation.tenantName',
key: 'tenantName',
title: intl.formatMessage({ id: 'label.tenant' }),
filters: data?.uniqueTenantNames?.map((a) => ({ text: a, value: a })),
onFilter: (value, record) => record.affiliation.tenantName === value
filteredValue: queryParams.tenantName?.filter((n): n is string => !!n)
},
{
dataIndex: ['candidate', 'forename'],
Expand All @@ -90,7 +112,7 @@ export default function VerificationAssignment() {
{ text: intl.formatMessage({ id: 'label.yes' }), value: true },
{ text: intl.formatMessage({ id: 'label.no' }), value: false }
],
onFilter: (value, record) => record.markDeduction === value,
filteredValue: queryParams.markDeduction === undefined || queryParams.markDeduction === null ? undefined : [queryParams.markDeduction],
filterMultiple: false
},
{
Expand All @@ -102,14 +124,14 @@ export default function VerificationAssignment() {
dataIndex: 'tags',
key: 'tags',
title: intl.formatMessage({ id: 'label.tags' }),
render: (value: string[]) =>
render: (value: DossierTag[]) =>
value.map((t) => {
let color: TagProps['color'] = 'default';
if (t === 'verified') {
if (t === DossierTag.verified) {
color = 'success';
} else if (t === 'not-verified' || t === 'no-final-mark') {
} else if (t === DossierTag.notVerified || t === DossierTag.noFinalMark) {
color = 'error';
} else if (t === 'insufficient' || t === 'just-enough' || t === 'very-good') {
} else if (t === DossierTag.insufficient || t === DossierTag.justEnough || t === DossierTag.veryGood) {
color = 'warning';
}
return (
Expand All @@ -118,8 +140,8 @@ export default function VerificationAssignment() {
</Tag>
);
}),
filters: [...new Set(data?.dossiers?.collection.flatMap((d) => d.tags))].map((t) => ({ text: intl.formatMessage({ id: `label.${t}` }), value: t })),
onFilter: (value, record) => record.tags.indexOf(value.toString()) !== -1,
filters: Object.values(DossierTag).map((t) => ({ text: intl.formatMessage({ id: `label.${t}` }), value: t })),
filteredValue: queryParams.tags ? [queryParams.tags] : undefined,
filterMultiple: false
},
{
Expand All @@ -141,6 +163,19 @@ export default function VerificationAssignment() {
}
];

const handleTableChanges: TableProps<AssignmentTable>['onChange'] = (_pagination, filters, _sorter, extra) => {
switch (extra.action) {
case 'filter':
const parsedFilters = Object.entries(filters).reduce((acc, [key, value]) => {
acc[key] = KEYS_WITH_SINGLE_SELECTION_FILTER.includes(key) ? value?.[0] : value;
return acc;
}, {} as Record<string, any>);

setQueryParams({ ...queryParams, ...parsedFilters, page: 1 });
break;
}
};

return (
<DefaultLayout
pageHeader={
Expand All @@ -153,6 +188,7 @@ export default function VerificationAssignment() {
>
<Table<AssignmentTable>
columns={columns}
onChange={handleTableChanges}
dataSource={data?.dossiers?.collection?.map((d) => ({ ...d, key: d.id })) ?? []}
loading={loading}
scroll={{ x: 800 }}
Expand Down
37 changes: 37 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5652,6 +5652,11 @@ fill-range@^7.0.1:
dependencies:
to-regex-range "^5.0.1"

filter-obj@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b"
integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==

[email protected]:
version "1.2.0"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
Expand Down Expand Up @@ -9232,6 +9237,16 @@ [email protected]:
dependencies:
side-channel "^1.0.4"

query-string@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.1.tgz#754620669db978625a90f635f12617c271a088e1"
integrity sha512-MplouLRDHBZSG9z7fpuAAcI7aAYjDLhtsiVZsevsfaHWDS2IDdORKbSd1kWUA+V4zyva/HZoSfpwnYMMQDhb0w==
dependencies:
decode-uri-component "^0.2.0"
filter-obj "^1.1.0"
split-on-first "^1.0.0"
strict-uri-encode "^2.0.0"

queue-microtask@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
Expand Down Expand Up @@ -10316,6 +10331,11 @@ serialize-javascript@^6.0.0:
dependencies:
randombytes "^2.1.0"

serialize-query-params@^1.3.5:
version "1.3.6"
resolved "https://registry.yarnpkg.com/serialize-query-params/-/serialize-query-params-1.3.6.tgz#5dd5225db85ce747fe6fbc4897628504faafec6d"
integrity sha512-VlH7sfWNyPVZClPkRacopn6sn5uQMXBsjPVz1+pBHX895VpcYVznfJtZ49e6jymcrz+l/vowkepCZn/7xEAEdw==

serve-index@^1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
Expand Down Expand Up @@ -10522,6 +10542,11 @@ spdy@^4.0.2:
select-hose "^2.0.0"
spdy-transport "^3.0.0"

split-on-first@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==

sponge-case@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/sponge-case/-/sponge-case-1.0.1.tgz#260833b86453883d974f84854cdb63aecc5aef4c"
Expand Down Expand Up @@ -10574,6 +10599,11 @@ streamsearch@^1.1.0:
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==

strict-uri-encode@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==

string-convert@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97"
Expand Down Expand Up @@ -11308,6 +11338,13 @@ url-parse-lax@^3.0.0:
dependencies:
prepend-http "^2.0.0"

use-query-params@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/use-query-params/-/use-query-params-1.2.3.tgz#306c31a0cbc714e8a3b4bd7e91a6a9aaccaa5e22"
integrity sha512-cdG0tgbzK+FzsV6DAt2CN8Saa3WpRnze7uC4Rdh7l15epSFq7egmcB/zuREvPNwO5Yk80nUpDZpiyHsoq50d8w==
dependencies:
serialize-query-params "^1.3.5"

util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
Expand Down

0 comments on commit 2a7136e

Please sign in to comment.