From 4a0e75c6e57b95361026803454770e97cc0b2edb Mon Sep 17 00:00:00 2001
From: daniel31x13
Date: Sun, 10 Mar 2024 06:08:28 -0400
Subject: [PATCH] improved UX + improved performance
---
components/CollectionListing.tsx | 5 +-
components/FilterSearchDropdown.tsx | 46 ++++++++++---------
components/LinkViews/Layouts/CardView.tsx | 15 +++++-
components/LinkViews/Layouts/ListView.tsx | 12 +++++
components/LinkViews/LinkCard.tsx | 18 +++++---
.../LinkComponents/LinkCollection.tsx | 11 +++--
components/LinkViews/LinkList.tsx | 16 +++++--
components/Navbar.tsx | 2 +-
components/SettingsSidebar.tsx | 2 +-
hooks/useLinks.tsx | 10 +++-
package.json | 3 +-
pages/dashboard.tsx | 6 +--
pages/public/collections/[id].tsx | 2 +-
pages/search.tsx | 28 ++++++++---
.../migration.sql | 5 ++
.../migration.sql | 2 +
prisma/schema.prisma | 4 ++
yarn.lock | 5 ++
18 files changed, 135 insertions(+), 57 deletions(-)
create mode 100644 prisma/migrations/20240310062152_added_indexes/migration.sql
create mode 100644 prisma/migrations/20240310062318_added_index_to_ownerid_on_tag_model/migration.sql
diff --git a/components/CollectionListing.tsx b/components/CollectionListing.tsx
index eb43386..171117b 100644
--- a/components/CollectionListing.tsx
+++ b/components/CollectionListing.tsx
@@ -47,7 +47,10 @@ const CollectionListing = () => {
useEffect(() => {
if (account.username) {
- if (!account.collectionOrder || account.collectionOrder.length === 0)
+ if (
+ (!account.collectionOrder || account.collectionOrder.length === 0) &&
+ collections.length > 0
+ )
updateAccount({
...account,
collectionOrder: collections
diff --git a/components/FilterSearchDropdown.tsx b/components/FilterSearchDropdown.tsx
index 57a0ea4..01b8906 100644
--- a/components/FilterSearchDropdown.tsx
+++ b/components/FilterSearchDropdown.tsx
@@ -26,7 +26,7 @@ export default function FilterSearchDropdown({
>
-
+
);
diff --git a/components/LinkViews/Layouts/CardView.tsx b/components/LinkViews/Layouts/CardView.tsx
index 77b0a54..892e3ff 100644
--- a/components/LinkViews/Layouts/CardView.tsx
+++ b/components/LinkViews/Layouts/CardView.tsx
@@ -1,14 +1,16 @@
import LinkCard from "@/components/LinkViews/LinkCard";
import { LinkIncludingShortenedCollectionAndTags } from "@/types/global";
+import { link } from "fs";
+import { GridLoader } from "react-spinners";
export default function CardView({
links,
- showCheckbox = true,
editMode,
+ isLoading,
}: {
links: LinkIncludingShortenedCollectionAndTags[];
- showCheckbox?: boolean;
editMode?: boolean;
+ isLoading?: boolean;
}) {
return (
@@ -23,6 +25,15 @@ export default function CardView({
/>
);
})}
+
+ {isLoading && links.length > 0 && (
+
+ )}
);
}
diff --git a/components/LinkViews/Layouts/ListView.tsx b/components/LinkViews/Layouts/ListView.tsx
index 1939f81..a83609c 100644
--- a/components/LinkViews/Layouts/ListView.tsx
+++ b/components/LinkViews/Layouts/ListView.tsx
@@ -1,12 +1,15 @@
import LinkList from "@/components/LinkViews/LinkList";
import { LinkIncludingShortenedCollectionAndTags } from "@/types/global";
+import { GridLoader } from "react-spinners";
export default function ListView({
links,
editMode,
+ isLoading,
}: {
links: LinkIncludingShortenedCollectionAndTags[];
editMode?: boolean;
+ isLoading?: boolean;
}) {
return (
@@ -21,6 +24,15 @@ export default function ListView({
/>
);
})}
+
+ {isLoading && links.length > 0 && (
+
+ )}
);
}
diff --git a/components/LinkViews/LinkCard.tsx b/components/LinkViews/LinkCard.tsx
index 3ee9050..d93904a 100644
--- a/components/LinkViews/LinkCard.tsx
+++ b/components/LinkViews/LinkCard.tsx
@@ -162,12 +162,18 @@ export default function LinkCard({ link, flipDropdown, editMode }: Props) {
{unescapeString(link.name || link.description) || link.url}
-
+ {
+ e.stopPropagation();
+ }}
+ className="flex gap-1 item-center select-none text-neutral mt-1 hover:opacity-70 duration-100"
+ >
+
+ {shortendURL}
+
diff --git a/components/LinkViews/LinkComponents/LinkCollection.tsx b/components/LinkViews/LinkComponents/LinkCollection.tsx
index 35b85b9..f7853ba 100644
--- a/components/LinkViews/LinkComponents/LinkCollection.tsx
+++ b/components/LinkViews/LinkComponents/LinkCollection.tsx
@@ -2,6 +2,7 @@ import {
CollectionIncludingMembersAndLinkCount,
LinkIncludingShortenedCollectionAndTags,
} from "@/types/global";
+import Link from "next/link";
import { useRouter } from "next/router";
import React from "react";
@@ -15,12 +16,12 @@ export default function LinkCollection({
const router = useRouter();
return (
- {
- e.preventDefault();
- router.push(`/collections/${link.collection.id}`);
+ e.stopPropagation();
}}
- className="flex items-center gap-1 max-w-full w-fit hover:opacity-70 duration-100"
+ className="flex items-center gap-1 max-w-full w-fit hover:opacity-70 duration-100 select-none"
title={collection?.name}
>
{collection?.name}
-
+
);
}
diff --git a/components/LinkViews/LinkList.tsx b/components/LinkViews/LinkList.tsx
index 89d26cd..a535adf 100644
--- a/components/LinkViews/LinkList.tsx
+++ b/components/LinkViews/LinkList.tsx
@@ -144,10 +144,18 @@ export default function LinkCardCompact({
) : undefined}
{link.url ? (
-
+ {
+ e.stopPropagation();
+ }}
+ className="flex gap-1 item-center select-none text-neutral mt-1 hover:opacity-70 duration-100"
+ >
+
+ {shortendURL}
+
) : (
{link.type}
diff --git a/components/Navbar.tsx b/components/Navbar.tsx
index 04a5d76..cb38c93 100644
--- a/components/Navbar.tsx
+++ b/components/Navbar.tsx
@@ -65,7 +65,7 @@ export default function Navbar() {
-
+
{
@@ -61,10 +63,14 @@ export default function useLinks(
basePath = "/api/v1/public/collections/links";
} else basePath = "/api/v1/links";
+ setIsLoading(true);
+
const response = await fetch(`${basePath}?${queryString}`);
const data = await response.json();
+ setIsLoading(false);
+
if (response.ok) setLinks(data.response, isInitialCall);
};
@@ -92,4 +98,6 @@ export default function useLinks(
setReachedBottom(false);
}, [reachedBottom]);
+
+ return { isLoading };
}
diff --git a/package.json b/package.json
index 1f17a6b..f1f2894 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "linkwarden",
- "version": "2.5.0",
+ "version": "2.5.1",
"main": "index.js",
"repository": "https://github.com/linkwarden/linkwarden.git",
"author": "Daniel31X13
",
@@ -61,6 +61,7 @@
"react-hot-toast": "^2.4.1",
"react-image-file-resizer": "^0.4.8",
"react-select": "^5.7.4",
+ "react-spinners": "^0.13.8",
"socks-proxy-agent": "^8.0.2",
"stripe": "^12.13.0",
"vaul": "^0.8.8",
diff --git a/pages/dashboard.tsx b/pages/dashboard.tsx
index ec5dc78..6fabf33 100644
--- a/pages/dashboard.tsx
+++ b/pages/dashboard.tsx
@@ -168,10 +168,7 @@ export default function Dashboard() {
>
{links[0] ? (
-
+
) : (
e.pinnedBy && e.pinnedBy[0]) ? (
e.pinnedBy && e.pinnedBy[0])
.slice(0, showLinks)}
diff --git a/pages/public/collections/[id].tsx b/pages/public/collections/[id].tsx
index 203f002..d918086 100644
--- a/pages/public/collections/[id].tsx
+++ b/pages/public/collections/[id].tsx
@@ -60,8 +60,8 @@ export default function PublicCollections() {
name: true,
url: true,
description: true,
- textContent: true,
tags: true,
+ textContent: false,
});
const [sortBy, setSortBy] = useState(Sort.DateNewestFirst);
diff --git a/pages/search.tsx b/pages/search.tsx
index ec686bf..f89c799 100644
--- a/pages/search.tsx
+++ b/pages/search.tsx
@@ -5,12 +5,13 @@ import MainLayout from "@/layouts/MainLayout";
import useLinkStore from "@/store/links";
import { Sort, ViewMode } from "@/types/global";
import { useRouter } from "next/router";
-import React, { useState } from "react";
+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, PropagateLoader } from "react-spinners";
export default function Search() {
const { links } = useLinkStore();
@@ -21,8 +22,8 @@ export default function Search() {
name: true,
url: true,
description: true,
- textContent: true,
tags: true,
+ textContent: false,
});
const [viewMode, setViewMode] = useState(
@@ -30,7 +31,7 @@ export default function Search() {
);
const [sortBy, setSortBy] = useState(Sort.DateNewestFirst);
- useLinks({
+ const { isLoading } = useLinks({
sort: sortBy,
searchQueryString: decodeURIComponent(router.query.q as string),
searchByName: searchFilter.name,
@@ -40,6 +41,10 @@ export default function Search() {
searchByTags: searchFilter.tags,
});
+ useEffect(() => {
+ console.log("isLoading", isLoading);
+ }, [isLoading]);
+
const linkView = {
[ViewMode.Card]: CardView,
// [ViewMode.Grid]: GridView,
@@ -51,7 +56,7 @@ export default function Search() {
return (
-
+
@@ -67,15 +72,24 @@ export default function Search() {
- {links[0] ? (
-
- ) : (
+ {!isLoading && !links[0] ? (
Nothing found.{" "}
¯\_(ツ)_/¯
+ ) : links[0] ? (
+
+ ) : (
+ isLoading && (
+
+ )
)}
diff --git a/prisma/migrations/20240310062152_added_indexes/migration.sql b/prisma/migrations/20240310062152_added_indexes/migration.sql
new file mode 100644
index 0000000..b152c15
--- /dev/null
+++ b/prisma/migrations/20240310062152_added_indexes/migration.sql
@@ -0,0 +1,5 @@
+-- CreateIndex
+CREATE INDEX "Collection_ownerId_idx" ON "Collection"("ownerId");
+
+-- CreateIndex
+CREATE INDEX "UsersAndCollections_userId_idx" ON "UsersAndCollections"("userId");
diff --git a/prisma/migrations/20240310062318_added_index_to_ownerid_on_tag_model/migration.sql b/prisma/migrations/20240310062318_added_index_to_ownerid_on_tag_model/migration.sql
new file mode 100644
index 0000000..92fc3d0
--- /dev/null
+++ b/prisma/migrations/20240310062318_added_index_to_ownerid_on_tag_model/migration.sql
@@ -0,0 +1,2 @@
+-- CreateIndex
+CREATE INDEX "Tag_ownerId_idx" ON "Tag"("ownerId");
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 64c7b86..da73115 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -93,6 +93,8 @@ model Collection {
links Link[]
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
+
+ @@index([ownerId])
}
model UsersAndCollections {
@@ -107,6 +109,7 @@ model UsersAndCollections {
updatedAt DateTime @default(now()) @updatedAt
@@id([userId, collectionId])
+ @@index([userId])
}
model Link {
@@ -139,6 +142,7 @@ model Tag {
updatedAt DateTime @default(now()) @updatedAt
@@unique([name, ownerId])
+ @@index([ownerId])
}
model Subscription {
diff --git a/yarn.lock b/yarn.lock
index 98b7692..37c6839 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5211,6 +5211,11 @@ react-select@^5.7.4:
react-transition-group "^4.3.0"
use-isomorphic-layout-effect "^1.1.2"
+react-spinners@^0.13.8:
+ version "0.13.8"
+ resolved "https://registry.yarnpkg.com/react-spinners/-/react-spinners-0.13.8.tgz#5262571be0f745d86bbd49a1e6b49f9f9cb19acc"
+ integrity sha512-3e+k56lUkPj0vb5NDXPVFAOkPC//XyhKPJjvcGjyMNPWsBKpplfeyialP74G7H7+It7KzhtET+MvGqbKgAqpZA==
+
react-style-singleton@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4"