select modal updates

This commit is contained in:
BFlat committed 2024-01-23 12:36:22 +07:00
1 parent 0f3ac28760
commit 7f6cb82ccc
9 files changed
+372 -164

No files matched your search

@@ -22,7 +22,7 @@ interface AudioCardProps {
showCreator?: boolean;
showCover?: boolean;
type: "media" | "weights";
inSearcher?: boolean;
inSelectModal?: boolean;
onResultSelect?: () => void;
}
@@ -34,7 +34,7 @@ export default function AudioCard({
showCreator,
showCover,
type,
inSearcher = false,
inSelectModal = false,
onResultSelect,
}: AudioCardProps) {
const { setToken, setWeightTitle } = useToken();
@@ -50,10 +50,12 @@ export default function AudioCard({
event.stopPropagation();
};
const handleSearcherResultSelect = () => {
setToken(data.weight_token);
setWeightTitle && setWeightTitle(data.title);
onResultSelect && onResultSelect();
const handleSelectModalResultSelect = () => {
if (inSelectModal) {
setToken(data.weight_token);
setWeightTitle && setWeightTitle(data.title);
onResultSelect && onResultSelect();
}
};
const timeAgo = useTimeAgo(data.created_at);
@@ -86,7 +88,11 @@ export default function AudioCard({
}
const card = (
<Card padding={true} canHover={true} onClick={handleSearcherResultSelect}>
<Card
padding={true}
canHover={true}
onClick={handleSelectModalResultSelect}
>
{type === "media" && (
<>
<div className="mb-3">
@@ -161,14 +167,14 @@ export default function AudioCard({
<div className="d-flex flex-grow-1">
<Badge label={weightBadgeLabel} color={weightBadgeColor} />
</div>
{inSearcher ? (
{inSelectModal ? (
<Button
icon={faArrowRight}
iconFlip={true}
variant="link"
label="Select"
className="fs-7"
onClick={handleSearcherResultSelect}
onClick={handleSelectModalResultSelect}
/>
) : (
<Button
@@ -246,7 +252,7 @@ export default function AudioCard({
return (
<>
{inSearcher ? (
{inSelectModal ? (
<>{card}</>
) : (
<Link
@@ -10,15 +10,17 @@ 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";
interface ImageCardProps {
bookmarks: any;
bookmarks?: any;
data: any;
origin?: string;
ratings: any;
ratings?: any;
showCreator?: boolean;
type: "media" | "weights";
inSearcher?: boolean;
inSelectModal?: boolean;
onResultSelect?: () => void;
}
export default function ImageCard({
@@ -28,9 +30,11 @@ export default function ImageCard({
showCreator,
ratings,
type,
inSearcher = false,
inSelectModal = false,
onResultSelect,
}: ImageCardProps) {
const history = useHistory();
const { setToken, setWeightTitle } = useToken();
const linkUrl =
type === "media"
? `/media/${data.token}`
@@ -42,11 +46,11 @@ export default function ImageCard({
event.stopPropagation();
};
const handleSearcherSelect = () => {
if (inSearcher) {
console.log("Searcher weight selected", data.weight_token);
} else {
return;
const handleSelectModalResultSelect = () => {
if (inSelectModal) {
setToken(data.weight_token);
setWeightTitle && setWeightTitle(data.title);
onResultSelect && onResultSelect();
}
};
@@ -83,7 +87,11 @@ export default function ImageCard({
}
const card = (
<Card padding={false} canHover={true}>
<Card
padding={false}
canHover={true}
onClick={handleSelectModalResultSelect}
>
{type === "media" && (
<>
<img src={coverImage} alt={data.weight_name} className="card-img" />
@@ -94,6 +102,16 @@ export default function ImageCard({
<div className="d-flex flex-grow-1">
<Badge label="Image" color="ultramarine" overlay={true} />
</div>
{inSelectModal && (
<Button
icon={faArrowRight}
iconFlip={true}
variant="link"
label="Select"
className="fs-7"
onClick={handleSelectModalResultSelect}
/>
)}
</div>
<div className="card-img-overlay-text">
@@ -125,16 +143,18 @@ export default function ImageCard({
</div>
)}
<div>
<LikeButton
{...{
...ratings.makeProps({
entityToken: data.token,
entityType: "media_file",
}),
}}
/>
</div>
{ratings && (
<div>
<LikeButton
{...{
...ratings.makeProps({
entityToken: data.token,
entityType: "media_file",
}),
}}
/>
</div>
)}
</div>
</div>
</div>
@@ -154,14 +174,14 @@ export default function ImageCard({
overlay={true}
/>
</div>
{inSearcher ? (
{inSelectModal ? (
<Button
icon={faArrowRight}
iconFlip={true}
variant="link"
label="Select"
className="fs-7"
onClick={handleSearcherSelect}
onClick={handleSelectModalResultSelect}
/>
) : (
<Button
@@ -209,24 +229,29 @@ export default function ImageCard({
</div>
)}
<div>
<LikeButton
{ratings && (
<div>
<LikeButton
{...{
...ratings.makeProps({
entityToken: data.weight_token,
entityType: "model_weight",
}),
}}
/>
</div>
)}
{bookmarks && (
<BookmarkButton
{...{
...ratings.makeProps({
...bookmarks.makeProps({
entityToken: data.weight_token,
entityType: "model_weight",
}),
}}
/>
</div>
<BookmarkButton
{...{
...bookmarks.makeProps({
entityToken: data.weight_token,
entityType: "model_weight",
}),
}}
/>
)}
</div>
</div>
</div>
@@ -237,7 +262,7 @@ export default function ImageCard({
return (
<>
{inSearcher ? (
{inSelectModal ? (
<>{card}</>
) : (
<Link
@@ -9,6 +9,7 @@ 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";
interface VideoCardProps {
data: any;
@@ -16,6 +17,8 @@ interface VideoCardProps {
ratings?: any;
showCreator?: boolean;
type: "media" | "weights";
inSelectModal?: boolean;
onResultSelect?: () => void;
}
export default function VideoCard({
@@ -24,7 +27,10 @@ export default function VideoCard({
ratings,
showCreator,
type,
inSelectModal = false,
onResultSelect,
}: VideoCardProps) {
const { setToken, setWeightTitle } = useToken();
const linkUrl =
type === "media" ? `/media/${data.token}` : `/weight/${data.weight_token}`;
@@ -32,6 +38,14 @@ export default function VideoCard({
event.stopPropagation();
};
const handleSelectModalResultSelect = () => {
if (inSelectModal) {
setToken(data.weight_token || data.token);
setWeightTitle && setWeightTitle(data.title);
onResultSelect && onResultSelect();
}
};
const timeAgo = useTimeAgo(data.created_at);
const bucketConfig = new BucketConfig();
@@ -48,62 +62,64 @@ export default function VideoCard({
);
}
return (
<Link
{...{
to: linkUrl,
state: { origin },
}}
const card = (
<Card
padding={false}
canHover={true}
onClick={handleSelectModalResultSelect}
>
<Card padding={false} canHover={true}>
{type === "media" && (
<>
<img
src={coverImage}
alt={data.weight_name}
className="card-video"
/>
<div className="card-img-overlay">
<div className="card-img-gradient" />
{type === "media" && (
<>
<img src={coverImage} 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>
<div className="d-flex align-items-center">
<div className="d-flex flex-grow-1">
<Badge label="Video" color="purple" overlay={true} />
</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>
<hr className="my-2" />
<div
className="d-flex align-items-center gap-2"
onClick={handleInnerClick}
>
{showCreator && (
<div className="flex-grow-1">
<CreatorName
displayName={
data.maybe_creator?.display_name || "Anonymous"
}
gravatarHash={data.maybe_creator?.gravatar_hash || ""}
avatarIndex={
data.maybe_creator?.default_avatar.image_index || ""
}
backgroundIndex={
data.maybe_creator?.default_avatar.color_index || ""
}
username={data.maybe_creator?.username || "anonymous"}
/>
</div>
)}
{inSelectModal && (
<Button
icon={faArrowRight}
iconFlip={true}
variant="link"
label="Select"
className="fs-7"
onClick={handleSelectModalResultSelect}
/>
)}
</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>
<hr className="my-2" />
<div
className="d-flex align-items-center gap-2"
onClick={handleInnerClick}
>
{showCreator && (
<div className="flex-grow-1">
<CreatorName
displayName={
data.maybe_creator?.display_name || "Anonymous"
}
gravatarHash={data.maybe_creator?.gravatar_hash || ""}
avatarIndex={
data.maybe_creator?.default_avatar.image_index || ""
}
backgroundIndex={
data.maybe_creator?.default_avatar.color_index || ""
}
username={data.maybe_creator?.username || "anonymous"}
/>
</div>
)}
{ratings && (
<div>
<LikeButton
{...{
@@ -114,63 +130,79 @@ export default function VideoCard({
}}
/>
</div>
</div>
)}
</div>
</div>
</div>
</>
)}
</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" />
{/* {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"
to={linkUrl}
className="fs-7"
/>
<div className="d-flex align-items-center">
<div className="d-flex flex-grow-1">
<Badge label="Video" color="purple" overlay={true} />
</div>
<FontAwesomeIcon
icon={faPlayCircle}
className="card-video-play"
<Button
icon={faArrowRight}
iconFlip={true}
variant="link"
label="Use"
className="fs-7"
onClick={() => {
history.push(linkUrl);
}}
/>
<div className="card-img-overlay-text">
</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>
<h6 className="fw-semibold text-white mb-1">
{data.weight_name}
</h6>
<p className="fs-7 opacity-75">{timeAgo}</p>
<div className="mt-2" onClick={handleInnerClick}>
<LikeButton
{...{
overlay: true,
...ratings.makeProps({
entityToken: data.weight_token,
entityType: "model_weight",
}),
}}
/>
</div>
<LikeButton
{...{
overlay: true,
...ratings.makeProps({
entityToken: data.weight_token,
entityType: "model_weight",
}),
}}
/>
</div>
</div>
</div>
</>
)}
</Card>
</Link>
</div>
</>
)} */}
</Card>
);
return (
<>
{inSelectModal ? (
<>{card}</>
) : (
<Link
{...{
to: linkUrl,
state: { origin },
}}
>
{card}
</Link>
)}
</>
);
}
@@ -128,7 +128,7 @@ export default function Searcher({
data,
showCreator: true,
type: "weights",
inSearcher: true,
inSelectModal: true,
onResultSelect,
};
@@ -186,7 +186,7 @@ export default function Searcher({
data,
showCreator: true,
type: "weights",
inSearcher: true,
inSelectModal: true,
onResultSelect,
};
@@ -0,0 +1,94 @@
import React, { useRef, useState } from "react";
import MasonryGrid from "../MasonryGrid/MasonryGrid";
import InfiniteScroll from "react-infinite-scroll-component";
import { useLazyLists } from "hooks";
import prepFilter from "resources/prepFilter";
import MediaCards from "../Card/MediaCards";
import { MediaFile } from "@storyteller/components/src/api/media_files/GetMediaFile";
import { ListMediaFiles } from "@storyteller/components/src/api/media_files/ListMediaFiles";
interface SelectMediaListProps {
mediaType: string;
listKey: string;
onResultSelect?: () => void;
}
export default function SelectMediaList({
mediaType,
listKey,
onResultSelect,
}: SelectMediaListProps) {
const gridContainerRef = useRef<HTMLDivElement | null>(null);
const [list, listSet] = useState<MediaFile[]>([]);
const media = useLazyLists({
addQueries: {
page_size: 9,
...prepFilter(mediaType, "filter_media_type"),
},
debug: "User Media List",
fetcher: ListMediaFiles,
list,
listSet,
requestList: true,
disableUrlQueries: true,
});
return (
<div className="searcher-container in-modal" id={listKey}>
<InfiniteScroll
dataLength={media.list.length}
next={media.getMore}
hasMore={!media.list.length || !!media.next}
loader={
media.list.length !== 0 &&
media.isLoading && (
<div className="mt-4 d-flex justify-content-center">
<div className="spinner-border text-light" role="status">
<span className="visually-hidden">Loading...</span>
</div>
</div>
)
}
endMessage={
<p className="text-center mt-4 opacity-75">No more results.</p>
}
className="overflow-hidden"
scrollableTarget={listKey}
scrollThreshold={0.95}
>
<>
{media.list.length === 0 && media.status === 3 ? (
<div className="text-center opacity-75">No media created yet.</div>
) : (
<MasonryGrid
gridRef={gridContainerRef}
onLayoutComplete={() => console.log("Layout complete!")}
>
{media.list.map((data: any, key: number) => {
let props = {
data,
showCreator: true,
type: "media",
inSelectModal: true,
onResultSelect,
};
return (
<div
{...{
className: "col-12 col-sm-6 col-xl-4 grid-item",
key,
}}
>
<MediaCards {...{ type: data.media_type, props }} />
</div>
);
})}
</MasonryGrid>
)}
</>
</InfiniteScroll>
</div>
);
}
@@ -1,4 +1,4 @@
import React, { useState, memo } from "react";
import React, { useState, memo, useEffect } from "react";
import Searcher from "../Searcher";
import Modal from "../Modal";
import NonRouteTabs from "../Tabs/NonRouteTabs";
@@ -6,12 +6,17 @@ 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";
import { set } from "date-fns";
interface TabConfig {
label: string;
searcherKey?: string;
tabKey: string;
type?: "media" | "weights";
weightTypeFilter?: string;
mediaTypeFilter?: string; // NOT DONE
mediaTypeFilter?: string;
searcher?: boolean;
}
interface SelectModalProps {
label?: string;
@@ -22,7 +27,34 @@ interface SelectModalProps {
const SelectModal = memo(
({ label, tabs, modalTitle = "Select" }: SelectModalProps) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const { weightTitle, setWeightTitle } = useToken();
const { token, setToken, weightTitle, setWeightTitle } = useToken();
const [activeTab, setActiveTab] = useState(tabs[0].tabKey);
const [mediaType, setMediaType] = useState(
tabs[0].mediaTypeFilter || "all"
);
const [weightType, setWeightType] = useState(
tabs[0].weightTypeFilter || "all"
);
// Update mediaType when activeTab changes
useEffect(() => {
const currentTab = tabs.find(tab => tab.tabKey === activeTab);
setMediaType(currentTab?.mediaTypeFilter || "all");
setWeightType(currentTab?.mediaTypeFilter || "all");
}, [activeTab, tabs]);
// const allWeights = useLazyLists({
// addQueries: {
// page_size: 9,
// ...prepFilter(weightType, "filter_media_type"),
// },
// debug: "Media List",
// fetcher: ListWeights,
// list: weightList,
// listSet: setWeightList,
// requestList: true,
// disableUrlQueries: true,
// });
const openModal = () => {
setIsModalOpen(true);
@@ -34,19 +66,32 @@ const SelectModal = memo(
const handleRemove = () => {
setWeightTitle && setWeightTitle("");
setToken("");
};
const searchTabs = tabs.map(tab => ({
label: tab.label,
content: tab.searcherKey ? (
content: tab.searcher ? (
<Searcher
type="modal"
onResultSelect={closeModal}
searcherKey={tab.searcherKey}
searcherKey={tab.tabKey}
weightType={tab.weightTypeFilter}
/>
) : null,
) : (
<>
{tab.type === "media" && (
<SelectMediaList
mediaType={mediaType}
listKey={tab.tabKey}
onResultSelect={closeModal}
/>
)}
{tab.type === "weights" && <SelectWeightsList />}
</>
),
padding: true,
onClick: () => setActiveTab(tab.tabKey),
}));
return (
@@ -59,13 +104,13 @@ const SelectModal = memo(
disabled={true}
className="w-100"
placeholder="None selected"
value={weightTitle ? weightTitle : ""}
value={weightTitle ? weightTitle : token || ""}
/>
<Button
label={weightTitle ? "Change" : "Select"}
onClick={openModal}
/>
{weightTitle && (
{token && (
<Button
square={true}
variant="danger"
@@ -0,0 +1,7 @@
import React from "react";
interface SelectWeightsListProps {}
export default function SelectWeightsList(props: SelectWeightsListProps) {
return <div>SelectWeightsList</div>;
}
@@ -13,13 +13,10 @@ export default function TabContentLibrary(props: {
tabs={[
{
label: "All Videos",
searcherKey: "allVideos",
mediaTypeFilter: "",
},
{
label: "Bookmarked",
searcherKey: "bookmarkedVideos",
mediaTypeFilter: "",
tabKey: "allVideos",
mediaTypeFilter: "video",
searcher: false,
type: "media",
},
]}
/>
@@ -338,13 +338,15 @@ function SdInferencePanel({
tabs={[
{
label: "All LoRA Weights",
searcherKey: "allLoraWeights",
tabKey: "allLoraWeights",
weightTypeFilter: "lora",
searcher: true,
},
{
label: "Bookmarked",
searcherKey: "bookmarkedLoraWeights",
tabKey: "bookmarkedLoraWeights",
weightTypeFilter: "lora",
searcher: false,
},
]}
/>