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/.eslintrc +3 -2
- package/.github/workflows/ci.yml +0 -1
- package/.nvmrc +1 -1
- package/Documentation/Configuration.html +0 -0
- package/Documentation/Configuration.md +0 -0
- package/Documentation/FooTracker/chat.ttl +0 -0
- package/Documentation/FooTracker/index.ttl +0 -0
- package/Documentation/FooTracker/state.ttl +0 -0
- package/Documentation/Makefile +0 -0
- package/Documentation/github-markdown.css +0 -0
- package/LICENSE.md +0 -0
- package/Makefile +0 -0
- package/README.md +0 -0
- package/board.js +7 -8
- package/issue.js +117 -108
- package/issuePane.js +129 -145
- package/newIssue.js +18 -23
- package/newTracker.js +22 -21
- package/package.json +10 -10
- package/tbl-bug-22.png +0 -0
- package/trackerSettingsForm.js +0 -0
- package/trackerSettingsForm.ttl +0 -0
- package/ui.js +0 -0
- package/ui.ttl +0 -0
- package/wf.js +0 -0
- package/wf.ttl +0 -0
package/issuePane.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
**
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import
|
|
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 =
|
|
18
|
-
const
|
|
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:
|
|
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 =
|
|
38
|
+
const t = kb.findTypeURIs(subject)
|
|
40
39
|
if (
|
|
41
40
|
t['http://www.w3.org/2005/01/wf/flow#Task'] ||
|
|
42
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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(
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
|
|
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
|
-
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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 =
|
|
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 =
|
|
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 =>
|
|
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 =
|
|
202
|
-
const 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 ' +
|
|
198
|
+
// alert('Same state ' + utils.label(currentState)) // @@ remove
|
|
206
199
|
return
|
|
207
200
|
}
|
|
208
201
|
try {
|
|
209
|
-
await
|
|
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
|
-
|
|
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 =
|
|
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,
|
|
230
|
+
const refreshButton = widgets.button(dom, icons.iconBase + 'noun_479395.svg',
|
|
238
231
|
'refresh table', async _event => {
|
|
239
232
|
try {
|
|
240
|
-
await
|
|
233
|
+
await kb.fetcher.load(stateStore, { force: true, clearPreviousData: true })
|
|
241
234
|
} catch (err) {
|
|
242
235
|
alert(err)
|
|
243
236
|
return
|
|
244
237
|
}
|
|
245
|
-
|
|
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 =
|
|
257
|
-
const cats =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
290
|
+
const possible = kb.each(undefined, ns.rdfs('subClassOf'), states)
|
|
298
291
|
possible.forEach(function (s) {
|
|
299
292
|
if (
|
|
300
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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 ((
|
|
389
|
-
(
|
|
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 =
|
|
397
|
+
const states = kb.any(tracker, ns.wf('issueClass'))
|
|
396
398
|
const items = [instancesView, tableView, states]
|
|
397
|
-
.concat(
|
|
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
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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
|
|
409
|
-
return
|
|
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
|
-
|
|
443
|
+
widgets.refreshTree(paneDiv)
|
|
415
444
|
exposeOverlay(issue, context)
|
|
416
|
-
|
|
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(
|
|
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 =
|
|
455
|
+
const states = kb.any(subject, ns.wf('issueClass'))
|
|
427
456
|
if (!states) throw new Error('This tracker has no issueClass')
|
|
428
|
-
const 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
|
-
|
|
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 =
|
|
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
|
-
|
|
469
|
+
const newIssueButton = dom.createElement('button')
|
|
441
470
|
const container = dom.createElement('div')
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
container.appendChild(
|
|
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',
|
|
476
|
+
img.setAttribute('src', icons.iconBase + 'noun_19460_green.svg')
|
|
448
477
|
img.setAttribute('style', 'width: 1em; height: 1em; margin: 0.2em;')
|
|
449
|
-
|
|
478
|
+
newIssueButton.appendChild(img)
|
|
450
479
|
const span = dom.createElement('span')
|
|
451
480
|
span.innerHTML = 'New ' + classLabel
|
|
452
|
-
|
|
453
|
-
|
|
481
|
+
newIssueButton.appendChild(span)
|
|
482
|
+
newIssueButton.addEventListener(
|
|
454
483
|
'click',
|
|
455
484
|
function (_event) {
|
|
456
|
-
|
|
457
|
-
container.appendChild(newIssueForm(dom,
|
|
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 =
|
|
494
|
-
const t =
|
|
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 =
|
|
499
|
-
if (!
|
|
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'),
|
|
530
|
+
$rdf.parse(require('./wf.js'), kb, flowOntology.uri, 'text/turtle') // Load ontology directly
|
|
502
531
|
}
|
|
503
|
-
const userInterfaceOntology =
|
|
504
|
-
if (!
|
|
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'),
|
|
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
|
-
|
|
541
|
+
kb.holds(subject, ns.wf('tracker'))
|
|
513
542
|
) {
|
|
514
|
-
|
|
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 =
|
|
569
|
+
loginOutButton = authn.loginStatusBox(dom, webIdUri => {
|
|
586
570
|
if (webIdUri) {
|
|
587
|
-
context.me =
|
|
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
|
|
3
|
+
import { ns, rdf, utils } from 'solid-ui'
|
|
4
4
|
|
|
5
|
-
const $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
|
-
|
|
38
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
for (
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
}
|