saving note detail

This commit is contained in:
zadam 2020-01-19 21:40:23 +01:00
parent 562c729ed6
commit 423a70d102
9 changed files with 80 additions and 58 deletions

View File

@ -27,8 +27,6 @@ async function openInTab(notePath, activate) {
}
async function switchToNote(notePath) {
await saveNotesIfChanged();
await loadNoteDetail(notePath);
appContext.openTabsChanged();
@ -38,15 +36,6 @@ function onNoteChange(func) {
return appContext.getActiveTabContext().getComponent().onNoteChange(func);
}
async function saveNotesIfChanged() {
for (const ctx of appContext.getTabContexts()) {
await ctx.saveNoteIfChanged();
}
// make sure indicator is visible in a case there was some race condition.
$savedIndicator.fadeIn();
}
function getActiveEditor() {
const activeTabContext = appContext.getActiveTabContext();
@ -210,10 +199,9 @@ function noteChanged() {
// this makes sure that when user e.g. reloads the page or navigates away from the page, the note's content is saved
// this sends the request asynchronously and doesn't wait for result
// FIXME
$(window).on('beforeunload', () => { saveNotesIfChanged(); }); // don't convert to short form, handler doesn't like returned promise
setInterval(saveNotesIfChanged, 3000);
export default {
reload,
openInTab,
@ -222,7 +210,6 @@ export default {
loadNoteDetail,
focusOnTitle,
focusAndSelectTitle,
saveNotesIfChanged,
onNoteChange,
addDetailLoadedListener,
getActiveEditor,

View File

@ -0,0 +1,36 @@
export default class SpacedUpdate {
constructor(updater, updateInterval = 1000) {
this.updater = updater;
this.lastUpdated = Date.now();
this.changed = false;
this.updateInterval = updateInterval;
}
scheduleUpdate() {
this.changed = true;
setTimeout(() => this.triggerUpdate())
}
async updateNowIfNecessary() {
if (this.changed) {
this.changed = false;
await this.updater();
}
}
triggerUpdate() {
if (!this.changed) {
return;
}
if (Date.now() - this.lastUpdated > this.updateInterval) {
this.updater();
this.lastUpdated = Date.now();
this.changed = false;
}
else {
// update not triggered but changes are still pending so we need to schedule another check
this.scheduleUpdate();
}
}
}

View File

@ -26,7 +26,6 @@ class TabContext extends Component {
this.tabRow = tabRow;
this.tabId = state.tabId || utils.randomString(4);
this.$tab = $(this.tabRow.addTab(this.tabId));
this.state = state;
this.attributes = new Attributes(this.appContext, this);

View File

@ -374,6 +374,7 @@ async function createNote(node, parentNoteId, target, extraOptions = {}) {
window.cutToNote.removeSelection();
}
// FIXME
await noteDetailService.saveNotesIfChanged();
noteDetailService.addDetailLoadedListener(note.noteId, noteDetailService.focusAndSelectTitle);

View File

@ -2,6 +2,8 @@ import TabAwareWidget from "./tab_aware_widget.js";
import utils from "../services/utils.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import appContext from "../services/app_context.js";
import SpacedUpdate from "../services/spaced_update.js";
import server from "../services/server.js";
const TPL = `
<div class="note-detail">
@ -32,6 +34,19 @@ export default class NoteDetailWidget extends TabAwareWidget {
this.typeWidgets = {};
this.typeWidgetPromises = {};
this.spacedUpdate = new SpacedUpdate(async () => {
const note = this.tabContext.note;
note.content = this.getTypeWidget().getContent();
const resp = await server.put('notes/' + note.noteId, note.dto);
// FIXME: minor - does not propagate to other tab contexts with this note though
note.dateModified = resp.dateModified;
note.utcDateModified = resp.utcDateModified;
this.trigger('noteChangesSaved', {noteId: note.noteId})
});
}
doRender() {
@ -114,12 +129,14 @@ export default class NoteDetailWidget extends TabAwareWidget {
async initWidgetType(type) {
const clazz = await import(typeWidgetClasses[type]);
this.typeWidgets[this.type] = new clazz.default(this.appContext);
this.children.push(this.typeWidgets[this.type]);
const typeWidget = this.typeWidgets[this.type] = new clazz.default(this.appContext);
this.children.push(typeWidget);
this.$widget.append(this.typeWidgets[this.type].render());
this.$widget.append(typeWidget.render());
this.typeWidgets[this.type].eventReceived('setTabContext', {tabContext: this.tabContext});
typeWidget.onNoteChange(() => this.spacedUpdate.scheduleUpdate());
typeWidget.eventReceived('setTabContext', {tabContext: this.tabContext});
}
getWidgetType(disableAutoBook) {
@ -153,4 +170,16 @@ export default class NoteDetailWidget extends TabAwareWidget {
widget.focus();
}
}
async beforeNoteSwitchListener({tabId}) {
if (this.isTab(tabId)) {
await this.spacedUpdate.updateNowIfNecessary();
}
}
async beforeTabRemoveListener({tabId}) {
if (this.isTab(tabId)) {
await this.spacedUpdate.updateNowIfNecessary();
}
}
}

View File

@ -3,6 +3,7 @@ import utils from "../services/utils.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import treeCache from "../services/tree_cache.js";
import server from "../services/server.js";
import SpacedUpdate from "../services/spaced_update.js";
const TPL = `
<div class="note-title-container">
@ -24,43 +25,6 @@ const TPL = `
<input autocomplete="off" value="" class="note-title" tabindex="1">
</div>`;
class SpacedUpdate {
constructor(updater, updateInterval = 1000) {
this.updater = updater;
this.lastUpdated = Date.now();
this.changed = false;
this.updateInterval = updateInterval;
}
scheduleUpdate() {
this.changed = true;
setTimeout(() => this.triggerUpdate())
}
async updateNowIfNecessary() {
if (this.changed) {
this.changed = false;
await this.updater();
}
}
triggerUpdate() {
if (!this.changed) {
return;
}
if (Date.now() - this.lastUpdated > this.updateInterval) {
this.updater();
this.lastUpdated = Date.now();
this.changed = false;
}
else {
// update not triggered but changes are still pending so we need to schedule another check
this.scheduleUpdate();
}
}
}
export default class NoteTitleWidget extends TabAwareWidget {
constructor(appContext) {
super(appContext);

View File

@ -109,6 +109,7 @@ class CodeTypeWidget extends TypeWidget {
}
// make sure note is saved so we load latest changes
// FIXME
await noteDetailService.saveNotesIfChanged();
if (this.tabContext.note.mime.endsWith("env=frontend")) {
@ -122,7 +123,9 @@ class CodeTypeWidget extends TypeWidget {
toastService.showMessage("Note executed");
}
onNoteChange(func) {
async onNoteChange(func) {
await this.initialized;
this.codeEditor.on('change', func);
}

View File

@ -13,6 +13,7 @@ class NoteDetailSearch {
this.$refreshButton = ctx.$tabContent.find('.note-detail-search-refresh-results-button');
this.$refreshButton.on('click', async () => {
// FIXME
await noteDetailService.saveNotesIfChanged();
await searchNotesService.refreshSearch();

View File

@ -174,7 +174,9 @@ class TextTypeWidget extends TypeWidget {
return this.textEditor;
}
onNoteChange(func) {
async onNoteChange(func) {
await this.initialized;
this.textEditor.model.document.on('change:data', func);
}