From 33de2208750a8510e833be6d5dc4b71ab2f9d1ca Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 17 Sep 2021 03:13:52 -0400 Subject: [PATCH] add voice stats mod page --- vocodes/src/common/ApiConfig.ts | 4 + .../api/moderation/GetVoiceInventoryStats.ts | 65 ++++++++++++++++ vocodes/src/v2/view/NewVocodesContainer.tsx | 7 ++ .../moderation_main/ModerationFc.tsx | 15 +++- .../ModerationVoiceStatsFc.tsx | 75 +++++++++++++++++++ 5 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 vocodes/src/v2/api/moderation/GetVoiceInventoryStats.ts create mode 100644 vocodes/src/v2/view/moderation/moderation_voice_stats/ModerationVoiceStatsFc.tsx diff --git a/vocodes/src/common/ApiConfig.ts b/vocodes/src/common/ApiConfig.ts index dd1d321ecd..af77239c11 100644 --- a/vocodes/src/common/ApiConfig.ts +++ b/vocodes/src/common/ApiConfig.ts @@ -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`; } diff --git a/vocodes/src/v2/api/moderation/GetVoiceInventoryStats.ts b/vocodes/src/v2/api/moderation/GetVoiceInventoryStats.ts new file mode 100644 index 0000000000..7748eae7a8 --- /dev/null +++ b/vocodes/src/v2/api/moderation/GetVoiceInventoryStats.ts @@ -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 +{ + 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; + }); +} diff --git a/vocodes/src/v2/view/NewVocodesContainer.tsx b/vocodes/src/v2/view/NewVocodesContainer.tsx index 9ae4a051c4..f05a3d90a0 100644 --- a/vocodes/src/v2/view/NewVocodesContainer.tsx +++ b/vocodes/src/v2/view/NewVocodesContainer.tsx @@ -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 { /> + + + + Job Stats + >Unapproved W2L Templates
Unapproved W2L Templates + >Voice Stats + +
+ + Job Stats
diff --git a/vocodes/src/v2/view/moderation/moderation_voice_stats/ModerationVoiceStatsFc.tsx b/vocodes/src/v2/view/moderation/moderation_voice_stats/ModerationVoiceStatsFc.tsx new file mode 100644 index 0000000000..19933bd764 --- /dev/null +++ b/vocodes/src/v2/view/moderation/moderation_voice_stats/ModerationVoiceStatsFc.tsx @@ -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(-1); + const [publicVoicesCount, setPublicVoicesCount] = useState(-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
+ } + + if (!props.sessionWrapper.canEditOtherUsersTtsModels()) { + return

Unauthorized

; + } + + return ( +
+

Voice Stats

+ + + +
+
+ + + + + + + + + + + + +
+ Public voice vount + {publicVoicesCount} voices
+ All voice count (incl banned) + {allVoicesCount} voices
+ +
+ +
+ ) +} + +export { ModerationVoiceStatsFc };