summaryrefslogtreecommitdiff
path: root/frontend/app/drive
diff options
context:
space:
mode:
authordiogo464 <[email protected]>2025-08-11 11:51:39 +0100
committerdiogo464 <[email protected]>2025-08-11 11:51:39 +0100
commit4af66f418b6837b6441b4e8eaf2d8ede585238b9 (patch)
tree34a4e913a2848515166b2ac0489794419a33bfcc /frontend/app/drive
parent0d3488a3811c8d58bd570af64cc29840df9ba439 (diff)
snapshot
Diffstat (limited to 'frontend/app/drive')
-rw-r--r--frontend/app/drive/[...path]/page.tsx136
-rw-r--r--frontend/app/drive/page.tsx94
2 files changed, 230 insertions, 0 deletions
diff --git a/frontend/app/drive/[...path]/page.tsx b/frontend/app/drive/[...path]/page.tsx
new file mode 100644
index 0000000..75a1bb1
--- /dev/null
+++ b/frontend/app/drive/[...path]/page.tsx
@@ -0,0 +1,136 @@
1import { Drive_ls, Drive_basename, Drive_parent } from "@/lib/drive"
2import { formatSize } from "@/lib/utils"
3import Link from "next/link"
4import { cookies } from 'next/headers';
5import { Auth_get_user } from "@/lib/auth";
6
7interface DrivePageProps {
8 params: Promise<{
9 path: string[]
10 }>
11}
12
13export default async function DrivePage({ params }: DrivePageProps) {
14 // Await params as required by Next.js 15
15 const { path } = await params
16
17 const user = await Auth_get_user();
18 console.log(user);
19
20 // Construct the full path from params
21 const fullPath = path ? `/${path.join('/')}` : ""
22
23 const entries = await Drive_ls(fullPath, false)
24
25 // Check if we have a parent directory
26 const parentDir = Drive_parent(fullPath)
27 const parentPath = path && path.length > 1
28 ? `/drive/${path.slice(0, -1).join('/')}`
29 : path && path.length === 1
30 ? '/drive'
31 : null
32
33 // Create entries with optional parent directory at top
34 const allEntries = []
35 if (parentDir !== null && parentPath !== null) {
36 allEntries.push({
37 path: '(parent)',
38 type: 'dir' as const,
39 lastmod: 0,
40 blob: null,
41 size: null,
42 author: '',
43 isParent: true,
44 parentPath
45 })
46 }
47
48 // Sort entries: directories first, then files, both alphabetically
49 const sortedEntries = entries.sort((a, b) => {
50 // First sort by type (directories before files)
51 if (a.type !== b.type) {
52 return a.type === 'dir' ? -1 : 1
53 }
54 // Then sort alphabetically by path
55 return a.path.localeCompare(b.path)
56 })
57
58 allEntries.push(...sortedEntries)
59
60 return (
61 <div className="min-h-screen bg-background">
62 <div className="container mx-auto p-4">
63 <Link href="/drive" className="inline-block mb-6">
64 <h1 className="text-2xl font-bold text-foreground hover:text-blue-600 dark:hover:text-blue-400 transition-colors cursor-pointer">FCTDrive</h1>
65 </Link>
66
67 <div className="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
68 <div className="overflow-x-auto">
69 <table className="w-full">
70 <thead className="bg-gray-50 dark:bg-gray-700">
71 <tr>
72 <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
73 Name
74 </th>
75 <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
76 Size
77 </th>
78 <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
79 Author
80 </th>
81 <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
82 Modified
83 </th>
84 </tr>
85 </thead>
86 <tbody className="divide-y divide-gray-200 dark:divide-gray-600">
87 {allEntries.map((entry, index) => (
88 <tr
89 key={entry.path}
90 className="hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
91 >
92 <td className="px-4 py-4 whitespace-nowrap">
93 <div className="flex items-center">
94 <div className="flex-shrink-0 h-5 w-5 mr-3">
95 {entry.type === 'dir' ? (
96 <div className="h-5 w-5 text-blue-500">📁</div>
97 ) : (
98 <div className="h-5 w-5 text-gray-400">📄</div>
99 )}
100 </div>
101 {entry.type === 'dir' ? (
102 <Link
103 href={(entry as any).isParent ? (entry as any).parentPath : `/drive${entry.path}`}
104 className="text-sm font-medium text-blue-600 dark:text-blue-400 hover:underline"
105 >
106 {(entry as any).isParent ? '(parent)' : Drive_basename(entry.path)}
107 </Link>
108 ) : (
109 <Link
110 href={`/blob/${entry.blob}?filename=${encodeURIComponent(Drive_basename(entry.path))}`}
111 className="text-sm font-medium text-blue-600 dark:text-blue-400 hover:underline"
112 >
113 {Drive_basename(entry.path)}
114 </Link>
115 )}
116 </div>
117 </td>
118 <td className="px-4 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-300">
119 {formatSize(entry.size)}
120 </td>
121 <td className="px-4 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-300">
122 {entry.author}
123 </td>
124 <td className="px-4 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-300">
125 {new Date(entry.lastmod * 1000).toLocaleString()}
126 </td>
127 </tr>
128 ))}
129 </tbody>
130 </table>
131 </div>
132 </div>
133 </div>
134 </div>
135 )
136}
diff --git a/frontend/app/drive/page.tsx b/frontend/app/drive/page.tsx
new file mode 100644
index 0000000..218774a
--- /dev/null
+++ b/frontend/app/drive/page.tsx
@@ -0,0 +1,94 @@
1import { Drive_ls, Drive_basename } from "@/lib/drive"
2import { formatSize } from "@/lib/utils"
3import Link from "next/link"
4
5export default async function DrivePage() {
6 const entries = await Drive_ls("", false)
7
8 // Sort entries: directories first, then files, both alphabetically
9 const sortedEntries = entries.sort((a, b) => {
10 // First sort by type (directories before files)
11 if (a.type !== b.type) {
12 return a.type === 'dir' ? -1 : 1
13 }
14 // Then sort alphabetically by path
15 return a.path.localeCompare(b.path)
16 })
17
18 return (
19 <div className="min-h-screen bg-background">
20 <div className="container mx-auto p-4">
21 <Link href="/drive" className="inline-block mb-6">
22 <h1 className="text-2xl font-bold text-foreground hover:text-blue-600 dark:hover:text-blue-400 transition-colors cursor-pointer">FCTDrive</h1>
23 </Link>
24
25 <div className="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
26 <div className="overflow-x-auto">
27 <table className="w-full">
28 <thead className="bg-gray-50 dark:bg-gray-700">
29 <tr>
30 <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
31 Name
32 </th>
33 <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
34 Size
35 </th>
36 <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
37 Author
38 </th>
39 <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
40 Modified
41 </th>
42 </tr>
43 </thead>
44 <tbody className="divide-y divide-gray-200 dark:divide-gray-600">
45 {sortedEntries.map((entry, index) => (
46 <tr
47 key={entry.path}
48 className="hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
49 >
50 <td className="px-4 py-4 whitespace-nowrap">
51 <div className="flex items-center">
52 <div className="flex-shrink-0 h-5 w-5 mr-3">
53 {entry.type === 'dir' ? (
54 <div className="h-5 w-5 text-blue-500">📁</div>
55 ) : (
56 <div className="h-5 w-5 text-gray-400">📄</div>
57 )}
58 </div>
59 {entry.type === 'dir' ? (
60 <Link
61 href={`/drive${entry.path}`}
62 className="text-sm font-medium text-blue-600 dark:text-blue-400 hover:underline"
63 >
64 {Drive_basename(entry.path)}
65 </Link>
66 ) : (
67 <Link
68 href={`/blob/${entry.blob}?filename=${encodeURIComponent(Drive_basename(entry.path))}`}
69 className="text-sm font-medium text-blue-600 dark:text-blue-400 hover:underline"
70 >
71 {Drive_basename(entry.path)}
72 </Link>
73 )}
74 </div>
75 </td>
76 <td className="px-4 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-300">
77 {formatSize(entry.size)}
78 </td>
79 <td className="px-4 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-300">
80 {entry.author}
81 </td>
82 <td className="px-4 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-300">
83 {new Date(entry.lastmod * 1000).toLocaleString()}
84 </td>
85 </tr>
86 ))}
87 </tbody>
88 </table>
89 </div>
90 </div>
91 </div>
92 </div>
93 )
94} \ No newline at end of file