mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	undelete note WIP
This commit is contained in:
		
							
								
								
									
										81
									
								
								db/migrations/0156__add_deleteId.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								db/migrations/0156__add_deleteId.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| CREATE TABLE IF NOT EXISTS "notes_mig" ( | ||||
|                                            `noteId`	TEXT NOT NULL, | ||||
|                                            `title`	TEXT NOT NULL DEFAULT "note", | ||||
|                                            `contentLength`	INT NOT NULL, | ||||
|                                            `isProtected`	INT NOT NULL DEFAULT 0, | ||||
|                                            `type` TEXT NOT NULL DEFAULT 'text', | ||||
|                                            `mime` TEXT NOT NULL DEFAULT 'text/html', | ||||
|                                            `hash` TEXT DEFAULT "" NOT NULL, | ||||
|                                            `isDeleted`	INT NOT NULL DEFAULT 0, | ||||
|                                            `deleteId`   TEXT DEFAULT NULL, | ||||
|                                            `isErased`	INT NOT NULL DEFAULT 0, | ||||
|                                            `dateCreated`	TEXT NOT NULL, | ||||
|                                            `dateModified`	TEXT NOT NULL, | ||||
|                                            `utcDateCreated`	TEXT NOT NULL, | ||||
|                                            `utcDateModified`	TEXT NOT NULL, | ||||
|                                            PRIMARY KEY(`noteId`)); | ||||
|  | ||||
| INSERT INTO notes_mig (noteId, title, contentLength, isProtected, type, mime, hash, isDeleted, isErased, dateCreated, dateModified, utcDateCreated, utcDateModified) | ||||
| SELECT noteId, title, -1, isProtected, type, mime, hash, isDeleted, isErased, dateCreated, dateModified, utcDateCreated, utcDateModified FROM notes; | ||||
|  | ||||
| DROP TABLE notes; | ||||
| ALTER TABLE notes_mig RENAME TO notes; | ||||
|  | ||||
| CREATE INDEX `IDX_notes_isDeleted` ON `notes` (`isDeleted`); | ||||
| CREATE INDEX `IDX_notes_title` ON `notes` (`title`); | ||||
| CREATE INDEX `IDX_notes_type` ON `notes` (`type`); | ||||
| CREATE INDEX `IDX_notes_dateCreated` ON `notes` (`dateCreated`); | ||||
| CREATE INDEX `IDX_notes_dateModified` ON `notes` (`dateModified`); | ||||
| CREATE INDEX `IDX_notes_utcDateModified` ON `notes` (`utcDateModified`); | ||||
| CREATE INDEX `IDX_notes_utcDateCreated` ON `notes` (`utcDateCreated`); | ||||
|  | ||||
| CREATE TABLE IF NOT EXISTS "branches_mig" ( | ||||
|                                           `branchId`	TEXT NOT NULL, | ||||
|                                           `noteId`	TEXT NOT NULL, | ||||
|                                           `parentNoteId`	TEXT NOT NULL, | ||||
|                                           `notePosition`	INTEGER NOT NULL, | ||||
|                                           `prefix`	TEXT, | ||||
|                                           `isExpanded`	INTEGER NOT NULL DEFAULT 0, | ||||
|                                           `isDeleted`	INTEGER NOT NULL DEFAULT 0, | ||||
|                                           `deleteId`    TEXT DEFAULT NULL, | ||||
|                                           `utcDateModified`	TEXT NOT NULL, | ||||
|                                           utcDateCreated TEXT NOT NULL, | ||||
|                                           hash TEXT DEFAULT "" NOT NULL, | ||||
|                                           PRIMARY KEY(`branchId`)); | ||||
|  | ||||
| INSERT INTO branches_mig (branchId, noteId, parentNoteId, notePosition, prefix, isExpanded, isDeleted, utcDateModified, utcDateCreated, hash) | ||||
|     SELECT branchId, noteId, parentNoteId, notePosition, prefix, isExpanded, isDeleted, utcDateModified, utcDateCreated, hash FROM branches; | ||||
|  | ||||
| DROP TABLE branches; | ||||
| ALTER TABLE branches_mig RENAME TO branches; | ||||
|  | ||||
| CREATE INDEX `IDX_branches_noteId_parentNoteId` ON `branches` (`noteId`,`parentNoteId`); | ||||
| CREATE INDEX IDX_branches_parentNoteId ON branches (parentNoteId); | ||||
|  | ||||
| CREATE TABLE IF NOT EXISTS "attributes_mig" | ||||
| ( | ||||
|     attributeId      TEXT not null primary key, | ||||
|     noteId       TEXT not null, | ||||
|     type         TEXT not null, | ||||
|     name         TEXT not null, | ||||
|     value        TEXT default '' not null, | ||||
|     position     INT  default 0 not null, | ||||
|     utcDateCreated  TEXT not null, | ||||
|     utcDateModified TEXT not null, | ||||
|     isDeleted    INT  not null, | ||||
|     `deleteId`    TEXT DEFAULT NULL, | ||||
|     hash         TEXT default "" not null, | ||||
|     isInheritable int DEFAULT 0 NULL); | ||||
|  | ||||
| INSERT INTO attributes_mig (attributeId, noteId, type, name, value, position, utcDateCreated, utcDateModified, isDeleted, hash, isInheritable) | ||||
| SELECT attributeId, noteId, type, name, value, position, utcDateCreated, utcDateModified, isDeleted, hash, isInheritable FROM attributes; | ||||
|  | ||||
| DROP TABLE attributes; | ||||
| ALTER TABLE attributes_mig RENAME TO attributes; | ||||
|  | ||||
| CREATE INDEX IDX_attributes_name_value | ||||
|     on attributes (name, value); | ||||
| CREATE INDEX IDX_attributes_noteId_index | ||||
|     on attributes (noteId); | ||||
| CREATE INDEX IDX_attributes_value_index | ||||
|     on attributes (value); | ||||
							
								
								
									
										113
									
								
								db/schema.sql
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								db/schema.sql
									
									
									
									
									
								
							| @@ -27,19 +27,6 @@ CREATE TABLE IF NOT EXISTS "options" | ||||
|   utcDateCreated TEXT not null, | ||||
|   utcDateModified TEXT NOT NULL | ||||
| ); | ||||
| CREATE TABLE IF NOT EXISTS "attributes" | ||||
| ( | ||||
|   attributeId      TEXT not null primary key, | ||||
|   noteId       TEXT not null, | ||||
|   type         TEXT not null, | ||||
|   name         TEXT not null, | ||||
|   value        TEXT default '' not null, | ||||
|   position     INT  default 0 not null, | ||||
|   utcDateCreated  TEXT not null, | ||||
|   utcDateModified TEXT not null, | ||||
|   isDeleted    INT  not null, | ||||
|   hash         TEXT default "" not null, | ||||
|   isInheritable int DEFAULT 0 NULL); | ||||
| CREATE UNIQUE INDEX `IDX_sync_entityName_entityId` ON `sync` ( | ||||
|                                                               `entityName`, | ||||
|                                                               `entityId` | ||||
| @@ -47,12 +34,6 @@ CREATE UNIQUE INDEX `IDX_sync_entityName_entityId` ON `sync` ( | ||||
| CREATE INDEX `IDX_sync_utcSyncDate` ON `sync` ( | ||||
|                                             `utcSyncDate` | ||||
|   ); | ||||
| CREATE INDEX IDX_attributes_name_value | ||||
|   on attributes (name, value); | ||||
| CREATE INDEX IDX_attributes_noteId_index | ||||
|   on attributes (noteId); | ||||
| CREATE INDEX IDX_attributes_value_index | ||||
|   on attributes (value); | ||||
| CREATE TABLE IF NOT EXISTS "note_contents" ( | ||||
|                                                    `noteId`	TEXT NOT NULL, | ||||
|                                                    `content`	TEXT NULL DEFAULT NULL, | ||||
| @@ -68,46 +49,10 @@ CREATE TABLE recent_notes | ||||
|     utcDateCreated TEXT not null, | ||||
|     isDeleted INT | ||||
| ); | ||||
| CREATE TABLE IF NOT EXISTS "branches" ( | ||||
|                                           `branchId`	TEXT NOT NULL, | ||||
|                                           `noteId`	TEXT NOT NULL, | ||||
|                                           `parentNoteId`	TEXT NOT NULL, | ||||
|                                           `notePosition`	INTEGER NOT NULL, | ||||
|                                           `prefix`	TEXT, | ||||
|                                           `isExpanded`	INTEGER NOT NULL DEFAULT 0, | ||||
|                                           `isDeleted`	INTEGER NOT NULL DEFAULT 0, | ||||
|                                           `utcDateModified`	TEXT NOT NULL, | ||||
|                                           utcDateCreated TEXT NOT NULL, | ||||
|                                           hash TEXT DEFAULT "" NOT NULL, | ||||
|                                           PRIMARY KEY(`branchId`)); | ||||
| CREATE INDEX `IDX_branches_noteId_parentNoteId` ON `branches` (`noteId`,`parentNoteId`); | ||||
| CREATE INDEX IDX_branches_parentNoteId ON branches (parentNoteId); | ||||
| CREATE TABLE IF NOT EXISTS "note_revision_contents" (`noteRevisionId`	TEXT NOT NULL PRIMARY KEY, | ||||
|                                                  `content`	TEXT, | ||||
|                                                  hash TEXT DEFAULT '' NOT NULL, | ||||
|                                                  `utcDateModified` TEXT NOT NULL); | ||||
| CREATE TABLE IF NOT EXISTS "notes" ( | ||||
|                                            `noteId`	TEXT NOT NULL, | ||||
|                                            `title`	TEXT NOT NULL DEFAULT "note", | ||||
|                                            `contentLength`	INT NOT NULL, | ||||
|                                            `isProtected`	INT NOT NULL DEFAULT 0, | ||||
|                                            `type` TEXT NOT NULL DEFAULT 'text', | ||||
|                                            `mime` TEXT NOT NULL DEFAULT 'text/html', | ||||
|                                            `hash` TEXT DEFAULT "" NOT NULL, | ||||
|                                            `isDeleted`	INT NOT NULL DEFAULT 0, | ||||
|                                            `isErased`	INT NOT NULL DEFAULT 0, | ||||
|                                            `dateCreated`	TEXT NOT NULL, | ||||
|                                            `dateModified`	TEXT NOT NULL, | ||||
|                                            `utcDateCreated`	TEXT NOT NULL, | ||||
|                                            `utcDateModified`	TEXT NOT NULL, | ||||
|                                            PRIMARY KEY(`noteId`)); | ||||
| CREATE INDEX `IDX_notes_isDeleted` ON `notes` (`isDeleted`); | ||||
| CREATE INDEX `IDX_notes_title` ON `notes` (`title`); | ||||
| CREATE INDEX `IDX_notes_type` ON `notes` (`type`); | ||||
| CREATE INDEX `IDX_notes_dateCreated` ON `notes` (`dateCreated`); | ||||
| CREATE INDEX `IDX_notes_dateModified` ON `notes` (`dateModified`); | ||||
| CREATE INDEX `IDX_notes_utcDateModified` ON `notes` (`utcDateModified`); | ||||
| CREATE INDEX `IDX_notes_utcDateCreated` ON `notes` (`utcDateCreated`); | ||||
| CREATE TABLE IF NOT EXISTS "note_revisions" (`noteRevisionId`	TEXT NOT NULL PRIMARY KEY, | ||||
|                                                  `noteId`	TEXT NOT NULL, | ||||
|                                                  `title`	TEXT, | ||||
| @@ -127,3 +72,61 @@ CREATE INDEX `IDX_note_revisions_utcDateCreated` ON `note_revisions` (`utcDateCr | ||||
| CREATE INDEX `IDX_note_revisions_utcDateLastEdited` ON `note_revisions` (`utcDateLastEdited`); | ||||
| CREATE INDEX `IDX_note_revisions_dateCreated` ON `note_revisions` (`dateCreated`); | ||||
| CREATE INDEX `IDX_note_revisions_dateLastEdited` ON `note_revisions` (`dateLastEdited`); | ||||
| CREATE TABLE IF NOT EXISTS "notes" ( | ||||
|                                            `noteId`	TEXT NOT NULL, | ||||
|                                            `title`	TEXT NOT NULL DEFAULT "note", | ||||
|                                            `contentLength`	INT NOT NULL, | ||||
|                                            `isProtected`	INT NOT NULL DEFAULT 0, | ||||
|                                            `type` TEXT NOT NULL DEFAULT 'text', | ||||
|                                            `mime` TEXT NOT NULL DEFAULT 'text/html', | ||||
|                                            `hash` TEXT DEFAULT "" NOT NULL, | ||||
|                                            `isDeleted`	INT NOT NULL DEFAULT 0, | ||||
|                                            `deleteId`   TEXT DEFAULT NULL, | ||||
|                                            `isErased`	INT NOT NULL DEFAULT 0, | ||||
|                                            `dateCreated`	TEXT NOT NULL, | ||||
|                                            `dateModified`	TEXT NOT NULL, | ||||
|                                            `utcDateCreated`	TEXT NOT NULL, | ||||
|                                            `utcDateModified`	TEXT NOT NULL, | ||||
|                                            PRIMARY KEY(`noteId`)); | ||||
| CREATE INDEX `IDX_notes_isDeleted` ON `notes` (`isDeleted`); | ||||
| CREATE INDEX `IDX_notes_title` ON `notes` (`title`); | ||||
| CREATE INDEX `IDX_notes_type` ON `notes` (`type`); | ||||
| CREATE INDEX `IDX_notes_dateCreated` ON `notes` (`dateCreated`); | ||||
| CREATE INDEX `IDX_notes_dateModified` ON `notes` (`dateModified`); | ||||
| CREATE INDEX `IDX_notes_utcDateModified` ON `notes` (`utcDateModified`); | ||||
| CREATE INDEX `IDX_notes_utcDateCreated` ON `notes` (`utcDateCreated`); | ||||
| CREATE TABLE IF NOT EXISTS "branches" ( | ||||
|                                           `branchId`	TEXT NOT NULL, | ||||
|                                           `noteId`	TEXT NOT NULL, | ||||
|                                           `parentNoteId`	TEXT NOT NULL, | ||||
|                                           `notePosition`	INTEGER NOT NULL, | ||||
|                                           `prefix`	TEXT, | ||||
|                                           `isExpanded`	INTEGER NOT NULL DEFAULT 0, | ||||
|                                           `isDeleted`	INTEGER NOT NULL DEFAULT 0, | ||||
|                                           `deleteId`    TEXT DEFAULT NULL, | ||||
|                                           `utcDateModified`	TEXT NOT NULL, | ||||
|                                           utcDateCreated TEXT NOT NULL, | ||||
|                                           hash TEXT DEFAULT "" NOT NULL, | ||||
|                                           PRIMARY KEY(`branchId`)); | ||||
| CREATE INDEX `IDX_branches_noteId_parentNoteId` ON `branches` (`noteId`,`parentNoteId`); | ||||
| CREATE INDEX IDX_branches_parentNoteId ON branches (parentNoteId); | ||||
| CREATE TABLE IF NOT EXISTS "attributes" | ||||
| ( | ||||
|     attributeId      TEXT not null primary key, | ||||
|     noteId       TEXT not null, | ||||
|     type         TEXT not null, | ||||
|     name         TEXT not null, | ||||
|     value        TEXT default '' not null, | ||||
|     position     INT  default 0 not null, | ||||
|     utcDateCreated  TEXT not null, | ||||
|     utcDateModified TEXT not null, | ||||
|     isDeleted    INT  not null, | ||||
|     `deleteId`    TEXT DEFAULT NULL, | ||||
|     hash         TEXT default "" not null, | ||||
|     isInheritable int DEFAULT 0 NULL); | ||||
| CREATE INDEX IDX_attributes_name_value | ||||
|     on attributes (name, value); | ||||
| CREATE INDEX IDX_attributes_noteId_index | ||||
|     on attributes (noteId); | ||||
| CREATE INDEX IDX_attributes_value_index | ||||
|     on attributes (value); | ||||
|   | ||||
| @@ -16,6 +16,7 @@ const sql = require('../services/sql'); | ||||
|  * @property {int} position | ||||
|  * @property {boolean} isInheritable | ||||
|  * @property {boolean} isDeleted | ||||
|  * @property {string|null} deleteId - ID identifying delete transaction | ||||
|  * @property {string} utcDateCreated | ||||
|  * @property {string} utcDateModified | ||||
|  * | ||||
|   | ||||
| @@ -16,6 +16,7 @@ const sql = require('../services/sql'); | ||||
|  * @property {string} prefix | ||||
|  * @property {boolean} isExpanded | ||||
|  * @property {boolean} isDeleted | ||||
|  * @property {string|null} deleteId - ID identifying delete transaction | ||||
|  * @property {string} utcDateModified | ||||
|  * @property {string} utcDateCreated | ||||
|  * | ||||
| @@ -25,7 +26,7 @@ class Branch extends Entity { | ||||
|     static get entityName() { return "branches"; } | ||||
|     static get primaryKeyName() { return "branchId"; } | ||||
|     // notePosition is not part of hash because it would produce a lot of updates in case of reordering | ||||
|     static get hashedProperties() { return ["branchId", "noteId", "parentNoteId", "isDeleted", "prefix"]; } | ||||
|     static get hashedProperties() { return ["branchId", "noteId", "parentNoteId", "isDeleted", "deleteId", "prefix"]; } | ||||
|  | ||||
|     constructor(row = {}) { | ||||
|         super(row); | ||||
|   | ||||
| @@ -24,6 +24,7 @@ const RELATION_DEFINITION = 'relation-definition'; | ||||
|  * @property {int} contentLength - length of content | ||||
|  * @property {boolean} isProtected - true if note is protected | ||||
|  * @property {boolean} isDeleted - true if note is deleted | ||||
|  * @property {string|null} deleteId - ID identifying delete transaction | ||||
|  * @property {boolean} isErased - true if note's content is erased after it has been deleted | ||||
|  * @property {string} dateCreated - local date time (with offset) | ||||
|  * @property {string} dateModified - local date time (with offset) | ||||
| @@ -35,7 +36,7 @@ const RELATION_DEFINITION = 'relation-definition'; | ||||
| class Note extends Entity { | ||||
|     static get entityName() { return "notes"; } | ||||
|     static get primaryKeyName() { return "noteId"; } | ||||
|     static get hashedProperties() { return ["noteId", "title", "type", "isProtected", "isDeleted"]; } | ||||
|     static get hashedProperties() { return ["noteId", "title", "type", "isProtected", "isDeleted", "deleteId"]; } | ||||
|  | ||||
|     /** | ||||
|      * @param row - object containing database row from "notes" table | ||||
|   | ||||
| @@ -28,31 +28,38 @@ export async function showDialog() { | ||||
|     const groupedByDate = groupByDate(result); | ||||
|  | ||||
|     for (const [dateDay, dayChanges] of groupedByDate) { | ||||
|         const changesListEl = $('<ul>'); | ||||
|         const $changesList = $('<ul>'); | ||||
|  | ||||
|         const dayEl = $('<div>').append($('<b>').html(utils.formatDate(dateDay))).append(changesListEl); | ||||
|         const dayEl = $('<div>').append($('<b>').html(utils.formatDate(dateDay))).append($changesList); | ||||
|  | ||||
|         for (const change of dayChanges) { | ||||
|             const formattedTime = utils.formatTime(utils.parseDate(change.date)); | ||||
|  | ||||
|             let noteLink; | ||||
|             let $noteLink; | ||||
|  | ||||
|             if (change.current_isDeleted) { | ||||
|                 noteLink = change.current_title; | ||||
|                 $noteLink = $("<span>").text(change.current_title); | ||||
|  | ||||
|                 if (change.canBeUndeleted) { | ||||
|                     $noteLink | ||||
|                         .append(' (') | ||||
|                         .append($(`<a href="">`).text("undelete")) | ||||
|                         .append(')'); | ||||
|                 } | ||||
|             } | ||||
|             else { | ||||
|                 const note = await treeCache.getNote(change.noteId); | ||||
|                 const notePath = await treeService.getSomeNotePath(note); | ||||
|  | ||||
|                 noteLink = await linkService.createNoteLink(notePath, { | ||||
|                 $noteLink = await linkService.createNoteLink(notePath, { | ||||
|                     title: change.title, | ||||
|                     showNotePath: true | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             changesListEl.append($('<li>') | ||||
|             $changesList.append($('<li>') | ||||
|                 .append(formattedTime + ' - ') | ||||
|                 .append(noteLink)); | ||||
|                 .append($noteLink)); | ||||
|         } | ||||
|  | ||||
|         $content.append(dayEl); | ||||
| @@ -85,5 +92,6 @@ function groupByDate(result) { | ||||
|  | ||||
|         groupedByDate.get(dateDay).push(row); | ||||
|     } | ||||
|  | ||||
|     return groupedByDate; | ||||
| } | ||||
|   | ||||
| @@ -10,6 +10,12 @@ function getNotePathFromUrl(url) { | ||||
| } | ||||
|  | ||||
| async function createNoteLink(notePath, options = {}) { | ||||
|     if (!notePath || !notePath.trim()) { | ||||
|         console.error("Missing note path"); | ||||
|  | ||||
|         return $("<span>").text("[missing note]"); | ||||
|     } | ||||
|  | ||||
|     let noteTitle = options.title; | ||||
|     const showTooltip = options.showTooltip === undefined ? true : options.showTooltip; | ||||
|     const showNotePath = options.showNotePath === undefined ? false : options.showNotePath; | ||||
|   | ||||
| @@ -316,6 +316,8 @@ async function getSomeNotePath(note) { | ||||
|         cur = parents[0]; | ||||
|     } | ||||
|  | ||||
|     path.push('root'); | ||||
|  | ||||
|     return path.reverse().join('/'); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -101,7 +101,8 @@ async function deleteBranch(req) { | ||||
|     const branch = await repository.getBranch(req.params.branchId); | ||||
|     const taskContext = TaskContext.getInstance(req.query.taskId, 'delete-notes'); | ||||
|  | ||||
|     const noteDeleted = await notes.deleteBranch(branch, taskContext); | ||||
|     const deleteId = utils.randomString(10); | ||||
|     const noteDeleted = await notes.deleteBranch(branch, deleteId, taskContext); | ||||
|  | ||||
|     if (last) { | ||||
|         taskContext.taskSucceeded(); | ||||
|   | ||||
| @@ -55,12 +55,15 @@ async function deleteNote(req) { | ||||
|     const taskId = req.query.taskId; | ||||
|     const last = req.query.last === 'true'; | ||||
|  | ||||
|     // note how deleteId is separate from taskId - single taskId produces separate deleteId for each "top level" deleted note | ||||
|     const deleteId = utils.randomString(10); | ||||
|  | ||||
|     const note = await repository.getNote(noteId); | ||||
|  | ||||
|     const taskContext = TaskContext.getInstance(taskId, 'delete-notes'); | ||||
|  | ||||
|     for (const branch of await note.getBranches()) { | ||||
|         await noteService.deleteBranch(branch, taskContext); | ||||
|         await noteService.deleteBranch(branch, deleteId, taskContext); | ||||
|     } | ||||
|  | ||||
|     if (last) { | ||||
|   | ||||
| @@ -10,6 +10,8 @@ async function getRecentChanges() { | ||||
|             SELECT  | ||||
|                 notes.noteId, | ||||
|                 notes.isDeleted AS current_isDeleted, | ||||
|                 notes.deleteId AS current_deleteId, | ||||
|                 notes.isErased AS current_isErased, | ||||
|                 notes.title AS current_title, | ||||
|                 notes.isProtected AS current_isProtected, | ||||
|                 note_revisions.title, | ||||
| @@ -19,21 +21,23 @@ async function getRecentChanges() { | ||||
|                 JOIN notes USING(noteId) | ||||
|             ORDER BY | ||||
|                 note_revisions.utcDateCreated DESC | ||||
|             LIMIT 1000 | ||||
|             LIMIT 200 | ||||
|         ) | ||||
|         UNION ALL SELECT * FROM ( | ||||
|             SELECT | ||||
|                 notes.noteId, | ||||
|                 notes.isDeleted AS current_isDeleted, | ||||
|                 notes.deleteId AS current_deleteId, | ||||
|                 notes.isErased AS current_isErased, | ||||
|                 notes.title AS current_title, | ||||
|                 notes.isProtected AS current_isProtected, | ||||
|                 notes.title, | ||||
|                 notes.utcDateCreated AS date | ||||
|                 notes.utcDateModified AS date | ||||
|             FROM | ||||
|                 notes | ||||
|             ORDER BY | ||||
|                 utcDateCreated DESC | ||||
|             LIMIT 1000 | ||||
|                 utcDateModified DESC | ||||
|             LIMIT 200 | ||||
|         ) | ||||
|         ORDER BY date DESC  | ||||
|         LIMIT 200`); | ||||
| @@ -48,6 +52,27 @@ async function getRecentChanges() { | ||||
|                 change.title = change.current_title = "[Protected]"; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (change.current_isDeleted) { | ||||
|             if (change.current_isErased) { | ||||
|                 change.canBeUndeleted = false; | ||||
|             } | ||||
|             else { | ||||
|                 const deleteId = change.current_deleteId; | ||||
|  | ||||
|                 const undeletedParentCount = await sql.getValue(` | ||||
|                     SELECT COUNT(parentNote.noteId) | ||||
|                     FROM branches | ||||
|                     JOIN notes AS parentNote ON parentNote.noteId = branches.parentNoteId | ||||
|                     WHERE branches.noteId = ? | ||||
|                       AND branches.isDeleted = 1 | ||||
|                       AND branches.deleteId = ? | ||||
|                       AND parentNote.isDeleted = 0`, [change.noteId, deleteId]); | ||||
|  | ||||
|                 // note (and the subtree) can be undeleted if there's at least one undeleted parent (whose branch would be undeleted by this op) | ||||
|                 change.canBeUndeleted = undeletedParentCount > 0; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return recentChanges; | ||||
|   | ||||
| @@ -4,8 +4,8 @@ const build = require('./build'); | ||||
| const packageJson = require('../../package'); | ||||
| const {TRILIUM_DATA_DIR} = require('./data_dir'); | ||||
|  | ||||
| const APP_DB_VERSION = 155; | ||||
| const SYNC_VERSION = 13; | ||||
| const APP_DB_VERSION = 156; | ||||
| const SYNC_VERSION = 14; | ||||
| const CLIPPER_PROTOCOL_VERSION = "1.0"; | ||||
|  | ||||
| module.exports = { | ||||
|   | ||||
| @@ -389,8 +389,14 @@ async function updateNote(noteId, noteUpdates) { | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** @return {boolean} - true if note has been deleted, false otherwise */ | ||||
| async function deleteBranch(branch, taskContext) { | ||||
| /** | ||||
|  * @param {Branch} branch | ||||
|  * @param {string} deleteId | ||||
|  * @param {TaskContext} taskContext | ||||
|  * | ||||
|  * @return {boolean} - true if note has been deleted, false otherwise | ||||
|  */ | ||||
| async function deleteBranch(branch, deleteId, taskContext) { | ||||
|     taskContext.increaseProgressCount(); | ||||
|  | ||||
|     if (!branch || branch.isDeleted) { | ||||
| @@ -405,6 +411,7 @@ async function deleteBranch(branch, taskContext) { | ||||
|     } | ||||
|  | ||||
|     branch.isDeleted = true; | ||||
|     branch.deleteId = deleteId; | ||||
|     await branch.save(); | ||||
|  | ||||
|     const note = await branch.getNote(); | ||||
| @@ -412,19 +419,22 @@ async function deleteBranch(branch, taskContext) { | ||||
|  | ||||
|     if (notDeletedBranches.length === 0) { | ||||
|         note.isDeleted = true; | ||||
|         note.deleteId = deleteId; | ||||
|         await note.save(); | ||||
|  | ||||
|         for (const childBranch of await note.getChildBranches()) { | ||||
|             await deleteBranch(childBranch, taskContext); | ||||
|             await deleteBranch(childBranch, deleteId, taskContext); | ||||
|         } | ||||
|  | ||||
|         for (const attribute of await note.getOwnedAttributes()) { | ||||
|             attribute.isDeleted = true; | ||||
|             attribute.deleteId = deleteId; | ||||
|             await attribute.save(); | ||||
|         } | ||||
|  | ||||
|         for (const relation of await note.getTargetRelations()) { | ||||
|             relation.isDeleted = true; | ||||
|             relation.deleteId = deleteId; | ||||
|             await relation.save(); | ||||
|         } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user