Skip to content

Commit

Permalink
In Ark table component, make it generic, and fix row-filtering behavi…
Browse files Browse the repository at this point in the history
…or (#576)

- **Make Table component generic, and introduce typing into its row
elements**
- **Convert other tables**
  • Loading branch information
shaldengeki authored Sep 30, 2024
1 parent 779bbb6 commit 9bd6753
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 32 deletions.
10 changes: 7 additions & 3 deletions ark_nova_stats/frontend/src/components/CardInfoBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,19 @@ type CardInfoBoxParams = {
mostPlayedBy: UserPlayCount[];
}

type CardPlayedTableRow = {
"User": React.JSX.Element,
"Count": React.JSX.Element,
}

const CardInfoBox = ({card, mostPlayedBy}: CardInfoBoxParams) => {
let innerContent = <p></p>;
if (!card) {
innerContent = <p>Error: card info could not be retrieved!</p>;
} else if (!mostPlayedBy) {
innerContent = <p>Error: card play info could not be retrieved!</p>;
} else {
const rows = mostPlayedBy.map((userPlayCount: UserPlayCount) => {
const rows: CardPlayedTableRow[] = mostPlayedBy.map((userPlayCount: UserPlayCount) => {
return {
"User": <Link to={"/user/" + userPlayCount.user.name}>{userPlayCount.user.name}</Link>,
"Count": <ul>{userPlayCount.count}</ul>,
Expand All @@ -29,8 +34,7 @@ const CardInfoBox = ({card, mostPlayedBy}: CardInfoBoxParams) => {
<li>BGA ID: {card.bgaId}</li>
</ul>
<h2 className={"text-xl"}>Most played by:</h2>
<Table
cols={["User", "Count"]}
<Table<CardPlayedTableRow>
rows={rows}
key="card-played-cards"
showFilters={false}
Expand Down
28 changes: 19 additions & 9 deletions ark_nova_stats/frontend/src/components/GameLogArchivesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,38 @@ type GameLogArchivesTableParams = {
gameLogArchives: GameLogArchive[];
}

type GameLogArchivesTableRow = {
"Link": React.JSX.Element,
"Date": React.JSX.Element,
"Type": React.JSX.Element,
"Games": React.JSX.Element,
"Users": React.JSX.Element,
"Latest table": React.JSX.Element,
"Size in MB": React.JSX.Element,

}

const GameLogArchivesTable = ({gameLogArchives}: GameLogArchivesTableParams) => {
let innerContent = <p></p>;
if (!gameLogArchives) {
innerContent = <p>Error: game log archives could not be retrieved!</p>;
} else {
var rows = gameLogArchives.map((gameLogArchive: GameLogArchive) => {
var rows: GameLogArchivesTableRow[] = gameLogArchives.map((gameLogArchive: GameLogArchive) => {
let latestTableDescription = <Link to={"https://boardgamearena.com/table?table=" + gameLogArchive.maxGameLog.bgaTableId}>
{gameLogArchive.maxGameLog.bgaTableId}
</Link>;
return {
"Link": <Link to={gameLogArchive.url}>Download</Link>,
"Date": getDate(gameLogArchive.createdAt),
"Type": gameLogArchive.archiveType,
"Games": gameLogArchive.numGameLogs,
"Users": gameLogArchive.numUsers,
"Latest table": latestTableDescription,
"Size in MB": Math.round((gameLogArchive.sizeBytes) / (1024 * 1024)),
"Date": <p>getDate(gameLogArchive.createdAt)</p>,
"Type": <p>gameLogArchive.archiveType</p>,
"Games": <p>gameLogArchive.numGameLogs</p>,
"Users": <p>gameLogArchive.numUsers</p>,
"Latest table": <p>latestTableDescription</p>,
"Size in MB": <p>Math.round((gameLogArchive.sizeBytes) / (1024 * 1024))</p>,
}
});
innerContent = (
<Table
cols={["Link", "Date", "Type", "Games", "Users", "Latest table", "Size in MB"]}
<Table<GameLogArchivesTableRow>
rows={rows}
key="game-log-archives"
showFilters={false}
Expand Down
11 changes: 8 additions & 3 deletions ark_nova_stats/frontend/src/components/GameLogsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ type GameLogsTableParams = {
currentPlayer?: User;
}

type GameLogsTableRow = {
"BGA table": React.JSX.Element,
"Players": React.JSX.Element,
"Rating changes"?: React.JSX.Element,
}

const GameLogsTable = ({gameLogs, currentPlayer}: GameLogsTableParams) => {
let innerContent = <p></p>;
if (!gameLogs) {
Expand All @@ -21,7 +27,7 @@ const GameLogsTable = ({gameLogs, currentPlayer}: GameLogsTableParams) => {
}

var rows = gameLogs.map((gameLog: GameLog) => {
const rowAttrs: any = {
const rowAttrs: GameLogsTableRow = {
"BGA table": <Link to={"https://boardgamearena.com/table?table=" + gameLog.bgaTableId}>{gameLog.bgaTableId}</Link>,
"Players": <ul>{gameLog.users.map((user: User) => {
const ratingChange = gameLog.gameRatingChanges.find((change) => { return change.user.bgaId === user.bgaId })
Expand All @@ -41,8 +47,7 @@ const GameLogsTable = ({gameLogs, currentPlayer}: GameLogsTableParams) => {
return rowAttrs;
});
innerContent = (
<Table
cols={tableColumns}
<Table<GameLogsTableRow>
rows={rows}
key="game-logs"
showFilters={false}
Expand Down
25 changes: 16 additions & 9 deletions ark_nova_stats/frontend/src/components/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from 'react'
import _ from 'lodash'

const renderColumn = (col: string, showFilters: Boolean, filters: _.Dictionary<any>, setFilter: Function, tablePrefix: string) => {
const renderColumn = (col: string, showFilters: Boolean | undefined, filters: _.Dictionary<any>, setFilter: Function, tablePrefix: string) => {
const filterInput = (
<input
className="border w-full"
Expand Down Expand Up @@ -42,22 +42,29 @@ const renderRow = (row: any, idx: number, cols: Array<string>, tablePrefix: stri
)
}

type TableProps = {
cols: Array<string>,
rows: Array<any>,
key: string,
showFilters?: Boolean
};
interface TableRow {
[index: string]:React.JSX.Element;
}

interface TableProps<T extends TableRow> {
key: string;
rows: Array<T>;
showFilters?: Boolean;
}

function Table<T extends TableRow>({ key, rows, showFilters }: TableProps<T>) {
const cols = Object.keys(rows[0]);

const Table = ({ cols, rows, key, showFilters = true }: TableProps) => {
const [filters, setFilter] = useColumnFilters(cols)
const tablePrefix = `Table-${key}`

let shownRows = rows || []
if (showFilters) {
_.forEach(cols, (col) => {
if (filters[col]) {
shownRows = _.filter(shownRows, (txn) => { return _.upperCase(txn[col]).includes(_.upperCase(filters[col])) })
shownRows = _.filter(shownRows, (row: T) => {
return _.upperCase(row[col].props.children).includes(_.upperCase(filters[col]))
})
}
})
}
Expand Down
10 changes: 7 additions & 3 deletions ark_nova_stats/frontend/src/components/UserInfoBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,19 @@ type UserInfoBoxParams = {
commonlyPlayedCards: UserPlayCount[];
}

type UserPlayedTableRow = {
"Card": React.JSX.Element,
"Count": React.JSX.Element,
}

const UserInfoBox = ({user, commonlyPlayedCards}: UserInfoBoxParams) => {
let innerContent = <p></p>;
if (!user) {
innerContent = <p>Error: user info could not be retrieved!</p>;
} else if (!commonlyPlayedCards) {
innerContent = <p>Error: card play info could not be retrieved!</p>;
} else {
const rows = commonlyPlayedCards.map((userPlayCount: UserPlayCount) => {
const rows: UserPlayedTableRow[] = commonlyPlayedCards.map((userPlayCount: UserPlayCount) => {
return {
"Card": <Link to={"/card/" + userPlayCount.card.bgaId}>{userPlayCount.card.name}</Link>,
"Count": <ul>{userPlayCount.count}</ul>,
Expand All @@ -32,8 +37,7 @@ const UserInfoBox = ({user, commonlyPlayedCards}: UserInfoBoxParams) => {
<li>Current Arena ELO: {user.currentArenaElo}</li>
</ul>
<h2 className={"text-xl"}>Most played:</h2>
<Table
cols={["Card", "Count"]}
<Table<UserPlayedTableRow>
rows={rows}
key="user-played-cards"
showFilters={false}
Expand Down
11 changes: 6 additions & 5 deletions ark_nova_stats/frontend/src/views/CardsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ export const CARDS_VIEW_QUERY = gql`
}
`;


type CardsTableRow = {
"Name": React.JSX.Element,
"Most played by": React.JSX.Element,
}

const CardsView = () => {
const { loading, error, data } = useQuery(
Expand All @@ -37,8 +40,7 @@ const CardsView = () => {
else if (error) innerContent = <p>Error: {error.message}</p>;
else {
const cards: Card[] = data.cards;
const tableColumns = ["Name", "Most played by"];
const cardRows = cards.map((card: Card) => {
const cardRows: CardsTableRow[] = cards.map((card: Card) => {
const mostPlayed = data.cards.find((c: any) => {return c.bgaId === card.bgaId}).mostPlayedBy[0];
const mostPlayedUser: User = mostPlayed.user;
return {
Expand All @@ -50,8 +52,7 @@ const CardsView = () => {
<div>
<PageTitle>Cards</PageTitle>
<div className={"py-2"}>
<Table
cols={tableColumns}
<Table<CardsTableRow>
rows={cardRows}
key="cards"
showFilters={true}
Expand Down

0 comments on commit 9bd6753

Please sign in to comment.