From fd96f8a7f6abe9b0b3d8907aa271377ef70000ec Mon Sep 17 00:00:00 2001 From: bflatastic Date: Sat, 2 Dec 2023 18:41:14 +0700 Subject: [PATCH 1/4] don't allow continue if no title --- .../voice_designer/VoiceDesignerFormPage.tsx | 123 +++++++++++------- .../components/StepperControls.tsx | 16 ++- 2 files changed, 89 insertions(+), 50 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerFormPage.tsx b/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerFormPage.tsx index 57a56586bb..7620418a69 100644 --- a/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerFormPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerFormPage.tsx @@ -1,6 +1,11 @@ import React, { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; -import { faEye, faLanguage, faPencil, faWaveform } from "@fortawesome/pro-solid-svg-icons"; +import { + faEye, + faLanguage, + faPencil, + faWaveform, +} from "@fortawesome/pro-solid-svg-icons"; import { usePrefixedDocumentTitle } from "common/UsePrefixedDocumentTitle"; import Panel from "components/common/Panel"; import { Stepper } from "./components/Stepper"; @@ -21,16 +26,23 @@ interface RouteParams { dataset_token?: string; } -function VoiceDesignerFormPage({ enqueueInferenceJob, sessionWrapper }: { enqueueInferenceJob: any, sessionWrapper: SessionWrapper }) { +function VoiceDesignerFormPage({ + enqueueInferenceJob, + sessionWrapper, +}: { + enqueueInferenceJob: any; + sessionWrapper: SessionWrapper; +}) { 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("hidden"); const [title, titleSet] = useState(""); - const [fetched,fetchedSet] = useState(false); - const [deleting,deletingSet] = useState([]); // samples currently being uploaded - const [inProgress,inProgressSet] = useState([]); // samples currently being uploaded - const [samples,samplesSet] = useState([]); // fetched/uploaded samples + const [fetched, fetchedSet] = useState(false); + const [deleting, deletingSet] = useState([]); // samples currently being uploaded + const [inProgress, inProgressSet] = useState([]); // samples currently being uploaded + const [samples, samplesSet] = useState([]); // fetched/uploaded samples const audioProps = useFile({}); const { user, sessionFetched } = useSession(); @@ -67,15 +79,26 @@ function VoiceDesignerFormPage({ enqueueInferenceJob, sessionWrapper }: { enqueu const initialStep = history.location.pathname.includes("/upload") ? 1 : 0; const [currentStep, setCurrentStep] = useState(initialStep); - const steps = existingVoice ? ["Edit Details", "Edit Samples"] : ["Voice Details", "Upload Samples"]; - const uploadProps = { audioProps, datasetToken: dataset_token, deleting, deletingSet, inProgress, inProgressSet, samples, samplesSet }; + const steps = existingVoice + ? ["Edit Details", "Edit Samples"] + : ["Voice Details", "Upload Samples"]; + const uploadProps = { + audioProps, + datasetToken: dataset_token, + deleting, + deletingSet, + inProgress, + inProgressSet, + samples, + samplesSet, + }; const displayStep = (step: any) => { switch (step) { case 0: return ; case 1: - return ; + return ; default: return null; } @@ -96,27 +119,30 @@ function VoiceDesignerFormPage({ enqueueInferenceJob, sessionWrapper }: { enqueu if (!existingVoice) { // It's a new creation and on the first step - datasets.create("",{ - title, - creator_set_visibility: visibility, - idempotency_token: uuidv4(), - }).then((res: any) => { - if (res && res.success && res.token) { - history.push(`/voice-designer/dataset/${ res.token }/upload`); - } - }); - + datasets + .create("", { + title, + creator_set_visibility: visibility, + idempotency_token: uuidv4(), + }) + .then((res: any) => { + if (res && res.success && res.token) { + history.push(`/voice-designer/dataset/${res.token}/upload`); + } + }); } else if (dataset_token) { // It's edit mode and on the first step - datasets.edit(dataset_token,{ - title, - creator_set_visibility: visibility, - ietf_language_tag: language - }).then((res: any) => { - if (res && res.success && res.token) { - history.push(`/voice-designer/dataset/${dataset_token}/upload`); - } - }); + datasets + .edit(dataset_token, { + title, + creator_set_visibility: visibility, + ietf_language_tag: language, + }) + .then((res: any) => { + if (res && res.success && res.token) { + history.push(`/voice-designer/dataset/${dataset_token}/upload`); + } + }); } setCurrentStep(currentStep + 1); } else if (currentStep < steps.length - 1) { @@ -145,14 +171,13 @@ function VoiceDesignerFormPage({ enqueueInferenceJob, sessionWrapper }: { enqueu useEffect(() => { if (!fetched && dataset_token) { fetchedSet(true); - datasets.get(dataset_token,{}) - .then((res) => { + datasets.get(dataset_token, {}).then(res => { languageSet(res.ietf_language_tag); titleSet(res.title); visibilitySet(res.creator_set_visibility); }); } - },[dataset_token,datasets,fetched]); + }, [dataset_token, datasets, fetched]); if (sessionFetched && !user) { history.push("/voice-designer"); @@ -175,23 +200,27 @@ function VoiceDesignerFormPage({ enqueueInferenceJob, sessionWrapper }: { enqueu existingVoice ? "/voice-designer/datasets" : "/voice-designer/voices" } /> - { sessionFetched && user && -
- -
+ {sessionFetched && user && ( + +
+ +
-
{displayStep(currentStep)}
+
{displayStep(currentStep)}
- -
- } + +
+ )} ); } diff --git a/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/StepperControls.tsx b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/StepperControls.tsx index 30de935985..50e33efa85 100644 --- a/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/StepperControls.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/StepperControls.tsx @@ -7,6 +7,7 @@ interface StepperControlsProps { createDisabled: boolean; steps: string[]; currentStep: number; + continueDisabled?: boolean; } const StepperControls: React.FC = ({ @@ -15,7 +16,8 @@ const StepperControls: React.FC = ({ steps, currentStep, onCreate, - createDisabled + createDisabled, + continueDisabled, }) => { return (
@@ -26,13 +28,21 @@ const StepperControls: React.FC = ({ )} {currentStep === 0 && ( - )} {currentStep === 1 && ( - )} From 7a80692bdd050de513313afd158473ad68d746b1 Mon Sep 17 00:00:00 2001 From: bflatastic Date: Sat, 2 Dec 2023 19:02:57 +0700 Subject: [PATCH 2/4] buttons layout changes --- .../components/StepperControls.tsx | 57 +++++++++++-------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/StepperControls.tsx b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/StepperControls.tsx index 50e33efa85..c6f48a789f 100644 --- a/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/StepperControls.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/StepperControls.tsx @@ -1,4 +1,6 @@ +import { Button } from "components/common"; import React from "react"; +import { faChevronRight } from "@fortawesome/pro-solid-svg-icons"; interface StepperControlsProps { onBack: () => void; @@ -20,33 +22,38 @@ const StepperControls: React.FC = ({ continueDisabled, }) => { return ( -
- {currentStep === 1 && ( - - )} + <> +
- {currentStep === 0 && ( - - )} +
+ {currentStep === 1 && ( + - )} -
+ {currentStep === 0 && ( + <> +
+ ); }; From 16343a63d5629c46dd228d83e2a0b36da16ad29b Mon Sep 17 00:00:00 2001 From: bflatastic Date: Sat, 2 Dec 2023 19:19:31 +0700 Subject: [PATCH 3/4] buttons and layout fixes --- .../components/common/TempInput/TempInput.tsx | 26 +- .../voice_designer/VoiceDesignerFormPage.tsx | 2 +- .../voice_designer/VoiceDesignerMainPage.tsx | 238 ++++++++++-------- .../VoiceDesignerVoiceEditPage.tsx | 21 +- 4 files changed, 166 insertions(+), 121 deletions(-) diff --git a/packages/fakeyou.com/src/components/common/TempInput/TempInput.tsx b/packages/fakeyou.com/src/components/common/TempInput/TempInput.tsx index ca6d166266..d0ad994969 100644 --- a/packages/fakeyou.com/src/components/common/TempInput/TempInput.tsx +++ b/packages/fakeyou.com/src/components/common/TempInput/TempInput.tsx @@ -8,13 +8,21 @@ interface InputProps extends React.InputHTMLAttributes { textArea?: boolean; } -export default function TempInput({ label, icon, textArea, ...rest }: InputProps) { - return <> - { label && } -
- { icon && } - +export default function TempInput({ + label, + icon, + textArea, + ...rest +}: InputProps) { + return ( +
+ {label && } +
+ {icon && ( + + )} + +
- ; -}; - + ); +} diff --git a/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerFormPage.tsx b/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerFormPage.tsx index 7620418a69..d234b9b07b 100644 --- a/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerFormPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerFormPage.tsx @@ -7,7 +7,7 @@ import { faWaveform, } from "@fortawesome/pro-solid-svg-icons"; import { usePrefixedDocumentTitle } from "common/UsePrefixedDocumentTitle"; -import Panel from "components/common/Panel"; +import { Panel } from "components/common"; import { Stepper } from "./components/Stepper"; import { StepperControls } from "./components/StepperControls"; import { UploadSamples } from "./components/steps/UploadSamples"; 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 649724fe92..9cfd50f8f3 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 @@ -39,9 +39,14 @@ function VoiceDesignerMainPage(props: Props) { usePrefixedDocumentTitle("AI Voice Designer"); const { pathname } = useLocation(); const { t } = useLocalize("FaceAnimator"); - const { datasets, voices, isLoading } = useVoiceRequests({ requestDatasets: true,requestVoices: true }); + const { datasets, voices, isLoading } = useVoiceRequests({ + requestDatasets: true, + requestVoices: true, + }); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); - const view = ["/voice-designer/datasets", "/voice-designer/voices"].indexOf(pathname); + const view = ["/voice-designer/datasets", "/voice-designer/voices"].indexOf( + pathname + ); const [deleteItem, setDeleteItem] = useState(""); const [deleteType, setDeleteType] = useState(""); const [deleteText, setDeleteText] = useState({ @@ -85,18 +90,26 @@ function VoiceDesignerMainPage(props: Props) { }; const DataBadge = () => Dataset; - const VoiceBadge = () => ; + const VoiceBadge = () => ( + + ); // these need to be abstracted to use over again -V - const voiceClick = (todo: any, type: string) => ({ target }: { target: any }) => { - let voiceToken = voices.list[target.name.split(",")[0].split(":")[1]].voice_token; - todo(voiceToken, type); - }; + const voiceClick = + (todo: any, type: string) => + ({ target }: { target: any }) => { + let voiceToken = + voices.list[target.name.split(",")[0].split(":")[1]].voice_token; + todo(voiceToken, type); + }; - const datasetClick = (todo: any, type: string) => ({ target }: { target: any }) => { - let datasetToken = datasets.list[target.name.split(",")[0].split(":")[1]].dataset_token; - todo(datasetToken, type); - }; + const datasetClick = + (todo: any, type: string) => + ({ target }: { target: any }) => { + let datasetToken = + datasets.list[target.name.split(",")[0].split(":")[1]].dataset_token; + todo(datasetToken, type); + }; const actionDataSets = datasets.list.map((dataset, i) => { return { @@ -175,109 +188,122 @@ function VoiceDesignerMainPage(props: Props) { to: "/pricing", }; - const dataPlaceholder = () =>
-
- You haven't created any voices. -
-
; + const dataPlaceholder = () => ( +
+
You haven't created any voices.
+
+ ); - const LogggedInView = () => <> - - - + const LogggedInView = () => ( + <> + + + -
- +
+ +
+ + + ); + + const LoggedOutView = () => ( + +
+
+

Please log in to access voice creation.

+ +

+ If you don't have an account yet, sign up now to unlock this + feature! +

+
+ +
+
- ; - - const LoggedOutView = () => -
-
-

Please log in to access voice creation.

- -

- If you don't have an account yet, sign up now to unlock this - feature! -

-
- -
-
-
-
; + ); return ( <> - - { user ? : } - {/* Delete Modal */} - {deleteText.text}

} - onConfirm={handleDelete} - /> + + {user ? : } + {/* Delete Modal */} + {deleteText.text}

} + onConfirm={handleDelete} + />
); diff --git a/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerVoiceEditPage.tsx b/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerVoiceEditPage.tsx index ff8ffb199b..207f40c7ae 100644 --- a/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerVoiceEditPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerVoiceEditPage.tsx @@ -46,7 +46,7 @@ function VoiceDesignerVoiceEditPage() { useEffect(() => { if (!fetched && voice_token) { fetchedSet(true); - voices.get(voice_token, {}).then((res) => { + voices.get(voice_token, {}).then(res => { languageSet(res.ietf_language_tag); titleSet(res.title); visibilitySet(res.creator_set_visibility); @@ -66,8 +66,8 @@ function VoiceDesignerVoiceEditPage() { backbuttonTo="/voice-designer" /> - -
+ +
- -
+
+
+
+
From f13742dfddc0d21450aed6dd0395626953482360 Mon Sep 17 00:00:00 2001 From: bflatastic Date: Sat, 2 Dec 2023 20:32:49 +0700 Subject: [PATCH 4/4] new split panel component --- .../common/SplitPanel/SplitPanel.tsx | 83 +++++++++++++++++++ .../components/common/SplitPanel/index.tsx | 1 + 2 files changed, 84 insertions(+) create mode 100644 packages/fakeyou.com/src/components/common/SplitPanel/SplitPanel.tsx create mode 100644 packages/fakeyou.com/src/components/common/SplitPanel/index.tsx diff --git a/packages/fakeyou.com/src/components/common/SplitPanel/SplitPanel.tsx b/packages/fakeyou.com/src/components/common/SplitPanel/SplitPanel.tsx new file mode 100644 index 0000000000..ae8ffb21f4 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/SplitPanel/SplitPanel.tsx @@ -0,0 +1,83 @@ +import React, { ReactNode } from "react"; + +// Header, Body, and Footer Interfaces and Components +interface HeaderProps { + children: ReactNode; + padding?: boolean; +} +const Header: React.FC = ({ children, padding }) => { + const headerClassName = `${padding ? "p-3 py-4 p-md-4" : ""}`.trim(); + return
{children}
; +}; + +interface BodyProps { + children: ReactNode; + padding?: boolean; +} +const Body: React.FC = ({ children, padding }) => { + const bodyClassName = `${padding ? "p-3 py-4 p-md-4" : ""}`.trim(); + return
{children}
; +}; + +interface FooterProps { + children: ReactNode; + padding?: boolean; +} +const Footer: React.FC = ({ children, padding }) => { + const footerClassName = `${padding ? "p-3 py-4 p-md-4" : ""}`.trim(); + return
{children}
; +}; + +// Panel Interface +interface PanelProps { + children: ReactNode; + divider?: boolean; + clear?: boolean; + className?: string; +} + +// Panel Component +const SplitPanel: React.FC & { + Header: typeof Header; + Body: typeof Body; + Footer: typeof Footer; +} = ({ children, divider, clear, className }) => { + let header: ReactNode, body: ReactNode, footer: ReactNode; + + const panelClassName = `${clear ? "panel-clear" : "panel"} ${ + className ? className : "" + }`.trim(); + + React.Children.toArray(children).forEach((child: ReactNode) => { + if (React.isValidElement(child)) { + switch (child.type) { + case Header: + header = child; + break; + case Body: + body = child; + break; + case Footer: + footer = child; + break; + } + } + }); + + return ( +
+ {header} + {divider &&
} + {body} + {divider &&
} + {footer} +
+ ); +}; + +// Attach Header, Body, and Footer as static properties +SplitPanel.Header = Header; +SplitPanel.Body = Body; +SplitPanel.Footer = Footer; + +export default SplitPanel; diff --git a/packages/fakeyou.com/src/components/common/SplitPanel/index.tsx b/packages/fakeyou.com/src/components/common/SplitPanel/index.tsx new file mode 100644 index 0000000000..4cc735649f --- /dev/null +++ b/packages/fakeyou.com/src/components/common/SplitPanel/index.tsx @@ -0,0 +1 @@ +export { default } from "./SplitPanel";