diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index 1436b152bd..301b8702e6 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -991,6 +991,8 @@ file_view_raw=Посмотреть исходник file_permalink=Постоянная ссылка file_too_large=Этот файл слишком большой, поэтому он не может быть отображён. +issues_tree=Дерево задач + file_copy_permalink=Копировать постоянную ссылку video_not_supported_in_browser=Ваш браузер не поддерживает HTML5 'video' тэг. audio_not_supported_in_browser=Ваш браузер не поддерживает HTML5 'audio' тэг. diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index daaa09a43e..7ec1af728f 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -47,6 +47,7 @@ const ( tplAttachment base.TplName = "repo/issue/view_content/attachments" tplIssues base.TplName = "repo/issue/list" + tplIssuesTree base.TplName = "repo/issue/tree" tplIssueNew base.TplName = "repo/issue/new" tplIssueChoose base.TplName = "repo/issue/choose" tplIssueView base.TplName = "repo/issue/view" @@ -114,7 +115,7 @@ func MustAllowPulls(ctx *context.Context) { } } -func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption util.OptionalBool) { +func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption util.OptionalBool, page_size int) { var err error viewType := ctx.FormString("type") sortType := ctx.FormString("sort") @@ -210,7 +211,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti } else { total = int(issueStats.ClosedCount) } - pager := context.NewPagination(total, setting.UI.IssuePagingNum, page, 5) + pager := context.NewPagination(total, page_size, page, 5) var mileIDs []int64 if milestoneID > 0 { @@ -224,7 +225,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti issues, err = models.Issues(&models.IssuesOptions{ ListOptions: db.ListOptions{ Page: pager.Paginater.Current(), - PageSize: setting.UI.IssuePagingNum, + PageSize: page_size, }, RepoID: repo.ID, AssigneeID: assigneeID, @@ -391,7 +392,7 @@ func Issues(ctx *context.Context) { ctx.Data["NewIssueChooseTemplate"] = len(ctx.IssueTemplatesFromDefaultBranch()) > 0 } - issues(ctx, ctx.FormInt64("milestone"), ctx.FormInt64("project"), util.OptionalBoolOf(isPullList)) + issues(ctx, ctx.FormInt64("milestone"), ctx.FormInt64("project"), util.OptionalBoolOf(isPullList), setting.UI.IssuePagingNum) if ctx.Written() { return } @@ -412,6 +413,47 @@ func Issues(ctx *context.Context) { ctx.HTML(http.StatusOK, tplIssues) } +// Issues Tree render issues page +func IssuesTree(ctx *context.Context) { + isPullList := ctx.Params(":type") == "pulls" + if isPullList { + MustAllowPulls(ctx) + if ctx.Written() { + return + } + ctx.Data["Title"] = ctx.Tr("repo.pulls") + ctx.Data["PageIsPullList"] = true + } else { + MustEnableIssues(ctx) + if ctx.Written() { + return + } + ctx.Data["Title"] = ctx.Tr("repo.issues_tree") + ctx.Data["PageIsIssuesTree"] = true + ctx.Data["NewIssueChooseTemplate"] = len(ctx.IssueTemplatesFromDefaultBranch()) > 0 + } + + issues(ctx, ctx.FormInt64("milestone"), ctx.FormInt64("project"), util.OptionalBoolOf(isPullList), 32*1024) + if ctx.Written() { + return + } + + var err error + // Get milestones + ctx.Data["Milestones"], _, err = models.GetMilestones(models.GetMilestonesOption{ + RepoID: ctx.Repo.Repository.ID, + State: api.StateType(ctx.FormString("state")), + }) + if err != nil { + ctx.ServerError("GetAllRepoMilestones", err) + return + } + + ctx.Data["CanWriteIssuesOrPulls"] = ctx.Repo.CanWriteIssuesOrPulls(isPullList) + + ctx.HTML(http.StatusOK, tplIssuesTree) +} + // RetrieveRepoMilestonesAndAssignees find all the milestones and assignees of a repository func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *repo_model.Repository) { var err error diff --git a/routers/web/repo/milestone.go b/routers/web/repo/milestone.go index df5fd411b4..e8660392d8 100644 --- a/routers/web/repo/milestone.go +++ b/routers/web/repo/milestone.go @@ -289,7 +289,7 @@ func MilestoneIssuesAndPulls(ctx *context.Context) { ctx.Data["Title"] = milestone.Name ctx.Data["Milestone"] = milestone - issues(ctx, milestoneID, 0, util.OptionalBoolNone) + issues(ctx, milestoneID, 0, util.OptionalBoolNone, setting.UI.IssuePagingNum) ctx.Data["NewIssueChooseTemplate"] = len(ctx.IssueTemplatesFromDefaultBranch()) > 0 ctx.Data["CanWriteIssues"] = ctx.Repo.CanWriteIssuesOrPulls(false) diff --git a/routers/web/web.go b/routers/web/web.go index 59629cb528..df09957b4a 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -885,6 +885,7 @@ func RegisterRoutes(m *web.Route) { m.Group("/{username}/{reponame}", func() { m.Group("", func() { m.Get("/{type:issues|pulls}", repo.Issues) + m.Get("/issues_tree", repo.IssuesTree) m.Get("/{type:issues|pulls}/{index}", repo.ViewIssue) m.Group("/{type:issues|pulls}/{index}/content-history", func() { m.Get("/overview", repo.GetContentHistoryOverview) diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl index c74d463325..13c76de5aa 100644 --- a/templates/repo/header.tmpl +++ b/templates/repo/header.tmpl @@ -2,7 +2,7 @@ {{with .Repository}}
-
+
{{$avatar := (repoAvatar . 32 "mr-3")}} {{if $avatar}} diff --git a/templates/repo/issue/navbar.tmpl b/templates/repo/issue/navbar.tmpl index 1e864458e7..551afb5f36 100644 --- a/templates/repo/issue/navbar.tmpl +++ b/templates/repo/issue/navbar.tmpl @@ -1,4 +1,5 @@ diff --git a/templates/repo/issue/tree.tmpl b/templates/repo/issue/tree.tmpl new file mode 100644 index 0000000000..8423795391 --- /dev/null +++ b/templates/repo/issue/tree.tmpl @@ -0,0 +1,293 @@ +{{template "base/head" .}} +
+ {{template "repo/header" .}} +
+
+
+ {{template "repo/issue/navbar" .}} +
+
+ {{template "repo/issue/search" .}} +
+ {{if not .Repository.IsArchived}} +
+ {{if .PageIsIssuesTree}} + {{.i18n.Tr "repo.issues.new"}} + {{else}} + {{.i18n.Tr "repo.pulls.new"}} + {{end}} +
+ {{else}} + {{if not .PageIsIssuesTree}} + + {{end}} + {{end}} +
+
+
+
+ {{template "repo/issue/openclose" .}} +
+
+ +
+
+
+
+ {{template "repo/issue/openclose" .}} +
+ {{/* Ten wide does not cope well and makes the columns stack. + This seems to be related to jQuery's hide/show: in fact, switching + issue-actions and issue-filters and having this ten wide will show + this one correctly, but not the other one. */}} +
+ +
+
+ + + +
+ + + + + + + + + +
+
+{{template "base/footer" .}} diff --git a/templates/shared/issuelistfortree.tmpl b/templates/shared/issuelistfortree.tmpl new file mode 100644 index 0000000000..faf20964bc --- /dev/null +++ b/templates/shared/issuelistfortree.tmpl @@ -0,0 +1,144 @@ +
+ {{ $approvalCounts := .ApprovalCounts}} + {{range .Issues}} +
+
  • +
    + {{if $.CanWriteIssuesOrPulls}} +
    + + +
    + {{end}} +
    + {{if .IsPull}} + {{if .PullRequest.HasMerged}} + {{svg "octicon-git-merge" 16 "text purple"}} + {{else}} + {{if .IsClosed}} + {{svg "octicon-git-pull-request" 16 "text red"}} + {{else}} + {{svg "octicon-git-pull-request" 16 "text green"}} + {{end}} + {{end}} + {{else}} + {{if .IsClosed}} + {{svg "octicon-issue-closed" 16 "text red"}} + {{else}} + {{svg "octicon-issue-opened" 16 "text green"}} + {{end}} + {{end}} +
    +
    +
    +
    + {{RenderEmoji .Title}} + {{if .IsPull}} + {{if (index $.CommitStatus .PullRequest.ID)}} + {{template "repo/commit_status" (index $.CommitStatus .PullRequest.ID)}} + {{end}} + {{end}} + + {{range .Labels}} + {{.Name | RenderEmoji}} + {{end}} + +
    +
    + + {{if eq $.listType "dashboard"}} + {{.Repo.FullName}}#{{.Index}} + {{else}} + #{{.Index}} + {{end}} + + {{ $timeStr := TimeSinceUnix .GetLastEventTimestamp $.Lang }} + {{if .OriginalAuthor }} + {{$.i18n.Tr .GetLastEventLabelFake $timeStr (.OriginalAuthor|Escape) | Safe}} + {{else if gt .Poster.ID 0}} + {{$.i18n.Tr .GetLastEventLabel $timeStr (.Poster.HomeLink|Escape) (.Poster.GetDisplayName | Escape) | Safe}} + {{else}} + {{$.i18n.Tr .GetLastEventLabelFake $timeStr (.Poster.GetDisplayName | Escape) | Safe}} + {{end}} + {{if and .Milestone (ne $.listType "milestone")}} + + {{svg "octicon-milestone" 14 "mr-2"}}{{.Milestone.Name}} + + {{end}} + {{if .Ref}} + + {{svg "octicon-git-branch" 14 "mr-2"}}{{index $.IssueRefEndNames .ID}} + + {{end}} + {{$tasks := .GetTasks}} + {{if gt $tasks 0}} + {{$tasksDone := .GetTasksDone}} + + {{svg "octicon-checklist" 14 "mr-2"}}{{$tasksDone}} / {{$tasks}} + + {{end}} + {{if ne .DeadlineUnix 0}} + + + {{svg "octicon-calendar" 14 "mr-2"}} + {{.DeadlineUnix.FormatShort}} + + + {{end}} + {{if .IsPull}} + {{$approveOfficial := call $approvalCounts .ID "approve"}} + {{$rejectOfficial := call $approvalCounts .ID "reject"}} + {{$waitingOfficial := call $approvalCounts .ID "waiting"}} + {{if gt $approveOfficial 0}} + + {{svg "octicon-check" 14 "mr-1"}} + {{$.i18n.TrN $approveOfficial "repo.pulls.approve_count_1" "repo.pulls.approve_count_n" $approveOfficial}} + + {{end}} + {{if gt $rejectOfficial 0}} + + {{svg "octicon-diff" 14 "mr-2"}} + {{$.i18n.TrN $rejectOfficial "repo.pulls.reject_count_1" "repo.pulls.reject_count_n" $rejectOfficial}} + + {{end}} + {{if gt $waitingOfficial 0}} + + {{svg "octicon-eye" 14 "mr-2"}} + {{$.i18n.TrN $waitingOfficial "repo.pulls.waiting_count_1" "repo.pulls.waiting_count_n" $waitingOfficial}} + + {{end}} + {{if and (not .PullRequest.HasMerged) (gt (len .PullRequest.ConflictedFiles) 0)}} + + {{svg "octicon-x" 14}} + {{$.i18n.TrN (len .PullRequest.ConflictedFiles) "repo.pulls.num_conflicting_files_1" "repo.pulls.num_conflicting_files_n" (len .PullRequest.ConflictedFiles)}} + + {{end}} + {{end}} +
    +
    +
    +
    + {{if .TotalTrackedTime}} + {{svg "octicon-clock" 16 "mr-2"}} + {{.TotalTrackedTime | Sec2Time}} + {{end}} +
    +
    + {{range .Assignees}} + + {{avatar .}} + + {{end}} +
    + +
    +
  • +
    + {{end}} +