From 30ef557f43a027c0d345c5a5f80f44f33ba5d648 Mon Sep 17 00:00:00 2001
From: daniel31x13
Date: Fri, 26 Apr 2024 12:18:31 -0400
Subject: [PATCH] small improvements
---
components/LinkViews/Layouts/GridView.tsx | 16 --
components/LinkViews/Layouts/MasonryView.tsx | 5 +-
components/LinkViews/LinkCard.tsx | 60 ++---
components/LinkViews/LinkGrid.tsx | 111 ---------
components/LinkViews/LinkMasonry.tsx | 244 +++++++++++++++++++
pages/collections/[id].tsx | 2 -
pages/dashboard.tsx | 3 +-
pages/links/index.tsx | 2 -
pages/links/pinned.tsx | 2 -
pages/public/collections/[id].tsx | 2 -
pages/search.tsx | 26 +-
pages/tags/[id].tsx | 2 -
12 files changed, 289 insertions(+), 186 deletions(-)
delete mode 100644 components/LinkViews/Layouts/GridView.tsx
delete mode 100644 components/LinkViews/LinkGrid.tsx
create mode 100644 components/LinkViews/LinkMasonry.tsx
diff --git a/components/LinkViews/Layouts/GridView.tsx b/components/LinkViews/Layouts/GridView.tsx
deleted file mode 100644
index 005ba28..0000000
--- a/components/LinkViews/Layouts/GridView.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import LinkGrid from "@/components/LinkViews/LinkGrid";
-import { LinkIncludingShortenedCollectionAndTags } from "@/types/global";
-
-export default function GridView({
- links,
-}: {
- links: LinkIncludingShortenedCollectionAndTags[];
-}) {
- return (
-
- {links.map((e, i) => {
- return ;
- })}
-
- );
-}
diff --git a/components/LinkViews/Layouts/MasonryView.tsx b/components/LinkViews/Layouts/MasonryView.tsx
index 1caca9f..9a06a0e 100644
--- a/components/LinkViews/Layouts/MasonryView.tsx
+++ b/components/LinkViews/Layouts/MasonryView.tsx
@@ -1,4 +1,4 @@
-import LinkCard from "@/components/LinkViews/LinkCard";
+import LinkMasonry from "@/components/LinkViews/LinkMasonry";
import { LinkIncludingShortenedCollectionAndTags } from "@/types/global";
import { GridLoader } from "react-spinners";
import Masonry from "react-masonry-css";
@@ -30,12 +30,11 @@ export default function MasonryView({
{links.map((e, i) => {
return (
-
- {viewMode === "masonry" && !previewAvailable(link) ? null : (
- <>
-
- {previewAvailable(link) ? (
-
{
- const target = e.target as HTMLElement;
- target.style.display = "none";
- }}
- />
- ) : link.preview === "unavailable" ? (
-
- ) : (
-
- )}
-
-
-
-
+
+ {previewAvailable(link) ? (
+
{
+ const target = e.target as HTMLElement;
+ target.style.display = "none";
+ }}
+ />
+ ) : link.preview === "unavailable" ? (
+
+ ) : (
+
+ )}
+
+
+
+
-
- >
- )}
+
@@ -234,11 +230,7 @@ export default function LinkCard({ link, flipDropdown, editMode }: Props) {
setShowInfo(!showInfo)}
linkInfo={showInfo}
flipDropdown={flipDropdown}
diff --git a/components/LinkViews/LinkGrid.tsx b/components/LinkViews/LinkGrid.tsx
deleted file mode 100644
index be4d6ed..0000000
--- a/components/LinkViews/LinkGrid.tsx
+++ /dev/null
@@ -1,111 +0,0 @@
-import {
- CollectionIncludingMembersAndLinkCount,
- LinkIncludingShortenedCollectionAndTags,
-} from "@/types/global";
-import { useEffect, useState } from "react";
-import useLinkStore from "@/store/links";
-import useCollectionStore from "@/store/collections";
-import unescapeString from "@/lib/client/unescapeString";
-import LinkActions from "@/components/LinkViews/LinkComponents/LinkActions";
-import LinkDate from "@/components/LinkViews/LinkComponents/LinkDate";
-import LinkCollection from "@/components/LinkViews/LinkComponents/LinkCollection";
-import LinkIcon from "@/components/LinkViews/LinkComponents/LinkIcon";
-import Link from "next/link";
-
-type Props = {
- link: LinkIncludingShortenedCollectionAndTags;
- count: number;
- className?: string;
-};
-
-export default function LinkGrid({ link }: Props) {
- const { collections } = useCollectionStore();
-
- const { links } = useLinkStore();
-
- let shortendURL;
-
- try {
- shortendURL = new URL(link.url || "").host.toLowerCase();
- } catch (error) {
- console.log(error);
- }
-
- const [collection, setCollection] =
- useState(
- collections.find(
- (e) => e.id === link.collection.id
- ) as CollectionIncludingMembersAndLinkCount
- );
-
- useEffect(() => {
- setCollection(
- collections.find(
- (e) => e.id === link.collection.id
- ) as CollectionIncludingMembersAndLinkCount
- );
- }, [collections, links]);
-
- return (
-
-
link.url && window.open(link.url || "", "_blank")}
- className="cursor-pointer"
- >
-
-
- {unescapeString(link.name || link.description) || link.url}
-
-
-
-
-
- ·
- {link.url ? (
-
{
- e.preventDefault();
- window.open(link.url || "", "_blank");
- }}
- className="flex items-center hover:opacity-60 cursor-pointer duration-100"
- >
-
{shortendURL}
-
- ) : (
-
- {link.type}
-
- )}
-
-
-
-
{unescapeString(link.description)}
- {link.tags[0] ? (
-
-
- {link.tags.map((e, i) => (
- {
- e.stopPropagation();
- }}
- className="btn btn-xs btn-ghost truncate max-w-[19rem]"
- >
- #{e.name}
-
- ))}
-
-
- ) : undefined}
-
-
-
{}}
- linkInfo={false}
- link={link}
- collection={collection}
- />
-
- );
-}
diff --git a/components/LinkViews/LinkMasonry.tsx b/components/LinkViews/LinkMasonry.tsx
new file mode 100644
index 0000000..62c6cfb
--- /dev/null
+++ b/components/LinkViews/LinkMasonry.tsx
@@ -0,0 +1,244 @@
+import {
+ ArchivedFormat,
+ CollectionIncludingMembersAndLinkCount,
+ LinkIncludingShortenedCollectionAndTags,
+} from "@/types/global";
+import { useEffect, useRef, useState } from "react";
+import useLinkStore from "@/store/links";
+import useCollectionStore from "@/store/collections";
+import unescapeString from "@/lib/client/unescapeString";
+import LinkActions from "@/components/LinkViews/LinkComponents/LinkActions";
+import LinkDate from "@/components/LinkViews/LinkComponents/LinkDate";
+import LinkCollection from "@/components/LinkViews/LinkComponents/LinkCollection";
+import Image from "next/image";
+import { previewAvailable } from "@/lib/shared/getArchiveValidity";
+import Link from "next/link";
+import LinkIcon from "./LinkComponents/LinkIcon";
+import useOnScreen from "@/hooks/useOnScreen";
+import { generateLinkHref } from "@/lib/client/generateLinkHref";
+import useAccountStore from "@/store/account";
+import usePermissions from "@/hooks/usePermissions";
+import toast from "react-hot-toast";
+import LinkTypeBadge from "./LinkComponents/LinkTypeBadge";
+
+type Props = {
+ link: LinkIncludingShortenedCollectionAndTags;
+ count: number;
+ className?: string;
+ flipDropdown?: boolean;
+ editMode?: boolean;
+};
+
+export default function LinkMasonry({ link, flipDropdown, editMode }: Props) {
+ const viewMode = localStorage.getItem("viewMode") || "card";
+ const { collections } = useCollectionStore();
+ const { account } = useAccountStore();
+
+ const { links, getLink, setSelectedLinks, selectedLinks } = useLinkStore();
+
+ useEffect(() => {
+ if (!editMode) {
+ setSelectedLinks([]);
+ }
+ }, [editMode]);
+
+ const handleCheckboxClick = (
+ link: LinkIncludingShortenedCollectionAndTags
+ ) => {
+ if (selectedLinks.includes(link)) {
+ setSelectedLinks(selectedLinks.filter((e) => e !== link));
+ } else {
+ setSelectedLinks([...selectedLinks, link]);
+ }
+ };
+
+ let shortendURL;
+
+ try {
+ if (link.url) {
+ shortendURL = new URL(link.url).host.toLowerCase();
+ }
+ } catch (error) {
+ console.log(error);
+ }
+
+ const [collection, setCollection] =
+ useState(
+ collections.find(
+ (e) => e.id === link.collection.id
+ ) as CollectionIncludingMembersAndLinkCount
+ );
+
+ useEffect(() => {
+ setCollection(
+ collections.find(
+ (e) => e.id === link.collection.id
+ ) as CollectionIncludingMembersAndLinkCount
+ );
+ }, [collections, links]);
+
+ const ref = useRef(null);
+ const isVisible = useOnScreen(ref);
+ const permissions = usePermissions(collection?.id as number);
+
+ useEffect(() => {
+ let interval: any;
+
+ if (
+ isVisible &&
+ !link.preview?.startsWith("archives") &&
+ link.preview !== "unavailable"
+ ) {
+ interval = setInterval(async () => {
+ getLink(link.id as number);
+ }, 5000);
+ }
+
+ return () => {
+ if (interval) {
+ clearInterval(interval);
+ }
+ };
+ }, [isVisible, link.preview]);
+
+ const [showInfo, setShowInfo] = useState(false);
+
+ const selectedStyle = selectedLinks.some(
+ (selectedLink) => selectedLink.id === link.id
+ )
+ ? "border-primary bg-base-300"
+ : "border-neutral-content";
+
+ const selectable =
+ editMode &&
+ (permissions === true || permissions?.canCreate || permissions?.canDelete);
+
+ return (
+
+ selectable
+ ? handleCheckboxClick(link)
+ : editMode
+ ? toast.error(
+ "You don't have permission to edit or delete this item."
+ )
+ : undefined
+ }
+ >
+
+ !editMode && window.open(generateLinkHref(link, account), "_blank")
+ }
+ >
+
+ {previewAvailable(link) ? (
+
{
+ const target = e.target as HTMLElement;
+ target.style.display = "none";
+ }}
+ />
+ ) : link.preview === "unavailable" ? null : (
+
+ )}
+
+
+
+
+
+ {link.preview !== "unavailable" && (
+
+ )}
+
+
+
+ {unescapeString(link.name || link.description) || link.url}
+
+
+
+
+
+
+
+
+
+ {collection && (
+
+ )}
+
+
+
+
+
+ {showInfo && (
+
+
setShowInfo(!showInfo)}
+ className=" float-right btn btn-sm outline-none btn-circle btn-ghost z-10"
+ >
+
+
+
Description
+
+
+
+ {link.description ? (
+ unescapeString(link.description)
+ ) : (
+
+ No description provided.
+
+ )}
+
+ {link.tags[0] && (
+ <>
+
Tags
+
+
+
+
+
+ {link.tags.map((e, i) => (
+ {
+ e.stopPropagation();
+ }}
+ className="btn btn-xs btn-ghost truncate max-w-[19rem]"
+ >
+ #{e.name}
+
+ ))}
+
+
+ >
+ )}
+
+ )}
+
+
setShowInfo(!showInfo)}
+ linkInfo={showInfo}
+ flipDropdown={flipDropdown}
+ />
+
+ );
+}
diff --git a/pages/collections/[id].tsx b/pages/collections/[id].tsx
index e1ba2b8..046c855 100644
--- a/pages/collections/[id].tsx
+++ b/pages/collections/[id].tsx
@@ -21,7 +21,6 @@ import EditCollectionSharingModal from "@/components/ModalContent/EditCollection
import DeleteCollectionModal from "@/components/ModalContent/DeleteCollectionModal";
import ViewDropdown from "@/components/ViewDropdown";
import CardView from "@/components/LinkViews/Layouts/CardView";
-// import GridView from "@/components/LinkViews/Layouts/GridView";
import ListView from "@/components/LinkViews/Layouts/ListView";
import { dropdownTriggerer } from "@/lib/client/utils";
import NewCollectionModal from "@/components/ModalContent/NewCollectionModal";
@@ -109,7 +108,6 @@ export default function Index() {
const linkView = {
[ViewMode.Card]: CardView,
- // [ViewMode.Grid]: GridView,
[ViewMode.List]: ListView,
[ViewMode.Masonry]: MasonryView,
};
diff --git a/pages/dashboard.tsx b/pages/dashboard.tsx
index 04882f1..c940b65 100644
--- a/pages/dashboard.tsx
+++ b/pages/dashboard.tsx
@@ -17,7 +17,6 @@ import ListView from "@/components/LinkViews/Layouts/ListView";
import ViewDropdown from "@/components/ViewDropdown";
import { dropdownTriggerer } from "@/lib/client/utils";
import MasonryView from "@/components/LinkViews/Layouts/MasonryView";
-// import GridView from "@/components/LinkViews/Layouts/GridView";
export default function Dashboard() {
const { collections } = useCollectionStore();
@@ -101,7 +100,7 @@ export default function Dashboard() {
const linkView = {
[ViewMode.Card]: CardView,
- // [ViewMode.Grid]: GridView,
+ // [ViewMode.Grid]: ,
[ViewMode.List]: ListView,
[ViewMode.Masonry]: MasonryView,
};
diff --git a/pages/links/index.tsx b/pages/links/index.tsx
index 2b1e67b..d617d15 100644
--- a/pages/links/index.tsx
+++ b/pages/links/index.tsx
@@ -13,7 +13,6 @@ import useCollectivePermissions from "@/hooks/useCollectivePermissions";
import toast from "react-hot-toast";
import BulkDeleteLinksModal from "@/components/ModalContent/BulkDeleteLinksModal";
import BulkEditLinksModal from "@/components/ModalContent/BulkEditLinksModal";
-// import GridView from "@/components/LinkViews/Layouts/GridView";
import { useRouter } from "next/router";
import MasonryView from "@/components/LinkViews/Layouts/MasonryView";
@@ -73,7 +72,6 @@ export default function Links() {
const linkView = {
[ViewMode.Card]: CardView,
- // [ViewMode.Grid]: GridView,
[ViewMode.List]: ListView,
[ViewMode.Masonry]: MasonryView,
};
diff --git a/pages/links/pinned.tsx b/pages/links/pinned.tsx
index f201844..a56af06 100644
--- a/pages/links/pinned.tsx
+++ b/pages/links/pinned.tsx
@@ -12,7 +12,6 @@ import BulkDeleteLinksModal from "@/components/ModalContent/BulkDeleteLinksModal
import BulkEditLinksModal from "@/components/ModalContent/BulkEditLinksModal";
import useCollectivePermissions from "@/hooks/useCollectivePermissions";
import toast from "react-hot-toast";
-// import GridView from "@/components/LinkViews/Layouts/GridView";
import { useRouter } from "next/router";
import MasonryView from "@/components/LinkViews/Layouts/MasonryView";
@@ -71,7 +70,6 @@ export default function PinnedLinks() {
const linkView = {
[ViewMode.Card]: CardView,
- // [ViewMode.Grid]: GridView,
[ViewMode.List]: ListView,
[ViewMode.Masonry]: MasonryView,
};
diff --git a/pages/public/collections/[id].tsx b/pages/public/collections/[id].tsx
index c72f0a5..05574a7 100644
--- a/pages/public/collections/[id].tsx
+++ b/pages/public/collections/[id].tsx
@@ -25,7 +25,6 @@ import ViewDropdown from "@/components/ViewDropdown";
import CardView from "@/components/LinkViews/Layouts/CardView";
import ListView from "@/components/LinkViews/Layouts/ListView";
import MasonryView from "@/components/LinkViews/Layouts/MasonryView";
-// import GridView from "@/components/LinkViews/Layouts/GridView";
const cardVariants: Variants = {
offscreen: {
@@ -108,7 +107,6 @@ export default function PublicCollections() {
const linkView = {
[ViewMode.Card]: CardView,
- // [ViewMode.Grid]: GridView,
[ViewMode.List]: ListView,
[ViewMode.Masonry]: MasonryView,
};
diff --git a/pages/search.tsx b/pages/search.tsx
index 9114f41..27e2361 100644
--- a/pages/search.tsx
+++ b/pages/search.tsx
@@ -8,7 +8,6 @@ import { useRouter } from "next/router";
import React, { useEffect, useState } from "react";
import ViewDropdown from "@/components/ViewDropdown";
import CardView from "@/components/LinkViews/Layouts/CardView";
-// import GridView from "@/components/LinkViews/Layouts/GridView";
import ListView from "@/components/LinkViews/Layouts/ListView";
import PageHeader from "@/components/PageHeader";
import { GridLoader } from "react-spinners";
@@ -19,7 +18,8 @@ import BulkEditLinksModal from "@/components/ModalContent/BulkEditLinksModal";
import MasonryView from "@/components/LinkViews/Layouts/MasonryView";
export default function Search() {
- const { links, selectedLinks, setSelectedLinks, deleteLinksById } = useLinkStore();
+ const { links, selectedLinks, setSelectedLinks, deleteLinksById } =
+ useLinkStore();
const router = useRouter();
@@ -59,7 +59,8 @@ export default function Search() {
const bulkDeleteLinks = async () => {
const load = toast.loading(
- `Deleting ${selectedLinks.length} Link${selectedLinks.length > 1 ? "s" : ""
+ `Deleting ${selectedLinks.length} Link${
+ selectedLinks.length > 1 ? "s" : ""
}...`
);
@@ -71,7 +72,8 @@ export default function Search() {
response.ok &&
toast.success(
- `Deleted ${selectedLinks.length} Link${selectedLinks.length > 1 ? "s" : ""
+ `Deleted ${selectedLinks.length} Link${
+ selectedLinks.length > 1 ? "s" : ""
}!`
);
};
@@ -92,7 +94,6 @@ export default function Search() {
const linkView = {
[ViewMode.Card]: CardView,
- // [ViewMode.Grid]: GridView,
[ViewMode.List]: ListView,
[ViewMode.Masonry]: MasonryView,
};
@@ -115,10 +116,11 @@ export default function Search() {
setEditMode(!editMode);
setSelectedLinks([]);
}}
- className={`btn btn-square btn-sm btn-ghost ${editMode
- ? "bg-primary/20 hover:bg-primary/20"
- : "hover:bg-neutral/20"
- }`}
+ className={`btn btn-square btn-sm btn-ghost ${
+ editMode
+ ? "bg-primary/20 hover:bg-primary/20"
+ : "hover:bg-neutral/20"
+ }`}
>
@@ -199,7 +201,11 @@ export default function Search() {
) : links[0] ? (
-
+
) : (
isLoading && (