refactored all mentions of "history" to "revision"

This commit is contained in:
azivner 2018-03-25 20:52:38 -04:00
parent a69d8737ce
commit 47eb1e3e02
22 changed files with 147 additions and 149 deletions

View file

@ -0,0 +1 @@
UPDATE options SET name = 'note_revision_snapshot_time_interval' WHERE name = 'history_snapshot_time_interval';

View file

@ -1,72 +0,0 @@
import noteDetailService from '../services/note_detail.js';
import utils from '../services/utils.js';
import server from '../services/server.js';
const $dialog = $("#note-history-dialog");
const $list = $("#note-history-list");
const $content = $("#note-history-content");
const $title = $("#note-history-title");
let historyItems = [];
async function showCurrentNoteHistory() {
await showNoteHistoryDialog(noteDetailService.getCurrentNoteId());
}
async function showNoteHistoryDialog(noteId, noteRevisionId) {
glob.activeDialog = $dialog;
$dialog.dialog({
modal: true,
width: 800,
height: 700
});
$list.empty();
$content.empty();
historyItems = await server.get('notes-history/' + noteId);
for (const item of historyItems) {
const dateModified = utils.parseDate(item.dateModifiedFrom);
$list.append($('<option>', {
value: item.noteRevisionId,
text: utils.formatDateTime(dateModified)
}));
}
if (historyItems.length > 0) {
if (!noteRevisionId) {
noteRevisionId = $list.find("option:first").val();
}
$list.val(noteRevisionId).trigger('change');
}
else {
$title.text("No history for this note yet...");
}
}
$list.on('change', () => {
const optVal = $list.find(":selected").val();
const historyItem = historyItems.find(r => r.noteRevisionId === optVal);
$title.html(historyItem.title);
$content.html(historyItem.content);
});
$(document).on('click', "a[action='note-history']", event => {
const linkEl = $(event.target);
const noteId = linkEl.attr('note-path');
const noteRevisionId = linkEl.attr('note-history-id');
showNoteHistoryDialog(noteId, noteRevisionId);
return false;
});
export default {
showCurrentNoteHistory
};

View file

@ -0,0 +1,72 @@
import noteDetailService from '../services/note_detail.js';
import utils from '../services/utils.js';
import server from '../services/server.js';
const $dialog = $("#note-revisions-dialog");
const $list = $("#note-revision-list");
const $content = $("#note-revision-content");
const $title = $("#note-revision-title");
let revisionItems = [];
async function showCurrentNoteRevisions() {
await showNoteRevisionsDialog(noteDetailService.getCurrentNoteId());
}
async function showNoteRevisionsDialog(noteId, noteRevisionId) {
glob.activeDialog = $dialog;
$dialog.dialog({
modal: true,
width: 800,
height: 700
});
$list.empty();
$content.empty();
revisionItems = await server.get('notes-revisions/' + noteId);
for (const item of revisionItems) {
const dateModified = utils.parseDate(item.dateModifiedFrom);
$list.append($('<option>', {
value: item.noteRevisionId,
text: utils.formatDateTime(dateModified)
}));
}
if (revisionItems.length > 0) {
if (!noteRevisionId) {
noteRevisionId = $list.find("option:first").val();
}
$list.val(noteRevisionId).trigger('change');
}
else {
$title.text("No revisions for this note yet...");
}
}
$list.on('change', () => {
const optVal = $list.find(":selected").val();
const revisionItem = revisionItems.find(r => r.noteRevisionId === optVal);
$title.html(revisionItem.title);
$content.html(revisionItem.content);
});
$(document).on('click', "a[action='note-revision']", event => {
const linkEl = $(event.target);
const noteId = linkEl.attr('note-path');
const noteRevisionId = linkEl.attr('note-revision-id');
showNoteRevisionsDialog(noteId, noteRevisionId);
return false;
});
export default {
showCurrentNoteRevisions
};

View file

@ -30,9 +30,9 @@ async function showDialog() {
const revLink = $("<a>", {
href: 'javascript:',
text: 'rev'
}).attr('action', 'note-history')
}).attr('action', 'note-revision')
.attr('note-path', change.noteId)
.attr('note-history-id', change.noteRevisionId);
.attr('note-revision-id', change.noteRevisionId);
let noteLink;

View file

@ -117,9 +117,9 @@ addModule((function() {
})());
addModule((function () {
const $form = $("#history-snapshot-time-interval-form");
const $timeInterval = $("#history-snapshot-time-interval-in-seconds");
const settingName = 'history_snapshot_time_interval';
const $form = $("#note-revision-snapshot-time-interval-form");
const $timeInterval = $("#note-revision-snapshot-time-interval-in-seconds");
const settingName = 'note_revision_snapshot_time_interval';
function settingsLoaded(settings) {
$timeInterval.val(settings[settingName]);

View file

@ -1,4 +1,4 @@
"use strict";
import server from './services/server.js';
$(document).ready(() => {
server.get('migration').then(result => {

View file

@ -1,7 +1,7 @@
import addLinkDialog from '../dialogs/add_link.js';
import jumpToNoteDialog from '../dialogs/jump_to_note.js';
import labelsDialog from '../dialogs/labels.js';
import noteRevisionsDialog from '../dialogs/note_history.js';
import noteRevisionsDialog from '../dialogs/note_revisions.js';
import noteSourceDialog from '../dialogs/note_source.js';
import recentChangesDialog from '../dialogs/recent_changes.js';
import recentNotesDialog from '../dialogs/recent_notes.js';
@ -43,7 +43,7 @@ utils.bindShortcut('ctrl+l', addLinkDialog.showDialog);
$("#jump-to-note-button").click(jumpToNoteDialog.showDialog);
utils.bindShortcut('ctrl+j', jumpToNoteDialog.showDialog);
$("#show-history-button").click(noteRevisionsDialog.showCurrentNoteHistory);
$("#show-note-revisions-button").click(noteRevisionsDialog.showCurrentNoteRevisions);
$("#show-source-button").click(noteSourceDialog.showDialog);
utils.bindShortcut('ctrl+u', noteSourceDialog.showDialog);

View file

@ -1,6 +1,5 @@
import linkService from './link.js';
import messagingService from './messaging.js';
import ScriptContext from './script_context.js';
//import messagingService from './messaging.js';
//import ScriptContext from './script_context.js';
function reloadApp() {
window.location.reload(true);
@ -189,7 +188,7 @@ async function requireScript(url) {
async function requireCss(url) {
const css = Array
.from(document.querySelectorAll('linkService'))
.from(document.querySelectorAll('link'))
.map(scr => scr.href);
if (!css.includes(url)) {

View file

@ -10,10 +10,10 @@ const wrap = require('express-promise-wrap').wrap;
router.get('/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => {
const noteId = req.params.noteId;
const history = await sql.getRows("SELECT * FROM note_revisions WHERE noteId = ? order by dateModifiedTo desc", [noteId]);
protected_session.decryptNoteHistoryRows(req, history);
const revisions = await sql.getRows("SELECT * FROM note_revisions WHERE noteId = ? order by dateModifiedTo desc", [noteId]);
protected_session.decryptNoteRevisions(req, revisions);
res.send(history);
res.send(revisions);
}));
router.put('', auth.checkApiAuth, wrap(async (req, res, next) => {
@ -22,7 +22,7 @@ router.put('', auth.checkApiAuth, wrap(async (req, res, next) => {
await sql.doInTransaction(async () => {
await sql.replace("note_revisions", req.body);
await sync_table.addNoteHistorySync(req.body.noteRevisionId, sourceId);
await sync_table.addNoteRevisionSync(req.body.noteRevisionId, sourceId);
});
res.send();

View file

@ -8,7 +8,7 @@ const auth = require('../../services/auth');
const wrap = require('express-promise-wrap').wrap;
// options allowed to be updated directly in settings dialog
const ALLOWED_OPTIONS = ['protected_session_timeout', 'history_snapshot_time_interval'];
const ALLOWED_OPTIONS = ['protected_session_timeout', 'note_revision_snapshot_time_interval'];
router.get('/all', auth.checkApiAuth, wrap(async (req, res, next) => {
const settings = await sql.getMap("SELECT name, value FROM options");

View file

@ -59,7 +59,7 @@ router.post('/force-note-sync/:noteId', auth.checkApiAuth, wrap(async (req, res,
}
for (const noteRevisionId of await sql.getColumn("SELECT noteRevisionId FROM note_revisions WHERE noteId = ?", [noteId])) {
await sync_table.addNoteHistorySync(noteRevisionId);
await sync_table.addNoteRevisionsSync(noteRevisionId);
}
});
@ -169,7 +169,7 @@ router.put('/branches', auth.checkApiAuth, wrap(async (req, res, next) => {
}));
router.put('/note_revisions', auth.checkApiAuth, wrap(async (req, res, next) => {
await syncUpdate.updateNoteHistory(req.body.entity, req.body.sourceId);
await syncUpdate.updateNoteRevision(req.body.entity, req.body.sourceId);
res.send({});
}));

View file

@ -9,7 +9,7 @@ const treeApiRoute = require('./api/tree');
const notesApiRoute = require('./api/notes');
const treeChangesApiRoute = require('./api/tree_changes');
const cloningApiRoute = require('./api/cloning');
const noteHistoryApiRoute = require('./api/note_history');
const noteRevisionsApiRoute = require('./api/note_revisions');
const recentChangesApiRoute = require('./api/recent_changes');
const settingsApiRoute = require('./api/settings');
const passwordApiRoute = require('./api/password');
@ -44,7 +44,7 @@ function register(app) {
app.use('/api/tree', treeChangesApiRoute);
app.use('/api/notes', cloningApiRoute);
app.use('/api', labelsRoute);
app.use('/api/notes-history', noteHistoryApiRoute);
app.use('/api/notes-revisions', noteRevisionsApiRoute);
app.use('/api/recent-changes', recentChangesApiRoute);
app.use('/api/settings', settingsApiRoute);
app.use('/api/password', passwordApiRoute);

View file

@ -3,7 +3,7 @@
const build = require('./build');
const packageJson = require('../../package');
const APP_DB_VERSION = 80;
const APP_DB_VERSION = 81;
module.exports = {
app_version: packageJson.version,

View file

@ -161,7 +161,7 @@ async function runAllChecks() {
note_revisions LEFT JOIN notes USING(noteId)
WHERE
notes.noteId IS NULL`,
"Missing notes records for following note history ID > note ID", errorList);
"Missing notes records for following note revision ID > note ID", errorList);
await runCheck(`
SELECT

View file

@ -154,32 +154,32 @@ async function protectNote(note, dataKey, protect, sourceId) {
await sync_table.addNoteSync(note.noteId, sourceId);
}
await protectNoteHistory(note.noteId, dataKey, protect, sourceId);
await protectNoteRevisions(note.noteId, dataKey, protect, sourceId);
}
async function protectNoteHistory(noteId, dataKey, protect, sourceId) {
const historyToChange = await sql.getRows("SELECT * FROM note_revisions WHERE noteId = ? AND isProtected != ?", [noteId, protect]);
async function protectNoteRevisions(noteId, dataKey, protect, sourceId) {
const revisionsToChange = await sql.getRows("SELECT * FROM note_revisions WHERE noteId = ? AND isProtected != ?", [noteId, protect]);
for (const history of historyToChange) {
for (const revision of revisionsToChange) {
if (protect) {
protected_session.encryptNoteHistoryRow(dataKey, history);
protected_session.encryptNoteRevision(dataKey, revision);
history.isProtected = true;
revision.isProtected = true;
}
else {
protected_session.decryptNoteHistoryRow(dataKey, history);
protected_session.decryptNoteRevision(dataKey, revision);
history.isProtected = false;
revision.isProtected = false;
}
await sql.execute("UPDATE note_revisions SET title = ?, content = ?, isProtected = ? WHERE noteRevisionId = ?",
[history.title, history.content, history.isProtected, history.noteRevisionId]);
[revision.title, revision.content, revision.isProtected, revision.noteRevisionId]);
await sync_table.addNoteHistorySync(history.noteRevisionId, sourceId);
await sync_table.addNoteRevisionSync(revision.noteRevisionId, sourceId);
}
}
async function saveNoteHistory(noteId, dataKey, sourceId, nowStr) {
async function saveNoteRevision(noteId, dataKey, sourceId, nowStr) {
const oldNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]);
if (oldNote.type === 'file') {
@ -200,12 +200,12 @@ async function saveNoteHistory(noteId, dataKey, sourceId, nowStr) {
// title and text should be decrypted now
title: oldNote.title,
content: oldNote.content,
isProtected: 0, // will be fixed in the protectNoteHistory() call
isProtected: 0, // will be fixed in the protectNoteRevisions() call
dateModifiedFrom: oldNote.dateModified,
dateModifiedTo: nowStr
});
await sync_table.addNoteHistorySync(newNoteRevisionId, sourceId);
await sync_table.addNoteRevisionSync(newNoteRevisionId, sourceId);
}
async function saveNoteImages(noteId, noteText, sourceId) {
@ -279,26 +279,26 @@ async function updateNote(noteId, newNote, dataKey, sourceId) {
const now = new Date();
const nowStr = utils.nowDate();
const historySnapshotTimeInterval = parseInt(await options.getOption('history_snapshot_time_interval'));
const noteRevisionSnapshotTimeInterval = parseInt(await options.getOption('note_revision_snapshot_time_interval'));
const historyCutoff = utils.dateStr(new Date(now.getTime() - historySnapshotTimeInterval * 1000));
const revisionCutoff = utils.dateStr(new Date(now.getTime() - noteRevisionSnapshotTimeInterval * 1000));
const existingnoteRevisionId = await sql.getValue(
"SELECT noteRevisionId FROM note_revisions WHERE noteId = ? AND dateModifiedTo >= ?", [noteId, historyCutoff]);
"SELECT noteRevisionId FROM note_revisions WHERE noteId = ? AND dateModifiedTo >= ?", [noteId, revisionCutoff]);
await sql.doInTransaction(async () => {
const msSinceDateCreated = now.getTime() - utils.parseDateTime(newNote.detail.dateCreated).getTime();
if (labelsMap.disable_versioning !== 'true'
&& !existingnoteRevisionId
&& msSinceDateCreated >= historySnapshotTimeInterval * 1000) {
&& msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) {
await saveNoteHistory(noteId, dataKey, sourceId, nowStr);
await saveNoteRevision(noteId, dataKey, sourceId, nowStr);
}
await saveNoteImages(noteId, newNote.detail.content, sourceId);
await protectNoteHistory(noteId, dataKey, newNote.detail.isProtected);
await protectNoteRevisions(noteId, dataKey, newNote.detail.isProtected);
await sql.execute("UPDATE notes SET title = ?, content = ?, isProtected = ?, dateModified = ? WHERE noteId = ?", [
newNote.detail.title,

View file

@ -76,7 +76,7 @@ async function initOptions(startNotePath) {
await createOption('start_note_path', startNotePath, false);
await createOption('protected_session_timeout', 600, true);
await createOption('history_snapshot_time_interval', 600, true);
await createOption('note_revision_snapshot_time_interval', 600, true);
await createOption('last_backup_date', utils.nowDate(), false);
await createOption('db_version', app_info.db_version, false);

View file

@ -75,7 +75,7 @@ function decryptNotes(dataKey, notes) {
}
}
function decryptNoteHistoryRow(dataKey, hist) {
function decryptNoteRevision(dataKey, hist) {
dataKey = getDataKey(dataKey);
if (!hist.isProtected) {
@ -91,11 +91,11 @@ function decryptNoteHistoryRow(dataKey, hist) {
}
}
function decryptNoteHistoryRows(dataKey, historyRows) {
function decryptNoteRevisions(dataKey, noteRevisions) {
dataKey = getDataKey(dataKey);
for (const hist of historyRows) {
decryptNoteHistoryRow(dataKey, hist);
for (const revision of noteRevisions) {
decryptNoteRevision(dataKey, revision);
}
}
@ -106,11 +106,11 @@ function encryptNote(dataKey, note) {
note.content = data_encryption.encrypt(dataKey, data_encryption.noteContentIv(note.noteId), note.content);
}
function encryptNoteHistoryRow(dataKey, history) {
function encryptNoteRevision(dataKey, revision) {
dataKey = getDataKey(dataKey);
history.title = data_encryption.encrypt(dataKey, data_encryption.noteTitleIv(history.noteRevisionId), history.title);
history.content = data_encryption.encrypt(dataKey, data_encryption.noteContentIv(history.noteRevisionId), history.content);
revision.title = data_encryption.encrypt(dataKey, data_encryption.noteTitleIv(revision.noteRevisionId), revision.title);
revision.content = data_encryption.encrypt(dataKey, data_encryption.noteContentIv(revision.noteRevisionId), revision.content);
}
module.exports = {
@ -120,8 +120,8 @@ module.exports = {
isProtectedSessionAvailable,
decryptNote,
decryptNotes,
decryptNoteHistoryRow,
decryptNoteHistoryRows,
decryptNoteRevision,
decryptNoteRevisions,
encryptNote,
encryptNoteHistoryRow
encryptNoteRevision
};

View file

@ -129,7 +129,7 @@ async function pullSync(syncContext) {
await syncUpdate.updateBranch(resp, syncContext.sourceId);
}
else if (sync.entityName === 'note_revisions') {
await syncUpdate.updateNoteHistory(resp, syncContext.sourceId);
await syncUpdate.updateNoteRevision(resp, syncContext.sourceId);
}
else if (sync.entityName === 'note_reordering') {
await syncUpdate.updateNoteReordering(resp, syncContext.sourceId);

View file

@ -16,7 +16,7 @@ async function addNoteReorderingSync(parentNoteId, sourceId) {
await addEntitySync("note_reordering", parentNoteId, sourceId)
}
async function addNoteHistorySync(noteRevisionId, sourceId) {
async function addNoteRevisionSync(noteRevisionId, sourceId) {
await addEntitySync("note_revisions", noteRevisionId, sourceId);
}
@ -104,7 +104,7 @@ module.exports = {
addNoteSync,
addBranchSync,
addNoteReorderingSync,
addNoteHistorySync,
addNoteRevisionSync,
addOptionsSync,
addRecentNoteSync,
addImageSync,

View file

@ -42,18 +42,18 @@ async function updateBranch(entity, sourceId) {
});
}
async function updateNoteHistory(entity, sourceId) {
async function updateNoteRevision(entity, sourceId) {
const orig = await sql.getRowOrNull("SELECT * FROM note_revisions WHERE noteRevisionId = ?", [entity.noteRevisionId]);
await sql.doInTransaction(async () => {
// we update note history even if date modified to is the same because the only thing which might have changed
// we update note revision even if date modified to is the same because the only thing which might have changed
// is the protected status (and correnspondingly title and content) which doesn't affect the dateModifiedTo
if (orig === null || orig.dateModifiedTo <= entity.dateModifiedTo) {
await sql.replace('note_revisions', entity);
await sync_table.addNoteHistorySync(entity.noteRevisionId, sourceId);
await sync_table.addNoteRevisionSync(entity.noteRevisionId, sourceId);
log.info("Update/sync note history " + entity.noteRevisionId);
log.info("Update/sync note revision " + entity.noteRevisionId);
}
});
}
@ -161,7 +161,7 @@ async function updateApiToken(entity, sourceId) {
module.exports = {
updateNote,
updateBranch,
updateNoteHistory,
updateNoteRevision,
updateNoteReordering,
updateOptions,
updateRecentNotes,

View file

@ -123,7 +123,7 @@
<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dLabel">
<li><a id="show-history-button"><kbd>Alt+H</kbd> History</a></li>
<li><a id="show-note-revisions-button">Note revisions</a></li>
<li><a class="show-labels-button"><kbd>Alt+L</kbd> Labels</a></li>
<li><a id="show-source-button"><kbd>Ctrl+U</kbd> HTML source</a></li>
<li><a id="upload-attachment-button">Upload attachment</a></li>
@ -277,7 +277,7 @@
<ul>
<li><a href="#change-password">Change password</a></li>
<li><a href="#protected-session-timeout">Protected session</a></li>
<li><a href="#history-snapshot-time-interval">History snapshots</a></li>
<li><a href="#note-revision-snapshot-time-interval">Note revisions</a></li>
<li><a href="#advanced">Advanced</a></li>
<li><a href="#about">About Trilium</a></li>
</ul>
@ -314,13 +314,13 @@
<button class="btn btn-sm">Save</button>
</form>
</div>
<div id="history-snapshot-time-interval">
<p>History snapshot time interval is time in seconds after which new history record will be created for the note.</p>
<div id="note-revision-snapshot-time-interval">
<p>Note revision snapshot time interval is time in seconds after which new note revision will be created for the note.</p>
<form id="history-snapshot-time-interval-form">
<form id="note-revision-snapshot-time-interval-form">
<div class="form-group">
<label for="history-snapshot-time-interval-in-seconds">History snapshot time interval (in seconds)</label>
<input class="form-control" id="history-snapshot-time-interval-in-seconds" type="number">
<label for="note-revision-snapshot-time-interval-in-seconds">Note revision snapshot time interval (in seconds)</label>
<input class="form-control" id="note-revision-snapshot-time-interval-in-seconds" type="number">
</div>
<button class="btn btn-sm">Save</button>
@ -346,7 +346,7 @@
<p>This will remove all image data of images not used in any current version of note from the database (metadata will remain).
This means that some images can disappear from note history.</p>
This means that some images can disappear from note revisions.</p>
<button id="cleanup-unused-images-button" class="btn btn-warning btn-sm">Permanently cleanup unused images</button>
@ -389,15 +389,15 @@
</div>
</div>
<div id="note-history-dialog" title="Note history" style="display: none;">
<div id="note-revisions-dialog" title="Note revisions" style="display: none;">
<div style="display: flex;">
<select id="note-history-list" size="25" style="width: 150px; height: 630px;">
<select id="note-revision-list" size="25" style="width: 150px; height: 630px;">
</select>
<div id="note-history-content-wrapper" style="flex-grow: 1; margin-left: 20px;">
<h3 id="note-history-title" style="margin: 3px;"></h3>
<div id="note-revision-content-wrapper" style="flex-grow: 1; margin-left: 20px;">
<h3 id="note-revision-title" style="margin: 3px;"></h3>
<div id="note-history-content" style="height: 600px; width: 600px; overflow: auto;"></div>
<div id="note-revision-content" style="height: 600px; width: 600px; overflow: auto;"></div>
</div>
</div>
</div>

View file

@ -67,8 +67,6 @@
<link href="libraries/bootstrap/css/bootstrap.css" rel="stylesheet">
<script src="libraries/bootstrap/js/bootstrap.js"></script>
<script src="javascripts/migration.js"></script>
<script src="javascripts/utils.js"></script>
<script src="javascripts/server.js"></script>
<script src="javascripts/migration.js" type="module"></script>
</body>
</html>