Skip to content

Commit

Permalink
Add createdAt field to DailyDepartmentNotification filters and update…
Browse files Browse the repository at this point in the history
… related resource models to use Luxon for date handling
  • Loading branch information
jthoward64 committed Jan 1, 2025
1 parent 39297de commit deddd79
Show file tree
Hide file tree
Showing 19 changed files with 379 additions and 434 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -274,5 +274,6 @@ export class ListDailyDepartmentNotificationsArgs extends FilteredListQueryArgs(
"SolicitationCodeNumber",
"SolicitationCodePrefix",
"BatchType",
"createdAt",
]
) {}
2 changes: 1 addition & 1 deletion packages/portal/graphql/graphql-env.d.ts

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions packages/portal/src/config/refine/UndoableNotification.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { UndoOutlined } from "@ant-design/icons";
import type { OpenNotificationParams } from "@refinedev/core";
import { Button, Progress } from "antd";

export interface UndoableNotificationProps {
notificationKey: OpenNotificationParams["key"];
message: OpenNotificationParams["message"];
cancelMutation: OpenNotificationParams["cancelMutation"];
undoableTimeout: OpenNotificationParams["undoableTimeout"];
}

export const UndoableNotification: React.FC<UndoableNotificationProps> = ({
message,
cancelMutation,
undoableTimeout,
}) => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
marginTop: "-7px",
}}
>
<Progress
type="circle"
percent={(undoableTimeout ?? 0) * 20}
format={(time) => time && time / 20}
size={50}
strokeColor="#1890ff"
status="normal"
/>
<span style={{ marginLeft: 8, width: "100%" }}>{message}</span>
<Button
style={{ flexShrink: 0 }}
onClick={cancelMutation}
disabled={undoableTimeout === 0}
icon={<UndoOutlined />}
/>
</div>
);
4 changes: 0 additions & 4 deletions packages/portal/src/config/refine/authentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type {
CheckResponse,
OnErrorResponse,
} from "@refinedev/core";
import { notification } from "antd";

import { API_BASE_URL, urqlClient } from "#config/api.ts";
import { getLoginState, refreshLoginState } from "#hooks/useLoginState.ts";
Expand Down Expand Up @@ -108,9 +107,6 @@ export const authProvider: AuthProvider = {
}
},
onError: (error): Promise<OnErrorResponse> => {
notification.error({
message: String(error),
});
return Promise.resolve({ error });
},
// optional methods
Expand Down
50 changes: 50 additions & 0 deletions packages/portal/src/config/refine/feedback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { NotificationProvider } from "@refinedev/core";

import { useAntFeedback } from "#hooks/useAntFeedback.ts";

import { UndoableNotification } from "./UndoableNotification";

export const useNotificationProvider = (): NotificationProvider => {
const { appNotification } = useAntFeedback();

const notificationProvider: NotificationProvider = {
open: ({
key,
message,
description,
type,
cancelMutation,
undoableTimeout,
}) => {
if (type === "progress") {
appNotification.open({
key,
description: (
<UndoableNotification
notificationKey={key}
message={message}
cancelMutation={() => {
cancelMutation?.();
appNotification.destroy(key ?? "");
}}
undoableTimeout={undoableTimeout}
/>
),
message: null,
duration: 0,
closeIcon: <></>,
});
} else {
appNotification.open({
key,
description: message,
message: description ?? null,
type,
});
}
},
close: (key) => appNotification.destroy(key),
};

return notificationProvider;
};
2 changes: 1 addition & 1 deletion packages/portal/src/config/refine/resources.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const refineResources: ResourceProps[] = [
list: "/fundraising/solicitation-code",
},
{
name: "ddn",
name: "dailyDepartmentNotification",
meta: {
label: "Uploaded DDNs",
parent: "fundraising-group",
Expand Down
208 changes: 20 additions & 188 deletions packages/portal/src/elements/tables/fundraising/DDNTable.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { EyeOutlined } from "@ant-design/icons";
import { useTable } from "@refinedev/antd";
import { Link } from "@tanstack/react-router";
import type { SolicitationCodeNode } from "@ukdanceblue/common";
import { BatchType } from "@ukdanceblue/common";
import { SortDirection, stringifyDDNBatchType } from "@ukdanceblue/common";
import { stringifyDDNBatchType } from "@ukdanceblue/common";
import { Button, Flex, Table } from "antd";
import { useQuery } from "urql";

import { graphql, readFragment } from "#graphql/index.js";
import { useListQuery } from "#hooks/useListQuery.js";
import {
useMakeNumberSearchFilterProps,
useMakeStringSearchFilterProps,
} from "#hooks/useMakeSearchFilterProps";
import { useQueryStatusWatcher } from "#hooks/useQueryStatusWatcher.js";
import { graphql, type ResultOf } from "#graphql/index.js";

const DDNsTableFragment = graphql(/* GraphQL */ `
fragment DDNsTableFragment on DailyDepartmentNotificationNode {
Expand All @@ -33,202 +27,45 @@ const DDNsTableFragment = graphql(/* GraphQL */ `
}
`);

const ddnsTableQueryDocument = graphql(
/* GraphQL */ `
query DdnsTable(
$page: Int
$pageSize: Int
$sortBy: [String!]
$sortDirection: [SortDirection!]
$isNullFilters: [DailyDepartmentNotificationResolverKeyedIsNullFilterItem!]
$oneOfFilters: [DailyDepartmentNotificationResolverKeyedOneOfFilterItem!]
$stringFilters: [DailyDepartmentNotificationResolverKeyedStringFilterItem!]
$numericFilters: [DailyDepartmentNotificationResolverKeyedNumericFilterItem!]
) {
dailyDepartmentNotifications(
page: $page
pageSize: $pageSize
sortBy: $sortBy
sortDirection: $sortDirection
isNullFilters: $isNullFilters
oneOfFilters: $oneOfFilters
stringFilters: $stringFilters
numericFilters: $numericFilters
) {
page
pageSize
total
data {
...DDNsTableFragment
}
}
}
`,
[DDNsTableFragment]
);

export const DDNTable = () => {
const {
queryOptions,
updatePagination,
clearSorting,
pushSorting,
updateFilter,
clearFilter,
} = useListQuery(
{
initPage: 1,
initPageSize: 10,
initSorting: [],
initialFilters: {},
const { searchFormProps, tableProps } = useTable<
ResultOf<typeof DDNsTableFragment>
>({
meta: {
gqlFragment: DDNsTableFragment,
fieldTypes: {
createdAt: "date",
},
},
{
allFields: [
"Amount",
"BatchType",
"Comment",
"Donor",
"SolicitationCodeName",
"SolicitationCodeNumber",
"SolicitationCodePrefix",
],
dateFields: [],
booleanFields: [],
isNullFields: [],
numericFields: ["Amount"],
oneOfFields: [
"BatchType",
"SolicitationCodePrefix",
"SolicitationCodeNumber",
syncWithLocation: true,
sorters: {
initial: [
{
field: "createdAt",
order: "desc",
},
],
stringFields: ["Donor", "Comment", "SolicitationCodeName"],
}
);

const [{ fetching, error, data: ddnsDocument }] = useQuery({
query: ddnsTableQueryDocument,
variables: queryOptions,
});

useQueryStatusWatcher({
error,
fetching,
loadingMessage: "Loading ddns...",
},
});

const listDDNsData = readFragment(
DDNsTableFragment,
ddnsDocument?.dailyDepartmentNotifications.data ?? []
);

return (
<Table
dataSource={listDDNsData}
rowKey={({ id }) => id}
loading={fetching}
pagination={
ddnsDocument
? {
current: ddnsDocument.dailyDepartmentNotifications.page,
pageSize: ddnsDocument.dailyDepartmentNotifications.pageSize,
total: ddnsDocument.dailyDepartmentNotifications.total,
showSizeChanger: true,
}
: false
}
sortDirections={["ascend", "descend"]}
onChange={(pagination, filters, sorter, _extra) => {
updatePagination({
page: pagination.current,
pageSize: pagination.pageSize,
});
clearSorting();
for (const sort of Array.isArray(sorter) ? sorter : [sorter]) {
if (!sort.order) {
continue;
}
let field:
| "Amount"
| "Donor"
| "Comment"
| "SolicitationCodeName"
| "SolicitationCodeNumber"
| "SolicitationCodePrefix"
| "BatchType";
switch (sort.field) {
case "combinedAmount": {
field = "Amount";
break;
}
case "combinedDonorName": {
field = "Donor";
break;
}
case "comment": {
field = "Comment";
break;
}
case "solicitationCode": {
field = "SolicitationCodeName";
break;
}
case "batch": {
field = "BatchType";
break;
}
default: {
throw new Error(`Unsupported sort field: ${String(sort.field)}`);
}
}
pushSorting({
field,
direction:
sort.order === "ascend" ? SortDirection.asc : SortDirection.desc,
});
}
clearFilter("BatchType");
for (const key of Object.keys(filters)) {
const value = filters[key];
if (!value) {
continue;
}
switch (key) {
case "batch": {
updateFilter("BatchType", {
field: "BatchType",
value: value.map((v) => v.toString()),
});
break;
}
}
}
}}
{...tableProps}
columns={[
{
title: "Donor",
dataIndex: "combinedDonorName",
sorter: true,
...useMakeStringSearchFilterProps("Donor", updateFilter, clearFilter),
},
{
title: "Amount",
dataIndex: "combinedAmount",
sorter: true,
...useMakeNumberSearchFilterProps(
"Amount",
updateFilter,
clearFilter
),
},
{
title: "Comment",
dataIndex: "comment",
sorter: true,
...useMakeStringSearchFilterProps(
"Comment",
updateFilter,
clearFilter
),
},
{
title: "Solicitation Code",
Expand All @@ -247,11 +84,6 @@ export const DDNTable = () => {
.toString()
.padStart(4, "0")}`}</b>
),
...useMakeStringSearchFilterProps(
"SolicitationCodeName",
updateFilter,
clearFilter
),
},
{
title: "Batch",
Expand Down
3 changes: 2 additions & 1 deletion packages/portal/src/routes/__root.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SettingOutlined } from "@ant-design/icons";
import { AuthPage, useNotificationProvider } from "@refinedev/antd";
import { AuthPage } from "@refinedev/antd";
import { Refine, useLogin } from "@refinedev/core";
import {
createRootRouteWithContext,
Expand All @@ -21,6 +21,7 @@ import type { Client as UrqlClient } from "urql";
import watermark from "#assets/watermark.svg";
import { authProvider } from "#config/refine/authentication.ts";
import { accessControlProvider } from "#config/refine/authorization.ts";
import { useNotificationProvider } from "#config/refine/feedback.tsx";
import { dataProvider } from "#config/refine/graphql/data.ts";
import { refineResources } from "#config/refine/resources.tsx";
import { routerBindings } from "#config/refine/router.tsx";
Expand Down
Loading

0 comments on commit deddd79

Please sign in to comment.