diff --git a/models/db/search.go b/models/db/search.go
index 26e082756a..105cb64c41 100644
--- a/models/db/search.go
+++ b/models/db/search.go
@@ -31,5 +31,5 @@ const (
const (
// Which means a condition to filter the records which don't match any id.
// It's different from zero which means the condition could be ignored.
- NoneID = -1
+ NoConditionID = -1
)
diff --git a/models/issues/issue.go b/models/issues/issue.go
index c8d148dd86..2dae8848c2 100644
--- a/models/issues/issue.go
+++ b/models/issues/issue.go
@@ -1266,7 +1266,9 @@ func (opts *IssuesOptions) setupSessionNoLimit(sess *xorm.Session) {
applySubscribedCondition(sess, opts.SubscriberID)
}
- if len(opts.MilestoneIDs) > 0 {
+ if len(opts.MilestoneIDs) == 1 && opts.MilestoneIDs[0] == db.NoConditionID {
+ sess.And("issue.milestone_id = 0")
+ } else if len(opts.MilestoneIDs) > 0 {
sess.In("issue.milestone_id", opts.MilestoneIDs)
}
@@ -1280,7 +1282,7 @@ func (opts *IssuesOptions) setupSessionNoLimit(sess *xorm.Session) {
if opts.ProjectID > 0 {
sess.Join("INNER", "project_issue", "issue.id = project_issue.issue_id").
And("project_issue.project_id=?", opts.ProjectID)
- } else if opts.ProjectID == db.NoneID { // show those that are in no project
+ } else if opts.ProjectID == db.NoConditionID { // show those that are in no project
sess.And(builder.NotIn("issue.id", builder.Select("issue_id").From("project_issue")))
}
@@ -1680,6 +1682,8 @@ func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats,
if opts.MilestoneID > 0 {
sess.And("issue.milestone_id = ?", opts.MilestoneID)
+ } else if opts.MilestoneID == db.NoConditionID {
+ sess.And("issue.milestone_id = 0")
}
if opts.ProjectID > 0 {
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 5154aadb68..8169cba108 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -1310,7 +1310,10 @@ issues.filter_label = Label
issues.filter_label_exclude = `Use alt
+ click/enter
to exclude labels`
issues.filter_label_no_select = All labels
issues.filter_milestone = Milestone
-issues.filter_milestone_no_select = All milestones
+issues.filter_milestone_all = All milestones
+issues.filter_milestone_none = No milestones
+issues.filter_milestone_open = Open milestones
+issues.filter_milestone_closed = Closed milestones
issues.filter_project = Project
issues.filter_project_all = All projects
issues.filter_project_none = No project
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index 3868e895f0..4f370c610d 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -237,7 +237,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
pager := context.NewPagination(total, setting.UI.IssuePagingNum, page, 5)
var mileIDs []int64
- if milestoneID > 0 {
+ if milestoneID > 0 || milestoneID == db.NoConditionID { // -1 to get those issues which have no any milestone assigned
mileIDs = []int64{milestoneID}
}
@@ -438,14 +438,8 @@ func Issues(ctx *context.Context) {
return
}
- var err error
- // Get milestones
- ctx.Data["Milestones"], _, err = issues_model.GetMilestones(issues_model.GetMilestonesOption{
- RepoID: ctx.Repo.Repository.ID,
- State: api.StateType(ctx.FormString("state")),
- })
- if err != nil {
- ctx.ServerError("GetAllRepoMilestones", err)
+ renderMilestones(ctx)
+ if ctx.Written() {
return
}
@@ -454,6 +448,29 @@ func Issues(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplIssues)
}
+func renderMilestones(ctx *context.Context) {
+ // Get milestones
+ milestones, _, err := issues_model.GetMilestones(issues_model.GetMilestonesOption{
+ RepoID: ctx.Repo.Repository.ID,
+ State: api.StateAll,
+ })
+ if err != nil {
+ ctx.ServerError("GetAllRepoMilestones", err)
+ return
+ }
+
+ openMilestones, closedMilestones := issues_model.MilestoneList{}, issues_model.MilestoneList{}
+ for _, milestone := range milestones {
+ if milestone.IsClosed {
+ closedMilestones = append(closedMilestones, milestone)
+ } else {
+ openMilestones = append(openMilestones, milestone)
+ }
+ }
+ ctx.Data["OpenMilestones"] = openMilestones
+ ctx.Data["ClosedMilestones"] = closedMilestones
+}
+
// 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/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl
index ddc197a889..a594801093 100644
--- a/templates/repo/issue/list.tmpl
+++ b/templates/repo/issue/list.tmpl
@@ -63,7 +63,7 @@
-