git ssb

0+

ev / microbay



forked from Dominic / patchbay

Commit 07376795ee2a1eb1ec1c2ae45fe872324b1edeea

Merge branch 'git'

Dominic Tarr committed on 8/4/2016, 4:34:29 AM
Parent: a7f84536ea1fe89fd65608f797f7caf6c4ef1c6c
Parent: eef541ee269f9363a161964af9193734d505418e

Files changed

modules/git.jschanged
modules/message.jschanged
modules/notifications.jschanged
style.csschanged
modules/git.jsView
@@ -4,8 +4,9 @@
44 var human = require('human-time')
55
66 var plugs = require('../plugs')
77 var message_link = plugs.first(exports.message_link = [])
8+var message_confirm = plugs.first(exports.message_confirm = [])
89 var sbot_links = plugs.first(exports.sbot_links = [])
910 var sbot_links2 = plugs.first(exports.sbot_links2 = [])
1011 var sbot_get = plugs.first(exports.sbot_get = [])
1112 var getAvatar = require('ssb-avatar')
@@ -28,48 +29,37 @@
2829 }
2930
3031 function getIssueState(id, cb) {
3132 pull(
32- sbot_links({dest: id, rel: 'issues', values: true}),
33+ sbot_links({dest: id, rel: 'issues', values: true, reverse: true}),
3334 pull.map(function (msg) {
34- var issues = msg.value.content.issues
35- if (!Array.isArray(issues)) return
36- return issues.filter(function (issue) {
37- return issue.link === id
38- }).map(function (issue) {
39- return {
40- ts: msg.value.timestamp,
41- open: issue.open,
42- merged: issue.merged,
43- }
44- })
35+ return msg.value.content.issues
4536 }),
4637 pull.flatten(),
38+ pull.filter(function (issue) {
39+ return issue.link === id
40+ }),
41+ pull.map(function (issue) {
42+ return issue.merged ? 'merged' : issue.open ? 'open' : 'closed'
43+ }),
44+ pull.take(1),
4745 pull.collect(function (err, updates) {
48- if (err) return cb(err)
49- var open = true, merged = false
50- updates.sort(function (a, b) {
51- return b.ts - a.ts
52- }).forEach(function (update) {
53- if (update.open != null)
54- open = update.open
55- if (update.merged != null)
56- merged = update.merged
57- })
58- cb(null, open ? 'open' : merged ? 'merged' : 'closed')
46+ cb(err, updates && updates[0] || 'open')
5947 })
6048 )
6149 }
6250
6351 //todo:
6452 function messageTimestampLink(msg) {
53+ var date = new Date(msg.value.timestamp)
6554 return h('a.timestamp', {
6655 timestamp: msg.value.timestamp,
67- title: new Date(msg.value.timestamp),
56+ title: date,
6857 href: '#'+msg.key
69- }, human(msg.value.timestamp))
58+ }, human(date))
7059 }
7160
61+// a thead+tbody where the thead only is added when the first row is added
7262 function tableRows(headerRow) {
7363 var thead = h('thead'), tbody = h('tbody')
7464 var first = true
7565 var t = [thead, tbody]
@@ -93,14 +83,23 @@
9383 })
9484 return el
9585 }
9686
87+function renderIssueEdit(c) {
88+ var id = c.issue || c.link
89+ return [
90+ c.title ? h('p', 'renamed issue ', message_link(id),
91+ ' to ', h('ins', c.title)) : null,
92+ c.open === false ? h('p', 'closed issue ', message_link(id)) : null,
93+ c.open === true ? h('p', 'reopened issue ', message_link(id)) : null]
94+}
95+
9796 exports.message_content = function (msg, sbot) {
9897 var c = msg.value.content
9998
10099 if(c.type === 'git-repo') {
101- var nameEl
102100 var branchesT, tagsT, openIssuesT, closedIssuesT, openPRsT, closedPRsT
101+ var forksT
103102 var div = h('div',
104103 h('p', 'git repo ', repoName(msg.key)),
105104 c.upstream ? h('p', 'fork of ', repoName(c.upstream, true)) : '',
106105 h('p', h('code', 'ssb://' + msg.key)),
@@ -124,9 +123,13 @@
124123 h('table',
125124 openPRsT = tableRows(h('tr',
126125 h('th', 'open pull requests'))),
127126 closedPRsT = tableRows(h('tr',
128- h('th', 'closed pull requests'))))))
127+ h('th', 'closed pull requests'))))),
128+ h('div.git-table-wrapper',
129+ h('table',
130+ forksT = tableRows(h('tr',
131+ h('th', 'forks'))))))
129132
130133 // compute refs
131134 var refs = {}
132135 pull(
@@ -137,23 +140,23 @@
137140 rel: 'repo',
138141 values: true
139142 }),
140143 pull.drain(function (link) {
141- var refUpdates = link.value.content.refs
142- for (var ref in refUpdates) {
143- if (refs[ref]) continue
144+ var refUpdates = link.value.content.refs || {}
145+ Object.keys(refUpdates).reverse().filter(function (ref) {
146+ if (refs[ref]) return
144147 refs[ref] = true
145148 var rev = refUpdates[ref]
146- if (!rev) continue
149+ if (!rev) return
147150 var parts = /^refs\/(heads|tags)\/(.*)$/.exec(ref) || []
148151 var t
149152 if (parts[1] === 'heads') t = branchesT
150153 else if (parts[1] === 'tags') t = tagsT
151154 if (t) t.append(h('tr',
152155 h('td', parts[2]),
153156 h('td', h('code', rev)),
154157 h('td', messageTimestampLink(link))))
155- }
158+ })
156159 }, function (err) {
157160 if (err) console.error(err)
158161 })
159162 )
@@ -174,11 +177,10 @@
174177 })
175178 }),
176179 pull.drain(function (link) {
177180 var c = link.value.content
178- // TODO: support renamed issues
179- var title = c.title || (c.text ? c.text.length > 30
180- ? c.text.substr(0, 30) + '…'
181+ var title = c.title || (c.text ? c.text.length > 70
182+ ? c.text.substr(0, 70) + '…'
181183 : c.text : link.key)
182184 var author = link.value.author
183185 var t = c.type === 'pull-request'
184186 ? link.state === 'open' ? openPRsT : closedPRsT
@@ -193,8 +195,24 @@
193195 if (err) console.error(err)
194196 })
195197 )
196198
199+ // list forks
200+ pull(
201+ sbot_links({
202+ reverse: true,
203+ dest: msg.key,
204+ rel: 'upstream'
205+ }),
206+ pull.drain(function (link) {
207+ forksT.append(h('tr', h('td',
208+ repoName(link.key, true),
209+ ' by ', h('a', {href: '#'+link.source}, avatar_name(link.source)))))
210+ }, function (err) {
211+ if (err) console.error(err)
212+ })
213+ )
214+
197215 return div
198216 }
199217
200218 if(c.type === 'git-update') {
@@ -217,17 +235,23 @@
217235 }) : null
218236 )
219237 }
220238
221- if (c.type === 'issue') {
239+ if(c.type === 'issue-edit') {
222240 return h('div',
241+ c.issue ? renderIssueEdit(c) : null,
242+ c.issues ? c.issues.map(renderIssueEdit) : null)
243+ }
244+
245+ if(c.type === 'issue') {
246+ return h('div',
223247 h('p', 'opened issue on ', repoLink(c.project)),
224248 c.title ? h('h4', c.title) : '',
225249 markdown(c)
226250 )
227251 }
228252
229- if (c.type === 'pull-request') {
253+ if(c.type === 'pull-request') {
230254 return h('div',
231255 h('p', 'opened pull-request ',
232256 'to ', repoLink(c.repo), ':', c.branch, ' ',
233257 'from ', repoLink(c.head_repo), ':', c.head_branch),
@@ -238,15 +262,48 @@
238262 }
239263
240264 exports.message_meta = function (msg, sbot) {
241265 var type = msg.value.content.type
242- if (type == 'issue' || type == 'pull-request') {
266+ if (type === 'issue' || type === 'pull-request') {
243267 var el = h('em', '...')
268+ // TODO: update if issue is changed
244269 getIssueState(msg.key, function (err, state) {
245270 if (err) return console.error(err)
246271 el.textContent = state
247272 })
248273 return el
249274 }
250275 }
251276
277+exports.message_action = function (msg, sbot) {
278+ var c = msg.value.content
279+ if(c.type === 'issue' || c.type === 'pull-request') {
280+ var isOpen
281+ var a = h('a', {href: '#', onclick: function () {
282+ message_confirm({
283+ type: 'issue-edit',
284+ root: msg.key,
285+ issues: [{
286+ link: msg.key,
287+ open: !isOpen
288+ }]
289+ }, function (err, msg) {
290+ if(err) return alert(err)
291+ if(!msg) return
292+ isOpen = msg.value.content.open
293+ update()
294+ })
295+ }})
296+ getIssueState(msg.key, function (err, state) {
297+ if (err) return console.error(err)
298+ isOpen = state === 'open'
299+ update()
300+ })
301+ function update() {
302+ a.textContent = c.type === 'pull-request'
303+ ? isOpen ? 'Close Pull Request' : 'Reopen Pull Request'
304+ : isOpen ? 'Close Issue' : 'Reopen Issue'
305+ }
306+ return a
307+ }
308+}
252309
modules/message.jsView
@@ -37,9 +37,9 @@
3737 h('div.message_meta.row', message_meta(msg))
3838 ),
3939 h('div.message_content', el),
4040 h('div.message_actions.row',
41- h('div.actions', message_action(msg), ' ',
41+ h('div.actions', message_action(msg),
4242 h('a', {href: '#' + msg.key}, 'Reply')
4343 )
4444 ),
4545 backlinks,
modules/notifications.jsView
@@ -28,15 +28,30 @@
2828 return link && link.link in ourIds
2929 }
3030
3131 function isOurMsg(id, cb) {
32+ if (!id) return cb(null, false)
33+ if (typeof id === 'object' && typeof id.link === 'string') id = id.link
3234 sbot_get(id, function (err, msg) {
3335 if (err && err.name == 'NotFoundError') cb(null, false)
3436 else if (err) cb(err)
37+ else if (msg.content.type === 'issue' || msg.content.type === 'pull-request')
38+ isOurMsg(msg.content.repo || msg.content.project, cb)
3539 else cb(err, msg.author in ourIds)
3640 })
3741 }
3842
43+ function isAnyOurMessage(msg, ids, cb) {
44+ cont.para(ids.map(function (id) {
45+ return function (cb) { isOurMsg(id, cb) }
46+ }))
47+ (function (err, results) {
48+ if (err) cb(err)
49+ else if (results.some(Boolean)) cb(null, msg)
50+ else cb()
51+ })
52+ }
53+
3954 return paramap(function (msg, cb) {
4055 var c = msg.value && msg.value.content
4156 if (!c || typeof c !== 'object') return cb()
4257 if (msg.value.author in ourIds) return cb()
@@ -49,16 +64,9 @@
4964
5065 switch (c.type) {
5166 case 'post':
5267 if (c.branch || c.root)
53- cont.para([].concat(c.branch, c.root).map(function (id) {
54- return function (cb) { isOurMsg(id, cb) }
55- }))
56- (function (err, results) {
57- if (err) cb(err)
58- else if (results.some(Boolean)) cb(null, msg)
59- else cb()
60- })
68+ return isAnyOurMessage(msg, [].concat(c.branch, c.root), cb)
6169 else return cb()
6270
6371 case 'contact':
6472 return cb(null, c.contact in ourIds ? msg : null)
@@ -69,8 +77,17 @@
6977 cb(err, isOurs ? msg : null)
7078 })
7179 else return cb()
7280
81+ case 'issue':
82+ case 'pull-request':
83+ return isOurMsg(c.project || c.repo, function (err, isOurs) {
84+ cb(err, isOurs ? msg : null)
85+ })
86+
87+ case 'issue-edit':
88+ return isAnyOurMessage(msg, [c.issue].concat(c.issues), cb)
89+
7390 default:
7491 cb()
7592 }
7693 }, 4)
style.cssView
@@ -160,12 +160,15 @@
160160 .message_actions {
161161 float: right;
162162 }
163163
164-.dig {
164+.actions > * {
165+ padding-left: 5px;
166+ margin-left: 1px;
167+}
168+.actions > :not(:last-child) {
165169 border-right: 2px solid #eee;
166- padding-right: .6ex;
167- margin-right: .1ex;
170+ padding-right: 5px;
168171 }
169172
170173 .message > .title > .avatar {
171174 margin-left: 0;

Built with git-ssb-web