Refactor: Add Open in New Tab for PDFs/Docs, upgrade details modal to 2-column lg, and enhance document cover thumbnails

This commit is contained in:
kenilkb 2026-07-15 18:23:19 +05:30
parent e7f50a6667
commit ea7d688f7c
3 changed files with 178 additions and 145 deletions

View File

@ -1,9 +1,7 @@
import React from 'react'; import React from 'react';
import { motion, AnimatePresence } from 'framer-motion'; import { motion, AnimatePresence } from 'framer-motion';
import { import {
Globe,
FileText, FileText,
Image as ImageIcon,
File, File,
Eye, Eye,
MoreVertical, MoreVertical,
@ -14,8 +12,7 @@ import {
ExternalLink, ExternalLink,
Download, Download,
Clock, Clock,
AlertCircle, AlertCircle
BookOpen
} from 'lucide-react'; } from 'lucide-react';
import type { Asset } from '../../../types/assets'; import type { Asset } from '../../../types/assets';
import type { User } from '../../../types/auth'; import type { User } from '../../../types/auth';
@ -69,13 +66,7 @@ export const AssetCard: React.FC<AssetCardProps> = ({
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}; };
const getAssetIcon = (type: string) => {
if (type === 'case_study') return BookOpen;
if (type === 'url') return Globe;
if (type.includes('pdf')) return FileText;
if (type.includes('image') || type.includes('png') || type.includes('jpg')) return ImageIcon;
return File;
};
const isRenderable = (type: string, url: string) => { const isRenderable = (type: string, url: string) => {
const isOffice = type.includes('word') || type.includes('presentation') || type.includes('sheet') || const isOffice = type.includes('word') || type.includes('presentation') || type.includes('sheet') ||
@ -104,7 +95,7 @@ export const AssetCard: React.FC<AssetCardProps> = ({
return resolvedUrl; return resolvedUrl;
}; };
const Icon = getAssetIcon(asset.type);
const isImage = asset.type.includes('image') || asset.type.includes('png') || asset.type.includes('jpg') || asset.url.match(/\.(png|jpe?g|gif|svg|webp)$/i); const isImage = asset.type.includes('image') || asset.type.includes('png') || asset.type.includes('jpg') || asset.url.match(/\.(png|jpe?g|gif|svg|webp)$/i);
const isPdf = asset.type.includes('pdf') || asset.url.toLowerCase().endsWith('.pdf'); const isPdf = asset.type.includes('pdf') || asset.url.toLowerCase().endsWith('.pdf');
@ -112,8 +103,8 @@ export const AssetCard: React.FC<AssetCardProps> = ({
const isPresentation = asset.type.includes('presentation') || asset.url.toLowerCase().endsWith('.pptx') || asset.url.toLowerCase().endsWith('.ppt'); const isPresentation = asset.type.includes('presentation') || asset.url.toLowerCase().endsWith('.pptx') || asset.url.toLowerCase().endsWith('.ppt');
const isSpreadsheet = asset.type.includes('sheet') || asset.url.toLowerCase().endsWith('.xlsx') || asset.url.toLowerCase().endsWith('.xls') || asset.url.toLowerCase().endsWith('.csv'); const isSpreadsheet = asset.type.includes('sheet') || asset.url.toLowerCase().endsWith('.xlsx') || asset.url.toLowerCase().endsWith('.xls') || asset.url.toLowerCase().endsWith('.csv');
const hasBanner = isImage || (asset.type === 'case_study' && !!asset.thumbnailUrl); const hasBanner = isImage || !!asset.thumbnailUrl;
const bannerSrc = (asset.type === 'case_study' && asset.thumbnailUrl) ? asset.thumbnailUrl : asset.url; const bannerSrc = asset.thumbnailUrl ? asset.thumbnailUrl : asset.url;
return ( return (
<motion.div <motion.div
@ -234,83 +225,95 @@ export const AssetCard: React.FC<AssetCardProps> = ({
/> />
) : null} ) : null}
{/* Fallbacks / simulated thumbnails */}
<div <div
id={`fallback-${asset.id}`} id={`fallback-${asset.id}`}
className="w-full h-full flex items-center justify-center" className="w-full h-full flex items-center justify-center bg-ink-50"
style={{ display: hasBanner ? 'none' : 'flex' }} style={{ display: hasBanner ? 'none' : 'flex' }}
> >
{isPdf ? ( {isPdf ? (
<div className="flex flex-col items-center justify-center w-full h-full p-4 relative"> <div className="flex flex-col items-center justify-center w-full h-full p-4 relative bg-red-500/[0.03] hover:bg-red-500/[0.06] transition-colors">
<div className="w-14 h-18 bg-ink-0 border border-ink-200 shadow-sm rounded flex flex-col justify-between p-1.5 relative overflow-hidden"> <div className="w-[105px] h-[135px] bg-ink-0 border border-red-500/20 shadow-md rounded-lg flex flex-col justify-between p-3 relative overflow-hidden transition-all duration-300 group-hover:scale-105">
<div className="absolute top-0 right-0 left-0 bg-red-600 text-ink-0 py-0.5 text-[8px] font-extrabold uppercase text-center tracking-wider"> <div className="absolute top-0 right-0 left-0 bg-red-600 text-ink-0 py-1 text-[8px] font-extrabold uppercase text-center tracking-wider font-sans">
PDF PDF Document
</div> </div>
<div className="space-y-1 mt-4"> <div className="space-y-1.5 mt-6 flex-grow pt-1">
<div className="h-1 bg-ink-200 rounded w-5/6" /> <div className="h-1 bg-ink-200 rounded w-11/12" />
<div className="h-1 bg-ink-200 rounded w-full" /> <div className="h-1 bg-ink-200 rounded w-full" />
<div className="h-1 bg-ink-200 rounded w-4/5" /> <div className="h-1 bg-ink-250 rounded w-10/12" />
<div className="h-1 bg-ink-200 rounded w-full" />
<div className="h-1 bg-ink-200 rounded w-3/4" />
</div> </div>
<div className="flex items-center justify-between text-[7px] text-ink-400 font-bold border-t border-ink-100 pt-0.5 mt-1"> <div className="flex items-center justify-between text-[7px] text-ink-400 font-bold border-t border-ink-100 pt-1 mt-1 font-sans">
<span>PDF</span> <span>PDF RESOURCE</span>
<FileText className="w-2.5 h-2.5 text-red-500" /> <FileText className="w-3 h-3 text-red-650" />
</div> </div>
</div> </div>
</div> </div>
) : isPresentation ? ( ) : isPresentation ? (
<div className="flex flex-col items-center justify-center w-full h-full p-4"> <div className="flex flex-col items-center justify-center w-full h-full p-4 bg-amber-500/[0.03] hover:bg-amber-500/[0.06] transition-colors">
<div className="w-18 h-13 bg-amber-500 border border-amber-600 shadow-sm rounded-lg flex flex-col justify-between p-1.5 relative overflow-hidden"> <div className="w-[125px] h-[90px] bg-amber-500 border border-amber-600 shadow-md rounded-lg flex flex-col justify-between p-2.5 relative overflow-hidden transition-all duration-300 group-hover:scale-105">
<div className="h-1.5 bg-ink-0/90 rounded w-3/4 mb-1" /> <div className="h-2 bg-ink-0/90 rounded w-3/4 mb-1" />
<div className="space-y-1"> <div className="space-y-1 flex-grow">
<div className="h-1 bg-ink-0/60 rounded w-full" /> <div className="h-1 bg-ink-0/60 rounded w-full" />
<div className="h-1 bg-ink-0/60 rounded w-5/6" /> <div className="h-1 bg-ink-0/60 rounded w-11/12" />
<div className="h-1 bg-ink-0/60 rounded w-10/12" />
</div> </div>
<div className="flex items-center justify-between text-[7px] text-ink-0/80 font-bold pt-0.5"> <div className="flex items-center justify-between text-[7px] text-ink-0/80 font-bold pt-1 border-t border-amber-400">
<span>SLIDE</span> <span>PRESENTATION</span>
<span className="font-extrabold">PPTX</span> <span className="font-extrabold uppercase">PPTX</span>
</div> </div>
</div> </div>
</div> </div>
) : isWord ? ( ) : isWord ? (
<div className="flex flex-col items-center justify-center w-full h-full p-4"> <div className="flex flex-col items-center justify-center w-full h-full p-4 bg-blue-500/[0.03] hover:bg-blue-500/[0.06] transition-colors">
<div className="w-14 h-18 bg-ink-0 border border-ink-200 shadow-sm rounded flex flex-col justify-between p-1.5 relative overflow-hidden"> <div className="w-[105px] h-[135px] bg-ink-0 border border-blue-500/20 shadow-md rounded-lg flex flex-col justify-between p-3 relative overflow-hidden transition-all duration-300 group-hover:scale-105">
<div className="absolute top-0 right-0 left-0 bg-blue-600 text-ink-0 py-0.5 text-[8px] font-extrabold uppercase text-center tracking-wider"> <div className="absolute top-0 right-0 left-0 bg-blue-600 text-ink-0 py-1 text-[8px] font-extrabold uppercase text-center tracking-wider font-sans">
DOC Word Doc
</div> </div>
<div className="space-y-1 mt-4"> <div className="space-y-1.5 mt-6 flex-grow pt-1">
<div className="h-1 bg-ink-200 rounded w-11/12" />
<div className="h-1 bg-ink-200 rounded w-full" /> <div className="h-1 bg-ink-200 rounded w-full" />
<div className="h-1 bg-ink-200 rounded w-5/6" /> <div className="h-1 bg-ink-250 rounded w-10/12" />
<div className="h-1 bg-ink-200 rounded w-full" /> <div className="h-1 bg-ink-200 rounded w-full" />
</div> </div>
<div className="flex items-center justify-between text-[7px] text-ink-400 font-bold border-t border-ink-100 pt-0.5 mt-1"> <div className="flex items-center justify-between text-[7px] text-ink-400 font-bold border-t border-ink-100 pt-1 mt-1 font-sans">
<span>WORD</span> <span>DOCX RESOURCE</span>
<FileText className="w-2.5 h-2.5 text-blue-500" /> <FileText className="w-3 h-3 text-blue-650" />
</div> </div>
</div> </div>
</div> </div>
) : isSpreadsheet ? ( ) : isSpreadsheet ? (
<div className="flex flex-col items-center justify-center w-full h-full p-4"> <div className="flex flex-col items-center justify-center w-full h-full p-4 bg-emerald-500/[0.03] hover:bg-emerald-500/[0.06] transition-colors">
<div className="w-16 h-13 bg-emerald-600 border border-emerald-700 shadow-sm rounded-lg flex flex-col justify-between p-1.5 relative overflow-hidden"> <div className="w-[115px] h-[90px] bg-ink-0 border border-emerald-500/20 shadow-md rounded-lg flex flex-col justify-between p-2 relative overflow-hidden transition-all duration-300 group-hover:scale-105">
<div className="grid grid-cols-3 gap-0.5 mt-0.5"> <div className="absolute top-0 right-0 left-0 bg-emerald-650 text-ink-0 py-1 text-[7px] font-extrabold uppercase text-center tracking-wider font-sans">
<div className="h-1.5 bg-ink-0/90 rounded-sm" /> Spreadsheet
<div className="h-1.5 bg-ink-0/70 rounded-sm" />
<div className="h-1.5 bg-ink-0/70 rounded-sm" />
<div className="h-1.5 bg-ink-0/60 rounded-sm" />
<div className="h-1.5 bg-ink-0/80 rounded-sm" />
<div className="h-1.5 bg-ink-0/60 rounded-sm" />
</div> </div>
<div className="flex items-center justify-between text-[7px] text-emerald-100 font-bold pt-0.5"> <div className="grid grid-cols-3 gap-1 mt-5 flex-grow pt-1">
<span>SHEET</span> <div className="h-2 bg-emerald-50 border border-emerald-100 rounded" />
<span className="font-extrabold">XLSX</span> <div className="h-2 bg-emerald-50 border border-emerald-100 rounded" />
<div className="h-2 bg-emerald-50 border border-emerald-100 rounded" />
<div className="h-2 bg-ink-50 border border-ink-100 rounded" />
<div className="h-2 bg-ink-50 border border-ink-100 rounded" />
<div className="h-2 bg-ink-50 border border-ink-100 rounded" />
</div>
<div className="flex items-center justify-between text-[7px] text-ink-400 font-bold border-t border-ink-100 pt-1 mt-1 font-sans">
<span>XLSX SHEET</span>
<span className="font-extrabold text-emerald-650 text-[6px]">EXCEL</span>
</div> </div>
</div> </div>
</div> </div>
) : ( ) : (
<div className="flex flex-col items-center justify-center w-full h-full p-4"> <div className="flex flex-col items-center justify-center w-full h-full p-4 bg-ink-500/[0.03] hover:bg-ink-500/[0.06] transition-colors">
<div className="w-12 h-12 rounded-xl bg-ink-100 border border-ink-200 flex items-center justify-center shadow-inner relative group-hover:scale-105 transition-transform"> <div className="w-[105px] h-[135px] bg-ink-0 border border-ink-200 shadow-md rounded-lg flex flex-col justify-between p-3 relative overflow-hidden transition-all duration-300 group-hover:scale-105">
<Icon className="w-6 h-6 text-ink-650" /> <div className="absolute top-0 right-0 left-0 bg-ink-700 text-ink-0 py-1 text-[8px] font-extrabold uppercase text-center tracking-wider font-sans">
<div className="absolute -bottom-1 -right-1 bg-ink-800 border border-ink-700 rounded px-1 py-0.5 text-[7px] font-bold text-ink-0 uppercase"> Resource File
{asset.type === 'case_study' ? 'CASE STUDY' : asset.type === 'url' ? 'LINK' : 'FILE'} </div>
<div className="flex-grow flex items-center justify-center pt-4">
<File className="w-8 h-8 text-ink-400" />
</div>
<div className="flex items-center justify-between text-[7px] text-ink-400 font-bold border-t border-ink-100 pt-1 mt-1 font-sans">
<span>BINARY</span>
<span className="font-extrabold uppercase text-[6px]">{asset.type.split('/').pop() || 'FILE'}</span>
</div> </div>
</div> </div>
</div> </div>

View File

@ -30,7 +30,7 @@ export const AssetDetailsModal: React.FC<AssetDetailsModalProps> = ({
isOpen={isOpen && !!asset} isOpen={isOpen && !!asset}
onClose={onClose} onClose={onClose}
title="Asset Details" title="Asset Details"
size="md" size="2xl"
footer={ footer={
<Button <Button
onClick={onClose} onClick={onClose}
@ -42,101 +42,107 @@ export const AssetDetailsModal: React.FC<AssetDetailsModalProps> = ({
} }
> >
{asset && ( {asset && (
<div className="space-y-4 text-xs font-medium text-ink-900"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 text-xs font-medium text-ink-900">
<div> {/* Left Column */}
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">Title</h4> <div className="space-y-4">
<p className="text-sm font-extrabold text-ink-900 mt-1 font-sans">{asset.title}</p>
</div>
{asset.description && (
<div> <div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">Description</h4> <h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">Title</h4>
<p className="text-ink-700 mt-1 leading-relaxed font-sans">{asset.description}</p> <p className="text-sm font-extrabold text-ink-900 mt-1 font-sans">{asset.title}</p>
</div> </div>
)}
{asset.type === 'case_study' && asset.thumbnailUrl && ( {asset.description && (
<div> <div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans mb-1.5">Banner Image</h4> <h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">Description</h4>
<div className="w-full h-40 rounded-lg overflow-hidden border border-ink-200 shadow-sm bg-ink-50"> <p className="text-ink-700 mt-1 leading-relaxed font-sans">{asset.description}</p>
<img </div>
src={asset.thumbnailUrl} )}
alt="Case Study Banner"
className="w-full h-full object-cover" {(asset.type === 'case_study' || asset.thumbnailUrl) && asset.thumbnailUrl && (
/> <div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans mb-1.5">Banner Image</h4>
<div className="w-full h-44 rounded-lg overflow-hidden border border-ink-200 shadow-sm bg-ink-50">
<img
src={asset.thumbnailUrl}
alt="Asset Banner"
className="w-full h-full object-cover"
/>
</div>
</div>
)}
<div className="grid grid-cols-2 gap-4">
<div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">Category</h4>
<p className="text-ink-900 mt-1 font-bold font-sans">{asset.categoryId || 'General'}</p>
</div>
<div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">Subcategory</h4>
<p className="text-ink-900 mt-1 font-bold font-sans">{asset.subcategory || '-'}</p>
</div> </div>
</div> </div>
)}
{asset.type === 'case_study' && asset.problemStatement && ( <div className="grid grid-cols-2 gap-4">
<div> <div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-red-600 font-sans mb-1">Problem / Challenge</h4> <h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">File Size</h4>
<p className="text-ink-700 leading-relaxed font-sans whitespace-pre-wrap text-xs bg-red-500/[0.02] border border-red-500/10 p-3 rounded-lg shadow-sm"> <p className="text-ink-900 mt-1 font-bold font-sans">{asset.type === 'url' ? 'N/A' : formatBytes(asset.size)}</p>
{asset.problemStatement} </div>
</p> <div>
</div> <h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">File Type</h4>
)} <p className="text-ink-900 mt-1 font-bold font-sans">{asset.type}</p>
{asset.type === 'case_study' && asset.solution && (
<div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-emerald-650 font-sans mb-1">Suggested Solution</h4>
<p className="text-ink-700 leading-relaxed font-sans whitespace-pre-wrap text-xs bg-emerald-500/[0.02] border border-emerald-500/10 p-3 rounded-lg shadow-sm">
{asset.solution}
</p>
</div>
)}
<div className="grid grid-cols-2 gap-4">
<div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">Category</h4>
<p className="text-ink-900 mt-1 font-bold font-sans">{asset.categoryId || 'General'}</p>
</div>
<div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">Subcategory</h4>
<p className="text-ink-900 mt-1 font-bold font-sans">{asset.subcategory || '-'}</p>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">File Size</h4>
<p className="text-ink-900 mt-1 font-bold font-sans">{asset.type === 'url' ? 'N/A' : formatBytes(asset.size)}</p>
</div>
<div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">File Type</h4>
<p className="text-ink-900 mt-1 font-bold font-sans">{asset.type}</p>
</div>
</div>
{asset.tags.length > 0 && (
<div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">Tags</h4>
<div className="flex flex-wrap gap-1.5 mt-1.5">
{asset.tags.map(tag => (
<span key={tag} className="px-2 py-0.5 rounded bg-ink-50 border border-ink-200 text-[10px] font-bold text-ink-600 font-sans">
{tag}
</span>
))}
</div> </div>
</div> </div>
)} </div>
{userRole === 'ADMIN' && asset.sharedWith && ( {/* Right Column */}
<div> <div className="space-y-4">
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">Shared With</h4> {asset.type === 'case_study' && asset.problemStatement && (
<div className="flex flex-wrap gap-1.5 mt-1.5"> <div>
{asset.sharedWith.length === 0 ? ( <h4 className="text-[10px] font-bold uppercase tracking-wider text-red-650 font-sans mb-1.5">Problem / Challenge</h4>
<span className="text-ink-500 font-semibold italic font-sans">Not shared with any organization</span> <p className="text-ink-700 leading-relaxed font-sans whitespace-pre-wrap text-xs bg-red-500/[0.02] border border-red-500/10 p-3 rounded-lg shadow-sm">
) : ( {asset.problemStatement}
asset.sharedWith.map(sw => ( </p>
<span key={sw.userId ? `${sw.organizationId}-${sw.userId}` : sw.organizationId} className="px-2 py-0.5 rounded bg-ink-900 text-ink-0 text-[10px] font-bold font-sans"> </div>
{sw.organization?.name || 'Unknown Organization'} {sw.user ? `(${sw.user.email})` : '(Entire Org)'} )}
{asset.type === 'case_study' && asset.solution && (
<div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-emerald-650 font-sans mb-1.5">Suggested Solution</h4>
<p className="text-ink-700 leading-relaxed font-sans whitespace-pre-wrap text-xs bg-emerald-500/[0.02] border border-emerald-500/10 p-3 rounded-lg shadow-sm">
{asset.solution}
</p>
</div>
)}
{asset.tags.length > 0 && (
<div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">Tags</h4>
<div className="flex flex-wrap gap-1.5 mt-1.5">
{asset.tags.map(tag => (
<span key={tag} className="px-2 py-0.5 rounded bg-ink-50 border border-ink-200 text-[10px] font-bold text-ink-600 font-sans">
{tag}
</span> </span>
)) ))}
)} </div>
</div> </div>
</div> )}
)}
{userRole === 'ADMIN' && asset.sharedWith && (
<div>
<h4 className="text-[10px] font-bold uppercase tracking-wider text-ink-500 font-sans">Shared With</h4>
<div className="flex flex-wrap gap-1.5 mt-1.5">
{asset.sharedWith.length === 0 ? (
<span className="text-ink-500 font-semibold italic font-sans">Not shared with any organization</span>
) : (
asset.sharedWith.map(sw => (
<span key={sw.userId ? `${sw.organizationId}-${sw.userId}` : sw.organizationId} className="px-2 py-0.5 rounded bg-ink-900 text-ink-0 text-[10px] font-bold font-sans">
{sw.organization?.name || 'Unknown Organization'} {sw.user ? `(${sw.user.email})` : '(Entire Org)'}
</span>
))
)}
</div>
</div>
)}
</div>
</div> </div>
)} )}
</Modal> </Modal>

View File

@ -229,6 +229,30 @@ export const AssetViewerModal: React.FC<AssetViewerModalProps> = ({
Close Preview Close Preview
</Button> </Button>
{asset && (user?.role === 'ADMIN' || asset.isDownloadable || asset.downloadRequests?.[0]?.status === 'APPROVED') && (
<Button
onClick={() => {
const url = getFullAssetUrl(asset.url);
const isOffice = asset.type.includes('word') || asset.type.includes('presentation') || asset.type.includes('sheet') ||
asset.url.toLowerCase().endsWith('.docx') || asset.url.toLowerCase().endsWith('.doc') ||
asset.url.toLowerCase().endsWith('.pptx') || asset.url.toLowerCase().endsWith('.ppt') ||
asset.url.toLowerCase().endsWith('.xlsx') || asset.url.toLowerCase().endsWith('.xls');
if (isOffice && !isLocalUrl(asset.url)) {
window.open(`https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`, '_blank');
} else {
window.open(url, '_blank');
}
}}
variant="secondary"
size="sm"
className="flex items-center gap-2"
>
<ExternalLink className="w-4 h-4" />
<span>Open in New Tab</span>
</Button>
)}
{asset && asset.type !== 'url' && (user?.role === 'ADMIN' || asset.isDownloadable || asset.downloadRequests?.[0]?.status === 'APPROVED') && ( {asset && asset.type !== 'url' && (user?.role === 'ADMIN' || asset.isDownloadable || asset.downloadRequests?.[0]?.status === 'APPROVED') && (
<Button <Button
onClick={() => onDownload(asset)} onClick={() => onDownload(asset)}