refactor: unify document panel empty state rendering and view mode logic, adjust related styles
This commit is contained in:
@@ -1023,13 +1023,9 @@ function DesktopWorkspaceView({
|
||||
}}
|
||||
>
|
||||
{!allSizesReady ? (
|
||||
<div className="desk-empty">
|
||||
<div className="empty-state">
|
||||
<p>Loading previews…</p>
|
||||
</div>
|
||||
) : items.length === 0 ? (
|
||||
<div className="desk-empty">
|
||||
<p>No documents to show here yet. Drop files to make this space come alive.</p>
|
||||
</div>
|
||||
) : (
|
||||
items.map((doc, index) => {
|
||||
const sizeInfo = ensureDocumentSize(doc);
|
||||
|
||||
@@ -40,6 +40,37 @@ const defaultGetDocumentAsset = (_doc?: unknown, _type?: string) => null;
|
||||
|
||||
export type DocumentLinkLike = { url?: string | null; mimeType?: string | null };
|
||||
|
||||
export interface DocumentsListProps {
|
||||
entries: Array<{ type: string; id: Identifier; key: string; folder?: any; document?: any }>;
|
||||
draggingDocumentIdsSet: Set<Identifier>;
|
||||
draggedFolderId: Identifier | 'root' | null;
|
||||
onFolderClick: (folder: any, event: React.MouseEvent) => void;
|
||||
onFolderSelect?: (id: Identifier) => void;
|
||||
onFolderDragOver?: (event: React.DragEvent, folder: any) => void;
|
||||
onFolderDragLeave?: (event: React.DragEvent) => void;
|
||||
onFolderDrop?: (event: React.DragEvent, folder: any) => void;
|
||||
onFolderDragStart?: (event: React.DragEvent, folder: any) => void;
|
||||
onFolderDragEnd?: (event: React.DragEvent) => void;
|
||||
onDocumentClick: (doc: any, event: React.MouseEvent) => void;
|
||||
onDocumentActivate: (doc: any, event?: React.MouseEvent | KeyboardEvent) => void;
|
||||
onDocumentDragStart?: (event: React.DragEvent, doc: any) => void;
|
||||
onDocumentDragEnd?: (event: React.DragEvent) => void;
|
||||
onDocumentTagDragOver?: (event: React.DragEvent) => void;
|
||||
onDocumentTagDragLeave?: (event: React.DragEvent) => void;
|
||||
onDocumentTagDrop?: (event: React.DragEvent, docId: Identifier) => void;
|
||||
ensureAssetUrl?: any;
|
||||
getDocumentAsset?: any;
|
||||
tagLookupById?: any;
|
||||
onTagClick?: (tagId: Identifier) => void;
|
||||
scrollRef?: React.RefObject<HTMLElement>;
|
||||
onCorrespondentClick?: (correspondentId: Identifier) => void;
|
||||
activeCorrespondentIdSet?: Set<Identifier>;
|
||||
onDocumentRename?: (id: Identifier, name: string) => void;
|
||||
onFolderRename?: (id: Identifier, name: string) => void;
|
||||
focusedRowKey?: string | null;
|
||||
gridIconSize?: number;
|
||||
}
|
||||
|
||||
const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
|
||||
headerLeading = null,
|
||||
onBreadcrumbNavigate,
|
||||
@@ -706,116 +737,69 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
|
||||
() => entries.some((entry) => entry.type === EntryType.document),
|
||||
[entries],
|
||||
);
|
||||
const showTableRows = entries.length > 0;
|
||||
const showDefaultEmptyState = !showingSearchResults && !isFilterActive && entries.length === 0;
|
||||
const showListSearchEmptyState = showingSearchResults && !hasDocumentEntries && !isGridView && !isSearchLoading;
|
||||
const showGridSearchEmptyState = isGridView && showingSearchResults && !hasDocumentEntries && !isSearchLoading;
|
||||
const renderBody = () => {
|
||||
if (isDeskView) {
|
||||
return deskWorkspaceProps ? (
|
||||
<DesktopWorkspace {...deskWorkspaceProps} />
|
||||
) : (
|
||||
<div className="empty-state empty-state--global">
|
||||
Desk view is unavailable.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (showDefaultEmptyState) {
|
||||
const renderBody = () => {
|
||||
const hasEntries = entries.length > 0;
|
||||
const isSearchEmpty = (showingSearchResults || isFilterActive) && !hasDocumentEntries && !isSearchLoading;
|
||||
|
||||
if (isSearchEmpty) {
|
||||
return (
|
||||
<div className="empty-state">
|
||||
Drop files anywhere or onto a folder to upload documents.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (showGridSearchEmptyState) {
|
||||
return (
|
||||
<div className="empty-state empty-state--global">
|
||||
No documents match the current filters.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (showListSearchEmptyState) {
|
||||
return (
|
||||
<div className="empty-state">No documents match the current filters.</div>
|
||||
);
|
||||
if (!hasEntries) {
|
||||
<div className="empty-state">
|
||||
No documents to show here yet. Drop files to make this space come alive.
|
||||
</div>
|
||||
}
|
||||
|
||||
if (!showTableRows) {
|
||||
return null;
|
||||
}
|
||||
const listProps: DocumentsListProps = {
|
||||
entries,
|
||||
draggingDocumentIdsSet: draggingSet,
|
||||
draggedFolderId,
|
||||
onFolderClick: handleFolderClick,
|
||||
onFolderSelect,
|
||||
onFolderDragOver,
|
||||
onFolderDragLeave,
|
||||
onFolderDrop,
|
||||
onFolderDragStart,
|
||||
onFolderDragEnd,
|
||||
onDocumentClick: handleDocumentClick,
|
||||
onDocumentActivate: handleDocumentActivate,
|
||||
onDocumentDragStart: handleDocumentDragStartLocal,
|
||||
onDocumentDragEnd: handleDocumentDragEndLocal,
|
||||
onDocumentTagDragOver: handleDocumentTagDragOver,
|
||||
onDocumentTagDragLeave: handleDocumentTagDragLeave,
|
||||
onDocumentTagDrop: handleDocumentTagDrop,
|
||||
onDocumentRename,
|
||||
onFolderRename,
|
||||
ensureAssetUrl,
|
||||
getDocumentAsset,
|
||||
tagLookupById,
|
||||
onTagClick: toggleTagFilter,
|
||||
onCorrespondentClick: toggleCorrespondentFilter,
|
||||
activeCorrespondentIdSet: activeCorrespondentIdSet,
|
||||
scrollRef,
|
||||
focusedRowKey,
|
||||
gridIconSize,
|
||||
};
|
||||
|
||||
if (isGridView) {
|
||||
return (
|
||||
<DocumentsGrid
|
||||
entries={entries}
|
||||
draggingDocumentIdsSet={draggingSet}
|
||||
draggedFolderId={draggedFolderId}
|
||||
onFolderClick={handleFolderClick}
|
||||
onFolderSelect={onFolderSelect}
|
||||
onFolderDragOver={onFolderDragOver}
|
||||
onFolderDragLeave={onFolderDragLeave}
|
||||
onFolderDrop={onFolderDrop}
|
||||
onFolderDragStart={onFolderDragStart}
|
||||
onFolderDragEnd={onFolderDragEnd}
|
||||
onDocumentClick={handleDocumentClick}
|
||||
onDocumentActivate={handleDocumentActivate}
|
||||
onDocumentDragStart={handleDocumentDragStartLocal}
|
||||
onDocumentDragEnd={handleDocumentDragEndLocal}
|
||||
onDocumentTagDragOver={handleDocumentTagDragOver}
|
||||
onDocumentTagDragLeave={handleDocumentTagDragLeave}
|
||||
onDocumentTagDrop={onDocumentTagDrop}
|
||||
ensureAssetUrl={ensureAssetUrl}
|
||||
getDocumentAsset={getDocumentAsset}
|
||||
gridIconSize={gridIconSize}
|
||||
tagLookupById={tagLookupById}
|
||||
onTagClick={toggleTagFilter}
|
||||
scrollRef={scrollRef}
|
||||
onCorrespondentClick={toggleCorrespondentFilter}
|
||||
activeCorrespondentIdSet={activeCorrespondentIdSet}
|
||||
onDocumentRename={onDocumentRename}
|
||||
onFolderRename={onFolderRename}
|
||||
/>
|
||||
);
|
||||
switch (viewMode) {
|
||||
case 'desk':
|
||||
return <DesktopWorkspace {...deskWorkspaceProps} />;
|
||||
case 'grid':
|
||||
return <DocumentsGrid {...listProps} />;
|
||||
case 'list':
|
||||
default:
|
||||
return <DocumentsList {...listProps} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<DocumentsList
|
||||
entries={entries}
|
||||
focusedRowKey={focusedRowKey}
|
||||
draggingDocumentIdsSet={draggingSet}
|
||||
draggedFolderId={draggedFolderId}
|
||||
ensureAssetUrl={ensureAssetUrl}
|
||||
getDocumentAsset={getDocumentAsset}
|
||||
onFolderClick={handleFolderClick}
|
||||
onFolderSelect={onFolderSelect}
|
||||
onFolderDragOver={onFolderDragOver}
|
||||
onFolderDragLeave={onFolderDragLeave}
|
||||
onFolderDrop={onFolderDrop}
|
||||
onFolderDragStart={onFolderDragStart}
|
||||
onFolderDragEnd={onFolderDragEnd}
|
||||
onFolderRename={onFolderRename}
|
||||
onDocumentClick={handleDocumentClick}
|
||||
onDocumentActivate={handleDocumentActivate}
|
||||
onDocumentDragStart={handleDocumentDragStartLocal}
|
||||
onDocumentDragEnd={handleDocumentDragEndLocal}
|
||||
onDocumentTagDragOver={handleDocumentTagDragOver}
|
||||
onDocumentTagDragLeave={handleDocumentTagDragLeave}
|
||||
onDocumentTagDrop={handleDocumentTagDrop}
|
||||
onDocumentRename={onDocumentRename}
|
||||
tagLookupById={tagLookupById}
|
||||
onTagClick={toggleTagFilter}
|
||||
onCorrespondentClick={toggleCorrespondentFilter}
|
||||
activeCorrespondentIdSet={activeCorrespondentIdSet}
|
||||
scrollRef={scrollRef}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const panelVariant = isDeskView ? 'desk' : isGridView ? 'grid' : 'list';
|
||||
const shouldHandlePanelInteractions = !isDeskView && showTableRows;
|
||||
const shouldHandlePanelInteractions = !isDeskView && entries.length > 0;
|
||||
|
||||
const handleSectionFocus = useCallback((event: React.FocusEvent<HTMLElement>) => {
|
||||
if (!shouldHandlePanelInteractions || event.target !== event.currentTarget) {
|
||||
|
||||
@@ -467,8 +467,8 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.documents-panel tbody tr.document > *,
|
||||
.documents-panel tbody tr.folder > * {
|
||||
.documents-panel tbody tr.document>*,
|
||||
.documents-panel tbody tr.folder>* {
|
||||
height: var(--documents-list-row-height);
|
||||
}
|
||||
|
||||
@@ -762,28 +762,11 @@
|
||||
padding: 0.2rem 0.4rem;
|
||||
font-weight: 600;
|
||||
border: none;
|
||||
background: oklch(
|
||||
min(1, calc(var(--tag-chip-resolved-l) + (1 - var(--tag-chip-resolved-l)) * var(--tag-chip-bg-lighten)))
|
||||
calc(var(--tag-chip-resolved-c) * var(--tag-chip-bg-chroma-scale))
|
||||
var(--tag-chip-resolved-h)
|
||||
/ 0.9
|
||||
);
|
||||
--tag-chip-outline-color: var(
|
||||
--tag-chip-outline,
|
||||
oklch(
|
||||
min(1, calc(var(--tag-chip-resolved-l) + (1 - var(--tag-chip-resolved-l)) * var(--tag-chip-outline-lighten)))
|
||||
min(1, calc(var(--tag-chip-resolved-c) * var(--tag-chip-outline-chroma-scale)))
|
||||
var(--tag-chip-resolved-h)
|
||||
)
|
||||
);
|
||||
--tag-chip-text-color: var(
|
||||
--tag-chip-text,
|
||||
oklch(
|
||||
clamp(0, calc(var(--tag-chip-resolved-l) + var(--tag-chip-text-lighten)), 1)
|
||||
clamp(0, calc(var(--tag-chip-resolved-c) * var(--tag-chip-text-chroma-scale)), 1)
|
||||
var(--tag-chip-resolved-h)
|
||||
)
|
||||
);
|
||||
background: oklch(min(1, calc(var(--tag-chip-resolved-l) + (1 - var(--tag-chip-resolved-l)) * var(--tag-chip-bg-lighten))) calc(var(--tag-chip-resolved-c) * var(--tag-chip-bg-chroma-scale)) var(--tag-chip-resolved-h) / 0.9);
|
||||
--tag-chip-outline-color: var(--tag-chip-outline,
|
||||
oklch(min(1, calc(var(--tag-chip-resolved-l) + (1 - var(--tag-chip-resolved-l)) * var(--tag-chip-outline-lighten))) min(1, calc(var(--tag-chip-resolved-c) * var(--tag-chip-outline-chroma-scale))) var(--tag-chip-resolved-h)));
|
||||
--tag-chip-text-color: var(--tag-chip-text,
|
||||
oklch(clamp(0, calc(var(--tag-chip-resolved-l) + var(--tag-chip-text-lighten)), 1) clamp(0, calc(var(--tag-chip-resolved-c) * var(--tag-chip-text-chroma-scale)), 1) var(--tag-chip-resolved-h)));
|
||||
color: var(--tag-chip-text-color, currentColor);
|
||||
}
|
||||
|
||||
@@ -822,15 +805,11 @@
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
border: 1px dashed var(--border);
|
||||
border-radius: 0;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
padding: 1.1rem 0.9rem;
|
||||
color: var(--muted);
|
||||
margin-top: 0.75rem;
|
||||
background: var(--surface-subtle);
|
||||
}
|
||||
|
||||
.empty-state--global {
|
||||
border-style: solid;
|
||||
}
|
||||
}
|
||||
@@ -28,18 +28,7 @@
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.desk-empty {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 3rem;
|
||||
text-align: center;
|
||||
color: var(--muted);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
body.desk-cursor-remove,
|
||||
body.desk-cursor-remove * {
|
||||
cursor: not-allowed !important;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user