} | } | ||||
// GetMilestones returns a list of milestones of given repository and status. | // GetMilestones returns a list of milestones of given repository and status. | ||||
func GetMilestones(repoID int64, page int, isClosed bool) ([]*Milestone, error) { | |||||
func GetMilestones(repoID int64, page int, isClosed bool, sortType string) ([]*Milestone, error) { | |||||
miles := make([]*Milestone, 0, setting.UI.IssuePagingNum) | miles := make([]*Milestone, 0, setting.UI.IssuePagingNum) | ||||
sess := x.Where("repo_id = ? AND is_closed = ?", repoID, isClosed) | sess := x.Where("repo_id = ? AND is_closed = ?", repoID, isClosed) | ||||
if page > 0 { | if page > 0 { | ||||
sess = sess.Limit(setting.UI.IssuePagingNum, (page-1)*setting.UI.IssuePagingNum) | sess = sess.Limit(setting.UI.IssuePagingNum, (page-1)*setting.UI.IssuePagingNum) | ||||
} | } | ||||
switch sortType { | |||||
case "furthestduedate": | |||||
sess.Desc("deadline_unix") | |||||
case "leastcomplete": | |||||
sess.Asc("completeness") | |||||
case "mostcomplete": | |||||
sess.Desc("completeness") | |||||
case "leastissues": | |||||
sess.Asc("num_issues") | |||||
case "mostissues": | |||||
sess.Desc("num_issues") | |||||
default: | |||||
sess.Asc("deadline_unix") | |||||
} | |||||
return miles, sess.Find(&miles) | return miles, sess.Find(&miles) | ||||
} | } | ||||
} | } | ||||
// GetLabelsByRepoID returns all labels that belong to given repository by ID. | // GetLabelsByRepoID returns all labels that belong to given repository by ID. | ||||
func GetLabelsByRepoID(repoID int64) ([]*Label, error) { | |||||
func GetLabelsByRepoID(repoID int64, sortType string) ([]*Label, error) { | |||||
labels := make([]*Label, 0, 10) | labels := make([]*Label, 0, 10) | ||||
return labels, x. | |||||
Where("repo_id = ?", repoID). | |||||
Asc("name"). | |||||
Find(&labels) | |||||
sess := x.Where("repo_id = ?", repoID) | |||||
switch sortType { | |||||
case "reversealphabetically": | |||||
sess.Desc("name") | |||||
case "leastissues": | |||||
sess.Asc("num_issues") | |||||
case "mostissues": | |||||
sess.Desc("num_issues") | |||||
default: | |||||
sess.Asc("name") | |||||
} | |||||
return labels, sess.Find(&labels) | |||||
} | } | ||||
func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) { | func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) { |
issues.label_deletion = Label Deletion | issues.label_deletion = Label Deletion | ||||
issues.label_deletion_desc = Deleting this label will remove its information in all related issues. Do you want to continue? | issues.label_deletion_desc = Deleting this label will remove its information in all related issues. Do you want to continue? | ||||
issues.label_deletion_success = Label has been deleted successfully! | issues.label_deletion_success = Label has been deleted successfully! | ||||
issues.label.filter_sort.alphabetically = Alphabetically | |||||
issues.label.filter_sort.reverse_alphabetically = Reverse alphabetically | |||||
issues.num_participants = %d Participants | issues.num_participants = %d Participants | ||||
issues.attachment.open_tab = `Click to see "%s" in a new tab` | issues.attachment.open_tab = `Click to see "%s" in a new tab` | ||||
issues.attachment.download = `Click to download "%s"` | issues.attachment.download = `Click to download "%s"` | ||||
milestones.deletion = Milestone Deletion | milestones.deletion = Milestone Deletion | ||||
milestones.deletion_desc = Deleting this milestone will remove its information in all related issues. Do you want to continue? | milestones.deletion_desc = Deleting this milestone will remove its information in all related issues. Do you want to continue? | ||||
milestones.deletion_success = Milestone has been deleted successfully! | milestones.deletion_success = Milestone has been deleted successfully! | ||||
milestones.filter_sort.closest_due_date = Closest due date | |||||
milestones.filter_sort.furthest_due_date = Furthest due date | |||||
milestones.filter_sort.least_complete = Least complete | |||||
milestones.filter_sort.most_complete = Most complete | |||||
milestones.filter_sort.most_issues = Most issues | |||||
milestones.filter_sort.least_issues = Least issues | |||||
wiki = Wiki | wiki = Wiki | ||||
wiki.welcome = Welcome to Wiki! | wiki.welcome = Welcome to Wiki! |
// ListLabels list all the labels of a repository | // ListLabels list all the labels of a repository | ||||
func ListLabels(ctx *context.APIContext) { | func ListLabels(ctx *context.APIContext) { | ||||
labels, err := models.GetLabelsByRepoID(ctx.Repo.Repository.ID) | |||||
labels, err := models.GetLabelsByRepoID(ctx.Repo.Repository.ID, ctx.Query("sort")) | |||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, "GetLabelsByRepoID", err) | ctx.Error(500, "GetLabelsByRepoID", err) | ||||
return | return |
// RetrieveLabels find all the labels of a repository | // RetrieveLabels find all the labels of a repository | ||||
func RetrieveLabels(ctx *context.Context) { | func RetrieveLabels(ctx *context.Context) { | ||||
labels, err := models.GetLabelsByRepoID(ctx.Repo.Repository.ID) | |||||
labels, err := models.GetLabelsByRepoID(ctx.Repo.Repository.ID, ctx.Query("sort")) | |||||
if err != nil { | if err != nil { | ||||
ctx.Handle(500, "RetrieveLabels.GetLabels", err) | ctx.Handle(500, "RetrieveLabels.GetLabels", err) | ||||
return | return | ||||
} | } | ||||
ctx.Data["Labels"] = labels | ctx.Data["Labels"] = labels | ||||
ctx.Data["NumLabels"] = len(labels) | ctx.Data["NumLabels"] = len(labels) | ||||
ctx.Data["SortType"] = ctx.Query("sort") | |||||
} | } | ||||
// Issues render issues page | // Issues render issues page | ||||
// RetrieveRepoMilestonesAndAssignees find all the milestones and assignees of a repository | // RetrieveRepoMilestonesAndAssignees find all the milestones and assignees of a repository | ||||
func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *models.Repository) { | func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *models.Repository) { | ||||
var err error | var err error | ||||
ctx.Data["OpenMilestones"], err = models.GetMilestones(repo.ID, -1, false) | |||||
ctx.Data["OpenMilestones"], err = models.GetMilestones(repo.ID, -1, false, "") | |||||
if err != nil { | if err != nil { | ||||
ctx.Handle(500, "GetMilestones", err) | ctx.Handle(500, "GetMilestones", err) | ||||
return | return | ||||
} | } | ||||
ctx.Data["ClosedMilestones"], err = models.GetMilestones(repo.ID, -1, true) | |||||
ctx.Data["ClosedMilestones"], err = models.GetMilestones(repo.ID, -1, true, "") | |||||
if err != nil { | if err != nil { | ||||
ctx.Handle(500, "GetMilestones", err) | ctx.Handle(500, "GetMilestones", err) | ||||
return | return | ||||
return nil | return nil | ||||
} | } | ||||
labels, err := models.GetLabelsByRepoID(repo.ID) | |||||
labels, err := models.GetLabelsByRepoID(repo.ID, "") | |||||
if err != nil { | if err != nil { | ||||
ctx.Handle(500, "GetLabelsByRepoID", err) | ctx.Handle(500, "GetLabelsByRepoID", err) | ||||
return nil | return nil | ||||
for i := range issue.Labels { | for i := range issue.Labels { | ||||
labelIDMark[issue.Labels[i].ID] = true | labelIDMark[issue.Labels[i].ID] = true | ||||
} | } | ||||
labels, err := models.GetLabelsByRepoID(repo.ID) | |||||
labels, err := models.GetLabelsByRepoID(repo.ID, "") | |||||
if err != nil { | if err != nil { | ||||
ctx.Handle(500, "GetLabelsByRepoID", err) | ctx.Handle(500, "GetLabelsByRepoID", err) | ||||
return | return | ||||
ctx.Data["OpenCount"] = openCount | ctx.Data["OpenCount"] = openCount | ||||
ctx.Data["ClosedCount"] = closedCount | ctx.Data["ClosedCount"] = closedCount | ||||
sortType := ctx.Query("sort") | |||||
page := ctx.QueryInt("page") | page := ctx.QueryInt("page") | ||||
if page <= 1 { | if page <= 1 { | ||||
page = 1 | page = 1 | ||||
} | } | ||||
ctx.Data["Page"] = paginater.New(total, setting.UI.IssuePagingNum, page, 5) | ctx.Data["Page"] = paginater.New(total, setting.UI.IssuePagingNum, page, 5) | ||||
miles, err := models.GetMilestones(ctx.Repo.Repository.ID, page, isShowClosed) | |||||
miles, err := models.GetMilestones(ctx.Repo.Repository.ID, page, isShowClosed, sortType) | |||||
if err != nil { | if err != nil { | ||||
ctx.Handle(500, "GetMilestones", err) | ctx.Handle(500, "GetMilestones", err) | ||||
return | return | ||||
ctx.Data["State"] = "open" | ctx.Data["State"] = "open" | ||||
} | } | ||||
ctx.Data["SortType"] = sortType | |||||
ctx.Data["IsShowClosed"] = isShowClosed | ctx.Data["IsShowClosed"] = isShowClosed | ||||
ctx.HTML(200, tplMilestone) | ctx.HTML(200, tplMilestone) | ||||
} | } |
</div> | </div> | ||||
<div class="ui divider"></div> | <div class="ui divider"></div> | ||||
<div class="ui right floated secondary filter menu"> | |||||
<!-- Sort --> | |||||
<div class="ui dropdown type jump item"> | |||||
<span class="text"> | |||||
{{.i18n.Tr "repo.issues.filter_sort"}} | |||||
<i class="dropdown icon"></i> | |||||
</span> | |||||
<div class="menu"> | |||||
<a class="{{if or (eq .SortType "alphabetically") (not .SortType)}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&state={{$.State}}">{{.i18n.Tr "repo.issues.label.filter_sort.alphabetically"}}</a> | |||||
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&state={{$.State}}">{{.i18n.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a> | |||||
<a class="{{if eq .SortType "leastissues"}}active{{end}} item" href="{{$.Link}}?sort=leastissues&state={{$.State}}">{{.i18n.Tr "repo.milestones.filter_sort.least_issues"}}</a> | |||||
<a class="{{if eq .SortType "mostissues"}}active{{end}} item" href="{{$.Link}}?sort=mostissues&state={{$.State}}">{{.i18n.Tr "repo.milestones.filter_sort.most_issues"}}</a> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
{{template "base/alert" .}} | {{template "base/alert" .}} | ||||
<div class="ui black label">{{.i18n.Tr "repo.issues.label_count" .NumLabels}}</div> | <div class="ui black label">{{.i18n.Tr "repo.issues.label_count" .NumLabels}}</div> | ||||
<div class="label list"> | <div class="label list"> |
</a> | </a> | ||||
</div> | </div> | ||||
<div class="ui right floated secondary filter menu"> | |||||
<!-- Sort --> | |||||
<div class="ui dropdown type jump item"> | |||||
<span class="text"> | |||||
{{.i18n.Tr "repo.issues.filter_sort"}} | |||||
<i class="dropdown icon"></i> | |||||
</span> | |||||
<div class="menu"> | |||||
<a class="{{if or (eq .SortType "closestduedate") (not .SortType)}}active{{end}} item" href="{{$.Link}}?sort=closestduedate&state={{$.State}}">{{.i18n.Tr "repo.milestones.filter_sort.closest_due_date"}}</a> | |||||
<a class="{{if eq .SortType "furthestduedate"}}active{{end}} item" href="{{$.Link}}?sort=furthestduedate&state={{$.State}}">{{.i18n.Tr "repo.milestones.filter_sort.furthest_due_date"}}</a> | |||||
<a class="{{if eq .SortType "leastcomplete"}}active{{end}} item" href="{{$.Link}}?sort=leastcomplete&state={{$.State}}">{{.i18n.Tr "repo.milestones.filter_sort.least_complete"}}</a> | |||||
<a class="{{if eq .SortType "mostcomplete"}}active{{end}} item" href="{{$.Link}}?sort=mostcomplete&state={{$.State}}">{{.i18n.Tr "repo.milestones.filter_sort.most_complete"}}</a> | |||||
<a class="{{if eq .SortType "mostissues"}}active{{end}} item" href="{{$.Link}}?sort=mostissues&state={{$.State}}">{{.i18n.Tr "repo.milestones.filter_sort.most_issues"}}</a> | |||||
<a class="{{if eq .SortType "leastissues"}}active{{end}} item" href="{{$.Link}}?sort=leastissues&state={{$.State}}">{{.i18n.Tr "repo.milestones.filter_sort.least_issues"}}</a> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="milestone list"> | <div class="milestone list"> | ||||
{{range .Milestones}} | {{range .Milestones}} | ||||
<li class="item"> | <li class="item"> |