From 8f00885d7066cb8eae2caee49b32face16218ccc Mon Sep 17 00:00:00 2001 From: Aamir Azad Date: Tue, 18 Jun 2024 18:02:28 +0530 Subject: [PATCH 1/4] feat: fill in current preferences to the settings form --- src/app/actions.ts | 10 ++++++++++ src/app/settings/page.tsx | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/src/app/actions.ts b/src/app/actions.ts index 6a31c59..e8073c2 100644 --- a/src/app/actions.ts +++ b/src/app/actions.ts @@ -39,3 +39,13 @@ export async function setPaperlessToken(token: string, userId: string) { throw new Error("Database error"); } } + +export async function getUserPreferences(userId: string) { + try { + await db.query.users.findFirst({ + where: (model, { eq }) => eq(model.userId, userId), + }); + } catch { + throw new Error("Database error"); + } +} diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx index c8c7f17..4395c7d 100644 --- a/src/app/settings/page.tsx +++ b/src/app/settings/page.tsx @@ -22,6 +22,7 @@ import { setFullUserName, setPaperlessToken, setPaperlessURL, + getUserPreferences, } from "../actions"; import { Toaster } from "@/components/ui/sonner"; import { toast } from "sonner"; @@ -33,6 +34,7 @@ function FullName({ }) { const { user, isLoaded } = useUser(); const pathname = usePathname(); + const formSchema = z.object({ FullName: z.string().min(1, { message: "Required.", @@ -53,6 +55,10 @@ function FullName({ return redirect("/sign-in?redirect=" + pathname); } + const preferences = async () => { + return await getUserPreferences(user?.id); + }; + async function onSubmit(values: z.infer) { setActiveTab((prevTab) => prevTab + 1); // Increment activeTab try { From e69025c6b9bac1bb94d31dfceb7ae5397dd5a714 Mon Sep 17 00:00:00 2001 From: Aamir Azad Date: Wed, 19 Jun 2024 10:57:11 +0530 Subject: [PATCH 2/4] 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 2a08fbb2185c9d964fa3e1f13ea019234807414c Mon Sep 17 00:00:00 2001 From: Aamir Azad Date: Wed, 19 Jun 2024 12:01:39 +0530 Subject: [PATCH 3/4] 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 7c82f34abbcbd59dee2e4949d051ad774eb1824d Mon Sep 17 00:00:00 2001 From: Aamir Azad Date: Tue, 18 Jun 2024 18:02:28 +0530 Subject: [PATCH 4/4] feat: fill in current preferences to the settings form --- src/app/actions.ts | 10 ++++++++++ src/app/settings/page.tsx | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/src/app/actions.ts b/src/app/actions.ts index a7381e3..1a256af 100644 --- a/src/app/actions.ts +++ b/src/app/actions.ts @@ -58,6 +58,16 @@ export async function setPaperlessToken(token: string) { } } +export async function getUserPreferences(userId: string) { + try { + await db.query.users.findFirst({ + where: (model, { eq }) => eq(model.userId, userId), + }); + } catch { + throw new Error("Database error"); + } +} + export async function getPaperlessDocuments(query: string) { const user = auth(); diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx index 44b2893..b8a698c 100644 --- a/src/app/settings/page.tsx +++ b/src/app/settings/page.tsx @@ -23,6 +23,7 @@ import { setFullUserName, setPaperlessToken, setPaperlessURL, + getUserPreferences, } from "../actions"; import { Toaster } from "@/components/ui/sonner"; import { toast } from "sonner"; @@ -34,6 +35,7 @@ function FullName({ }) { const { user, isLoaded } = useUser(); const pathname = usePathname(); + const formSchema = z.object({ FullName: z.string().min(1, { message: "Required.", @@ -54,6 +56,10 @@ function FullName({ return redirect("/sign-in?redirect=" + pathname); } + const preferences = async () => { + return await getUserPreferences(user?.id); + }; + async function onSubmit(values: z.infer) { setActiveTab((prevTab) => prevTab + 1); // Increment activeTab try {