This commit is contained in:
2025-11-18 13:16:35 +01:00
parent 0b0a1a88fd
commit 0c37ef5578
20 changed files with 434 additions and 417 deletions
+68 -82
View File
@@ -9,7 +9,6 @@ import {
WarningIcon,
BottombarCollapseIcon,
BottombarExpandIcon,
ClearAllIcon,
} from '../ui/icons';
import PanelHeader from '../ui/PanelHeader';
@@ -86,11 +85,21 @@ const UploadQueueOverlay = ({ queue = [], onClearQueue }: UploadQueueOverlayProp
const hasActiveUploads = queue.some((item) => item.status === 'uploading' || item.status === 'pending');
const handleClearQueue = () => {
if (!onClearQueue || hasActiveUploads) {
const handleDismissOverlay = () => {
if (!queue.length) {
setDismissed(true);
return;
}
onClearQueue();
if (hasActiveUploads) {
const confirmed = window.confirm('Uploads are still running. Clear the queue and hide the overlay?');
if (!confirmed) {
return;
}
}
onClearQueue?.();
setDismissed(true);
};
if (!queue.length || dismissed) {
@@ -100,11 +109,10 @@ const UploadQueueOverlay = ({ queue = [], onClearQueue }: UploadQueueOverlayProp
return (
<div className={`upload-queue-overlay${collapsed ? ' upload-queue-overlay--collapsed' : ''}`}>
<PanelHeader
className="upload-queue-overlay__header"
title={(
<span className="upload-queue-overlay__title">
<span>
<span>Uploads</span>
<span className="upload-queue-overlay__summary">{summary}</span>
<span className="panel-header__subtitle">{summary}</span>
</span>
)}
actions={(
@@ -117,20 +125,11 @@ const UploadQueueOverlay = ({ queue = [], onClearQueue }: UploadQueueOverlayProp
>
{collapsed ? <BottombarExpandIcon size={16} /> : <BottombarCollapseIcon size={16} />}
</button>
<button
type="button"
className="icon-button ghost"
onClick={handleClearQueue}
disabled={hasActiveUploads || !queue.length}
aria-label="Clear completed uploads"
>
<ClearAllIcon size={16} />
</button>
<button
type="button"
className="icon-button"
onClick={() => setDismissed(true)}
aria-label="Hide upload queue"
onClick={handleDismissOverlay}
aria-label="Clear uploads and hide overlay"
>
<CloseIcon size={16} />
</button>
@@ -138,82 +137,69 @@ const UploadQueueOverlay = ({ queue = [], onClearQueue }: UploadQueueOverlayProp
)}
/>
{!collapsed ? (
<ul className="upload-queue-overlay__list">
{[...queue]
.slice()
.reverse()
.map((item) => {
const meta = STATUS_META[item.status] || STATUS_META.pending;
const fileLabel = item.name;
const duplicateLabel = item.status === 'duplicate' ? item.document?.title || null : null;
const documentId = item.document?.id || item.conflictDocumentId || null;
const hasLink = Boolean(documentId);
const handleNavigate = () => {
if (!documentId) {
return;
}
navigate(`/documents/${documentId}`);
};
return (
<li key={item.id} className={`upload-queue-overlay__item upload-queue-overlay__item--${item.status}`}>
<span className={`upload-queue-overlay__status upload-queue-overlay__status--${meta.tone}`}>
{meta.icon}
</span>
<div className="upload-queue-overlay__details">
{item.status === 'success' && hasLink ? (
<button
type="button"
className="upload-queue-overlay__name-link"
onClick={handleNavigate}
>
{fileLabel}
</button>
) : (
<div className="upload-queue-overlay__name">
{fileLabel}
</div>
)}
<div className="upload-queue-overlay__meta-line">
{item.status === 'duplicate' && duplicateLabel ? (
<span className="upload-queue-overlay__meta-duplicate">
Duplicate of{' '}
<div className="upload-queue-overlay__body">
<ul className="upload-queue-overlay__list">
{[...queue]
.slice()
.reverse()
.map((item) => {
const meta = STATUS_META[item.status] || STATUS_META.pending;
const fileLabel = item.name;
const documentTitle = item.document?.title || null;
const duplicateLabel = item.status === 'duplicate' ? documentTitle : null;
const documentId = item.document?.id || item.conflictDocumentId || null;
const hasLink = Boolean(documentId);
const handleNavigate = () => {
if (!documentId) {
return;
}
navigate(`/documents/${documentId}`);
};
return (
<li key={item.id} className={`upload-queue-overlay__item upload-queue-overlay__item--${item.status}`}>
<span className={`upload-queue-overlay__status upload-queue-overlay__status--${meta.tone}`}>
{meta.icon}
</span>
<div className="upload-queue-overlay__details">
{item.status === 'success' && hasLink ? (
<button
type="button"
className="upload-queue-overlay__meta-link"
className="upload-queue-overlay__name-link"
onClick={handleNavigate}
>
{duplicateLabel}
{fileLabel}
</button>
</span>
) : item.status === 'error' && item.error ? (
<span className="upload-queue-overlay__meta-error" title={item.error}>
{item.error}
</span>
) : (
<>
<span>{meta.label}</span>
{documentId ? (
<span className="upload-queue-overlay__meta-id">
(
) : (
<div className="upload-queue-overlay__name">
{fileLabel}
</div>
)}
<div className="upload-queue-overlay__meta-line">
{item.status === 'duplicate' && duplicateLabel ? (
<span className="upload-queue-overlay__meta-duplicate">
Duplicate of{' '}
<button
type="button"
className="upload-queue-overlay__meta-link"
onClick={handleNavigate}
disabled={!hasLink}
>
{documentId}
{duplicateLabel}
</button>
)
</span>
) : null}
</>
)}
</div>
</div>
</li>
);
})}
</ul>
) : item.status === 'error' && item.error ? (
<span className="upload-queue-overlay__meta-error" title={item.error}>
{item.error}
</span>
) : (
<span>{meta.label}</span>
)}
</div>
</div>
</li>
);
})}
</ul>
</div>
) : null}
</div>
);