feat(App, FileManager): add Print Manager functionality and enhance file manager path handling
This commit is contained in:
parent
63d2ff9f69
commit
4ce0b46b07
|
|
@ -1,5 +1,5 @@
|
|||
import { useState } from 'react';
|
||||
import { Cpu, Settings, Wifi, Network, HardDrive, Activity, MoreHorizontal, Search, Wrench, User, LogOut, Bell, FileText, AppWindow, Folder, Edit, Eye, Database, Upload, Download, Code2, LayoutList, Image, ChevronLeft, Loader2, Check, AlertCircle, RefreshCw, Terminal, Link } from 'lucide-react';
|
||||
import { Cpu, Settings, Wifi, Network, HardDrive, Activity, MoreHorizontal, Search, Wrench, User, LogOut, Bell, FileText, AppWindow, Folder, Edit, Eye, Database, Upload, Download, Code2, LayoutList, Image, ChevronLeft, Loader2, Check, AlertCircle, RefreshCw, Terminal, Link, Printer } from 'lucide-react';
|
||||
import { Toaster } from 'sonner';
|
||||
import StatusPage from './components/StatusPage';
|
||||
import DevicesPage from './components/DevicesPage';
|
||||
|
|
@ -17,6 +17,7 @@ type Page = 'status' | 'devices' | 'iec' | 'network' | 'other' | 'general' | 'to
|
|||
|
||||
type AppId =
|
||||
| 'file-manager'
|
||||
| 'print-manager'
|
||||
| 'serial-console'
|
||||
| 'directory-editor'
|
||||
| 'sector-editor'
|
||||
|
|
@ -60,6 +61,7 @@ export default function App() {
|
|||
<h2 className="text-lg font-semibold mb-4 text-blue-700">Management</h2>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
|
||||
<AppCard icon={<Folder className="w-7 h-7" />} label="File Manager" onClick={() => setCurrentPage('file-manager')} />
|
||||
<AppCard icon={<Printer className="w-7 h-7" />} label="Print Manager" onClick={() => setCurrentPage('print-manager')} />
|
||||
<AppCard icon={<Terminal className="w-7 h-7" />} label="Serial Console" onClick={() => setCurrentPage('serial-console')} />
|
||||
<AppCard icon={<Link className="w-7 h-7" />} label="Short Codes" onClick={() => setCurrentPage('serial-console')} />
|
||||
</div>
|
||||
|
|
@ -115,6 +117,13 @@ export default function App() {
|
|||
setConfig={setConfig}
|
||||
onNavigateToDevice={(id) => { setCurrentPage('devices'); setDevicesOpenId(id); }}
|
||||
/>,
|
||||
'print-manager': <FileManager
|
||||
title="Print Manager"
|
||||
rootPath="/sd/.print"
|
||||
onBack={() => setCurrentPage('apps')}
|
||||
config={config}
|
||||
setConfig={setConfig}
|
||||
/>,
|
||||
'serial-console': <AppPage title="Serial Console" onBack={() => setCurrentPage('apps')} />,
|
||||
'directory-editor': <AppPage title="Directory Editor" onBack={() => setCurrentPage('apps')} />,
|
||||
'sector-editor': <AppPage title="Sector Editor" onBack={() => setCurrentPage('apps')} />,
|
||||
|
|
|
|||
|
|
@ -247,6 +247,8 @@ function EntryIcon({ entry }: { entry: EntryInfo }) {
|
|||
|
||||
interface FileManagerProps {
|
||||
initialPath?: string;
|
||||
rootPath?: string;
|
||||
title?: string;
|
||||
config?: any;
|
||||
setConfig?: (c: any) => void;
|
||||
onBack?: () => void;
|
||||
|
|
@ -303,8 +305,9 @@ async function _getEntryBytes(entry: EntryInfo): Promise<Uint8Array> {
|
|||
|
||||
const FM_PATH_KEY = 'fileManager.path';
|
||||
|
||||
export default function FileManager({ initialPath = '/', config, setConfig, onBack, onNavigateToDevice }: FileManagerProps) {
|
||||
const [path, setPath] = useState(() => normalizePath(localStorage.getItem(FM_PATH_KEY) || initialPath));
|
||||
export default function FileManager({ initialPath = '/', rootPath, title, config, setConfig, onBack, onNavigateToDevice }: FileManagerProps) {
|
||||
const pathKey = rootPath ? `fileManager.path:${rootPath}` : FM_PATH_KEY;
|
||||
const [path, setPath] = useState(() => normalizePath(localStorage.getItem(pathKey) || rootPath || initialPath));
|
||||
const [entries, setEntries] = useState<EntryInfo[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
|
@ -357,12 +360,13 @@ export default function FileManager({ initialPath = '/', config, setConfig, onBa
|
|||
useEffect(() => { localStorage.setItem('fileManager.sortAsc', String(sortAsc)); }, [sortAsc]);
|
||||
|
||||
const navigateTo = (p: string) => {
|
||||
const norm = normalizePath(p);
|
||||
localStorage.setItem(FM_PATH_KEY, norm);
|
||||
let norm = normalizePath(p);
|
||||
if (rootPath && !norm.startsWith(rootPath)) norm = rootPath;
|
||||
localStorage.setItem(pathKey, norm);
|
||||
setPath(norm);
|
||||
setFilter('');
|
||||
};
|
||||
const navigateUp = () => { if (path !== '/') navigateTo(splitPath(path).parent); };
|
||||
const navigateUp = () => { if (path !== (rootPath ?? '/')) navigateTo(splitPath(path).parent); };
|
||||
|
||||
// ── Sort + filter ────────────────────────────────────────────────────────
|
||||
|
||||
|
|
@ -674,7 +678,7 @@ export default function FileManager({ initialPath = '/', config, setConfig, onBa
|
|||
<ChevronLeft className="w-5 h-5" />
|
||||
</button>
|
||||
)}
|
||||
<h2 className="font-semibold flex-1 text-sm">File Manager</h2>
|
||||
<h2 className="font-semibold flex-1 text-sm">{title ?? 'File Manager'}</h2>
|
||||
<button onClick={() => void load(path)} className="p-1.5 rounded hover:bg-neutral-100" title="Refresh">
|
||||
<RefreshCw className="w-4 h-4" />
|
||||
</button>
|
||||
|
|
@ -689,7 +693,7 @@ export default function FileManager({ initialPath = '/', config, setConfig, onBa
|
|||
|
||||
{/* Breadcrumb */}
|
||||
<div className="flex items-center gap-1 text-sm text-neutral-600 overflow-x-auto">
|
||||
<button onClick={() => navigateTo('/')} className="p-1 rounded hover:bg-neutral-100 flex-shrink-0" title="Root">
|
||||
<button onClick={() => navigateTo(rootPath ?? '/')} className="p-1 rounded hover:bg-neutral-100 flex-shrink-0" title="Root">
|
||||
<Home className="w-4 h-4" />
|
||||
</button>
|
||||
{pathParts.map((part, i) => (
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user