frontend lint
This commit is contained in:
+1
-248
@@ -397,33 +397,6 @@ const DocumentsLayout = ({ sidebarProps, children, sidebarCollapsed }) => (
|
||||
</main>
|
||||
);
|
||||
|
||||
const MainContentShell = ({
|
||||
className,
|
||||
header = {},
|
||||
sidebarToggleButton = null,
|
||||
children,
|
||||
}) => {
|
||||
const { title = '', subtitle = null, leading = null, actions = null } = header || {};
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className="panel-header main-content__header">
|
||||
<div className="panel-actions main-content__actions">
|
||||
{sidebarToggleButton}
|
||||
{leading}
|
||||
<h2 className="main-content__title">
|
||||
{title}
|
||||
{subtitle ? <span className="main-content__subtitle">{subtitle}</span> : null}
|
||||
</h2>
|
||||
<div className="spacer" />
|
||||
{actions}
|
||||
</div>
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const AppLayout = () => {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
@@ -445,9 +418,6 @@ const AppLayout = () => {
|
||||
({ message, variant }) => setStatusMessage(message, variant),
|
||||
[setStatusMessage],
|
||||
);
|
||||
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
|
||||
const collapseSidebar = useCallback(() => setSidebarCollapsed(true), []);
|
||||
const expandSidebar = useCallback(() => setSidebarCollapsed(false), []);
|
||||
const reportApiError = useApiError({
|
||||
onReport: handleApiReport,
|
||||
});
|
||||
@@ -616,12 +586,6 @@ const AppLayout = () => {
|
||||
}
|
||||
const tagManager = tagManagerRef.current;
|
||||
|
||||
|
||||
const buildTagPayload = useCallback(
|
||||
({ label, color } = {}) => tagManager.buildPayload({ label, color }),
|
||||
[tagManager],
|
||||
);
|
||||
|
||||
const getDocumentAsset = useCallback((doc, type) => {
|
||||
if (!doc || !type) return null;
|
||||
return getAssetFromVersion(doc.current_version || null, type);
|
||||
@@ -1247,16 +1211,6 @@ const AppLayout = () => {
|
||||
[selectedRowKeys, updateSelectionOrder],
|
||||
);
|
||||
|
||||
const visibleSelectedCount = useMemo(
|
||||
() => selectedDocumentIds.filter((id) => visibleDocumentIds.includes(id)).length,
|
||||
[selectedDocumentIds, visibleDocumentIds],
|
||||
);
|
||||
|
||||
const allDocumentsSelected =
|
||||
visibleDocumentIds.length > 0 &&
|
||||
visibleSelectedCount === visibleDocumentIds.length;
|
||||
const someDocumentsSelected =
|
||||
visibleSelectedCount > 0 && !allDocumentsSelected;
|
||||
|
||||
const folderOptions = useMemo(() => {
|
||||
const cache = new Map();
|
||||
@@ -2498,73 +2452,6 @@ const AppLayout = () => {
|
||||
};
|
||||
}, [appStatus, appDispatch, initializeAfterLogin]);
|
||||
|
||||
const handleBulkMoveSubmit = useCallback(
|
||||
async (event) => {
|
||||
event.preventDefault();
|
||||
if (!selectedDocumentIds.length) {
|
||||
setStatusMessage('Select documents before moving.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const form = new FormData(event.currentTarget);
|
||||
const target = form.get('target')?.toString() || 'root';
|
||||
const folderId = target === 'root' ? null : target;
|
||||
|
||||
if (!refreshOnly) {
|
||||
setLoading(true);
|
||||
}
|
||||
try {
|
||||
await api.post('/documents/bulk/move', {
|
||||
document_ids: selectedDocumentIds,
|
||||
folder_id: folderId,
|
||||
});
|
||||
|
||||
const count = selectedDocumentIds.length;
|
||||
const suffix = count === 1 ? '' : 's';
|
||||
const folderLabel =
|
||||
folderId === null
|
||||
? DEFAULT_FOLDER_NAME
|
||||
: folderLabelMap.get(target) || 'target folder';
|
||||
setStatusMessage(
|
||||
`Moved ${count} document${suffix} to ${folderLabel}.`,
|
||||
'success',
|
||||
);
|
||||
|
||||
applySelection([], { anchor: null });
|
||||
|
||||
await refreshCurrentFolder();
|
||||
if (folderId && folderId !== selectedFolder) {
|
||||
await ensureFolderData(folderId, { force: true, prefetchDepth: 1 });
|
||||
}
|
||||
|
||||
event.currentTarget.reset();
|
||||
} catch (error) {
|
||||
const message = error.response?.data?.error || 'Failed to move documents.';
|
||||
notifyApiError(error, message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
},
|
||||
[
|
||||
api,
|
||||
selectedDocumentIds,
|
||||
folderLabelMap,
|
||||
applySelection,
|
||||
refreshCurrentFolder,
|
||||
ensureFolderData,
|
||||
notifyApiError,
|
||||
selectedFolder,
|
||||
setStatusMessage,
|
||||
],
|
||||
);
|
||||
|
||||
const parseTagInput = useCallback((value) => {
|
||||
return value
|
||||
.split(',')
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean);
|
||||
}, []);
|
||||
|
||||
const bulkTagOperation = useCallback(
|
||||
async ({ labels, action, documentIds }) => {
|
||||
const normalized = labels.map((label) => label.trim()).filter((label) => label.length > 0);
|
||||
@@ -2650,81 +2537,6 @@ const AppLayout = () => {
|
||||
],
|
||||
);
|
||||
|
||||
const handleBulkTagAdd = useCallback(
|
||||
async (event) => {
|
||||
event.preventDefault();
|
||||
if (!selectedDocumentIds.length) {
|
||||
setStatusMessage('Select documents before assigning tags.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const form = new FormData(event.currentTarget);
|
||||
const raw = form.get('tags')?.toString().trim() || '';
|
||||
const labels = parseTagInput(raw);
|
||||
if (!labels.length) {
|
||||
setStatusMessage('Enter at least one tag label.', 'error');
|
||||
return;
|
||||
}
|
||||
const result = await bulkTagOperation({ labels, action: 'add' });
|
||||
if (result?.ok) {
|
||||
const { tagCount, docsCount } = result;
|
||||
setStatusMessage(
|
||||
`Assigned ${tagCount} tag${tagCount === 1 ? '' : 's'} to ${docsCount} document${
|
||||
docsCount === 1 ? '' : 's'
|
||||
}.`,
|
||||
'success',
|
||||
);
|
||||
event.currentTarget.reset();
|
||||
} else if (result?.reason === 'no-labels') {
|
||||
setStatusMessage('Enter at least one tag label.', 'error');
|
||||
}
|
||||
},
|
||||
[
|
||||
selectedDocumentIds,
|
||||
setStatusMessage,
|
||||
parseTagInput,
|
||||
bulkTagOperation,
|
||||
],
|
||||
);
|
||||
|
||||
const handleBulkTagRemove = useCallback(
|
||||
async (event) => {
|
||||
event.preventDefault();
|
||||
if (!selectedDocumentIds.length) {
|
||||
setStatusMessage('Select documents before removing tags.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const form = new FormData(event.currentTarget);
|
||||
const raw = form.get('tags')?.toString().trim() || '';
|
||||
const labels = parseTagInput(raw);
|
||||
if (!labels.length) {
|
||||
setStatusMessage('Enter at least one tag label to remove.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await bulkTagOperation({ labels, action: 'remove' });
|
||||
if (result?.ok) {
|
||||
const { docsCount } = result;
|
||||
setStatusMessage(
|
||||
`Removed tags from ${docsCount} document${docsCount === 1 ? '' : 's'}.`,
|
||||
'success',
|
||||
);
|
||||
event.currentTarget.reset();
|
||||
} else if (result?.reason === 'no-labels') {
|
||||
setStatusMessage('Enter at least one tag label to remove.', 'error');
|
||||
} else if (result?.reason === 'tag-missing') {
|
||||
setStatusMessage(`Tag “${result.label}” not found.`, 'error');
|
||||
}
|
||||
},
|
||||
[
|
||||
selectedDocumentIds,
|
||||
setStatusMessage,
|
||||
parseTagInput,
|
||||
bulkTagOperation,
|
||||
],
|
||||
);
|
||||
|
||||
const handleBulkTagAddFromDetail = useCallback(
|
||||
async ({ label, input, documentIds }) => {
|
||||
const trimmed = (label || '').trim();
|
||||
@@ -3371,7 +3183,7 @@ const AppLayout = () => {
|
||||
}),
|
||||
);
|
||||
|
||||
Array.from(dataTransfer.files || []).forEach((file, index) => {
|
||||
Array.from(dataTransfer.files || []).forEach((file) => {
|
||||
if (!file) return;
|
||||
// FileList entry suppressed
|
||||
const relativePath =
|
||||
@@ -4554,54 +4366,6 @@ const AppLayout = () => {
|
||||
};
|
||||
}, [handleTagRemove, setTagRemovalCursor]);
|
||||
|
||||
const handleLogin = useCallback(
|
||||
async (event) => {
|
||||
event.preventDefault();
|
||||
const form = new FormData(event.currentTarget);
|
||||
const payload = {
|
||||
username: form.get('username')?.toString().trim(),
|
||||
password: form.get('password')?.toString() || '',
|
||||
};
|
||||
if (!payload.username || !payload.password) {
|
||||
setStatusMessage('Username and password are required.', 'error');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setLoading(true);
|
||||
appDispatch({ type: 'LOGIN_REQUEST' });
|
||||
const { data } = await api.post('/auth/login', payload);
|
||||
|
||||
if (data?.access_token && Array.isArray(data?.tenants)) {
|
||||
appDispatch({
|
||||
type: 'TENANT_SELECTION_REQUIRED',
|
||||
selectionToken: data.access_token,
|
||||
tenants: data.tenants,
|
||||
});
|
||||
setStatusMessage('Select a tenant to continue.', 'info');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data?.access_token) {
|
||||
throw new Error('Invalid login response.');
|
||||
}
|
||||
|
||||
appDispatch({
|
||||
type: 'LOGIN_SUCCESS',
|
||||
token: data.access_token,
|
||||
tenant: data.tenant || null,
|
||||
});
|
||||
setStatusMessage('Login successful.', 'success');
|
||||
} catch (error) {
|
||||
const message = error?.response?.data?.error || 'Login failed. Check credentials.';
|
||||
appDispatch({ type: 'LOGIN_FAILURE', error: message });
|
||||
notifyApiError(error, message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
},
|
||||
[appDispatch, notifyApiError, setStatusMessage],
|
||||
);
|
||||
|
||||
const handleLogout = useCallback(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
@@ -5333,7 +5097,6 @@ const AppLayout = () => {
|
||||
isFilterActive,
|
||||
onLogout: handleLogout,
|
||||
status,
|
||||
onCollapse: collapseSidebar,
|
||||
tenantSlug,
|
||||
tenants: tenantOptions,
|
||||
activeTenantId: currentTenantId,
|
||||
@@ -5341,16 +5104,6 @@ const AppLayout = () => {
|
||||
onOpenSettings: openSettingsModal,
|
||||
};
|
||||
|
||||
const sidebarPropsWithActions = useMemo(
|
||||
() => ({
|
||||
...sidebarProps,
|
||||
onManageTags: openTagsModal,
|
||||
onManageCorrespondents: openCorrespondentsModal,
|
||||
onCollapse: collapseSidebar,
|
||||
}),
|
||||
[sidebarProps, openTagsModal, openCorrespondentsModal, collapseSidebar],
|
||||
);
|
||||
|
||||
const handleDetailPanelClose = useCallback(() => {
|
||||
setDetailPanelOpen(false);
|
||||
clearDocumentSelection();
|
||||
|
||||
Reference in New Issue
Block a user