mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 01:38:44 +00:00
Merge pull request #363 from storytold/olivicmic-fy-voice-designer-consume-api-react
added config object to useVoiceRequests to activate dataset/voice list fetches
This commit is contained in:
9 files changed
+113
-17
No files matched your search
@@ -0,0 +1,89 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
// import { a } from '@react-spring/web';
|
||||
import {
|
||||
GetPendingTtsJobCount,
|
||||
GetPendingTtsJobCountIsOk,
|
||||
GetPendingTtsJobCountSuccessResponse,
|
||||
} from "@storyteller/components/src/api/tts/GetPendingTtsJobCount";
|
||||
// import { springs } from "resources";
|
||||
import { useInferenceJobs } from "hooks";
|
||||
import { Button } from 'components/common';
|
||||
import { Analytics } from "common/Analytics";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faChevronRight, faHourglass1, faRemove, faTrophy, faWarning } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
const DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS = 15000;
|
||||
|
||||
export default function InferenceJobsList({ t }: { t: any }) {
|
||||
const { inferenceJobs = [] } = useInferenceJobs({ type: 0 });
|
||||
const [pending, pendingSet] = useState<GetPendingTtsJobCountSuccessResponse>({
|
||||
success: true,
|
||||
pending_job_count: 0,
|
||||
cache_time: new Date(0), // NB: Epoch is used for vector clock's initial state
|
||||
refresh_interval_millis: DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS,
|
||||
});
|
||||
const statusIcons = [faHourglass1,faHourglass1,faWarning,faRemove,faTrophy];
|
||||
const statusTxt = (which: number, config = {}) => ["animationPending","animationInProgress","animationFailed","animationDead","animationSuccess"].map((str,i) => t(`status.${str}`,config))[which];
|
||||
|
||||
const processFail = (fail = "") => {
|
||||
switch (fail) {
|
||||
case "face_not_detected": return "Face not detected, try another picture";
|
||||
default: return "Uknown failure";
|
||||
}
|
||||
};
|
||||
|
||||
// const transitions = useTransition(inferenceJobs, { // not today
|
||||
// ...springs.soft,
|
||||
// from: { opacity: 0, position: "absolute" },
|
||||
// enter: { opacity: 1, position: "relative" },
|
||||
// leave: { opacity: 0, position: "absolute" },
|
||||
// });
|
||||
|
||||
useEffect(() => {
|
||||
const fetch = async () => {
|
||||
const response = await GetPendingTtsJobCount();
|
||||
if (GetPendingTtsJobCountIsOk(response)) {
|
||||
if (
|
||||
response.cache_time.getTime() > pending.cache_time.getTime()
|
||||
) {
|
||||
pendingSet(response);
|
||||
}
|
||||
}
|
||||
};
|
||||
// TODO: We're having an outage and need to lower this.
|
||||
//const interval = setInterval(async () => fetch(), 15000);
|
||||
const refreshInterval = Math.max(
|
||||
DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS,
|
||||
pending.refresh_interval_millis
|
||||
);
|
||||
const interval = setInterval(async () => fetch(), refreshInterval);
|
||||
fetch();
|
||||
return () => clearInterval(interval);
|
||||
}, [pending]);
|
||||
|
||||
return inferenceJobs.length ? <div {...{ className: "face-animator-jobs panel" }}>
|
||||
<h5>{ t("headings.yourJobs") }</h5>
|
||||
{ inferenceJobs.map((job, key) => {
|
||||
return <div {...{ className: "panel face-animator-job", key }}>
|
||||
<FontAwesomeIcon {...{ className: `job-status-icon job-status-${job.statusIndex}`, icon: statusIcons[job.statusIndex] }}/>
|
||||
<div {...{ className: "job-details" }}>
|
||||
<h4>
|
||||
{ statusTxt(job.statusIndex,{ attemptCount: job.attemptCount || "" }) }
|
||||
</h4>
|
||||
<span>
|
||||
{ job.maybeFailureCategory ? `${ processFail(job.maybeFailureCategory) }` : "" }
|
||||
</span>
|
||||
</div>
|
||||
{
|
||||
job.maybeResultToken ? <Button {...{
|
||||
href: `media/${job.maybeResultToken}`,
|
||||
icon: faChevronRight,
|
||||
iconFlip: true,
|
||||
label: t("inputs.viewResult"),
|
||||
onClick:() => Analytics.voiceConversionClickDownload()
|
||||
}} />: null
|
||||
}
|
||||
</div>
|
||||
}).reverse()}
|
||||
</div> : null;
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './InferenceJobsList';
|
||||
@@ -22,7 +22,7 @@ import FaceAnimatorTitle from "./FaceAnimatorTitle";
|
||||
import FaceAnimatorInput from "./FaceAnimatorInput";
|
||||
import FaceAnimatorWorking from "./FaceAnimatorWorking";
|
||||
import FaceAnimatorSuccess from "./FaceAnimatorSuccess";
|
||||
import FaceAnimatorJobs from "./FaceAnimatorJobs";
|
||||
import InferenceJobsList from "components/layout/InferenceJobsList";
|
||||
import { FaceAnimatorCore } from "./FaceAnimatorTypes";
|
||||
import { BasicVideo } from "components/common";
|
||||
import "./LipsyncEditor.scss";
|
||||
@@ -182,7 +182,7 @@ export default function LipsyncEditor({
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<FaceAnimatorJobs {...{ inferenceJobsByCategory, t }}/>
|
||||
<InferenceJobsList {...{ t }}/>
|
||||
<div {...{ className: "face-animator-mobile-sample" }}>
|
||||
<BasicVideo {...{ src: "/videos/face-animator-instruction-en.mp4" }} />
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,7 @@ interface RouteParams {
|
||||
}
|
||||
|
||||
export default function DatasetEditor({ value }: Props) {
|
||||
const { datasets, inputCtrl } = useVoiceRequests();
|
||||
const { datasets, inputCtrl } = useVoiceRequests({});
|
||||
const [title, titleSet] = useState("");
|
||||
const [language,languageSet] = useState("en");
|
||||
const [visibility,visibilitySet] = useState("");
|
||||
|
||||
@@ -28,7 +28,7 @@ interface RouteParams {
|
||||
|
||||
function VoiceDesignerFormPage() {
|
||||
const history = useHistory();
|
||||
const { datasets, inputCtrl, languages, visibilityOptions, voices } = useVoiceRequests();
|
||||
const { datasets, inputCtrl, languages, visibilityOptions, voices } = useVoiceRequests({});
|
||||
const [language, languageSet] = useState("en");
|
||||
const [visibility, visibilitySet] = useState("");
|
||||
const [title, titleSet] = useState("");
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React, { useState } from "react";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
import { faPlus, faWaveform } from "@fortawesome/pro-solid-svg-icons";
|
||||
import InferenceJobsList from "components/layout/InferenceJobsList";
|
||||
import { useLocalize } from "hooks";
|
||||
// import { usePrefixedDocumentTitle } from "common/UsePrefixedDocumentTitle";
|
||||
import Panel from "components/common/Panel";
|
||||
import PageHeader from "components/layout/PageHeader";
|
||||
@@ -12,7 +14,8 @@ import useVoiceRequests from "./useVoiceRequests";
|
||||
|
||||
function VoiceDesignerMainPage() {
|
||||
const { pathname } = useLocation();
|
||||
const { datasets, voices } = useVoiceRequests();
|
||||
const { t } = useLocalize("FaceAnimator");
|
||||
const { datasets, voices } = useVoiceRequests({ requestDatasets: true, requestVoices: true });
|
||||
const [isDeleteVoiceModalOpen, setIsDeleteVoiceModalOpen] = useState(false);
|
||||
const [isDeleteDatasetModalOpen, setIsDeleteDatasetModalOpen] =
|
||||
useState(false);
|
||||
@@ -128,7 +131,7 @@ function VoiceDesignerMainPage() {
|
||||
panel={false}
|
||||
imageUrl="/images/header/voice-designer.png"
|
||||
/>
|
||||
|
||||
<InferenceJobsList {...{ t }}/>
|
||||
<Panel mb={true}>
|
||||
<nav>
|
||||
<ul className="nav nav-tabs">
|
||||
|
||||
@@ -60,7 +60,7 @@ export default function VoiceDesignerUseVoicePage(
|
||||
voiceToken: "",
|
||||
languageTag: "",
|
||||
});
|
||||
const { inference } = useVoiceRequests();
|
||||
const { inference } = useVoiceRequests({});
|
||||
const [isEnqueuing, setIsEnqueuing] = useState(false);
|
||||
|
||||
const getVoiceDetails = useCallback(async (voice_token) => {
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ function VoiceDesignerVoiceEditPage() {
|
||||
const history = useHistory();
|
||||
const { voice_token } = useParams();
|
||||
|
||||
const { inputCtrl, languages, visibilityOptions, voices } = useVoiceRequests();
|
||||
const { inputCtrl, languages, visibilityOptions, voices } = useVoiceRequests({});
|
||||
|
||||
usePrefixedDocumentTitle("Edit Voice");
|
||||
|
||||
|
||||
@@ -24,18 +24,18 @@ import { UpdateDataset, UpdateDatasetRequest, UpdateDatasetResponse } from "@sto
|
||||
import { EnqueueTts } from "@storyteller/components/src/api/voice_designer/inference/EnqueueTts";
|
||||
import { useSession } from "hooks";
|
||||
|
||||
export default function useVoiceRequests() {
|
||||
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<Dataset[]>([]);
|
||||
const [voices, voicesSet] = useState<Voice[]>([]);
|
||||
|
||||
// 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 [fetchedDatasets, fetchedDatasetsSet] = useState(false);
|
||||
const [fetchedVoices,fetchedVoicesSet] = useState(false);
|
||||
const [fetchDatasets, fetchDatasetsSet] = useState(requestDatasets);
|
||||
const [fetchVoices,fetchVoicesSet] = useState(requestVoices);
|
||||
const { user } = useSession();
|
||||
// const [timestamp, timestampSet] = useState(Date.now());
|
||||
|
||||
const refreshData = () => { fetchedDatasetsSet(false); fetchedVoicesSet(false); }; // 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<CreateDatasetResponse> =>
|
||||
CreateDataset(urlRouteArgs, request).then(res => {
|
||||
@@ -80,6 +80,8 @@ export default function useVoiceRequests() {
|
||||
});
|
||||
};
|
||||
|
||||
const listDatasets = () => { fetchDatasetsSet(true); return datasets; }
|
||||
|
||||
const languages = [
|
||||
{ value: "en", label: "English" },
|
||||
{ value: "es", label: "Spanish" },
|
||||
@@ -93,20 +95,20 @@ export default function useVoiceRequests() {
|
||||
|
||||
useEffect(() => {
|
||||
if (user && user.username) {
|
||||
if (!fetchedDatasets) {
|
||||
fetchedDatasetsSet(true);
|
||||
if (fetchDatasets) {
|
||||
fetchDatasetsSet(false);
|
||||
ListDatasetsByUser(user.username,{}).then(res => {
|
||||
if (res.datasets) datasetsSet(res.datasets);
|
||||
});
|
||||
}
|
||||
if (!fetchedVoices) {
|
||||
fetchedVoicesSet(true);
|
||||
if (fetchVoices) {
|
||||
fetchVoicesSet(false);
|
||||
ListVoicesByUser(user.username,{}).then(res => {
|
||||
if (res.voices) voicesSet(res.voices);
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [user, fetchedDatasets, fetchedVoices]);
|
||||
}, [user, fetchDatasets, fetchVoices]);
|
||||
|
||||
return {
|
||||
datasets: {
|
||||
@@ -116,6 +118,7 @@ export default function useVoiceRequests() {
|
||||
edit: editDataSet,
|
||||
get: GetDataset,
|
||||
list: datasets,
|
||||
listDatasets,
|
||||
refresh: refreshData
|
||||
},
|
||||
inference: {
|
||||
|
||||
Reference in new issue
Block a user