Refactor: Add metadata and thumbnail scraping to External URL tab

This commit is contained in:
kenilkb 2026-07-15 14:57:45 +05:30
parent c9ec1296a6
commit e7f50a6667
2 changed files with 96 additions and 34 deletions

View File

@ -271,35 +271,58 @@ export const AssetViewerModal: React.FC<AssetViewerModalProps> = ({
</div>
</div>
) : asset.type === 'url' ? (
<div className="text-center p-12 max-w-md space-y-4 flex flex-col justify-center items-center">
<div className="w-16 h-16 rounded-2xl bg-ink-100 border border-ink-200 flex items-center justify-center text-ink-900 shadow-sm">
<Globe className="w-8 h-8" />
<div className="w-full h-full flex flex-col min-h-0 bg-ink-0">
<div className="bg-ink-100 px-4 py-2 border-b border-ink-200 flex justify-between items-center text-xs text-ink-600 font-bold select-none shrink-0">
<span className="flex items-center gap-1.5">
<Globe className="w-4 h-4 text-ink-950" />
<span className="font-sans">External Web Link Preview</span>
</span>
<span className="text-[10px] text-ink-400 font-mono font-normal truncate max-w-xs">{asset.url}</span>
</div>
<div>
<h4 className="text-sm font-bold text-ink-900 font-sans">External Resource Portal</h4>
<p className="text-xs text-ink-500 mt-2 leading-relaxed font-sans">
This asset points to an external destination outside of the local CDN container.
</p>
<div className="bg-ink-100 border border-ink-200 rounded-xl px-4 py-2 text-xs font-mono text-ink-600 truncate mt-3 max-w-sm">
{asset.url}
<div className="flex-1 overflow-auto p-6 md:p-12 flex items-center justify-center bg-ink-50">
<div className="bg-ink-0 border border-ink-200 rounded-2xl p-6 shadow-xl max-w-xl w-full flex flex-col items-center text-center space-y-5">
{asset.thumbnailUrl ? (
<div className="w-full h-48 border border-ink-100 rounded-xl overflow-hidden shadow-sm shrink-0">
<img
src={asset.thumbnailUrl}
alt="Web Preview Banner"
className="w-full h-full object-cover"
/>
</div>
) : (
<div className="w-16 h-16 rounded-2xl bg-ink-50 border border-ink-200 flex items-center justify-center text-ink-900 shadow-sm shrink-0">
<Globe className="w-8 h-8 text-ink-500" />
</div>
)}
<div className="space-y-2 w-full">
<h3 className="text-base font-extrabold text-ink-950 font-sans leading-snug">{asset.title}</h3>
{asset.description ? (
<p className="text-xs text-ink-500 font-sans leading-relaxed px-4">{asset.description}</p>
) : (
<p className="text-xs text-ink-400 font-sans italic leading-relaxed">No description provided for this external link.</p>
)}
</div>
<div className="w-full pt-2 px-4">
{(user?.role === 'ADMIN' || asset.isDownloadable || asset.downloadRequests?.[0]?.status === 'APPROVED') ? (
<a
href={asset.url}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center justify-center gap-2 px-6 py-2.5 rounded-xl bg-ink-900 text-ink-0 text-xs font-bold hover:bg-ink-850 transition-all hover:scale-[1.02] active:scale-95 shadow-md w-full font-sans cursor-pointer"
>
<span>Open Website in New Tab</span>
<ExternalLink className="w-4 h-4" />
</a>
) : (
<div className="bg-amber-50 border border-amber-200 text-amber-900 rounded-xl p-4 text-xs font-medium text-center font-sans">
Access Restricted: You must request and receive approval from the Administrator to open this external link.
</div>
)}
</div>
</div>
</div>
{(user?.role === 'ADMIN' || asset.isDownloadable || asset.downloadRequests?.[0]?.status === 'APPROVED') ? (
<a
href={asset.url}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center justify-center gap-2 px-6 py-2.5 rounded-lg bg-ink-900 text-ink-0 text-xs font-bold hover:bg-ink-800 transition-all shadow-sm w-full font-sans"
>
<span>Open Link in New Tab</span>
<ExternalLink className="w-4 h-4" />
</a>
) : (
<div className="bg-amber-50 border border-amber-205 text-amber-900 rounded-xl p-4 text-xs text-center font-medium max-w-sm font-sans">
Access Restricted: You must request and receive download approval from the Administrator to open this resource link.
</div>
)}
</div>
) : asset.type.includes('pdf') ? (
<div className="w-full h-full flex flex-col min-h-0">

View File

@ -95,6 +95,30 @@ export const UploadAssetModal: React.FC<UploadAssetModalProps> = ({
}
};
const handleFetchUrlDetails = async () => {
if (!uploadUrl) {
error('URL Required', 'Please enter a URL first.');
return;
}
if (!uploadUrl.startsWith('http')) {
error('Invalid URL', 'Please enter a valid URL starting with http:// or https://');
return;
}
setIsScraping(true);
try {
const data = await scrapeCaseStudy(uploadUrl);
setUploadTitle(data.title);
setThumbnailUrl(data.thumbnailUrl || '');
success('Page Details Fetched', 'Title and banner image successfully retrieved.');
} catch (err: any) {
console.error('Failed to scrape URL details', err);
error('Failed to retrieve page details', err.response?.data?.error || 'Make sure the URL is accessible.');
} finally {
setIsScraping(false);
}
};
const formatBytes = (bytes: number, decimals = 2) => {
if (bytes === 0) return '0 Bytes';
const k = 1024;
@ -318,14 +342,29 @@ export const UploadAssetModal: React.FC<UploadAssetModalProps> = ({
) : uploadTab === 'url' ? (
<div>
<label className="text-xs font-semibold text-ink-500 mb-1.5 block">External Asset URL</label>
<input
type="url"
value={uploadUrl}
onChange={(e) => setUploadUrl(e.target.value)}
placeholder="https://example.com/partner-docs"
required={uploadTab === 'url'}
className="w-full bg-ink-50 border border-ink-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ink-900/10 text-ink-900 placeholder-ink-400"
/>
<div className="flex gap-2">
<input
type="url"
value={uploadUrl}
onChange={(e) => setUploadUrl(e.target.value)}
placeholder="https://example.com/partner-docs"
required={uploadTab === 'url'}
className="flex-1 bg-ink-50 border border-ink-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ink-900/10 text-ink-900 placeholder-ink-400"
/>
<Button
type="button"
onClick={handleFetchUrlDetails}
disabled={isScraping || !uploadUrl}
variant="primary"
size="sm"
className="flex-shrink-0"
>
{isScraping ? 'Fetching...' : 'Fetch Details'}
</Button>
</div>
<span className="text-[10px] text-ink-450 mt-1 block">
Fetches title and thumbnail banner image from the target webpage automatically.
</span>
</div>
) : (
<div className="space-y-4">