Add button in admin backend to cleanup revisions of a specific pad

This commit is contained in:
Stefan Müller 2024-09-10 16:55:14 +02:00
parent 491d4af19e
commit 593d1021b6
6 changed files with 64 additions and 4 deletions

View file

@ -14,6 +14,7 @@
"ep_adminpads2_autoupdate.title": "Aktiviert oder deaktiviert automatische Aktualisierungen für die aktuelle Abfrage.",
"ep_adminpads2_confirm": "Willst du das Pad {{padID}} wirklich löschen?",
"ep_adminpads2_delete.value": "Löschen",
"ep_adminpads2_cleanup": "Historie aufräumen",
"ep_adminpads2_last-edited": "Zuletzt bearbeitet",
"ep_adminpads2_loading": "Lädt...",
"ep_adminpads2_manage-pads": "Pads verwalten",

View file

@ -4,6 +4,7 @@
"ep_adminpads2_autoupdate.title": "Enables or disables automatic updates for the current query.",
"ep_adminpads2_confirm": "Do you really want to delete the pad {{padID}}?",
"ep_adminpads2_delete.value": "Delete",
"ep_adminpads2_cleanup": "Cleanup revisions",
"ep_adminpads2_last-edited": "Last edited",
"ep_adminpads2_loading": "Loading…",
"ep_adminpads2_manage-pads": "Manage pads",

View file

@ -6,7 +6,7 @@ import {useDebounce} from "../utils/useDebounce.ts";
import {determineSorting} from "../utils/sorting.ts";
import * as Dialog from "@radix-ui/react-dialog";
import {IconButton} from "../components/IconButton.tsx";
import {ChevronLeft, ChevronRight, Eye, Trash2} from "lucide-react";
import {ChevronLeft, ChevronRight, Eye, Trash2, FileStack} from "lucide-react";
import {SearchField} from "../components/SearchField.tsx";
export const PadPage = ()=>{
@ -68,12 +68,30 @@ export const PadPage = ()=>{
results: newPads
})
})
settingsSocket.on('results:cleanupPadRevisions', (data)=>{
let newPads = useStore.getState().pads?.results ?? []
newPads.forEach((pad)=>{
if (pad.padName === data.padId) {
pad.revisionNumber = data.keepRevisions
}
})
useStore.getState().setPads({
results: newPads,
total: useStore.getState().pads!.total
})
})
}, [settingsSocket, pads]);
const deletePad = (padID: string)=>{
settingsSocket?.emit('deletePad', padID)
}
const cleanupPad = (padID: string)=>{
settingsSocket?.emit('cleanupPadRevisions', padID)
}
return <div>
@ -150,6 +168,9 @@ export const PadPage = ()=>{
setPadToDelete(pad.padName)
setDeleteDialog(true)
}}/>
<IconButton icon={<FileStack/>} title={<Trans i18nKey="ep_admin_pads:ep_adminpads2_cleanup"/>} onClick={()=>{
cleanupPad(pad.padName)
}}/>
<IconButton icon={<Eye/>} title="view" onClick={()=>window.open(`/p/${pad.padName}`, '_blank')}/>
</div>
</td>

View file

@ -13,6 +13,7 @@ const settings = require('../../utils/Settings');
const UpdateCheck = require('../../utils/UpdateCheck');
const padManager = require('../../db/PadManager');
const api = require('../../db/API');
const cleanup = require('../../utils/Cleanup');
const queryPadLimit = 12;
@ -252,6 +253,26 @@ exports.socketio = (hookName: string, {io}: any) => {
}
})
socket.on('cleanupPadRevisions', async (padId: string) => {
const padExists = await padManager.doesPadExists(padId);
if (padExists) {
logger.info(`Cleanup pad revisions: ${padId}`);
try {
const result = await cleanup.deleteRevisions(padId, settings.cleanup.keepRevisions)
if (result) {
socket.emit('results:cleanupPadRevisions', {
padId: padId,
keepRevisions: settings.cleanup.keepRevisions,
});
logger.info('successful cleaned up pad: ', padId)
}
} catch (err: any) {
logger.error(`Error in pad ${padId}: ${err.stack || err}`);
return;
}
}
})
socket.on('restartServer', async () => {
logger.info('Admin request to restart server through a socket on /admin/settings');
settings.reloadSettings();

View file

@ -39,7 +39,7 @@ const createRevision = async (aChangeset: AChangeSet, timestamp: number, isKeyRe
};
}
exports.deleteRevisions = async (padId: string, keepRevisions: number): Promise<void> => {
exports.deleteRevisions = async (padId: string, keepRevisions: number): Promise<boolean> => {
logger.debug('Start cleanup revisions', padId)
@ -48,6 +48,11 @@ exports.deleteRevisions = async (padId: string, keepRevisions: number): Promise<
logger.debug('Initial pad is valid')
if (pad.head < keepRevisions) {
logger.debug('Pad has not enough revisions')
return false
}
padMessageHandler.kickSessionsFromPad(padId)
const cleanupUntilRevision = pad.head - keepRevisions
@ -116,6 +121,8 @@ exports.deleteRevisions = async (padId: string, keepRevisions: number): Promise<
let newPad = await padManager.getPad(padId);
await newPad.check();
return true
}
exports.checkTodos = async () => {
@ -139,8 +146,10 @@ exports.checkTodos = async () => {
}
try {
await exports.deleteRevisions(padId, settings.keepRevisions)
logger.info('successful cleaned up pad: ', padId)
const result = await exports.deleteRevisions(padId, settings.keepRevisions)
if (result) {
logger.info('successful cleaned up pad: ', padId)
}
} catch (err: any) {
logger.error(`Error in pad ${padId}: ${err.stack || err}`);
return;

View file

@ -380,6 +380,13 @@ exports.sso = {
*/
exports.showSettingsInAdminPage = true;
/*
* Settings for cleanup of pads
*/
exports.cleanup = {
keepRevisions: 100,
}
/*
* By default, when caret is moved out of viewport, it scrolls the minimum
* height needed to make this line visible.