From ce79eaada80a9210c636c6a22a248dd6c76c54d2 Mon Sep 17 00:00:00 2001 From: bati11 Date: Sat, 5 Apr 2014 20:31:30 +0900 Subject: [PATCH 001/152] Add escapeTaskList method, it escapse '- [] ' characters --- src/main/scala/view/Markdown.scala | 5 ++ .../view/GitBucketHtmlSerializerSpec.scala | 65 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/main/scala/view/Markdown.scala b/src/main/scala/view/Markdown.scala index 4d998bd27..c347d14ad 100644 --- a/src/main/scala/view/Markdown.scala +++ b/src/main/scala/view/Markdown.scala @@ -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} @@ -149,4 +150,8 @@ object GitBucketHtmlSerializer { val noSpecialChars = StringUtil.urlEncode(normalized) noSpecialChars.toLowerCase(Locale.ENGLISH) } + + def escapeTaskList(text: String): String = { + Pattern.compile("""^ *- \[([x| ])\] """, Pattern.MULTILINE).matcher(text).replaceAll("task:$1: ") + } } diff --git a/src/test/scala/view/GitBucketHtmlSerializerSpec.scala b/src/test/scala/view/GitBucketHtmlSerializerSpec.scala index 946b62629..5b49c886a 100644 --- a/src/test/scala/view/GitBucketHtmlSerializerSpec.scala +++ b/src/test/scala/view/GitBucketHtmlSerializerSpec.scala @@ -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: :'" 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" + } + } } + From 843722f82ef4c911cff81db1357b2ca2b260368d Mon Sep 17 00:00:00 2001 From: bati11 Date: Sun, 6 Apr 2014 00:45:19 +0900 Subject: [PATCH 002/152] Implement the feature "Task List" --- src/main/scala/app/IssuesController.scala | 4 +- .../app/RepositoryViewerController.scala | 3 +- src/main/scala/view/Markdown.scala | 29 +++++++++--- src/main/scala/view/helpers.scala | 4 +- src/main/twirl/helper/preview.scala.html | 5 ++- src/main/twirl/issues/commentform.scala.html | 4 +- src/main/twirl/issues/commentlist.scala.html | 45 +++++++++++++++++-- src/main/twirl/issues/create.scala.html | 2 +- src/main/twirl/issues/issuedetail.scala.html | 40 ++++++++++++++++- src/main/twirl/pulls/compare.scala.html | 2 +- src/main/twirl/wiki/edit.scala.html | 4 +- 11 files changed, 117 insertions(+), 25 deletions(-) diff --git a/src/main/scala/app/IssuesController.scala b/src/main/scala/app/IssuesController.scala index be564ee39..b8f168208 100644 --- a/src/main/scala/app/IssuesController.scala +++ b/src/main/scala/app/IssuesController.scala @@ -186,7 +186,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) )) } } else Unauthorized @@ -203,7 +203,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) )) } } else Unauthorized diff --git a/src/main/scala/app/RepositoryViewerController.scala b/src/main/scala/app/RepositoryViewerController.scala index dda0e6147..c38eb011e 100644 --- a/src/main/scala/app/RepositoryViewerController.scala +++ b/src/main/scala/app/RepositoryViewerController.scala @@ -30,7 +30,8 @@ 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) }) /** diff --git a/src/main/scala/view/Markdown.scala b/src/main/scala/view/Markdown.scala index c347d14ad..f83ef10d7 100644 --- a/src/main/scala/view/Markdown.scala +++ b/src/main/scala/view/Markdown.scala @@ -11,7 +11,7 @@ import java.text.Normalizer import java.util.Locale import java.util.regex.Pattern import scala.collection.JavaConverters._ -import service.{RequestCache, WikiService} +import service.{RepositoryService, RequestCache, WikiService} object Markdown { @@ -19,17 +19,22 @@ 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)(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).toHtml(rootNode) } } @@ -83,11 +88,12 @@ class GitBucketHtmlSerializer( markdown: String, repository: service.RepositoryService.RepositoryInfo, enableWikiLink: Boolean, - enableRefsLink: Boolean + enableRefsLink: Boolean, + enableTaskList: Boolean )(implicit val context: app.Context) extends ToHtmlSerializer( new GitBucketLinkRender(context, repository, enableWikiLink), Map[String, VerbatimSerializer](VerbatimSerializer.DEFAULT -> new GitBucketVerbatimSerializer).asJava - ) with LinkConverter with RequestCache { + ) with RepositoryService with LinkConverter with RequestCache { override protected def printImageTag(imageNode: SuperNode, url: String): Unit = printer.print("\"").printEncoded(printChildrenToString(imageNode)).print("\"/") @@ -130,7 +136,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(repository.owner, repository.name, context.loginAccount)) else t if (abbreviations.isEmpty) { printer.print(text) @@ -154,4 +163,10 @@ object GitBucketHtmlSerializer { def escapeTaskList(text: String): String = { Pattern.compile("""^ *- \[([x| ])\] """, Pattern.MULTILINE).matcher(text).replaceAll("task:$1: ") } + + def convertCheckBox(text: String, hasWritePermission: Boolean): String = { + val disabled = if (hasWritePermission) "" else "disabled" + text.replaceAll("task:x:", """") + .replaceAll("task: :", """") + } } diff --git a/src/main/scala/view/helpers.scala b/src/main/scala/view/helpers.scala index feb5f21fb..774c0346b 100644 --- a/src/main/scala/view/helpers.scala +++ b/src/main/scala/view/helpers.scala @@ -41,8 +41,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)(implicit context: app.Context): Html = + Html(Markdown.toHtml(value, repository, enableWikiLink, enableRefsLink, enableTaskList)) def renderMarkup(filePath: List[String], fileContent: String, branch: String, repository: service.RepositoryService.RepositoryInfo, diff --git a/src/main/twirl/helper/preview.scala.html b/src/main/twirl/helper/preview.scala.html index cc6504bdc..1586128de 100644 --- a/src/main/twirl/helper/preview.scala.html +++ b/src/main/twirl/helper/preview.scala.html @@ -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, style: String = "", placeholder: String = "Leave a comment", elastic: Boolean = false)(implicit context: app.Context) @import context._ @import view.helpers._ @@ -36,7 +36,8 @@ $(function(){ $.post('@url(repository)/_preview', { content : $('#content').val(), enableWikiLink : @enableWikiLink, - enableRefsLink : @enableRefsLink + enableRefsLink : @enableRefsLink, + enableTaskList : @enableTaskList }, function(data){ $('#preview-area').html(data); prettyPrint(); diff --git a/src/main/twirl/issues/commentform.scala.html b/src/main/twirl/issues/commentform.scala.html index edf656eaf..e4a6836c8 100644 --- a/src/main/twirl/issues/commentform.scala.html +++ b/src/main/twirl/issues/commentform.scala.html @@ -8,7 +8,7 @@
@avatar(loginAccount.get.userName, 48)
- @helper.html.preview(repository, "", false, true, "width: 680px; height: 100px; max-height: 150px;", elastic = true) + @helper.html.preview(repository, "", false, true, true, "width: 680px; height: 100px; max-height: 150px;", elastic = true)
@@ -26,4 +26,4 @@ $(function(){ $('').attr('name', 'action').val($(this).val().toLowerCase()).appendTo('form'); }); }); - \ No newline at end of file + diff --git a/src/main/twirl/issues/commentlist.scala.html b/src/main/twirl/issues/commentlist.scala.html index 92a82f75c..0c3399aef 100644 --- a/src/main/twirl/issues/commentlist.scala.html +++ b/src/main/twirl/issues/commentlist.scala.html @@ -30,7 +30,7 @@ @if(comment.action == "commit" && comment.content.split(" ").last.matches("[a-f0-9]{40}")){ @defining(comment.content.substring(comment.content.length - 40)){ id => - @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) } } else { @if(comment.action == "refer"){ @@ -38,7 +38,7 @@ Issue #@issueId: @rest.mkString(":") } } else { - @markdown(comment.content, repository, false, true) + @markdown(comment.content, repository, false, true, true) } }
@@ -109,5 +109,44 @@ $(function(){ } return false; }); + + var extractMarkdown = function(data){ + $('body').append('
'); + $('#tmp').html(data); + var markdown = $('#tmp textarea').val(); + $('#tmp').remove(); + return markdown; + }; + + $('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(data){ + var ss = [], + markdown = extractMarkdown(data), + xs = markdown.split(/- \[[x| ]\]/g); + for (var i=0; i \ No newline at end of file + diff --git a/src/main/twirl/issues/create.scala.html b/src/main/twirl/issues/create.scala.html index b82884c5b..b91456ace 100644 --- a/src/main/twirl/issues/create.scala.html +++ b/src/main/twirl/issues/create.scala.html @@ -56,7 +56,7 @@
- @helper.html.preview(repository, "", false, true, "width: 600px; height: 200px; max-height: 250px;", elastic = true) + @helper.html.preview(repository, "", false, true, true, "width: 600px; height: 200px; max-height: 250px;", elastic = true)
diff --git a/src/main/twirl/issues/issuedetail.scala.html b/src/main/twirl/issues/issuedetail.scala.html index df678d1ef..d6975619f 100644 --- a/src/main/twirl/issues/issuedetail.scala.html +++ b/src/main/twirl/issues/issuedetail.scala.html @@ -77,7 +77,7 @@
- @markdown(issue.content getOrElse "No description given.", repository, false, true) + @markdown(issue.content getOrElse "No description given.", repository, false, true, true)
@@ -141,5 +141,41 @@ $(function(){ } }); }); + + var extractMarkdown = function(data){ + $('body').append('
'); + $('#tmp').html(data); + var markdown = $('#tmp textarea').val(); + $('#tmp').remove(); + return markdown; + }; + + $('#issueContent').on('click', ':checkbox', function(ev){ + var checkboxes = $('#issueContent :checkbox'); + $.get('@url(repository)/issues/_data/@issue.issueId', + { + dataType : 'html' + }, + function(data){ + var ss = [], + markdown = extractMarkdown(data), + xs = markdown.split(/- \[[x| ]\]/g); + for (var i=0; i \ No newline at end of file + diff --git a/src/main/twirl/pulls/compare.scala.html b/src/main/twirl/pulls/compare.scala.html index 92fc8f813..ddf679e0d 100644 --- a/src/main/twirl/pulls/compare.scala.html +++ b/src/main/twirl/pulls/compare.scala.html @@ -58,7 +58,7 @@
- @helper.html.preview(repository, "", false, true, "width: 600px; height: 200px;") + @helper.html.preview(repository, "", false, true, true, "width: 600px; height: 200px;") diff --git a/src/main/twirl/wiki/edit.scala.html b/src/main/twirl/wiki/edit.scala.html index d75ccbb39..9e7c5fc56 100644 --- a/src/main/twirl/wiki/edit.scala.html +++ b/src/main/twirl/wiki/edit.scala.html @@ -23,7 +23,7 @@
- @helper.html.preview(repository, page.map(_.content).getOrElse(""), true, false, "width: 900px; height: 400px;", "") + @helper.html.preview(repository, page.map(_.content).getOrElse(""), true, false, false, "width: 900px; height: 400px;", "") @@ -36,4 +36,4 @@ $(function(){ return confirm('Are you sure you want to delete this page?'); }); }); - \ No newline at end of file + From b13820fc0e88caa30713325898d414794eff2db2 Mon Sep 17 00:00:00 2001 From: shimamoto Date: Mon, 28 Jul 2014 04:52:56 +0900 Subject: [PATCH 003/152] Improved model package. The details are as follows: * Fix the Profiles class from package object to simple object * Fix the row case class to model package * Define the alias of JdbcBackend#Session --- src/main/scala/model/Account.scala | 31 +++++++++---------- src/main/scala/model/Activity.scala | 22 ++++++------- src/main/scala/model/Collaborator.scala | 12 +++---- src/main/scala/model/GroupMembers.scala | 12 +++---- src/main/scala/model/Issue.scala | 29 ++++++++--------- src/main/scala/model/IssueComment.scala | 24 +++++++------- src/main/scala/model/IssueLabels.scala | 13 ++++---- src/main/scala/model/Labels.scala | 30 +++++++++--------- src/main/scala/model/Milestone.scala | 19 ++++++------ src/main/scala/model/Profile.scala | 26 +++++++++++++++- src/main/scala/model/PullRequest.scala | 24 +++++++------- src/main/scala/model/Repository.scala | 30 +++++++++--------- src/main/scala/model/SshKey.scala | 14 ++++----- src/main/scala/model/WebHook.scala | 12 +++---- src/main/scala/model/package.scala | 22 ++----------- src/main/scala/service/AccountService.scala | 5 +-- src/main/scala/service/ActivityService.scala | 3 +- src/main/scala/service/IssuesService.scala | 3 +- src/main/scala/service/LabelsService.scala | 3 +- .../scala/service/MilestonesService.scala | 5 +-- .../scala/service/PullRequestService.scala | 3 +- .../service/RepositorySearchService.scala | 4 +-- .../scala/service/RepositoryService.scala | 3 +- src/main/scala/service/RequestCache.scala | 5 ++- src/main/scala/service/SshKeyService.scala | 3 +- src/main/scala/service/WebHookService.scala | 3 +- .../servlet/BasicAuthenticationFilter.scala | 3 +- .../scala/servlet/GitRepositoryServlet.scala | 4 +-- .../servlet/PluginActionInvokeFilter.scala | 4 +-- src/main/scala/ssh/GitCommand.scala | 2 +- src/main/scala/util/Notifier.scala | 2 +- 31 files changed, 195 insertions(+), 180 deletions(-) diff --git a/src/main/scala/model/Account.scala b/src/main/scala/model/Account.scala index ca7aff53f..012c559cc 100644 --- a/src/main/scala/model/Account.scala +++ b/src/main/scala/model/Account.scala @@ -21,20 +21,19 @@ trait AccountComponent { self: Profile => val removed = column[Boolean]("REMOVED") def * = (userName, fullName, mailAddress, password, isAdmin, url.?, registeredDate, updatedDate, lastLoginDate.?, image.?, groupAccount, removed) <> (Account.tupled, Account.unapply) } - - case class Account( - - userName: String, - fullName: String, - mailAddress: String, - password: String, - isAdmin: Boolean, - url: Option[String], - registeredDate: java.util.Date, - updatedDate: java.util.Date, - lastLoginDate: Option[java.util.Date], - image: Option[String], - isGroupAccount: Boolean, - isRemoved: Boolean - ) } + +case class Account( + userName: String, + fullName: String, + mailAddress: String, + password: String, + isAdmin: Boolean, + url: Option[String], + registeredDate: java.util.Date, + updatedDate: java.util.Date, + lastLoginDate: Option[java.util.Date], + image: Option[String], + isGroupAccount: Boolean, + isRemoved: Boolean +) diff --git a/src/main/scala/model/Activity.scala b/src/main/scala/model/Activity.scala index 7977047f5..8e3960ef2 100644 --- a/src/main/scala/model/Activity.scala +++ b/src/main/scala/model/Activity.scala @@ -15,15 +15,15 @@ trait ActivityComponent extends TemplateComponent { self: Profile => val activityDate = column[java.util.Date]("ACTIVITY_DATE") def * = (userName, repositoryName, activityUserName, activityType, message, additionalInfo.?, activityDate, activityId) <> (Activity.tupled, Activity.unapply) } - - case class Activity( - userName: String, - repositoryName: String, - activityUserName: String, - activityType: String, - message: String, - additionalInfo: Option[String], - activityDate: java.util.Date, - activityId: Int = 0 - ) } + +case class Activity( + userName: String, + repositoryName: String, + activityUserName: String, + activityType: String, + message: String, + additionalInfo: Option[String], + activityDate: java.util.Date, + activityId: Int = 0 +) diff --git a/src/main/scala/model/Collaborator.scala b/src/main/scala/model/Collaborator.scala index 7ef52e0c0..1b96872fc 100644 --- a/src/main/scala/model/Collaborator.scala +++ b/src/main/scala/model/Collaborator.scala @@ -12,10 +12,10 @@ trait CollaboratorComponent extends TemplateComponent { self: Profile => def byPrimaryKey(owner: String, repository: String, collaborator: String) = byRepository(owner, repository) && (collaboratorName is collaborator.bind) } - - case class Collaborator( - userName: String, - repositoryName: String, - collaboratorName: String - ) } + +case class Collaborator( + userName: String, + repositoryName: String, + collaboratorName: String +) diff --git a/src/main/scala/model/GroupMembers.scala b/src/main/scala/model/GroupMembers.scala index 966bdbaa5..f0161d350 100644 --- a/src/main/scala/model/GroupMembers.scala +++ b/src/main/scala/model/GroupMembers.scala @@ -11,10 +11,10 @@ trait GroupMemberComponent { self: Profile => val isManager = column[Boolean]("MANAGER") def * = (groupName, userName, isManager) <> (GroupMember.tupled, GroupMember.unapply) } - - case class GroupMember( - groupName: String, - userName: String, - isManager: Boolean - ) } + +case class GroupMember( + groupName: String, + userName: String, + isManager: Boolean +) diff --git a/src/main/scala/model/Issue.scala b/src/main/scala/model/Issue.scala index d18c09839..85c6014b3 100644 --- a/src/main/scala/model/Issue.scala +++ b/src/main/scala/model/Issue.scala @@ -31,18 +31,19 @@ trait IssueComponent extends TemplateComponent { self: Profile => def byPrimaryKey(owner: String, repository: String, issueId: Int) = byIssue(owner, repository, issueId) } - - case class Issue( - userName: String, - repositoryName: String, - issueId: Int, - openedUserName: String, - milestoneId: Option[Int], - assignedUserName: Option[String], - title: String, - content: Option[String], - closed: Boolean, - registeredDate: java.util.Date, - updatedDate: java.util.Date, - isPullRequest: Boolean) } + +case class Issue( + userName: String, + repositoryName: String, + issueId: Int, + openedUserName: String, + milestoneId: Option[Int], + assignedUserName: Option[String], + title: String, + content: Option[String], + closed: Boolean, + registeredDate: java.util.Date, + updatedDate: java.util.Date, + isPullRequest: Boolean +) diff --git a/src/main/scala/model/IssueComment.scala b/src/main/scala/model/IssueComment.scala index 8d42702dc..8d5e2be71 100644 --- a/src/main/scala/model/IssueComment.scala +++ b/src/main/scala/model/IssueComment.scala @@ -19,16 +19,16 @@ trait IssueCommentComponent extends TemplateComponent { self: Profile => def byPrimaryKey(commentId: Int) = this.commentId is commentId.bind } - - case class IssueComment( - userName: String, - repositoryName: String, - issueId: Int, - commentId: Int = 0, - action: String, - commentedUserName: String, - content: String, - registeredDate: java.util.Date, - updatedDate: java.util.Date - ) } + +case class IssueComment( + userName: String, + repositoryName: String, + issueId: Int, + commentId: Int = 0, + action: String, + commentedUserName: String, + content: String, + registeredDate: java.util.Date, + updatedDate: java.util.Date +) diff --git a/src/main/scala/model/IssueLabels.scala b/src/main/scala/model/IssueLabels.scala index 413dbd723..d6b83c16b 100644 --- a/src/main/scala/model/IssueLabels.scala +++ b/src/main/scala/model/IssueLabels.scala @@ -10,10 +10,11 @@ trait IssueLabelComponent extends TemplateComponent { self: Profile => def byPrimaryKey(owner: String, repository: String, issueId: Int, labelId: Int) = byIssue(owner, repository, issueId) && (this.labelId is labelId.bind) } - - case class IssueLabel( - userName: String, - repositoryName: String, - issueId: Int, - labelId: Int) } + +case class IssueLabel( + userName: String, + repositoryName: String, + issueId: Int, + labelId: Int +) diff --git a/src/main/scala/model/Labels.scala b/src/main/scala/model/Labels.scala index 13e66d9c4..e36746aa3 100644 --- a/src/main/scala/model/Labels.scala +++ b/src/main/scala/model/Labels.scala @@ -14,24 +14,24 @@ trait LabelComponent extends TemplateComponent { self: Profile => def byPrimaryKey(owner: String, repository: String, labelId: Int) = byLabel(owner, repository, labelId) def byPrimaryKey(userName: Column[String], repositoryName: Column[String], labelId: Column[Int]) = byLabel(userName, repositoryName, labelId) } +} - case class Label( - userName: String, - repositoryName: String, - labelId: Int = 0, - labelName: String, - color: String){ +case class Label( + userName: String, + repositoryName: String, + labelId: Int = 0, + labelName: String, + color: String){ - val fontColor = { - val r = color.substring(0, 2) - val g = color.substring(2, 4) - val b = color.substring(4, 6) + val fontColor = { + val r = color.substring(0, 2) + val g = color.substring(2, 4) + val b = color.substring(4, 6) - if(Integer.parseInt(r, 16) + Integer.parseInt(g, 16) + Integer.parseInt(b, 16) > 408){ - "000000" - } else { - "FFFFFF" - } + if(Integer.parseInt(r, 16) + Integer.parseInt(g, 16) + Integer.parseInt(b, 16) > 408){ + "000000" + } else { + "FFFFFF" } } } diff --git a/src/main/scala/model/Milestone.scala b/src/main/scala/model/Milestone.scala index 3aa4314b4..c392219b8 100644 --- a/src/main/scala/model/Milestone.scala +++ b/src/main/scala/model/Milestone.scala @@ -17,13 +17,14 @@ trait MilestoneComponent extends TemplateComponent { self: Profile => def byPrimaryKey(owner: String, repository: String, milestoneId: Int) = byMilestone(owner, repository, milestoneId) def byPrimaryKey(userName: Column[String], repositoryName: Column[String], milestoneId: Column[Int]) = byMilestone(userName, repositoryName, milestoneId) } - - case class Milestone( - userName: String, - repositoryName: String, - milestoneId: Int = 0, - title: String, - description: Option[String], - dueDate: Option[java.util.Date], - closedDate: Option[java.util.Date]) } + +case class Milestone( + userName: String, + repositoryName: String, + milestoneId: Int = 0, + title: String, + description: Option[String], + dueDate: Option[java.util.Date], + closedDate: Option[java.util.Date] +) diff --git a/src/main/scala/model/Profile.scala b/src/main/scala/model/Profile.scala index 3d2a2e7bc..9bfee3b6c 100644 --- a/src/main/scala/model/Profile.scala +++ b/src/main/scala/model/Profile.scala @@ -1,7 +1,7 @@ package model trait Profile { - val profile = slick.driver.H2Driver + val profile: slick.driver.JdbcProfile import profile.simple._ // java.util.Date Mapped Column Types @@ -15,3 +15,27 @@ trait Profile { } } + +object Profile extends { + val profile = slick.driver.H2Driver + +} with AccountComponent + with ActivityComponent + with CollaboratorComponent + with GroupMemberComponent + with IssueComponent + with IssueCommentComponent + with IssueLabelComponent + with LabelComponent + with MilestoneComponent + with PullRequestComponent + with RepositoryComponent + with SshKeyComponent + with WebHookComponent with Profile { + + /** + * Returns system date. + */ + def currentDate = new java.util.Date() + +} diff --git a/src/main/scala/model/PullRequest.scala b/src/main/scala/model/PullRequest.scala index 500e8ab42..3ba87ea40 100644 --- a/src/main/scala/model/PullRequest.scala +++ b/src/main/scala/model/PullRequest.scala @@ -17,16 +17,16 @@ trait PullRequestComponent extends TemplateComponent { self: Profile => def byPrimaryKey(userName: String, repositoryName: String, issueId: Int) = byIssue(userName, repositoryName, issueId) def byPrimaryKey(userName: Column[String], repositoryName: Column[String], issueId: Column[Int]) = byIssue(userName, repositoryName, issueId) } - - case class PullRequest( - userName: String, - repositoryName: String, - issueId: Int, - branch: String, - requestUserName: String, - requestRepositoryName: String, - requestBranch: String, - commitIdFrom: String, - commitIdTo: String - ) } + +case class PullRequest( + userName: String, + repositoryName: String, + issueId: Int, + branch: String, + requestUserName: String, + requestRepositoryName: String, + requestBranch: String, + commitIdFrom: String, + commitIdTo: String +) diff --git a/src/main/scala/model/Repository.scala b/src/main/scala/model/Repository.scala index fe0df8a8b..5a888fc4a 100644 --- a/src/main/scala/model/Repository.scala +++ b/src/main/scala/model/Repository.scala @@ -21,19 +21,19 @@ trait RepositoryComponent extends TemplateComponent { self: Profile => def byPrimaryKey(owner: String, repository: String) = byRepository(owner, repository) } - - case class Repository( - userName: String, - repositoryName: String, - isPrivate: Boolean, - description: Option[String], - defaultBranch: String, - registeredDate: java.util.Date, - updatedDate: java.util.Date, - lastActivityDate: java.util.Date, - originUserName: Option[String], - originRepositoryName: Option[String], - parentUserName: Option[String], - parentRepositoryName: Option[String] - ) } + +case class Repository( + userName: String, + repositoryName: String, + isPrivate: Boolean, + description: Option[String], + defaultBranch: String, + registeredDate: java.util.Date, + updatedDate: java.util.Date, + lastActivityDate: java.util.Date, + originUserName: Option[String], + originRepositoryName: Option[String], + parentUserName: Option[String], + parentRepositoryName: Option[String] +) diff --git a/src/main/scala/model/SshKey.scala b/src/main/scala/model/SshKey.scala index 5106ab203..d1d0aab5d 100644 --- a/src/main/scala/model/SshKey.scala +++ b/src/main/scala/model/SshKey.scala @@ -14,11 +14,11 @@ trait SshKeyComponent { self: Profile => def byPrimaryKey(userName: String, sshKeyId: Int) = (this.userName is userName.bind) && (this.sshKeyId is sshKeyId.bind) } - - case class SshKey( - userName: String, - sshKeyId: Int = 0, - title: String, - publicKey: String - ) } + +case class SshKey( + userName: String, + sshKeyId: Int = 0, + title: String, + publicKey: String +) diff --git a/src/main/scala/model/WebHook.scala b/src/main/scala/model/WebHook.scala index da7fb8fbc..8eb3719e1 100644 --- a/src/main/scala/model/WebHook.scala +++ b/src/main/scala/model/WebHook.scala @@ -11,10 +11,10 @@ trait WebHookComponent extends TemplateComponent { self: Profile => def byPrimaryKey(owner: String, repository: String, url: String) = byRepository(owner, repository) && (this.url is url.bind) } - - case class WebHook( - userName: String, - repositoryName: String, - url: String - ) } + +case class WebHook( + userName: String, + repositoryName: String, + url: String +) diff --git a/src/main/scala/model/package.scala b/src/main/scala/model/package.scala index b806c3372..c65e72e84 100644 --- a/src/main/scala/model/package.scala +++ b/src/main/scala/model/package.scala @@ -1,21 +1,3 @@ -package object model extends Profile - with AccountComponent - with ActivityComponent - with CollaboratorComponent - with GroupMemberComponent - with IssueComponent - with IssueCommentComponent - with IssueLabelComponent - with LabelComponent - with MilestoneComponent - with PullRequestComponent - with RepositoryComponent - with SshKeyComponent - with WebHookComponent { - - /** - * Returns system date. - */ - def currentDate = new java.util.Date() - +package object model { + type Session = slick.jdbc.JdbcBackend#Session } diff --git a/src/main/scala/service/AccountService.scala b/src/main/scala/service/AccountService.scala index 71934f18a..8f34dcb9b 100644 --- a/src/main/scala/service/AccountService.scala +++ b/src/main/scala/service/AccountService.scala @@ -1,9 +1,10 @@ package service -import model._ +import model.Profile._ import profile.simple._ +import model.{Account, GroupMember} // TODO [Slick 2.0]NOT import directly? -import model.dateColumnType +import model.Profile.dateColumnType import service.SystemSettingsService.SystemSettings import util.StringUtil._ import util.LDAPUtil diff --git a/src/main/scala/service/ActivityService.scala b/src/main/scala/service/ActivityService.scala index d9219dc53..127bae55e 100644 --- a/src/main/scala/service/ActivityService.scala +++ b/src/main/scala/service/ActivityService.scala @@ -1,7 +1,8 @@ package service -import model._ +import model.Profile._ import profile.simple._ +import model.Activity trait ActivityService { diff --git a/src/main/scala/service/IssuesService.scala b/src/main/scala/service/IssuesService.scala index 2c4a7fd94..c123be957 100644 --- a/src/main/scala/service/IssuesService.scala +++ b/src/main/scala/service/IssuesService.scala @@ -3,8 +3,9 @@ package service import scala.slick.jdbc.{StaticQuery => Q} import Q.interpolation -import model._ +import model.Profile._ import profile.simple._ +import model.{Issue, IssueComment, IssueLabel, Label} import util.Implicits._ import util.StringUtil._ diff --git a/src/main/scala/service/LabelsService.scala b/src/main/scala/service/LabelsService.scala index 251e5fd32..37c3d35c4 100644 --- a/src/main/scala/service/LabelsService.scala +++ b/src/main/scala/service/LabelsService.scala @@ -1,7 +1,8 @@ package service -import model._ +import model.Profile._ import profile.simple._ +import model.Label trait LabelsService { diff --git a/src/main/scala/service/MilestonesService.scala b/src/main/scala/service/MilestonesService.scala index 2f73f227b..e9b27becd 100644 --- a/src/main/scala/service/MilestonesService.scala +++ b/src/main/scala/service/MilestonesService.scala @@ -1,9 +1,10 @@ package service -import model._ +import model.Profile._ import profile.simple._ +import model.Milestone // TODO [Slick 2.0]NOT import directly? -import model.dateColumnType +import model.Profile.dateColumnType trait MilestonesService { diff --git a/src/main/scala/service/PullRequestService.scala b/src/main/scala/service/PullRequestService.scala index c91abe1d3..619f2fa78 100644 --- a/src/main/scala/service/PullRequestService.scala +++ b/src/main/scala/service/PullRequestService.scala @@ -1,7 +1,8 @@ package service -import model._ +import model.Profile._ import profile.simple._ +import model.{PullRequest, Issue} trait PullRequestService { self: IssuesService => import PullRequestService._ diff --git a/src/main/scala/service/RepositorySearchService.scala b/src/main/scala/service/RepositorySearchService.scala index 292507c06..e31d6da25 100644 --- a/src/main/scala/service/RepositorySearchService.scala +++ b/src/main/scala/service/RepositorySearchService.scala @@ -7,7 +7,7 @@ import org.eclipse.jgit.revwalk.RevWalk import org.eclipse.jgit.treewalk.TreeWalk import org.eclipse.jgit.lib.FileMode import org.eclipse.jgit.api.Git -import model._ +import model.Profile._ import profile.simple._ trait RepositorySearchService { self: IssuesService => @@ -107,7 +107,7 @@ object RepositorySearchService { case class SearchResult( files : List[(String, String)], - issues: List[(Issue, Int, String)]) + issues: List[(model.Issue, Int, String)]) case class IssueSearchResult( issueId: Int, diff --git a/src/main/scala/service/RepositoryService.scala b/src/main/scala/service/RepositoryService.scala index 5a9fec699..2adcca8b8 100644 --- a/src/main/scala/service/RepositoryService.scala +++ b/src/main/scala/service/RepositoryService.scala @@ -1,7 +1,8 @@ package service -import model._ +import model.Profile._ import profile.simple._ +import model.{Repository, Account, Collaborator} import util.JGitUtil trait RepositoryService { self: AccountService => diff --git a/src/main/scala/service/RequestCache.scala b/src/main/scala/service/RequestCache.scala index 34c5ef3d2..4ff502b5e 100644 --- a/src/main/scala/service/RequestCache.scala +++ b/src/main/scala/service/RequestCache.scala @@ -1,7 +1,6 @@ package service -import model._ -import slick.jdbc.JdbcBackend +import model.{Account, Issue, Session} import util.Implicits.request2Session /** @@ -12,7 +11,7 @@ import util.Implicits.request2Session */ trait RequestCache extends SystemSettingsService with AccountService with IssuesService { - private implicit def context2Session(implicit context: app.Context): JdbcBackend#Session = + private implicit def context2Session(implicit context: app.Context): Session = request2Session(context.request) def getIssue(userName: String, repositoryName: String, issueId: String) diff --git a/src/main/scala/service/SshKeyService.scala b/src/main/scala/service/SshKeyService.scala index d38804a0d..7d5b9aa4a 100644 --- a/src/main/scala/service/SshKeyService.scala +++ b/src/main/scala/service/SshKeyService.scala @@ -1,7 +1,8 @@ package service -import model._ +import model.Profile._ import profile.simple._ +import model.SshKey trait SshKeyService { diff --git a/src/main/scala/service/WebHookService.scala b/src/main/scala/service/WebHookService.scala index 9061a0733..9f3f11ed9 100644 --- a/src/main/scala/service/WebHookService.scala +++ b/src/main/scala/service/WebHookService.scala @@ -1,7 +1,8 @@ package service -import model._ +import model.Profile._ import profile.simple._ +import model.{WebHook, Account} import org.slf4j.LoggerFactory import service.RepositoryService.RepositoryInfo import util.JGitUtil diff --git a/src/main/scala/servlet/BasicAuthenticationFilter.scala b/src/main/scala/servlet/BasicAuthenticationFilter.scala index 64d85ad63..8272c7acd 100644 --- a/src/main/scala/servlet/BasicAuthenticationFilter.scala +++ b/src/main/scala/servlet/BasicAuthenticationFilter.scala @@ -5,7 +5,6 @@ import javax.servlet.http._ import service.{SystemSettingsService, AccountService, RepositoryService} import model._ import org.slf4j.LoggerFactory -import slick.jdbc.JdbcBackend import util.Implicits._ import util.ControlUtil._ import util.Keys @@ -67,7 +66,7 @@ class BasicAuthenticationFilter extends Filter with RepositoryService with Accou } private def getWritableUser(username: String, password: String, repository: RepositoryService.RepositoryInfo) - (implicit session: JdbcBackend#Session): Option[Account] = + (implicit session: Session): Option[Account] = authenticate(loadSystemSettings(), username, password) match { case x @ Some(account) if(hasWritePermission(repository.owner, repository.name, x)) => x case _ => None diff --git a/src/main/scala/servlet/GitRepositoryServlet.scala b/src/main/scala/servlet/GitRepositoryServlet.scala index 0b1985880..bf99ba0a5 100644 --- a/src/main/scala/servlet/GitRepositoryServlet.scala +++ b/src/main/scala/servlet/GitRepositoryServlet.scala @@ -17,7 +17,7 @@ import WebHookService._ import org.eclipse.jgit.api.Git import util.JGitUtil.CommitInfo import service.IssuesService.IssueSearchCondition -import slick.jdbc.JdbcBackend +import model.Session /** * Provides Git repository via HTTP. @@ -95,7 +95,7 @@ class GitBucketReceivePackFactory extends ReceivePackFactory[HttpServletRequest] import scala.collection.JavaConverters._ -class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: String)(implicit session: JdbcBackend#Session) +class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: String)(implicit session: Session) extends PostReceiveHook with PreReceiveHook with RepositoryService with AccountService with IssuesService with ActivityService with PullRequestService with WebHookService { diff --git a/src/main/scala/servlet/PluginActionInvokeFilter.scala b/src/main/scala/servlet/PluginActionInvokeFilter.scala index 6a35121ef..eb28fea61 100644 --- a/src/main/scala/servlet/PluginActionInvokeFilter.scala +++ b/src/main/scala/servlet/PluginActionInvokeFilter.scala @@ -5,7 +5,7 @@ import javax.servlet.http.{HttpServletResponse, HttpServletRequest} import org.apache.commons.io.IOUtils import twirl.api.Html import service.{AccountService, RepositoryService, SystemSettingsService} -import model.Account +import model.{Account, Session} import util.{JGitUtil, Keys} import plugin.PluginConnectionHolder @@ -50,7 +50,7 @@ class PluginActionInvokeFilter extends Filter with SystemSettingsService with Re } private def processRepositoryAction(path: String, request: HttpServletRequest, response: HttpServletResponse) - (implicit session: model.profile.simple.Session): Boolean = { + (implicit session: Session): Boolean = { val elements = path.split("/") if(elements.length > 3){ val owner = elements(1) diff --git a/src/main/scala/ssh/GitCommand.scala b/src/main/scala/ssh/GitCommand.scala index eeb269ec6..d1d42330d 100644 --- a/src/main/scala/ssh/GitCommand.scala +++ b/src/main/scala/ssh/GitCommand.scala @@ -12,7 +12,7 @@ import servlet.{Database, CommitLogHook} import service.{AccountService, RepositoryService, SystemSettingsService} import org.eclipse.jgit.errors.RepositoryNotFoundException import javax.servlet.ServletContext -import model.profile.simple.Session +import model.Session object GitCommand { val CommandRegex = """\Agit-(upload|receive)-pack '/([a-zA-Z0-9\-_.]+)/([a-zA-Z0-9\-_.]+).git'\Z""".r diff --git a/src/main/scala/util/Notifier.scala b/src/main/scala/util/Notifier.scala index afc65aa60..ae6e25ceb 100644 --- a/src/main/scala/util/Notifier.scala +++ b/src/main/scala/util/Notifier.scala @@ -6,11 +6,11 @@ import org.apache.commons.mail.{DefaultAuthenticator, HtmlEmail} import org.slf4j.LoggerFactory import app.Context +import model.Session import service.{AccountService, RepositoryService, IssuesService, SystemSettingsService} import servlet.Database import SystemSettingsService.Smtp import _root_.util.ControlUtil.defining -import model.profile.simple.Session trait Notifier extends RepositoryService with AccountService with IssuesService { def toNotify(r: RepositoryService.RepositoryInfo, issueId: Int, content: String) From 2bb1f6168a5e10ed215a78a23c05fbc0c2f30789 Mon Sep 17 00:00:00 2001 From: Tomofumi Tanaka Date: Mon, 28 Jul 2014 23:07:26 +0900 Subject: [PATCH 004/152] (refs #437)Show author instead of committer * Explicit classify committer and author * Use author to render avatar image html * Support commit view --- .../scala/app/PullRequestsController.scala | 2 +- .../app/RepositoryViewerController.scala | 2 +- src/main/scala/service/WebHookService.scala | 6 ++--- .../scala/servlet/GitRepositoryServlet.scala | 2 +- src/main/scala/util/JGitUtil.scala | 27 ++++++++++++------- src/main/scala/view/helpers.scala | 2 +- src/main/twirl/pulls/commits.scala.html | 4 +-- src/main/twirl/repo/blob.scala.html | 4 +-- src/main/twirl/repo/commit.scala.html | 18 ++++++++++--- src/main/twirl/repo/commits.scala.html | 6 ++--- src/main/twirl/repo/files.scala.html | 4 +-- src/main/twirl/wiki/history.scala.html | 4 +-- .../webapp/assets/common/css/gitbucket.css | 9 +++++++ 13 files changed, 60 insertions(+), 30 deletions(-) diff --git a/src/main/scala/app/PullRequestsController.scala b/src/main/scala/app/PullRequestsController.scala index e7680e9af..8fd467283 100644 --- a/src/main/scala/app/PullRequestsController.scala +++ b/src/main/scala/app/PullRequestsController.scala @@ -443,7 +443,7 @@ trait PullRequestsControllerBase extends ControllerBase { val commits = newGit.log.addRange(oldId, newId).call.iterator.asScala.map { revCommit => new CommitInfo(revCommit) }.toList.splitWith { (commit1, commit2) => - view.helpers.date(commit1.time) == view.helpers.date(commit2.time) + view.helpers.date(commit1.commitTime) == view.helpers.date(commit2.commitTime) } val diffs = JGitUtil.getDiffs(newGit, oldId.getName, newId.getName, true) diff --git a/src/main/scala/app/RepositoryViewerController.scala b/src/main/scala/app/RepositoryViewerController.scala index ab2cf05cd..0fea61fb0 100644 --- a/src/main/scala/app/RepositoryViewerController.scala +++ b/src/main/scala/app/RepositoryViewerController.scala @@ -106,7 +106,7 @@ trait RepositoryViewerControllerBase extends ControllerBase { case Right((logs, hasNext)) => repo.html.commits(if(path.isEmpty) Nil else path.split("/").toList, branchName, repository, logs.splitWith{ (commit1, commit2) => - view.helpers.date(commit1.time) == view.helpers.date(commit2.time) + view.helpers.date(commit1.commitTime) == view.helpers.date(commit2.commitTime) }, page, hasNext) case Left(_) => NotFound } diff --git a/src/main/scala/service/WebHookService.scala b/src/main/scala/service/WebHookService.scala index 9061a0733..ea6501ab7 100644 --- a/src/main/scala/service/WebHookService.scala +++ b/src/main/scala/service/WebHookService.scala @@ -89,15 +89,15 @@ object WebHookService { WebHookCommit( id = commit.id, message = commit.fullMessage, - timestamp = commit.time.toString, + timestamp = commit.commitTime.toString, url = commitUrl, added = diffs._1.collect { case x if(x.changeType == DiffEntry.ChangeType.ADD) => x.newPath }, removed = diffs._1.collect { case x if(x.changeType == DiffEntry.ChangeType.DELETE) => x.oldPath }, modified = diffs._1.collect { case x if(x.changeType != DiffEntry.ChangeType.ADD && x.changeType != DiffEntry.ChangeType.DELETE) => x.newPath }, author = WebHookUser( - name = commit.committer, - email = commit.mailAddress + name = commit.committerName, + email = commit.committerEmailAddress ) ) }, diff --git a/src/main/scala/servlet/GitRepositoryServlet.scala b/src/main/scala/servlet/GitRepositoryServlet.scala index 0b1985880..747dbf57a 100644 --- a/src/main/scala/servlet/GitRepositoryServlet.scala +++ b/src/main/scala/servlet/GitRepositoryServlet.scala @@ -205,7 +205,7 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: private def createIssueComment(commit: CommitInfo) = { StringUtil.extractIssueId(commit.fullMessage).foreach { issueId => if(getIssue(owner, repository, issueId).isDefined){ - getAccountByMailAddress(commit.mailAddress).foreach { account => + getAccountByMailAddress(commit.committerEmailAddress).foreach { account => createComment(owner, repository, account.userName, issueId.toInt, commit.fullMessage + " " + commit.id, "commit") } } diff --git a/src/main/scala/util/JGitUtil.scala b/src/main/scala/util/JGitUtil.scala index f4ced75cc..46f088833 100644 --- a/src/main/scala/util/JGitUtil.scala +++ b/src/main/scala/util/JGitUtil.scala @@ -61,24 +61,31 @@ object JGitUtil { * The commit data. * * @param id the commit id - * @param time the commit time - * @param committer the committer name - * @param mailAddress the mail address of the committer * @param shortMessage the short message * @param fullMessage the full message * @param parents the list of parent commit id + * @param authorTime the author time + * @param authorName the author name + * @param authorEmailAddress the mail address of the author + * @param commitTime the commit time + * @param committerName the committer name + * @param committerEmailAddress the mail address of the committer */ - case class CommitInfo(id: String, time: Date, committer: String, mailAddress: String, - shortMessage: String, fullMessage: String, parents: List[String]){ + case class CommitInfo(id: String, shortMessage: String, fullMessage: String, parents: List[String], + authorTime: Date, authorName: String, authorEmailAddress: String, + commitTime: Date, committerName: String, committerEmailAddress: String){ def this(rev: org.eclipse.jgit.revwalk.RevCommit) = this( rev.getName, + rev.getFullMessage, + rev.getShortMessage, + rev.getParents().map(_.name).toList, + rev.getAuthorIdent.getWhen, + rev.getAuthorIdent.getName, + rev.getAuthorIdent.getEmailAddress, rev.getCommitterIdent.getWhen, rev.getCommitterIdent.getName, - rev.getCommitterIdent.getEmailAddress, - rev.getShortMessage, - rev.getFullMessage, - rev.getParents().map(_.name).toList) + rev.getCommitterIdent.getEmailAddress) val summary = getSummaryMessage(fullMessage, shortMessage) @@ -87,6 +94,8 @@ object JGitUtil { Some(fullMessage.trim.substring(i).trim) } else None } + + def isDiffrentCommitter: Boolean = authorName != committerName || authorEmailAddress != committerEmailAddress } case class DiffInfo(changeType: ChangeType, oldPath: String, newPath: String, oldContent: Option[String], newContent: Option[String]) diff --git a/src/main/scala/view/helpers.scala b/src/main/scala/view/helpers.scala index ddf4a0ae4..e83606a2e 100644 --- a/src/main/scala/view/helpers.scala +++ b/src/main/scala/view/helpers.scala @@ -74,7 +74,7 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache * This method looks up Gravatar if avatar icon has not been configured in user settings. */ def avatar(commit: util.JGitUtil.CommitInfo, size: Int)(implicit context: app.Context): Html = - getAvatarImageHtml(commit.committer, size, commit.mailAddress) + getAvatarImageHtml(commit.authorName, size, commit.authorEmailAddress) /** * Converts commit id, issue id and username to the link. diff --git a/src/main/twirl/pulls/commits.scala.html b/src/main/twirl/pulls/commits.scala.html index 68636d5f5..fa180562d 100644 --- a/src/main/twirl/pulls/commits.scala.html +++ b/src/main/twirl/pulls/commits.scala.html @@ -6,13 +6,13 @@ @commits.map { day => - + @day.map { commit =>
@date(day.head.time)@date(day.head.commitTime)
@avatar(commit, 20) - @user(commit.committer, commit.mailAddress, "username") + @user(commit.authorName, commit.authorEmailAddress, "username") @commit.shortMessage diff --git a/src/main/twirl/repo/blob.scala.html b/src/main/twirl/repo/blob.scala.html index df13f90c2..9df602c59 100644 --- a/src/main/twirl/repo/blob.scala.html +++ b/src/main/twirl/repo/blob.scala.html @@ -33,8 +33,8 @@
@avatar(latestCommit, 20) - @user(latestCommit.committer, latestCommit.mailAddress, "username strong") - @datetime(latestCommit.time) + @user(latestCommit.committerName, latestCommit.committerEmailAddress, "username strong") + @datetime(latestCommit.commitTime) @link(latestCommit.summary, repository)
diff --git a/src/main/twirl/repo/commit.scala.html b/src/main/twirl/repo/commit.scala.html index 61a2ce49c..ac8992e27 100644 --- a/src/main/twirl/repo/commit.scala.html +++ b/src/main/twirl/repo/commit.scala.html @@ -42,9 +42,6 @@
- @avatar(commit, 20) - @user(commit.committer, commit.mailAddress, "username strong") - @datetime(commit.time)
@if(commit.parents.size == 0){ @@ -66,6 +63,21 @@
}
+ +
+
+ @avatar(commit, 20) + @user(commit.authorName, commit.authorEmailAddress, "username strong") + authored on @datetime(commit.authorTime) +
+ @if(commit.isDiffrentCommitter) { +
+ + @user(commit.committerName, commit.committerEmailAddress, "username strong") + committed on @datetime(commit.commitTime) +
+ } +
diff --git a/src/main/twirl/repo/commits.scala.html b/src/main/twirl/repo/commits.scala.html index 8fc49bfaa..ae93996cc 100644 --- a/src/main/twirl/repo/commits.scala.html +++ b/src/main/twirl/repo/commits.scala.html @@ -36,7 +36,7 @@ @commits.map { day => - + @day.map { commit => @@ -57,8 +57,8 @@ }
- @user(commit.committer, commit.mailAddress, "username") - @datetime(commit.time) + @user(commit.committerName, commit.committerEmailAddress, "username") + @datetime(commit.commitTime)
diff --git a/src/main/twirl/repo/files.scala.html b/src/main/twirl/repo/files.scala.html index 3e6d9993e..9744ed4fb 100644 --- a/src/main/twirl/repo/files.scala.html +++ b/src/main/twirl/repo/files.scala.html @@ -41,8 +41,8 @@ - + } diff --git a/src/main/webapp/assets/common/css/gitbucket.css b/src/main/webapp/assets/common/css/gitbucket.css index 934080dac..e4a29880c 100644 --- a/src/main/webapp/assets/common/css/gitbucket.css +++ b/src/main/webapp/assets/common/css/gitbucket.css @@ -824,6 +824,15 @@ a.absent { color: #c00; } +/****************************************************************************/ +/* Commit */ +/****************************************************************************/ +div.author-info div.committer { + display: block; + margin-left: 25px; + font-size: 12px; +} + /****************************************************************************/ /* Diff */ /****************************************************************************/ From 3bef71f5f26b61ddd11c32937c7ac2609ce2cc63 Mon Sep 17 00:00:00 2001 From: jparound30 Date: Tue, 29 Jul 2014 00:22:22 +0900 Subject: [PATCH 005/152] (refs #423)Change blob view's table-layout property. --- src/main/twirl/repo/blob.scala.html | 2 +- src/main/webapp/assets/common/css/gitbucket.css | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/twirl/repo/blob.scala.html b/src/main/twirl/repo/blob.scala.html index df13f90c2..ae56faba5 100644 --- a/src/main/twirl/repo/blob.scala.html +++ b/src/main/twirl/repo/blob.scala.html @@ -28,7 +28,7 @@ } -
@date(day.head.time)@date(day.head.commitTime)
@avatar(latestCommit, 20) - @user(latestCommit.committer, latestCommit.mailAddress, "username strong") - @datetime(latestCommit.time) + @user(latestCommit.committerName, latestCommit.committerEmailAddress, "username strong") + @datetime(latestCommit.commitTime) diff --git a/src/main/twirl/wiki/history.scala.html b/src/main/twirl/wiki/history.scala.html index 198f0b1d0..6c5c2ac7f 100644 --- a/src/main/twirl/wiki/history.scala.html +++ b/src/main/twirl/wiki/history.scala.html @@ -34,9 +34,9 @@ @commits.map { commit =>
@avatar(commit, 20) @user(commit.committer, commit.mailAddress)@avatar(commit, 20) @user(commit.committerName, commit.committerEmailAddress) - @datetime(commit.time): @commit.shortMessage + @datetime(commit.commitTime): @commit.shortMessage
+
From 972628eb65ba3ae33297731229a1e88623b86f84 Mon Sep 17 00:00:00 2001 From: Tomofumi Tanaka Date: Tue, 29 Jul 2014 01:11:27 +0900 Subject: [PATCH 007/152] (refs #437)Show author and committer at files view --- src/main/twirl/repo/files.scala.html | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/twirl/repo/files.scala.html b/src/main/twirl/repo/files.scala.html index 4e121d872..83db80b3b 100644 --- a/src/main/twirl/repo/files.scala.html +++ b/src/main/twirl/repo/files.scala.html @@ -40,12 +40,23 @@ From d2317d0a972a42590ae13531e42a3d62a10dbeca Mon Sep 17 00:00:00 2001 From: Tomofumi Tanaka Date: Tue, 29 Jul 2014 01:24:09 +0900 Subject: [PATCH 008/152] (refs #437)Fix typo Threre is more good function name, but i have no idea :dizzy_face: --- src/main/scala/util/JGitUtil.scala | 2 +- src/main/twirl/repo/commit.scala.html | 2 +- src/main/twirl/repo/files.scala.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/util/JGitUtil.scala b/src/main/scala/util/JGitUtil.scala index 043dc776e..ae1612c2b 100644 --- a/src/main/scala/util/JGitUtil.scala +++ b/src/main/scala/util/JGitUtil.scala @@ -95,7 +95,7 @@ object JGitUtil { } else None } - def isDiffrentCommitter: Boolean = authorName != committerName || authorEmailAddress != committerEmailAddress + def isDifferentFromAuthor: Boolean = authorName != committerName || authorEmailAddress != committerEmailAddress } case class DiffInfo(changeType: ChangeType, oldPath: String, newPath: String, oldContent: Option[String], newContent: Option[String]) diff --git a/src/main/twirl/repo/commit.scala.html b/src/main/twirl/repo/commit.scala.html index ac8992e27..a02223692 100644 --- a/src/main/twirl/repo/commit.scala.html +++ b/src/main/twirl/repo/commit.scala.html @@ -70,7 +70,7 @@ @user(commit.authorName, commit.authorEmailAddress, "username strong") authored on @datetime(commit.authorTime) - @if(commit.isDiffrentCommitter) { + @if(commit.isDifferentFromAuthor) {
@user(commit.committerName, commit.committerEmailAddress, "username strong") diff --git a/src/main/twirl/repo/files.scala.html b/src/main/twirl/repo/files.scala.html index 83db80b3b..d0c074f8c 100644 --- a/src/main/twirl/repo/files.scala.html +++ b/src/main/twirl/repo/files.scala.html @@ -49,7 +49,7 @@ @user(latestCommit.authorName, latestCommit.authorEmailAddress, "username strong") authored on @datetime(latestCommit.authorTime)
- @if(latestCommit.isDiffrentCommitter) { + @if(latestCommit.isDifferentFromAuthor) {
@user(latestCommit.committerName, latestCommit.committerEmailAddress, "username strong") From 0ede7e992196e4f6c33e32ead89b9a03bcaae4b7 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Wed, 30 Jul 2014 07:36:35 +0900 Subject: [PATCH 009/152] (refs #374)Upgrading to Scalatra 2.3 and Slick 2.1. Some compilation errors in Slick code are remaining. --- project/build.scala | 10 +++---- src/main/scala/app/ControllerBase.scala | 15 ++++++----- src/main/scala/service/AccountService.scala | 26 +++++++++---------- src/main/scala/service/ActivityService.scala | 8 +++--- src/main/scala/service/IssuesService.scala | 14 +++++----- .../scala/service/PullRequestService.scala | 14 +++++----- .../scala/service/RepositoryService.scala | 26 +++++++++---------- src/main/scala/service/SshKeyService.scala | 2 +- 8 files changed, 59 insertions(+), 56 deletions(-) diff --git a/project/build.scala b/project/build.scala index f776c9f5d..dfd46b0a6 100644 --- a/project/build.scala +++ b/project/build.scala @@ -8,8 +8,8 @@ object MyBuild extends Build { val Organization = "jp.sf.amateras" val Name = "gitbucket" val Version = "0.0.1" - val ScalaVersion = "2.10.3" - val ScalatraVersion = "2.2.1" + val ScalaVersion = "2.11.1" + val ScalatraVersion = "2.3.0" lazy val project = Project ( "gitbucket", @@ -30,15 +30,15 @@ object MyBuild extends Build { "org.scalatra" %% "scalatra" % ScalatraVersion, "org.scalatra" %% "scalatra-specs2" % ScalatraVersion % "test", "org.scalatra" %% "scalatra-json" % ScalatraVersion, - "org.json4s" %% "json4s-jackson" % "3.2.5", - "jp.sf.amateras" %% "scalatra-forms" % "0.0.14", + "org.json4s" %% "json4s-jackson" % "3.2.10", + "jp.sf.amateras" %% "scalatra-forms" % "0.1.0", "commons-io" % "commons-io" % "2.4", "org.pegdown" % "pegdown" % "1.4.1", "org.apache.commons" % "commons-compress" % "1.5", "org.apache.commons" % "commons-email" % "1.3.1", "org.apache.httpcomponents" % "httpclient" % "4.3", "org.apache.sshd" % "apache-sshd" % "0.11.0", - "com.typesafe.slick" %% "slick" % "2.0.2", + "com.typesafe.slick" %% "slick" % "2.1.0-RC3", "org.mozilla" % "rhino" % "1.7R4", "com.novell.ldap" % "jldap" % "2009-10-07", "org.quartz-scheduler" % "quartz" % "2.2.1", diff --git a/src/main/scala/app/ControllerBase.scala b/src/main/scala/app/ControllerBase.scala index b36d53c24..c31b90f7e 100644 --- a/src/main/scala/app/ControllerBase.scala +++ b/src/main/scala/app/ControllerBase.scala @@ -24,8 +24,9 @@ abstract class ControllerBase extends ScalatraFilter implicit val jsonFormats = DefaultFormats - // Don't set content type via Accept header. - override def format(implicit request: HttpServletRequest) = "" +// TODO Scala 2.11 +// // Don't set content type via Accept header. +// override def format(implicit request: HttpServletRequest) = "" override def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain): Unit = try { val httpRequest = request.asInstanceOf[HttpServletRequest] @@ -125,11 +126,13 @@ abstract class ControllerBase extends ScalatraFilter } } - override def fullUrl(path: String, params: Iterable[(String, Any)] = Iterable.empty, - includeContextPath: Boolean = true, includeServletPath: Boolean = true) - (implicit request: HttpServletRequest, response: HttpServletResponse) = + // TODO Scala 2.11 + override def url(path: String, params: Iterable[(String, Any)] = Iterable.empty, + includeContextPath: Boolean = true, includeServletPath: Boolean = true, + absolutize: Boolean = true, withSessionId: Boolean = true) + (implicit request: HttpServletRequest, response: HttpServletResponse): String = if (path.startsWith("http")) path - else baseUrl + url(path, params, false, false, false) + else baseUrl + super.url(path, params, false, false, false) } diff --git a/src/main/scala/service/AccountService.scala b/src/main/scala/service/AccountService.scala index 8f34dcb9b..d7e4eb774 100644 --- a/src/main/scala/service/AccountService.scala +++ b/src/main/scala/service/AccountService.scala @@ -75,16 +75,16 @@ trait AccountService { } def getAccountByUserName(userName: String, includeRemoved: Boolean = false)(implicit s: Session): Option[Account] = - Accounts filter(t => (t.userName is userName.bind) && (t.removed is false.bind, !includeRemoved)) firstOption + Accounts filter(t => (t.userName === userName.bind) && (t.removed is false.bind, !includeRemoved)) firstOption def getAccountByMailAddress(mailAddress: String, includeRemoved: Boolean = false)(implicit s: Session): Option[Account] = - Accounts filter(t => (t.mailAddress.toLowerCase is mailAddress.toLowerCase.bind) && (t.removed is false.bind, !includeRemoved)) firstOption + Accounts filter(t => (t.mailAddress.toLowerCase === mailAddress.toLowerCase.bind) && (t.removed is false.bind, !includeRemoved)) firstOption def getAllUsers(includeRemoved: Boolean = true)(implicit s: Session): List[Account] = if(includeRemoved){ Accounts sortBy(_.userName) list } else { - Accounts filter (_.removed is false.bind) sortBy(_.userName) list + Accounts filter (_.removed === false.bind) sortBy(_.userName) list } def createAccount(userName: String, password: String, fullName: String, mailAddress: String, isAdmin: Boolean, url: Option[String]) @@ -105,7 +105,7 @@ trait AccountService { def updateAccount(account: Account)(implicit s: Session): Unit = Accounts - .filter { a => a.userName is account.userName.bind } + .filter { a => a.userName === account.userName.bind } .map { a => (a.password, a.fullName, a.mailAddress, a.isAdmin, a.url.?, a.registeredDate, a.updatedDate, a.lastLoginDate.?, a.removed) } .update ( account.password, @@ -119,10 +119,10 @@ trait AccountService { account.isRemoved) def updateAvatarImage(userName: String, image: Option[String])(implicit s: Session): Unit = - Accounts.filter(_.userName is userName.bind).map(_.image.?).update(image) + Accounts.filter(_.userName === userName.bind).map(_.image.?).update(image) def updateLastLoginDate(userName: String)(implicit s: Session): Unit = - Accounts.filter(_.userName is userName.bind).map(_.lastLoginDate).update(currentDate) + Accounts.filter(_.userName === userName.bind).map(_.lastLoginDate).update(currentDate) def createGroup(groupName: String, url: Option[String])(implicit s: Session): Unit = Accounts insert Account( @@ -140,10 +140,10 @@ trait AccountService { isRemoved = false) def updateGroup(groupName: String, url: Option[String], removed: Boolean)(implicit s: Session): Unit = - Accounts.filter(_.userName is groupName.bind).map(t => t.url.? -> t.removed).update(url, removed) + Accounts.filter(_.userName === groupName.bind).map(t => t.url.? -> t.removed).update(url, removed) def updateGroupMembers(groupName: String, members: List[(String, Boolean)])(implicit s: Session): Unit = { - GroupMembers.filter(_.groupName is groupName.bind).delete + GroupMembers.filter(_.groupName === groupName.bind).delete members.foreach { case (userName, isManager) => GroupMembers insert GroupMember (groupName, userName, isManager) } @@ -151,21 +151,21 @@ trait AccountService { def getGroupMembers(groupName: String)(implicit s: Session): List[GroupMember] = GroupMembers - .filter(_.groupName is groupName.bind) + .filter(_.groupName === groupName.bind) .sortBy(_.userName) .list def getGroupsByUserName(userName: String)(implicit s: Session): List[String] = GroupMembers - .filter(_.userName is userName.bind) + .filter(_.userName === userName.bind) .sortBy(_.groupName) .map(_.groupName) .list def removeUserRelatedData(userName: String)(implicit s: Session): Unit = { - GroupMembers.filter(_.userName is userName.bind).delete - Collaborators.filter(_.collaboratorName is userName.bind).delete - Repositories.filter(_.userName is userName.bind).delete + GroupMembers.filter(_.userName === userName.bind).delete + Collaborators.filter(_.collaboratorName === userName.bind).delete + Repositories.filter(_.userName === userName.bind).delete } } diff --git a/src/main/scala/service/ActivityService.scala b/src/main/scala/service/ActivityService.scala index 127bae55e..76107ae36 100644 --- a/src/main/scala/service/ActivityService.scala +++ b/src/main/scala/service/ActivityService.scala @@ -11,9 +11,9 @@ trait ActivityService { .innerJoin(Repositories).on((t1, t2) => t1.byRepository(t2.userName, t2.repositoryName)) .filter { case (t1, t2) => if(isPublic){ - (t1.activityUserName is activityUserName.bind) && (t2.isPrivate is false.bind) + (t1.activityUserName === activityUserName.bind) && (t2.isPrivate === false.bind) } else { - (t1.activityUserName is activityUserName.bind) + (t1.activityUserName === activityUserName.bind) } } .sortBy { case (t1, t2) => t1.activityId desc } @@ -24,7 +24,7 @@ trait ActivityService { def getRecentActivities()(implicit s: Session): List[Activity] = Activities .innerJoin(Repositories).on((t1, t2) => t1.byRepository(t2.userName, t2.repositoryName)) - .filter { case (t1, t2) => t2.isPrivate is false.bind } + .filter { case (t1, t2) => t2.isPrivate === false.bind } .sortBy { case (t1, t2) => t1.activityId desc } .map { case (t1, t2) => t1 } .take(30) @@ -33,7 +33,7 @@ trait ActivityService { def getRecentActivitiesByOwners(owners : Set[String])(implicit s: Session): List[Activity] = Activities .innerJoin(Repositories).on((t1, t2) => t1.byRepository(t2.userName, t2.repositoryName)) - .filter { case (t1, t2) => (t2.isPrivate is false.bind) || (t2.userName inSetBind owners) } + .filter { case (t1, t2) => (t2.isPrivate === false.bind) || (t2.userName inSetBind owners) } .sortBy { case (t1, t2) => t1.activityId desc } .map { case (t1, t2) => t1 } .take(30) diff --git a/src/main/scala/service/IssuesService.scala b/src/main/scala/service/IssuesService.scala index c123be957..55b60fb6c 100644 --- a/src/main/scala/service/IssuesService.scala +++ b/src/main/scala/service/IssuesService.scala @@ -166,13 +166,13 @@ trait IssuesService { .getOrElse (repos) .map { case (owner, repository) => t1.byRepository(owner, repository) } .foldLeft[Column[Boolean]](false) ( _ || _ ) && - (t1.closed is (condition.state == "closed").bind) && - (t1.milestoneId is condition.milestoneId.get.get.bind, condition.milestoneId.flatten.isDefined) && - (t1.milestoneId isNull, condition.milestoneId == Some(None)) && - (t1.assignedUserName is filterUser("assigned").bind, filterUser.get("assigned").isDefined) && - (t1.openedUserName is filterUser("created_by").bind, filterUser.get("created_by").isDefined) && - (t1.openedUserName isNot filterUser("not_created_by").bind, filterUser.get("not_created_by").isDefined) && - (t1.pullRequest is true.bind, onlyPullRequest) && + (t1.closed === (condition.state == "closed").bind) && + (t1.milestoneId === condition.milestoneId.get.get.bind, condition.milestoneId.flatten.isDefined) && + (t1.milestoneId isEmpty, condition.milestoneId == Some(None)) && + (t1.assignedUserName === filterUser("assigned").bind, filterUser.get("assigned").isDefined) && + (t1.openedUserName === filterUser("created_by").bind, filterUser.get("created_by").isDefined) && + (t1.openedUserName =!= filterUser("not_created_by").bind, filterUser.get("not_created_by").isDefined) && + (t1.pullRequest === true.bind, onlyPullRequest) && (IssueLabels filter { t2 => (t2.byIssue(t1.userName, t1.repositoryName, t1.issueId)) && (t2.labelId in diff --git a/src/main/scala/service/PullRequestService.scala b/src/main/scala/service/PullRequestService.scala index 619f2fa78..2129d0791 100644 --- a/src/main/scala/service/PullRequestService.scala +++ b/src/main/scala/service/PullRequestService.scala @@ -26,9 +26,9 @@ trait PullRequestService { self: IssuesService => PullRequests .innerJoin(Issues).on { (t1, t2) => t1.byPrimaryKey(t2.userName, t2.repositoryName, t2.issueId) } .filter { case (t1, t2) => - (t2.closed is closed.bind) && - (t1.userName is owner.get.bind, owner.isDefined) && - (t1.repositoryName is repository.get.bind, repository.isDefined) + (t2.closed === closed.bind) && + (t1.userName === owner.get.bind, owner.isDefined) && + (t1.repositoryName === repository.get.bind, repository.isDefined) } .groupBy { case (t1, t2) => t2.openedUserName } .map { case (userName, t) => userName -> t.length } @@ -55,10 +55,10 @@ trait PullRequestService { self: IssuesService => PullRequests .innerJoin(Issues).on { (t1, t2) => t1.byPrimaryKey(t2.userName, t2.repositoryName, t2.issueId) } .filter { case (t1, t2) => - (t1.requestUserName is userName.bind) && - (t1.requestRepositoryName is repositoryName.bind) && - (t1.requestBranch is branch.bind) && - (t2.closed is closed.bind) + (t1.requestUserName === userName.bind) && + (t1.requestRepositoryName === repositoryName.bind) && + (t1.requestBranch === branch.bind) && + (t2.closed === closed.bind) } .map { case (t1, t2) => t1 } .list diff --git a/src/main/scala/service/RepositoryService.scala b/src/main/scala/service/RepositoryService.scala index 2adcca8b8..9e340fe9a 100644 --- a/src/main/scala/service/RepositoryService.scala +++ b/src/main/scala/service/RepositoryService.scala @@ -58,15 +58,15 @@ trait RepositoryService { self: AccountService => val collaborators = Collaborators.filter(_.byRepository(oldUserName, oldRepositoryName)).list Repositories.filter { t => - (t.originUserName is oldUserName.bind) && (t.originRepositoryName is oldRepositoryName.bind) + (t.originUserName === oldUserName.bind) && (t.originRepositoryName === oldRepositoryName.bind) }.map { t => t.originUserName -> t.originRepositoryName }.update(newUserName, newRepositoryName) Repositories.filter { t => - (t.parentUserName is oldUserName.bind) && (t.parentRepositoryName is oldRepositoryName.bind) + (t.parentUserName === oldUserName.bind) && (t.parentRepositoryName === oldRepositoryName.bind) }.map { t => t.originUserName -> t.originRepositoryName }.update(newUserName, newRepositoryName) PullRequests.filter { t => - t.requestRepositoryName is oldRepositoryName.bind + t.requestRepositoryName === oldRepositoryName.bind }.map { t => t.requestUserName -> t.requestRepositoryName }.update(newUserName, newRepositoryName) deleteRepository(oldUserName, oldRepositoryName) @@ -136,7 +136,7 @@ trait RepositoryService { self: AccountService => * @return the list of repository names */ def getRepositoryNamesOfUser(userName: String)(implicit s: Session): List[String] = - Repositories filter(_.userName is userName.bind) map (_.repositoryName) list + Repositories filter(_.userName === userName.bind) map (_.repositoryName) list /** * Returns the specified repository information. @@ -150,7 +150,7 @@ trait RepositoryService { self: AccountService => (Repositories filter { t => t.byRepository(userName, repositoryName) } firstOption) map { repository => // for getting issue count and pull request count val issues = Issues.filter { t => - t.byRepository(repository.userName, repository.repositoryName) && (t.closed is false.bind) + t.byRepository(repository.userName, repository.repositoryName) && (t.closed === false.bind) }.map(_.pullRequest).list new RepositoryInfo( @@ -175,8 +175,8 @@ trait RepositoryService { self: AccountService => def getUserRepositories(userName: String, baseUrl: String, withoutPhysicalInfo: Boolean = false) (implicit s: Session): List[RepositoryInfo] = { Repositories.filter { t1 => - (t1.userName is userName.bind) || - (Collaborators.filter { t2 => t2.byRepository(t1.userName, t1.repositoryName) && (t2.collaboratorName is userName.bind)} exists) + (t1.userName === userName.bind) || + (Collaborators.filter { t2 => t2.byRepository(t1.userName, t1.repositoryName) && (t2.collaboratorName === userName.bind)} exists) }.sortBy(_.lastActivityDate desc).list.map{ repository => new RepositoryInfo( if(withoutPhysicalInfo){ @@ -212,13 +212,13 @@ trait RepositoryService { self: AccountService => case Some(x) if(x.isAdmin) => Repositories // for Normal Users case Some(x) if(!x.isAdmin) => - Repositories filter { t => (t.isPrivate is false.bind) || (t.userName is x.userName) || - (Collaborators.filter { t2 => t2.byRepository(t.userName, t.repositoryName) && (t2.collaboratorName is x.userName.bind)} exists) + Repositories filter { t => (t.isPrivate === false.bind) || (t.userName === x.userName) || + (Collaborators.filter { t2 => t2.byRepository(t.userName, t.repositoryName) && (t2.collaboratorName === x.userName.bind)} exists) } // for Guests - case None => Repositories filter(_.isPrivate is false.bind) + case None => Repositories filter(_.isPrivate === false.bind) }).filter { t => - repositoryUserName.map { userName => t.userName is userName.bind } getOrElse LiteralColumn(true) + repositoryUserName.map { userName => t.userName === userName.bind } getOrElse LiteralColumn(true) }.sortBy(_.lastActivityDate desc).list.map{ repository => new RepositoryInfo( if(withoutPhysicalInfo){ @@ -307,13 +307,13 @@ trait RepositoryService { self: AccountService => private def getForkedCount(userName: String, repositoryName: String)(implicit s: Session): Int = Query(Repositories.filter { t => - (t.originUserName is userName.bind) && (t.originRepositoryName is repositoryName.bind) + (t.originUserName === userName.bind) && (t.originRepositoryName === repositoryName.bind) }.length).first def getForkedRepositories(userName: String, repositoryName: String)(implicit s: Session): List[(String, String)] = Repositories.filter { t => - (t.originUserName is userName.bind) && (t.originRepositoryName is repositoryName.bind) + (t.originUserName === userName.bind) && (t.originRepositoryName === repositoryName.bind) } .sortBy(_.userName asc).map(t => t.userName -> t.repositoryName).list diff --git a/src/main/scala/service/SshKeyService.scala b/src/main/scala/service/SshKeyService.scala index 7d5b9aa4a..4446084a4 100644 --- a/src/main/scala/service/SshKeyService.scala +++ b/src/main/scala/service/SshKeyService.scala @@ -10,7 +10,7 @@ trait SshKeyService { SshKeys insert SshKey(userName = userName, title = title, publicKey = publicKey) def getPublicKeys(userName: String)(implicit s: Session): List[SshKey] = - SshKeys.filter(_.userName is userName.bind).sortBy(_.sshKeyId).list + SshKeys.filter(_.userName === userName.bind).sortBy(_.sshKeyId).list def deletePublicKey(userName: String, sshKeyId: Int)(implicit s: Session): Unit = SshKeys filter (_.byPrimaryKey(userName, sshKeyId)) delete From 82beed1f44460f28446cb68e657dc70d76c127c2 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Wed, 30 Jul 2014 07:43:32 +0900 Subject: [PATCH 010/152] (refs #374)Upgrading to Scala 2.11.2 --- project/build.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.scala b/project/build.scala index dfd46b0a6..69bd711fb 100644 --- a/project/build.scala +++ b/project/build.scala @@ -8,7 +8,7 @@ object MyBuild extends Build { val Organization = "jp.sf.amateras" val Name = "gitbucket" val Version = "0.0.1" - val ScalaVersion = "2.11.1" + val ScalaVersion = "2.11.2" val ScalatraVersion = "2.3.0" lazy val project = Project ( From 212f3725ed1444c8a62189a4c5633c401d434f4b Mon Sep 17 00:00:00 2001 From: Tomofumi Tanaka Date: Wed, 30 Jul 2014 22:41:04 +0900 Subject: [PATCH 011/152] (refs #437)Show author at blob, commits and wiki history view --- src/main/twirl/repo/blob.scala.html | 2 +- src/main/twirl/repo/commits.scala.html | 9 +++++++-- src/main/twirl/wiki/history.scala.html | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/twirl/repo/blob.scala.html b/src/main/twirl/repo/blob.scala.html index 9df602c59..52e2bb098 100644 --- a/src/main/twirl/repo/blob.scala.html +++ b/src/main/twirl/repo/blob.scala.html @@ -33,7 +33,7 @@
- + } From 55722f87afb6c07a381f4c486ee42b54d8e9da54 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Thu, 31 Jul 2014 22:04:52 +0900 Subject: [PATCH 012/152] Fix TestCase --- src/test/scala/service/AccountServiceSpec.scala | 2 +- src/test/scala/service/ServiceSpecBase.scala | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/scala/service/AccountServiceSpec.scala b/src/test/scala/service/AccountServiceSpec.scala index dfb178c89..a9fa49317 100644 --- a/src/test/scala/service/AccountServiceSpec.scala +++ b/src/test/scala/service/AccountServiceSpec.scala @@ -16,7 +16,7 @@ class AccountServiceSpec extends Specification with ServiceSpecBase { }} "getAccountByUserName" in { withTestDB { implicit session => - AccountService.getAccountByUserName("root") must beSome.like{ + AccountService.getAccountByUserName("root") must beSome.like { case user => user.userName must_== "root" } diff --git a/src/test/scala/service/ServiceSpecBase.scala b/src/test/scala/service/ServiceSpecBase.scala index 94d8f627e..467105914 100644 --- a/src/test/scala/service/ServiceSpecBase.scala +++ b/src/test/scala/service/ServiceSpecBase.scala @@ -1,6 +1,7 @@ package service -import model.profile.simple._ +import model.Profile._ +import profile.simple._ import util.ControlUtil._ import java.sql.DriverManager import org.apache.commons.io.FileUtils From c22aef8ee29744868eb76b13898391c7526e4316 Mon Sep 17 00:00:00 2001 From: Tomofumi Tanaka Date: Fri, 1 Aug 2014 23:53:23 +0900 Subject: [PATCH 013/152] (refs #421)Add tar.gz archive download * Update jgit version * Add new lib org.eclipse.jgit.archive * TODO: Add link in views --- project/build.scala | 3 +- .../app/RepositoryViewerController.scala | 84 +++++++++---------- 2 files changed, 40 insertions(+), 47 deletions(-) diff --git a/project/build.scala b/project/build.scala index f776c9f5d..47f37296d 100644 --- a/project/build.scala +++ b/project/build.scala @@ -26,7 +26,8 @@ object MyBuild extends Build { ), scalacOptions := Seq("-deprecation", "-language:postfixOps"), libraryDependencies ++= Seq( - "org.eclipse.jgit" % "org.eclipse.jgit.http.server" % "3.0.0.201306101825-r", + "org.eclipse.jgit" % "org.eclipse.jgit.http.server" % "3.4.1.201406201815-r", + "org.eclipse.jgit" % "org.eclipse.jgit.archive" % "3.4.1.201406201815-r", "org.scalatra" %% "scalatra" % ScalatraVersion, "org.scalatra" %% "scalatra-specs2" % ScalatraVersion % "test", "org.scalatra" %% "scalatra-json" % ScalatraVersion, diff --git a/src/main/scala/app/RepositoryViewerController.scala b/src/main/scala/app/RepositoryViewerController.scala index 0fea61fb0..702590a2f 100644 --- a/src/main/scala/app/RepositoryViewerController.scala +++ b/src/main/scala/app/RepositoryViewerController.scala @@ -8,11 +8,12 @@ import _root_.util._ import service._ import org.scalatra._ import java.io.File -import org.eclipse.jgit.api.Git + +import org.eclipse.jgit.api.{ArchiveCommand, Git} +import org.eclipse.jgit.archive.{TgzFormat, ZipFormat} import org.eclipse.jgit.lib._ import org.apache.commons.io.FileUtils import org.eclipse.jgit.treewalk._ -import java.util.zip.{ZipEntry, ZipOutputStream} import jp.sf.amateras.scalatra.forms._ import org.eclipse.jgit.dircache.DirCache import org.eclipse.jgit.revwalk.RevCommit @@ -22,6 +23,7 @@ class RepositoryViewerController extends RepositoryViewerControllerBase with RepositoryService with AccountService with ActivityService with IssuesService with WebHookService with ReferrerAuthenticator with CollaboratorsAuthenticator + /** * The repository viewer. */ @@ -29,6 +31,9 @@ trait RepositoryViewerControllerBase extends ControllerBase { self: RepositoryService with AccountService with ActivityService with IssuesService with WebHookService with ReferrerAuthenticator with CollaboratorsAuthenticator => + ArchiveCommand.registerFormat("zip", new ZipFormat) + ArchiveCommand.registerFormat("tar.gz", new TgzFormat) + case class EditorForm( branch: String, path: String, @@ -259,50 +264,12 @@ trait RepositoryViewerControllerBase extends ControllerBase { * Download repository contents as an archive. */ get("/:owner/:repository/archive/*")(referrersOnly { repository => - val name = multiParams("splat").head - - if(name.endsWith(".zip")){ - val revision = name.stripSuffix(".zip") - val workDir = getDownloadWorkDir(repository.owner, repository.name, session.getId) - if(workDir.exists){ - FileUtils.deleteDirectory(workDir) - } - workDir.mkdirs - - val zipFile = new File(workDir, repository.name + "-" + - (if(revision.length == 40) revision.substring(0, 10) else revision).replace('/', '_') + ".zip") - - using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git => - val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(revision)) - using(new TreeWalk(git.getRepository)){ walk => - val reader = walk.getObjectReader - val objectId = new MutableObjectId - - using(new ZipOutputStream(new java.io.FileOutputStream(zipFile))){ out => - walk.addTree(revCommit.getTree) - walk.setRecursive(true) - - while(walk.next){ - val name = walk.getPathString - val mode = walk.getFileMode(0) - if(mode == FileMode.REGULAR_FILE || mode == FileMode.EXECUTABLE_FILE){ - walk.getObjectId(objectId, 0) - val entry = new ZipEntry(name) - val loader = reader.open(objectId) - entry.setSize(loader.getSize) - out.putNextEntry(entry) - loader.copyTo(out) - } - } - } - } - } - - contentType = "application/octet-stream" - response.setHeader("Content-Disposition", s"attachment; filename=${zipFile.getName}") - zipFile - } else { - BadRequest + multiParams("splat").head match { + case name if name.endsWith(".zip") => + archiveRepository(name, ".zip", repository) + case name if name.endsWith(".tar.gz") => + archiveRepository(name, ".tar.gz", repository) + case _ => BadRequest } }) @@ -447,4 +414,29 @@ trait RepositoryViewerControllerBase extends ControllerBase { } } + private def archiveRepository(name: String, suffix: String, repository: RepositoryService.RepositoryInfo): File = { + val revision = name.stripSuffix(suffix) + val workDir = getDownloadWorkDir(repository.owner, repository.name, session.getId) + if(workDir.exists) { + FileUtils.deleteDirectory(workDir) + } + workDir.mkdirs + + val file = new File(workDir, repository.name + "-" + + (if(revision.length == 40) revision.substring(0, 10) else revision).replace('/', '_') + suffix) + + using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git => + val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(revision)) + using(new java.io.FileOutputStream(file)) { out => + git.archive + .setFormat(suffix.tail) + .setTree(revCommit.getTree) + .setOutputStream(out) + .call() + } + contentType = "application/octet-stream" + response.setHeader("Content-Disposition", s"attachment; filename=${file.getName}") + file + } + } } From d0ccfc52b80a04f9071e4b1f5eb749ca5e474dc7 Mon Sep 17 00:00:00 2001 From: Tomofumi Tanaka Date: Sat, 2 Aug 2014 21:22:49 +0900 Subject: [PATCH 014/152] (refs #421)Add tar.gz archive download link --- src/main/twirl/menu.scala.html | 3 +++ src/main/twirl/repo/branches.scala.html | 5 ++++- src/main/twirl/repo/tags.scala.html | 5 ++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/twirl/menu.scala.html b/src/main/twirl/menu.scala.html index 9b1581ff9..8076c825c 100644 --- a/src/main/twirl/menu.scala.html +++ b/src/main/twirl/menu.scala.html @@ -87,6 +87,9 @@ + } } diff --git a/src/main/twirl/repo/branches.scala.html b/src/main/twirl/repo/branches.scala.html index 1b051706f..214c37c92 100644 --- a/src/main/twirl/repo/branches.scala.html +++ b/src/main/twirl/repo/branches.scala.html @@ -31,7 +31,10 @@ to @{repository.repository.defaultBranch} } - + }
diff --git a/src/main/webapp/assets/common/css/gitbucket.css b/src/main/webapp/assets/common/css/gitbucket.css index 934080dac..df059f1fe 100644 --- a/src/main/webapp/assets/common/css/gitbucket.css +++ b/src/main/webapp/assets/common/css/gitbucket.css @@ -510,6 +510,10 @@ a.header-link:hover { text-decoration: none; } +table.blobview { + table-layout: fixed; +} + table.table-file-list { margin-bottom: 0px; border: 1px solid #ddd; From 51a56356cb09066528cee0b21249cf68e44829c3 Mon Sep 17 00:00:00 2001 From: Tomofumi Tanaka Date: Tue, 29 Jul 2014 00:55:26 +0900 Subject: [PATCH 006/152] (refs #437)Show author at repo file list view --- src/main/scala/service/WikiService.scala | 2 +- src/main/scala/util/JGitUtil.scala | 14 +++++++------- src/main/twirl/repo/files.scala.html | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/scala/service/WikiService.scala b/src/main/scala/service/WikiService.scala index f634e343a..ac9dbd69a 100644 --- a/src/main/scala/service/WikiService.scala +++ b/src/main/scala/service/WikiService.scala @@ -64,7 +64,7 @@ trait WikiService { if(!JGitUtil.isEmpty(git)){ JGitUtil.getFileList(git, "master", ".").find(_.name == pageName + ".md").map { file => WikiPageInfo(file.name, StringUtil.convertFromByteArray(git.getRepository.open(file.id).getBytes), - file.committer, file.time, file.commitId) + file.author, file.time, file.commitId) } } else None } diff --git a/src/main/scala/util/JGitUtil.scala b/src/main/scala/util/JGitUtil.scala index 46f088833..043dc776e 100644 --- a/src/main/scala/util/JGitUtil.scala +++ b/src/main/scala/util/JGitUtil.scala @@ -47,15 +47,15 @@ object JGitUtil { * @param id the object id * @param isDirectory whether is it directory * @param name the file (or directory) name - * @param time the last modified time * @param message the last commit message * @param commitId the last commit id - * @param committer the last committer name + * @param time the last modified time + * @param author the last committer name * @param mailAddress the committer's mail address * @param linkUrl the url of submodule */ - case class FileInfo(id: ObjectId, isDirectory: Boolean, name: String, time: Date, message: String, commitId: String, - committer: String, mailAddress: String, linkUrl: Option[String]) + case class FileInfo(id: ObjectId, isDirectory: Boolean, name: String, message: String, commitId: String, + time: Date, author: String, mailAddress: String, linkUrl: Option[String]) /** * The commit data. @@ -240,11 +240,11 @@ object JGitUtil { objectId, fileMode == FileMode.TREE || fileMode == FileMode.GITLINK, name, - commit.getCommitterIdent.getWhen, getSummaryMessage(commit.getFullMessage, commit.getShortMessage), commit.getName, - commit.getCommitterIdent.getName, - commit.getCommitterIdent.getEmailAddress, + commit.getAuthorIdent.getWhen, + commit.getAuthorIdent.getName, + commit.getAuthorIdent.getEmailAddress, linkUrl) } }.sortWith { (file1, file2) => diff --git a/src/main/twirl/repo/files.scala.html b/src/main/twirl/repo/files.scala.html index 9744ed4fb..4e121d872 100644 --- a/src/main/twirl/repo/files.scala.html +++ b/src/main/twirl/repo/files.scala.html @@ -41,8 +41,8 @@
@avatar(latestCommit, 20) - @user(latestCommit.committerName, latestCommit.committerEmailAddress, "username strong") - @datetime(latestCommit.commitTime) + @user(latestCommit.authorName, latestCommit.authorEmailAddress, "username strong") + @datetime(latestCommit.authorTime) @@ -83,7 +83,7 @@
@link(file.message, repository) - [@user(file.committer, file.mailAddress)] + [@user(file.author, file.mailAddress)] @datetime(file.time)
- @avatar(latestCommit, 20) - @user(latestCommit.authorName, latestCommit.authorEmailAddress, "username strong") - @datetime(latestCommit.authorTime) +
+
+ @avatar(latestCommit, 20) + @user(latestCommit.authorName, latestCommit.authorEmailAddress, "username strong") + authored on @datetime(latestCommit.authorTime) +
+ @if(latestCommit.isDiffrentCommitter) { +
+ + @user(latestCommit.committerName, latestCommit.committerEmailAddress, "username strong") + committed on @datetime(latestCommit.commitTime) +
+ } +
@avatar(latestCommit, 20) - @user(latestCommit.committerName, latestCommit.committerEmailAddress, "username strong") + @user(latestCommit.authorName, latestCommit.authorEmailAddress, "username strong") @datetime(latestCommit.commitTime) @link(latestCommit.summary, repository)
diff --git a/src/main/twirl/repo/commits.scala.html b/src/main/twirl/repo/commits.scala.html index ae93996cc..be2b02f20 100644 --- a/src/main/twirl/repo/commits.scala.html +++ b/src/main/twirl/repo/commits.scala.html @@ -57,8 +57,13 @@ }
- @user(commit.committerName, commit.committerEmailAddress, "username") - @datetime(commit.commitTime) + @user(commit.authorName, commit.authorEmailAddress, "username") + authored @datetime(commit.authorTime) + @if(commit.isDifferentFromAuthor) { + + @user(commit.committerName, commit.committerEmailAddress, "username") + committed @datetime(commit.authorTime) + }
diff --git a/src/main/twirl/wiki/history.scala.html b/src/main/twirl/wiki/history.scala.html index 6c5c2ac7f..bd2ba49d5 100644 --- a/src/main/twirl/wiki/history.scala.html +++ b/src/main/twirl/wiki/history.scala.html @@ -34,9 +34,9 @@ @commits.map { commit =>
@avatar(commit, 20) @user(commit.committerName, commit.committerEmailAddress)@avatar(commit, 20) @user(commit.authorName, commit.authorEmailAddress) - @datetime(commit.commitTime): @commit.shortMessage + @datetime(commit.authorTime): @commit.shortMessage
ZIP + ZIP + TAR.GZ +
diff --git a/src/main/twirl/repo/tags.scala.html b/src/main/twirl/repo/tags.scala.html index a04da0757..82d77c08f 100644 --- a/src/main/twirl/repo/tags.scala.html +++ b/src/main/twirl/repo/tags.scala.html @@ -16,7 +16,10 @@ @tag.name @datetime(tag.time) @tag.id.substring(0, 10) - ZIP + + ZIP + TAR.GZ + } From 601f8c42490fba8487c93c256843b99fcecdc9b5 Mon Sep 17 00:00:00 2001 From: shimamoto Date: Sun, 3 Aug 2014 18:41:03 +0900 Subject: [PATCH 015/152] (refs #374) Fix compile error. --- src/main/scala/model/BasicTemplate.scala | 16 ++++++++-------- src/main/scala/model/Collaborator.scala | 2 +- src/main/scala/model/IssueComment.scala | 2 +- src/main/scala/model/IssueLabels.scala | 2 +- src/main/scala/model/SshKey.scala | 2 +- src/main/scala/model/WebHook.scala | 2 +- src/main/scala/service/AccountService.scala | 4 ++-- src/main/scala/service/IssuesService.scala | 2 +- src/main/scala/service/MilestonesService.scala | 2 +- src/main/scala/service/RepositoryService.scala | 2 +- src/main/scala/service/WebHookService.scala | 2 +- src/main/scala/util/Notifier.scala | 2 +- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/main/scala/model/BasicTemplate.scala b/src/main/scala/model/BasicTemplate.scala index e0460a911..6266ebca9 100644 --- a/src/main/scala/model/BasicTemplate.scala +++ b/src/main/scala/model/BasicTemplate.scala @@ -8,40 +8,40 @@ protected[model] trait TemplateComponent { self: Profile => val repositoryName = column[String]("REPOSITORY_NAME") def byRepository(owner: String, repository: String) = - (userName is owner.bind) && (repositoryName is repository.bind) + (userName === owner.bind) && (repositoryName === repository.bind) def byRepository(userName: Column[String], repositoryName: Column[String]) = - (this.userName is userName) && (this.repositoryName is repositoryName) + (this.userName === userName) && (this.repositoryName === repositoryName) } trait IssueTemplate extends BasicTemplate { self: Table[_] => val issueId = column[Int]("ISSUE_ID") def byIssue(owner: String, repository: String, issueId: Int) = - byRepository(owner, repository) && (this.issueId is issueId.bind) + byRepository(owner, repository) && (this.issueId === issueId.bind) def byIssue(userName: Column[String], repositoryName: Column[String], issueId: Column[Int]) = - byRepository(userName, repositoryName) && (this.issueId is issueId) + byRepository(userName, repositoryName) && (this.issueId === issueId) } trait LabelTemplate extends BasicTemplate { self: Table[_] => val labelId = column[Int]("LABEL_ID") def byLabel(owner: String, repository: String, labelId: Int) = - byRepository(owner, repository) && (this.labelId is labelId.bind) + byRepository(owner, repository) && (this.labelId === labelId.bind) def byLabel(userName: Column[String], repositoryName: Column[String], labelId: Column[Int]) = - byRepository(userName, repositoryName) && (this.labelId is labelId) + byRepository(userName, repositoryName) && (this.labelId === labelId) } trait MilestoneTemplate extends BasicTemplate { self: Table[_] => val milestoneId = column[Int]("MILESTONE_ID") def byMilestone(owner: String, repository: String, milestoneId: Int) = - byRepository(owner, repository) && (this.milestoneId is milestoneId.bind) + byRepository(owner, repository) && (this.milestoneId === milestoneId.bind) def byMilestone(userName: Column[String], repositoryName: Column[String], milestoneId: Column[Int]) = - byRepository(userName, repositoryName) && (this.milestoneId is milestoneId) + byRepository(userName, repositoryName) && (this.milestoneId === milestoneId) } } diff --git a/src/main/scala/model/Collaborator.scala b/src/main/scala/model/Collaborator.scala index 1b96872fc..88311e188 100644 --- a/src/main/scala/model/Collaborator.scala +++ b/src/main/scala/model/Collaborator.scala @@ -10,7 +10,7 @@ trait CollaboratorComponent extends TemplateComponent { self: Profile => def * = (userName, repositoryName, collaboratorName) <> (Collaborator.tupled, Collaborator.unapply) def byPrimaryKey(owner: String, repository: String, collaborator: String) = - byRepository(owner, repository) && (collaboratorName is collaborator.bind) + byRepository(owner, repository) && (collaboratorName === collaborator.bind) } } diff --git a/src/main/scala/model/IssueComment.scala b/src/main/scala/model/IssueComment.scala index 8d5e2be71..4c8ca6e9f 100644 --- a/src/main/scala/model/IssueComment.scala +++ b/src/main/scala/model/IssueComment.scala @@ -17,7 +17,7 @@ trait IssueCommentComponent extends TemplateComponent { self: Profile => val updatedDate = column[java.util.Date]("UPDATED_DATE") def * = (userName, repositoryName, issueId, commentId, action, commentedUserName, content, registeredDate, updatedDate) <> (IssueComment.tupled, IssueComment.unapply) - def byPrimaryKey(commentId: Int) = this.commentId is commentId.bind + def byPrimaryKey(commentId: Int) = this.commentId === commentId.bind } } diff --git a/src/main/scala/model/IssueLabels.scala b/src/main/scala/model/IssueLabels.scala index d6b83c16b..5d422728a 100644 --- a/src/main/scala/model/IssueLabels.scala +++ b/src/main/scala/model/IssueLabels.scala @@ -8,7 +8,7 @@ trait IssueLabelComponent extends TemplateComponent { self: Profile => class IssueLabels(tag: Tag) extends Table[IssueLabel](tag, "ISSUE_LABEL") with IssueTemplate with LabelTemplate { def * = (userName, repositoryName, issueId, labelId) <> (IssueLabel.tupled, IssueLabel.unapply) def byPrimaryKey(owner: String, repository: String, issueId: Int, labelId: Int) = - byIssue(owner, repository, issueId) && (this.labelId is labelId.bind) + byIssue(owner, repository, issueId) && (this.labelId === labelId.bind) } } diff --git a/src/main/scala/model/SshKey.scala b/src/main/scala/model/SshKey.scala index d1d0aab5d..dcf346384 100644 --- a/src/main/scala/model/SshKey.scala +++ b/src/main/scala/model/SshKey.scala @@ -12,7 +12,7 @@ trait SshKeyComponent { self: Profile => val publicKey = column[String]("PUBLIC_KEY") def * = (userName, sshKeyId, title, publicKey) <> (SshKey.tupled, SshKey.unapply) - def byPrimaryKey(userName: String, sshKeyId: Int) = (this.userName is userName.bind) && (this.sshKeyId is sshKeyId.bind) + def byPrimaryKey(userName: String, sshKeyId: Int) = (this.userName === userName.bind) && (this.sshKeyId === sshKeyId.bind) } } diff --git a/src/main/scala/model/WebHook.scala b/src/main/scala/model/WebHook.scala index 8eb3719e1..4c13c8787 100644 --- a/src/main/scala/model/WebHook.scala +++ b/src/main/scala/model/WebHook.scala @@ -9,7 +9,7 @@ trait WebHookComponent extends TemplateComponent { self: Profile => val url = column[String]("URL") def * = (userName, repositoryName, url) <> (WebHook.tupled, WebHook.unapply) - def byPrimaryKey(owner: String, repository: String, url: String) = byRepository(owner, repository) && (this.url is url.bind) + def byPrimaryKey(owner: String, repository: String, url: String) = byRepository(owner, repository) && (this.url === url.bind) } } diff --git a/src/main/scala/service/AccountService.scala b/src/main/scala/service/AccountService.scala index d7e4eb774..b815c5411 100644 --- a/src/main/scala/service/AccountService.scala +++ b/src/main/scala/service/AccountService.scala @@ -75,10 +75,10 @@ trait AccountService { } def getAccountByUserName(userName: String, includeRemoved: Boolean = false)(implicit s: Session): Option[Account] = - Accounts filter(t => (t.userName === userName.bind) && (t.removed is false.bind, !includeRemoved)) firstOption + Accounts filter(t => (t.userName === userName.bind) && (t.removed === false.bind, !includeRemoved)) firstOption def getAccountByMailAddress(mailAddress: String, includeRemoved: Boolean = false)(implicit s: Session): Option[Account] = - Accounts filter(t => (t.mailAddress.toLowerCase === mailAddress.toLowerCase.bind) && (t.removed is false.bind, !includeRemoved)) firstOption + Accounts filter(t => (t.mailAddress.toLowerCase === mailAddress.toLowerCase.bind) && (t.removed === false.bind, !includeRemoved)) firstOption def getAllUsers(includeRemoved: Boolean = true)(implicit s: Session): List[Account] = if(includeRemoved){ diff --git a/src/main/scala/service/IssuesService.scala b/src/main/scala/service/IssuesService.scala index 55b60fb6c..292b93ae0 100644 --- a/src/main/scala/service/IssuesService.scala +++ b/src/main/scala/service/IssuesService.scala @@ -168,7 +168,7 @@ trait IssuesService { .foldLeft[Column[Boolean]](false) ( _ || _ ) && (t1.closed === (condition.state == "closed").bind) && (t1.milestoneId === condition.milestoneId.get.get.bind, condition.milestoneId.flatten.isDefined) && - (t1.milestoneId isEmpty, condition.milestoneId == Some(None)) && + (t1.milestoneId.? isEmpty, condition.milestoneId == Some(None)) && (t1.assignedUserName === filterUser("assigned").bind, filterUser.get("assigned").isDefined) && (t1.openedUserName === filterUser("created_by").bind, filterUser.get("created_by").isDefined) && (t1.openedUserName =!= filterUser("not_created_by").bind, filterUser.get("not_created_by").isDefined) && diff --git a/src/main/scala/service/MilestonesService.scala b/src/main/scala/service/MilestonesService.scala index e9b27becd..476e0c4bf 100644 --- a/src/main/scala/service/MilestonesService.scala +++ b/src/main/scala/service/MilestonesService.scala @@ -41,7 +41,7 @@ trait MilestonesService { def getMilestonesWithIssueCount(owner: String, repository: String)(implicit s: Session): List[(Milestone, Int, Int)] = { val counts = Issues - .filter { t => (t.byRepository(owner, repository)) && (t.milestoneId isNotNull) } + .filter { t => (t.byRepository(owner, repository)) && (t.milestoneId.? isDefined) } .groupBy { t => t.milestoneId -> t.closed } .map { case (t1, t2) => t1._1 -> t1._2 -> t2.length } .toMap diff --git a/src/main/scala/service/RepositoryService.scala b/src/main/scala/service/RepositoryService.scala index 9e340fe9a..8e204a867 100644 --- a/src/main/scala/service/RepositoryService.scala +++ b/src/main/scala/service/RepositoryService.scala @@ -102,7 +102,7 @@ trait RepositoryService { self: AccountService => }.map { t => t.activityId -> t.message }.list updateActivities.foreach { case (activityId, message) => - Activities.filter(_.activityId is activityId.bind).map(_.message).update( + Activities.filter(_.activityId === activityId.bind).map(_.message).update( message .replace(s"[repo:${oldUserName}/${oldRepositoryName}]" ,s"[repo:${newUserName}/${newRepositoryName}]") .replace(s"[branch:${oldUserName}/${oldRepositoryName}#" ,s"[branch:${newUserName}/${newRepositoryName}#") diff --git a/src/main/scala/service/WebHookService.scala b/src/main/scala/service/WebHookService.scala index 9f3f11ed9..20130174b 100644 --- a/src/main/scala/service/WebHookService.scala +++ b/src/main/scala/service/WebHookService.scala @@ -44,7 +44,7 @@ trait WebHookService { val httpClient = HttpClientBuilder.create.build webHookURLs.foreach { webHookUrl => - val f = future { + val f = Future { logger.debug(s"start web hook invocation for ${webHookUrl}") val httpPost = new HttpPost(webHookUrl.url) diff --git a/src/main/scala/util/Notifier.scala b/src/main/scala/util/Notifier.scala index ae6e25ceb..95ec6bf2f 100644 --- a/src/main/scala/util/Notifier.scala +++ b/src/main/scala/util/Notifier.scala @@ -69,7 +69,7 @@ class Mailer(private val smtp: Smtp) extends Notifier { (msg: String => String)(implicit context: Context) = { val database = Database(context.request.getServletContext) - val f = future { + val f = Future { database withSession { implicit session => getIssue(r.owner, r.name, issueId.toString) foreach { issue => defining( From f88ce3f671ba9ceb3ae431a94f8e6c89ce10fc84 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 3 Aug 2014 19:19:15 +0900 Subject: [PATCH 016/152] Update version number to 2.2 --- src/main/scala/servlet/AutoUpdateListener.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/scala/servlet/AutoUpdateListener.scala b/src/main/scala/servlet/AutoUpdateListener.scala index ea82d41ad..7e9d768b6 100644 --- a/src/main/scala/servlet/AutoUpdateListener.scala +++ b/src/main/scala/servlet/AutoUpdateListener.scala @@ -52,6 +52,7 @@ object AutoUpdate { * The history of versions. A head of this sequence is the current BitBucket version. */ val versions = Seq( + new Version(2, 2), new Version(2, 1), new Version(2, 0){ override def update(conn: Connection): Unit = { From 93cc1be166408f55f2573401c346a732c09a4b92 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 3 Aug 2014 19:26:01 +0900 Subject: [PATCH 017/152] (refs #374)Fix build.xml --- build.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.xml b/build.xml index 1af360deb..b0416d8ed 100644 --- a/build.xml +++ b/build.xml @@ -4,7 +4,7 @@ - + From 1ca55805b51a4a13b0936a5db3f0f71ec054e5ba Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 3 Aug 2014 23:59:56 +0900 Subject: [PATCH 018/152] JSON response support for plug-ins --- .../servlet/PluginActionInvokeFilter.scala | 60 ++++++++++++------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/src/main/scala/servlet/PluginActionInvokeFilter.scala b/src/main/scala/servlet/PluginActionInvokeFilter.scala index eb28fea61..486587bbc 100644 --- a/src/main/scala/servlet/PluginActionInvokeFilter.scala +++ b/src/main/scala/servlet/PluginActionInvokeFilter.scala @@ -8,6 +8,8 @@ import service.{AccountService, RepositoryService, SystemSettingsService} import model.{Account, Session} import util.{JGitUtil, Keys} import plugin.PluginConnectionHolder +import service.RepositoryService.RepositoryInfo +import service.SystemSettingsService.SystemSettings class PluginActionInvokeFilter extends Filter with SystemSettingsService with RepositoryService with AccountService { @@ -31,18 +33,14 @@ class PluginActionInvokeFilter extends Filter with SystemSettingsService with Re private def processGlobalAction(path: String, request: HttpServletRequest, response: HttpServletResponse): Boolean = { plugin.PluginSystem.globalActions.find(_.path == path).map { action => val result = action.function(request, response) + val systemSettings = loadSystemSettings() result match { - case x: String => { - response.setContentType("text/html; charset=UTF-8") - val loginAccount = request.getSession.getAttribute(Keys.Session.LoginAccount).asInstanceOf[Account] - implicit val context = app.Context(loadSystemSettings(), Option(loginAccount), request) - val html = _root_.html.main("GitBucket", None)(Html(x)) - IOUtils.write(html.toString.getBytes("UTF-8"), response.getOutputStream) - } - case x => { - // TODO returns as JSON? - response.setContentType("application/json; charset=UTF-8") - + case x: String => renderGlobalHtml(request, response, systemSettings, x) + case x: org.mozilla.javascript.NativeObject => { + x.get("format") match { + case "html" => renderGlobalHtml(request, response, systemSettings, x.get("body").toString) + case "json" => renderJson(request, response, x.get("body").toString) + } } } true @@ -66,17 +64,12 @@ class PluginActionInvokeFilter extends Filter with SystemSettingsService with Re PluginConnectionHolder.threadLocal.remove() } result match { - case x: String => { - response.setContentType("text/html; charset=UTF-8") - val loginAccount = request.getSession.getAttribute(Keys.Session.LoginAccount).asInstanceOf[Account] - implicit val context = app.Context(systemSettings, Option(loginAccount), request) - val html = _root_.html.main("GitBucket", None)(_root_.html.menu("", repository)(Html(x))) // TODO specify active side menu - IOUtils.write(html.toString.getBytes("UTF-8"), response.getOutputStream) - } - case x => { - // TODO returns as JSON? - response.setContentType("application/json; charset=UTF-8") - + case x: String => renderRepositoryHtml(request, response, systemSettings, repository, x) + case x: org.mozilla.javascript.NativeObject => { + x.get("format") match { + case "html" => renderRepositoryHtml(request, response, systemSettings, repository, x.get("body").toString) + case "json" => renderJson(request, response, x.get("body").toString) + } } } true @@ -85,4 +78,27 @@ class PluginActionInvokeFilter extends Filter with SystemSettingsService with Re } else false } + private def renderGlobalHtml(request: HttpServletRequest, response: HttpServletResponse, + systemSettings: SystemSettings, body: String): Unit = { + response.setContentType("text/html; charset=UTF-8") + val loginAccount = request.getSession.getAttribute(Keys.Session.LoginAccount).asInstanceOf[Account] + implicit val context = app.Context(systemSettings, Option(loginAccount), request) + val html = _root_.html.main("GitBucket", None)(Html(body)) + IOUtils.write(html.toString.getBytes("UTF-8"), response.getOutputStream) + } + + private def renderRepositoryHtml(request: HttpServletRequest, response: HttpServletResponse, + systemSettings: SystemSettings, repository: RepositoryInfo, body: String): Unit = { + response.setContentType("text/html; charset=UTF-8") + val loginAccount = request.getSession.getAttribute(Keys.Session.LoginAccount).asInstanceOf[Account] + implicit val context = app.Context(systemSettings, Option(loginAccount), request) + val html = _root_.html.main("GitBucket", None)(_root_.html.menu("", repository)(Html(body))) // TODO specify active side menu + IOUtils.write(html.toString.getBytes("UTF-8"), response.getOutputStream) + } + + private def renderJson(request: HttpServletRequest, response: HttpServletResponse, body: String): Unit = { + response.setContentType("application/json; charset=UTF-8") + IOUtils.write(body.getBytes("UTF-8"), response.getOutputStream) + } + } From 2bc915f51b5d548e6f083b5e4e255803d5c4a27d Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 4 Aug 2014 00:00:41 +0900 Subject: [PATCH 019/152] Disable JavaScript console --- .../scala/app/SystemSettingsController.scala | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/scala/app/SystemSettingsController.scala b/src/main/scala/app/SystemSettingsController.scala index ecc95b6c8..72b71d281 100644 --- a/src/main/scala/app/SystemSettingsController.scala +++ b/src/main/scala/app/SystemSettingsController.scala @@ -111,15 +111,15 @@ trait SystemSettingsControllerBase extends ControllerBase { redirect("/admin/plugins") }) - get("/admin/plugins/console")(adminOnly { - admin.plugins.html.console() - }) - - post("/admin/plugins/console")(adminOnly { - val script = request.getParameter("script") - val result = plugin.JavaScriptPlugin.evaluateJavaScript(script) - Ok(result) - }) +// get("/admin/plugins/console")(adminOnly { +// admin.plugins.html.console() +// }) +// +// post("/admin/plugins/console")(adminOnly { +// val script = request.getParameter("script") +// val result = plugin.JavaScriptPlugin.evaluateJavaScript(script) +// Ok(result) +// }) // TODO Move these methods to PluginSystem or Service? private def deletePlugins(pluginIds: List[String]): Unit = { From 57879eb72e45f2b1fdb6abfee17c3217925af10e Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 4 Aug 2014 00:08:05 +0900 Subject: [PATCH 020/152] Update README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index d794db7fa..2975fe2b4 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,14 @@ Run the following commands in `Terminal` to Release Notes -------- +### 2.2 - 4 Aug 2014 +- Plug-in system is available +- Move to Scala 2.11, Scalatra 2.3 and Slick 2.1 +- tar.gz export for repository contents +- LDAP authentication improvement (mail address became optional) +- Show news feed of a private repository to members +- Some bug fix and improvements + ### 2.1 - 6 Jul 2014 - Upgrade to Slick 2.0 from 1.9 - Base part of the plug-in system is merged From 05afec323609c7590c644b9bcec8f21ec4bb0e38 Mon Sep 17 00:00:00 2001 From: Tomofumi Tanaka Date: Tue, 5 Aug 2014 00:07:21 +0900 Subject: [PATCH 021/152] (refs#458)Correct short and full message Swaped short and full message in commit info by accident. --- src/main/scala/util/JGitUtil.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/util/JGitUtil.scala b/src/main/scala/util/JGitUtil.scala index ae1612c2b..b4083a4a9 100644 --- a/src/main/scala/util/JGitUtil.scala +++ b/src/main/scala/util/JGitUtil.scala @@ -77,8 +77,8 @@ object JGitUtil { def this(rev: org.eclipse.jgit.revwalk.RevCommit) = this( rev.getName, - rev.getFullMessage, rev.getShortMessage, + rev.getFullMessage, rev.getParents().map(_.name).toList, rev.getAuthorIdent.getWhen, rev.getAuthorIdent.getName, From be79ac2eb296f6ff170be9264ba1c05d7884549e Mon Sep 17 00:00:00 2001 From: Tomofumi Tanaka Date: Tue, 5 Aug 2014 00:43:20 +0900 Subject: [PATCH 022/152] (refs #458)Skip unexpected commit message This patch is temporary measures. MUST create AutoUpdate before release 2.3. --- src/main/twirl/helper/activities.scala.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/twirl/helper/activities.scala.html b/src/main/twirl/helper/activities.scala.html index 980eaf53c..c85dd8c83 100644 --- a/src/main/twirl/helper/activities.scala.html +++ b/src/main/twirl/helper/activities.scala.html @@ -22,7 +22,7 @@ case "fork" => simpleActivity(activity, "activity-fork.png") case "push" => customActivity(activity, "activity-commit.png"){
- {activity.additionalInfo.get.split("\n").reverse.take(4).zipWithIndex.map{ case (commit, i) => + {activity.additionalInfo.get.split("\n").reverse.filter(_ matches "[0-9a-z]{40}:.*").take(4).zipWithIndex.map{ case (commit, i) => if(i == 3){
...
} else { From 2ebf2b99bd1879c51573decdfa1934f49678dac6 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Tue, 5 Aug 2014 02:15:36 +0900 Subject: [PATCH 023/152] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 2975fe2b4..f0c6a975f 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,9 @@ Run the following commands in `Terminal` to Release Notes -------- +### 2.2.1 - 5 Aug 2014 +- Bug fix + ### 2.2 - 4 Aug 2014 - Plug-in system is available - Move to Scala 2.11, Scalatra 2.3 and Slick 2.1 From b65d41731b441cd0edb6801e871b9864f479ec99 Mon Sep 17 00:00:00 2001 From: Tomofumi Tanaka Date: Tue, 5 Aug 2014 22:58:31 +0900 Subject: [PATCH 024/152] (refs #458)Correct commit message in activity info --- .../scala/servlet/AutoUpdateListener.scala | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/scala/servlet/AutoUpdateListener.scala b/src/main/scala/servlet/AutoUpdateListener.scala index 7e9d768b6..eb52c5b46 100644 --- a/src/main/scala/servlet/AutoUpdateListener.scala +++ b/src/main/scala/servlet/AutoUpdateListener.scala @@ -52,6 +52,25 @@ object AutoUpdate { * The history of versions. A head of this sequence is the current BitBucket version. */ val versions = Seq( + new Version(2, 3) { + override def update(conn: Connection): Unit = { + super.update(conn) + using(conn.createStatement.executeQuery("SELECT ACTIVITY_ID, ADDITIONAL_INFO FROM ACTIVITY WHERE ACTIVITY_TYPE='push'")){ rs => + while(rs.next) { + val info = rs.getString("ADDITIONAL_INFO") + val newInfo = info.split("\n").filter(_ matches "^[0-9a-z]{40}:.*").mkString("\n") + if (info != newInfo) { + val id = rs.getString("ACTIVITY_ID") + using(conn.prepareStatement("UPDATE ACTIVITY SET ADDITIONAL_INFO=? WHERE ACTIVITY_ID=?")) { sql => + sql.setString(1, newInfo) + sql.setLong(2, id.toLong) + sql.executeUpdate + } + } + } + } + } + }, new Version(2, 2), new Version(2, 1), new Version(2, 0){ From 45545d3815fe97df7dbb372d9ae06956c082532f Mon Sep 17 00:00:00 2001 From: Tomofumi Tanaka Date: Tue, 5 Aug 2014 23:02:31 +0900 Subject: [PATCH 025/152] Revert "(refs #458)Skip unexpected commit message" This reverts commit be79ac2eb296f6ff170be9264ba1c05d7884549e. --- src/main/twirl/helper/activities.scala.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/twirl/helper/activities.scala.html b/src/main/twirl/helper/activities.scala.html index c85dd8c83..980eaf53c 100644 --- a/src/main/twirl/helper/activities.scala.html +++ b/src/main/twirl/helper/activities.scala.html @@ -22,7 +22,7 @@ case "fork" => simpleActivity(activity, "activity-fork.png") case "push" => customActivity(activity, "activity-commit.png"){
- {activity.additionalInfo.get.split("\n").reverse.filter(_ matches "[0-9a-z]{40}:.*").take(4).zipWithIndex.map{ case (commit, i) => + {activity.additionalInfo.get.split("\n").reverse.take(4).zipWithIndex.map{ case (commit, i) => if(i == 3){
...
} else { From 098b18fe6d6ac976d420d950c69c6dc8d94a630c Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 10 Aug 2014 04:33:36 +0900 Subject: [PATCH 026/152] (refs #464)Experimental implementation of Scala based plugin --- project/build.scala | 1 - .../scala/app/SystemSettingsController.scala | 18 +-- src/main/scala/plugin/JavaScriptPlugin.scala | 117 ------------------ src/main/scala/plugin/PluginSystem.scala | 37 +++--- src/main/scala/plugin/ScalaPlugin.scala | 22 +++- src/main/scala/plugin/package.scala | 29 +++++ .../servlet/PluginActionInvokeFilter.scala | 26 ++-- 7 files changed, 85 insertions(+), 165 deletions(-) delete mode 100644 src/main/scala/plugin/JavaScriptPlugin.scala create mode 100644 src/main/scala/plugin/package.scala diff --git a/project/build.scala b/project/build.scala index 37ec82cba..6418f50e4 100644 --- a/project/build.scala +++ b/project/build.scala @@ -40,7 +40,6 @@ object MyBuild extends Build { "org.apache.httpcomponents" % "httpclient" % "4.3", "org.apache.sshd" % "apache-sshd" % "0.11.0", "com.typesafe.slick" %% "slick" % "2.1.0-RC3", - "org.mozilla" % "rhino" % "1.7R4", "com.novell.ldap" % "jldap" % "2009-10-07", "org.quartz-scheduler" % "quartz" % "2.2.1", "com.h2database" % "h2" % "1.4.180", diff --git a/src/main/scala/app/SystemSettingsController.scala b/src/main/scala/app/SystemSettingsController.scala index 72b71d281..82aabbd89 100644 --- a/src/main/scala/app/SystemSettingsController.scala +++ b/src/main/scala/app/SystemSettingsController.scala @@ -111,15 +111,15 @@ trait SystemSettingsControllerBase extends ControllerBase { redirect("/admin/plugins") }) -// get("/admin/plugins/console")(adminOnly { -// admin.plugins.html.console() -// }) -// -// post("/admin/plugins/console")(adminOnly { -// val script = request.getParameter("script") -// val result = plugin.JavaScriptPlugin.evaluateJavaScript(script) -// Ok(result) -// }) + get("/admin/plugins/console")(adminOnly { + admin.plugins.html.console() + }) + + post("/admin/plugins/console")(adminOnly { + val script = request.getParameter("script") + val result = plugin.ScalaPlugin.eval(script) + Ok() + }) // TODO Move these methods to PluginSystem or Service? private def deletePlugins(pluginIds: List[String]): Unit = { diff --git a/src/main/scala/plugin/JavaScriptPlugin.scala b/src/main/scala/plugin/JavaScriptPlugin.scala deleted file mode 100644 index adaca5ef8..000000000 --- a/src/main/scala/plugin/JavaScriptPlugin.scala +++ /dev/null @@ -1,117 +0,0 @@ -package plugin - -import org.mozilla.javascript.{Context => JsContext} -import org.mozilla.javascript.{Function => JsFunction} -import scala.collection.mutable.ListBuffer -import plugin.PluginSystem._ -import util.ControlUtil._ -import plugin.PluginSystem.GlobalMenu -import plugin.PluginSystem.RepositoryAction -import plugin.PluginSystem.Action -import plugin.PluginSystem.RepositoryMenu - -class JavaScriptPlugin(val id: String, val version: String, - val author: String, val url: String, val description: String) extends Plugin { - - private val repositoryMenuList = ListBuffer[RepositoryMenu]() - private val globalMenuList = ListBuffer[GlobalMenu]() - private val repositoryActionList = ListBuffer[RepositoryAction]() - private val globalActionList = ListBuffer[Action]() - - def repositoryMenus : List[RepositoryMenu] = repositoryMenuList.toList - def globalMenus : List[GlobalMenu] = globalMenuList.toList - def repositoryActions : List[RepositoryAction] = repositoryActionList.toList - def globalActions : List[Action] = globalActionList.toList - - def addRepositoryMenu(label: String, name: String, url: String, icon: String, condition: JsFunction): Unit = { - repositoryMenuList += RepositoryMenu(label, name, url, icon, (context) => { - val context = JsContext.enter() - try { - condition.call(context, condition, condition, Array(context)).asInstanceOf[Boolean] - } finally { - JsContext.exit() - } - }) - } - - def addGlobalMenu(label: String, url: String, icon: String, condition: JsFunction): Unit = { - globalMenuList += GlobalMenu(label, url, icon, (context) => { - val context = JsContext.enter() - try { - condition.call(context, condition, condition, Array(context)).asInstanceOf[Boolean] - } finally { - JsContext.exit() - } - }) - } - - def addGlobalAction(path: String, function: JsFunction): Unit = { - globalActionList += Action(path, (request, response) => { - val context = JsContext.enter() - try { - function.call(context, function, function, Array(request, response)) - } finally { - JsContext.exit() - } - }) - } - - def addRepositoryAction(path: String, function: JsFunction): Unit = { - repositoryActionList += RepositoryAction(path, (request, response, repository) => { - val context = JsContext.enter() - try { - function.call(context, function, function, Array(request, response, repository)) - } finally { - JsContext.exit() - } - }) - } - - object db { - // TODO Use JavaScript Map instead of java.util.Map - def select(sql: String): Array[java.util.Map[String, String]] = { - defining(PluginConnectionHolder.threadLocal.get){ conn => - using(conn.prepareStatement(sql)){ stmt => - using(stmt.executeQuery()){ rs => - val list = new java.util.ArrayList[java.util.Map[String, String]]() - while(rs.next){ - defining(rs.getMetaData){ meta => - val map = new java.util.HashMap[String, String]() - Range(1, meta.getColumnCount).map { i => - val name = meta.getColumnName(i) - map.put(name, rs.getString(name)) - } - list.add(map) - } - } - list.toArray(new Array[java.util.Map[String, String]](list.size)) - } - } - } - } - } - -} - -object JavaScriptPlugin { - - def define(id: String, version: String, author: String, url: String, description: String) - = new JavaScriptPlugin(id, version, author, url, description) - - def evaluateJavaScript(script: String, vars: Map[String, Any] = Map.empty): Any = { - val context = JsContext.enter() - try { - val scope = context.initStandardObjects() - scope.put("PluginSystem", scope, PluginSystem) - scope.put("JavaScriptPlugin", scope, this) - vars.foreach { case (key, value) => - scope.put(key, scope, value) - } - val result = context.evaluateString(scope, script, "", 1, null) - result - } finally { - JsContext.exit - } - } - -} \ No newline at end of file diff --git a/src/main/scala/plugin/PluginSystem.scala b/src/main/scala/plugin/PluginSystem.scala index 6c96ac9ed..6ba432b3b 100644 --- a/src/main/scala/plugin/PluginSystem.scala +++ b/src/main/scala/plugin/PluginSystem.scala @@ -10,6 +10,9 @@ import org.apache.commons.io.FileUtils import util.JGitUtil import org.eclipse.jgit.api.Git import service.RepositoryService.RepositoryInfo +import scala.reflect.runtime.currentMirror +import scala.tools.reflect.ToolBox + /** * Provides extension points to plug-ins. @@ -54,25 +57,26 @@ object PluginSystem { // TODO Method name seems to not so good. def installPlugin(id: String): Unit = { val pluginDir = new java.io.File(PluginHome) - val javaScriptFile = new java.io.File(pluginDir, id + "/plugin.js") - if(javaScriptFile.exists && javaScriptFile.isFile){ + val scalaFile = new java.io.File(pluginDir, id + "/plugin.scala") + if(scalaFile.exists && scalaFile.isFile){ val properties = new java.util.Properties() using(new java.io.FileInputStream(new java.io.File(pluginDir, id + "/plugin.properties"))){ in => properties.load(in) } - val script = FileUtils.readFileToString(javaScriptFile, "UTF-8") + val source = s""" + |val id = "${properties.getProperty("id")}" + |val version = "${properties.getProperty("version")}" + |val author = "${properties.getProperty("author")}" + |val url = "${properties.getProperty("url")}" + |val description = "${properties.getProperty("description")}" + """.stripMargin + FileUtils.readFileToString(scalaFile, "UTF-8") + try { - JavaScriptPlugin.evaluateJavaScript(script, Map( - "id" -> properties.getProperty("id"), - "version" -> properties.getProperty("version"), - "author" -> properties.getProperty("author"), - "url" -> properties.getProperty("url"), - "description" -> properties.getProperty("description") - )) + ScalaPlugin.eval(source) } catch { - case e: Exception => logger.warn(s"Error in plugin loading for ${javaScriptFile.getAbsolutePath}", e) + case e: Exception => logger.warn(s"Error in plugin loading for ${scalaFile.getAbsolutePath}", e) } } } @@ -109,17 +113,6 @@ object PluginSystem { } } - // TODO This is a test -// addGlobalMenu("Google", "http://www.google.co.jp/", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEvwAABL8BkeKJvAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAIgSURBVEiJtdZNiI1hFAfw36ORhSFFPgYLszOKJAsWRLGzks1gYyFZKFs7C7K2Y2XDRiwmq9kIJWQjJR9Tk48xRtTIRwjH4p473nm99yLNqdNTz/mf//+555x7ektEmEmbNaPs6OkUKKX0YBmWp6/IE8bwIs8xjEfEt0aiiJBl6sEuXMRLfEf8pX/PnIvJ0TPFWxE4+w+Ef/Kzbd5qDx5l8H8tkku7LG17gH7sxWatevdhEUoXsjda5RnDTZzH6jagtMe0lHIa23AJw3iOiSRZlmJ9mfcyfTzFl2AldmI3rkbEkbrAYKrX7S1eVRyWVnxhQ87eiLjQ+o2/mtyve+PuYy3W4+EfsP2/TVGKTHRI+Iz9Fdx8XOmAnZjGWRMYqoF/4ESW4hpOYk1iZ2WsLjDUTeBYBfgeuyux2XiNT5hXud+DD5W8Y90EtifoSfultfjx7MVtrKzcr8No5m7vJtCLx1hQJ8/4IZzClpyoy5ibsYUYQW81Z9o2jYgPeKr15+poEXE9+1XF9WIkOaasaV2P4k4pZUdDbEm+VEQcjIgtEfGxlLIVd/Gs6TX1MhzQquU3HK1t23f4IsuS94fxNXMO/MbXIDBg+tidw5yMbcCmylSdqWEH/kagYLKWeAt9Fcxi3KhhJuXq6SqQBMO15NDalvswmLWux4cbuToIbMS9BpJOfg8bm7imtmmTlVJWaa3hpnU9nufziBjtyDHTny0/AaA7Qnb4AM4aAAAAAElFTkSuQmCC") -// { context => context.loginAccount.isDefined } -// -// addRepositoryMenu("Board", "board", "/board", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEvwAABL8BkeKJvAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAIgSURBVEiJtdZNiI1hFAfw36ORhSFFPgYLszOKJAsWRLGzks1gYyFZKFs7C7K2Y2XDRiwmq9kIJWQjJR9Tk48xRtTIRwjH4p473nm99yLNqdNTz/mf//+555x7ektEmEmbNaPs6OkUKKX0YBmWp6/IE8bwIs8xjEfEt0aiiJBl6sEuXMRLfEf8pX/PnIvJ0TPFWxE4+w+Ef/Kzbd5qDx5l8H8tkku7LG17gH7sxWatevdhEUoXsjda5RnDTZzH6jagtMe0lHIa23AJw3iOiSRZlmJ9mfcyfTzFl2AldmI3rkbEkbrAYKrX7S1eVRyWVnxhQ87eiLjQ+o2/mtyve+PuYy3W4+EfsP2/TVGKTHRI+Iz9Fdx8XOmAnZjGWRMYqoF/4ESW4hpOYk1iZ2WsLjDUTeBYBfgeuyux2XiNT5hXud+DD5W8Y90EtifoSfultfjx7MVtrKzcr8No5m7vJtCLx1hQJ8/4IZzClpyoy5ibsYUYQW81Z9o2jYgPeKr15+poEXE9+1XF9WIkOaasaV2P4k4pZUdDbEm+VEQcjIgtEfGxlLIVd/Gs6TX1MhzQquU3HK1t23f4IsuS94fxNXMO/MbXIDBg+tidw5yMbcCmylSdqWEH/kagYLKWeAt9Fcxi3KhhJuXq6SqQBMO15NDalvswmLWux4cbuToIbMS9BpJOfg8bm7imtmmTlVJWaa3hpnU9nufziBjtyDHTny0/AaA7Qnb4AM4aAAAAAElFTkSuQmCC") -// { context => true} -// -// addGlobalAction("/hello"){ (request, response) => -// "Hello World!" -// } - } diff --git a/src/main/scala/plugin/ScalaPlugin.scala b/src/main/scala/plugin/ScalaPlugin.scala index e9ccc3b95..af43d9448 100644 --- a/src/main/scala/plugin/ScalaPlugin.scala +++ b/src/main/scala/plugin/ScalaPlugin.scala @@ -1,10 +1,15 @@ package plugin -import app.Context import scala.collection.mutable.ListBuffer -import plugin.PluginSystem._ import javax.servlet.http.{HttpServletResponse, HttpServletRequest} +import plugin.PluginSystem.GlobalMenu +import plugin.PluginSystem.Action +import plugin.PluginSystem.RepositoryAction +import app.Context +import plugin.PluginSystem.RepositoryMenu import service.RepositoryService.RepositoryInfo +import scala.reflect.runtime.currentMirror +import scala.tools.reflect.ToolBox // TODO This is a sample implementation for Scala based plug-ins. class ScalaPlugin(val id: String, val version: String, @@ -37,3 +42,16 @@ class ScalaPlugin(val id: String, val version: String, } } + +object ScalaPlugin { + + def define(id: String, version: String, author: String, url: String, description: String) + = new ScalaPlugin(id, version, author, url, description) + + def eval(source: String): Any = { + val toolbox = currentMirror.mkToolBox() + val tree = toolbox.parse(source) + toolbox.eval(tree) + } + +} diff --git a/src/main/scala/plugin/package.scala b/src/main/scala/plugin/package.scala new file mode 100644 index 000000000..f90c1a930 --- /dev/null +++ b/src/main/scala/plugin/package.scala @@ -0,0 +1,29 @@ +import util.ControlUtil._ +import scala.collection.mutable.ListBuffer + +package object plugin { + + object db { + // TODO Use JavaScript Map instead of java.util.Map + def select(sql: String): Seq[Map[String, String]] = { + defining(PluginConnectionHolder.threadLocal.get){ conn => + using(conn.prepareStatement(sql)){ stmt => + using(stmt.executeQuery()){ rs => + val list = new ListBuffer[Map[String, String]]() + while(rs.next){ + defining(rs.getMetaData){ meta => + val map = Range(1, meta.getColumnCount + 1).map { i => + val name = meta.getColumnName(i) + (name, rs.getString(name)) + }.toMap + list += map + } + } + list + } + } + } + } + } + +} diff --git a/src/main/scala/servlet/PluginActionInvokeFilter.scala b/src/main/scala/servlet/PluginActionInvokeFilter.scala index 486587bbc..7da143c69 100644 --- a/src/main/scala/servlet/PluginActionInvokeFilter.scala +++ b/src/main/scala/servlet/PluginActionInvokeFilter.scala @@ -10,6 +10,7 @@ import util.{JGitUtil, Keys} import plugin.PluginConnectionHolder import service.RepositoryService.RepositoryInfo import service.SystemSettingsService.SystemSettings +import org.json4s.jackson.Json class PluginActionInvokeFilter extends Filter with SystemSettingsService with RepositoryService with AccountService { @@ -36,12 +37,7 @@ class PluginActionInvokeFilter extends Filter with SystemSettingsService with Re val systemSettings = loadSystemSettings() result match { case x: String => renderGlobalHtml(request, response, systemSettings, x) - case x: org.mozilla.javascript.NativeObject => { - x.get("format") match { - case "html" => renderGlobalHtml(request, response, systemSettings, x.get("body").toString) - case "json" => renderJson(request, response, x.get("body").toString) - } - } + case x: AnyRef => renderJson(request, response, x) } true } getOrElse false @@ -65,12 +61,7 @@ class PluginActionInvokeFilter extends Filter with SystemSettingsService with Re } result match { case x: String => renderRepositoryHtml(request, response, systemSettings, repository, x) - case x: org.mozilla.javascript.NativeObject => { - x.get("format") match { - case "html" => renderRepositoryHtml(request, response, systemSettings, repository, x.get("body").toString) - case "json" => renderJson(request, response, x.get("body").toString) - } - } + case x: AnyRef => renderJson(request, response, x) } true } @@ -96,9 +87,16 @@ class PluginActionInvokeFilter extends Filter with SystemSettingsService with Re IOUtils.write(html.toString.getBytes("UTF-8"), response.getOutputStream) } - private def renderJson(request: HttpServletRequest, response: HttpServletResponse, body: String): Unit = { + private def renderJson(request: HttpServletRequest, response: HttpServletResponse, obj: AnyRef): Unit = { + import org.json4s._ + import org.json4s.jackson.Serialization + import org.json4s.jackson.Serialization.write + implicit val formats = Serialization.formats(NoTypeHints) + + val json = write(obj) + response.setContentType("application/json; charset=UTF-8") - IOUtils.write(body.getBytes("UTF-8"), response.getOutputStream) + IOUtils.write(json.getBytes("UTF-8"), response.getOutputStream) } } From 93536d3365ff41fc69d23c8eff616603e3e9608e Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 10 Aug 2014 05:42:06 +0900 Subject: [PATCH 027/152] (refs #464)Add new extension point to add buttons --- src/main/scala/app/IssuesController.scala | 4 +++- src/main/scala/plugin/Plugin.scala | 9 +++++---- src/main/scala/plugin/PluginSystem.scala | 10 ++++++---- src/main/scala/plugin/ScalaPlugin.scala | 23 ++++++++++++++++------- src/main/twirl/issues/list.scala.html | 5 +++-- src/main/twirl/issues/tab.scala.html | 6 +++++- 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/main/scala/app/IssuesController.scala b/src/main/scala/app/IssuesController.scala index 4f28466f2..07b275a06 100644 --- a/src/main/scala/app/IssuesController.scala +++ b/src/main/scala/app/IssuesController.scala @@ -9,6 +9,7 @@ import util.Implicits._ import util.ControlUtil._ import org.scalatra.Ok import model.Issue +import plugin.PluginSystem class IssuesController extends IssuesControllerBase with IssuesService with RepositoryService with AccountService with LabelsService with MilestonesService with ActivityService @@ -396,7 +397,8 @@ trait IssuesControllerBase extends ControllerBase { condition, filter, repository, - hasWritePermission(owner, repoName, context.loginAccount)) + hasWritePermission(owner, repoName, context.loginAccount), + PluginSystem.buttons("issues")) } } diff --git a/src/main/scala/plugin/Plugin.scala b/src/main/scala/plugin/Plugin.scala index 43ce3733d..57d2c0289 100644 --- a/src/main/scala/plugin/Plugin.scala +++ b/src/main/scala/plugin/Plugin.scala @@ -10,10 +10,11 @@ trait Plugin { val url: String val description: String - def repositoryMenus : List[RepositoryMenu] - def globalMenus : List[GlobalMenu] - def repositoryActions : List[RepositoryAction] - def globalActions : List[Action] + def repositoryMenus : List[RepositoryMenu] + def globalMenus : List[GlobalMenu] + def repositoryActions : List[RepositoryAction] + def globalActions : List[Action] + def buttons(name: String) : List[Button] } object PluginConnectionHolder { diff --git a/src/main/scala/plugin/PluginSystem.scala b/src/main/scala/plugin/PluginSystem.scala index 6ba432b3b..488c1b7a3 100644 --- a/src/main/scala/plugin/PluginSystem.scala +++ b/src/main/scala/plugin/PluginSystem.scala @@ -81,10 +81,11 @@ object PluginSystem { } } - def repositoryMenus : List[RepositoryMenu] = pluginsMap.values.flatMap(_.repositoryMenus).toList - def globalMenus : List[GlobalMenu] = pluginsMap.values.flatMap(_.globalMenus).toList - def repositoryActions : List[RepositoryAction] = pluginsMap.values.flatMap(_.repositoryActions).toList - def globalActions : List[Action] = pluginsMap.values.flatMap(_.globalActions).toList + def repositoryMenus : List[RepositoryMenu] = pluginsMap.values.flatMap(_.repositoryMenus).toList + def globalMenus : List[GlobalMenu] = pluginsMap.values.flatMap(_.globalMenus).toList + def repositoryActions : List[RepositoryAction] = pluginsMap.values.flatMap(_.repositoryActions).toList + def globalActions : List[Action] = pluginsMap.values.flatMap(_.globalActions).toList + def buttons(name: String) : List[Button] = pluginsMap.values.flatMap(_.buttons(name)).toList // Case classes to hold plug-ins information internally in GitBucket case class PluginRepository(id: String, url: String) @@ -92,6 +93,7 @@ object PluginSystem { case class RepositoryMenu(label: String, name: String, url: String, icon: String, condition: Context => Boolean) case class Action(path: String, function: (HttpServletRequest, HttpServletResponse) => Any) case class RepositoryAction(path: String, function: (HttpServletRequest, HttpServletResponse, RepositoryInfo) => Any) + case class Button(label: String, href: String) /** * Checks whether the plugin is updatable. diff --git a/src/main/scala/plugin/ScalaPlugin.scala b/src/main/scala/plugin/ScalaPlugin.scala index af43d9448..0b2718d08 100644 --- a/src/main/scala/plugin/ScalaPlugin.scala +++ b/src/main/scala/plugin/ScalaPlugin.scala @@ -1,10 +1,9 @@ package plugin import scala.collection.mutable.ListBuffer +import scala.collection.mutable.{Map => MutableMap} import javax.servlet.http.{HttpServletResponse, HttpServletRequest} -import plugin.PluginSystem.GlobalMenu -import plugin.PluginSystem.Action -import plugin.PluginSystem.RepositoryAction +import plugin.PluginSystem._ import app.Context import plugin.PluginSystem.RepositoryMenu import service.RepositoryService.RepositoryInfo @@ -19,11 +18,13 @@ class ScalaPlugin(val id: String, val version: String, private val globalMenuList = ListBuffer[GlobalMenu]() private val repositoryActionList = ListBuffer[RepositoryAction]() private val globalActionList = ListBuffer[Action]() + private val buttonMap = MutableMap[String, ListBuffer[Button]]() - def repositoryMenus : List[RepositoryMenu] = repositoryMenuList.toList - def globalMenus : List[GlobalMenu] = globalMenuList.toList - def repositoryActions : List[RepositoryAction] = repositoryActionList.toList - def globalActions : List[Action] = globalActionList.toList + def repositoryMenus : List[RepositoryMenu] = repositoryMenuList.toList + def globalMenus : List[GlobalMenu] = globalMenuList.toList + def repositoryActions : List[RepositoryAction] = repositoryActionList.toList + def globalActions : List[Action] = globalActionList.toList + def buttons(name: String) : List[Button] = buttonMap.get(name).map(_.toList).getOrElse(Nil) def addRepositoryMenu(label: String, name: String, url: String, icon: String)(condition: (Context) => Boolean): Unit = { repositoryMenuList += RepositoryMenu(label, name, url, icon, condition) @@ -41,6 +42,14 @@ class ScalaPlugin(val id: String, val version: String, repositoryActionList += RepositoryAction(path, function) } + def addButton(name: String, label: String, href: String): Unit = { + if(!buttonMap.contains(name)){ + buttonMap.put(name, ListBuffer[Button]()) + } + val list = buttonMap(name) + list += Button(label, href) + } + } object ScalaPlugin { diff --git a/src/main/twirl/issues/list.scala.html b/src/main/twirl/issues/list.scala.html index 0e41fbae0..6450eb1e4 100644 --- a/src/main/twirl/issues/list.scala.html +++ b/src/main/twirl/issues/list.scala.html @@ -12,12 +12,13 @@ condition: service.IssuesService.IssueSearchCondition, filter: String, repository: service.RepositoryService.RepositoryInfo, - hasWritePermission: Boolean)(implicit context: app.Context) + hasWritePermission: Boolean, + buttons: List[plugin.PluginSystem.Button])(implicit context: app.Context) @import context._ @import view.helpers._ @html.main(s"Issues - ${repository.owner}/${repository.name}", Some(repository)){ @html.menu("issues", repository){ - @tab("issues", false, repository) + @tab("issues", false, repository, buttons)
@issue.assignedUserName.map { userName => - @avatar(userName, 20) @user(userName, styleClass="username strong") + @avatar(userName, 20) @user(userName, styleClass="username strong small") }.getOrElse(No one)
@@ -145,5 +145,25 @@ $(function(){ }); }); + $('a.assign').click(function(){ + var $this = $(this); + var userName = $this.data('name'); + $.post('@url(repository)/issues/@issue.issueId/assign', + { + assignedUserName: userName + }, + function(){ + $('a.assign i.icon-ok').attr('class', 'icon-white'); + if(userName == ''){ + $('#label-assigned').html($('').text('No one')); + } else { + $('#label-assigned').empty() + .append($this.find('img.avatar-mini').clone(false)).append(' ') + .append($('').attr('href', '@context.path/' + userName).text(userName)); + $('a.assign[data-name=' + jqSelectorEscape(userName) + '] i').attr('class', 'icon-ok'); + } + }); + }); + }); From 2f95c766340b8a5897986cd137a902f671a157b3 Mon Sep 17 00:00:00 2001 From: shimamoto Date: Mon, 6 Oct 2014 01:39:42 +0900 Subject: [PATCH 123/152] (refs #488) Fixed compile error. --- src/main/twirl/pulls/conversation.scala.html | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/twirl/pulls/conversation.scala.html b/src/main/twirl/pulls/conversation.scala.html index 17c6484e4..bddfcef33 100644 --- a/src/main/twirl/pulls/conversation.scala.html +++ b/src/main/twirl/pulls/conversation.scala.html @@ -11,7 +11,6 @@ @import view.helpers._
- @issues.html.issuedetail(issue, comments, collaborators, milestones, hasWritePermission, repository) @issues.html.commentlist(issue, comments, hasWritePermission, repository, Some(pullreq)) @defining(comments.exists(_.action == "merge")){ merged => @if(hasWritePermission && !issue.closed){ From 9d69a48c657451b5310da80772ce3a648d0cdb0d Mon Sep 17 00:00:00 2001 From: shimamoto Date: Mon, 6 Oct 2014 01:40:23 +0900 Subject: [PATCH 124/152] (refs #488) Fix bug for refer comment. --- src/main/scala/app/IssuesController.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/scala/app/IssuesController.scala b/src/main/scala/app/IssuesController.scala index 95fd25bb2..ad5799e64 100644 --- a/src/main/scala/app/IssuesController.scala +++ b/src/main/scala/app/IssuesController.scala @@ -126,8 +126,7 @@ trait IssuesControllerBase extends ControllerBase { // update issue updateIssue(owner, name, issue.issueId, title, issue.content) // extract references and create refer comment - // TODO Confirmation(about "issue" parameter) - createReferComment(owner, name, issue, title) + createReferComment(owner, name, issue.copy(title = title), title) redirect(s"/${owner}/${name}/issues/_data/${issue.issueId}") } else Unauthorized From 353852d6da5efe7385fd1a0698fb04ec1c8b3f09 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 6 Oct 2014 02:14:10 +0900 Subject: [PATCH 125/152] Update README.md --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index f4fef2400..4cd79aee0 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,13 @@ Run the following commands in `Terminal` to Release Notes -------- +### 2.4 - 6 Oct 2014 +- New UI is applied to Issues and Pull requests +- Side-by-side diff is available +- Fix relative path problem in Markdown links and images +- Plugin System is disabled in default +- Some bug fix and improvements + ### 2.3 - 1 Sep 2014 - Scala based plugin system - Embedded Jetty war extraction directory moved to `GITBUCKET_HOME/tmp` From afe0b1dd716e1416a520afa86b7c654b78e011df Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 6 Oct 2014 03:08:35 +0900 Subject: [PATCH 126/152] Fix link bug in pull requests --- src/main/twirl/issues/list.scala.html | 2 +- src/main/twirl/issues/listparts.scala.html | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/main/twirl/issues/list.scala.html b/src/main/twirl/issues/list.scala.html index 5956ac889..cd00ac3c2 100644 --- a/src/main/twirl/issues/list.scala.html +++ b/src/main/twirl/issues/list.scala.html @@ -14,7 +14,7 @@ @html.main((if(target == "issues") "Issues" else "Pull requests") + s" - ${repository.owner}/${repository.name}", Some(repository)){ @html.menu(target, repository){ @tab(target, true, repository) - @listparts(issues, page, openCount, closedCount, condition, collaborators, milestones, labels, Some(repository), hasWritePermission) + @listparts(target, issues, page, openCount, closedCount, condition, collaborators, milestones, labels, Some(repository), hasWritePermission) @if(hasWritePermission){ diff --git a/src/main/twirl/issues/listparts.scala.html b/src/main/twirl/issues/listparts.scala.html index 2e6beb5bb..8580d56d3 100644 --- a/src/main/twirl/issues/listparts.scala.html +++ b/src/main/twirl/issues/listparts.scala.html @@ -1,4 +1,5 @@ -@(issues: List[service.IssuesService.IssueInfo], +@(target: String, + issues: List[service.IssuesService.IssueInfo], page: Int, openCount: Int, closedCount: Int, @@ -149,12 +150,20 @@ @if(issues.isEmpty){ - No issues to show. + @if(target == "issues"){ + No issues to show. + } else { + No pull requests to show. + } @if(condition.labels.nonEmpty || condition.milestoneId.isDefined){ Clear active filters. } else { @if(repository.isDefined){ - Create a new issue. + @if(target == "issues"){ + Create a new issue. + } else { + Create a new pull request. + } } } @@ -170,7 +179,11 @@ @if(repository.isEmpty){ @issue.repositoryName ・ } - @issue.title + @if(target == "issues"){ + @issue.title + } else { + @issue.title + } @labels.map { label => @label.labelName } From e0148695f2360910533902929e2adbc4ee00e1b8 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 6 Oct 2014 13:22:42 +0900 Subject: [PATCH 127/152] (refs #509)Fix link broken bug in Wiki --- src/main/scala/view/Markdown.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/view/Markdown.scala b/src/main/scala/view/Markdown.scala index 500781acb..05120244e 100644 --- a/src/main/scala/view/Markdown.scala +++ b/src/main/scala/view/Markdown.scala @@ -103,10 +103,10 @@ class GitBucketHtmlSerializer( } private def fixUrl(url: String, isImage: Boolean = false): String = { - if(!enableWikiLink){ - if(url.startsWith("http://") || url.startsWith("https://") || url.startsWith("#") || url.startsWith("/")){ - url - } else if(context.currentPath.contains("/blob/")){ + if(url.startsWith("http://") || url.startsWith("https://") || url.startsWith("#") || url.startsWith("/")){ + url + } else if(!enableWikiLink){ + if(context.currentPath.contains("/blob/")){ url + (if(isImage) "?raw=true" else "") } else if(context.currentPath.contains("/tree/")){ val paths = context.currentPath.split("/") From cc128a49c1d44c6271189d1e01842f8544fa1e86 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 6 Oct 2014 13:37:32 +0900 Subject: [PATCH 128/152] (refs #510)Dirty fix for Firefox --- src/main/twirl/issues/listparts.scala.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/twirl/issues/listparts.scala.html b/src/main/twirl/issues/listparts.scala.html index 8580d56d3..d3b5a113f 100644 --- a/src/main/twirl/issues/listparts.scala.html +++ b/src/main/twirl/issues/listparts.scala.html @@ -21,6 +21,7 @@
} +  - + } diff --git a/src/main/twirl/wiki/page.scala.html b/src/main/twirl/wiki/page.scala.html index 8d103d8bf..74dabb2b5 100644 --- a/src/main/twirl/wiki/page.scala.html +++ b/src/main/twirl/wiki/page.scala.html @@ -12,7 +12,7 @@
  • @pageName

    - @page.committer edited this page at @datetime(page.time) + @page.committer edited this page @helper.html.datetimeago(page.time)
  • From 5b875d7c73b58fcc1a8e7285a198995ac637b8f3 Mon Sep 17 00:00:00 2001 From: Shintaro Murakami Date: Sun, 19 Oct 2014 01:22:31 +0900 Subject: [PATCH 141/152] Refactored, sorry. --- src/main/scala/view/helpers.scala | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main/scala/view/helpers.scala b/src/main/scala/view/helpers.scala index 6bb1d0ccb..a14392978 100644 --- a/src/main/scala/view/helpers.scala +++ b/src/main/scala/view/helpers.scala @@ -45,15 +45,13 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache */ def datetimeAgoRecentOnly(date: Date): String = { val duration = new Date().getTime - date.getTime - val list = timeUnits.map(tuple => (duration / tuple._1, tuple._2)).filter(tuple => tuple._1 > 0) - if (list.isEmpty) - "just now" - else { - list.head match { - case (_, "month") => s"on ${new SimpleDateFormat("d MMM", Locale.ENGLISH).format(date)}" - case (_, "year") => s"on ${new SimpleDateFormat("d MMM yyyy", Locale.ENGLISH).format(date)}" - case (value, unitString) => s"${value} ${unitString}${if (value > 1) "s" else ""} ago" - } + 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" } } From 13c206d0689dbe9e874b660ffe96bb67205f5e03 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 19 Oct 2014 21:34:12 +0900 Subject: [PATCH 142/152] Applying new Issues UI to dashboard --- src/main/scala/app/DashboardController.scala | 21 +- src/main/twirl/dashboard/issues.scala.html | 52 +--- .../twirl/dashboard/issueslist.scala.html | 277 +++++++----------- 3 files changed, 119 insertions(+), 231 deletions(-) diff --git a/src/main/scala/app/DashboardController.scala b/src/main/scala/app/DashboardController.scala index b470f0ec9..9a3c28f0a 100644 --- a/src/main/scala/app/DashboardController.scala +++ b/src/main/scala/app/DashboardController.scala @@ -12,7 +12,7 @@ trait DashboardControllerBase extends ControllerBase { self: IssuesService with PullRequestService with RepositoryService with UsersAuthenticator => get("/dashboard/issues/repos")(usersOnly { - searchIssues("all") + searchIssues("created_by") }) get("/dashboard/issues/assigned")(usersOnly { @@ -54,19 +54,12 @@ trait DashboardControllerBase extends ControllerBase { val page = IssueSearchCondition.page(request) dashboard.html.issues( - dashboard.html.issueslist( - searchIssue(condition, filterUser, false, (page - 1) * IssueLimit, IssueLimit, userRepos: _*), - page, - countIssue(condition.copy(state = "open" ), filterUser, false, userRepos: _*), - countIssue(condition.copy(state = "closed"), filterUser, false, userRepos: _*), - condition), - countIssue(condition.copy(assigned = None, author = None), filterUser, false, userRepos: _*), - countIssue(condition.copy(assigned = Some(userName), author = None), filterUser, false, userRepos: _*), - countIssue(condition.copy(assigned = None, author = Some(userName)), filterUser, false, userRepos: _*), - countIssueGroupByRepository(condition, filterUser, false, userRepos: _*), - condition, - filter) - + searchIssue(condition, filterUser, false, (page - 1) * IssueLimit, IssueLimit, userRepos: _*), + page, + countIssue(condition.copy(state = "open" ), filterUser, false, userRepos: _*), + countIssue(condition.copy(state = "closed"), filterUser, false, userRepos: _*), + condition, + filter) } private def searchPullRequests(filter: String, repository: Option[String]) = { diff --git a/src/main/twirl/dashboard/issues.scala.html b/src/main/twirl/dashboard/issues.scala.html index f6f9bbb71..4d5af5d0c 100644 --- a/src/main/twirl/dashboard/issues.scala.html +++ b/src/main/twirl/dashboard/issues.scala.html @@ -1,50 +1,14 @@ -@(listparts: play.twirl.api.Html, - allCount: Int, - assignedCount: Int, - createdByCount: Int, - repositories: List[(String, String, Int)], +@(issues: List[service.IssuesService.IssueInfo], + page: Int, + openCount: Int, + closedCount: Int, condition: service.IssuesService.IssueSearchCondition, filter: String)(implicit context: app.Context) @import context._ @import view.helpers._ -@html.main("Your Issues"){ -
    - @dashboard.html.tab("issues") -
    - - @listparts +@html.main("Issues"){ +
    + @dashboard.html.tab("issues") + @issueslist(issues, page, openCount, closedCount, condition, filter)
    -
    } diff --git a/src/main/twirl/dashboard/issueslist.scala.html b/src/main/twirl/dashboard/issueslist.scala.html index 4f27ea8c4..248f68871 100644 --- a/src/main/twirl/dashboard/issueslist.scala.html +++ b/src/main/twirl/dashboard/issueslist.scala.html @@ -3,182 +3,113 @@ openCount: Int, closedCount: Int, condition: service.IssuesService.IssueSearchCondition, - collaborators: List[String] = Nil, - milestones: List[model.Milestone] = Nil, - labels: List[model.Label] = Nil, - repository: Option[service.RepositoryService.RepositoryInfo] = None, - hasWritePermission: Boolean = false)(implicit context: app.Context) + filter: String)(implicit context: app.Context) @import context._ @import view.helpers._ @import service.IssuesService.IssueInfo -
    - @if(condition.labels.nonEmpty || condition.milestoneId.isDefined){ - - Clear milestone and label filters + +
  • From 3b08dc2e416a4fc2b153fc84a5608cfc85bef844 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 6 Oct 2014 13:47:41 +0900 Subject: [PATCH 129/152] (refs #510)Fix dropdown presentation --- src/main/twirl/issues/issueinfo.scala.html | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/twirl/issues/issueinfo.scala.html b/src/main/twirl/issues/issueinfo.scala.html index ea0a276ab..5de46006e 100644 --- a/src/main/twirl/issues/issueinfo.scala.html +++ b/src/main/twirl/issues/issueinfo.scala.html @@ -33,7 +33,7 @@ Milestone @if(hasWritePermission){
    - @helper.html.dropdown() { + @helper.html.dropdown(right = true) {
  • Clear this milestone
  • @milestones.filter(_._1.closedDate.isEmpty).map { case (milestone, _, _) =>
  • @@ -69,14 +69,16 @@ @milestones.collect { case (milestone, _, _) if(milestone.milestoneId == milestoneId) => @milestone.title } - }.getOrElse(No milestone) + }.getOrElse { + No milestone + }
    Assignee @if(hasWritePermission){
    - @helper.html.dropdown() { + @helper.html.dropdown(right = true) {
  • Clear assignee
  • @collaborators.map { collaborator =>
  • @@ -92,7 +94,9 @@ @issue.assignedUserName.map { userName => @avatar(userName, 20) @user(userName, styleClass="username strong small") - }.getOrElse(No one) + }.getOrElse{ + No one + }
    From ca0f888a995b0c4d09a5a70d63025c82fa41e5a1 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 6 Oct 2014 13:56:33 +0900 Subject: [PATCH 130/152] Update for 2.4.1 --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 4cd79aee0..4a44fce05 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,9 @@ Run the following commands in `Terminal` to Release Notes -------- +### 2.4.1 - 6 Oct 2014 +- Bug fix + ### 2.4 - 6 Oct 2014 - New UI is applied to Issues and Pull requests - Side-by-side diff is available From 320585a5305c2eb4fb314a0435321c0913ebd652 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Tue, 7 Oct 2014 14:52:11 +0900 Subject: [PATCH 131/152] Fix presentation problem on Firefox --- src/main/twirl/issues/labels/list.scala.html | 1 + src/main/twirl/issues/milestones/list.scala.html | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/twirl/issues/labels/list.scala.html b/src/main/twirl/issues/labels/list.scala.html index a9a81290c..135f77c9d 100644 --- a/src/main/twirl/issues/labels/list.scala.html +++ b/src/main/twirl/issues/labels/list.scala.html @@ -7,6 +7,7 @@ @html.main(s"Labels - ${repository.owner}/${repository.name}"){ @html.menu("issues", repository){ @issues.html.tab("labels", hasWritePermission, repository) +   diff --git a/src/main/twirl/issues/milestones/list.scala.html b/src/main/twirl/issues/milestones/list.scala.html index 0a3853866..877083205 100644 --- a/src/main/twirl/issues/milestones/list.scala.html +++ b/src/main/twirl/issues/milestones/list.scala.html @@ -7,6 +7,7 @@ @html.main(s"Milestones - ${repository.owner}/${repository.name}"){ @html.menu("issues", repository){ @issues.html.tab("milestones", hasWritePermission, repository) +   - + }
    From 26a45d0117e5cc9bb976bae6b1fa842ddcf39d08 Mon Sep 17 00:00:00 2001 From: Shintaro Murakami Date: Thu, 9 Oct 2014 22:05:42 +0900 Subject: [PATCH 132/152] (refs #514) Fix problems of renaming repository. --- src/main/scala/app/RepositorySettingsController.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/app/RepositorySettingsController.scala b/src/main/scala/app/RepositorySettingsController.scala index 53c3ef44c..cce95bbca 100644 --- a/src/main/scala/app/RepositorySettingsController.scala +++ b/src/main/scala/app/RepositorySettingsController.scala @@ -94,7 +94,7 @@ trait RepositorySettingsControllerBase extends ControllerBase { } } // Change repository HEAD - using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git => + using(Git.open(getRepositoryDir(repository.owner, form.repositoryName))) { git => git.getRepository.updateRef(Constants.HEAD, true).link(Constants.R_HEADS + defaultBranch) } flash += "info" -> "Repository settings has been updated." From ba218053f9f7f971c9bcb588a50aa8f1ec5e3aeb Mon Sep 17 00:00:00 2001 From: bati11 Date: Sat, 11 Oct 2014 13:50:32 +0900 Subject: [PATCH 133/152] Modify to correspond to that "issuedetail.scala.html" has been deleted --- src/main/twirl/issues/commentlist.scala.html | 49 ++++++++++++++------ 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/src/main/twirl/issues/commentlist.scala.html b/src/main/twirl/issues/commentlist.scala.html index 1ebf73f93..ff3ff7e2e 100644 --- a/src/main/twirl/issues/commentlist.scala.html +++ b/src/main/twirl/issues/commentlist.scala.html @@ -16,7 +16,7 @@
    - @markdown(issue.content getOrElse "No description provided.", repository, false, true) + @markdown(issue.content getOrElse "No description provided.", repository, false, true, true, hasWritePermission)
    @@ -143,7 +143,39 @@ $(function(){ return markdown; }; - $('div[id^=commentContent-').on('click', ':checkbox', function(ev){ + var replaceTaskList = function(issueContentHtml, checkboxes) { + var ss = [], + markdown = extractMarkdown(issueContentHtml), + xs = markdown.split(/- \[[x| ]\]/g); + for (var i=0; i Date: Sun, 12 Oct 2014 15:49:49 +0900 Subject: [PATCH 134/152] (refs #518)Compile for Java7 --- project/build.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.scala b/project/build.scala index 8586d342b..dbdff717f 100644 --- a/project/build.scala +++ b/project/build.scala @@ -53,7 +53,7 @@ object MyBuild extends Build { "com.typesafe.play" %% "twirl-compiler" % "1.0.2" ), EclipseKeys.withSource := true, - javacOptions in compile ++= Seq("-target", "6", "-source", "6"), + javacOptions in compile ++= Seq("-target", "7", "-source", "7"), testOptions in Test += Tests.Argument(TestFrameworks.Specs2, "junitxml", "console"), packageOptions += Package.MainClass("JettyLauncher") ).enablePlugins(SbtTwirl) From 435eac7ae69956a83798d802b78ab81c7754b837 Mon Sep 17 00:00:00 2001 From: takezoe Date: Sun, 12 Oct 2014 16:29:41 +0900 Subject: [PATCH 135/152] (refs #511)Fix problem which is not possible to choose color at the colorpicker --- src/main/twirl/issues/labels/edit.scala.html | 4 ++-- src/main/twirl/issues/labels/list.scala.html | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/twirl/issues/labels/edit.scala.html b/src/main/twirl/issues/labels/edit.scala.html index b21d33d8c..dd558d249 100644 --- a/src/main/twirl/issues/labels/edit.scala.html +++ b/src/main/twirl/issues/labels/edit.scala.html @@ -6,14 +6,14 @@
    - +
    - + diff --git a/src/main/twirl/issues/labels/list.scala.html b/src/main/twirl/issues/labels/list.scala.html index 135f77c9d..f21a88b1b 100644 --- a/src/main/twirl/issues/labels/list.scala.html +++ b/src/main/twirl/issues/labels/list.scala.html @@ -36,14 +36,14 @@ diff --git a/src/main/twirl/helper/error.scala.html b/src/main/twirl/helper/error.scala.html new file mode 100644 index 000000000..00f43e210 --- /dev/null +++ b/src/main/twirl/helper/error.scala.html @@ -0,0 +1,7 @@ +@(error: Option[Any]) +@if(error.isDefined){ +
    + + @error +
    +} \ No newline at end of file diff --git a/src/main/twirl/helper/information.scala.html b/src/main/twirl/helper/information.scala.html index d8bcff593..ff382a203 100644 --- a/src/main/twirl/helper/information.scala.html +++ b/src/main/twirl/helper/information.scala.html @@ -1,7 +1,7 @@ @(info: Option[Any]) @if(info.isDefined){
    - + @info
    } diff --git a/src/main/twirl/menu.scala.html b/src/main/twirl/menu.scala.html index 8076c825c..7ac1dc83b 100644 --- a/src/main/twirl/menu.scala.html +++ b/src/main/twirl/menu.scala.html @@ -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 @@ }
    + @helper.html.information(info) + @helper.html.error(error) @if(repository.commitCount > 0){
    diff --git a/src/main/twirl/repo/blob.scala.html b/src/main/twirl/repo/blob.scala.html index 2c895ac36..c85fc0a72 100644 --- a/src/main/twirl/repo/blob.scala.html +++ b/src/main/twirl/repo/blob.scala.html @@ -9,10 +9,10 @@ @html.main(s"${repository.owner}/${repository.name}", Some(repository)) { @html.menu("code", repository){
    - @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 =>
  • @helper.html.checkicon(x == branch) @x
  • diff --git a/src/main/twirl/repo/commits.scala.html b/src/main/twirl/repo/commits.scala.html index be2b02f20..4fce02893 100644 --- a/src/main/twirl/repo/commits.scala.html +++ b/src/main/twirl/repo/commits.scala.html @@ -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){
    - @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 =>
  • @helper.html.checkicon(x == branch) @x
  • diff --git a/src/main/twirl/repo/files.scala.html b/src/main/twirl/repo/files.scala.html index 2235d6ecd..d663b570f 100644 --- a/src/main/twirl/repo/files.scala.html +++ b/src/main/twirl/repo/files.scala.html @@ -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){
    - @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 =>
  • @helper.html.checkicon(x == branch) @x
  • diff --git a/src/main/webapp/assets/common/css/gitbucket.css b/src/main/webapp/assets/common/css/gitbucket.css index d84bc0818..551574640 100644 --- a/src/main/webapp/assets/common/css/gitbucket.css +++ b/src/main/webapp/assets/common/css/gitbucket.css @@ -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 */ /****************************************************************************/ From 4c89c4094427d7d882e09315df09f392a9a54e81 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sat, 18 Oct 2014 19:11:30 +0900 Subject: [PATCH 138/152] (refs #522)Recover user filter in dashboard --- src/main/scala/app/DashboardController.scala | 24 ++++++++--------- src/main/scala/app/IssuesController.scala | 6 ++--- src/main/scala/app/LabelsController.scala | 6 ++--- .../scala/app/PullRequestsController.scala | 6 ++--- src/main/scala/service/IssuesService.scala | 26 +++++++++++-------- .../scala/servlet/GitRepositoryServlet.scala | 4 +-- 6 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/main/scala/app/DashboardController.scala b/src/main/scala/app/DashboardController.scala index 9ac588b28..b470f0ec9 100644 --- a/src/main/scala/app/DashboardController.scala +++ b/src/main/scala/app/DashboardController.scala @@ -50,20 +50,20 @@ trait DashboardControllerBase extends ControllerBase { val userName = context.loginAccount.get.userName val userRepos = getUserRepositories(userName, context.baseUrl, true).map(repo => repo.owner -> repo.name) - //val filterUser = Map(filter -> userName) + val filterUser = Map(filter -> userName) val page = IssueSearchCondition.page(request) dashboard.html.issues( dashboard.html.issueslist( - searchIssue(condition, false, (page - 1) * IssueLimit, IssueLimit, userRepos: _*), + searchIssue(condition, filterUser, false, (page - 1) * IssueLimit, IssueLimit, userRepos: _*), page, - countIssue(condition.copy(state = "open" ), false, userRepos: _*), - countIssue(condition.copy(state = "closed"), false, userRepos: _*), + countIssue(condition.copy(state = "open" ), filterUser, false, userRepos: _*), + countIssue(condition.copy(state = "closed"), filterUser, false, userRepos: _*), condition), - countIssue(condition.copy(assigned = None, author = None), false, userRepos: _*), - countIssue(condition.copy(assigned = Some(userName), author = None), false, userRepos: _*), - countIssue(condition.copy(assigned = None, author = Some(userName)), false, userRepos: _*), - countIssueGroupByRepository(condition, false, userRepos: _*), + countIssue(condition.copy(assigned = None, author = None), filterUser, false, userRepos: _*), + countIssue(condition.copy(assigned = Some(userName), author = None), filterUser, false, userRepos: _*), + countIssue(condition.copy(assigned = None, author = Some(userName)), filterUser, false, userRepos: _*), + countIssueGroupByRepository(condition, filterUser, false, userRepos: _*), condition, filter) @@ -86,14 +86,14 @@ trait DashboardControllerBase extends ControllerBase { val page = IssueSearchCondition.page(request) val counts = countIssueGroupByRepository( - IssueSearchCondition().copy(state = condition.state), true, userRepos: _*) + IssueSearchCondition().copy(state = condition.state), filterUser, true, userRepos: _*) dashboard.html.pulls( dashboard.html.pullslist( - searchIssue(condition, true, (page - 1) * PullRequestLimit, PullRequestLimit, allRepos: _*), + searchIssue(condition, filterUser, true, (page - 1) * PullRequestLimit, PullRequestLimit, allRepos: _*), page, - countIssue(condition.copy(state = "open" ), true, allRepos: _*), - countIssue(condition.copy(state = "closed"), true, allRepos: _*), + countIssue(condition.copy(state = "open" ), filterUser, true, allRepos: _*), + countIssue(condition.copy(state = "closed"), filterUser, true, allRepos: _*), condition, None, false), diff --git a/src/main/scala/app/IssuesController.scala b/src/main/scala/app/IssuesController.scala index ad5799e64..b6b7bb94a 100644 --- a/src/main/scala/app/IssuesController.scala +++ b/src/main/scala/app/IssuesController.scala @@ -396,13 +396,13 @@ trait IssuesControllerBase extends ControllerBase { issues.html.list( "issues", - searchIssue(condition, false, (page - 1) * IssueLimit, IssueLimit, owner -> repoName), + searchIssue(condition, Map.empty, false, (page - 1) * IssueLimit, IssueLimit, owner -> repoName), page, (getCollaborators(owner, repoName) :+ owner).sorted, getMilestones(owner, repoName), getLabels(owner, repoName), - countIssue(condition.copy(state = "open" ), false, owner -> repoName), - countIssue(condition.copy(state = "closed"), false, owner -> repoName), + countIssue(condition.copy(state = "open" ), Map.empty, false, owner -> repoName), + countIssue(condition.copy(state = "closed"), Map.empty, false, owner -> repoName), condition, repository, hasWritePermission(owner, repoName, context.loginAccount)) diff --git a/src/main/scala/app/LabelsController.scala b/src/main/scala/app/LabelsController.scala index f84012da5..7cd42bf83 100644 --- a/src/main/scala/app/LabelsController.scala +++ b/src/main/scala/app/LabelsController.scala @@ -25,7 +25,7 @@ trait LabelsControllerBase extends ControllerBase { get("/:owner/:repository/issues/labels")(referrersOnly { repository => issues.labels.html.list( getLabels(repository.owner, repository.name), - countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition()), + countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition(), Map.empty), repository, hasWritePermission(repository.owner, repository.name, context.loginAccount)) }) @@ -39,7 +39,7 @@ trait LabelsControllerBase extends ControllerBase { issues.labels.html.label( getLabel(repository.owner, repository.name, labelId).get, // TODO futility - countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition()), + countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition(), Map.empty), repository, hasWritePermission(repository.owner, repository.name, context.loginAccount)) }) @@ -55,7 +55,7 @@ trait LabelsControllerBase extends ControllerBase { issues.labels.html.label( getLabel(repository.owner, repository.name, params("labelId").toInt).get, // TODO futility - countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition()), + countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition(), Map.empty), repository, hasWritePermission(repository.owner, repository.name, context.loginAccount)) }) diff --git a/src/main/scala/app/PullRequestsController.scala b/src/main/scala/app/PullRequestsController.scala index 2f9aba512..c079f0198 100644 --- a/src/main/scala/app/PullRequestsController.scala +++ b/src/main/scala/app/PullRequestsController.scala @@ -460,13 +460,13 @@ trait PullRequestsControllerBase extends ControllerBase { issues.html.list( "pulls", - searchIssue(condition, true, (page - 1) * PullRequestLimit, PullRequestLimit, owner -> repoName), + searchIssue(condition, Map.empty, true, (page - 1) * PullRequestLimit, PullRequestLimit, owner -> repoName), page, (getCollaborators(owner, repoName) :+ owner).sorted, getMilestones(owner, repoName), getLabels(owner, repoName), - countIssue(condition.copy(state = "open" ), true, owner -> repoName), - countIssue(condition.copy(state = "closed"), true, owner -> repoName), + countIssue(condition.copy(state = "open" ), Map.empty, true, owner -> repoName), + countIssue(condition.copy(state = "closed"), Map.empty, true, owner -> repoName), condition, repository, hasWritePermission(owner, repoName, context.loginAccount)) diff --git a/src/main/scala/service/IssuesService.scala b/src/main/scala/service/IssuesService.scala index 9e7bfa61d..5688fc78f 100644 --- a/src/main/scala/service/IssuesService.scala +++ b/src/main/scala/service/IssuesService.scala @@ -47,9 +47,9 @@ trait IssuesService { * @param repos Tuple of the repository owner and the repository name * @return the count of the search result */ - def countIssue(condition: IssueSearchCondition, onlyPullRequest: Boolean, repos: (String, String)*) - (implicit s: Session): Int = - Query(searchIssueQuery(repos, condition, onlyPullRequest).length).first + def countIssue(condition: IssueSearchCondition, filterUser: Map[String, String], onlyPullRequest: Boolean, + repos: (String, String)*)(implicit s: Session): Int = + Query(searchIssueQuery(repos, condition, filterUser, onlyPullRequest).length).first /** * Returns the Map which contains issue count for each labels. @@ -59,10 +59,10 @@ trait IssuesService { * @param condition the search condition * @return the Map which contains issue count for each labels (key is label name, value is issue count) */ - def countIssueGroupByLabels(owner: String, repository: String, - condition: IssueSearchCondition)(implicit s: Session): Map[String, Int] = { + def countIssueGroupByLabels(owner: String, repository: String, condition: IssueSearchCondition, + filterUser: Map[String, String])(implicit s: Session): Map[String, Int] = { - searchIssueQuery(Seq(owner -> repository), condition.copy(labels = Set.empty), false) + searchIssueQuery(Seq(owner -> repository), condition.copy(labels = Set.empty), filterUser, false) .innerJoin(IssueLabels).on { (t1, t2) => t1.byIssue(t2.userName, t2.repositoryName, t2.issueId) } @@ -87,9 +87,9 @@ trait IssuesService { * @return list which contains issue count for each repository */ def countIssueGroupByRepository( - condition: IssueSearchCondition, onlyPullRequest: Boolean, + condition: IssueSearchCondition, filterUser: Map[String, String], onlyPullRequest: Boolean, repos: (String, String)*)(implicit s: Session): List[(String, String, Int)] = { - searchIssueQuery(repos, condition.copy(repo = None), onlyPullRequest) + searchIssueQuery(repos, condition.copy(repo = None), filterUser, onlyPullRequest) .groupBy { t => t.userName -> t.repositoryName } @@ -104,18 +104,19 @@ trait IssuesService { * Returns the search result against issues. * * @param condition the search condition + * @param filterUser the filter user name (key is "all", "assigned", "created_by" or "not_created_by", value is the user name) * @param pullRequest if true then returns only pull requests, false then returns only issues. * @param offset the offset for pagination * @param limit the limit for pagination * @param repos Tuple of the repository owner and the repository name * @return the search result (list of tuples which contain issue, labels and comment count) */ - def searchIssue(condition: IssueSearchCondition, pullRequest: Boolean, + def searchIssue(condition: IssueSearchCondition, filterUser: Map[String, String], pullRequest: Boolean, offset: Int, limit: Int, repos: (String, String)*) (implicit s: Session): List[IssueInfo] = { // get issues and comment count and labels - searchIssueQuery(repos, condition, pullRequest) + searchIssueQuery(repos, condition, filterUser, pullRequest) .innerJoin(IssueOutline).on { (t1, t2) => t1.byIssue(t2.userName, t2.repositoryName, t2.issueId) } .sortBy { case (t1, t2) => (condition.sort match { @@ -157,7 +158,7 @@ trait IssuesService { * Assembles query for conditional issue searching. */ private def searchIssueQuery(repos: Seq[(String, String)], condition: IssueSearchCondition, - pullRequest: Boolean)(implicit s: Session) = + filterUser: Map[String, String], pullRequest: Boolean)(implicit s: Session) = Issues filter { t1 => condition.repo .map { _.split('/') match { case array => Seq(array(0) -> array(1)) } } @@ -167,6 +168,9 @@ trait IssuesService { (t1.closed === (condition.state == "closed").bind) && (t1.milestoneId === condition.milestoneId.get.get.bind, condition.milestoneId.flatten.isDefined) && (t1.milestoneId.? isEmpty, condition.milestoneId == Some(None)) && + (t1.assignedUserName === filterUser("assigned").bind, filterUser.get("assigned").isDefined) && + (t1.openedUserName === filterUser("created_by").bind, filterUser.get("created_by").isDefined) && + (t1.openedUserName =!= filterUser("not_created_by").bind, filterUser.get("not_created_by").isDefined) && (t1.assignedUserName === condition.assigned.get.bind, condition.assigned.isDefined) && (t1.openedUserName === condition.author.get.bind, condition.author.isDefined) && (t1.pullRequest === pullRequest.bind) && diff --git a/src/main/scala/servlet/GitRepositoryServlet.scala b/src/main/scala/servlet/GitRepositoryServlet.scala index df55d46fd..012c6ea00 100644 --- a/src/main/scala/servlet/GitRepositoryServlet.scala +++ b/src/main/scala/servlet/GitRepositoryServlet.scala @@ -134,8 +134,8 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: // Retrieve all issue count in the repository val issueCount = - countIssue(IssueSearchCondition(state = "open"), false, owner -> repository) + - countIssue(IssueSearchCondition(state = "closed"), false, owner -> repository) + countIssue(IssueSearchCondition(state = "open"), Map.empty, false, owner -> repository) + + countIssue(IssueSearchCondition(state = "closed"), Map.empty, false, owner -> repository) // Extract new commit and apply issue comment val defaultBranch = getRepository(owner, repository, baseUrl).get.repository.defaultBranch From 876491055318763ac45ec219dccdfa59dc1f2fdf Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sat, 18 Oct 2014 19:26:11 +0900 Subject: [PATCH 139/152] (refs #504)Fix word-break of "Pages" table --- src/main/twirl/wiki/page.scala.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/twirl/wiki/page.scala.html b/src/main/twirl/wiki/page.scala.html index 21528d314..8d103d8bf 100644 --- a/src/main/twirl/wiki/page.scala.html +++ b/src/main/twirl/wiki/page.scala.html @@ -32,7 +32,7 @@
    -
      +
        @pages.map { page =>
      • @page
      • } From e33dd9008b3ac2869659f52ceeff487833d643d5 Mon Sep 17 00:00:00 2001 From: Shintaro Murakami Date: Sat, 18 Oct 2014 23:21:47 +0900 Subject: [PATCH 140/152] (ref #519) Change datetime formats --- src/main/scala/view/helpers.scala | 45 ++++++++++++++++++- .../twirl/account/repositories.scala.html | 2 +- .../twirl/dashboard/issueslist.scala.html | 2 +- src/main/twirl/dashboard/pullslist.scala.html | 2 +- src/main/twirl/helper/activities.scala.html | 6 +-- src/main/twirl/helper/datetimeago.scala.html | 10 +++++ src/main/twirl/issues/commentlist.scala.html | 14 +++--- src/main/twirl/issues/issue.scala.html | 2 +- src/main/twirl/issues/listparts.scala.html | 2 +- .../twirl/issues/milestones/list.scala.html | 2 +- src/main/twirl/pulls/pullreq.scala.html | 2 +- src/main/twirl/repo/blob.scala.html | 2 +- src/main/twirl/repo/branches.scala.html | 2 +- src/main/twirl/repo/commit.scala.html | 4 +- src/main/twirl/repo/commits.scala.html | 4 +- src/main/twirl/repo/files.scala.html | 6 +-- src/main/twirl/repo/tags.scala.html | 2 +- src/main/twirl/search/code.scala.html | 2 +- src/main/twirl/search/issues.scala.html | 2 +- src/main/twirl/wiki/history.scala.html | 2 +- src/main/twirl/wiki/page.scala.html | 2 +- 21 files changed, 85 insertions(+), 32 deletions(-) create mode 100644 src/main/twirl/helper/datetimeago.scala.html diff --git a/src/main/scala/view/helpers.scala b/src/main/scala/view/helpers.scala index 78f658f62..6bb1d0ccb 100644 --- a/src/main/scala/view/helpers.scala +++ b/src/main/scala/view/helpers.scala @@ -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,49 @@ 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 + val list = timeUnits.map(tuple => (duration / tuple._1, tuple._2)).filter(tuple => tuple._1 > 0) + if (list.isEmpty) + "just now" + else { + list.head match { + case (_, "month") => s"on ${new SimpleDateFormat("d MMM", Locale.ENGLISH).format(date)}" + case (_, "year") => s"on ${new SimpleDateFormat("d MMM yyyy", Locale.ENGLISH).format(date)}" + case (value, unitString) => s"${value} ${unitString}${if (value > 1) "s" else ""} ago" + } + } + } + + /** * Format java.util.Date to "yyyy-MM-dd'T'hh:mm:ss'Z'". */ diff --git a/src/main/twirl/account/repositories.scala.html b/src/main/twirl/account/repositories.scala.html index 1ad52dfa8..8a3706b28 100644 --- a/src/main/twirl/account/repositories.scala.html +++ b/src/main/twirl/account/repositories.scala.html @@ -25,7 +25,7 @@ @if(repository.repository.description.isDefined){
        @repository.repository.description
        } -
        Last updated: @datetime(repository.repository.lastActivityDate)
        +
        Updated @helper.html.datetimeago(repository.repository.lastActivityDate)
        } diff --git a/src/main/twirl/dashboard/issueslist.scala.html b/src/main/twirl/dashboard/issueslist.scala.html index 4f27ea8c4..186eb986d 100644 --- a/src/main/twirl/dashboard/issueslist.scala.html +++ b/src/main/twirl/dashboard/issueslist.scala.html @@ -165,7 +165,7 @@ #@issue.issueId
        - Opened by @user(issue.openedUserName, styleClass="username") @datetime(issue.registeredDate)  + Opened by @user(issue.openedUserName, styleClass="username") @helper.html.datetimeago(issue.registeredDate)  @if(commentCount > 0){ @commentCount @plural(commentCount, "comment") } diff --git a/src/main/twirl/dashboard/pullslist.scala.html b/src/main/twirl/dashboard/pullslist.scala.html index 46343b46e..dc90d9ed8 100644 --- a/src/main/twirl/dashboard/pullslist.scala.html +++ b/src/main/twirl/dashboard/pullslist.scala.html @@ -86,7 +86,7 @@ }
        - @avatarLink(issue.openedUserName, 20) by @user(issue.openedUserName, styleClass="username") @datetime(issue.registeredDate)  + @avatarLink(issue.openedUserName, 20) by @user(issue.openedUserName, styleClass="username") @helper.html.datetimeago(issue.registeredDate)  @if(commentCount > 0){ @commentCount @plural(commentCount, "comment") } diff --git a/src/main/twirl/helper/activities.scala.html b/src/main/twirl/helper/activities.scala.html index 980eaf53c..9bb3f8df1 100644 --- a/src/main/twirl/helper/activities.scala.html +++ b/src/main/twirl/helper/activities.scala.html @@ -62,7 +62,7 @@ @detailActivity(activity: model.Activity, image: String) = {
        -
        @datetime(activity.activityDate)
        +
        @helper.html.datetimeago(activity.activityDate)
        @avatar(activity.activityUserName, 16) @activityMessage(activity.message) @@ -76,7 +76,7 @@ @customActivity(activity: model.Activity, image: String)(additionalInfo: Any) = {
        -
        @datetime(activity.activityDate)
        +
        @helper.html.datetimeago(activity.activityDate)
        @avatar(activity.activityUserName, 16) @activityMessage(activity.message) @@ -91,7 +91,7 @@
        @avatar(activity.activityUserName, 16) @activityMessage(activity.message) - @datetime(activity.activityDate) + @helper.html.datetimeago(activity.activityDate)
        } diff --git a/src/main/twirl/helper/datetimeago.scala.html b/src/main/twirl/helper/datetimeago.scala.html new file mode 100644 index 000000000..3b68f34c7 --- /dev/null +++ b/src/main/twirl/helper/datetimeago.scala.html @@ -0,0 +1,10 @@ +@(latestUpdatedDate: java.util.Date, + recentOnly: Boolean = true) +@import view.helpers._ + + @if(recentOnly){ + @datetimeAgoRecentOnly(latestUpdatedDate) + }else{ + @datetimeAgo(latestUpdatedDate) + } + diff --git a/src/main/twirl/issues/commentlist.scala.html b/src/main/twirl/issues/commentlist.scala.html index 979062f17..32532d658 100644 --- a/src/main/twirl/issues/commentlist.scala.html +++ b/src/main/twirl/issues/commentlist.scala.html @@ -8,7 +8,7 @@
        @avatar(issue.openedUserName, 48)
        - @user(issue.openedUserName, styleClass="username strong") commented on @datetime(issue.registeredDate) + @user(issue.openedUserName, styleClass="username strong") commented @helper.html.datetimeago(issue.registeredDate) @if(hasWritePermission || loginAccount.map(_.userName == issue.openedUserName).getOrElse(false)){ @@ -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) @if(comment.action != "commit" && comment.action != "merge" && comment.action != "refer" && @@ -70,7 +70,7 @@ } else { @pullreq.map(_.userName):@pullreq.map(_.branch) to @pullreq.map(_.requestUserName):@pullreq.map(_.requestBranch) } - @datetime(comment.registeredDate) + @helper.html.datetimeago(comment.registeredDate)
        } @if(comment.action == "close" || comment.action == "close_comment"){ @@ -78,9 +78,9 @@ Closed @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) }
        } @@ -88,14 +88,14 @@
        Reopened @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)
        } @if(comment.action == "delete_branch"){
        Deleted @avatar(comment.commentedUserName, 20) - @user(comment.commentedUserName, styleClass="username strong") deleted the @pullreq.map(_.requestBranch) branch @datetime(comment.registeredDate) + @user(comment.commentedUserName, styleClass="username strong") deleted the @pullreq.map(_.requestBranch) branch @helper.html.datetimeago(comment.registeredDate)
        } } diff --git a/src/main/twirl/issues/issue.scala.html b/src/main/twirl/issues/issue.scala.html index 3b45ebf3c..3b7f125f6 100644 --- a/src/main/twirl/issues/issue.scala.html +++ b/src/main/twirl/issues/issue.scala.html @@ -28,7 +28,7 @@ Open } - @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") diff --git a/src/main/twirl/issues/listparts.scala.html b/src/main/twirl/issues/listparts.scala.html index d3b5a113f..ab9cbadf7 100644 --- a/src/main/twirl/issues/listparts.scala.html +++ b/src/main/twirl/issues/listparts.scala.html @@ -203,7 +203,7 @@ }
        - #@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 => @milestone } diff --git a/src/main/twirl/issues/milestones/list.scala.html b/src/main/twirl/issues/milestones/list.scala.html index 877083205..84a03a403 100644 --- a/src/main/twirl/issues/milestones/list.scala.html +++ b/src/main/twirl/issues/milestones/list.scala.html @@ -34,7 +34,7 @@ @milestone.title
        @if(milestone.closedDate.isDefined){ - Closed @datetime(milestone.closedDate.get) + Closed @helper.html.datetimeago(milestone.closedDate.get) } else { @milestone.dueDate.map { dueDate => @if(isPast(dueDate)){ diff --git a/src/main/twirl/pulls/pullreq.scala.html b/src/main/twirl/pulls/pullreq.scala.html index 35cebb3fd..495379bed 100644 --- a/src/main/twirl/pulls/pullreq.scala.html +++ b/src/main/twirl/pulls/pullreq.scala.html @@ -20,7 +20,7 @@ Merged @user(comment.commentedUserName, styleClass="username strong") merged @commits.size @plural(commits.size, "commit") into @pullreq.userName:@pullreq.branch from @pullreq.requestUserName:@pullreq.requestBranch - at @datetime(comment.registeredDate) + @helper.html.datetimeago(comment.registeredDate) }.getOrElse { Closed @user(issue.openedUserName, styleClass="username strong") wants to merge @commits.size @plural(commits.size, "commit") diff --git a/src/main/twirl/repo/blob.scala.html b/src/main/twirl/repo/blob.scala.html index 2c895ac36..68d3870d6 100644 --- a/src/main/twirl/repo/blob.scala.html +++ b/src/main/twirl/repo/blob.scala.html @@ -34,7 +34,7 @@
        @avatar(latestCommit, 20) @user(latestCommit.authorName, latestCommit.authorEmailAddress, "username strong") - @datetime(latestCommit.commitTime) + @helper.html.datetimeago(latestCommit.commitTime) @link(latestCommit.summary, repository)
        diff --git a/src/main/twirl/repo/branches.scala.html b/src/main/twirl/repo/branches.scala.html index 214c37c92..98576841e 100644 --- a/src/main/twirl/repo/branches.scala.html +++ b/src/main/twirl/repo/branches.scala.html @@ -22,7 +22,7 @@ }
    - @datetime(latestUpdateDate) + @helper.html.datetimeago(latestUpdateDate, false) @if(repository.repository.defaultBranch == branchName){ diff --git a/src/main/twirl/repo/commit.scala.html b/src/main/twirl/repo/commit.scala.html index a02223692..9b7c2f074 100644 --- a/src/main/twirl/repo/commit.scala.html +++ b/src/main/twirl/repo/commit.scala.html @@ -68,13 +68,13 @@
    @avatar(commit, 20) @user(commit.authorName, commit.authorEmailAddress, "username strong") - authored on @datetime(commit.authorTime) + authored @helper.html.datetimeago(commit.authorTime)
    @if(commit.isDifferentFromAuthor) {
    @user(commit.committerName, commit.committerEmailAddress, "username strong") - committed on @datetime(commit.commitTime) + committed @helper.html.datetimeago(commit.commitTime)
    } diff --git a/src/main/twirl/repo/commits.scala.html b/src/main/twirl/repo/commits.scala.html index be2b02f20..f0aaf3b9a 100644 --- a/src/main/twirl/repo/commits.scala.html +++ b/src/main/twirl/repo/commits.scala.html @@ -58,11 +58,11 @@ }
    @user(commit.authorName, commit.authorEmailAddress, "username") - authored @datetime(commit.authorTime) + authored @helper.html.datetimeago(commit.authorTime) @if(commit.isDifferentFromAuthor) { @user(commit.committerName, commit.committerEmailAddress, "username") - committed @datetime(commit.authorTime) + committed @helper.html.datetimeago(commit.authorTime) }
    diff --git a/src/main/twirl/repo/files.scala.html b/src/main/twirl/repo/files.scala.html index 2235d6ecd..ab14364a7 100644 --- a/src/main/twirl/repo/files.scala.html +++ b/src/main/twirl/repo/files.scala.html @@ -47,13 +47,13 @@
    @avatar(latestCommit, 20) @user(latestCommit.authorName, latestCommit.authorEmailAddress, "username strong") - authored on @datetime(latestCommit.authorTime) + authored @helper.html.datetimeago(latestCommit.authorTime)
    @if(latestCommit.isDifferentFromAuthor) {
    @user(latestCommit.committerName, latestCommit.committerEmailAddress, "username strong") - committed on @datetime(latestCommit.commitTime) + committed @helper.html.datetimeago(latestCommit.commitTime)
    } @@ -106,7 +106,7 @@ @link(file.message, repository) [@user(file.author, file.mailAddress)]
    @datetime(file.time)@helper.html.datetimeago(file.time, false)
    diff --git a/src/main/twirl/repo/tags.scala.html b/src/main/twirl/repo/tags.scala.html index e5b0fa928..cd611fbb6 100644 --- a/src/main/twirl/repo/tags.scala.html +++ b/src/main/twirl/repo/tags.scala.html @@ -14,7 +14,7 @@ @repository.tags.reverse.map { tag =>
  • @tag.name@datetime(tag.time)@helper.html.datetimeago(tag.time, false) @tag.id.substring(0, 10) ZIP diff --git a/src/main/twirl/search/code.scala.html b/src/main/twirl/search/code.scala.html index 20b08a611..04d0a1922 100644 --- a/src/main/twirl/search/code.scala.html +++ b/src/main/twirl/search/code.scala.html @@ -16,7 +16,7 @@ @files.drop((page - 1) * CodeLimit).take(CodeLimit).map { file =>
    @file.path
    -
    Latest commit at @datetime(file.lastModified)
    +
    Last commited @helper.html.datetimeago(file.lastModified)
    @Html(file.highlightText)
    } diff --git a/src/main/twirl/search/issues.scala.html b/src/main/twirl/search/issues.scala.html index d381091e2..7a9c17ae9 100644 --- a/src/main/twirl/search/issues.scala.html +++ b/src/main/twirl/search/issues.scala.html @@ -22,7 +22,7 @@ }
    Opened by @issue.openedUserName - at @datetime(issue.registeredDate) + @helper.html.datetimeago(issue.registeredDate) @if(issue.commentCount > 0){   @issue.commentCount @plural(issue.commentCount, "comment") } diff --git a/src/main/twirl/wiki/history.scala.html b/src/main/twirl/wiki/history.scala.html index bd2ba49d5..2052f4ce0 100644 --- a/src/main/twirl/wiki/history.scala.html +++ b/src/main/twirl/wiki/history.scala.html @@ -36,7 +36,7 @@
    @avatar(commit, 20) @user(commit.authorName, commit.authorEmailAddress) - @datetime(commit.authorTime): @commit.shortMessage + @helper.html.datetimeago(commit.authorTime): @commit.shortMessage
    + + + + @issues.map { case IssueInfo(issue, labels, milestone, commentCount) => + + + + } +
    + + + + @openCount Open +    + + + @closedCount Closed - } - @if(condition.repo.isDefined){ - - Clear filter on @condition.repo - - } -
    - @helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.IssuesService.IssueLimit, 7, condition.toURL) -
    - - @helper.html.dropdown( - value = (condition.sort, condition.direction) match { - case ("created" , "desc") => "Newest" - case ("created" , "asc" ) => "Oldest" - case ("comments", "desc") => "Most commented" - case ("comments", "asc" ) => "Least commented" - case ("updated" , "desc") => "Recently updated" - case ("updated" , "asc" ) => "Least recently updated" - }, - prefix = "Sort", - mini = false - ){ -
  • - - @helper.html.checkicon(condition.sort == "created" && condition.direction == "desc") Newest - -
  • -
  • - - @helper.html.checkicon(condition.sort == "created" && condition.direction == "asc") Oldest - -
  • -
  • - - @helper.html.checkicon(condition.sort == "comments" && condition.direction == "desc") Most commented - -
  • -
  • - - @helper.html.checkicon(condition.sort == "comments" && condition.direction == "asc") Least commented - -
  • -
  • - - @helper.html.checkicon(condition.sort == "updated" && condition.direction == "desc") Recently updated - -
  • -
  • - - @helper.html.checkicon(condition.sort == "updated" && condition.direction == "asc") Least recently updated - -
  • - } - - @if(issues.isEmpty){ - - - - } else { - @if(hasWritePermission){ - - - + + - - - } -
    - No issues to show. - @if(condition.labels.nonEmpty || condition.milestoneId.isDefined){ - Clear active filters. - } else { - @if(repository.isDefined){ - Create a new issue. - } - } -
    -
    - -
    - @helper.html.dropdown("Label") { - @labels.map { label => -
  • - - -   - @label.labelName - -
  • - } - } - @helper.html.dropdown("Assignee") { -
  • Clear assignee
  • - @collaborators.map { collaborator => -
  • @avatar(collaborator, 20) @collaborator
  • - } - } - @helper.html.dropdown("Milestone") { -
  • Clear this milestone
  • - @milestones.map { milestone => -
  • - - @milestone.title -
    - @milestone.dueDate.map { dueDate => - @if(isPast(dueDate)){ - Due by @date(dueDate) - } else { - Due by @date(dueDate) - } - }.getOrElse { - No due date - } -
    -
    -
  • - } - } -
    - @if(hasWritePermission){ - - } -
    -
    - @helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.IssuesService.IssueLimit, 10, condition.toURL)
    - - +
    + @if(issue.isPullRequest){ + + } else { + + } + @issue.repositoryName ・ + @if(issue.isPullRequest){ + @issue.title + } else { + @issue.title + } + @labels.map { label => + @label.labelName + } + + @issue.assignedUserName.map { userName => + @avatar(userName, 20, tooltip = true) + } + @if(commentCount > 0){ + + @commentCount + + } else { + + @commentCount + + } + +
    + #@issue.issueId opened by @user(issue.openedUserName, styleClass="username") @datetime(issue.registeredDate) + @milestone.map { milestone => + @milestone + } +
    +
    +
    + @helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.IssuesService.IssueLimit, 10, condition.toURL) +
    From 4c1b8004fcb32cbdde97c2f6a550eeb1d6819cc8 Mon Sep 17 00:00:00 2001 From: Tomofumi Tanaka Date: Wed, 29 Oct 2014 09:15:20 +0900 Subject: [PATCH 143/152] (refs #533)Admin user must not disable self account yourself --- src/main/scala/app/UserManagementController.scala | 12 +++++++++++- src/main/twirl/admin/users/user.scala.html | 3 +++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/scala/app/UserManagementController.scala b/src/main/scala/app/UserManagementController.scala index 612503959..d98d70366 100644 --- a/src/main/scala/app/UserManagementController.scala +++ b/src/main/scala/app/UserManagementController.scala @@ -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 + } + } + } } diff --git a/src/main/twirl/admin/users/user.scala.html b/src/main/twirl/admin/users/user.scala.html index fb022c0c2..1f2585777 100644 --- a/src/main/twirl/admin/users/user.scala.html +++ b/src/main/twirl/admin/users/user.scala.html @@ -16,6 +16,9 @@ Disable +
    + +
    } @if(account.map(_.password.nonEmpty).getOrElse(true)){ From e6e3786b4783be14d5c86a04abfb94cdd43de0fa Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sat, 1 Nov 2014 03:05:52 +0900 Subject: [PATCH 144/152] (refs #529)Visibility filter --- src/main/scala/app/DashboardController.scala | 21 +-- src/main/scala/service/IssuesService.scala | 66 +++++---- .../scala/service/PullRequestService.scala | 34 ++--- .../twirl/dashboard/issueslist.scala.html | 13 +- src/main/twirl/dashboard/pulls.scala.html | 44 +----- src/main/twirl/dashboard/pullslist.scala.html | 139 ++++++++++++------ 6 files changed, 177 insertions(+), 140 deletions(-) diff --git a/src/main/scala/app/DashboardController.scala b/src/main/scala/app/DashboardController.scala index 9a3c28f0a..4e0ffb23e 100644 --- a/src/main/scala/app/DashboardController.scala +++ b/src/main/scala/app/DashboardController.scala @@ -74,29 +74,16 @@ trait DashboardControllerBase extends ControllerBase { val userName = context.loginAccount.get.userName val allRepos = getAllRepositories(userName) - val userRepos = getUserRepositories(userName, context.baseUrl, true).map(repo => repo.owner -> repo.name) val filterUser = Map(filter -> userName) val page = IssueSearchCondition.page(request) - val counts = countIssueGroupByRepository( - IssueSearchCondition().copy(state = condition.state), filterUser, true, userRepos: _*) - dashboard.html.pulls( - dashboard.html.pullslist( - searchIssue(condition, filterUser, true, (page - 1) * PullRequestLimit, PullRequestLimit, allRepos: _*), - page, - countIssue(condition.copy(state = "open" ), filterUser, true, allRepos: _*), - countIssue(condition.copy(state = "closed"), filterUser, true, allRepos: _*), - condition, - None, - false), - getAllPullRequestCountGroupByUser(condition.state == "closed", userName), - userRepos.map { case (userName, repoName) => - (userName, repoName, counts.find { x => x._1 == userName && x._2 == repoName }.map(_._3).getOrElse(0)) - }.sortBy(_._3).reverse, + searchIssue(condition, filterUser, true, (page - 1) * PullRequestLimit, PullRequestLimit, allRepos: _*), + page, + countIssue(condition.copy(state = "open" ), filterUser, true, allRepos: _*), + countIssue(condition.copy(state = "closed"), filterUser, true, allRepos: _*), condition, filter) - } diff --git a/src/main/scala/service/IssuesService.scala b/src/main/scala/service/IssuesService.scala index 5688fc78f..e563b9ccc 100644 --- a/src/main/scala/service/IssuesService.scala +++ b/src/main/scala/service/IssuesService.scala @@ -77,28 +77,29 @@ trait IssuesService { } .toMap } - /** - * Returns list which contains issue count for each repository. - * If the issue does not exist, its repository is not included in the result. - * - * @param condition the search condition - * @param onlyPullRequest if true then returns only pull request, false then returns both of issue and pull request. - * @param repos Tuple of the repository owner and the repository name - * @return list which contains issue count for each repository - */ - def countIssueGroupByRepository( - condition: IssueSearchCondition, filterUser: Map[String, String], onlyPullRequest: Boolean, - repos: (String, String)*)(implicit s: Session): List[(String, String, Int)] = { - searchIssueQuery(repos, condition.copy(repo = None), filterUser, onlyPullRequest) - .groupBy { t => - t.userName -> t.repositoryName - } - .map { case (repo, t) => - (repo._1, repo._2, t.length) - } - .sortBy(_._3 desc) - .list - } + +// /** +// * Returns list which contains issue count for each repository. +// * If the issue does not exist, its repository is not included in the result. +// * +// * @param condition the search condition +// * @param onlyPullRequest if true then returns only pull request, false then returns both of issue and pull request. +// * @param repos Tuple of the repository owner and the repository name +// * @return list which contains issue count for each repository +// */ +// def countIssueGroupByRepository( +// condition: IssueSearchCondition, filterUser: Map[String, String], onlyPullRequest: Boolean, +// repos: (String, String)*)(implicit s: Session): List[(String, String, Int)] = { +// searchIssueQuery(repos, condition.copy(repo = None), filterUser, onlyPullRequest) +// .groupBy { t => +// t.userName -> t.repositoryName +// } +// .map { case (repo, t) => +// (repo._1, repo._2, t.length) +// } +// .sortBy(_._3 desc) +// .list +// } /** * Returns the search result against issues. @@ -181,7 +182,11 @@ trait IssuesService { (t3.byRepository(t1.userName, t1.repositoryName)) && (t3.labelName inSetBind condition.labels) } map(_.labelId))) - } exists, condition.labels.nonEmpty) + } exists, condition.labels.nonEmpty) && + (Repositories filter { t3 => + (t3.byRepository(t1.userName, t1.repositoryName)) && + (t3.isPrivate === (condition.visibility == Some("private")).bind) + } exists, condition.visibility.nonEmpty) } def createIssue(owner: String, repository: String, loginUser: String, title: String, content: Option[String], @@ -343,11 +348,12 @@ object IssuesService { repo: Option[String] = None, state: String = "open", sort: String = "created", - direction: String = "desc"){ + direction: String = "desc", + visibility: Option[String] = None){ def isEmpty: Boolean = { labels.isEmpty && milestoneId.isEmpty && author.isEmpty && assigned.isEmpty && - state == "open" && sort == "created" && direction == "desc" + state == "open" && sort == "created" && direction == "desc" && visibility.isEmpty } def nonEmpty: Boolean = !isEmpty @@ -364,7 +370,9 @@ object IssuesService { repo.map("for=" + urlEncode(_)), Some("state=" + urlEncode(state)), Some("sort=" + urlEncode(sort)), - Some("direction=" + urlEncode(direction))).flatten.mkString("&") + Some("direction=" + urlEncode(direction)), + visibility.map(x => "visibility=" + urlEncode(x)) + ).flatten.mkString("&") } @@ -378,7 +386,7 @@ object IssuesService { def apply(request: HttpServletRequest): IssueSearchCondition = IssueSearchCondition( param(request, "labels").map(_.split(",").toSet).getOrElse(Set.empty), - param(request, "milestone").map{ + param(request, "milestone").map { case "none" => None case x => x.toIntOpt }, @@ -387,7 +395,9 @@ object IssuesService { param(request, "for"), param(request, "state", Seq("open", "closed")).getOrElse("open"), param(request, "sort", Seq("created", "comments", "updated")).getOrElse("created"), - param(request, "direction", Seq("asc", "desc")).getOrElse("desc")) + param(request, "direction", Seq("asc", "desc")).getOrElse("desc"), + param(request, "visibility") + ) def page(request: HttpServletRequest) = try { val i = param(request, "page").getOrElse("1").toInt diff --git a/src/main/scala/service/PullRequestService.scala b/src/main/scala/service/PullRequestService.scala index d5bcb0b2b..9a3239b4c 100644 --- a/src/main/scala/service/PullRequestService.scala +++ b/src/main/scala/service/PullRequestService.scala @@ -36,23 +36,23 @@ trait PullRequestService { self: IssuesService => .list .map { x => PullRequestCount(x._1, x._2) } - def getAllPullRequestCountGroupByUser(closed: Boolean, userName: String)(implicit s: Session): List[PullRequestCount] = - PullRequests - .innerJoin(Issues).on { (t1, t2) => t1.byPrimaryKey(t2.userName, t2.repositoryName, t2.issueId) } - .innerJoin(Repositories).on { case ((t1, t2), t3) => t2.byRepository(t3.userName, t3.repositoryName) } - .filter { case ((t1, t2), t3) => - (t2.closed === closed.bind) && - ( - (t3.isPrivate === false.bind) || - (t3.userName === userName.bind) || - (Collaborators.filter { t4 => t4.byRepository(t3.userName, t3.repositoryName) && (t4.collaboratorName === userName.bind)} exists) - ) - } - .groupBy { case ((t1, t2), t3) => t2.openedUserName } - .map { case (userName, t) => userName -> t.length } - .sortBy(_._2 desc) - .list - .map { x => PullRequestCount(x._1, x._2) } +// def getAllPullRequestCountGroupByUser(closed: Boolean, userName: String)(implicit s: Session): List[PullRequestCount] = +// PullRequests +// .innerJoin(Issues).on { (t1, t2) => t1.byPrimaryKey(t2.userName, t2.repositoryName, t2.issueId) } +// .innerJoin(Repositories).on { case ((t1, t2), t3) => t2.byRepository(t3.userName, t3.repositoryName) } +// .filter { case ((t1, t2), t3) => +// (t2.closed === closed.bind) && +// ( +// (t3.isPrivate === false.bind) || +// (t3.userName === userName.bind) || +// (Collaborators.filter { t4 => t4.byRepository(t3.userName, t3.repositoryName) && (t4.collaboratorName === userName.bind)} exists) +// ) +// } +// .groupBy { case ((t1, t2), t3) => t2.openedUserName } +// .map { case (userName, t) => userName -> t.length } +// .sortBy(_._2 desc) +// .list +// .map { x => PullRequestCount(x._1, x._2) } def createPullRequest(originUserName: String, originRepositoryName: String, issueId: Int, originBranch: String, requestUserName: String, requestRepositoryName: String, requestBranch: String, diff --git a/src/main/twirl/dashboard/issueslist.scala.html b/src/main/twirl/dashboard/issueslist.scala.html index 248f68871..9e0bad8f7 100644 --- a/src/main/twirl/dashboard/issueslist.scala.html +++ b/src/main/twirl/dashboard/issueslist.scala.html @@ -29,7 +29,18 @@
    @helper.html.dropdown("Visibility", flat = true){ -
  • TODO
  • +
  • + + @helper.html.checkicon(condition.visibility == Some("private")) + Private repository only + +
  • +
  • + + @helper.html.checkicon(condition.visibility == Some("public")) + Public repository only + +
  • } @helper.html.dropdown("Organization", flat = true){
  • TODO
  • diff --git a/src/main/twirl/dashboard/pulls.scala.html b/src/main/twirl/dashboard/pulls.scala.html index 25caafec6..3b310e101 100644 --- a/src/main/twirl/dashboard/pulls.scala.html +++ b/src/main/twirl/dashboard/pulls.scala.html @@ -1,42 +1,14 @@ -@(listparts: play.twirl.api.Html, - counts: List[service.PullRequestService.PullRequestCount], - repositories: List[(String, String, Int)], +@(issues: List[service.IssuesService.IssueInfo], + page: Int, + openCount: Int, + closedCount: Int, condition: service.IssuesService.IssueSearchCondition, filter: String)(implicit context: app.Context) @import context._ @import view.helpers._ -@html.main("Your Issues"){ -
    - @dashboard.html.tab("pulls") -
    - - @listparts +@html.main("Pull Requests"){ +
    + @dashboard.html.tab("pulls") + @issueslist(issues, page, openCount, closedCount, condition, filter)
    -
    } diff --git a/src/main/twirl/dashboard/pullslist.scala.html b/src/main/twirl/dashboard/pullslist.scala.html index 46343b46e..9cfed59c4 100644 --- a/src/main/twirl/dashboard/pullslist.scala.html +++ b/src/main/twirl/dashboard/pullslist.scala.html @@ -3,20 +3,19 @@ openCount: Int, closedCount: Int, condition: service.IssuesService.IssueSearchCondition, - repository: Option[service.RepositoryService.RepositoryInfo], - hasWritePermission: Boolean)(implicit context: app.Context) + filter: String)(implicit context: app.Context) @import context._ @import view.helpers._ @import service.IssuesService.IssueInfo + +@*
    - @repository.map { repository => - @if(hasWritePermission){ -
    - @helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.PullRequestService.PullRequestLimit, 7, condition.toURL) - New pull request -
    - } - }
    @openCount Open @closedCount Closed @@ -64,38 +63,96 @@ } - - @if(issues.isEmpty){ - - - - } + *@ +
    - No pull requests to show. -
    + + + @issues.map { case IssueInfo(issue, labels, milestone, commentCount) => - - + - +
    + @avatarLink(issue.openedUserName, 20) by @user(issue.openedUserName, styleClass="username") @datetime(issue.registeredDate)  + @if(commentCount > 0){ + @commentCount @plural(commentCount, "comment") + } +
    + + } -
    + + + + @openCount Open +    + + + @closedCount Closed + + + +
    - - @issue.title - #@issue.issueId -
    - @issue.content.map { content => - @cut(content, 90) - }.getOrElse { - No description available - } -
    -
    - @avatarLink(issue.openedUserName, 20) by @user(issue.openedUserName, styleClass="username") @datetime(issue.registeredDate)  - @if(commentCount > 0){ - @commentCount @plural(commentCount, "comment") +
    + + @issue.title + #@issue.issueId +
    + @issue.content.map { content => + @cut(content, 90) + }.getOrElse { + No description available }
    -
    -
    - @helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.PullRequestService.PullRequestLimit, 10, condition.toURL) -
    -
    \ No newline at end of file + +
    + @helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.PullRequestService.PullRequestLimit, 10, condition.toURL) +
    From 2db674bb0310aab96d1784d616883cac303fb5d2 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 2 Nov 2014 13:26:46 +0900 Subject: [PATCH 145/152] (refs #529)Organization filter --- src/main/scala/app/DashboardController.scala | 9 ++- src/main/scala/service/AccountService.scala | 5 ++ src/main/scala/service/IssuesService.scala | 12 ++- src/main/twirl/dashboard/header.scala.html | 74 +++++++++++++++++++ src/main/twirl/dashboard/issues.scala.html | 5 +- .../twirl/dashboard/issueslist.scala.html | 65 +--------------- src/main/twirl/dashboard/pulls.scala.html | 5 +- src/main/twirl/dashboard/pullslist.scala.html | 65 +--------------- 8 files changed, 105 insertions(+), 135 deletions(-) create mode 100644 src/main/twirl/dashboard/header.scala.html diff --git a/src/main/scala/app/DashboardController.scala b/src/main/scala/app/DashboardController.scala index 4e0ffb23e..c8ea7d67d 100644 --- a/src/main/scala/app/DashboardController.scala +++ b/src/main/scala/app/DashboardController.scala @@ -9,7 +9,8 @@ class DashboardController extends DashboardControllerBase with UsersAuthenticator trait DashboardControllerBase extends ControllerBase { - self: IssuesService with PullRequestService with RepositoryService with UsersAuthenticator => + self: IssuesService with PullRequestService with RepositoryService with AccountService + with UsersAuthenticator => get("/dashboard/issues/repos")(usersOnly { searchIssues("created_by") @@ -59,7 +60,8 @@ trait DashboardControllerBase extends ControllerBase { countIssue(condition.copy(state = "open" ), filterUser, false, userRepos: _*), countIssue(condition.copy(state = "closed"), filterUser, false, userRepos: _*), condition, - filter) + filter, + getGroupNames(userName)) } private def searchPullRequests(filter: String, repository: Option[String]) = { @@ -83,7 +85,8 @@ trait DashboardControllerBase extends ControllerBase { countIssue(condition.copy(state = "open" ), filterUser, true, allRepos: _*), countIssue(condition.copy(state = "closed"), filterUser, true, allRepos: _*), condition, - filter) + filter, + getGroupNames(userName)) } diff --git a/src/main/scala/service/AccountService.scala b/src/main/scala/service/AccountService.scala index b815c5411..c502eb7b4 100644 --- a/src/main/scala/service/AccountService.scala +++ b/src/main/scala/service/AccountService.scala @@ -168,6 +168,11 @@ trait AccountService { Repositories.filter(_.userName === userName.bind).delete } + def getGroupNames(userName: String)(implicit s: Session): List[String] = { + List(userName) ++ + Collaborators.filter(_.collaboratorName === userName.bind).sortBy(_.userName).map(_.userName).list + } + } object AccountService extends AccountService diff --git a/src/main/scala/service/IssuesService.scala b/src/main/scala/service/IssuesService.scala index e563b9ccc..9f5e1e348 100644 --- a/src/main/scala/service/IssuesService.scala +++ b/src/main/scala/service/IssuesService.scala @@ -186,7 +186,8 @@ trait IssuesService { (Repositories filter { t3 => (t3.byRepository(t1.userName, t1.repositoryName)) && (t3.isPrivate === (condition.visibility == Some("private")).bind) - } exists, condition.visibility.nonEmpty) + } exists, condition.visibility.nonEmpty) && + (t1.userName inSetBind condition.groups, condition.groups.nonEmpty) } def createIssue(owner: String, repository: String, loginUser: String, title: String, content: Option[String], @@ -349,7 +350,8 @@ object IssuesService { state: String = "open", sort: String = "created", direction: String = "desc", - visibility: Option[String] = None){ + visibility: Option[String] = None, + groups: Set[String] = Set.empty){ def isEmpty: Boolean = { labels.isEmpty && milestoneId.isEmpty && author.isEmpty && assigned.isEmpty && @@ -371,7 +373,8 @@ object IssuesService { Some("state=" + urlEncode(state)), Some("sort=" + urlEncode(sort)), Some("direction=" + urlEncode(direction)), - visibility.map(x => "visibility=" + urlEncode(x)) + visibility.map(x => "visibility=" + urlEncode(x)), + if(groups.isEmpty) None else Some("groups=" + urlEncode(groups.mkString(","))) ).flatten.mkString("&") } @@ -396,7 +399,8 @@ object IssuesService { param(request, "state", Seq("open", "closed")).getOrElse("open"), param(request, "sort", Seq("created", "comments", "updated")).getOrElse("created"), param(request, "direction", Seq("asc", "desc")).getOrElse("desc"), - param(request, "visibility") + param(request, "visibility"), + param(request, "groups").map(_.split(",").toSet).getOrElse(Set.empty) ) def page(request: HttpServletRequest) = try { diff --git a/src/main/twirl/dashboard/header.scala.html b/src/main/twirl/dashboard/header.scala.html new file mode 100644 index 000000000..01c5bfc2e --- /dev/null +++ b/src/main/twirl/dashboard/header.scala.html @@ -0,0 +1,74 @@ +@(openCount: Int, + closedCount: Int, + condition: service.IssuesService.IssueSearchCondition, + groups: List[String])(implicit context: app.Context) +@import context._ +@import view.helpers._ + + + + @openCount Open +    + + + @closedCount Closed + + + \ No newline at end of file diff --git a/src/main/twirl/dashboard/issues.scala.html b/src/main/twirl/dashboard/issues.scala.html index 4d5af5d0c..09d3a4f6d 100644 --- a/src/main/twirl/dashboard/issues.scala.html +++ b/src/main/twirl/dashboard/issues.scala.html @@ -3,12 +3,13 @@ openCount: Int, closedCount: Int, condition: service.IssuesService.IssueSearchCondition, - filter: String)(implicit context: app.Context) + filter: String, + groups: List[String])(implicit context: app.Context) @import context._ @import view.helpers._ @html.main("Issues"){
    @dashboard.html.tab("issues") - @issueslist(issues, page, openCount, closedCount, condition, filter) + @issueslist(issues, page, openCount, closedCount, condition, filter, groups)
    } diff --git a/src/main/twirl/dashboard/issueslist.scala.html b/src/main/twirl/dashboard/issueslist.scala.html index 9e0bad8f7..b80b24768 100644 --- a/src/main/twirl/dashboard/issueslist.scala.html +++ b/src/main/twirl/dashboard/issueslist.scala.html @@ -3,7 +3,8 @@ openCount: Int, closedCount: Int, condition: service.IssuesService.IssueSearchCondition, - filter: String)(implicit context: app.Context) + filter: String, + groups: List[String])(implicit context: app.Context) @import context._ @import view.helpers._ @import service.IssuesService.IssueInfo @@ -17,67 +18,7 @@ @issues.map { case IssueInfo(issue, labels, milestone, commentCount) => diff --git a/src/main/twirl/dashboard/pulls.scala.html b/src/main/twirl/dashboard/pulls.scala.html index 3b310e101..13ec94b4d 100644 --- a/src/main/twirl/dashboard/pulls.scala.html +++ b/src/main/twirl/dashboard/pulls.scala.html @@ -3,12 +3,13 @@ openCount: Int, closedCount: Int, condition: service.IssuesService.IssueSearchCondition, - filter: String)(implicit context: app.Context) + filter: String, + groups: List[String])(implicit context: app.Context) @import context._ @import view.helpers._ @html.main("Pull Requests"){
    @dashboard.html.tab("pulls") - @issueslist(issues, page, openCount, closedCount, condition, filter) + @issueslist(issues, page, openCount, closedCount, condition, filter, groups)
    } diff --git a/src/main/twirl/dashboard/pullslist.scala.html b/src/main/twirl/dashboard/pullslist.scala.html index 9cfed59c4..eec1c3931 100644 --- a/src/main/twirl/dashboard/pullslist.scala.html +++ b/src/main/twirl/dashboard/pullslist.scala.html @@ -3,7 +3,8 @@ openCount: Int, closedCount: Int, condition: service.IssuesService.IssueSearchCondition, - filter: String)(implicit context: app.Context) + filter: String, + groups: List[String])(implicit context: app.Context) @import context._ @import view.helpers._ @import service.IssuesService.IssueInfo @@ -67,67 +68,7 @@
    - - - - @openCount Open -    - - - @closedCount Closed - - - + @dashboard.html.header(openCount, closedCount, condition, groups)
    @issues.map { case IssueInfo(issue, labels, milestone, commentCount) => From bb3f086aa66ab80f9e4b3432e3ff3567aba50c28 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 3 Nov 2014 00:31:34 +0900 Subject: [PATCH 146/152] (refs #529)Enhance dashboard header --- src/main/twirl/dashboard/issues.scala.html | 2 +- .../twirl/dashboard/issueslist.scala.html | 6 +- src/main/twirl/dashboard/pulls.scala.html | 2 +- src/main/twirl/dashboard/pullslist.scala.html | 56 +------------------ src/main/twirl/dashboard/tab.scala.html | 51 +++++++++++++---- src/main/twirl/index.scala.html | 2 +- 6 files changed, 48 insertions(+), 71 deletions(-) diff --git a/src/main/twirl/dashboard/issues.scala.html b/src/main/twirl/dashboard/issues.scala.html index 09d3a4f6d..16e3564ab 100644 --- a/src/main/twirl/dashboard/issues.scala.html +++ b/src/main/twirl/dashboard/issues.scala.html @@ -8,8 +8,8 @@ @import context._ @import view.helpers._ @html.main("Issues"){ + @dashboard.html.tab("issues")
    - @dashboard.html.tab("issues") @issueslist(issues, page, openCount, closedCount, condition, filter, groups)
    } diff --git a/src/main/twirl/dashboard/issueslist.scala.html b/src/main/twirl/dashboard/issueslist.scala.html index b80b24768..ae3b1308e 100644 --- a/src/main/twirl/dashboard/issueslist.scala.html +++ b/src/main/twirl/dashboard/issueslist.scala.html @@ -10,10 +10,8 @@ @import service.IssuesService.IssueInfo
    - - - - @openCount Open -    - - - @closedCount Closed - - - + @dashboard.html.header(openCount, closedCount, condition, groups)
    diff --git a/src/main/twirl/dashboard/pulls.scala.html b/src/main/twirl/dashboard/pulls.scala.html index 13ec94b4d..614dc9a0e 100644 --- a/src/main/twirl/dashboard/pulls.scala.html +++ b/src/main/twirl/dashboard/pulls.scala.html @@ -8,8 +8,8 @@ @import context._ @import view.helpers._ @html.main("Pull Requests"){ + @dashboard.html.tab("pulls")
    - @dashboard.html.tab("pulls") @issueslist(issues, page, openCount, closedCount, condition, filter, groups)
    } diff --git a/src/main/twirl/dashboard/pullslist.scala.html b/src/main/twirl/dashboard/pullslist.scala.html index eec1c3931..987764004 100644 --- a/src/main/twirl/dashboard/pullslist.scala.html +++ b/src/main/twirl/dashboard/pullslist.scala.html @@ -10,61 +10,9 @@ @import service.IssuesService.IssueInfo -@* -
    - - @helper.html.dropdown( - value = (condition.sort, condition.direction) match { - case ("created" , "desc") => "Newest" - case ("created" , "asc" ) => "Oldest" - case ("comments", "desc") => "Most commented" - case ("comments", "asc" ) => "Least commented" - case ("updated" , "desc") => "Recently updated" - case ("updated" , "asc" ) => "Least recently updated" - }, - prefix = "Sort", - mini = false - ){ -
  • - - @helper.html.checkicon(condition.sort == "created" && condition.direction == "desc") Newest - -
  • -
  • - - @helper.html.checkicon(condition.sort == "created" && condition.direction == "asc") Oldest - -
  • -
  • - - @helper.html.checkicon(condition.sort == "comments" && condition.direction == "desc") Most commented - -
  • -
  • - - @helper.html.checkicon(condition.sort == "comments" && condition.direction == "asc") Least commented - -
  • -
  • - - @helper.html.checkicon(condition.sort == "updated" && condition.direction == "desc") Recently updated - -
  • -
  • - - @helper.html.checkicon(condition.sort == "updated" && condition.direction == "asc") Least recently updated - -
  • - } - *@
    diff --git a/src/main/twirl/dashboard/tab.scala.html b/src/main/twirl/dashboard/tab.scala.html index 1a4326571..98d07ce8e 100644 --- a/src/main/twirl/dashboard/tab.scala.html +++ b/src/main/twirl/dashboard/tab.scala.html @@ -1,13 +1,44 @@ @(active: String = "")(implicit context: app.Context) @import context._ @import view.helpers._ - +
    +
    + News Feed + @if(loginAccount.isDefined){ + + + Pull Requests + + + + Issues + + } + @* + @if(active == ""){ + activities + } + *@ +
    +
    + \ No newline at end of file diff --git a/src/main/twirl/index.scala.html b/src/main/twirl/index.scala.html index ec8b7ce78..5cbe664c8 100644 --- a/src/main/twirl/index.scala.html +++ b/src/main/twirl/index.scala.html @@ -4,8 +4,8 @@ @import context._ @import view.helpers._ @main("GitBucket"){ + @dashboard.html.tab()
    - @dashboard.html.tab()
    @helper.html.activities(activities) From a9d58698cdeb710bf45bad26456f1d2ad2fccbc0 Mon Sep 17 00:00:00 2001 From: takezoe Date: Mon, 3 Nov 2014 01:40:47 +0900 Subject: [PATCH 147/152] (refs #529)Adjust bottom line --- src/main/twirl/dashboard/tab.scala.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/twirl/dashboard/tab.scala.html b/src/main/twirl/dashboard/tab.scala.html index 98d07ce8e..3ce36059e 100644 --- a/src/main/twirl/dashboard/tab.scala.html +++ b/src/main/twirl/dashboard/tab.scala.html @@ -31,7 +31,7 @@ div.dashboard-nav { div.dashboard-nav a { line-height: 10px; margin-left: 20px; - padding-bottom: 12px; + padding-bottom: 13px; padding-left: 4px; padding-right: 4px; color: #888; From badbe73f4ecf07de052314812ef66e513752258a Mon Sep 17 00:00:00 2001 From: takezoe Date: Mon, 3 Nov 2014 02:30:19 +0900 Subject: [PATCH 148/152] Fix for Firefox --- src/main/twirl/issues/labels/list.scala.html | 2 +- src/main/twirl/issues/listparts.scala.html | 2 +- src/main/twirl/issues/milestones/list.scala.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/twirl/issues/labels/list.scala.html b/src/main/twirl/issues/labels/list.scala.html index f21a88b1b..3493ddd1b 100644 --- a/src/main/twirl/issues/labels/list.scala.html +++ b/src/main/twirl/issues/labels/list.scala.html @@ -7,7 +7,7 @@ @html.main(s"Labels - ${repository.owner}/${repository.name}"){ @html.menu("issues", repository){ @issues.html.tab("labels", hasWritePermission, repository) -   +
    diff --git a/src/main/twirl/issues/listparts.scala.html b/src/main/twirl/issues/listparts.scala.html index ab9cbadf7..1ff944f79 100644 --- a/src/main/twirl/issues/listparts.scala.html +++ b/src/main/twirl/issues/listparts.scala.html @@ -12,6 +12,7 @@ @import context._ @import view.helpers._ @import service.IssuesService.IssueInfo +
    @if(condition.nonEmpty){ } - 
    diff --git a/src/main/twirl/issues/milestones/list.scala.html b/src/main/twirl/issues/milestones/list.scala.html index 84a03a403..b0c498b3a 100644 --- a/src/main/twirl/issues/milestones/list.scala.html +++ b/src/main/twirl/issues/milestones/list.scala.html @@ -7,7 +7,7 @@ @html.main(s"Milestones - ${repository.owner}/${repository.name}"){ @html.menu("issues", repository){ @issues.html.tab("milestones", hasWritePermission, repository) -   +
    From 1c2af36c92db338dc11fc0513420532fa4538b42 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 3 Nov 2014 04:35:41 +0900 Subject: [PATCH 149/152] (refs #529)Mentioned filter --- src/main/scala/app/DashboardController.scala | 8 ++++++++ src/main/scala/service/IssuesService.scala | 18 +++++++++++++----- src/main/twirl/dashboard/issueslist.scala.html | 2 +- src/main/twirl/dashboard/pullslist.scala.html | 2 +- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/main/scala/app/DashboardController.scala b/src/main/scala/app/DashboardController.scala index c8ea7d67d..7bf30c1d5 100644 --- a/src/main/scala/app/DashboardController.scala +++ b/src/main/scala/app/DashboardController.scala @@ -24,6 +24,10 @@ trait DashboardControllerBase extends ControllerBase { searchIssues("created_by") }) + get("/dashboard/issues/mentioned")(usersOnly { + searchIssues("mentioned") + }) + get("/dashboard/pulls")(usersOnly { searchPullRequests("created_by", None) }) @@ -32,6 +36,10 @@ trait DashboardControllerBase extends ControllerBase { searchPullRequests("created_by", None) }) + get("/dashboard/pulls/mentioned")(usersOnly { + searchPullRequests("mentioned", None) + }) + get("/dashboard/pulls/public")(usersOnly { searchPullRequests("not_created_by", None) }) diff --git a/src/main/scala/service/IssuesService.scala b/src/main/scala/service/IssuesService.scala index 9f5e1e348..ef39a368f 100644 --- a/src/main/scala/service/IssuesService.scala +++ b/src/main/scala/service/IssuesService.scala @@ -105,7 +105,7 @@ trait IssuesService { * Returns the search result against issues. * * @param condition the search condition - * @param filterUser the filter user name (key is "all", "assigned", "created_by" or "not_created_by", value is the user name) + * @param filterUser the filter user name (key is "all", "assigned", "created_by", "not_created_by" or "mentioned", value is the user name) * @param pullRequest if true then returns only pull requests, false then returns only issues. * @param offset the offset for pagination * @param limit the limit for pagination @@ -175,6 +175,7 @@ trait IssuesService { (t1.assignedUserName === condition.assigned.get.bind, condition.assigned.isDefined) && (t1.openedUserName === condition.author.get.bind, condition.author.isDefined) && (t1.pullRequest === pullRequest.bind) && + // Label filter (IssueLabels filter { t2 => (t2.byIssue(t1.userName, t1.repositoryName, t1.issueId)) && (t2.labelId in @@ -183,11 +184,18 @@ trait IssuesService { (t3.labelName inSetBind condition.labels) } map(_.labelId))) } exists, condition.labels.nonEmpty) && - (Repositories filter { t3 => - (t3.byRepository(t1.userName, t1.repositoryName)) && - (t3.isPrivate === (condition.visibility == Some("private")).bind) + // Visibility filter + (Repositories filter { t2 => + (t2.byRepository(t1.userName, t1.repositoryName)) && + (t2.isPrivate === (condition.visibility == Some("private")).bind) } exists, condition.visibility.nonEmpty) && - (t1.userName inSetBind condition.groups, condition.groups.nonEmpty) + // Organization (group) filter + (t1.userName inSetBind condition.groups, condition.groups.nonEmpty) && + // Mentioned filter + ((t1.openedUserName === filterUser("mentioned").bind) || t1.assignedUserName === filterUser("mentioned").bind || + (IssueComments filter { t2 => + (t2.byIssue(t1.userName, t1.repositoryName, t1.issueId)) && (t2.commentedUserName === filterUser("mentioned").bind) + } exists), filterUser.get("mentioned").isDefined) } def createIssue(owner: String, repository: String, loginUser: String, title: String, content: Option[String], diff --git a/src/main/twirl/dashboard/issueslist.scala.html b/src/main/twirl/dashboard/issueslist.scala.html index ae3b1308e..79c55177a 100644 --- a/src/main/twirl/dashboard/issueslist.scala.html +++ b/src/main/twirl/dashboard/issueslist.scala.html @@ -11,7 +11,7 @@ diff --git a/src/main/twirl/dashboard/pullslist.scala.html b/src/main/twirl/dashboard/pullslist.scala.html index 987764004..fbddac5ee 100644 --- a/src/main/twirl/dashboard/pullslist.scala.html +++ b/src/main/twirl/dashboard/pullslist.scala.html @@ -11,7 +11,7 @@
    From f59e86f5ca46c2eb1b4bf1afcbe4f1272c53913f Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 3 Nov 2014 05:25:03 +0900 Subject: [PATCH 150/152] (refs #529)Add icons --- etc/icons.svg | 2592 +++++------------ src/main/twirl/dashboard/tab.scala.html | 19 +- src/main/twirl/index.scala.html | 3 + .../webapp/assets/common/images/menu-feed.png | Bin 0 -> 4404 bytes 4 files changed, 765 insertions(+), 1849 deletions(-) create mode 100644 src/main/webapp/assets/common/images/menu-feed.png diff --git a/etc/icons.svg b/etc/icons.svg index 1d50b97e7..9372a97d2 100644 --- a/etc/icons.svg +++ b/etc/icons.svg @@ -1,1844 +1,754 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/twirl/dashboard/tab.scala.html b/src/main/twirl/dashboard/tab.scala.html index 3ce36059e..aca044f5e 100644 --- a/src/main/twirl/dashboard/tab.scala.html +++ b/src/main/twirl/dashboard/tab.scala.html @@ -3,22 +3,20 @@ @import view.helpers._
    - News Feed + + + News Feed + @if(loginAccount.isDefined){ - + Pull Requests - + Issues } - @* - @if(active == ""){ - activities - } - *@