proper syncing of note positions

This commit is contained in:
azivner 2017-11-02 22:55:22 -04:00
parent c3d776ae13
commit a7f95e95e9
5 changed files with 72 additions and 14 deletions

View File

@ -40,16 +40,17 @@ router.put('/:noteId/moveBefore/:beforeNoteId', async (req, res, next) => {
const beforeNote = await sql.getSingleResult("select * from notes_tree where note_id = ?", [beforeNoteId]);
if (beforeNote) {
const now = utils.nowTimestamp();
await sql.doInTransaction(async () => {
await sql.execute("update notes_tree set note_pos = note_pos + 1, date_modified = ? where note_id = ?", [now, beforeNoteId]);
// we don't change date_modified so other changes are prioritized in case of conflict
await sql.execute("update notes_tree set note_pos = note_pos + 1 where note_pid = ? and note_pos >= ? and is_deleted = 0",
[beforeNote['note_pid'], beforeNote['note_pos']]);
await sql.execute("update notes_tree set note_pid = ?, note_pos = ?, date_modified = ? where note_id = ?",
[beforeNote['note_pid'], beforeNote['note_pos'], now, noteId]);
await sql.execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?",
[beforeNote['note_pid'], beforeNote['note_pos'], noteId]);
await sql.addNoteTreeSync(noteId);
await sql.addAudit(audit_category.CHANGE_POSITION, req, noteId);
await sql.addNoteReorderingSync(beforeNote['note_pid']);
await sql.addAudit(audit_category.CHANGE_POSITION, req, beforeNote['note_pid']);
});
}
@ -63,17 +64,17 @@ router.put('/:noteId/moveAfter/:afterNoteId', async (req, res, next) => {
const afterNote = await sql.getSingleResult("select * from notes_tree where note_id = ?", [afterNoteId]);
if (afterNote) {
const now = utils.nowTimestamp();
await sql.doInTransaction(async () => {
await sql.execute("update notes_tree set note_pos = note_pos + 1, date_modified = ? where note_pid = ? and note_pos > ? and is_deleted = 0",
[now, afterNote['note_pid'], afterNote['note_pos']]);
// we don't change date_modified so other changes are prioritized in case of conflict
await sql.execute("update notes_tree set note_pos = note_pos + 1 where note_pid = ? and note_pos > ? and is_deleted = 0",
[afterNote['note_pid'], afterNote['note_pos']]);
await sql.execute("update notes_tree set note_pid = ?, note_pos = ?, date_modified = ? where note_id = ?",
[afterNote['note_pid'], afterNote['note_pos'] + 1, now, noteId]);
await sql.execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?",
[afterNote['note_pid'], afterNote['note_pos'] + 1, noteId]);
await sql.addNoteTreeSync(noteId);
await sql.addAudit(audit_category.CHANGE_POSITION, req, noteId);
await sql.addNoteReorderingSync(afterNote['note_pid']);
await sql.addAudit(audit_category.CHANGE_POSITION, req, afterNote['note_pid']);
});
}
@ -86,7 +87,8 @@ router.put('/:noteId/expanded/:expanded', async (req, res, next) => {
const now = utils.nowTimestamp();
await sql.doInTransaction(async () => {
await sql.execute("update notes_tree set is_expanded = ?, date_modified = ? where note_id = ?", [expanded, now, noteId]);
// we don't change date_modified so other changes are prioritized in case of conflict
await sql.execute("update notes_tree set is_expanded = ? where note_id = ?", [expanded, noteId]);
await sql.addNoteTreeSync(noteId);
await sql.addAudit(audit_category.CHANGE_EXPANDED, req, noteId, null, expanded);

View File

@ -55,6 +55,15 @@ router.get('/options/:optName', auth.checkApiAuth, async (req, res, next) => {
}
});
router.get('/notes_reordering/:noteParentId', auth.checkApiAuth, async (req, res, next) => {
const noteParentId = req.params.noteParentId;
res.send({
note_pid: noteParentId,
ordering: await sql.getMap("SELECT note_id, note_pos FROM notes_tree WHERE note_pid = ?", [noteParentId])
});
});
router.put('/notes', auth.checkApiAuth, async (req, res, next) => {
await sync.updateNote(req.body.entity, req.body.links, req.body.sourceId);
@ -73,6 +82,12 @@ router.put('/notes_history', auth.checkApiAuth, async (req, res, next) => {
res.send({});
});
router.put('/notes_reordering', auth.checkApiAuth, async (req, res, next) => {
await sync.updateNoteReordering(req.body.entity, req.body.sourceId);
res.send({});
});
router.put('/options', auth.checkApiAuth, async (req, res, next) => {
await sync.updateOptions(req.body.entity, req.body.sourceId);

View File

@ -3,6 +3,7 @@
module.exports = {
UPDATE_CONTENT: 'CONTENT',
UPDATE_TITLE: 'TITLE',
// associated noteId is parent of notes where position changes happened
CHANGE_POSITION: 'POSITION',
CHANGE_EXPANDED: 'EXPANDED',
CREATE_NOTE: 'CREATE',

View File

@ -62,6 +62,19 @@ async function getResults(query, params = []) {
return await wrap(async () => db.all(query, ...params));
}
async function getMap(query, params = []) {
const map = {};
const results = await getResults(query, params);
for (const row of results) {
const keys = Object.keys(row);
map[row[keys[0]]] = row[keys[1]];
}
return map;
}
async function getFlattenedResults(key, query, params = []) {
const list = [];
const result = await getResults(query, params);
@ -123,6 +136,10 @@ async function addNoteTreeSync(noteId, sourceId) {
await addEntitySync("notes_tree", noteId, sourceId)
}
async function addNoteReorderingSync(noteId, sourceId) {
await addEntitySync("notes_reordering", noteId, sourceId)
}
async function addNoteHistorySync(noteHistoryId, sourceId) {
await addEntitySync("notes_history", noteHistoryId, sourceId);
}
@ -180,6 +197,7 @@ module.exports = {
getSingleResult,
getSingleResultOrNull,
getResults,
getMap,
getFlattenedResults,
execute,
executeScript,
@ -190,6 +208,7 @@ module.exports = {
doInTransaction,
addNoteSync,
addNoteTreeSync,
addNoteReorderingSync,
addNoteHistorySync,
addOptionsSync
};

View File

@ -60,6 +60,9 @@ async function pullSync(syncContext, syncLog) {
else if (sync.entity_name === 'notes_history') {
await updateNoteHistory(resp, syncContext.sourceId, syncLog);
}
else if (sync.entity_name === 'notes_reordering') {
await updateNoteReordering(resp, syncContext.sourceId, syncLog);
}
else if (sync.entity_name === 'options') {
await updateOptions(resp, syncContext.sourceId, syncLog);
}
@ -110,6 +113,12 @@ async function readAndPushEntity(sync, syncLog, syncContext) {
else if (sync.entity_name === 'notes_history') {
entity = await sql.getSingleResult('SELECT * FROM notes_history WHERE note_history_id = ?', [sync.entity_id]);
}
else if (sync.entity_name === 'notes_reordering') {
entity = {
note_pid: sync.entity_id,
ordering: await sql.getMap('SELECT note_id, note_pos FROM notes_tree WHERE note_pid = ?', [sync.entity_id])
};
}
else if (sync.entity_name === 'options') {
entity = await sql.getSingleResult('SELECT * FROM options WHERE opt_name = ?', [sync.entity_id]);
}
@ -306,6 +315,17 @@ async function updateNoteHistory(entity, sourceId, syncLog) {
}
}
async function updateNoteReordering(entity, sourceId, syncLog) {
await sql.doInTransaction(async () => {
Object.keys(entity.ordering).forEach(async key => {
await sql.execute("UPDATE notes_tree SET note_pos = ? WHERE note_id = ?", [entity.ordering[key], key]);
});
await sql.addNoteReorderingSync(entity.note_pid, sourceId);
await sql.addSyncAudit(audit_category.CHANGE_POSITION, sourceId, entity.note_pid);
});
}
async function updateOptions(entity, sourceId, syncLog) {
if (!options.SYNCED_OPTIONS.includes(entity.opt_name)) {
return;
@ -344,6 +364,7 @@ module.exports = {
updateNote,
updateNoteTree,
updateNoteHistory,
updateNoteReordering,
updateOptions,
isSyncSetup
};