This commit is contained in:
2025-10-31 02:06:38 +01:00
parent 17db827e3a
commit f796932cd8
6 changed files with 493 additions and 306 deletions
+67 -227
View File
@@ -13,14 +13,11 @@ import AssetManager, {
createAssetView,
} from '../asset_manager';
import useApiError from '../hooks/useApiError';
import TagsPanel from '../tags/TagsPanel';
import CorrespondentsPanel from '../correspondents/CorrespondentsPanel';
import DocumentTypesPanel from '../documentTypes/DocumentTypesPanel';
import TagManager from '../tag_manager';
import SettingsModal from '../settings/SettingsModal';
import usePasskeys from '../settings/usePasskeys';
import { AppShellContext } from '../appShellContext';
import DropOverlay from './DropOverlay';
import { useManagementModals } from './useManagementModals';
import { api, useAppDispatch, useAppState } from './appState';
const ASSET_PRESIGN_TTL_MS = 240 * 1000; // backend issues 5 min tokens; refresh slightly early
@@ -182,10 +179,6 @@ const AppLayout = () => {
[reportApiError],
);
const [loading, setLoading] = useState(false);
const [isTagsModalOpen, setTagsModalOpen] = useState(false);
const [isCorrespondentsModalOpen, setCorrespondentsModalOpen] = useState(false);
const [isDocumentTypesModalOpen, setDocumentTypesModalOpen] = useState(false);
const [isSettingsModalOpen, setSettingsModalOpen] = useState(false);
const [creatingFolder, setCreatingFolder] = useState(false);
const [folderNodes, setFolderNodes] = useState(() => {
const rootNode = createRootNode();
@@ -1596,20 +1589,6 @@ const AppLayout = () => {
token,
});
useEffect(() => {
if (!isSettingsModalOpen) {
return;
}
refreshWebdavTokens();
refreshPasskeys();
}, [isSettingsModalOpen, refreshPasskeys, refreshWebdavTokens]);
useEffect(() => {
if (!isSettingsModalOpen) {
setWebdavTokenSecret(null);
}
}, [isSettingsModalOpen]);
const handleTagUpdate = useCallback(
async (tagId, changes) => {
if (!tagId) {
@@ -4059,83 +4038,34 @@ const AppLayout = () => {
}
}, [creatingFolder, handleFolderCreate, setStatusMessage]);
const openTagsModal = useCallback(() => {
setCorrespondentsModalOpen(false);
setDocumentTypesModalOpen(false);
setTagsModalOpen(true);
}, []);
const {
managementModals,
openTagsModal,
openCorrespondentsModal,
openDocumentTypesModal,
} = useManagementModals({
locationPathname: location.pathname,
tags,
refreshTags,
onTagCreate: handleTagCreate,
onTagUpdate: handleTagUpdate,
onTagDelete: handleTagDelete,
correspondents,
refreshCorrespondents,
onCorrespondentCreate: handleCorrespondentCreate,
onCorrespondentUpdate: handleCorrespondentUpdate,
onCorrespondentDelete: handleCorrespondentDelete,
documentTypes,
refreshDocumentTypes,
onDocumentTypeCreate: handleDocumentTypeCreate,
onDocumentTypeUpdate: handleDocumentTypeUpdate,
onDocumentTypeDelete: handleDocumentTypeDelete,
setStatusMessage,
});
const closeTagsModal = useCallback(() => {
setTagsModalOpen(false);
}, []);
const openCorrespondentsModal = useCallback(() => {
setTagsModalOpen(false);
setCorrespondentsModalOpen(true);
setDocumentTypesModalOpen(false);
}, []);
const closeCorrespondentsModal = useCallback(() => {
setCorrespondentsModalOpen(false);
}, []);
const openDocumentTypesModal = useCallback(() => {
setTagsModalOpen(false);
setCorrespondentsModalOpen(false);
setDocumentTypesModalOpen(true);
}, []);
const closeDocumentTypesModal = useCallback(() => {
setDocumentTypesModalOpen(false);
}, []);
const openSettingsModal = useCallback(() => {
setSettingsModalOpen(true);
}, []);
const closeSettingsModal = useCallback(() => {
setSettingsModalOpen(false);
}, []);
useEffect(() => {
setTagsModalOpen(false);
setCorrespondentsModalOpen(false);
setDocumentTypesModalOpen(false);
setSettingsModalOpen(false);
}, [location.pathname]);
useEffect(() => {
if (!isTagsModalOpen && !isCorrespondentsModalOpen && !isDocumentTypesModalOpen && !isSettingsModalOpen) {
return;
}
const handleKeyDown = (event) => {
if (event.key === 'Escape') {
event.preventDefault();
if (isTagsModalOpen) {
closeTagsModal();
} else if (isCorrespondentsModalOpen) {
closeCorrespondentsModal();
} else if (isDocumentTypesModalOpen) {
closeDocumentTypesModal();
} else if (isSettingsModalOpen) {
closeSettingsModal();
}
}
};
window.addEventListener('keydown', handleKeyDown);
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}, [
isTagsModalOpen,
isCorrespondentsModalOpen,
isDocumentTypesModalOpen,
isSettingsModalOpen,
closeTagsModal,
closeCorrespondentsModal,
closeDocumentTypesModal,
closeSettingsModal,
]);
const openSettings = useCallback(() => {
navigate('/settings');
}, [navigate]);
useEffect(() => {
if (!token) return undefined;
@@ -5216,7 +5146,7 @@ const AppLayout = () => {
tenants: tenantOptions,
activeTenantId: currentTenantId,
onSelectTenant: handleTenantSelect,
onOpenSettings: openSettingsModal,
onOpenSettings: openSettings,
}),
[
activeCorrespondentFilters,
@@ -5237,7 +5167,7 @@ const AppLayout = () => {
handleSearchSubmit,
handleTenantSelect,
loading,
openSettingsModal,
openSettings,
previewActive,
searchQuery,
draggedFolderId,
@@ -5401,6 +5331,23 @@ const AppLayout = () => {
handleDocumentTypeSet,
handleBulkDocumentTypeSet,
handleBulkDocumentTypeClear,
webdavTokens,
webdavTokensLoading,
creatingWebdavToken,
deletingWebdavTokenId,
refreshWebdavTokens,
createWebdavToken,
deleteWebdavToken,
webdavTokenSecret,
dismissCreatedWebdavToken,
passkeys,
passkeysSupported,
passkeysLoading,
registeringPasskey,
revokingPasskeyId,
refreshPasskeys,
registerPasskey,
revokePasskey,
previewActive,
previewWorkspaceDocument,
previewWorkspaceEntry,
@@ -5420,7 +5367,7 @@ const AppLayout = () => {
openTagsModal,
openCorrespondentsModal,
openDocumentTypesModal,
openSettingsModal,
openSettings,
detailPanelOpen,
setDetailPanelOpen,
}),
@@ -5455,6 +5402,23 @@ const AppLayout = () => {
handleDocumentTypeSet,
handleBulkDocumentTypeSet,
handleBulkDocumentTypeClear,
webdavTokens,
webdavTokensLoading,
creatingWebdavToken,
deletingWebdavTokenId,
refreshWebdavTokens,
createWebdavToken,
deleteWebdavToken,
webdavTokenSecret,
dismissCreatedWebdavToken,
passkeys,
passkeysSupported,
passkeysLoading,
registeringPasskey,
revokingPasskeyId,
refreshPasskeys,
registerPasskey,
revokePasskey,
previewActive,
previewWorkspaceDocument,
previewWorkspaceEntry,
@@ -5473,7 +5437,7 @@ const AppLayout = () => {
openTagsModal,
openCorrespondentsModal,
openDocumentTypesModal,
openSettingsModal,
openSettings,
detailPanelOpen,
setDetailPanelOpen,
],
@@ -5502,131 +5466,7 @@ const AppLayout = () => {
folderName={dropOverlayState.folderName}
/>
<Outlet />
{isTagsModalOpen && (
<div
className="modal-backdrop"
role="presentation"
onClick={closeTagsModal}
>
<div
className="modal modal--panel"
role="dialog"
aria-modal="true"
aria-labelledby="tags-modal-title"
onClick={(event) => event.stopPropagation()}
>
<div className="panel-modal__header">
<h3 id="tags-modal-title">Manage Tags</h3>
<button type="button" className="secondary" onClick={closeTagsModal}>
Close
</button>
</div>
<div className="panel-modal__body">
<TagsPanel
tags={tags}
onRefresh={refreshTags}
onCreateTag={handleTagCreate}
onUpdateTag={handleTagUpdate}
onDeleteTag={handleTagDelete}
onNotify={setStatusMessage}
/>
</div>
</div>
</div>
)}
{isCorrespondentsModalOpen && (
<div
className="modal-backdrop"
role="presentation"
onClick={closeCorrespondentsModal}
>
<div
className="modal modal--panel"
role="dialog"
aria-modal="true"
aria-labelledby="correspondents-modal-title"
onClick={(event) => event.stopPropagation()}
>
<div className="panel-modal__header">
<h3 id="correspondents-modal-title">Manage Correspondents</h3>
<button
type="button"
className="secondary"
onClick={closeCorrespondentsModal}
>
Close
</button>
</div>
<div className="panel-modal__body">
<CorrespondentsPanel
correspondents={correspondents}
onRefresh={refreshCorrespondents}
onCreate={handleCorrespondentCreate}
onUpdate={handleCorrespondentUpdate}
onDelete={handleCorrespondentDelete}
onNotify={setStatusMessage}
/>
</div>
</div>
</div>
)}
{isDocumentTypesModalOpen && (
<div
className="modal-backdrop"
role="presentation"
onClick={closeDocumentTypesModal}
>
<div
className="modal modal--panel"
role="dialog"
aria-modal="true"
aria-labelledby="document-types-modal-title"
onClick={(event) => event.stopPropagation()}
>
<div className="panel-modal__header">
<h3 id="document-types-modal-title">Manage Document Types</h3>
<button
type="button"
className="secondary"
onClick={closeDocumentTypesModal}
>
Close
</button>
</div>
<div className="panel-modal__body">
<DocumentTypesPanel
documentTypes={documentTypes}
onRefresh={refreshDocumentTypes}
onCreate={handleDocumentTypeCreate}
onUpdate={handleDocumentTypeUpdate}
onDelete={handleDocumentTypeDelete}
onNotify={setStatusMessage}
/>
</div>
</div>
</div>
)}
<SettingsModal
open={isSettingsModalOpen}
onClose={closeSettingsModal}
tokens={webdavTokens}
loading={webdavTokensLoading}
creating={creatingWebdavToken}
deletingId={deletingWebdavTokenId}
onRefresh={refreshWebdavTokens}
onCreate={createWebdavToken}
onDelete={deleteWebdavToken}
createdToken={webdavTokenSecret}
onDismissCreatedToken={dismissCreatedWebdavToken}
passkeys={passkeys}
passkeysSupported={passkeysSupported}
passkeysLoading={passkeysLoading}
registeringPasskey={registeringPasskey}
revokingPasskeyId={revokingPasskeyId}
onRefreshPasskeys={refreshPasskeys}
onRegisterPasskey={registerPasskey}
onRevokePasskey={revokePasskey}
/>
{managementModals}
</div>
</AppShellContext.Provider>
);