mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Added sorting to the labels & milestones page (#199)
This commit is contained in:
		@@ -1503,12 +1503,28 @@ func GetMilestonesByRepoID(repoID int64) ([]*Milestone, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 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)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -171,12 +171,22 @@ func GetLabelsInRepoByIDs(repoID int64, labelIDs []int64) ([]*Label, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 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.
 | 
						sess := x.Where("repo_id = ?", repoID)
 | 
				
			||||||
		Where("repo_id = ?", repoID).
 | 
					
 | 
				
			||||||
		Asc("name").
 | 
						switch sortType {
 | 
				
			||||||
		Find(&labels)
 | 
						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) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -557,6 +557,8 @@ issues.label_modify = Label Modification
 | 
				
			|||||||
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"`
 | 
				
			||||||
@@ -610,6 +612,12 @@ milestones.edit_success = Changes of milestone '%s' has been saved successfully!
 | 
				
			|||||||
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!
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// 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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,7 +82,7 @@ func MustAllowPulls(ctx *context.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// 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
 | 
				
			||||||
@@ -92,6 +92,7 @@ func RetrieveLabels(ctx *context.Context) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	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
 | 
				
			||||||
@@ -274,12 +275,12 @@ func renderAttachmentSettings(ctx *context.Context) {
 | 
				
			|||||||
// 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
 | 
				
			||||||
@@ -298,7 +299,7 @@ func RetrieveRepoMetas(ctx *context.Context, repo *models.Repository) []*models.
 | 
				
			|||||||
		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
 | 
				
			||||||
@@ -583,7 +584,7 @@ func ViewIssue(ctx *context.Context) {
 | 
				
			|||||||
	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
 | 
				
			||||||
@@ -1079,6 +1080,7 @@ func Milestones(ctx *context.Context) {
 | 
				
			|||||||
	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
 | 
				
			||||||
@@ -1092,7 +1094,7 @@ func Milestones(ctx *context.Context) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	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
 | 
				
			||||||
@@ -1108,6 +1110,7 @@ func Milestones(ctx *context.Context) {
 | 
				
			|||||||
		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)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,6 +34,21 @@
 | 
				
			|||||||
		</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">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,23 @@
 | 
				
			|||||||
			</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">
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user