feat: Add file manager view using VueFinder
All checks were successful
Build Companion Agent / build (push) Successful in 32s
Test Asgard Runner / test (push) Successful in 3s

Installs VueFinder and wires it to the backend /api/files endpoint with
JWT Bearer auth. Adds /files route, File Manager nav item (files.view
permission-gated, FolderOpen icon), and imports VueFinder CSS globally.
Driver token is computed reactively so it tracks token refreshes automatically.
Uses midnight theme to match the dark admin panel aesthetic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell
2026-02-21 16:13:10 -05:00
parent e9f9b449b1
commit 2df5c80928
6 changed files with 645 additions and 2 deletions

View File

@@ -26,6 +26,7 @@ import {
Clock,
AlertTriangle,
FileText,
FolderOpen,
Menu,
X,
} from 'lucide-vue-next'
@@ -42,6 +43,7 @@ const navItems = [
{ name: 'Console', path: '/console', icon: Terminal, permission: 'console.view' },
{ name: 'Players', path: '/players', icon: Users, permission: 'players.view' },
{ name: 'Plugins', path: '/plugins', icon: Puzzle, permission: 'plugins.view' },
{ name: 'File Manager', path: '/files', icon: FolderOpen, permission: 'files.view' },
{ name: 'Auto-Wiper', path: '/wipes', icon: RefreshCw, permission: 'wipes.view' },
{ name: 'Maps', path: '/maps', icon: Map, permission: 'maps.view' },
{ name: 'Chat Log', path: '/chat', icon: MessageSquare, permission: 'chat.view' },

View File

@@ -5,6 +5,7 @@ import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import App from './App.vue'
import router from './router'
import './style.css'
import 'vuefinder/dist/vuefinder.css'
const app = createApp(App)

View File

@@ -105,6 +105,11 @@ const panelRoutes: RouteRecordRaw[] = [
name: 'plugins',
component: () => import('@/views/admin/PluginsView.vue'),
},
{
path: 'files',
name: 'files',
component: () => import('@/views/admin/FileManagerView.vue'),
},
{
path: 'wipes',
name: 'wipes',

View File

@@ -0,0 +1,49 @@
<script setup lang="ts">
import { computed } from 'vue'
import { VueFinder, RemoteDriver } from 'vuefinder'
import { useAuthStore } from '@/stores/auth'
const auth = useAuthStore()
// Recreate the RemoteDriver reactively so the token stays current across
// automatic refresh cycles (useApi composable silently rotates accessToken).
const driver = computed(
() =>
new RemoteDriver({
baseURL: '/api/files',
token: auth.accessToken ?? undefined,
})
)
// Non-persistent config passed to VueFinder per session.
// maxFileSize in bytes — 10 MB limit matches the backend upload ceiling.
const finderConfig = {
theme: 'midnight',
maxFileSize: 10 * 1024 * 1024,
showMenuBar: true,
showToolbar: true,
}
</script>
<template>
<div class="space-y-6 p-6">
<div class="flex items-center justify-between">
<div>
<h1 class="text-2xl font-bold text-white">File Manager</h1>
<p class="text-sm text-gray-400 mt-1">Browse and edit your server files</p>
</div>
</div>
<div
class="bg-neutral-900 rounded-lg border border-neutral-800 overflow-hidden"
style="min-height: 640px;"
>
<VueFinder
id="corrosion-filemanager"
:driver="driver"
:config="finderConfig"
locale="en"
/>
</div>
</div>
</template>