Skip to content

Commit 60f297e

Browse files
gwymorfuxiaohei
authored andcommitted
Add ability to see open and closed issues at the same time (go-gitea#28757)
By clicking the currently active "Open" or "Closed" filter button in the issue list, the user can toggle that filter off in order to see all issues regardless of state. The URL "state" parameter will be set to "all" and the "Open"/"Closed" button will not show as active.
1 parent 20a394d commit 60f297e

File tree

4 files changed

+42
-19
lines changed

4 files changed

+42
-19
lines changed

models/issues/tracked_time.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ func GetTrackedTimeByID(ctx context.Context, id int64) (*TrackedTime, error) {
340340
}
341341

342342
// GetIssueTotalTrackedTime returns the total tracked time for issues by given conditions.
343-
func GetIssueTotalTrackedTime(ctx context.Context, opts *IssuesOptions, isClosed bool) (int64, error) {
343+
func GetIssueTotalTrackedTime(ctx context.Context, opts *IssuesOptions, isClosed util.OptionalBool) (int64, error) {
344344
if len(opts.IssueIDs) <= MaxQueryParameters {
345345
return getIssueTotalTrackedTimeChunk(ctx, opts, isClosed, opts.IssueIDs)
346346
}
@@ -363,7 +363,7 @@ func GetIssueTotalTrackedTime(ctx context.Context, opts *IssuesOptions, isClosed
363363
return accum, nil
364364
}
365365

366-
func getIssueTotalTrackedTimeChunk(ctx context.Context, opts *IssuesOptions, isClosed bool, issueIDs []int64) (int64, error) {
366+
func getIssueTotalTrackedTimeChunk(ctx context.Context, opts *IssuesOptions, isClosed util.OptionalBool, issueIDs []int64) (int64, error) {
367367
sumSession := func(opts *IssuesOptions, issueIDs []int64) *xorm.Session {
368368
sess := db.GetEngine(ctx).
369369
Table("tracked_time").
@@ -377,7 +377,9 @@ func getIssueTotalTrackedTimeChunk(ctx context.Context, opts *IssuesOptions, isC
377377
Time int64
378378
}
379379

380-
return sumSession(opts, issueIDs).
381-
And("issue.is_closed = ?", isClosed).
382-
SumInt(new(trackedTime), "tracked_time.time")
380+
session := sumSession(opts, issueIDs)
381+
if !isClosed.IsNone() {
382+
session = session.And("issue.is_closed = ?", isClosed.IsTrue())
383+
}
384+
return session.SumInt(new(trackedTime), "tracked_time.time")
383385
}

models/issues/tracked_time_test.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
issues_model "code.gitea.io/gitea/models/issues"
1212
"code.gitea.io/gitea/models/unittest"
1313
user_model "code.gitea.io/gitea/models/user"
14+
"code.gitea.io/gitea/modules/util"
1415

1516
"github.com/stretchr/testify/assert"
1617
)
@@ -119,11 +120,15 @@ func TestTotalTimesForEachUser(t *testing.T) {
119120
func TestGetIssueTotalTrackedTime(t *testing.T) {
120121
assert.NoError(t, unittest.PrepareTestDatabase())
121122

122-
ttt, err := issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, false)
123+
ttt, err := issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, util.OptionalBoolFalse)
123124
assert.NoError(t, err)
124125
assert.EqualValues(t, 3682, ttt)
125126

126-
ttt, err = issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, true)
127+
ttt, err = issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, util.OptionalBoolTrue)
127128
assert.NoError(t, err)
128129
assert.EqualValues(t, 0, ttt)
130+
131+
ttt, err = issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, util.OptionalBoolNone)
132+
assert.NoError(t, err)
133+
assert.EqualValues(t, 3682, ttt)
129134
}

routers/web/repo/issue.go

+26-10
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,18 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
237237
}
238238
}
239239

240-
isShowClosed := ctx.FormString("state") == "closed"
241-
// if open issues are zero and close don't, use closed as default
240+
var isShowClosed util.OptionalBool
241+
switch ctx.FormString("state") {
242+
case "closed":
243+
isShowClosed = util.OptionalBoolTrue
244+
case "all":
245+
isShowClosed = util.OptionalBoolNone
246+
default:
247+
isShowClosed = util.OptionalBoolFalse
248+
}
249+
// if there are closed issues and no open issues, default to showing all issues
242250
if len(ctx.FormString("state")) == 0 && issueStats.OpenCount == 0 && issueStats.ClosedCount != 0 {
243-
isShowClosed = true
251+
isShowClosed = util.OptionalBoolNone
244252
}
245253

246254
if repo.IsTimetrackerEnabled(ctx) {
@@ -260,10 +268,13 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
260268
}
261269

262270
var total int
263-
if !isShowClosed {
264-
total = int(issueStats.OpenCount)
265-
} else {
271+
switch isShowClosed {
272+
case util.OptionalBoolTrue:
266273
total = int(issueStats.ClosedCount)
274+
case util.OptionalBoolNone:
275+
total = int(issueStats.OpenCount + issueStats.ClosedCount)
276+
default:
277+
total = int(issueStats.OpenCount)
267278
}
268279
pager := context.NewPagination(total, setting.UI.IssuePagingNum, page, 5)
269280

@@ -282,7 +293,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
282293
ReviewedID: reviewedID,
283294
MilestoneIDs: mileIDs,
284295
ProjectID: projectID,
285-
IsClosed: util.OptionalBoolOf(isShowClosed),
296+
IsClosed: isShowClosed,
286297
IsPull: isPullOption,
287298
LabelIDs: labelIDs,
288299
SortType: sortType,
@@ -428,6 +439,9 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
428439
ctx.Data["OpenCount"] = issueStats.OpenCount
429440
ctx.Data["ClosedCount"] = issueStats.ClosedCount
430441
linkStr := "%s?q=%s&type=%s&sort=%s&state=%s&labels=%s&milestone=%d&project=%d&assignee=%d&poster=%d&archived=%t"
442+
ctx.Data["AllStatesLink"] = fmt.Sprintf(linkStr, ctx.Link,
443+
url.QueryEscape(keyword), url.QueryEscape(viewType), url.QueryEscape(sortType), "all", url.QueryEscape(selectLabels),
444+
mentionedID, projectID, assigneeID, posterID, archived)
431445
ctx.Data["OpenLink"] = fmt.Sprintf(linkStr, ctx.Link,
432446
url.QueryEscape(keyword), url.QueryEscape(viewType), url.QueryEscape(sortType), "open", url.QueryEscape(selectLabels),
433447
mentionedID, projectID, assigneeID, posterID, archived)
@@ -442,11 +456,13 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
442456
ctx.Data["ProjectID"] = projectID
443457
ctx.Data["AssigneeID"] = assigneeID
444458
ctx.Data["PosterID"] = posterID
445-
ctx.Data["IsShowClosed"] = isShowClosed
446459
ctx.Data["Keyword"] = keyword
447-
if isShowClosed {
460+
switch isShowClosed {
461+
case util.OptionalBoolTrue:
448462
ctx.Data["State"] = "closed"
449-
} else {
463+
case util.OptionalBoolNone:
464+
ctx.Data["State"] = "all"
465+
default:
450466
ctx.Data["State"] = "open"
451467
}
452468
ctx.Data["ShowArchivedLabels"] = archived

templates/repo/issue/openclose.tmpl

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div class="small-menu-items ui compact tiny menu">
2-
<a class="{{if not .IsShowClosed}}active {{end}}item" href="{{.OpenLink}}">
2+
<a class="{{if eq .State "open"}}active {{end}}item" href="{{if eq .State "open"}}{{.AllStatesLink}}{{else}}{{.OpenLink}}{{end}}">
33
{{if .PageIsMilestones}}
44
{{svg "octicon-milestone" 16 "gt-mr-3"}}
55
{{else if .PageIsPullList}}
@@ -9,7 +9,7 @@
99
{{end}}
1010
{{ctx.Locale.PrettyNumber .OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}}
1111
</a>
12-
<a class="{{if .IsShowClosed}}active {{end}}item" href="{{.ClosedLink}}">
12+
<a class="{{if eq .State "closed"}}active {{end}}item" href="{{if eq .State "closed"}}{{.AllStatesLink}}{{else}}{{.ClosedLink}}{{end}}">
1313
{{svg "octicon-check" 16 "gt-mr-3"}}
1414
{{ctx.Locale.PrettyNumber .ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}}
1515
</a>

0 commit comments

Comments
 (0)