From 01955e36e73d6ebf3b92caff3e44fa9782f6f383 Mon Sep 17 00:00:00 2001 From: Joonatan Kuosa Date: Wed, 2 Oct 2024 12:16:45 +0300 Subject: [PATCH] fix: table scrolling when clicking show more - fix: don't reset Table keys unless sort has changed - refactor: remove double Table implementation (reuse one styled table) refs: TILA-3576 --- apps/admin-ui/src/component/Table.tsx | 29 ++-- .../spa/application-rounds/CustomTable.tsx | 50 ------- .../src/spa/application-rounds/index.tsx | 141 +++++++++--------- 3 files changed, 79 insertions(+), 141 deletions(-) delete mode 100644 apps/admin-ui/src/spa/application-rounds/CustomTable.tsx diff --git a/apps/admin-ui/src/component/Table.tsx b/apps/admin-ui/src/component/Table.tsx index 7e5e7cbb47..430aeb0dc0 100644 --- a/apps/admin-ui/src/component/Table.tsx +++ b/apps/admin-ui/src/component/Table.tsx @@ -45,6 +45,7 @@ const StyledTable = styled(Table)` type Props = Omit & { setSort?: (col: string) => void; isLoading?: boolean; + enableFrontendSorting?: boolean; }; // @param isLoading - if true, table is rendered with a loading overlay @@ -52,11 +53,14 @@ type Props = Omit & { export function CustomTable({ isLoading, setSort, + enableFrontendSorting, ...props }: Props): JSX.Element { + const [keyOverride, setKeyOverride] = React.useState(0); const onSort = (order: "asc" | "desc", colKey: string) => { const field = order === "asc" ? colKey : `-${colKey}`; if (setSort) { + setKeyOverride((prev) => prev + 1); setSort(field); } }; @@ -65,11 +69,11 @@ export function CustomTable({ ); } - -// React elements can't be serialized into json -function replacer(_key: string, value: unknown) { - if (typeof value === "object" && value != null) { - if ( - "$$typeof" in value && - value.$$typeof != null && - // eslint-disable-next-line @typescript-eslint/no-base-to-string - value.$$typeof.toString() === "Symbol(react.element)" - ) { - return undefined; - } - } - return value; -} diff --git a/apps/admin-ui/src/spa/application-rounds/CustomTable.tsx b/apps/admin-ui/src/spa/application-rounds/CustomTable.tsx deleted file mode 100644 index 2d05bef64f..0000000000 --- a/apps/admin-ui/src/spa/application-rounds/CustomTable.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Table, TableProps } from "hds-react"; -import React from "react"; -import styled from "styled-components"; -import { breakpoints } from "common/src/common/style"; - -type TableWrapperProps = { - $headingBackground?: string; - $tableBackground?: string; -}; - -const TableWrapper = styled.div` - div { - overflow-x: auto; - @media (min-width: ${breakpoints.xl}) { - overflow-x: unset !important; - } - } - - caption { - text-align: end; - } - table { - th { - font-family: var(--font-bold); - padding: var(--spacing-xs); - background: ${({ $headingBackground = "var(--color-black-10)" }) => - $headingBackground}; - position: sticky; - top: 0; - box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.4); - } - td { - white-space: nowrap; - padding: var(--spacing-xs); - background: ${({ $tableBackground = "transparent" }) => $tableBackground}; - } - } -`; - -/// Styled version of HDS Table -/// Compared to the StyledTable in components.tsx, this version uses HDS, while that one is custom code -/// Leaving this primarily because we want to remove the custom implementation if possible -export const StyledHDSTable = (props: TableProps): JSX.Element => ( - - - -); diff --git a/apps/admin-ui/src/spa/application-rounds/index.tsx b/apps/admin-ui/src/spa/application-rounds/index.tsx index 64b3200fc7..04a1eb1764 100644 --- a/apps/admin-ui/src/spa/application-rounds/index.tsx +++ b/apps/admin-ui/src/spa/application-rounds/index.tsx @@ -19,8 +19,9 @@ import { Container } from "@/styles/layout"; import { truncate } from "@/helpers"; import Loader from "@/component/Loader"; import { ApplicationRoundCard } from "./ApplicationRoundCard"; -import { StyledHDSTable } from "./CustomTable"; import { TableLink } from "@/styles/util"; +import { CustomTable } from "@/component/Table"; +import Error404 from "@/common/Error404"; const AccordionContainer = styled.div` display: flex; @@ -83,7 +84,7 @@ function AllApplicationRounds(): JSX.Element | null { const { t } = useTranslation(); // TODO pagination - const { data, loading } = useApplicationRoundsQuery({ + const { data, loading, error } = useApplicationRoundsQuery({ onError: (err: ApolloError) => { errorToast({ text: err.message }); }, @@ -93,12 +94,13 @@ function AllApplicationRounds(): JSX.Element | null { data?.applicationRounds?.edges?.map((ar) => ar?.node) ); - if (loading) { + if (loading && allApplicationRounds == null) { return ; } - if (!allApplicationRounds) { - return null; + if (allApplicationRounds == null || error != null) { + // TODO should be a different error page + return ; } const currentApplicationRounds = allApplicationRounds.filter( @@ -117,6 +119,51 @@ function AllApplicationRounds(): JSX.Element | null { (ar) => ar.status === ApplicationRoundStatusChoice.Handled ); + const cols = [ + { + isSortable: true, + headerName: t("ApplicationRound.headings.name"), + transform: (applicationRound: ApplicationRoundNode) => ( + + + {truncate(applicationRound.nameFi ?? "", 50)} + + + ), + key: "nameFi", + }, + { + isSortable: true, + headerName: t("ApplicationRound.headings.reservationUnitCount"), + transform: (applicationRound: ApplicationRoundNode) => + String(applicationRound.applicationsCount), + key: "applicationsCount", + }, + { + isSortable: true, + headerName: t("ApplicationRound.headings.applicationCount"), + transform: (applicationRound: ApplicationRoundNode) => + String(applicationRound.reservationUnitCount), + key: "reservationUnitCount", + }, + { + isSortable: true, + headerName: t("ApplicationRound.headings.sent"), + transform: (applicationRound: ApplicationRoundNode) => + formatDate(applicationRound.statusTimestamp || null) || "-", + key: "statusTimestampSort", + }, + ]; + + const rows = orderBy( + sentApplicationRounds, + ["statusTimestamp"], + ["desc"] + ).map((a) => ({ + ...a, + statusTimestampSort: new Date(a.statusTimestamp || "").getTime(), + })); + return (
@@ -127,13 +174,11 @@ function AllApplicationRounds(): JSX.Element | null { initiallyOpen hideIfEmpty name={t("ApplicationRound.groupLabel.handling")} - rounds={ - orderBy( - currentApplicationRounds, - ["status", "applicationPeriodEnd"], - ["asc", "asc"] - ) || [] - } + rounds={orderBy( + currentApplicationRounds, + ["status", "applicationPeriodEnd"], + ["asc", "asc"] + )} />
{t("ApplicationRound.noUpcoming")}
@@ -169,58 +213,13 @@ function AllApplicationRounds(): JSX.Element | null { heading={t("ApplicationRound.groupLabel.previousRounds")} className="previous-rounds" > - ( - - - {truncate(applicationRound.nameFi ?? "", 50)} - - - ), - key: "nameFi", - }, - { - isSortable: true, - headerName: t("ApplicationRound.headings.reservationUnitCount"), - transform: (applicationRound: ApplicationRoundNode) => - String(applicationRound.applicationsCount), - key: "applicationsCount", - }, - { - isSortable: true, - headerName: t("ApplicationRound.headings.applicationCount"), - transform: (applicationRound: ApplicationRoundNode) => - String(applicationRound.reservationUnitCount), - key: "reservationUnitCount", - }, - { - isSortable: true, - headerName: t("ApplicationRound.headings.sent"), - transform: (applicationRound: ApplicationRoundNode) => - formatDate(applicationRound.statusTimestamp || null) || "-", - key: "statusTimestampSort", - }, - ]} + cols={cols} indexKey="pk" - rows={ - orderBy(sentApplicationRounds, ["statusTimestamp"], ["desc"]).map( - (a) => ({ - ...a, - statusTimestampSort: new Date( - a.statusTimestamp || "" - ).getTime(), - }) - ) || [] - } + rows={rows} variant="light" />