Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions models/issues/comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/htmlutil"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/references"
Expand Down Expand Up @@ -233,11 +234,17 @@ func (r RoleInRepo) LocaleHelper(lang translation.Locale) string {
return lang.TrString("repo.issues.role." + string(r) + "_helper")
}

type SpecialDoerNameType string

const SpecialDoerNameCodeOwners SpecialDoerNameType = "CODEOWNERS"

// CommentMetaData stores metadata for a comment, these data will not be changed once inserted into database
type CommentMetaData struct {
ProjectColumnID int64 `json:"project_column_id,omitempty"`
ProjectColumnTitle string `json:"project_column_title,omitempty"`
ProjectTitle string `json:"project_title,omitempty"`

SpecialDoerName SpecialDoerNameType `json:"special_doer_name,omitempty"` // e.g. "CODEOWNERS" for CODEOWNERS-triggered review requests
}

// Comment represents a comment in commit and issue page.
Expand Down Expand Up @@ -764,6 +771,37 @@ func (c *Comment) CodeCommentLink(ctx context.Context) string {
return fmt.Sprintf("%s/files#%s", c.Issue.Link(), c.HashTag())
}

func (c *Comment) MetaSpecialDoerTr(locale translation.Locale) template.HTML {
if c.CommentMetaData == nil {
return ""
}
if c.CommentMetaData.SpecialDoerName == SpecialDoerNameCodeOwners {
return locale.Tr("repo.issues.review.codeowners_rules")
}
return htmlutil.HTMLFormat("%s", c.CommentMetaData.SpecialDoerName)
}

func (c *Comment) TimelineRequestedReviewTr(locale translation.Locale, createdStr template.HTML) template.HTML {
if c.AssigneeID > 0 {
// it guarantees LoadAssigneeUserAndTeam has been called, and c.Assignee is Ghost user but not nil if the user doesn't exist
if c.RemovedAssignee {
if c.PosterID == c.AssigneeID {
return locale.Tr("repo.issues.review.remove_review_request_self", createdStr)
}
return locale.Tr("repo.issues.review.remove_review_request", c.Assignee.GetDisplayName(), createdStr)
}
return locale.Tr("repo.issues.review.add_review_request", c.Assignee.GetDisplayName(), createdStr)
}
teamName := "Ghost Team"
if c.AssigneeTeam != nil {
teamName = c.AssigneeTeam.Name
}
if c.RemovedAssignee {
return locale.Tr("repo.issues.review.remove_review_request", teamName, createdStr)
}
return locale.Tr("repo.issues.review.add_review_request", teamName, createdStr)
}

// CreateComment creates comment with context
func CreateComment(ctx context.Context, opts *CreateCommentOptions) (_ *Comment, err error) {
return db.WithTx2(ctx, func(ctx context.Context) (*Comment, error) {
Expand All @@ -780,6 +818,11 @@ func CreateComment(ctx context.Context, opts *CreateCommentOptions) (_ *Comment,
ProjectTitle: opts.ProjectTitle,
}
}
if opts.SpecialDoerName != "" {
commentMetaData = &CommentMetaData{
SpecialDoerName: opts.SpecialDoerName,
}
}

comment := &Comment{
Type: opts.Type,
Expand Down Expand Up @@ -976,6 +1019,7 @@ type CreateCommentOptions struct {
RefIsPull bool
IsForcePush bool
Invalidated bool
SpecialDoerName SpecialDoerNameType // e.g. "CODEOWNERS" for CODEOWNERS-triggered review requests
}

// GetCommentByID returns the comment by given ID.
Expand Down
2 changes: 1 addition & 1 deletion models/issues/pull_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func TestLoadRequestedReviewers(t *testing.T) {
user1, err := user_model.GetUserByID(t.Context(), 1)
assert.NoError(t, err)

comment, err := issues_model.AddReviewRequest(t.Context(), issue, user1, &user_model.User{})
comment, err := issues_model.AddReviewRequest(t.Context(), issue, user1, &user_model.User{}, false)
assert.NoError(t, err)
assert.NotNil(t, comment)

Expand Down
6 changes: 4 additions & 2 deletions models/issues/review.go
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ func InsertReviews(ctx context.Context, reviews []*Review) error {
}

// AddReviewRequest add a review request from one reviewer
func AddReviewRequest(ctx context.Context, issue *Issue, reviewer, doer *user_model.User) (*Comment, error) {
func AddReviewRequest(ctx context.Context, issue *Issue, reviewer, doer *user_model.User, isCodeOwners bool) (*Comment, error) {
return db.WithTx2(ctx, func(ctx context.Context) (*Comment, error) {
sess := db.GetEngine(ctx)

Expand Down Expand Up @@ -702,6 +702,7 @@ func AddReviewRequest(ctx context.Context, issue *Issue, reviewer, doer *user_mo
RemovedAssignee: false, // Use RemovedAssignee as !isRequest
AssigneeID: reviewer.ID, // Use AssigneeID as reviewer ID
ReviewID: review.ID,
SpecialDoerName: util.Iif(isCodeOwners, SpecialDoerNameCodeOwners, ""),
})
if err != nil {
return nil, err
Expand Down Expand Up @@ -767,7 +768,7 @@ func restoreLatestOfficialReview(ctx context.Context, issueID, reviewerID int64)
}

// AddTeamReviewRequest add a review request from one team
func AddTeamReviewRequest(ctx context.Context, issue *Issue, reviewer *organization.Team, doer *user_model.User) (*Comment, error) {
func AddTeamReviewRequest(ctx context.Context, issue *Issue, reviewer *organization.Team, doer *user_model.User, isCodeOwners bool) (*Comment, error) {
return db.WithTx2(ctx, func(ctx context.Context) (*Comment, error) {
review, err := GetTeamReviewerByIssueIDAndTeamID(ctx, issue.ID, reviewer.ID)
if err != nil && !IsErrReviewNotExist(err) {
Expand Down Expand Up @@ -812,6 +813,7 @@ func AddTeamReviewRequest(ctx context.Context, issue *Issue, reviewer *organizat
RemovedAssignee: false, // Use RemovedAssignee as !isRequest
AssigneeTeamID: reviewer.ID, // Use AssigneeTeamID as reviewer team ID
ReviewID: review.ID,
SpecialDoerName: util.Iif(isCodeOwners, SpecialDoerNameCodeOwners, ""),
})
if err != nil {
return nil, fmt.Errorf("CreateComment(): %w", err)
Expand Down
18 changes: 16 additions & 2 deletions models/issues/review_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,14 +321,28 @@ func TestAddReviewRequest(t *testing.T) {
pull.HasMerged = false
assert.NoError(t, pull.UpdateCols(t.Context(), "has_merged"))
issue.IsClosed = true
_, err = issues_model.AddReviewRequest(t.Context(), issue, reviewer, &user_model.User{})
_, err = issues_model.AddReviewRequest(t.Context(), issue, reviewer, &user_model.User{}, false)
assert.Error(t, err)
assert.True(t, issues_model.IsErrReviewRequestOnClosedPR(err))

pull.HasMerged = true
assert.NoError(t, pull.UpdateCols(t.Context(), "has_merged"))
issue.IsClosed = false
_, err = issues_model.AddReviewRequest(t.Context(), issue, reviewer, &user_model.User{})
_, err = issues_model.AddReviewRequest(t.Context(), issue, reviewer, &user_model.User{}, false)
assert.Error(t, err)
assert.True(t, issues_model.IsErrReviewRequestOnClosedPR(err))

// Test CODEOWNERS review request stores metadata correctly
pull2 := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2})
assert.NoError(t, pull2.LoadIssue(t.Context()))
issue2 := pull2.Issue
assert.NoError(t, issue2.LoadRepo(t.Context()))
reviewer2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 7})
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})

comment, err := issues_model.AddReviewRequest(t.Context(), issue2, reviewer2, doer, true)
assert.NoError(t, err)
assert.NotNil(t, comment)
assert.NotNil(t, comment.CommentMetaData)
assert.Equal(t, issues_model.SpecialDoerNameCodeOwners, comment.CommentMetaData.SpecialDoerName)
}
1 change: 1 addition & 0 deletions options/locale/locale_en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -1702,6 +1702,7 @@
"repo.issues.review.content.empty": "You need to leave a comment indicating the requested change(s).",
"repo.issues.review.reject": "requested changes %s",
"repo.issues.review.wait": "was requested for review %s",
"repo.issues.review.codeowners_rules": "CODEOWNERS rules",
"repo.issues.review.add_review_request": "requested review from %s %s",
"repo.issues.review.remove_review_request": "removed review request for %s %s",
"repo.issues.review.remove_review_request_self": "declined to review %s",
Expand Down
4 changes: 2 additions & 2 deletions services/issue/assignee.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func ReviewRequest(ctx context.Context, issue *issues_model.Issue, doer *user_mo
}

if isAdd {
comment, err = issues_model.AddReviewRequest(ctx, issue, reviewer, doer)
comment, err = issues_model.AddReviewRequest(ctx, issue, reviewer, doer, false)
} else {
comment, err = issues_model.RemoveReviewRequest(ctx, issue, reviewer, doer)
}
Expand Down Expand Up @@ -224,7 +224,7 @@ func TeamReviewRequest(ctx context.Context, issue *issues_model.Issue, doer *use
return nil, err
}
if isAdd {
comment, err = issues_model.AddTeamReviewRequest(ctx, issue, reviewer, doer)
comment, err = issues_model.AddTeamReviewRequest(ctx, issue, reviewer, doer, false)
} else {
comment, err = issues_model.RemoveTeamReviewRequest(ctx, issue, reviewer, doer)
}
Expand Down
4 changes: 2 additions & 2 deletions services/issue/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ func PullRequestCodeOwnersReview(ctx context.Context, pr *issues_model.PullReque

for _, u := range uniqUsers {
if u.ID != issue.Poster.ID && !contain(latestReivews, u) {
comment, err := issues_model.AddReviewRequest(ctx, issue, u, issue.Poster)
comment, err := issues_model.AddReviewRequest(ctx, issue, u, issue.Poster, true)
if err != nil {
log.Warn("Failed add assignee user: %s to PR review: %s#%d, error: %s", u.Name, pr.BaseRepo.Name, pr.ID, err)
return nil, err
Expand All @@ -166,7 +166,7 @@ func PullRequestCodeOwnersReview(ctx context.Context, pr *issues_model.PullReque
}

for _, t := range uniqTeams {
comment, err := issues_model.AddTeamReviewRequest(ctx, issue, t, issue.Poster)
comment, err := issues_model.AddTeamReviewRequest(ctx, issue, t, issue.Poster, true)
if err != nil {
log.Warn("Failed add assignee team: %s to PR review: %s#%d, error: %s", t.Name, pr.BaseRepo.Name, pr.ID, err)
return nil, err
Expand Down
4 changes: 2 additions & 2 deletions templates/repo/graph/commits.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@
{{end}}
</span>

<span class="author flex-text-inline">
<span class="flex-text-inline tw-text-12">
{{$userName := $commit.Commit.Author.Name}}
{{if $commit.User}}
{{if and $commit.User.FullName DefaultShowFullName}}
{{$userName = $commit.User.FullName}}
{{end}}
{{ctx.AvatarUtils.Avatar $commit.User 18}}
<a href="{{$commit.User.HomeLink}}">{{$userName}}</a>
<a class="muted" href="{{$commit.User.HomeLink}}">{{$userName}}</a>
{{else}}
{{ctx.AvatarUtils.AvatarByEmail $commit.Commit.Author.Email $userName 18}}
{{$userName}}
Expand Down
40 changes: 14 additions & 26 deletions templates/repo/issue/view_content/comments.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -514,32 +514,20 @@
{{else if eq .Type 27}}
<div class="timeline-item event" id="{{.HashTag}}">
<span class="badge">{{svg "octicon-eye"}}</span>
{{template "shared/user/avatarlink" dict "user" .Poster}}
<span class="comment-text-line">
{{template "shared/user/authorlink" .Poster}}
{{if (gt .AssigneeID 0)}}
{{if .RemovedAssignee}}
{{if eq .PosterID .AssigneeID}}
{{ctx.Locale.Tr "repo.issues.review.remove_review_request_self" $createdStr}}
{{else}}
{{ctx.Locale.Tr "repo.issues.review.remove_review_request" .Assignee.GetDisplayName $createdStr}}
{{end}}
{{else}}
{{ctx.Locale.Tr "repo.issues.review.add_review_request" .Assignee.GetDisplayName $createdStr}}
{{end}}
{{else}}
<!-- If the assigned team is deleted, just displaying "Ghost Team" in the comment -->
{{$teamName := "Ghost Team"}}
{{if .AssigneeTeam}}
{{$teamName = .AssigneeTeam.Name}}
{{end}}
{{if .RemovedAssignee}}
{{ctx.Locale.Tr "repo.issues.review.remove_review_request" $teamName $createdStr}}
{{else}}
{{ctx.Locale.Tr "repo.issues.review.add_review_request" $teamName $createdStr}}
{{end}}
{{end}}
</span>
{{$specialDoerHtml := .MetaSpecialDoerTr ctx.Locale}}
{{$timelineRequestedReviewHtml := .TimelineRequestedReviewTr ctx.Locale $createdStr}}
{{if $specialDoerHtml}}
<span class="comment-text-line">
{{$specialDoerHtml}}
{{$timelineRequestedReviewHtml}}
</span>
{{else}}
{{template "shared/user/avatarlink" dict "user" .Poster}}
<span class="comment-text-line">
{{template "shared/user/authorlink" .Poster}}
{{$timelineRequestedReviewHtml}}
</span>
{{end}}
</div>
{{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. //-->
Expand Down
2 changes: 1 addition & 1 deletion templates/shared/user/authorlink.tmpl
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<a class="author text black tw-font-semibold muted"{{if gt .ID 0}} href="{{.HomeLink}}"{{end}}>{{.GetDisplayName}}</a>{{if .IsTypeBot}}<span class="ui basic label tw-p-1 tw-align-baseline">bot</span>{{end}}
<a class="muted text black tw-font-semibold"{{if gt .ID 0}} href="{{.HomeLink}}"{{end}}>{{.GetDisplayName}}</a>{{if .IsTypeBot}}<span class="ui basic label tw-p-1 tw-align-baseline">bot</span>{{end}}
2 changes: 1 addition & 1 deletion templates/shared/user/avatarlink.tmpl
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<a class="avatar-with-link" {{if gt .user.ID 0}}href="{{.user.HomeLink}}"{{end}}>{{ctx.AvatarUtils.Avatar .user}}</a>
<a class="avatar-with-link" {{if gt .user.ID 0}}href="{{.user.HomeLink}}"{{end}}>{{ctx.AvatarUtils.Avatar .user (or .size 20)}}</a>
14 changes: 1 addition & 13 deletions web_src/css/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -469,19 +469,6 @@ a.label,
box-shadow: 1px 1px 0 0 var(--color-secondary);
}

.ui.comments .comment .text {
margin: 0;
}

.ui.comments .comment .text,
.ui.comments .comment .author {
color: var(--color-text);
}

.ui.comments .comment a.author:hover {
color: var(--color-primary);
}

.ui.comments .comment .metadata {
color: var(--color-text-light-2);
}
Expand Down Expand Up @@ -562,6 +549,7 @@ img.ui.avatar,
color: var(--color-purple) !important;
}

/* it is different from tw-text-black: this one changes in dark theme */
.text.black {
color: var(--color-text) !important;
}
Expand Down
4 changes: 0 additions & 4 deletions web_src/css/features/gitgraph.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@
height: 20px;
}

#git-graph-container li .author {
color: var(--color-text-light);
}

#git-graph-container li .time {
color: var(--color-text-light-3);
font-size: 80%;
Expand Down
9 changes: 0 additions & 9 deletions web_src/css/modules/comment.css
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,6 @@
min-width: 0;
}

.ui.comments .comment .author {
font-size: 1em;
font-weight: var(--font-weight-medium);
}

.ui.comments .comment a.author {
cursor: pointer;
}

.ui.comments .comment .metadata {
display: inline-block;
margin-left: 0.5em;
Expand Down