add voice stats mod page

This commit is contained in:
Brandon Thomas committed 2021-09-17 03:13:52 -04:00
1 parent de75a9cea3
commit 33de220875
5 files changed
+162 -4

No files matched your search

+4
View File
@@ -258,6 +258,10 @@ class ApiConfig {
return `${this.getScheme()}://${this.getNewApiHost()}/moderation/user/list`;
}
getTtsVoiceInventoryStats() : string {
return `${this.getScheme()}://${this.getNewApiHost()}/moderation/stats/tts_voices`;
}
getTtsInferenceStats() : string {
return `${this.getScheme()}://${this.getNewApiHost()}/moderation/jobs/tts_inference_queue_stats`;
}
@@ -0,0 +1,65 @@
import { ApiConfig } from "../../../common/ApiConfig";
export interface VoiceInventoryStats {
success: boolean,
public_voices_count: number,
all_voices_count_including_deleted: number,
}
export enum VoiceInventoryStatsError {
NotAuthorized,
ServerError,
FrontendError,
}
export type GetVoiceInventoryStatsResponse = VoiceInventoryStats | VoiceInventoryStatsError;
export function GetVoiceInventoryStatsIsOk(response: GetVoiceInventoryStatsResponse): response is VoiceInventoryStats {
return response.hasOwnProperty('public_voices_count');
}
export function GetVoiceInventoryStatsIsErr(response: GetVoiceInventoryStatsResponse): response is VoiceInventoryStatsError {
return !response.hasOwnProperty('public_voices_count');
}
interface VoiceInventoryStatsResponsePayload {
success: boolean,
error_reason?: string,
pending_count?: number,
seconds_since_first?: number,
}
export async function GetVoiceInventoryStats() : Promise<GetVoiceInventoryStatsResponse>
{
const endpoint = new ApiConfig().getTtsVoiceInventoryStats();
return await fetch(endpoint, {
method: 'GET',
headers: {
'Accept': 'application/json',
},
credentials: 'include',
})
.then(res => res.json())
.then(res => {
const response : VoiceInventoryStatsResponsePayload = res;
if (response?.success) {
return res as VoiceInventoryStats; // TODO: This is not the way.
}
if (response?.success === false) {
if (response.error_reason?.includes("authorized")) {
return VoiceInventoryStatsError.NotAuthorized;
} else {
return VoiceInventoryStatsError.ServerError;
}
}
return VoiceInventoryStatsError.FrontendError;
})
.catch(e => {
return VoiceInventoryStatsError.FrontendError;
});
}
@@ -41,6 +41,7 @@ import { ModerationUserListFc } from './moderation/moderation_user_list/Moderati
import { LeaderboardFc } from './leaderboard/LeaderboardFc';
import { ModerationJobStatsFc } from './moderation/moderation_job_stats/ModerationJobStatsFc';
import { ModerationPendingW2lTemplatesFc } from './moderation/moderation_pending_w2l_templates/ModerationPendingW2lTemplatesFc';
import { ModerationVoiceStatsFc } from './moderation/moderation_voice_stats/ModerationVoiceStatsFc';
interface Props {
sessionWrapper: SessionWrapper,
@@ -280,6 +281,12 @@ class NewVocodesContainer extends React.Component<Props, State> {
/>
</Route>
<Route path="/moderation/voice_stats">
<ModerationVoiceStatsFc
sessionWrapper={this.props.sessionWrapper}
/>
</Route>
<Route path="/moderation/job_stats">
<ModerationJobStatsFc
sessionWrapper={this.props.sessionWrapper}
@@ -31,16 +31,23 @@ function ModerationFc(props: Props) {
<br />
<Link
to="/moderation/job_stats"
to="/moderation/approve/w2l_templates"
className="button is-link is-large is-fullwidth is-light"
>Job Stats</Link>
>Unapproved W2L Templates</Link>
<br />
<Link
to="/moderation/approve/w2l_templates"
to="/moderation/voice_stats"
className="button is-link is-large is-fullwidth is-light"
>Unapproved W2L Templates</Link>
>Voice Stats</Link>
<br />
<Link
to="/moderation/job_stats"
className="button is-link is-large is-fullwidth is-light"
>Job Stats</Link>
<br />
@@ -0,0 +1,75 @@
import React, { useCallback, useEffect, useState } from 'react';
import { SessionWrapper } from '../../../../session/SessionWrapper';
import { FrontendUrlConfig } from '../../../../common/FrontendUrlConfig';
import { BackLink } from '../../_common/BackLink';
import { GetVoiceInventoryStats, GetVoiceInventoryStatsIsOk } from '../../../api/moderation/GetVoiceInventoryStats';
interface Props {
sessionWrapper: SessionWrapper,
}
function ModerationVoiceStatsFc(props: Props) {
const [allVoicesCount, setAllVoicesCount] = useState<number>(-1);
const [publicVoicesCount, setPublicVoicesCount] = useState<number>(-1);
const getVoiceStats = useCallback(async () => {
const response = await GetVoiceInventoryStats();
if (GetVoiceInventoryStatsIsOk(response)) {
setAllVoicesCount(response.all_voices_count_including_deleted);
setPublicVoicesCount(response.public_voices_count);
}
}, []);
const reloadStats = useCallback(async () => {
getVoiceStats();
}, [getVoiceStats]);
useEffect(() => {
reloadStats();
}, [reloadStats]);
if (allVoicesCount === -1 && publicVoicesCount === -1) {
return <div />
}
if (!props.sessionWrapper.canEditOtherUsersTtsModels()) {
return <h1>Unauthorized</h1>;
}
return (
<div>
<h1 className="title is-1"> Voice Stats </h1>
<BackLink link={FrontendUrlConfig.moderationMain()} text="Back to moderation" />
<br />
<br />
<table className="table is-fullwidth">
<tbody>
<tr>
<th>
Public voice vount
</th>
<td>{publicVoicesCount} voices </td>
</tr>
<tr>
<th>
All voice count (incl banned)
</th>
<td>{allVoicesCount} voices </td>
</tr>
</tbody>
</table>
<br />
<button
className="button is-info is-large is-fullwidth"
onClick={() => reloadStats()}
>Reload</button>
</div>
)
}
export { ModerationVoiceStatsFc };