Implement Repository Wiki page
swadhinbiswas committed 10 months ago
f86dd0b
1 parent 926bcc4
commit f86dd0b
2 files changed
+130 -46
Showing 2 changed files+130-46
▼scripts/debug_search.ts
+0-46
| @@ -1,46 +0,0 @@ | ||
1 | - | |
2 | -import { drizzle } from 'drizzle-orm/better-sqlite3'; | |
3 | -import Database from 'better-sqlite3'; | |
4 | -import * as schema from '../src/db/schema'; | |
5 | -import { like, or } from 'drizzle-orm'; | |
6 | - | |
7 | -const sqlite = new Database('./data/opencodehub.db'); | |
8 | -const db = drizzle(sqlite, { schema }); | |
9 | - | |
10 | -async function run() { | |
11 | - console.log('Running search debug...'); | |
12 | - const query = 'swadhin'; | |
13 | - | |
14 | - console.log(`Query: "${query}"`); | |
15 | - | |
16 | - // Search Users | |
17 | - const users = await db.query.users.findMany({ | |
18 | - where: or( | |
19 | - like(schema.users.username, `%${query}%`), | |
20 | - like(schema.users.displayName, `%${query}%`) | |
21 | - ), | |
22 | - limit: 3 | |
23 | - }); | |
24 | - console.log('Users found:', users.length); | |
25 | - users.forEach(u => console.log(` - ${u.username} (${u.displayName})`)); | |
26 | - | |
27 | - // Search Repos | |
28 | - const repos = await db.query.repositories.findMany({ | |
29 | - where: or( | |
30 | - like(schema.repositories.name, `%${query}%`), | |
31 | - like(schema.repositories.description, `%${query}%`) | |
32 | - ), | |
33 | - with: { owner: true }, | |
34 | - limit: 5 | |
35 | - }); | |
36 | - console.log('Repos found:', repos.length); | |
37 | - repos.forEach(r => console.log(` - ${r.namespace}/${r.name}`)); | |
38 | - | |
39 | - if (users.length === 0 && repos.length === 0) { | |
40 | - console.log('WARNING: No results found in DB!'); | |
41 | - } else { | |
42 | - console.log('SUCCESS: DB returns results.'); | |
43 | - } | |
44 | -} | |
45 | - | |
46 | -run().catch(console.error); | |
47 | 0 | |
▼src/pages/[owner]/[repo]/wiki/index.astro
+130-0
| @@ -0,0 +1,130 @@ | ||
1 | +--- | |
2 | +import RepoHeader from "@/components/repo/RepoHeader.astro"; | |
3 | +import { Button } from "@/components/ui/button"; | |
4 | +import { getDatabase, schema } from "@/db"; | |
5 | +import BaseLayout from "@/layouts/BaseLayout.astro"; | |
6 | +import { canReadRepo } from "@/lib/permissions"; | |
7 | +import { and, eq } from "drizzle-orm"; | |
8 | +import { Book, Plus } from "lucide-react"; | |
9 | +import { marked } from "marked"; | |
10 | + | |
11 | +const { owner: ownerName, repo: repoName } = Astro.params; | |
12 | +const db = getDatabase(); | |
13 | + | |
14 | +// 1. Fetch Repo & Owner | |
15 | +const user = await db.query.users.findFirst({ | |
16 | + where: eq(schema.users.username, ownerName!), | |
17 | +}); | |
18 | + | |
19 | +if (!user) return Astro.redirect("/404"); | |
20 | + | |
21 | +const repoData = await db.query.repositories.findFirst({ | |
22 | + where: and( | |
23 | + eq(schema.repositories.ownerId, user.id), | |
24 | + eq(schema.repositories.name, repoName!) | |
25 | + ), | |
26 | + with: { | |
27 | + owner: true, | |
28 | + }, | |
29 | +}); | |
30 | + | |
31 | +if (!repoData) return Astro.redirect("/404"); | |
32 | + | |
33 | +// Check permissions | |
34 | +const currentUser = Astro.locals.user; | |
35 | +const hasAccess = await canReadRepo(currentUser?.id, repoData); | |
36 | + | |
37 | +if (!hasAccess) { | |
38 | + return Astro.redirect("/404"); | |
39 | +} | |
40 | + | |
41 | +// Check if Wiki is enabled | |
42 | +if (!repoData.hasWiki) { | |
43 | + return Astro.redirect("/404"); | |
44 | +} | |
45 | + | |
46 | +const repo = { | |
47 | + owner: repoData.owner.username, | |
48 | + name: repoData.name, | |
49 | + description: repoData.description, | |
50 | + visibility: repoData.visibility, | |
51 | + defaultBranch: repoData.defaultBranch, | |
52 | + stars: repoData.starCount, | |
53 | + forks: repoData.forkCount, | |
54 | + watchers: repoData.watchCount, | |
55 | + topics: repoData.topics ? JSON.parse(repoData.topics) : [], | |
56 | + openIssueCount: repoData.openIssueCount, | |
57 | + openPrCount: repoData.openPrCount, | |
58 | +}; | |
59 | + | |
60 | +// Fetch Wiki Home Page | |
61 | +// Assuming 'home' is the default slug | |
62 | +const homePage = await db.query.wikiPages.findFirst({ | |
63 | + where: and( | |
64 | + eq(schema.wikiPages.repositoryId, repoData.id), | |
65 | + eq(schema.wikiPages.slug, 'home') | |
66 | + ) | |
67 | +}); | |
68 | + | |
69 | +let contentHtml = ''; | |
70 | +if (homePage) { | |
71 | + contentHtml = await marked.parse(homePage.content); | |
72 | +} | |
73 | +--- | |
74 | + | |
75 | +<BaseLayout title={`Wiki · ${repo.owner}/${repo.name}`}> | |
76 | + <div class="container py-6"> | |
77 | + <RepoHeader repo={repo} activeTab="wiki" /> | |
78 | + | |
79 | + <div class="flex flex-col md:flex-row gap-6 mt-6"> | |
80 | + <!-- Sidebar (Page List) - Placeholder for now --> | |
81 | + <div class="w-full md:w-64 flex-shrink-0 space-y-4"> | |
82 | + <div class="flex items-center justify-between"> | |
83 | + <h3 class="font-semibold">Pages</h3> | |
84 | + {homePage && ( | |
85 | + <Button size="sm" variant="outline" asChild> | |
86 | + <a href={`/${repo.owner}/${repo.name}/wiki/_new`}> | |
87 | + <Plus className="h-4 w-4" /> | |
88 | + </a> | |
89 | + </Button> | |
90 | + )} | |
91 | + </div> | |
92 | + {/* List pages here if needed */} | |
93 | + <nav class="flex flex-col space-y-1"> | |
94 | + <a href={`/${repo.owner}/${repo.name}/wiki`} class:list={["px-3 py-2 rounded-md text-sm font-medium", !homePage || homePage.slug === 'home' ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50"]}> | |
95 | + Home | |
96 | + </a> | |
97 | + </nav> | |
98 | + </div> | |
99 | + | |
100 | + {/* Main Content */} | |
101 | + <div class="flex-1 min-w-0"> | |
102 | + {homePage ? ( | |
103 | + <div class="space-y-4"> | |
104 | + <div class="flex items-center justify-between border-b pb-4"> | |
105 | + <h1 class="text-3xl font-bold">{homePage.title}</h1> | |
106 | + <div class="flex gap-2"> | |
107 | + <Button variant="outline" size="sm">Edit</Button> | |
108 | + <Button variant="outline" size="sm">History</Button> | |
109 | + </div> | |
110 | + </div> | |
111 | + <div class="prose max-w-none dark:prose-invert" set:html={contentHtml} /> | |
112 | + </div> | |
113 | + ) : ( | |
114 | + <div class="p-12 text-center border rounded-lg bg-muted/10"> | |
115 | + <Book className="h-12 w-12 text-muted-foreground mx-auto mb-4" /> | |
116 | + <h3 class="text-lg font-semibold mb-2">Welcome to the Wiki!</h3> | |
117 | + <p class="text-muted-foreground mb-6"> | |
118 | + This repository has no wiki pages yet. Start by creating the home page. | |
119 | + </p> | |
120 | + <Button asChild> | |
121 | + <a href={`/${repo.owner}/${repo.name}/wiki/_new`}> | |
122 | + Create the first page | |
123 | + </a> | |
124 | + </Button> | |
125 | + </div> | |
126 | + )} | |
127 | + </div> | |
128 | + </div> | |
129 | + </div> | |
130 | +</BaseLayout> | |
0 | 131 | |