|
@@ -912,10 +912,11 @@ interface FileCardProps {
|
|
|
thumbnailVersion?: number;
|
|
thumbnailVersion?: number;
|
|
|
hasPermission: (permission: Permission) => boolean;
|
|
hasPermission: (permission: Permission) => boolean;
|
|
|
canModify: (resource: 'queue' | 'archives' | 'library', action: 'update' | 'delete' | 'reprint', createdById: number | null | undefined) => boolean;
|
|
canModify: (resource: 'queue' | 'archives' | 'library', action: 'update' | 'delete' | 'reprint', createdById: number | null | undefined) => boolean;
|
|
|
|
|
+ authEnabled: boolean;
|
|
|
t: TFunction;
|
|
t: TFunction;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function FileCard({ file, isSelected, isMobile, onSelect, onDelete, onDownload, onAddToQueue, onPrint, onRename, onGenerateThumbnail, thumbnailVersion, hasPermission, canModify, t }: FileCardProps) {
|
|
|
|
|
|
|
+function FileCard({ file, isSelected, isMobile, onSelect, onDelete, onDownload, onAddToQueue, onPrint, onRename, onGenerateThumbnail, thumbnailVersion, hasPermission, canModify, authEnabled, t }: FileCardProps) {
|
|
|
const [showActions, setShowActions] = useState(false);
|
|
const [showActions, setShowActions] = useState(false);
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
@@ -974,7 +975,7 @@ function FileCard({ file, isSelected, isMobile, onSelect, onDelete, onDownload,
|
|
|
{t('fileManager.printedCount', { count: file.print_count })}
|
|
{t('fileManager.printedCount', { count: file.print_count })}
|
|
|
</div>
|
|
</div>
|
|
|
)}
|
|
)}
|
|
|
- {file.created_by_username && (
|
|
|
|
|
|
|
+ {authEnabled && file.created_by_username && (
|
|
|
<div className="mt-1 text-xs text-bambu-gray flex items-center gap-1">
|
|
<div className="mt-1 text-xs text-bambu-gray flex items-center gap-1">
|
|
|
<User className="w-3 h-3" />
|
|
<User className="w-3 h-3" />
|
|
|
{file.created_by_username}
|
|
{file.created_by_username}
|
|
@@ -1089,7 +1090,7 @@ export function FileManagerPage() {
|
|
|
const { t } = useTranslation();
|
|
const { t } = useTranslation();
|
|
|
const queryClient = useQueryClient();
|
|
const queryClient = useQueryClient();
|
|
|
const { showToast } = useToast();
|
|
const { showToast } = useToast();
|
|
|
- const { hasPermission, hasAnyPermission, canModify } = useAuth();
|
|
|
|
|
|
|
+ const { hasPermission, hasAnyPermission, canModify, authEnabled } = useAuth();
|
|
|
const [searchParams] = useSearchParams();
|
|
const [searchParams] = useSearchParams();
|
|
|
|
|
|
|
|
// Read folder ID from URL query parameter
|
|
// Read folder ID from URL query parameter
|
|
@@ -1762,31 +1763,33 @@ export function FileManagerPage() {
|
|
|
</select>
|
|
</select>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- {/* Username filter with autocomplete */}
|
|
|
|
|
- <div className="relative">
|
|
|
|
|
- <input
|
|
|
|
|
- type="text"
|
|
|
|
|
- placeholder={t('fileManager.filterByUser', { defaultValue: 'Filter by user' })}
|
|
|
|
|
- value={filterUsername}
|
|
|
|
|
- onChange={(e) => setFilterUsername(e.target.value)}
|
|
|
|
|
- list="usernames-list"
|
|
|
|
|
- className={`w-32 sm:w-40 px-2 py-1.5 bg-bambu-dark border border-bambu-dark-tertiary rounded text-sm text-white placeholder-bambu-gray focus:outline-none focus:border-bambu-green ${filterUsername ? 'pr-7' : ''}`}
|
|
|
|
|
- style={filterUsername ? { WebkitAppearance: 'none', MozAppearance: 'textfield' } : undefined}
|
|
|
|
|
- />
|
|
|
|
|
- {filterUsername && (
|
|
|
|
|
- <button
|
|
|
|
|
- onClick={() => setFilterUsername('')}
|
|
|
|
|
- className="absolute right-2 top-1/2 -translate-y-1/2 text-bambu-gray hover:text-white z-10"
|
|
|
|
|
- >
|
|
|
|
|
- <X className="w-3 h-3" />
|
|
|
|
|
- </button>
|
|
|
|
|
- )}
|
|
|
|
|
- <datalist id="usernames-list">
|
|
|
|
|
- {users?.map((user) => (
|
|
|
|
|
- <option key={user.id} value={user.username} />
|
|
|
|
|
- ))}
|
|
|
|
|
- </datalist>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ {/* Username filter with autocomplete - only show when auth is enabled */}
|
|
|
|
|
+ {authEnabled && (
|
|
|
|
|
+ <div className="relative">
|
|
|
|
|
+ <input
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ placeholder={t('fileManager.filterByUser', { defaultValue: 'Filter by user' })}
|
|
|
|
|
+ value={filterUsername}
|
|
|
|
|
+ onChange={(e) => setFilterUsername(e.target.value)}
|
|
|
|
|
+ list="usernames-list"
|
|
|
|
|
+ className={`w-32 sm:w-40 px-2 py-1.5 bg-bambu-dark border border-bambu-dark-tertiary rounded text-sm text-white placeholder-bambu-gray focus:outline-none focus:border-bambu-green ${filterUsername ? 'pr-7' : ''}`}
|
|
|
|
|
+ style={filterUsername ? { WebkitAppearance: 'none', MozAppearance: 'textfield' } : undefined}
|
|
|
|
|
+ />
|
|
|
|
|
+ {filterUsername && (
|
|
|
|
|
+ <button
|
|
|
|
|
+ onClick={() => setFilterUsername('')}
|
|
|
|
|
+ className="absolute right-2 top-1/2 -translate-y-1/2 text-bambu-gray hover:text-white z-10"
|
|
|
|
|
+ >
|
|
|
|
|
+ <X className="w-3 h-3" />
|
|
|
|
|
+ </button>
|
|
|
|
|
+ )}
|
|
|
|
|
+ <datalist id="usernames-list">
|
|
|
|
|
+ {users?.map((user) => (
|
|
|
|
|
+ <option key={user.id} value={user.username} />
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </datalist>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
|
|
|
|
|
{/* Sort */}
|
|
{/* Sort */}
|
|
|
<div className="flex items-center gap-2">
|
|
<div className="flex items-center gap-2">
|
|
@@ -1995,6 +1998,7 @@ export function FileManagerPage() {
|
|
|
thumbnailVersion={thumbnailVersions[file.id]}
|
|
thumbnailVersion={thumbnailVersions[file.id]}
|
|
|
hasPermission={hasPermission}
|
|
hasPermission={hasPermission}
|
|
|
canModify={canModify}
|
|
canModify={canModify}
|
|
|
|
|
+ authEnabled={authEnabled}
|
|
|
/>
|
|
/>
|
|
|
))}
|
|
))}
|
|
|
</div>
|
|
</div>
|
|
@@ -2003,10 +2007,10 @@ export function FileManagerPage() {
|
|
|
<div className="flex-1 lg:overflow-y-auto">
|
|
<div className="flex-1 lg:overflow-y-auto">
|
|
|
<div className="bg-bambu-dark-secondary rounded-lg border border-bambu-dark-tertiary overflow-hidden">
|
|
<div className="bg-bambu-dark-secondary rounded-lg border border-bambu-dark-tertiary overflow-hidden">
|
|
|
{/* List header - hidden on mobile, show simplified on small screens */}
|
|
{/* List header - hidden on mobile, show simplified on small screens */}
|
|
|
- <div className="hidden sm:grid grid-cols-[auto_1fr_120px_100px_100px_100px_80px] gap-4 px-4 py-2 bg-bambu-dark-secondary border-b border-bambu-dark-tertiary text-xs text-bambu-gray font-medium">
|
|
|
|
|
|
|
+ <div className={`hidden sm:grid ${authEnabled ? 'grid-cols-[auto_1fr_120px_100px_100px_100px_80px]' : 'grid-cols-[auto_1fr_100px_100px_100px_80px]'} gap-4 px-4 py-2 bg-bambu-dark-secondary border-b border-bambu-dark-tertiary text-xs text-bambu-gray font-medium`}>
|
|
|
<div className="w-6" />
|
|
<div className="w-6" />
|
|
|
<div>{t('common.name')}</div>
|
|
<div>{t('common.name')}</div>
|
|
|
- <div>{t('fileManager.uploadedBy', { defaultValue: 'Uploaded By' })}</div>
|
|
|
|
|
|
|
+ {authEnabled && <div>{t('fileManager.uploadedBy', { defaultValue: 'Uploaded By' })}</div>}
|
|
|
<div>{t('common.type')}</div>
|
|
<div>{t('common.type')}</div>
|
|
|
<div>{t('fileManager.size')}</div>
|
|
<div>{t('fileManager.size')}</div>
|
|
|
<div>{t('fileManager.prints')}</div>
|
|
<div>{t('fileManager.prints')}</div>
|
|
@@ -2016,7 +2020,7 @@ export function FileManagerPage() {
|
|
|
{filteredAndSortedFiles.map((file) => (
|
|
{filteredAndSortedFiles.map((file) => (
|
|
|
<div
|
|
<div
|
|
|
key={file.id}
|
|
key={file.id}
|
|
|
- className={`grid grid-cols-[auto_1fr_120px_100px_100px_100px_80px] gap-4 px-4 py-3 items-center border-b border-bambu-dark-tertiary last:border-b-0 cursor-pointer hover:bg-bambu-dark/50 transition-colors ${
|
|
|
|
|
|
|
+ className={`grid ${authEnabled ? 'grid-cols-[auto_1fr_120px_100px_100px_100px_80px]' : 'grid-cols-[auto_1fr_100px_100px_100px_80px]'} gap-4 px-4 py-3 items-center border-b border-bambu-dark-tertiary last:border-b-0 cursor-pointer hover:bg-bambu-dark/50 transition-colors ${
|
|
|
selectedFiles.includes(file.id) ? 'bg-bambu-green/10' : ''
|
|
selectedFiles.includes(file.id) ? 'bg-bambu-green/10' : ''
|
|
|
}`}
|
|
}`}
|
|
|
onClick={() => handleFileSelect(file.id)}
|
|
onClick={() => handleFileSelect(file.id)}
|
|
@@ -2062,17 +2066,19 @@ export function FileManagerPage() {
|
|
|
<div className="text-sm text-white truncate">{file.print_name || file.filename}</div>
|
|
<div className="text-sm text-white truncate">{file.print_name || file.filename}</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- {/* Uploaded By */}
|
|
|
|
|
- <div className="text-sm text-bambu-gray flex items-center gap-1">
|
|
|
|
|
- {file.created_by_username ? (
|
|
|
|
|
- <>
|
|
|
|
|
- <User className="w-3 h-3" />
|
|
|
|
|
- <span className="truncate">{file.created_by_username}</span>
|
|
|
|
|
- </>
|
|
|
|
|
- ) : (
|
|
|
|
|
- '-'
|
|
|
|
|
- )}
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ {/* Uploaded By - only show when auth is enabled */}
|
|
|
|
|
+ {authEnabled && (
|
|
|
|
|
+ <div className="text-sm text-bambu-gray flex items-center gap-1">
|
|
|
|
|
+ {file.created_by_username ? (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <User className="w-3 h-3" />
|
|
|
|
|
+ <span className="truncate">{file.created_by_username}</span>
|
|
|
|
|
+ </>
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ '-'
|
|
|
|
|
+ )}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
{/* Type */}
|
|
{/* Type */}
|
|
|
<div>
|
|
<div>
|
|
|
<span className={`text-xs px-1.5 py-0.5 rounded font-medium ${
|
|
<span className={`text-xs px-1.5 py-0.5 rounded font-medium ${
|