mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-09 03:21:23 +00:00
add voice stats mod page
This commit is contained in:
1 parent
de75a9cea3
commit
33de220875
5 files changed
+162
-4
No files matched your search
@@ -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 };
|
||||
Reference in new issue
Block a user