From cce4d8c796dbb231093ee6d4361e8a4f6afcbf6c Mon Sep 17 00:00:00 2001 From: Aamir Azad Date: Wed, 19 Jun 2024 09:45:47 +0530 Subject: [PATCH 1/6] perf: set avatar image priority --- src/components/topnav.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/topnav.tsx b/src/components/topnav.tsx index 6fb514e..29c4897 100644 --- a/src/components/topnav.tsx +++ b/src/components/topnav.tsx @@ -43,6 +43,7 @@ function UserSettings() { src={user.imageUrl} width={32} height={32} + priority={true} alt="Avatar" className="mt-1 overflow-hidden rounded-full" /> @@ -73,8 +74,8 @@ function UserSettings() { Cancel { - signOut(); + onClick={async () => { + await signOut(); }} > Continue From b33c5e40230dd8dc44e2376ded3bc23a84880465 Mon Sep 17 00:00:00 2001 From: Aamir Azad Date: Wed, 19 Jun 2024 10:57:11 +0530 Subject: [PATCH 2/6] feat: seperate user config --- src/app/actions.ts | 56 +++++++++++++++++++++++++++++++++++--- src/app/paperless/page.tsx | 48 ++++++-------------------------- src/types/index.ts | 37 +++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 44 deletions(-) create mode 100644 src/types/index.ts diff --git a/src/app/actions.ts b/src/app/actions.ts index 6a31c59..a7381e3 100644 --- a/src/app/actions.ts +++ b/src/app/actions.ts @@ -2,9 +2,15 @@ import { db } from "@/server/db"; import { users } from "@/server/db/schema"; -import { currentUser } from "@clerk/nextjs/server"; +import { auth } from "@clerk/nextjs/server"; + +export async function setFullUserName(name: string) { + const { userId } = auth(); + + if (!userId) { + throw new Error("Not authenticated"); + } -export async function setFullUserName(name: string, userId: string) { try { await db .insert(users) @@ -15,7 +21,13 @@ export async function setFullUserName(name: string, userId: string) { } } -export async function setPaperlessURL(url: string, userId: string) { +export async function setPaperlessURL(url: string) { + const { userId } = auth(); + + if (!userId) { + throw new Error("Not authenticated"); + } + try { await db .insert(users) @@ -26,7 +38,13 @@ export async function setPaperlessURL(url: string, userId: string) { } } -export async function setPaperlessToken(token: string, userId: string) { +export async function setPaperlessToken(token: string) { + const { userId } = auth(); + + if (!userId) { + throw new Error("Not authenticated"); + } + try { await db .insert(users) @@ -39,3 +57,33 @@ export async function setPaperlessToken(token: string, userId: string) { throw new Error("Database error"); } } + +export async function getPaperlessDocuments(query: string) { + const user = auth(); + + if (!user.userId) + return Response.json({ error: "Unauthorized" }, { status: 401 }); + + const userData = await db.query.users.findFirst({ + where: (model, { eq }) => eq(model.userId, user.userId), + }); + + if (!query || query == "null" || query.length < 3 || !userData) + return Response.json({ error: "Bad Request" }, { status: 400 }); + + + const response = await fetch( + `${userData.paperlessURL}/api/search/?query=${query}` + query, + { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Token ${userData.paperlessToken}`, + }, + }, + ); + + const data = await response.json(); + + return Response.json({ data }); +} diff --git a/src/app/paperless/page.tsx b/src/app/paperless/page.tsx index 0f77e2f..2bb6118 100644 --- a/src/app/paperless/page.tsx +++ b/src/app/paperless/page.tsx @@ -23,6 +23,7 @@ import { QueryClient, } from "@tanstack/react-query"; import LoadingSpinner from "@/components/loading-spinner"; +import { PaperlessDocumentsType } from "@/types"; const queryClient = new QueryClient(); @@ -83,63 +84,30 @@ function DocumentsSearch() { } function DocumentsPage() { - type DataType = { - data: { - total: number; - documents: { - added: string; - archive_serial_number: string; - archived_file_name: string; - content: string; - correspondent: string; - created: string; - created_date: string; - custom_fields: []; - document_type: number; - id: number; - is_shared_by_requester: boolean; - modified: string; - notes: []; - original_file_name: string; - owner: number; - storage_path: number; - tags: []; - title: string; - user_can_change: boolean; - }[]; - saved_views: []; - correspondents: []; - document_types: []; - storage_paths: []; - tags: []; - users: []; - groups: []; - mail_accounts: []; - mail_rules: []; - custom_fields: []; - workflows: []; - }; - }; const searchParams = useSearchParams(); const query = searchParams.get("query"); const QueryResult = useQuery({ - queryKey: ["key"], + queryKey: ["key", query], queryFn: async () => { const response = await fetch("/api/paperless?query=" + query); - const data = (await response.json()) as DataType; + const data = (await response.json()) as PaperlessDocumentsType; return data; }, }); useEffect(() => { - queryClient.refetchQueries(); + void queryClient.refetchQueries(); }, [query]); + console.log(QueryResult.isLoading); + return (
{QueryResult.isLoading ? ( Loading... + ) : QueryResult.data === null ? ( // Check if QueryResult.data is null +

Connection failed!

) : QueryResult.data?.data ? (

Search Results

diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..c1657d9 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,37 @@ +export type PaperlessDocumentsType = { + data: { + total: number; + documents: { + added: string; + archive_serial_number: string; + archived_file_name: string; + content: string; + correspondent: string; + created: string; + created_date: string; + custom_fields: []; + document_type: number; + id: number; + is_shared_by_requester: boolean; + modified: string; + notes: []; + original_file_name: string; + owner: number; + storage_path: number; + tags: []; + title: string; + user_can_change: boolean; + }[]; + saved_views: []; + correspondents: []; + document_types: []; + storage_paths: []; + tags: []; + users: []; + groups: []; + mail_accounts: []; + mail_rules: []; + custom_fields: []; + workflows: []; + }; + }; \ No newline at end of file From 3bfda85545fe578a44cb77f12df18d7b3a6d08fb Mon Sep 17 00:00:00 2001 From: Aamir Azad Date: Wed, 19 Jun 2024 12:01:39 +0530 Subject: [PATCH 3/6] refactor: fix eslint issues --- src/app/paperless/page.tsx | 10 +++++----- src/app/settings/page.tsx | 25 +++++++++++++------------ 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/app/paperless/page.tsx b/src/app/paperless/page.tsx index 2bb6118..adcd8ae 100644 --- a/src/app/paperless/page.tsx +++ b/src/app/paperless/page.tsx @@ -23,7 +23,7 @@ import { QueryClient, } from "@tanstack/react-query"; import LoadingSpinner from "@/components/loading-spinner"; -import { PaperlessDocumentsType } from "@/types"; +import type { PaperlessDocumentsType } from "@/types"; const queryClient = new QueryClient(); @@ -34,7 +34,7 @@ function DocumentsSearch() { const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); - const givenQuery = searchParams.get("query") || ""; + const givenQuery = searchParams.get("query") ?? ""; // 1. Define your form. const form = useForm>({ resolver: zodResolver(formSchema), @@ -54,9 +54,9 @@ function DocumentsSearch() { ); function onSubmit(values: z.infer) { - if (values["query"]) + if (values.query) router.replace( - pathname + "?" + createQueryString("query", values["query"]), + pathname + "?" + createQueryString("query", values.query), ); } @@ -91,7 +91,7 @@ function DocumentsPage() { queryKey: ["key", query], queryFn: async () => { const response = await fetch("/api/paperless?query=" + query); - const data = (await response.json()) as PaperlessDocumentsType; + const data = await response.json() as PaperlessDocumentsType; return data; }, }); diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx index c8c7f17..44b2893 100644 --- a/src/app/settings/page.tsx +++ b/src/app/settings/page.tsx @@ -14,7 +14,8 @@ import { Input } from "@/components/ui/input"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { useForm } from "react-hook-form"; -import { Dispatch, SetStateAction, useState } from "react"; +import type { Dispatch, SetStateAction } from "react"; +import { useState } from "react"; import { useUser } from "@clerk/nextjs"; import { redirect, usePathname } from "next/navigation"; import LoadingSpinner from "@/components/loading-spinner"; @@ -56,7 +57,7 @@ function FullName({ async function onSubmit(values: z.infer) { setActiveTab((prevTab) => prevTab + 1); // Increment activeTab try { - await setFullUserName(values["FullName"], user!.id); + await setFullUserName(values.FullName); // Operation succeeded, show success toast toast("Your name preferences was saved"); // Optionally, move to a new tab or take another action to indicate success @@ -120,13 +121,13 @@ function PaperlessURL({ } async function onSubmit(values: z.infer) { - if (values["URL"] == "") { + if (values.URL == "") { setActiveTab((prevTab) => prevTab + 2); // Skip api key form } else { setActiveTab((prevTab) => prevTab + 1); // Increment activeTab } try { - await setPaperlessURL(values["URL"], user!.id); + await setPaperlessURL(values.URL); // Operation succeeded, show success toast toast("Your paperless URL preferences was saved"); // Optionally, move to a new tab or take another action to indicate success @@ -193,7 +194,7 @@ function PaperlessToken({ setActiveTab((prevTab) => prevTab + 1); // Increment activeTab try { - await setPaperlessToken(values["token"], user!.id); + await setPaperlessToken(values.token); // Operation succeeded, show success toast toast("Your paperless token preferences was saved"); } catch { @@ -221,9 +222,9 @@ function PaperlessToken({ - You can create (or re-create) an API token by opening the "My - Profile" link in the user dropdown found in the web UI and - clicking the circular arrow button. + You can create (or re-create) an API token by opening the + "My Profile" link in the user dropdown found in the + web UI and clicking the circular arrow button. )} @@ -271,10 +272,10 @@ export default function SettingsPage() { const [activeTab, setActiveTab] = useState(0); const formElements = [ - , - , - , - , + , + , + , + , ]; return ( <> From 5b6e49c0c9462da34be9eb2cd8f9c1d5841fc0c6 Mon Sep 17 00:00:00 2001 From: Aamir Azad Date: Wed, 19 Jun 2024 10:57:11 +0530 Subject: [PATCH 4/6] feat: seperate user config --- src/app/actions.ts | 56 +++++++++++++++++++++++++++++++++++--- src/app/paperless/page.tsx | 48 ++++++-------------------------- src/types/index.ts | 37 +++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 44 deletions(-) create mode 100644 src/types/index.ts diff --git a/src/app/actions.ts b/src/app/actions.ts index 6a31c59..a7381e3 100644 --- a/src/app/actions.ts +++ b/src/app/actions.ts @@ -2,9 +2,15 @@ import { db } from "@/server/db"; import { users } from "@/server/db/schema"; -import { currentUser } from "@clerk/nextjs/server"; +import { auth } from "@clerk/nextjs/server"; + +export async function setFullUserName(name: string) { + const { userId } = auth(); + + if (!userId) { + throw new Error("Not authenticated"); + } -export async function setFullUserName(name: string, userId: string) { try { await db .insert(users) @@ -15,7 +21,13 @@ export async function setFullUserName(name: string, userId: string) { } } -export async function setPaperlessURL(url: string, userId: string) { +export async function setPaperlessURL(url: string) { + const { userId } = auth(); + + if (!userId) { + throw new Error("Not authenticated"); + } + try { await db .insert(users) @@ -26,7 +38,13 @@ export async function setPaperlessURL(url: string, userId: string) { } } -export async function setPaperlessToken(token: string, userId: string) { +export async function setPaperlessToken(token: string) { + const { userId } = auth(); + + if (!userId) { + throw new Error("Not authenticated"); + } + try { await db .insert(users) @@ -39,3 +57,33 @@ export async function setPaperlessToken(token: string, userId: string) { throw new Error("Database error"); } } + +export async function getPaperlessDocuments(query: string) { + const user = auth(); + + if (!user.userId) + return Response.json({ error: "Unauthorized" }, { status: 401 }); + + const userData = await db.query.users.findFirst({ + where: (model, { eq }) => eq(model.userId, user.userId), + }); + + if (!query || query == "null" || query.length < 3 || !userData) + return Response.json({ error: "Bad Request" }, { status: 400 }); + + + const response = await fetch( + `${userData.paperlessURL}/api/search/?query=${query}` + query, + { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Token ${userData.paperlessToken}`, + }, + }, + ); + + const data = await response.json(); + + return Response.json({ data }); +} diff --git a/src/app/paperless/page.tsx b/src/app/paperless/page.tsx index 0f77e2f..2bb6118 100644 --- a/src/app/paperless/page.tsx +++ b/src/app/paperless/page.tsx @@ -23,6 +23,7 @@ import { QueryClient, } from "@tanstack/react-query"; import LoadingSpinner from "@/components/loading-spinner"; +import { PaperlessDocumentsType } from "@/types"; const queryClient = new QueryClient(); @@ -83,63 +84,30 @@ function DocumentsSearch() { } function DocumentsPage() { - type DataType = { - data: { - total: number; - documents: { - added: string; - archive_serial_number: string; - archived_file_name: string; - content: string; - correspondent: string; - created: string; - created_date: string; - custom_fields: []; - document_type: number; - id: number; - is_shared_by_requester: boolean; - modified: string; - notes: []; - original_file_name: string; - owner: number; - storage_path: number; - tags: []; - title: string; - user_can_change: boolean; - }[]; - saved_views: []; - correspondents: []; - document_types: []; - storage_paths: []; - tags: []; - users: []; - groups: []; - mail_accounts: []; - mail_rules: []; - custom_fields: []; - workflows: []; - }; - }; const searchParams = useSearchParams(); const query = searchParams.get("query"); const QueryResult = useQuery({ - queryKey: ["key"], + queryKey: ["key", query], queryFn: async () => { const response = await fetch("/api/paperless?query=" + query); - const data = (await response.json()) as DataType; + const data = (await response.json()) as PaperlessDocumentsType; return data; }, }); useEffect(() => { - queryClient.refetchQueries(); + void queryClient.refetchQueries(); }, [query]); + console.log(QueryResult.isLoading); + return (
{QueryResult.isLoading ? ( Loading... + ) : QueryResult.data === null ? ( // Check if QueryResult.data is null +

Connection failed!

) : QueryResult.data?.data ? (

Search Results

diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..c1657d9 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,37 @@ +export type PaperlessDocumentsType = { + data: { + total: number; + documents: { + added: string; + archive_serial_number: string; + archived_file_name: string; + content: string; + correspondent: string; + created: string; + created_date: string; + custom_fields: []; + document_type: number; + id: number; + is_shared_by_requester: boolean; + modified: string; + notes: []; + original_file_name: string; + owner: number; + storage_path: number; + tags: []; + title: string; + user_can_change: boolean; + }[]; + saved_views: []; + correspondents: []; + document_types: []; + storage_paths: []; + tags: []; + users: []; + groups: []; + mail_accounts: []; + mail_rules: []; + custom_fields: []; + workflows: []; + }; + }; \ No newline at end of file From 6d447da55d71cc828f31a6aa454763bfeb6f3cb3 Mon Sep 17 00:00:00 2001 From: Aamir Azad Date: Sat, 22 Jun 2024 10:23:43 +0530 Subject: [PATCH 5/6] It finally works --- src/app/actions.ts | 16 ++++----- src/app/paperless/page.tsx | 18 ++++------ src/types/index.ts | 70 ++++++++++++++++++-------------------- 3 files changed, 49 insertions(+), 55 deletions(-) diff --git a/src/app/actions.ts b/src/app/actions.ts index 4453230..6559d12 100644 --- a/src/app/actions.ts +++ b/src/app/actions.ts @@ -1,7 +1,8 @@ "use server"; import { db } from "@/server/db"; -import { UsersTableType, users } from "@/server/db/schema"; +import type { UsersTableType } from "@/server/db/schema"; +import { users } from "@/server/db/schema"; import type { PaperlessDocumentsType } from "@/types"; import { auth } from "@clerk/nextjs/server"; interface User { @@ -18,7 +19,7 @@ export async function setUserProperty( const { userId } = auth(); if (!userId) { - throw new Error("Not authenticated"); + return null; } try { @@ -30,7 +31,7 @@ export async function setUserProperty( set: { [propertyName]: value }, }); } catch { - throw new Error("Database error"); + return null; } } @@ -38,7 +39,7 @@ export async function getUserData() { const { userId } = auth(); if (!userId) { - throw new Error("Not authenticated"); + return null; } const userData = await db.query.users.findFirst({ @@ -51,12 +52,11 @@ export async function getUserData() { export async function getPaperlessDocuments(query: string) { const { userId } = auth(); - if (!userId) return Response.json({ error: "Unauthorized" }, { status: 401 }); + if (!userId) return null; const userData = await getUserData(); - if (!query || query == "null" || query.length < 3 || !userData) - return Response.json({ error: "Bad Request" }, { status: 400 }); + if (!query || query == "null" || query.length < 3 || !userData) return null; const response = await fetch( `${userData.paperlessURL}/api/search/?query=${query}`, @@ -71,5 +71,5 @@ export async function getPaperlessDocuments(query: string) { const data = (await response.json()) as PaperlessDocumentsType; - return Response.json({ data }); + return data; } diff --git a/src/app/paperless/page.tsx b/src/app/paperless/page.tsx index 1b635d5..8a5b36a 100644 --- a/src/app/paperless/page.tsx +++ b/src/app/paperless/page.tsx @@ -1,11 +1,7 @@ "use client"; import { SignedIn, SignedOut } from "@clerk/nextjs"; -import { - usePathname, - useRouter, - useSearchParams, -} from "next/navigation"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { Button } from "@/components/ui/button"; @@ -26,7 +22,6 @@ import { QueryClient, } from "@tanstack/react-query"; import LoadingSpinner from "@/components/loading-spinner"; -import type { PaperlessDocumentsType } from "@/types"; import { getPaperlessDocuments, getUserData } from "../actions"; import Link from "next/link"; @@ -97,8 +92,7 @@ function DocumentsPage() { return Promise.resolve(null); } const response = await getPaperlessDocuments(query); - const data = (await response.json()) as PaperlessDocumentsType; - return data; + return response; }, // This ensures the query does not run if there's no query string enabled: !!query, @@ -126,16 +120,18 @@ function DocumentsPage() { ); } else if (!PaperlessDocuments.data || PaperlessDocuments.error) { + console.log(PaperlessDocuments.data); return (

- Connection failed! Check that the paperless url is set correctly in{" "} - settings + Connection failed! Check that the paperless url/token is set correctly + in settings

); } const paperlessURL = userData.data?.paperlessURL; - const paperlessDocumentMap = PaperlessDocuments.data.data.documents; + + const paperlessDocumentMap = PaperlessDocuments.data.documents; return (
diff --git a/src/types/index.ts b/src/types/index.ts index c1657d9..6ea11af 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,37 +1,35 @@ export type PaperlessDocumentsType = { - data: { - total: number; - documents: { - added: string; - archive_serial_number: string; - archived_file_name: string; - content: string; - correspondent: string; - created: string; - created_date: string; - custom_fields: []; - document_type: number; - id: number; - is_shared_by_requester: boolean; - modified: string; - notes: []; - original_file_name: string; - owner: number; - storage_path: number; - tags: []; - title: string; - user_can_change: boolean; - }[]; - saved_views: []; - correspondents: []; - document_types: []; - storage_paths: []; - tags: []; - users: []; - groups: []; - mail_accounts: []; - mail_rules: []; - custom_fields: []; - workflows: []; - }; - }; \ No newline at end of file + total: number; + documents: { + added: string; + archive_serial_number: string; + archived_file_name: string; + content: string; + correspondent: string; + created: string; + created_date: string; + custom_fields: []; + document_type: number; + id: number; + is_shared_by_requester: boolean; + modified: string; + notes: []; + original_file_name: string; + owner: number; + storage_path: number; + tags: []; + title: string; + user_can_change: boolean; + }[]; + saved_views: []; + correspondents: []; + document_types: []; + storage_paths: []; + tags: []; + users: []; + groups: []; + mail_accounts: []; + mail_rules: []; + custom_fields: []; + workflows: []; +}; From e2ba94252e0c8967bf19cef078d83c57687b58f4 Mon Sep 17 00:00:00 2001 From: Aamir Azad Date: Wed, 19 Jun 2024 12:01:39 +0530 Subject: [PATCH 6/6] refactor: fix eslint issues --- src/app/paperless/page.tsx | 4 +++- src/app/settings/page.tsx | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/app/paperless/page.tsx b/src/app/paperless/page.tsx index 8a5b36a..4223dbe 100644 --- a/src/app/paperless/page.tsx +++ b/src/app/paperless/page.tsx @@ -54,7 +54,9 @@ function DocumentsSearch() { function onSubmit(values: z.infer) { if (values.query) - router.replace(pathname + "?" + createQueryString("query", values.query)); + router.replace( + pathname + "?" + createQueryString("query", values.query), + ); } return ( diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx index 324e55d..8d5e002 100644 --- a/src/app/settings/page.tsx +++ b/src/app/settings/page.tsx @@ -268,9 +268,9 @@ export default function SettingsPage() { const [activeTab, setActiveTab] = useState(0); const formElements = [ - , - , - , + , + , + , , ]; return (