git ssb

0+

cel / ssb-issues



Commit 1e2d415297dc67684478280b7b309f1e3432d2e4

Add issue labels

cel committed on 5/23/2020, 9:23:28 PM
Parent: eb15fe70a933fb5906d227f9b4d88d570c179867

Files changed

README.mdchanged
index.jschanged
lib/schemas.jschanged
README.mdView
@@ -12,29 +12,50 @@
1212 {
1313 type: 'issue',
1414 project: Link?,
1515 title: string?,
16- text: string?
16 + text: string?,
17 + labels: [LabelRef]?
1718 }
1819 ```
1920
2021 #### issue edits
2122
22-Edits to an issue may be done by any ssb message type. For example, you can
23-make a post that updates an issue, or push a git commit that updates an issue.
24-If the message does not have any content other than to update the issue, then
25-the type may be `issue-edit`.
23 +Edits to an issue open/closed state may be done by ssb message type
24 +`issue-edit`, `post`, or `git-update`. For example, you can make a post that
25 +updates an issue, or push a git commit that updates an issue. Other issue
26 +edits should be done with message type `issue-edit`.
2627
2728 ```js
2829 {
2930 type: 'issue-edit'|'post'|'git-update',
3031 issues: [{
31- link: IssueRef,
32- open: boolean,
32 + link: IssueRef,
33 + open: boolean?,
34 + labels: {
35 + add: [IssueRef]?,
36 + remove: [IssueRef]?,
37 + }?
3338 }]
3439 }
3540 ```
3641
42 +#### issue labels
43 +
44 +An issue label represents a tag that can be applied to issues in a repo/project.
45 +It can be renamed using `about` messages. Issue labels can be added to or removed from issues using `issue-edit` messages.
46 +
47 +```js
48 +{
49 + type: 'issue-label',
50 + project: Link?,
51 + name: string?,
52 + issues: [issueRef]?
53 +}
54 +```
55 +
56 +- `issues`: initial set of issues to add the label to
57 +
3758 ## API
3859
3960 ```js
4061 var Issues = require('ssb-issues')
@@ -60,8 +81,9 @@
6081 created_at: number,
6182 updated_at: number,
6283 open: boolean,
6384 msg: Msg,
85 + labels: MsgRefs
6486 }
6587 ```
6688
6789 - `id`: id of the issue
@@ -73,8 +95,9 @@
7395 - `project`: the project that the issue is for
7496 - `projectAuthor`: the author of the project
7597 - `msg`: ssb message object that created the issue (with
7698 `.key` and `.value`).
99 +- `labels`: ids of issue-labels associated with the issue
77100
78101 #### list: source
79102
80103 Get a stream of issues
@@ -186,14 +209,24 @@
186209 - `project` (Ref): id of project to associate the issue with
187210 - `title` (string): title to give the issue (deprecated)
188211 - `text` (string): text body for the issue
189212
213 +#### `issueSchemas.newLabel(project, name, issues)`
214 +
215 +Create a new issue label.
216 +
217 +- `project` (Ref): id of project to associate the issue/label with
218 +- `name` (string): name to give the issue (optional)
219 +- `issues` (IssueRefs): ids of issues to add the label to
220 +
190221 #### `issueSchemas.edit(id, opts)`
191222
192223 Edit an issue.
193224
194225 - `opts.open` (boolean): open or close the issue
195226 - `opts.title` (string): set the title of the issue (deprecated)
227 +- `opts.addLabels` (LabelRefs): ids of labels to add to issue
228 +- `opts.removeLabels` (LabelRefs): ids of labels to remove from issue
196229
197230 #### `issueSchemas.close(id)`
198231
199232 Close an issue.
index.jsView
@@ -95,11 +95,32 @@
9595 var ssbGet = asyncMemo(ssb.get)
9696 var liveStreams = []
9797
9898 var getIssue = asyncMemo(function (id, cb) {
99- var issue = {}
99 + var issue = {
100 + labels: []
101 + }
102 + var labelCounts = {}
100103 var issueMsg
101104
105 + function addLabel(id) {
106 + var count = labelCounts[id] || 0
107 + labelCounts[id] = ++count
108 + if (count === 1) {
109 + var i = issue.labels.indexOf(id)
110 + if (i === -1) issue.labels.push(id)
111 + }
112 + }
113 +
114 + function removeLabel(id) {
115 + var count = labelCounts[id] || 0
116 + labelCounts[id] = --count
117 + if (count === 0) {
118 + var i = issue.labels.indexOf(id)
119 + if (i > -1) issue.labels.splice(i, 1)
120 + }
121 + }
122 +
102123 ssbGet(id, function (err, msg) {
103124 msg = {key: id, value: msg}
104125 if (err) return cb(err)
105126 issueMsg = msg
@@ -109,8 +130,9 @@
109130 var c = msg.value.content
110131 issue.project = c.project
111132 issue.text = c.text || c.title || JSON.stringify(msg, null, 2)
112133 issue.created_at = issue.updated_at = msg.value.timestamp
134 + if (Array.isArray(c.labels)) c.labels.forEach(addLabel)
113135 if (c.project)
114136 ssbGet(c.project, gotProjectMsg)
115137 else
116138 getLinks()
@@ -150,20 +172,31 @@
150172 if (c.open != null && issue.open == null)
151173 issue.open = c.open
152174 if (c.title != null && issue.title == null)
153175 issue.title = c.title
176 + if (c.labels) {
177 + if (Array.isArray(c.labels.add))
178 + c.labels.add.forEach(addLabel)
179 + if (Array.isArray(c.labels.remove))
180 + c.labels.remove.forEach(removeLabel)
181 + }
154182 if (msg.value.timestamp > issue.updated_at)
155183 issue.updated_at = msg.value.timestamp
156184 }
157185
158186 // handle updates via mention
159187 if (c.issues) {
160- for (var i = 0; i < c.issues.length; i++)
161- onOldMsg({value: {
162- timestamp: msg.value.timestamp,
163- author: msg.value.author,
164- content: c.issues[i]
165- }})
188 + for (var i = 0; i < c.issues.length; i++) {
189 + if (c.type === 'issue-label') {
190 + if (c.issues[i] === id) addLabel(msg.key)
191 + } else {
192 + onOldMsg({value: {
193 + timestamp: msg.value.timestamp,
194 + author: msg.value.author,
195 + content: c.issues[i]
196 + }})
197 + }
198 + }
166199 }
167200
168201 checkReady()
169202 }
@@ -180,8 +213,14 @@
180213 if (c.title != null)
181214 issue.title = c.title
182215 if (msg.value.timestamp > issue.updated_at)
183216 issue.updated_at = msg.value.timestamp
217 + if (c.labels) {
218 + if (Array.isArray(c.labels.add))
219 + c.labels.add.forEach(addLabel)
220 + if (Array.isArray(c.labels.remove))
221 + c.labels.remove.forEach(removeLabel)
222 + }
184223 }
185224
186225 // handle updates via mention
187226 if (c.issues) {
lib/schemas.jsView
@@ -23,8 +23,28 @@
2323 }
2424 return msg
2525 }
2626
27 +exports.newLabel = function (project, name, issues) {
28 + if (!ssbRef.isLink(project))
29 + throw new Error('invalid project id')
30 +
31 + var msg = { type: 'issue-label', project: project }
32 + if (name) {
33 + if (typeof name === 'string')
34 + msg.name = name
35 + else
36 + throw new Error('invalid issue label name')
37 + }
38 + if (issues) {
39 + if (Array.isArray(issues) && issues.every(ssbRef.isMsg))
40 + msg.issues = issues
41 + else
42 + throw new Error('invalid issues list')
43 + }
44 + return msg
45 +}
46 +
2747 exports.edit = function (id, opts) {
2848 if (!ssbRef.isMsg(id))
2949 throw new Error('invalid issue id')
3050 var msg = {
@@ -32,12 +52,30 @@
3252 issues: [{
3353 link: id
3454 }]
3555 }
56 + var labels = {}
3657 if (opts.open != null)
3758 msg.issues[0].open = opts.open
3859 if (opts.title != null)
3960 msg.issues[0].title = opts.title
61 + if (opts.addLabels != null) {
62 + if (Array.isArray(opts.addLabels) && opts.addLabels.every(ssbRef.isMsg)) {
63 + msg.issues[0].labels = labels
64 + labels.add = opts.addLabels
65 + } else {
66 + throw new Error('invalid addLabels')
67 + }
68 + }
69 + if (opts.removeLabels != null) {
70 + if (Array.isArray(opts.removeLabels)
71 + && opts.removeLabels.every(ssbRef.isMsg)) {
72 + msg.issues[0].labels = labels
73 + labels.remove = opts.removeLabels
74 + } else {
75 + throw new Error('invalid removeLabels')
76 + }
77 + }
4078 return msg
4179 }
4280
4381 exports.close = function (id) {

Built with git-ssb-web