Leaderboard view

This commit is contained in:
Brandon Thomas committed 2021-09-06 08:43:12 -04:00
1 parent c37667f5e8
commit ecc4bc6a72
5 files changed
+199 -5

No files matched your search

+4
View File
@@ -230,6 +230,10 @@ class ApiConfig {
return `${this.getScheme()}://${this.getNewApiHost()}/events`;
}
getLeaderboard() : string {
return `${this.getScheme()}://${this.getNewApiHost()}/leaderboard`;
}
getModerationIpBanList(): string {
return `${this.getScheme()}://${this.getNewApiHost()}/moderation/ip_bans/list`;
}
+72
View File
@@ -0,0 +1,72 @@
import { ApiConfig } from "../../../common/ApiConfig";
export interface Leaderboard {
success: boolean,
tts_leaderboard: Array<LeaderboardEntryForList>
w2l_leaderboard: Array<LeaderboardEntryForList>
}
export interface LeaderboardEntryForList {
username: string,
display_name: string,
gravatar_hash: string,
uploaded_count: number,
}
export enum LeaderboardLookupError {
NotFound,
ServerError,
FrontendError,
}
export type GetLeaderboardResponse = Leaderboard | LeaderboardLookupError;
export function GetLeaderboardIsOk(response: GetLeaderboardResponse): response is Leaderboard {
return response.hasOwnProperty('tts_leaderboard');
}
export function GetLeaderboardIsErr(response: GetLeaderboardResponse): response is LeaderboardLookupError {
return !response.hasOwnProperty('tts_leaderboard');
}
interface LeaderboardResponsePayload {
success: boolean,
error_reason?: string,
tts_leaderboard?: Leaderboard,
w2l_leaderboard?: Leaderboard,
}
export async function GetLeaderboard() : Promise<GetLeaderboardResponse>
{
const endpoint = new ApiConfig().getLeaderboard();
return await fetch(endpoint, {
method: 'GET',
headers: {
'Accept': 'application/json',
},
credentials: 'include',
})
.then(res => res.json())
.then(res => {
const response : LeaderboardResponsePayload = res;
if (response?.success) {
return res as Leaderboard; // TODO: This is not the way.
}
if (response?.success === false) {
if (response.error_reason?.includes("not found")) {
return LeaderboardLookupError.NotFound;
} else {
return LeaderboardLookupError.ServerError;
}
}
return LeaderboardLookupError.FrontendError;
})
.catch(e => {
return LeaderboardLookupError.FrontendError;
});
}
+7 -5
View File
@@ -22,12 +22,12 @@ function NewTopNavFc(props: Props) {
<div className="column">
<Link to="/"
className="button is-link is-medium is-inverted"
>Text to Speech️</Link>
>TTS</Link>
</div>
<div className="column">
<Link to="/video"
className="button is-link is-medium is-inverted"
>Lip Sync Video</Link>
>Video</Link>
</div>
<div className="column">
<Link to="/upload"
@@ -35,9 +35,6 @@ function NewTopNavFc(props: Props) {
>Upload</Link>
</div>
<div className="column">
{/*<Link to={myDataLink}
className="button is-link is-medium is-inverted"
>Pending</Link>*/}
<Link to={myDataLink}
className="button is-link is-medium is-inverted"
>My Data</Link>
@@ -47,6 +44,11 @@ function NewTopNavFc(props: Props) {
className="button is-link is-medium is-inverted"
>Feed</Link>
</div>
<div className="column">
<Link to="/leaderboard"
className="button is-link is-medium is-inverted"
>Leaderboard</Link>
</div>
</div>
<hr />
</nav>
@@ -38,6 +38,7 @@ import { TtsModelListFc } from './tts/tts_model_list/TtsModelListFc';
import { TtsModelListItem } from '../api/tts/ListTtsModels';
import { ProfileBanFc } from './profile/profile_ban/ProfileBanFc';
import { ModerationUserListFc } from './moderation/moderation_user_list/ModerationUserList';
import { LeaderboardFc } from './leaderboard/LeaderboardFc';
interface Props {
sessionWrapper: SessionWrapper,
@@ -97,6 +98,12 @@ class NewVocodesContainer extends React.Component<Props, State> {
/>
</Route>
<Route path="/leaderboard">
<LeaderboardFc
sessionWrapper={this.props.sessionWrapper}
/>
</Route>
<Route path="/login">
<LoginFc
sessionWrapper={this.props.sessionWrapper}
@@ -0,0 +1,109 @@
import React, { useCallback, useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { FrontendUrlConfig } from '../../../common/FrontendUrlConfig';
import { SessionWrapper } from '../../../session/SessionWrapper';
import { GetLeaderboard, GetLeaderboardIsOk, Leaderboard, LeaderboardEntryForList } from '../../api/misc/GetLeaderboard';
import { GravatarFc } from '../_common/GravatarFc';
interface Props {
sessionWrapper: SessionWrapper,
}
function LeaderboardFc(props: Props) {
const [leaderboard, setLeaderboard] = useState<Leaderboard|undefined>(undefined);
const [ttsLeaderboard, setTtsLeaderboard] = useState<Array<LeaderboardEntryForList>|undefined>(undefined);
const [w2lLeaderboard, setW2lLeaderboard] = useState<Array<LeaderboardEntryForList>|undefined>(undefined);
const getLeaderboard = useCallback(async () => {
const leaderboardReponse = await GetLeaderboard();
if (GetLeaderboardIsOk(leaderboardReponse)) {
setLeaderboard(leaderboardReponse);
setTtsLeaderboard(leaderboardReponse.tts_leaderboard);
setW2lLeaderboard(leaderboardReponse.w2l_leaderboard);
} else {
}
}, []);
useEffect(() => {
getLeaderboard();
}, [getLeaderboard]);
if (!leaderboard) {
return <div />;
}
let ttsRows : Array<JSX.Element> = [];
if (ttsLeaderboard) {
ttsLeaderboard.forEach(ttsEntry => {
ttsRows.push(
<tr>
<td>
<Link to={FrontendUrlConfig.userProfilePage(ttsEntry.display_name)}>
<GravatarFc
size={12}
username={ttsEntry.display_name}
email_hash={ttsEntry.gravatar_hash} />
&nbsp;
{ttsEntry.display_name}
</Link>
</td>
<td>{ttsEntry.uploaded_count}</td>
</tr>
)
})
}
let w2lRows : Array<JSX.Element> = [];
if (w2lLeaderboard) {
w2lLeaderboard.forEach(w2lEntry => {
w2lRows.push(
<tr>
<td>
<Link to={FrontendUrlConfig.userProfilePage(w2lEntry.display_name)}>
<GravatarFc
size={12}
username={w2lEntry.display_name}
email_hash={w2lEntry.gravatar_hash} />
&nbsp;
{w2lEntry.display_name}
</Link>
</td>
<td>{w2lEntry.uploaded_count}</td>
</tr>
)
})
}
return (
<div>
<h1 className="title is-1"> Leaderboard </h1>
<table className="table is-fullwidth">
<tbody>
<tr>
<td colSpan={2}>
<h4 className="subtitle is-4"> TTS Models Uploaded </h4>
</td>
</tr>
{ttsRows}
<tr>
<td colSpan={2}>
<br />
<h4 className="subtitle is-4"> W2L Templates Uploaded </h4>
</td>
</tr>
{w2lRows}
</tbody>
</table>
</div>
)
}
export { LeaderboardFc }