Added allLinksOfCollection to linksStore

Removed duplicated tags
Fixed overflow for line
added disclosure for tags in public collection
This commit is contained in:
Oliver Schwamb
2024-07-09 13:50:08 +02:00
parent e045c18b7d
commit e8d0cce58a
3 changed files with 87 additions and 36 deletions
+39 -24
View File
@@ -18,7 +18,7 @@ export default function useLinks(
searchByTextContent, searchByTextContent,
}: LinkRequestQuery = { sort: 0 } }: LinkRequestQuery = { sort: 0 }
) { ) {
const { links, setLinks, resetLinks, selectedLinks, setSelectedLinks } = const { links, setLinks, resetLinks, selectedLinks, setSelectedLinks, setAllLinksOfCollection } =
useLinkStore(); useLinkStore();
const router = useRouter(); const router = useRouter();
@@ -26,6 +26,34 @@ export default function useLinks(
const { reachedBottom, setReachedBottom } = useDetectPageBottom(); const { reachedBottom, setReachedBottom } = useDetectPageBottom();
const getPath = (params?: LinkRequestQuery) => {
const buildQueryString = (params: LinkRequestQuery) => {
return Object.keys(params)
.filter((key) => params[key as keyof LinkRequestQuery] !== undefined)
.map(
(key) =>
`${encodeURIComponent(key)}=${encodeURIComponent(
params[key as keyof LinkRequestQuery] as string
)}`
)
.join("&");
};
let queryString = '';
if (params) {
queryString = buildQueryString(params);
}
let basePath;
if (router.pathname === "/dashboard") basePath = "/api/v1/dashboard";
else if (router.pathname.startsWith("/public/collections/[id]")) {
queryString = queryString + "&collectionId=" + router.query.id;
basePath = "/api/v1/public/collections/links";
} else basePath = "/api/v1/links";
return `${basePath}?${queryString}`;
}
const getLinks = async (isInitialCall: boolean, cursor?: number) => { const getLinks = async (isInitialCall: boolean, cursor?: number) => {
const params = { const params = {
sort, sort,
@@ -41,31 +69,9 @@ export default function useLinks(
searchByTextContent, searchByTextContent,
}; };
const buildQueryString = (params: LinkRequestQuery) => {
return Object.keys(params)
.filter((key) => params[key as keyof LinkRequestQuery] !== undefined)
.map(
(key) =>
`${encodeURIComponent(key)}=${encodeURIComponent(
params[key as keyof LinkRequestQuery] as string
)}`
)
.join("&");
};
let queryString = buildQueryString(params);
let basePath;
if (router.pathname === "/dashboard") basePath = "/api/v1/dashboard";
else if (router.pathname.startsWith("/public/collections/[id]")) {
queryString = queryString + "&collectionId=" + router.query.id;
basePath = "/api/v1/public/collections/links";
} else basePath = "/api/v1/links";
setIsLoading(true); setIsLoading(true);
const response = await fetch(`${basePath}?${queryString}`); const response = await fetch(getPath(params));
const data = await response.json(); const data = await response.json();
@@ -74,6 +80,14 @@ export default function useLinks(
if (response.ok) setLinks(data.response, isInitialCall); if (response.ok) setLinks(data.response, isInitialCall);
}; };
const getAllLinks = async () => {
const response = await fetch(getPath());
const data = await response.json();
if (response.ok) setAllLinksOfCollection(data.response);
};
useEffect(() => { useEffect(() => {
// Save the selected links before resetting the links // Save the selected links before resetting the links
// and then restore the selected links after resetting the links // and then restore the selected links after resetting the links
@@ -81,6 +95,7 @@ export default function useLinks(
resetLinks(); resetLinks();
setSelectedLinks(previouslySelected); setSelectedLinks(previouslySelected);
getAllLinks();
getLinks(true); getLinks(true);
}, [ }, [
router, router,
+43 -11
View File
@@ -26,6 +26,7 @@ import ViewDropdown from "@/components/ViewDropdown";
import CardView from "@/components/LinkViews/Layouts/CardView"; import CardView from "@/components/LinkViews/Layouts/CardView";
import ListView from "@/components/LinkViews/Layouts/ListView"; import ListView from "@/components/LinkViews/Layouts/ListView";
import useTagStore from "@/store/tags"; import useTagStore from "@/store/tags";
import { Disclosure, Transition } from "@headlessui/react";
// import GridView from "@/components/LinkViews/Layouts/GridView"; // import GridView from "@/components/LinkViews/Layouts/GridView";
const cardVariants: Variants = { const cardVariants: Variants = {
@@ -43,9 +44,11 @@ const cardVariants: Variants = {
}; };
export default function PublicCollections() { export default function PublicCollections() {
const { links } = useLinkStore(); const { links, allLinksOfCollection } = useLinkStore();
const tagsInCollection = links.map(l => l.tags).flat(); const tagsInCollection = allLinksOfCollection.map(l => l.tags).flat().filter((value, index, self) =>
index === self.findIndex((t) => (
t.name === value.name
)));
const { settings } = useLocalSettingsStore(); const { settings } = useLocalSettingsStore();
const router = useRouter(); const router = useRouter();
@@ -101,7 +104,6 @@ export default function PublicCollections() {
const [collection, setCollection] = const [collection, setCollection] =
useState<CollectionIncludingMembersAndLinkCount>(); useState<CollectionIncludingMembersAndLinkCount>();
useEffect(() => { useEffect(() => {
if (router.query.id) { if (router.query.id) {
getPublicCollectionData(Number(router.query.id), setCollection); getPublicCollectionData(Number(router.query.id), setCollection);
@@ -132,6 +134,14 @@ export default function PublicCollections() {
[ViewMode.List]: ListView, [ViewMode.List]: ListView,
}; };
const [tagDisclosure, setTagDisclosure] = useState<boolean>(() => {
const storedValue = localStorage.getItem("tagDisclosureForPublicCollection" + collection?.id);
return storedValue ? storedValue === "true" : true;
});
useEffect(() => {
localStorage.setItem("tagDisclosureForPublicCollection" + collection?.id, tagDisclosure ? "true" : "false");
}, [tagDisclosure]);
// @ts-ignore // @ts-ignore
const LinkComponent = linkView[viewMode]; const LinkComponent = linkView[viewMode];
@@ -243,10 +253,31 @@ export default function PublicCollections() {
</div> </div>
</div> </div>
{collection.tagsArePublic && tagsInCollection[0] && ( {collection.tagsArePublic && tagsInCollection[0] && (
<div> <Disclosure defaultOpen={tagDisclosure}>
<p className="text-sm">Browse by topic</p> <Disclosure.Button
<div className="flex gap-2 mt-2 mb-6"> onClick={() => {
<button onClick={() => handleTagSelection(undefined)}> setTagDisclosure(!tagDisclosure);
}}
className="flex items-center justify-between w-full text-left mb-2 pl-2 font-bold text-neutral mt-5"
>
<p className="text-sm">Browse by topic</p>
<i
className={`bi-chevron-down ${
tagDisclosure ? "rotate-reverse" : "rotate"
}`}
></i>
</Disclosure.Button>
<Transition
enter="transition duration-100 ease-out"
enterFrom="transform opacity-0 -translate-y-3"
enterTo="transform opacity-100 translate-y-0"
leave="transition duration-100 ease-out"
leaveFrom="transform opacity-100 translate-y-0"
leaveTo="transform opacity-0 -translate-y-3"
>
<Disclosure.Panel>
<div className="flex gap-2 mt-2 mb-6 flex-wrap">
<button className="max-w-full" onClick={() => handleTagSelection(undefined)}>
<div <div
className=" className="
bg-neutral-content/20 hover:bg-neutral/20 duration-100 py-1 px-2 cursor-pointer flex items-center gap-2 rounded-md h-8" bg-neutral-content/20 hover:bg-neutral/20 duration-100 py-1 px-2 cursor-pointer flex items-center gap-2 rounded-md h-8"
@@ -263,7 +294,7 @@ export default function PublicCollections() {
.map((e, i) => { .map((e, i) => {
const active = router.query.q === e.name; const active = router.query.q === e.name;
return ( return (
<button key={i} onClick={() => handleTagSelection(e)}> <button className="max-w-full" key={i} onClick={() => handleTagSelection(e)}>
<div <div
className={` className={`
${ ${
@@ -283,8 +314,9 @@ export default function PublicCollections() {
}) })
} }
</div> </div>
</div> </Disclosure.Panel>
)} </Transition>
</Disclosure>)}
{links[0] ? ( {links[0] ? (
<LinkComponent <LinkComponent
links={links links={links
+4
View File
@@ -11,11 +11,13 @@ type ResponseObject = {
type LinkStore = { type LinkStore = {
links: LinkIncludingShortenedCollectionAndTags[]; links: LinkIncludingShortenedCollectionAndTags[];
selectedLinks: LinkIncludingShortenedCollectionAndTags[]; selectedLinks: LinkIncludingShortenedCollectionAndTags[];
allLinksOfCollection: LinkIncludingShortenedCollectionAndTags[];
setLinks: ( setLinks: (
data: LinkIncludingShortenedCollectionAndTags[], data: LinkIncludingShortenedCollectionAndTags[],
isInitialCall: boolean isInitialCall: boolean
) => void; ) => void;
setSelectedLinks: (links: LinkIncludingShortenedCollectionAndTags[]) => void; setSelectedLinks: (links: LinkIncludingShortenedCollectionAndTags[]) => void;
setAllLinksOfCollection: (links: LinkIncludingShortenedCollectionAndTags[]) => void;
addLink: ( addLink: (
body: LinkIncludingShortenedCollectionAndTags body: LinkIncludingShortenedCollectionAndTags
) => Promise<ResponseObject>; ) => Promise<ResponseObject>;
@@ -39,6 +41,7 @@ type LinkStore = {
const useLinkStore = create<LinkStore>()((set) => ({ const useLinkStore = create<LinkStore>()((set) => ({
links: [], links: [],
selectedLinks: [], selectedLinks: [],
allLinksOfCollection: [],
setLinks: async (data, isInitialCall) => { setLinks: async (data, isInitialCall) => {
isInitialCall && isInitialCall &&
set(() => ({ set(() => ({
@@ -58,6 +61,7 @@ const useLinkStore = create<LinkStore>()((set) => ({
})); }));
}, },
setSelectedLinks: (links) => set({ selectedLinks: links }), setSelectedLinks: (links) => set({ selectedLinks: links }),
setAllLinksOfCollection: (links) => set({allLinksOfCollection: links}),
addLink: async (body) => { addLink: async (body) => {
const response = await fetch("/api/v1/links", { const response = await fetch("/api/v1/links", {
body: JSON.stringify(body), body: JSON.stringify(body),