mirror of
https://github.com/apankrat/nullboard.git
synced 2025-08-02 19:27:47 +02:00
first draft of BackupStorage support
This commit is contained in:
183
nullboard.html
183
nullboard.html
@@ -1455,6 +1455,8 @@
|
|||||||
this.listWidth = null; // list-width
|
this.listWidth = null; // list-width
|
||||||
this.theme = null; // default or 'dark'
|
this.theme = null; // default or 'dark'
|
||||||
|
|
||||||
|
this.backups = [ ]; // [ { id: '?', conf: { } } ];
|
||||||
|
|
||||||
this.board = null; // active board
|
this.board = null; // active board
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1464,6 +1466,7 @@
|
|||||||
this.current = 1; // revision
|
this.current = 1; // revision
|
||||||
this.ui_spot = 0; // 0 = not set
|
this.ui_spot = 0; // 0 = not set
|
||||||
this.history = [ ]; // revision IDs
|
this.history = [ ]; // revision IDs
|
||||||
|
this.backups = [ ]; // backup agents IDs with which this board is stored
|
||||||
}
|
}
|
||||||
|
|
||||||
class Storage
|
class Storage
|
||||||
@@ -1474,6 +1477,8 @@
|
|||||||
|
|
||||||
this.conf = new AppConfig();
|
this.conf = new AppConfig();
|
||||||
this.boardIndex = new Map();
|
this.boardIndex = new Map();
|
||||||
|
|
||||||
|
this.backups = []; // BackupStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
open()
|
open()
|
||||||
@@ -1494,13 +1499,13 @@
|
|||||||
setVerLast(ver)
|
setVerLast(ver)
|
||||||
{
|
{
|
||||||
this.conf.verLast = ver || NB.codeVersion;
|
this.conf.verLast = ver || NB.codeVersion;
|
||||||
return this.setJson('config', this.conf);
|
return this.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
setVerSeen(ver)
|
setVerSeen(ver)
|
||||||
{
|
{
|
||||||
this.conf.verSeen = ver || NB.codeVersion;
|
this.conf.verSeen = ver || NB.codeVersion;
|
||||||
return this.setJson('config', this.conf);
|
return this.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
setActiveBoard(board_id)
|
setActiveBoard(board_id)
|
||||||
@@ -1510,42 +1515,56 @@
|
|||||||
if (! meta)
|
if (! meta)
|
||||||
throw `Invalid board_id in setActiveBoard(... ${board_id})`;
|
throw `Invalid board_id in setActiveBoard(... ${board_id})`;
|
||||||
|
|
||||||
|
if (this.conf.board == board_id)
|
||||||
|
return true;
|
||||||
|
|
||||||
this.conf.board = board_id;
|
this.conf.board = board_id;
|
||||||
return this.setJson('config', this.conf);
|
return this.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
setTheme(theme)
|
setTheme(theme)
|
||||||
{
|
{
|
||||||
if (this.conf.theme == theme) return;
|
if (this.conf.theme == theme) return;
|
||||||
this.conf.theme = theme;
|
this.conf.theme = theme;
|
||||||
return this.setJson('config', this.conf);
|
return this.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
setFontName(fname)
|
setFontName(fname)
|
||||||
{
|
{
|
||||||
if (this.conf.fontName == fname) return;
|
if (this.conf.fontName == fname) return;
|
||||||
this.conf.fontName = fname;
|
this.conf.fontName = fname;
|
||||||
return this.setJson('config', this.conf);
|
return this.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
setFontSize(fs)
|
setFontSize(fs)
|
||||||
{
|
{
|
||||||
if (this.conf.fontSize == fs) return;
|
if (this.conf.fontSize == fs) return;
|
||||||
this.conf.fontSize = fs;
|
this.conf.fontSize = fs;
|
||||||
return this.setJson('config', this.conf);
|
return this.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
setLineHeight(lh)
|
setLineHeight(lh)
|
||||||
{
|
{
|
||||||
if (this.conf.lineHeight == lh) return;
|
if (this.conf.lineHeight == lh) return;
|
||||||
this.conf.lineHeight = lh;
|
this.conf.lineHeight = lh;
|
||||||
return this.setJson('config', this.conf);
|
return this.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
setListWidth(lw)
|
setListWidth(lw)
|
||||||
{
|
{
|
||||||
if (this.conf.listWidth == lw) return;
|
if (this.conf.listWidth == lw) return;
|
||||||
this.conf.listWidth = lw;
|
this.conf.listWidth = lw;
|
||||||
|
return this.saveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
saveConfig()
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.backups.forEach(function(store){
|
||||||
|
store.saveConfig(self.conf);
|
||||||
|
});
|
||||||
|
|
||||||
return this.setJson('config', this.conf);
|
return this.setJson('config', this.conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1613,9 +1632,20 @@
|
|||||||
meta.history = rebuild;
|
meta.history = rebuild;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meta.backups = [];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save meta
|
||||||
|
*/
|
||||||
ok_meta = this.setJson('board.' + board.id + '.meta', meta) &&
|
ok_meta = this.setJson('board.' + board.id + '.meta', meta) &&
|
||||||
this.setJson('board.' + board.id, meta.current); // for older versions
|
this.setJson('board.' + board.id, meta.current); // for older versions
|
||||||
|
|
||||||
|
/*
|
||||||
|
* run backups
|
||||||
|
*/
|
||||||
|
if (ok_meta && ok_data)
|
||||||
|
this.backupBoard(board)
|
||||||
|
|
||||||
board.history = meta.history; // restore
|
board.history = meta.history; // restore
|
||||||
|
|
||||||
console.log( `Saved revision ${board.revision} of ${board.id} (${board.title}), ok = ${ok_data} | ${ok_meta}` );
|
console.log( `Saved revision ${board.revision} of ${board.id} (${board.title}), ok = ${ok_data} | ${ok_meta}` );
|
||||||
@@ -1675,6 +1705,10 @@
|
|||||||
this.delItem('board.' + board_id + '.meta');
|
this.delItem('board.' + board_id + '.meta');
|
||||||
this.boardIndex.delete(board_id);
|
this.boardIndex.delete(board_id);
|
||||||
|
|
||||||
|
this.backups.forEach(function(store){
|
||||||
|
store.nukeBoard(board_id);
|
||||||
|
});
|
||||||
|
|
||||||
console.log( `Deleted board ${board_id} (${title})` );
|
console.log( `Deleted board ${board_id} (${title})` );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1749,6 +1783,22 @@
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backupBoard(board)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
var meta = this.boardIndex.get(board.id);
|
||||||
|
var toGo = 0;
|
||||||
|
|
||||||
|
this.backups.forEach(function(store){
|
||||||
|
store.saveBoard(board.id, board, meta, function(ok){
|
||||||
|
console.log( `Backup of ${board.id} to ${store.id} -> ${ok ? 'ok' : 'failed'}` );
|
||||||
|
if (ok) meta.backups.push(store.id);
|
||||||
|
if (! --toGo) self.setJson('board.' + board.id + '.meta', meta);
|
||||||
|
});
|
||||||
|
toGo++;
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Storage_Local extends Storage
|
class Storage_Local extends Storage
|
||||||
@@ -1791,7 +1841,7 @@
|
|||||||
|
|
||||||
if (conf)
|
if (conf)
|
||||||
{
|
{
|
||||||
this.conf = conf;
|
this.conf = Object.assign(new AppConfig(), conf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1951,6 +2001,89 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class BackupStorage
|
||||||
|
{
|
||||||
|
constructor(conf)
|
||||||
|
{
|
||||||
|
this.id = '?';
|
||||||
|
this.conf = conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkStatus(cb) { return false; }
|
||||||
|
saveConfig(conf, cb) { throw 'implement-me'; }
|
||||||
|
saveBoard (id, data, meta, cb) { throw 'implement-me'; }
|
||||||
|
nukeBoard (id, cb) { throw 'implement-me'; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class SimpleBackup extends BackupStorage
|
||||||
|
{
|
||||||
|
constructor(conf)
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
this.id = 'sb';
|
||||||
|
this.conf = { base: 'http://127.0.0.1:10001', auth: '' }
|
||||||
|
this.conf = Object.assign(this.conf, conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkStatus(cb)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
$.get(this.conf.base + '/nullboard/status')
|
||||||
|
.done(function(){ cb.call(self, true); })
|
||||||
|
.fail(function(){ cb.call(self, false); })
|
||||||
|
}
|
||||||
|
|
||||||
|
saveConfig(conf, cb)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: this.conf.base + '/nullboard/config',
|
||||||
|
type: 'put',
|
||||||
|
headers: { 'X-Access-Token': this.conf.auth },
|
||||||
|
data: JSON.stringify(conf),
|
||||||
|
})
|
||||||
|
.done(function(){ if (cb) cb.call(self, true); })
|
||||||
|
.fail(function(){ if (cb) cb.call(self, false); })
|
||||||
|
}
|
||||||
|
|
||||||
|
saveBoard(id, data, meta, cb)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: this.conf.base + '/nullboard/board/' + id,
|
||||||
|
type: 'put',
|
||||||
|
headers: { 'X-Access-Token': this.conf.auth },
|
||||||
|
data:
|
||||||
|
{
|
||||||
|
data: data ? JSON.stringify(data) : null,
|
||||||
|
meta: meta ? JSON.stringify(meta) : null
|
||||||
|
},
|
||||||
|
dataType: 'json',
|
||||||
|
})
|
||||||
|
.done(function(){ if (cb) cb.call(self, true); })
|
||||||
|
.fail(function(){ if (cb) cb.call(self, false); })
|
||||||
|
}
|
||||||
|
|
||||||
|
nukeBoard(id, cb)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: this.conf.base + '/nullboard/board/' + id,
|
||||||
|
type: 'delete',
|
||||||
|
headers: { 'X-Access-Token': this.conf.auth },
|
||||||
|
})
|
||||||
|
.done(function(){ if (cb) cb.call(self, true); })
|
||||||
|
.fail(function(){ if (cb) cb.call(self, false); })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
@@ -2047,8 +2180,6 @@
|
|||||||
|
|
||||||
this.onPrimed = function()
|
this.onPrimed = function()
|
||||||
{
|
{
|
||||||
console.log('onPrimed');
|
|
||||||
|
|
||||||
clearTimeout(this.priming);
|
clearTimeout(this.priming);
|
||||||
this.priming = null;
|
this.priming = null;
|
||||||
|
|
||||||
@@ -2568,8 +2699,9 @@
|
|||||||
NB.board = null;
|
NB.board = null;
|
||||||
NB.storage.setActiveBoard(null);
|
NB.storage.setActiveBoard(null);
|
||||||
|
|
||||||
updateUndoRedo();
|
// updateUndoRedo();
|
||||||
updateBoardIndex();
|
updateBoardIndex();
|
||||||
|
updatePageTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -2614,13 +2746,16 @@
|
|||||||
function deleteBoard()
|
function deleteBoard()
|
||||||
{
|
{
|
||||||
var $list = $('.wrap .board .list');
|
var $list = $('.wrap .board .list');
|
||||||
|
var board_id = NB.board.id;
|
||||||
|
|
||||||
if ($list.length && ! confirm("PERMANENTLY delete this board, all its lists and their notes?"))
|
if ($list.length && ! confirm("PERMANENTLY delete this board, all its lists and their notes?"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
NB.storage.nukeBoard(NB.board.id);
|
|
||||||
|
|
||||||
closeBoard();
|
closeBoard();
|
||||||
|
|
||||||
|
NB.storage.nukeBoard(board_id);
|
||||||
|
|
||||||
|
updateBoardIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -2885,6 +3020,23 @@
|
|||||||
openBoard(data[0].id);
|
openBoard(data[0].id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function initBackups()
|
||||||
|
{
|
||||||
|
var conf = NB.storage.getConfig();
|
||||||
|
|
||||||
|
NB.backupTypes = new Map();
|
||||||
|
NB.backupTypes.set('sb', SimpleBackup);
|
||||||
|
|
||||||
|
conf.backups.forEach(function(agent){
|
||||||
|
var x = NB.backupTypes.get(agent.id);
|
||||||
|
if (x)
|
||||||
|
NB.storage.backups.push(new x(agent.conf));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -3319,7 +3471,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (drag.org_log != noteLocation($note))
|
if (this.org_loc != noteLocation($note))
|
||||||
saveBoard();
|
saveBoard();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4027,7 +4179,8 @@
|
|||||||
console.log( `Theme: [${conf.theme}]` );
|
console.log( `Theme: [${conf.theme}]` );
|
||||||
console.log( `Font: [${conf.fontName}], size [${conf.fontSize || '-'}], line-height [${conf.lineHeight || '-'}]` );
|
console.log( `Font: [${conf.fontName}], size [${conf.fontSize || '-'}], line-height [${conf.lineHeight || '-'}]` );
|
||||||
|
|
||||||
//
|
initBackups();
|
||||||
|
|
||||||
initFonts();
|
initFonts();
|
||||||
|
|
||||||
initDragAndDrop();
|
initDragAndDrop();
|
||||||
|
Reference in New Issue
Block a user