mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 17:38:10 +00:00
Move API call to common package
This commit is contained in:
1 parent
ee0d4c883d
commit
e42a1a5a73
5 files changed
+166
-121
No files matched your search
File renamed without changes.
@@ -38,7 +38,7 @@ import {
|
||||
GetRetrievalJobStatus,
|
||||
GetRetrievalJobStatusIsOk,
|
||||
} from "@storyteller/components/src/api/retrieval/GetRetrievalJobStatus";
|
||||
import { GetComputedTtsCategoryAssignmentsSuccessResponse } from "./v2/api/category/GetComputedTtsCategoryAssignments";
|
||||
import { GetComputedTtsCategoryAssignmentsSuccessResponse } from "@storyteller/components/src/api/category/GetComputedTtsCategoryAssignments";
|
||||
|
||||
i18n
|
||||
.use(initReactI18next) // passes i18n down to react-i18next
|
||||
@@ -75,7 +75,9 @@ interface Props {
|
||||
setAllTtsModels: (allTtsModels: TtsModelListItem[]) => void;
|
||||
|
||||
computedTtsCategoryAssignments?: GetComputedTtsCategoryAssignmentsSuccessResponse;
|
||||
setComputedTtsCategoryAssignments: (categoryAssignments: GetComputedTtsCategoryAssignmentsSuccessResponse) => void;
|
||||
setComputedTtsCategoryAssignments: (
|
||||
categoryAssignments: GetComputedTtsCategoryAssignmentsSuccessResponse
|
||||
) => void;
|
||||
|
||||
allTtsCategoriesByTokenMap: Map<string, TtsCategoryType>;
|
||||
allTtsModelsByTokenMap: Map<string, TtsModelListItem>;
|
||||
@@ -708,8 +710,12 @@ class App extends React.Component<Props, State> {
|
||||
setTtsModels={this.props.setAllTtsModels}
|
||||
allTtsCategories={this.props.allTtsCategories}
|
||||
setAllTtsCategories={this.props.setAllTtsCategories}
|
||||
computedTtsCategoryAssignments={this.props.computedTtsCategoryAssignments}
|
||||
setComputedTtsCategoryAssignments={this.props.setComputedTtsCategoryAssignments}
|
||||
computedTtsCategoryAssignments={
|
||||
this.props.computedTtsCategoryAssignments
|
||||
}
|
||||
setComputedTtsCategoryAssignments={
|
||||
this.props.setComputedTtsCategoryAssignments
|
||||
}
|
||||
allTtsCategoriesByTokenMap={
|
||||
this.props.allTtsCategoriesByTokenMap
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { TtsCategory } from './v2/api/category/ListTtsCategories';
|
||||
import { TtsModelListItem } from '@storyteller/components/src/api/tts/ListTtsModels';
|
||||
import { App } from './App';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { GetComputedTtsCategoryAssignmentsSuccessResponse } from './v2/api/category/GetComputedTtsCategoryAssignments';
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { TtsCategory } from "./v2/api/category/ListTtsCategories";
|
||||
import { TtsModelListItem } from "@storyteller/components/src/api/tts/ListTtsModels";
|
||||
import { App } from "./App";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { GetComputedTtsCategoryAssignmentsSuccessResponse } from "@storyteller/components/src/api/category/GetComputedTtsCategoryAssignments";
|
||||
|
||||
interface Props {
|
||||
// Certan browsers (iPhone) have pitiful support for drawing APIs. Worse yet,
|
||||
// they seem to lose the "touch event sandboxing" that allows for audio to be
|
||||
// they seem to lose the "touch event sandboxing" that allows for audio to be
|
||||
// played after user interaction if the XHRs delivering the audio don't do so
|
||||
// as actual audio mimetypes. (Decoding from base64 and trying to play fails.)
|
||||
enableSpectrograms: boolean,
|
||||
enableSpectrograms: boolean;
|
||||
|
||||
// Whether or not to inform users that the name of the website has changed.
|
||||
flashVocodesNotice: boolean,
|
||||
flashVocodesNotice: boolean;
|
||||
}
|
||||
|
||||
// Special synthetic categories created on the frontend.
|
||||
@@ -26,7 +26,11 @@ export class SyntheticCategory {
|
||||
|
||||
ttsModels: Set<TtsModelListItem>;
|
||||
|
||||
constructor(name: string, token?: string, maybe_super_category_token?: string) {
|
||||
constructor(
|
||||
name: string,
|
||||
token?: string,
|
||||
maybe_super_category_token?: string
|
||||
) {
|
||||
this.name = name;
|
||||
this.name_for_dropdown = name;
|
||||
this.category_token = !!token ? token : `syn:${uuidv4()}`;
|
||||
@@ -35,146 +39,163 @@ export class SyntheticCategory {
|
||||
}
|
||||
}
|
||||
|
||||
export type TtsCategoryType = TtsCategory|SyntheticCategory;
|
||||
export type TtsCategoryType = TtsCategory | SyntheticCategory;
|
||||
|
||||
export function AppWrapper(props: Props) {
|
||||
// Caches of all objects queried
|
||||
// These may be triggered by a different page than the user initially lands on.
|
||||
const [allTtsCategories, setAllTtsCategories] = useState<TtsCategoryType[]>([]);
|
||||
const [allTtsCategories, setAllTtsCategories] = useState<TtsCategoryType[]>(
|
||||
[]
|
||||
);
|
||||
const [allTtsModels, setAllTtsModels] = useState<TtsModelListItem[]>([]);
|
||||
const [computedTtsCategoryAssignments, setComputedTtsCategoryAssignments] = useState<GetComputedTtsCategoryAssignmentsSuccessResponse|undefined>(undefined);
|
||||
const [computedTtsCategoryAssignments, setComputedTtsCategoryAssignments] =
|
||||
useState<GetComputedTtsCategoryAssignmentsSuccessResponse | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
// Precalculated maps for lookup by primary key
|
||||
const [allCategoriesByTokenMap, setAllCategoriesByTokenMap] = useState<Map<string,TtsCategoryType>>(new Map());
|
||||
const [allTtsModelsByTokenMap, setAllTtsModelsByTokenMap] = useState<Map<string,TtsModelListItem>>(new Map());
|
||||
const [allCategoriesByTokenMap, setAllCategoriesByTokenMap] = useState<
|
||||
Map<string, TtsCategoryType>
|
||||
>(new Map());
|
||||
const [allTtsModelsByTokenMap, setAllTtsModelsByTokenMap] = useState<
|
||||
Map<string, TtsModelListItem>
|
||||
>(new Map());
|
||||
|
||||
// Precalculated map for lookup by foreign key
|
||||
// A TTS voice is attached to every category up the tree from the leaf.
|
||||
// We recursively build this, 1) to ensure we can access a voice at all levels
|
||||
// We recursively build this, 1) to ensure we can access a voice at all levels
|
||||
// of specificity, and 2) to prune empty categories.
|
||||
const [ttsModelsByCategoryToken, setTtsModelsByCategoryToken] = useState<Map<string,Set<TtsModelListItem>>>(new Map());
|
||||
const [ttsModelsByCategoryToken, setTtsModelsByCategoryToken] = useState<
|
||||
Map<string, Set<TtsModelListItem>>
|
||||
>(new Map());
|
||||
|
||||
// Calculated dropdown options for every level of categories.
|
||||
// Outer array has length of at least one, one element per <select>
|
||||
// Inner array contains the categories in each level.
|
||||
// Structure: [dropdownLevel][categories]
|
||||
const [dropdownCategories, setDropdownCategories] = useState<TtsCategoryType[][]>([]);
|
||||
const [dropdownCategories, setDropdownCategories] = useState<
|
||||
TtsCategoryType[][]
|
||||
>([]);
|
||||
|
||||
// User selections.
|
||||
// Every category in the heirarchy that has been selected by the user.
|
||||
// Empty list if none are selected.
|
||||
// Structure: [firstSelected, secondSelected...]
|
||||
const [selectedCategories, setSelectedCategories] = useState<TtsCategoryType[]>([]);
|
||||
const [selectedCategories, setSelectedCategories] = useState<
|
||||
TtsCategoryType[]
|
||||
>([]);
|
||||
|
||||
// User selections.
|
||||
const [maybeSelectedTtsModel, setMaybeSelectedTtsModel] = useState<TtsModelListItem|undefined>(undefined);
|
||||
const [maybeSelectedTtsModel, setMaybeSelectedTtsModel] = useState<
|
||||
TtsModelListItem | undefined
|
||||
>(undefined);
|
||||
|
||||
// TODO: Handle empty category list
|
||||
useEffect(() => {
|
||||
// Category lookup by token
|
||||
let categoriesByTokenMap = new Map();
|
||||
allTtsCategories.forEach(category => {
|
||||
allTtsCategories.forEach((category) => {
|
||||
categoriesByTokenMap.set(category.category_token, category);
|
||||
})
|
||||
});
|
||||
setAllCategoriesByTokenMap(categoriesByTokenMap);
|
||||
|
||||
// TTS model lookup by token
|
||||
let ttsModelsByTokenMap = new Map();
|
||||
allTtsModels.forEach(model => {
|
||||
allTtsModels.forEach((model) => {
|
||||
ttsModelsByTokenMap.set(model.model_token, model);
|
||||
})
|
||||
});
|
||||
setAllTtsModelsByTokenMap(ttsModelsByTokenMap);
|
||||
|
||||
// Initial dropdown state
|
||||
const rootCategories = allTtsCategories.filter(category => {
|
||||
const rootCategories = allTtsCategories.filter((category) => {
|
||||
return !category.maybe_super_category_token;
|
||||
});
|
||||
const rootLevel = [rootCategories];
|
||||
setDropdownCategories(rootLevel);
|
||||
|
||||
/// NB: This was the really expensive cubic time++ aglorithm to recursively calculate nested category assignments.
|
||||
/// This has since been ported to the server and will no longer be computed here. We're preserving this for posterity.
|
||||
///
|
||||
/// // Voice lookup table
|
||||
/// let categoriesToTtsModelTokens = new Map();
|
||||
/// // Category ancestry memoization
|
||||
/// let categoryTokenToAllAncestorTokens : Map<string, Set<string>> = new Map();
|
||||
///
|
||||
/// // N * M with memoization should't be too bad here.
|
||||
/// // Also note that the models should be lexographically sorted by name.
|
||||
/// allTtsModels.forEach(ttsModel => {
|
||||
/// if (ttsModel.category_tokens.length === 0) {
|
||||
/// // TODO: Attach to "uncategorized" special category
|
||||
/// return;
|
||||
/// }
|
||||
/// ttsModel.category_tokens.forEach(categoryToken => {
|
||||
/// let ancestors = categoryTokenToAllAncestorTokens.get(categoryToken);
|
||||
/// if (ancestors === undefined) {
|
||||
/// ancestors = findAllAncestorTokens(categoryToken, categoriesByTokenMap);
|
||||
/// categoryTokenToAllAncestorTokens.set(categoryToken, ancestors);
|
||||
/// }
|
||||
/// ancestors.forEach(categoryToken => {
|
||||
/// let models : Set<TtsModelListItem> = categoriesToTtsModelTokens.get(categoryToken);
|
||||
/// if (models === undefined) {
|
||||
/// models = new Set();
|
||||
/// categoriesToTtsModelTokens.set(categoryToken, models);
|
||||
/// }
|
||||
/// models.add(ttsModel);
|
||||
/// })
|
||||
/// });
|
||||
/// });
|
||||
/// setTtsModelsByCategoryToken(categoriesToTtsModelTokens);
|
||||
/// NB: This was the really expensive cubic time++ aglorithm to recursively calculate nested category assignments.
|
||||
/// This has since been ported to the server and will no longer be computed here. We're preserving this for posterity.
|
||||
///
|
||||
/// // Voice lookup table
|
||||
/// let categoriesToTtsModelTokens = new Map();
|
||||
/// // Category ancestry memoization
|
||||
/// let categoryTokenToAllAncestorTokens : Map<string, Set<string>> = new Map();
|
||||
///
|
||||
/// // N * M with memoization should't be too bad here.
|
||||
/// // Also note that the models should be lexographically sorted by name.
|
||||
/// allTtsModels.forEach(ttsModel => {
|
||||
/// if (ttsModel.category_tokens.length === 0) {
|
||||
/// // TODO: Attach to "uncategorized" special category
|
||||
/// return;
|
||||
/// }
|
||||
/// ttsModel.category_tokens.forEach(categoryToken => {
|
||||
/// let ancestors = categoryTokenToAllAncestorTokens.get(categoryToken);
|
||||
/// if (ancestors === undefined) {
|
||||
/// ancestors = findAllAncestorTokens(categoryToken, categoriesByTokenMap);
|
||||
/// categoryTokenToAllAncestorTokens.set(categoryToken, ancestors);
|
||||
/// }
|
||||
/// ancestors.forEach(categoryToken => {
|
||||
/// let models : Set<TtsModelListItem> = categoriesToTtsModelTokens.get(categoryToken);
|
||||
/// if (models === undefined) {
|
||||
/// models = new Set();
|
||||
/// categoriesToTtsModelTokens.set(categoryToken, models);
|
||||
/// }
|
||||
/// models.add(ttsModel);
|
||||
/// })
|
||||
/// });
|
||||
/// });
|
||||
/// setTtsModelsByCategoryToken(categoriesToTtsModelTokens);
|
||||
|
||||
const nestedCategoryTokenToModelTokensMap : Map<string, Set<string>> = computedTtsCategoryAssignments?.category_token_to_tts_model_tokens.recursive || new Map();
|
||||
const nestedCategoryTokenToModelTokensMap: Map<
|
||||
string,
|
||||
Set<string>
|
||||
> = computedTtsCategoryAssignments?.category_token_to_tts_model_tokens
|
||||
.recursive || new Map();
|
||||
|
||||
let categoriesToTtsModelTokens = new Map();
|
||||
|
||||
nestedCategoryTokenToModelTokensMap.forEach((ttsModelTokens, categoryToken) => {
|
||||
ttsModelTokens.forEach(ttsModelToken => {
|
||||
let ttsModel = ttsModelsByTokenMap.get(ttsModelToken);
|
||||
if (ttsModel === undefined) {
|
||||
return;
|
||||
}
|
||||
let models : Set<TtsModelListItem> = categoriesToTtsModelTokens.get(categoryToken);
|
||||
if (models === undefined) {
|
||||
models = new Set();
|
||||
categoriesToTtsModelTokens.set(categoryToken, models);
|
||||
}
|
||||
models.add(ttsModel);
|
||||
})
|
||||
})
|
||||
nestedCategoryTokenToModelTokensMap.forEach(
|
||||
(ttsModelTokens, categoryToken) => {
|
||||
ttsModelTokens.forEach((ttsModelToken) => {
|
||||
let ttsModel = ttsModelsByTokenMap.get(ttsModelToken);
|
||||
if (ttsModel === undefined) {
|
||||
return;
|
||||
}
|
||||
let models: Set<TtsModelListItem> =
|
||||
categoriesToTtsModelTokens.get(categoryToken);
|
||||
if (models === undefined) {
|
||||
models = new Set();
|
||||
categoriesToTtsModelTokens.set(categoryToken, models);
|
||||
}
|
||||
models.add(ttsModel);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
setTtsModelsByCategoryToken(categoriesToTtsModelTokens);
|
||||
|
||||
}, [allTtsCategories, allTtsModels, computedTtsCategoryAssignments]);
|
||||
|
||||
return (
|
||||
<App
|
||||
enableSpectrograms={props.enableSpectrograms}
|
||||
flashVocodesNotice={props.flashVocodesNotice}
|
||||
|
||||
allTtsCategories={allTtsCategories}
|
||||
setAllTtsCategories={setAllTtsCategories}
|
||||
|
||||
allTtsModels={allTtsModels}
|
||||
setAllTtsModels={setAllTtsModels}
|
||||
|
||||
computedTtsCategoryAssignments={computedTtsCategoryAssignments}
|
||||
setComputedTtsCategoryAssignments={setComputedTtsCategoryAssignments}
|
||||
|
||||
allTtsCategoriesByTokenMap={allCategoriesByTokenMap}
|
||||
allTtsModelsByTokenMap={allTtsModelsByTokenMap}
|
||||
ttsModelsByCategoryToken={ttsModelsByCategoryToken}
|
||||
|
||||
dropdownCategories={dropdownCategories}
|
||||
setDropdownCategories={setDropdownCategories}
|
||||
selectedCategories={selectedCategories}
|
||||
setSelectedCategories={setSelectedCategories}
|
||||
|
||||
maybeSelectedTtsModel={maybeSelectedTtsModel}
|
||||
setMaybeSelectedTtsModel={setMaybeSelectedTtsModel}
|
||||
/>
|
||||
)
|
||||
<App
|
||||
enableSpectrograms={props.enableSpectrograms}
|
||||
flashVocodesNotice={props.flashVocodesNotice}
|
||||
allTtsCategories={allTtsCategories}
|
||||
setAllTtsCategories={setAllTtsCategories}
|
||||
allTtsModels={allTtsModels}
|
||||
setAllTtsModels={setAllTtsModels}
|
||||
computedTtsCategoryAssignments={computedTtsCategoryAssignments}
|
||||
setComputedTtsCategoryAssignments={setComputedTtsCategoryAssignments}
|
||||
allTtsCategoriesByTokenMap={allCategoriesByTokenMap}
|
||||
allTtsModelsByTokenMap={allTtsModelsByTokenMap}
|
||||
ttsModelsByCategoryToken={ttsModelsByCategoryToken}
|
||||
dropdownCategories={dropdownCategories}
|
||||
setDropdownCategories={setDropdownCategories}
|
||||
selectedCategories={selectedCategories}
|
||||
setSelectedCategories={setSelectedCategories}
|
||||
maybeSelectedTtsModel={maybeSelectedTtsModel}
|
||||
setMaybeSelectedTtsModel={setMaybeSelectedTtsModel}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/// NB: This was the really expensive cubic time++ aglorithm to recursively calculate nested category assignments.
|
||||
@@ -194,7 +215,7 @@ export function AppWrapper(props: Props) {
|
||||
/// return [categoryToken];
|
||||
/// }
|
||||
/// return [
|
||||
/// ...recursiveFindAllAncestorTokens(category.maybe_super_category_token, allCategoriesByTokenMap),
|
||||
/// ...recursiveFindAllAncestorTokens(category.maybe_super_category_token, allCategoriesByTokenMap),
|
||||
/// categoryToken,
|
||||
/// ];
|
||||
/// }
|
||||
@@ -62,7 +62,7 @@ import { CheckoutSuccessPage } from "./premium/CheckoutSuccessPage";
|
||||
import { CheckoutCancelPage } from "./premium/CheckoutCancelPage";
|
||||
import { PortalSuccessPage } from "./premium/PortalSuccessPage";
|
||||
import { PrivacyPage } from "./about/privacy_page/PrivacyPage";
|
||||
import { GetComputedTtsCategoryAssignmentsSuccessResponse } from "../api/category/GetComputedTtsCategoryAssignments";
|
||||
import { GetComputedTtsCategoryAssignmentsSuccessResponse } from "@storyteller/components/src/api/category/GetComputedTtsCategoryAssignments";
|
||||
//import { LandingPage } from "./landing/LandingPage";
|
||||
//import { VcModelListPage } from "./vc/vc_model_list/VcModelListPage";
|
||||
|
||||
@@ -114,9 +114,11 @@ interface Props {
|
||||
|
||||
allTtsCategories: TtsCategoryType[];
|
||||
setAllTtsCategories: (allTtsCategories: TtsCategoryType[]) => void;
|
||||
|
||||
|
||||
computedTtsCategoryAssignments?: GetComputedTtsCategoryAssignmentsSuccessResponse;
|
||||
setComputedTtsCategoryAssignments: (categoryAssignments: GetComputedTtsCategoryAssignmentsSuccessResponse) => void;
|
||||
setComputedTtsCategoryAssignments: (
|
||||
categoryAssignments: GetComputedTtsCategoryAssignmentsSuccessResponse
|
||||
) => void;
|
||||
|
||||
allTtsCategoriesByTokenMap: Map<string, TtsCategoryType>;
|
||||
allTtsModelsByTokenMap: Map<string, TtsModelListItem>;
|
||||
@@ -478,8 +480,12 @@ class PageContainer extends React.Component<Props, State> {
|
||||
allTtsCategoriesByTokenMap={
|
||||
this.props.allTtsCategoriesByTokenMap
|
||||
}
|
||||
computedTtsCategoryAssignments={this.props.computedTtsCategoryAssignments}
|
||||
setComputedTtsCategoryAssignments={this.props.setComputedTtsCategoryAssignments}
|
||||
computedTtsCategoryAssignments={
|
||||
this.props.computedTtsCategoryAssignments
|
||||
}
|
||||
setComputedTtsCategoryAssignments={
|
||||
this.props.setComputedTtsCategoryAssignments
|
||||
}
|
||||
allTtsModelsByTokenMap={this.props.allTtsModelsByTokenMap}
|
||||
ttsModelsByCategoryToken={this.props.ttsModelsByCategoryToken}
|
||||
dropdownCategories={this.props.dropdownCategories}
|
||||
|
||||
@@ -49,7 +49,12 @@ import { container, panel } from "../../../../data/animation";
|
||||
import { SessionSubscriptionsWrapper } from "@storyteller/components/src/session/SessionSubscriptionsWrapper";
|
||||
import { TtsPageHero } from "./TtsPageHero";
|
||||
import { Analytics } from "../../../../common/Analytics";
|
||||
import { GetComputedTtsCategoryAssignments, GetComputedTtsCategoryAssignmentsIsError, GetComputedTtsCategoryAssignmentsIsOk, GetComputedTtsCategoryAssignmentsSuccessResponse } from "../../../api/category/GetComputedTtsCategoryAssignments";
|
||||
import {
|
||||
GetComputedTtsCategoryAssignments,
|
||||
GetComputedTtsCategoryAssignmentsIsError,
|
||||
GetComputedTtsCategoryAssignmentsIsOk,
|
||||
GetComputedTtsCategoryAssignmentsSuccessResponse,
|
||||
} from "@storyteller/components/src/api/category/GetComputedTtsCategoryAssignments";
|
||||
|
||||
export interface EnqueueJobResponsePayload {
|
||||
success: boolean;
|
||||
@@ -92,7 +97,9 @@ interface Props {
|
||||
setAllTtsCategories: (allTtsCategories: TtsCategoryType[]) => void;
|
||||
|
||||
computedTtsCategoryAssignments?: GetComputedTtsCategoryAssignmentsSuccessResponse;
|
||||
setComputedTtsCategoryAssignments: (categoryAssignments: GetComputedTtsCategoryAssignmentsSuccessResponse) => void;
|
||||
setComputedTtsCategoryAssignments: (
|
||||
categoryAssignments: GetComputedTtsCategoryAssignmentsSuccessResponse
|
||||
) => void;
|
||||
|
||||
allTtsCategoriesByTokenMap: Map<string, TtsCategoryType>;
|
||||
allTtsModelsByTokenMap: Map<string, TtsModelListItem>;
|
||||
@@ -125,9 +132,10 @@ function TtsModelListPage(props: Props) {
|
||||
|
||||
const ttsModelsLoaded = ttsModels.length > 0;
|
||||
const ttsCategoriesLoaded = allTtsCategories.length > 0;
|
||||
const computedTtsCategoryAssignmentsLoaded =
|
||||
computedTtsCategoryAssignments !== undefined &&
|
||||
computedTtsCategoryAssignments.category_token_to_tts_model_tokens.recursive.size > 0;
|
||||
const computedTtsCategoryAssignmentsLoaded =
|
||||
computedTtsCategoryAssignments !== undefined &&
|
||||
computedTtsCategoryAssignments.category_token_to_tts_model_tokens.recursive
|
||||
.size > 0;
|
||||
|
||||
const listModels = useCallback(async () => {
|
||||
if (ttsModelsLoaded) {
|
||||
@@ -186,7 +194,7 @@ function TtsModelListPage(props: Props) {
|
||||
useEffect(() => {
|
||||
listModels();
|
||||
listTtsCategories();
|
||||
getComputedAssignments()
|
||||
getComputedAssignments();
|
||||
}, [listModels, listTtsCategories, getComputedAssignments]);
|
||||
|
||||
const handleChangeText = (ev: React.FormEvent<HTMLTextAreaElement>) => {
|
||||
@@ -243,11 +251,13 @@ function TtsModelListPage(props: Props) {
|
||||
let modelName = props.maybeSelectedTtsModel.title;
|
||||
let userName = props.maybeSelectedTtsModel.creator_display_name;
|
||||
directViewLink = (
|
||||
<Link
|
||||
to={modelLink}
|
||||
onClick={() => { Analytics.ttsClickModelDetailsLink() } }
|
||||
className="py-2"
|
||||
>
|
||||
<Link
|
||||
to={modelLink}
|
||||
onClick={() => {
|
||||
Analytics.ttsClickModelDetailsLink();
|
||||
}}
|
||||
className="py-2"
|
||||
>
|
||||
<Trans i18nKey="tts.TtsModelListPage.form.modelSeeMoreLink">
|
||||
See more details about the "
|
||||
<span className="fw-semibold">{{ modelName }}</span>" model by
|
||||
@@ -402,7 +412,9 @@ function TtsModelListPage(props: Props) {
|
||||
|
||||
<div className="text-input">
|
||||
<textarea
|
||||
onClick={() => { Analytics.ttsClickTextInputBox() } }
|
||||
onClick={() => {
|
||||
Analytics.ttsClickTextInputBox();
|
||||
}}
|
||||
onChange={handleChangeText}
|
||||
className="form-control fs-5"
|
||||
style={{ minHeight: "200px" }}
|
||||
|
||||
Reference in new issue
Block a user