mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-01-31 18:05:00 -05:00
Compare commits
4 commits
2fc217b921
...
233c3f4819
Author | SHA1 | Date | |
---|---|---|---|
|
233c3f4819 | ||
|
c993e4a157 | ||
|
8ae2e4b2ef | ||
|
faad7e0017 |
4 changed files with 613 additions and 927 deletions
|
@ -238,10 +238,30 @@ func (r RoleInRepo) LocaleHelper(lang translation.Locale) string {
|
|||
return lang.TrString("repo.issues.role." + string(r) + "_helper")
|
||||
}
|
||||
|
||||
type RequestReviewTarget interface {
|
||||
ID() int64
|
||||
Name() string
|
||||
Type() string
|
||||
type RequestReviewTarget struct {
|
||||
User *user_model.User
|
||||
Team *organization.Team
|
||||
}
|
||||
|
||||
func (t *RequestReviewTarget) ID() int64 {
|
||||
if t.User != nil {
|
||||
return t.User.ID
|
||||
}
|
||||
return t.Team.ID
|
||||
}
|
||||
|
||||
func (t *RequestReviewTarget) Name() string {
|
||||
if t.User != nil {
|
||||
return t.User.GetDisplayName()
|
||||
}
|
||||
return t.Team.Name
|
||||
}
|
||||
|
||||
func (t *RequestReviewTarget) Type() string {
|
||||
if t.User != nil {
|
||||
return "user"
|
||||
}
|
||||
return "team"
|
||||
}
|
||||
|
||||
// Comment represents a comment in commit and issue page.
|
||||
|
|
|
@ -5,24 +5,20 @@ package issues
|
|||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
type CommentAggregator struct {
|
||||
StartUnix int64
|
||||
Indexes []int
|
||||
PosterID int64
|
||||
Indexes []int
|
||||
PosterID int64
|
||||
|
||||
PrevClosed bool
|
||||
IsClosed bool
|
||||
IsClosed bool
|
||||
|
||||
AddedLabels []*Label
|
||||
AddedLabels []*Label
|
||||
RemovedLabels []*Label
|
||||
|
||||
AddedRequestReview []RequestReviewTarget
|
||||
AddedRequestReview []RequestReviewTarget
|
||||
RemovedRequestReview []RequestReviewTarget
|
||||
}
|
||||
|
||||
|
@ -33,46 +29,41 @@ type CommentAggregator struct {
|
|||
func (agg *CommentAggregator) aggregateComment(c *Comment, index int) {
|
||||
agg.Indexes = append(agg.Indexes, index)
|
||||
|
||||
if (c.Type == CommentTypeClose) {
|
||||
if c.Type == CommentTypeClose {
|
||||
agg.IsClosed = true
|
||||
|
||||
} else if (c.Type == CommentTypeReopen) {
|
||||
} else if c.Type == CommentTypeReopen {
|
||||
agg.IsClosed = false
|
||||
|
||||
} else if (c.Type == CommentTypeReviewRequest) {
|
||||
if c.AssigneeID >= 0 {
|
||||
req := ReqReviewTarget { User: c.Assignee }
|
||||
} else if c.Type == CommentTypeReviewRequest {
|
||||
if c.AssigneeID > 0 {
|
||||
req := RequestReviewTarget{User: c.Assignee}
|
||||
if c.RemovedAssignee {
|
||||
agg.delReviewRequest(&req)
|
||||
agg.delReviewRequest(req)
|
||||
} else {
|
||||
agg.addReviewRequest(&req)
|
||||
agg.addReviewRequest(req)
|
||||
}
|
||||
|
||||
} else if c.AssigneeTeamID >= 0 {
|
||||
req := ReqReviewTarget { Team: c.AssigneeTeam }
|
||||
} else if c.AssigneeTeamID > 0 {
|
||||
req := RequestReviewTarget{Team: c.AssigneeTeam}
|
||||
if c.RemovedAssignee {
|
||||
agg.delReviewRequest(&req)
|
||||
agg.delReviewRequest(req)
|
||||
} else {
|
||||
agg.addReviewRequest(&req)
|
||||
agg.addReviewRequest(req)
|
||||
}
|
||||
}
|
||||
|
||||
for _, r := range c.RemovedRequestReview {
|
||||
agg.delReviewRequest(r)
|
||||
}
|
||||
|
||||
for _, r := range c.AddedRequestReview {
|
||||
agg.addReviewRequest(r)
|
||||
}
|
||||
|
||||
} else if (c.Type == CommentTypeLabel) {
|
||||
log.Warn("Aggregated label comment %v %v %v", c.Type, c.Label.Name, c.Label.ID)
|
||||
} else if c.Type == CommentTypeLabel {
|
||||
if c.Content == "1" {
|
||||
agg.addLabel(c.Label)
|
||||
} else {
|
||||
agg.delLabel(c.Label)
|
||||
}
|
||||
|
||||
} else if (c.Type == CommentTypeAggregator) {
|
||||
} else if c.Type == CommentTypeAggregator {
|
||||
agg.Merge(c.Aggregator)
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +105,7 @@ func (agg *CommentAggregator) addLabel(lbl *Label) {
|
|||
for l, agglbl := range agg.RemovedLabels {
|
||||
if agglbl.ID == lbl.ID {
|
||||
agg.RemovedLabels = append(agg.RemovedLabels[:l], agg.RemovedLabels[l+1:]...)
|
||||
return;
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,7 +119,7 @@ func (agg *CommentAggregator) delLabel(lbl *Label) {
|
|||
for l, agglbl := range agg.AddedLabels {
|
||||
if agglbl.ID == lbl.ID {
|
||||
agg.AddedLabels = append(agg.AddedLabels[:l], agg.AddedLabels[l+1:]...)
|
||||
return;
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,9 +133,9 @@ func (agg *CommentAggregator) addReviewRequest(req RequestReviewTarget) {
|
|||
reqid := req.ID()
|
||||
reqty := req.Type()
|
||||
for r, aggreq := range agg.RemovedRequestReview {
|
||||
if (aggreq.ID() == reqid) && (aggreq.Type() == reqty){
|
||||
if (aggreq.ID() == reqid) && (aggreq.Type() == reqty) {
|
||||
agg.RemovedRequestReview = append(agg.RemovedRequestReview[:r], agg.RemovedRequestReview[r+1:]...)
|
||||
return;
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,9 +149,9 @@ func (agg *CommentAggregator) delReviewRequest(req RequestReviewTarget) {
|
|||
reqid := req.ID()
|
||||
reqty := req.Type()
|
||||
for r, aggreq := range agg.AddedRequestReview {
|
||||
if (aggreq.ID() == reqid) && (aggreq.Type() == reqty){
|
||||
if (aggreq.ID() == reqid) && (aggreq.Type() == reqty) {
|
||||
agg.AddedRequestReview = append(agg.AddedRequestReview[:r], agg.AddedRequestReview[r+1:]...)
|
||||
return;
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,6 +206,12 @@ func (agg *CommentAggregator) Reset(cur *Comment) {
|
|||
agg.RemovedRequestReview = []RequestReviewTarget{}
|
||||
}
|
||||
|
||||
// Function that replaces all the comments aggregated with a single one
|
||||
// Its CommentType depend on whether multiple type of comments are been aggregated or not
|
||||
// If nothing has changed, we remove all the comments that get nullified
|
||||
//
|
||||
// The function returns how many comments has been removed, in order for the "for" loop
|
||||
// of the main algorithm to change its index
|
||||
func (agg *CommentAggregator) createAggregatedComment(issue *Issue, final bool) int {
|
||||
endind := agg.Indexes[len(agg.Indexes)-1]
|
||||
startind := agg.Indexes[0]
|
||||
|
@ -223,21 +220,24 @@ func (agg *CommentAggregator) createAggregatedComment(issue *Issue, final bool)
|
|||
if !agg.Changed() {
|
||||
if final {
|
||||
issue.Comments = issue.Comments[:startind]
|
||||
log.Warn("Case 1: [:%v]", startind)
|
||||
} else {
|
||||
issue.Comments = append(issue.Comments[:startind], issue.Comments[endind+1:]...)
|
||||
log.Warn("Case 2: [:%v] + [:%v]", startind, endind+1)
|
||||
}
|
||||
return endind - startind
|
||||
}
|
||||
|
||||
new_agg := *agg // Trigger a memory allocation, get a COPY of the aggregator
|
||||
newAgg := *agg // Trigger a memory allocation, get a COPY of the aggregator
|
||||
|
||||
// Keep the same author, time, etc... But reset the parts we may want to use
|
||||
comment := issue.Comments[startind]
|
||||
comment.Content = ""
|
||||
comment.Label = nil
|
||||
comment.Aggregator = nil
|
||||
comment.Assignee = nil
|
||||
comment.AssigneeID = -1
|
||||
comment.AssigneeTeam = nil
|
||||
comment.AssigneeTeamID = -1
|
||||
comment.RemovedAssignee = false
|
||||
comment.AddedLabels = nil
|
||||
comment.RemovedLabels = nil
|
||||
|
||||
|
@ -245,42 +245,38 @@ func (agg *CommentAggregator) createAggregatedComment(issue *Issue, final bool)
|
|||
// instead of an aggregator
|
||||
if agg.OnlyLabelsChanged() {
|
||||
comment.Type = CommentTypeLabel
|
||||
|
||||
} else if agg.OnlyClosedReopened() {
|
||||
if agg.IsClosed {
|
||||
comment.Type = CommentTypeClose
|
||||
} else {
|
||||
comment.Type = CommentTypeReopen
|
||||
}
|
||||
|
||||
} else if agg.OnlyRequestReview() {
|
||||
comment.Type = CommentTypeReviewRequest
|
||||
|
||||
} else {
|
||||
comment.Type = CommentTypeAggregator
|
||||
comment.Aggregator = &new_agg
|
||||
comment.Aggregator = &newAgg
|
||||
}
|
||||
|
||||
if len(new_agg.AddedLabels) > 0 {
|
||||
comment.AddedLabels = new_agg.AddedLabels
|
||||
if len(newAgg.AddedLabels) > 0 {
|
||||
comment.AddedLabels = newAgg.AddedLabels
|
||||
}
|
||||
|
||||
if len(new_agg.RemovedLabels) > 0 {
|
||||
comment.RemovedLabels = new_agg.RemovedLabels
|
||||
if len(newAgg.RemovedLabels) > 0 {
|
||||
comment.RemovedLabels = newAgg.RemovedLabels
|
||||
}
|
||||
|
||||
if len(new_agg.AddedRequestReview) > 0 {
|
||||
comment.AddedRequestReview = new_agg.AddedRequestReview
|
||||
if len(newAgg.AddedRequestReview) > 0 {
|
||||
comment.AddedRequestReview = newAgg.AddedRequestReview
|
||||
}
|
||||
if len(new_agg.RemovedRequestReview) > 0 {
|
||||
comment.RemovedRequestReview = new_agg.RemovedRequestReview
|
||||
|
||||
if len(newAgg.RemovedRequestReview) > 0 {
|
||||
comment.RemovedRequestReview = newAgg.RemovedRequestReview
|
||||
}
|
||||
|
||||
if final {
|
||||
log.Warn("Case 3: [:%v] + [%v]", startind, comment.Type)
|
||||
issue.Comments = append(issue.Comments[:startind], comment)
|
||||
} else {
|
||||
log.Warn("Case 4: [:%v] + [%v] + [%v:]", startind, comment.Type, endind + 1)
|
||||
issue.Comments = append(append(issue.Comments[:startind], comment), issue.Comments[endind+1:]...)
|
||||
}
|
||||
return endind - startind
|
||||
|
@ -288,29 +284,25 @@ func (agg *CommentAggregator) createAggregatedComment(issue *Issue, final bool)
|
|||
|
||||
// combineCommentsHistory combines nearby elements in the history as one
|
||||
func CombineCommentsHistory(issue *Issue) {
|
||||
log.Warn("=== START ===")
|
||||
// Initialise a new empty aggregator, ready to combine comments
|
||||
var agg CommentAggregator;
|
||||
var agg CommentAggregator
|
||||
agg.StartUnix = 0
|
||||
agg.PosterID = -1
|
||||
req_reset := false
|
||||
reqReset := false
|
||||
|
||||
for i := 0; i < len(issue.Comments); i++ {
|
||||
cur := issue.Comments[i]
|
||||
log.Warn("%v %v %v", i, cur.Type, int64(cur.CreatedUnix) - agg.StartUnix)
|
||||
if req_reset {
|
||||
if reqReset {
|
||||
agg.Reset(cur)
|
||||
req_reset = false
|
||||
reqReset = false
|
||||
}
|
||||
|
||||
// If the comment we encounter is not accepted inside an aggregator
|
||||
if !agg.IsAggregated(&cur.Type) {
|
||||
|
||||
// If we aggregated some data, create the resulting comment for it
|
||||
if len(agg.Indexes) > 1 {
|
||||
if len(agg.Indexes) > 0 {
|
||||
i -= agg.createAggregatedComment(issue, false)
|
||||
}
|
||||
req_reset = true
|
||||
reqReset = true
|
||||
|
||||
// Do not need to continue the aggregation loop, skip to next comment
|
||||
continue
|
||||
|
@ -320,7 +312,7 @@ func CombineCommentsHistory(issue *Issue) {
|
|||
// we create a new empty aggregator
|
||||
if ((int64(cur.CreatedUnix) - agg.StartUnix) > 60) || (cur.PosterID != agg.PosterID) {
|
||||
// First, create the aggregated comment if there's data in it
|
||||
if len(agg.Indexes) > 1 {
|
||||
if len(agg.Indexes) > 0 {
|
||||
i -= agg.createAggregatedComment(issue, false)
|
||||
}
|
||||
agg.Reset(cur)
|
||||
|
@ -330,34 +322,7 @@ func CombineCommentsHistory(issue *Issue) {
|
|||
}
|
||||
|
||||
// Create the aggregated comment if there's data in it
|
||||
if !req_reset && len(agg.Indexes) > 1 {
|
||||
if !reqReset && len(agg.Indexes) > 0 {
|
||||
agg.createAggregatedComment(issue, true)
|
||||
}
|
||||
log.Warn("=== END ===")
|
||||
}
|
||||
|
||||
type ReqReviewTarget struct {
|
||||
User *user_model.User
|
||||
Team *organization.Team
|
||||
}
|
||||
|
||||
func (t *ReqReviewTarget) ID() int64 {
|
||||
if t.User != nil {
|
||||
return t.User.ID
|
||||
}
|
||||
return t.Team.ID
|
||||
}
|
||||
|
||||
func (t *ReqReviewTarget) Name() string {
|
||||
if t.User != nil {
|
||||
return t.User.GetDisplayName()
|
||||
}
|
||||
return t.Team.Name
|
||||
}
|
||||
|
||||
func (t *ReqReviewTarget) Type() string {
|
||||
if t.User != nil {
|
||||
return "user"
|
||||
}
|
||||
return "team"
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -524,7 +524,7 @@
|
|||
</div>
|
||||
</div>
|
||||
{{else if eq .Type 27}}
|
||||
{{if or .AddedRequestReview .RemovedRequestReview}}
|
||||
{{if or .AddedRequestReview .RemovedRequestReview}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-tag"}}</span>
|
||||
{{template "shared/user/avatarlink" dict "user" .Poster}}
|
||||
|
@ -540,7 +540,7 @@
|
|||
{{end}}
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{else if and (eq .Type 29) (or (gt .CommitsNum 0) .IsForcePush)}}
|
||||
<!-- If PR is closed, the comments whose type is CommentTypePullRequestPush(29) after latestCloseCommentID won't be rendered. //-->
|
||||
{{if and .Issue.IsClosed (gt .ID $.LatestCloseCommentID)}}
|
||||
|
@ -683,12 +683,12 @@
|
|||
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{ $createdStr }}
|
||||
{{$createdStr}}
|
||||
|
||||
<ul class="comment-aggregator">
|
||||
|
||||
<!-- OPEN / CLOSE -->
|
||||
{{if and .Aggregator.PrevClosed (not .Aggregator.IsClosed) }}
|
||||
{{if and .Aggregator.PrevClosed (not .Aggregator.IsClosed)}}
|
||||
<li>
|
||||
<span class="badge tw-bg-green tw-text-white">{{svg "octicon-dot-fill"}}</span>
|
||||
{{if .Issue.IsPull}}
|
||||
|
|
Loading…
Add table
Reference in a new issue