reloading notes after script changes

This commit is contained in:
zadam 2019-10-20 12:29:34 +02:00
parent 78f5b7b288
commit 2305ad7405
21 changed files with 115 additions and 82 deletions

View File

@ -1581,7 +1581,7 @@
<h4 class="name" id="getActiveNote"><span class="type-signature"></span>getActiveNote<span class="signature">()</span><span class="type-signature"> &rarr; {<a href="NoteFull.html">NoteFull</a>}</span></h4> <h4 class="name" id="getActiveTabNote"><span class="type-signature"></span>getActiveTabNote<span class="signature">()</span><span class="type-signature"> &rarr; {<a href="NoteFull.html">NoteFull</a>}</span></h4>
@ -1687,7 +1687,7 @@
<h4 class="name" id="getActiveNotePath"><span class="type-signature"></span>getActiveNotePath<span class="signature">()</span><span class="type-signature"> &rarr; {Promise.&lt;(string|null)>}</span></h4> <h4 class="name" id="getActiveTabNotePath"><span class="type-signature"></span>getActiveTabNotePath<span class="signature">()</span><span class="type-signature"> &rarr; {Promise.&lt;(string|null)>}</span></h4>

View File

@ -236,7 +236,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
* @param {string} noteId * @param {string} noteId
* @method * @method
*/ */
this.reloadChildren = async noteId => await treeCache.reloadChildren(noteId); this.reloadChildren = async noteId => await treeCache.reloadNotesAndTheirChildren(noteId);
/** /**
* @param {string} noteId * @param {string} noteId
@ -303,13 +303,13 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
* @method * @method
* @returns {NoteFull} active note (loaded into right pane) * @returns {NoteFull} active note (loaded into right pane)
*/ */
this.getActiveNote = noteDetailService.getActiveNote; this.getActiveTabNote = noteDetailService.getActiveTabNote;
/** /**
* @method * @method
* @returns {Promise&lt;string|null>} returns note path of active note or null if there isn't active note * @returns {Promise&lt;string|null>} returns note path of active note or null if there isn't active note
*/ */
this.getActiveNotePath = () => { this.getActiveTabNotePath = () => {
const activeTabContext = noteDetailService.getActiveTabContext(); const activeTabContext = noteDetailService.getActiveTabContext();
return activeTabContext ? activeTabContext.notePath : null; return activeTabContext ? activeTabContext.notePath : null;

View File

@ -29,8 +29,8 @@
async function validatorJavaScript(text, options) { async function validatorJavaScript(text, options) {
if (glob.isMobile() if (glob.isMobile()
|| glob.getActiveNote() == null || glob.getActiveTabNote() == null
|| glob.getActiveNote().mime === 'application/json') { || glob.getActiveTabNote().mime === 'application/json') {
// eslint doesn't seem to validate pure JSON well // eslint doesn't seem to validate pure JSON well
return []; return [];
} }

View File

@ -43,7 +43,7 @@ window.glob.noteChanged = noteDetailService.noteChanged;
window.glob.refreshTree = treeService.reload; window.glob.refreshTree = treeService.reload;
// required for ESLint plugin // required for ESLint plugin
window.glob.getActiveNote = noteDetailService.getActiveNote; window.glob.getActiveTabNote = noteDetailService.getActiveTabNote;
window.glob.requireLibrary = libraryLoader.requireLibrary; window.glob.requireLibrary = libraryLoader.requireLibrary;
window.glob.ESLINT = libraryLoader.ESLINT; window.glob.ESLINT = libraryLoader.ESLINT;

View File

@ -33,7 +33,7 @@ export async function showDialog(linkType) {
glob.activeDialog = $dialog; glob.activeDialog = $dialog;
if (noteDetailService.getActiveNoteType() === 'text') { if (noteDetailService.getActiveTabNoteType() === 'text') {
$linkTypeHtml.prop('disabled', false); $linkTypeHtml.prop('disabled', false);
setLinkType('html'); setLinkType('html');
@ -110,14 +110,14 @@ $form.submit(() => {
else if (linkType === 'selected-to-active') { else if (linkType === 'selected-to-active') {
const prefix = $clonePrefix.val(); const prefix = $clonePrefix.val();
cloningService.cloneNoteTo(noteId, noteDetailService.getActiveNoteId(), prefix); cloningService.cloneNoteTo(noteId, noteDetailService.getActiveTabNoteId(), prefix);
$dialog.modal('hide'); $dialog.modal('hide');
} }
else if (linkType === 'active-to-selected') { else if (linkType === 'active-to-selected') {
const prefix = $clonePrefix.val(); const prefix = $clonePrefix.val();
cloningService.cloneNoteTo(noteDetailService.getActiveNoteId(), noteId, prefix); cloningService.cloneNoteTo(noteDetailService.getActiveTabNoteId(), noteId, prefix);
$dialog.modal('hide'); $dialog.modal('hide');
} }

View File

@ -92,7 +92,7 @@ function AttributesModel() {
} }
this.loadAttributes = async function() { this.loadAttributes = async function() {
const noteId = noteDetailService.getActiveNoteId(); const noteId = noteDetailService.getActiveTabNoteId();
const attributes = await server.get('notes/' + noteId + '/attributes'); const attributes = await server.get('notes/' + noteId + '/attributes');
@ -138,7 +138,7 @@ function AttributesModel() {
self.updateAttributePositions(); self.updateAttributePositions();
const noteId = noteDetailService.getActiveNoteId(); const noteId = noteDetailService.getActiveTabNoteId();
const attributesToSave = self.ownedAttributes() const attributesToSave = self.ownedAttributes()
.map(attribute => attribute()) .map(attribute => attribute())

View File

@ -23,7 +23,7 @@ export async function showDialog() {
// set default settings // set default settings
$maxNotesInput.val(20); $maxNotesInput.val(20);
const note = noteDetailService.getActiveNote(); const note = noteDetailService.getActiveTabNote();
if (!note) { if (!note) {
return; return;

View File

@ -16,7 +16,7 @@ export function showDialog() {
$dialog.modal(); $dialog.modal();
const activeNote = noteDetailService.getActiveNote(); const activeNote = noteDetailService.getActiveTabNote();
$noteId.text(activeNote.noteId); $noteId.text(activeNote.noteId);
$dateCreated.text(activeNote.dateCreated); $dateCreated.text(activeNote.dateCreated);

View File

@ -11,7 +11,7 @@ let revisionItems = [];
let note; let note;
export async function showCurrentNoteRevisions() { export async function showCurrentNoteRevisions() {
await showNoteRevisionsDialog(noteDetailService.getActiveNoteId()); await showNoteRevisionsDialog(noteDetailService.getActiveTabNoteId());
} }
export async function showNoteRevisionsDialog(noteId, noteRevisionId) { export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
@ -24,7 +24,7 @@ export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
$list.empty(); $list.empty();
$content.empty(); $content.empty();
note = noteDetailService.getActiveNote(); note = noteDetailService.getActiveTabNote();
revisionItems = await server.get('notes/' + noteId + '/revisions'); revisionItems = await server.get('notes/' + noteId + '/revisions');
for (const item of revisionItems) { for (const item of revisionItems) {

View File

@ -11,7 +11,7 @@ export function showDialog() {
$dialog.modal(); $dialog.modal();
const noteText = noteDetailService.getActiveNote().content; const noteText = noteDetailService.getActiveTabNote().content;
$noteSource.text(formatHtml(noteText)); $noteSource.text(formatHtml(noteText));
} }

View File

@ -162,9 +162,7 @@ async function deleteNodes(nodes) {
node.remove(); node.remove();
} }
for (const parentNoteId of parentNoteIds) { await treeService.reloadNotes(parentNoteIds);
await treeService.reloadNote(parentNoteId);
}
// activate after all the reloading // activate after all the reloading
if (activeNotePath) { if (activeNotePath) {

View File

@ -14,7 +14,7 @@ async function cloneNoteTo(childNoteId, parentNoteId, prefix) {
treeCache.addBranchRelationship(resp.branchId, childNoteId, parentNoteId); treeCache.addBranchRelationship(resp.branchId, childNoteId, parentNoteId);
await treeService.reloadNote(parentNoteId); await treeService.reloadNotes([parentNoteId]);
} }
// beware that first arg is noteId and second is branchId! // beware that first arg is noteId and second is branchId!
@ -30,7 +30,7 @@ async function cloneNoteAfter(noteId, afterBranchId) {
treeCache.addBranchRelationship(resp.branchId, noteId, afterBranch.parentNoteId); treeCache.addBranchRelationship(resp.branchId, noteId, afterBranch.parentNoteId);
await treeService.reloadNote(afterBranch.parentNoteId); await treeService.reloadNotes([afterBranch.parentNoteId]);
} }
export default { export default {

View File

@ -210,7 +210,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
* @param {string} noteId * @param {string} noteId
* @method * @method
*/ */
this.reloadChildren = async noteId => await treeCache.reloadChildren(noteId); this.reloadNotesAndTheirChildren = async noteId => await treeCache.reloadNotesAndTheirChildren(noteId);
/** /**
* @param {string} noteId * @param {string} noteId
@ -277,17 +277,13 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
* @method * @method
* @returns {NoteFull} active note (loaded into right pane) * @returns {NoteFull} active note (loaded into right pane)
*/ */
this.getActiveNote = noteDetailService.getActiveNote; this.getActiveTabNote = noteDetailService.getActiveTabNote;
/** /**
* @method * @method
* @returns {Promise<string|null>} returns note path of active note or null if there isn't active note * @returns {Promise<string|null>} returns note path of active note or null if there isn't active note
*/ */
this.getActiveNotePath = () => { this.getActiveTabNotePath = noteDetailService.getActiveTabNotePath;
const activeTabContext = noteDetailService.getActiveTabContext();
return activeTabContext ? activeTabContext.notePath : null;
};
/** /**
* This method checks whether user navigated away from the note from which the scripts has been started. * This method checks whether user navigated away from the note from which the scripts has been started.

View File

@ -63,7 +63,7 @@ ws.subscribeToMessages(async message => {
toastService.showPersistent(toast); toastService.showPersistent(toast);
await treeService.reloadNote(message.parentNoteId); await treeService.reloadNotes([message.parentNoteId]);
if (message.result.importedNoteId) { if (message.result.importedNoteId) {
const node = await treeService.activateNote(message.result.importedNoteId); const node = await treeService.activateNote(message.result.importedNoteId);

View File

@ -8,7 +8,7 @@ const SELECTED_PATH_KEY = "data-note-path";
async function autocompleteSource(term, cb) { async function autocompleteSource(term, cb) {
const result = await server.get('autocomplete' const result = await server.get('autocomplete'
+ '?query=' + encodeURIComponent(term) + '?query=' + encodeURIComponent(term)
+ '&activeNoteId=' + noteDetailService.getActiveNoteId()); + '&activeNoteId=' + noteDetailService.getActiveTabNoteId());
if (result.length === 0) { if (result.length === 0) {
result.push({ result.push({

View File

@ -107,20 +107,26 @@ function getActiveTabContext() {
return tabContexts.find(tc => tc.tabId === tabId); return tabContexts.find(tc => tc.tabId === tabId);
} }
/** @returns {string|null} */
function getActiveTabNotePath() {
const activeContext = getActiveTabContext();
return activeContext ? activeContext.notePath : null;
}
/** @return {NoteFull} */ /** @return {NoteFull} */
function getActiveNote() { function getActiveTabNote() {
const activeContext = getActiveTabContext(); const activeContext = getActiveTabContext();
return activeContext ? activeContext.note : null; return activeContext ? activeContext.note : null;
} }
function getActiveNoteId() { function getActiveTabNoteId() {
const activeNote = getActiveNote(); const activeNote = getActiveTabNote();
return activeNote ? activeNote.noteId : null; return activeNote ? activeNote.noteId : null;
} }
function getActiveNoteType() { function getActiveTabNoteType() {
const activeNote = getActiveNote(); const activeNote = getActiveTabNote();
return activeNote ? activeNote.type : null; return activeNote ? activeNote.type : null;
} }
@ -300,7 +306,7 @@ function addDetailLoadedListener(noteId, callback) {
function fireDetailLoaded() { function fireDetailLoaded() {
for (const {noteId, callback} of detailLoadedListeners) { for (const {noteId, callback} of detailLoadedListeners) {
if (noteId === getActiveNoteId()) { if (noteId === getActiveTabNoteId()) {
callback(); callback();
} }
} }
@ -337,7 +343,7 @@ $tabContentsContainer.on("dragover", e => e.preventDefault());
$tabContentsContainer.on("dragleave", e => e.preventDefault()); $tabContentsContainer.on("dragleave", e => e.preventDefault());
$tabContentsContainer.on("drop", async e => { $tabContentsContainer.on("drop", async e => {
const activeNote = getActiveNote(); const activeNote = getActiveTabNote();
if (!activeNote) { if (!activeNote) {
return; return;
@ -497,9 +503,6 @@ export default {
switchToNote, switchToNote,
loadNote, loadNote,
loadNoteDetail, loadNoteDetail,
getActiveNote,
getActiveNoteType,
getActiveNoteId,
focusOnTitle, focusOnTitle,
focusAndSelectTitle, focusAndSelectTitle,
saveNotesIfChanged, saveNotesIfChanged,
@ -508,6 +511,10 @@ export default {
switchToTab, switchToTab,
getTabContexts, getTabContexts,
getActiveTabContext, getActiveTabContext,
getActiveTabNotePath,
getActiveTabNote,
getActiveTabNoteType,
getActiveTabNoteId,
getActiveEditor, getActiveEditor,
activateOrOpenNote, activateOrOpenNote,
clearOpenTabsTask, clearOpenTabsTask,

View File

@ -70,13 +70,13 @@ async function enterProtectedSessionOnServer(password) {
} }
async function protectNoteAndSendToServer() { async function protectNoteAndSendToServer() {
if (!noteDetailService.getActiveNote() || noteDetailService.getActiveNote().isProtected) { if (!noteDetailService.getActiveTabNote() || noteDetailService.getActiveTabNote().isProtected) {
return; return;
} }
await enterProtectedSession(); await enterProtectedSession();
const note = noteDetailService.getActiveNote(); const note = noteDetailService.getActiveTabNote();
note.isProtected = true; note.isProtected = true;
await noteDetailService.getActiveTabContext().saveNote(); await noteDetailService.getActiveTabContext().saveNote();
@ -87,7 +87,7 @@ async function protectNoteAndSendToServer() {
} }
async function unprotectNoteAndSendToServer() { async function unprotectNoteAndSendToServer() {
const activeNote = noteDetailService.getActiveNote(); const activeNote = noteDetailService.getActiveTabNote();
if (!activeNote.isProtected) { if (!activeNote.isProtected) {
toastService.showAndLogError(`Note ${activeNote.noteId} is not protected`); toastService.showAndLogError(`Note ${activeNote.noteId} is not protected`);

View File

@ -580,14 +580,11 @@ async function scrollToActiveNote() {
} }
} }
function setBranchBackgroundBasedOnProtectedStatus(noteId) {
getNodesByNoteId(noteId).map(node => node.toggleClass("protected", node.data.isProtected));
}
function setProtected(noteId, isProtected) { function setProtected(noteId, isProtected) {
getNodesByNoteId(noteId).map(node => node.data.isProtected = isProtected); getNodesByNoteId(noteId).map(node => {
node.data.isProtected = isProtected;
setBranchBackgroundBasedOnProtectedStatus(noteId); node.toggleClass("protected", isProtected);
});
} }
async function setNoteTitle(noteId, title) { async function setNoteTitle(noteId, title) {
@ -619,7 +616,7 @@ async function createNote(node, parentNoteId, target, extraOptions = {}) {
extraOptions.isProtected = false; extraOptions.isProtected = false;
} }
if (noteDetailService.getActiveNoteType() !== 'text') { if (noteDetailService.getActiveTabNoteType() !== 'text') {
extraOptions.saveSelection = false; extraOptions.saveSelection = false;
} }
else { else {
@ -762,13 +759,27 @@ ws.subscribeToMessages(message => {
}); });
ws.subscribeToOutsideSyncMessages(syncData => { ws.subscribeToOutsideSyncMessages(syncData => {
if (syncData.some(sync => sync.entityName === 'branches') const noteIdsToRefresh = [];
|| syncData.some(sync => sync.entityName === 'notes')) {
console.log(utils.now(), "Reloading tree because of background changes"); for (const sync of syncData.filter(sync => sync.entityName === 'branches')) {
if (!noteIdsToRefresh.includes(sync.parentNoteId)) {
reload(); noteIdsToRefresh.push(sync.parentNoteId);
}
} }
for (const sync of syncData.filter(sync => sync.entityName === 'notes')) {
if (!noteIdsToRefresh.includes(sync.noteId)) {
noteIdsToRefresh.push(sync.noteId);
}
}
for (const sync of syncData.filter(sync => sync.entityName === 'note_reordering')) {
if (!noteIdsToRefresh.includes(sync.entityId)) {
noteIdsToRefresh.push(sync.entityId);
}
}
reloadNotes(noteIdsToRefresh);
}); });
utils.bindGlobalShortcut('ctrl+o', async () => { utils.bindGlobalShortcut('ctrl+o', async () => {
@ -805,13 +816,25 @@ async function checkFolderStatus(node) {
node.renderTitle(); node.renderTitle();
} }
async function reloadNote(noteId) { async function reloadNotes(noteIds) {
await treeCache.reloadChildren(noteId); await treeCache.reloadNotesAndTheirChildren(noteIds);
for (const node of getNodesByNoteId(noteId)) { const activeNotePath = noteDetailService.getActiveTabNotePath();
await node.load(true);
await checkFolderStatus(node); for (const noteId of noteIds) {
for (const node of getNodesByNoteId(noteId)) {
await node.load(true);
await checkFolderStatus(node);
}
}
if (activeNotePath) {
const node = await getNodeFromPath(activeNotePath);
if (node) {
node.setActive(true, {noEvents: true}); // this node has been already active so no need to fire events again
}
} }
} }
@ -868,7 +891,6 @@ frontendLoaded.then(bundle.executeStartupBundles);
export default { export default {
reload, reload,
collapseTree, collapseTree,
setBranchBackgroundBasedOnProtectedStatus,
setProtected, setProtected,
activateNote, activateNote,
getFocusedNode, getFocusedNode,
@ -887,7 +909,7 @@ export default {
setExpandedToServer, setExpandedToServer,
getNodesByNoteId, getNodesByNoteId,
checkFolderStatus, checkFolderStatus,
reloadNote, reloadNotes,
loadTreeCache, loadTreeCache,
expandToNote, expandToNote,
getNodeFromPath, getNodeFromPath,

View File

@ -54,24 +54,27 @@ class TreeCache {
} }
/** /**
* Reload children of given noteId. * Reload notes and their children.
*/ */
async reloadChildren(noteId) { async reloadNotesAndTheirChildren(noteIds) {
const resp = await server.post('tree/load', { noteIds: [noteId] }); // first load the data before clearing the cache
const resp = await server.post('tree/load', { noteIds });
for (const childNoteId of this.children[noteId] || []) { for (const noteId of noteIds) {
this.parents[childNoteId] = this.parents[childNoteId].filter(p => p !== noteId); for (const childNoteId of this.children[noteId] || []) {
this.parents[childNoteId] = this.parents[childNoteId].filter(p => p !== noteId);
const branchId = this.getBranchIdByChildParent(childNoteId, noteId); const branchId = this.getBranchIdByChildParent(childNoteId, noteId);
delete this.branches[branchId]; delete this.branches[branchId];
delete this.childParentToBranch[childNoteId + '-' + noteId]; delete this.childParentToBranch[childNoteId + '-' + noteId];
}
this.children[noteId] = [];
delete this.notes[noteId];
} }
this.children[noteId] = [];
delete this.notes[noteId];
this.addResp(resp.notes, resp.branches, resp.relations); this.addResp(resp.notes, resp.branches, resp.relations);
} }
@ -83,12 +86,10 @@ class TreeCache {
// to be able to find parents we need first to make sure it is actually loaded // to be able to find parents we need first to make sure it is actually loaded
await this.getNote(noteId); await this.getNote(noteId);
for (const parentNoteId of this.parents[noteId] || []) { await this.reloadNotesAndTheirChildren(this.parents[noteId] || []);
await this.reloadChildren(parentNoteId);
}
// this is done to load the new parents for the noteId // this is done to load the new parents for the noteId
await this.reloadChildren(noteId); await this.reloadNotesAndTheirChildren([noteId]);
} }
/** @return {Promise<NoteShort[]>} */ /** @return {Promise<NoteShort[]>} */

View File

@ -863,12 +863,14 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
position: absolute; position: absolute;
width: 100%; width: 100%;
top: 20px; top: 20px;
z-index: -100; pointer-events: none;
} }
.toast { .toast {
background-color: var(--accented-background-color) !important; background-color: var(--accented-background-color) !important;
color: var(--main-text-color) !important; color: var(--main-text-color) !important;
z-index: 9999999999 !important;
pointer-events: all;
} }
.toast-header { .toast-header {

View File

@ -67,12 +67,19 @@ async function sendPing(client, lastSentSyncId) {
const syncData = await sql.getRows("SELECT * FROM sync WHERE id > ?", [lastSentSyncId]); const syncData = await sql.getRows("SELECT * FROM sync WHERE id > ?", [lastSentSyncId]);
for (const sync of syncData) { for (const sync of syncData) {
// fill in some extra data needed by the frontend
if (sync.entityName === 'attributes') { if (sync.entityName === 'attributes') {
sync.noteId = await sql.getValue(`SELECT noteId FROM attributes WHERE attributeId = ?`, [sync.entityId]); sync.noteId = await sql.getValue(`SELECT noteId FROM attributes WHERE attributeId = ?`, [sync.entityId]);
} }
else if (sync.entityName === 'note_revisions') { else if (sync.entityName === 'note_revisions') {
sync.noteId = await sql.getValue(`SELECT noteId FROM note_revisions WHERE noteRevisionId = ?`, [sync.entityId]); sync.noteId = await sql.getValue(`SELECT noteId FROM note_revisions WHERE noteRevisionId = ?`, [sync.entityId]);
} }
else if (sync.entityName === 'branches') {
const {noteId, parentNoteId} = await sql.getRow(`SELECT noteId, parentNoteId FROM branches WHERE branchId = ?`, [sync.entityId]);
sync.noteId = noteId;
sync.parentNoteId = parentNoteId;
}
} }
const stats = require('./sync').stats; const stats = require('./sync').stats;