Files
Open-Assistant/website/src/components/LeaderboardTable/LeaderboardTable.tsx
T
notmd ef548edb72 Trollboard expandable (#1354)
* wip

* hide necessary column in trollboard

* remove console.log

* fix build

* clean up

* remove commented code
2023-02-09 09:20:27 +01:00

141 lines
4.5 KiB
TypeScript

import { Box, CircularProgress, Flex, Link, useColorModeValue } from "@chakra-ui/react";
import { createColumnHelper } from "@tanstack/react-table";
import { MoreHorizontal } from "lucide-react";
import NextLink from "next/link";
import { useTranslation } from "next-i18next";
import React, { useMemo } from "react";
import { useHasRole } from "src/hooks/auth/useHasRole";
import { LeaderboardEntity, LeaderboardReply, LeaderboardTimeFrame } from "src/types/Leaderboard";
import { DataTable, DataTableColumnDef } from "../DataTable/DataTable";
import { createJsonExpandRowModel } from "../DataTable/jsonExpandRowModel";
import { useBoardPagination } from "./useBoardPagination";
import { useBoardRowProps } from "./useBoardRowProps";
import { useFetchBoard } from "./useFetchBoard";
type WindowLeaderboardEntity = LeaderboardEntity & { isSpaceRow?: boolean };
const columnHelper = createColumnHelper<WindowLeaderboardEntity>();
const jsonExpandRowModel = createJsonExpandRowModel<WindowLeaderboardEntity>();
/**
* Presents a grid of leaderboard entries with more detailed information.
*/
export const LeaderboardTable = ({
timeFrame,
limit: limit,
rowPerPage,
hideCurrentUserRanking,
}: {
timeFrame: LeaderboardTimeFrame;
limit: number;
rowPerPage: number;
hideCurrentUserRanking?: boolean;
}) => {
const { t } = useTranslation("leaderboard");
const {
data: reply,
isLoading,
error,
lastUpdated,
} = useFetchBoard<LeaderboardReply & { user_stats_window?: LeaderboardReply["leaderboard"] }>(
`/api/leaderboard?time_frame=${timeFrame}&limit=${limit}&includeUserStats=${!hideCurrentUserRanking}`
);
const isAdmin = useHasRole("admin");
const columns: DataTableColumnDef<WindowLeaderboardEntity>[] = useMemo(
() => [
{
...columnHelper.accessor("rank", {
header: t("rank"),
cell: (ctx) =>
ctx.row.original.isSpaceRow ? (
<SpaceRow></SpaceRow>
) : isAdmin ? (
jsonExpandRowModel.renderCell(ctx)
) : (
ctx.getValue()
),
}),
span: (cell) => (cell.row.original.isSpaceRow ? 6 : jsonExpandRowModel.span(cell)),
},
columnHelper.accessor("display_name", {
header: t("user"),
cell: ({ getValue, row }) =>
isAdmin ? (
<Link as={NextLink} href={`/admin/manage_user/${row.original.user_id}`}>
{getValue()}
</Link>
) : (
getValue()
),
}),
columnHelper.accessor("leader_score", {
header: t("score"),
}),
columnHelper.accessor("prompts", {
header: t("prompt"),
}),
columnHelper.accessor((row) => row.replies_assistant + row.replies_prompter, {
header: t("reply"),
}),
columnHelper.accessor((row) => row.labels_full + row.labels_simple, {
header: t("label"),
}),
],
[isAdmin, t]
);
const {
data: paginatedData,
end,
...pagnationProps
} = useBoardPagination({ rowPerPage, data: jsonExpandRowModel.toExpandable(reply?.leaderboard || []), limit });
const data = useMemo(() => {
if (hideCurrentUserRanking || !reply?.user_stats_window || reply.user_stats_window.length === 0) {
return paginatedData;
}
const userStatsWindow: WindowLeaderboardEntity[] = jsonExpandRowModel.toExpandable(reply.user_stats_window);
const userStats = userStatsWindow.find((stats) => stats.highlighted);
if (userStats && userStats.rank > end) {
paginatedData.push(
{ isSpaceRow: true } as WindowLeaderboardEntity,
...userStatsWindow.filter(
(stats) => paginatedData.findIndex((leaderBoardEntity) => leaderBoardEntity.user_id === stats.user_id) === -1
) // filter to avoid duplicated row
);
}
return paginatedData;
}, [hideCurrentUserRanking, reply?.user_stats_window, end, paginatedData]);
const rowProps = useBoardRowProps<WindowLeaderboardEntity>();
if (isLoading) {
return <CircularProgress isIndeterminate></CircularProgress>;
}
if (error) {
return <span>Unable to load leaderboard</span>;
}
return (
<DataTable<WindowLeaderboardEntity>
data={data}
columns={columns}
caption={lastUpdated}
rowProps={rowProps}
getSubRows={jsonExpandRowModel.getSubRows}
{...pagnationProps}
></DataTable>
);
};
const SpaceRow = () => {
const color = useColorModeValue("gray.600", "gray.400");
return (
<Flex justify="center">
<Box as={MoreHorizontal} color={color}></Box>
</Flex>
);
};