cleanup
This commit is contained in:
@@ -17,7 +17,7 @@ function CorrespondentsPanel({
|
|||||||
|
|
||||||
const startEdit = useCallback((correspondent) => {
|
const startEdit = useCallback((correspondent) => {
|
||||||
setEditingId(correspondent.id);
|
setEditingId(correspondent.id);
|
||||||
setDraftName(correspondent.name || '');
|
setDraftName(correspondent.name);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const cancelEdit = useCallback(() => {
|
const cancelEdit = useCallback(() => {
|
||||||
|
|||||||
@@ -30,12 +30,9 @@ const derivePreviewOrientation = (metadata) => {
|
|||||||
|
|
||||||
const sortCorrespondents = (entries = []) =>
|
const sortCorrespondents = (entries = []) =>
|
||||||
entries
|
entries
|
||||||
.map((entry) => ({
|
.filter((entry) => entry && entry.name)
|
||||||
id: entry.id,
|
.map(({ id, name, count }) => ({ id, name, count }))
|
||||||
name: entry.name || '',
|
.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
count: entry.count,
|
|
||||||
}))
|
|
||||||
.sort((a, b) => (a.name || '').localeCompare(b.name || ''));
|
|
||||||
|
|
||||||
const resolveDocumentType = (doc) => {
|
const resolveDocumentType = (doc) => {
|
||||||
if (!doc) {
|
if (!doc) {
|
||||||
@@ -46,15 +43,8 @@ const resolveDocumentType = (doc) => {
|
|||||||
if (!type) {
|
if (!type) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (typeof type === 'string') {
|
if (typeof type === 'object' && typeof type.name === 'string') {
|
||||||
const name = type.trim();
|
const name = type.name.trim();
|
||||||
if (!name) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return { id: fallbackId, name };
|
|
||||||
}
|
|
||||||
if (typeof type === 'object') {
|
|
||||||
const name = (type.name || type.label || '').trim();
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -265,7 +255,7 @@ const PreviewStack = ({
|
|||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={entry.url}
|
src={entry.url}
|
||||||
alt={entry.alt || ''}
|
alt={entry.alt}
|
||||||
className="preview-stack__image"
|
className="preview-stack__image"
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@@ -405,7 +395,7 @@ const DetailPanel = ({
|
|||||||
const startTitleEdit = useCallback(() => {
|
const startTitleEdit = useCallback(() => {
|
||||||
if (!singleDoc) return;
|
if (!singleDoc) return;
|
||||||
setTitleEditDocId(singleDoc.id);
|
setTitleEditDocId(singleDoc.id);
|
||||||
setTitleDraft(singleDoc.title || singleDoc.original_name || '');
|
setTitleDraft(singleDoc.title || singleDoc.original_name);
|
||||||
setTitleError(null);
|
setTitleError(null);
|
||||||
}, [singleDoc]);
|
}, [singleDoc]);
|
||||||
|
|
||||||
@@ -576,14 +566,15 @@ const DetailPanel = ({
|
|||||||
const tagMap = new Map();
|
const tagMap = new Map();
|
||||||
selectedDocuments.forEach((doc) => {
|
selectedDocuments.forEach((doc) => {
|
||||||
(doc.tags || []).forEach((tag) => {
|
(doc.tags || []).forEach((tag) => {
|
||||||
const label = (tag?.label || '').trim();
|
if (!tag?.label) return;
|
||||||
|
const label = tag.label.trim();
|
||||||
if (!label) return;
|
if (!label) return;
|
||||||
if (!tagMap.has(label)) {
|
if (!tagMap.has(label)) {
|
||||||
const fallback = tagLookupById.get(tag.id) || {};
|
const fallback = tagLookupById.get(tag.id);
|
||||||
tagMap.set(label, {
|
tagMap.set(label, {
|
||||||
id: tag.id,
|
id: tag.id,
|
||||||
label,
|
label,
|
||||||
color: tag.color || fallback.color,
|
color: tag.color ?? fallback?.color ?? null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -608,32 +599,42 @@ const DetailPanel = ({
|
|||||||
|
|
||||||
const correspondentOptions = useMemo(() => {
|
const correspondentOptions = useMemo(() => {
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
return availableCorrespondents
|
return availableCorrespondents.reduce((options, entry) => {
|
||||||
.map((entry) => (entry?.name || '').trim())
|
if (typeof entry?.name !== 'string') {
|
||||||
.filter((name) => {
|
return options;
|
||||||
if (!name) return false;
|
}
|
||||||
const lower = name.toLowerCase();
|
const name = entry.name.trim();
|
||||||
if (seen.has(lower)) {
|
if (!name) {
|
||||||
return false;
|
return options;
|
||||||
}
|
}
|
||||||
seen.add(lower);
|
const lower = name.toLowerCase();
|
||||||
return true;
|
if (seen.has(lower)) {
|
||||||
});
|
return options;
|
||||||
|
}
|
||||||
|
seen.add(lower);
|
||||||
|
options.push(name);
|
||||||
|
return options;
|
||||||
|
}, []);
|
||||||
}, [availableCorrespondents]);
|
}, [availableCorrespondents]);
|
||||||
|
|
||||||
const documentTypeOptions = useMemo(() => {
|
const documentTypeOptions = useMemo(() => {
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
return (documentTypes || [])
|
return (documentTypes || []).reduce((options, entry) => {
|
||||||
.map((entry) => (entry?.name || '').trim())
|
if (typeof entry?.name !== 'string') {
|
||||||
.filter((name) => {
|
return options;
|
||||||
if (!name) return false;
|
}
|
||||||
const lower = name.toLowerCase();
|
const name = entry.name.trim();
|
||||||
if (seen.has(lower)) {
|
if (!name) {
|
||||||
return false;
|
return options;
|
||||||
}
|
}
|
||||||
seen.add(lower);
|
const lower = name.toLowerCase();
|
||||||
return true;
|
if (seen.has(lower)) {
|
||||||
});
|
return options;
|
||||||
|
}
|
||||||
|
seen.add(lower);
|
||||||
|
options.push(name);
|
||||||
|
return options;
|
||||||
|
}, []);
|
||||||
}, [documentTypes]);
|
}, [documentTypes]);
|
||||||
|
|
||||||
const singleDocumentType = useMemo(() => resolveDocumentType(singleDoc), [singleDoc]);
|
const singleDocumentType = useMemo(() => resolveDocumentType(singleDoc), [singleDoc]);
|
||||||
@@ -751,11 +752,11 @@ const DetailPanel = ({
|
|||||||
selectedDocuments.forEach((doc) => {
|
selectedDocuments.forEach((doc) => {
|
||||||
if (!doc?.id) return;
|
if (!doc?.id) return;
|
||||||
(doc.correspondents || []).forEach((entry) => {
|
(doc.correspondents || []).forEach((entry) => {
|
||||||
if (!entry?.id) return;
|
if (!entry?.id || typeof entry.name !== 'string') return;
|
||||||
if (!map.has(entry.id)) {
|
if (!map.has(entry.id)) {
|
||||||
map.set(entry.id, {
|
map.set(entry.id, {
|
||||||
id: entry.id,
|
id: entry.id,
|
||||||
name: entry.name || '',
|
name: entry.name,
|
||||||
documentIds: new Set(),
|
documentIds: new Set(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -770,7 +771,7 @@ const DetailPanel = ({
|
|||||||
documentIds: [...entry.documentIds],
|
documentIds: [...entry.documentIds],
|
||||||
count: entry.documentIds.size,
|
count: entry.documentIds.size,
|
||||||
}))
|
}))
|
||||||
.sort((a, b) => (a.name || '').localeCompare(b.name || ''));
|
.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
}, [selectedDocuments]);
|
}, [selectedDocuments]);
|
||||||
|
|
||||||
const bulkDocumentTypes = useMemo(() => {
|
const bulkDocumentTypes = useMemo(() => {
|
||||||
@@ -789,7 +790,7 @@ const DetailPanel = ({
|
|||||||
map.get(key).count += 1;
|
map.get(key).count += 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
return [...map.values()].sort((a, b) => (a.name || '').localeCompare(b.name || ''));
|
return [...map.values()].sort((a, b) => a.name.localeCompare(b.name));
|
||||||
}, [selectedDocuments]);
|
}, [selectedDocuments]);
|
||||||
|
|
||||||
const bulkDocumentTypeSummary = useMemo(() => {
|
const bulkDocumentTypeSummary = useMemo(() => {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ function DocumentTypesPanel({
|
|||||||
|
|
||||||
const startEdit = useCallback((entry) => {
|
const startEdit = useCallback((entry) => {
|
||||||
setEditingId(entry.id);
|
setEditingId(entry.id);
|
||||||
setDraftName(entry.name || '');
|
setDraftName(entry.name);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const cancelEdit = useCallback(() => {
|
const cancelEdit = useCallback(() => {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const resolveCorrespondents = (doc) => {
|
|||||||
const results = [];
|
const results = [];
|
||||||
|
|
||||||
doc.correspondents.forEach((entry, index) => {
|
doc.correspondents.forEach((entry, index) => {
|
||||||
if (!entry) return;
|
if (!entry || typeof entry.name !== 'string') return;
|
||||||
|
|
||||||
const id = entry.id;
|
const id = entry.id;
|
||||||
const name = entry.name.trim();
|
const name = entry.name.trim();
|
||||||
@@ -68,16 +68,8 @@ const resolveDocumentType = (doc) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof type === 'string') {
|
if (typeof type === 'object' && typeof type.name === 'string') {
|
||||||
const name = type.trim();
|
const name = type.name.trim();
|
||||||
if (!name) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return { id: fallbackId, name };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof type === 'object') {
|
|
||||||
const name = (type.name || type.label || '').trim();
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -138,7 +130,7 @@ const DocumentThumbnailImage = ({
|
|||||||
document,
|
document,
|
||||||
ensureAssetUrl,
|
ensureAssetUrl,
|
||||||
getDocumentAsset,
|
getDocumentAsset,
|
||||||
alt,
|
alt = '',
|
||||||
maxSize = LIST_ICON_SIZE,
|
maxSize = LIST_ICON_SIZE,
|
||||||
scrollRootRef = null,
|
scrollRootRef = null,
|
||||||
}) => {
|
}) => {
|
||||||
@@ -210,7 +202,7 @@ const DocumentThumbnailImage = ({
|
|||||||
{url ? (
|
{url ? (
|
||||||
<img
|
<img
|
||||||
src={url}
|
src={url}
|
||||||
alt={alt || ''}
|
alt={alt}
|
||||||
className="document-thumbnail"
|
className="document-thumbnail"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
decoding="async"
|
decoding="async"
|
||||||
@@ -883,7 +875,7 @@ const DocumentsTable = ({
|
|||||||
aria-label={`Rename folder ${folder.name}`}
|
aria-label={`Rename folder ${folder.name}`}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
const nextName = window.prompt('Rename folder', folder.name || '');
|
const nextName = window.prompt('Rename folder', folder.name);
|
||||||
if (!nextName) {
|
if (!nextName) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,26 +29,14 @@ const sanitizeTags = (tags) => {
|
|||||||
if (!Array.isArray(tags)) {
|
if (!Array.isArray(tags)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return tags
|
return tags.filter((tag) => tag && (tag.label || tag.id));
|
||||||
.filter((tag) => tag && (tag.label || tag.id))
|
|
||||||
.map((tag) => ({
|
|
||||||
id: tag.id,
|
|
||||||
label: tag.label || '',
|
|
||||||
color: tag.color || null,
|
|
||||||
}));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const sanitizeCorrespondents = (entries) => {
|
const sanitizeCorrespondents = (entries) => {
|
||||||
if (!Array.isArray(entries)) {
|
if (!Array.isArray(entries)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return entries
|
return entries.filter((entry) => entry && (entry.name || entry.id));
|
||||||
.filter((entry) => entry && (entry.name || entry.id))
|
|
||||||
.map((entry) => ({
|
|
||||||
id: entry.id,
|
|
||||||
name: entry.name || '',
|
|
||||||
count: entry.count,
|
|
||||||
}));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const describeDocumentSummary = (document, options = {}) => {
|
export const describeDocumentSummary = (document, options = {}) => {
|
||||||
@@ -76,8 +64,8 @@ export const describeDocumentSummary = (document, options = {}) => {
|
|||||||
formatDateTime = defaultFormatDateTime,
|
formatDateTime = defaultFormatDateTime,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const title = document.title || '';
|
const title = document.title;
|
||||||
const originalName = document.original_name || '';
|
const originalName = document.original_name;
|
||||||
const mimeTypeLabel = document.content_type || 'Unknown';
|
const mimeTypeLabel = document.content_type || 'Unknown';
|
||||||
|
|
||||||
const sizeBytes = Number(document.current_version?.size_bytes);
|
const sizeBytes = Number(document.current_version?.size_bytes);
|
||||||
|
|||||||
+23
-23
@@ -55,7 +55,7 @@ const api = axios.create({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const storage = typeof window !== 'undefined' ? window.sessionStorage : undefined;
|
const storage = typeof window !== 'undefined' ? window.sessionStorage : undefined;
|
||||||
const STORED_TOKEN = storage?.getItem('papercrate_token') || '';
|
const STORED_TOKEN = storage?.getItem('papercrate_token') ?? '';
|
||||||
let STORED_TENANT = null;
|
let STORED_TENANT = null;
|
||||||
if (storage) {
|
if (storage) {
|
||||||
try {
|
try {
|
||||||
@@ -192,7 +192,7 @@ const AppStateProvider = ({ children }) => {
|
|||||||
const [state, dispatch] = useReducer(appStateReducer, initialAppState);
|
const [state, dispatch] = useReducer(appStateReducer, initialAppState);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const token = state.token || '';
|
const token = state.token ?? '';
|
||||||
if (token) {
|
if (token) {
|
||||||
api.defaults.headers.common.Authorization = `Bearer ${token}`;
|
api.defaults.headers.common.Authorization = `Bearer ${token}`;
|
||||||
storage?.setItem('papercrate_token', token);
|
storage?.setItem('papercrate_token', token);
|
||||||
@@ -1952,7 +1952,7 @@ const AppLayout = () => {
|
|||||||
|
|
||||||
const handleCorrespondentCreate = useCallback(
|
const handleCorrespondentCreate = useCallback(
|
||||||
async ({ name }) => {
|
async ({ name }) => {
|
||||||
const trimmed = (name || '').trim();
|
const trimmed = typeof name === 'string' ? name.trim() : '';
|
||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
throw new Error('Correspondent name is required.');
|
throw new Error('Correspondent name is required.');
|
||||||
}
|
}
|
||||||
@@ -2073,7 +2073,7 @@ const AppLayout = () => {
|
|||||||
if (!document?.id) {
|
if (!document?.id) {
|
||||||
throw new Error('Missing document for correspondent assignment.');
|
throw new Error('Missing document for correspondent assignment.');
|
||||||
}
|
}
|
||||||
const trimmed = (name || '').trim();
|
const trimmed = typeof name === 'string' ? name.trim() : '';
|
||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
setStatusMessage('Correspondent name is required.', 'error');
|
setStatusMessage('Correspondent name is required.', 'error');
|
||||||
return;
|
return;
|
||||||
@@ -2149,7 +2149,7 @@ const AppLayout = () => {
|
|||||||
|
|
||||||
const handleDocumentTypeCreate = useCallback(
|
const handleDocumentTypeCreate = useCallback(
|
||||||
async ({ name }) => {
|
async ({ name }) => {
|
||||||
const trimmed = (name || '').trim();
|
const trimmed = typeof name === 'string' ? name.trim() : '';
|
||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
throw new Error('Document type name is required.');
|
throw new Error('Document type name is required.');
|
||||||
}
|
}
|
||||||
@@ -2184,12 +2184,8 @@ const AppLayout = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const existingType = doc.document_type;
|
const existingType = doc.document_type;
|
||||||
const existingTypeId =
|
const existingTypeId = doc.document_type_id ?? existingType?.id ?? null;
|
||||||
doc.document_type_id ?? (typeof existingType === 'object' ? existingType?.id : null);
|
const existingTypeName = typeof existingType?.name === 'string' ? existingType.name : undefined;
|
||||||
const existingTypeName =
|
|
||||||
typeof existingType === 'string'
|
|
||||||
? existingType
|
|
||||||
: existingType?.name || existingType?.label || '';
|
|
||||||
|
|
||||||
const shouldClear =
|
const shouldClear =
|
||||||
existingTypeId === documentTypeId ||
|
existingTypeId === documentTypeId ||
|
||||||
@@ -2223,7 +2219,7 @@ const AppLayout = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleDocumentTypeAssign = useCallback(
|
const handleDocumentTypeAssign = useCallback(
|
||||||
async ({ documentId, documentTypeId }, { notify = true } = {}) => {
|
async ({ documentId, documentTypeId, documentType }, { notify = true } = {}) => {
|
||||||
if (!documentId) {
|
if (!documentId) {
|
||||||
throw new Error('Missing document identifier.');
|
throw new Error('Missing document identifier.');
|
||||||
}
|
}
|
||||||
@@ -2240,8 +2236,12 @@ const AppLayout = () => {
|
|||||||
|
|
||||||
const next = { ...doc };
|
const next = { ...doc };
|
||||||
if (documentTypeId) {
|
if (documentTypeId) {
|
||||||
const entry = documentTypeLookupById.get(documentTypeId);
|
const entry =
|
||||||
next.document_type = entry || { id: documentTypeId, name: entry?.name || '' };
|
documentTypeLookupById.get(documentTypeId) ||
|
||||||
|
(documentType?.name ? documentType : null);
|
||||||
|
next.document_type = entry
|
||||||
|
? { id: entry.id ?? documentTypeId, name: entry.name }
|
||||||
|
: { id: documentTypeId, name: '' };
|
||||||
} else {
|
} else {
|
||||||
next.document_type = null;
|
next.document_type = null;
|
||||||
}
|
}
|
||||||
@@ -2282,7 +2282,7 @@ const AppLayout = () => {
|
|||||||
if (!document?.id) {
|
if (!document?.id) {
|
||||||
throw new Error('Missing document for document type assignment.');
|
throw new Error('Missing document for document type assignment.');
|
||||||
}
|
}
|
||||||
const trimmed = (name || '').trim();
|
const trimmed = typeof name === 'string' ? name.trim() : '';
|
||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
setStatusMessage('Document type name is required.', 'error');
|
setStatusMessage('Document type name is required.', 'error');
|
||||||
return;
|
return;
|
||||||
@@ -2303,7 +2303,7 @@ const AppLayout = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const success = await handleDocumentTypeAssign(
|
const success = await handleDocumentTypeAssign(
|
||||||
{ documentId: document.id, documentTypeId: target.id },
|
{ documentId: document.id, documentTypeId: target.id, documentType: target },
|
||||||
{ notify: true },
|
{ notify: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2334,7 +2334,7 @@ const AppLayout = () => {
|
|||||||
|
|
||||||
const handleBulkDocumentTypeSet = useCallback(
|
const handleBulkDocumentTypeSet = useCallback(
|
||||||
async ({ name, input, documentIds }) => {
|
async ({ name, input, documentIds }) => {
|
||||||
const trimmed = (name || '').trim();
|
const trimmed = typeof name === 'string' ? name.trim() : '';
|
||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
setStatusMessage('Document type name is required.', 'error');
|
setStatusMessage('Document type name is required.', 'error');
|
||||||
return;
|
return;
|
||||||
@@ -2658,7 +2658,7 @@ const AppLayout = () => {
|
|||||||
|
|
||||||
const handleBulkCorrespondentAdd = useCallback(
|
const handleBulkCorrespondentAdd = useCallback(
|
||||||
async ({ name, input, documentIds }) => {
|
async ({ name, input, documentIds }) => {
|
||||||
const trimmed = (name || '').trim();
|
const trimmed = typeof name === 'string' ? name.trim() : '';
|
||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
setStatusMessage('Correspondent name is required.', 'error');
|
setStatusMessage('Correspondent name is required.', 'error');
|
||||||
return;
|
return;
|
||||||
@@ -2887,7 +2887,7 @@ const AppLayout = () => {
|
|||||||
|
|
||||||
const handleBulkTagAddFromDetail = useCallback(
|
const handleBulkTagAddFromDetail = useCallback(
|
||||||
async ({ label, input, documentIds }) => {
|
async ({ label, input, documentIds }) => {
|
||||||
const trimmed = (label || '').trim();
|
const trimmed = typeof label === 'string' ? label.trim() : '';
|
||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
setStatusMessage('Enter a tag label.', 'error');
|
setStatusMessage('Enter a tag label.', 'error');
|
||||||
return;
|
return;
|
||||||
@@ -2920,7 +2920,7 @@ const AppLayout = () => {
|
|||||||
|
|
||||||
const handleBulkTagRemoveFromDetail = useCallback(
|
const handleBulkTagRemoveFromDetail = useCallback(
|
||||||
async ({ label, input, documentIds }) => {
|
async ({ label, input, documentIds }) => {
|
||||||
const trimmed = (label || '').trim();
|
const trimmed = typeof label === 'string' ? label.trim() : '';
|
||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
setStatusMessage('Enter a tag label to remove.', 'error');
|
setStatusMessage('Enter a tag label to remove.', 'error');
|
||||||
return;
|
return;
|
||||||
@@ -4190,7 +4190,7 @@ const AppLayout = () => {
|
|||||||
setStatusMessage('The root folder cannot be renamed.', 'error');
|
setStatusMessage('The root folder cannot be renamed.', 'error');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const trimmed = (nextName || '').trim();
|
const trimmed = typeof nextName === 'string' ? nextName.trim() : '';
|
||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
setStatusMessage('Folder name cannot be empty.', 'error');
|
setStatusMessage('Folder name cannot be empty.', 'error');
|
||||||
return false;
|
return false;
|
||||||
@@ -6157,7 +6157,7 @@ const LoginRoute = () => {
|
|||||||
|
|
||||||
const handlePasskeyLogin = useCallback(
|
const handlePasskeyLogin = useCallback(
|
||||||
async (rawUsername) => {
|
async (rawUsername) => {
|
||||||
const username = (rawUsername || '').trim();
|
const username = typeof rawUsername === 'string' ? rawUsername.trim() : '';
|
||||||
if (!username) {
|
if (!username) {
|
||||||
setStatusMessage('Enter your username before using a passkey.', 'error');
|
setStatusMessage('Enter your username before using a passkey.', 'error');
|
||||||
return;
|
return;
|
||||||
@@ -6238,7 +6238,7 @@ const LoginRoute = () => {
|
|||||||
|
|
||||||
const handleSignup = useCallback(
|
const handleSignup = useCallback(
|
||||||
async (rawUsername) => {
|
async (rawUsername) => {
|
||||||
const username = (rawUsername || '').trim();
|
const username = typeof rawUsername === 'string' ? rawUsername.trim() : '';
|
||||||
if (!username) {
|
if (!username) {
|
||||||
setStatusMessage('Choose a username to create your account.', 'error');
|
setStatusMessage('Choose a username to create your account.', 'error');
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ const FolderNode = ({
|
|||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
if (!onRename) return;
|
if (!onRename) return;
|
||||||
const nextName = window.prompt('Rename folder', node.name || '');
|
const nextName = window.prompt('Rename folder', node.name);
|
||||||
if (!nextName) {
|
if (!nextName) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -174,24 +174,28 @@ const Sidebar = ({
|
|||||||
onSelectTenant,
|
onSelectTenant,
|
||||||
onOpenSettings,
|
onOpenSettings,
|
||||||
}) => {
|
}) => {
|
||||||
const sortedCorrespondents = useMemo(
|
const sortedCorrespondents = useMemo(() => {
|
||||||
() =>
|
if (!Array.isArray(correspondents)) {
|
||||||
[...correspondents].sort((a, b) =>
|
return [];
|
||||||
(a?.name || '').localeCompare(b?.name || '', undefined, { sensitivity: 'base' }),
|
}
|
||||||
),
|
return correspondents
|
||||||
[correspondents],
|
.filter((entry) => entry?.name)
|
||||||
);
|
.slice()
|
||||||
|
.sort((a, b) => a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }));
|
||||||
|
}, [correspondents]);
|
||||||
const activeCorrespondentSet = useMemo(
|
const activeCorrespondentSet = useMemo(
|
||||||
() => new Set(activeCorrespondentIds || []),
|
() => new Set(activeCorrespondentIds || []),
|
||||||
[activeCorrespondentIds],
|
[activeCorrespondentIds],
|
||||||
);
|
);
|
||||||
const sortedDocumentTypes = useMemo(
|
const sortedDocumentTypes = useMemo(() => {
|
||||||
() =>
|
if (!Array.isArray(documentTypes)) {
|
||||||
[...documentTypes].sort((a, b) =>
|
return [];
|
||||||
(a?.name || '').localeCompare(b?.name || '', undefined, { sensitivity: 'base' }),
|
}
|
||||||
),
|
return documentTypes
|
||||||
[documentTypes],
|
.filter((entry) => entry?.name)
|
||||||
);
|
.slice()
|
||||||
|
.sort((a, b) => a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }));
|
||||||
|
}, [documentTypes]);
|
||||||
const activeDocumentTypeSet = useMemo(
|
const activeDocumentTypeSet = useMemo(
|
||||||
() => new Set(activeDocumentTypeIds || []),
|
() => new Set(activeDocumentTypeIds || []),
|
||||||
[activeDocumentTypeIds],
|
[activeDocumentTypeIds],
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ function TagsPanel({
|
|||||||
|
|
||||||
const startEdit = useCallback((tag) => {
|
const startEdit = useCallback((tag) => {
|
||||||
setEditingId(tag.id);
|
setEditingId(tag.id);
|
||||||
setDraftLabel(tag.label || '');
|
setDraftLabel(tag.label);
|
||||||
setDraftColor(tag.color || '');
|
setDraftColor(tag.color ?? '');
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const cancelEdit = useCallback(() => {
|
const cancelEdit = useCallback(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user