diff --git a/design.drawio b/design.drawio new file mode 100644 index 0000000..6118e3e --- /dev/null +++ b/design.drawio @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/page.go b/page.go index ee5c255..e8ab1af 100644 --- a/page.go +++ b/page.go @@ -29,6 +29,5 @@ func (p Page) GetLayout() string { func (p Page) GetData() any { p.Data["_dev"] = FlagDev - p.Data["GRIS"] = "foo" return p.Data } diff --git a/static/images/design.svg b/static/images/design.svg index 4fe5ef9..6af2931 100644 --- a/static/images/design.svg +++ b/static/images/design.svg @@ -53,8 +53,8 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1" - inkscape:cx="666.5" - inkscape:cy="485" + inkscape:cx="647.5" + inkscape:cy="483" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" @@ -263,7 +263,7 @@ y="32.808334" />API.logout()}>Log out - <${Tree} app=${this} /> + + <${Tree} ref=${this.tree} app=${this} /> ` }//}}} setStartNode() {//{{{ @@ -26,7 +27,8 @@ export class Notes2 { const req = {} API.query('POST', '/node/tree', req) .then(response => { - console.log(response) + console.log(response.Nodes) + nodeStore.add(response.Nodes) }) .catch(e => console.log(e.type, e.error)) } @@ -51,8 +53,7 @@ class Tree extends Component { }//}}} retrieve(callback = null) {//{{{ - const req = { StartNodeID: 0 } - API.query('POST', '/node/tree', req) + nodeStore.getTreeNodes() .then(res => { this.treeNodes = {} this.treeNodeComponents = {} @@ -63,7 +64,7 @@ class Tree extends Component { // returned from the server to be sorted in such a way that // a parent node always appears before a child node. // The server uses a recursive SQL query delivering this. - res.Nodes.forEach(nodeData => { + res.forEach(nodeData => { let node = new Node( this, nodeData.ID, diff --git a/static/js/key.mjs b/static/js/key.mjs index 4cc8f28..1f8c40f 100644 --- a/static/js/key.mjs +++ b/static/js/key.mjs @@ -1,4 +1,3 @@ -import 'preact/devtools' import { h, Component } from 'preact' import htm from 'htm' import Crypto from 'crypto' diff --git a/static/js/node_store.mjs b/static/js/node_store.mjs new file mode 100644 index 0000000..0a24dbe --- /dev/null +++ b/static/js/node_store.mjs @@ -0,0 +1,87 @@ +export class NodeStore { + constructor() { + if (!('indexedDB' in window)) { + throw 'Missing IndexedDB' + } + + this.db = null + } + + async initializeDB() { + return new Promise((resolve, reject) => { + let req = indexedDB.open('notes', 2) + + + // Schema upgrades for IndexedDB. + // These can start from different points depending on updates to Notes2 since a device was online. + req.onupgradeneeded = (event) => { + var store + let db = event.target.result + let trx = event.target.transaction + + for (let i = event.oldVersion + 1; i <= event.newVersion; i++) { + console.log(`Upgrade to schema ${i}`) + + // The schema transformations. + switch (i) { + case 1: + store = db.createObjectStore('nodes', { keyPath: 'ID' }) + store.createIndex('nameIndex', 'Name', { unique: false }) + break + case 2: + trx.objectStore('nodes').createIndex('parentIndex', 'ParentID', { unique: false }) + break + } + } + } + + req.onsuccess = (event) => { + this.db = event.target.result + resolve() + } + + req.onerror = (event) => { + reject(event.target.error) + } + }) + } + + async add(records) { + return new Promise((resolve, reject) => { + try { + let t = this.db.transaction('nodes', 'readwrite') + let nodeStore = t.objectStore('nodes') + t.onerror = (event) => { + console.log('transaction error', event.target.error) + reject(event.target.error) + } + t.oncomplete = () => { + resolve() + } + + records.forEach(record => { + let addReq = nodeStore.add(record) + addReq.onsuccess = (event) => { + console.log('OK!', record.ID, record.Name) + } + addReq.onerror = (event) => { + console.log('Error!', event.target.error, record.ID) + } + }) + + } catch (e) { + console.log(e) + } + }) + } + + async getTreeNodes() { + return new Promise((resolve, reject)=>{ + let trx = this.db.transaction('nodes', 'readonly') + let nodeStore = trx.objectStore('nodes') + let req = nodeStore.getAll() + req.onsuccess = (event)=>resolve(event.target.result) + req.onerror = (event)=>reject(event.target.error) + }) + } +} diff --git a/views/layouts/main.gotmpl b/views/layouts/main.gotmpl index 98bd8d0..1931f13 100644 --- a/views/layouts/main.gotmpl +++ b/views/layouts/main.gotmpl @@ -15,25 +15,23 @@ "imports": { "preact": "/js/{{ .VERSION }}/lib/preact/preact.mjs", "preact/hooks": "/js/{{ .VERSION }}/lib/preact/hooks.mjs", + {{- if .Data._dev }} "preact/debug": "/js/{{ .VERSION }}/lib/preact/debug.mjs", "preact/devtools": "/js/{{ .VERSION }}/lib/preact/devtools.mjs", + {{- end }} "@preact/signals-core": "/js/{{ .VERSION }}/lib/signals/signals-core.mjs", "preact/signals": "/js/{{ .VERSION }}/lib/signals/signals.mjs", "htm": "/js/{{ .VERSION }}/lib/htm/htm.mjs", - "api": "/js/{{ .VERSION }}/api.mjs", - "key": "/js/{{ .VERSION }}/key.mjs", - "checklist": "/js/{{ .VERSION }}/checklist.mjs", - "crypto": "/js/{{ .VERSION }}/crypto.mjs", - "node": "/js/{{ .VERSION }}/node.mjs" + "api": "/js/{{ .VERSION }}/api.mjs", + "key": "/js/{{ .VERSION }}/key.mjs", + "checklist": "/js/{{ .VERSION }}/checklist.mjs", + "crypto": "/js/{{ .VERSION }}/crypto.mjs", + "node_store": "/js/{{ .VERSION }}/node_store.mjs", + "node": "/js/{{ .VERSION }}/node.mjs" {{/* - "session": "/js/{{ .VERSION }}/session.mjs", - "node": "/js/{{ .VERSION }}/node.mjs", - "node_store": "/js/{{ .VERSION }}/node_store.mjs", - "key": "/js/{{ .VERSION }}/key.mjs", - "crypto": "/js/{{ .VERSION }}/crypto.mjs", - "checklist": "/js/{{ .VERSION }}/checklist.mjs", - "ws": "/_js/{{ .VERSION }}/websocket.mjs" + "session": "/js/{{ .VERSION }}/session.mjs", + "ws": "/_js/{{ .VERSION }}/websocket.mjs" */}} } } diff --git a/views/pages/notes2.gotmpl b/views/pages/notes2.gotmpl index b3e37e0..9894ce3 100644 --- a/views/pages/notes2.gotmpl +++ b/views/pages/notes2.gotmpl @@ -8,6 +8,7 @@ import htm from 'htm' import 'preact/debug' import 'preact/devtools' {{- end }} +import { NodeStore } from 'node_store' import { Notes2 } from "/js/{{ .VERSION }}/app.mjs" import { API } from 'api' @@ -15,8 +16,15 @@ if (!API.hasAuthenticationToken()) { location.href = '/login' } else { const html = htm.bind(h) - window._notes2 = createRef() - render(html`<${Notes2} ref=${window._notes2} />`, document.getElementById('app')) + try { + window.nodeStore = new NodeStore() + window.nodeStore.initializeDB().then(() => { + window._notes2 = createRef() + render(html`<${Notes2} ref=${window._notes2} />`, document.getElementById('app')) + }) + } catch (e) { + alert(e) + } }