This commit is contained in:
2025-11-02 04:40:07 +01:00
parent f7b274c1ec
commit e7e7881772
13 changed files with 560 additions and 243 deletions
+46 -26
View File
@@ -21,9 +21,9 @@ import { useManagementModals } from './useManagementModals';
import { api, useAppDispatch, useAppState } from './appState';
import { useDetailPanel } from './useDetailPanel';
import { useDocumentSelection } from './useDocumentSelection';
import { isTagTransferEvent } from '../documents/tagTransfer';
const ASSET_PRESIGN_TTL_MS = 240 * 1000; // backend issues 5 min tokens; refresh slightly early
const TAG_MIME_TYPES = ['application/x-papercrate-tag', 'text/papercrate-tag'];
const DEFAULT_FOLDER_NAME = 'Documents';
@@ -2180,9 +2180,8 @@ const AppLayout = () => {
};
const { data } = await api.post('/folders/path', payload);
const folderId = data.folder.id;
cache.set(cacheKey, folderId);
return folderId;
cache.set(cacheKey, data.folder.id);
return data.folder.id;
},
[],
);
@@ -2547,7 +2546,7 @@ const AppLayout = () => {
const entry = {
url: href,
contentType: docResponse.data?.document?.current_version?.version?.content_type || null,
filename: docResponse.data?.document?.filename || 'document',
filename: docResponse.data?.document?.filename,
expiresAt: Date.now() + 5 * 60 * 1000,
};
setPreviewEntries((prev) => {
@@ -3106,6 +3105,8 @@ const AppLayout = () => {
? focusedRowKey
: null;
let initializedFromEmptyState = false;
if (!activeKey) {
for (let index = selectedEntries.length - 1; index >= 0; index -= 1) {
const candidate = selectedEntries[index];
@@ -3117,8 +3118,17 @@ const AppLayout = () => {
}
if (!activeKey) {
activeKey = navigableRowKeys[0];
if (key === 'ArrowUp') {
const lastKey = navigableRowKeys[navigableRowKeys.length - 1];
if (!lastKey) {
return;
}
activeKey = lastKey;
} else {
activeKey = navigableRowKeys[0];
}
setFocusedRowKey(activeKey);
initializedFromEmptyState = true;
}
let currentIndex = navigableRowKeys.indexOf(activeKey);
@@ -3140,8 +3150,22 @@ const AppLayout = () => {
let nextIndex = currentIndex;
if (key === 'ArrowDown') {
if (initializedFromEmptyState && selectedEntries.length === 0) {
handleRowSelection(activeKey, {
shiftKey,
preventDefault: () => {},
});
return;
}
nextIndex = currentIndex === -1 ? 0 : Math.min(currentIndex + 1, navigableRows.length - 1);
} else if (key === 'ArrowUp') {
if (initializedFromEmptyState && selectedEntries.length === 0) {
handleRowSelection(activeKey, {
shiftKey,
preventDefault: () => {},
});
return;
}
nextIndex = currentIndex === -1 ? navigableRows.length - 1 : Math.max(currentIndex - 1, 0);
} else if (key === 'Home') {
nextIndex = 0;
@@ -3363,16 +3387,14 @@ const AppLayout = () => {
const resolveTagForCache = () => {
const lookupTag = tagLookupById.get(tagId);
const source = lookupTag || tagData;
if (!source) {
return { id: tagId, label: 'Tag', color: null };
const source = lookupTag ?? tagData;
if (!source || source.id == null || typeof source.label !== 'string') {
return null;
}
return {
id: source.id ?? tagId,
label: source.label || source.name || 'Tag',
color: Object.prototype.hasOwnProperty.call(source, 'color')
? source.color
: null,
id: source.id,
label: source.label,
color: Object.prototype.hasOwnProperty.call(source, 'color') ? source.color : null,
};
};
@@ -3386,10 +3408,16 @@ const AppLayout = () => {
if (currentTags.some((existing) => existing?.id === tagId)) {
return doc;
}
return { ...doc, tags: [...currentTags, resolveTagForCache()] };
const resolvedTag = resolveTagForCache();
if (!resolvedTag) {
return doc;
}
return { ...doc, tags: [...currentTags, resolvedTag] };
});
setStatusMessage('Tag assigned.', 'success');
await refreshCurrentFolder();
if (documentsViewMode !== 'desk') {
await refreshCurrentFolder();
}
return true;
} catch (error) {
const message = error.response?.data?.error || 'Failed to assign tag.';
@@ -3399,6 +3427,7 @@ const AppLayout = () => {
},
[
refreshCurrentFolder,
documentsViewMode,
notifyApiError,
setStatusMessage,
updateDocumentCaches,
@@ -3851,16 +3880,7 @@ const AppLayout = () => {
return undefined;
}
const isTagTransfer = (event) => {
const types = event?.dataTransfer?.types;
if (!types) {
return false;
}
if (typeof types.includes === 'function') {
return TAG_MIME_TYPES.some((type) => types.includes(type));
}
return TAG_MIME_TYPES.some((type) => Array.from(types).includes(type));
};
const isTagTransfer = (event) => isTagTransferEvent(event);
const isDocumentDropTarget = (target) =>
target instanceof Element ? Boolean(target.closest('[data-doc-id]')) : false;