mirror of
https://github.com/zadam/trilium.git
synced 2025-11-14 01:05:49 +01:00
erasing unused attachments
This commit is contained in:
@@ -28,6 +28,7 @@ import ConsistencyChecksOptions from "./options/advanced/consistency_checks.js";
|
||||
import VacuumDatabaseOptions from "./options/advanced/vacuum_database.js";
|
||||
import DatabaseAnonymizationOptions from "./options/advanced/database_anonymization.js";
|
||||
import BackendLogWidget from "./content/backend_log.js";
|
||||
import AttachmentErasureTimeoutOptions from "./options/other/attachment_erasure_timeout.js";
|
||||
|
||||
const TPL = `<div class="note-detail-content-widget note-detail-printable">
|
||||
<style>
|
||||
@@ -77,6 +78,7 @@ const CONTENT_WIDGETS = {
|
||||
_optionsOther: [
|
||||
TrayOptions,
|
||||
NoteErasureTimeoutOptions,
|
||||
AttachmentErasureTimeoutOptions,
|
||||
NoteRevisionsSnapshotIntervalOptions,
|
||||
NetworkConnectionsOptions
|
||||
],
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import OptionsWidget from "../options_widget.js";
|
||||
import server from "../../../../services/server.js";
|
||||
import toastService from "../../../../services/toast.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="options-section">
|
||||
<h4>Attachment erasure timeout</h4>
|
||||
|
||||
<p>Attachment images get automatically deleted (and erased) if they are not referenced by their note anymore after a defined time out.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Erase image attachments after X seconds of not being used in its note</label>
|
||||
<input class="erase-unused-attachments-after-time-in-seconds form-control" type="number" min="0">
|
||||
</div>
|
||||
|
||||
<p>You can also trigger erasing manually (without considering the timeout defined above):</p>
|
||||
|
||||
<button class="erase-unused-attachments-now-button btn">Erase unused attachment notes now</button>
|
||||
</div>`;
|
||||
|
||||
export default class AttachmentErasureTimeoutOptions extends OptionsWidget {
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
this.$eraseUnusedAttachmentsAfterTimeInSeconds = this.$widget.find(".erase-unused-attachments-after-time-in-seconds");
|
||||
this.$eraseUnusedAttachmentsAfterTimeInSeconds.on('change', () => this.updateOption('eraseUnusedImageAttachmentsAfterSeconds', this.$eraseUnusedAttachmentsAfterTimeInSeconds.val()));
|
||||
|
||||
this.$eraseDeletedNotesButton = this.$widget.find(".erase-unused-attachments-now-button");
|
||||
this.$eraseDeletedNotesButton.on('click', () => {
|
||||
server.post('notes/erase-unused-attachments-now').then(() => {
|
||||
toastService.showMessage("Unused image attachments have been erased.");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async optionsLoaded(options) {
|
||||
this.$eraseUnusedAttachmentsAfterTimeInSeconds.val(options.eraseUnusedImageAttachmentsAfterSeconds);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ const TPL = `
|
||||
<input class="erase-entities-after-time-in-seconds form-control" type="number" min="0">
|
||||
</div>
|
||||
|
||||
<p>You can also trigger erasing manually:</p>
|
||||
<p>You can also trigger erasing manually (without considering the timeout defined above):</p>
|
||||
|
||||
<button class="erase-deleted-notes-now-button btn">Erase deleted notes now</button>
|
||||
</div>`;
|
||||
|
||||
@@ -982,7 +982,7 @@ button.close:hover {
|
||||
}
|
||||
|
||||
.options-section h4 {
|
||||
margin-top: 15px;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
|
||||
@@ -168,6 +168,10 @@ function eraseDeletedNotesNow() {
|
||||
noteService.eraseDeletedNotesNow();
|
||||
}
|
||||
|
||||
function eraseUnusedAttachmentsNow() {
|
||||
noteService.eraseUnusedAttachmentsNow();
|
||||
}
|
||||
|
||||
function getDeleteNotesPreview(req) {
|
||||
const {branchIdsToDelete, deleteAllClones} = req.body;
|
||||
|
||||
@@ -275,6 +279,7 @@ module.exports = {
|
||||
changeTitle,
|
||||
duplicateSubtree,
|
||||
eraseDeletedNotesNow,
|
||||
eraseUnusedAttachmentsNow,
|
||||
getDeleteNotesPreview,
|
||||
uploadModifiedFile,
|
||||
forceSaveNoteRevision
|
||||
|
||||
@@ -293,6 +293,7 @@ function register(app) {
|
||||
|
||||
apiRoute(PST, '/api/relation-map', relationMapApiRoute.getRelationMap);
|
||||
apiRoute(PST, '/api/notes/erase-deleted-notes-now', notesApiRoute.eraseDeletedNotesNow);
|
||||
apiRoute(PST, '/api/notes/erase-unused-attachments-now', notesApiRoute.eraseUnusedAttachmentsNow);
|
||||
apiRoute(GET, '/api/similar-notes/:noteId', similarNotesRoute.getSimilarNotes);
|
||||
apiRoute(GET, '/api/backend-log', backendLogRoute.getBackendLog);
|
||||
apiRoute(GET, '/api/stats/note-size/:noteId', statsRoute.getNoteSize);
|
||||
|
||||
@@ -899,23 +899,33 @@ function eraseDeletedEntities(eraseEntitiesAfterTimeInSeconds = null) {
|
||||
}
|
||||
|
||||
function eraseNotesWithDeleteId(deleteId) {
|
||||
const noteIdsToErase = sql.getColumn("SELECT noteId FROM notes WHERE deleteId = ?", [deleteId]);
|
||||
const noteIdsToErase = sql.getColumn("SELECT noteId FROM notes WHERE isDeleted = 1 AND deleteId = ?", [deleteId]);
|
||||
|
||||
eraseNotes(noteIdsToErase);
|
||||
|
||||
const branchIdsToErase = sql.getColumn("SELECT branchId FROM branches WHERE deleteId = ?", [deleteId]);
|
||||
const branchIdsToErase = sql.getColumn("SELECT branchId FROM branches WHERE isDeleted = 1 AND deleteId = ?", [deleteId]);
|
||||
|
||||
eraseBranches(branchIdsToErase);
|
||||
|
||||
const attributeIdsToErase = sql.getColumn("SELECT attributeId FROM attributes WHERE deleteId = ?", [deleteId]);
|
||||
const attributeIdsToErase = sql.getColumn("SELECT attributeId FROM attributes WHERE isDeleted = 1 AND deleteId = ?", [deleteId]);
|
||||
|
||||
eraseAttributes(attributeIdsToErase);
|
||||
|
||||
const attachmentIdsToErase = sql.getColumn("SELECT attachmentId FROM attachments WHERE isDeleted = 1 AND deleteId = ?", [deleteId]);
|
||||
|
||||
eraseAttachments(attachmentIdsToErase);
|
||||
|
||||
eraseUnusedBlobs();
|
||||
}
|
||||
|
||||
function eraseDeletedNotesNow() {
|
||||
eraseDeletedEntities(0);
|
||||
}
|
||||
|
||||
function eraseUnusedAttachmentsNow() {
|
||||
eraseScheduledAttachments(0);
|
||||
}
|
||||
|
||||
// do a replace in str - all keys should be replaced by the corresponding values
|
||||
function replaceByMap(str, mapObj) {
|
||||
const re = new RegExp(Object.keys(mapObj).join("|"),"g");
|
||||
@@ -962,7 +972,7 @@ function duplicateSubtreeWithoutRoot(origNoteId, newNoteId) {
|
||||
|
||||
function duplicateSubtreeInner(origNote, origBranch, newParentNoteId, noteIdMapping) {
|
||||
if (origNote.isProtected && !protectedSessionService.isProtectedSessionAvailable()) {
|
||||
throw new Error(`Cannot duplicate note=${origNote.noteId} because it is protected and protected session is not available. Enter protected session and try again.`);
|
||||
throw new Error(`Cannot duplicate note '${origNote.noteId}' because it is protected and protected session is not available. Enter protected session and try again.`);
|
||||
}
|
||||
|
||||
const newNoteId = noteIdMapping[origNote.noteId];
|
||||
@@ -1047,9 +1057,12 @@ function getNoteIdMapping(origNote) {
|
||||
return noteIdMapping;
|
||||
}
|
||||
|
||||
function eraseScheduledAttachments() {
|
||||
const eraseIntervalSeconds = optionService.getOptionInt('eraseUnusedImageAttachmentsAfterSeconds');
|
||||
const cutOffDate = dateUtils.utcDateTimeStr(new Date(Date.now() - (eraseIntervalSeconds * 1000)));
|
||||
function eraseScheduledAttachments(eraseUnusedImageAttachmentsAfterSeconds = null) {
|
||||
if (eraseUnusedImageAttachmentsAfterSeconds === null) {
|
||||
eraseUnusedImageAttachmentsAfterSeconds = optionService.getOptionInt('eraseUnusedImageAttachmentsAfterSeconds');
|
||||
}
|
||||
|
||||
const cutOffDate = dateUtils.utcDateTimeStr(new Date(Date.now() - (eraseUnusedImageAttachmentsAfterSeconds * 1000)));
|
||||
const attachmentIdsToErase = sql.getColumn('SELECT attachmentId FROM attachments WHERE utcDateScheduledForErasureSince < ?', [cutOffDate]);
|
||||
|
||||
eraseAttachments(attachmentIdsToErase);
|
||||
@@ -1075,6 +1088,7 @@ module.exports = {
|
||||
getUndeletedParentBranchIds,
|
||||
triggerNoteTitleChanged,
|
||||
eraseDeletedNotesNow,
|
||||
eraseUnusedAttachmentsNow,
|
||||
eraseNotesWithDeleteId,
|
||||
saveNoteRevisionIfNeeded,
|
||||
downloadImages,
|
||||
|
||||
Reference in New Issue
Block a user