Refactored Store Page (search, tags working)
This commit is contained in:
parent
066a1a263b
commit
abc708b933
3 changed files with 78 additions and 137 deletions
|
|
@ -11,9 +11,9 @@ import IconComponent from "../genericIconComponent";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
|
|
||||||
export default function PaginatorComponent({
|
export default function PaginatorComponent({
|
||||||
pageSize = 10,
|
pageSize = 12,
|
||||||
pageIndex = 1,
|
pageIndex = 1,
|
||||||
rowsCount = [10, 20, 50, 100],
|
rowsCount = [12, 24, 48, 96],
|
||||||
totalRowsCount = 0,
|
totalRowsCount = 0,
|
||||||
paginate,
|
paginate,
|
||||||
storeComponent = false,
|
storeComponent = false,
|
||||||
|
|
|
||||||
|
|
@ -609,8 +609,8 @@ export async function getStoreComponents(
|
||||||
if (status !== undefined && status !== null) {
|
if (status !== undefined && status !== null) {
|
||||||
queryParams.push(`status=${status}`);
|
queryParams.push(`status=${status}`);
|
||||||
}
|
}
|
||||||
if (tags !== undefined && tags !== null) {
|
if (tags !== undefined && tags !== null && tags.length > 0) {
|
||||||
queryParams.push(`tags=${tags}`);
|
queryParams.push(`tags=${tags.join(",")}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sort !== undefined && sort !== null) {
|
if (sort !== undefined && sort !== null) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { cloneDeep } from "lodash";
|
|
||||||
import { Search } from "lucide-react";
|
import { Search } from "lucide-react";
|
||||||
import { useContext, useEffect, useRef, useState } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
import PaginatorComponent from "../../components/PaginatorComponent";
|
import PaginatorComponent from "../../components/PaginatorComponent";
|
||||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
|
|
@ -23,7 +22,6 @@ import {
|
||||||
getStoreComponents,
|
getStoreComponents,
|
||||||
getStoreSavedComponents,
|
getStoreSavedComponents,
|
||||||
getStoreTags,
|
getStoreTags,
|
||||||
searchComponent,
|
|
||||||
} from "../../controllers/API";
|
} from "../../controllers/API";
|
||||||
import StoreApiKeyModal from "../../modals/StoreApiKeyModal";
|
import StoreApiKeyModal from "../../modals/StoreApiKeyModal";
|
||||||
import { storeComponent } from "../../types/store";
|
import { storeComponent } from "../../types/store";
|
||||||
|
|
@ -34,42 +32,51 @@ export default function StorePage(): JSX.Element {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTabId("");
|
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<any[]>([]);
|
const [filteredCategories, setFilterCategories] = useState<any[]>([]);
|
||||||
const [inputText, setInputText] = useState<string>("");
|
const [inputText, setInputText] = useState<string>("");
|
||||||
const [searchData, setSearchData] = useState<storeComponent[]>([]);
|
const [searchData, setSearchData] = useState<storeComponent[]>([]);
|
||||||
const { setErrorData } = useContext(alertContext);
|
|
||||||
const [totalRowsCount, setTotalRowsCount] = useState(0);
|
const [totalRowsCount, setTotalRowsCount] = useState(0);
|
||||||
const [size, setPageSize] = useState(10);
|
const [pageSize, setPageSize] = useState(12);
|
||||||
const [index, setPageIndex] = useState(1);
|
const [pageIndex, setPageIndex] = useState(1);
|
||||||
|
const [pageOrder, setPageOrder] = useState("Popular");
|
||||||
const [errorApiKey, setErrorApiKey] = useState(false);
|
const [errorApiKey, setErrorApiKey] = useState(false);
|
||||||
const { setSavedFlows, hasApiKey } = useContext(StoreContext);
|
|
||||||
const [tags, setTags] = useState<{ id: string; name: string }[]>([]);
|
const [tags, setTags] = useState<{ id: string; name: string }[]>([]);
|
||||||
const tagListId = useRef<{ id: string; name: string }[]>([]);
|
|
||||||
const [renderPagination, setRenderPagination] = useState(false);
|
|
||||||
const filterComponent = useRef<boolean | null>(null);
|
|
||||||
const [tabActive, setTabActive] = useState("Flows");
|
const [tabActive, setTabActive] = useState("Flows");
|
||||||
|
const [searchText, setSearchText] = useState("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
handleGetSavedComponents();
|
||||||
|
handleGetTags();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleGetComponents();
|
||||||
|
}, [
|
||||||
|
searchText,
|
||||||
|
tabActive,
|
||||||
|
pageOrder,
|
||||||
|
pageIndex,
|
||||||
|
pageSize,
|
||||||
|
filteredCategories,
|
||||||
|
]);
|
||||||
|
|
||||||
|
function handleGetTags() {
|
||||||
|
setLoadingTags(true);
|
||||||
getStoreTags().then((res) => {
|
getStoreTags().then((res) => {
|
||||||
tagListId.current = res;
|
|
||||||
setTags(res);
|
setTags(res);
|
||||||
|
setLoadingTags(false);
|
||||||
});
|
});
|
||||||
}, []);
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
function handleGetSavedComponents() {
|
||||||
filterComponent.current = false;
|
setLoadingSaved(true);
|
||||||
getSavedComponents()
|
getStoreSavedComponents()
|
||||||
.finally(() => handleGetComponents())
|
.then((data) => {
|
||||||
.catch((err) => {
|
|
||||||
setErrorApiKey(true);
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
async function getSavedComponents() {
|
|
||||||
setLoading(true);
|
|
||||||
const data = await getStoreSavedComponents();
|
|
||||||
let savedIds = new Set<string>();
|
let savedIds = new Set<string>();
|
||||||
let results = data?.results ?? [];
|
let results = data?.results ?? [];
|
||||||
results.forEach((flow) => {
|
results.forEach((flow) => {
|
||||||
|
|
@ -77,14 +84,26 @@ export default function StorePage(): JSX.Element {
|
||||||
});
|
});
|
||||||
setSavedFlows(savedIds);
|
setSavedFlows(savedIds);
|
||||||
setErrorApiKey(false);
|
setErrorApiKey(false);
|
||||||
setLoading(false);
|
setLoadingSaved(false);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
setSavedFlows(new Set<string>());
|
||||||
|
setErrorApiKey(true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleGetComponents = () => {
|
const handleGetComponents = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setRenderPagination(true);
|
getStoreComponents(
|
||||||
|
pageIndex,
|
||||||
getStoreComponents(index - 1, size, filterComponent.current)
|
pageSize,
|
||||||
|
tabActive === "All" ? null : tabActive === "Flows" ? false : true,
|
||||||
|
pageOrder === "Popular" ? "-count(liked_by)" : "name",
|
||||||
|
filteredCategories,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
searchText === "" ? null : searchText
|
||||||
|
)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setSearchData(res?.results ?? []);
|
setSearchData(res?.results ?? []);
|
||||||
|
|
@ -101,85 +120,17 @@ export default function StorePage(): JSX.Element {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSearch = (inputText: string) => {
|
const updateTags = (tagName: string) => {
|
||||||
if (inputText === "") {
|
setFilterCategories((prevArray) => {
|
||||||
handleGetComponents();
|
const index = prevArray.indexOf(tagName);
|
||||||
return;
|
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);
|
||||||
}
|
}
|
||||||
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);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
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 (
|
return (
|
||||||
|
|
@ -224,14 +175,14 @@ export default function StorePage(): JSX.Element {
|
||||||
}}
|
}}
|
||||||
onKeyDown={(e) => {
|
onKeyDown={(e) => {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
handleSearch(inputText);
|
setSearchText(inputText);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
value={inputText}
|
value={inputText}
|
||||||
/>
|
/>
|
||||||
<Search
|
<Search
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleSearch(inputText);
|
setSearchText(inputText);
|
||||||
}}
|
}}
|
||||||
className="absolute bottom-0 right-4 top-0 my-auto h-6 cursor-pointer stroke-1 text-muted-foreground"
|
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 {
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setTabActive("All");
|
setTabActive("All");
|
||||||
handleChangeTab("All");
|
|
||||||
}}
|
}}
|
||||||
className={
|
className={
|
||||||
tabActive === "All"
|
tabActive === "All"
|
||||||
|
|
@ -253,7 +203,6 @@ export default function StorePage(): JSX.Element {
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setTabActive("Flows");
|
setTabActive("Flows");
|
||||||
handleChangeTab("Flows");
|
|
||||||
}}
|
}}
|
||||||
className={
|
className={
|
||||||
tabActive === "Flows"
|
tabActive === "Flows"
|
||||||
|
|
@ -266,7 +215,6 @@ export default function StorePage(): JSX.Element {
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setTabActive("Components");
|
setTabActive("Components");
|
||||||
handleChangeTab("Components");
|
|
||||||
}}
|
}}
|
||||||
className={
|
className={
|
||||||
tabActive === "Components"
|
tabActive === "Components"
|
||||||
|
|
@ -285,19 +233,11 @@ export default function StorePage(): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2 px-2">
|
<div className="flex items-center gap-2 px-2">
|
||||||
{!loading &&
|
{!loadingTags &&
|
||||||
tags.map((tag, idx) => (
|
tags.map((tag, idx) => (
|
||||||
<Badge
|
<Badge
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const index = filteredCategories?.indexOf(tag.name);
|
updateTags(tag.name);
|
||||||
const copyFilterArray = cloneDeep(filteredCategories);
|
|
||||||
if (index === -1) {
|
|
||||||
copyFilterArray.push(tag.name);
|
|
||||||
} else {
|
|
||||||
copyFilterArray.splice(index, 1);
|
|
||||||
}
|
|
||||||
setFilterCategories(copyFilterArray);
|
|
||||||
handleFilterByTags(copyFilterArray);
|
|
||||||
}}
|
}}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sq"
|
size="sq"
|
||||||
|
|
@ -316,14 +256,14 @@ export default function StorePage(): JSX.Element {
|
||||||
<span className="px-0.5 text-sm text-muted-foreground">
|
<span className="px-0.5 text-sm text-muted-foreground">
|
||||||
{!loading && (
|
{!loading && (
|
||||||
<>
|
<>
|
||||||
{totalRowsCount} {totalRowsCount > 0 ? "results" : "result"}
|
{totalRowsCount} {totalRowsCount !== 1 ? "results" : "result"}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
onValueChange={(e) => {
|
onValueChange={(e) => {
|
||||||
handleOrderPage(e);
|
setPageOrder(e);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
|
|
@ -356,15 +296,16 @@ export default function StorePage(): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!loading && renderPagination && (
|
{!loading && (
|
||||||
<div className="relative my-3">
|
<div className="relative my-3">
|
||||||
<PaginatorComponent
|
<PaginatorComponent
|
||||||
storeComponent={true}
|
storeComponent={true}
|
||||||
pageIndex={index}
|
pageIndex={pageIndex}
|
||||||
pageSize={size}
|
pageSize={pageSize}
|
||||||
totalRowsCount={totalRowsCount}
|
totalRowsCount={totalRowsCount}
|
||||||
paginate={(pageSize, pageIndex) => {
|
paginate={(pageSize, pageIndex) => {
|
||||||
handleChangePagination(pageIndex, pageSize);
|
setPageIndex(pageIndex);
|
||||||
|
setPageSize(pageSize);
|
||||||
}}
|
}}
|
||||||
></PaginatorComponent>
|
></PaginatorComponent>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue