solid-panes 3.7.3-125af630 → 3.7.3-1bd42721

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/RDFXMLPane.js +58 -0
  2. package/dist/RDFXMLPane.js.map +1 -0
  3. package/dist/argument/argumentPane.js +61 -0
  4. package/dist/argument/argumentPane.js.map +1 -0
  5. package/dist/attach/attachPane.js +394 -0
  6. package/dist/attach/attachPane.js.map +1 -0
  7. package/dist/audio/audioPane.js +182 -0
  8. package/dist/audio/audioPane.js.map +1 -0
  9. package/dist/classInstancePane.js +92 -0
  10. package/dist/classInstancePane.js.map +1 -0
  11. package/dist/dataContentPane.js +259 -0
  12. package/dist/dataContentPane.js.map +1 -0
  13. package/dist/defaultPane.js +75 -0
  14. package/dist/defaultPane.js.map +1 -0
  15. package/dist/dokieli/dokieliPane.js +169 -0
  16. package/dist/dokieli/dokieliPane.js.map +1 -0
  17. package/dist/dokieli/new.js +28 -0
  18. package/dist/dokieli/new.js.map +1 -0
  19. package/dist/form/pane.js +185 -0
  20. package/dist/form/pane.js.map +1 -0
  21. package/dist/humanReadablePane.js +135 -0
  22. package/dist/humanReadablePane.js.map +1 -0
  23. package/dist/imagePane.js +70 -0
  24. package/dist/imagePane.js.map +1 -0
  25. package/dist/microblogPane/microblogPane.js +1031 -0
  26. package/dist/microblogPane/microblogPane.js.map +1 -0
  27. package/dist/n3Pane.js +56 -0
  28. package/dist/n3Pane.js.map +1 -0
  29. package/dist/outline/manager.js +1997 -0
  30. package/dist/outline/manager.js.map +1 -0
  31. package/dist/outline/outlineIcons.js +127 -0
  32. package/dist/outline/outlineIcons.js.map +1 -0
  33. package/dist/outline/queryByExample.js +285 -0
  34. package/dist/outline/queryByExample.js.map +1 -0
  35. package/dist/outline/userInput.js +1819 -0
  36. package/dist/outline/userInput.js.map +1 -0
  37. package/dist/playlist/playlistPane.js +124 -0
  38. package/dist/playlist/playlistPane.js.map +1 -0
  39. package/dist/registerPanes.js +146 -0
  40. package/dist/registerPanes.js.map +1 -0
  41. package/dist/schedule/formsForSchedule.js +124 -0
  42. package/dist/schedule/formsForSchedule.js.map +1 -0
  43. package/dist/schedule/schedulePane.js +889 -0
  44. package/dist/schedule/schedulePane.js.map +1 -0
  45. package/dist/slideshow/slideshowPane.js +80 -0
  46. package/dist/slideshow/slideshowPane.js.map +1 -0
  47. package/dist/socialPane.js +430 -0
  48. package/dist/socialPane.js.map +1 -0
  49. package/dist/tableViewPane.js +57 -0
  50. package/dist/tableViewPane.js.map +1 -0
  51. package/dist/transaction/pane.js +478 -0
  52. package/dist/transaction/pane.js.map +1 -0
  53. package/dist/transaction/period.js +324 -0
  54. package/dist/transaction/period.js.map +1 -0
  55. package/dist/trip/tripPane.js +175 -0
  56. package/dist/trip/tripPane.js.map +1 -0
  57. package/dist/ui/pane.js +147 -0
  58. package/dist/ui/pane.js.map +1 -0
  59. package/dist/versionInfo.js +2 -2
  60. package/dist/video/videoPane.js +43 -0
  61. package/dist/video/videoPane.js.map +1 -0
  62. package/package.json +3 -2
@@ -0,0 +1,889 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.schedulePane = void 0;
7
+ var UI = _interopRequireWildcard(require("solid-ui"));
8
+ var _solidLogic = require("solid-logic");
9
+ var _formsForSchedule = _interopRequireDefault(require("./formsForSchedule.js"));
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ 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); }
12
+ /* Scheduler Pane
13
+ **
14
+ **
15
+ */
16
+ /* global alert */
17
+
18
+ const $rdf = UI.rdf;
19
+ const ns = UI.ns;
20
+
21
+ // @@ Give other combos too-- see schedule ontology
22
+ const possibleAvailabilities = [ns.sched('No'), ns.sched('Maybe'), ns.sched('Yes')];
23
+ const schedulePane = exports.schedulePane = {
24
+ icon: UI.icons.iconBase + 'noun_346777.svg',
25
+ // @@ better?
26
+
27
+ name: 'schedule',
28
+ audience: [ns.solid('PowerUser')],
29
+ // Does the subject deserve an Scheduler pane?
30
+ label: function (subject, context) {
31
+ const kb = context.session.store;
32
+ const t = kb.findTypeURIs(subject);
33
+ if (t['http://www.w3.org/ns/pim/schedule#SchedulableEvent']) {
34
+ return 'Scheduling poll';
35
+ }
36
+ return null; // No under other circumstances
37
+ },
38
+ // Mint a new Schedule poll
39
+ mintClass: ns.sched('SchedulableEvent'),
40
+ mintNew: function (context, options) {
41
+ return new Promise(function (resolve, reject) {
42
+ const ns = UI.ns;
43
+ const kb = context.session.store;
44
+ let newBase = options.newBase;
45
+ const thisInstance = options.useExisting || $rdf.sym(options.newBase + 'index.ttl#this');
46
+ const complainIfBad = function (ok, body) {
47
+ if (ok) return;
48
+ console.log('Error in Schedule Pane: Error constructing new scheduler: ' + body);
49
+ reject(new Error(body));
50
+ };
51
+
52
+ // ////////////////////// Accesss control
53
+
54
+ // Two constiations of ACL for this app, public read and public read/write
55
+ // In all cases owner has read write control
56
+
57
+ const genACLtext = function (docURI, aclURI, allWrite) {
58
+ const g = $rdf.graph();
59
+ const auth = $rdf.Namespace('http://www.w3.org/ns/auth/acl#');
60
+ let a = g.sym(aclURI + '#a1');
61
+ const acl = g.sym(aclURI);
62
+ const doc = g.sym(docURI);
63
+ g.add(a, UI.ns.rdf('type'), auth('Authorization'), acl);
64
+ g.add(a, auth('accessTo'), doc, acl);
65
+ g.add(a, auth('agent'), me, acl);
66
+ g.add(a, auth('mode'), auth('Read'), acl);
67
+ g.add(a, auth('mode'), auth('Write'), acl);
68
+ g.add(a, auth('mode'), auth('Control'), acl);
69
+ a = g.sym(aclURI + '#a2');
70
+ g.add(a, UI.ns.rdf('type'), auth('Authorization'), acl);
71
+ g.add(a, auth('accessTo'), doc, acl);
72
+ g.add(a, auth('agentClass'), ns.foaf('Agent'), acl);
73
+ g.add(a, auth('mode'), auth('Read'), acl);
74
+ if (allWrite) {
75
+ g.add(a, auth('mode'), auth('Write'), acl);
76
+ }
77
+ return $rdf.serialize(acl, g, aclURI, 'text/turtle');
78
+ };
79
+
80
+ /*
81
+ const setACL3 = function (docURI, allWrite, callbackFunction) {
82
+ const aclText = genACLtext(docURI, aclDoc.uri, allWrite)
83
+ return UI.acl.setACL(docURI, aclText, callbackFunction)
84
+ }
85
+ */
86
+
87
+ const setACL2 = function setACL2(docURI, allWrite, callbackFunction) {
88
+ const aclDoc = kb.any(kb.sym(docURI), kb.sym('http://www.iana.org/assignments/link-relations/acl')); // @@ check that this get set by web.js
89
+
90
+ if (aclDoc) {
91
+ // Great we already know where it is
92
+ const aclText = genACLtext(docURI, aclDoc.uri, allWrite);
93
+ return fetcher.webOperation('PUT', aclDoc.uri, {
94
+ data: aclText,
95
+ contentType: 'text/turtle'
96
+ }).then(_result => callbackFunction(true)).catch(err => {
97
+ callbackFunction(false, err.message);
98
+ });
99
+ } else {
100
+ return fetcher.load(docURI).catch(err => {
101
+ callbackFunction(false, 'Getting headers for ACL: ' + err);
102
+ }).then(() => {
103
+ const aclDoc = kb.any(kb.sym(docURI), kb.sym('http://www.iana.org/assignments/link-relations/acl'));
104
+ if (!aclDoc) {
105
+ // complainIfBad(false, "No Link rel=ACL header for " + docURI)
106
+ throw new Error('No Link rel=ACL header for ' + docURI);
107
+ }
108
+ const aclText = genACLtext(docURI, aclDoc.uri, allWrite);
109
+ return fetcher.webOperation('PUT', aclDoc.uri, {
110
+ data: aclText,
111
+ contentType: 'text/turtle'
112
+ });
113
+ }).then(_result => callbackFunction(true)).catch(err => {
114
+ callbackFunction(false, err.message);
115
+ });
116
+ }
117
+ };
118
+
119
+ // Body of mintNew
120
+ const fetcher = kb.fetcher;
121
+ const updater = kb.updater;
122
+ let me = options.me || _solidLogic.authn.currentUser();
123
+ if (!me) {
124
+ console.log('MUST BE LOGGED IN');
125
+ alert('NOT LOGGED IN');
126
+ return;
127
+ }
128
+ const base = thisInstance.dir().uri;
129
+ let newDetailsDoc, newInstance; // , newIndexDoc
130
+
131
+ if (options.useExisting) {
132
+ newInstance = options.useExisting;
133
+ newBase = thisInstance.dir().uri;
134
+ newDetailsDoc = newInstance.doc();
135
+ // newIndexDoc = null
136
+ if (options.newBase) {
137
+ throw new Error('mint new scheduler: Illegal - have both new base and existing event');
138
+ }
139
+ } else {
140
+ newDetailsDoc = kb.sym(newBase + 'details.ttl');
141
+ // newIndexDoc = kb.sym(newBase + 'index.html')
142
+ newInstance = kb.sym(newDetailsDoc.uri + '#event');
143
+ }
144
+ const newResultsDoc = kb.sym(newBase + 'results.ttl');
145
+ const toBeCopied = options.noIndexHTML ? {} : [{
146
+ local: 'index.html',
147
+ contentType: 'text/html'
148
+ }];
149
+ const agenda = [];
150
+
151
+ // @@ This needs some form of visible progress bar
152
+ for (let f = 0; f < toBeCopied.length; f++) {
153
+ const item = toBeCopied[f];
154
+ const fun = function copyItem(item) {
155
+ agenda.push(function () {
156
+ const newURI = newBase + item.local;
157
+ console.log('Copying ' + base + item.local + ' to ' + newURI);
158
+ const setThatACL = function () {
159
+ setACL2(newURI, false, function (ok, message) {
160
+ if (!ok) {
161
+ complainIfBad(ok, 'FAILED to set ACL ' + newURI + ' : ' + message);
162
+ console.log('FAILED to set ACL ' + newURI + ' : ' + message);
163
+ } else {
164
+ agenda.shift()(); // beware too much nesting
165
+ }
166
+ });
167
+ };
168
+ kb.fetcher.webCopy(base + item.local, newBase + item.local, item.contentType).then(() => _solidLogic.authn.checkUser()).then(webId => {
169
+ me = webId;
170
+ setThatACL();
171
+ }).catch(err => {
172
+ console.log('FAILED to copy ' + base + item.local + ' : ' + err.message);
173
+ complainIfBad(false, 'FAILED to copy ' + base + item.local + ' : ' + err.message);
174
+ });
175
+ });
176
+ };
177
+ fun(item);
178
+ }
179
+ agenda.push(function createDetailsFile() {
180
+ kb.add(newInstance, ns.rdf('type'), ns.sched('SchedulableEvent'), newDetailsDoc);
181
+ if (me) {
182
+ kb.add(newInstance, ns.dc('author'), me, newDetailsDoc); // Who is sending the invitation?
183
+ kb.add(newInstance, ns.foaf('maker'), me, newDetailsDoc); // Uneditable - wh is allowed to edit this?
184
+ }
185
+ kb.add(newInstance, ns.dc('created'), new Date(), newDetailsDoc);
186
+ kb.add(newInstance, ns.sched('resultsDocument'), newDetailsDoc);
187
+ updater.put(newDetailsDoc, kb.statementsMatching(undefined, undefined, undefined, newDetailsDoc), 'text/turtle', function (uri2, ok, message) {
188
+ if (ok) {
189
+ agenda.shift()();
190
+ } else {
191
+ complainIfBad(ok, 'FAILED to save new scheduler at: ' + newDetailsDoc + ' : ' + message);
192
+ console.log('FAILED to save new scheduler at: ' + newDetailsDoc + ' : ' + message);
193
+ }
194
+ });
195
+ });
196
+ agenda.push(function () {
197
+ kb.fetcher.webOperation('PUT', newResultsDoc.uri, {
198
+ data: '',
199
+ contentType: 'text/turtle'
200
+ }).then(() => {
201
+ agenda.shift()();
202
+ }).catch(err => {
203
+ complainIfBad(false, 'Failed to initialize empty results file: ' + err.message);
204
+ });
205
+ });
206
+ agenda.push(function () {
207
+ setACL2(newResultsDoc.uri, true, function (ok, body) {
208
+ complainIfBad(ok, 'Failed to set Read-Write ACL on results file: ' + body);
209
+ if (ok) agenda.shift()();
210
+ });
211
+ });
212
+ agenda.push(function () {
213
+ setACL2(newDetailsDoc.uri, false, function (ok, body) {
214
+ complainIfBad(ok, 'Failed to set read ACL on configuration file: ' + body);
215
+ if (ok) agenda.shift()();
216
+ });
217
+ });
218
+ agenda.push(function () {
219
+ // give the user links to the new app
220
+ console.log('Finished minting new scheduler');
221
+ options.newInstance = newInstance;
222
+ resolve(options);
223
+ });
224
+ agenda.shift()();
225
+ // Created new data files.
226
+ }); // promise
227
+ },
228
+ // mintNew
229
+
230
+ // Render one meeting schedule poll
231
+ render: function (subject, context) {
232
+ const dom = context.dom;
233
+ const kb = context.session.store;
234
+ const ns = UI.ns;
235
+ const invitation = subject;
236
+ const appPathSegment = 'app-when-can-we.w3.org'; // how to allocate this string and connect to
237
+
238
+ // ////////////////////////////////////////////
239
+
240
+ const fetcher = kb.fetcher;
241
+ const updater = kb.updater;
242
+ let waitingForLogin = false;
243
+ const thisInstance = subject;
244
+ const detailsDoc = subject.doc();
245
+ const baseDir = detailsDoc.dir();
246
+ const base = baseDir.uri;
247
+ const resultsDoc = $rdf.sym(base + 'results.ttl');
248
+ // const formsURI = base + 'forms.ttl'
249
+ // We can't in fact host stuff from there because of CORS
250
+ const formsURI = 'https://solidos.github.io/solid-panes/schedule/formsForSchedule.ttl';
251
+ const form1 = kb.sym(formsURI + '#form1');
252
+ const form2 = kb.sym(formsURI + '#form2');
253
+ const form3 = kb.sym(formsURI + '#form3');
254
+ $rdf.parse(_formsForSchedule.default, kb, formsURI, 'text/turtle'); // Load forms directly
255
+
256
+ const inputStyle = 'background-color: #eef; padding: 0.5em; border: .5em solid white; font-size: 100%'; // font-size: 120%
257
+ const buttonIconStyle = 'width: 1.8em; height: 1.8em;';
258
+
259
+ // Utility functions
260
+
261
+ const complainIfBad = function (ok, message) {
262
+ if (!ok) {
263
+ div.appendChild(UI.widgets.errorMessageBlock(dom, message, 'pink'));
264
+ }
265
+ };
266
+ const clearElement = function (ele) {
267
+ while (ele.firstChild) {
268
+ ele.removeChild(ele.firstChild);
269
+ }
270
+ return ele;
271
+ };
272
+ const refreshCellColor = function (cell, value) {
273
+ const bg = kb.any(value, UI.ns.ui('backgroundColor'));
274
+ if (bg) {
275
+ cell.setAttribute('style', 'padding: 0.3em; text-align: center; background-color: ' + bg + ';');
276
+ }
277
+ };
278
+ let me;
279
+ _solidLogic.authn.checkUser().then(webId => {
280
+ me = webId;
281
+ if (logInOutButton) {
282
+ logInOutButton.refresh();
283
+ }
284
+ if (webId && waitingForLogin) {
285
+ waitingForLogin = false;
286
+ showAppropriateDisplay();
287
+ }
288
+ });
289
+ console.log('me: ' + me); // @@ curently not actually used elsewhere
290
+
291
+ // ////////////////////////////// Reproduction: spawn a new instance
292
+ //
293
+ // Viral growth path: user of app decides to make another instance
294
+ //
295
+
296
+ const newInstanceButton = function () {
297
+ const b = UI.login.newAppInstance(dom, {
298
+ noun: 'scheduler'
299
+ }, initializeNewInstanceInWorkspace);
300
+ b.firstChild.setAttribute('style', inputStyle);
301
+ return b;
302
+ }; // newInstanceButton
303
+
304
+ // /////////////////////// Create new document files for new instance of app
305
+
306
+ const initializeNewInstanceInWorkspace = function (ws) {
307
+ let newBase = kb.any(ws, ns.space('uriPrefix'));
308
+ if (!newBase) {
309
+ newBase = ws.uri.split('#')[0];
310
+ } else {
311
+ newBase = newBase.value;
312
+ }
313
+ if (newBase.slice(-1) !== '/') {
314
+ $rdf.log.error(appPathSegment + ': No / at end of uriPrefix ' + newBase); // @@ paramater?
315
+ newBase = newBase + '/';
316
+ }
317
+ const now = new Date();
318
+ newBase += appPathSegment + '/id' + now.getTime() + '/'; // unique id
319
+
320
+ initializeNewInstanceAtBase(thisInstance, newBase);
321
+ };
322
+ const initializeNewInstanceAtBase = function (thisInstance, newBase) {
323
+ const options = {
324
+ thisInstance,
325
+ newBase
326
+ };
327
+ this.mintNew(context, options).then(function (options) {
328
+ const p = div.appendChild(dom.createElement('p'));
329
+ p.setAttribute('style', 'font-size: 140%;');
330
+ p.innerHTML = 'Your <a href=\'' + options.newInstance.uri + '\'><b>new scheduler</b></a> is ready to be set up. ' + '<br/><br/><a href=\'' + options.newInstance.uri + '\'>Say when you what days work for you.</a>';
331
+ }).catch(function (error) {
332
+ complainIfBad(false, 'Error createing new scheduler at ' + options.newInstance + ': ' + error);
333
+ });
334
+ };
335
+
336
+ // ///////////////////////
337
+
338
+ const getForms = function () {
339
+ console.log('getforms()');
340
+ getDetails();
341
+ /*
342
+ fetcher.nowOrWhenFetched(formsURI, undefined, function (ok, body) {
343
+ console.log('getforms() ok? ' + ok)
344
+ if (!ok) return complainIfBad(ok, body)
345
+ getDetails()
346
+ })
347
+ */
348
+ };
349
+ const getDetails = function () {
350
+ console.log('getDetails()'); // Looking for blank screen hang-up
351
+ fetcher.nowOrWhenFetched(detailsDoc.uri, undefined, function (ok, body) {
352
+ console.log('getDetails() ok? ' + ok);
353
+ if (!ok) return complainIfBad(ok, body);
354
+ showAppropriateDisplay();
355
+ });
356
+ };
357
+ const showAppropriateDisplay = function showAppropriateDisplay() {
358
+ console.log('showAppropriateDisplay()');
359
+ _solidLogic.authn.checkUser().then(webId => {
360
+ if (!webId) {
361
+ return showSignon();
362
+ }
363
+
364
+ // On gh-pages, the turtle will not load properly (bad mime type)
365
+ // but we can trap it as being a non-editable server.
366
+
367
+ if (!kb.updater.editable(detailsDoc.uri, kb) || kb.holds(subject, ns.rdf('type'), ns.wf('TemplateInstance'))) {
368
+ // This is read-only example e.g. on github pages, etc
369
+ showBootstrap(div);
370
+ return;
371
+ }
372
+ const ready = kb.any(subject, ns.sched('ready'));
373
+ if (!ready) {
374
+ showForms();
375
+ } else {
376
+ // no editing not author
377
+ getResults();
378
+ }
379
+ });
380
+ };
381
+ const showSignon = function showSignon() {
382
+ clearElement(naviMain);
383
+ const signonContext = {
384
+ div,
385
+ dom
386
+ };
387
+ UI.login.ensureLoggedIn(signonContext).then(context => {
388
+ me = context.me;
389
+ waitingForLogin = false; // untested
390
+ showAppropriateDisplay();
391
+ });
392
+ };
393
+ const showBootstrap = function showBootstrap() {
394
+ const div = clearElement(naviMain);
395
+ div.appendChild(UI.login.newAppInstance(dom, {
396
+ noun: 'poll'
397
+ }, initializeNewInstanceInWorkspace));
398
+ div.appendChild(dom.createElement('hr')); // @@
399
+
400
+ const p = div.appendChild(dom.createElement('p'));
401
+ p.textContent = 'Where would you like to store the data for the poll? ' + 'Give the URL of the directory where you would like the data stored.';
402
+ const baseField = div.appendChild(dom.createElement('input'));
403
+ baseField.setAttribute('type', 'text');
404
+ baseField.size = 80; // really a string
405
+ baseField.label = 'base URL';
406
+ baseField.autocomplete = 'on';
407
+ div.appendChild(dom.createElement('br')); // @@
408
+
409
+ const button = div.appendChild(dom.createElement('button'));
410
+ button.setAttribute('style', inputStyle);
411
+ button.textContent = 'Start new poll at this URI';
412
+ button.addEventListener('click', function (_e) {
413
+ let newBase = baseField.value;
414
+ if (newBase.slice(-1) !== '/') {
415
+ newBase += '/';
416
+ }
417
+ initializeNewInstanceAtBase(thisInstance, newBase);
418
+ });
419
+ };
420
+
421
+ // ///////////// The forms to configure the poll
422
+
423
+ const doneButton = dom.createElement('button');
424
+ const showForms = function () {
425
+ clearElement(naviCenter); // Remove refresh button if nec
426
+ const div = naviMain;
427
+ const wizard = true;
428
+ let currentSlide = 0;
429
+ let gotDoneButton = false;
430
+ if (wizard) {
431
+ const forms = [form1, form2, form3];
432
+ const slides = [];
433
+ currentSlide = 0;
434
+ for (let f = 0; f < forms.length; f++) {
435
+ const slide = dom.createElement('div');
436
+ UI.widgets.appendForm(document, slide, {}, subject, forms[f], detailsDoc, complainIfBad);
437
+ slides.push(slide);
438
+ }
439
+ const refresh = function () {
440
+ clearElement(naviMain).appendChild(slides[currentSlide]);
441
+ if (currentSlide === 0) {
442
+ b1.setAttribute('disabled', '');
443
+ } else {
444
+ b1.removeAttribute('disabled');
445
+ }
446
+ if (currentSlide === slides.length - 1) {
447
+ b2.setAttribute('disabled', '');
448
+ if (!gotDoneButton) {
449
+ // Only expose at last slide seen
450
+ naviCenter.appendChild(emailButton); // could also check data shape
451
+ naviCenter.appendChild(doneButton); // could also check data shape
452
+ gotDoneButton = true;
453
+ }
454
+ } else {
455
+ b2.removeAttribute('disabled');
456
+ }
457
+ };
458
+ const b1 = clearElement(naviLeft).appendChild(dom.createElement('button'));
459
+ b1.setAttribute('style', inputStyle);
460
+ b1.textContent = '<- go back';
461
+ b1.addEventListener('click', function (_e) {
462
+ if (currentSlide > 0) {
463
+ currentSlide -= 1;
464
+ refresh();
465
+ }
466
+ }, false);
467
+ const b2 = clearElement(naviRight).appendChild(dom.createElement('button'));
468
+ b2.setAttribute('style', inputStyle);
469
+ b2.textContent = 'continue ->';
470
+ b2.addEventListener('click', function (_e) {
471
+ if (currentSlide < slides.length - 1) {
472
+ currentSlide += 1;
473
+ refresh();
474
+ }
475
+ }, false);
476
+ refresh();
477
+ } else {
478
+ // not wizard one big form
479
+ // @@@ create the initial config doc if not exist
480
+ const table = div.appendChild(dom.createElement('table'));
481
+ UI.widgets.appendForm(document, table, {}, subject, form1, detailsDoc, complainIfBad);
482
+ UI.widgets.appendForm(document, table, {}, subject, form2, detailsDoc, complainIfBad);
483
+ UI.widgets.appendForm(document, table, {}, subject, form3, detailsDoc, complainIfBad);
484
+ naviCenter.appendChild(doneButton); // could also check data shape
485
+ }
486
+ // @@@ link config to results
487
+
488
+ const insertables = [];
489
+ insertables.push($rdf.st(subject, ns.sched('availabilityOptions'), ns.sched('YesNoMaybe'), detailsDoc));
490
+ insertables.push($rdf.st(subject, ns.sched('ready'), new Date(), detailsDoc));
491
+ insertables.push($rdf.st(subject, ns.sched('results'), resultsDoc, detailsDoc)); // @@ also link in results
492
+
493
+ doneButton.setAttribute('style', inputStyle);
494
+ doneButton.textContent = 'Go to poll';
495
+ doneButton.addEventListener('click', function (_e) {
496
+ if (kb.any(subject, ns.sched('ready'))) {
497
+ // already done
498
+ getResults();
499
+ naviRight.appendChild(emailButton);
500
+ } else {
501
+ naviRight.appendChild(emailButton);
502
+ kb.updater.update([], insertables, function (uri, success, errorBody) {
503
+ if (!success) {
504
+ complainIfBad(success, errorBody);
505
+ } else {
506
+ // naviRight.appendChild(emailButton)
507
+ getResults();
508
+ }
509
+ });
510
+ }
511
+ }, false);
512
+ const emailButton = dom.createElement('button');
513
+ emailButton.setAttribute('style', inputStyle);
514
+ const emailIcon = emailButton.appendChild(dom.createElement('img'));
515
+ emailIcon.setAttribute('src', UI.icons.iconBase + 'noun_480183.svg'); // noun_480183.svg
516
+ emailIcon.setAttribute('style', buttonIconStyle);
517
+ // emailButton.textContent = 'email invitations'
518
+ emailButton.addEventListener('click', function (_e) {
519
+ const title = kb.anyValue(subject, ns.cal('summary')) || kb.anyValue(subject, ns.dc('title')) || '';
520
+ const mailto = 'mailto:' + kb.each(subject, ns.sched('invitee')).map(function (who) {
521
+ const mbox = kb.any(who, ns.foaf('mbox'));
522
+ return mbox ? mbox.uri.replace('mailto:', '') : '';
523
+ }).join(',') + '?subject=' + encodeURIComponent(title + '-- When can we meet?') + '&body=' + encodeURIComponent(title + '\n\nWhen can you?\n\nSee ' + subject + '\n');
524
+ // @@ assumed there is a data browser
525
+
526
+ console.log('Mail: ' + mailto);
527
+ window.location.href = mailto;
528
+ }, false);
529
+ }; // showForms
530
+
531
+ // Ask for each day, what times .. @@ to be added some time
532
+ /*
533
+ const setTimesOfDay = function () {
534
+ const i, j, x, y, slot, cell, day
535
+ const insertables = []
536
+ const possibleDays = kb.each(invitation, ns.sched('option'))
537
+ .map(function (opt) {return kb.any(opt, ns.cal('dtstart'))})
538
+ const cellLookup = []
539
+ const slots = kb.each(invitation, ns.sched('slot'))
540
+ if (slots.length === 0) {
541
+ for (i = 0; i < 2; i++) {
542
+ slot = UI.widgets.newThing(detailsDoc)
543
+ insertables.push($rdf.st(invitation, ns.sched('slot'), slot))
544
+ insertables.push($rdf.st(slot, ns.rdfs('label'), 'slot ' + (i + 1)))
545
+ for (j = 0; j < possibleDays.length; j++) {
546
+ day - possibleDays[j]
547
+ x = kb.any(slot, ns.rdfs('label'))
548
+ y = kb.any(day, ns.cal('dtstart'))
549
+ cell = UI.widgets.newThing(detailsDoc)
550
+ cellLookup[x.toNT() + y.toNT()] = cell
551
+ insertables.push($rdf.st(slot, ns.sched('cell'), cell))
552
+ insertables.push($rdf.st(cell, ns.sched('day'), possibleDays[j]))
553
+ }
554
+ }
555
+ }
556
+ const query = new $rdf.Query('TimesOfDay')
557
+ const v = {}['day', 'label', 'value', 'slot', 'cell'].map(function (x) {
558
+ query.consts.push(v[x] = $rdf.constiable(x)) })
559
+ query.pat.add(invitation, ns.sched('slot'), v.slot)
560
+ query.pat.add(v.slot, ns.rdfs('label'), v.label)
561
+ query.pat.add(v.slot, ns.sched('cell'), v.cell)
562
+ query.pat.add(v.cell, ns.sched('timeOfDay'), v.value)
563
+ query.pat.add(v.cell, ns.sched('day'), v.day)
564
+ const options = {}
565
+ options.set_x = kb.each(subject, ns.sched('slot')) // @@@@@ option -> dtstart in future
566
+ options.set_x = options.set_x.map(function (opt) { return kb.any(opt, ns.rdfs('label')) })
567
+ options.set_y = kb.each(subject, ns.sched('option')); // @@@@@ option -> dtstart in future
568
+ options.set_y = options.set_y.map(function (opt) { return kb.any(opt, ns.cal('dtstart')) })
569
+ const possibleTimes = kb.each(invitation, ns.sched('option'))
570
+ .map(function (opt) { return kb.any(opt, ns.cal('dtstart')) })
571
+ const displayTheMatrix = function () {
572
+ const matrix = div.appendChild(UI.matrix.matrixForQuery(
573
+ dom, query, v.time, v.author, v.value, options, function () {}))
574
+ matrix.setAttribute('class', 'matrix')
575
+ const refreshButton = dom.createElement('button')
576
+ refreshButton.setAttribute('style', inputStyle)
577
+ refreshButton.textContent = 'refresh'
578
+ refreshButton.addEventListener('click', function (e) {
579
+ refreshButton.disabled = true
580
+ store.fetcher.nowOrWhenFetched(subject.doc(), undefined, function (ok, body) {
581
+ if (!ok) {
582
+ console.log('Cant refresh matrix' + body)
583
+ } else {
584
+ matrix.refresh()
585
+ refreshButton.disabled = false
586
+ }
587
+ })
588
+ }, false)
589
+ clearElement(naviCenter)
590
+ naviCenter.appendChild(refreshButton)
591
+ }
592
+ const dataPointForNT = []
593
+ const doc = resultsDoc
594
+ options.set_y = options.set_y.filter(function (z) { return (! z.sameTerm(me)) })
595
+ options.set_y.push(me) // Put me on the end
596
+ options.cellFunction = function (cell, x, y, value) {
597
+ // const point = cellLookup[x.toNT() + y.toNT()]
598
+ if (y.sameTerm(me)) {
599
+ const callbackFunction = function () { refreshCellColor(cell, value); }; // @@ may need that
600
+ const selectOptions = {}
601
+ const predicate = ns.sched('timeOfDay')
602
+ const cellSubject = dataPointForNT[x.toNT()]
603
+ const selector = UI.widgets.makeSelectForOptions(dom, kb, cellSubject, predicate,
604
+ possibleAvailabilities, selectOptions, resultsDoc, callbackFunction)
605
+ cell.appendChild(selector)
606
+ } else if (value !== null) {
607
+ cell.textContent = UI.utils.label(value)
608
+ }
609
+ }
610
+ const responses = kb.each(invitation, ns.sched('response'))
611
+ const myResponse = null
612
+ responses.map(function (r) {
613
+ if (kb.holds(r, ns.dc('author'), me)) {
614
+ myResponse = r
615
+ }
616
+ })
617
+ const id = UI.widgets.newThing(doc).uri
618
+ if (myResponse === null) {
619
+ myResponse = $rdf.sym(id + '_response')
620
+ insertables.push($rdf.st(invitation, ns.sched('response'), myResponse, doc))
621
+ insertables.push($rdf.st(myResponse, ns.dc('author'), me, doc))
622
+ } else {
623
+ const dps = kb.each(myResponse, ns.sched('cell'))
624
+ dps.map(function (dataPoint) {
625
+ const time = kb.any(dataPoint, ns.cal('dtstart'))
626
+ dataPointForNT[time.toNT()] = dataPoint
627
+ })
628
+ }
629
+ for (let j = 0; j < possibleTimes.length; j++) {
630
+ if (dataPointForNT[possibleTimes[j].toNT()]) continue
631
+ const dataPoint = $rdf.sym(id + '_' + j)
632
+ insertables.push($rdf.st(myResponse, ns.sched('cell'), dataPoint, doc))
633
+ insertables.push($rdf.st(dataPoint, ns.cal('dtstart'), possibleTimes[j], doc)) // @@
634
+ dataPointForNT[possibleTimes[j].toNT()] = dataPoint
635
+ }
636
+ if (insertables.length) {
637
+ store.updater.update([], insertables, function (uri, success, errorBody) {
638
+ if (!success) {
639
+ complainIfBad(success, errorBody)
640
+ } else {
641
+ displayTheMatrix()
642
+ }
643
+ })
644
+ } else { // no insertables
645
+ displayTheMatrix()
646
+ }
647
+ }
648
+ */
649
+ // end setTimesOfDay
650
+
651
+ // Read or create empty results file
652
+ function getResults() {
653
+ fetcher.nowOrWhenFetched(resultsDoc.uri, (ok, body, response) => {
654
+ if (!ok) {
655
+ if (response.status === 404) {
656
+ // / Check explicitly for 404 error
657
+ console.log('Initializing details file ' + resultsDoc);
658
+ updater.put(resultsDoc, [], 'text/turtle', function (uri2, ok, message) {
659
+ if (ok) {
660
+ clearElement(naviMain);
661
+ showResults();
662
+ } else {
663
+ complainIfBad(ok, 'FAILED to create results file at: ' + resultsDoc.uri + ' : ' + message);
664
+ console.log('FAILED to craete results file at: ' + resultsDoc.uri + ' : ' + message);
665
+ }
666
+ });
667
+ } else {
668
+ // Other error, not 404 -- do not try to overwite the file
669
+ complainIfBad(ok, 'FAILED to read results file: ' + body);
670
+ }
671
+ } else {
672
+ // Happy read
673
+ clearElement(naviMain);
674
+ showResults();
675
+ }
676
+ });
677
+ }
678
+ function showResults() {
679
+ // Now the form for responsing to the poll
680
+ //
681
+
682
+ // div.appendChild(dom.createElement('hr'))
683
+
684
+ // const invitation = subject
685
+ const title = kb.any(invitation, ns.cal('summary'));
686
+ const comment = kb.any(invitation, ns.cal('comment'));
687
+ const location = kb.any(invitation, ns.cal('location'));
688
+ const div = naviMain;
689
+ if (title) div.appendChild(dom.createElement('h3')).textContent = title;
690
+ if (location) {
691
+ div.appendChild(dom.createElement('address')).textContent = location.value;
692
+ }
693
+ if (comment) {
694
+ div.appendChild(dom.createElement('p')).textContent = comment.value;
695
+ }
696
+ const author = kb.any(invitation, ns.dc('author'));
697
+ if (author) {
698
+ const authorName = kb.any(author, ns.foaf('name'));
699
+ if (authorName) {
700
+ div.appendChild(dom.createElement('p')).textContent = authorName;
701
+ }
702
+ }
703
+ const query = new $rdf.Query('Responses');
704
+ const v = {};
705
+ const vs = ['time', 'author', 'value', 'resp', 'cell'];
706
+ vs.forEach(function (x) {
707
+ query.vars.push(v[x] = $rdf.variable(x));
708
+ });
709
+ query.pat.add(invitation, ns.sched('response'), v.resp);
710
+ query.pat.add(v.resp, ns.dc('author'), v.author);
711
+ query.pat.add(v.resp, ns.sched('cell'), v.cell);
712
+ query.pat.add(v.cell, ns.sched('availabilty'), v.value);
713
+ query.pat.add(v.cell, ns.cal('dtstart'), v.time);
714
+
715
+ // Sort by by person @@@
716
+
717
+ const options = {};
718
+ options.set_x = kb.each(subject, ns.sched('option')); // @@@@@ option -> dtstart in future
719
+ options.set_x = options.set_x.map(function (opt) {
720
+ return kb.any(opt, ns.cal('dtstart'));
721
+ });
722
+ options.set_y = kb.each(subject, ns.sched('response'));
723
+ options.set_y = options.set_y.map(function (resp) {
724
+ return kb.any(resp, ns.dc('author'));
725
+ });
726
+ const possibleTimes = kb.each(invitation, ns.sched('option')).map(function (opt) {
727
+ return kb.any(opt, ns.cal('dtstart'));
728
+ });
729
+ const displayTheMatrix = function () {
730
+ const matrix = div.appendChild(UI.matrix.matrixForQuery(dom, query, v.time, v.author, v.value, options, function () {}));
731
+ matrix.setAttribute('class', 'matrix');
732
+ const refreshButton = dom.createElement('button');
733
+ refreshButton.setAttribute('style', inputStyle);
734
+ // refreshButton.textContent = 'refresh' // noun_479395.svg
735
+ const refreshIcon = dom.createElement('img');
736
+ refreshIcon.setAttribute('src', UI.icons.iconBase + 'noun_479395.svg');
737
+ refreshIcon.setAttribute('style', buttonIconStyle);
738
+ refreshButton.appendChild(refreshIcon);
739
+ refreshButton.addEventListener('click', function (_e) {
740
+ refreshButton.disabled = true;
741
+ kb.fetcher.refresh(resultsDoc, function (ok, body) {
742
+ if (!ok) {
743
+ console.log('Cant refresh matrix' + body);
744
+ } else {
745
+ matrix.refresh();
746
+ refreshButton.disabled = false;
747
+ }
748
+ });
749
+ }, false);
750
+ clearElement(naviCenter);
751
+ naviCenter.appendChild(refreshButton);
752
+ };
753
+
754
+ // @@ Give other combos too-- see schedule ontology
755
+ // const possibleAvailabilities = [ SCHED('No'), SCHED('Maybe'), SCHED('Yes') ]
756
+
757
+ // const me = authn.currentUser()
758
+
759
+ const dataPointForNT = [];
760
+ const loginContext = {
761
+ div: naviCenter,
762
+ dom
763
+ };
764
+ UI.login.ensureLoggedIn(loginContext).then(context => {
765
+ const me = context.me;
766
+ const doc = resultsDoc;
767
+ options.set_y = options.set_y.filter(function (z) {
768
+ return !z.sameTerm(me);
769
+ });
770
+ options.set_y.push(me); // Put me on the end
771
+
772
+ options.cellFunction = function (cell, x, y, value) {
773
+ if (value !== null) {
774
+ kb.fetcher.nowOrWhenFetched(value.uri.split('#')[0], undefined, function (ok, _error) {
775
+ if (ok) refreshCellColor(cell, value);
776
+ });
777
+ }
778
+ if (y.sameTerm(me)) {
779
+ const callbackFunction = function () {
780
+ refreshCellColor(cell, value);
781
+ }; // @@ may need that
782
+ const selectOptions = {};
783
+ const predicate = ns.sched('availabilty');
784
+ const cellSubject = dataPointForNT[x.toNT()];
785
+ const selector = UI.widgets.makeSelectForOptions(dom, kb, cellSubject, predicate, possibleAvailabilities, selectOptions, resultsDoc, callbackFunction);
786
+ cell.appendChild(selector);
787
+ } else if (value !== null) {
788
+ cell.textContent = UI.utils.label(value);
789
+ }
790
+ };
791
+ const responses = kb.each(invitation, ns.sched('response'));
792
+ let myResponse = null;
793
+ responses.forEach(function (r) {
794
+ if (kb.holds(r, ns.dc('author'), me)) {
795
+ myResponse = r;
796
+ }
797
+ });
798
+ const insertables = []; // list of statements to be stored
799
+
800
+ const id = UI.widgets.newThing(doc).uri;
801
+ if (myResponse === null) {
802
+ myResponse = $rdf.sym(id + '_response');
803
+ insertables.push($rdf.st(invitation, ns.sched('response'), myResponse, doc));
804
+ insertables.push($rdf.st(myResponse, ns.dc('author'), me, doc));
805
+ } else {
806
+ const dps = kb.each(myResponse, ns.sched('cell'));
807
+ dps.forEach(function (dataPoint) {
808
+ const time = kb.any(dataPoint, ns.cal('dtstart'));
809
+ dataPointForNT[time.toNT()] = dataPoint;
810
+ });
811
+ }
812
+ for (let j = 0; j < possibleTimes.length; j++) {
813
+ if (dataPointForNT[possibleTimes[j].toNT()]) continue;
814
+ const dataPoint = $rdf.sym(id + '_' + j);
815
+ insertables.push($rdf.st(myResponse, ns.sched('cell'), dataPoint, doc));
816
+ insertables.push($rdf.st(dataPoint, ns.cal('dtstart'), possibleTimes[j], doc)); // @@
817
+ dataPointForNT[possibleTimes[j].toNT()] = dataPoint;
818
+ }
819
+ if (insertables.length) {
820
+ kb.updater.update([], insertables, function (uri, success, errorBody) {
821
+ if (!success) {
822
+ complainIfBad(success, errorBody);
823
+ } else {
824
+ displayTheMatrix();
825
+ }
826
+ });
827
+ } else {
828
+ // no insertables
829
+ displayTheMatrix();
830
+ }
831
+ }); // @@@@ end of .then
832
+
833
+ // If I made this in the first place, allow me to edit it.
834
+ // @@ optionally -- allows others to if according to original
835
+ const instanceCreator = kb.any(subject, ns.foaf('maker')); // owner?
836
+ if (!instanceCreator || instanceCreator.sameTerm(me)) {
837
+ const editButton = dom.createElement('button');
838
+ editButton.setAttribute('style', inputStyle);
839
+ // editButton.textContent = '(Modify the poll)' // noun_344563.svg
840
+ const editIcon = dom.createElement('img');
841
+ editIcon.setAttribute('src', UI.icons.iconBase + 'noun_344563.svg');
842
+ editIcon.setAttribute('style', buttonIconStyle);
843
+ editButton.appendChild(editIcon);
844
+ editButton.addEventListener('click', function (_e) {
845
+ clearElement(div);
846
+ showForms();
847
+ }, false);
848
+ clearElement(naviLeft);
849
+ naviLeft.appendChild(editButton);
850
+ }
851
+
852
+ // div.appendChild(editButton)
853
+
854
+ clearElement(naviRight);
855
+ naviRight.appendChild(newInstanceButton());
856
+ } // showResults
857
+
858
+ const div = dom.createElement('div');
859
+ const structure = div.appendChild(dom.createElement('table')); // @@ make responsive style
860
+ structure.setAttribute('style', 'background-color: white; min-width: 40em; min-height: 13em;');
861
+ const naviLoginoutTR = structure.appendChild(dom.createElement('tr'));
862
+ naviLoginoutTR.appendChild(dom.createElement('td'));
863
+ naviLoginoutTR.appendChild(dom.createElement('td'));
864
+ naviLoginoutTR.appendChild(dom.createElement('td'));
865
+ const logInOutButton = null;
866
+ /*
867
+ const logInOutButton = UI.login.loginStatusBox(dom, setUser)
868
+ // floating divs lead to a mess
869
+ // logInOutButton.setAttribute('style', 'float: right') // float the beginning of the end
870
+ naviLoginout3.appendChild(logInOutButton)
871
+ logInOutButton.setAttribute('style', 'margin-right: 0em;')
872
+ */
873
+
874
+ const naviTop = structure.appendChild(dom.createElement('tr'));
875
+ const naviMain = naviTop.appendChild(dom.createElement('td'));
876
+ naviMain.setAttribute('colspan', '3');
877
+ const naviMenu = structure.appendChild(dom.createElement('tr'));
878
+ naviMenu.setAttribute('class', 'naviMenu');
879
+ naviMenu.setAttribute('style', ' text-align: middle; vertical-align: middle; padding-top: 4em; ');
880
+ // naviMenu.setAttribute('style', 'margin-top: 3em;')
881
+ const naviLeft = naviMenu.appendChild(dom.createElement('td'));
882
+ const naviCenter = naviMenu.appendChild(dom.createElement('td'));
883
+ const naviRight = naviMenu.appendChild(dom.createElement('td'));
884
+ getForms();
885
+ return div;
886
+ } // render
887
+ }; // property list
888
+ // ends
889
+ //# sourceMappingURL=schedulePane.js.map