UNPKG

solid-panes

Version:

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

431 lines (412 loc) 17.3 kB
"use strict"; function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } Object.defineProperty(exports, "__esModule", { value: true }); exports.socialPane = void 0; var UI = _interopRequireWildcard(require("solid-ui")); var _solidLogic = require("solid-logic"); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(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 (var _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); } /* Social Pane ** ** This outline pane provides social network functions ** Using for example the FOAF ontology. ** Goal: A *distributed* version of facebook, advogato, etc etc ** - Similarly easy user interface, but data storage distributed ** - Read and write both user-private (address book) and public data clearly ** -- todo: use common code to get username and load profile and set 'me' */ var socialPane = exports.socialPane = { icon: UI.icons.originalIconBase + 'foaf/foafTiny.gif', name: 'social', label: function label(subject, context) { var kb = context.session.store; var types = kb.findTypeURIs(subject); if (types[UI.ns.foaf('Person').uri] || types[UI.ns.vcard('Individual').uri]) { return 'Friends'; } return null; }, render: function render(s, context) { var dom = context.dom; var common = function common(x, y) { // Find common members of two lists var both = []; for (var i = 0; i < x.length; i++) { for (var j = 0; j < y.length; j++) { if (y[j].sameTerm(x[i])) { both.push(y[j]); break; } } } return both; }; var people = function people(n) { var res = ' '; res += n || 'no'; if (n === 1) return res + ' person'; return res + ' people'; }; var say = function say(str) { console.log(str); var p = dom.createElement('p'); p.textContent = str; tips.appendChild(p); }; var link = function link(contents, uri) { if (!uri) return contents; var a = dom.createElement('a'); a.setAttribute('href', uri); a.appendChild(contents); return a; }; var text = function text(str) { return dom.createTextNode(str); }; var buildCheckboxForm = function buildCheckboxForm(lab, statement, state) { var f = dom.createElement('form'); var input = dom.createElement('input'); f.appendChild(input); var tx = dom.createTextNode(lab); tx.className = 'question'; f.appendChild(tx); input.setAttribute('type', 'checkbox'); var boxHandler = function boxHandler(_e) { tx.className = 'pendingedit'; // alert('Should be greyed out') if (this.checked) { // Add link try { outliner.UserInput.sparqler.insert_statement(statement, function (uri, success, errorBody) { tx.className = 'question'; if (!success) { UI.log.alert(null, 'Message', 'Error occurs while inserting ' + statement + '\n\n' + errorBody); input.checked = false; // rollback UI return; } kb.add(statement.subject, statement.predicate, statement.object, statement.why); }); } catch (e) { UI.log.error('Data write fails:' + e); UI.log.alert('Data write fails:' + e); input.checked = false; // rollback UI tx.className = 'question'; } } else { // Remove link try { outliner.UserInput.sparqler.delete_statement(statement, function (uri, success, errorBody) { tx.className = 'question'; if (!success) { UI.log.alert('Error occurs while deleting ' + statement + '\n\n' + errorBody); this.checked = true; // Rollback UI } else { kb.removeMany(statement.subject, statement.predicate, statement.object, statement.why); } }); } catch (e) { UI.log.alert('Delete fails:' + e); this.checked = true; // Rollback UI // return } } }; input.checked = state; input.addEventListener('click', boxHandler, false); return f; }; var oneFriend = function oneFriend(friend, _confirmed) { return UI.widgets.personTR(dom, UI.ns.foaf('knows'), friend, {}); }; // ////////// Body of render(): var outliner = context.getOutliner(dom); var kb = context.session.store; var div = dom.createElement('div'); div.setAttribute('class', 'socialPane'); var foaf = UI.ns.foaf; var vcard = UI.ns.vcard; // extracted from tabbedtab.css 2017-03-21 var navBlockStyle = 'background-color: #eee; width: 25%; border: 0; padding: 0.5em; margin: 0;'; var mainBlockStyle = 'background-color: #fff; color: #000; width: 46%; margin: 0; border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; padding: 0;'; var foafPicStyle = ' width: 100% ; border: none; margin: 0; padding: 0;'; var structure = div.appendChild(dom.createElement('table')); var tr = structure.appendChild(dom.createElement('tr')); var left = tr.appendChild(dom.createElement('td')); var middle = tr.appendChild(dom.createElement('td')); var right = tr.appendChild(dom.createElement('td')); var tools = left; tools.style.cssText = navBlockStyle; var mainTable = middle.appendChild(dom.createElement('table')); mainTable.style.cssText = mainBlockStyle; var tips = right; tips.style.cssText = navBlockStyle; // Image top left var src = kb.any(s, foaf('img')) || kb.any(s, foaf('depiction')); if (src) { var img = dom.createElement('IMG'); img.setAttribute('src', src.uri); // w640 h480 // img.className = 'foafPic' img.style.cssText = foafPicStyle; tools.appendChild(img); } var name = kb.anyValue(s, foaf('name')) || '???'; var h3 = dom.createElement('H3'); h3.appendChild(dom.createTextNode(name)); var me = _solidLogic.authn.currentUser(); var meUri = me ? me.uri : null; // @@ Add: event handler to redraw the stuff below when me changes. var loginOutButton = UI.login.loginStatusBox(dom, function (webIdUri) { me = kb.sym(webIdUri); // @@ To be written: redraw as a function the new me // @@ refresh the sidebars UI.widgets.refreshTree(div); // this refreshes the middle at least }); tips.appendChild(loginOutButton); var thisIsYou = me && kb.sameThings(me, s); var knows = foaf('knows'); // var givenName = kb.sym('http://www.w3.org/2000/10/swap/pim/contact#givenName') var familiar = kb.anyValue(s, foaf('givenname')) || kb.anyValue(s, foaf('firstName')) || kb.anyValue(s, foaf('nick')) || kb.anyValue(s, foaf('name')) || kb.anyValue(s, vcard('fn')); var friends = kb.each(s, knows); // Do I have a public profile document? var profile = null; // This could be SPARQL { ?me foaf:primaryTopic [ a foaf:PersonalProfileDocument ] } var editable = false; var incoming; var outgoing; if (me) { // The definition of FAF personal profile document is .. var works = kb.each(undefined, foaf('primaryTopic'), me); // having me as primary topic var message = ''; for (var i = 0; i < works.length; i++) { if (kb.whether(works[i], UI.ns.rdf('type'), foaf('PersonalProfileDocument'))) { editable = outliner.UserInput.sparqler.editable(works[i].uri, kb); if (!editable) { message += 'Your profile <' + UI.utils.escapeForXML(works[i].uri) + '> is not remotely editable.'; } else { profile = works[i]; break; } } } if (!profile) { say(message + "\nI couldn't find your editable personal profile document."); } else { say('Editing your profile ' + profile + '.'); // Do I have an EDITABLE profile? editable = outliner.UserInput.sparqler.editable(profile.uri, kb); } if (thisIsYou) { // This is about me // pass... @@ } else { // This is about someone else // My relationship with this person h3 = dom.createElement('h3'); h3.appendChild(dom.createTextNode('You and ' + familiar)); tools.appendChild(h3); var cme = kb.canon(me); incoming = kb.whether(s, knows, cme); outgoing = false; var outgoingSt = kb.statementsMatching(cme, knows, s); if (outgoingSt.length) { outgoing = true; if (!profile) profile = outgoingSt[0].why; } var _tr = dom.createElement('tr'); tools.appendChild(_tr); var youAndThem = function youAndThem() { _tr.appendChild(link(text('You'), meUri)); _tr.appendChild(text(' and ')); _tr.appendChild(link(text(familiar), s.uri)); }; if (!incoming) { if (!outgoing) { youAndThem(); _tr.appendChild(text(' have not said you know each other.')); } else { _tr.appendChild(link(text('You'), meUri)); _tr.appendChild(text(' know ')); _tr.appendChild(link(text(familiar), s.uri)); _tr.appendChild(text(' (unconfirmed)')); } } else { if (!outgoing) { _tr.appendChild(link(text(familiar), s.uri)); _tr.appendChild(text(' knows ')); _tr.appendChild(link(text('you'), meUri)); _tr.appendChild(text(' (unconfirmed).')); // @@ _tr.appendChild(text(' confirm you know ')); _tr.appendChild(link(text(familiar), s.uri)); _tr.appendChild(text('.')); } else { youAndThem(); _tr.appendChild(text(' say you know each other.')); } } if (editable) { var f = buildCheckboxForm('You know ' + familiar, new UI.rdf.Statement(me, knows, s, profile), outgoing); tools.appendChild(f); } // editable // //////////////// Mutual friends if (friends) { var myFriends = kb.each(me, foaf('knows')); if (myFriends.length) { var mutualFriends = common(friends, myFriends); var _tr2 = dom.createElement('tr'); tools.appendChild(_tr2); _tr2.appendChild(dom.createTextNode('You' + (familiar ? ' and ' + familiar : '') + ' know' + people(mutualFriends.length) + ' found in common')); if (mutualFriends) { for (var _i = 0; _i < mutualFriends.length; _i++) { _tr2.appendChild(dom.createTextNode(', ' + UI.utils.label(mutualFriends[_i]))); } } } var _tr3 = dom.createElement('tr'); tools.appendChild(_tr3); } // friends } // About someone else } // me is defined // End of you and s // div.appendChild(dom.createTextNode(plural(friends.length, 'acquaintance') +'. ')) // ///////////////////////////////////////////// Main block // // Should: Find the intersection and difference sets // List all x such that s knows x. UI.widgets.attachmentList(dom, s, mainTable, { doc: profile, modify: !!editable, predicate: foaf('knows'), noun: 'friend' }); // Figure out which are reciprocated: // @@ Does not look up profiles // Does distinguish reciprocated from unreciprocated friendships // function _triageFriends(s) { outgoing = kb.each(s, foaf('knows')); incoming = kb.each(undefined, foaf('knows'), s); // @@ have to load the friends var confirmed = []; var unconfirmed = []; var requests = []; for (var _i2 = 0; _i2 < outgoing.length; _i2++) { var friend = outgoing[_i2]; var found = false; for (var j = 0; j < incoming.length; j++) { if (incoming[j].sameTerm(friend)) { found = true; break; } } if (found) confirmed.push(friend);else unconfirmed.push(friend); } // outgoing for (var _i3 = 0; _i3 < incoming.length; _i3++) { var _friend = incoming[_i3]; // var lab = UI.utils.label(friend) var _found = false; for (var _j = 0; _j < outgoing.length; _j++) { if (outgoing[_j].sameTerm(_friend)) { _found = true; break; } } if (!_found) requests.push(_friend); } // incoming var cases = [['Acquaintances', outgoing], ['Mentioned as acquaintances by: ', requests]]; for (var _i4 = 0; _i4 < cases.length; _i4++) { var thisCase = cases[_i4]; var _friends = thisCase[1]; if (_friends.length === 0) continue; // Skip empty sections (sure?) var _h = dom.createElement('h3'); _h.textContent = thisCase[0]; var htr = dom.createElement('tr'); htr.appendChild(_h); mainTable.appendChild(htr); var items = []; for (var j9 = 0; j9 < _friends.length; j9++) { items.push([UI.utils.label(_friends[j9]), _friends[j9]]); } items.sort(); var last = null; var fr = void 0; for (var j7 = 0; j7 < items.length; j7++) { fr = items[j7][1]; if (fr.sameTerm(last)) continue; // unique last = fr; if (UI.utils.label(fr) !== '...') { // This check is to avoid bnodes with no labels attached // appearing in the friends list with "..." - Oshani mainTable.appendChild(oneFriend(fr)); } } } } /* if ($rdf.keepThisCodeForLaterButDisableFerossConstantConditionPolice) { triageFriends(s) } */ // //////////////////////////////////// Basic info on left h3 = dom.createElement('h3'); h3.appendChild(dom.createTextNode('Basic Information')); tools.appendChild(h3); // For each home page like thing make a label which will // make sense and add the domain (like "w3.org blog") if there are more than one of the same type // var preds = [UI.ns.foaf('homepage'), UI.ns.foaf('weblog'), UI.ns.foaf('workplaceHomepage'), UI.ns.foaf('schoolHomepage')]; for (var i6 = 0; i6 < preds.length; i6++) { var pred = preds[i6]; var sts = kb.statementsMatching(s, pred); if (sts.length === 0) { // if (editable) say("No home page set. Use the blue + icon at the bottom of the main view to add information.") } else { var uris = []; for (var j5 = 0; j5 < sts.length; j5++) { var st = sts[j5]; if (st.object.uri) uris.push(st.object.uri); // Ignore if not symbol } uris.sort(); var last2 = ''; var lab2 = void 0; for (var k = 0; k < uris.length; k++) { var uri = uris[k]; if (uri === last2) continue; // uniques only last2 = uri; var hostlabel = ''; lab2 = UI.utils.label(pred); if (uris.length > 1) { var l = uri.indexOf('//'); if (l > 0) { var r = uri.indexOf('/', l + 2); var r2 = uri.lastIndexOf('.', r); if (r2 > 0) r = r2; hostlabel = uri.slice(l + 2, r); } } if (hostlabel) lab2 = hostlabel + ' ' + lab2; // disambiguate var t = dom.createTextNode(lab2); var a = dom.createElement('a'); a.appendChild(t); a.setAttribute('href', uri); var d = dom.createElement('div'); // d.className = 'social_linkButton' d.style.cssText = 'width: 80%; background-color: #fff; border: solid 0.05em #ccc; margin-top: 0.1em; margin-bottom: 0.1em; padding: 0.1em; text-align: center;'; d.appendChild(a); tools.appendChild(d); } } } var preds2 = [UI.ns.foaf('openid'), UI.ns.foaf('nick')]; for (var i2 = 0; i2 < preds2.length; i2++) { var _pred2 = preds2[i2]; var sts2 = kb.statementsMatching(s, _pred2); if (sts2.length === 0) { // if (editable) say("No home page set. Use the blue + icon at the bottom of the main view to add information.") } else { outliner.appendPropertyTRs(tools, sts2, false, function (_pred) { return true; }); } } return div; } // render() }; // // ends //# sourceMappingURL=socialPane.js.map