mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-09 03:21:23 +00:00
Searcher memo and store states
This commit is contained in:
1 parent
97917cccf0
commit
ce28bf84a4
9 files changed
+153
-92
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useRef, useState } from "react";
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import Input from "../Input";
|
||||
import { faSearch } from "@fortawesome/pro-solid-svg-icons";
|
||||
import MasonryGrid from "../MasonryGrid/MasonryGrid";
|
||||
@@ -9,6 +9,7 @@ import { SearchWeights } from "@storyteller/components/src/api/weights/SearchWei
|
||||
import debounce from "lodash.debounce";
|
||||
import WeightsCards from "../Card/WeightsCards";
|
||||
import LoadingSpinner from "../LoadingSpinner";
|
||||
import useSearcherStore from "hooks/useSearcherStore";
|
||||
|
||||
interface SearcherProps {
|
||||
type?: "page" | "modal";
|
||||
@@ -16,6 +17,7 @@ interface SearcherProps {
|
||||
weightType?: string;
|
||||
onResultSelect?: () => void;
|
||||
weightTypeFilter?: any;
|
||||
searcherKey: string;
|
||||
}
|
||||
|
||||
export default function Searcher({
|
||||
@@ -24,18 +26,27 @@ export default function Searcher({
|
||||
weightType = "all",
|
||||
onResultSelect,
|
||||
weightTypeFilter,
|
||||
searcherKey,
|
||||
}: SearcherProps) {
|
||||
const gridContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const { searchTerm, setSearchTerm } = useSearcherStore();
|
||||
const [foundWeights, setFoundWeights] = useState<Weight[]>([]);
|
||||
const [isSearching, setIsSearching] = useState(false);
|
||||
const [searchCompleted, setSearchCompleted] = useState(0);
|
||||
const bookmarks = useBookmarks();
|
||||
const ratings = useRatings();
|
||||
|
||||
useEffect(() => {
|
||||
if (searchTerm[searcherKey]) {
|
||||
setSearchTerm(searcherKey, searchTerm[searcherKey]);
|
||||
}
|
||||
doSearch(searchTerm[searcherKey]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const handleInputChange = (e: any) => {
|
||||
const newValue = e.target.value;
|
||||
setSearchTerm(newValue);
|
||||
setSearchTerm(searcherKey, newValue);
|
||||
debouncedDoSearch(newValue);
|
||||
};
|
||||
|
||||
@@ -79,7 +90,7 @@ export default function Searcher({
|
||||
<Input
|
||||
icon={faSearch}
|
||||
placeholder="Search..."
|
||||
value={searchTerm}
|
||||
value={searchTerm[searcherKey]}
|
||||
onChange={handleInputChange}
|
||||
className="mb-3"
|
||||
/>
|
||||
@@ -92,11 +103,7 @@ export default function Searcher({
|
||||
{isSearching ? (
|
||||
<LoadingSpinner />
|
||||
) : (
|
||||
<MasonryGrid
|
||||
key={searchCompleted}
|
||||
gridRef={gridContainerRef}
|
||||
onLayoutComplete={() => console.log("Layout complete!")}
|
||||
>
|
||||
<MasonryGrid key={searchCompleted} gridRef={gridContainerRef}>
|
||||
{dataType === "weights" &&
|
||||
foundWeights.map((data: any, key: number) => {
|
||||
let props = {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
white-space: nowrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 3rem;
|
||||
min-height: 46.5px;
|
||||
padding: 0.75rem;
|
||||
transition: 0.1s background-color ease-in-out;
|
||||
font-size: 14px;
|
||||
|
||||
@@ -1,76 +1,106 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, memo } from "react";
|
||||
import Searcher from "../Searcher";
|
||||
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";
|
||||
|
||||
interface SelectSearcherProps {
|
||||
label?: string;
|
||||
weightTypeFilter?: string;
|
||||
}
|
||||
|
||||
export default function SelectSearcher({
|
||||
label,
|
||||
weightTypeFilter,
|
||||
}: SelectSearcherProps) {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const { weightTitle } = useToken();
|
||||
const SelectSearcher = memo(
|
||||
({ label, weightTypeFilter }: SelectSearcherProps) => {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const { weightTitle, setWeightTitle } = useToken();
|
||||
|
||||
const openModal = () => {
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
const openModal = () => {
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
const closeModal = () => {
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
|
||||
const searchTabs = [
|
||||
{
|
||||
label: "All LoRA Weights",
|
||||
content: (
|
||||
<Searcher
|
||||
type="modal"
|
||||
onResultSelect={closeModal}
|
||||
weightTypeFilter={weightTypeFilter}
|
||||
/>
|
||||
),
|
||||
padding: true,
|
||||
},
|
||||
{
|
||||
label: "Bookmarked",
|
||||
content: <Searcher type="modal" onResultSelect={closeModal} />,
|
||||
padding: true,
|
||||
},
|
||||
];
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
{label && <label className="sub-title">{label}</label>}
|
||||
const handleRemove = () => {
|
||||
setWeightTitle && setWeightTitle("");
|
||||
};
|
||||
|
||||
<div className="d-flex gap-2">
|
||||
<Input
|
||||
disabled={true}
|
||||
className="w-100"
|
||||
placeholder="None selected"
|
||||
value={weightTitle ? weightTitle : ""}
|
||||
const searchTabs = [
|
||||
{
|
||||
label: "All LoRA Weights",
|
||||
content: (
|
||||
<Searcher
|
||||
type="modal"
|
||||
onResultSelect={closeModal}
|
||||
weightTypeFilter={weightTypeFilter}
|
||||
searcherKey="allLoraWeights"
|
||||
/>
|
||||
<Button label="Select" onClick={openModal} />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
padding: true,
|
||||
},
|
||||
{
|
||||
label: "Bookmarked",
|
||||
content: (
|
||||
<>
|
||||
<Searcher
|
||||
type="modal"
|
||||
onResultSelect={closeModal}
|
||||
searcherKey="bookmarkedLoraWeights"
|
||||
/>
|
||||
<h2 className="text-center py-4">
|
||||
NEEDS USER BOOKMARK ELASTIC SEARCH HERE
|
||||
</h2>
|
||||
</>
|
||||
),
|
||||
padding: true,
|
||||
},
|
||||
];
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
{label && <label className="sub-title">{label}</label>}
|
||||
|
||||
<Modal
|
||||
show={isModalOpen}
|
||||
handleClose={closeModal}
|
||||
title="Select a LoRA Weight"
|
||||
content={() => <NonRouteTabs tabs={searchTabs} />}
|
||||
showButtons={false}
|
||||
padding={false}
|
||||
large={true}
|
||||
position="top"
|
||||
mobileFullscreen={true}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
<div className="d-flex gap-2">
|
||||
<Input
|
||||
disabled={true}
|
||||
className="w-100"
|
||||
placeholder="None selected"
|
||||
value={weightTitle ? weightTitle : ""}
|
||||
/>
|
||||
<Button
|
||||
label={weightTitle ? "Change" : "Select"}
|
||||
onClick={openModal}
|
||||
/>
|
||||
{weightTitle && (
|
||||
<Button
|
||||
square={true}
|
||||
variant="danger"
|
||||
icon={faTrash}
|
||||
onClick={handleRemove}
|
||||
tooltip="Remove"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
show={isModalOpen}
|
||||
handleClose={closeModal}
|
||||
title="Select a LoRA Weight"
|
||||
content={() => <NonRouteTabs tabs={searchTabs} />}
|
||||
showButtons={false}
|
||||
padding={false}
|
||||
large={true}
|
||||
position="top"
|
||||
mobileFullscreen={true}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default SelectSearcher;
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "./useSearcherStore";
|
||||
@@ -0,0 +1,21 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
interface SearcherState {
|
||||
searchTerm: { [searcherKey: string]: string };
|
||||
}
|
||||
|
||||
interface SearcherActions {
|
||||
setSearchTerm: (searcherKey: string, value: string) => void;
|
||||
}
|
||||
|
||||
type SearcherStore = SearcherState & SearcherActions;
|
||||
|
||||
const useSearcherStore = create<SearcherStore>(set => ({
|
||||
searchTerm: {},
|
||||
setSearchTerm: (searcherKey, value) =>
|
||||
set((state: SearcherState) => ({
|
||||
searchTerm: { ...state.searchTerm, [searcherKey]: value },
|
||||
})),
|
||||
}));
|
||||
|
||||
export default useSearcherStore;
|
||||
@@ -431,7 +431,7 @@ styles with important tags:
|
||||
.form-select {
|
||||
border-width: 1px;
|
||||
border-color: $white;
|
||||
padding: 11px 0.75rem;
|
||||
padding: 10.25px 0.75rem;
|
||||
|
||||
&:focus {
|
||||
border-color: $primary;
|
||||
@@ -1719,7 +1719,7 @@ textarea {
|
||||
}
|
||||
|
||||
.fy-studio-frame {
|
||||
border-radius: .5rem;
|
||||
border-radius: 0.5rem;
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
}
|
||||
@@ -770,16 +770,16 @@ class PageContainer extends React.Component<
|
||||
</Route>
|
||||
|
||||
<Route path="/video-mocap/:mediaToken?">
|
||||
<VideoMocap
|
||||
{...{
|
||||
enqueueInferenceJob: this.props.enqueueInferenceJob,
|
||||
sessionSubscriptionsWrapper:
|
||||
this.props.sessionSubscriptionsWrapper,
|
||||
inferenceJobs: this.props.inferenceJobs,
|
||||
inferenceJobsByCategory: this.props.inferenceJobsByCategory,
|
||||
}}
|
||||
/>
|
||||
</Route>
|
||||
<VideoMocap
|
||||
{...{
|
||||
enqueueInferenceJob: this.props.enqueueInferenceJob,
|
||||
sessionSubscriptionsWrapper:
|
||||
this.props.sessionSubscriptionsWrapper,
|
||||
inferenceJobs: this.props.inferenceJobs,
|
||||
inferenceJobsByCategory: this.props.inferenceJobsByCategory,
|
||||
}}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/character/donald-trump">
|
||||
<TrumpTtsPage
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
} from "@storyteller/components/src/api/media_files/UploadMedia";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { Link } from "react-router-dom";
|
||||
import SelectSearcher from "components/common/SelectSearcher/SelectSearcher";
|
||||
|
||||
interface DevUploadProps {}
|
||||
|
||||
@@ -68,10 +67,6 @@ export default function DevUpload(props: DevUploadProps) {
|
||||
))}
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
<div className="mt-5">
|
||||
<SelectSearcher label="Additional LoRA Weight" />
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
@@ -116,13 +116,20 @@ export default function WeightPage({
|
||||
);
|
||||
case WeightCategory.VC:
|
||||
return (
|
||||
<VcInferencePanel
|
||||
sessionSubscriptionsWrapper={sessionSubscriptionsWrapper}
|
||||
enqueueInferenceJob={enqueueInferenceJob}
|
||||
inferenceJobs={inferenceJobs}
|
||||
inferenceJobsByCategory={inferenceJobsByCategory}
|
||||
voiceToken={weight.weight_token}
|
||||
/>
|
||||
<>
|
||||
<VcInferencePanel
|
||||
sessionSubscriptionsWrapper={sessionSubscriptionsWrapper}
|
||||
enqueueInferenceJob={enqueueInferenceJob}
|
||||
inferenceJobs={inferenceJobs}
|
||||
inferenceJobsByCategory={inferenceJobsByCategory}
|
||||
voiceToken={weight.weight_token}
|
||||
/>
|
||||
|
||||
<SdInferencePanel
|
||||
sd_model_token={weight.weight_token}
|
||||
enqueueInferenceJob={enqueueInferenceJob}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
case WeightCategory.ZS:
|
||||
|
||||
Reference in new issue
Block a user