This commit is contained in:
2025-10-29 00:40:13 +01:00
parent d9b2297eca
commit 4b18429945
6 changed files with 622 additions and 47 deletions
+114 -1
View File
@@ -539,6 +539,11 @@ const AppLayout = () => {
const [searchResults, setSearchResults] = useState(null);
const [tags, setTags] = useState([]);
const [correspondents, setCorrespondents] = useState([]);
const [webdavTokens, setWebdavTokens] = useState([]);
const [webdavTokensLoading, setWebdavTokensLoading] = useState(false);
const [creatingWebdavToken, setCreatingWebdavToken] = useState(false);
const [deletingWebdavTokenId, setDeletingWebdavTokenId] = useState(null);
const [webdavTokenSecret, setWebdavTokenSecret] = useState(null);
const [searchQuery, setSearchQuery] = useState('');
const [activeTagFilters, setActiveTagFilters] = useState([]);
const [activeCorrespondentFilters, setActiveCorrespondentFilters] = useState([]);
@@ -743,6 +748,11 @@ const AppLayout = () => {
setSearchResults(null);
setTags([]);
setCorrespondents([]);
setWebdavTokens([]);
setWebdavTokensLoading(false);
setCreatingWebdavToken(false);
setDeletingWebdavTokenId(null);
setWebdavTokenSecret(null);
setSearchQuery('');
setActiveTagFilters([]);
setDropOverlayState({ active: false, folderName: DEFAULT_FOLDER_NAME });
@@ -1734,6 +1744,97 @@ const AppLayout = () => {
}
}, [api, notifyApiError]);
const refreshWebdavTokens = useCallback(async () => {
if (!token) {
return;
}
setWebdavTokensLoading(true);
try {
const { data } = await api.get('/profile/webdav-tokens');
setWebdavTokens(Array.isArray(data) ? data : []);
} catch (error) {
notifyApiError(error, 'Failed to load WebDAV tokens.');
} finally {
setWebdavTokensLoading(false);
}
}, [api, notifyApiError, token]);
const createWebdavToken = useCallback(
async ({ label, expires_at } = {}) => {
if (creatingWebdavToken) {
return false;
}
setCreatingWebdavToken(true);
try {
const payload = {};
if (label) {
payload.label = label;
}
if (expires_at) {
payload.expires_at = expires_at;
}
const { data } = await api.post('/profile/webdav-tokens', payload);
if (data?.token_info) {
setWebdavTokens((previous) => {
const filtered = previous.filter((entry) => entry.id !== data.token_info.id);
return [data.token_info, ...filtered];
});
} else {
await refreshWebdavTokens();
}
if (data?.token) {
setWebdavTokenSecret(data.token);
}
setStatusMessage('WebDAV token created.', 'success');
return data;
} catch (error) {
notifyApiError(error, 'Failed to create WebDAV token.');
return false;
} finally {
setCreatingWebdavToken(false);
}
},
[api, creatingWebdavToken, notifyApiError, refreshWebdavTokens, setStatusMessage],
);
const deleteWebdavToken = useCallback(
async (tokenId) => {
if (!tokenId) {
return false;
}
setDeletingWebdavTokenId(tokenId);
try {
await api.delete(`/profile/webdav-tokens/${tokenId}`);
setWebdavTokens((previous) => previous.filter((entry) => entry.id !== tokenId));
setStatusMessage('WebDAV token revoked.', 'success');
return true;
} catch (error) {
notifyApiError(error, 'Failed to revoke WebDAV token.');
return false;
} finally {
setDeletingWebdavTokenId(null);
}
},
[api, notifyApiError, setStatusMessage],
);
const dismissCreatedWebdavToken = useCallback(() => {
setWebdavTokenSecret(null);
}, []);
useEffect(() => {
if (!isSettingsModalOpen) {
return;
}
refreshWebdavTokens();
}, [isSettingsModalOpen, refreshWebdavTokens]);
useEffect(() => {
if (!isSettingsModalOpen) {
setWebdavTokenSecret(null);
}
}, [isSettingsModalOpen]);
const handleTagUpdate = useCallback(
async (tagId, changes) => {
if (!tagId) {
@@ -5404,7 +5505,19 @@ const AppLayout = () => {
</div>
</div>
)}
<SettingsModal open={isSettingsModalOpen} onClose={closeSettingsModal} />
<SettingsModal
open={isSettingsModalOpen}
onClose={closeSettingsModal}
tokens={webdavTokens}
loading={webdavTokensLoading}
creating={creatingWebdavToken}
deletingId={deletingWebdavTokenId}
onRefresh={refreshWebdavTokens}
onCreate={createWebdavToken}
onDelete={deleteWebdavToken}
createdToken={webdavTokenSecret}
onDismissCreatedToken={dismissCreatedWebdavToken}
/>
</div>
</AppShellContext.Provider>
);