Skip to content

Commit

Permalink
Added basic prefs as (fior now) extra tab in dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Berners-Lee committed Aug 2, 2019
1 parent dcb1e4b commit 1273f70
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 15 deletions.
49 changes: 49 additions & 0 deletions dashboard/basicPreferences.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"use strict";
exports.__esModule = true;
var solid_ui_1 = require("solid-ui");
var pane_registry_1 = require("pane-registry");
var panes;
var UI;
var kb = UI.store;
var nodeMode = (typeof module !== 'undefined');
if (nodeMode) {
UI = solid_ui_1["default"];
panes = pane_registry_1["default"];
}
else { // Add to existing mashlib
panes = window.panes;
UI = panes.UI;
}
exports.basicPreferencesPane = {
icon: UI.icons.iconBase + 'noun_Sliders_341315_000000.svg',
name: 'preferences',
label: function (subject) {
if (subject.uri === subject.site().uri) {
return "Prefs";
}
return null;
},
// Render the pane
// The subject should be the logged in user.
render: function (subject, dom) {
var container = dom.createElement('div');
/* Preferences
**
** Things like whether to color text by author webid, to expand image URLs inline,
** expanded inline image height. ...
** In general, preferences can be set per user, per user/app combo, per instance,
** and per instance/user combo. (Seee the long chat pane preferences for an example.)
** Here in the basic preferences, we are only setting per-user defaults.
*/
var preferencesFormText = "\n\n @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.\n @prefix solid: <http://www.w3.org/ns/solid/terms#>.\n @prefix ui: <http://www.w3.org/ns/ui#>.\n @prefix : <#>.\n\n :this\n <http://purl.org/dc/elements/1.1/title> \"Basic preferences\" ;\n a ui:Form ;\n ui:part :powerUser, :developerUser, :newestFirst, :inlineImageHeightEms;\n ui:parts ( :powerUser :developerUser :newestFirst :inlineImageHeightEms ).\n\n:powerUser a ui:BooleanField; ui:property solid:powerUser;\n ui:label \"Color user input by user\".\n:developerUser a ui:BooleanField; ui:property solid:developerUser;\n ui:label \"Expand image URLs inline\".\n:newestFirst a ui:BooleanField; ui:property solid:newestFirst;\n ui:label \"Newest messages at the top\".\n\n:inlineImageHeightEms a ui:IntegerField; ui:property solid:inlineImageHeightEms;\n ui:label \"Inline image height (lines)\".\n\n";
var preferencesForm = kb.sym('https://solid.github.io/solid-panes/dashboard/basicPreferencesForm.ttl#this');
var preferencesFormDoc = preferencesForm.doc();
if (!kb.holds(undefined, undefined, undefined, preferencesFormDoc)) { // If not loaded already
$rdf.parse(preferencesFormText, kb, preferencesFormDoc.uri, 'text/turtle'); // Load form directly
}
var preferenceProperties = kb.statementsMatching(null, ns.ui.property, null, preferencesFormDoc).map(function (st) { return st.object; });
var context = { noun: 'chat room', me: me, statusArea: statusArea, div: menuArea, dom: dom, kb: kb };
container.appendChild(UI.preferences.renderPreferencesForm(chatChannel, mainClass, preferencesForm, context));
}
};
// ends
31 changes: 23 additions & 8 deletions dashboard/basicPreferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { generateHomepage } from "./homepage"

let panes: any
let UI: SolidUi
const kb = UI.store
const $rdf = UI.rdf
const ns = UI.ns

const nodeMode = (typeof module !== 'undefined')

Expand All @@ -19,7 +22,7 @@ if (nodeMode) {

export const basicPreferencesPane: PaneDefinition = {
icon: UI.icons.iconBase + 'noun_Sliders_341315_000000.svg',
name: 'preferences',
name: 'basicPreferences',
label: (subject) => {
if (subject.uri === subject.site().uri) {
return "Prefs"
Expand All @@ -29,9 +32,18 @@ export const basicPreferencesPane: PaneDefinition = {

// Render the pane
// The subject should be the logged in user.
render: (subject, dom) => {
render: (subject: NamedNode, dom: HTMLDocument, paneOptions: any) => {
function complainIfBad (ok: Boolean, mess: any) {
if (ok) return
container.appendChild(UI.widgets.errorMessageBlock(dom, mess, '#fee'))
}

const container = dom.createElement('div')

const formArea = container.appendChild(dom.createElement('div'))
const statusArea = container.appendChild(dom.createElement('div'))


/* Preferences
**
** Things like whether to color text by author webid, to expand image URLs inline,
Expand All @@ -51,8 +63,8 @@ export const basicPreferencesPane: PaneDefinition = {
:this
<http://purl.org/dc/elements/1.1/title> "Basic preferences" ;
a ui:Form ;
ui:part :powerUser, :developerUser, :newestFirst, :inlineImageHeightEms;
ui:parts ( :powerUser :developerUser :newestFirst :inlineImageHeightEms ).
ui:part :powerUser, :developerUser;
ui:parts ( :powerUser :developerUser ).
:powerUser a ui:BooleanField; ui:property solid:powerUser;
ui:label "Color user input by user".
Expand All @@ -70,10 +82,13 @@ export const basicPreferencesPane: PaneDefinition = {
if (!kb.holds(undefined, undefined, undefined, preferencesFormDoc)) { // If not loaded already
$rdf.parse(preferencesFormText, kb, preferencesFormDoc.uri, 'text/turtle') // Load form directly
}
let preferenceProperties = kb.statementsMatching(null, ns.ui.property, null, preferencesFormDoc).map(st => st.object)

var context = {noun: 'chat room', me: me, statusArea: statusArea, div: menuArea, dom, kb}
container.appendChild(UI.preferences.renderPreferencesForm(chatChannel, mainClass, preferencesForm, context))
// todo make Statement type for fn nelow
let preferenceProperties = kb.statementsMatching(null, ns.ui.property, null, preferencesFormDoc).map(function (st: any) {return st.object})
var me = UI.authn.currentUser()
// var context = {noun: 'chat room', me: me, statusArea: statusArea, div: formArea, dom, kb}
// container.appendChild(UI.preferences.renderPreferencesForm(me, mainClass, preferencesForm, context))
UI.widgets.appendForm(dom, formArea, {}, me, preferencesForm, me.doc(), complainIfBad)
return container
}
}
// ends
107 changes: 107 additions & 0 deletions dashboard/homepage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
var rdflib_1 = require("rdflib");
var solid_ui_1 = require("solid-ui");
var ns = solid_ui_1["default"].ns;
function generateHomepage(subject, store, fetcher) {
return __awaiter(this, void 0, void 0, function () {
var pod, ownersProfile, name, wrapper;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
pod = subject.site().uri;
return [4 /*yield*/, loadProfile(pod + "/profile/card#me", fetcher)];
case 1:
ownersProfile = _a.sent();
name = getName(store, ownersProfile);
wrapper = document.createElement('div');
wrapper.classList.add('container');
wrapper.appendChild(createTitle(ownersProfile.uri, name));
wrapper.appendChild(createDataSection(name));
return [2 /*return*/, wrapper];
}
});
});
}
exports.generateHomepage = generateHomepage;
function createDataSection(name) {
var dataSection = document.createElement('section');
var title = document.createElement('h2');
title.innerText = 'Data';
dataSection.appendChild(title);
var listGroup = document.createElement('div');
listGroup.classList.add('list-group');
dataSection.appendChild(listGroup);
var publicDataLink = document.createElement('a');
publicDataLink.classList.add('list-group-item');
publicDataLink.href = '/public/';
publicDataLink.innerText = "View " + name + "'s files";
listGroup.appendChild(publicDataLink);
return dataSection;
}
function createTitle(uri, name) {
var profileLink = document.createElement('a');
profileLink.href = uri;
profileLink.innerText = name;
var profileLinkPost = document.createElement('span');
profileLinkPost.innerText = "'s Pod";
var title = document.createElement('h1');
title.appendChild(profileLink);
title.appendChild(profileLinkPost);
return title;
}
function loadProfile(profileUrl, fetcher) {
return __awaiter(this, void 0, void 0, function () {
var webId;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
webId = rdflib_1["default"].sym(profileUrl);
return [4 /*yield*/, fetcher.load(webId)];
case 1:
_a.sent();
return [2 /*return*/, webId];
}
});
});
}
function getName(store, ownersProfile) {
return store.anyValue(ownersProfile, ns.vcard("fn"), null, ownersProfile.doc())
|| store.anyValue(ownersProfile, ns.foaf("name"), null, ownersProfile.doc())
|| new URL(ownersProfile.uri).host.split('.')[0];
}
7 changes: 3 additions & 4 deletions outline/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,8 @@ module.exports = function (doc) {
const me = UI.authn.currentUser()
var items = [ // {paneName: 'folder', label: 'Your files', subject: me.site()}, // replaced with storages
{paneName: 'home', label: 'Your stuff', icon: UI.icons.iconBase + 'noun_547570.svg'},
{paneName: 'trustedApplications', label: 'Preferences', icon: UI.icons.iconBase + 'noun_Sliders_341315_00000.svg'},
{paneName: 'basicPreferences', label: 'Preferences', icon: UI.icons.iconBase + 'noun_Sliders_341315_00000.svg'},
{paneName: 'trustedApplications', label: 'Trusted Aps', icon: UI.icons.iconBase + 'noun_15177.svg.svg'},
{paneName: 'editProfile', label: 'Edit your profile', icon: UI.icons.iconBase + 'noun_492246.svg'}
]

Expand All @@ -303,7 +304,7 @@ module.exports = function (doc) {

const storages = kb.each(me, ns.space('storage'), null, me.doc())
for (var pod of storages) {
var label = storages.length > 1 ? pod.uri.split('//')[1].slice(0,-1) : 'Your storage'
var label = storages.length > 1 ? pod.uri.split('//')[1].slice(0, -1) : 'Your storage'
items.push({paneName: 'folder', label: label, subject: pod, icon: UI.icons.iconBase + 'noun_Cabinet_251723.svg'})
}

Expand All @@ -317,8 +318,6 @@ module.exports = function (doc) {
containerDiv.innerHTML = ''
var table = containerDiv.appendChild(dom.createElement('table'))
const me = UI.authn.currentUser()
// @@ Using document.location.origin here is a hack, inserted there because Tim wants this before his presentation Thursday:
const subject = (item === 'folder') ? $rdf.sym(document.location.origin) : me
thisOutline.GotoSubject(item.subject || me, true, pane, false, undefined, table)
}

Expand Down
2 changes: 1 addition & 1 deletion profile/editProfilePane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const thisPane: PaneDefinition = { // 'noun_638141.svg' not editing
} // renderProfileForm

var div = dom.createElement('div')
var editableProfile
var editableProfile: NamedNode | null
div.setAttribute('style', 'border: 0.3em solid ' + highlightColor + '; border-radius: 0.5em; padding: 0.7em; margin-top:0.7em;')

var table = div.appendChild(dom.createElement('table'))
Expand Down
5 changes: 3 additions & 2 deletions profile/profilePane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// import UI from 'solid-ui'
// import solidUi, { SolidUi } from 'solid-ui'
import { NamedNode } from 'rdflib'
import panes from 'pane-registry'
// import panes from 'pane-registry'

import { PaneDefinition } from '../types'
import { getLabel } from './profilePaneUtils'
Expand Down Expand Up @@ -62,7 +62,8 @@ const thisPane: PaneDefinition = { // 'noun_638141.svg' not editing
return d
}

async function doRender(container, subject, dom) {
async function doRender(container: HTMLElement, subject: NamedNode | null, dom: HTMLDocument) {
if (!subject) throw new Error('subject missing')
const profile = subject.doc()
let otherProfiles = kb.each(subject, ns.rdfs('seeAlso'), null, profile)
if (otherProfiles.length > 0) {
Expand Down

0 comments on commit 1273f70

Please sign in to comment.