var pull = require('pull-stream')
var cat = require('pull-cat')
var u = require('../util')
var markdown = require('../markdown')
var forms = require('../forms')
module.exports = function (repoRoutes, web) {
return new RepoIssueRoutes(repoRoutes, web)
}
function RepoIssueRoutes(repoRoutes, web) {
this.repo = repoRoutes
this.web = web
}
var I = RepoIssueRoutes.prototype
function getMention(msg, id) {
if (msg.key == id) return msg
var mentions = msg.value.content.mentions
if (mentions) for (var i = 0; i < mentions.length; i++) {
var mention = mentions[i]
if (mention.link == id)
return mention
}
return null
}
/* Issues */
I.serveRepoIssues = function (req, repo, isPRs) {
var self = this
var count = 0
var state = req._u.query.state || 'open'
var newPath = isPRs ? [repo.id, 'compare'] : [repo.id, 'issues', 'new']
var title = req._t('Issues') + ' · %{author}/%{repo}'
var page = isPRs ? 'pulls' : 'issues'
return self.repo.serveRepoTemplate(req, repo, page, null, title, cat([
pull.once(
(self.web.isPublic ? '' :
'
') +
'' + req._t(isPRs ? 'PullRequests' : 'Issues') + '
'
),
u.nav([
['?', req._t('issues.Open'), 'open'],
['?state=closed', req._t('issues.Closed'), 'closed'],
['?state=all', req._t('issues.All'), 'all']
], state),
pull(
(isPRs ? self.web.pullReqs : self.web.issues).list({
repo: repo.id,
project: repo.id,
reverse: true,
open: {open: true, closed: false}[state]
}),
pull.map(function (issue) {
count++
var state = (issue.open ? 'open' : 'closed')
var stateStr = req._t(issue.open ?
'issue.state.Open' : 'issue.state.Closed')
return ''
})
),
u.readOnce(function (cb) {
cb(null, count > 0 ? '' :
'' + req._t(isPRs ? 'NoPullRequests' : 'NoIssues') + '
')
})
]))
}
/* New Issue */
I.serveRepoNewIssue = function (req, repo, issueId, path) {
var title = req._t('issue.New') + ' · %{author}/%{repo}'
return this.repo.serveRepoTemplate(req, repo, 'issues', null, title, pull.once(
'' + req._t('issue.New') + '
' +
''))
}
/* Issue */
I.serveRepoIssue = function (req, repo, issue, path, postId) {
var self = this
var newestMsg = {key: issue.id, value: {timestamp: issue.created_at}}
var title = u.formatMarkdownTitle(issue.title) + ' · %{author}/%{repo}'
return self.repo.serveRepoTemplate(req, repo, 'issues', null, title, cat([
pull.once(
'' + u.link([issue.id], u.formatMarkdownTitle(issue.title)) + '
' +
'' + issue.id + '
' +
'' +
(issue.open
? '' +
req._t('issue.state.Open') + ''
: '' +
req._t('issue.state.Closed') + '')),
u.readOnce(function (cb) {
self.web.about.getName(issue.author, function (err, authorName) {
if (err) return cb(err)
var authorLink = u.link([issue.author], authorName)
cb(null, req._t('issue.Opened',
{name: authorLink, datetime: u.timestamp(issue.created_at, req)}))
})
}),
pull.once('
' + markdown(issue.text, repo) + ''),
// render posts and edits
pull(
self.web.ssb.links({
dest: issue.id,
values: true
}),
pull.unique('key'),
u.decryptMessages(self.web.ssb),
u.readableMessages(),
self.web.addAuthorName(),
u.sortMsgs(),
pull.through(function (msg) {
// the newest message in the issue thread
// becomes the branch of the new post
if (msg.value
&& msg.value.timestamp > newestMsg.value.timestamp
&& msg.value.content.root == issue.id)
newestMsg = msg
}),
pull.map(self.renderIssueActivityMsg.bind(self, req, repo, issue,
req._t('issue.'), postId))
),
self.web.isPublic ? pull.empty() : u.readOnce(function (cb) {
cb(null, forms.issueComment(req, issue, repo,
newestMsg.key, req._t('issue.')))
})
]))
}
I.renderIssueActivityMsg = function (req, repo, issue, type, postId, msg) {
var id = u.msgIdToDomId(msg.key)
var authorLink = u.link([msg.value.author], msg.authorName)
var msgHref = u.encodeLink(msg.key) + '#' + id
var msgTimeLink = '' +
new Date(msg.value.timestamp).toLocaleString(req._locale) + ''
var c = msg.value.content
switch (c.type) {
case 'vote':
return ''
case 'post':
if (c.root == issue.id) {
var changed = this.web.issues.isStatusChanged(msg, issue)
return '' +
(msg.key == postId ? '' : '') +
'' + msg.key + ' ' +
(changed == null ? authorLink : req._t(
changed ? 'issue.Reopened' : 'issue.Closed',
{name: authorLink, type: type})) +
' · ' + msgTimeLink +
(msg.key == postId ? '
' : '') +
markdown(c.text, repo) +
''
} else {
var text = c.text || (c.type + ' ' + msg.key)
return ''
}
case 'issue':
case 'pull-request':
return '' +
req._t('issue.MentionedIn', {
name: authorLink,
type: type,
post: u.link([msg.key], u.messageTitle(msg))
}) + ''
case 'issue-edit':
return '' +
(msg.key == postId ? '' : '') +
// handle deprecated rename
(c.title == null ? '' : req._t('issue.Renamed', {
author: authorLink,
type: type,
name: '' + u.escape(c.title) + '
'
})) + ' · ' + msgTimeLink +
(msg.key == postId ? '
' : '') +
''
case 'git-update':
var mention = this.web.issues.getMention(msg, issue)
if (mention) {
var commitLink = u.link([repo.id, 'commit', mention.object],
mention.label || mention.object)
return '' +
req._t(mention.open ? 'issue.Reopened' : 'issue.Closed', {
name: authorLink,
type: type
}) + ' · ' + msgTimeLink + '
' +
commitLink +
''
} else if ((mention = getMention(msg, issue.id))) {
var commitLink = u.link(mention.object ?
[repo.id, 'commit', mention.object] : [msg.key],
mention.label || mention.object || msg.key)
return '' +
req._t('issue.Mentioned', {
name: authorLink,
type: type
}) + ' · ' + msgTimeLink + '
' +
commitLink +
''
} else {
// fallthrough
}
default:
return '' +
authorLink +
' · ' + msgTimeLink +
u.json(c) +
''
}
}