moderation job status page

This commit is contained in:
Brandon Thomas committed 2021-09-11 05:19:47 -04:00
1 parent 80cbf79811
commit 6e5443244d
8 files changed
+226 -16

No files matched your search

+8
View File
@@ -258,6 +258,14 @@ class ApiConfig {
return `${this.getScheme()}://${this.getNewApiHost()}/moderation/user/list`;
}
getTtsInferenceStats() : string {
return `${this.getScheme()}://${this.getNewApiHost()}/moderation/jobs/tts_inference_queue_stats`;
}
getW2lInferenceStats() : string {
return `${this.getScheme()}://${this.getNewApiHost()}/moderation/jobs/w2l_inference_queue_stats`;
}
private getScheme() : string {
return this.isLocalDev ? "http" : "https";
}
@@ -0,0 +1,63 @@
import { ApiConfig } from "../../../common/ApiConfig";
export interface TtsInferenceStats {
success: boolean,
pending_count: number,
}
export enum TtsInferenceStatsError {
NotAuthorized,
ServerError,
FrontendError,
}
export type GetTtsInferenceStatsResponse = TtsInferenceStats | TtsInferenceStatsError;
export function GetTtsInferenceStatsIsOk(response: GetTtsInferenceStatsResponse): response is TtsInferenceStats {
return response.hasOwnProperty('pending_count');
}
export function GetTtsInferenceStatsIsErr(response: GetTtsInferenceStatsResponse): response is TtsInferenceStatsError {
return !response.hasOwnProperty('pending_count');
}
interface TtsInferenceStatsResponsePayload {
success: boolean,
error_reason?: string,
pending_count?: number,
}
export async function GetTtsInferenceStats() : Promise<GetTtsInferenceStatsResponse>
{
const endpoint = new ApiConfig().getTtsInferenceStats();
return await fetch(endpoint, {
method: 'GET',
headers: {
'Accept': 'application/json',
},
credentials: 'include',
})
.then(res => res.json())
.then(res => {
const response : TtsInferenceStatsResponsePayload = res;
if (response?.success) {
return res as TtsInferenceStats; // TODO: This is not the way.
}
if (response?.success === false) {
if (response.error_reason?.includes("authorized")) {
return TtsInferenceStatsError.NotAuthorized;
} else {
return TtsInferenceStatsError.ServerError;
}
}
return TtsInferenceStatsError.FrontendError;
})
.catch(e => {
return TtsInferenceStatsError.FrontendError;
});
}
+1 -4
View File
@@ -1,8 +1,5 @@
import { ApiConfig } from "../../../common/ApiConfig";
//export interface GetUserListRequest {
//}
export interface GetUserListSuccessResponse {
success: boolean,
users: Array<UserForList>
@@ -53,7 +50,7 @@ export async function GetUserList() : Promise<GetUserListResponse>
.then(res => res.json())
.then(res => {
if (!res) {
return { success : false };
return { success : false }; // TODO: This loses error semantics and is deprecated
}
if (res && 'success' in res) {
@@ -0,0 +1,64 @@
import { ApiConfig } from "../../../common/ApiConfig";
export interface W2lInferenceStats {
success: boolean,
pending_count: number,
}
export enum W2lInferenceStatsError {
NotAuthorized,
ServerError,
FrontendError,
}
export type GetW2lInferenceStatsResponse = W2lInferenceStats | W2lInferenceStatsError;
export function GetW2lInferenceStatsIsOk(response: GetW2lInferenceStatsResponse): response is W2lInferenceStats {
return response.hasOwnProperty('pending_count');
}
export function GetW2lInferenceStatsIsErr(response: GetW2lInferenceStatsResponse): response is W2lInferenceStatsError {
return !response.hasOwnProperty('pending_count');
}
interface W2lInferenceStatsResponsePayload {
success: boolean,
error_reason?: string,
pending_count?: number,
}
export async function GetW2lInferenceStats() : Promise<GetW2lInferenceStatsResponse>
{
const endpoint = new ApiConfig().getW2lInferenceStats();
return await fetch(endpoint, {
method: 'GET',
headers: {
'Accept': 'application/json',
},
credentials: 'include',
})
.then(res => res.json())
.then(res => {
const response : W2lInferenceStatsResponsePayload = res;
if (response?.success) {
return res as W2lInferenceStats; // TODO: This is not the way.
}
if (response?.success === false) {
if (response.error_reason?.includes("authorized")) {
return W2lInferenceStatsError.NotAuthorized;
} else {
return W2lInferenceStatsError.ServerError;
}
}
return W2lInferenceStatsError.FrontendError;
})
.catch(e => {
return W2lInferenceStatsError.FrontendError;
});
}
@@ -39,6 +39,7 @@ 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';
import { ModerationJobStatsFc } from './moderation/moderation_job_stats/ModerationJobStatsFc';
interface Props {
sessionWrapper: SessionWrapper,
@@ -278,6 +279,12 @@ class NewVocodesContainer extends React.Component<Props, State> {
/>
</Route>
<Route path="/moderation/job_stats">
<ModerationJobStatsFc
sessionWrapper={this.props.sessionWrapper}
/>
</Route>
<Route path="/moderation">
<ModerationFc
sessionWrapper={this.props.sessionWrapper}
@@ -9,16 +9,6 @@ interface FirehoseEventListResponsePayload {
events: Array<FirehoseEvent>,
}
/*
event_token "EV:YR8HA4VCVYX9JMH5AMDFHTNRGSYGD"
event_type "w2l_template_upload_completed"
maybe_target_user_token "U:WNZCXKV1AN7XD"
maybe_target_username "brandon"
maybe_target_display_name "brandon"
maybe_target_entity_token "W2L_TPL:MJZ2SMCXX9DRNZ249VK70TWJ"
created_at "2021-05-30T06:42:39Z"
updated_at "2021-05-30T06:42:39Z"
*/
interface FirehoseEvent {
event_token: string,
event_type: string,
@@ -0,0 +1,74 @@
import React, { useCallback, useEffect, useState } from 'react';
import { SessionWrapper } from '../../../../session/SessionWrapper';
import { FrontendUrlConfig } from '../../../../common/FrontendUrlConfig';
import { BackLink } from '../../_common/BackLink';
import { GetTtsInferenceStats, GetTtsInferenceStatsIsOk } from '../../../api/moderation/GetTtsInferenceStats';
import { GetW2lInferenceStats, GetW2lInferenceStatsIsOk } from '../../../api/moderation/GetW2lInferenceStats';
interface Props {
sessionWrapper: SessionWrapper,
}
function ModerationJobStatsFc(props: Props) {
const [ttsPendingJobCount, setTtsPendingJobCount] = useState<number>(-1);
const [w2lPendingJobCount, setW2lPendingJobCount] = useState<number>(-1);
const getTtsStats = useCallback(async () => {
const response = await GetTtsInferenceStats();
if (GetTtsInferenceStatsIsOk(response)) {
setTtsPendingJobCount(response.pending_count);
}
}, []);
const getW2lStats = useCallback(async () => {
const response = await GetW2lInferenceStats();
if (GetW2lInferenceStatsIsOk(response)) {
setW2lPendingJobCount(response.pending_count);
}
}, []);
useEffect(() => {
getTtsStats();
getW2lStats();
}, [getTtsStats, getW2lStats]);
if (ttsPendingJobCount === -1 && w2lPendingJobCount === -1) {
return <div />
}
if (!props.sessionWrapper.canBanUsers()) {
return <h1>Unauthorized</h1>;
}
return (
<div>
<h1 className="title is-1"> Job Stats </h1>
<BackLink link={FrontendUrlConfig.moderationMain()} text="Back to moderation" />
<br />
<br />
<table className="table is-fullwidth">
<tbody>
<tr>
<th>
Pending TTS Inference Jobs
</th>
<td>{ttsPendingJobCount}</td>
</tr>
<tr>
<th>
Pending W2L Inference Jobs
</th>
<td>{w2lPendingJobCount}</td>
</tr>
</tbody>
</table>
</div>
)
}
export { ModerationJobStatsFc };
@@ -18,18 +18,25 @@ function ModerationFc(props: Props) {
<Link
to="/moderation/user/list"
className="button is-link is-large is-fullwidth is-outlined"
className="button is-link is-large is-fullwidth is-light"
>User List</Link>
<br />
<Link
to="/moderation/ip_bans"
className="button is-link is-large is-fullwidth is-outlined"
className="button is-link is-large is-fullwidth is-light"
>IP Ban List</Link>
<br />
<Link
to="/moderation/job_stats"
className="button is-link is-large is-fullwidth is-light"
>Job Stats</Link>
<br />
<p>
More mod controls will be added in the future: user roles, activity tracking,
timed bans, account bans, etc.