From 04572a8e5081b1e4871e273cde9dbaaa44c52fe0 Mon Sep 17 00:00:00 2001 From: MohamedBassem Date: Wed, 13 Mar 2024 21:43:44 +0000 Subject: structure: Create apps dir and copy tooling dir from t3-turbo repo --- packages/web/app/api/auth/[...nextauth]/route.tsx | 3 - packages/web/app/api/trpc/[trpc]/route.ts | 36 ---- packages/web/app/dashboard/admin/page.tsx | 203 --------------------- packages/web/app/dashboard/archive/page.tsx | 9 - packages/web/app/dashboard/bookmarks/layout.tsx | 23 --- packages/web/app/dashboard/bookmarks/loading.tsx | 11 -- packages/web/app/dashboard/bookmarks/page.tsx | 5 - packages/web/app/dashboard/error.tsx | 9 - packages/web/app/dashboard/favourites/page.tsx | 14 -- packages/web/app/dashboard/layout.tsx | 24 --- packages/web/app/dashboard/lists/[listId]/page.tsx | 44 ----- packages/web/app/dashboard/lists/page.tsx | 14 -- packages/web/app/dashboard/not-found.tsx | 7 - .../app/dashboard/preview/[bookmarkId]/page.tsx | 14 -- packages/web/app/dashboard/search/page.tsx | 41 ----- packages/web/app/dashboard/settings/page.tsx | 9 - packages/web/app/dashboard/tags/[tagName]/page.tsx | 55 ------ packages/web/app/dashboard/tags/page.tsx | 56 ------ packages/web/app/favicon.ico | Bin 15406 -> 0 bytes packages/web/app/globals.css | 76 -------- packages/web/app/layout.tsx | 51 ------ packages/web/app/page.tsx | 12 -- packages/web/app/signin/page.tsx | 25 --- 23 files changed, 741 deletions(-) delete mode 100644 packages/web/app/api/auth/[...nextauth]/route.tsx delete mode 100644 packages/web/app/api/trpc/[trpc]/route.ts delete mode 100644 packages/web/app/dashboard/admin/page.tsx delete mode 100644 packages/web/app/dashboard/archive/page.tsx delete mode 100644 packages/web/app/dashboard/bookmarks/layout.tsx delete mode 100644 packages/web/app/dashboard/bookmarks/loading.tsx delete mode 100644 packages/web/app/dashboard/bookmarks/page.tsx delete mode 100644 packages/web/app/dashboard/error.tsx delete mode 100644 packages/web/app/dashboard/favourites/page.tsx delete mode 100644 packages/web/app/dashboard/layout.tsx delete mode 100644 packages/web/app/dashboard/lists/[listId]/page.tsx delete mode 100644 packages/web/app/dashboard/lists/page.tsx delete mode 100644 packages/web/app/dashboard/not-found.tsx delete mode 100644 packages/web/app/dashboard/preview/[bookmarkId]/page.tsx delete mode 100644 packages/web/app/dashboard/search/page.tsx delete mode 100644 packages/web/app/dashboard/settings/page.tsx delete mode 100644 packages/web/app/dashboard/tags/[tagName]/page.tsx delete mode 100644 packages/web/app/dashboard/tags/page.tsx delete mode 100644 packages/web/app/favicon.ico delete mode 100644 packages/web/app/globals.css delete mode 100644 packages/web/app/layout.tsx delete mode 100644 packages/web/app/page.tsx delete mode 100644 packages/web/app/signin/page.tsx (limited to 'packages/web/app') diff --git a/packages/web/app/api/auth/[...nextauth]/route.tsx b/packages/web/app/api/auth/[...nextauth]/route.tsx deleted file mode 100644 index 2f7f1cb0..00000000 --- a/packages/web/app/api/auth/[...nextauth]/route.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { authHandler } from "@/server/auth"; - -export { authHandler as GET, authHandler as POST }; diff --git a/packages/web/app/api/trpc/[trpc]/route.ts b/packages/web/app/api/trpc/[trpc]/route.ts deleted file mode 100644 index b6753101..00000000 --- a/packages/web/app/api/trpc/[trpc]/route.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { fetchRequestHandler } from "@trpc/server/adapters/fetch"; -import { appRouter } from "@hoarder/trpc/routers/_app"; -import { createContext } from "@/server/api/client"; -import { authenticateApiKey } from "@hoarder/trpc/auth"; -import { db } from "@hoarder/db"; - -const handler = (req: Request) => - fetchRequestHandler({ - endpoint: "/api/trpc", - req, - router: appRouter, - onError: ({ path, error }) => { - if (process.env.NODE_ENV === "development") { - console.error(`❌ tRPC failed on ${path}`); - } - console.error(error); - }, - - createContext: async (opts) => { - // TODO: This is a hack until we offer a proper REST API instead of the trpc based one. - // Check if the request has an Authorization token, if it does, assume that API key authentication is requested. - const authorizationHeader = opts.req.headers.get("Authorization"); - if (authorizationHeader && authorizationHeader.startsWith("Bearer ")) { - const token = authorizationHeader.split(" ")[1]; - try { - const user = await authenticateApiKey(token); - return { user, db }; - } catch (e) { - // Fallthrough to cookie-based auth - } - } - - return createContext(); - }, - }); -export { handler as GET, handler as POST }; diff --git a/packages/web/app/dashboard/admin/page.tsx b/packages/web/app/dashboard/admin/page.tsx deleted file mode 100644 index 6babdd79..00000000 --- a/packages/web/app/dashboard/admin/page.tsx +++ /dev/null @@ -1,203 +0,0 @@ -"use client"; - -import { ActionButton } from "@/components/ui/action-button"; -import LoadingSpinner from "@/components/ui/spinner"; -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@/components/ui/table"; -import { toast } from "@/components/ui/use-toast"; -import { api } from "@/lib/trpc"; -import { keepPreviousData } from "@tanstack/react-query"; -import { Trash } from "lucide-react"; -import { useSession } from "next-auth/react"; -import { useRouter } from "next/navigation"; - -function ActionsSection() { - const { mutate: recrawlLinks, isPending: isRecrawlPending } = - api.admin.recrawlAllLinks.useMutation({ - onSuccess: () => { - toast({ - description: "Recrawl enqueued", - }); - }, - onError: (e) => { - toast({ - variant: "destructive", - description: e.message, - }); - }, - }); - - const { mutate: reindexBookmarks, isPending: isReindexPending } = - api.admin.reindexAllBookmarks.useMutation({ - onSuccess: () => { - toast({ - description: "Reindex enqueued", - }); - }, - onError: (e) => { - toast({ - variant: "destructive", - description: e.message, - }); - }, - }); - - return ( - <> -

Actions

- recrawlLinks()} - > - Recrawl All Links - - reindexBookmarks()} - > - Reindex All Bookmarks - - - ); -} - -function ServerStatsSection() { - const { data: serverStats } = api.admin.stats.useQuery(undefined, { - refetchInterval: 1000, - placeholderData: keepPreviousData, - }); - - if (!serverStats) { - return ; - } - - return ( - <> -

Server Stats

- - - - Num Users - {serverStats.numUsers} - - - Num Bookmarks - {serverStats.numBookmarks} - - -
-
-

Background Jobs

- - - - Pending Crawling Jobs - {serverStats.pendingCrawls} - - - Pending Indexing Jobs - {serverStats.pendingIndexing} - - - Pending OpenAI Jobs - {serverStats.pendingOpenai} - - -
- - ); -} - -function UsersSection() { - const { data: session } = useSession(); - const invalidateUserList = api.useUtils().users.list.invalidate; - const { data: users } = api.users.list.useQuery(); - const { mutate: deleteUser, isPending: isDeletionPending } = - api.users.delete.useMutation({ - onSuccess: () => { - toast({ - description: "User deleted", - }); - invalidateUserList(); - }, - onError: (e) => { - toast({ - variant: "destructive", - description: `Something went wrong: ${e.message}`, - }); - }, - }); - - if (!users) { - return ; - } - - return ( - <> -

Users

- - - Name - Email - Role - Action - - - {users.users.map((u) => ( - - {u.name} - {u.email} - {u.role} - - deleteUser({ userId: u.id })} - loading={isDeletionPending} - disabled={session!.user.id == u.id} - > - - - - - ))} - -
- - ); -} - -export default function AdminPage() { - const router = useRouter(); - const { data: session, status } = useSession(); - - if (status == "loading") { - return ; - } - - if (!session || session.user.role != "admin") { - router.push("/"); - return; - } - - return ( -
-

Admin

-
- -
- -
- -
- ); -} diff --git a/packages/web/app/dashboard/archive/page.tsx b/packages/web/app/dashboard/archive/page.tsx deleted file mode 100644 index 69559185..00000000 --- a/packages/web/app/dashboard/archive/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import Bookmarks from "@/components/dashboard/bookmarks/Bookmarks"; - -export default async function ArchivedBookmarkPage() { - return ( -
- -
- ); -} diff --git a/packages/web/app/dashboard/bookmarks/layout.tsx b/packages/web/app/dashboard/bookmarks/layout.tsx deleted file mode 100644 index 71ee143b..00000000 --- a/packages/web/app/dashboard/bookmarks/layout.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; -import TopNav from "@/components/dashboard/bookmarks/TopNav"; -import type { Metadata } from "next"; - -export const metadata: Metadata = { - title: "Hoarder - Bookmarks", -}; - -export default function BookmarksLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - return ( -
-
- -
-
-
{children}
-
- ); -} diff --git a/packages/web/app/dashboard/bookmarks/loading.tsx b/packages/web/app/dashboard/bookmarks/loading.tsx deleted file mode 100644 index 4e56c3c4..00000000 --- a/packages/web/app/dashboard/bookmarks/loading.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import Spinner from "@/components/ui/spinner"; - -export default function Loading() { - return ( -
-
- -
-
- ); -} diff --git a/packages/web/app/dashboard/bookmarks/page.tsx b/packages/web/app/dashboard/bookmarks/page.tsx deleted file mode 100644 index c9391d85..00000000 --- a/packages/web/app/dashboard/bookmarks/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import Bookmarks from "@/components/dashboard/bookmarks/Bookmarks"; - -export default async function BookmarksPage() { - return ; -} diff --git a/packages/web/app/dashboard/error.tsx b/packages/web/app/dashboard/error.tsx deleted file mode 100644 index 556e59a3..00000000 --- a/packages/web/app/dashboard/error.tsx +++ /dev/null @@ -1,9 +0,0 @@ -"use client"; - -export default function Error() { - return ( -
-
Something went wrong
-
- ); -} diff --git a/packages/web/app/dashboard/favourites/page.tsx b/packages/web/app/dashboard/favourites/page.tsx deleted file mode 100644 index de17461d..00000000 --- a/packages/web/app/dashboard/favourites/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import Bookmarks from "@/components/dashboard/bookmarks/Bookmarks"; - -export default async function FavouritesBookmarkPage() { - return ( -
- -
- ); -} diff --git a/packages/web/app/dashboard/layout.tsx b/packages/web/app/dashboard/layout.tsx deleted file mode 100644 index 31d592fb..00000000 --- a/packages/web/app/dashboard/layout.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { Separator } from "@/components/ui/separator"; -import MobileSidebar from "@/components/dashboard/sidebar/ModileSidebar"; -import Sidebar from "@/components/dashboard/sidebar/Sidebar"; - -export default async function Dashboard({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - return ( -
-
- -
-
-
- - -
- {children} -
-
- ); -} diff --git a/packages/web/app/dashboard/lists/[listId]/page.tsx b/packages/web/app/dashboard/lists/[listId]/page.tsx deleted file mode 100644 index 006fd3ad..00000000 --- a/packages/web/app/dashboard/lists/[listId]/page.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { api } from "@/server/api/client"; -import { getServerAuthSession } from "@/server/auth"; -import { TRPCError } from "@trpc/server"; -import { notFound, redirect } from "next/navigation"; -import ListView from "@/components/dashboard/lists/ListView"; -import DeleteListButton from "@/components/dashboard/lists/DeleteListButton"; - -export default async function ListPage({ - params, -}: { - params: { listId: string }; -}) { - const session = await getServerAuthSession(); - if (!session) { - redirect("/"); - } - - let list; - try { - list = await api.lists.get({ listId: params.listId }); - } catch (e) { - if (e instanceof TRPCError) { - if (e.code == "NOT_FOUND") { - notFound(); - } - } - throw e; - } - - const bookmarks = await api.bookmarks.getBookmarks({ ids: list.bookmarks }); - - return ( -
-
- - {list.icon} {list.name} - - -
-
- -
- ); -} diff --git a/packages/web/app/dashboard/lists/page.tsx b/packages/web/app/dashboard/lists/page.tsx deleted file mode 100644 index 88eeda47..00000000 --- a/packages/web/app/dashboard/lists/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { api } from "@/server/api/client"; -import AllListsView from "@/components/dashboard/lists/AllListsView"; - -export default async function ListsPage() { - const lists = await api.lists.list(); - - return ( -
-

📋 All Lists

-
- -
- ); -} diff --git a/packages/web/app/dashboard/not-found.tsx b/packages/web/app/dashboard/not-found.tsx deleted file mode 100644 index 64df220c..00000000 --- a/packages/web/app/dashboard/not-found.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function NotFound() { - return ( -
-
Not Found :(
-
- ); -} diff --git a/packages/web/app/dashboard/preview/[bookmarkId]/page.tsx b/packages/web/app/dashboard/preview/[bookmarkId]/page.tsx deleted file mode 100644 index 707d2b69..00000000 --- a/packages/web/app/dashboard/preview/[bookmarkId]/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { api } from "@/server/api/client"; -import BookmarkPreview from "@/components/dashboard/bookmarks/BookmarkPreview"; - -export default async function BookmarkPreviewPage({ - params, -}: { - params: { bookmarkId: string }; -}) { - const bookmark = await api.bookmarks.getBookmark({ - bookmarkId: params.bookmarkId, - }); - - return ; -} diff --git a/packages/web/app/dashboard/search/page.tsx b/packages/web/app/dashboard/search/page.tsx deleted file mode 100644 index 602f6aa0..00000000 --- a/packages/web/app/dashboard/search/page.tsx +++ /dev/null @@ -1,41 +0,0 @@ -"use client"; - -import BookmarksGrid from "@/components/dashboard/bookmarks/BookmarksGrid"; -import Loading from "../bookmarks/loading"; -import { Suspense, useRef } from "react"; -import { SearchInput } from "@/components/dashboard/search/SearchInput"; -import { useBookmarkSearch } from "@/lib/hooks/bookmark-search"; - -function SearchComp() { - const { data, isPending, isPlaceholderData } = useBookmarkSearch(); - - const inputRef: React.MutableRefObject = - useRef(null); - - return ( -
- -
- {data ? ( - b.id) }} - bookmarks={data.bookmarks} - /> - ) : ( - - )} -
- ); -} - -export default function SearchPage() { - return ( - - - - ); -} diff --git a/packages/web/app/dashboard/settings/page.tsx b/packages/web/app/dashboard/settings/page.tsx deleted file mode 100644 index 38091e6c..00000000 --- a/packages/web/app/dashboard/settings/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import ApiKeySettings from "@/components/dashboard/settings/ApiKeySettings"; -export default async function Settings() { - return ( -
-

Settings

- -
- ); -} diff --git a/packages/web/app/dashboard/tags/[tagName]/page.tsx b/packages/web/app/dashboard/tags/[tagName]/page.tsx deleted file mode 100644 index c978b86a..00000000 --- a/packages/web/app/dashboard/tags/[tagName]/page.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { getServerAuthSession } from "@/server/auth"; -import { db } from "@hoarder/db"; -import { notFound, redirect } from "next/navigation"; -import BookmarksGrid from "@/components/dashboard/bookmarks/BookmarksGrid"; -import { api } from "@/server/api/client"; -import { bookmarkTags, tagsOnBookmarks } from "@hoarder/db/schema"; -import { and, eq } from "drizzle-orm"; - -export default async function TagPage({ - params, -}: { - params: { tagName: string }; -}) { - const session = await getServerAuthSession(); - if (!session) { - redirect("/"); - } - const tagName = decodeURIComponent(params.tagName); - const tag = await db.query.bookmarkTags.findFirst({ - where: and( - eq(bookmarkTags.userId, session.user.id), - eq(bookmarkTags.name, tagName), - ), - columns: { - id: true, - }, - }); - - if (!tag) { - // TODO: Better error message when the tag is not there - notFound(); - } - - const bookmarkIds = await db.query.tagsOnBookmarks.findMany({ - where: eq(tagsOnBookmarks.tagId, tag.id), - columns: { - bookmarkId: true, - }, - }); - - const query = { - ids: bookmarkIds.map((b) => b.bookmarkId), - archived: false, - }; - - const bookmarks = await api.bookmarks.getBookmarks(query); - - return ( -
- {tagName} -
- -
- ); -} diff --git a/packages/web/app/dashboard/tags/page.tsx b/packages/web/app/dashboard/tags/page.tsx deleted file mode 100644 index 44c164e1..00000000 --- a/packages/web/app/dashboard/tags/page.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { Separator } from "@/components/ui/separator"; -import { getServerAuthSession } from "@/server/auth"; -import { db } from "@hoarder/db"; -import { bookmarkTags, tagsOnBookmarks } from "@hoarder/db/schema"; -import { count, eq } from "drizzle-orm"; -import Link from "next/link"; -import { redirect } from "next/navigation"; - -function TagPill({ name, count }: { name: string; count: number }) { - return ( - - {name} {count} - - ); -} - -export default async function TagsPage() { - const session = await getServerAuthSession(); - if (!session) { - redirect("/"); - } - - let tags = await db - .select({ - id: tagsOnBookmarks.tagId, - name: bookmarkTags.name, - count: count(), - }) - .from(tagsOnBookmarks) - .where(eq(bookmarkTags.userId, session.user.id)) - .groupBy(tagsOnBookmarks.tagId) - .innerJoin(bookmarkTags, eq(bookmarkTags.id, tagsOnBookmarks.tagId)); - - // Sort tags by usage desc - tags = tags.sort((a, b) => b.count - a.count); - - let tagPill; - if (tags.length) { - tagPill = tags.map((t) => ( - - )); - } else { - tagPill = "No Tags"; - } - - return ( -
- All Tags -
-
{tagPill}
-
- ); -} diff --git a/packages/web/app/favicon.ico b/packages/web/app/favicon.ico deleted file mode 100644 index 750e3c04..00000000 Binary files a/packages/web/app/favicon.ico and /dev/null differ diff --git a/packages/web/app/globals.css b/packages/web/app/globals.css deleted file mode 100644 index 8abdb15c..00000000 --- a/packages/web/app/globals.css +++ /dev/null @@ -1,76 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -@layer base { - :root { - --background: 0 0% 100%; - --foreground: 222.2 84% 4.9%; - - --card: 0 0% 100%; - --card-foreground: 222.2 84% 4.9%; - - --popover: 0 0% 100%; - --popover-foreground: 222.2 84% 4.9%; - - --primary: 222.2 47.4% 11.2%; - --primary-foreground: 210 40% 98%; - - --secondary: 210 40% 96.1%; - --secondary-foreground: 222.2 47.4% 11.2%; - - --muted: 210 40% 96.1%; - --muted-foreground: 215.4 16.3% 46.9%; - - --accent: 210 40% 96.1%; - --accent-foreground: 222.2 47.4% 11.2%; - - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 210 40% 98%; - - --border: 214.3 31.8% 91.4%; - --input: 214.3 31.8% 91.4%; - --ring: 222.2 84% 4.9%; - - --radius: 0.5rem; - } - - .dark { - --background: 222.2 84% 4.9%; - --foreground: 210 40% 98%; - - --card: 222.2 84% 4.9%; - --card-foreground: 210 40% 98%; - - --popover: 222.2 84% 4.9%; - --popover-foreground: 210 40% 98%; - - --primary: 210 40% 98%; - --primary-foreground: 222.2 47.4% 11.2%; - - --secondary: 217.2 32.6% 17.5%; - --secondary-foreground: 210 40% 98%; - - --muted: 217.2 32.6% 17.5%; - --muted-foreground: 215 20.2% 65.1%; - - --accent: 217.2 32.6% 17.5%; - --accent-foreground: 210 40% 98%; - - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 210 40% 98%; - - --border: 217.2 32.6% 17.5%; - --input: 217.2 32.6% 17.5%; - --ring: 212.7 26.8% 83.9%; - } -} - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } -} diff --git a/packages/web/app/layout.tsx b/packages/web/app/layout.tsx deleted file mode 100644 index b1790a1f..00000000 --- a/packages/web/app/layout.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import type { Metadata } from "next"; -import { Inter } from "next/font/google"; -import "./globals.css"; -import React from "react"; -import { Toaster } from "@/components/ui/toaster"; -import Providers from "@/lib/providers"; -import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; -import { getServerAuthSession } from "@/server/auth"; -import type { Viewport } from "next"; - -const inter = Inter({ subsets: ["latin"] }); - -export const metadata: Metadata = { - title: "Hoarder", - applicationName: "Hoarder", - description: "Your AI powered second brain", - manifest: "/manifest.json", - appleWebApp: { - capable: true, - title: "Hoarder", - }, - formatDetection: { - telephone: false, - }, -}; - -export const viewport: Viewport = { - width: "device-width", - initialScale: 1, - maximumScale: 1, - userScalable: false, -}; - -export default async function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - const session = await getServerAuthSession(); - return ( - - - - {children} - - - - - - ); -} diff --git a/packages/web/app/page.tsx b/packages/web/app/page.tsx deleted file mode 100644 index f467b64b..00000000 --- a/packages/web/app/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { getServerAuthSession } from "@/server/auth"; -import { redirect } from "next/navigation"; - -export default async function Home() { - // TODO: Home currently just redirects between pages until we build a proper landing page - const session = await getServerAuthSession(); - if (!session) { - redirect("/signin"); - } - - redirect("/dashboard/bookmarks"); -} diff --git a/packages/web/app/signin/page.tsx b/packages/web/app/signin/page.tsx deleted file mode 100644 index fed71b62..00000000 --- a/packages/web/app/signin/page.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { PackageOpen } from "lucide-react"; -import SignInForm from "@/components/signin/SignInForm"; -import { redirect } from "next/dist/client/components/navigation"; -import { getServerAuthSession } from "@/server/auth"; - -export default async function SignInPage() { - const session = await getServerAuthSession(); - if (session) { - redirect("/"); - } - - return ( -
-
- - - -

Hoarder

-
-
- -
-
- ); -} -- cgit v1.2.3-70-g09d2