mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-05 21:51:23 +02:00
Added sort dropdown to printer file manager with options for:
- Name (A-Z / Z-A) - Size (smallest / largest first) - Date (oldest / newest first) Directories are always sorted first regardless of sort option.
This commit is contained in:
@@ -9,6 +9,11 @@ All notable changes to Bambuddy will be documented in this file.
|
||||
- 8 basic colors shown by default (White, Black, Red, Blue, Green, Yellow, Orange, Gray)
|
||||
- Click "+" to expand 24 additional colors (Cyan, Magenta, Purple, Pink, Brown, Beige, Navy, Teal, Lime, Gold, Silver, Maroon, Olive, Coral, Salmon, Turquoise, Violet, Indigo, Chocolate, Tan, Slate, Charcoal, Ivory, Cream)
|
||||
- Click "-" to collapse back to basic colors
|
||||
- **File Manager Sorting** - Printer file manager now has sorting options:
|
||||
- Sort by name (A-Z or Z-A)
|
||||
- Sort by size (smallest or largest first)
|
||||
- Sort by date (oldest or newest first)
|
||||
- Directories always sorted first
|
||||
|
||||
### Fixed
|
||||
- **User preset AMS configuration** - Fixed user presets (inheriting from Bambu presets) showing empty fields in Bambu Studio after configuration:
|
||||
|
||||
@@ -1470,6 +1470,7 @@ export const api = {
|
||||
is_directory: boolean;
|
||||
size: number;
|
||||
path: string;
|
||||
mtime?: string;
|
||||
}>;
|
||||
}>(`/printers/${printerId}/files?path=${encodeURIComponent(path)}`),
|
||||
getPrinterFileDownloadUrl: (printerId: number, path: string) =>
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
FileText,
|
||||
Image,
|
||||
Search,
|
||||
ArrowUpDown,
|
||||
} from 'lucide-react';
|
||||
import { api } from '../api/client';
|
||||
import { Button } from './Button';
|
||||
@@ -66,6 +67,17 @@ function getFileIcon(filename: string, isDirectory: boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
type SortOption = 'name-asc' | 'name-desc' | 'size-asc' | 'size-desc' | 'date-asc' | 'date-desc';
|
||||
|
||||
const SORT_OPTIONS: { value: SortOption; label: string }[] = [
|
||||
{ value: 'name-asc', label: 'Name (A-Z)' },
|
||||
{ value: 'name-desc', label: 'Name (Z-A)' },
|
||||
{ value: 'size-asc', label: 'Size (smallest)' },
|
||||
{ value: 'size-desc', label: 'Size (largest)' },
|
||||
{ value: 'date-asc', label: 'Date (oldest)' },
|
||||
{ value: 'date-desc', label: 'Date (newest)' },
|
||||
];
|
||||
|
||||
export function FileManagerModal({ printerId, printerName, onClose }: FileManagerModalProps) {
|
||||
const { showToast } = useToast();
|
||||
const queryClient = useQueryClient();
|
||||
@@ -73,6 +85,7 @@ export function FileManagerModal({ printerId, printerName, onClose }: FileManage
|
||||
const [selectedFile, setSelectedFile] = useState<string | null>(null);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [fileToDelete, setFileToDelete] = useState<string | null>(null);
|
||||
const [sortBy, setSortBy] = useState<SortOption>('name-asc');
|
||||
|
||||
// Close on Escape key
|
||||
useEffect(() => {
|
||||
@@ -206,6 +219,20 @@ export function FileManagerModal({ printerId, printerName, onClose }: FileManage
|
||||
className="w-40 pl-8 pr-3 py-1.5 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white text-sm focus:border-bambu-green focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex items-center gap-1">
|
||||
<ArrowUpDown className="w-4 h-4 text-bambu-gray" />
|
||||
<select
|
||||
value={sortBy}
|
||||
onChange={(e) => setSortBy(e.target.value as SortOption)}
|
||||
className="appearance-none bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white text-sm py-1.5 pl-2 pr-6 focus:border-bambu-green focus:outline-none cursor-pointer"
|
||||
>
|
||||
{SORT_OPTIONS.map((option) => (
|
||||
<option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
@@ -240,15 +267,39 @@ export function FileManagerModal({ printerId, printerName, onClose }: FileManage
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-1">
|
||||
{/* Filter and sort: directories first, then files */}
|
||||
{/* Filter and sort: directories first, then files with selected sort */}
|
||||
{[...data.files]
|
||||
.filter((file) =>
|
||||
!searchQuery || file.name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
)
|
||||
.sort((a, b) => {
|
||||
// Directories always first
|
||||
if (a.is_directory && !b.is_directory) return -1;
|
||||
if (!a.is_directory && b.is_directory) return 1;
|
||||
return a.name.localeCompare(b.name);
|
||||
|
||||
// Apply selected sort within same type
|
||||
switch (sortBy) {
|
||||
case 'name-asc':
|
||||
return a.name.localeCompare(b.name);
|
||||
case 'name-desc':
|
||||
return b.name.localeCompare(a.name);
|
||||
case 'size-asc':
|
||||
return a.size - b.size;
|
||||
case 'size-desc':
|
||||
return b.size - a.size;
|
||||
case 'date-asc': {
|
||||
const aTime = a.mtime ? new Date(a.mtime).getTime() : 0;
|
||||
const bTime = b.mtime ? new Date(b.mtime).getTime() : 0;
|
||||
return aTime - bTime;
|
||||
}
|
||||
case 'date-desc': {
|
||||
const aTime = a.mtime ? new Date(a.mtime).getTime() : 0;
|
||||
const bTime = b.mtime ? new Date(b.mtime).getTime() : 0;
|
||||
return bTime - aTime;
|
||||
}
|
||||
default:
|
||||
return a.name.localeCompare(b.name);
|
||||
}
|
||||
})
|
||||
.map((file) => {
|
||||
const FileIcon = getFileIcon(file.name, file.is_directory);
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
-2
@@ -23,8 +23,8 @@
|
||||
|
||||
<!-- Splash screens for iOS -->
|
||||
<link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
|
||||
<script type="module" crossorigin src="/assets/index-CO2y-9S4.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CMAdGpGJ.css">
|
||||
<script type="module" crossorigin src="/assets/index-BQHdfJWP.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Sa64ulbW.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
Reference in New Issue
Block a user