From abc708b93300db9acbcdf645b64e1d49fce6a805 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Wed, 8 Nov 2023 15:35:56 -0300 Subject: [PATCH] Refactored Store Page (search, tags working) --- .../components/PaginatorComponent/index.tsx | 4 +- src/frontend/src/controllers/API/index.ts | 4 +- src/frontend/src/pages/StorePage/index.tsx | 207 +++++++----------- 3 files changed, 78 insertions(+), 137 deletions(-) diff --git a/src/frontend/src/components/PaginatorComponent/index.tsx b/src/frontend/src/components/PaginatorComponent/index.tsx index 1840c4d0e..c5ed90f33 100644 --- a/src/frontend/src/components/PaginatorComponent/index.tsx +++ b/src/frontend/src/components/PaginatorComponent/index.tsx @@ -11,9 +11,9 @@ import IconComponent from "../genericIconComponent"; import { Button } from "../ui/button"; export default function PaginatorComponent({ - pageSize = 10, + pageSize = 12, pageIndex = 1, - rowsCount = [10, 20, 50, 100], + rowsCount = [12, 24, 48, 96], totalRowsCount = 0, paginate, storeComponent = false, diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index 116980870..1551c1e13 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -609,8 +609,8 @@ export async function getStoreComponents( if (status !== undefined && status !== null) { queryParams.push(`status=${status}`); } - if (tags !== undefined && tags !== null) { - queryParams.push(`tags=${tags}`); + if (tags !== undefined && tags !== null && tags.length > 0) { + queryParams.push(`tags=${tags.join(",")}`); } if (sort !== undefined && sort !== null) { diff --git a/src/frontend/src/pages/StorePage/index.tsx b/src/frontend/src/pages/StorePage/index.tsx index 929dacd77..7af500025 100644 --- a/src/frontend/src/pages/StorePage/index.tsx +++ b/src/frontend/src/pages/StorePage/index.tsx @@ -1,6 +1,5 @@ -import { cloneDeep } from "lodash"; import { Search } from "lucide-react"; -import { useContext, useEffect, useRef, useState } from "react"; +import { useContext, useEffect, useState } from "react"; import PaginatorComponent from "../../components/PaginatorComponent"; import ShadTooltip from "../../components/ShadTooltipComponent"; import IconComponent from "../../components/genericIconComponent"; @@ -23,7 +22,6 @@ import { getStoreComponents, getStoreSavedComponents, getStoreTags, - searchComponent, } from "../../controllers/API"; import StoreApiKeyModal from "../../modals/StoreApiKeyModal"; import { storeComponent } from "../../types/store"; @@ -34,57 +32,78 @@ export default function StorePage(): JSX.Element { useEffect(() => { setTabId(""); }, []); - const [loading, setLoading] = useState(false); + const { setSavedFlows, hasApiKey } = useContext(StoreContext); + const { setErrorData } = useContext(alertContext); + const [loading, setLoading] = useState(true); + const [loadingTags, setLoadingTags] = useState(true); + const [loadingSaved, setLoadingSaved] = useState(false); const [filteredCategories, setFilterCategories] = useState([]); const [inputText, setInputText] = useState(""); const [searchData, setSearchData] = useState([]); - const { setErrorData } = useContext(alertContext); const [totalRowsCount, setTotalRowsCount] = useState(0); - const [size, setPageSize] = useState(10); - const [index, setPageIndex] = useState(1); + const [pageSize, setPageSize] = useState(12); + const [pageIndex, setPageIndex] = useState(1); + const [pageOrder, setPageOrder] = useState("Popular"); const [errorApiKey, setErrorApiKey] = useState(false); - const { setSavedFlows, hasApiKey } = useContext(StoreContext); const [tags, setTags] = useState<{ id: string; name: string }[]>([]); - const tagListId = useRef<{ id: string; name: string }[]>([]); - const [renderPagination, setRenderPagination] = useState(false); - const filterComponent = useRef(null); const [tabActive, setTabActive] = useState("Flows"); + const [searchText, setSearchText] = useState(""); useEffect(() => { + handleGetSavedComponents(); + handleGetTags(); + }, []); + + useEffect(() => { + handleGetComponents(); + }, [ + searchText, + tabActive, + pageOrder, + pageIndex, + pageSize, + filteredCategories, + ]); + + function handleGetTags() { + setLoadingTags(true); getStoreTags().then((res) => { - tagListId.current = res; setTags(res); + setLoadingTags(false); }); - }, []); + } - useEffect(() => { - filterComponent.current = false; - getSavedComponents() - .finally(() => handleGetComponents()) + function handleGetSavedComponents() { + setLoadingSaved(true); + getStoreSavedComponents() + .then((data) => { + let savedIds = new Set(); + let results = data?.results ?? []; + results.forEach((flow) => { + savedIds.add(flow.id); + }); + setSavedFlows(savedIds); + setErrorApiKey(false); + setLoadingSaved(false); + }) .catch((err) => { + setSavedFlows(new Set()); setErrorApiKey(true); - console.error(err); }); - }, []); - - async function getSavedComponents() { - setLoading(true); - const data = await getStoreSavedComponents(); - let savedIds = new Set(); - let results = data?.results ?? []; - results.forEach((flow) => { - savedIds.add(flow.id); - }); - setSavedFlows(savedIds); - setErrorApiKey(false); - setLoading(false); } const handleGetComponents = () => { setLoading(true); - setRenderPagination(true); - - getStoreComponents(index - 1, size, filterComponent.current) + getStoreComponents( + pageIndex, + pageSize, + tabActive === "All" ? null : tabActive === "Flows" ? false : true, + pageOrder === "Popular" ? "-count(liked_by)" : "name", + filteredCategories, + null, + null, + searchText === "" ? null : searchText + ) .then((res) => { setLoading(false); setSearchData(res?.results ?? []); @@ -101,85 +120,17 @@ export default function StorePage(): JSX.Element { }); }; - const handleSearch = (inputText: string) => { - if (inputText === "") { - handleGetComponents(); - return; - } - setLoading(true); - searchComponent(inputText).then( - (res) => { - setSearchData(res?.results ?? []); - setTotalRowsCount(Number(res?.count ?? 0)); - setLoading(false); - setRenderPagination(false); - setTotalRowsCount(Number(res?.count ?? 0)); - }, - (error) => { - setLoading(false); + const updateTags = (tagName: string) => { + setFilterCategories((prevArray) => { + const index = prevArray.indexOf(tagName); + if (index === -1) { + // Item does not exist in array, add it + return [...prevArray, tagName]; + } else { + // Item exists in array, remove it + return prevArray.filter((_, i) => i !== index); } - ); - }; - - function handleChangePagination(pageIndex: number, pageSize: number) { - setLoading(true); - setRenderPagination(true); - getStoreComponents(pageIndex, pageSize, filterComponent.current) - .then((res) => { - setSearchData(res?.results ?? []); - setPageIndex(pageIndex); - setPageSize(pageSize); - setLoading(false); - }) - .catch((err) => { - setSearchData([]); - setLoading(false); - setErrorData({ - title: "Error to get components.", - list: [err["response"]["data"]["detail"]], - }); - }); - } - - function handleFilterByTags(filterArray) { - if (filterArray.length === 0) { - handleGetComponents(); - return; - } - setRenderPagination(false); - searchComponent(null, 1, 10000, null, filterArray).then( - (res) => { - setSearchData(res?.results ?? []); - setLoading(false); - setTotalRowsCount(Number(res?.count ?? 0)); - }, - (error) => { - setLoading(false); - setSearchData([]); - } - ); - } - - function handleChangeTab(tab: string) { - if (tab === "All") { - filterComponent.current = null; - } else if (tab === "Flows") { - filterComponent.current = false; - } else if (tab === "Components") { - filterComponent.current = true; - } - setPageIndex(1); - setPageSize(10); - handleGetComponents(); - } - - const handleOrderPage = (e) => { - let sort; - if (e === "Popular") { - sort = "-count(liked_by)"; - } else if (e === "Alphabetical") { - sort = "name"; - } + }); }; return ( @@ -224,14 +175,14 @@ export default function StorePage(): JSX.Element { }} onKeyDown={(e) => { if (e.key === "Enter") { - handleSearch(inputText); + setSearchText(inputText); } }} value={inputText} /> { - handleSearch(inputText); + setSearchText(inputText); }} className="absolute bottom-0 right-4 top-0 my-auto h-6 cursor-pointer stroke-1 text-muted-foreground" /> @@ -240,7 +191,6 @@ export default function StorePage(): JSX.Element {