UNPKG

solid-panes

Version:

Solid-compatible Panes: applets and views for the mashlib and databrowser

323 lines (306 loc) 13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var UI = _interopRequireWildcard(require("solid-ui")); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /* Financial Period Pane ** ** This outline pane allows a user to interact with a period ** downloaded from a bank statement, annotting it with classes and comments, ** trips, etc */ const ns = UI.ns; var _default = exports.default = { icon: UI.icons.iconBase + 'noun_142708.svg', name: 'period', audience: [ns.solid('PowerUser')], // Does the subject deserve this pane? label: function (subject, context) { const kb = context.session.store; const t = kb.findTypeURIs(subject); if (t['http://www.w3.org/2000/10/swap/pim/qif#Period']) return 'period'; return null; // No under other circumstances (while testing at least!) }, render: function (subject, context) { const dom = context.dom; const kb = context.session.store; const ns = UI.ns; const div = dom.createElement('div'); div.setAttribute('class', 'periodPane'); const mention = function mention(message, style) { if (!style) style = 'color: grey;'; const pre = dom.createElement('pre'); pre.setAttribute('style', style); div.appendChild(pre); pre.appendChild(dom.createTextNode(message)); }; const happy = function happy(message) { return mention('✓ ' + message, 'color: #010; background-color: #efe'); }; const complain = function complain(message) { return mention(message, 'color: #100; background-color: #fee'); }; /* var rerender = function (div) { var parent = div.parentNode var div2 = thisPane.render(subject, dom) parent.replaceChild(div2, div) } */ const renderPeriod = function () { const dtstart = kb.any(subject, ns.cal('dtstart')); if (dtstart === undefined) { complain('(Error: There is no start date known for this period <' + subject.uri + '>,\n -- every period needs one.)'); } const dtend = kb.any(subject, ns.cal('dtend')); if (dtend === undefined) { complain('(Error: There is no end date known for this period <' + subject.uri + '>,\n -- every period needs one.)'); } // var store = kb.any(subject, UI.ns.qu('annotationStore')) || null const predicateURIsDone = {}; const donePredicate = function (pred) { predicateURIsDone[pred.uri] = true; }; donePredicate(ns.rdf('type')); const inPeriod = function (date) { return !!(date && date >= dtstart && date < dtend); }; const d2 = function (n) { const s = '' + n; if (s.indexOf('.') >= 0) { return s.split('.')[0] + '.' + (s.split('.')[1] + '00').slice(0, 2); } return s + '.00'; }; const transactionInPeriod = function (x) { return inPeriod(kb.any(x, ns.qu('date'))); }; const oderByDate = function (x, y) { const dx = kb.any(x, ns.qu('date')); const dy = kb.any(y, ns.qu('date')); if (dx !== undefined && dy !== undefined) { if (dx.value < dy.value) return -1; if (dx.value > dy.value) return 1; } if (x.uri < y.uri) return -1; // Arbitrary but repeatable if (x.uri > y.uri) return 1; return 0; }; /* var setPaneStyle = function (account) { var mystyle = 'padding: 0.5em 1.5em 1em 1.5em; ' if (account) { var backgroundColor = kb.any(account, UI.ns.ui('backgroundColor')) if (backgroundColor) { mystyle += 'background-color: ' + backgroundColor.value + '; ' } } div.setAttribute('style', mystyle) } // setPaneStyle(); */ const h2 = div.appendChild(dom.createElement('h2')); h2.textContent = 'Period ' + dtstart.value.slice(0, 10) + ' - ' + dtend.value.slice(0, 10); const insertedPane = function (context, subject, paneName) { const p = context.session.paneRegistry.byName(paneName); const d = p.render(subject, context); d.setAttribute('style', 'border: 0.1em solid green;'); return d; }; const expandAfterRow = function (dom, row, subject, paneName, solo) { const siblings = row.parentNode.children; if (solo) { for (let j = siblings.length - 1; j >= 0; j--) { if (siblings[j].expanded) { siblings[j].parentNode.removeChild(siblings[j].expanded); siblings[j].expanded = false; } } } const tr = dom.createElement('tr'); const td = tr.appendChild(dom.createElement('td')); td.setAttribute('style', 'width: 98%; padding: 1em; border: 0.1em solid grey;'); const cols = row.children.length; if (row.nextSibling) { row.parentNode.insertBefore(tr, row.nextSibling); } else { row.parentNode.appendChild(tr); } row.expanded = tr; td.setAttribute('colspan', '' + cols); td.appendChild(insertedPane(context, subject, paneName)); }; const expandAfterRowOrCollapse = function (dom, row, subject, paneName, solo) { if (row.expanded) { row.parentNode.removeChild(row.expanded); row.expanded = false; } else { expandAfterRow(dom, row, subject, paneName, solo); } }; const transactionTable = function (dom, list) { const table = dom.createElement('table'); table.setAttribute('style', 'margin-left: 100; font-size: 9pt; width: 85%;'); const transactionRow = function (dom, x) { const tr = dom.createElement('tr'); const setTRStyle = function (tr, account) { // var mystyle = "padding: 0.5em 1.5em 1em 1.5em; "; let mystyle = 'margin-left: 8em; padding-left: 5em;'; if (account) { const backgroundColor = kb.any(account, UI.ns.ui('backgroundColor')); if (backgroundColor) { mystyle += 'background-color: ' + backgroundColor.value + '; '; } } tr.setAttribute('style', mystyle); }; const account = kb.any(x, ns.qu('toAccount')); setTRStyle(tr, account); const c0 = tr.appendChild(dom.createElement('td')); const date = kb.any(x, ns.qu('date')); c0.textContent = date ? date.value.slice(0, 10) : '???'; c0.setAttribute('style', 'width: 7em;'); const c1 = tr.appendChild(dom.createElement('td')); c1.setAttribute('style', 'width: 36em;'); const payee = kb.any(x, ns.qu('payee')); c1.textContent = payee ? payee.value : '???'; const a1 = c1.appendChild(dom.createElement('a')); a1.textContent = ' ➜'; a1.setAttribute('href', x.uri); const c3 = tr.appendChild(dom.createElement('td')); const amount = kb.any(x, ns.qu('in_USD')); c3.textContent = amount ? d2(amount.value) : '???'; c3.setAttribute('style', 'width: 6em; text-align: right; '); // @@ decimal alignment? tr.addEventListener('click', function (e) { // solo unless shift key expandAfterRowOrCollapse(dom, tr, x, 'transaction', !e.shiftKey); }, false); return tr; }; const list2 = list.filter(transactionInPeriod); list2.sort(oderByDate); for (let i = 0; i < list2.length; i++) { table.appendChild(transactionRow(dom, list2[i])); } return table; }; // List unclassified transactions const dummies = { 'http://www.w3.org/2000/10/swap/pim/qif#Transaction': true, // (we knew) 'http://www.w3.org/2000/10/swap/pim/qif#Unclassified': true, // pseudo classifications we may phase out 'http://www.w3.org/2000/10/swap/pim/qif#UnclassifiedOutgoing': true, 'http://www.w3.org/2000/10/swap/pim/qif#UnclassifiedIncome': true }; const xURIs = kb.findMemberURIs(ns.qu('Transaction')); const unclassifiedIn = []; const unclassifiedOut = []; let usd, z; for (const y in xURIs) { // For each thing which can be inferred to be a transaction // @@ TODO: Write away the need for exception on next line if (Object.prototype.hasOwnProperty.call(xURIs, y)) { z = kb.sym(y); const tt = kb.each(z, ns.rdf('type')); // What EXPLICIT definitions let classified = false; for (let j = 0; j < tt.length; j++) { const t = tt[j]; if (dummies[t.uri] === undefined) { classified = true; } } if (!classified) { usd = kb.any(z, ns.qu('in_USD')); if (usd === undefined) { usd = kb.any(z, ns.qu('amount')); } if (usd && ('' + usd.value).indexOf('-') >= 0) { unclassifiedOut.push(kb.sym(y)); } else { unclassifiedIn.push(kb.sym(y)); } } } } let tab, count; if (unclassifiedIn.length) { tab = transactionTable(dom, unclassifiedIn); count = tab.children.length; div.appendChild(dom.createElement('h3')).textContent = 'Unclassified Income' + (count < 4 ? '' : ' (' + count + ')'); div.appendChild(tab); } else { happy('No unclassified income'); } if (unclassifiedOut.length) { tab = transactionTable(dom, unclassifiedOut); count = tab.children.length; div.appendChild(dom.createElement('h3')).textContent = 'Unclassified Outgoings' + (count < 4 ? '' : ' (' + count + ')'); div.appendChild(tab); } else { happy('No unclassified outgoings '); } // /////////////// Check some categories of transaction for having given fields const catSymbol = function (catTail) { const cats = kb.findSubClassesNT(ns.qu('Transaction')); for (const cat in cats) { // @@ TODO: Write away the need for exception on next line if (Object.prototype.hasOwnProperty.call(cats, cat)) { if (cat.slice(1, -1).split('#')[1] === catTail) { return kb.sym(cat.slice(1, -1)); } } } return null; }; const checkCatHasField = function (catTail, pred) { const cat = catSymbol(catTail); let tab; const guilty = []; let count = 0; if (!cat) { complain('Error: No category correspnding to ' + catTail); return null; } const list = kb.each(undefined, ns.rdf('type'), cat); for (let i = 0; i < list.length; i++) { if (!kb.any(list[i], pred)) { guilty.push(list[i]); } } if (guilty.length) { tab = transactionTable(dom, guilty); count = tab.children.length; div.appendChild(dom.createElement('h3')).textContent = UI.utils.label(cat) + ' with no ' + UI.utils.label(pred) + (count < 4 ? '' : ' (' + count + ')'); div.appendChild(tab); } return count; }; // Load dynamically as properties of period if (checkCatHasField('Reimbursables', ns.trip('trip')) === 0) { happy('Reimbursables all have trips'); } if (checkCatHasField('Other_Inc_Speaking', ns.trip('trip')) === 0) { happy('Speaking income all has trips'); } // end of render period instance }; // renderPeriod // ////////////////////////////////////////////////////////////////////////////// // var me = authn.currentUser() // Render a single Period // This works only if enough metadata about the properties can drive the RDFS // (or actual type statements whichtypically are NOT there on) const t = kb.findTypeURIs(subject); if (t['http://www.w3.org/2000/10/swap/pim/qif#Period']) { const needed = kb.each(subject, ns.rdfs('seeAlso')); console.log('Loading before render: ' + needed.length); kb.fetcher.load(needed).then(function () { renderPeriod(); }); } // if (!me) complain("You do not have your Web Id set. Set your Web ID to make changes."); return div; } }; // ends