Merge branch 'feature/mvp' into fixes/mvp1_improvements

This commit is contained in:
wil committed 2024-02-08 15:59:27 -05:00
commit ece670c223
25 files changed
+209 -70

No files matched your search

+4 -2
View File
@@ -837,11 +837,11 @@ class App extends React.Component<Props, State> {
*/}
<div className="migrationComponentWrapper">
<ModalProvider>
<InferenceJobs
{...{
enqueue: this.enqueueInferenceJob,
byCategory: this.state.inferenceJobsByCategory,
inferenceJobs: this.state.inferenceJobs
}}
>
<SessionProvider
@@ -852,6 +852,8 @@ class App extends React.Component<Props, State> {
sessionFetched: this.state.sessionFetched,
}}
>
<ModalProvider>
<Switch>
<Route path="/">
<PageContainer
@@ -959,9 +961,9 @@ class App extends React.Component<Props, State> {
/>
</Route>
</Switch>
</ModalProvider>
</SessionProvider>
</InferenceJobs>
</ModalProvider>
</div>
</div>
</div>
@@ -6,12 +6,14 @@ import {
// import { useTransition } from "@react-spring/web";
import JobItem from "./JobItem";
import { useInferenceJobs, useLocalize } from "hooks";
import { JobListTypes } from "hooks/useInferenceJobs/useInferenceJobs";
import "./InferenceJobsList.scss";
import { Panel } from "components/common";
interface JobsListProps {
failures: (fail: string) => string;
jobType: FrontendInferenceJobType;
jobType?: FrontendInferenceJobType;
value?: JobListTypes;
onSelect?: (e: any) => any;
showNoJobs?: boolean;
}
@@ -19,11 +21,16 @@ interface JobsListProps {
export default function InferenceJobsList({
failures,
jobType,
value,
onSelect,
showNoJobs = false,
}: JobsListProps) {
const { inferenceJobs = [], jobStatusDescription } =
useInferenceJobs(jobType);
// undefined specified here to allow 0.
// jobType + 1 because the difference between FrontendInferenceJobType and JobListTypes is an "all" option
const jobValue = value !== undefined ? value : jobType !== undefined ? (jobType || 0) + 1 : 0;
const { inferenceJobs = [], jobStatusDescription } = useInferenceJobs(jobValue);
const { t } = useLocalize("InferenceJobs");
if (inferenceJobs.length || showNoJobs) {
@@ -36,7 +43,6 @@ export default function InferenceJobsList({
{...{
failures,
jobStatusDescription,
jobType,
key,
onSelect,
t,
@@ -8,7 +8,6 @@ import { JobState } from "@storyteller/components/src/jobs/JobStates";
interface JobListItem extends InferenceJob {
failures: (fail: string) => string,
jobType: FrontendInferenceJobType,
jobStatusDescription?: any,
onSelect?: any,
refSet?: any,
@@ -20,13 +19,13 @@ const OuterItem = ({ className, children, success, jobToken, maybeResultToken, o
<a.a {...{ className, href: `/media/${maybeResultToken}`, id: `ijobitem-${ jobToken }`, onClick: () => onSelect(), ref: refSet }}>{ children }</a.a> :
<a.div {...{ className, id: `ijobitem-${ jobToken }`, ref: refSet }}>{ children }</a.div>;
export default function JobItem({ failures, maybeFailureCategory, maybeResultToken, onSelect, jobToken, jobState, jobStatusDescription, jobType: inputType, refSet, t, ...rest }: JobListItem) {
export default function JobItem({ failures, frontendJobType, maybeFailureCategory, maybeResultToken, onSelect, jobToken, jobState, jobStatusDescription, refSet, t, ...rest }: JobListItem) {
const [hasBounced,hasBouncedSet] = useState(false);
// const [jobState,jobStateSet] = useState(0); // for animation debugging
// useInterval({ interval: 3000, onTick: ({ index }: { index: number }) => { jobStateSet(index); if (!index) hasBouncedSet(false) } });
const jobType = FrontendInferenceJobType[inputType];
const jobType = FrontendInferenceJobType[frontendJobType];
const jobStatus = jobStatusDescription(jobState);
const jobStatusClass = jobStatus.toLowerCase().replace("_","-");
@@ -20,6 +20,7 @@ import {
faWandMagicSparkles,
faWaveformLines,
faTransporter,
faClipboardList
} from "@fortawesome/pro-solid-svg-icons";
import {
@@ -406,6 +407,19 @@ export default function SideNav({
Explore
</NavLink>
</li>
<li>
<NavLink
to="/inference-jobs-list"
activeClassName="active-link"
onClick={handleNavLinkClick}
>
<FontAwesomeIcon
icon={faClipboardList}
className="sidebar-heading-icon"
/>
My Jobs
</NavLink>
</li>
<hr className="mb-3 mt-3" />
<li className="sidebar-heading">{t("speechTitle")}</li>
<li>
@@ -7,6 +7,7 @@ import {
faWandMagicSparkles,
faWaveformLines,
faXmark,
faClipboardList
} from "@fortawesome/pro-solid-svg-icons";
import { Button } from "components/common";
import SearchBar from "components/common/SearchBar";
@@ -14,6 +15,8 @@ import React, { useEffect, useState } from "react";
import { Link, useHistory } from "react-router-dom";
import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
import { Logout } from "@storyteller/components/src/api/session/Logout";
import { useModal } from "hooks";
import { InferenceJobsModal } from "components/modals";
import { useDomainConfig } from "context/DomainConfigContext";
import NavItem from "../../common/NavItem/NavItem";
import ProfileDropdown from "components/common/ProfileDropdown";
@@ -45,6 +48,9 @@ export default function TopNav({
window.location.pathname === "/signup" ||
window.location.pathname === "/signup/";
const { open } = useModal();
const openModal = () => open({ component: InferenceJobsModal });
const handleMenuButtonClick = () => {
if (window.innerWidth < 1200) {
if (wrapper) {
@@ -204,6 +210,7 @@ export default function TopNav({
<div className="d-flex align-items-center gap-2">
<div className="d-none d-lg-flex gap-2">
<Button {...{ icon: faClipboardList, label: "My Jobs", onClick: openModal, variant: "secondary" }}/>
{loggedIn ? (
profileDropdown
) : (
@@ -0,0 +1,39 @@
import React, { useState } from "react";
import InferenceJobsList from "components/layout/InferenceJobsList";
import { FrontendInferenceJobType } from "@storyteller/components/src/jobs/InferenceJob";
import { TempSelect } from "components/common";
import { enumToKeyArr } from "resources";
import ModalHeader from "../ModalHeader";
interface Props {
handleClose?: any,
jobType?: FrontendInferenceJobType
}
export default function InferenceJobsModal({ handleClose, jobType: inJobType = -1 }: Props) {
const presetFilter = enumToKeyArr(FrontendInferenceJobType)[inJobType];
const [jobType,jobTypeSet] = useState(inJobType > -1 ? presetFilter : "All");
const typeObj = ["All", ...Object.values(FrontendInferenceJobType)];
const options = typeObj.filter(val => isNaN(Number(val)))
.map((value) => {
if (typeof value === "string") return { value, label: value }
return { label: "", value: "" };
});
const failures = (fail = "") => {
switch (fail) {
default:
return "Uknown failure";
}
};
return <>
<ModalHeader {...{ handleClose, title: "My Jobs" }} />
<TempSelect {...{ onChange: ({ target }: { target: any }) => jobTypeSet(target.value), options, value: jobType }} />
<InferenceJobsList {...{
failures,
value: typeObj.indexOf(jobType),
}} />
</>;
};
@@ -0,0 +1 @@
export { default } from "./InferenceJobsModal";
@@ -10,9 +10,9 @@ import { GetWeightsByUser } from "@storyteller/components/src/api/weights/GetWei
import { MediaFile } from "@storyteller/components/src/api/media_files/GetMedia";
import { Weight } from "@storyteller/components/src/api/weights/GetWeight";
import { useListContent, useRatings } from "hooks";
import { FontAwesomeIcon as Icon } from "@fortawesome/react-fontawesome";
import { faArrowDownWideShort, faFilter, faXmark } from "@fortawesome/pro-solid-svg-icons";
import { faArrowDownWideShort, faFilter } from "@fortawesome/pro-solid-svg-icons";
import prepFilter from "resources/prepFilter";
import ModalHeader from "../ModalHeader";
import "./MediaBrowser.scss";
interface Props {
@@ -66,37 +66,33 @@ export default function MediaBrowser({ entityType, filterType: inputFilter, medi
// { value: "mostliked", label: "Most Liked" },
];
const title = ["",`${ owner ? owner + "'s " : "" }Media`,"Weights"][entityType];
const onClick = (data: any) => {
onSelect(data);
handleClose();
};
return <>
<header {...{ className: "fy-media-browser-header" }}>
<div {...{ className: "fy-media-browser-tools" }}>
<h3>{ ["",`${ owner ? owner + "'s " : "" }Media`,"Weights"][entityType] }</h3>
<Icon {...{ className: "icon-close-button", icon: faXmark, onClick: () => handleClose() }}/>
</div>
<div {...{ className: "fy-media-browser-tools" }}>
<TempSelect
{...{
icon: faArrowDownWideShort,
options: sortOptions,
name: "sort",
<ModalHeader {...{ handleClose, title}}>
<TempSelect
{...{
icon: faArrowDownWideShort,
options: sortOptions,
name: "sort",
onChange: entities.onChange,
value: entities.sort,
}}
/>
{ (!inputFilter || inputFilter === "all") && <TempSelect {...{
icon: faFilter,
options: EntityFilterOptions(entityType),
name: "filterType",
onChange: entities.onChange,
value: entities.sort,
}}
/>
{ (!inputFilter || inputFilter === "all") && <TempSelect {...{
icon: faFilter,
options: EntityFilterOptions(entityType),
name: "filterType",
onChange: entities.onChange,
value: filterType,
}}/> }
<Pagination {...paginationProps} />
</div>
</header>
value: filterType,
}}/> }
<Pagination {...paginationProps} />
</ModalHeader>
<AudioPlayerProvider>
{ entities.isLoading ? (
<div {...{ className: "row gx-3 gy-3" }}>
@@ -0,0 +1,21 @@
import React from "react";
import { FontAwesomeIcon as Icon } from "@fortawesome/react-fontawesome";
import { faXmark } from "@fortawesome/pro-solid-svg-icons";
interface Props {
children?: any,
handleClose?: any,
title?: string
}
export default function ModalHeader({ children, handleClose, title }: Props) {
return <header {...{ className: "fy-media-browser-header" }}>
<div {...{ className: "fy-media-browser-tools" }}>
{ title && <h3>{ title }</h3> }
{ handleClose && <Icon {...{ className: "icon-close-button", icon: faXmark, onClick: () => handleClose() }}/> }
</div>
{ children && <div {...{ className: "fy-media-browser-tools" }}>
{ children }
</div> }
</header>;
};
@@ -1,3 +1,4 @@
import InferenceJobsModal from "./InferenceJobsModal";
import MediaBrowser from "./MediaBrowser";
export { MediaBrowser };
export { InferenceJobsModal, MediaBrowser };
@@ -3,12 +3,12 @@ import { InferenceJobsContext } from 'context';
interface Props {
children?: any;
enqueue?: any;
byCategory?: any;
// enqueue?: any;
// byCategory?: any;
}
export default function InferenceJobs({ byCategory, children, enqueue }: Props) {
return <InferenceJobsContext.Provider {...{ value: { byCategory, enqueue } }}>
export default function InferenceJobs({ children, ...value }: Props) {
return <InferenceJobsContext.Provider {...{ value }}>
{ children }
</InferenceJobsContext.Provider>
};
@@ -1,5 +1,5 @@
import { createContext } from 'react';
interface InferenceJobsContext { byCategory?: any, enqueue?: any }
interface InferenceJobsContext { inferenceJobs?: any, byCategory?: any, enqueue?: any }
export default createContext<InferenceJobsContext>({ });
@@ -2,13 +2,25 @@ import { useContext } from 'react';
import { JobState } from "@storyteller/components/src/jobs/JobStates";
import { FrontendInferenceJobType } from "@storyteller/components/src/jobs/InferenceJob";
import { InferenceJobsContext } from 'context';
import { useModal } from "hooks";
import { InferenceJobsModal } from "components/modals";
export default function useInferenceJobs(jobType: FrontendInferenceJobType) {
const { byCategory, enqueue } = useContext(InferenceJobsContext);
export enum JobListAll { All }
export type JobListTypes = FrontendInferenceJobType | JobListAll;
export default function useInferenceJobs(jobType: JobListTypes, debug = false) {
const { byCategory, enqueue, inferenceJobs } = useContext(InferenceJobsContext);
const { open } = useModal();
const openJobListModal = () => open({ component: InferenceJobsModal, props: { jobType } });
return {
enqueue,
inferenceJobs: (byCategory?.get(jobType) || []),
// enqueue,
enqueue: (jobToken: string) => {
openJobListModal();
enqueue(jobToken,jobType);
},
inferenceJobs: jobType === JobListAll.All ? inferenceJobs : (byCategory?.get(jobType - 1) || []),
jobStatusDescription: (jobState: JobState) => Object.keys(JobState).filter(key => isNaN(Number(key)))[jobState]
};
};
@@ -14,7 +14,7 @@ export default function useLoraUpload() {
const [descriptionMD, descriptionMDSet] = useState("");
const [writeStatus, writeStatusSet] = useState(FetchStatus.paused);
const coverImg = useCoverImgUpload();
const { enqueue } = useInferenceJobs(FrontendInferenceJobType.ImageGeneration);
const { enqueue } = useInferenceJobs(FrontendInferenceJobType.ImageGeneration, true);
const onChange = ({ target }: { target: { name: string; value: any } }) => {
const todo: { [key: string]: (x: any) => void } = {
@@ -41,9 +41,8 @@ export default function useLoraUpload() {
})
.then((res: any) => {
if (res.success && res.inference_job_token) {
console.log("🌠", res);
writeStatusSet(FetchStatus.success);
enqueue(res.inference_job_token, FrontendInferenceJobType.ImageGeneration);
enqueue(res.inference_job_token);
}
})
.catch(err => {
@@ -0,0 +1,3 @@
const enumToKeyArr = (type: any) => Object.keys(type).filter(val => isNaN(Number(val)));
export default enumToKeyArr;
+2 -1
View File
@@ -1,7 +1,8 @@
import basicTransition from "./basicTransition";
import baseColors from "./baseColors";
import enumToKeyArr from "./enumToKeyArr";
import getBatch from "./getBatch";
import onChanger from "./onChanger";
import springs from "./springs";
export { basicTransition, baseColors, getBatch, onChanger, springs }
export { basicTransition, baseColors, enumToKeyArr, getBatch, onChanger, springs }
+2
View File
@@ -194,6 +194,8 @@ $topbar-height: 66px;
.topbar-nav-center {
grid-column: 2;
}
.button { white-space: nowrap; }
}
.topbar-mobile-search-bar-container {
@@ -97,6 +97,7 @@ import VoiceDesignerUseVoicePage from "./pages/voice_designer/VoiceDesignerUseVo
import { PasswordResetEmailPage } from "./pages/password_reset/PasswordResetEmailPage";
import { PasswordResetVerificationPage } from "./pages/password_reset/PasswordResetVerificationPage";
import EngineCompositor from "./pages/EngineCompositor";
import InferenceJobsPage from "./pages/inference_jobs_page";
import { NewProfilePage } from "./pages/profile/profile_view/NewProfilePage";
import { ModerationJobControlPage } from "./pages/moderation/job_control/ModerationJobControlPage";
import WeightPage from "./pages/weight/WeightPage";
@@ -825,6 +826,10 @@ class PageContainer extends React.Component<
/>
</Route>
<Route path="/inference-jobs-list">
<InferenceJobsPage/>
</Route>
<Route path="/voice-designer">
<VoiceDesignerMainPage />
</Route>
@@ -206,7 +206,7 @@ function FooterNav(props: Props) {
</div>
<div className="d-flex flex-column flex-lg-row pt-2 align-items-center gap-2 gap-xl-4 flex-wrap">
<span className="flex-grow-1 opacity-75">© {domain.title} 2023</span>
<span className="flex-grow-1 opacity-75">© {domain.title} 2024</span>
<div className="d-flex flex-column flex-lg-row align-items-center mt-4 mt-lg-0">
{moderationLink}
@@ -1,5 +1,6 @@
import React, { useState } from "react";
import { Button, MocapInput } from "components/common";
import { Button } from "components/common";
import { EntityInput } from "components/entities";
import { useInferenceJobs } from "hooks";
import InferenceJobsList from "components/layout/InferenceJobsList";
import { EnqueueEngineCompositing } from "@storyteller/components/src/api/engine_compositor/EnqueueEngineCompositing";
@@ -26,10 +27,7 @@ export default function EngineCompositor({ value, sessionWrapper }: Props) {
})
.then((res: any) => {
if (res && res.success) {
inferenceJobs.enqueue( // I need to pass this
res.inference_job_token,
FrontendInferenceJobType.EngineComposition
);
inferenceJobs.enqueue(res.inference_job_token);
}
});
}
@@ -51,7 +49,7 @@ export default function EngineCompositor({ value, sessionWrapper }: Props) {
<h2>Engine Compositor</h2>
<Button {...{ label: "Enqueue", onClick, variant: "primary" }}/>
</header>
<MocapInput {...{ aspectRatio: "landscape", label: "Choose 3D data", onChange, type: "bvh" }}/>
<EntityInput {...{ aspectRatio: "landscape", label: "Choose 3D data", onChange, mediaType: "bvh" }}/>
</div>
<InferenceJobsList
{...{
@@ -1,6 +1,8 @@
import React, { useState } from "react";
import { EntityInput } from "components/entities";
import { EntityFilterOptions, EntityType, MediaFilterProp, WeightFilterProp } from "components/entities/EntityTypes";
import { useModal } from "hooks";
import { InferenceJobsModal } from "components/modals";
import { Button, SegmentButtons, TempInput, TempSelect } from "components/common";
interface Props {
@@ -15,9 +17,13 @@ export default function DevMediaInput({ value }: Props) {
const [owner,ownerSet] = useState("");
const onChange = ({ target }: any) => mediaTokenSet(target.value);
const { open } = useModal();
const options = [{ label: "Media", value: EntityType.media },{ label: "Weights", value: EntityType.weights }];
const changeFilter = ({ target }: { target: any }) => [mediaTypeSet,mediaTypeSet,weightTypeSet][entityType](target.value);
const openModal = () => open({ component: InferenceJobsModal });
return <div {...{ className: "fy-engine-compositor"}}>
<div {...{ className: "panel engine-compositor-container" }}>
<header>
@@ -34,6 +40,7 @@ export default function DevMediaInput({ value }: Props) {
owner,
...([{},{ mediaType },{ weightType }][entityType])
}}/>
<Button {...{ className: "mt-3", label: "Open modal", onClick: openModal, variant: "primary" }}/>
<div>
{ mediaToken }
</div>
@@ -0,0 +1,10 @@
import React from "react";
import { InferenceJobsModal } from "components/modals";
export default function InferenceJobsPage() {
return <div {...{ className: "fy-inference-jobs-list-page p-3"}}>
<div {...{ className: "panel p-3" }}>
<InferenceJobsModal />
</div>
</div>;
};
@@ -0,0 +1 @@
export { default } from "./InferenceJobsPage";
@@ -11,11 +11,11 @@ import { useLocalize } from "hooks";
import React from "react";
import { Link } from "react-router-dom";
interface FakeYouDashboardProps {
interface DashboardProps {
sessionWrapper: SessionWrapper;
}
export default function FakeYouDashboard(props: FakeYouDashboardProps) {
export default function Dashboard(props: DashboardProps) {
const { t } = useLocalize("LandingPage");
const isLoggedIn = props.sessionWrapper.isLoggedIn();
@@ -6,9 +6,10 @@ import {} from "@fortawesome/pro-solid-svg-icons";
import { PosthogClient } from "@storyteller/components/src/analytics/PosthogClient";
import { Container } from "components/common";
import FakeYouLandingHeader from "./fakeyou/FakeYouLandingHeader";
import FakeYouDashboard from "./Dashboard";
import Dashboard from "./Dashboard";
import FakeYouLandingBody from "./fakeyou/FakeYouLandingBody";
// import StorytellerLanding from "./StorytellerLanding";
import { useDomainConfig } from "context/DomainConfigContext";
import StorytellerLanding from "./storyteller/StorytellerLanding";
interface Props {
sessionWrapper: SessionWrapper;
@@ -18,23 +19,37 @@ interface Props {
function LandingPage(props: Props) {
usePrefixedDocumentTitle("FakeYou Celebrity Voice Generator");
PosthogClient.recordPageview();
const domain = useDomainConfig();
const isLoggedIn = props.sessionWrapper.isLoggedIn();
return (
<>
<Container type="panel">
{/* HEADER IF NOT LOGGED IN */}
{!isLoggedIn && (
<FakeYouLandingHeader
sessionWrapper={props.sessionWrapper}
sessionSubscriptionsWrapper={props.sessionSubscriptionsWrapper}
/>
{domain.title === "FakeYou" ? (
<>
{/* FAKEYOU.COM */}
{!isLoggedIn && (
<FakeYouLandingHeader
sessionWrapper={props.sessionWrapper}
sessionSubscriptionsWrapper={props.sessionSubscriptionsWrapper}
/>
)}
<Dashboard sessionWrapper={props.sessionWrapper} />
{!isLoggedIn && <FakeYouLandingBody />}
</>
) : (
<>
{/* STORYTELLER,AI */}
{!isLoggedIn ? (
<StorytellerLanding />
) : (
<Dashboard sessionWrapper={props.sessionWrapper} />
)}
</>
)}
<FakeYouDashboard sessionWrapper={props.sessionWrapper} />
{!isLoggedIn && <FakeYouLandingBody />}
</Container>
</>
);