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 messagesCharles Lehner committed on 7/24/2016, 3:46:54 PM
Parent: 627bb1ceef39b5cccd4915b82591d2b085d4716e
Files changed
modules/git.js | changed |
style.css | changed |
modules/git.js | ||
---|---|---|
@@ -8,8 +8,10 @@ | ||
8 | 8 | var sbot_links = plugs.first(exports.sbot_links = []) |
9 | 9 | var sbot_links2 = plugs.first(exports.sbot_links2 = []) |
10 | 10 | var sbot_get = plugs.first(exports.sbot_get = []) |
11 | 11 | var getAvatar = require('ssb-avatar') |
12 | +var avatar_name = plugs.first(exports.avatar_name = []) | |
13 | +var markdown = plugs.first(exports.markdown = []) | |
12 | 14 | |
13 | 15 | var self_id = require('../keys').id |
14 | 16 | |
15 | 17 | function shortRefName(ref) { |
@@ -57,28 +59,77 @@ | ||
57 | 59 | }) |
58 | 60 | ) |
59 | 61 | } |
60 | 62 | |
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 | + | |
61 | 97 | exports.message_content = function (msg, sbot) { |
62 | 98 | var c = msg.value.content |
63 | 99 | |
64 | 100 | if(c.type === 'git-repo') { |
65 | - var nameEl, refsTable | |
101 | + var nameEl | |
102 | + var branchesT, tagsT, openIssuesT, closedIssuesT, openPRsT, closedPRsT | |
66 | 103 | 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)) : '', | |
68 | 106 | 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')))))) | |
71 | 129 | |
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 | - | |
78 | 130 | // compute refs |
79 | 131 | var refs = {} |
80 | - var first = true | |
81 | 132 | pull( |
82 | 133 | sbot_links({ |
83 | 134 | reverse: true, |
84 | 135 | source: msg.value.author, |
@@ -87,34 +138,63 @@ | ||
87 | 138 | values: true |
88 | 139 | }), |
89 | 140 | pull.drain(function (link) { |
90 | 141 | 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 | - } | |
98 | 142 | for (var ref in refUpdates) { |
99 | 143 | if (refs[ref]) continue |
100 | 144 | refs[ref] = true |
101 | 145 | 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]), | |
105 | 153 | 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)))) | |
111 | 155 | } |
112 | 156 | }, function (err) { |
113 | 157 | if (err) console.error(err) |
114 | 158 | }) |
115 | 159 | ) |
116 | 160 | |
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 | + | |
117 | 197 | return div |
118 | 198 | } |
119 | 199 | |
120 | 200 | if(c.type === 'git-update') { |
@@ -136,8 +216,26 @@ | ||
136 | 216 | h('code', issue.object), ' ', h('q', issue.label)] |
137 | 217 | }) : null |
138 | 218 | ) |
139 | 219 | } |
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 | + } | |
140 | 238 | } |
141 | 239 | |
142 | 240 | exports.message_meta = function (msg, sbot) { |
143 | 241 | var type = msg.value.content.type |
Built with git-ssb-web