@@ -4,7 +4,7 @@ definePageMeta({
44 mainClass: " " ,
55});
66
7- import { ref , onMounted } from ' vue' ;
7+ import { ref , onMounted } from " vue" ;
88
99// Define types for the repository and log data
1010interface RepositoryOwner {
@@ -39,7 +39,7 @@ interface Repository {
3939interface LogEntry {
4040 timestamp: string ;
4141 message: string ;
42- type: ' info' | ' error' | ' success' ;
42+ type: " info" | " error" | " success" ;
4343 data: any ;
4444}
4545
@@ -51,57 +51,65 @@ const clientLogs = ref<LogEntry[]>([]);
5151const showLogs = ref (false );
5252
5353// Function to add logs that will be visible in the client
54- const logToClient = (message : string , type : ' info' | ' error' | ' success' = ' info' , data : any = null ): void => {
54+ const logToClient = (
55+ message : string ,
56+ type : " info" | " error" | " success" = " info" ,
57+ data : any = null ,
58+ ): void => {
5559 const timestamp = new Date ().toISOString ();
5660 const logEntry: LogEntry = {
5761 timestamp ,
5862 message ,
5963 type ,
60- data
64+ data ,
6165 };
6266 clientLogs .value .unshift (logEntry );
63- console .log (` [CLIENT-LOG][${type }] ${message } ` , data || ' ' );
67+ console .log (` [CLIENT-LOG][${type }] ${message } ` , data || " " );
6468};
6569
6670// Fetch all repositories from R2 storage
6771const fetchRepositories = async (): Promise <void > => {
6872 try {
6973 loading .value = true ;
70- logToClient (' Fetching repositories from R2 storage...' , ' info' );
71-
72- const response = await fetch (' /api/repos' );
73- const responseData = await response .json () as {
74+ logToClient (" Fetching repositories from R2 storage..." , " info" );
75+
76+ const response = await fetch (" /api/repos" );
77+ const responseData = ( await response .json () ) as {
7478 repositories: Repository [];
7579 error? : boolean ;
7680 message? : string ;
7781 debug_info? : any ;
7882 };
79-
83+
8084 if (responseData .error ) {
81- logToClient (` Error fetching repositories: ${responseData .message || ' Unknown error' } ` , ' error' , responseData .debug_info );
82- error .value = responseData .message || ' Unknown error' ;
85+ logToClient (
86+ ` Error fetching repositories: ${responseData .message || " Unknown error" } ` ,
87+ " error" ,
88+ responseData .debug_info ,
89+ );
90+ error .value = responseData .message || " Unknown error" ;
8391 loading .value = false ;
8492 return ;
8593 }
86-
94+
8795 repositories .value = responseData .repositories ;
8896 logToClient (
89- ` Successfully fetched ${responseData .repositories .length } repositories from R2 storage ` ,
90- ' success' ,
91- responseData .debug_info
97+ ` Successfully fetched ${responseData .repositories .length } repositories from R2 storage ` ,
98+ " success" ,
99+ responseData .debug_info ,
92100 );
93-
101+
94102 // Log available repositories
95- repositories .value .forEach (repo => {
96- logToClient (` Repository available: ${repo .full_name } ` , ' info' , {
103+ repositories .value .forEach (( repo ) => {
104+ logToClient (` Repository available: ${repo .full_name } ` , " info" , {
97105 default_branch: repo .default_branch ,
98- latest_commit: repo .latest_commit ?
99- ` ${repo .latest_commit .sha .substring (0 , 7 )} - ${repo .latest_commit .message .split (' \n ' )[0 ]} ` :
100- ' No commits found'
106+ latest_commit: repo .latest_commit
107+ ? ` ${repo .latest_commit .sha .substring (0 , 7 )} - ${repo .latest_commit .message .split (" \n " )[0 ]} `
108+ : " No commits found" ,
101109 });
102110 });
103111 } catch (e : any ) {
104- logToClient (` Failed to fetch repositories: ${e .message } ` , ' error' );
112+ logToClient (` Failed to fetch repositories: ${e .message } ` , " error" );
105113 error .value = ` Failed to fetch repositories: ${e .message } ` ;
106114 } finally {
107115 loading .value = false ;
@@ -110,13 +118,13 @@ const fetchRepositories = async (): Promise<void> => {
110118
111119// Truncate long texts
112120const truncate = (text : string , length = 60 ): string => {
113- if (! text ) return ' ' ;
114- return text .length > length ? text .substring (0 , length ) + ' ...' : text ;
121+ if (! text ) return " " ;
122+ return text .length > length ? text .substring (0 , length ) + " ..." : text ;
115123};
116124
117125// Format date
118126const formatDate = (dateString : string ): string => {
119- if (! dateString ) return ' Unknown' ;
127+ if (! dateString ) return " Unknown" ;
120128 const date = new Date (dateString );
121129 return date .toLocaleString ();
122130};
@@ -129,7 +137,7 @@ const toggleLogs = (): void => {
129137// Clear logs
130138const clearLogs = (): void => {
131139 clientLogs .value = [];
132- logToClient (' Logs cleared' , ' info' );
140+ logToClient (" Logs cleared" , " info" );
133141};
134142
135143// Load repositories on mount
@@ -149,125 +157,198 @@ function scrollToGettingStarted() {
149157
150158<template >
151159 <div >
152- <div class =" my-container flex flex-col items-center gap-4 md:gap-8 min-h-[calc(100vh-80px)]" >
160+ <div
161+ class =" my-container flex flex-col items-center gap-4 md:gap-8 min-h-[calc(100vh-80px)]"
162+ >
153163 <img src =" /favicon.svg" alt =" logo" width =" 64" height =" 64" />
154164
155165 <!-- Repository search -->
156166 <RepoSearch />
157167
158168 <!-- Repository List -->
159169 <div class =" w-full max-w-4xl mt-4" >
160- <h2 class =" text-xl font-semibold mb-4" >Available Repositories in R2 Storage</h2 >
161-
170+ <h2 class =" text-xl font-semibold mb-4" >
171+ Available Repositories in R2 Storage
172+ </h2 >
173+
162174 <div v-if =" loading" class =" p-4 text-center" >
163- <div class =" animate-spin rounded-full h-10 w-10 border-b-2 border-primary-500 mx-auto" ></div >
175+ <div
176+ class =" animate-spin rounded-full h-10 w-10 border-b-2 border-primary-500 mx-auto"
177+ ></div >
164178 <p class =" mt-2" >Loading repositories...</p >
165179 </div >
166-
167- <div v-else-if =" error" class =" p-4 border border-red-300 bg-red-50 dark:bg-red-900/20 dark:border-red-800 rounded-lg" >
180+
181+ <div
182+ v-else-if =" error"
183+ class =" p-4 border border-red-300 bg-red-50 dark:bg-red-900/20 dark:border-red-800 rounded-lg"
184+ >
168185 <p class =" text-red-600 dark:text-red-400" >{{ error }}</p >
169- <button @click =" fetchRepositories" class =" mt-2 px-4 py-2 bg-primary-500 text-white rounded hover:bg-primary-600 transition" >
186+ <button
187+ @click =" fetchRepositories"
188+ class =" mt-2 px-4 py-2 bg-primary-500 text-white rounded hover:bg-primary-600 transition"
189+ >
170190 Try Again
171191 </button >
172192 </div >
173-
174- <div v-else-if =" repositories.length === 0" class =" p-4 border border-gray-300 dark:border-gray-700 rounded-lg" >
193+
194+ <div
195+ v-else-if =" repositories.length === 0"
196+ class =" p-4 border border-gray-300 dark:border-gray-700 rounded-lg"
197+ >
175198 <p >No repositories found in R2 storage.</p >
176199 </div >
177-
200+
178201 <div v-else class =" grid gap-4 md:grid-cols-2" >
179- <div v-for =" repo in repositories" :key =" repo.id"
180- class =" border border-gray-200 dark:border-gray-700 rounded-lg p-4 hover:shadow-md transition" >
202+ <div
203+ v-for =" repo in repositories"
204+ :key =" repo.id"
205+ class =" border border-gray-200 dark:border-gray-700 rounded-lg p-4 hover:shadow-md transition"
206+ >
181207 <div class =" flex items-center gap-3 mb-2" >
182- <img v-if =" repo.owner.avatar_url" :src =" repo.owner.avatar_url" alt =" avatar" class =" w-8 h-8 rounded-full" />
183- <div v-else class =" w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center" >
208+ <img
209+ v-if =" repo.owner.avatar_url"
210+ :src =" repo.owner.avatar_url"
211+ alt =" avatar"
212+ class =" w-8 h-8 rounded-full"
213+ />
214+ <div
215+ v-else
216+ class =" w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center"
217+ >
184218 <span >{{ repo.owner.login[0] }}</span >
185219 </div >
186-
220+
187221 <h3 class =" font-semibold" >
188- <NuxtLink :to =" `/view/${repo.owner.login}/${repo.name}`" class =" text-primary-500 hover:underline" >
222+ <NuxtLink
223+ :to =" `/view/${repo.owner.login}/${repo.name}`"
224+ class =" text-primary-500 hover:underline"
225+ >
189226 {{ repo.full_name }}
190227 </NuxtLink >
191228 </h3 >
192229 </div >
193-
194- <p v-if =" repo.description" class =" text-sm text-gray-600 dark:text-gray-300 mb-3" >
230+
231+ <p
232+ v-if =" repo.description"
233+ class =" text-sm text-gray-600 dark:text-gray-300 mb-3"
234+ >
195235 {{ truncate(repo.description) }}
196236 </p >
197-
237+
198238 <div class =" mt-2 text-sm text-gray-500 dark:text-gray-400" >
199239 <div class =" flex gap-2 items-center" >
200240 <UIcon name =" i-heroicons-code-bracket" />
201241 <span >Default branch: {{ repo.default_branch }}</span >
202242 </div >
203-
243+
204244 <div class =" flex gap-2 items-center mt-1" >
205245 <UIcon name =" i-heroicons-star" />
206246 <span >{{ repo.stargazers_count || 0 }} stars</span >
207247 </div >
208-
248+
209249 <div class =" mt-2" >
210250 <p class =" font-medium" >Latest commit:</p >
211- <div v-if =" repo.latest_commit" class =" bg-gray-50 dark:bg-gray-800 p-2 rounded mt-1" >
251+ <div
252+ v-if =" repo.latest_commit"
253+ class =" bg-gray-50 dark:bg-gray-800 p-2 rounded mt-1"
254+ >
212255 <div class =" flex gap-2 items-center" >
213256 <UIcon name =" i-heroicons-hashtag" />
214- <span class =" text-xs font-mono" >{{ repo.latest_commit.sha.substring(0, 7) }}</span >
257+ <span class =" text-xs font-mono" >{{
258+ repo.latest_commit.sha.substring(0, 7)
259+ }}</span >
215260 </div >
216- <p class =" text-xs mt-1" >{{ truncate(repo.latest_commit.message, 80) }}</p >
217- <p class =" text-xs mt-1 text-gray-400" >{{ formatDate(repo.latest_commit.date) }}</p >
261+ <p class =" text-xs mt-1" >
262+ {{ truncate(repo.latest_commit.message, 80) }}
263+ </p >
264+ <p class =" text-xs mt-1 text-gray-400" >
265+ {{ formatDate(repo.latest_commit.date) }}
266+ </p >
218267 </div >
219- <p v-else class =" text-yellow-600 dark:text-yellow-400 italic" >No commits found</p >
268+ <p v-else class =" text-yellow-600 dark:text-yellow-400 italic" >
269+ No commits found
270+ </p >
220271 </div >
221-
272+
222273 <div class =" text-xs mt-2 text-gray-400" >
223274 Indexed: {{ formatDate(repo.indexed_at) }}
224275 </div >
225276 </div >
226277 </div >
227278 </div >
228279 </div >
229-
280+
230281 <!-- Client-side Logs Panel -->
231282 <div class =" fixed bottom-4 right-4 z-50" >
232- <button @click =" toggleLogs"
233- class =" px-4 py-2 bg-gray-700 text-white rounded-full flex items-center gap-2 hover:bg-gray-800 transition" >
283+ <button
284+ @click =" toggleLogs"
285+ class =" px-4 py-2 bg-gray-700 text-white rounded-full flex items-center gap-2 hover:bg-gray-800 transition"
286+ >
234287 <UIcon name =" i-heroicons-bug-ant" />
235- <span >{{ showLogs ? 'Hide' : 'Show' }} Logs</span >
236- <span class =" bg-red-500 rounded-full px-2 text-xs" >{{ clientLogs.length }}</span >
288+ <span >{{ showLogs ? "Hide" : "Show" }} Logs</span >
289+ <span class =" bg-red-500 rounded-full px-2 text-xs" >{{
290+ clientLogs.length
291+ }}</span >
237292 </button >
238-
239- <div v-if =" showLogs" class =" mt-2 bg-gray-800 text-white p-4 rounded-lg w-96 max-h-96 overflow-y-auto shadow-xl" >
293+
294+ <div
295+ v-if =" showLogs"
296+ class =" mt-2 bg-gray-800 text-white p-4 rounded-lg w-96 max-h-96 overflow-y-auto shadow-xl"
297+ >
240298 <div class =" flex justify-between items-center mb-2" >
241299 <h3 class =" font-bold" >Client Logs</h3 >
242- <button @click =" clearLogs" class =" text-xs px-2 py-1 bg-red-600 rounded hover:bg-red-700" >
300+ <button
301+ @click =" clearLogs"
302+ class =" text-xs px-2 py-1 bg-red-600 rounded hover:bg-red-700"
303+ >
243304 Clear
244305 </button >
245306 </div >
246-
247- <div v-if =" clientLogs.length === 0" class =" text-center py-4 text-gray-400" >
307+
308+ <div
309+ v-if =" clientLogs.length === 0"
310+ class =" text-center py-4 text-gray-400"
311+ >
248312 No logs yet
249313 </div >
250-
251- <div v-for =" (log, index) in clientLogs" :key =" index"
252- :class =" `mb-2 p-2 rounded text-xs ${
253- log.type === 'error' ? 'bg-red-900/50 border-l-2 border-red-600' :
254- log.type === 'success' ? 'bg-green-900/50 border-l-2 border-green-600' :
255- 'bg-gray-700/50 border-l-2 border-gray-500'
256- }`" >
314+
315+ <div
316+ v-for =" (log, index) in clientLogs"
317+ :key =" index"
318+ :class =" `mb-2 p-2 rounded text-xs ${
319+ log.type === 'error'
320+ ? 'bg-red-900/50 border-l-2 border-red-600'
321+ : log.type === 'success'
322+ ? 'bg-green-900/50 border-l-2 border-green-600'
323+ : 'bg-gray-700/50 border-l-2 border-gray-500'
324+ }`"
325+ >
257326 <div class =" flex justify-between text-xs" >
258- <span class =" font-mono" >{{ new Date(log.timestamp).toLocaleTimeString() }}</span >
259- <span :class =" `font-bold ${
260- log.type === 'error' ? 'text-red-400' :
261- log.type === 'success' ? 'text-green-400' :
262- 'text-blue-400'
263- }`" >
327+ <span class =" font-mono" >{{
328+ new Date(log.timestamp).toLocaleTimeString()
329+ }}</span >
330+ <span
331+ :class =" `font-bold ${
332+ log.type === 'error'
333+ ? 'text-red-400'
334+ : log.type === 'success'
335+ ? 'text-green-400'
336+ : 'text-blue-400'
337+ }`"
338+ >
264339 {{ log.type.toUpperCase() }}
265340 </span >
266341 </div >
267342 <div class =" mt-1" >{{ log.message }}</div >
268- <div v-if =" log.data"
269- class =" mt-1 p-1 bg-black/30 rounded font-mono text-gray-300 overflow-x-auto" >
270- <pre >{{ typeof log.data === 'string' ? log.data : JSON.stringify(log.data, null, 2) }}</pre >
343+ <div
344+ v-if =" log.data"
345+ class =" mt-1 p-1 bg-black/30 rounded font-mono text-gray-300 overflow-x-auto"
346+ >
347+ <pre >{{
348+ typeof log.data === "string"
349+ ? log.data
350+ : JSON.stringify(log.data, null, 2)
351+ }}</pre >
271352 </div >
272353 </div >
273354 </div >
0 commit comments