Update frontend/src/pages/Repository.jsx
Browse files
frontend/src/pages/Repository.jsx
CHANGED
|
@@ -114,6 +114,8 @@ export default function Repository() {
|
|
| 114 |
const [pdfPages, setPdfPages] = useState(null);
|
| 115 |
const [isLoadingPdf, setIsLoadingPdf] = useState(false);
|
| 116 |
const [isDeleting, setIsDeleting] = useState(false);
|
|
|
|
|
|
|
| 117 |
const fileInputRef = useRef(null);
|
| 118 |
|
| 119 |
const toggleProduct = (productId) => {
|
|
@@ -706,7 +708,7 @@ export default function Repository() {
|
|
| 706 |
<FolderOpen className="w-4 h-4" />
|
| 707 |
<span className="font-medium text-sm">All Assets</span>
|
| 708 |
<Badge variant="secondary" className="ml-auto text-xs">
|
| 709 |
-
{
|
| 710 |
</Badge>
|
| 711 |
</button>
|
| 712 |
|
|
@@ -849,6 +851,13 @@ export default function Repository() {
|
|
| 849 |
e.stopPropagation();
|
| 850 |
setPreviewAsset(asset);
|
| 851 |
setPreviewDialogOpen(true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 852 |
}}
|
| 853 |
>
|
| 854 |
<Eye className="w-4 h-4" />
|
|
@@ -890,12 +899,15 @@ export default function Repository() {
|
|
| 890 |
<DropdownMenuItem onClick={async () => {
|
| 891 |
setPreviewAsset(asset);
|
| 892 |
setPreviewDialogOpen(true);
|
|
|
|
|
|
|
| 893 |
// Load PDF pages if it's a PDF
|
| 894 |
if (asset.type === 'document' && asset.name.toLowerCase().endsWith('.pdf')) {
|
| 895 |
await loadPdfPages(String(asset.id));
|
| 896 |
} else {
|
| 897 |
setPdfPages(null);
|
| 898 |
}
|
|
|
|
| 899 |
}}>
|
| 900 |
<Eye className="w-4 h-4 mr-2" /> Preview
|
| 901 |
</DropdownMenuItem>
|
|
@@ -975,12 +987,15 @@ export default function Repository() {
|
|
| 975 |
<DropdownMenuItem onClick={async () => {
|
| 976 |
setPreviewAsset(asset);
|
| 977 |
setPreviewDialogOpen(true);
|
|
|
|
|
|
|
| 978 |
// Load PDF pages if it's a PDF
|
| 979 |
if (asset.type === 'document' && asset.name.toLowerCase().endsWith('.pdf')) {
|
| 980 |
await loadPdfPages(String(asset.id));
|
| 981 |
} else {
|
| 982 |
setPdfPages(null);
|
| 983 |
}
|
|
|
|
| 984 |
}}>
|
| 985 |
<Eye className="w-4 h-4 mr-2" /> Preview
|
| 986 |
</DropdownMenuItem>
|
|
@@ -1017,6 +1032,7 @@ export default function Repository() {
|
|
| 1017 |
if (!open) {
|
| 1018 |
setPreviewAsset(null);
|
| 1019 |
setPdfPages(null);
|
|
|
|
| 1020 |
}
|
| 1021 |
}}>
|
| 1022 |
<DialogContent className="max-w-6xl max-h-[90vh] flex flex-col">
|
|
@@ -1043,20 +1059,63 @@ export default function Repository() {
|
|
| 1043 |
<div className="mt-4 flex-1 overflow-auto">
|
| 1044 |
{previewAsset && (
|
| 1045 |
<div className="space-y-4">
|
| 1046 |
-
{
|
| 1047 |
-
<
|
| 1048 |
-
|
| 1049 |
-
|
| 1050 |
-
className="
|
| 1051 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1052 |
) : previewAsset.type === 'video' ? (
|
| 1053 |
-
<
|
| 1054 |
-
|
| 1055 |
-
|
| 1056 |
-
|
| 1057 |
-
|
| 1058 |
-
|
| 1059 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1060 |
) : previewAsset.type === 'document' && previewAsset.name.toLowerCase().endsWith('.pdf') ? (
|
| 1061 |
<div className="space-y-4">
|
| 1062 |
{isLoadingPdf ? (
|
|
|
|
| 114 |
const [pdfPages, setPdfPages] = useState(null);
|
| 115 |
const [isLoadingPdf, setIsLoadingPdf] = useState(false);
|
| 116 |
const [isDeleting, setIsDeleting] = useState(false);
|
| 117 |
+
const [previewError, setPreviewError] = useState(null);
|
| 118 |
+
const [isLoadingPreview, setIsLoadingPreview] = useState(false);
|
| 119 |
const fileInputRef = useRef(null);
|
| 120 |
|
| 121 |
const toggleProduct = (productId) => {
|
|
|
|
| 708 |
<FolderOpen className="w-4 h-4" />
|
| 709 |
<span className="font-medium text-sm">All Assets</span>
|
| 710 |
<Badge variant="secondary" className="ml-auto text-xs">
|
| 711 |
+
{assets.length}
|
| 712 |
</Badge>
|
| 713 |
</button>
|
| 714 |
|
|
|
|
| 851 |
e.stopPropagation();
|
| 852 |
setPreviewAsset(asset);
|
| 853 |
setPreviewDialogOpen(true);
|
| 854 |
+
setPreviewError(null);
|
| 855 |
+
setIsLoadingPreview(true);
|
| 856 |
+
if (asset.type === 'document' && asset.name.toLowerCase().endsWith('.pdf')) {
|
| 857 |
+
loadPdfPages(String(asset.id)).finally(() => setIsLoadingPreview(false));
|
| 858 |
+
} else {
|
| 859 |
+
setIsLoadingPreview(false);
|
| 860 |
+
}
|
| 861 |
}}
|
| 862 |
>
|
| 863 |
<Eye className="w-4 h-4" />
|
|
|
|
| 899 |
<DropdownMenuItem onClick={async () => {
|
| 900 |
setPreviewAsset(asset);
|
| 901 |
setPreviewDialogOpen(true);
|
| 902 |
+
setPreviewError(null);
|
| 903 |
+
setIsLoadingPreview(true);
|
| 904 |
// Load PDF pages if it's a PDF
|
| 905 |
if (asset.type === 'document' && asset.name.toLowerCase().endsWith('.pdf')) {
|
| 906 |
await loadPdfPages(String(asset.id));
|
| 907 |
} else {
|
| 908 |
setPdfPages(null);
|
| 909 |
}
|
| 910 |
+
setIsLoadingPreview(false);
|
| 911 |
}}>
|
| 912 |
<Eye className="w-4 h-4 mr-2" /> Preview
|
| 913 |
</DropdownMenuItem>
|
|
|
|
| 987 |
<DropdownMenuItem onClick={async () => {
|
| 988 |
setPreviewAsset(asset);
|
| 989 |
setPreviewDialogOpen(true);
|
| 990 |
+
setPreviewError(null);
|
| 991 |
+
setIsLoadingPreview(true);
|
| 992 |
// Load PDF pages if it's a PDF
|
| 993 |
if (asset.type === 'document' && asset.name.toLowerCase().endsWith('.pdf')) {
|
| 994 |
await loadPdfPages(String(asset.id));
|
| 995 |
} else {
|
| 996 |
setPdfPages(null);
|
| 997 |
}
|
| 998 |
+
setIsLoadingPreview(false);
|
| 999 |
}}>
|
| 1000 |
<Eye className="w-4 h-4 mr-2" /> Preview
|
| 1001 |
</DropdownMenuItem>
|
|
|
|
| 1032 |
if (!open) {
|
| 1033 |
setPreviewAsset(null);
|
| 1034 |
setPdfPages(null);
|
| 1035 |
+
setPreviewError(null);
|
| 1036 |
}
|
| 1037 |
}}>
|
| 1038 |
<DialogContent className="max-w-6xl max-h-[90vh] flex flex-col">
|
|
|
|
| 1059 |
<div className="mt-4 flex-1 overflow-auto">
|
| 1060 |
{previewAsset && (
|
| 1061 |
<div className="space-y-4">
|
| 1062 |
+
{previewError ? (
|
| 1063 |
+
<div className="flex flex-col items-center justify-center p-12 bg-red-50 rounded-lg border border-red-200">
|
| 1064 |
+
<FileText className="w-16 h-16 text-red-400 mb-4" />
|
| 1065 |
+
<p className="text-red-600 font-medium mb-2">Failed to load preview</p>
|
| 1066 |
+
<p className="text-red-500 text-sm mb-4 text-center max-w-md">{previewError}</p>
|
| 1067 |
+
<p className="text-slate-600 text-xs mb-4 text-center max-w-md">
|
| 1068 |
+
The file may not exist in the database or on disk. You can try downloading it instead.
|
| 1069 |
+
</p>
|
| 1070 |
+
<Button
|
| 1071 |
+
onClick={() => window.open(`/api/assets/${String(previewAsset.id)}/download`, '_blank')}
|
| 1072 |
+
variant="outline"
|
| 1073 |
+
className="border-red-200 text-red-600 hover:bg-red-100"
|
| 1074 |
+
>
|
| 1075 |
+
<Download className="w-4 h-4 mr-2" />
|
| 1076 |
+
Download File
|
| 1077 |
+
</Button>
|
| 1078 |
+
</div>
|
| 1079 |
+
) : previewAsset.type === 'image' ? (
|
| 1080 |
+
<div className="relative">
|
| 1081 |
+
{isLoadingPreview && (
|
| 1082 |
+
<div className="absolute inset-0 flex items-center justify-center bg-slate-50 rounded-lg">
|
| 1083 |
+
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
|
| 1084 |
+
</div>
|
| 1085 |
+
)}
|
| 1086 |
+
<img
|
| 1087 |
+
src={`/api/assets/${String(previewAsset.id)}/download`}
|
| 1088 |
+
alt={previewAsset.name}
|
| 1089 |
+
className="max-w-full h-auto rounded-lg mx-auto"
|
| 1090 |
+
onLoad={() => setIsLoadingPreview(false)}
|
| 1091 |
+
onError={(e) => {
|
| 1092 |
+
setIsLoadingPreview(false);
|
| 1093 |
+
setPreviewError('Failed to load image. The file may not exist or may have been deleted.');
|
| 1094 |
+
e.target.style.display = 'none';
|
| 1095 |
+
}}
|
| 1096 |
+
/>
|
| 1097 |
+
</div>
|
| 1098 |
) : previewAsset.type === 'video' ? (
|
| 1099 |
+
<div className="relative">
|
| 1100 |
+
{isLoadingPreview && (
|
| 1101 |
+
<div className="absolute inset-0 flex items-center justify-center bg-slate-50 rounded-lg">
|
| 1102 |
+
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
|
| 1103 |
+
</div>
|
| 1104 |
+
)}
|
| 1105 |
+
<video
|
| 1106 |
+
src={`/api/assets/${String(previewAsset.id)}/download`}
|
| 1107 |
+
controls
|
| 1108 |
+
className="max-w-full rounded-lg mx-auto"
|
| 1109 |
+
onLoadedData={() => setIsLoadingPreview(false)}
|
| 1110 |
+
onError={(e) => {
|
| 1111 |
+
setIsLoadingPreview(false);
|
| 1112 |
+
setPreviewError('Failed to load video. The file may not exist or may have been deleted.');
|
| 1113 |
+
e.target.style.display = 'none';
|
| 1114 |
+
}}
|
| 1115 |
+
>
|
| 1116 |
+
Your browser does not support the video tag.
|
| 1117 |
+
</video>
|
| 1118 |
+
</div>
|
| 1119 |
) : previewAsset.type === 'document' && previewAsset.name.toLowerCase().endsWith('.pdf') ? (
|
| 1120 |
<div className="space-y-4">
|
| 1121 |
{isLoadingPdf ? (
|