Refactor GetTts API into shared package, add featured flags + edit UI

This commit is contained in:
Brandon Thomas committed 2022-02-11 11:29:33 -05:00
1 parent a355d4c1e4
commit 176ff7cfb9
4 files changed
+123 -57

No files matched your search

@@ -1,4 +1,4 @@
import { ApiConfig } from "@storyteller/components";
import { ApiConfig } from "../ApiConfig";
export interface TtsModel {
model_token: string,
@@ -12,6 +12,8 @@ export interface TtsModel {
creator_gravatar_hash: string,
description_markdown: string,
description_rendered_html: string,
is_front_page_featured: boolean,
is_twitch_featured: boolean,
creator_set_visibility: string,
updatable_slug: string,
created_at: string,
@@ -3,7 +3,7 @@ import { AssignTtsCategory, AssignTtsCategoryIsError, AssignTtsCategoryIsOk } fr
import { BackLink } from '../../_common/BackLink';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { FrontendUrlConfig } from '../../../../common/FrontendUrlConfig';
import { GetTtsModel, GetTtsModelIsErr, GetTtsModelIsOk, TtsModel, TtsModelLookupError } from '../../../api/tts/GetTtsModel';
import { GetTtsModel, GetTtsModelIsErr, GetTtsModelIsOk, TtsModel, TtsModelLookupError } from '@storyteller/components/src/api/tts/GetTtsModel';
import { ListTtsCategories, ListTtsCategoriesIsError, ListTtsCategoriesIsOk, TtsCategory } from '../../../api/category/ListTtsCategories';
import { ListTtsCategoriesForModel, ListTtsCategoriesForModelIsError, ListTtsCategoriesForModelIsOk, TtsModelCategory } from '../../../api/category/ListTtsCategoriesForModel';
import { SessionWrapper } from '../../../../session/SessionWrapper';
@@ -6,42 +6,16 @@ import { useParams, useHistory } from 'react-router-dom';
import { FrontendUrlConfig } from '../../../../common/FrontendUrlConfig';
import { VisibleIconFc } from '../../_icons/VisibleIcon';
import { HiddenIconFc } from '../../_icons/HiddenIcon';
import { GetTtsModel, GetTtsModelIsErr, GetTtsModelIsOk, TtsModel, TtsModelLookupError } from '@storyteller/components/src/api/tts/GetTtsModel';
import { BackLink } from '../../_common/BackLink';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faHeadphones, faHome } from '@fortawesome/free-solid-svg-icons';
import { faTwitch } from '@fortawesome/free-brands-svg-icons';
const DEFAULT_VISIBILITY = 'public';
const DEFAULT_PRETRAINED_VOCODER = 'hifigan-superres';
interface TtsModelViewResponsePayload {
success: boolean,
model: TtsModel,
}
interface TtsModel {
model_token: string,
title: string,
tts_model_type: string,
maybe_default_pretrained_vocoder: string | null,
text_preprocessing_algorithm: string,
creator_user_token: string,
creator_username: string,
creator_display_name: string,
description_markdown: string,
description_rendered_html: string,
creator_set_visibility: string,
updatable_slug: string,
created_at: string,
updated_at: string,
maybe_moderator_fields: TtsModelModeratorFields | null | undefined,
}
interface TtsModelModeratorFields {
creator_ip_address_creation: string,
creator_ip_address_last_update: string,
mod_deleted_at: string | undefined | null,
user_deleted_at: string | undefined | null,
}
interface Props {
sessionWrapper: SessionWrapper,
enqueueTtsJob: (jobToken: string) => void,
@@ -53,37 +27,38 @@ function TtsModelEditFc(props: Props) {
const history = useHistory();
// Model lookup
const [ttsModel, setTtsModel] = useState<TtsModel|undefined>(undefined);
const [notFoundState, setNotFoundState] = useState<boolean>(false);
// Fields
const [title, setTitle] = useState<string>("");
const [descriptionMarkdown, setDescriptionMarkdown] = useState<string>("");
const [visibility, setVisibility] = useState<string>(DEFAULT_VISIBILITY);
const [defaultPretrainedVocoder, setDefaultPretrainedVocoder] = useState<string>(DEFAULT_PRETRAINED_VOCODER);
const [isFrontPageFeatured, setIsFrontPageFeatured] = useState<boolean>(false);
const [isTwitchFeatured, setIsTwitchFeatured] = useState<boolean>(false);
const getModel = useCallback((token) => {
const api = new ApiConfig();
const endpointUrl = api.viewTtsModel(token);
const getModel = useCallback(async (token) => {
const model = await GetTtsModel(token);
fetch(endpointUrl, {
method: 'GET',
headers: {
'Accept': 'application/json',
},
credentials: 'include',
})
.then(res => res.json())
.then(res => {
const modelsResponse : TtsModelViewResponsePayload = res;
if (!modelsResponse.success) {
return;
if (GetTtsModelIsOk(model)) {
setTtsModel(model);
setTitle(model.title || "")
setDescriptionMarkdown(model.description_markdown || "")
setVisibility(model.creator_set_visibility || DEFAULT_VISIBILITY);
setDefaultPretrainedVocoder(model.maybe_default_pretrained_vocoder || DEFAULT_PRETRAINED_VOCODER);
setIsFrontPageFeatured(model.is_front_page_featured|| false);
setIsTwitchFeatured(model.is_twitch_featured || false);
} else if (GetTtsModelIsErr(model)) {
switch(model) {
case TtsModelLookupError.NotFound:
setNotFoundState(true);
break;
}
setTitle(modelsResponse.model.title || "")
setDescriptionMarkdown(modelsResponse.model.description_markdown || "")
setVisibility(modelsResponse.model.creator_set_visibility || DEFAULT_VISIBILITY);
setDefaultPretrainedVocoder(modelsResponse.model.maybe_default_pretrained_vocoder || DEFAULT_PRETRAINED_VOCODER);
setTtsModel(modelsResponse.model);
})
.catch(e => {});
}
}, []);
@@ -113,8 +88,20 @@ function TtsModelEditFc(props: Props) {
setDefaultPretrainedVocoder((ev.target as HTMLSelectElement).value)
};
const handleIsFrontPageFeaturedChange = (ev: React.FormEvent<HTMLSelectElement>) => {
const value = !((ev.target as HTMLSelectElement).value === 'false');
setIsFrontPageFeatured(value);
};
const handleIsTwitchFeaturedChange = (ev: React.FormEvent<HTMLSelectElement>) => {
const value = !((ev.target as HTMLSelectElement).value === 'false');
setIsTwitchFeatured(value);
};
const modelLink = FrontendUrlConfig.ttsModelPage(token);
const isModerator = props.sessionWrapper.canEditOtherUsersTtsModels();
const handleFormSubmit = (ev: React.FormEvent<HTMLFormElement>) => {
ev.preventDefault();
@@ -131,13 +118,18 @@ function TtsModelEditFc(props: Props) {
const api = new ApiConfig();
const endpointUrl = api.editTtsModel(modelToken);
const request = {
let request : any = {
title: title,
description_markdown: descriptionMarkdown,
creator_set_visibility: visibility || DEFAULT_VISIBILITY,
maybe_default_pretrained_vocoder: defaultPretrainedVocoder || DEFAULT_PRETRAINED_VOCODER,
}
if (isModerator) {
request.is_front_page_featured = isFrontPageFeatured;
request.is_twitch_featured = isTwitchFeatured;
}
fetch(endpointUrl, {
method: 'POST',
headers: {
@@ -162,6 +154,65 @@ function TtsModelEditFc(props: Props) {
return false;
};
if (notFoundState) {
return (
<h1 className="title is-1">Model not found</h1>
);
}
if (!ttsModel) {
return <div />
}
let optionalModeratorFields = <></>;
if (isModerator) {
let isFrontPageFeaturedFormValue = isFrontPageFeatured ? "true" : "false";
let isTwitchFeaturedFormValue = isTwitchFeatured ? "true" : "false";
optionalModeratorFields = (<>
<div className="field">
<label className="label">Is Front Page Featured? (Don't set too many!)</label>
<div className="control has-icons-left">
<div className="select">
<select
name="default_pretrained_vocoder"
onChange={handleIsFrontPageFeaturedChange}
value={isFrontPageFeaturedFormValue}
>
<option value="true">Yes (randomly used as a default)</option>
<option value="false">No</option>
</select>
</div>
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faHome} />
</span>
</div>
</div>
<div className="field">
<label className="label">Is Twitch Featured? (Don't set too many!)</label>
<div className="control has-icons-left">
<div className="select">
<select
name="default_pretrained_vocoder"
onChange={handleIsTwitchFeaturedChange}
value={isTwitchFeaturedFormValue}
>
<option value="true">Yes (randomly used as a default)</option>
<option value="false">No</option>
</select>
</div>
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faTwitch} />
</span>
</div>
</div>
</>);
}
let isDisabled = ttsModel === undefined;
const visibilityIcon = (visibility === 'public') ? <VisibleIconFc /> : <HiddenIconFc />;
@@ -187,6 +238,9 @@ function TtsModelEditFc(props: Props) {
placeholder="Model Title"
value={title}
/>
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faHeadphones} />
</span>
</div>
{/*<p className="help">{invalidReason}</p>*/}
</div>
@@ -233,6 +287,8 @@ function TtsModelEditFc(props: Props) {
</div>
</div>
{optionalModeratorFields}
<br />
<button className="button is-link is-large is-fullwidth">Update</button>
@@ -9,7 +9,7 @@ import { v4 as uuidv4 } from 'uuid';
import { FrontendUrlConfig } from '../../../../common/FrontendUrlConfig';
import { HiddenIconFc } from '../../_icons/HiddenIcon';
import { VisibleIconFc } from '../../_icons/VisibleIcon';
import { GetTtsModel, GetTtsModelIsErr, GetTtsModelIsOk, TtsModel, TtsModelLookupError } from '../../../api/tts/GetTtsModel';
import { GetTtsModel, GetTtsModelIsErr, GetTtsModelIsOk, TtsModel, TtsModelLookupError } from '@storyteller/components/src/api/tts/GetTtsModel';
import { GravatarFc } from '../../_common/GravatarFc';
import { GetTtsModelUseCount } from '../../../api/tts/GetTtsModelUseCount';
import { BackLink } from '../../_common/BackLink';
@@ -226,6 +226,14 @@ function TtsModelViewFc(props: Props) {
<th>User deleted at (UTC)</th>
<td>{ttsModel?.maybe_moderator_fields?.user_deleted_at || "not deleted"}</td>
</tr>
<tr>
<th>Is Front Page Featured?</th>
<td>{ttsModel?.is_front_page_featured ? "yes" : "no"}</td>
</tr>
<tr>
<th>Is Twitch Featured?</th>
<td>{ttsModel?.is_twitch_featured ? "yes" : "no" }</td>
</tr>
</>
);
}