detached select modal from useToken, fixed all the components that need that, fix redirect for file upload, more UI elements that corresponds to ticket

This commit is contained in:
wil committed 2024-02-01 15:21:30 -05:00
1 parent 565ec1fa69
commit 08ff13b93a
14 files changed
+186 -170

No files matched your search

@@ -11,6 +11,7 @@ import { faChevronDown } from "@fortawesome/pro-solid-svg-icons";
import { animated, useSpring } from "@react-spring/web";
interface AccordionProps {
className?: string;
children: React.ReactNode;
}
@@ -96,7 +97,7 @@ function AccordionItem({
);
}
function Accordion({ children }: AccordionProps) {
function Accordion({ children, className }: AccordionProps) {
// Extract titles of items that should be initially open
const defaultOpenTitles = React.Children.toArray(children)
.filter((child: any) => child.props.defaultOpen)
@@ -115,7 +116,9 @@ function Accordion({ children }: AccordionProps) {
return (
<AccordionContext.Provider value={{ openItems, toggleItem }}>
<div className="d-flex flex-column gap-3">{children}</div>
<div className={`d-flex flex-column gap-3 ${className}`}>
{children}
</div>
</AccordionContext.Provider>
);
}
@@ -12,7 +12,7 @@ import Button from "components/common/Button";
import useWeightTypeInfo from "hooks/useWeightTypeInfo/useWeightTypeInfo";
import WeightCoverImage from "components/common/WeightCoverImage";
import { BucketConfig } from "@storyteller/components/src/api/BucketConfig";
import useToken from "hooks/useToken";
// import useToken from "hooks/useToken";
import getCardUrl from "../getCardUrl";
interface AudioCardProps {
@@ -24,7 +24,7 @@ interface AudioCardProps {
source?: string;
type: "media" | "weights";
inSelectModal?: boolean;
onResultSelect?: () => void;
onResultSelect?: (data:{token: string, title:string}) => void;
}
export default function AudioCard({
@@ -38,7 +38,7 @@ export default function AudioCard({
inSelectModal = false,
onResultSelect,
}: AudioCardProps) {
const { setToken, setWeightTitle } = useToken();
// const { setToken, setWeightTitle } = useToken();
const linkUrl = getCardUrl(data,source,type);
const history = useHistory();
@@ -47,10 +47,13 @@ export default function AudioCard({
};
const handleSelectModalResultSelect = () => {
if (inSelectModal) {
setToken(data.weight_token);
setWeightTitle && setWeightTitle(data.title);
onResultSelect && onResultSelect();
console.log(`inSelectModal : ${inSelectModal}`);
console.log(`onResultSelect : ${onResultSelect}`);
if (inSelectModal && onResultSelect) {
onResultSelect({
token: data.weight_token,
title: data.title
});
}
};
@@ -10,7 +10,7 @@ import Button from "components/common/Button";
import { faArrowRight } from "@fortawesome/pro-solid-svg-icons";
import useWeightTypeInfo from "hooks/useWeightTypeInfo/useWeightTypeInfo";
import { BucketConfig } from "@storyteller/components/src/api/BucketConfig";
import useToken from "hooks/useToken";
// import useToken from "hooks/useToken";
import getCardUrl from "../getCardUrl";
interface ImageCardProps {
@@ -21,7 +21,7 @@ interface ImageCardProps {
source?: string;
type: "media" | "weights";
inSelectModal?: boolean;
onResultSelect?: () => void;
onResultSelect?: (data:{token: string, title:string}) => void;
}
export default function ImageCard({
@@ -35,18 +35,22 @@ export default function ImageCard({
onResultSelect,
}: ImageCardProps) {
const history = useHistory();
const { setToken, setWeightTitle } = useToken();
// const { setToken, setWeightTitle } = useToken();
const linkUrl = getCardUrl(data,source,type);
const handleInnerClick = (event: any) => {
console.log("handleInnderClick")
event.stopPropagation();
};
const handleSelectModalResultSelect = () => {
console.log("handleSelectModalResultSelect")
if (inSelectModal) {
setToken(data.weight_token);
setWeightTitle && setWeightTitle(data.title);
onResultSelect && onResultSelect();
onResultSelect && onResultSelect({
token: data.weight_token,
title: data.title
});
}
};
@@ -9,7 +9,6 @@ import Button from "components/common/Button";
import CreatorName from "../CreatorName";
import { BucketConfig } from "@storyteller/components/src/api/BucketConfig";
import { Link } from "react-router-dom";
import useToken from "hooks/useToken";
import getCardUrl from "../getCardUrl";
interface VideoCardProps {
@@ -19,7 +18,7 @@ interface VideoCardProps {
source?: string;
type: "media" | "weights";
inSelectModal?: boolean;
onResultSelect?: () => void;
onResultSelect?: (data:{token: string, title:string}) => void;
}
export default function VideoCard({
@@ -31,7 +30,6 @@ export default function VideoCard({
inSelectModal = false,
onResultSelect,
}: VideoCardProps) {
const { setToken, setWeightTitle } = useToken();
const linkUrl = getCardUrl(data,source,type);
const handleInnerClick = (event: any) => {
@@ -39,10 +37,8 @@ export default function VideoCard({
};
const handleSelectModalResultSelect = () => {
if (inSelectModal) {
setToken(data.weight_token || data.token);
setWeightTitle && setWeightTitle(data.title);
onResultSelect && onResultSelect();
if (inSelectModal && onResultSelect) {
onResultSelect(data);
}
};
@@ -137,55 +133,6 @@ export default function VideoCard({
</div>
</>
)}
{/* {type === "weights" && (
<>
<img
src={data.public_bucket_path}
alt={data.weight_name}
className="card-video"
/>
<div className="card-img-overlay">
<div className="card-img-gradient" />
<div className="d-flex align-items-center">
<div className="d-flex flex-grow-1">
<Badge label="Video" color="purple" overlay={true} />
</div>
<Button
icon={faArrowRight}
iconFlip={true}
variant="link"
label="Use"
className="fs-7"
onClick={() => {
history.push(linkUrl);
}}
/>
</div>
<FontAwesomeIcon icon={faPlayCircle} className="card-video-play" />
<div className="card-img-overlay-text">
<div>
<h6 className="fw-semibold text-white mb-1">
{data.weight_name}
</h6>
<p className="fs-7 opacity-75">{timeAgo}</p>
<div>
<LikeButton
{...{
overlay: true,
...ratings.makeProps({
entityToken: data.weight_token,
entityType: "model_weight",
}),
}}
/>
</div>
</div>
</div>
</div>
</>
)} */}
</Card>
);
@@ -10,7 +10,7 @@ import { ListMediaFiles } from "@storyteller/components/src/api/media_files/List
interface SelectMediaListProps {
mediaType: string;
listKey: string;
onResultSelect?: () => void;
onResultSelect?: (data:{token:string, title:string}) => void;
}
export default function SelectMediaList({
@@ -4,7 +4,6 @@ import Modal from "../Modal";
import NonRouteTabs from "../Tabs/NonRouteTabs";
import Input from "../Input";
import Button from "../Button";
import useToken from "hooks/useToken";
import { faTrash } from "@fortawesome/free-solid-svg-icons";
import SelectMediaList from "./SelectMediaList";
import SelectWeightsList from "./SelectWeightsList";
@@ -21,7 +20,10 @@ interface SelectModalProps {
label?: string;
tabs: TabConfig[];
modalTitle?: string;
onSelect?: (token: string) => void;
onSelect?: (data:{
token: string,
title: string,
}) => void;
required?: boolean;
}
@@ -34,8 +36,8 @@ const SelectModal = memo(
required,
}: SelectModalProps) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const { token, setToken, weightTitle, setWeightTitle } = useToken();
const [selectedValue, setSelectedValue] = useState("");
const initialValue = {token:"", title:""};
const [selectedValue, setSelectedValue] = useState(initialValue);
const [activeTab, setActiveTab] = useState(tabs[0].tabKey);
const [mediaType, setMediaType] = useState(
tabs[0].mediaTypeFilter || "all"
@@ -51,19 +53,6 @@ const SelectModal = memo(
setWeightType(currentTab?.weightTypeFilter || "all");
}, [activeTab, tabs]);
useEffect(() => {
if (token && token !== selectedValue && onSelect) {
setSelectedValue(token);
onSelect(token);
} else if (weightTitle && weightTitle !== selectedValue && onSelect) {
setSelectedValue(weightTitle);
onSelect(weightTitle);
}
console.log("token", token, "weightTitle", weightTitle);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [token, weightTitle]);
const openModal = () => {
setIsModalOpen(true);
};
@@ -73,10 +62,18 @@ const SelectModal = memo(
};
const handleRemove = () => {
setWeightTitle && setWeightTitle("");
setToken("");
setSelectedValue(initialValue);
};
const handleOnSelect = (data:{token:string, title:string}) => {
console.log("selct modal handleOnSelect")
console.log(data);
console.log(data.title);
setSelectedValue({token: data.token, title: data.title || ""});
if (onSelect) onSelect(data);
closeModal();
}
const searchTabs = tabs.map(tab => ({
label: tab.label,
content: tab.searcher ? (
@@ -92,14 +89,14 @@ const SelectModal = memo(
<SelectMediaList
mediaType={mediaType}
listKey={tab.tabKey}
onResultSelect={closeModal}
onResultSelect={handleOnSelect}
/>
)}
{tab.type === "weights" && (
<SelectWeightsList
weightType={weightType}
listKey={tab.tabKey}
onResultSelect={closeModal}
onResultSelect={handleOnSelect}
/>
)}
</>
@@ -122,10 +119,12 @@ const SelectModal = memo(
disabled={true}
className="w-100"
placeholder="None selected"
value={weightTitle ? weightTitle : token || ""}
value={selectedValue.title !==""
? selectedValue.title
: selectedValue.token || ""}
/>
<Button label={token ? "Change" : "Select"} onClick={openModal} />
{token && (
<Button label={selectedValue.token !== "" ? "Change" : "Select"} onClick={openModal} />
{selectedValue.token && (
<Button
square={true}
variant="danger"
@@ -10,7 +10,7 @@ import { Weight } from "@storyteller/components/src/api/weights/GetWeight";
interface SelectWeightsListProps {
weightType: string;
listKey: string;
onResultSelect?: () => void;
onResultSelect?: (data:{token:string, title:string}) => void;
}
export default function SelectWeightsList({
@@ -0,0 +1 @@
export { default } from "./SelectModal";
@@ -1,3 +1,4 @@
import Accordion from "./Accordion";
import AudioBlobPreview from "./AudioBlobPreview";
import AudioInput from "./AudioInput";
import BasicVideo from "./BasicVideo";
@@ -20,6 +21,7 @@ import Panel from "./Panel";
import Radio from "./Radio";
import SegmentButtons from "./SegmentButtons";
import Select from "./Select";
import SelectModal from "./SelectModal";
import Skeleton from "./Skeleton";
import Slider from "./Slider";
import Spinner from "./Spinner";
@@ -35,6 +37,7 @@ import TintSpinner from "./TintSpinner";
import VideoInput from "./VideoInput";
export {
Accordion,
AudioBlobPreview,
AudioInput,
BasicVideo,
@@ -57,6 +60,7 @@ export {
Radio,
SegmentButtons,
Select,
SelectModal,
Skeleton,
Slider,
Spinner,
@@ -5,10 +5,12 @@ import { useMedia } from "hooks";
import { BucketConfig } from "@storyteller/components/src/api/BucketConfig";
import { states, Action, State } from "../storytellerFilterReducer";
import {
Accordion,
BasicVideo,
ErrorMessage,
NumberSliderV2,
Panel,
SelectModal,
Spinner,
TextAreaV2
} from "components/common";
@@ -38,6 +40,8 @@ export default function PageFilterControls({
});
const [filterState, setFilterState] = useState({
sdModelToken: "",
loraModelToken: "",
posPrompt: "",
negPrompt: "",
firstPass: 15,
@@ -53,68 +57,115 @@ export default function PageFilterControls({
if (mediaLink)
return(
<>
<Panel>
<div className="row g-3 p-3">
{/* <h1>{t("message.fileUploaded")}</h1> */}
{debug && <p>{`File Token: ${pageState.mediaFileToken}`}</p> }
<div className="col-5">
<BasicVideo src={mediaLink} />
<Panel>
<div className="row g-3 p-3">
{/* <h1>{t("message.fileUploaded")}</h1> */}
{debug && <p>{`File Token: ${pageState.mediaFileToken}`}</p> }
<div className="col-5">
<BasicVideo src={mediaLink} />
</div>
<div className="col-1 d-flex align-items-center justify-items-center">
<FontAwesomeIcon icon={faChevronRight} className="fa-6x"/>
</div>
<div className="col-6">
<BasicVideo src={mediaLink} />
</div>
</div>
<div className="col-1 d-flex align-items-center justify-items-center">
<FontAwesomeIcon icon={faChevronRight} className="fa-6x"/>
</div>
<div className="col-6">
<BasicVideo src={mediaLink} />
</div>
</div>
</Panel>
<Panel className="mt-4">
<div className="row g-3 p-3">
<p>Select A Stable Diffusion Model</p>
<br />
<p>Select A LoRA</p>
<TextAreaV2
{...{
label: "Prompt",
placeholder: "Enter a prompt",
onChange: (val:string)=>handleOnChange("posPrompt", val),
value: filterState.posPrompt,
required: false,
}}
/>
<TextAreaV2
{...{
label: "Negative Prompt",
placeholder: "Enter Negative Prompt",
onChange: (val:string)=>handleOnChange("negPrompt", val),
value: filterState.negPrompt,
required: false,
}}
/>
</div>
</Panel>
<Panel className="mt-4">
<div className="row g-3 p-3">
<NumberSliderV2 {...{
min: 1,
max: 30,
step: 0.5,
initialValue: filterState.firstPass,
label: " Denoise First Pass",
thumbTip: "Denoise First Pass",
onChange: (val)=>{handleOnChange("firstPass",val)}
}}/>
<NumberSliderV2 {...{
min: 1,
max: 30,
initialValue: filterState.upScalePass,
label: "Denoise Upscale Pass",
thumbTip: "Denoise Upscale Pass",
onChange: (val)=>{handleOnChange("upScalePass", val)}
}}/>
<br />
</div>
</Panel>
</Panel>
<Accordion className="mt-4">
<Accordion.Item title={t("heading1")}>
<div className="row g-3 p-3">
<SelectModal
modalTitle="Select a Stable Diffusion Weight"
label="Select a Stable Diffusion Weight"
onSelect={({token})=>{
console.log(`calling from select modal result select ${token}`);
handleOnChange("sdModelToken", token);
}}
tabs={[
{
label: "All Weights",
tabKey: "allWeights",
weightTypeFilter: "sdxl",
searcher: true,
type: "weights",
},
{
label: "Bookmarked",
tabKey: "bookmarkedWeights",
weightTypeFilter: "sdxl",
searcher: false,
type: "weights",
},
]}
/>
<SelectModal
modalTitle="Select a LoRA Weight"
label="Additional LoRA Weight"
onSelect={({token})=>{
console.log(`calling from select modal result select ${token}`);
handleOnChange("loraModelToken", token);
}}
tabs={[
{
label: "All LoRA Weights",
tabKey: "allLoraWeights",
weightTypeFilter: "rvc_v2",
searcher: true,
type: "weights",
},
{
label: "Bookmarked",
tabKey: "bookmarkedLoraWeights",
weightTypeFilter: "rvc_v2",
searcher: false,
type: "weights",
},
]}
/>
<TextAreaV2
{...{
label: "Prompt",
placeholder: "Enter a prompt",
onChange: (val:string)=>handleOnChange("posPrompt", val),
value: filterState.posPrompt,
required: false,
}}
/>
<TextAreaV2
{...{
label: "Negative Prompt",
placeholder: "Enter Negative Prompt",
onChange: (val:string)=>handleOnChange("negPrompt", val),
value: filterState.negPrompt,
required: false,
}}
/>
</div>
</Accordion.Item>
<Accordion.Item title={t("headings2")}>
<div className="row g-3 p-3">
<NumberSliderV2 {...{
min: 1,
max: 30,
step: 0.5,
initialValue: filterState.firstPass,
label: " Denoise First Pass",
thumbTip: "Denoise First Pass",
onChange: (val)=>{handleOnChange("firstPass",val)}
}}/>
<NumberSliderV2 {...{
min: 1,
max: 30,
initialValue: filterState.upScalePass,
label: "Denoise Upscale Pass",
thumbTip: "Denoise Upscale Pass",
onChange: (val)=>{handleOnChange("upScalePass", val)}
}}/>
<br />
</div>
</Accordion.Item>
</Accordion>
</>
);
}else if (pageState.status <= states.FILE_LOADING){
@@ -14,10 +14,10 @@ export default function TabContentLibrary({
const handleProceed = ()=>{
dispatchPageState({type: "loadFile"})
}
const handleOnSelect = (token:string)=>{
const handleOnSelect = (data:{token:string, title:string})=>{
dispatchPageState({
type: "selectedFile",
payload: {mediaFileToken: token}
payload: {mediaFileToken: data.token}
});
};
return (
@@ -1,4 +1,5 @@
import React from "react";
import { Redirect } from "react-router-dom";
import { v4 as uuidv4 } from "uuid";
import { UploadMedia } from "@storyteller/components/src/api/media_files/UploadMedia";
@@ -15,7 +16,7 @@ export default function TabContentUpload({
dispatchPageState: (action: Action) => void;
}) {
const videoProps = useFile({});
const {NO_FILE, FILE_STAGED, FILE_UPLOADING} = states;
const {NO_FILE, FILE_STAGED, FILE_UPLOADING, FILE_UPLOADED} = states;
const makeVideoUploadRequest = () => ({
uuid_idempotency_token: uuidv4(),
@@ -85,6 +86,10 @@ export default function TabContentUpload({
</div>
</div>
);
}else if (pageState.status === FILE_UPLOADED){
return(
<Redirect to={`load/${pageState.mediaFileToken}`}/>
)
}
return <ErrorMessage />;
}
@@ -20,8 +20,8 @@ export default function TabContentLibrary({
payload: { mediaFileToken: token },
});
};
const handleOnSelect = (token: string) => {
setToken(token);
const handleOnSelect = (data:{token:string,title:string}) => {
setToken(data.token);
};
return (
@@ -1,16 +1,17 @@
import React, { useRef, useState, memo } from "react";
import {
Accordion,
Button,
Input,
Label,
NumberSlider,
Panel,
SegmentButtons,
SelectModal,
TempSelect,
TempTextArea,
} from "components/common";
import { onChanger } from "resources";
import Accordion from "components/common/Accordion";
import {
faRectangleLandscape,
faRectanglePortrait,
@@ -23,7 +24,6 @@ import {
EnqueueImageGenIsError,
} from "@storyteller/components/src/api/image_generation/EnqueueImageGen";
import { FrontendInferenceJobType } from "@storyteller/components/src/jobs/InferenceJob";
import SelectModal from "components/common/SelectModal/SelectModal";
import { SessionSubscriptionsWrapper } from "@storyteller/components/src/session/SessionSubscriptionsWrapper";
import PremiumLock from "components/PremiumLock";
@@ -46,12 +46,11 @@ function SdInferencePanel({
const [loraToken, setLoraToken] = useState<string | null>(null);
const [weightToken, setWeightToken] = useState(sd_model_token);
const handleOnWeightSelect = (token: string) => {
setWeightToken(token);
const handleOnWeightSelect = (data:{token:string,title:string}) => {
setLoraToken(data.token);
};
const handleOnSelect = (token: string) => {
setLoraToken(token);
const handleOnSelect = (data:{token:string,title:string}) => {
setLoraToken(data.token);
};
const [isEnqueuing, setIsEnqueuing] = useState(false);