mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-11 20:32:12 +00:00
Delete page for TTS results (WIP)
This commit is contained in:
1 parent
b328d8f9b0
commit
2a4d6d448a
5 files changed
+263
-9
No files matched your search
@@ -20,6 +20,10 @@ class FrontendUrlConfig {
|
||||
return `/tts/${modelToken}/edit`;
|
||||
}
|
||||
|
||||
static ttsResultDeletePage(resultToken: string) : string {
|
||||
return `/tts/result/${resultToken}/delete`;
|
||||
}
|
||||
|
||||
// User links
|
||||
|
||||
static userProfilePage(userDisplayName: string) : string {
|
||||
|
||||
@@ -118,6 +118,13 @@ export class SessionWrapper {
|
||||
public canDeleteOtherUsersW2lResults() : boolean {
|
||||
return this.sessionStateResponse?.user?.can_delete_other_users_w2l_results || false;
|
||||
}
|
||||
|
||||
public deleteTtsResultAsMod(creatorUserToken: MaybeString) : boolean {
|
||||
if (this.verifyUserTokenMatch(creatorUserToken)) {
|
||||
return true;
|
||||
}
|
||||
return this.canDeleteOtherUsersTtsResults();
|
||||
}
|
||||
|
||||
private verifyUserTokenMatch(otherUserToken: MaybeString) : boolean {
|
||||
// Default to false if user token on either side is falsey.
|
||||
|
||||
@@ -28,6 +28,7 @@ import { ModerationViewIpBanFc } from './moderation/moderation_view_ip_ban/Moder
|
||||
import { AboutFc } from './about/about_page/AboutFc';
|
||||
import { TermsFc } from './about/terms_page/TermsFc';
|
||||
import { TtsModelEditFc } from './tts/tts_model_edit/TtsModelEditFc';
|
||||
import { TtsResultDeleteFc } from './tts/tts_result_delete/TtsResultDeleteFc';
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper,
|
||||
@@ -109,11 +110,17 @@ class NewVocodesContainer extends React.Component<Props, State> {
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/tts/result/:token/delete">
|
||||
<TtsResultDeleteFc
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/tts/result/:token">
|
||||
<TtsResultViewFc
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
/>
|
||||
</Route>
|
||||
</Route>
|
||||
|
||||
<Route path="/tts/:token/edit">
|
||||
<TtsModelEditFc
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { ApiConfig } from '../../../common/ApiConfig';
|
||||
import { SessionWrapper } from '../../../session/SessionWrapper';
|
||||
import { useParams, Link, useHistory } from 'react-router-dom';
|
||||
import { GravatarFc } from '../../common/GravatarFc';
|
||||
|
||||
interface TtsInferenceResultResponsePayload {
|
||||
success: boolean,
|
||||
result: TtsInferenceResult,
|
||||
}
|
||||
|
||||
interface TtsInferenceResult {
|
||||
tts_result_token: string,
|
||||
|
||||
tts_model_token: string,
|
||||
tts_model_title: string,
|
||||
|
||||
raw_inference_text: string,
|
||||
|
||||
maybe_creator_user_token?: string,
|
||||
maybe_creator_username?: string,
|
||||
maybe_creator_display_name?: string,
|
||||
maybe_creator_gravatar_hash?: string,
|
||||
|
||||
maybe_model_creator_user_token?: string,
|
||||
maybe_model_creator_username?: string,
|
||||
maybe_model_creator_display_name?: string,
|
||||
maybe_model_creator_gravatar_hash?: string,
|
||||
|
||||
public_bucket_wav_audio_path: string,
|
||||
public_bucket_spectrogram_path: string,
|
||||
|
||||
file_size_bytes: number,
|
||||
duration_millis: number,
|
||||
created_at: string,
|
||||
updated_at: string,
|
||||
|
||||
maybe_moderator_fields: TtsInferenceResultModeratorFields | null | undefined,
|
||||
}
|
||||
|
||||
interface TtsInferenceResultModeratorFields {
|
||||
creator_ip_address: string,
|
||||
mod_deleted_at: string | undefined | null,
|
||||
user_deleted_at: string | undefined | null,
|
||||
}
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper,
|
||||
}
|
||||
|
||||
function TtsResultDeleteFc(props: Props) {
|
||||
const history = useHistory();
|
||||
|
||||
let { token } : { token: string } = useParams();
|
||||
|
||||
const [ttsInferenceResult, setTtsInferenceResult] = useState<TtsInferenceResult|undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
const api = new ApiConfig();
|
||||
const endpointUrl = api.viewTtsInferenceResult(token);
|
||||
|
||||
fetch(endpointUrl, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
const modelsResponse : TtsInferenceResultResponsePayload = res;
|
||||
if (!modelsResponse.success) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTtsInferenceResult(modelsResponse.result)
|
||||
})
|
||||
.catch(e => {
|
||||
//this.props.onSpeakErrorCallback();
|
||||
});
|
||||
}, [token]); // NB: Empty array dependency sets to run ONLY on mount
|
||||
|
||||
const currentlyDeleted = !!ttsInferenceResult?.maybe_moderator_fields?.mod_deleted_at || !!ttsInferenceResult?.maybe_moderator_fields?.user_deleted_at;
|
||||
|
||||
const handleDeleteFormSubmit = (ev: React.FormEvent<HTMLFormElement>) : boolean => {
|
||||
ev.preventDefault();
|
||||
|
||||
const api = new ApiConfig();
|
||||
const endpointUrl = api.deleteTtsInferenceResult(token);
|
||||
|
||||
const request = {
|
||||
set_delete: !currentlyDeleted,
|
||||
as_mod: props.sessionWrapper.deleteTtsResultAsMod(ttsInferenceResult?.maybe_creator_user_token)
|
||||
}
|
||||
|
||||
fetch(endpointUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(request),
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
if (res.success) {
|
||||
if (props.sessionWrapper.canDeleteOtherUsersTtsResults()) {
|
||||
history.go(0); // force reload
|
||||
} else {
|
||||
history.push('/');
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ttsInferenceResult === undefined) {
|
||||
return <div />;
|
||||
}
|
||||
|
||||
let modelLink = `/tts/${ttsInferenceResult.tts_model_token}`;
|
||||
let durationSeconds = ttsInferenceResult?.duration_millis / 1000;
|
||||
let modelName = ttsInferenceResult.tts_model_title;
|
||||
|
||||
let creatorDetails = <span>Anonymous user</span>;
|
||||
if (!!ttsInferenceResult.maybe_creator_user_token) {
|
||||
let creatorLink = `/profile/${ttsInferenceResult.maybe_creator_username}`;
|
||||
creatorDetails = (
|
||||
<span>
|
||||
<GravatarFc
|
||||
size={15}
|
||||
username={ttsInferenceResult.maybe_creator_display_name || ""}
|
||||
email_hash={ttsInferenceResult.maybe_creator_gravatar_hash || ""}
|
||||
/>
|
||||
|
||||
<Link to={creatorLink}>{ttsInferenceResult.maybe_creator_display_name}</Link>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
let modelCreatorDetails = <span>Anonymous user</span>;
|
||||
if (!!ttsInferenceResult.maybe_model_creator_user_token) {
|
||||
let modelCreatorLink = `/profile/${ttsInferenceResult.maybe_model_creator_username}`;
|
||||
modelCreatorDetails = (
|
||||
<span>
|
||||
<GravatarFc
|
||||
size={15}
|
||||
username={ttsInferenceResult.maybe_model_creator_display_name || ""}
|
||||
email_hash={ttsInferenceResult.maybe_model_creator_gravatar_hash || ""}
|
||||
/>
|
||||
|
||||
<Link to={modelCreatorLink}>{ttsInferenceResult.maybe_model_creator_display_name}</Link>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
const buttonTitle = currentlyDeleted ? "Undelete" : "Delete";
|
||||
|
||||
const buttonCss = currentlyDeleted ?
|
||||
"button is-warning is-large is-fullwidth" :
|
||||
"button is-danger is-large is-fullwidth";
|
||||
|
||||
const formLabel = currentlyDeleted ?
|
||||
"Recover the TTS Result (makes it visible again)" :
|
||||
"Delete TTS Result (hides from everyone but mods)";
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title is-1"> Delete Result ?</h1>
|
||||
|
||||
<form onSubmit={handleDeleteFormSubmit}>
|
||||
|
||||
<br />
|
||||
<label className="label">{formLabel}</label>
|
||||
|
||||
<p className="control">
|
||||
<button className={buttonCss}>
|
||||
{buttonTitle}
|
||||
</button>
|
||||
</p>
|
||||
|
||||
</form>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<h3 className="title is-3"> Info </h3>
|
||||
|
||||
<table className="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><abbr title="Detail">Detail</abbr></th>
|
||||
<th><abbr title="Value">Value</abbr></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Original Text</th>
|
||||
<td>
|
||||
{ttsInferenceResult.raw_inference_text}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Audio Creator</th>
|
||||
<td>
|
||||
{creatorDetails}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Model used</th>
|
||||
<td>
|
||||
<Link to={modelLink}>
|
||||
{modelName}
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Model creator</th>
|
||||
<td>
|
||||
{modelCreatorDetails}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Duration</th>
|
||||
<td>{durationSeconds} seconds</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export { TtsResultDeleteFc };
|
||||
@@ -4,9 +4,9 @@ import { SessionWrapper } from '../../../session/SessionWrapper';
|
||||
import { useParams, Link } from 'react-router-dom';
|
||||
import { GravatarFc } from '../../common/GravatarFc';
|
||||
import { SpectrogramFc } from './SpectrogramFc';
|
||||
import { TtsResultViewDeleteFc } from './TtsResultView_DeleteFc';
|
||||
import { ReportDiscordLinkFc } from '../../common/DiscordReportLinkFc';
|
||||
import { BucketConfig } from '../../../common/BucketConfig';
|
||||
import { FrontendUrlConfig } from '../../../common/FrontendUrlConfig';
|
||||
|
||||
interface TtsInferenceResultResponsePayload {
|
||||
success: boolean,
|
||||
@@ -98,7 +98,7 @@ function TtsResultViewFc(props: Props) {
|
||||
|
||||
let modelName = ttsInferenceResult.tts_model_title;
|
||||
|
||||
const currentlyDeleted = !!ttsInferenceResult?.maybe_moderator_fields?.mod_deleted_at || !!ttsInferenceResult?.maybe_moderator_fields?.user_deleted_at;
|
||||
//const currentlyDeleted = !!ttsInferenceResult?.maybe_moderator_fields?.mod_deleted_at || !!ttsInferenceResult?.maybe_moderator_fields?.user_deleted_at;
|
||||
|
||||
let moderatorRows = null;
|
||||
|
||||
@@ -234,12 +234,10 @@ function TtsResultViewFc(props: Props) {
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<TtsResultViewDeleteFc
|
||||
sessionWrapper={props.sessionWrapper}
|
||||
resultToken={token}
|
||||
currentlyDeleted={currentlyDeleted}
|
||||
maybeCreatorUserToken={ttsInferenceResult?.maybe_creator_user_token}
|
||||
/>
|
||||
<Link
|
||||
className="button is-danger is-large is-fullwidth"
|
||||
to={FrontendUrlConfig.ttsResultDeletePage(token)}
|
||||
>Delete?</Link>
|
||||
|
||||
<br />
|
||||
<ReportDiscordLinkFc />
|
||||
|
||||
Reference in new issue
Block a user