mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-06 02:00:46 +00:00
upload lora page
This commit is contained in:
1 parent
0fc18f6610
commit
89bdf04528
6 files changed
+333
-112
No files matched your search
@@ -0,0 +1 @@
|
||||
export { default } from "./useLoraUpload";
|
||||
@@ -0,0 +1,59 @@
|
||||
import { useState } from "react";
|
||||
import { UploadModel } from "@storyteller/components/src/api/image_generation/UploadModel";
|
||||
import { FetchStatus } from "@storyteller/components/src/api/_common/SharedFetchTypes";
|
||||
import { useCoverImgUpload } from "hooks";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
// this hook is mostly for organizational purposes while I work -V
|
||||
|
||||
export default function useLoraUpload() {
|
||||
const [title, titleSet] = useState("");
|
||||
const [uploadPath, uploadPathSet] = useState("");
|
||||
const [visibility, visibilitySet] = useState("public");
|
||||
const [descriptionMD, descriptionMDSet] = useState("");
|
||||
const [writeStatus, writeStatusSet] = useState(FetchStatus.paused);
|
||||
const coverImg = useCoverImgUpload();
|
||||
|
||||
const onChange = ({ target }: { target: { name: string; value: any } }) => {
|
||||
const todo: { [key: string]: (x: any) => void } = {
|
||||
descriptionMDSet,
|
||||
uploadPathSet,
|
||||
titleSet,
|
||||
visibilitySet,
|
||||
};
|
||||
todo[target.name + "Set"](target.value);
|
||||
};
|
||||
|
||||
const upload = () => {
|
||||
writeStatusSet(FetchStatus.in_progress);
|
||||
UploadModel("", {
|
||||
...(coverImg.token
|
||||
? { cover_image_media_file_token: coverImg.token }
|
||||
: {}),
|
||||
description: descriptionMD,
|
||||
uuid_idempotency_token: uuidv4(),
|
||||
type_of_inference: "inference",
|
||||
maybe_upload_path: uploadPath,
|
||||
title,
|
||||
visibility,
|
||||
})
|
||||
.then((res: any) => {
|
||||
writeStatusSet(FetchStatus.success);
|
||||
console.log("🌠", res);
|
||||
// history.replace(`/weight/${token}`);
|
||||
})
|
||||
.catch(err => {
|
||||
writeStatusSet(FetchStatus.error);
|
||||
});
|
||||
};
|
||||
return {
|
||||
coverImg,
|
||||
descriptionMD,
|
||||
onChange,
|
||||
title,
|
||||
upload,
|
||||
uploadPath,
|
||||
visibility,
|
||||
writeStatus,
|
||||
};
|
||||
}
|
||||
@@ -107,6 +107,7 @@ import WeightEditPage from "./pages/weight/WeightEditPage";
|
||||
import UploadSdWeightPage from "./pages/upload/UploadSdWeightPage";
|
||||
import { FooterNav } from "./nav/FooterNav";
|
||||
import FbxToGltfPage from "./pages/fbx_to_gltf/FbxToGltfPage";
|
||||
import UploadLoraWeightPage from "./pages/upload/UploadLoraWeightPage";
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper;
|
||||
@@ -349,12 +350,6 @@ class PageContainer extends React.Component<
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/upload/sd">
|
||||
<UploadSdWeightPage
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/media/:token">
|
||||
<MediaPage />
|
||||
</Route>
|
||||
@@ -543,6 +538,18 @@ class PageContainer extends React.Component<
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/upload/sd">
|
||||
<UploadSdWeightPage
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/upload/lora">
|
||||
<UploadLoraWeightPage
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/contribute">
|
||||
<ContributeIndexPage
|
||||
sessionWrapper={this.props.sessionWrapper}
|
||||
|
||||
@@ -17,10 +17,12 @@ import { PageHeader } from "../../_common/PageHeader";
|
||||
import {
|
||||
faFileArrowUp,
|
||||
faHandHoldingHeart,
|
||||
faImage,
|
||||
faMicrophone,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import { faMicrophoneStand } from "@fortawesome/pro-duotone-svg-icons";
|
||||
import { faWaveformLines } from "@fortawesome/pro-regular-svg-icons";
|
||||
import { PosthogClient } from "@storyteller/components/src/analytics/PosthogClient";
|
||||
import { Button } from "components/common";
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper;
|
||||
@@ -96,25 +98,39 @@ function ContributeIndexPage(props: Props) {
|
||||
</p>
|
||||
<div className="row gx-3 gy-3">
|
||||
<div className="col-12 col-md-6">
|
||||
<Link
|
||||
<Button
|
||||
icon={faMicrophone}
|
||||
label="Upload Voice to Voice Weight"
|
||||
to="/upload/voice_conversion"
|
||||
className="btn btn-primary w-100"
|
||||
>
|
||||
<FontAwesomeIcon icon={faMicrophoneStand} className="me-3" />
|
||||
Upload Voice to Voice Model
|
||||
</Link>
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12 col-md-6">
|
||||
<Link to="/upload/tts" className="btn btn-primary w-100">
|
||||
<FontAwesomeIcon icon={faVolumeHigh} className="me-3" />
|
||||
{t("pages.contributeIndex.buttonUploadVoice")}
|
||||
</Link>
|
||||
<Button
|
||||
icon={faVolumeHigh}
|
||||
label={t("pages.contributeIndex.buttonUploadVoice")}
|
||||
to="/upload/tts"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12 col-md-6">
|
||||
<Link to="/upload/vocoder" className="btn btn-primary w-100">
|
||||
<FontAwesomeIcon icon={faWaveformLines} className="me-3" />
|
||||
Upload Vocoder
|
||||
</Link>
|
||||
<Button
|
||||
icon={faWaveformLines}
|
||||
label="Upload Vocoder"
|
||||
to="/upload/vocoder"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12 col-md-6">
|
||||
<Button
|
||||
icon={faImage}
|
||||
label="Upload Stable Diffusion Weight"
|
||||
to="/upload/sd"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12 col-md-6">
|
||||
<Button
|
||||
icon={faImage}
|
||||
label="Upload LoRa Weight"
|
||||
to="/upload/lora"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
import React from "react";
|
||||
import {
|
||||
faCircleExclamation,
|
||||
faEye,
|
||||
faWaveform,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import { usePrefixedDocumentTitle } from "common/UsePrefixedDocumentTitle";
|
||||
import PageHeader from "components/layout/PageHeader";
|
||||
import {
|
||||
Button,
|
||||
Container,
|
||||
CoverImageInput,
|
||||
SplitPanel,
|
||||
TempInput,
|
||||
TempSelect,
|
||||
TempTextArea,
|
||||
} from "components/common";
|
||||
import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
|
||||
import useLoraUpload from "hooks/useLoraUpload";
|
||||
|
||||
interface UploadLoraWeightPageProps {
|
||||
sessionWrapper: SessionWrapper;
|
||||
}
|
||||
|
||||
export default function UploadLoraWeightPage({
|
||||
sessionWrapper,
|
||||
}: UploadLoraWeightPageProps) {
|
||||
usePrefixedDocumentTitle("Edit Voice");
|
||||
|
||||
const visibilityOptions = [
|
||||
{ label: "Public", value: "public" },
|
||||
{ label: "Private", value: "private" },
|
||||
];
|
||||
|
||||
const {
|
||||
coverImg,
|
||||
descriptionMD,
|
||||
onChange,
|
||||
title,
|
||||
upload,
|
||||
uploadPath,
|
||||
visibility,
|
||||
} = useLoraUpload();
|
||||
|
||||
if (!sessionWrapper.isLoggedIn()) {
|
||||
return (
|
||||
<Container type="panel">
|
||||
<PageHeader
|
||||
titleIcon={faCircleExclamation}
|
||||
title="Access Denied"
|
||||
subText="This weight does not exist or is not owned by you."
|
||||
panel={true}
|
||||
extension={
|
||||
<div className="d-flex">
|
||||
<Button
|
||||
label="Back to homepage"
|
||||
to={`/weight/{}`}
|
||||
className="d-flex"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container type="panel">
|
||||
<PageHeader
|
||||
title="Upload LoRA Weight"
|
||||
titleIcon={faWaveform}
|
||||
subText="Upload a LoRA model weight. Once your weight is successfully uploaded, you'll be able to start using it and sharing it with others."
|
||||
panel={false}
|
||||
/>
|
||||
|
||||
<SplitPanel dividerFooter={true}>
|
||||
<SplitPanel.Body padding={true}>
|
||||
<div className="row gx-4 gy-3">
|
||||
<div className="col-12 col-lg-5">
|
||||
<label className="sub-title required">Cover Image</label>
|
||||
<CoverImageInput
|
||||
{...{
|
||||
currentPath: "",
|
||||
onClick: coverImg.upload,
|
||||
status: coverImg.status,
|
||||
...coverImg.fileProps,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12 col-lg-7 order-first order-lg-last">
|
||||
<TempInput
|
||||
{...{
|
||||
label: "Title",
|
||||
name: "title",
|
||||
onChange,
|
||||
placeholder: "Title",
|
||||
value: title,
|
||||
required: true,
|
||||
}}
|
||||
/>
|
||||
|
||||
<TempInput
|
||||
{...{
|
||||
label: "Download URL, eg. Google Drive link",
|
||||
name: "uploadPath",
|
||||
onChange,
|
||||
placeholder: "Download URL",
|
||||
value: uploadPath,
|
||||
required: true,
|
||||
}}
|
||||
/>
|
||||
|
||||
<TempSelect
|
||||
{...{
|
||||
icon: faEye,
|
||||
label: "Visibility",
|
||||
name: "visibility",
|
||||
onChange,
|
||||
options: visibilityOptions,
|
||||
placeholder: "Voice name",
|
||||
value: visibility,
|
||||
}}
|
||||
/>
|
||||
<TempTextArea
|
||||
{...{
|
||||
label: "Description",
|
||||
name: "descriptionMD",
|
||||
onChange,
|
||||
placeholder: "Description",
|
||||
value: descriptionMD,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</SplitPanel.Body>
|
||||
<SplitPanel.Footer padding={true}>
|
||||
<div className="d-flex gap-2 justify-content-end">
|
||||
<Button
|
||||
{...{
|
||||
label: "Upload Weight",
|
||||
onClick: upload,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</SplitPanel.Footer>
|
||||
</SplitPanel>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import React from "react";
|
||||
import {
|
||||
faCircleExclamation,
|
||||
faEye,
|
||||
@@ -10,8 +10,6 @@ import {
|
||||
Button,
|
||||
Container,
|
||||
CoverImageInput,
|
||||
Panel,
|
||||
Skeleton,
|
||||
SplitPanel,
|
||||
TempInput,
|
||||
TempSelect,
|
||||
@@ -27,8 +25,6 @@ interface UploadSdWeightPageProps {
|
||||
export default function UploadSdWeightPage({
|
||||
sessionWrapper,
|
||||
}: UploadSdWeightPageProps) {
|
||||
const [isLoading] = useState(false);
|
||||
|
||||
usePrefixedDocumentTitle("Edit Voice");
|
||||
|
||||
const visibilityOptions = [
|
||||
@@ -36,9 +32,17 @@ export default function UploadSdWeightPage({
|
||||
{ label: "Private", value: "private" },
|
||||
];
|
||||
|
||||
const { coverImg, descriptionMD, onChange, title, upload, uploadPath, visibility } = useSdUpload();
|
||||
const {
|
||||
coverImg,
|
||||
descriptionMD,
|
||||
onChange,
|
||||
title,
|
||||
upload,
|
||||
uploadPath,
|
||||
visibility,
|
||||
} = useSdUpload();
|
||||
|
||||
if (!sessionWrapper.isLoggedIn() && !isLoading) {
|
||||
if (!sessionWrapper.isLoggedIn()) {
|
||||
return (
|
||||
<Container type="panel">
|
||||
<PageHeader
|
||||
@@ -65,96 +69,81 @@ export default function UploadSdWeightPage({
|
||||
<PageHeader
|
||||
title="Upload Stable Diffusion Weight"
|
||||
titleIcon={faWaveform}
|
||||
subText="Upload a Stable Diffusion Image model weight. Once your weight is successfully uploaded, you'll be able to start using it and sharing it with others."
|
||||
subText="Upload a Stable Diffusion image model weight. Once your weight is successfully uploaded, you'll be able to start using it and sharing it with others."
|
||||
panel={false}
|
||||
/>
|
||||
|
||||
<>
|
||||
{isLoading ? (
|
||||
<Panel padding={true}>
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<Skeleton type="short" />
|
||||
<Skeleton height="40px" />
|
||||
<Skeleton type="short" />
|
||||
<Skeleton height="40px" />
|
||||
<div className="d-flex justify-content-end mt-3 gap-2">
|
||||
<Skeleton height="40px" width="120px" />
|
||||
<Skeleton height="40px" width="120px" />
|
||||
</div>
|
||||
<SplitPanel dividerFooter={true}>
|
||||
<SplitPanel.Body padding={true}>
|
||||
<div className="row gx-4 gy-3">
|
||||
<div className="col-12 col-lg-5">
|
||||
<label className="sub-title required">Cover Image</label>
|
||||
<CoverImageInput
|
||||
{...{
|
||||
currentPath: "",
|
||||
onClick: coverImg.upload,
|
||||
status: coverImg.status,
|
||||
...coverImg.fileProps,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Panel>
|
||||
) : (
|
||||
<SplitPanel dividerFooter={true}>
|
||||
<SplitPanel.Body padding={true}>
|
||||
<div className="row gx-4 gy-3">
|
||||
<div className="col-12 col-lg-5">
|
||||
<label className="sub-title required">Cover Image</label>
|
||||
<CoverImageInput {...{
|
||||
currentPath: "",
|
||||
onClick: coverImg.upload,
|
||||
status: coverImg.status,
|
||||
...coverImg.fileProps
|
||||
}} />
|
||||
</div>
|
||||
<div className="col-12 col-lg-7 order-first order-lg-last">
|
||||
<TempInput
|
||||
{...{
|
||||
label: "Title",
|
||||
name: "title",
|
||||
onChange,
|
||||
placeholder: "Title",
|
||||
value: title,
|
||||
required: true,
|
||||
}}
|
||||
/>
|
||||
<div className="col-12 col-lg-7 order-first order-lg-last">
|
||||
<TempInput
|
||||
{...{
|
||||
label: "Title",
|
||||
name: "title",
|
||||
onChange,
|
||||
placeholder: "Title",
|
||||
value: title,
|
||||
required: true,
|
||||
}}
|
||||
/>
|
||||
|
||||
<TempInput
|
||||
{...{
|
||||
label: "Download URL, eg. Google Drive link",
|
||||
name: "uploadPath",
|
||||
onChange,
|
||||
placeholder: "Download URL",
|
||||
value: uploadPath,
|
||||
required: true,
|
||||
}}
|
||||
/>
|
||||
<TempInput
|
||||
{...{
|
||||
label: "Download URL, eg. Google Drive link",
|
||||
name: "uploadPath",
|
||||
onChange,
|
||||
placeholder: "Download URL",
|
||||
value: uploadPath,
|
||||
required: true,
|
||||
}}
|
||||
/>
|
||||
|
||||
<TempSelect
|
||||
{...{
|
||||
icon: faEye,
|
||||
label: "Visibility",
|
||||
name: "visibility",
|
||||
onChange,
|
||||
options: visibilityOptions,
|
||||
placeholder: "Voice name",
|
||||
value: visibility,
|
||||
}}
|
||||
/>
|
||||
<TempTextArea
|
||||
{...{
|
||||
label: "Description",
|
||||
name: "descriptionMD",
|
||||
onChange,
|
||||
placeholder: "Description",
|
||||
value: descriptionMD,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</SplitPanel.Body>
|
||||
<SplitPanel.Footer padding={true}>
|
||||
<div className="d-flex gap-2 justify-content-end">
|
||||
<Button
|
||||
{...{
|
||||
label: "Upload Weight",
|
||||
onClick: upload
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</SplitPanel.Footer>
|
||||
</SplitPanel>
|
||||
)}
|
||||
</>
|
||||
<TempSelect
|
||||
{...{
|
||||
icon: faEye,
|
||||
label: "Visibility",
|
||||
name: "visibility",
|
||||
onChange,
|
||||
options: visibilityOptions,
|
||||
placeholder: "Voice name",
|
||||
value: visibility,
|
||||
}}
|
||||
/>
|
||||
<TempTextArea
|
||||
{...{
|
||||
label: "Description",
|
||||
name: "descriptionMD",
|
||||
onChange,
|
||||
placeholder: "Description",
|
||||
value: descriptionMD,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</SplitPanel.Body>
|
||||
<SplitPanel.Footer padding={true}>
|
||||
<div className="d-flex gap-2 justify-content-end">
|
||||
<Button
|
||||
{...{
|
||||
label: "Upload Weight",
|
||||
onClick: upload,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</SplitPanel.Footer>
|
||||
</SplitPanel>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user