Added progressbar for issues (#1146). (#3171)

* Added progressbar for issues (#1146).

* Updated the generated index.css.

Signed-off-by: modmew8 <modmew8@gmail.com>

* Removed stored progress percentage and changed it to css calc. Also added the issue task progress to the user/dashboard/issues.

Signed-off-by: modmew8 <modmew8@gmail.com>

* Removed unnecessary blanks.

Signed-off-by: modmew8 <modmew8@gmail.com>

* Formatted the files correctly, fmt-check terminates now without errors.

Signed-off-by: modmew8 <modmew8@gmail.com>

* Removed variables, made computing the tasks on demand with precompiled regexp.

Signed-off-by: modmew8 <modmew8@gmail.com>
tokarchuk/v1.17
modmew8 7 years ago committed by Lunny Xiao
parent 22a7a7ec9b
commit d996da6bab
  1. 25
      models/issue.go
  2. 2
      public/css/index.css
  3. 14
      public/less/_repository.less
  4. 5
      templates/repo/issue/list.tmpl
  5. 5
      templates/user/dashboard/issues.tmpl

@ -7,6 +7,7 @@ package models
import ( import (
"fmt" "fmt"
"path" "path"
"regexp"
"sort" "sort"
"strings" "strings"
@ -54,6 +55,19 @@ type Issue struct {
Reactions ReactionList `xorm:"-"` Reactions ReactionList `xorm:"-"`
} }
var (
issueTasksPat *regexp.Regexp
issueTasksDonePat *regexp.Regexp
)
const issueTasksRegexpStr = `(^\s*-\s\[[\sx]\]\s)|(\n\s*-\s\[[\sx]\]\s)`
const issueTasksDoneRegexpStr = `(^\s*-\s\[[x]\]\s)|(\n\s*-\s\[[x]\]\s)`
func init() {
issueTasksPat = regexp.MustCompile(issueTasksRegexpStr)
issueTasksDonePat = regexp.MustCompile(issueTasksDoneRegexpStr)
}
func (issue *Issue) loadRepo(e Engine) (err error) { func (issue *Issue) loadRepo(e Engine) (err error) {
if issue.Repo == nil { if issue.Repo == nil {
issue.Repo, err = getRepositoryByID(e, issue.RepoID) issue.Repo, err = getRepositoryByID(e, issue.RepoID)
@ -741,6 +755,7 @@ func AddDeletePRBranchComment(doer *User, repo *Repository, issueID int64, branc
func (issue *Issue) ChangeContent(doer *User, content string) (err error) { func (issue *Issue) ChangeContent(doer *User, content string) (err error) {
oldContent := issue.Content oldContent := issue.Content
issue.Content = content issue.Content = content
if err = UpdateIssueCols(issue, "content"); err != nil { if err = UpdateIssueCols(issue, "content"); err != nil {
return fmt.Errorf("UpdateIssueCols: %v", err) return fmt.Errorf("UpdateIssueCols: %v", err)
} }
@ -818,6 +833,16 @@ func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) {
return nil return nil
} }
// GetTasks returns the amount of tasks in the issues content
func (issue *Issue) GetTasks() int {
return len(issueTasksPat.FindAllStringIndex(issue.Content, -1))
}
// GetTasksDone returns the amount of completed tasks in the issues content
func (issue *Issue) GetTasksDone() int {
return len(issueTasksDonePat.FindAllStringIndex(issue.Content, -1))
}
// NewIssueOptions represents the options of a new issue. // NewIssueOptions represents the options of a new issue.
type NewIssueOptions struct { type NewIssueOptions struct {
Repo *Repository Repo *Repository

File diff suppressed because one or more lines are too long

@ -1491,6 +1491,20 @@
.desc { .desc {
padding-top: 5px; padding-top: 5px;
color: #999; color: #999;
.progress-bar {
width: 80px;
height: 6px;
display: inline-block;
background-color: #eee;
overflow: hidden;
border-radius: 3px;
vertical-align: middle !important;
.progress {
background-color: #ccc;
display: block;
height: 100%;
}
}
a.milestone { a.milestone {
padding-left: 5px; padding-left: 5px;
color: #999!important; color: #999!important;

@ -200,6 +200,11 @@
<p class="desc"> <p class="desc">
{{$.i18n.Tr "repo.issues.opened_by" $timeStr .Poster.HomeLink .Poster.Name | Safe}} {{$.i18n.Tr "repo.issues.opened_by" $timeStr .Poster.HomeLink .Poster.Name | Safe}}
{{$tasks := .GetTasks}}
{{if gt $tasks 0}}
{{$tasksDone := .GetTasksDone}}
<span class="octicon octicon-checklist"></span> {{$tasksDone}} / {{$tasks}} <span class="progress-bar"><span class="progress" style="width:calc(100% * {{$tasksDone}} / {{$tasks}});"></span></span>
{{end}}
{{if .Milestone}} {{if .Milestone}}
<a class="milestone" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{.Milestone.ID}}&assignee={{$.AssigneeID}}"> <a class="milestone" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{.Milestone.ID}}&assignee={{$.AssigneeID}}">
<span class="octicon octicon-milestone"></span> {{.Milestone.Name}} <span class="octicon octicon-milestone"></span> {{.Milestone.Name}}

@ -87,6 +87,11 @@
<img class="ui avatar image" src="{{.Assignee.RelAvatarLink}}"> <img class="ui avatar image" src="{{.Assignee.RelAvatarLink}}">
</a> </a>
{{end}} {{end}}
{{$tasks := .GetTasks}}
{{if gt $tasks 0}}
{{$tasksDone := .GetTasksDone}}
<span class="octicon octicon-checklist"></span> {{$tasksDone}} / {{$tasks}} <span class="progress-bar"><span class="progress" style="width:calc(100% * {{$tasksDone}} / {{$tasks}});"></span></span>
{{end}}
</p> </p>
</li> </li>
{{end}} {{end}}

Loading…
Cancel
Save