diff --git a/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.scss b/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.scss index a2f59e40b5..dbd3a8bb82 100644 --- a/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.scss +++ b/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.scss @@ -11,8 +11,7 @@ animation: loading 1.5s infinite; border-radius: 0.25rem; width: 100%; - height: 1em; - display: inline-block; + min-height: 1em; } @keyframes loading { diff --git a/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.tsx b/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.tsx index 1ca5a22671..6d3b80cd7f 100644 --- a/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.tsx +++ b/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.tsx @@ -7,7 +7,7 @@ interface SkeletonProps { } export default function Skeleton({ type = "full", rounded }: SkeletonProps) { - const skeletonClass = `skeleton ${type} ${rounded && "rounded"}`; + const skeletonClass = `skeleton ${type} ${rounded ? "rounded" : ""}`; return
; } diff --git a/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerMainPage.tsx b/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerMainPage.tsx index 007662764d..81acef19f5 100644 --- a/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerMainPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerMainPage.tsx @@ -17,10 +17,14 @@ import { // InferenceJob, } from "@storyteller/components/src/jobs/InferenceJob"; -function VoiceDesignerMainPage({ inferenceJobsByCategory }: { inferenceJobsByCategory: any }) { +function VoiceDesignerMainPage({ + inferenceJobsByCategory, +}: { + inferenceJobsByCategory: any; +}) { const { pathname } = useLocation(); const { t } = useLocalize("FaceAnimator"); - const { datasets, voices } = useVoiceRequests({ + const { datasets, voices, isFetching } = useVoiceRequests({ requestDatasets: true, requestVoices: true, }); @@ -135,13 +139,14 @@ function VoiceDesignerMainPage({ inferenceJobsByCategory }: { inferenceJobsByCat }; }); - const statusTxt = (status: number, config: any) => [ - "Voice pending...", - "Voice in progress", - "Voice failed", - "Voice dead", - "Voice created successfully" - ][status]; + const statusTxt = (status: number, config: any) => + [ + "Voice pending...", + "Voice in progress", + "Voice failed", + "Voice dead", + "Voice created successfully", + ][status]; const button = { label: `Create new voice`, @@ -160,11 +165,15 @@ function VoiceDesignerMainPage({ inferenceJobsByCategory }: { inferenceJobsByCat panel={false} imageUrl="/images/header/voice-designer.png" /> - +
- +
diff --git a/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/NewList.tsx b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/NewList.tsx index 6a69af4327..e3dfeb87dd 100644 --- a/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/NewList.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/NewList.tsx @@ -4,9 +4,11 @@ import { faMicrophone, faPlus } from "@fortawesome/pro-solid-svg-icons"; import "./ListItems/ListItems.scss"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import Skeleton from "components/common/Skeleton"; interface ListItemsProps { data: any[]; + isLoading: boolean; } interface ListItem { @@ -79,7 +81,7 @@ const ItemRow = ({ ); }; -export default function NewList({ data }: ListItemsProps) { +export default function NewList({ data, isLoading }: ListItemsProps) { const DataPlaceholder = () => (
You haven't created any voices.
@@ -91,6 +93,25 @@ export default function NewList({ data }: ListItemsProps) { />
); + + if (isLoading) { + const loaderView = ( +
+

+ +

+
+ ); + + return ( +
+ {[...Array(2)].map((_, i) => ( + {loaderView} + ))} +
+ ); + } + return data.length ? (
{data.map((item, key) => ( diff --git a/packages/fakeyou.com/src/v2/view/pages/voice_designer/useVoiceRequests.tsx b/packages/fakeyou.com/src/v2/view/pages/voice_designer/useVoiceRequests.tsx index b926f90417..02c8a0451c 100644 --- a/packages/fakeyou.com/src/v2/view/pages/voice_designer/useVoiceRequests.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/voice_designer/useVoiceRequests.tsx @@ -3,13 +3,21 @@ import { useEffect, useState } from "react"; // voice imports import { GetVoice } from "@storyteller/components/src/api/voice_designer/voices/GetVoice"; -import { CreateVoice, CreateVoiceRequest, CreateVoiceResponse } from "@storyteller/components/src/api/voice_designer/voices/CreateVoice"; -import { ListVoicesByUser, Voice } from "@storyteller/components/src/api/voice_designer/voices/ListVoicesByUser"; -import { - DeleteVoice, +import { + CreateVoice, + CreateVoiceRequest, + CreateVoiceResponse, +} from "@storyteller/components/src/api/voice_designer/voices/CreateVoice"; +import { + ListVoicesByUser, + Voice, +} from "@storyteller/components/src/api/voice_designer/voices/ListVoicesByUser"; +import { + DeleteVoice, // DeleteVoiceRequest, use me somewhere pls - DeleteVoiceResponse } from "@storyteller/components/src/api/voice_designer/voices/DeleteVoice"; - import { UpdateVoice } from "@storyteller/components/src/api/voice_designer/voices/UpdateVoice"; + DeleteVoiceResponse, +} from "@storyteller/components/src/api/voice_designer/voices/DeleteVoice"; +import { UpdateVoice } from "@storyteller/components/src/api/voice_designer/voices/UpdateVoice"; // dataset imports @@ -18,69 +26,102 @@ import { ListDatasetsByUser, Dataset, } from "@storyteller/components/src/api/voice_designer/voice_datasets/ListDatasetsByUser"; -import { DeleteDataset, DeleteDatasetResponse } from "@storyteller/components/src/api/voice_designer/voice_datasets/DeleteDataset"; -import { CreateDataset, CreateDatasetRequest, CreateDatasetResponse } from "@storyteller/components/src/api/voice_designer/voice_datasets/CreateDataset"; -import { UpdateDataset, UpdateDatasetRequest, UpdateDatasetResponse } from "@storyteller/components/src/api/voice_designer/voice_datasets/UpdateDataset"; +import { + DeleteDataset, + DeleteDatasetResponse, +} from "@storyteller/components/src/api/voice_designer/voice_datasets/DeleteDataset"; +import { + CreateDataset, + CreateDatasetRequest, + CreateDatasetResponse, +} from "@storyteller/components/src/api/voice_designer/voice_datasets/CreateDataset"; +import { + UpdateDataset, + UpdateDatasetRequest, + UpdateDatasetResponse, +} from "@storyteller/components/src/api/voice_designer/voice_datasets/UpdateDataset"; import { EnqueueTts } from "@storyteller/components/src/api/voice_designer/inference/EnqueueTts"; import { useSession } from "hooks"; -export default function useVoiceRequests({ requestDatasets = false, requestVoices = false }){ +export default function useVoiceRequests({ + requestDatasets = false, + requestVoices = false, +}) { // this state will be provided as params, triggering the appropriate api call if present const [datasets, datasetsSet] = useState([]); const [voices, voicesSet] = useState([]); // this state stays here, fetched states are not success, merely an attempt was made. Each list fetch sets to true. Set to false to retry const [fetchDatasets, fetchDatasetsSet] = useState(requestDatasets); - const [fetchVoices,fetchVoicesSet] = useState(requestVoices); + const [fetchVoices, fetchVoicesSet] = useState(requestVoices); + const [isFetchingVoices, setIsFetchingVoices] = useState(requestVoices); + const [isFetchingDatasets, setIsFetchingDatasets] = useState(requestDatasets); const { user } = useSession(); // const [timestamp, timestampSet] = useState(Date.now()); - const refreshData = () => { fetchDatasetsSet(true); fetchVoicesSet(true); }; // later we can do refresh per list + const refreshData = () => { + fetchDatasetsSet(true); + fetchVoicesSet(true); + }; // later we can do refresh per list - const createDataset = (urlRouteArgs: string, request: CreateDatasetRequest): Promise => - CreateDataset(urlRouteArgs, request).then(res => { + const createDataset = ( + urlRouteArgs: string, + request: CreateDatasetRequest + ): Promise => + CreateDataset(urlRouteArgs, request).then((res) => { // refreshData(); // not needed because creating a dataset navigates to the upload page with no lists return res; }); + const createVoice = ( + urlRouteArgs: string, + request: CreateVoiceRequest + ): Promise => + CreateVoice(urlRouteArgs, request).then((res) => { + // refreshData(); // not needed because creating a voice navigates to a new page with a new instance of useVoiceRequest + return res; + }); - const createVoice = (urlRouteArgs: string, request: CreateVoiceRequest): Promise => CreateVoice(urlRouteArgs, request).then(res => { - // refreshData(); // not needed because creating a voice navigates to a new page with a new instance of useVoiceRequest - return res; - }); + const deleteVoice = (voiceToken: string): Promise => + DeleteVoice(voiceToken, { + set_delete: true, + as_mod: false, + }).then((res) => { + refreshData(); + return res; + // console.log("🏧",res); + }); - const deleteVoice = (voiceToken: string): Promise => DeleteVoice(voiceToken, { - set_delete: true, - as_mod: false - }).then(res => { - refreshData(); - return res; - // console.log("🏧",res); - }); - - const deleteDataset = (voiceToken: string): Promise => DeleteDataset(voiceToken, { - set_delete: true, - as_mod: false - }).then(res => { - refreshData(); - return res; - // console.log("🏧",res); - }); + const deleteDataset = (voiceToken: string): Promise => + DeleteDataset(voiceToken, { + set_delete: true, + as_mod: false, + }).then((res) => { + refreshData(); + return res; + // console.log("🏧",res); + }); const datasetByToken = (datasetToken?: string) => datasets.filter( ({ dataset_token }, i) => datasetToken === dataset_token )[0]; - const editDataSet = (datasetToken: string, request: UpdateDatasetRequest): Promise => { + const editDataSet = ( + datasetToken: string, + request: UpdateDatasetRequest + ): Promise => { // console.log("🍄", datasetToken); - return UpdateDataset(datasetToken, request).then(res => { + return UpdateDataset(datasetToken, request).then((res) => { refreshData(); return res; }); }; - const listDatasets = () => { fetchDatasetsSet(true); return datasets; } + const listDatasets = () => { + fetchDatasetsSet(true); + return datasets; + }; const languages = [ { value: "en", label: "English" }, @@ -93,24 +134,29 @@ export default function useVoiceRequests({ requestDatasets = false, requestVoice { label: "Hidden", value: "hidden" }, ]; - useEffect(() => { + useEffect(() => { if (user && user.username) { if (fetchDatasets) { + setIsFetchingDatasets(true); fetchDatasetsSet(false); - ListDatasetsByUser(user.username,{}).then(res => { + ListDatasetsByUser(user.username, {}).then((res) => { if (res.datasets) datasetsSet(res.datasets); + setIsFetchingDatasets(false); }); } if (fetchVoices) { + setIsFetchingVoices(true); fetchVoicesSet(false); - ListVoicesByUser(user.username,{}).then(res => { + ListVoicesByUser(user.username, {}).then((res) => { if (res.voices) voicesSet(res.voices); + setIsFetchingVoices(false); }); } } }, [user, fetchDatasets, fetchVoices]); return { + isFetching: isFetchingVoices || isFetchingDatasets, datasets: { byToken: datasetByToken, create: createDataset, @@ -119,7 +165,7 @@ export default function useVoiceRequests({ requestDatasets = false, requestVoice get: GetDataset, list: datasets, listDatasets, - refresh: refreshData + refresh: refreshData, }, inference: { enqueue: EnqueueTts, @@ -136,9 +182,9 @@ export default function useVoiceRequests({ requestDatasets = false, requestVoice }, inputCtrl: (todo: any) => - ({ target }: { target: any }) => { - console.log("🌿", target); - todo(target.value); - }, + ({ target }: { target: any }) => { + console.log("🌿", target); + todo(target.value); + }, }; }