refactor
This commit is contained in:
@@ -1,48 +0,0 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useEntryPointerHandler as useEntryPointerCore, isPointerModifierEvent, isPrimaryPointerEvent } from '../documents/useEntryPointer';
|
||||
|
||||
export const useEntryPointer = ({
|
||||
resolveDocumentRowKey,
|
||||
resolveFolderRowKey,
|
||||
onSelectDocument,
|
||||
onInspectDocument,
|
||||
onSelectFolder,
|
||||
}) => {
|
||||
const coreHandler = useEntryPointerCore({
|
||||
resolveDocumentRowKey,
|
||||
resolveFolderRowKey,
|
||||
onSelectDocument: (documentId, event, meta) => {
|
||||
const { modifierClick, primaryClick, rowKey } = meta;
|
||||
onSelectDocument(documentId, event, { modifierClick, primaryClick, rowKey });
|
||||
if (!modifierClick && primaryClick && typeof onInspectDocument === 'function') {
|
||||
onInspectDocument(documentId, meta);
|
||||
}
|
||||
},
|
||||
onSelectFolder,
|
||||
});
|
||||
|
||||
return useCallback((entry, event) => {
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
if (entry.type !== 'document') {
|
||||
coreHandler(entry, event);
|
||||
return;
|
||||
}
|
||||
|
||||
const modifierClick = isPointerModifierEvent(event);
|
||||
const primaryClick = isPrimaryPointerEvent(event);
|
||||
|
||||
onSelectDocument(entry.id, event, {
|
||||
modifierClick,
|
||||
primaryClick,
|
||||
rowKey: entry.key,
|
||||
});
|
||||
|
||||
if (!modifierClick && primaryClick) {
|
||||
onInspectDocument?.(entry.id, { modifierClick, primaryClick, rowKey: entry.key });
|
||||
}
|
||||
}, [coreHandler, onInspectDocument, onSelectDocument]);
|
||||
};
|
||||
|
||||
export default useEntryPointer;
|
||||
@@ -1,8 +1,4 @@
|
||||
export const clamp = (value, min, max) => {
|
||||
if (value < min) return min;
|
||||
if (value > max) return max;
|
||||
return value;
|
||||
};
|
||||
export { clamp } from '../utils/math';
|
||||
|
||||
export const formatTransform = (x, y, rotation = 0, scale = 1) =>
|
||||
`translate3d(${x}px, ${y}px, 0) rotate(${rotation}deg) scale(${scale})`;
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { ArrowLeftIcon, ArrowRightIcon } from '../ui/icons';
|
||||
import { clamp } from '../utils/math';
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
const clamp = (value, min, max) => {
|
||||
if (value < min) return min;
|
||||
if (value > max) return max;
|
||||
return value;
|
||||
};
|
||||
|
||||
const ensureDocumentRoot = () => {
|
||||
if (typeof document === 'undefined') {
|
||||
return null;
|
||||
|
||||
@@ -2,50 +2,13 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { EditIcon, IconX, PlusIcon } from '../ui/icons';
|
||||
import QuickAddMenu from '../ui/QuickAddMenu';
|
||||
import { getTagColorStyle } from '../utils/colors';
|
||||
import {
|
||||
formatDate,
|
||||
toDateInputValue,
|
||||
toIssuedTimestamp,
|
||||
} from '../utils/date';
|
||||
import { describeDocumentSummary } from './documentSummary';
|
||||
|
||||
const formatDate = (value) => {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return null;
|
||||
}
|
||||
return date.toLocaleDateString();
|
||||
};
|
||||
|
||||
const toDateInputValue = (value) => {
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return '';
|
||||
}
|
||||
const timezoneOffset = date.getTimezoneOffset();
|
||||
const localDate = new Date(date.getTime() - timezoneOffset * 60000);
|
||||
return localDate.toISOString().slice(0, 10);
|
||||
};
|
||||
|
||||
const toIssuedTimestamp = (dateString, fallback) => {
|
||||
if (!dateString) {
|
||||
return null;
|
||||
}
|
||||
const base = fallback ? new Date(fallback) : new Date();
|
||||
if (Number.isNaN(base.getTime())) {
|
||||
return null;
|
||||
}
|
||||
const [year, month, day] = dateString.split('-').map((part) => Number.parseInt(part, 10));
|
||||
if (!year || !month || !day) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const candidate = new Date(base);
|
||||
candidate.setUTCFullYear(year, month - 1, day);
|
||||
return candidate.toISOString();
|
||||
};
|
||||
|
||||
export const sortCorrespondents = (entries = []) =>
|
||||
entries
|
||||
.filter((entry) => entry && entry.name)
|
||||
@@ -257,7 +220,10 @@ const DocumentSummarySection = ({
|
||||
}
|
||||
return describeDocumentSummary(document);
|
||||
}, [document]);
|
||||
const issuedDateLabel = useMemo(() => formatDate(document?.issued_at), [document?.issued_at]);
|
||||
const issuedDateLabel = useMemo(
|
||||
() => formatDate(document?.issued_at, { fallback: null }),
|
||||
[document?.issued_at],
|
||||
);
|
||||
|
||||
const editableTitle = Boolean(document && onUpdateTitle);
|
||||
const editableIssued = Boolean(document && onUpdateIssued);
|
||||
|
||||
@@ -1,23 +1,13 @@
|
||||
import React from 'react';
|
||||
import { FolderIcon, CheckIcon, CloseIcon } from '../ui/icons';
|
||||
import { getTagColorStyle } from '../utils/colors';
|
||||
import { formatDate } from '../utils/date';
|
||||
import DocumentThumbnailImage from './DocumentThumbnailImage';
|
||||
import CorrespondentLinks from './CorrespondentLinks';
|
||||
import { resolveCorrespondents } from './correspondents';
|
||||
import { writeTagTransferData } from './tagTransfer';
|
||||
import useInlineRename from './useInlineRename';
|
||||
|
||||
const formatDate = (value) => {
|
||||
if (!value) {
|
||||
return "—";
|
||||
}
|
||||
const timestamp = Date.parse(value);
|
||||
if (Number.isNaN(timestamp)) {
|
||||
return "—";
|
||||
}
|
||||
return new Date(timestamp).toLocaleDateString();
|
||||
};
|
||||
|
||||
const DocumentsList = ({
|
||||
entries,
|
||||
focusedRowKey,
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
const formatDateTime = (value) => {
|
||||
if (!value) {
|
||||
return '—';
|
||||
}
|
||||
const date = new Date(value);
|
||||
return Number.isNaN(date.getTime()) ? '—' : date.toLocaleString();
|
||||
};
|
||||
import { formatDateTime } from '../utils/date';
|
||||
|
||||
export const buildDocumentMetadataItems = (document) => {
|
||||
if (!document) {
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
import { formatFileSize } from '../utils/format';
|
||||
|
||||
const defaultFormatDateTime = (value) => {
|
||||
if (!value) {
|
||||
return '—';
|
||||
}
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return '—';
|
||||
}
|
||||
return date.toLocaleString();
|
||||
};
|
||||
import { formatDateTime as defaultFormatDateTime } from '../utils/date';
|
||||
|
||||
const coercePageCount = (metadata) => {
|
||||
const raw = metadata?.page_count;
|
||||
|
||||
@@ -14,11 +14,12 @@ export const isPrimaryPointerEvent = (event) => {
|
||||
return type === 'click' || type === 'pointerdown' || type === 'pointerup';
|
||||
};
|
||||
|
||||
export const useEntryPointerHandler = ({
|
||||
export const useEntryPointer = ({
|
||||
resolveDocumentRowKey,
|
||||
resolveFolderRowKey,
|
||||
onSelectDocument,
|
||||
onSelectFolder,
|
||||
onInspectDocument,
|
||||
}) =>
|
||||
useCallback(
|
||||
(entry, event) => {
|
||||
@@ -39,16 +40,20 @@ export const useEntryPointerHandler = ({
|
||||
|
||||
const modifierClick = isPointerModifierEvent(event);
|
||||
const primaryClick = isPrimaryPointerEvent(event);
|
||||
const metadata = { modifierClick, primaryClick, rowKey };
|
||||
|
||||
if (type === 'document') {
|
||||
if (typeof onSelectDocument === 'function') {
|
||||
onSelectDocument(id, event, { modifierClick, primaryClick, rowKey });
|
||||
onSelectDocument(id, event, metadata);
|
||||
}
|
||||
if (!modifierClick && primaryClick && typeof onInspectDocument === 'function') {
|
||||
onInspectDocument(id, metadata);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof onSelectFolder === 'function') {
|
||||
onSelectFolder(id, event, { modifierClick, primaryClick, rowKey });
|
||||
onSelectFolder(id, event, metadata);
|
||||
}
|
||||
},
|
||||
[
|
||||
@@ -56,7 +61,8 @@ export const useEntryPointerHandler = ({
|
||||
resolveFolderRowKey,
|
||||
onSelectDocument,
|
||||
onSelectFolder,
|
||||
onInspectDocument,
|
||||
],
|
||||
);
|
||||
|
||||
export default useEntryPointerHandler;
|
||||
export default useEntryPointer;
|
||||
|
||||
@@ -12,7 +12,7 @@ import usePasskeys from '../../settings/usePasskeys';
|
||||
import { useManagementModals } from '../../app/useManagementModals';
|
||||
import { api, useAppDispatch, useAppState } from '../../app/appState';
|
||||
import useWorkspaceSelection from '../../app/useWorkspaceSelection';
|
||||
import { useEntryPointerHandler as useEntryPointerCore } from '../../documents/useEntryPointer';
|
||||
import { useEntryPointer as useEntryPointerCore } from '../../documents/useEntryPointer';
|
||||
import { isTagTransferEvent } from '../../documents/tagTransfer';
|
||||
import useDocumentsSelection from '../../documents/hooks/useDocumentsSelection';
|
||||
import useBulkDocumentActions from '../../documents/hooks/useBulkDocumentActions';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
const composeClassName = (base, extra) => (extra ? `${base} ${extra}` : base);
|
||||
import composeClassName from './classNames';
|
||||
|
||||
const PanelHeader = ({
|
||||
className = '',
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export const composeClassName = (base, extra) => (extra ? `${base} ${extra}` : base);
|
||||
|
||||
export default composeClassName;
|
||||
@@ -41,8 +41,7 @@ import {
|
||||
IconFileInfo,
|
||||
} from '@tabler/icons-react';
|
||||
import FolderSvg from '../assets/folder.svg';
|
||||
|
||||
const composeClassName = (base, extra) => (extra ? `${base} ${extra}` : base);
|
||||
import composeClassName from './classNames';
|
||||
|
||||
export const ChevronIcon = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||
<TablerChevronRight
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { clamp } from '../utils/math';
|
||||
|
||||
const DEFAULT_VIEWPORT_MARGIN = 8;
|
||||
|
||||
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
||||
|
||||
const resolveViewportWidth = () => {
|
||||
if (typeof window !== 'undefined' && typeof window.innerWidth === 'number') {
|
||||
return window.innerWidth;
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
const ensureDate = (value) => {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
const date = value instanceof Date ? new Date(value.getTime()) : new Date(value);
|
||||
return Number.isNaN(date.getTime()) ? null : date;
|
||||
};
|
||||
|
||||
export const formatDate = (value, { fallback = '—', locale, options } = {}) => {
|
||||
const date = ensureDate(value);
|
||||
if (!date) {
|
||||
return fallback;
|
||||
}
|
||||
return date.toLocaleDateString(locale, options);
|
||||
};
|
||||
|
||||
export const formatDateTime = (value, { fallback = '—', locale, options } = {}) => {
|
||||
const date = ensureDate(value);
|
||||
if (!date) {
|
||||
return fallback;
|
||||
}
|
||||
return date.toLocaleString(locale, options);
|
||||
};
|
||||
|
||||
export const toDateInputValue = (value) => {
|
||||
const date = ensureDate(value);
|
||||
if (!date) {
|
||||
return '';
|
||||
}
|
||||
const timezoneOffset = date.getTimezoneOffset();
|
||||
const localDate = new Date(date.getTime() - timezoneOffset * 60000);
|
||||
return localDate.toISOString().slice(0, 10);
|
||||
};
|
||||
|
||||
export const toIssuedTimestamp = (dateString, fallback) => {
|
||||
if (!dateString) {
|
||||
return null;
|
||||
}
|
||||
const base = ensureDate(fallback) || new Date();
|
||||
const [year, month, day] = dateString.split('-').map((part) => Number.parseInt(part, 10));
|
||||
if (!year || !month || !day) {
|
||||
return null;
|
||||
}
|
||||
const candidate = new Date(base);
|
||||
candidate.setUTCFullYear(year, month - 1, day);
|
||||
return Number.isNaN(candidate.getTime()) ? null : candidate.toISOString();
|
||||
};
|
||||
|
||||
export const parseDateValue = (value) => ensureDate(value);
|
||||
|
||||
export default {
|
||||
formatDate,
|
||||
formatDateTime,
|
||||
toDateInputValue,
|
||||
toIssuedTimestamp,
|
||||
parseDateValue,
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
export const clamp = (value, min, max) => {
|
||||
if (value < min) {
|
||||
return min;
|
||||
}
|
||||
if (value > max) {
|
||||
return max;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
export default {
|
||||
clamp,
|
||||
};
|
||||
Reference in New Issue
Block a user