git ssb

16+

Dominic / patchbay



Commit 6bd94bf8ab683004a0730dbb0b860ef5e8cd28a1

Show git issues and pull requests

- Refactor table rendering
- Get repo names from about messages
- Lists issues and pull requests on git-repo message
- Render issue and pull-request messages
Charles Lehner committed on 7/24/2016, 3:46:54 PM
Parent: 627bb1ceef39b5cccd4915b82591d2b085d4716e

Files changed

modules/git.jschanged
style.csschanged
modules/git.jsView
@@ -8,8 +8,10 @@
88 var sbot_links = plugs.first(exports.sbot_links = [])
99 var sbot_links2 = plugs.first(exports.sbot_links2 = [])
1010 var sbot_get = plugs.first(exports.sbot_get = [])
1111 var getAvatar = require('ssb-avatar')
12+var avatar_name = plugs.first(exports.avatar_name = [])
13+var markdown = plugs.first(exports.markdown = [])
1214
1315 var self_id = require('../keys').id
1416
1517 function shortRefName(ref) {
@@ -57,28 +59,77 @@
5759 })
5860 )
5961 }
6062
63+function messageTimestampLink(msg) {
64+ var m = moment(msg.value.timestamp)
65+ return h('a.timestamp', {
66+ timestamp: m,
67+ title: m.format('LLLL'),
68+ href: '#'+msg.key
69+ }, m.fromNow())
70+}
71+
72+function tableRows(headerRow) {
73+ var thead = h('thead'), tbody = h('tbody')
74+ var first = true
75+ var t = [thead, tbody]
76+ t.append = function (row) {
77+ if (first) {
78+ first = false
79+ thead.appendChild(headerRow)
80+ }
81+ tbody.appendChild(row)
82+ }
83+ return t
84+}
85+
86+function repoName(id, link) {
87+ var el = link
88+ ? h('a', {href: '#'+id}, id.substr(0, 8) + '…')
89+ : h('ins', id.substr(0, 8) + '…')
90+ getAvatar({links: sbot_links}, self_id, id, function (err, avatar) {
91+ if(err) return console.error(err)
92+ el.textContent = avatar.name
93+ })
94+ return el
95+}
96+
6197 exports.message_content = function (msg, sbot) {
6298 var c = msg.value.content
6399
64100 if(c.type === 'git-repo') {
65- var nameEl, refsTable
101+ var nameEl
102+ var branchesT, tagsT, openIssuesT, closedIssuesT, openPRsT, closedPRsT
66103 var div = h('div',
67- h('p', 'git repo ', nameEl = h('ins')),
104+ h('p', 'git repo ', repoName(msg.key)),
105+ c.upstream ? h('p', 'fork of ', repoName(c.upstream, true)) : '',
68106 h('p', h('code', 'ssb://' + msg.key)),
69- refsTable = h('table')
70- )
107+ h('div.git-table-wrapper', {style: {'max-height': '12em'}},
108+ h('table',
109+ branchesT = tableRows(h('tr',
110+ h('th', 'branch'),
111+ h('th', 'commit'),
112+ h('th', 'last update'))),
113+ tagsT = tableRows(h('tr',
114+ h('th', 'tag'),
115+ h('th', 'commit'),
116+ h('th', 'last update'))))),
117+ h('div.git-table-wrapper', {style: {'max-height': '16em'}},
118+ h('table',
119+ openIssuesT = tableRows(h('tr',
120+ h('th', 'open issues'))),
121+ closedIssuesT = tableRows(h('tr',
122+ h('th', 'closed issues'))))),
123+ h('div.git-table-wrapper', {style: {'max-height': '16em'}},
124+ h('table',
125+ openPRsT = tableRows(h('tr',
126+ h('th', 'open pull requests'))),
127+ closedPRsT = tableRows(h('tr',
128+ h('th', 'closed pull requests'))))))
71129
72- // show repo name
73- getAvatar({links: sbot_links}, self_id, msg.key, function (err, avatar) {
74- if(err) return console.error(err)
75- nameEl.textContent = avatar.name
76- })
77-
78130 // compute refs
79131 var refs = {}
80- var first = true
81132 pull(
82133 sbot_links({
83134 reverse: true,
84135 source: msg.value.author,
@@ -87,34 +138,63 @@
87138 values: true
88139 }),
89140 pull.drain(function (link) {
90141 var refUpdates = link.value.content.refs
91- if (first) {
92- first = false
93- refsTable.appendChild(h('tr',
94- h('th', 'branch'),
95- h('th', 'commit'),
96- h('th', 'last update')))
97- }
98142 for (var ref in refUpdates) {
99143 if (refs[ref]) continue
100144 refs[ref] = true
101145 var rev = refUpdates[ref]
102- var m = moment(link.value.timestamp)
103- refsTable.appendChild(h('tr',
104- h('td', shortRefName(ref)),
146+ if (!rev) continue
147+ var parts = /^refs\/(heads|tags)\/(.*)$/.exec(ref) || []
148+ var t
149+ if (parts[1] === 'heads') t = branchesT
150+ else if (parts[1] === 'tags') t = tagsT
151+ if (t) t.append(h('tr',
152+ h('td', parts[2]),
105153 h('td', h('code', rev)),
106- h('td', h('a.timestamp', {
107- timestamp: m,
108- title: m.format('LLLL'),
109- href: '#'+link.key
110- }, m.fromNow()))))
154+ h('td', messageTimestampLink(link))))
111155 }
112156 }, function (err) {
113157 if (err) console.error(err)
114158 })
115159 )
116160
161+ // list issues and pull requests
162+ pull(
163+ sbot_links({
164+ reverse: true,
165+ dest: msg.key,
166+ rel: 'project',
167+ values: true
168+ }),
169+ paramap(function (link, cb) {
170+ getIssueState(link.key, function (err, state) {
171+ if(err) return cb(err)
172+ link.state = state
173+ cb(null, link)
174+ })
175+ }),
176+ pull.drain(function (link) {
177+ 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+ : c.text : link.key)
182+ var author = link.value.author
183+ var t = c.type === 'pull-request'
184+ ? link.state === 'open' ? openPRsT : closedPRsT
185+ : link.state === 'open' ? openIssuesT : closedIssuesT
186+ t.append(h('tr',
187+ h('td',
188+ h('a', {href: '#'+link.key}, title), h('br'),
189+ h('small',
190+ 'opened ', messageTimestampLink(link),
191+ ' by ', h('a', {href: '#'+author}, avatar_name(author))))))
192+ }, function (err) {
193+ if (err) console.error(err)
194+ })
195+ )
196+
117197 return div
118198 }
119199
120200 if(c.type === 'git-update') {
@@ -136,8 +216,26 @@
136216 h('code', issue.object), ' ', h('q', issue.label)]
137217 }) : null
138218 )
139219 }
220+
221+ if (c.type === 'issue') {
222+ return h('div',
223+ h('p', 'opened issue on ', repoLink(c.project)),
224+ c.title ? h('h4', c.title) : '',
225+ markdown(c)
226+ )
227+ }
228+
229+ if (c.type === 'pull-request') {
230+ return h('div',
231+ h('p', 'opened pull-request ',
232+ 'to ', repoLink(c.repo), ':', c.branch, ' ',
233+ 'from ', repoLink(c.head_repo), ':', c.head_branch),
234+ c.title ? h('h4', c.title) : '',
235+ markdown(c)
236+ )
237+ }
140238 }
141239
142240 exports.message_meta = function (msg, sbot) {
143241 var type = msg.value.content.type
style.cssView
@@ -273,4 +273,15 @@
273273
274274 .hypercrop__canvas {
275275 width: 100%;
276276 }
277+
278+.git-table-wrapper {
279+ max-height: 12em;
280+ overflow: auto;
281+ word-break: break-all;
282+ margin: 1em 0;
283+}
284+
285+.git-table-wrapper table {
286+ width: 100%;
287+}

Built with git-ssb-web