mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 09:28:11 +00:00
Leaderboard view
This commit is contained in:
1 parent
c37667f5e8
commit
ecc4bc6a72
5 files changed
+199
-5
No files matched your search
@@ -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`;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
}
|
||||
@@ -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} />
|
||||
|
||||
{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} />
|
||||
|
||||
{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 }
|
||||
Reference in new issue
Block a user