stuff
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import React from 'react';
|
||||
import { FolderIcon } from '../ui/icons';
|
||||
import { FolderIcon, CheckIcon, CloseIcon } from '../ui/icons';
|
||||
import DocumentThumbnailImage from './DocumentThumbnailImage';
|
||||
import CorrespondentLinks from './CorrespondentLinks';
|
||||
import { getTagColorStyle } from '../utils/colors';
|
||||
import { resolveCorrespondents } from './correspondents';
|
||||
import { writeTagTransferData } from './tagTransfer';
|
||||
import useInlineRename from './useInlineRename';
|
||||
|
||||
const DocumentsGrid = ({
|
||||
entries,
|
||||
@@ -35,7 +36,42 @@ const DocumentsGrid = ({
|
||||
onCorrespondentClick,
|
||||
activeCorrespondentIdSet,
|
||||
onClearSelection,
|
||||
}) => (
|
||||
onDocumentRename,
|
||||
onFolderRename,
|
||||
}) => {
|
||||
const {
|
||||
editingId: editingDocumentId,
|
||||
draftValue: documentDraft,
|
||||
setDraftValue: setDocumentDraft,
|
||||
beginEditing: beginDocumentEditing,
|
||||
cancelEditing: cancelDocumentEditing,
|
||||
submitEditing: submitDocumentEditing,
|
||||
savingId: savingDocumentId,
|
||||
attachInputRef: attachDocumentInputRef,
|
||||
} = useInlineRename(onDocumentRename, {
|
||||
getCurrentValue: (doc) => doc?.title ?? '',
|
||||
getEntityId: (doc) => doc?.id ?? null,
|
||||
});
|
||||
|
||||
const {
|
||||
editingId: editingFolderId,
|
||||
draftValue: folderDraft,
|
||||
setDraftValue: setFolderDraft,
|
||||
beginEditing: beginFolderEditing,
|
||||
cancelEditing: cancelFolderEditing,
|
||||
submitEditing: submitFolderEditing,
|
||||
savingId: savingFolderId,
|
||||
attachInputRef: attachFolderInputRef,
|
||||
} = useInlineRename(onFolderRename, {
|
||||
getCurrentValue: (folder) => folder?.name ?? '',
|
||||
getEntityId: (folder) => folder?.id ?? null,
|
||||
});
|
||||
|
||||
const documentSelectionCount = selectedDocumentIdsSet?.size ?? 0;
|
||||
const folderSelectionCount = selectedFolderIdsSet?.size ?? 0;
|
||||
const totalSelectionCount = documentSelectionCount + folderSelectionCount;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="documents-grid"
|
||||
role="list"
|
||||
@@ -58,6 +94,14 @@ const DocumentsGrid = ({
|
||||
const classes = ['document-card', 'folder-card'];
|
||||
if (isDraggingFolder) classes.push('is-dragging');
|
||||
if (isSelectedFolder) classes.push('selected');
|
||||
const canRenameFolder = folder.id !== 'root' && typeof onFolderRename === 'function';
|
||||
const isFolderEditing = editingFolderId === folder.id;
|
||||
const folderDraftValue = isFolderEditing ? folderDraft : folder.name;
|
||||
const trimmedFolderDraft = isFolderEditing ? folderDraft.trim() : '';
|
||||
const isFolderSaving = savingFolderId === folder.id;
|
||||
const canSubmitFolder =
|
||||
isFolderEditing && trimmedFolderDraft.length > 0 && trimmedFolderDraft !== folder.name;
|
||||
const allowInlineFolderEdit = canRenameFolder && isSelectedFolder && totalSelectionCount === 1;
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -89,9 +133,83 @@ const DocumentsGrid = ({
|
||||
<FolderIcon className="folder-card__icon-svg" size={gridIconSize} />
|
||||
</div>
|
||||
<div className="folder-card__meta">
|
||||
<div className="folder-card__name" title={folder.name}>
|
||||
{folder.name}
|
||||
</div>
|
||||
{isFolderEditing ? (
|
||||
<div className="folder-card__edit doc-title-edit">
|
||||
<input
|
||||
type="text"
|
||||
ref={attachFolderInputRef}
|
||||
value={folderDraftValue}
|
||||
onChange={(event) => setFolderDraft(event.target.value)}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
submitFolderEditing(folder);
|
||||
} else if (event.key === 'Escape') {
|
||||
event.preventDefault();
|
||||
cancelFolderEditing(event);
|
||||
}
|
||||
}}
|
||||
onBlur={(event) => {
|
||||
const nextFocus = event.relatedTarget;
|
||||
if (!nextFocus || !event.currentTarget.parentElement?.contains(nextFocus)) {
|
||||
cancelFolderEditing();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="icon-button"
|
||||
aria-label="Save name"
|
||||
title="Save name"
|
||||
disabled={!canSubmitFolder || isFolderSaving}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
submitFolderEditing(folder);
|
||||
}}
|
||||
>
|
||||
<CheckIcon />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="icon-button"
|
||||
aria-label="Cancel"
|
||||
title="Cancel"
|
||||
onClick={(event) => cancelFolderEditing(event)}
|
||||
>
|
||||
<CloseIcon />
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="folder-card__label-row">
|
||||
<span
|
||||
className="folder-card__name"
|
||||
title={folder.name}
|
||||
role={allowInlineFolderEdit ? 'button' : undefined}
|
||||
tabIndex={allowInlineFolderEdit ? 0 : undefined}
|
||||
onClick={(event) => {
|
||||
if (!allowInlineFolderEdit) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
beginFolderEditing(folder);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (!allowInlineFolderEdit) {
|
||||
return;
|
||||
}
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
beginFolderEditing(folder);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{folder.name}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -111,6 +229,13 @@ const DocumentsGrid = ({
|
||||
const cardClasses = ['document-card', 'document'];
|
||||
if (isSelected) cardClasses.push('selected');
|
||||
if (isDraggingDoc) cardClasses.push('is-dragging');
|
||||
const isEditingDoc = editingDocumentId === doc.id;
|
||||
const documentDraftValue = isEditingDoc ? documentDraft : doc.title;
|
||||
const trimmedDocumentDraft = isEditingDoc ? documentDraft.trim() : '';
|
||||
const isDocumentSaving = savingDocumentId === doc.id;
|
||||
const canSubmitDocument =
|
||||
isEditingDoc && trimmedDocumentDraft.length > 0 && trimmedDocumentDraft !== doc.title;
|
||||
const allowInlineDocumentEdit = onDocumentRename && isSelected && totalSelectionCount === 1;
|
||||
return (
|
||||
<div
|
||||
key={entry.key}
|
||||
@@ -149,7 +274,82 @@ const DocumentsGrid = ({
|
||||
/>
|
||||
</span>
|
||||
) : null}
|
||||
<span className="doc-name__primary">{doc.title}</span>
|
||||
{isEditingDoc ? (
|
||||
<div className="document-card__title-edit doc-title-edit">
|
||||
<input
|
||||
type="text"
|
||||
ref={attachDocumentInputRef}
|
||||
value={documentDraftValue}
|
||||
onChange={(event) => setDocumentDraft(event.target.value)}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
submitDocumentEditing(doc);
|
||||
} else if (event.key === 'Escape') {
|
||||
event.preventDefault();
|
||||
cancelDocumentEditing(event);
|
||||
}
|
||||
}}
|
||||
onBlur={(event) => {
|
||||
const nextFocus = event.relatedTarget;
|
||||
if (!nextFocus || !event.currentTarget.parentElement?.contains(nextFocus)) {
|
||||
cancelDocumentEditing();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="icon-button"
|
||||
aria-label="Save title"
|
||||
title="Save title"
|
||||
disabled={!canSubmitDocument || isDocumentSaving}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
submitDocumentEditing(doc);
|
||||
}}
|
||||
>
|
||||
<CheckIcon />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="icon-button"
|
||||
aria-label="Cancel"
|
||||
title="Cancel"
|
||||
onClick={(event) => cancelDocumentEditing(event)}
|
||||
>
|
||||
<CloseIcon />
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="document-card__title-row">
|
||||
<span
|
||||
className="document-card__title-badge"
|
||||
role={allowInlineDocumentEdit ? 'button' : undefined}
|
||||
tabIndex={allowInlineDocumentEdit ? 0 : undefined}
|
||||
onClick={(event) => {
|
||||
if (!allowInlineDocumentEdit) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
beginDocumentEditing(doc);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (!allowInlineDocumentEdit) {
|
||||
return;
|
||||
}
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
beginDocumentEditing(doc);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{doc.title}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{visibleTags.length > 0 && (
|
||||
<div className="document-card__tags">
|
||||
@@ -204,6 +404,7 @@ const DocumentsGrid = ({
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
export default DocumentsGrid;
|
||||
|
||||
Reference in New Issue
Block a user