mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-30 18:05:55 +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, |   utcDateCreated TEXT not null, | ||||||
|   utcDateModified 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` ( | CREATE UNIQUE INDEX `IDX_sync_entityName_entityId` ON `sync` ( | ||||||
|                                                               `entityName`, |                                                               `entityName`, | ||||||
|                                                               `entityId` |                                                               `entityId` | ||||||
| @@ -47,12 +34,6 @@ CREATE UNIQUE INDEX `IDX_sync_entityName_entityId` ON `sync` ( | |||||||
| CREATE INDEX `IDX_sync_utcSyncDate` ON `sync` ( | CREATE INDEX `IDX_sync_utcSyncDate` ON `sync` ( | ||||||
|                                             `utcSyncDate` |                                             `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" ( | CREATE TABLE IF NOT EXISTS "note_contents" ( | ||||||
|                                                    `noteId`	TEXT NOT NULL, |                                                    `noteId`	TEXT NOT NULL, | ||||||
|                                                    `content`	TEXT NULL DEFAULT NULL, |                                                    `content`	TEXT NULL DEFAULT NULL, | ||||||
| @@ -68,46 +49,10 @@ CREATE TABLE recent_notes | |||||||
|     utcDateCreated TEXT not null, |     utcDateCreated TEXT not null, | ||||||
|     isDeleted INT |     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, | CREATE TABLE IF NOT EXISTS "note_revision_contents" (`noteRevisionId`	TEXT NOT NULL PRIMARY KEY, | ||||||
|                                                  `content`	TEXT, |                                                  `content`	TEXT, | ||||||
|                                                  hash TEXT DEFAULT '' NOT NULL, |                                                  hash TEXT DEFAULT '' NOT NULL, | ||||||
|                                                  `utcDateModified` TEXT 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, | CREATE TABLE IF NOT EXISTS "note_revisions" (`noteRevisionId`	TEXT NOT NULL PRIMARY KEY, | ||||||
|                                                  `noteId`	TEXT NOT NULL, |                                                  `noteId`	TEXT NOT NULL, | ||||||
|                                                  `title`	TEXT, |                                                  `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_utcDateLastEdited` ON `note_revisions` (`utcDateLastEdited`); | ||||||
| CREATE INDEX `IDX_note_revisions_dateCreated` ON `note_revisions` (`dateCreated`); | CREATE INDEX `IDX_note_revisions_dateCreated` ON `note_revisions` (`dateCreated`); | ||||||
| CREATE INDEX `IDX_note_revisions_dateLastEdited` ON `note_revisions` (`dateLastEdited`); | 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 {int} position | ||||||
|  * @property {boolean} isInheritable |  * @property {boolean} isInheritable | ||||||
|  * @property {boolean} isDeleted |  * @property {boolean} isDeleted | ||||||
|  |  * @property {string|null} deleteId - ID identifying delete transaction | ||||||
|  * @property {string} utcDateCreated |  * @property {string} utcDateCreated | ||||||
|  * @property {string} utcDateModified |  * @property {string} utcDateModified | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -16,6 +16,7 @@ const sql = require('../services/sql'); | |||||||
|  * @property {string} prefix |  * @property {string} prefix | ||||||
|  * @property {boolean} isExpanded |  * @property {boolean} isExpanded | ||||||
|  * @property {boolean} isDeleted |  * @property {boolean} isDeleted | ||||||
|  |  * @property {string|null} deleteId - ID identifying delete transaction | ||||||
|  * @property {string} utcDateModified |  * @property {string} utcDateModified | ||||||
|  * @property {string} utcDateCreated |  * @property {string} utcDateCreated | ||||||
|  * |  * | ||||||
| @@ -25,7 +26,7 @@ class Branch extends Entity { | |||||||
|     static get entityName() { return "branches"; } |     static get entityName() { return "branches"; } | ||||||
|     static get primaryKeyName() { return "branchId"; } |     static get primaryKeyName() { return "branchId"; } | ||||||
|     // notePosition is not part of hash because it would produce a lot of updates in case of reordering |     // 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 = {}) { |     constructor(row = {}) { | ||||||
|         super(row); |         super(row); | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ const RELATION_DEFINITION = 'relation-definition'; | |||||||
|  * @property {int} contentLength - length of content |  * @property {int} contentLength - length of content | ||||||
|  * @property {boolean} isProtected - true if note is protected |  * @property {boolean} isProtected - true if note is protected | ||||||
|  * @property {boolean} isDeleted - true if note is deleted |  * @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 {boolean} isErased - true if note's content is erased after it has been deleted | ||||||
|  * @property {string} dateCreated - local date time (with offset) |  * @property {string} dateCreated - local date time (with offset) | ||||||
|  * @property {string} dateModified - 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 { | class Note extends Entity { | ||||||
|     static get entityName() { return "notes"; } |     static get entityName() { return "notes"; } | ||||||
|     static get primaryKeyName() { return "noteId"; } |     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 |      * @param row - object containing database row from "notes" table | ||||||
|   | |||||||
| @@ -28,31 +28,38 @@ export async function showDialog() { | |||||||
|     const groupedByDate = groupByDate(result); |     const groupedByDate = groupByDate(result); | ||||||
|  |  | ||||||
|     for (const [dateDay, dayChanges] of groupedByDate) { |     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) { |         for (const change of dayChanges) { | ||||||
|             const formattedTime = utils.formatTime(utils.parseDate(change.date)); |             const formattedTime = utils.formatTime(utils.parseDate(change.date)); | ||||||
|  |  | ||||||
|             let noteLink; |             let $noteLink; | ||||||
|  |  | ||||||
|             if (change.current_isDeleted) { |             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 { |             else { | ||||||
|                 const note = await treeCache.getNote(change.noteId); |                 const note = await treeCache.getNote(change.noteId); | ||||||
|                 const notePath = await treeService.getSomeNotePath(note); |                 const notePath = await treeService.getSomeNotePath(note); | ||||||
|  |  | ||||||
|                 noteLink = await linkService.createNoteLink(notePath, { |                 $noteLink = await linkService.createNoteLink(notePath, { | ||||||
|                     title: change.title, |                     title: change.title, | ||||||
|                     showNotePath: true |                     showNotePath: true | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             changesListEl.append($('<li>') |             $changesList.append($('<li>') | ||||||
|                 .append(formattedTime + ' - ') |                 .append(formattedTime + ' - ') | ||||||
|                 .append(noteLink)); |                 .append($noteLink)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         $content.append(dayEl); |         $content.append(dayEl); | ||||||
| @@ -85,5 +92,6 @@ function groupByDate(result) { | |||||||
|  |  | ||||||
|         groupedByDate.get(dateDay).push(row); |         groupedByDate.get(dateDay).push(row); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return groupedByDate; |     return groupedByDate; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -10,6 +10,12 @@ function getNotePathFromUrl(url) { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function createNoteLink(notePath, options = {}) { | async function createNoteLink(notePath, options = {}) { | ||||||
|  |     if (!notePath || !notePath.trim()) { | ||||||
|  |         console.error("Missing note path"); | ||||||
|  |  | ||||||
|  |         return $("<span>").text("[missing note]"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     let noteTitle = options.title; |     let noteTitle = options.title; | ||||||
|     const showTooltip = options.showTooltip === undefined ? true : options.showTooltip; |     const showTooltip = options.showTooltip === undefined ? true : options.showTooltip; | ||||||
|     const showNotePath = options.showNotePath === undefined ? false : options.showNotePath; |     const showNotePath = options.showNotePath === undefined ? false : options.showNotePath; | ||||||
|   | |||||||
| @@ -316,6 +316,8 @@ async function getSomeNotePath(note) { | |||||||
|         cur = parents[0]; |         cur = parents[0]; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     path.push('root'); | ||||||
|  |  | ||||||
|     return path.reverse().join('/'); |     return path.reverse().join('/'); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -101,7 +101,8 @@ async function deleteBranch(req) { | |||||||
|     const branch = await repository.getBranch(req.params.branchId); |     const branch = await repository.getBranch(req.params.branchId); | ||||||
|     const taskContext = TaskContext.getInstance(req.query.taskId, 'delete-notes'); |     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) { |     if (last) { | ||||||
|         taskContext.taskSucceeded(); |         taskContext.taskSucceeded(); | ||||||
|   | |||||||
| @@ -55,12 +55,15 @@ async function deleteNote(req) { | |||||||
|     const taskId = req.query.taskId; |     const taskId = req.query.taskId; | ||||||
|     const last = req.query.last === 'true'; |     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 note = await repository.getNote(noteId); | ||||||
|  |  | ||||||
|     const taskContext = TaskContext.getInstance(taskId, 'delete-notes'); |     const taskContext = TaskContext.getInstance(taskId, 'delete-notes'); | ||||||
|  |  | ||||||
|     for (const branch of await note.getBranches()) { |     for (const branch of await note.getBranches()) { | ||||||
|         await noteService.deleteBranch(branch, taskContext); |         await noteService.deleteBranch(branch, deleteId, taskContext); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (last) { |     if (last) { | ||||||
|   | |||||||
| @@ -10,6 +10,8 @@ async function getRecentChanges() { | |||||||
|             SELECT  |             SELECT  | ||||||
|                 notes.noteId, |                 notes.noteId, | ||||||
|                 notes.isDeleted AS current_isDeleted, |                 notes.isDeleted AS current_isDeleted, | ||||||
|  |                 notes.deleteId AS current_deleteId, | ||||||
|  |                 notes.isErased AS current_isErased, | ||||||
|                 notes.title AS current_title, |                 notes.title AS current_title, | ||||||
|                 notes.isProtected AS current_isProtected, |                 notes.isProtected AS current_isProtected, | ||||||
|                 note_revisions.title, |                 note_revisions.title, | ||||||
| @@ -19,21 +21,23 @@ async function getRecentChanges() { | |||||||
|                 JOIN notes USING(noteId) |                 JOIN notes USING(noteId) | ||||||
|             ORDER BY |             ORDER BY | ||||||
|                 note_revisions.utcDateCreated DESC |                 note_revisions.utcDateCreated DESC | ||||||
|             LIMIT 1000 |             LIMIT 200 | ||||||
|         ) |         ) | ||||||
|         UNION ALL SELECT * FROM ( |         UNION ALL SELECT * FROM ( | ||||||
|             SELECT |             SELECT | ||||||
|                 notes.noteId, |                 notes.noteId, | ||||||
|                 notes.isDeleted AS current_isDeleted, |                 notes.isDeleted AS current_isDeleted, | ||||||
|  |                 notes.deleteId AS current_deleteId, | ||||||
|  |                 notes.isErased AS current_isErased, | ||||||
|                 notes.title AS current_title, |                 notes.title AS current_title, | ||||||
|                 notes.isProtected AS current_isProtected, |                 notes.isProtected AS current_isProtected, | ||||||
|                 notes.title, |                 notes.title, | ||||||
|                 notes.utcDateCreated AS date |                 notes.utcDateModified AS date | ||||||
|             FROM |             FROM | ||||||
|                 notes |                 notes | ||||||
|             ORDER BY |             ORDER BY | ||||||
|                 utcDateCreated DESC |                 utcDateModified DESC | ||||||
|             LIMIT 1000 |             LIMIT 200 | ||||||
|         ) |         ) | ||||||
|         ORDER BY date DESC  |         ORDER BY date DESC  | ||||||
|         LIMIT 200`); |         LIMIT 200`); | ||||||
| @@ -48,6 +52,27 @@ async function getRecentChanges() { | |||||||
|                 change.title = change.current_title = "[Protected]"; |                 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; |     return recentChanges; | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ const build = require('./build'); | |||||||
| const packageJson = require('../../package'); | const packageJson = require('../../package'); | ||||||
| const {TRILIUM_DATA_DIR} = require('./data_dir'); | const {TRILIUM_DATA_DIR} = require('./data_dir'); | ||||||
|  |  | ||||||
| const APP_DB_VERSION = 155; | const APP_DB_VERSION = 156; | ||||||
| const SYNC_VERSION = 13; | const SYNC_VERSION = 14; | ||||||
| const CLIPPER_PROTOCOL_VERSION = "1.0"; | const CLIPPER_PROTOCOL_VERSION = "1.0"; | ||||||
|  |  | ||||||
| module.exports = { | 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(); |     taskContext.increaseProgressCount(); | ||||||
|  |  | ||||||
|     if (!branch || branch.isDeleted) { |     if (!branch || branch.isDeleted) { | ||||||
| @@ -405,6 +411,7 @@ async function deleteBranch(branch, taskContext) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     branch.isDeleted = true; |     branch.isDeleted = true; | ||||||
|  |     branch.deleteId = deleteId; | ||||||
|     await branch.save(); |     await branch.save(); | ||||||
|  |  | ||||||
|     const note = await branch.getNote(); |     const note = await branch.getNote(); | ||||||
| @@ -412,19 +419,22 @@ async function deleteBranch(branch, taskContext) { | |||||||
|  |  | ||||||
|     if (notDeletedBranches.length === 0) { |     if (notDeletedBranches.length === 0) { | ||||||
|         note.isDeleted = true; |         note.isDeleted = true; | ||||||
|  |         note.deleteId = deleteId; | ||||||
|         await note.save(); |         await note.save(); | ||||||
|  |  | ||||||
|         for (const childBranch of await note.getChildBranches()) { |         for (const childBranch of await note.getChildBranches()) { | ||||||
|             await deleteBranch(childBranch, taskContext); |             await deleteBranch(childBranch, deleteId, taskContext); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         for (const attribute of await note.getOwnedAttributes()) { |         for (const attribute of await note.getOwnedAttributes()) { | ||||||
|             attribute.isDeleted = true; |             attribute.isDeleted = true; | ||||||
|  |             attribute.deleteId = deleteId; | ||||||
|             await attribute.save(); |             await attribute.save(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         for (const relation of await note.getTargetRelations()) { |         for (const relation of await note.getTargetRelations()) { | ||||||
|             relation.isDeleted = true; |             relation.isDeleted = true; | ||||||
|  |             relation.deleteId = deleteId; | ||||||
|             await relation.save(); |             await relation.save(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user