issue-pane 2.6.1 → 3.0.0-a58a4367

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.
package/issuePane.js DELETED
@@ -1,594 +0,0 @@
1
- /* Issue Tracker Pane
2
- **
3
- ** This solid view allows a user to interact with an issue tracker, or individual issue,
4
- ** to change its state according to an ontology, comment on it, etc.
5
- **
6
- */
7
-
8
- import { create, login, ns, icons, rdf, tabs, table, utils, widgets } from 'solid-ui'
9
- import { store, authn } from 'solid-logic'
10
- import { board } from './board' // @@ will later be in solid-UI
11
- import { renderIssue, renderIssueCard, getState, exposeOverlay } from './issue'
12
- import { newTrackerButton } from './newTracker'
13
- import { newIssueForm } from './newIssue'
14
- import { csvButton } from './csvButton'
15
- import { trackerSettingsFormText } from './trackerSettingsForm.js'
16
- // import { trackerInstancesFormText } from './trackerInstancesForm.js'
17
-
18
- const $rdf = rdf
19
- const kb = store
20
-
21
- // const MY_TRACKERS_ICON = UI.icons.iconBase + 'noun_Document_998605.svg'
22
- // const TRACKER_ICON = UI.icons.iconBase + 'noun_list_638112'
23
- // const TASK_ICON = UI.icons.iconBase + 'noun_17020.svg'
24
-
25
- const OVERFLOW_STYLE = 'position: fixed; z-index: 100; top: 1.51em; right: 2em; left: 2em; bottom:1.5em; border: 0.1em grey; overflow: scroll;'
26
- export default {
27
- icon: icons.iconBase + 'noun_122196.svg', // was: js/panes/issue/tbl-bug-22.png
28
- // noun_list_638112 is a checklist document
29
- // noun_Document_998605.svg is a stack of twpo checklists
30
- // noun_97839.svg is a ladybug
31
- // noun_122196.svg is a clipboard with a check list on it
32
- // noun_17020.svg is a single check box
33
- name: 'issue',
34
-
35
- audience: [], // Anyone. was [ns.solid('PowerUser')]
36
-
37
- // Does the subject deserve an issue pane?
38
- label: function (subject, _context) {
39
- const t = kb.findTypeURIs(subject)
40
- if (
41
- t['http://www.w3.org/2005/01/wf/flow#Task'] ||
42
- kb.holds(subject, ns.wf('tracker'))
43
- ) { return 'issue' } // in case ontology not available
44
- if (t['http://www.w3.org/2005/01/wf/flow#Tracker']) return 'tracker'
45
- // Later: Person. For a list of things assigned to them,
46
- // open bugs on projects they are developer on, etc
47
- return null // No under other circumstances (while testing at least!)
48
- },
49
-
50
- mintClass: ns.wf('Tracker'),
51
-
52
- mintNew: async function (context, options) {
53
- /** Perform updates on more than one document @@ Move to rdflib!
54
- */
55
- async function updateMany (deletions, insertions) {
56
- const docs = deletions.concat(insertions).map(st => st.why)
57
- const uniqueDocs = Array.from(new Set(docs))
58
- const updates = uniqueDocs.map(doc =>
59
- kb.updater.update(deletions.filter(st => st.why.sameTerm(doc)),
60
- insertions.filter(st => st.why.sameTerm(doc))))
61
- return Promise.all(updates)
62
- }
63
-
64
- const kb = context.session.store
65
- let stateStore
66
- if (options.newInstance) {
67
- stateStore = kb.sym(options.newInstance.doc().uri + '_state.ttl')
68
- } else {
69
- options.newInstance = kb.sym(options.newBase + 'index.ttl#this')
70
- stateStore = kb.sym(options.newBase + 'state.ttl')
71
- }
72
- const tracker = options.newInstance
73
- const appDoc = tracker.doc()
74
-
75
- const me = authn.currentUser()
76
- if (me) {
77
- kb.add(tracker, ns.dc('author'), me, appDoc)
78
- }
79
-
80
- kb.add(tracker, ns.rdf('type'), ns.wf('Tracker'), appDoc)
81
- kb.add(tracker, ns.dc('created'), new Date(), appDoc)
82
-
83
- // @@ to do --- adk user what sort of tracker they want
84
-
85
- kb.add(tracker, ns.wf('issueClass'), ns.wf('Task'), appDoc) // @@ ask user
86
- kb.add(tracker, ns.wf('initialState'), ns.wf('Open'), appDoc)
87
- kb.add(tracker, ns.wf('stateStore'), stateStore, appDoc)
88
- kb.add(tracker, ns.wf('assigneeClass'), ns.foaf('Person'), appDoc) // @@ set to people in the meeting?
89
-
90
- kb.add(tracker, ns.wf('stateStore'), stateStore, stateStore) // Back Link
91
-
92
- const ins = kb.statementsMatching(undefined, undefined, undefined, appDoc).concat(kb.statementsMatching(undefined, undefined, undefined, stateStore))
93
- try {
94
- await updateMany([], ins)
95
- } catch (err) {
96
- return widgets.complain(context, 'Error writing tracker configuration: ' + err)
97
- }
98
- /*
99
- try {
100
- await kb.updater.updateMany([], kb.statementsMatching(undefined, undefined, undefined, stateStore))
101
- } catch (err) {
102
- return widgets.complain(context, 'Error writing tracker state file: ' + err)
103
- }
104
- */
105
- const dom = context.dom
106
- const div = options.div
107
-
108
- const notice = div.appendChild(dom.createElement('div'))
109
- notice.innerHTML = `<h4>Success</h4>
110
- <p>Your <a href="${tracker.uri}">new tracker</a> has been made.
111
- Use the settings tab to configure it.
112
- </p>
113
- `
114
- // console.log('New tracker created ' + tracker)
115
- // alert('New tracker created')
116
- return options
117
- },
118
-
119
- render: function (subject, context) {
120
- const dom = context.dom
121
-
122
- const paneDiv = dom.createElement('div')
123
- context.paneDiv = paneDiv
124
- paneDiv.setAttribute('class', 'issuePane')
125
-
126
- function complain (message) {
127
- console.warn(message)
128
- paneDiv.appendChild(widgets.errorMessageBlock(dom, message))
129
- }
130
-
131
- function complainIfBad (ok, message) {
132
- if (!ok) {
133
- complain(message)
134
- }
135
- }
136
-
137
- /** Infer subclass from disjoint Union
138
- **
139
- ** This is would not be needed if our quey language
140
- ** allowed is to query ardf Collection membership.
141
- */
142
- async function fixSubClasses (kb, tracker) { // 20220228
143
- async function checkOneSuperclass (klass) {
144
- const collection = kb.any(klass, ns.owl('disjointUnionOf'), null, doc)
145
- if (!collection) throw new Error(`Classification ${klass} has no disjointUnionOf`)
146
- if (!collection.elements) throw new Error(`Classification ${klass} has no array`)
147
- const needed = new Set(collection.elements.map(x => x.uri))
148
- const existing = new Set(kb.each(null, ns.rdfs('subClassOf'), klass, doc).map(x => x.uri))
149
-
150
- const superfluous = [...existing].filter(sub => !needed.has(sub))
151
- const deleteActions = superfluous.map(sub => { return { action: 'delete', st: $rdf.st(kb.sym(sub), ns.rdfs('subClassOf'), klass, doc) } })
152
-
153
- const missing = [...needed].filter(sub => !existing.has(sub))
154
- const insertActions = missing.map(sub => { return { action: 'insert', st: $rdf.st(kb.sym(sub), ns.rdfs('subClassOf'), klass, doc) } })
155
- return deleteActions.concat(insertActions)
156
- }
157
- const doc = tracker.doc()
158
- const states = kb.any(tracker, ns.wf('issueClass'))
159
- const cats = kb.each(tracker, ns.wf('issueCategory')).concat([states])
160
- let damage = [] // to make totally functionaly need to deal with map over async.
161
- for (const klass of cats) {
162
- damage = damage.concat(await checkOneSuperclass(klass))
163
- }
164
- if (damage.length) {
165
- const insertables = damage.filter(fix => fix.action === 'insert').map(fix => fix.st)
166
- const deletables = damage.filter(fix => fix.action === 'delete').map(fix => fix.st)
167
- // alert(`Internal error: s${damage} subclasses inconsistences!`)
168
- console.log('Damage:', damage)
169
- if (confirm(`Fix ${damage} inconsistent subclasses in tracker config?`)) {
170
- await kb.updater.update(deletables, insertables)
171
- }
172
- }
173
- }
174
-
175
- /** /////////////////////////// Board
176
- */
177
- function renderBoard (tracker, klass) {
178
- const states = kb.any(tracker, ns.wf('issueClass'))
179
- klass = klass || states // default to states
180
- const doingStates = klass.sameTerm(states)
181
-
182
- // These are states we will show by default: the open issues.
183
- const stateArray = kb.any(klass, ns.owl('disjointUnionOf'))
184
- if (!stateArray) {
185
- return complain(`Configuration error: state ${states} does not have substates`)
186
- }
187
- let columnValues = stateArray.elements
188
- if (doingStates && columnValues.length > 2 // and there are more than two
189
- ) { // strip out closed states
190
- columnValues = columnValues.filter(state => kb.holds(state, ns.rdfs('subClassOf'), ns.wf('Open')) || state.sameTerm(ns.wf('Open')))
191
- }
192
-
193
- async function columnDropHandler (issue, newState) {
194
- const currentState = getState(issue, klass)
195
- const tracker = kb.the(issue, ns.wf('tracker'), null, issue.doc())
196
- const stateStore = kb.any(tracker, ns.wf('stateStore'))
197
-
198
- if (newState.sameTerm(currentState)) {
199
- // alert('Same state ' + utils.label(currentState)) // @@ remove
200
- return
201
- }
202
- try {
203
- await kb.updater.update(
204
- [$rdf.st(issue, ns.rdf('type'), currentState, stateStore)],
205
- [$rdf.st(issue, ns.rdf('type'), newState, stateStore)])
206
- } catch (err) {
207
- widgets.complain(context, 'Unable to change issue state: ' + err)
208
- }
209
- boardDiv.refresh() // reorganize board to match the new reality
210
- }
211
-
212
- function isOpen (issue) {
213
- const types = kb.findTypeURIs(issue)
214
- return !!types[ns.wf('Open').uri]
215
- }
216
-
217
- const options = { columnDropHandler, filter: doingStates ? null : isOpen }
218
- options.sortBy = ns.dct('created')
219
- options.sortReverse = true
220
- function localRenderIssueCard (issue) {
221
- return renderIssueCard(issue, context)
222
- }
223
- // const columnValues = states // @@ optionally selected states would work
224
- const boardDiv = board(dom, columnValues, localRenderIssueCard, options)
225
- return boardDiv
226
- }
227
-
228
- /** ////////////// Table
229
- */
230
- function tableRefreshButton (stateStore, tableDiv) {
231
- const refreshButton = widgets.button(dom, icons.iconBase + 'noun_479395.svg',
232
- 'refresh table', async _event => {
233
- try {
234
- await kb.fetcher.load(stateStore, { force: true, clearPreviousData: true })
235
- } catch (err) {
236
- alert(err)
237
- return
238
- }
239
- widgets.refreshTree(tableDiv)
240
- })
241
- return refreshButton
242
- }
243
-
244
- function renderTable (tracker) {
245
- function newOptionalClause () {
246
- const clause = new $rdf.IndexedFormula()
247
- query.pat.optional.push(clause)
248
- return clause
249
- }
250
- const states = kb.any(subject, ns.wf('issueClass'))
251
- const cats = kb.each(tracker, ns.wf('issueCategory')) // zero or more
252
- const vars = ['issue', 'state', 'created']
253
- const query = new $rdf.Query(utils.label(subject))
254
- for (let i = 0; i < cats.length; i++) {
255
- vars.push('_cat_' + i)
256
- }
257
- const v = {} // The RDF variable objects for each variable name
258
- vars.forEach(function (x) {
259
- query.vars.push((v[x] = $rdf.variable(x)))
260
- })
261
- query.pat.add(v.issue, ns.wf('tracker'), tracker)
262
- // query.pat.add(v['issue'], ns.dc('title'), v['title'])
263
- query.pat.add(v.issue, ns.dct('created'), v.created)
264
- query.pat.add(v.issue, ns.rdf('type'), v.state)
265
- query.pat.add(v.state, ns.rdfs('subClassOf'), states)
266
-
267
- query.pat.optional = []
268
-
269
- for (let i = 0; i < cats.length; i++) {
270
- const clause = newOptionalClause()
271
- clause.add(v.issue, ns.rdf('type'), v['_cat_' + i])
272
- clause.add(v['_cat_' + i], ns.rdfs('subClassOf'), cats[i])
273
- }
274
-
275
- const propertyList = kb.any(tracker, ns.wf('propertyList')) // List of extra properties
276
- if (propertyList) {
277
- const properties = propertyList.elements
278
- for (let p = 0; p < properties.length; p++) {
279
- const prop = properties[p]
280
- let vname = '_prop_' + p
281
- if (prop.uri.indexOf('#') >= 0) {
282
- vname = prop.uri.split('#')[1]
283
- }
284
- const oneOpt = newOptionalClause()
285
- query.vars.push((v[vname] = $rdf.variable(vname)))
286
- oneOpt.add(v.issue, prop, v[vname])
287
- }
288
- }
289
-
290
- const selectedStates = {}
291
- const possible = kb.each(undefined, ns.rdfs('subClassOf'), states)
292
- possible.forEach(function (s) {
293
- if (
294
- kb.holds(s, ns.rdfs('subClassOf'), ns.wf('Open')) ||
295
- s.sameTerm(ns.wf('Open'))
296
- ) {
297
- selectedStates[s.uri] = true
298
- // console.log('on '+s.uri); // @@
299
- }
300
- })
301
-
302
- function exposeThisOverlay (href) {
303
- const subject = $rdf.sym(href)
304
- exposeOverlay(subject, context)
305
- }
306
-
307
- const tableDiv = table(dom, {
308
- query: query,
309
- keyVariable: '?issue', // Charactersic of row
310
- sortBy: '?created', // By default, sort by date
311
- sortReverse: true, // most recent at the top
312
- hints: {
313
- '?issue': { linkFunction: exposeThisOverlay, label: 'Title' },
314
- '?created': { cellFormat: 'shortDate' },
315
- '?state': { initialSelection: selectedStates, label: 'Status' }
316
- }
317
- })
318
- const stateStore = kb.any(subject, ns.wf('stateStore'))
319
- tableDiv.appendChild(tableRefreshButton(stateStore, tableDiv))
320
- return tableDiv
321
- }
322
-
323
- // Allow user to create new things within the folder
324
- function renderCreationControl (refreshTarget) {
325
- const creationDiv = dom.createElement('div')
326
- const me = authn.currentUser()
327
- const creationContext = {
328
- // folder: subject,
329
- div: creationDiv,
330
- dom: dom,
331
- noun: 'tracker',
332
- statusArea: creationDiv,
333
- me: me,
334
- refreshTarget: refreshTarget
335
- }
336
- const issuePane = context.session.paneRegistry.byName('issue')
337
- const relevantPanes = [issuePane]
338
- create.newThingUI(creationContext, context, relevantPanes) // Have to pass panes down newUI
339
- return creationDiv
340
- }
341
-
342
- function renderInstances (theClass) {
343
- const instancesDiv = dom.createElement('div')
344
- const context = { dom, div: instancesDiv, noun: 'tracker' }
345
- login.registrationList(context, { public: true, private: true, type: theClass }).then(_context2 => {
346
- instancesDiv.appendChild(renderCreationControl(instancesDiv))
347
- /* // keep this code in case we need a form
348
- const InstancesForm = ns.wf('TrackerInstancesForm')
349
- const text = trackerInstancesFormText
350
- $rdf.parse(text, kb, InstancesForm.doc().uri, 'text/turtle')
351
- widgets.appendForm(dom, instancesDiv, {}, tracker, InstancesForm,
352
- tracker.doc(), complainIfBad)
353
- */
354
- })
355
- return instancesDiv
356
- }
357
- function renderSettings (tracker) {
358
- const settingsDiv = dom.createElement('div')
359
- settingsDiv.appendChild(csvButton(dom, tracker)) // Button to copy the tracker as a CSV file
360
- const states = kb.any(tracker, ns.wf('issueClass'))
361
- const views = [tableView, states] // Possible default views
362
- .concat(kb.each(tracker, ns.wf('issueCategory')))
363
- const box = settingsDiv.appendChild(dom.createElement('div'))
364
- const lhs = widgets.renderNameValuePair(dom, kb, box, null, 'Default view') // @@ use a predicate?
365
- lhs.appendChild(widgets.makeSelectForOptions(dom, kb, tracker,
366
- ns.wf('defaultView'),
367
- views, {}, tracker.doc()))
368
-
369
- // A registration control allows the to record this tracker in their type index
370
- const context = { dom, div: settingsDiv, noun: 'tracker' }
371
- login.registrationControl(context, tracker, ns.wf('Tracker')).then(_context2 => {
372
- const settingsForm = ns.wf('TrackerSettingsForm')
373
- const text = trackerSettingsFormText
374
- $rdf.parse(text, kb, settingsForm.doc().uri, 'text/turtle')
375
- widgets.appendForm(dom, settingsDiv, {}, tracker, settingsForm,
376
- tracker.doc(), complainIfBad)
377
- })
378
- return settingsDiv
379
- }
380
-
381
- function renderTabsTableAndBoard () {
382
- function renderMain (ele, object) {
383
- ele.innerHTML = '' // Clear out "loading message"
384
- if (object.sameTerm(boardView)) {
385
- ele.appendChild(renderBoard(tracker))
386
- } else if (object.sameTerm(tableView)) {
387
- ele.appendChild(renderTable(tracker))
388
- } else if (object.sameTerm(settingsView)) {
389
- ele.appendChild(renderSettings(tracker))
390
- } else if (object.sameTerm(instancesView)) {
391
- ele.appendChild(renderInstances(ns.wf('Tracker')))
392
- } else if ((kb.holds(tracker, ns.wf('issueCategory'), object)) ||
393
- (kb.holds(tracker, ns.wf('issueClass'), object))) {
394
- ele.appendChild(renderBoard(tracker, object))
395
- } else {
396
- throw new Error('Unexpected tab type: ' + object)
397
- }
398
- }
399
- const states = kb.any(tracker, ns.wf('issueClass'))
400
- const items = [instancesView, tableView, states]
401
- .concat(kb.each(tracker, ns.wf('issueCategory')))
402
- items.push(settingsView)
403
- const selectedTab = kb.any(tracker, ns.wf('defaultView'), null, tracker.doc()) || tableView
404
- const options = { renderMain, items, selectedTab }
405
-
406
- // Add stuff to the ontologies which we believe but they don't say
407
- const doc = instancesView.doc()
408
- kb.add(instancesView, ns.rdfs('label'), 'My Trackers', doc) // @@ squatting on wf ns
409
- kb.add(settingsView, ns.rdfs('label'), 'Settings', doc) // @@ squatting on wf ns
410
- kb.add(states, ns.rdfs('label'), 'By State', doc) // @@ squatting on wf ns
411
-
412
- const myTabs = tabs.tabWidget(options)
413
- return myTabs
414
- }
415
-
416
- async function renderSingleIssue () {
417
- tracker = kb.any(subject, ns.wf('tracker'))
418
- if (!tracker) throw new Error('This issue ' + subject + 'has no tracker')
419
-
420
- // Much data is in the tracker instance, so wait for the data from it
421
- try {
422
- const _xhrs = await context.session.store.fetcher.load(tracker.doc())
423
- } catch (err) {
424
- const msg = 'Failed to load tracker config ' + tracker.doc() + ': ' + err
425
- return complain(msg)
426
- }
427
-
428
- const stateStore = kb.any(tracker, ns.wf('stateStore'))
429
- if (!stateStore) {
430
- return complain('Tracker has no state store: ' + tracker)
431
- }
432
- try {
433
- await context.session.store.fetcher.load(subject)
434
- } catch (err) {
435
- return complain('Failed to load issue state ' + stateStore + ': ' + err)
436
- }
437
- paneDiv.appendChild(renderIssue(subject, context))
438
- updater.addDownstreamChangeListener(stateStore, function () {
439
- widgets.refreshTree(paneDiv)
440
- }) // Live update
441
- }
442
-
443
- async function renderTracker () {
444
- function showNewIssue (issue) {
445
- widgets.refreshTree(paneDiv)
446
- exposeOverlay(issue, context)
447
- newIssueButton.disabled = false // https://stackoverflow.com/questions/41176582/enable-disable-a-button-in-pure-javascript
448
- }
449
- tracker = subject
450
-
451
- try {
452
- await fixSubClasses(kb, tracker)
453
- } catch (err) {
454
- console.log('@@@ Error fixing subclasses in config: ' + err)
455
- }
456
-
457
- const states = kb.any(subject, ns.wf('issueClass'))
458
- if (!states) throw new Error('This tracker has no issueClass')
459
- const stateStore = kb.any(subject, ns.wf('stateStore'))
460
- if (!stateStore) throw new Error('This tracker has no stateStore')
461
-
462
- // const me = await authn.currentUser()
463
-
464
- const h = dom.createElement('h2')
465
- h.setAttribute('style', 'font-size: 150%')
466
- paneDiv.appendChild(h)
467
- const classLabel = utils.label(states)
468
- h.appendChild(dom.createTextNode(classLabel + ' list')) // Use class label @@I18n
469
-
470
- // New Issue button
471
- const newIssueButton = dom.createElement('button')
472
- const container = dom.createElement('div')
473
- newIssueButton.setAttribute('type', 'button')
474
- newIssueButton.setAttribute('style', 'padding: 0.3em; font-size: 100%; margin: 0.5em;')
475
- container.appendChild(newIssueButton)
476
- paneDiv.appendChild(container)
477
- const img = dom.createElement('img')
478
- img.setAttribute('src', icons.iconBase + 'noun_19460_green.svg')
479
- img.setAttribute('style', 'width: 1em; height: 1em; margin: 0.2em;')
480
- newIssueButton.appendChild(img)
481
- const span = dom.createElement('span')
482
- span.innerHTML = 'New ' + classLabel
483
- newIssueButton.appendChild(span)
484
- newIssueButton.addEventListener(
485
- 'click',
486
- function (_event) {
487
- newIssueButton.disabled = true
488
- container.appendChild(newIssueForm(dom, kb, tracker, null, showNewIssue))
489
- },
490
- false
491
- )
492
-
493
- // Table of issues - when we have the main issue list
494
- // We also need the ontology loaded
495
- //
496
- context.session.store.fetcher
497
- .load([stateStore])
498
- .then(function (_xhrs) {
499
- const tableDiv = renderTabsTableAndBoard(tracker)
500
- // const tableDiv = renderTable(tracker) // was
501
- paneDiv.appendChild(tableDiv)
502
-
503
- if (tableDiv.refresh) {
504
- // Refresh function
505
- } else {
506
- console.log('No table refresh function?!')
507
- }
508
- paneDiv.appendChild(newTrackerButton(subject, context))
509
- updater.addDownstreamChangeListener(stateStore, tableDiv.refresh) // Live update
510
- })
511
- .catch(function (err) {
512
- return console.log('Cannot load state store: ' + err)
513
- })
514
- // end of Tracker instance
515
- } // render tracker
516
-
517
- /* Render tabs with both views
518
- */
519
- const boardView = ns.wf('BoardView')
520
- const tableView = ns.wf('TableView')
521
- const settingsView = ns.wf('SettingsView')
522
- const instancesView = ns.wf('InstancesView')
523
-
524
- const updater = kb.updater
525
- const t = kb.findTypeURIs(subject)
526
- let tracker
527
-
528
- // Whatever we are rendering, lets load the ontology
529
- const flowOntology = ns.wf('').doc()
530
- if (!kb.holds(undefined, undefined, undefined, flowOntology)) {
531
- // If not loaded already
532
- $rdf.parse(require('./wf.js'), kb, flowOntology.uri, 'text/turtle') // Load ontology directly
533
- }
534
- const userInterfaceOntology = ns.ui('').doc()
535
- if (!kb.holds(undefined, undefined, undefined, userInterfaceOntology)) {
536
- // If not loaded already
537
- $rdf.parse(require('./ui.js'), kb, userInterfaceOntology.uri, 'text/turtle') // Load ontology directly
538
- }
539
-
540
- // Render a single issue
541
- if (
542
- t['http://www.w3.org/2005/01/wf/flow#Task'] ||
543
- kb.holds(subject, ns.wf('tracker'))
544
- ) {
545
- renderSingleIssue().then(() => console.log('Single issue rendered'))
546
- } else if (t['http://www.w3.org/2005/01/wf/flow#Tracker']) {
547
- // Render a Tracker instance
548
- renderTracker().then(() => console.log('Tracker rendered'))
549
- } else {
550
- console.log(
551
- 'Error: Issue pane: No evidence that ' +
552
- subject +
553
- ' is either a bug or a tracker.'
554
- )
555
- }
556
-
557
- let loginOutButton
558
- const overlay = paneDiv.appendChild(dom.createElement('div'))
559
- context.overlay = overlay
560
- overlay.style = OVERFLOW_STYLE
561
- overlay.style.visibility = 'hidden'
562
-
563
- authn.checkUser().then(webId => {
564
- if (webId) {
565
- console.log('Web ID set already: ' + webId)
566
- context.me = webId
567
- // @@ enable things
568
- return
569
- }
570
-
571
- loginOutButton = login.loginStatusBox(dom, webIdUri => {
572
- authn.log
573
- if (webIdUri) {
574
- context.me = kb.sym(webIdUri)
575
- console.log('Web ID set from login button: ' + webIdUri)
576
- paneDiv.removeChild(loginOutButton)
577
- // enable things
578
- } else {
579
- context.me = null
580
- }
581
- })
582
-
583
- loginOutButton.setAttribute('style', 'margin: 0.5em 1em;')
584
- paneDiv.appendChild(loginOutButton)
585
- if (!context.statusArea) {
586
- context.statusArea = paneDiv.appendChild(dom.createElement('div'))
587
- }
588
- })
589
-
590
- return paneDiv
591
- }
592
- }
593
-
594
- // ends