issue-pane 2.4.20-9a4e6f86 → 2.4.20-c8b693ad

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/Makefile CHANGED
@@ -1,6 +1,8 @@
1
1
  # Wrap TTL files into JS files for bundling with library
2
2
 
3
- ,all : wf.js trackerSettingsForm.js trackerInstancesForm.js ui.js
3
+ # unused: trackerInstancesForm.js
4
+
5
+ ,all : wf.js trackerSettingsForm.js ui.js
4
6
 
5
7
  #individualForm.js : individualForm.ttl
6
8
  # (echo 'module.exports = `' ; cat individualForm.ttl; echo '`') > individualForm.js
package/csvButton.js ADDED
@@ -0,0 +1,98 @@
1
+ // A Button to copy the state of the tracker in CSV format
2
+ // Comma-separated Values
3
+ //
4
+ // Yes this mixes the layers but that is not all bad if it gets it in one file
5
+ // one can look at
6
+
7
+ import { icons, ns, utils, widgets } from 'solid-ui'
8
+ import { store } from 'solid-logic'
9
+
10
+ export function csvText(store, tracker) {
11
+ function encode(value) {
12
+ // https://www.rfc-editor.org/rfc/rfc4180
13
+ const stripped = value.replace('\n', ' ')
14
+ if (!stripped.contains(',')) {
15
+ return stripped
16
+ } // If contains comma then put in quotes and double up internal quotes
17
+ return '"' + stripped.replace('"', '""') + '"'
18
+ }
19
+
20
+ function columnText(task, column) {
21
+ let thing
22
+ if (column.predicate) {
23
+ thing = store.any(task, column.predicate)
24
+ }
25
+ else if (column.category) {
26
+ const types = store.each(task, ns.rdf('type'))
27
+ for (const t of types) {
28
+ if (store.holds(t, ns.rdfs('subClassOf'), column.category)){
29
+ thing = t
30
+ }
31
+ }
32
+ if (!thing) throw new Error('wot no category', column.category)
33
+ } else {
34
+ throw new Error('wot no pred or cat', column)
35
+ }
36
+ return utils.label(thing)
37
+ }
38
+
39
+ function taskLine(task) {
40
+ return columns.map(column => columnText(task, column))
41
+ .map(encode)
42
+ .join(',')
43
+ + '/n'
44
+ }
45
+ const stateStore = store.any(tracker, ns.wf('stateStore'))
46
+ const tasks = store.any(null, ns.wf('tracker'), tracker, stateStore)
47
+
48
+ let columns = [
49
+ /* like:
50
+ { label: 'Name', predicate: ns.dct('title') },
51
+ { label: 'State', category: ns.wf('Task') }
52
+ */
53
+ ]
54
+ const states = store.any(tracker, ns.wf('issueClass')) // Main states are subclasses of this class
55
+ const categories = store.each(tracker, ns.wf('issueCategory')) | []
56
+ const classifications = [states ] + categories
57
+ for (const c in classifications){
58
+ const column = { label: utils.label(c), category: c}
59
+ console.log(' CSV: found column from classifications', column)
60
+ columns.append(column) // Classes are different
61
+ }
62
+
63
+ // const propertyList = ns.wf('propertyList')
64
+ const form = store.any(tracker, ns.wf('extrasEntryForm'), null, tracker.doc())
65
+ if (form) {
66
+ const parts = store.any(form, ns.ui('parts'), null, form.doc())
67
+ const fields = parts.elements
68
+ for (const field of fields) {
69
+ const prop = store.any(field,ns.ui('property'))
70
+ const lab = utils.label(prop)
71
+ const column = {label: lab, predicate: prop}
72
+ console.log(' CSV: found column from form', column)
73
+ columns.append(column)
74
+ }
75
+ }
76
+ const header = columns.map(col => col.label).join(',') + '\n'
77
+ // Order tasks?? By Creation date? By Status?
78
+ const body = tasks.map(taskLine)
79
+ return header + body
80
+ }
81
+
82
+ export function csvButton (dom, tracker) {
83
+ const wrapper = dom.createElement('div')
84
+ // Add a button
85
+ const button = widgets.button(dom, icons.iconBase + 'noun_479395.svg',
86
+ 'Copy as CSV', async _event => {
87
+ const csv = csvText(store, tracker)
88
+ var copyEvent = new ClipboardEvent('copy');
89
+ copyEvent.clipboardData.items.add(csv, 'text/csv');
90
+ copyEvent.clipboardData.items.add(csv, 'text/plain');
91
+ dom.dispatchEvent(copyEvent);
92
+ alert('Copy dispatched.')
93
+ })
94
+
95
+ wrapper.appendChild(button)
96
+ return wrapper
97
+ }
98
+
package/issuePane.js CHANGED
@@ -1,4 +1,4 @@
1
- /* Issue Tracker Pane
1
+ /* Issue Tracker Pane
2
2
  **
3
3
  ** This solid view allows a user to interact with an issue tracker, or individual issue,
4
4
  ** to change its state according to an ontology, comment on it, etc.
@@ -11,6 +11,7 @@ import { board } from './board' // @@ will later be in solid-UI
11
11
  import { renderIssue, renderIssueCard, getState, exposeOverlay } from './issue'
12
12
  import { newTrackerButton } from './newTracker'
13
13
  import { newIssueForm } from './newIssue'
14
+ import { csvButton } from './csvButton'
14
15
  import { trackerSettingsFormText } from './trackerSettingsForm.js'
15
16
  // import { trackerInstancesFormText } from './trackerInstancesForm.js'
16
17
 
@@ -355,6 +356,7 @@ export default {
355
356
  }
356
357
  function renderSettings (tracker) {
357
358
  const settingsDiv = dom.createElement('div')
359
+ settingsDiv.appendChild(csvButton(dom, tracker)) // Button to copy the tracker as a CSV file
358
360
  const states = kb.any(tracker, ns.wf('issueClass'))
359
361
  const views = [tableView, states] // Possible default views
360
362
  .concat(kb.each(tracker, ns.wf('issueCategory')))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "issue-pane",
3
- "version": "2.4.20-9a4e6f86",
3
+ "version": "2.4.20-c8b693ad",
4
4
  "description": "Solid-compatible Panes: issue editor",
5
5
  "main": "./issuePane.js",
6
6
  "scripts": {