linting, tenant slug -> name

This commit is contained in:
2025-10-29 18:26:59 +01:00
parent b6bcb72165
commit abc0116945
23 changed files with 324 additions and 487 deletions
+59 -219
View File
@@ -53,10 +53,9 @@ if (storage) {
if (rawTenant) {
STORED_TENANT = JSON.parse(rawTenant);
}
} catch (
// eslint-disable-next-line no-empty
error
) {}
} catch (error) {
console.warn('[app] Failed to parse stored tenant metadata', error);
}
}
if (STORED_TOKEN) {
api.defaults.headers.common.Authorization = `Bearer ${STORED_TOKEN}`;
@@ -428,7 +427,7 @@ const LoginView = ({
: 'login-card__tenant-button'
}
>
{tenant.slug}
{tenant.name}
</button>
))}
</div>
@@ -492,7 +491,7 @@ const AppLayout = () => {
const routeDocumentId = docMatch?.params?.documentId || null;
const previewDocumentId = routeDocumentId;
const { status: appStatus, token, tenant, tenants: tenantOptions = [] } = appState;
const tenantSlug = tenant?.slug || null;
const tenantName = tenant?.name || tenant?.slug || null;
const currentTenantId = tenant?.id || null;
const [status, setStatus] = useState(null);
const setStatusMessage = useCallback((message, variant = 'info') => {
@@ -586,6 +585,8 @@ const AppLayout = () => {
}
}, [appDispatch]);
const [searchResults, setSearchResults] = useState(null);
const [previewEntries, setPreviewEntries] = useState(() => new Map());
const previewInflightRef = useRef(new Map());
const [tags, setTags] = useState([]);
const [correspondents, setCorrespondents] = useState([]);
const [webdavTokens, setWebdavTokens] = useState([]);
@@ -596,6 +597,7 @@ const AppLayout = () => {
const [searchQuery, setSearchQuery] = useState('');
const [activeTagFilters, setActiveTagFilters] = useState([]);
const [activeCorrespondentFilters, setActiveCorrespondentFilters] = useState([]);
const [searchLoading, setSearchLoading] = useState(false);
const documentsRouteMatch = useMatch('/documents');
const documentsFolderRouteMatch = useMatch('/documents/folder/:folderId');
const documentsDetailRouteMatch = useMatch('/documents/:documentId');
@@ -656,7 +658,6 @@ const AppLayout = () => {
folderName: DEFAULT_FOLDER_NAME,
});
const [activePreviewId, setActivePreviewId] = useState(routeDocumentId || null);
const [searchLoading, setSearchLoading] = useState(false);
const shellRef = useRef(null);
const assetManagerRef = useRef(null);
if (!assetManagerRef.current) {
@@ -1951,6 +1952,21 @@ const AppLayout = () => {
[refreshCorrespondents, notifyApiError, setStatusMessage, mapDocumentCaches],
);
const refreshCurrentFolder = useCallback(async () => {
setLoading(true);
try {
const contents = await ensureFolderData(selectedFolder, {
force: true,
prefetchDepth: 1,
});
applySelectedFolder(selectedFolder, contents);
} catch (error) {
notifyApiError(error, 'Failed to refresh folder.');
} finally {
setLoading(false);
}
}, [selectedFolder, ensureFolderData, applySelectedFolder, notifyApiError]);
const handleDocumentCorrespondentAttach = useCallback(
async ({ documentId, correspondentId }, { notify = true, refresh = true } = {}) => {
if (!documentId || !correspondentId) {
@@ -2033,10 +2049,10 @@ const AppLayout = () => {
if (input) {
input.value = '';
}
} catch (
// eslint-disable-next-line no-empty
error
) {}
} catch (error) {
setStatusMessage('Failed to assign correspondent.', 'error');
console.error('[documents] assign correspondent failed', error);
}
},
[
handleCorrespondentCreate,
@@ -2286,21 +2302,6 @@ const AppLayout = () => {
selectFolder,
]);
const refreshCurrentFolder = useCallback(async () => {
setLoading(true);
try {
const contents = await ensureFolderData(selectedFolder, {
force: true,
prefetchDepth: 1,
});
applySelectedFolder(selectedFolder, contents);
} catch (error) {
notifyApiError(error, 'Failed to refresh folder.');
} finally {
setLoading(false);
}
}, [selectedFolder, ensureFolderData, applySelectedFolder, notifyApiError]);
const resolveTargetDocumentIds = useCallback(
(candidateIds) => {
const normalized = Array.isArray(candidateIds)
@@ -2671,8 +2672,6 @@ const AppLayout = () => {
);
const folderPathCacheRef = useRef(new Map());
const [previewEntries, setPreviewEntries] = useState(() => new Map());
const previewInflightRef = useRef(new Map());
const ensureFolderPathOnServer = useCallback(
async (baseFolderId, segments) => {
@@ -2919,10 +2918,9 @@ const AppLayout = () => {
event.dataTransfer.setData('application/x-papercrate-folder', folderSelection[0]);
}
}
} catch (
// eslint-disable-next-line no-empty
error
) {}
} catch (error) {
console.warn('[documents] Failed to populate drag payload', error);
}
if (previewNode) {
const width = previewNode.offsetWidth || 96;
const height = previewNode.offsetHeight || 96;
@@ -2993,10 +2991,9 @@ const AppLayout = () => {
JSON.stringify(effectiveDocumentSelection),
);
}
} catch (
// eslint-disable-next-line no-empty
error
) {}
} catch (error) {
console.warn('[folders] Failed to set drag payload', error);
}
const previewDocs = effectiveDocumentSelection
.map((id) => documentLookup.get(id) || null)
@@ -3112,14 +3109,14 @@ const AppLayout = () => {
const readAllEntries = async (reader) => {
const entries = [];
while (true) {
let batch = [];
do {
// eslint-disable-next-line no-await-in-loop
const batch = await new Promise((resolve, reject) => reader.readEntries(resolve, reject));
if (!batch.length) {
break;
batch = await new Promise((resolve, reject) => reader.readEntries(resolve, reject));
if (batch.length) {
entries.push(...batch);
}
entries.push(...batch);
}
} while (batch.length);
return entries;
};
@@ -4424,10 +4421,9 @@ const AppLayout = () => {
folderIds = parsed.filter(Boolean);
}
}
} catch (
// eslint-disable-next-line no-empty
error
) {}
} catch (error) {
console.warn('[folders] Failed to parse folder list drag payload', error);
}
if (!folderIds.length) {
let folderSourceId = draggedFolderId;
@@ -4436,10 +4432,9 @@ const AppLayout = () => {
if (event.dataTransfer.types?.includes('application/x-papercrate-folder')) {
folderSourceId = event.dataTransfer.getData('application/x-papercrate-folder');
}
} catch (
// eslint-disable-next-line no-empty
error
) {}
} catch (error) {
console.warn('[folders] Failed to read folder id from drag payload', error);
}
}
if (folderSourceId) {
@@ -4480,21 +4475,19 @@ const AppLayout = () => {
docIds = parsed.filter(Boolean);
}
}
} catch (
// eslint-disable-next-line no-empty
error
) {}
} catch (error) {
console.warn('[documents] Failed to parse document list drag payload', error);
}
if (!docIds.length) {
try {
const single = event.dataTransfer.getData('application/x-papercrate-doc');
if (single) {
docIds = [single];
}
} catch (
// eslint-disable-next-line no-empty
error
) {}
try {
const single = event.dataTransfer.getData('application/x-papercrate-doc');
if (single) {
docIds = [single];
}
} catch (error) {
console.warn('[documents] Failed to read single document drag payload', error);
}
}
if (!docIds.length && draggedDocumentIds.length) {
@@ -4551,159 +4544,6 @@ const AppLayout = () => {
setStatusMessage,
],
);
const node = folderNodes.get(folderId);
const nextExpanded = !(node?.expanded ?? false);
if (nextExpanded) {
try {
await ensureFolderData(folderId, {
includeDocuments: false,
prefetchDepth: 1,
});
} catch (error) {
notifyApiError(error, 'Failed to load folder.');
}
} else if (node && !node.loaded) {
try {
await ensureFolderData(folderId, {
includeDocuments: false,
prefetchDepth: 1,
});
} catch (error) {
notifyApiError(error, 'Failed to load folder.');
}
}
setFolderNodes((prev) => {
const next = new Map(prev);
const current = next.get(folderId);
if (!current) return prev;
next.set(folderId, { ...current, expanded: nextExpanded });
return next;
});
},
onSelect: selectFolder,
onDrop: async (event, folderId) => {
event.preventDefault();
event.stopPropagation();
event.currentTarget.classList.remove('is-drop-target');
let folderIds = [];
try {
const rawFolderList = event.dataTransfer.getData('application/x-papercrate-folder-list');
if (rawFolderList) {
const parsed = JSON.parse(rawFolderList);
if (Array.isArray(parsed)) {
folderIds = parsed.filter(Boolean);
}
}
} catch (
// eslint-disable-next-line no-empty
error
) {}
if (!folderIds.length) {
let folderSourceId = draggedFolderId;
if (!folderSourceId) {
try {
if (event.dataTransfer.types?.includes('application/x-papercrate-folder')) {
folderSourceId = event.dataTransfer.getData('application/x-papercrate-folder');
}
} catch (
// eslint-disable-next-line no-empty
error
) {}
}
if (folderSourceId) {
folderIds = [folderSourceId];
}
}
folderIds = Array.from(new Set(folderIds.filter(Boolean)));
if (folderIds.length) {
setDraggedFolderId(null);
const invalidMove = folderIds.some((sourceId) => isInvalidFolderDrop(sourceId, folderId));
if (invalidMove) {
setStatusMessage(
'Cannot move a folder into itself or one of its descendants.',
'error',
);
return;
}
for (const sourceId of folderIds) {
// eslint-disable-next-line no-await-in-loop
await moveFolder(sourceId, folderId);
}
}
if (hasFiles(event)) {
await handleFileDrop(event.dataTransfer, folderId);
return;
}
let docIds = [];
try {
const raw = event.dataTransfer.getData('application/x-papercrate-doc-list');
if (raw) {
const parsed = JSON.parse(raw);
if (Array.isArray(parsed)) {
docIds = parsed.filter(Boolean);
}
}
} catch (
// eslint-disable-next-line no-empty
error
) {}
if (!docIds.length) {
try {
const single = event.dataTransfer.getData('application/x-papercrate-doc');
if (single) {
docIds = [single];
}
} catch (
// eslint-disable-next-line no-empty
error
) {}
}
if (!docIds.length && draggedDocumentIds.length) {
docIds = draggedDocumentIds;
}
docIds = Array.from(new Set(docIds));
if (!docIds.length || folderId === selectedFolder) {
return;
}
setDraggedDocumentIds([]);
await moveDocumentsToFolder(docIds, folderId);
},
onDragOver: (event, folderId) => {
const folderDragActive = Boolean(draggedFolderId);
if (folderDragActive && isInvalidFolderDrop(draggedFolderId, folderId)) {
return;
}
if (hasFiles(event)) {
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
event.currentTarget.classList.add('is-drop-target');
return;
}
if (draggedDocumentIds.length || folderDragActive) {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
event.currentTarget.classList.add('is-drop-target');
}
},
onDragLeave: (event) => {
event.currentTarget.classList.remove('is-drop-target');
},
};
const selectedDocument = useMemo(() => {
if (!focusedDocumentId) {
@@ -5163,7 +5003,7 @@ const AppLayout = () => {
await Promise.all([refreshTags(), refreshCorrespondents()]);
await loadFolder('root', { showLoading: false, preserveSearch: false });
const tenantLabel = data?.tenant?.slug || data?.tenant?.id || 'tenant';
const tenantLabel = data?.tenant?.name || data?.tenant?.id || 'tenant';
setStatusMessage(`Switched to ${tenantLabel}.`, 'info');
} catch (error) {
notifyApiError(error, 'Failed to switch tenant.');
@@ -5314,7 +5154,7 @@ const AppLayout = () => {
isFilterActive,
onLogout: handleLogout,
status,
tenantSlug,
tenantName,
tenants: tenantOptions,
activeTenantId: currentTenantId,
onSelectTenant: handleTenantSelect,
@@ -5347,7 +5187,7 @@ const AppLayout = () => {
status,
tags,
tenantOptions,
tenantSlug,
tenantName,
toggleCorrespondentFilter,
toggleTagFilter,
],