issue-pane 2.4.10 → 2.4.11-b4735355

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