mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-06 02:00:46 +00:00
Merge pull request #499 from storytold/fixes/select_modal_overhaul
Fixes/select modal overhaul
This commit is contained in:
20 files changed
+679
-85
No files matched your search
@@ -0,0 +1,23 @@
|
||||
import {
|
||||
MediaFileType,
|
||||
GetMediaByUser
|
||||
} from "./media_files";
|
||||
|
||||
import {
|
||||
Weight,
|
||||
ListWeights
|
||||
} from "./weights";
|
||||
|
||||
import {
|
||||
GetBookmarksByUser
|
||||
} from "./bookmarks/GetBookmarksByUser";
|
||||
|
||||
export type{
|
||||
MediaFileType,
|
||||
Weight
|
||||
}
|
||||
export {
|
||||
GetBookmarksByUser,
|
||||
GetMediaByUser,
|
||||
ListWeights
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import { MediaFile } from "./GetMediaFile";
|
||||
import { GetMediaByUser } from "./GetMediaByUser";
|
||||
|
||||
|
||||
export type{
|
||||
MediaFile as MediaFileType
|
||||
}
|
||||
export {
|
||||
GetMediaByUser
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { ListWeights } from "./ListWeights";
|
||||
import { Weight } from "./GetWeight";
|
||||
|
||||
export type { Weight };
|
||||
export { ListWeights };
|
||||
@@ -1 +1,10 @@
|
||||
export { default } from "./Card";
|
||||
import MediaCards from "./MediaCards";
|
||||
import WeightsCards from "./WeightsCards";
|
||||
import SkeletonCard from "./SkeletonCard";
|
||||
import Card from "./Card";
|
||||
export {
|
||||
Card as default,
|
||||
MediaCards,
|
||||
SkeletonCard,
|
||||
WeightsCards
|
||||
};
|
||||
@@ -13,9 +13,11 @@ interface PaginationComponentProps {
|
||||
pageCount: number
|
||||
}
|
||||
|
||||
export default function Pagination({ currentPage, onPageChange, pageCount }: PaginationComponentProps) {
|
||||
// const pageCount = Math.ceil(totalItems / itemsPerPage);
|
||||
|
||||
export default function Pagination({
|
||||
currentPage,
|
||||
onPageChange,
|
||||
pageCount
|
||||
}: PaginationComponentProps) {
|
||||
return (
|
||||
<ReactPaginate
|
||||
previousLabel={<FontAwesomeIcon icon={faChevronLeft} />}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
import React, {
|
||||
memo,
|
||||
ReactNode,
|
||||
useEffect,
|
||||
useState,
|
||||
} from "react";
|
||||
|
||||
import {
|
||||
Button,
|
||||
TempInput as Input,
|
||||
Modal,
|
||||
} from "components/common";
|
||||
|
||||
import { faTrash } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
export type SelectModalData = {
|
||||
token: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
interface SelectModalProps {
|
||||
label?: string;
|
||||
modalTitle?: string;
|
||||
value?: string;
|
||||
onClear: () => void;
|
||||
required?: boolean;
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export default memo(function SelectModal ({
|
||||
label,
|
||||
// tabs,
|
||||
modalTitle = "Select",
|
||||
onClear,
|
||||
value = "",
|
||||
required,
|
||||
children
|
||||
}: SelectModalProps) {
|
||||
const [isModalOpen, setModalOpen] = useState(false
|
||||
)
|
||||
const openModal = () => {
|
||||
setModalOpen(true);
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
setModalOpen(false);
|
||||
};
|
||||
|
||||
useEffect(closeModal, [value]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
{label && (
|
||||
<label className={`sub-title ${required && "required"}`.trim()}>
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
|
||||
<div className="d-flex gap-2 position-relative">
|
||||
<div
|
||||
className="position-absolute w-100 h-100"
|
||||
style={{"cursor": "pointer"}}
|
||||
onClick={openModal}
|
||||
/>
|
||||
<Input
|
||||
disabled={true}
|
||||
wrapperClassName="w-100"
|
||||
placeholder="None selected"
|
||||
onClick={openModal}
|
||||
value={value}
|
||||
/>
|
||||
|
||||
<Button label={value !== "" ? "Change" : "Select"} onClick={openModal} />
|
||||
{value && (
|
||||
<Button
|
||||
square={true}
|
||||
variant="danger"
|
||||
icon={faTrash}
|
||||
onClick={onClear}
|
||||
tooltip="Remove"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
show={isModalOpen}
|
||||
handleClose={closeModal}
|
||||
title={modalTitle}
|
||||
content={()=>{return(<>{children}</>)}}
|
||||
showButtons={false}
|
||||
padding={false}
|
||||
large={true}
|
||||
position="top"
|
||||
mobileFullscreen={true}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
);
|
||||
@@ -1 +1,5 @@
|
||||
export { default } from "./SelectModal";
|
||||
import SelectModal from "./SelectModal";
|
||||
import SelectModalV2, { SelectModalData } from "./SelectModalV2";
|
||||
|
||||
export type { SelectModalData };
|
||||
export { SelectModal as default, SelectModalV2 };
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
import React, { memo, useRef, useState } from "react";
|
||||
|
||||
import { useListContent, useSession } from "hooks";
|
||||
|
||||
import {
|
||||
MediaFileType,
|
||||
GetMediaByUser
|
||||
} from "@storyteller/components/src/api";
|
||||
|
||||
import {
|
||||
MasonryGrid,
|
||||
MediaCards,
|
||||
Pagination,
|
||||
SkeletonCard,
|
||||
NonRouteTabs
|
||||
} from "components/common";
|
||||
|
||||
import { SelectModalData, SelectModalV2} from "../SelectModal";
|
||||
|
||||
import prepFilter from "resources/prepFilter";
|
||||
|
||||
export default memo(function SelectModalWrapper({
|
||||
debug = false,
|
||||
value = "",
|
||||
modalTitle,
|
||||
inputLabel,
|
||||
onSelect
|
||||
}: {
|
||||
debug?: boolean;
|
||||
value?: string;
|
||||
modalTitle: string;
|
||||
inputLabel: string;
|
||||
onSelect: (data:SelectModalData) => void;
|
||||
}) {
|
||||
const tabs = [{
|
||||
label: "All Videos",
|
||||
content: (
|
||||
<div className="searcher-container in-modal m-4" id="allVideos">
|
||||
<VideoTabsContent debug={debug} onSelect={onSelect}/>
|
||||
</div>
|
||||
)
|
||||
}]
|
||||
return (
|
||||
<SelectModalV2
|
||||
modalTitle={modalTitle}
|
||||
label={inputLabel}
|
||||
value={value}
|
||||
onClear={()=>{onSelect({title:"",token:""})}}
|
||||
>
|
||||
<NonRouteTabs tabs={tabs} />
|
||||
</SelectModalV2>
|
||||
);
|
||||
});
|
||||
|
||||
function VideoTabsContent({
|
||||
debug=false,
|
||||
onSelect
|
||||
}:{
|
||||
debug?: boolean
|
||||
onSelect: (data:SelectModalData) => void;
|
||||
}){
|
||||
const gridContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const [list, listSet] = useState<MediaFileType[]>([]);
|
||||
const { user } = useSession();
|
||||
const media = useListContent({
|
||||
addQueries: {
|
||||
page_size: 9,
|
||||
...prepFilter("video", "filter_media_type"),
|
||||
},
|
||||
urlUpdate: false,
|
||||
debug: debug ? "Video List" : undefined,
|
||||
fetcher: GetMediaByUser,
|
||||
list,
|
||||
listSet,
|
||||
requestList: true,
|
||||
urlParam: user?.username || ""
|
||||
});
|
||||
const handlePageClick = (selectedItem: { selected: number }) => {
|
||||
media.pageChange(selectedItem.selected);
|
||||
};
|
||||
|
||||
const paginationProps = {
|
||||
onPageChange: handlePageClick,
|
||||
pageCount: media.pageCount+1, // account for index 0
|
||||
currentPage: media.page,
|
||||
};
|
||||
if (media.isLoading){
|
||||
return (
|
||||
<div className="row gx-3 gy-3">
|
||||
{Array.from({ length: 12 }).map((_, index) => (
|
||||
<SkeletonCard key={index} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}else if (media.list.length === 0 && media.status === 3){
|
||||
return(
|
||||
<div className="text-center m-4 opacity-75">
|
||||
No media created yet.
|
||||
</div>
|
||||
);
|
||||
}else {
|
||||
return(
|
||||
<>
|
||||
{paginationProps.pageCount > 1 &&
|
||||
<div className="d-flex justify-content-end mb-4">
|
||||
<Pagination {...paginationProps} />
|
||||
</div>
|
||||
}
|
||||
<MasonryGrid
|
||||
gridRef={gridContainerRef}
|
||||
onLayoutComplete={() => {if (debug) console.log("Layout complete!")}}
|
||||
>
|
||||
{media.list.map((data: MediaFileType, key: number) => {
|
||||
let props = {
|
||||
data,
|
||||
showCreator: true,
|
||||
type: "media",
|
||||
inSelectModal: true,
|
||||
onResultSelect: onSelect,
|
||||
};
|
||||
return (
|
||||
<div
|
||||
{...{
|
||||
className: "col-12 col-sm-6 col-xl-4 grid-item",
|
||||
key,
|
||||
}}
|
||||
>
|
||||
<MediaCards {...{ type: data.media_type, props }} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</MasonryGrid>
|
||||
{paginationProps.pageCount > 1 &&
|
||||
<div className="d-flex justify-content-end mt-4">
|
||||
<Pagination {...paginationProps} />
|
||||
</div>
|
||||
}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "./SelectModalVideoTabs";
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
import React, { memo } from "react";
|
||||
|
||||
import { NonRouteTabs } from "components/common";
|
||||
import { SelectModalData, SelectModalV2} from "../SelectModal";
|
||||
import TabAllWeights from "./tabAllWeights";
|
||||
import TabBookmarkedWeights from "./tabBookmarkedWeights"
|
||||
|
||||
export default memo(function SelectModalWrapper({
|
||||
debug = false,
|
||||
value = {title:"",token:""},
|
||||
modalTitle,
|
||||
inputLabel,
|
||||
weightType,
|
||||
onSelect
|
||||
}: {
|
||||
debug?: boolean;
|
||||
value?: SelectModalData;
|
||||
modalTitle: string;
|
||||
inputLabel: string;
|
||||
weightType: "sd_1.5" | "loRA";
|
||||
onSelect: (data:SelectModalData) => void;
|
||||
}) {
|
||||
const tabs = [{
|
||||
label: "All Weights",
|
||||
content: (
|
||||
<div className="searcher-container in-modal m-4" id="allWeights">
|
||||
<TabAllWeights {...{debug, onSelect, weightType}}/>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: "Bookmarked Weights",
|
||||
content: (
|
||||
<div className="searcher-container in-modal m-4" id="allWeights">
|
||||
<TabBookmarkedWeights {...{debug, onSelect, weightType}}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
]
|
||||
return (
|
||||
<SelectModalV2
|
||||
modalTitle={modalTitle}
|
||||
label={inputLabel}
|
||||
value={value.title || value.token}
|
||||
onClear={()=>{onSelect({title:"",token:""})}}
|
||||
>
|
||||
<NonRouteTabs tabs={tabs} />
|
||||
</SelectModalV2>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "./SelectModalWeightsTabs";
|
||||
@@ -0,0 +1,124 @@
|
||||
import React, {useRef, useState} from 'react';
|
||||
import {
|
||||
useBookmarks,
|
||||
useLazyLists,
|
||||
useRatings,
|
||||
// useSession
|
||||
} from "hooks";
|
||||
import {
|
||||
Weight as WeightI,
|
||||
ListWeights
|
||||
} from "@storyteller/components/src/api";
|
||||
import { SelectModalData } from "../SelectModal";
|
||||
import prepFilter from "resources/prepFilter";
|
||||
import {
|
||||
MasonryGrid,
|
||||
WeightsCards,
|
||||
Pagination,
|
||||
SkeletonCard,
|
||||
} from "components/common";
|
||||
|
||||
export default function WeightsTabsContent({
|
||||
debug=false,
|
||||
weightType,
|
||||
onSelect
|
||||
}:{
|
||||
debug?: boolean
|
||||
weightType: "sd_1.5" | "loRA";
|
||||
onSelect: (data:SelectModalData) => void;
|
||||
}){
|
||||
const gridContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const bookmarks = useBookmarks();
|
||||
const ratings = useRatings();
|
||||
const [list, listSet] = useState<WeightI[]>([]);
|
||||
const [pages, setPages] = useState<{
|
||||
currPageWeights: any[],
|
||||
lookup: string[]
|
||||
}>({
|
||||
currPageWeights: [],
|
||||
lookup: []
|
||||
});
|
||||
|
||||
const weights = useLazyLists({
|
||||
addQueries: {
|
||||
page_size: 9,
|
||||
...prepFilter(weightType, "weight_type"),
|
||||
},
|
||||
fetcher: ListWeights,
|
||||
onSuccess: (res)=>{
|
||||
setPages((curr)=>{
|
||||
return{
|
||||
currPageWeights: [...res.results],
|
||||
lookup: [...curr.lookup, res.pagination.maybe_next]
|
||||
}
|
||||
})
|
||||
},
|
||||
list,
|
||||
listSet,
|
||||
requestList: true,
|
||||
urlUpdate: false,
|
||||
});
|
||||
|
||||
|
||||
const handlePageClick = (selectedItem: { selected: number }) => {
|
||||
weights.getMore();
|
||||
};
|
||||
|
||||
const paginationProps = {
|
||||
onPageChange: handlePageClick,
|
||||
pageCount: pages.lookup.length+1,
|
||||
currentPage: 0,
|
||||
};
|
||||
if (weights.isLoading){
|
||||
return (
|
||||
<div className="row gx-3 gy-3">
|
||||
{Array.from({ length: 12 }).map((_, index) => (
|
||||
<SkeletonCard key={index} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}else if (weights.list.length === 0 && weights.status === 3){
|
||||
return(
|
||||
<div className="text-center m-4 opacity-75">
|
||||
No weights created yet.
|
||||
</div>
|
||||
);
|
||||
}else {
|
||||
return(
|
||||
<>
|
||||
<div className="d-flex justify-content-end mb-4">
|
||||
<Pagination {...paginationProps} />
|
||||
</div>
|
||||
<MasonryGrid
|
||||
gridRef={gridContainerRef}
|
||||
// onLayoutComplete={() => console.log("Layout complete!")}
|
||||
>
|
||||
{pages.currPageWeights.map((data: any, key: number) => {
|
||||
let props = {
|
||||
data,
|
||||
ratings,
|
||||
bookmarks,
|
||||
showCreator: true,
|
||||
type: "weights",
|
||||
inSelectModal: true,
|
||||
onResultSelect: onSelect,
|
||||
};
|
||||
return (
|
||||
<div
|
||||
{...{
|
||||
className: "col-12 col-sm-6 col-xl-4 grid-item",
|
||||
key,
|
||||
}}
|
||||
>
|
||||
<WeightsCards {...{ type: data.weight_category, props }} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</MasonryGrid>
|
||||
<div className="d-flex justify-content-end mt-4">
|
||||
<Pagination {...paginationProps} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
import React, {useRef, useState} from 'react';
|
||||
import {
|
||||
// useBookmarks,
|
||||
useListContent,
|
||||
useRatings,
|
||||
useSession
|
||||
} from "hooks";
|
||||
import {
|
||||
Weight as WeightI,
|
||||
GetBookmarksByUser
|
||||
} from "@storyteller/components/src/api";
|
||||
import { SelectModalData } from "../SelectModal";
|
||||
import prepFilter from "resources/prepFilter";
|
||||
import {
|
||||
MasonryGrid,
|
||||
WeightsCards,
|
||||
Pagination,
|
||||
SkeletonCard,
|
||||
} from "components/common";
|
||||
|
||||
export default function WeightsTabsContent({
|
||||
debug=false,
|
||||
weightType,
|
||||
onSelect
|
||||
}:{
|
||||
debug?: boolean;
|
||||
weightType: "sd_1.5" | "loRA";
|
||||
onSelect: (data:SelectModalData) => void;
|
||||
}){
|
||||
const gridContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
// const bookmarks = useBookmarks();
|
||||
const ratings = useRatings();
|
||||
const [list, listSet] = useState<WeightI[]>([]);
|
||||
const { user } = useSession();
|
||||
const weights = useListContent({
|
||||
addQueries: {
|
||||
page_size: 9,
|
||||
...prepFilter(weightType, "weight_type"),
|
||||
},
|
||||
urlUpdate: false,
|
||||
debug: debug ? "Bookmarked Weights" : undefined,
|
||||
fetcher: GetBookmarksByUser,
|
||||
list,
|
||||
listSet,
|
||||
requestList: true,
|
||||
urlParam: user?.username || ""
|
||||
});
|
||||
const handlePageClick = (selectedItem: { selected: number }) => {
|
||||
weights.pageChange(selectedItem.selected);
|
||||
};
|
||||
console.log("BOOKMARKED");
|
||||
console.log(weights);
|
||||
const paginationProps = {
|
||||
onPageChange: handlePageClick,
|
||||
pageCount: weights.pageCount + 1,
|
||||
currentPage: weights.page,
|
||||
};
|
||||
if (weights.isLoading){
|
||||
return (
|
||||
<div className="row gx-3 gy-3">
|
||||
{Array.from({ length: 12 }).map((_, index) => (
|
||||
<SkeletonCard key={index} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}else if (weights.list.length === 0 && weights.status === 3){
|
||||
return(
|
||||
<div className="text-center m-4 opacity-75">
|
||||
No weights created yet.
|
||||
</div>
|
||||
);
|
||||
}else {
|
||||
return(
|
||||
<>
|
||||
{paginationProps.pageCount > 1 &&
|
||||
<div className="d-flex justify-content-end mb-4">
|
||||
<Pagination {...paginationProps} />
|
||||
</div>
|
||||
}
|
||||
<MasonryGrid
|
||||
gridRef={gridContainerRef}
|
||||
onLayoutComplete={() => console.log("Layout complete!")}
|
||||
>
|
||||
{weights.list.map((data: any, key: number) => {
|
||||
//TODO: data should be TYPED
|
||||
let props = {
|
||||
data,
|
||||
ratings,
|
||||
// bookmarks,
|
||||
showCreator: true,
|
||||
type: "weights",
|
||||
inSelectModal: true,
|
||||
onResultSelect: onSelect,
|
||||
};
|
||||
return (
|
||||
<div
|
||||
{...{
|
||||
className: "col-12 col-sm-6 col-xl-4 grid-item",
|
||||
key,
|
||||
}}
|
||||
>
|
||||
<WeightsCards {...{
|
||||
type: data.details.maybe_weight_data.weight_category, props }} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</MasonryGrid>
|
||||
{paginationProps.pageCount > 1 &&
|
||||
<div className="d-flex justify-content-end mt-4">
|
||||
<Pagination {...paginationProps} />
|
||||
</div>
|
||||
}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1 +1,3 @@
|
||||
export { default } from "./Tabs";
|
||||
import Tabs from "./Tabs";
|
||||
import NonRouteTabs from "./NonRouteTabs";
|
||||
export { Tabs as default, NonRouteTabs };
|
||||
@@ -5,6 +5,11 @@ import Badge from "./Badge";
|
||||
import Button from "./Button";
|
||||
import ButtonRevertToDefault from "./ButtonRevertToDefault";
|
||||
import Checkbox from "./Checkbox";
|
||||
import {
|
||||
MediaCards,
|
||||
SkeletonCard,
|
||||
WeightsCards,
|
||||
} from "./Card";
|
||||
import Container from "./Container";
|
||||
import CoverImageInput from "./CoverImageInput";
|
||||
import ErrorMessage from "./ErrorMessage"
|
||||
@@ -18,12 +23,14 @@ import InputSeed from "./InputSeed";
|
||||
import Label from "./Label";
|
||||
import LikeButton from "./LikeButton";
|
||||
import MocapInput from "./MocapInput";
|
||||
import MasonryGrid from "./MasonryGrid/MasonryGrid";
|
||||
import Modal from "./Modal";
|
||||
import NumberSlider from "./NumberSlider";
|
||||
import NumberSliderV2 from "./NumberSliderV2";
|
||||
import Pagination from "./Pagination";
|
||||
import Panel from "./Panel";
|
||||
import Radio from "./Radio";
|
||||
import Searcher from "./Searcher";
|
||||
import SegmentButtons from "./SegmentButtons";
|
||||
import Select from "./Select";
|
||||
import SelectModal from "./SelectModal";
|
||||
@@ -31,7 +38,7 @@ import Skeleton from "./Skeleton";
|
||||
import Slider from "./Slider";
|
||||
import Spinner from "./Spinner";
|
||||
import SplitPanel from "./SplitPanel";
|
||||
import Tabs from "./Tabs";
|
||||
import Tabs, {NonRouteTabs} from "./Tabs";
|
||||
import TempAudioPlayer from "./TempAudioPlayer";
|
||||
import TempInput from "./TempInput";
|
||||
import TempSelect from "./TempSelect";
|
||||
@@ -49,6 +56,11 @@ export {
|
||||
AudioInput,
|
||||
Badge,
|
||||
Button,
|
||||
//Cards
|
||||
MediaCards,
|
||||
SkeletonCard,
|
||||
WeightsCards,
|
||||
//End Cards
|
||||
ButtonRevertToDefault,
|
||||
Checkbox,
|
||||
Container,
|
||||
@@ -64,13 +76,16 @@ export {
|
||||
Label,
|
||||
LikeButton,
|
||||
MocapInput,
|
||||
MasonryGrid,
|
||||
Modal,
|
||||
NonRouteTabs,
|
||||
NumberSlider,
|
||||
NumberSliderV2,
|
||||
Pagination,
|
||||
Panel,
|
||||
Radio,
|
||||
SegmentButtons,
|
||||
Searcher,
|
||||
Select,
|
||||
SelectModal,
|
||||
Skeleton,
|
||||
|
||||
+27
-30
@@ -16,6 +16,8 @@ import {
|
||||
TextArea
|
||||
} from "components/common";
|
||||
|
||||
import SelectModalWeightsTabs from "components/common/SelectModalWeightsTabs";
|
||||
|
||||
import SectionControlNets, {ControlNetsInitialValues as CnIvs} from "./sectionControlNets";
|
||||
import SectionVideoSettings, {VideoSettingsInitialValues as VideoIvs} from "./sectionVideoSettings";
|
||||
import SectionAdvanceOptions, {AdvanceOptionsInitialValues as AdvIvs} from "./sectionAdvanceOptions";
|
||||
@@ -63,8 +65,8 @@ export default function PageFilterControls({
|
||||
...CnIvs
|
||||
});
|
||||
|
||||
const handleOnChange = (key: string, newValue:any,) => {
|
||||
setWorkflowValues((curr)=>({...curr, [key]: newValue}));
|
||||
const handleOnChange = (val:{[key: string]: number|string|boolean|undefined}) => {
|
||||
setWorkflowValues((curr)=>({...curr, ...val}));
|
||||
}
|
||||
const handleReset = ()=>{
|
||||
setWorkflowValues((curr)=>({
|
||||
@@ -132,7 +134,7 @@ export default function PageFilterControls({
|
||||
<div className="col-6">
|
||||
<SectionVideoSettings
|
||||
workflowValues={workflowValues}
|
||||
onChange={(key,val)=>handleOnChange(key,val)}
|
||||
onChange={handleOnChange}
|
||||
videoElement={videoRef?.current}
|
||||
/>
|
||||
<div className="d-flex my-3 justify-content-end">
|
||||
@@ -164,37 +166,32 @@ export default function PageFilterControls({
|
||||
<Accordion className="mt-4">
|
||||
<Accordion.Item title={"Basics"} defaultOpen>
|
||||
<div className="row g-3 p-3">
|
||||
<SelectModal
|
||||
<SelectModalWeightsTabs
|
||||
modalTitle="Select a Stable Diffusion Weight"
|
||||
label="Select a Stable Diffusion Weight"
|
||||
onSelect={({token})=>{
|
||||
handleOnChange("sdModelToken", token);
|
||||
inputLabel="Select a Stable Diffusion Weight"
|
||||
weightType="sd_1.5"
|
||||
onSelect={({title,token})=>{
|
||||
handleOnChange({
|
||||
"sdModelTitle": title,
|
||||
"sdModelToken": token,
|
||||
});
|
||||
}}
|
||||
value={{
|
||||
token:workflowValues.sdModelToken,
|
||||
title:""
|
||||
}}
|
||||
tabs={[
|
||||
{
|
||||
label: "All Weights",
|
||||
tabKey: "allWeights",
|
||||
typeFilter: "sd_1.5",
|
||||
searcher: true,
|
||||
type: "weights",
|
||||
},
|
||||
{
|
||||
label: "Bookmarked",
|
||||
tabKey: "bookmarkedWeights",
|
||||
typeFilter: "sd_1.5",
|
||||
searcher: false,
|
||||
type: "weights",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div className="row g-3 p-3">
|
||||
<SelectModal
|
||||
modalTitle="Select a LoRA Weight"
|
||||
label="Additional LoRA Weight"
|
||||
onSelect={({token})=>{
|
||||
onSelect={({title,token})=>{
|
||||
console.log(`calling from select modal result select ${token}`);
|
||||
handleOnChange("loraModelToken", token);
|
||||
handleOnChange({
|
||||
"loraModelTitle": title,
|
||||
"loraModelToken": token
|
||||
});
|
||||
}}
|
||||
tabs={[
|
||||
{
|
||||
@@ -220,7 +217,7 @@ export default function PageFilterControls({
|
||||
{...{
|
||||
label: "Prompt",
|
||||
placeholder: "Enter a prompt",
|
||||
onChange: (e:React.ChangeEvent<HTMLTextAreaElement>)=>handleOnChange("posPrompt", e.target.value),
|
||||
onChange: (e:React.ChangeEvent<HTMLTextAreaElement>)=>handleOnChange({"posPrompt": e.target.value}),
|
||||
value: workflowValues.posPrompt,
|
||||
required: false,
|
||||
}}
|
||||
@@ -231,7 +228,7 @@ export default function PageFilterControls({
|
||||
{...{
|
||||
label: "Negative Prompt",
|
||||
placeholder: "Enter Negative Prompt",
|
||||
onChange: (e:React.ChangeEvent<HTMLTextAreaElement>)=>handleOnChange("negPrompt", e.target.value),
|
||||
onChange: (e:React.ChangeEvent<HTMLTextAreaElement>)=>handleOnChange({"negPrompt": e.target.value}),
|
||||
value: workflowValues.negPrompt,
|
||||
required: false,
|
||||
}}
|
||||
@@ -240,7 +237,7 @@ export default function PageFilterControls({
|
||||
</div>
|
||||
<div className="row g-3 p-3">
|
||||
<InputSeed label="Seed" onChange={
|
||||
(val:string)=>handleOnChange("seed", val)
|
||||
(val:string)=>handleOnChange({seed: val})
|
||||
}/>
|
||||
</div>
|
||||
|
||||
@@ -248,13 +245,13 @@ export default function PageFilterControls({
|
||||
<Accordion.Item title="Advance" defaultOpen>
|
||||
<SectionAdvanceOptions
|
||||
workflowValues={workflowValues}
|
||||
onChange={(key,val)=>handleOnChange(key,val)}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
</Accordion.Item>
|
||||
<Accordion.Item title="Control Nets" defaultOpen>
|
||||
<SectionControlNets
|
||||
workflowValues={workflowValues}
|
||||
onChange={(key,val)=>handleOnChange(key,val)}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
|
||||
+11
-11
@@ -23,7 +23,7 @@ export default memo( function SectionAdvanceOptions({
|
||||
onChange : handleOnChange
|
||||
} : {
|
||||
workflowValues : WorkflowValuesType
|
||||
onChange: (key:string, val:number|boolean)=>void}
|
||||
onChange: (val:{[key: string]: number|string|boolean})=>void}
|
||||
){
|
||||
|
||||
return(
|
||||
@@ -35,7 +35,7 @@ export default memo( function SectionAdvanceOptions({
|
||||
initialValue: wfVal.firstPass,
|
||||
label: " Denoise First Pass",
|
||||
thumbTip: "Denoise First Pass",
|
||||
onChange: (val)=>{handleOnChange("firstPass",val)}
|
||||
onChange: (val)=>{handleOnChange({firstPass:val})}
|
||||
}}/>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
@@ -44,7 +44,7 @@ export default memo( function SectionAdvanceOptions({
|
||||
initialValue: wfVal.upscalePass,
|
||||
label: "Denoise Upscale Pass",
|
||||
thumbTip: "Denoise Upscale Pass",
|
||||
onChange: (val)=>{handleOnChange("upscalePass", val)}
|
||||
onChange: (val)=>{handleOnChange({upscalePass: val})}
|
||||
}}/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -55,7 +55,7 @@ export default memo( function SectionAdvanceOptions({
|
||||
initialValue: wfVal.motionScale,
|
||||
label: "Motion Scale",
|
||||
thumbTip: "Motion Scale",
|
||||
onChange: (val)=>{handleOnChange("motionScale", val)}
|
||||
onChange: (val)=>{handleOnChange({motionScale: val})}
|
||||
}}/>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
@@ -64,7 +64,7 @@ export default memo( function SectionAdvanceOptions({
|
||||
initialValue: wfVal.upscaleMultiplier,
|
||||
label: "Upscale Multiplier",
|
||||
thumbTip: "Upscale Multiplier",
|
||||
onChange: (val)=>{handleOnChange("upscaleMultiplier", val)}
|
||||
onChange: (val)=>{handleOnChange({upscaleMultiplier: val})}
|
||||
}}/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -73,14 +73,14 @@ export default memo( function SectionAdvanceOptions({
|
||||
<Checkbox
|
||||
label="Use Empty Latent"
|
||||
checked={wfVal.useEmptyLatent}
|
||||
onChange={(e:{target:{ checked: boolean, name:string, type: string }})=>{handleOnChange("useEmptyLatent", e.target.checked)}}
|
||||
onChange={(e:{target:{ checked: boolean, name:string, type: string }})=>{handleOnChange({useEmptyLatent: e.target.checked})}}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<Checkbox
|
||||
label="Use Face Detailer"
|
||||
checked={wfVal.useFaceDetailer}
|
||||
onChange={(e:{target:{ checked: boolean, name:string, type: string }})=>{handleOnChange("useFaceDetailer", e.target.checked)}}
|
||||
onChange={(e:{target:{ checked: boolean, name:string, type: string }})=>{handleOnChange({useFaceDetailer: e.target.checked})}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -94,7 +94,7 @@ export default memo( function SectionAdvanceOptions({
|
||||
initialValue: wfVal.denoiseFaceDetailer,
|
||||
label: "Denoise Face Detailer",
|
||||
thumbTip: "Denoise Face Detailer",
|
||||
onChange: (val)=>{handleOnChange("denoiseFaceDetailer", val)}
|
||||
onChange: (val)=>{handleOnChange({denoiseFaceDetailer: val})}
|
||||
}}/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -102,7 +102,7 @@ export default memo( function SectionAdvanceOptions({
|
||||
<Checkbox
|
||||
label="Use LCM"
|
||||
checked={wfVal.useLCM}
|
||||
onChange={(e:{target:{ checked: boolean, name:string, type: string }})=>{handleOnChange("useLCM", e.target.checked)}}
|
||||
onChange={(e:{target:{ checked: boolean, name:string, type: string }})=>{handleOnChange({useLCM: e.target.checked})}}
|
||||
/>
|
||||
</div>
|
||||
<div className="row g-3 p-3">
|
||||
@@ -113,7 +113,7 @@ export default memo( function SectionAdvanceOptions({
|
||||
withRevert: true,
|
||||
label: "LCM CFG",
|
||||
thumbTip: "LCM CFG",
|
||||
onChange: (val)=>{handleOnChange("lcmCFG", val)}
|
||||
onChange: (val)=>{handleOnChange({lcmCFG: val})}
|
||||
}}/>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
@@ -122,7 +122,7 @@ export default memo( function SectionAdvanceOptions({
|
||||
initialValue: wfVal.lcmSteps,
|
||||
label: "LCM Steps",
|
||||
thumbTip: "LCM Steps",
|
||||
onChange: (val)=>{handleOnChange("lcmSteps", val)}
|
||||
onChange: (val)=>{handleOnChange({lcmSteps: val})}
|
||||
}}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+9
-9
@@ -18,7 +18,7 @@ export default memo( function SectionControlNets({
|
||||
onChange : handleOnChange
|
||||
} : {
|
||||
workflowValues : WorkflowValuesType
|
||||
onChange: (key:string, val:number)=>void}
|
||||
onChange: (val:{[key: string]: number|string|boolean})=>void}
|
||||
){
|
||||
|
||||
return(
|
||||
@@ -30,7 +30,7 @@ export default memo( function SectionControlNets({
|
||||
initialValue: wfVal.cnCanny,
|
||||
label: "Canny",
|
||||
thumbTip: "Canny",
|
||||
onChange: (val)=>{handleOnChange("cnCanny", val)}
|
||||
onChange: (val)=>{handleOnChange({cnCanny: val})}
|
||||
}}/>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
@@ -39,7 +39,7 @@ export default memo( function SectionControlNets({
|
||||
initialValue: wfVal.cnLinearAnime,
|
||||
label: "Line Art Anime",
|
||||
thumbTip: "Line Art Anime",
|
||||
onChange: (val)=>{handleOnChange("cnLinearAnime", val)}
|
||||
onChange: (val)=>{handleOnChange({cnLinearAnime: val})}
|
||||
}}/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -50,7 +50,7 @@ export default memo( function SectionControlNets({
|
||||
initialValue: wfVal.cnDepth,
|
||||
label: "Depth",
|
||||
thumbTip: "Depth",
|
||||
onChange: (val)=>{handleOnChange("cnDepth", val)}
|
||||
onChange: (val)=>{handleOnChange({cnDepth: val})}
|
||||
}}/>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
@@ -59,7 +59,7 @@ export default memo( function SectionControlNets({
|
||||
initialValue: wfVal.cnOpenPose,
|
||||
label: "OpenPose",
|
||||
thumbTip: "OpenPose",
|
||||
onChange: (val)=>{handleOnChange("cnOpenPose", val)}
|
||||
onChange: (val)=>{handleOnChange({cnOpenPose: val})}
|
||||
}}/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -70,7 +70,7 @@ export default memo( function SectionControlNets({
|
||||
initialValue: wfVal.cnPipeFace,
|
||||
label: "Media Pipe Face",
|
||||
thumbTip: "Media Pipe Face",
|
||||
onChange: (val)=>{handleOnChange("cnPipeFace", val)}
|
||||
onChange: (val)=>{handleOnChange({cnPipeFace: val})}
|
||||
}}/>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
@@ -79,7 +79,7 @@ export default memo( function SectionControlNets({
|
||||
initialValue: wfVal.cnSparse,
|
||||
label: "Sparse Scribble",
|
||||
thumbTip: "Sparse Scribble",
|
||||
onChange: (val)=>{handleOnChange("cnSparse", val)}
|
||||
onChange: (val)=>{handleOnChange({cnSparse: val})}
|
||||
}}/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -90,7 +90,7 @@ export default memo( function SectionControlNets({
|
||||
initialValue: wfVal.cnLinearRealistic,
|
||||
label: "Video CN (Linear Realistic)",
|
||||
thumbTip: "Video CN",
|
||||
onChange: (val)=>{handleOnChange("cnLinearRealistic", val)}
|
||||
onChange: (val)=>{handleOnChange({cnLinearRealistic: val})}
|
||||
}}/>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
@@ -99,7 +99,7 @@ export default memo( function SectionControlNets({
|
||||
initialValue: wfVal.cnTile,
|
||||
label: "Tile CN",
|
||||
thumbTip: "Tile CN",
|
||||
onChange: (val)=>{handleOnChange("cnTile", val)}
|
||||
onChange: (val)=>{handleOnChange({cnTile: val})}
|
||||
}}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+15
-16
@@ -18,7 +18,7 @@ export default memo( function SectionVideoSettings({
|
||||
workflowValues: wfVal,
|
||||
videoElement: ve
|
||||
} : {
|
||||
onChange: (key:string, val:number)=>void,
|
||||
onChange: (val:{[key: string]: number|string|boolean|undefined})=>void,
|
||||
workflowValues: WorkflowValuesType,
|
||||
videoElement: HTMLVideoElement | null,
|
||||
}){
|
||||
@@ -26,33 +26,32 @@ export default memo( function SectionVideoSettings({
|
||||
|
||||
const handleFramesCap = (newValue: number)=>{
|
||||
if(newValue - wfVal.skipFrames >= 16)
|
||||
handleOnChange("framesCap",newValue);
|
||||
handleOnChange({framesCap:newValue});
|
||||
}
|
||||
const handleSkipFrames = (newValue: number)=>{
|
||||
if(wfVal.framesCap - newValue >= 16)
|
||||
handleOnChange("skipFrames",newValue);
|
||||
handleOnChange({skipFrames:newValue});
|
||||
}
|
||||
|
||||
if(ve && ve!==null){
|
||||
ve.onloadedmetadata = () =>{
|
||||
const newValues : {
|
||||
width?: number;
|
||||
height?: number;
|
||||
maxFrames?: number;
|
||||
framesCap?: number;
|
||||
} = {};
|
||||
if (ve.videoWidth && ve.videoHeight) {
|
||||
const aspectRatio = ve.videoWidth/ve.videoHeight
|
||||
if (aspectRatio > 1){
|
||||
handleOnChange("width",960);
|
||||
}
|
||||
else if (aspectRatio < 1) {
|
||||
handleOnChange("height",960);
|
||||
}else{
|
||||
console.log(`aspectRaio: ${aspectRatio}`);
|
||||
}
|
||||
if (aspectRatio > 1) newValues.width = 960;
|
||||
else if (aspectRatio < 1) newValues.height = 960
|
||||
else console.log(`aspectRaio: ${aspectRatio}`);
|
||||
}
|
||||
if(ve.duration){
|
||||
handleOnChange("maxFrames",
|
||||
Math.floor(ve.duration)*wfVal.inputFps
|
||||
);
|
||||
newValues.maxFrames = Math.floor(ve.duration)*wfVal.inputFps;
|
||||
newValues.framesCap = newValues.maxFrames;
|
||||
}
|
||||
//TODO: Optimizer to make ONE handleOnChange only
|
||||
//TODO: deal with maxFrames with more reliable math
|
||||
handleOnChange(newValues);
|
||||
}
|
||||
}
|
||||
return(
|
||||
|
||||
+5
-12
@@ -2,7 +2,8 @@ import React from "react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import { states, Action, State } from "../videoWorkflowReducer";
|
||||
import { Button } from "components/common";
|
||||
import SelectModal, { SelectModalData } from "components/common/SelectModal/SelectModal";
|
||||
import SelectModalVideoTabs from "components/common/SelectModalVideoTabs";
|
||||
import { SelectModalData } from "components/common/SelectModal/SelectModalV2";
|
||||
import VideoFakeyou from "components/common/VideoFakeyou";
|
||||
|
||||
export default function TabContentLibrary({
|
||||
@@ -29,19 +30,11 @@ export default function TabContentLibrary({
|
||||
return (
|
||||
<div className="row g-3">
|
||||
<div className="col-12">
|
||||
<SelectModal
|
||||
<SelectModalVideoTabs
|
||||
value={pageState.mediaFileToken}
|
||||
modalTitle="Select a Video"
|
||||
label="Select a Video"
|
||||
inputLabel="Select a Video"
|
||||
onSelect={handleOnSelect}
|
||||
tabs={[
|
||||
{
|
||||
label: "All Videos",
|
||||
tabKey: "allVideos",
|
||||
typeFilter: "video",
|
||||
searcher: false,
|
||||
type: "media",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
{pageState.mediaFileToken &&
|
||||
<VideoFakeyou mediaToken={pageState.mediaFileToken} />
|
||||
|
||||
Reference in new issue
Block a user