UNPKG

solid-panes

Version:

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

444 lines (367 loc) • 15.6 kB
"use strict"; /* Attachment Pane ** ** - Attach a document to a thing ** - View attachments ** - Look at all unattached Supporting Documents. ** - Drag a document onto the pane to attach it @@ ** ** */ var UI = require('solid-ui'); var $rdf = require('rdflib'); module.exports = { icon: UI.icons.iconBase + 'noun_25830.svg', // noun_25830 name: 'attachments', // Does the subject deserve an attachments pane? // // In this case we will render any thing which is in any subclass of // certain classes, or also the certain classes themselves, as a // triage tool for correlating many attachees with attachments. // We also offer the pane for anything of any class which just has an attachment already. // label: function label(subject, context) { var kb = context.session.store; var t = kb.findTypeURIs(subject); var QU = $rdf.Namespace('http://www.w3.org/2000/10/swap/pim/qif#'); var WF = $rdf.Namespace('http://www.w3.org/2005/01/wf/flow#'); if (t['http://www.w3.org/ns/pim/trip#Trip'] || // If in any subclass subject.uri === 'http://www.w3.org/ns/pim/trip#Trip' || t['http://www.w3.org/2005/01/wf/flow#Task'] || t['http://www.w3.org/2000/10/swap/pim/qif#Transaction'] || // subject.uri == 'http://www.w3.org/2000/10/swap/pim/qif#Transaction' || QU('Transaction') in kb.findSuperClassesNT(subject) || kb.holds(subject, WF('attachment'))) { return 'attachments'; } return null; }, render: function render(subject, context) { var dom = context.dom; var kb = context.session.store; var WF = $rdf.Namespace('http://www.w3.org/2005/01/wf/flow#'); var QU = $rdf.Namespace('http://www.w3.org/2000/10/swap/pim/qif#'); // //////////////////////////////////////////////////////////////////////////// var complain = function complain(message) { var pre = dom.createElement('pre'); pre.setAttribute('style', 'background-color: pink'); div.appendChild(pre); pre.appendChild(dom.createTextNode(message)); }; // Where can we write about this thing? // // Returns term for document or null var findStore = function findStore(kb, subject) { if (kb.updater.editable(subject.doc(), kb)) return subject.doc(); var store = kb.any(subject.doc(), QU('annotationStore')); return store; }; var div = dom.createElement('div'); var esc = UI.utils.escapeForXML; div.setAttribute('class', 'attachPane'); div.innerHTML = '<h1>' + esc(UI.utils.label(subject, true)) + ' attachments</h1>'; // var predicate = WF('attachment'); var range = QU('SupportingDocument'); var subjects, multi; var options = {}; var currentMode = 0; // 0 -> Show all; 1 -> Attached; 2 -> unattached var currentSubject = null; var currentObject = null; var objectType = QU('SupportingDocument'); // Find all members of the class which we know about // and sort them by an appropriate property. @@ Move to library // var getSortKeySimple = function getSortKeySimple(_c) { var uriMap = { 'http://www.w3.org/2005/01/wf/flow#Task': 'http://purl.org/dc/elements/1.1/created', 'http://www.w3.org/ns/pim/trip#Trip': 'http://www.w3.org/2002/12/cal/ical#dtstart', 'http://www.w3.org/2000/10/swap/pim/qif#Transaction': 'http://www.w3.org/2000/10/swap/pim/qif#date', 'http://www.w3.org/2000/10/swap/pim/qif#SupportingDocument': 'http://purl.org/dc/elements/1.1/date' }; var uri = uriMap[subject.uri]; return uri ? kb.sym(uri) : kb.any(subject, UI.ns.ui('sortBy')); }; var getSortKey = function getSortKey(c) { var k = getSortKeySimple(c.uri); if (k) return k; var sup = kb.findSuperClassesNT(c); for (var cl in sup) { // note unordered -- could be closest first k = getSortKeySimple(kb.fromNT(cl).uri); if (k) return k; } return undefined; // failure }; var getMembersAndSort = function getMembersAndSort(subject) { var sortBy = getSortKey(subject); var u, x, key; var uriHash = kb.findMemberURIs(subject); var pairs = []; var subjects = []; for (u in uriHash) { // @@ TODO: Write away the need for exception on next line // eslint-disable-next-line no-prototype-builtins if (uriHash.hasOwnProperty(u)) { x = kb.sym(u); if (sortBy) { key = kb.any(x, sortBy); if (!key) { // complain("No key "+key+" sortby "+sortBy+" for "+x) key = '8888-12-31'; } else { key = key.value; } } else { complain('No sortby ' + sortBy + ' for ' + x); key = '9999-12-31'; } // key = (sortBy && kb.any(x, sortBy)) || kb.literal("9999-12-31") // Undated appear future // if (!key) complain("Sort: '"+key+"' No "+sortBy+" for "+x) // Assume just not in this year pairs.push([key, x]); } } pairs.sort(); pairs.reverse(); // @@ Descending order .. made a toggle? for (var i = 0; i < pairs.length; i++) { subjects.push(pairs[i][1]); } return subjects; }; // Set up a triage of many class members against documents or just one if (subject.uri === 'http://www.w3.org/ns/pim/trip#Trip' || QU('Transaction') in kb.findSuperClassesNT(subject) // subject.uri == 'http://www.w3.org/2000/10/swap/pim/qif#Transaction' ) { multi = true; subjects = getMembersAndSort(subject); } else { currentSubject = subject; currentMode = 1; // Show attached only. subjects = [subject]; multi = false; } // var store = findStore(kb, subject) // if (!store) complain("There is no annotation store for: "+subject.uri) // var objects = kb.each(undefined, ns.rdf('type'), range) var objects = getMembersAndSort(range); if (!objects) complain('objects:' + objects.length); var deselectObject = function deselectObject() { currentObject = null; preview.innerHTML = ''; }; var showFiltered = function showFiltered(mode) { var filtered = mode === 0 ? objects : getFiltered(); // eslint-enable UI.widgets.selectorPanelRefresh(objectList, dom, kb, objectType, predicate, true, filtered, options, showObject, linkClicked); if (filtered.length === 1) { currentObject = filtered[0]; showObject(currentObject, null, true); // @@ (Sure?) if only one select it. } else { deselectObject(); } function getFiltered() { return mode === 1 ? currentSubject === null ? objects.filter(function (y) { return !!kb.holds(undefined, predicate, y); }) : objects.filter(function (y) { return !!kb.holds(currentSubject, predicate, y); }) : objects.filter(function (y) { return kb.each(undefined, predicate, y).length === 0; }); } }; var setAttachment = function setAttachment(x, y, value, refresh) { if (kb.holds(x, predicate, y) === value) return; var verb = value ? 'attach' : 'detach'; // complain("Info: starting to "+verb+" " + y.uri + " to "+x.uri+ ":\n") var linkDone3 = function linkDone3(uri, ok, body) { if (ok) { // complain("Success "+verb+" "+y.uri+" to "+x.uri+ ":\n"+ body) refresh(); } else { complain('Error: Unable to ' + verb + ' ' + y.uri + ' to ' + x.uri + ':\n' + body); } }; var store = findStore(kb, x); if (!store) { complain('There is no annotation store for: ' + x.uri); } else { var sts = [$rdf.st(x, predicate, y, store)]; if (value) { kb.updater.update([], sts, linkDone3); } else { kb.updater.update(sts, [], linkDone3); } } }; var linkClicked = function linkClicked(x, event, inverse, refresh) { var s, o; if (inverse) { // Objectlist if (!currentSubject) { complain('No subject for the link has been selected'); return; } else { s = currentSubject; o = x; } } else { // Subjectlist if (!currentObject) { complain('No object for the link has been selected'); return; } else { s = x; o = currentObject; } } setAttachment(s, o, !kb.holds(s, predicate, o), refresh); // @@ toggle }; // When you click on a subject, filter the objects connected to the subject in Mode 1 var showSubject = function showSubject(x, event, selected) { if (selected) { currentSubject = x; } else { currentSubject = null; if (currentMode === 1) deselectObject(); } // If all are displayed, refresh would just annoy: if (currentMode !== 0) showFiltered(currentMode); // Refresh the objects }; if (multi) { var subjectList = UI.widgets.selectorPanel(dom, kb, subject, predicate, false, subjects, options, showSubject, linkClicked); subjectList.setAttribute('style', 'background-color: white; width: 25em; height: 100%; padding: 0 em; overflow:scroll; float:left'); div.appendChild(subjectList); } var showObject = function showObject(x, event, selected) { if (!selected) { deselectObject(); preview.innerHTML = ''; // Clean out what is there // complain("Show object "+x.uri) return; } currentObject = x; try { /* var dispalyable = function (kb, x) { var cts = kb.fetcher.getHeader(x, 'content-type') if (cts) { var displayables = ['text/html', 'image/png', 'application/pdf'] for (var j = 0; j < cts.length; j++) { for (var k = 0; k < displayables.length; k++) { if (cts[j].indexOf(displayables[k]) >= 0) { return true } } } } return false } */ preview.innerHTML = 'Loading ....'; if (x.uri) { kb.fetcher.load(x.uri).then(function () { var outliner = context.getOutliner(dom); var display = outliner.propertyTable(x); // ,table, pane preview.innerHTML = ''; preview.appendChild(display); })["catch"](function (err) { preview.textContent = 'Error loading ' + x.uri + ': ' + err; }); } /* if (dispalyable(kb, x) || x.uri.slice(-4) == ".pdf" || x.uri.slice(-4) == ".png" || x.uri.slice(-5) == ".html" || x.uri.slice(-5) == ".jpeg") { // @@@@@@ MAJOR KLUDGE! use metadata after HEAD preview.innerHTML = '<iframe height="100%" width="100%"src="' + x.uri + '">' + x.uri + '</iframe>' } else { } */ } catch (e) { preview.innerHTML = '<span style="background-color: pink;">' + 'Error:' + e + '</span>'; // @@ enc } }; div.setAttribute('style', 'background-color: white; width:40cm; height:20cm;'); var headerButtons = function headerButtons(dom, labels, intial, callback) { var head = dom.createElement('table'); var current = intial; head.setAttribute('style', 'float: left; width: 30em; padding: 0.5em; height: 1.5em; background-color: #ddd; color: #444; font-weight: bold'); var tr = dom.createElement('tr'); var style0 = 'border-radius: 0.6em; text-align: center;'; var style1 = style0 + 'background-color: #ccc; color: black;'; head.appendChild(tr); var setStyles = function setStyles() { for (i = 0; i < labels.length; i++) { buttons[i].setAttribute('style', i === current ? style1 : style0); } }; var i, b; var buttons = []; for (i = 0; i < labels.length; i++) { b = buttons[i] = dom.createElement('td'); b.textContent = labels[i]; tr.appendChild(buttons[i]); var listen = function listen(b, i) { b.addEventListener('click', function (_e) { current = i; setStyles(); callback(i); }); }; listen(b, i); } setStyles(); return head; }; var setMode = function setMode(mode) { if (mode !== currentMode) { currentMode = mode; deselectObject(); showFiltered(mode); } }; var wrapper = dom.createElement('div'); wrapper.setAttribute('style', ' width: 30em; height: 100%; padding: 0em; float:left;'); // wrapper.appendChild(head) div.appendChild(wrapper); wrapper.appendChild(headerButtons(dom, ['all', 'attached', 'not attached'], currentMode, setMode)); var objectList = UI.widgets.selectorPanel(dom, kb, objectType, predicate, true, objects, options, showObject, linkClicked); objectList.setAttribute('style', 'background-color: #ffe; width: 30em; height: 100%; padding: 0em; overflow:scroll;'); // float:left wrapper.appendChild(objectList); // objectList.insertBefore(head, objectList.firstChild) var preview = dom.createElement('div'); preview.setAttribute('style', /* background-color: black; */ 'padding: 0em; margin: 0; height: 100%; overflow:scroll;'); div.appendChild(preview); showFiltered(currentMode); if (subjects.length > 0 && multi) { var stores = {}; for (var k = 0; k < subjects.length; k++) { var store = findStore(kb, subjects[k]); if (store) stores[store.uri] = subjects[k]; // if (!store) complain("No store for "+subjects[k].uri) } var _loop = function _loop() { // var store = findStore(kb,subjects[subjectList.length-1]) var store = kb.sym(storeURI); mintBox = dom.createElement('div'); mintBox.setAttribute('style', 'clear: left; width: 20em; margin-top:2em; background-color:#ccc; border-radius: 1em; padding: 1em; font-weight: bold;'); mintBox.textContent = '+ New ' + UI.utils.label(subject); mintBox.textContent += ' in ' + UI.utils.label(store); storeLab = dom.createElement('span'); storeLab.setAttribute('style', 'font-weight: normal; font-size: 80%; color: #777;'); storeLab.textContent = storeURI; mintBox.appendChild(dom.createElement('br')); mintBox.appendChild(storeLab); /* var mintButton = dom.createElement('img') mintBox.appendChild(mintButton) mintButton.setAttribute('src', ...); @@ Invokes master handler */ mintBox.addEventListener('click', function (_event) { var thisForm = UI.widgets.promptForNew(dom, kb, subject, predicate, subject, null, store, function (ok, _body) { if (!ok) {// callback(ok, body); // @@ if ok, need some form of refresh of the select for the new thing } else {// Refresh @@ } }); try { div.insertBefore(thisForm, mintBox.nextSibling); // Sigh no insertAfter } catch (e) { div.appendChild(thisForm); } // var newObject = thisForm.AJAR_subject }, false); div.appendChild(mintBox); }; for (var storeURI in stores) { var mintBox; var storeLab; _loop(); } } // if (!me) complain("(You do not have your Web Id set. Set your Web ID to make changes.)") return div; } }; // pane object // ends //# sourceMappingURL=attachPane.js.map