1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
window.API = {
async get(url) { const r = await fetch(url,{credentials:'same-origin'}); if(!r.ok)throw new Error(await r.text()); return r.json(); },
async post(url,data) { const r = await fetch(url,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(data),credentials:'same-origin'}); if(!r.ok)throw new Error(await r.text()); return r.json(); },
async put(url,data) { const r = await fetch(url,{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(data),credentials:'same-origin'}); if(!r.ok)throw new Error(await r.text()); return r.json(); },
async del(url) { const r = await fetch(url,{method:'DELETE',credentials:'same-origin'}); if(!r.ok)throw new Error(await r.text()); return r.json(); }
};
window.$ = (sel) => document.querySelector(sel);
window.$$ = (sel) => document.querySelectorAll(sel);
window.notify = function(msg, type) {
var el = document.createElement('div');
el.className = 'notification ' + (type || '');
el.textContent = msg;
document.body.appendChild(el);
setTimeout(function() { el.remove(); }, 3000);
};
window.undoState = null;
window.updateUndoBar = function() {
API.get('/api/undo/state').then(function(s) {
undoState = s;
var uBtn = $('.undo-btn');
var rBtn = $('.redo-btn');
var uLabel = $('.undo-label');
if (uBtn) { uBtn.disabled = !s.can_undo; uBtn.title = s.undo_desc || ''; }
if (rBtn) { rBtn.disabled = !s.can_redo; rBtn.title = s.redo_desc || ''; }
if (uLabel) { uLabel.textContent = s.undo_desc || ''; }
}).catch(function() {});
};
window.doUndo = function() {
API.post('/api/undo/undo').then(function(r) { notify(r.message || 'Undo complete', 'success'); updateUndoBar(); if(window.refreshPage)refreshPage(); }).catch(function(e) { notify('Undo failed: '+e.message, 'error'); });
};
window.doRedo = function() {
API.post('/api/undo/redo').then(function(r) { notify(r.message || 'Redo complete', 'success'); updateUndoBar(); if(window.refreshPage)refreshPage(); }).catch(function(e) { notify('Redo failed: '+e.message, 'error'); });
};
window.addEventListener('keydown', function(e) {
if ((e.ctrlKey || e.metaKey) && e.key === 'z') {
e.preventDefault();
if (e.shiftKey) { doRedo(); } else { doUndo(); }
}
});
window.saveForm = function(url, data, msg) {
API.put(url, data).then(function() {
updateUndoBar();
notify(msg || 'Saved', 'success');
}).catch(function(e) { notify('Save failed: '+e.message, 'error'); });
};
document.addEventListener('DOMContentLoaded', function() { updateUndoBar(); });
|