mirror of
https://github.com/gitbucket/gitbucket.git
synced 2026-05-07 15:47:06 +02:00
Show the commit status in various places (#2601)
This commit is contained in:
@@ -21,11 +21,17 @@ class DashboardController
|
||||
with WebHookPullRequestService
|
||||
with WebHookPullRequestReviewCommentService
|
||||
with MilestonesService
|
||||
with CommitStatusService
|
||||
with UsersAuthenticator
|
||||
with RequestCache
|
||||
|
||||
trait DashboardControllerBase extends ControllerBase {
|
||||
self: IssuesService with PullRequestService with RepositoryService with AccountService with UsersAuthenticator =>
|
||||
self: IssuesService
|
||||
with PullRequestService
|
||||
with RepositoryService
|
||||
with AccountService
|
||||
with CommitStatusService
|
||||
with UsersAuthenticator =>
|
||||
|
||||
get("/dashboard/repos")(usersOnly {
|
||||
val repos = getVisibleRepositories(
|
||||
@@ -86,9 +92,10 @@ trait DashboardControllerBase extends ControllerBase {
|
||||
val condition = getOrCreateCondition(Keys.Session.DashboardIssues, filter, userName)
|
||||
val userRepos = getUserRepositories(userName, true).map(repo => repo.owner -> repo.name)
|
||||
val page = IssueSearchCondition.page(request)
|
||||
val issues = searchIssue(condition, IssueSearchOption.Issues, (page - 1) * IssueLimit, IssueLimit, userRepos: _*)
|
||||
|
||||
html.issues(
|
||||
searchIssue(condition, IssueSearchOption.Issues, (page - 1) * IssueLimit, IssueLimit, userRepos: _*),
|
||||
issues.map(issue => (issue, None)),
|
||||
page,
|
||||
countIssue(condition.copy(state = "open"), IssueSearchOption.Issues, userRepos: _*),
|
||||
countIssue(condition.copy(state = "closed"), IssueSearchOption.Issues, userRepos: _*),
|
||||
@@ -116,15 +123,21 @@ trait DashboardControllerBase extends ControllerBase {
|
||||
val condition = getOrCreateCondition(Keys.Session.DashboardPulls, filter, userName)
|
||||
val allRepos = getAllRepositories(userName)
|
||||
val page = IssueSearchCondition.page(request)
|
||||
val issues = searchIssue(
|
||||
condition,
|
||||
IssueSearchOption.PullRequests,
|
||||
(page - 1) * PullRequestLimit,
|
||||
PullRequestLimit,
|
||||
allRepos: _*
|
||||
)
|
||||
val status = issues.map { issue =>
|
||||
issue.commitId.flatMap { commitId =>
|
||||
getCommitStatusWithSummary(issue.issue.userName, issue.issue.repositoryName, commitId)
|
||||
}
|
||||
}
|
||||
|
||||
html.pulls(
|
||||
searchIssue(
|
||||
condition,
|
||||
IssueSearchOption.PullRequests,
|
||||
(page - 1) * PullRequestLimit,
|
||||
PullRequestLimit,
|
||||
allRepos: _*
|
||||
),
|
||||
issues.zip(status),
|
||||
page,
|
||||
countIssue(condition.copy(state = "open"), IssueSearchOption.PullRequests, allRepos: _*),
|
||||
countIssue(condition.copy(state = "closed"), IssueSearchOption.PullRequests, allRepos: _*),
|
||||
|
||||
@@ -467,13 +467,15 @@ trait IssuesControllerBase extends ControllerBase {
|
||||
defining(repository.owner, repository.name) {
|
||||
case (owner, repoName) =>
|
||||
val page = IssueSearchCondition.page(request)
|
||||
|
||||
// retrieve search condition
|
||||
val condition = IssueSearchCondition(request)
|
||||
// search issues
|
||||
val issues =
|
||||
searchIssue(condition, IssueSearchOption.Issues, (page - 1) * IssueLimit, IssueLimit, owner -> repoName)
|
||||
|
||||
html.list(
|
||||
"issues",
|
||||
searchIssue(condition, IssueSearchOption.Issues, (page - 1) * IssueLimit, IssueLimit, owner -> repoName),
|
||||
issues.map(issue => (issue, None)),
|
||||
page,
|
||||
getAssignableUserNames(owner, repoName),
|
||||
getMilestones(owner, repoName),
|
||||
|
||||
@@ -2,7 +2,13 @@ package gitbucket.core.controller
|
||||
|
||||
import gitbucket.core.issues.milestones.html
|
||||
import gitbucket.core.service.IssuesService.{IssueLimit, IssueSearchCondition}
|
||||
import gitbucket.core.service.{AccountService, IssueSearchOption, MilestonesService, RepositoryService}
|
||||
import gitbucket.core.service.{
|
||||
AccountService,
|
||||
CommitStatusService,
|
||||
IssueSearchOption,
|
||||
MilestonesService,
|
||||
RepositoryService
|
||||
}
|
||||
import gitbucket.core.util.Implicits._
|
||||
import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator}
|
||||
import gitbucket.core.util.SyntaxSugars._
|
||||
@@ -15,11 +21,16 @@ class MilestonesController
|
||||
with MilestonesService
|
||||
with RepositoryService
|
||||
with AccountService
|
||||
with CommitStatusService
|
||||
with ReferrerAuthenticator
|
||||
with WritableUsersAuthenticator
|
||||
|
||||
trait MilestonesControllerBase extends ControllerBase {
|
||||
self: MilestonesService with RepositoryService with ReferrerAuthenticator with WritableUsersAuthenticator =>
|
||||
self: MilestonesService
|
||||
with RepositoryService
|
||||
with CommitStatusService
|
||||
with ReferrerAuthenticator
|
||||
with WritableUsersAuthenticator =>
|
||||
|
||||
case class MilestoneForm(title: String, description: Option[String], dueDate: Option[java.util.Date])
|
||||
|
||||
@@ -45,15 +56,22 @@ trait MilestonesControllerBase extends ControllerBase {
|
||||
request,
|
||||
milestone.get.title
|
||||
)
|
||||
val issues = searchIssue(
|
||||
condition,
|
||||
IssueSearchOption.Both,
|
||||
(page - 1) * IssueLimit,
|
||||
IssueLimit,
|
||||
repository.owner -> repository.name
|
||||
)
|
||||
val status = issues.map { issue =>
|
||||
issue.commitId.flatMap { commitId =>
|
||||
getCommitStatusWithSummary(issue.issue.userName, issue.issue.repositoryName, commitId)
|
||||
}
|
||||
}
|
||||
|
||||
html.milestone(
|
||||
condition.state,
|
||||
searchIssue(
|
||||
condition,
|
||||
IssueSearchOption.Both,
|
||||
(page - 1) * IssueLimit,
|
||||
IssueLimit,
|
||||
repository.owner -> repository.name
|
||||
),
|
||||
issues.zip(status),
|
||||
page,
|
||||
getAssignableUserNames(repository.owner, repository.name),
|
||||
getPriorities(repository.owner, repository.name),
|
||||
|
||||
@@ -219,7 +219,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
val branchProtection = getProtectedBranchInfo(owner, name, pullreq.branch)
|
||||
val mergeStatus = PullRequestService.MergeStatus(
|
||||
conflictMessage = conflictMessage,
|
||||
commitStatues = getCommitStatues(owner, name, pullreq.commitIdTo),
|
||||
commitStatuses = getCommitStatuses(owner, name, pullreq.commitIdTo),
|
||||
branchProtection = branchProtection,
|
||||
branchIsOutOfDate = JGitUtil.getShaByRef(owner, name, pullreq.branch) != Some(pullreq.commitIdFrom),
|
||||
needStatusCheck = context.loginAccount
|
||||
@@ -637,19 +637,26 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
defining(repository.owner, repository.name) {
|
||||
case (owner, repoName) =>
|
||||
val page = IssueSearchCondition.page(request)
|
||||
|
||||
// retrieve search condition
|
||||
val condition = IssueSearchCondition(request)
|
||||
// search issues
|
||||
val issues = searchIssue(
|
||||
condition,
|
||||
IssueSearchOption.PullRequests,
|
||||
(page - 1) * PullRequestLimit,
|
||||
PullRequestLimit,
|
||||
owner -> repoName
|
||||
)
|
||||
// commit status
|
||||
val status = issues.map { issue =>
|
||||
issue.commitId.flatMap { commitId =>
|
||||
getCommitStatusWithSummary(owner, repoName, commitId)
|
||||
}
|
||||
}
|
||||
|
||||
gitbucket.core.issues.html.list(
|
||||
"pulls",
|
||||
searchIssue(
|
||||
condition,
|
||||
IssueSearchOption.PullRequests,
|
||||
(page - 1) * PullRequestLimit,
|
||||
PullRequestLimit,
|
||||
owner -> repoName
|
||||
),
|
||||
issues.zip(status),
|
||||
page,
|
||||
getAssignableUserNames(owner, repoName),
|
||||
getMilestones(owner, repoName),
|
||||
|
||||
@@ -186,7 +186,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
|
||||
redirect(s"/${repository.owner}/${repository.name}/settings/branches")
|
||||
} else {
|
||||
val protection = ApiBranchProtection(getProtectedBranchInfo(repository.owner, repository.name, branch))
|
||||
val lastWeeks = getRecentStatuesContexts(
|
||||
val lastWeeks = getRecentStatusContexts(
|
||||
repository.owner,
|
||||
repository.name,
|
||||
Date.from(LocalDateTime.now.minusWeeks(1).toInstant(ZoneOffset.UTC))
|
||||
|
||||
@@ -4,7 +4,6 @@ import java.io.{File, FileInputStream, FileOutputStream}
|
||||
|
||||
import scala.util.Using
|
||||
import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
|
||||
import gitbucket.core.plugin.PluginRegistry
|
||||
import gitbucket.core.repo.html
|
||||
import gitbucket.core.helper
|
||||
import gitbucket.core.model.activity.DeleteBranchInfo
|
||||
@@ -15,9 +14,9 @@ import gitbucket.core.util.StringUtil._
|
||||
import gitbucket.core.util.SyntaxSugars._
|
||||
import gitbucket.core.util.Implicits._
|
||||
import gitbucket.core.util.Directory._
|
||||
import gitbucket.core.model.{Account, CommitState, CommitStatus}
|
||||
import gitbucket.core.model.Account
|
||||
import gitbucket.core.service.RepositoryService.RepositoryInfo
|
||||
import gitbucket.core.util.JGitUtil.{CommitInfo, createBranch}
|
||||
import gitbucket.core.util.JGitUtil.CommitInfo
|
||||
import gitbucket.core.view
|
||||
import gitbucket.core.view.helpers
|
||||
import org.apache.commons.compress.archivers.{ArchiveEntry, ArchiveOutputStream}
|
||||
@@ -263,23 +262,8 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
val (branchName, path) = repository.splitPath(multiParams("splat").head)
|
||||
val page = params.get("page").flatMap(_.toIntOpt).getOrElse(1)
|
||||
|
||||
def getStatuses(sha: String): List[CommitStatus] = {
|
||||
getCommitStatues(repository.owner, repository.name, sha)
|
||||
}
|
||||
|
||||
def getSummary(statuses: List[CommitStatus]): (CommitState, String) = {
|
||||
val stateMap = statuses.groupBy(_.state)
|
||||
val state = CommitState.combine(stateMap.keySet)
|
||||
val summary = stateMap.map { case (keyState, states) => s"${states.size} ${keyState.name}" }.mkString(", ")
|
||||
state -> summary
|
||||
}
|
||||
|
||||
Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) {
|
||||
git =>
|
||||
def getTags(sha: String): List[String] = {
|
||||
JGitUtil.getTagsOnCommit(git, sha)
|
||||
}
|
||||
|
||||
JGitUtil.getCommitLog(git, branchName, page, 30, path) match {
|
||||
case Right((logs, hasNext)) =>
|
||||
html.commits(
|
||||
@@ -288,34 +272,33 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
repository,
|
||||
logs
|
||||
.map {
|
||||
c =>
|
||||
CommitInfo(
|
||||
id = c.id,
|
||||
shortMessage = c.shortMessage,
|
||||
fullMessage = c.fullMessage,
|
||||
parents = c.parents,
|
||||
authorTime = c.authorTime,
|
||||
authorName = c.authorName,
|
||||
authorEmailAddress = c.authorEmailAddress,
|
||||
commitTime = c.commitTime,
|
||||
committerName = c.committerName,
|
||||
committerEmailAddress = c.committerEmailAddress,
|
||||
commitSign = c.commitSign,
|
||||
verified = c.commitSign
|
||||
.flatMap { s =>
|
||||
GpgUtil.verifySign(s)
|
||||
}
|
||||
commit =>
|
||||
(
|
||||
CommitInfo(
|
||||
id = commit.id,
|
||||
shortMessage = commit.shortMessage,
|
||||
fullMessage = commit.fullMessage,
|
||||
parents = commit.parents,
|
||||
authorTime = commit.authorTime,
|
||||
authorName = commit.authorName,
|
||||
authorEmailAddress = commit.authorEmailAddress,
|
||||
commitTime = commit.commitTime,
|
||||
committerName = commit.committerName,
|
||||
committerEmailAddress = commit.committerEmailAddress,
|
||||
commitSign = commit.commitSign,
|
||||
verified = commit.commitSign.flatMap(GpgUtil.verifySign)
|
||||
),
|
||||
JGitUtil.getTagsOnCommit(git, commit.id),
|
||||
getCommitStatusWithSummary(repository.owner, repository.name, commit.id)
|
||||
)
|
||||
}
|
||||
.splitWith { (commit1, commit2) =>
|
||||
view.helpers.date(commit1.commitTime) == view.helpers.date(commit2.commitTime)
|
||||
.splitWith {
|
||||
case ((commit1, _, _), (commit2, _, _)) =>
|
||||
view.helpers.date(commit1.commitTime) == view.helpers.date(commit2.commitTime)
|
||||
},
|
||||
page,
|
||||
hasNext,
|
||||
hasDeveloperRole(repository.owner, repository.name, context.loginAccount),
|
||||
getStatuses,
|
||||
getSummary,
|
||||
getTags
|
||||
hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
|
||||
)
|
||||
case Left(_) => NotFound()
|
||||
}
|
||||
@@ -731,6 +714,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
new JGitUtil.CommitInfo(revCommit),
|
||||
JGitUtil.getBranchesOfCommit(git, revCommit.getName),
|
||||
JGitUtil.getTagsOfCommit(git, revCommit.getName),
|
||||
getCommitStatusWithSummary(repository.owner, repository.name, revCommit.getName),
|
||||
getCommitComments(repository.owner, repository.name, id, true),
|
||||
repository,
|
||||
diffs,
|
||||
@@ -889,19 +873,20 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
defaultBranch = repository.repository.defaultBranch,
|
||||
origin = repository.repository.originUserName.isEmpty
|
||||
)
|
||||
.sortBy(br => (br.mergeInfo.isEmpty, br.commitTime))
|
||||
.sortBy(branch => (branch.mergeInfo.isEmpty, branch.commitTime))
|
||||
.map(
|
||||
br =>
|
||||
branch =>
|
||||
(
|
||||
br,
|
||||
branch,
|
||||
getPullRequestByRequestCommit(
|
||||
repository.owner,
|
||||
repository.name,
|
||||
repository.repository.defaultBranch,
|
||||
br.name,
|
||||
br.commitId
|
||||
branch.name,
|
||||
branch.commitId
|
||||
),
|
||||
protectedBranches.contains(br.name)
|
||||
protectedBranches.contains(branch.name),
|
||||
getCommitStatusWithSummary(repository.owner, repository.name, branch.commitId)
|
||||
)
|
||||
)
|
||||
.reverse
|
||||
@@ -1085,6 +1070,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
repository,
|
||||
if (path == ".") Nil else path.split("/").toList, // current path
|
||||
new JGitUtil.CommitInfo(lastModifiedCommit), // last modified commit
|
||||
getCommitStatusWithSummary(repository.owner, repository.name, lastModifiedCommit.getName),
|
||||
commitCount,
|
||||
files,
|
||||
readme,
|
||||
|
||||
@@ -47,7 +47,7 @@ trait ApiRepositoryStatusControllerBase extends ControllerBase {
|
||||
ref <- params.get("ref")
|
||||
sha <- JGitUtil.getShaByRef(repository.owner, repository.name, ref)
|
||||
} yield {
|
||||
JsonFormat(getCommitStatuesWithCreator(repository.owner, repository.name, sha).map {
|
||||
JsonFormat(getCommitStatusesWithCreator(repository.owner, repository.name, sha).map {
|
||||
case (status, creator) =>
|
||||
ApiCommitStatus(status, ApiUser(creator))
|
||||
})
|
||||
@@ -73,7 +73,7 @@ trait ApiRepositoryStatusControllerBase extends ControllerBase {
|
||||
owner <- getAccountByUserName(repository.owner)
|
||||
sha <- JGitUtil.getShaByRef(repository.owner, repository.name, ref)
|
||||
} yield {
|
||||
val statuses = getCommitStatuesWithCreator(repository.owner, repository.name, sha)
|
||||
val statuses = getCommitStatusesWithCreator(repository.owner, repository.name, sha)
|
||||
JsonFormat(ApiCombinedCommitStatus(sha, statuses, ApiRepository(repository, owner)))
|
||||
}) getOrElse NotFound()
|
||||
})
|
||||
|
||||
@@ -47,6 +47,18 @@ trait CommitStatusService {
|
||||
)
|
||||
}
|
||||
|
||||
def getCommitStatusWithSummary(userName: String, repositoryName: String, sha: String)(
|
||||
implicit s: Session
|
||||
): Option[(CommitState, List[CommitStatus])] = {
|
||||
val statuses = getCommitStatuses(userName, repositoryName, sha)
|
||||
if (statuses.isEmpty) {
|
||||
None
|
||||
} else {
|
||||
val summary = CommitState.combine(statuses.groupBy(_.state).keySet)
|
||||
Some((summary, statuses))
|
||||
}
|
||||
}
|
||||
|
||||
def getCommitStatus(userName: String, repositoryName: String, id: Int)(implicit s: Session): Option[CommitStatus] =
|
||||
CommitStatuses.filter(t => t.byPrimaryKey(id) && t.byRepository(userName, repositoryName)).firstOption
|
||||
|
||||
@@ -55,10 +67,12 @@ trait CommitStatusService {
|
||||
): Option[CommitStatus] =
|
||||
CommitStatuses.filter(t => t.byCommit(userName, repositoryName, sha) && t.context === context.bind).firstOption
|
||||
|
||||
def getCommitStatues(userName: String, repositoryName: String, sha: String)(implicit s: Session): List[CommitStatus] =
|
||||
byCommitStatues(userName, repositoryName, sha).list
|
||||
def getCommitStatuses(userName: String, repositoryName: String, sha: String)(
|
||||
implicit s: Session
|
||||
): List[CommitStatus] =
|
||||
byCommitStatus(userName, repositoryName, sha).list
|
||||
|
||||
def getRecentStatuesContexts(userName: String, repositoryName: String, time: java.util.Date)(
|
||||
def getRecentStatusContexts(userName: String, repositoryName: String, time: java.util.Date)(
|
||||
implicit s: Session
|
||||
): List[String] =
|
||||
CommitStatuses
|
||||
@@ -68,15 +82,15 @@ trait CommitStatusService {
|
||||
.map(_._1)
|
||||
.list
|
||||
|
||||
def getCommitStatuesWithCreator(userName: String, repositoryName: String, sha: String)(
|
||||
def getCommitStatusesWithCreator(userName: String, repositoryName: String, sha: String)(
|
||||
implicit s: Session
|
||||
): List[(CommitStatus, Account)] =
|
||||
byCommitStatues(userName, repositoryName, sha)
|
||||
byCommitStatus(userName, repositoryName, sha)
|
||||
.join(Accounts)
|
||||
.filter { case (t, a) => t.creator === a.userName }
|
||||
.list
|
||||
|
||||
protected def byCommitStatues(userName: String, repositoryName: String, sha: String)(implicit s: Session) =
|
||||
protected def byCommitStatus(userName: String, repositoryName: String, sha: String)(implicit s: Session) =
|
||||
CommitStatuses.filter(t => t.byCommit(userName, repositoryName, sha)).sortBy(_.updatedDate desc)
|
||||
|
||||
}
|
||||
|
||||
@@ -188,37 +188,6 @@ trait IssuesService {
|
||||
.toMap
|
||||
}
|
||||
|
||||
def getCommitStatues(userName: String, repositoryName: String, issueId: Int)(
|
||||
implicit s: Session
|
||||
): Option[CommitStatusInfo] = {
|
||||
val status = PullRequests
|
||||
.filter { pr =>
|
||||
pr.userName === userName.bind && pr.repositoryName === repositoryName.bind && pr.issueId === issueId.bind
|
||||
}
|
||||
.join(CommitStatuses)
|
||||
.on {
|
||||
case pr ~ cs =>
|
||||
pr.userName === cs.userName && pr.repositoryName === cs.repositoryName && pr.commitIdTo === cs.commitId
|
||||
}
|
||||
.list
|
||||
|
||||
if (status.nonEmpty) {
|
||||
val (_, cs) = status.head
|
||||
Some(
|
||||
CommitStatusInfo(
|
||||
count = status.length,
|
||||
successCount = status.count(_._2.state == CommitState.SUCCESS),
|
||||
context = (if (status.length == 1) Some(cs.context) else None),
|
||||
state = (if (status.length == 1) Some(cs.state) else None),
|
||||
targetUrl = (if (status.length == 1) cs.targetUrl else None),
|
||||
description = (if (status.length == 1) cs.description else None)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the search result against issues.
|
||||
*
|
||||
@@ -246,9 +215,11 @@ trait IssuesService {
|
||||
.on { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 => t1.byMilestone(t5.userName, t5.repositoryName, t5.milestoneId) }
|
||||
.joinLeft(Priorities)
|
||||
.on { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 => t1.byPriority(t6.userName, t6.repositoryName, t6.priorityId) }
|
||||
.sortBy { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 => i asc }
|
||||
.joinLeft(PullRequests)
|
||||
.on { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 ~ t7 => t1.byIssue(t7.userName, t7.repositoryName, t7.issueId) }
|
||||
.sortBy { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 ~ t7 => i asc }
|
||||
.map {
|
||||
case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 =>
|
||||
case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 ~ t7 =>
|
||||
(
|
||||
t1,
|
||||
t2.commentCount,
|
||||
@@ -256,7 +227,8 @@ trait IssuesService {
|
||||
t4.map(_.labelName),
|
||||
t4.map(_.color),
|
||||
t5.map(_.title),
|
||||
t6.map(_.priorityName)
|
||||
t6.map(_.priorityName),
|
||||
t7.map(_.commitIdTo)
|
||||
)
|
||||
}
|
||||
.list
|
||||
@@ -266,7 +238,7 @@ trait IssuesService {
|
||||
|
||||
result.map { issues =>
|
||||
issues.head match {
|
||||
case (issue, commentCount, _, _, _, milestone, priority) =>
|
||||
case (issue, commentCount, _, _, _, milestone, priority, commitId) =>
|
||||
IssueInfo(
|
||||
issue,
|
||||
issues.flatMap { t =>
|
||||
@@ -275,7 +247,7 @@ trait IssuesService {
|
||||
milestone,
|
||||
priority,
|
||||
commentCount,
|
||||
getCommitStatues(issue.userName, issue.repositoryName, issue.issueId)
|
||||
commitId
|
||||
)
|
||||
}
|
||||
} toList
|
||||
@@ -974,24 +946,14 @@ object IssuesService {
|
||||
}
|
||||
}
|
||||
|
||||
case class CommitStatusInfo(
|
||||
count: Int,
|
||||
successCount: Int,
|
||||
context: Option[String],
|
||||
state: Option[CommitState],
|
||||
targetUrl: Option[String],
|
||||
description: Option[String]
|
||||
)
|
||||
|
||||
case class IssueInfo(
|
||||
issue: Issue,
|
||||
labels: List[Label],
|
||||
milestone: Option[String],
|
||||
priority: Option[String],
|
||||
commentCount: Int,
|
||||
status: Option[CommitStatusInfo]
|
||||
commitId: Option[String]
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
sealed trait IssueSearchOption
|
||||
|
||||
@@ -154,7 +154,7 @@ object ProtectedBranchService {
|
||||
if (contexts.isEmpty) {
|
||||
Set.empty
|
||||
} else {
|
||||
contexts.toSet -- getCommitStatues(owner, repository, sha1)
|
||||
contexts.toSet -- getCommitStatuses(owner, repository, sha1)
|
||||
.filter(_.state == CommitState.SUCCESS)
|
||||
.map(_.context)
|
||||
.toSet
|
||||
|
||||
@@ -611,7 +611,7 @@ object PullRequestService {
|
||||
|
||||
case class MergeStatus(
|
||||
conflictMessage: Option[String],
|
||||
commitStatues: List[CommitStatus],
|
||||
commitStatuses: List[CommitStatus],
|
||||
branchProtection: ProtectedBranchService.ProtectedBranchInfo,
|
||||
branchIsOutOfDate: Boolean,
|
||||
hasUpdatePermission: Boolean,
|
||||
@@ -622,7 +622,7 @@ object PullRequestService {
|
||||
|
||||
val hasConflict = conflictMessage.isDefined
|
||||
val statuses: List[CommitStatus] =
|
||||
commitStatues ++ (branchProtection.contexts.toSet -- commitStatues.map(_.context).toSet)
|
||||
commitStatuses ++ (branchProtection.contexts.toSet -- commitStatuses.map(_.context).toSet)
|
||||
.map(CommitStatus.pending(branchProtection.owner, branchProtection.repository, _))
|
||||
val hasRequiredStatusProblem = needStatusCheck && branchProtection.contexts.exists(
|
||||
context => statuses.find(_.context == context).map(_.state) != Some(CommitState.SUCCESS)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@(issues: List[gitbucket.core.service.IssuesService.IssueInfo],
|
||||
@(issues: List[(gitbucket.core.service.IssuesService.IssueInfo, Option[(gitbucket.core.model.CommitState, List[gitbucket.core.model.CommitStatus])])],
|
||||
page: Int,
|
||||
openCount: Int,
|
||||
closedCount: Int,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@(issues: List[gitbucket.core.service.IssuesService.IssueInfo],
|
||||
@(issues: List[(gitbucket.core.service.IssuesService.IssueInfo, Option[(gitbucket.core.model.CommitState, List[gitbucket.core.model.CommitStatus])])],
|
||||
page: Int,
|
||||
openCount: Int,
|
||||
closedCount: Int,
|
||||
@@ -17,7 +17,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@issues.map { case IssueInfo(issue, labels, milestone, priority, commentCount, commitStatus) => {
|
||||
@issues.map { case (IssueInfo(issue, labels, milestone, priority, commentCount, commitId), status) =>
|
||||
<tr>
|
||||
<td style="padding-top: 12px; padding-bottom: 12px;">
|
||||
<a href="@context.path/@issue.userName/@issue.repositoryName">@issue.userName/@issue.repositoryName</a> ・
|
||||
@@ -26,7 +26,9 @@
|
||||
} else {
|
||||
<a id="issue_@(issue.issueId)_link" href="@context.path/@issue.userName/@issue.repositoryName/issues/@issue.issueId" class="issue-title">@issue.title</a>
|
||||
}
|
||||
@gitbucket.core.issues.html.commitstatus(issue, commitStatus)
|
||||
@status.map { case (summary, statuses) =>
|
||||
@gitbucket.core.helper.html.commitstatus(commitId.get, summary, statuses)
|
||||
}
|
||||
@labels.map { label =>
|
||||
<span class="label-color small" style="background-color: #@label.color; color: #@label.fontColor; padding-left: 4px; padding-right: 4px">@label.labelName</span>
|
||||
}
|
||||
@@ -52,7 +54,7 @@
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}}
|
||||
}
|
||||
@if(issues.isEmpty){
|
||||
<tr>
|
||||
<td style="padding: 20px; background-color: #eee; text-align: center;">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@(issues: List[gitbucket.core.service.IssuesService.IssueInfo],
|
||||
@(issues: List[(gitbucket.core.service.IssuesService.IssueInfo, Option[(gitbucket.core.model.CommitState, List[gitbucket.core.model.CommitStatus])])],
|
||||
page: Int,
|
||||
openCount: Int,
|
||||
closedCount: Int,
|
||||
|
||||
26
src/main/twirl/gitbucket/core/helper/commitstatus.scala.html
Normal file
26
src/main/twirl/gitbucket/core/helper/commitstatus.scala.html
Normal file
@@ -0,0 +1,26 @@
|
||||
@(commitId: String, summary: gitbucket.core.model.CommitState, statuses: List[gitbucket.core.model.CommitStatus])(implicit context: gitbucket.core.controller.Context)
|
||||
@import gitbucket.core.view.helpers
|
||||
<strong class="text-@{summary.name}">@helpers.commitStateIcon(summary)</strong>
|
||||
<span class="text-@{summary.name}" id="commit-status-@commitId" style="cursor : pointer;">@{statuses.groupBy(_.state).map { case (keyState, states) => s"${states.size} ${keyState.name}" }.mkString(", ")} checks</span>
|
||||
|
||||
<div id="tooltip-commit-status-@commitId" style="display: none; width: 300px;">
|
||||
@statuses.map{ status =>
|
||||
<div class="build-status-item">
|
||||
<span class="build-status-icon text-@{status.state.name}">@helpers.commitStateIcon(status.state)</span>
|
||||
<strong>@status.context</strong>
|
||||
@status.description.map { desc => <span class="muted">- @desc</span> }
|
||||
<span>@status.targetUrl.map { url => - <a href="@url">Details</a> }</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
Tipped.create('#commit-status-@commitId', {
|
||||
skin: 'light',
|
||||
inline: 'tooltip-commit-status-@commitId',
|
||||
size: 'large',
|
||||
position: 'bottomleft'
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -1,19 +0,0 @@
|
||||
@(issue: gitbucket.core.model.Issue, statusInfo: Option[gitbucket.core.service.IssuesService.CommitStatusInfo])(implicit context: gitbucket.core.controller.Context)
|
||||
@import gitbucket.core.view.helpers
|
||||
@statusInfo.map{ status =>
|
||||
@if(status.count==1 && status.state.isDefined){
|
||||
@if(status.targetUrl.isDefined){
|
||||
<a href="@status.targetUrl.get" class="text-@status.state.get.name" data-toggle="tooltip" title="@status.state.get.name : @status.description.getOrElse(status.context.get)">@helpers.commitStateIcon(status.state.get)</a>
|
||||
}else{
|
||||
<span class="text-@status.state.get.name">@helpers.commitStateIcon(status.state.get)
|
||||
}
|
||||
}else{
|
||||
@defining(status.count==status.successCount){ isSuccess =>
|
||||
<a href="@context.path/@issue.userName/@issue.repositoryName/@issue.issueId" class="@if(isSuccess){ text-success }else{ text-error }" data-toggle="tooltip" title="@status.successCount / @status.count checks OK">@if(isSuccess){
|
||||
✔
|
||||
}else{
|
||||
×
|
||||
}</a>
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
@(target: String,
|
||||
issues: List[gitbucket.core.service.IssuesService.IssueInfo],
|
||||
issues: List[(gitbucket.core.service.IssuesService.IssueInfo, Option[(gitbucket.core.model.CommitState, List[gitbucket.core.model.CommitStatus])])],
|
||||
page: Int,
|
||||
collaborators: List[String],
|
||||
milestones: List[gitbucket.core.model.Milestone],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@(target: String,
|
||||
issues: List[gitbucket.core.service.IssuesService.IssueInfo],
|
||||
issues: List[(gitbucket.core.service.IssuesService.IssueInfo, Option[(gitbucket.core.model.CommitState, List[gitbucket.core.model.CommitStatus])])],
|
||||
page: Int,
|
||||
openCount: Int,
|
||||
closedCount: Int,
|
||||
@@ -206,7 +206,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@issues.map { case IssueInfo(issue, labels, milestone, priority, commentCount, commitStatus) => {
|
||||
@issues.map { case (IssueInfo(issue, labels, milestone, priority, commentCount, commitId), status) =>
|
||||
<tr>
|
||||
<td style="padding-top: 12px; padding-bottom: 12px;">
|
||||
@if(isManageable){
|
||||
@@ -223,7 +223,9 @@
|
||||
} else {
|
||||
<a id="issue_@(issue.issueId)_link" href="@context.path/@issue.userName/@issue.repositoryName/pull/@issue.issueId" class="issue-title">@issue.title</a>
|
||||
}
|
||||
@gitbucket.core.issues.html.commitstatus(issue, commitStatus)
|
||||
@status.map { case (summary, statuses) =>
|
||||
@gitbucket.core.helper.html.commitstatus(commitId.get, summary, statuses)
|
||||
}
|
||||
@labels.map { label =>
|
||||
<span class="label-color small" style="background-color: #@label.color; color: #@label.fontColor; padding-left: 4px; padding-right: 4px">@label.labelName</span>
|
||||
}
|
||||
@@ -253,7 +255,7 @@
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="pull-right">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@(issues: List[gitbucket.core.service.IssuesService.IssueInfo],
|
||||
@(issues: List[(gitbucket.core.service.IssuesService.IssueInfo, Option[(gitbucket.core.model.CommitState, List[gitbucket.core.model.CommitStatus])])],
|
||||
page: Int,
|
||||
openCount: Int,
|
||||
closedCount: Int,
|
||||
@@ -62,7 +62,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@issues.map { case IssueInfo(issue, labels, milestone, priority, commentCount, commitStatus) => {
|
||||
@issues.map { case (IssueInfo(issue, labels, milestone, priority, commentCount, commitId), status) =>
|
||||
<tr>
|
||||
<td style="padding-top: 12px; padding-bottom: 12px;">
|
||||
@if(isManageable){
|
||||
@@ -83,7 +83,9 @@
|
||||
@if(issue.closed){<i class="menu-icon octicon octicon-issue-closed"></i>}else{<i class="menu-icon octicon octicon-issue-opened"></i>}@issue.title@issue.title
|
||||
</a>
|
||||
}
|
||||
@gitbucket.core.issues.html.commitstatus(issue, commitStatus)
|
||||
@status.map { case (summary, statuses) =>
|
||||
@gitbucket.core.helper.html.commitstatus(commitId.get, summary, statuses)
|
||||
}
|
||||
@labels.map { label =>
|
||||
<span class="label-color small" style="background-color: #@label.color; color: #@label.fontColor; padding-left: 4px; padding-right: 4px">@label.labelName</span>
|
||||
}
|
||||
@@ -113,7 +115,7 @@
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="pull-right">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@(state: String,
|
||||
issues: List[gitbucket.core.service.IssuesService.IssueInfo],
|
||||
issues: List[(gitbucket.core.service.IssuesService.IssueInfo, Option[(gitbucket.core.model.CommitState, List[gitbucket.core.model.CommitStatus])])],
|
||||
page: Int,
|
||||
collaborators: List[String],
|
||||
priorities: List[gitbucket.core.model.Priority],
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<link href="@helpers.assets("/vendors/jquery-ui/jquery-ui.structure.min.css")" rel="stylesheet">
|
||||
<link href="@helpers.assets("/vendors/jquery-ui/jquery-ui.theme.min.css")" rel="stylesheet">
|
||||
<link href="@helpers.assets("/common/css/gitbucket.css")" rel="stylesheet">
|
||||
<link href="@helpers.assets("/vendors/tipped/tipped.css")" rel="stylesheet">
|
||||
<script src="@helpers.assets("/vendors/jquery/jquery-3.5.1.min.js")"></script>
|
||||
<script src="@helpers.assets("/vendors/jquery-ui/jquery-ui.min.js")"></script>
|
||||
<script src="@helpers.assets("/vendors/dropzone/dropzone.min.js")"></script>
|
||||
@@ -51,6 +52,7 @@
|
||||
<script src="@helpers.assets("/vendors/facebox/facebox.js")"></script>
|
||||
<script src="@helpers.assets("/vendors/jquery-hotkeys/jquery.hotkeys.js")"></script>
|
||||
<script src="@helpers.assets("/vendors/jquery-textcomplete-1.8.4/jquery.textcomplete.min.js")"></script>
|
||||
<script src="@helpers.assets("/vendors/tipped/tipped.min.js")"></script>
|
||||
@repository.map { repository =>
|
||||
<meta name="go-import" content="@context.baseUrl.replaceFirst("^https?://", "")/@repository.owner/@repository.name git @repository.httpUrl" />
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
@(branchInfo: Seq[(gitbucket.core.util.JGitUtil.BranchInfo, Option[(gitbucket.core.model.PullRequest, gitbucket.core.model.Issue)], Boolean)],
|
||||
@(branchInfo: Seq[(
|
||||
gitbucket.core.util.JGitUtil.BranchInfo,
|
||||
Option[(gitbucket.core.model.PullRequest, gitbucket.core.model.Issue)],
|
||||
Boolean,
|
||||
Option[(gitbucket.core.model.CommitState, List[gitbucket.core.model.CommitStatus])]
|
||||
)],
|
||||
hasWritePermission: Boolean,
|
||||
repository: gitbucket.core.service.RepositoryService.RepositoryInfo)(implicit context: gitbucket.core.controller.Context)
|
||||
@import gitbucket.core.view.helpers
|
||||
@@ -11,7 +16,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@branchInfo.map { case (branch, prs, isProtected) =>
|
||||
@branchInfo.map { case (branch, prs, isProtected, status) =>
|
||||
<tr>
|
||||
<td class="branch-details">
|
||||
@if(isProtected){ <span class="octicon octicon-shield" title="This branch is protected"></span> }
|
||||
@@ -21,6 +26,9 @@
|
||||
by <span>@helpers.user(branch.committerName, branch.committerEmailAddress, "muted-link")</span>
|
||||
</span>
|
||||
</span>
|
||||
@status.map { case (summary, statuses) =>
|
||||
@gitbucket.core.helper.html.commitstatus(branch.commitId, summary, statuses)
|
||||
}
|
||||
</td>
|
||||
<td class="branch-a-b-count">
|
||||
@if(repository.repository.defaultBranch == branch.name){
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
commit: gitbucket.core.util.JGitUtil.CommitInfo,
|
||||
branches: List[String],
|
||||
tags: List[String],
|
||||
status: Option[(gitbucket.core.model.CommitState, List[gitbucket.core.model.CommitStatus])],
|
||||
comments: List[gitbucket.core.model.Comment],
|
||||
repository: gitbucket.core.service.RepositoryService.RepositoryInfo,
|
||||
diffs: Seq[gitbucket.core.util.JGitUtil.DiffInfo],
|
||||
@@ -49,22 +50,22 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="pull-right monospace small" style="text-align: right;">
|
||||
<div class="pull-right">
|
||||
<div>
|
||||
@if(commit.parents.size == 0){
|
||||
<span class="muted">0 parent</span>
|
||||
}
|
||||
@if(commit.parents.size == 1){
|
||||
<span class="muted">1 parent</span>
|
||||
<a href="@helpers.url(repository)/commit/@commit.parents(0)" class="commit-id">@commit.parents(0).substring(0, 7)</a>
|
||||
<a href="@helpers.url(repository)/commit/@commit.parents(0)" class="commit-id monospace strong">@commit.parents(0).substring(0, 7)</a>
|
||||
}
|
||||
<span class="muted">commit</span> @commit.id
|
||||
<span class="muted ">commit</span> <span class="commit-id monospace strong">@commit.id</span>
|
||||
</div>
|
||||
@if(commit.parents.size > 1){
|
||||
<div>
|
||||
<span class="muted">@commit.parents.size parents
|
||||
@commit.parents.map { parent =>
|
||||
<a href="@helpers.url(repository)/commit/@parent" class="commit-id">@parent.substring(0, 7)</a>
|
||||
<a href="@helpers.url(repository)/commit/@parent" class="commit-id monospace strong">@parent.substring(0, 7)</a>
|
||||
}.mkHtml(" + ")
|
||||
</span>
|
||||
</div>
|
||||
@@ -76,13 +77,16 @@
|
||||
@helpers.avatarLink(commit, 20)
|
||||
<span>@helpers.user(commit.authorName, commit.authorEmailAddress, "username strong")</span>
|
||||
<span class="muted">authored @gitbucket.core.helper.html.datetimeago(commit.authorTime)</span>
|
||||
@status.map { case (summary, statuses) =>
|
||||
@gitbucket.core.helper.html.commitstatus(commit.id, summary, statuses)
|
||||
}
|
||||
</div>
|
||||
@if(commit.isDifferentFromAuthor) {
|
||||
<div class="committer">
|
||||
<span class="octicon octicon-arrow-right"></span>
|
||||
<span>@helpers.user(commit.committerName, commit.committerEmailAddress, "username strong")</span>
|
||||
<span class="muted"> committed @gitbucket.core.helper.html.datetimeago(commit.commitTime)</span>
|
||||
</div>
|
||||
<div class="committer">
|
||||
<span class="octicon octicon-arrow-right"></span>
|
||||
<span>@helpers.user(commit.committerName, commit.committerEmailAddress, "username strong")</span>
|
||||
<span class="muted"> committed @gitbucket.core.helper.html.datetimeago(commit.commitTime)</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
@(pathList: List[String],
|
||||
branch: String,
|
||||
repository: gitbucket.core.service.RepositoryService.RepositoryInfo,
|
||||
commits: Seq[Seq[gitbucket.core.util.JGitUtil.CommitInfo]],
|
||||
commits: Seq[Seq[(gitbucket.core.util.JGitUtil.CommitInfo, List[String], Option[(gitbucket.core.model.CommitState, List[gitbucket.core.model.CommitStatus])])]],
|
||||
page: Int,
|
||||
hasNext: Boolean,
|
||||
hasWritePermission: Boolean,
|
||||
getStatuses: String => List[gitbucket.core.model.CommitStatus],
|
||||
getSummary: List[gitbucket.core.model.CommitStatus] => (gitbucket.core.model.CommitState, String),
|
||||
getTags: String => List[String])(implicit context: gitbucket.core.controller.Context)
|
||||
hasWritePermission: Boolean)(implicit context: gitbucket.core.controller.Context)
|
||||
@import gitbucket.core.view.helpers
|
||||
@gitbucket.core.html.main(s"${repository.owner}/${repository.name}", Some(repository)) {
|
||||
@gitbucket.core.html.menu("files", repository){
|
||||
@@ -35,8 +32,8 @@
|
||||
<table class="table table-bordered table-hover">
|
||||
@commits.map { day =>
|
||||
<tr>
|
||||
<th rowspan="@day.size" width="100">@helpers.date(day.head.commitTime)</th>
|
||||
@day.zipWithIndex.map { case (commit, i) =>
|
||||
<th rowspan="@day.size" width="100">@helpers.date(day.head._1.commitTime)</th>
|
||||
@day.zipWithIndex.map { case ((commit, tags, status), i) =>
|
||||
@if(i != 0){ <tr> }
|
||||
<td>
|
||||
<div class="pull-right text-right">
|
||||
@@ -47,15 +44,13 @@
|
||||
<span class="gpg-unverified">Unverified</span>
|
||||
}
|
||||
}
|
||||
@defining(getTags(commit.id)) { tags =>
|
||||
@if(tags.nonEmpty){
|
||||
<span class="muted">
|
||||
<i class="octicon octicon-tag"></i>
|
||||
@tags.map { tag =>
|
||||
<a href="@helpers.url(repository)/tree/@tag" class="tag">@tag</a>
|
||||
}
|
||||
</span>
|
||||
}
|
||||
@if(tags.nonEmpty){
|
||||
<span class="muted">
|
||||
<i class="octicon octicon-tag"></i>
|
||||
@tags.map { tag =>
|
||||
<a href="@helpers.url(repository)/tree/@tag" class="tag">@tag</a>
|
||||
}
|
||||
</span>
|
||||
}
|
||||
<a href="@helpers.url(repository)/commit/@commit.id" class="monospace commit-message strong"><i class="octicon octicon-diff" style="color: black;"></i>@commit.id.substring(0, 7)</a><br>
|
||||
<a href="@helpers.url(repository)/tree/@commit.id" class="button-link">Browse files »</a>
|
||||
@@ -79,30 +74,9 @@
|
||||
}
|
||||
@helpers.user(commit.committerName, commit.committerEmailAddress, "username")
|
||||
<span class="muted">committed @gitbucket.core.helper.html.datetimeago(commit.commitTime)</span>
|
||||
@defining({
|
||||
val statuses = getStatuses(commit.id)
|
||||
val (summary, summaryText) = getSummary(statuses)
|
||||
(statuses, summary, summaryText)
|
||||
}){ case (statuses, summaryState, summaryText) =>
|
||||
@if(statuses.nonEmpty){
|
||||
@helpers.commitStateIcon(summaryState)
|
||||
<strong class="text-@{summaryState.name}">@helpers.commitStateText(summaryState, commit.id)</strong>
|
||||
<span class="text-@{summaryState.name}">- @summaryText checks</span>
|
||||
<a href="#" class="toggle-check">Show all checks</a>
|
||||
<div style="display: none;">
|
||||
@statuses.map{ status =>
|
||||
<div class="build-status-item">
|
||||
<span class="build-status-icon text-@{status.state.name}">@helpers.commitStateIcon(status.state)</span>
|
||||
<strong>@status.context</strong>
|
||||
@status.description.map { desc => <span class="muted">- @desc</span> }
|
||||
<span>
|
||||
@status.targetUrl.map { url => - <a href="@url">Details</a> }
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@status.map { case (summary, statuses) =>
|
||||
@gitbucket.core.helper.html.commitstatus(commit.id, summary, statuses)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -127,20 +101,9 @@
|
||||
</ul>
|
||||
</nav>
|
||||
<script>
|
||||
$(function () {
|
||||
$(function() {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
$('.toggle-check').click(function(){
|
||||
var div = $(this).next('div');
|
||||
if(div.is(':visible')){
|
||||
$(this).text('Show all checks');
|
||||
} else {
|
||||
$(this).text('Hide all checks');
|
||||
}
|
||||
div.toggle();
|
||||
return false;
|
||||
});
|
||||
})
|
||||
});
|
||||
</script>
|
||||
<style type="text/css">
|
||||
a.tag {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
repository: gitbucket.core.service.RepositoryService.RepositoryInfo,
|
||||
pathList: List[String],
|
||||
latestCommit: gitbucket.core.util.JGitUtil.CommitInfo,
|
||||
commitStatus: Option[(gitbucket.core.model.CommitState, List[gitbucket.core.model.CommitStatus])],
|
||||
commitCount: Int,
|
||||
files: List[gitbucket.core.util.JGitUtil.FileInfo],
|
||||
readme: Option[(List[String], String)],
|
||||
@@ -109,16 +110,24 @@
|
||||
</tr>
|
||||
*@
|
||||
<tr>
|
||||
<th colspan="4" class="latest-commit">
|
||||
<th colspan="4" class="latest-commit" style="font-weight: normal;">
|
||||
<div>
|
||||
<div class="pull-right align-right" style="line-height: 18px;">
|
||||
<a href="@helpers.url(repository)/commit/@latestCommit.id" class="commit-id"><span class="muted">latest commit</span> <span class="monospace">@latestCommit.id.substring(0, 10)</span></a>
|
||||
<a href="@helpers.url(repository)/commit/@latestCommit.id" class="commit-id">
|
||||
<span class="muted">latest commit</span>
|
||||
<span class="monospace commit-message strong">@latestCommit.id.substring(0, 10)</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="author-info">
|
||||
<div class="author">
|
||||
@helpers.avatarLink(latestCommit, 20)
|
||||
<span>@helpers.user(latestCommit.authorName, latestCommit.authorEmailAddress, "username strong")</span>
|
||||
<span class="muted"> authored @gitbucket.core.helper.html.datetimeago(latestCommit.authorTime)</span>
|
||||
<span>
|
||||
@commitStatus.map { case (summary, statuses) =>
|
||||
@gitbucket.core.helper.html.commitstatus(latestCommit.id, summary, statuses)
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
@if(latestCommit.isDifferentFromAuthor) {
|
||||
<div class="committer">
|
||||
|
||||
935
src/main/webapp/assets/vendors/tipped/tipped.css
vendored
Normal file
935
src/main/webapp/assets/vendors/tipped/tipped.css
vendored
Normal file
@@ -0,0 +1,935 @@
|
||||
.tpd-tooltip {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* Fix for CSS frameworks that don't keep the use of box-sizing: border-box
|
||||
within their own namespace */
|
||||
.tpd-tooltip {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
.tpd-tooltip [class^="tpd-"] {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
.tpd-content-wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
float: left;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.tpd-content-spacer,
|
||||
.tpd-content-relative,
|
||||
.tpd-content-relative-padder {
|
||||
float: left;
|
||||
position: relative;
|
||||
}
|
||||
.tpd-content-relative {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tpd-content {
|
||||
float: left;
|
||||
clear: both;
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
color: #fff;
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
.tpd-has-inner-close .tpd-content-relative .tpd-content {
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
.tpd-tooltip .tpd-content-no-padding {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.tpd-title-wrapper {
|
||||
float: left;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.tpd-title-spacer {
|
||||
float: left;
|
||||
}
|
||||
.tpd-title-relative,
|
||||
.tpd-title-relative-padder {
|
||||
float: left;
|
||||
position: relative;
|
||||
}
|
||||
.tpd-title-relative {
|
||||
width: 100%;
|
||||
}
|
||||
.tpd-title {
|
||||
float: left;
|
||||
position: relative;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
padding: 10px;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
color: #fff;
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
.tpd-has-title-close .tpd-title {
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
.tpd-close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
color: #fff;
|
||||
}
|
||||
.tpd-close-icon {
|
||||
float: left;
|
||||
font-family: Arial, Baskerville, monospace;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
text-decoration: none;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
font-size: 28px;
|
||||
line-height: 28px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Skin */
|
||||
.tpd-skin {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.tpd-frames {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.tpd-frames .tpd-frame {
|
||||
float: left;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
clear: both;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tpd-visible-frame-top .tpd-frame-top {
|
||||
display: block;
|
||||
}
|
||||
.tpd-visible-frame-bottom .tpd-frame-bottom {
|
||||
display: block;
|
||||
}
|
||||
.tpd-visible-frame-left .tpd-frame-left {
|
||||
display: block;
|
||||
}
|
||||
.tpd-visible-frame-right .tpd-frame-right {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tpd-backgrounds {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
-webkit-transform-origin: 0% 0%;
|
||||
transform-origin: 0% 0%;
|
||||
}
|
||||
.tpd-background-shadow {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
.tpd-no-shadow .tpd-skin .tpd-background-shadow {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.tpd-background-box {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
/* only the top background box should be shown when not using a stem */
|
||||
.tpd-no-stem .tpd-background-box,
|
||||
.tpd-no-stem .tpd-shift-stem {
|
||||
display: none;
|
||||
}
|
||||
.tpd-no-stem .tpd-background-box-top {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tpd-background-box-shift,
|
||||
.tpd-background-box-shift-further {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.tpd-background {
|
||||
border-radius: 10px;
|
||||
float: left;
|
||||
clear: both;
|
||||
background: none;
|
||||
-webkit-background-clip: padding-box; /* Safari */
|
||||
background-clip: padding-box; /* IE9+, Firefox 4+, Opera, Chrome */
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: rgba(
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
0.1
|
||||
); /* opacity here bugs out in firefox, .tpd-background-content should have no opacity if this opacity is less than 1 */
|
||||
}
|
||||
.tpd-background-loading {
|
||||
display: none;
|
||||
}
|
||||
/* no radius */
|
||||
.tpd-no-radius
|
||||
.tpd-skin
|
||||
.tpd-frames
|
||||
.tpd-frame
|
||||
.tpd-backgrounds
|
||||
.tpd-background {
|
||||
border-radius: 0;
|
||||
}
|
||||
.tpd-background-title {
|
||||
float: left;
|
||||
clear: both;
|
||||
width: 100%;
|
||||
background-color: #282828;
|
||||
}
|
||||
.tpd-background-content {
|
||||
float: left;
|
||||
clear: both;
|
||||
width: 100%;
|
||||
background-color: #282828;
|
||||
}
|
||||
.tpd-background-border-hack {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.tpd-background-box-top {
|
||||
top: 0;
|
||||
}
|
||||
.tpd-background-box-bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
.tpd-background-box-left {
|
||||
left: 0;
|
||||
}
|
||||
.tpd-background-box-right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
/* Skin / Stems */
|
||||
.tpd-shift-stem {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.tpd-shift-stem-side {
|
||||
position: absolute;
|
||||
}
|
||||
.tpd-frame-top .tpd-shift-stem-side,
|
||||
.tpd-frame-bottom .tpd-shift-stem-side {
|
||||
width: 100%;
|
||||
}
|
||||
.tpd-frame-left .tpd-shift-stem-side,
|
||||
.tpd-frame-right .tpd-shift-stem-side {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tpd-stem {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
overflow: hidden; /* shows possible invalid subpx rendering */
|
||||
width: 16px; /* best cross browser stem: width = 2 x height (90deg angle) */
|
||||
height: 8px;
|
||||
margin-left: 3px; /* space from the side */
|
||||
margin-top: 2px; /* space between target and stem */
|
||||
-webkit-transform-origin: 0% 0%;
|
||||
transform-origin: 0% 0%;
|
||||
}
|
||||
/* remove margins once we're done measuring */
|
||||
.tpd-tooltip .tpd-skin .tpd-frames .tpd-frame .tpd-shift-stem .tpd-stem-reset {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.tpd-stem-spacer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.tpd-stem-reset .tpd-stem-spacer {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.tpd-stem-point {
|
||||
width: 100px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
}
|
||||
.tpd-stem-downscale,
|
||||
.tpd-stem-transform {
|
||||
float: left;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
-webkit-transform-origin: 0% 0%;
|
||||
transform-origin: 0% 0%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tpd-stem-side {
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
float: left;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.tpd-stem-side-inversed {
|
||||
-webkit-transform: scale(-1, 1);
|
||||
transform: scale(-1, 1);
|
||||
}
|
||||
.tpd-stem-triangle {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-bottom-style: solid;
|
||||
border-left-color: transparent;
|
||||
border-left-style: solid;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.tpd-stem-border {
|
||||
width: 20px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
background-color: #fff; /* will become transparent */
|
||||
border-right-color: #fff;
|
||||
border-right-style: solid;
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
.tpd-stem-border-corner {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
height: 100%;
|
||||
border-right-style: solid;
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
/* fixes rendering issue in IE */
|
||||
.tpd-stem * {
|
||||
z-index: 0;
|
||||
zoom: 1;
|
||||
}
|
||||
|
||||
/* used by IE < 9 */
|
||||
.tpd-stem-border-center-offset,
|
||||
.tpd-stem-border-center-offset-inverse {
|
||||
float: left;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.tpd-stem-notransform {
|
||||
float: left;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.tpd-stem-notransform .tpd-stem-border {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
float: left;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.tpd-stem-notransform .tpd-stem-border-center {
|
||||
position: absolute;
|
||||
}
|
||||
.tpd-stem-notransform .tpd-stem-border-corner {
|
||||
background: #fff;
|
||||
border: 0;
|
||||
top: auto;
|
||||
left: auto;
|
||||
}
|
||||
.tpd-stem-notransform .tpd-stem-border-center,
|
||||
.tpd-stem-notransform .tpd-stem-triangle {
|
||||
height: 0;
|
||||
border: 0;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
/* transformations for left/right/bottom */
|
||||
.tpd-stem-transform-left {
|
||||
-webkit-transform: rotate(-90deg) scale(-1, 1);
|
||||
transform: rotate(-90deg) scale(-1, 1);
|
||||
}
|
||||
.tpd-stem-transform-right {
|
||||
-webkit-transform: rotate(90deg) translate(0, -100%);
|
||||
transform: rotate(90deg) translate(0, -100%);
|
||||
}
|
||||
.tpd-stem-transform-bottom {
|
||||
-webkit-transform: scale(1, -1) translate(0, -100%);
|
||||
transform: scale(1, -1) translate(0, -100%);
|
||||
}
|
||||
|
||||
/* Spinner */
|
||||
.tpd-spinner {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 46px;
|
||||
height: 36px;
|
||||
}
|
||||
.tpd-spinner-spin {
|
||||
position: relative;
|
||||
float: left;
|
||||
margin: 8px 0 0 13px;
|
||||
text-indent: -9999em;
|
||||
border-top: 2px solid rgba(255, 255, 255, 0.2);
|
||||
border-right: 2px solid rgba(255, 255, 255, 0.2);
|
||||
border-bottom: 2px solid rgba(255, 255, 255, 0.2);
|
||||
border-left: 2px solid #fff;
|
||||
-webkit-animation: tpd-spinner-animation 1.1s infinite linear;
|
||||
animation: tpd-spinner-animation 1.1s infinite linear;
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
.tpd-spinner-spin,
|
||||
.tpd-spinner-spin:after {
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
@-webkit-keyframes tpd-spinner-animation {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes tpd-spinner-animation {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* show the loader while loading and hide all the content */
|
||||
.tpd-is-loading .tpd-content-wrapper,
|
||||
.tpd-is-loading .tpd-title-wrapper {
|
||||
display: none;
|
||||
}
|
||||
.tpd-is-loading .tpd-background {
|
||||
display: none;
|
||||
}
|
||||
.tpd-is-loading .tpd-background-loading {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Resets while measuring content */
|
||||
.tpd-tooltip-measuring {
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.tpd-tooltip-measuring .tpd-skin,
|
||||
.tpd-tooltip-measuring .tpd-spinner {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tpd-tooltip-measuring .tpd-content-wrapper,
|
||||
.tpd-tooltip-measuring .tpd-title-wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Links */
|
||||
.tpd-tooltip a,
|
||||
.tpd-tooltip a:hover {
|
||||
color: #808080;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.tpd-tooltip a:hover {
|
||||
color: #6c6c6c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sizes
|
||||
*/
|
||||
/* x-small */
|
||||
.tpd-size-x-small .tpd-content,
|
||||
.tpd-size-x-small .tpd-title {
|
||||
padding: 7px 8px;
|
||||
font-size: 10px;
|
||||
line-height: 15px;
|
||||
}
|
||||
.tpd-size-x-small .tpd-background {
|
||||
border-radius: 5px;
|
||||
}
|
||||
.tpd-size-x-small .tpd-stem {
|
||||
width: 12px;
|
||||
height: 6px;
|
||||
margin-left: 4px;
|
||||
margin-top: 2px; /* space between target and stem */
|
||||
}
|
||||
.tpd-size-x-small.tpd-no-radius .tpd-stem {
|
||||
margin-left: 7px;
|
||||
}
|
||||
.tpd-size-x-small .tpd-close {
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
.tpd-size-x-small .tpd-spinner {
|
||||
width: 35px;
|
||||
height: 29px;
|
||||
}
|
||||
.tpd-size-x-small .tpd-spinner-spin {
|
||||
margin: 6px 0 0 9px;
|
||||
}
|
||||
.tpd-size-x-small .tpd-spinner-spin,
|
||||
.tpd-size-x-small .tpd-spinner-spin:after {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
}
|
||||
|
||||
/* small */
|
||||
.tpd-size-small .tpd-content,
|
||||
.tpd-size-small .tpd-title {
|
||||
padding: 8px;
|
||||
font-size: 10px;
|
||||
line-height: 16px;
|
||||
}
|
||||
.tpd-size-small .tpd-background {
|
||||
border-radius: 6px;
|
||||
}
|
||||
.tpd-size-small .tpd-stem {
|
||||
width: 14px;
|
||||
height: 7px;
|
||||
margin-left: 5px;
|
||||
margin-top: 2px; /* space between target and stem */
|
||||
}
|
||||
.tpd-size-small.tpd-no-radius .tpd-stem {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.tpd-size-small .tpd-close {
|
||||
margin: 2px 1px;
|
||||
}
|
||||
.tpd-size-small .tpd-spinner {
|
||||
width: 42px;
|
||||
height: 32px;
|
||||
}
|
||||
.tpd-size-small .tpd-spinner-spin {
|
||||
margin: 7px 0 0 13px;
|
||||
}
|
||||
.tpd-size-small .tpd-spinner-spin,
|
||||
.tpd-size-small .tpd-spinner-spin:after {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
/* medium (default) */
|
||||
.tpd-size-medium .tpd-content,
|
||||
.tpd-size-medium .tpd-title {
|
||||
padding: 10px;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
}
|
||||
.tpd-size-medium .tpd-background {
|
||||
border-radius: 8px;
|
||||
}
|
||||
.tpd-size-medium .tpd-stem {
|
||||
width: 16px; /* best cross browser stem width is 2xheight, for a 90deg angle */
|
||||
height: 8px;
|
||||
margin-left: 6px; /* space from the side */
|
||||
margin-top: 2px; /* space between target and stem */
|
||||
}
|
||||
.tpd-size-medium.tpd-no-radius .tpd-stem {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.tpd-size-medium .tpd-close {
|
||||
margin: 4px 2px;
|
||||
}
|
||||
/* ideal spinner dimensions don't cause movement op top and
|
||||
on the stem when switching to text using position:'topleft' */
|
||||
.tpd-size-medium .tpd-spinner {
|
||||
width: 50px;
|
||||
height: 36px;
|
||||
}
|
||||
.tpd-size-medium .tpd-spinner-spin {
|
||||
margin: 8px 0 0 15px;
|
||||
}
|
||||
.tpd-size-medium .tpd-spinner-spin,
|
||||
.tpd-size-medium .tpd-spinner-spin:after {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* large */
|
||||
.tpd-size-large .tpd-content,
|
||||
.tpd-size-large .tpd-title {
|
||||
padding: 10px;
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
}
|
||||
.tpd-size-large .tpd-background {
|
||||
border-radius: 8px;
|
||||
}
|
||||
.tpd-size-large .tpd-stem {
|
||||
width: 18px;
|
||||
height: 9px;
|
||||
margin-left: 7px;
|
||||
margin-top: 2px; /* space between target and stem */
|
||||
}
|
||||
.tpd-size-large.tpd-no-radius .tpd-stem {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.tpd-size-large .tpd-close {
|
||||
margin: 5px 2px 5px 2px;
|
||||
}
|
||||
.tpd-size-large .tpd-spinner {
|
||||
width: 54px;
|
||||
height: 38px;
|
||||
}
|
||||
.tpd-size-large .tpd-spinner-spin {
|
||||
margin: 9px 0 0 17px;
|
||||
}
|
||||
.tpd-size-large .tpd-spinner-spin,
|
||||
.tpd-size-large .tpd-spinner-spin:after {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* Skins */
|
||||
/* default (dark) */
|
||||
.tpd-skin-dark .tpd-content,
|
||||
.tpd-skin-dark .tpd-title,
|
||||
.tpd-skin-dark .tpd-close {
|
||||
color: #fff;
|
||||
}
|
||||
.tpd-skin-dark .tpd-background-content,
|
||||
.tpd-skin-dark .tpd-background-title {
|
||||
background-color: #282828;
|
||||
}
|
||||
.tpd-skin-dark .tpd-background {
|
||||
border-width: 1px;
|
||||
border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
/* line below the title */
|
||||
.tpd-skin-dark .tpd-title-wrapper {
|
||||
border-bottom: 1px solid #404040;
|
||||
}
|
||||
/* spinner */
|
||||
.tpd-skin-dark .tpd-spinner-spin {
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
border-left-color: #fff;
|
||||
}
|
||||
/* links */
|
||||
.tpd-skin-dark a {
|
||||
color: #ccc;
|
||||
}
|
||||
.tpd-skin-dark a:hover {
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
/* light */
|
||||
.tpd-skin-light .tpd-content,
|
||||
.tpd-skin-light .tpd-title,
|
||||
.tpd-skin-light .tpd-close {
|
||||
color: #333;
|
||||
}
|
||||
.tpd-skin-light .tpd-background-content {
|
||||
background-color: #fff;
|
||||
}
|
||||
.tpd-skin-light .tpd-background {
|
||||
border-width: 1px;
|
||||
border-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.tpd-skin-light .tpd-background-title {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
.tpd-skin-light .tpd-title-wrapper {
|
||||
border-bottom: 1px solid #c0c0c0;
|
||||
}
|
||||
.tpd-skin-light .tpd-background-shadow {
|
||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
/* fallback for no/disabled shadow */
|
||||
.tpd-skin-light.tpd-no-shadow .tpd-background {
|
||||
border-color: rgba(100, 100, 100, 0.3);
|
||||
}
|
||||
.tpd-skin-light .tpd-spinner-spin {
|
||||
border-color: rgba(51, 51, 51, 0.2);
|
||||
border-left-color: #333;
|
||||
}
|
||||
.tpd-skin-light a {
|
||||
color: #808080;
|
||||
}
|
||||
.tpd-skin-light a:hover {
|
||||
color: #6c6c6c;
|
||||
}
|
||||
|
||||
/* gray */
|
||||
.tpd-skin-gray .tpd-content,
|
||||
.tpd-skin-gray .tpd-title,
|
||||
.tpd-skin-gray .tpd-close {
|
||||
color: #fff;
|
||||
}
|
||||
.tpd-skin-gray .tpd-background-content,
|
||||
.tpd-skin-gray .tpd-background-title {
|
||||
background-color: #727272;
|
||||
}
|
||||
.tpd-skin-gray .tpd-background {
|
||||
border-width: 1px;
|
||||
border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.tpd-skin-gray .tpd-title-wrapper {
|
||||
border-bottom: 1px solid #505050;
|
||||
}
|
||||
.tpd-skin-gray .tpd-spinner-spin {
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
border-left-color: #fff;
|
||||
}
|
||||
.tpd-skin-gray a {
|
||||
color: #ccc;
|
||||
}
|
||||
.tpd-skin-gray a:hover {
|
||||
color: #b6b6b6;
|
||||
}
|
||||
|
||||
/* red */
|
||||
.tpd-skin-red .tpd-content,
|
||||
.tpd-skin-red .tpd-title,
|
||||
.tpd-skin-red .tpd-close {
|
||||
color: #fff;
|
||||
}
|
||||
.tpd-skin-red .tpd-background-content {
|
||||
background-color: #e13c37;
|
||||
}
|
||||
.tpd-skin-red .tpd-background {
|
||||
border-width: 1px;
|
||||
border-color: rgba(12, 0, 0, 0.6);
|
||||
}
|
||||
.tpd-skin-red .tpd-background-title {
|
||||
background-color: #e13c37;
|
||||
}
|
||||
.tpd-skin-red .tpd-title-wrapper {
|
||||
border-bottom: 1px solid #a30500;
|
||||
}
|
||||
.tpd-skin-red .tpd-background-shadow {
|
||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.tpd-skin-red .tpd-spinner-spin {
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
border-left-color: #fff;
|
||||
}
|
||||
.tpd-skin-red a {
|
||||
color: #ddd;
|
||||
}
|
||||
.tpd-skin-red a:hover {
|
||||
color: #c6c6c6;
|
||||
}
|
||||
|
||||
/* green */
|
||||
.tpd-skin-green .tpd-content,
|
||||
.tpd-skin-green .tpd-title,
|
||||
.tpd-skin-green .tpd-close {
|
||||
color: #fff;
|
||||
}
|
||||
.tpd-skin-green .tpd-background-content {
|
||||
background-color: #4aab3a;
|
||||
}
|
||||
.tpd-skin-green .tpd-background {
|
||||
border-width: 1px;
|
||||
border-color: rgba(0, 12, 0, 0.6);
|
||||
}
|
||||
.tpd-skin-green .tpd-background-title {
|
||||
background-color: #4aab3a;
|
||||
}
|
||||
.tpd-skin-green .tpd-title-wrapper {
|
||||
border-bottom: 1px solid #127c00;
|
||||
}
|
||||
.tpd-skin-green .tpd-background-shadow {
|
||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.tpd-skin-green .tpd-spinner-spin {
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
border-left-color: #fff;
|
||||
}
|
||||
.tpd-skin-green a {
|
||||
color: #ddd;
|
||||
}
|
||||
.tpd-skin-green a:hover {
|
||||
color: #c6c6c6;
|
||||
}
|
||||
|
||||
/* blue */
|
||||
.tpd-skin-blue .tpd-content,
|
||||
.tpd-skin-blue .tpd-title,
|
||||
.tpd-skin-blue .tpd-close {
|
||||
color: #fff;
|
||||
}
|
||||
.tpd-skin-blue .tpd-background-content {
|
||||
background-color: #45a3e3;
|
||||
}
|
||||
.tpd-skin-blue .tpd-background {
|
||||
border-width: 1px;
|
||||
border-color: rgba(0, 0, 12, 0.6);
|
||||
}
|
||||
.tpd-skin-blue .tpd-background-title {
|
||||
background-color: #45a3e3;
|
||||
}
|
||||
.tpd-skin-blue .tpd-title-wrapper {
|
||||
border-bottom: 1px solid #1674b4;
|
||||
}
|
||||
.tpd-skin-blue .tpd-background-shadow {
|
||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.tpd-skin-blue .tpd-spinner-spin {
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
border-left-color: #fff;
|
||||
}
|
||||
.tpd-skin-blue a {
|
||||
color: #ddd;
|
||||
}
|
||||
.tpd-skin-blue a:hover {
|
||||
color: #c6c6c6;
|
||||
}
|
||||
|
||||
/* lightyellow */
|
||||
.tpd-skin-lightyellow .tpd-content,
|
||||
.tpd-skin-lightyellow .tpd-title,
|
||||
.tpd-skin-lightyellow .tpd-close {
|
||||
color: #333;
|
||||
}
|
||||
.tpd-skin-lightyellow .tpd-background-content {
|
||||
background-color: #ffffa9;
|
||||
}
|
||||
.tpd-skin-lightyellow .tpd-background {
|
||||
border-width: 1px;
|
||||
border-color: rgba(8, 8, 0, 0.35);
|
||||
}
|
||||
.tpd-skin-lightyellow .tpd-background-title {
|
||||
background-color: #ffffa9;
|
||||
}
|
||||
.tpd-skin-lightyellow .tpd-title-wrapper {
|
||||
border-bottom: 1px solid #a7a697;
|
||||
}
|
||||
.tpd-skin-lightyellow .tpd-background-shadow {
|
||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.tpd-skin-lightyellow .tpd-spinner-spin {
|
||||
border-color: rgba(51, 51, 51, 0.2);
|
||||
border-left-color: #333;
|
||||
}
|
||||
.tpd-skin-lightyellow a {
|
||||
color: #777;
|
||||
}
|
||||
.tpd-skin-lightyellow a:hover {
|
||||
color: #868686;
|
||||
}
|
||||
|
||||
/* lightblue */
|
||||
.tpd-skin-lightblue .tpd-content,
|
||||
.tpd-skin-lightblue .tpd-title,
|
||||
.tpd-skin-lightblue .tpd-close {
|
||||
color: #333;
|
||||
}
|
||||
.tpd-skin-lightblue .tpd-background-content {
|
||||
background-color: #bce5ff;
|
||||
}
|
||||
.tpd-skin-lightblue .tpd-background {
|
||||
border-width: 1px;
|
||||
border-color: rgba(0, 0, 8, 0.35);
|
||||
}
|
||||
.tpd-skin-lightblue .tpd-background-title {
|
||||
background-color: #bce5ff;
|
||||
}
|
||||
.tpd-skin-lightblue .tpd-title-wrapper {
|
||||
border-bottom: 1px solid #909b9f;
|
||||
}
|
||||
.tpd-skin-lightblue .tpd-background-shadow {
|
||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.tpd-skin-lightblue .tpd-spinner-spin {
|
||||
border-color: rgba(51, 51, 51, 0.2);
|
||||
border-left-color: #333;
|
||||
}
|
||||
.tpd-skin-lightblue a {
|
||||
color: #777;
|
||||
}
|
||||
.tpd-skin-lightblue a:hover {
|
||||
color: #868686;
|
||||
}
|
||||
|
||||
/* lightpink */
|
||||
.tpd-skin-lightpink .tpd-content,
|
||||
.tpd-skin-lightpink .tpd-title,
|
||||
.tpd-skin-lightpink .tpd-close {
|
||||
color: #333;
|
||||
}
|
||||
.tpd-skin-lightpink .tpd-background-content {
|
||||
background-color: #ffc4bf;
|
||||
}
|
||||
.tpd-skin-lightpink .tpd-background {
|
||||
border-width: 1px;
|
||||
border-color: rgba(8, 0, 0, 0.35);
|
||||
}
|
||||
.tpd-skin-lightpink .tpd-background-title {
|
||||
background-color: #ffc4bf;
|
||||
}
|
||||
.tpd-skin-lightpink .tpd-title-wrapper {
|
||||
border-bottom: 1px solid #a08f8f;
|
||||
}
|
||||
.tpd-skin-lightpink .tpd-background-shadow {
|
||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.tpd-skin-lightpink .tpd-spinner-spin {
|
||||
border-color: rgba(51, 51, 51, 0.2);
|
||||
border-left-color: #333;
|
||||
}
|
||||
.tpd-skin-lightpink a {
|
||||
color: #777;
|
||||
}
|
||||
.tpd-skin-lightpink a:hover {
|
||||
color: #868686;
|
||||
}
|
||||
9
src/main/webapp/assets/vendors/tipped/tipped.min.js
vendored
Normal file
9
src/main/webapp/assets/vendors/tipped/tipped.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,97 +0,0 @@
|
||||
package gitbucket.core.service
|
||||
|
||||
import gitbucket.core.model._
|
||||
import gitbucket.core.service.IssuesService._
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
|
||||
class IssuesServiceSpec extends AnyFunSuite with ServiceSpecBase {
|
||||
test("getCommitStatues") {
|
||||
withTestDB { implicit session =>
|
||||
val user1 = generateNewUserWithDBRepository("user1", "repo1")
|
||||
|
||||
def getCommitStatues(issueId: Int) = dummyService.getCommitStatues("user1", "repo1", issueId)
|
||||
|
||||
assert(getCommitStatues(1) == None)
|
||||
|
||||
val now = new java.util.Date()
|
||||
val issueId = generateNewIssue("user1", "repo1")
|
||||
assert(issueId == 1)
|
||||
|
||||
assert(getCommitStatues(1) == None)
|
||||
|
||||
val cs = dummyService.createCommitStatus(
|
||||
"user1",
|
||||
"repo1",
|
||||
"shasha",
|
||||
"default",
|
||||
CommitState.SUCCESS,
|
||||
Some("http://exmple.com/ci"),
|
||||
Some("exampleService"),
|
||||
now,
|
||||
user1
|
||||
)
|
||||
|
||||
assert(getCommitStatues(1) == None)
|
||||
|
||||
val (is2, pr2) = generateNewPullRequest("user1/repo1/master", "user1/repo1/feature1", loginUser = "root")
|
||||
assert(pr2.issueId == 2)
|
||||
|
||||
// if there are no statuses, state is none
|
||||
assert(getCommitStatues(2) == None)
|
||||
|
||||
// if there is a status, state is that
|
||||
val cs2 = dummyService.createCommitStatus(
|
||||
"user1",
|
||||
"repo1",
|
||||
"feature1",
|
||||
"default",
|
||||
CommitState.SUCCESS,
|
||||
Some("http://exmple.com/ci"),
|
||||
Some("exampleService"),
|
||||
now,
|
||||
user1
|
||||
)
|
||||
assert(
|
||||
getCommitStatues(2) == Some(
|
||||
CommitStatusInfo(
|
||||
1,
|
||||
1,
|
||||
Some("default"),
|
||||
Some(CommitState.SUCCESS),
|
||||
Some("http://exmple.com/ci"),
|
||||
Some("exampleService")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// if there are two statuses, state is none
|
||||
val cs3 = dummyService.createCommitStatus(
|
||||
"user1",
|
||||
"repo1",
|
||||
"feature1",
|
||||
"pend",
|
||||
CommitState.PENDING,
|
||||
Some("http://exmple.com/ci"),
|
||||
Some("exampleService"),
|
||||
now,
|
||||
user1
|
||||
)
|
||||
assert(getCommitStatues(2) == Some(CommitStatusInfo(2, 1, None, None, None, None)))
|
||||
|
||||
// get only statuses in query issues
|
||||
val (is3, pr3) = generateNewPullRequest("user1/repo1/master", "user1/repo1/feature3", loginUser = "root")
|
||||
val cs4 = dummyService.createCommitStatus(
|
||||
"user1",
|
||||
"repo1",
|
||||
"feature3",
|
||||
"none",
|
||||
CommitState.PENDING,
|
||||
None,
|
||||
None,
|
||||
now,
|
||||
user1
|
||||
)
|
||||
assert(getCommitStatues(2) == Some(CommitStatusInfo(2, 1, None, None, None, None)))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user