mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-08 22:45:51 +01:00
Merge branch 'master' into newui-for-dashboard
Conflicts: src/main/twirl/dashboard/issueslist.scala.html src/main/twirl/dashboard/pullslist.scala.html
This commit is contained in:
@@ -195,7 +195,7 @@ trait IssuesControllerBase extends ControllerBase {
|
||||
org.json4s.jackson.Serialization.write(
|
||||
Map("title" -> x.title,
|
||||
"content" -> view.Markdown.toHtml(x.content getOrElse "No description given.",
|
||||
repository, false, true)
|
||||
repository, false, true, true, isEditable(x.userName, x.repositoryName, x.openedUserName))
|
||||
))
|
||||
}
|
||||
} else Unauthorized
|
||||
@@ -212,7 +212,7 @@ trait IssuesControllerBase extends ControllerBase {
|
||||
contentType = formats("json")
|
||||
org.json4s.jackson.Serialization.write(
|
||||
Map("content" -> view.Markdown.toHtml(x.content,
|
||||
repository, false, true)
|
||||
repository, false, true, true, isEditable(x.userName, x.repositoryName, x.commentedUserName))
|
||||
))
|
||||
}
|
||||
} else Unauthorized
|
||||
|
||||
@@ -77,7 +77,9 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
contentType = "text/html"
|
||||
view.helpers.markdown(params("content"), repository,
|
||||
params("enableWikiLink").toBoolean,
|
||||
params("enableRefsLink").toBoolean)
|
||||
params("enableRefsLink").toBoolean,
|
||||
params("enableTaskList").toBoolean,
|
||||
hasWritePermission(repository.owner, repository.name, context.loginAccount))
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -112,7 +114,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
repo.html.commits(if(path.isEmpty) Nil else path.split("/").toList, branchName, repository,
|
||||
logs.splitWith{ (commit1, commit2) =>
|
||||
view.helpers.date(commit1.commitTime) == view.helpers.date(commit2.commitTime)
|
||||
}, page, hasNext)
|
||||
}, page, hasNext, hasWritePermission(repository.owner, repository.name, context.loginAccount))
|
||||
case Left(_) => NotFound
|
||||
}
|
||||
}
|
||||
@@ -239,6 +241,24 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Creates a branch.
|
||||
*/
|
||||
post("/:owner/:repository/branches")(collaboratorsOnly { repository =>
|
||||
val newBranchName = params.getOrElse("new", halt(400))
|
||||
val fromBranchName = params.getOrElse("from", halt(400))
|
||||
using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git =>
|
||||
JGitUtil.createBranch(git, fromBranchName, newBranchName)
|
||||
} match {
|
||||
case Right(message) =>
|
||||
flash += "info" -> message
|
||||
redirect(s"/${repository.owner}/${repository.name}/tree/${StringUtil.urlEncode(newBranchName).replace("%2F", "/")}")
|
||||
case Left(message) =>
|
||||
flash += "error" -> message
|
||||
redirect(s"/${repository.owner}/${repository.name}/tree/${fromBranchName}")
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Deletes branch.
|
||||
*/
|
||||
@@ -331,7 +351,8 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
repo.html.files(revision, repository,
|
||||
if(path == ".") Nil else path.split("/").toList, // current path
|
||||
new JGitUtil.CommitInfo(lastModifiedCommit), // last modified commit
|
||||
files, readme, hasWritePermission(repository.owner, repository.name, context.loginAccount))
|
||||
files, readme, hasWritePermission(repository.owner, repository.name, context.loginAccount),
|
||||
flash.get("info"), flash.get("error"))
|
||||
}
|
||||
} getOrElse NotFound
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ trait UserManagementControllerBase extends AccountManagementControllerBase {
|
||||
"url" -> trim(label("URL" ,optional(text(maxlength(200))))),
|
||||
"fileId" -> trim(label("File ID" ,optional(text()))),
|
||||
"clearImage" -> trim(label("Clear image" ,boolean())),
|
||||
"removed" -> trim(label("Disable" ,boolean()))
|
||||
"removed" -> trim(label("Disable" ,boolean(disableByNotYourself("userName"))))
|
||||
)(EditUserForm.apply)
|
||||
|
||||
val newGroupForm = mapping(
|
||||
@@ -190,4 +190,14 @@ trait UserManagementControllerBase extends AccountManagementControllerBase {
|
||||
}
|
||||
}
|
||||
|
||||
protected def disableByNotYourself(paramName: String): Constraint = new Constraint() {
|
||||
override def validate(name: String, value: String, messages: Messages): Option[String] = {
|
||||
params.get(paramName).flatMap { userName =>
|
||||
if(userName == context.loginAccount.get.userName)
|
||||
Some("You can't disable your account yourself")
|
||||
else
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.eclipse.jgit.treewalk.filter._
|
||||
import org.eclipse.jgit.diff.DiffEntry.ChangeType
|
||||
import org.eclipse.jgit.errors.{ConfigInvalidException, MissingObjectException}
|
||||
import java.util.Date
|
||||
import org.eclipse.jgit.api.errors.NoHeadException
|
||||
import org.eclipse.jgit.api.errors.{JGitInternalException, InvalidRefNameException, RefAlreadyExistsException, NoHeadException}
|
||||
import service.RepositoryService
|
||||
import org.eclipse.jgit.dircache.DirCacheEntry
|
||||
import org.slf4j.LoggerFactory
|
||||
@@ -507,6 +507,17 @@ object JGitUtil {
|
||||
}.find(_._1 != null)
|
||||
}
|
||||
|
||||
def createBranch(git: Git, fromBranch: String, newBranch: String) = {
|
||||
try {
|
||||
git.branchCreate().setStartPoint(fromBranch).setName(newBranch).call()
|
||||
Right("Branch created.")
|
||||
} catch {
|
||||
case e: RefAlreadyExistsException => Left("Sorry, that branch already exists.")
|
||||
// JGitInternalException occurs when new branch name is 'a' and the branch whose name is 'a/*' exists.
|
||||
case _: InvalidRefNameException | _: JGitInternalException => Left("Sorry, that name is invalid.")
|
||||
}
|
||||
}
|
||||
|
||||
def createDirCacheEntry(path: String, mode: FileMode, objectId: ObjectId): DirCacheEntry = {
|
||||
val entry = new DirCacheEntry(path)
|
||||
entry.setFileMode(mode)
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.pegdown.ast._
|
||||
import org.pegdown.LinkRenderer.Rendering
|
||||
import java.text.Normalizer
|
||||
import java.util.Locale
|
||||
import java.util.regex.Pattern
|
||||
import scala.collection.JavaConverters._
|
||||
import service.{RequestCache, WikiService}
|
||||
|
||||
@@ -18,17 +19,23 @@ object Markdown {
|
||||
* Converts Markdown of Wiki pages to HTML.
|
||||
*/
|
||||
def toHtml(markdown: String, repository: service.RepositoryService.RepositoryInfo,
|
||||
enableWikiLink: Boolean, enableRefsLink: Boolean)(implicit context: app.Context): String = {
|
||||
enableWikiLink: Boolean, enableRefsLink: Boolean,
|
||||
enableTaskList: Boolean = false, hasWritePermission: Boolean = false)(implicit context: app.Context): String = {
|
||||
// escape issue id
|
||||
val source = if(enableRefsLink){
|
||||
val s = if(enableRefsLink){
|
||||
markdown.replaceAll("(?<=(\\W|^))#(\\d+)(?=(\\W|$))", "issue:$2")
|
||||
} else markdown
|
||||
|
||||
// escape task list
|
||||
val source = if(enableTaskList){
|
||||
GitBucketHtmlSerializer.escapeTaskList(s)
|
||||
} else s
|
||||
|
||||
val rootNode = new PegDownProcessor(
|
||||
Extensions.AUTOLINKS | Extensions.WIKILINKS | Extensions.FENCED_CODE_BLOCKS | Extensions.TABLES | Extensions.HARDWRAPS
|
||||
).parseMarkdown(source.toCharArray)
|
||||
|
||||
new GitBucketHtmlSerializer(markdown, repository, enableWikiLink, enableRefsLink).toHtml(rootNode)
|
||||
new GitBucketHtmlSerializer(markdown, repository, enableWikiLink, enableRefsLink, enableTaskList, hasWritePermission).toHtml(rootNode)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +89,9 @@ class GitBucketHtmlSerializer(
|
||||
markdown: String,
|
||||
repository: service.RepositoryService.RepositoryInfo,
|
||||
enableWikiLink: Boolean,
|
||||
enableRefsLink: Boolean
|
||||
enableRefsLink: Boolean,
|
||||
enableTaskList: Boolean,
|
||||
hasWritePermission: Boolean
|
||||
)(implicit val context: app.Context) extends ToHtmlSerializer(
|
||||
new GitBucketLinkRender(context, repository, enableWikiLink),
|
||||
Map[String, VerbatimSerializer](VerbatimSerializer.DEFAULT -> new GitBucketVerbatimSerializer).asJava
|
||||
@@ -143,7 +152,10 @@ class GitBucketHtmlSerializer(
|
||||
|
||||
override def visit(node: TextNode): Unit = {
|
||||
// convert commit id and username to link.
|
||||
val text = if(enableRefsLink) convertRefsLinks(node.getText, repository, "issue:") else node.getText
|
||||
val t = if(enableRefsLink) convertRefsLinks(node.getText, repository, "issue:") else node.getText
|
||||
|
||||
// convert task list to checkbox.
|
||||
val text = if(enableTaskList) GitBucketHtmlSerializer.convertCheckBox(t, hasWritePermission) else t
|
||||
|
||||
if (abbreviations.isEmpty) {
|
||||
printer.print(text)
|
||||
@@ -151,6 +163,28 @@ class GitBucketHtmlSerializer(
|
||||
printWithAbbreviations(text)
|
||||
}
|
||||
}
|
||||
|
||||
override def visit(node: BulletListNode): Unit = {
|
||||
if (printChildrenToString(node).contains("""class="task-list-item-checkbox" """)) {
|
||||
printer.println().print("""<ul class="task-list">""").indent(+2)
|
||||
visitChildren(node)
|
||||
printer.indent(-2).println().print("</ul>")
|
||||
} else {
|
||||
printIndentedTag(node, "ul")
|
||||
}
|
||||
}
|
||||
|
||||
override def visit(node: ListItemNode): Unit = {
|
||||
if (printChildrenToString(node).contains("""class="task-list-item-checkbox" """)) {
|
||||
printer.println()
|
||||
printer.print("""<li class="task-list-item">""")
|
||||
visitChildren(node)
|
||||
printer.print("</li>")
|
||||
} else {
|
||||
printer.println()
|
||||
printTag(node, "li")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object GitBucketHtmlSerializer {
|
||||
@@ -163,4 +197,14 @@ object GitBucketHtmlSerializer {
|
||||
val noSpecialChars = StringUtil.urlEncode(normalized)
|
||||
noSpecialChars.toLowerCase(Locale.ENGLISH)
|
||||
}
|
||||
|
||||
def escapeTaskList(text: String): String = {
|
||||
Pattern.compile("""^( *)- \[([x| ])\] """, Pattern.MULTILINE).matcher(text).replaceAll("$1* task:$2: ")
|
||||
}
|
||||
|
||||
def convertCheckBox(text: String, hasWritePermission: Boolean): String = {
|
||||
val disabled = if (hasWritePermission) "" else "disabled"
|
||||
text.replaceAll("task:x:", """<input type="checkbox" class="task-list-item-checkbox" checked="checked" """ + disabled + "/>")
|
||||
.replaceAll("task: :", """<input type="checkbox" class="task-list-item-checkbox" """ + disabled + "/>")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package view
|
||||
import java.util.{Date, TimeZone}
|
||||
import java.util.{Locale, Date, TimeZone}
|
||||
import java.text.SimpleDateFormat
|
||||
import play.twirl.api.Html
|
||||
import util.StringUtil
|
||||
@@ -15,6 +15,47 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
|
||||
*/
|
||||
def datetime(date: Date): String = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date)
|
||||
|
||||
val timeUnits = List(
|
||||
(1000L, "second"),
|
||||
(1000L * 60, "minute"),
|
||||
(1000L * 60 * 60, "hour"),
|
||||
(1000L * 60 * 60 * 24, "day"),
|
||||
(1000L * 60 * 60 * 24 * 30, "month"),
|
||||
(1000L * 60 * 60 * 24 * 365, "year")
|
||||
).reverse
|
||||
|
||||
/**
|
||||
* Format java.util.Date to "x {seconds/minutes/hours/days/months/years} ago"
|
||||
*/
|
||||
def datetimeAgo(date: Date): String = {
|
||||
val duration = new Date().getTime - date.getTime
|
||||
timeUnits.find(tuple => duration / tuple._1 > 0) match {
|
||||
case Some((unitValue, unitString)) =>
|
||||
val value = duration / unitValue
|
||||
s"${value} ${unitString}${if (value > 1) "s" else ""} ago"
|
||||
case None => "just now"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Format java.util.Date to "x {seconds/minutes/hours/days} ago"
|
||||
* If duration over 1 month, format to "d MMM (yyyy)"
|
||||
*
|
||||
*/
|
||||
def datetimeAgoRecentOnly(date: Date): String = {
|
||||
val duration = new Date().getTime - date.getTime
|
||||
timeUnits.find(tuple => duration / tuple._1 > 0) match {
|
||||
case Some((_, "month")) => s"on ${new SimpleDateFormat("d MMM", Locale.ENGLISH).format(date)}"
|
||||
case Some((_, "year")) => s"on ${new SimpleDateFormat("d MMM yyyy", Locale.ENGLISH).format(date)}"
|
||||
case Some((unitValue, unitString)) =>
|
||||
val value = duration / unitValue
|
||||
s"${value} ${unitString}${if (value > 1) "s" else ""} ago"
|
||||
case None => "just now"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Format java.util.Date to "yyyy-MM-dd'T'hh:mm:ss'Z'".
|
||||
*/
|
||||
@@ -48,8 +89,8 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
|
||||
* Converts Markdown of Wiki pages to HTML.
|
||||
*/
|
||||
def markdown(value: String, repository: service.RepositoryService.RepositoryInfo,
|
||||
enableWikiLink: Boolean, enableRefsLink: Boolean)(implicit context: app.Context): Html =
|
||||
Html(Markdown.toHtml(value, repository, enableWikiLink, enableRefsLink))
|
||||
enableWikiLink: Boolean, enableRefsLink: Boolean, enableTaskList: Boolean = false, hasWritePermission: Boolean = false)(implicit context: app.Context): Html =
|
||||
Html(Markdown.toHtml(value, repository, enableWikiLink, enableRefsLink, enableTaskList, hasWritePermission))
|
||||
|
||||
def renderMarkup(filePath: List[String], fileContent: String, branch: String,
|
||||
repository: service.RepositoryService.RepositoryInfo,
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
@if(repository.repository.description.isDefined){
|
||||
<div>@repository.repository.description</div>
|
||||
}
|
||||
<div><span class="muted small">Last updated: @datetime(repository.repository.lastActivityDate)</span></div>
|
||||
<div><span class="muted small">Updated @helper.html.datetimeago(repository.repository.lastActivityDate)</span></div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
<input type="checkbox" name="removed" id="removed" value="true" @if(account.get.isRemoved){checked}/>
|
||||
Disable
|
||||
</label>
|
||||
<div>
|
||||
<span id="error-removed" class="error"></span>
|
||||
</div>
|
||||
}
|
||||
</fieldset>
|
||||
@if(account.map(_.password.nonEmpty).getOrElse(true)){
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
@detailActivity(activity: model.Activity, image: String) = {
|
||||
<div class="activity-icon-large"><img src="@assets/common/images/@image"/></div>
|
||||
<div class="activity-content">
|
||||
<div class="muted small">@datetime(activity.activityDate)</div>
|
||||
<div class="muted small">@helper.html.datetimeago(activity.activityDate)</div>
|
||||
<div class="strong">
|
||||
@avatar(activity.activityUserName, 16)
|
||||
@activityMessage(activity.message)
|
||||
@@ -76,7 +76,7 @@
|
||||
@customActivity(activity: model.Activity, image: String)(additionalInfo: Any) = {
|
||||
<div class="activity-icon-large"><img src="@assets/common/images/@image"/></div>
|
||||
<div class="activity-content">
|
||||
<div class="muted small">@datetime(activity.activityDate)</div>
|
||||
<div class="muted small">@helper.html.datetimeago(activity.activityDate)</div>
|
||||
<div class="strong">
|
||||
@avatar(activity.activityUserName, 16)
|
||||
@activityMessage(activity.message)
|
||||
@@ -91,7 +91,7 @@
|
||||
<div>
|
||||
@avatar(activity.activityUserName, 16)
|
||||
@activityMessage(activity.message)
|
||||
<span class="muted small">@datetime(activity.activityDate)</span>
|
||||
<span class="muted small">@helper.html.datetimeago(activity.activityDate)</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
62
src/main/twirl/helper/branchcontrol.scala.html
Normal file
62
src/main/twirl/helper/branchcontrol.scala.html
Normal file
@@ -0,0 +1,62 @@
|
||||
@(branch: String = "",
|
||||
repository: service.RepositoryService.RepositoryInfo,
|
||||
hasWritePermission: Boolean)(body: Html)(implicit context: app.Context)
|
||||
@import context._
|
||||
@import view.helpers._
|
||||
@helper.html.dropdown(
|
||||
value = if(branch.length == 40) branch.substring(0, 10) else branch,
|
||||
prefix = if(branch.length == 40) "tree" else if(repository.branchList.contains(branch)) "branch" else "tree",
|
||||
mini = true
|
||||
) {
|
||||
<li><div id="branch-control-title">Switch branches<button id="branch-control-close" class="pull-right">×</button></div></li>
|
||||
<li><input id="branch-control-input" type="text" placeholder="Find or create branch ..."/></li>
|
||||
@body
|
||||
@if(hasWritePermission) {
|
||||
<li id="create-branch" style="display: none;">
|
||||
<a><form action="@url(repository)/branches" method="post" style="margin: 0;">
|
||||
<span class="new-branch-name">Create branch: <span class="new-branch"></span></span>
|
||||
<br><span style="padding-left: 17px;">from '@branch'</span>
|
||||
<input type="hidden" name="new">
|
||||
<input type="hidden" name="from" value="@branch">
|
||||
</form></a>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
<script>
|
||||
$(function(){
|
||||
$('#branch-control-input').parent().click(function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
$('#branch-control-close').click(function() {
|
||||
$('[data-toggle="dropdown"]').parent().removeClass('open');
|
||||
});
|
||||
$('#branch-control-input').keyup(function() {
|
||||
var inputVal = $('#branch-control-input').val();
|
||||
$.each($('#branch-control-input').parent().parent().find('a'), function(index, elem) {
|
||||
if (!inputVal || !elem.text.trim() || elem.text.trim().lastIndexOf(inputVal, 0) >= 0) {
|
||||
$(elem).parent().show();
|
||||
} else {
|
||||
$(elem).parent().hide();
|
||||
}
|
||||
});
|
||||
@if(hasWritePermission) {
|
||||
if (inputVal) {
|
||||
$('#create-branch').parent().find('li:last-child').show().find('.new-branch').text(inputVal);
|
||||
} else {
|
||||
$('#create-branch').parent().find('li:last-child').hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
@if(hasWritePermission) {
|
||||
$('#create-branch').click(function() {
|
||||
$(this).find('input[name="new"]').val($('.dropdown-menu input').val())
|
||||
$(this).find('form').submit()
|
||||
});
|
||||
}
|
||||
$('.btn-group').click(function() {
|
||||
$('#branch-control-input').val('');
|
||||
$('.dropdown-menu li').show();
|
||||
$('#create-branch').hide();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
10
src/main/twirl/helper/datetimeago.scala.html
Normal file
10
src/main/twirl/helper/datetimeago.scala.html
Normal file
@@ -0,0 +1,10 @@
|
||||
@(latestUpdatedDate: java.util.Date,
|
||||
recentOnly: Boolean = true)
|
||||
@import view.helpers._
|
||||
<span data-toggle="tooltip" title="@datetime(latestUpdatedDate)">
|
||||
@if(recentOnly){
|
||||
@datetimeAgoRecentOnly(latestUpdatedDate)
|
||||
}else{
|
||||
@datetimeAgo(latestUpdatedDate)
|
||||
}
|
||||
</span>
|
||||
7
src/main/twirl/helper/error.scala.html
Normal file
7
src/main/twirl/helper/error.scala.html
Normal file
@@ -0,0 +1,7 @@
|
||||
@(error: Option[Any])
|
||||
@if(error.isDefined){
|
||||
<div class='alert alert-danger'>
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
@error
|
||||
</div>
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
@(info: Option[Any])
|
||||
@if(info.isDefined){
|
||||
<div class="alert alert-info">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
@info
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@(repository: service.RepositoryService.RepositoryInfo, content: String, enableWikiLink: Boolean, enableRefsLink: Boolean,
|
||||
@(repository: service.RepositoryService.RepositoryInfo, content: String, enableWikiLink: Boolean, enableRefsLink: Boolean, enableTaskList: Boolean, hasWritePermission: Boolean,
|
||||
style: String = "", placeholder: String = "Leave a comment", elastic: Boolean = false)(implicit context: app.Context)
|
||||
@import context._
|
||||
@import view.helpers._
|
||||
@@ -38,7 +38,8 @@ $(function(){
|
||||
$.post('@url(repository)/_preview', {
|
||||
content : $('#content').val(),
|
||||
enableWikiLink : @enableWikiLink,
|
||||
enableRefsLink : @enableRefsLink
|
||||
enableRefsLink : @enableRefsLink,
|
||||
enableTaskList : @enableTaskList
|
||||
}, function(data){
|
||||
$('#preview-area').html(data);
|
||||
prettyPrint();
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="issue-avatar-image">@avatar(loginAccount.get.userName, 48)</div>
|
||||
<div class="box issue-comment-box">
|
||||
<div class="box-content">
|
||||
@helper.html.preview(repository, "", false, true, "width: 635px; height: 100px; max-height: 150px;", elastic = true)
|
||||
@helper.html.preview(repository, "", false, true, true, hasWritePermission, "width: 635px; height: 100px; max-height: 150px;", elastic = true)
|
||||
</div>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
@@ -28,4 +28,4 @@ $(function(){
|
||||
$('<input type="hidden">').attr('name', 'action').val($(this).val().toLowerCase()).appendTo('form');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<div class="issue-avatar-image">@avatar(issue.openedUserName, 48)</div>
|
||||
<div class="box issue-comment-box">
|
||||
<div class="box-header-small">
|
||||
@user(issue.openedUserName, styleClass="username strong") <span class="muted">commented on @datetime(issue.registeredDate)</span>
|
||||
@user(issue.openedUserName, styleClass="username strong") <span class="muted">commented @helper.html.datetimeago(issue.registeredDate)</span>
|
||||
<span class="pull-right">
|
||||
@if(hasWritePermission || loginAccount.map(_.userName == issue.openedUserName).getOrElse(false)){
|
||||
<a href="#" data-issue-id="@issue.issueId"><i class="icon-pencil"></i></a>
|
||||
@@ -16,7 +16,7 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="box-content issue-content" id="issueContent">
|
||||
@markdown(issue.content getOrElse "No description provided.", repository, false, true)
|
||||
@markdown(issue.content getOrElse "No description provided.", repository, false, true, true, hasWritePermission)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
} else {
|
||||
@if(pullreq.isEmpty){ referenced the issue } else { referenced the pull request }
|
||||
}
|
||||
on @datetime(comment.registeredDate)
|
||||
@helper.html.datetimeago(comment.registeredDate)
|
||||
</span>
|
||||
<span class="pull-right">
|
||||
@if(comment.action != "commit" && comment.action != "merge" && comment.action != "refer" &&
|
||||
@@ -46,7 +46,7 @@
|
||||
@if(comment.action == "commit" && comment.content.split(" ").last.matches("[a-f0-9]{40}")){
|
||||
@defining(comment.content.substring(comment.content.length - 40)){ id =>
|
||||
<div class="pull-right"><a href="@path/@repository.owner/@repository.name/commit/@id" class="monospace">@id.substring(0, 7)</a></div>
|
||||
@markdown(comment.content.substring(0, comment.content.length - 41), repository, false, true)
|
||||
@markdown(comment.content.substring(0, comment.content.length - 41), repository, false, true, true, hasWritePermission)
|
||||
}
|
||||
} else {
|
||||
@if(comment.action == "refer"){
|
||||
@@ -54,7 +54,7 @@
|
||||
<strong><a href="@path/@repository.owner/@repository.name/issues/@issueId">Issue #@issueId</a>: @rest.mkString(":")</strong>
|
||||
}
|
||||
} else {
|
||||
@markdown(comment.content, repository, false, true)
|
||||
@markdown(comment.content, repository, false, true, true, hasWritePermission)
|
||||
}
|
||||
}
|
||||
</div>
|
||||
@@ -70,7 +70,7 @@
|
||||
} else {
|
||||
<span class="label label-info monospace">@pullreq.map(_.userName):@pullreq.map(_.branch)</span> to <span class="label label-info monospace">@pullreq.map(_.requestUserName):@pullreq.map(_.requestBranch)</span>
|
||||
}
|
||||
@datetime(comment.registeredDate)
|
||||
@helper.html.datetimeago(comment.registeredDate)
|
||||
</div>
|
||||
}
|
||||
@if(comment.action == "close" || comment.action == "close_comment"){
|
||||
@@ -78,9 +78,9 @@
|
||||
<span class="label label-important">Closed</span>
|
||||
@avatar(comment.commentedUserName, 20)
|
||||
@if(issue.isPullRequest){
|
||||
@user(comment.commentedUserName, styleClass="username strong") closed the pull request @datetime(comment.registeredDate)
|
||||
@user(comment.commentedUserName, styleClass="username strong") closed the pull request @helper.html.datetimeago(comment.registeredDate)
|
||||
} else {
|
||||
@user(comment.commentedUserName, styleClass="username strong") closed the issue @datetime(comment.registeredDate)
|
||||
@user(comment.commentedUserName, styleClass="username strong") closed the issue @helper.html.datetimeago(comment.registeredDate)
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@@ -88,14 +88,14 @@
|
||||
<div class="small issue-comment-action">
|
||||
<span class="label label-success">Reopened</span>
|
||||
@avatar(comment.commentedUserName, 20)
|
||||
@user(comment.commentedUserName, styleClass="username strong") reopened the issue @datetime(comment.registeredDate)
|
||||
@user(comment.commentedUserName, styleClass="username strong") reopened the issue @helper.html.datetimeago(comment.registeredDate)
|
||||
</div>
|
||||
}
|
||||
@if(comment.action == "delete_branch"){
|
||||
<div class="small issue-comment-action">
|
||||
<span class="label">Deleted</span>
|
||||
@avatar(comment.commentedUserName, 20)
|
||||
@user(comment.commentedUserName, styleClass="username strong") deleted the <span class="label label-info monospace">@pullreq.map(_.requestBranch)</span> branch @datetime(comment.registeredDate)
|
||||
@user(comment.commentedUserName, styleClass="username strong") deleted the <span class="label label-info monospace">@pullreq.map(_.requestBranch)</span> branch @helper.html.datetimeago(comment.registeredDate)
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -134,5 +134,67 @@ $(function(){
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
var extractMarkdown = function(data){
|
||||
$('body').append('<div id="tmp"></div>');
|
||||
$('#tmp').html(data);
|
||||
var markdown = $('#tmp textarea').val();
|
||||
$('#tmp').remove();
|
||||
return markdown;
|
||||
};
|
||||
|
||||
var replaceTaskList = function(issueContentHtml, checkboxes) {
|
||||
var ss = [],
|
||||
markdown = extractMarkdown(issueContentHtml),
|
||||
xs = markdown.split(/- \[[x| ]\]/g);
|
||||
for (var i=0; i<xs.length; i++) {
|
||||
ss.push(xs[i]);
|
||||
if (checkboxes.eq(i).prop('checked')) ss.push('- [x]');
|
||||
else ss.push('- [ ]');
|
||||
}
|
||||
ss.pop();
|
||||
return ss.join('');
|
||||
};
|
||||
|
||||
$('#issueContent').on('click', ':checkbox', function(ev){
|
||||
var checkboxes = $('#issueContent :checkbox');
|
||||
$.get('@url(repository)/issues/_data/@issue.issueId',
|
||||
{
|
||||
dataType : 'html'
|
||||
},
|
||||
function(responseContent){
|
||||
$.ajax({
|
||||
url: '@url(repository)/issues/edit/@issue.issueId',
|
||||
type: 'POST',
|
||||
data: {
|
||||
title : $('#issueTitle').text(),
|
||||
content : replaceTaskList(responseContent, checkboxes)
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$('div[id^=commentContent-]').on('click', ':checkbox', function(ev){
|
||||
var $commentContent = $(ev.target).parents('div[id^=commentContent-]'),
|
||||
commentId = $commentContent.attr('id').replace(/commentContent-/, ''),
|
||||
checkboxes = $commentContent.find(':checkbox');
|
||||
$.get('@url(repository)/issue_comments/_data/' + commentId,
|
||||
{
|
||||
dataType : 'html'
|
||||
},
|
||||
function(responseContent){
|
||||
$.ajax({
|
||||
url: '@url(repository)/issue_comments/edit/' + commentId,
|
||||
type: 'POST',
|
||||
data: {
|
||||
issueId : 0,
|
||||
content : replaceTaskList(responseContent, checkboxes)
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
@helper.html.preview(repository, "", false, true, "width: 565px; height: 200px; max-height: 250px;", elastic = true)
|
||||
@helper.html.preview(repository, "", false, true, true, hasWritePermission, "width: 565px; height: 200px; max-height: 250px;", elastic = true)
|
||||
</div>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<span class="label label-success issue-status">Open</span>
|
||||
}
|
||||
<span class="muted">
|
||||
@user(issue.openedUserName, styleClass="username strong") opened this issue on @datetime(issue.registeredDate) - @defining(
|
||||
@user(issue.openedUserName, styleClass="username strong") opened this issue @helper.html.datetimeago(issue.registeredDate) - @defining(
|
||||
comments.filter( _.action.contains("comment") ).size
|
||||
){ count =>
|
||||
@count @plural(count, "comment")
|
||||
|
||||
@@ -203,7 +203,7 @@
|
||||
}
|
||||
</span>
|
||||
<div class="small muted" style="margin-left: 40px; margin-top: 5px;">
|
||||
#@issue.issueId opened by @user(issue.openedUserName, styleClass="username") @datetime(issue.registeredDate)
|
||||
#@issue.issueId opened @helper.html.datetimeago(issue.registeredDate) by @user(issue.openedUserName, styleClass="username")
|
||||
@milestone.map { milestone =>
|
||||
<span style="margin: 20px;"><a href="@condition.copy(milestoneId = Some(Some(1))).toURL" class="username"><img src="@assets/common/images/milestone.png"> @milestone</a></span>
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<a href="@url(repository)/issues?milestone=@milestone.milestoneId&state=open" class="milestone-title">@milestone.title</a>
|
||||
<div style="margin-top: 6px">
|
||||
@if(milestone.closedDate.isDefined){
|
||||
<span class="muted">Closed @datetime(milestone.closedDate.get)</span>
|
||||
<span class="muted">Closed @helper.html.datetimeago(milestone.closedDate.get)</span>
|
||||
} else {
|
||||
@milestone.dueDate.map { dueDate =>
|
||||
@if(isPast(dueDate)){
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
@(active: String,
|
||||
repository: service.RepositoryService.RepositoryInfo,
|
||||
id: Option[String] = None,
|
||||
expand: Boolean = false)(body: Html)(implicit context: app.Context)
|
||||
expand: Boolean = false,
|
||||
info: Option[Any] = None,
|
||||
error: Option[Any] = None)(body: Html)(implicit context: app.Context)
|
||||
@import context._
|
||||
@import view.helpers._
|
||||
|
||||
@@ -31,6 +33,8 @@
|
||||
}
|
||||
|
||||
<div class="container">
|
||||
@helper.html.information(info)
|
||||
@helper.html.error(error)
|
||||
@if(repository.commitCount > 0){
|
||||
<div class="pull-right">
|
||||
<div class="input-prepend">
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
<div style="width: 600px; border-right: 1px solid #d4d4d4;">
|
||||
<span class="error" id="error-title"></span>
|
||||
<input type="text" name="title" style="width: 580px" placeholder="Title"/>
|
||||
@helper.html.preview(repository, "", false, true, "width: 580px; height: 200px;")
|
||||
@helper.html.preview(repository, "", false, true, true, hasWritePermission, "width: 580px; height: 200px;")
|
||||
<input type="hidden" name="targetUserName" value="@originRepository.owner"/>
|
||||
<input type="hidden" name="targetBranch" value="@originId"/>
|
||||
<input type="hidden" name="requestUserName" value="@forkedRepository.owner"/>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<span class="label label-info">Merged</span>
|
||||
@user(comment.commentedUserName, styleClass="username strong") merged @commits.size @plural(commits.size, "commit")
|
||||
into <code>@pullreq.userName:@pullreq.branch</code> from <code>@pullreq.requestUserName:@pullreq.requestBranch</code>
|
||||
at @datetime(comment.registeredDate)
|
||||
@helper.html.datetimeago(comment.registeredDate)
|
||||
}.getOrElse {
|
||||
<span class="label label-important">Closed</span>
|
||||
@user(issue.openedUserName, styleClass="username strong") wants to merge @commits.size @plural(commits.size, "commit")
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
@html.main(s"${repository.owner}/${repository.name}", Some(repository)) {
|
||||
@html.menu("code", repository){
|
||||
<div class="head">
|
||||
@helper.html.dropdown(
|
||||
value = if(branch.length == 40) branch.substring(0, 10) else branch,
|
||||
prefix = if(branch.length == 40) "tree" else if(repository.branchList.contains(branch)) "branch" else "tree",
|
||||
mini = true
|
||||
@helper.html.branchcontrol(
|
||||
branch,
|
||||
repository,
|
||||
hasWritePermission
|
||||
){
|
||||
@repository.branchList.map { x =>
|
||||
<li><a href="@url(repository)/blob/@encodeRefName(x)/@pathList.mkString("/")">@helper.html.checkicon(x == branch) @x</a></li>
|
||||
@@ -34,7 +34,7 @@
|
||||
<div class="pull-left">
|
||||
@avatar(latestCommit, 20)
|
||||
@user(latestCommit.authorName, latestCommit.authorEmailAddress, "username strong")
|
||||
<span class="muted">@datetime(latestCommit.commitTime)</span>
|
||||
<span class="muted">@helper.html.datetimeago(latestCommit.commitTime)</span>
|
||||
<a href="@url(repository)/commit/@latestCommit.id" class="commit-message">@link(latestCommit.summary, repository)</a>
|
||||
</div>
|
||||
<div class="btn-group pull-right">
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@datetime(latestUpdateDate)
|
||||
@helper.html.datetimeago(latestUpdateDate, false)
|
||||
</td>
|
||||
<td>
|
||||
@if(repository.repository.defaultBranch == branchName){
|
||||
|
||||
@@ -68,13 +68,13 @@
|
||||
<div class="author">
|
||||
@avatar(commit, 20)
|
||||
<span>@user(commit.authorName, commit.authorEmailAddress, "username strong")</span>
|
||||
<span class="muted">authored on @datetime(commit.authorTime)</span>
|
||||
<span class="muted">authored @helper.html.datetimeago(commit.authorTime)</span>
|
||||
</div>
|
||||
@if(commit.isDifferentFromAuthor) {
|
||||
<div class="committer">
|
||||
<span class="icon-arrow-right"></span>
|
||||
<span>@user(commit.committerName, commit.committerEmailAddress, "username strong")</span>
|
||||
<span class="muted"> committed on @datetime(commit.commitTime)</span>
|
||||
<span class="muted"> committed @helper.html.datetimeago(commit.commitTime)</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -3,16 +3,17 @@
|
||||
repository: service.RepositoryService.RepositoryInfo,
|
||||
commits: Seq[Seq[util.JGitUtil.CommitInfo]],
|
||||
page: Int,
|
||||
hasNext: Boolean)(implicit context: app.Context)
|
||||
hasNext: Boolean,
|
||||
hasWritePermission: Boolean)(implicit context: app.Context)
|
||||
@import context._
|
||||
@import view.helpers._
|
||||
@html.main(s"${repository.owner}/${repository.name}", Some(repository)) {
|
||||
@html.menu("code", repository){
|
||||
<div class="head">
|
||||
@helper.html.dropdown(
|
||||
value = if(branch.length == 40) branch.substring(0, 10) else branch,
|
||||
prefix = if(branch.length == 40) "tree" else if(repository.branchList.contains(branch)) "branch" else "tree",
|
||||
mini = true
|
||||
@helper.html.branchcontrol(
|
||||
branch,
|
||||
repository,
|
||||
hasWritePermission
|
||||
){
|
||||
@repository.branchList.map { x =>
|
||||
<li><a href="@url(repository)/commits/@encodeRefName(x)">@helper.html.checkicon(x == branch) @x</a></li>
|
||||
@@ -58,11 +59,11 @@
|
||||
}
|
||||
<div class="small">
|
||||
@user(commit.authorName, commit.authorEmailAddress, "username")
|
||||
<span class="muted">authored @datetime(commit.authorTime)</span>
|
||||
<span class="muted">authored @helper.html.datetimeago(commit.authorTime)</span>
|
||||
@if(commit.isDifferentFromAuthor) {
|
||||
<span class="icon-arrow-right" style="margin-top : -2px ;"></span>
|
||||
@user(commit.committerName, commit.committerEmailAddress, "username")
|
||||
<span class="muted">committed @datetime(commit.authorTime)</span>
|
||||
<span class="muted">committed @helper.html.datetimeago(commit.authorTime)</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,16 +4,18 @@
|
||||
latestCommit: util.JGitUtil.CommitInfo,
|
||||
files: List[util.JGitUtil.FileInfo],
|
||||
readme: Option[(List[String], String)],
|
||||
hasWritePermission: Boolean)(implicit context: app.Context)
|
||||
hasWritePermission: Boolean,
|
||||
info: Option[Any] = None,
|
||||
error: Option[Any] = None)(implicit context: app.Context)
|
||||
@import context._
|
||||
@import view.helpers._
|
||||
@html.main(s"${repository.owner}/${repository.name}", Some(repository)) {
|
||||
@html.menu("code", repository, Some(branch), pathList.isEmpty){
|
||||
@html.menu("code", repository, Some(branch), pathList.isEmpty, info, error){
|
||||
<div class="head">
|
||||
@helper.html.dropdown(
|
||||
value = if(branch.length == 40) branch.substring(0, 10) else branch,
|
||||
prefix = if(branch.length == 40) "tree" else if(repository.branchList.contains(branch)) "branch" else "tree",
|
||||
mini = true
|
||||
@helper.html.branchcontrol(
|
||||
branch,
|
||||
repository,
|
||||
hasWritePermission
|
||||
){
|
||||
@repository.branchList.map { x =>
|
||||
<li><a href="@url(repository)/tree/@encodeRefName(x)">@helper.html.checkicon(x == branch) @x</a></li>
|
||||
@@ -47,13 +49,13 @@
|
||||
<div class="author">
|
||||
@avatar(latestCommit, 20)
|
||||
<span>@user(latestCommit.authorName, latestCommit.authorEmailAddress, "username strong")</span>
|
||||
<span class="muted"> authored on @datetime(latestCommit.authorTime)</span>
|
||||
<span class="muted"> authored @helper.html.datetimeago(latestCommit.authorTime)</span>
|
||||
</div>
|
||||
@if(latestCommit.isDifferentFromAuthor) {
|
||||
<div class="committer">
|
||||
<span class="icon-arrow-right"></span>
|
||||
<span>@user(latestCommit.committerName, latestCommit.committerEmailAddress, "username strong")</span>
|
||||
<span class="muted"> committed on @datetime(latestCommit.commitTime)</span>
|
||||
<span class="muted"> committed @helper.html.datetimeago(latestCommit.commitTime)</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -106,7 +108,7 @@
|
||||
<a href="@url(repository)/commit/@file.commitId" class="commit-message">@link(file.message, repository)</a>
|
||||
[@user(file.author, file.mailAddress)]
|
||||
</td>
|
||||
<td style="text-align: right;">@datetime(file.time)</td>
|
||||
<td style="text-align: right;">@helper.html.datetimeago(file.time, false)</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
@repository.tags.reverse.map { tag =>
|
||||
<tr>
|
||||
<td><a href="@url(repository)/tree/@encodeRefName(tag.name)">@tag.name</a></td>
|
||||
<td>@datetime(tag.time)</td>
|
||||
<td>@helper.html.datetimeago(tag.time, false)</td>
|
||||
<td class="monospace"><a href="@url(repository)/commit/@tag.id">@tag.id.substring(0, 10)</a></td>
|
||||
<td>
|
||||
<a href="@url(repository)/archive/@{encodeRefName(tag.name)}.zip">ZIP</a>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
@files.drop((page - 1) * CodeLimit).take(CodeLimit).map { file =>
|
||||
<div>
|
||||
<h5><a href="@url(repository)/blob/@repository.repository.defaultBranch/@file.path">@file.path</a></h5>
|
||||
<div class="small muted">Latest commit at @datetime(file.lastModified)</div>
|
||||
<div class="small muted">Last commited @helper.html.datetimeago(file.lastModified)</div>
|
||||
<pre class="prettyprint linenums:@file.highlightLineNumber" style="padding-left: 25px;">@Html(file.highlightText)</pre>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
}
|
||||
<div class="small muted">
|
||||
Opened by <a href="@url(issue.openedUserName)" class="username">@issue.openedUserName</a>
|
||||
at @datetime(issue.registeredDate)
|
||||
@helper.html.datetimeago(issue.registeredDate)
|
||||
@if(issue.commentCount > 0){
|
||||
<i class="icon-comment"></i><span class="strong">@issue.commentCount</span> @plural(issue.commentCount, "comment")
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<form action="@url(repository)/wiki/@if(page.isEmpty){_new} else {_edit}" method="POST" validate="true">
|
||||
<span id="error-pageName" class="error"></span>
|
||||
<input type="text" name="pageName" value="@pageName" style="width: 850px; font-weight: bold;" placeholder="Input a page name."/>
|
||||
@helper.html.preview(repository, page.map(_.content).getOrElse(""), true, false, "width: 850px; height: 400px;", "")
|
||||
@helper.html.preview(repository, page.map(_.content).getOrElse(""), true, false, false, false, "width: 850px; height: 400px;", "")
|
||||
<input type="text" name="message" value="" style="width: 850px;" placeholder="Write a small message here explaining this change. (Optional)"/>
|
||||
<input type="hidden" name="currentPageName" value="@pageName"/>
|
||||
<input type="hidden" name="id" value="@page.map(_.id)"/>
|
||||
@@ -36,4 +36,4 @@ $(function(){
|
||||
return confirm('Are you sure you want to delete this page?');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<td width="0%"><input type="checkbox" name="commitId" value="@commit.id"></td>
|
||||
<td>@avatar(commit, 20) @user(commit.authorName, commit.authorEmailAddress)</td>
|
||||
<td width="80%">
|
||||
<span class="muted">@datetime(commit.authorTime):</span> @commit.shortMessage
|
||||
<span class="muted">@helper.html.datetimeago(commit.authorTime):</span> @commit.shortMessage
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<li>
|
||||
<h1 class="wiki-title">@pageName</h1>
|
||||
<div class="small">
|
||||
<span class="muted"><strong>@page.committer</strong> edited this page at @datetime(page.time)</span>
|
||||
<span class="muted"><strong>@page.committer</strong> edited this page @helper.html.datetimeago(page.time)</span>
|
||||
</div>
|
||||
</li>
|
||||
<li class="pull-right">
|
||||
|
||||
@@ -617,6 +617,30 @@ span.simplified-path {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
#branch-control-title {
|
||||
margin: 5px 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#branch-control-close {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #aaa;
|
||||
font-weight: bold;
|
||||
line-height: 15px;
|
||||
}
|
||||
|
||||
#branch-control-input {
|
||||
border: solid 1px #ccc;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.new-branch-name {
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* nav pulls group */
|
||||
/****************************************************************************/
|
||||
@@ -877,6 +901,20 @@ div.attachable div.clickable {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
ul.task-list {
|
||||
padding-left: 2em;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
li.task-list-item {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
li.task-list-item input.task-list-item-checkbox {
|
||||
margin: 0 4px 0.25em -20px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Pull Request */
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -25,4 +25,69 @@ class GitBucketHtmlSerializerSpec extends Specification {
|
||||
after mustEqual "foo%21bar%40baz%3e9000"
|
||||
}
|
||||
}
|
||||
|
||||
"escapeTaskList" should {
|
||||
"convert '- [ ] ' to '* task: :'" in {
|
||||
val before = "- [ ] aaaa"
|
||||
val after = escapeTaskList(before)
|
||||
after mustEqual "* task: : aaaa"
|
||||
}
|
||||
|
||||
"convert ' - [ ] ' to ' * task: :'" in {
|
||||
val before = " - [ ] aaaa"
|
||||
val after = escapeTaskList(before)
|
||||
after mustEqual " * task: : aaaa"
|
||||
}
|
||||
|
||||
"convert only first '- [ ] '" in {
|
||||
val before = " - [ ] aaaa - [ ] bbb"
|
||||
val after = escapeTaskList(before)
|
||||
after mustEqual " * task: : aaaa - [ ] bbb"
|
||||
}
|
||||
|
||||
"convert '- [x] ' to '* task:x:'" in {
|
||||
val before = " - [x] aaaa"
|
||||
val after = escapeTaskList(before)
|
||||
after mustEqual " * task:x: aaaa"
|
||||
}
|
||||
|
||||
"convert multi lines" in {
|
||||
val before = """
|
||||
tasks
|
||||
- [x] aaaa
|
||||
- [ ] bbb
|
||||
"""
|
||||
val after = escapeTaskList(before)
|
||||
after mustEqual """
|
||||
tasks
|
||||
* task:x: aaaa
|
||||
* task: : bbb
|
||||
"""
|
||||
}
|
||||
|
||||
"no convert if inserted before '- [ ] '" in {
|
||||
val before = " a - [ ] aaaa"
|
||||
val after = escapeTaskList(before)
|
||||
after mustEqual " a - [ ] aaaa"
|
||||
}
|
||||
|
||||
"no convert '- [] '" in {
|
||||
val before = " - [] aaaa"
|
||||
val after = escapeTaskList(before)
|
||||
after mustEqual " - [] aaaa"
|
||||
}
|
||||
|
||||
"no convert '- [ ]a'" in {
|
||||
val before = " - [ ]a aaaa"
|
||||
val after = escapeTaskList(before)
|
||||
after mustEqual " - [ ]a aaaa"
|
||||
}
|
||||
|
||||
"no convert '-[ ] '" in {
|
||||
val before = " -[ ] aaaa"
|
||||
val after = escapeTaskList(before)
|
||||
after mustEqual " -[ ] aaaa"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user