Skip to content

Commit ef064c5

Browse files
committed
Add enable weight configuration options.
Add weight based progress fore milestones.
1 parent 88784a1 commit ef064c5

File tree

26 files changed

+294
-84
lines changed

26 files changed

+294
-84
lines changed

models/fixtures/issue.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
created_unix: 946684800
1515
updated_unix: 978307200
1616
is_locked: false
17+
weight: 10
1718

1819
-
1920
id: 2
@@ -31,6 +32,7 @@
3132
created_unix: 946684810
3233
updated_unix: 978307190
3334
is_locked: false
35+
weight: 12
3436

3537
-
3638
id: 3
@@ -48,6 +50,7 @@
4850
created_unix: 946684820
4951
updated_unix: 978307180
5052
is_locked: false
53+
weight: 5
5154

5255
-
5356
id: 4
@@ -65,6 +68,7 @@
6568
created_unix: 946684830
6669
updated_unix: 978307200
6770
is_locked: false
71+
weight: 10
6872

6973
-
7074
id: 5
@@ -82,6 +86,7 @@
8286
created_unix: 946684840
8387
updated_unix: 978307200
8488
is_locked: false
89+
weight: 20
8590

8691
-
8792
id: 6
@@ -99,6 +104,7 @@
99104
created_unix: 946684850
100105
updated_unix: 978307200
101106
is_locked: false
107+
weight: 0
102108

103109
-
104110
id: 7
@@ -116,6 +122,7 @@
116122
created_unix: 946684830
117123
updated_unix: 978307200
118124
is_locked: false
125+
weight: 10
119126

120127
-
121128
id: 8
@@ -133,6 +140,7 @@
133140
created_unix: 946684820
134141
updated_unix: 978307180
135142
is_locked: false
143+
weight: 0
136144

137145
-
138146
id: 9
@@ -150,6 +158,7 @@
150158
created_unix: 946684820
151159
updated_unix: 978307180
152160
is_locked: false
161+
weight: 10
153162

154163
-
155164
id: 10
@@ -168,6 +177,7 @@
168177
created_unix: 946684830
169178
updated_unix: 999307200
170179
is_locked: false
180+
weight: 4
171181

172182
-
173183
id: 11
@@ -185,6 +195,7 @@
185195
created_unix: 1579194806
186196
updated_unix: 1579194806
187197
is_locked: false
198+
weight: 0
188199

189200
-
190201
id: 12
@@ -202,6 +213,7 @@
202213
created_unix: 1602935696
203214
updated_unix: 1602935696
204215
is_locked: false
216+
weight: 22
205217

206218
-
207219
id: 13
@@ -219,6 +231,7 @@
219231
created_unix: 1602935696
220232
updated_unix: 1602935696
221233
is_locked: false
234+
weight: 13
222235

223236
-
224237
id: 14
@@ -236,6 +249,7 @@
236249
created_unix: 1602935696
237250
updated_unix: 1602935696
238251
is_locked: false
252+
weight: 8
239253

240254
-
241255
id: 15
@@ -253,6 +267,7 @@
253267
created_unix: 1602935696
254268
updated_unix: 1602935696
255269
is_locked: false
270+
weight: 52
256271

257272
-
258273
id: 16
@@ -270,6 +285,7 @@
270285
created_unix: 1602935696
271286
updated_unix: 1602935696
272287
is_locked: false
288+
weight: 10
273289

274290
-
275291
id: 17
@@ -287,6 +303,7 @@
287303
created_unix: 1602935696
288304
updated_unix: 1602935696
289305
is_locked: false
306+
weight: 0
290307

291308
-
292309
id: 18
@@ -304,6 +321,7 @@
304321
created_unix: 946684830
305322
updated_unix: 978307200
306323
is_locked: false
324+
weight: 20
307325

308326
-
309327
id: 19
@@ -321,6 +339,7 @@
321339
created_unix: 946684830
322340
updated_unix: 978307200
323341
is_locked: false
342+
weight: 10
324343

325344
-
326345
id: 20
@@ -338,6 +357,7 @@
338357
created_unix: 978307210
339358
updated_unix: 978307210
340359
is_locked: false
360+
weight: 24
341361

342362
-
343363
id: 21
@@ -355,6 +375,7 @@
355375
created_unix: 1707270422
356376
updated_unix: 1707270422
357377
is_locked: false
378+
weight: 40
358379

359380
-
360381
id: 22
@@ -372,3 +393,4 @@
372393
created_unix: 1707270422
373394
updated_unix: 1707270422
374395
is_locked: false
396+
weight: 2

models/issues/issue_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,26 @@ func TestLoadTotalTrackedTime(t *testing.T) {
375375
assert.Equal(t, int64(3682), milestone.TotalTrackedTime)
376376
}
377377

378+
func TestMilestoneList_LoadTotalWeight(t *testing.T) {
379+
assert.NoError(t, unittest.PrepareTestDatabase())
380+
miles := issues_model.MilestoneList{
381+
unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1}),
382+
}
383+
384+
assert.NoError(t, miles.LoadTotalWeight(db.DefaultContext))
385+
386+
assert.Equal(t, 12, miles[0].TotalWeight)
387+
}
388+
389+
func TestLoadTotalWeight(t *testing.T) {
390+
assert.NoError(t, unittest.PrepareTestDatabase())
391+
milestone := unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1})
392+
393+
assert.NoError(t, milestone.LoadTotalWeight(db.DefaultContext))
394+
395+
assert.Equal(t, 12, milestone.TotalWeight)
396+
}
397+
378398
func TestCountIssues(t *testing.T) {
379399
assert.NoError(t, unittest.PrepareTestDatabase())
380400
count, err := issues_model.CountIssues(db.DefaultContext, &issues_model.IssuesOptions{})

models/issues/milestone.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@ type Milestone struct {
6464
ClosedDateUnix timeutil.TimeStamp
6565
DeadlineString string `xorm:"-"`
6666

67-
TotalTrackedTime int64 `xorm:"-"`
68-
TotalWeight int `xorm:"-"`
67+
TotalTrackedTime int64 `xorm:"-"`
68+
TotalWeight int `xorm:"-"`
69+
WeightedCompleteness int `xorm:"-"`
6970
}
7071

7172
func init() {
@@ -358,23 +359,28 @@ func (m *Milestone) LoadTotalTrackedTime(ctx context.Context) error {
358359

359360
// LoadTotalWeight loads the total weight for the milestone
360361
func (m *Milestone) LoadTotalWeight(ctx context.Context) error {
361-
type totalTimesByMilestone struct {
362-
MilestoneID int64
363-
Weight int
362+
type totalWeightByMilestone struct {
363+
MilestoneID int64
364+
Weight int
365+
WeightClosed int
364366
}
365-
totalTime := &totalTimesByMilestone{MilestoneID: m.ID}
367+
368+
totalWeight := &totalWeightByMilestone{MilestoneID: m.ID}
366369
has, err := db.GetEngine(ctx).Table("issue").
367370
Join("INNER", "milestone", "issue.milestone_id = milestone.id").
368-
Select("milestone_id, sum(weight) as weight").
371+
Select("milestone_id, sum(weight) as weight, sum(CASE WHEN is_closed THEN 0 ELSE weight END) as weight_closed").
369372
Where("milestone_id = ?", m.ID).
370373
GroupBy("milestone_id").
371-
Get(totalTime)
374+
Get(totalWeight)
372375
if err != nil {
373376
return err
374377
} else if !has {
375378
return nil
376379
}
377-
m.TotalWeight = totalTime.Weight
380+
381+
m.TotalWeight = totalWeight.Weight
382+
m.WeightedCompleteness = totalWeight.WeightClosed * 100 / totalWeight.Weight
383+
378384
return nil
379385
}
380386

models/issues/milestone_list.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,39 +133,43 @@ func (milestones MilestoneList) LoadTotalTrackedTimes(ctx context.Context) error
133133
// LoadTotalWeight loads for every milestone in the list the TotalWeight by a batch request
134134
func (milestones MilestoneList) LoadTotalWeight(ctx context.Context) error {
135135
type totalWeightByMilestone struct {
136-
MilestoneID int64
137-
Weight int
136+
MilestoneID int64
137+
Weight int
138+
WeightClosed int
138139
}
139140
if len(milestones) == 0 {
140141
return nil
141142
}
142-
trackedTimes := make(map[int64]int, len(milestones))
143143

144-
// Get total tracked time by milestone_id
144+
weight := make(map[int64]int, len(milestones))
145+
closedWeight := make(map[int64]int, len(milestones))
146+
145147
rows, err := db.GetEngine(ctx).Table("issue").
146148
Join("INNER", "milestone", "issue.milestone_id = milestone.id").
147-
Select("milestone_id, sum(weight) as weight").
149+
Select("milestone_id, sum(weight) as weight, sum(CASE WHEN is_closed THEN 0 ELSE weight END) as weight_closed").
148150
In("milestone_id", milestones.getMilestoneIDs()).
149151
GroupBy("milestone_id").
150152
Rows(new(totalWeightByMilestone))
151153
if err != nil {
152154
return err
153155
}
154-
155156
defer rows.Close()
156157

157158
for rows.Next() {
158-
var totalTime totalWeightByMilestone
159-
err = rows.Scan(&totalTime)
159+
var totalWeight totalWeightByMilestone
160+
err = rows.Scan(&totalWeight)
160161
if err != nil {
161162
return err
162163
}
163-
trackedTimes[totalTime.MilestoneID] = totalTime.Weight
164+
weight[totalWeight.MilestoneID] = totalWeight.Weight
165+
closedWeight[totalWeight.MilestoneID] = totalWeight.WeightClosed
164166
}
165167

166168
for _, milestone := range milestones {
167-
milestone.TotalWeight = trackedTimes[milestone.ID]
169+
milestone.TotalWeight = weight[milestone.ID]
170+
milestone.WeightedCompleteness = closedWeight[milestone.ID] * 100 / milestone.TotalWeight
168171
}
172+
169173
return nil
170174
}
171175

models/issues/weight.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package issues
2+
3+
import (
4+
"context"
5+
6+
"code.gitea.io/gitea/models/db"
7+
)
8+
9+
// GetIssueTotalWeight returns the total weight for issues by given conditions.
10+
func GetIssueTotalWeight(ctx context.Context, opts *IssuesOptions) (int, int, error) {
11+
if len(opts.IssueIDs) <= MaxQueryParameters {
12+
return getIssueTotalWeightChunk(ctx, opts, opts.IssueIDs)
13+
}
14+
15+
// If too long a list of IDs is provided,
16+
// we get the statistics in smaller chunks and get accumulates
17+
var weightSum int
18+
var closedWeightSum int
19+
for i := 0; i < len(opts.IssueIDs); {
20+
chunk := i + MaxQueryParameters
21+
if chunk > len(opts.IssueIDs) {
22+
chunk = len(opts.IssueIDs)
23+
}
24+
weight, closedWeight, err := getIssueTotalWeightChunk(ctx, opts, opts.IssueIDs[i:chunk])
25+
if err != nil {
26+
return 0, 0, err
27+
}
28+
weightSum += weight
29+
closedWeightSum += closedWeight
30+
i = chunk
31+
}
32+
33+
return weightSum, closedWeightSum, nil
34+
}
35+
36+
func getIssueTotalWeightChunk(ctx context.Context, opts *IssuesOptions, issueIDs []int64) (int, int, error) {
37+
type totalWeight struct {
38+
Weight int
39+
WeightClosed int
40+
}
41+
42+
tw := &totalWeight{}
43+
44+
session := db.GetEngine(ctx).Table("issue").
45+
Select("sum(weight) as weight, sum(CASE WHEN is_closed THEN 0 ELSE weight END) as weight_closed")
46+
47+
has, err := applyIssuesOptions(session, opts, issueIDs).
48+
Get(tw)
49+
50+
if err != nil {
51+
return 0, 0, err
52+
} else if !has {
53+
return 0, 0, nil
54+
}
55+
56+
return tw.Weight, tw.WeightClosed, nil
57+
}

models/issues/weight_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2019 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package issues_test
5+
6+
import (
7+
"testing"
8+
9+
"code.gitea.io/gitea/models/db"
10+
issues_model "code.gitea.io/gitea/models/issues"
11+
"code.gitea.io/gitea/models/unittest"
12+
13+
"github.com/stretchr/testify/assert"
14+
)
15+
16+
func TestGetIssueTotalWeight(t *testing.T) {
17+
assert.NoError(t, unittest.PrepareTestDatabase())
18+
19+
tw, twc, err := issues_model.GetIssueTotalWeight(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}})
20+
assert.NoError(t, err)
21+
assert.EqualValues(t, 12, tw)
22+
assert.EqualValues(t, 12, twc)
23+
24+
tw, twc, err = issues_model.GetIssueTotalWeight(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{3}})
25+
assert.NoError(t, err)
26+
assert.EqualValues(t, 5, tw)
27+
assert.EqualValues(t, 5, twc)
28+
29+
tw, twc, err = issues_model.GetIssueTotalWeight(db.DefaultContext, &issues_model.IssuesOptions{RepoIDs: []int64{2}})
30+
assert.NoError(t, err)
31+
assert.EqualValues(t, 20, tw)
32+
assert.EqualValues(t, 10, twc)
33+
}

0 commit comments

Comments
 (0)