mirror of
https://github.com/Noooste/garage-ui.git
synced 2026-07-27 08:08:56 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b28e975a56 | |||
| 430d1a5d68 | |||
| 460793632e | |||
| f888b7c77c | |||
| ef118dc3a7 |
@@ -1,3 +1,3 @@
|
||||
{
|
||||
".": "0.8.4"
|
||||
".": "0.8.5"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# Changelog
|
||||
|
||||
## [0.8.5](https://github.com/Noooste/garage-ui/compare/v0.8.4...v0.8.5) (2026-07-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **frontend:** add downloadObject function for downloading files from a bucket ([430d1a5](https://github.com/Noooste/garage-ui/commit/430d1a5d68e4f9915a2951d5b31c1b5ea56cb24c))
|
||||
|
||||
## [0.8.4](https://github.com/Noooste/garage-ui/compare/v0.8.3...v0.8.4) (2026-06-22)
|
||||
|
||||
|
||||
|
||||
Generated
+617
-850
File diff suppressed because it is too large
Load Diff
@@ -36,7 +36,7 @@
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/react": "^19.2.5",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.1",
|
||||
"@vitejs/plugin-react": "^5.2.0",
|
||||
"autoprefixer": "^10.4.22",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
@@ -46,6 +46,6 @@
|
||||
"tailwindcss": "^4.1.17",
|
||||
"typescript": "~5.9.3",
|
||||
"typescript-eslint": "^8.46.4",
|
||||
"vite": "^7.3.2"
|
||||
"vite": "^8.0.16"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { IconTile } from '@/components/ui/icon-tile';
|
||||
import { ConfirmDialog } from '@/components/ui/confirm-dialog';
|
||||
import { ArrowLeft, ChevronRight, Copy, Download, File, Loader2, Trash2 } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
import { formatBytes } from '@/lib/file-utils';
|
||||
import { downloadObject, formatBytes } from '@/lib/file-utils';
|
||||
import { formatDate } from '@/lib/utils';
|
||||
|
||||
function CardSection({ title, children }: { title: string; children: React.ReactNode }) {
|
||||
@@ -73,22 +73,9 @@ export function ObjectDetailsView() {
|
||||
toast.success(label);
|
||||
};
|
||||
|
||||
const handleDownload = async () => {
|
||||
const handleDownload = () => {
|
||||
if (!bucketName || !objectKey) return;
|
||||
try {
|
||||
const blob = await objectsApi.get(bucketName, objectKey);
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = fileName || 'download';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
document.body.removeChild(a);
|
||||
toast.success('Download started');
|
||||
} catch {
|
||||
// error toast handled by axios interceptor
|
||||
}
|
||||
downloadObject(bucketName, objectKey);
|
||||
};
|
||||
|
||||
const handleDelete = async () => {
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import {ChevronLeft, ChevronRight, Download, Eye, FileIcon, FolderIcon, Loader2, MoreVertical, Trash2} from 'lucide-react';
|
||||
import {Select, SelectOption} from '@/components/ui/select';
|
||||
import {formatBytes, formatRelativeTime} from '@/lib/file-utils';
|
||||
import {downloadObject, formatBytes, formatRelativeTime} from '@/lib/file-utils';
|
||||
import type {S3Object} from '@/types';
|
||||
|
||||
interface ObjectsTableProps {
|
||||
@@ -353,7 +353,7 @@ export function ObjectsTable({
|
||||
<Eye className="h-4 w-4" />
|
||||
View Details
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => downloadObject(bucketName, obj.key)}>
|
||||
<Download className="h-4 w-4" />
|
||||
Download
|
||||
</DropdownMenuItem>
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
import { objectsApi } from './api';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
/**
|
||||
* Download an object from a bucket by fetching it as a blob and clicking a
|
||||
* temporary anchor element. Errors are surfaced by the axios interceptor.
|
||||
*/
|
||||
export async function downloadObject(bucket: string, key: string): Promise<void> {
|
||||
try {
|
||||
const blob = await objectsApi.get(bucket, key);
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = key.split('/').pop() || 'download';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
document.body.removeChild(a);
|
||||
toast.success('Download started');
|
||||
} catch {
|
||||
// error toast handled by axios interceptor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file type based on file extension
|
||||
*/
|
||||
|
||||
@@ -3,8 +3,8 @@ name: garage-ui
|
||||
description: A Helm chart for Garage UI - Web interface for Garage S3 object storage
|
||||
icon: https://helm.noste.dev/garage.png
|
||||
type: application
|
||||
version: 0.8.4 # x-release-please-version
|
||||
appVersion: v0.8.4 # x-release-please-version
|
||||
version: 0.8.5 # x-release-please-version
|
||||
appVersion: v0.8.5 # x-release-please-version
|
||||
keywords:
|
||||
- garage
|
||||
- s3
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
A Helm chart for deploying [Garage UI](https://github.com/Noooste/garage-ui), a modern web interface for managing [Garage](https://garagehq.deuxfleurs.fr/) distributed object storage systems.
|
||||
|
||||
[](Chart.yaml) <!-- x-release-please-version -->
|
||||
[](Chart.yaml) <!-- x-release-please-version -->
|
||||
[](Chart.yaml) <!-- x-release-please-version -->
|
||||
[](Chart.yaml) <!-- x-release-please-version -->
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
||||
Reference in New Issue
Block a user