w2l result pages styling + animation

This commit is contained in:
BFlat committed 2022-07-23 20:52:08 +01:00
1 parent 52e94a59ca
commit 87a104dcaa
4 files changed
+530 -396

No files matched your search

@@ -1,26 +1,34 @@
import React, { useState, useEffect, useCallback } from "react";
import { ApiConfig } from "@storyteller/components";
import { FrontendUrlConfig } from "../../../../common/FrontendUrlConfig";
import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
import { useParams, Link, useHistory } from "react-router-dom";
import {
GetW2lResult,
GetW2lResultIsOk,
W2lResult,
} from "../../../api/w2l/GetW2lResult";
import { distance, delay, duration } from "../../../../data/animation";
import React, { useState, useEffect, useCallback } from 'react';
import { ApiConfig } from '@storyteller/components';
import { FrontendUrlConfig } from '../../../../common/FrontendUrlConfig';
import { SessionWrapper } from '@storyteller/components/src/session/SessionWrapper';
import { useParams, Link, useHistory } from 'react-router-dom';
import { GetW2lResult, GetW2lResultIsOk, W2lResult } from '../../../api/w2l/GetW2lResult';
const Fade = require("react-reveal/Fade");
interface Props {
sessionWrapper: SessionWrapper,
sessionWrapper: SessionWrapper;
}
function W2lResultDeleteFc(props: Props) {
const history = useHistory();
let { token } = useParams() as { token : string };
let { token } = useParams() as { token: string };
const [w2lInferenceResult, setW2lInferenceResult] = useState<W2lResult|undefined>(undefined);
const [w2lInferenceResult, setW2lInferenceResult] = useState<
W2lResult | undefined
>(undefined);
const getInferenceResult = useCallback(async (token) => {
const templateResponse = await GetW2lResult(token);
if (GetW2lResultIsOk(templateResponse)) {
setW2lInferenceResult(templateResponse)
setW2lInferenceResult(templateResponse);
}
}, []);
@@ -30,7 +38,9 @@ function W2lResultDeleteFc(props: Props) {
const templateResultLink = FrontendUrlConfig.w2lResultPage(token);
const handleDeleteFormSubmit = (ev: React.FormEvent<HTMLFormElement>) : boolean => {
const handleDeleteFormSubmit = (
ev: React.FormEvent<HTMLFormElement>
): boolean => {
ev.preventDefault();
const endpointUrl = new ApiConfig().deleteW2lInferenceResult(token);
@@ -38,108 +48,120 @@ function W2lResultDeleteFc(props: Props) {
const request = {
set_delete: !currentlyDeleted,
as_mod: props.sessionWrapper.canDeleteOtherUsersW2lResults(),
}
};
fetch(endpointUrl, {
method: 'POST',
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
Accept: "application/json",
"Content-Type": "application/json",
},
credentials: 'include',
credentials: "include",
body: JSON.stringify(request),
})
.then(res => res.json())
.then(res => {
if (res.success) {
if (props.sessionWrapper.canDeleteOtherUsersW2lResults()) {
history.push(templateResultLink); // Mods can perform further actions
} else {
history.push('/');
.then((res) => res.json())
.then((res) => {
if (res.success) {
if (props.sessionWrapper.canDeleteOtherUsersW2lResults()) {
history.push(templateResultLink); // Mods can perform further actions
} else {
history.push("/");
}
}
}
})
.catch(e => {
});
})
.catch((e) => {});
return false;
}
};
let creatorLink = <span />;
if (!!w2lInferenceResult?.maybe_creator_display_name) {
const creatorUrl = FrontendUrlConfig.userProfilePage(w2lInferenceResult?.maybe_creator_display_name);
const creatorUrl = FrontendUrlConfig.userProfilePage(
w2lInferenceResult?.maybe_creator_display_name
);
creatorLink = (
<Link to={creatorUrl}>{w2lInferenceResult?.maybe_creator_display_name}</Link>
<Link to={creatorUrl}>
{w2lInferenceResult?.maybe_creator_display_name}
</Link>
);
}
let currentlyDeleted = !!w2lInferenceResult?.maybe_moderator_fields?.mod_deleted_at ||
!!w2lInferenceResult?.maybe_moderator_fields?.result_creator_deleted_at;
let currentlyDeleted =
!!w2lInferenceResult?.maybe_moderator_fields?.mod_deleted_at ||
!!w2lInferenceResult?.maybe_moderator_fields?.result_creator_deleted_at;
const h1Title = currentlyDeleted ? "Undelete Result?" : "Delete Result?";
const buttonTitle = currentlyDeleted ? "Confirm Undelete" : "Confirm Delete";
const buttonCss = currentlyDeleted ?
"button is-warning is-large is-fullwidth" :
"button is-danger is-large is-fullwidth";
const buttonCss = currentlyDeleted
? "btn btn-primary w-100"
: "btn btn-primary w-100";
const formLabel = currentlyDeleted ?
"Recover the W2L Result (makes it visible again)" :
"Delete W2L Result (hides from everyone but mods)";
const formLabel = currentlyDeleted
? "Recover the W2L Result (makes it visible again)"
: "Delete W2L Result (hides from everyone but mods)";
const durationSeconds = (w2lInferenceResult?.duration_millis || 0) / 1000;
return (
<div className="content">
<h1 className="title is-1"> {h1Title} </h1>
<p>
<Link to={templateResultLink}>&lt; Back to result</Link>
</p>
<table className="table">
<thead>
<tr>
<th><abbr title="Detail">Detail</abbr></th>
<th><abbr title="Value">Value</abbr></th>
</tr>
</thead>
<tbody>
<tr>
<th>Creator</th>
<td>
{creatorLink}
</td>
</tr>
<tr>
<th>Template title</th>
<td>{w2lInferenceResult?.template_title}</td>
</tr>
<tr>
<th>Duration</th>
<td>{durationSeconds} seconds</td>
</tr>
</tbody>
</table>
<div>
<Fade cascade bottom duration={duration} distance={distance}>
<div className="container pt-5 pb-4 px-md-4 px-lg-5 px-xl-3">
<h1 className="display-5 fw-bold">{h1Title}</h1>
<div className="pt-3">
<Link to={templateResultLink}>&lt; Back to result</Link>
</div>
</div>
</Fade>
<br />
<Fade
cascade
bottom
duration={duration}
distance={distance}
delay={delay}
>
<div className="container-panel pt-4 pb-5">
<div className="panel p-3 py-4 p-lg-4">
<table className="table">
<thead>
<tr>
<th>
<abbr title="Detail">Detail</abbr>
</th>
<th>
<abbr title="Value">Value</abbr>
</th>
</tr>
</thead>
<tbody>
<tr>
<th>Creator</th>
<td>{creatorLink}</td>
</tr>
<tr>
<th>Template title</th>
<td>{w2lInferenceResult?.template_title}</td>
</tr>
<tr>
<th>Duration</th>
<td>{durationSeconds} seconds</td>
</tr>
</tbody>
</table>
</div>
</div>
<form onSubmit={handleDeleteFormSubmit}>
<label className="label">{formLabel}</label>
<p className="control">
<button className={buttonCss}>
{buttonTitle}
</button>
</p>
</form>
<br />
<br />
<Link to={templateResultLink}>&lt; Back to result</Link>
<div className="container pb-5">
<form onSubmit={handleDeleteFormSubmit}>
<button className={buttonCss}>{buttonTitle}</button>
<p className="pt-4">{formLabel}</p>
</form>
</div>
</Fade>
</div>
)
);
}
export { W2lResultDeleteFc };
@@ -1,65 +1,70 @@
import React, { useState, useEffect, useCallback } from 'react';
import { ApiConfig } from '@storyteller/components';
import { SessionWrapper } from '@storyteller/components/src/session/SessionWrapper';
import { useParams, Link, useHistory } from 'react-router-dom';
import { FrontendUrlConfig } from '../../../../common/FrontendUrlConfig';
import { VisibleIconFc } from '../../_icons/VisibleIcon';
import { HiddenIconFc } from '../../_icons/HiddenIcon';
import React, { useState, useEffect, useCallback } from "react";
import { ApiConfig } from "@storyteller/components";
import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
import { useParams, Link, useHistory } from "react-router-dom";
import { FrontendUrlConfig } from "../../../../common/FrontendUrlConfig";
import { VisibleIconFc } from "../../_icons/VisibleIcon";
import { HiddenIconFc } from "../../_icons/HiddenIcon";
import { distance, delay, duration } from "../../../../data/animation";
const DEFAULT_VISIBILITY = 'public';
const Fade = require("react-reveal/Fade");
const DEFAULT_VISIBILITY = "public";
interface W2lInferenceResultResponsePayload {
success: boolean,
result: W2lInferenceResult,
success: boolean;
result: W2lInferenceResult;
}
interface W2lInferenceResult {
w2l_result_token: string,
w2l_result_token: string;
w2l_model_token: string,
w2l_model_title: string,
w2l_model_token: string;
w2l_model_title: string;
raw_inference_text: 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_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,
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,
public_bucket_wav_audio_path: string;
public_bucket_spectrogram_path: string;
creator_set_visibility?: string,
creator_set_visibility?: string;
file_size_bytes: number,
duration_millis: number,
created_at: string,
updated_at: string,
file_size_bytes: number;
duration_millis: number;
created_at: string;
updated_at: string;
maybe_moderator_fields: W2lInferenceResultModeratorFields | null | undefined,
maybe_moderator_fields: W2lInferenceResultModeratorFields | null | undefined;
}
interface W2lInferenceResultModeratorFields {
creator_ip_address: string,
mod_deleted_at: string | undefined | null,
user_deleted_at: string | undefined | null,
creator_ip_address: string;
mod_deleted_at: string | undefined | null;
user_deleted_at: string | undefined | null;
}
interface Props {
sessionWrapper: SessionWrapper,
sessionWrapper: SessionWrapper;
}
function W2lResultEditFc(props: Props) {
let { token } : { token : string } = useParams();
let { token }: { token: string } = useParams();
const history = useHistory();
const [w2lInferenceResult, setW2lInferenceResult] = useState<W2lInferenceResult|undefined>(undefined);
const [w2lInferenceResult, setW2lInferenceResult] = useState<
W2lInferenceResult | undefined
>(undefined);
const [visibility, setVisibility] = useState<string>(DEFAULT_VISIBILITY);
const getW2lResult = useCallback((token) => {
@@ -67,24 +72,25 @@ function W2lResultEditFc(props: Props) {
const endpointUrl = api.viewW2lInferenceResult(token);
fetch(endpointUrl, {
method: 'GET',
method: "GET",
headers: {
'Accept': 'application/json',
Accept: "application/json",
},
credentials: 'include',
credentials: "include",
})
.then(res => res.json())
.then(res => {
const modelsResponse : W2lInferenceResultResponsePayload = res;
if (!modelsResponse.success) {
return;
}
.then((res) => res.json())
.then((res) => {
const modelsResponse: W2lInferenceResultResponsePayload = res;
if (!modelsResponse.success) {
return;
}
setW2lInferenceResult(modelsResponse.result);
setVisibility(modelsResponse?.result?.creator_set_visibility || DEFAULT_VISIBILITY);
})
.catch(e => {
});
setW2lInferenceResult(modelsResponse.result);
setVisibility(
modelsResponse?.result?.creator_set_visibility || DEFAULT_VISIBILITY
);
})
.catch((e) => {});
}, []);
useEffect(() => {
@@ -92,12 +98,12 @@ function W2lResultEditFc(props: Props) {
}, [token, getW2lResult]);
const handleVisibilityChange = (ev: React.FormEvent<HTMLSelectElement>) => {
setVisibility((ev.target as HTMLSelectElement).value)
setVisibility((ev.target as HTMLSelectElement).value);
};
const resultLink = FrontendUrlConfig.w2lResultPage(token);
const handleFormSubmit = (ev: React.FormEvent<HTMLFormElement>) => {
const handleFormSubmit = (ev: React.FormEvent<HTMLFormElement>) => {
ev.preventDefault();
if (!w2lInferenceResult) {
@@ -108,76 +114,88 @@ function W2lResultEditFc(props: Props) {
const api = new ApiConfig();
const endpointUrl = api.editW2lInferenceResult(resultToken);
const request = {
creator_set_visibility: visibility || DEFAULT_VISIBILITY,
}
};
fetch(endpointUrl, {
method: 'POST',
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
Accept: "application/json",
"Content-Type": "application/json",
},
credentials: 'include',
credentials: "include",
body: JSON.stringify(request),
})
.then(res => res.json())
.then(res => {
if (res === undefined ||
!res.success) {
return; // Endpoint error?
}
.then((res) => res.json())
.then((res) => {
if (res === undefined || !res.success) {
return; // Endpoint error?
}
history.push(resultLink);
})
.catch(e => {
});
history.push(resultLink);
})
.catch((e) => {});
return false;
};
let isDisabled = !w2lInferenceResult;
const visibilityIcon = (visibility === 'public') ? <VisibleIconFc /> : <HiddenIconFc />;
const visibilityIcon =
visibility === "public" ? <VisibleIconFc /> : <HiddenIconFc />;
return (
<div className="content">
<h1 className="title is-1"> Edit Result Visibility </h1>
<div>
<Fade cascade bottom duration={duration} distance={distance}>
<div className="container pb-4 pt-5 px-md-4 px-lg-5 px-xl-3">
<h1 className="display-5 fw-bold">Edit Result Visibility</h1>
<div className="pt-3">
<Link to={resultLink}>&lt; Back to result </Link>
</div>
</div>
</Fade>
<p>
<Link to={resultLink}>&lt; Back to result </Link>
</p>
<form onSubmit={handleFormSubmit}>
<fieldset disabled={isDisabled}>
<div className="field">
<label className="label">
Result Visibility&nbsp;{visibilityIcon}
</label>
<div className="control select">
<select
name="creator_set_visibility"
onChange={handleVisibilityChange}
value={visibility}
>
<option value="public">Public (visible from your profile)</option>
<option value="hidden">Unlisted (shareable URLs)</option>
</select>
<Fade
cascade
bottom
duration={duration}
distance={distance}
delay={delay}
>
<form onSubmit={handleFormSubmit}>
<div className="container-panel pt-4 pb-5">
<div className="panel p-3 py-4 p-lg-4">
<fieldset disabled={isDisabled}>
<div>
<label className="sub-title">
Result Visibility&nbsp;{visibilityIcon}
</label>
<div className="form-group">
<select
name="creator_set_visibility"
onChange={handleVisibilityChange}
value={visibility}
className="form-control"
>
<option value="public">
Public (visible from your profile)
</option>
<option value="hidden">Unlisted (shareable URLs)</option>
</select>
</div>
</div>
</fieldset>
</div>
</div>
<br />
<button className="button is-link is-large is-fullwidth">Update</button>
</fieldset>
</form>
<div className="container pb-5">
<button className="btn btn-primary w-100">Update</button>
</div>
</form>
</Fade>
</div>
)
);
}
export { W2lResultEditFc };
@@ -1,32 +1,44 @@
import React, { useState, useEffect, useCallback } from 'react';
import { Gravatar } from '@storyteller/components/src/elements/Gravatar';
import { SessionWrapper } from '@storyteller/components/src/session/SessionWrapper';
import { useParams, Link } from 'react-router-dom';
import { ReportDiscordLinkFc } from '../../_common/DiscordReportLinkFc';
import { BucketConfig } from '@storyteller/components/src/api/BucketConfig';
import { HiddenIconFc } from '../../_icons/HiddenIcon';
import { VisibleIconFc } from '../../_icons/VisibleIcon';
import { FrontendUrlConfig } from '../../../../common/FrontendUrlConfig';
import { DownloadIcon } from '../../_icons/DownloadIcon';
import { GetW2lResult, GetW2lResultIsErr, GetW2lResultIsOk, W2lResult, W2lResultLookupError } from '../../../api/w2l/GetW2lResult';
import { MetaTags } from '../../../../common/MetaTags';
import React, { useState, useEffect, useCallback } from "react";
import { Gravatar } from "@storyteller/components/src/elements/Gravatar";
import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
import { useParams, Link } from "react-router-dom";
import { ReportDiscordLinkFc } from "../../_common/DiscordReportLinkFc";
import { BucketConfig } from "@storyteller/components/src/api/BucketConfig";
import { HiddenIconFc } from "../../_icons/HiddenIcon";
import { VisibleIconFc } from "../../_icons/VisibleIcon";
import { FrontendUrlConfig } from "../../../../common/FrontendUrlConfig";
import {
GetW2lResult,
GetW2lResultIsErr,
GetW2lResultIsOk,
W2lResult,
W2lResultLookupError,
} from "../../../api/w2l/GetW2lResult";
import { MetaTags } from "../../../../common/MetaTags";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faDownload, faEdit, faTrash } from "@fortawesome/free-solid-svg-icons";
import { distance, delay, duration } from "../../../../data/animation";
const Fade = require("react-reveal/Fade");
interface Props {
sessionWrapper: SessionWrapper,
sessionWrapper: SessionWrapper;
}
function W2lResultViewFc(props: Props) {
let { token } = useParams() as { token : string };
let { token } = useParams() as { token: string };
const [w2lInferenceResult, setW2lInferenceResult] = useState<W2lResult|undefined>(undefined);
const [w2lInferenceResult, setW2lInferenceResult] = useState<
W2lResult | undefined
>(undefined);
const [notFoundState, setNotFoundState] = useState<boolean>(false);
const getInferenceResult = useCallback(async (token) => {
const templateResponse = await GetW2lResult(token);
if (GetW2lResultIsOk(templateResponse)) {
setW2lInferenceResult(templateResponse)
setW2lInferenceResult(templateResponse);
} else if (GetW2lResultIsErr(templateResponse)) {
switch(templateResponse) {
switch (templateResponse) {
case W2lResultLookupError.NotFound:
setNotFoundState(true);
break;
@@ -39,58 +51,89 @@ function W2lResultViewFc(props: Props) {
}, [token, getInferenceResult]); // NB: Empty array dependency sets to run ONLY on mount
if (notFoundState) {
return (
<h1 className="title is-1">Template result not found</h1>
);
return <h1 className="title is-1">Template result not found</h1>;
}
if (!w2lInferenceResult) {
return <div />
return <div />;
}
let videoLink = new BucketConfig().getGcsUrl(w2lInferenceResult?.public_bucket_video_path);
let videoLink = new BucketConfig().getGcsUrl(
w2lInferenceResult?.public_bucket_video_path
);
let templateLink = `/w2l/${w2lInferenceResult.maybe_w2l_template_token}`;
let videoDownloadFilename = `vocodes-${w2lInferenceResult.w2l_result_token.replace(':', '')}.mp4`;
let videoDownloadFilename = `vocodes-${w2lInferenceResult.w2l_result_token.replace(
":",
""
)}.mp4`;
MetaTags.setVideoUrl(videoLink);
MetaTags.setTitle('testing...');
MetaTags.setTitle("testing...");
let durationSeconds = w2lInferenceResult?.duration_millis / 1000;
let templateName = w2lInferenceResult.template_title;
let moderatorRows = null;
if (props.sessionWrapper.canDeleteOtherUsersW2lResults() || props.sessionWrapper.canDeleteOtherUsersW2lTemplates()) {
if (
props.sessionWrapper.canDeleteOtherUsersW2lResults() ||
props.sessionWrapper.canDeleteOtherUsersW2lTemplates()
) {
moderatorRows = (
<>
<tr>
<td colSpan={2}>
<br />
<h4 className="subtitle is-4"> Moderator Details </h4>
</td>
</tr>
<tr>
<th>Template creator is banned</th>
<td>{w2lInferenceResult?.maybe_moderator_fields?.template_creator_is_banned ? "banned" : "good standing" }</td>
</tr>
<tr>
<th>Result creator is banned (if user)</th>
<td>{w2lInferenceResult?.maybe_moderator_fields?.result_creator_is_banned_if_user ? "banned" : "good standing" }</td>
</tr>
<tr>
<th>Result creator IP address</th>
<td>{w2lInferenceResult?.maybe_moderator_fields?.result_creator_ip_address || "server error"}</td>
</tr>
<tr>
<th>Mod deleted at (UTC)</th>
<td>{w2lInferenceResult?.maybe_moderator_fields?.mod_deleted_at || "not deleted"}</td>
</tr>
<tr>
<th>Result creator deleted at (UTC)</th>
<td>{w2lInferenceResult?.maybe_moderator_fields?.result_creator_deleted_at || "not deleted"}</td>
</tr>
<Fade bottom duration={duration} distance={distance} delay={delay}>
<div className="container-panel pt-3 pb-5">
<div className="panel p-3 p-lg-4">
<h2 className="panel-title fw-bold">Moderator Details</h2>
<div className="py-6">
<table className="table">
<tbody>
<tr>
<th>Template creator is banned</th>
<td>
{w2lInferenceResult?.maybe_moderator_fields
?.template_creator_is_banned
? "banned"
: "good standing"}
</td>
</tr>
<tr>
<th>Result creator is banned (if user)</th>
<td>
{w2lInferenceResult?.maybe_moderator_fields
?.result_creator_is_banned_if_user
? "banned"
: "good standing"}
</td>
</tr>
<tr>
<th>Result creator IP address</th>
<td>
{w2lInferenceResult?.maybe_moderator_fields
?.result_creator_ip_address || "server error"}
</td>
</tr>
<tr>
<th>Mod deleted at (UTC)</th>
<td>
{w2lInferenceResult?.maybe_moderator_fields
?.mod_deleted_at || "not deleted"}
</td>
</tr>
<tr>
<th>Result creator deleted at (UTC)</th>
<td>
{w2lInferenceResult?.maybe_moderator_fields
?.result_creator_deleted_at || "not deleted"}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</Fade>
</>
);
}
@@ -106,11 +149,13 @@ function W2lResultViewFc(props: Props) {
<span>
<Gravatar
size={15}
username={w2lInferenceResult.maybe_creator_display_name || ""}
email_hash={w2lInferenceResult.maybe_creator_gravatar_hash || ""}
/>
username={w2lInferenceResult.maybe_creator_display_name || ""}
email_hash={w2lInferenceResult.maybe_creator_gravatar_hash || ""}
/>
&nbsp;
<Link to={creatorLink}>{w2lInferenceResult.maybe_creator_display_name}</Link>
<Link to={creatorLink}>
{w2lInferenceResult.maybe_creator_display_name}
</Link>
</span>
);
}
@@ -122,135 +167,179 @@ function W2lResultViewFc(props: Props) {
<span>
<Gravatar
size={15}
username={w2lInferenceResult.maybe_template_creator_display_name || ""}
email_hash={w2lInferenceResult.maybe_template_creator_gravatar_hash || ""}
/>
username={
w2lInferenceResult.maybe_template_creator_display_name || ""
}
email_hash={
w2lInferenceResult.maybe_template_creator_gravatar_hash || ""
}
/>
&nbsp;
<Link to={templateCreatorLink}>{w2lInferenceResult.maybe_template_creator_display_name}</Link>
<Link to={templateCreatorLink}>
{w2lInferenceResult.maybe_template_creator_display_name}
</Link>
</span>
);
}
let resultVisibility = w2lInferenceResult?.creator_set_visibility === 'hidden' ?
<span>Hidden <HiddenIconFc /></span> :
<span>Public <VisibleIconFc /></span> ;
let resultVisibility =
w2lInferenceResult?.creator_set_visibility === "hidden" ? (
<span>
Hidden <HiddenIconFc />
</span>
) : (
<span>
Public <VisibleIconFc />
</span>
);
const currentlyDeleted = !!w2lInferenceResult?.maybe_moderator_fields?.mod_deleted_at ||
!!w2lInferenceResult?.maybe_moderator_fields?.result_creator_deleted_at;
const currentlyDeleted =
!!w2lInferenceResult?.maybe_moderator_fields?.mod_deleted_at ||
!!w2lInferenceResult?.maybe_moderator_fields?.result_creator_deleted_at;
const deleteButtonTitle = currentlyDeleted ? "Undelete Result?" : "Delete Result?";
const deleteButtonTitle = currentlyDeleted
? "Undelete Result?"
: "Delete Result?";
const deleteButtonCss = currentlyDeleted ?
"button is-warning is-large is-fullwidth" :
"button is-danger is-large is-fullwidth";
const deleteButtonCss = currentlyDeleted
? "btn btn-secondary w-100"
: "btn btn-destructive w-100";
let editButton = null;
const canEdit = props.sessionWrapper.canEditW2lResultAsUserOrMod(w2lInferenceResult?.maybe_creator_user_token);
const canEdit = props.sessionWrapper.canEditW2lResultAsUserOrMod(
w2lInferenceResult?.maybe_creator_user_token
);
if (canEdit) {
editButton = (
<>
<br />
<Link
className="button is-info is-large is-fullwidth"
<Link
className="btn btn-secondary w-100"
to={FrontendUrlConfig.w2lResultEditPage(token)}
>Edit Result Visibility</Link>
>
<FontAwesomeIcon icon={faEdit} className="me-2" />
Edit Result Visibility
</Link>
</>
);
}
let deleteButton = null;
const canDelete = props.sessionWrapper.canDeleteW2lResultAsUserOrMod(w2lInferenceResult?.maybe_creator_user_token);
const canDelete = props.sessionWrapper.canDeleteW2lResultAsUserOrMod(
w2lInferenceResult?.maybe_creator_user_token
);
if (canDelete) {
deleteButton = (
<>
<br />
<Link
<Link
className={deleteButtonCss}
to={FrontendUrlConfig.w2lResultDeletePage(token)}
>{deleteButtonTitle}</Link>
>
<FontAwesomeIcon icon={faTrash} className="me-2" />
{deleteButtonTitle}
</Link>
</>
);
}
return (
<div>
<h1 className="title is-1"> Lipsync Result </h1>
<Fade cascade bottom duration={duration} distance={distance}>
<div className="container py-5 px-md-4 px-lg-5 px-xl-3">
<h1 className="display-5 fw-bold text-center text-lg-start">
Lipsync Result
</h1>
</div>
</Fade>
<video width="100%" height="auto" controls={true}>
<source src={videoLink} />
Your device doesn't support video.
</video>
<Fade bottom duration={duration} distance={distance} delay={delay}>
<div className="container">
<video width="100%" height="auto" controls={true} className="rounded">
<source src={videoLink} />
Your device doesn't support video.
</video>
</div>
<br />
<br />
<div className="container pt-4 pb-5">
<a
className="btn btn-primary w-100"
href={videoLink}
download={videoDownloadFilename}
>
{" "}
<FontAwesomeIcon icon={faDownload} className="me-2" />
Download File
</a>
</div>
<a className="button is-large is-primary is-fullwidth"
href={videoLink}
download={videoDownloadFilename}> <DownloadIcon />&nbsp;Download File</a>
<div className="container-panel pt-5 pb-5">
<div className="panel p-3 p-lg-4">
<h2 className="panel-title fw-bold">Result Details</h2>
<div className="py-6">
<table className="table">
<tbody>
<tr>
<th>Creator</th>
<td>{creatorDetails}</td>
</tr>
<tr>
<th>Duration</th>
<td>{durationSeconds} seconds</td>
</tr>
<tr>
<th>Visibility</th>
<td>{resultVisibility}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div className="container-panel pt-3 pb-5">
<div className="panel p-3 p-lg-4">
<h2 className="panel-title fw-bold"> Template Details </h2>
<div className="py-6">
<table className="table">
<tbody>
<tr>
<th>Template used</th>
<td>
<Link to={templateLink}>{templateName}</Link>
</td>
</tr>
<tr>
<th>Template creator</th>
<td>{templateCreatorDetails}</td>
</tr>
<tr>
<th>Dimensions</th>
<td>
{w2lInferenceResult?.frame_width} x{" "}
{w2lInferenceResult?.frame_height}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</Fade>
<br />
<br />
<div>{moderatorRows}</div>
<table className="table is-fullwidth">
<tbody>
<tr>
<td colSpan={2}>
<h4 className="subtitle is-4"> Result Details </h4>
</td>
</tr>
<tr>
<th>Creator</th>
<td>
{creatorDetails}
</td>
</tr>
<tr>
<th>Duration</th>
<td>{durationSeconds} seconds</td>
</tr>
<tr>
<th>Visibility</th>
<td>{resultVisibility}</td>
</tr>
<tr>
<td colSpan={2}>
<br />
<h4 className="subtitle is-4"> Template Details </h4>
</td>
</tr>
<tr>
<th>Template used</th>
<td>
<Link to={templateLink}>
{templateName}
</Link>
</td>
</tr>
<tr>
<th>Template creator</th>
<td>
{templateCreatorDetails}
</td>
</tr>
<tr>
<th>Dimensions</th>
<td>{w2lInferenceResult?.frame_width} x {w2lInferenceResult?.frame_height}</td>
</tr>
{moderatorRows}
</tbody>
</table>
{editButton}
{deleteButton}
<br />
<ReportDiscordLinkFc />
<Fade bottom duration={duration} distance={distance} delay={delay}>
<div className="container pb-5">
<div className="d-flex gap-3 flex-column flex-md-row">
{editButton}
{deleteButton}
</div>
<div className="mt-4">
<ReportDiscordLinkFc />
</div>
</div>
</Fade>
</div>
)
);
}
export { W2lResultViewFc };
@@ -21,7 +21,10 @@ import {
} from "../../../api/w2l/GetW2lTemplate";
import { GetW2lTemplateUseCount } from "../../../api/w2l/GetW2lTemplateUseCount";
import { BackLink } from "../../_common/BackLink";
import { distance, delay, delay2, duration } from "../../../../data/animation";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faEdit, faTrash, faCheck } from "@fortawesome/free-solid-svg-icons";
import { distance, delay, duration } from "../../../../data/animation";
const Fade = require("react-reveal/Fade");
interface EnqueueJobResponsePayload {
@@ -203,53 +206,55 @@ function W2lTemplateViewFc(props: Props) {
) {
moderatorRows = (
<>
<div className="container-panel pt-3 pb-5">
<div className="panel p-3 p-lg-4">
<h2 className="panel-title fw-bold">Moderator Details</h2>
<div className="py-6">
<table className="table">
<tbody>
<tr>
<th>Creator is banned</th>
<td>
{w2lTemplate?.maybe_moderator_fields?.creator_is_banned
? "banned"
: "good standing"}
</td>
</tr>
<tr>
<th>Create IP address</th>
<td>
{w2lTemplate?.maybe_moderator_fields
?.creator_ip_address_creation || "server error"}
</td>
</tr>
<tr>
<th>Update IP address</th>
<td>
{w2lTemplate?.maybe_moderator_fields
?.creator_ip_address_last_update || "server error"}
</td>
</tr>
<tr>
<th>Mod deleted at (UTC)</th>
<td>
{w2lTemplate?.maybe_moderator_fields?.mod_deleted_at ||
"not deleted"}
</td>
</tr>
<tr>
<th>User deleted at (UTC)</th>
<td>
{w2lTemplate?.maybe_moderator_fields?.user_deleted_at ||
"not deleted"}
</td>
</tr>
</tbody>
</table>
<Fade bottom duration={duration} distance={distance} delay={delay}>
<div className="container-panel pt-3 pb-5">
<div className="panel p-3 p-lg-4">
<h2 className="panel-title fw-bold">Moderator Details</h2>
<div className="py-6">
<table className="table">
<tbody>
<tr>
<th>Creator is banned</th>
<td>
{w2lTemplate?.maybe_moderator_fields?.creator_is_banned
? "banned"
: "good standing"}
</td>
</tr>
<tr>
<th>Create IP address</th>
<td>
{w2lTemplate?.maybe_moderator_fields
?.creator_ip_address_creation || "server error"}
</td>
</tr>
<tr>
<th>Update IP address</th>
<td>
{w2lTemplate?.maybe_moderator_fields
?.creator_ip_address_last_update || "server error"}
</td>
</tr>
<tr>
<th>Mod deleted at (UTC)</th>
<td>
{w2lTemplate?.maybe_moderator_fields?.mod_deleted_at ||
"not deleted"}
</td>
</tr>
<tr>
<th>User deleted at (UTC)</th>
<td>
{w2lTemplate?.maybe_moderator_fields?.user_deleted_at ||
"not deleted"}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</Fade>
</>
);
}
@@ -292,6 +297,7 @@ function W2lTemplateViewFc(props: Props) {
className={"btn btn-secondary w-100"}
to={FrontendUrlConfig.w2lTemplateEditPage(templateSlug)}
>
<FontAwesomeIcon icon={faEdit} className="me-2" />
Edit Template Details
</Link>
</>
@@ -348,6 +354,7 @@ function W2lTemplateViewFc(props: Props) {
className={deleteButtonCss}
to={FrontendUrlConfig.w2lTemplateDeletePage(templateSlug)}
>
<FontAwesomeIcon icon={faTrash} className="me-2" />
{deleteButtonTitle}
</Link>
</>
@@ -359,19 +366,21 @@ function W2lTemplateViewFc(props: Props) {
if (!!w2lTemplate?.description_rendered_html) {
templateDescription = (
<>
<div className="container-panel pt-3 pb-5">
<div className="panel p-3 p-lg-4">
<h2 className="panel-title fw-bold">Model Description</h2>
<div className="py-6">
<div
className="profile content is-medium"
dangerouslySetInnerHTML={{
__html: w2lTemplate?.description_rendered_html || "",
}}
/>
<Fade bottom duration={duration} distance={distance} delay={delay}>
<div className="container-panel pt-3 pb-5">
<div className="panel p-3 p-lg-4">
<h2 className="panel-title fw-bold">Model Description</h2>
<div className="py-6">
<div
className="profile content is-medium"
dangerouslySetInnerHTML={{
__html: w2lTemplate?.description_rendered_html || "",
}}
/>
</div>
</div>
</div>
</div>
</Fade>
</>
);
}
@@ -449,9 +458,7 @@ function W2lTemplateViewFc(props: Props) {
</div>
</form>
<div>
<div>{templateDescription}</div>
</div>
<div>{templateDescription}</div>
<div className="container-panel pt-3 pb-5">
<div className="panel p-3 p-lg-4">
@@ -519,9 +526,7 @@ function W2lTemplateViewFc(props: Props) {
</div>
</div>
<div>
<div>{moderatorRows}</div>
</div>
<div>{moderatorRows}</div>
<div className="container">
<div className="d-flex flex-column flex-lg-row gap-3">