1
0
Fork 0

Refactor commentTags functionality (#17558)

* feat: Allow multiple tags on comments

- Allow for multiples tags(Currently Poster + {Owner, Writer}).
- Utilize the Poster tag within the commentTag function and remove the
checking from templates.
- Use bitwise on CommentTags to enable specific tags.
- Don't show poster tag(view_content.tmpl) on the initial issue comment.

* Change parameters naming

* Change function name

* refactor variable wording

* Merge 'master' branch into 'tags-comments' branch

* Change naming

* `tag` -> `role`

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
Gusted 2021-11-11 07:29:30 +01:00 committed by GitHub
parent a4dc0c5a82
commit 492e1c2fbd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 112 additions and 75 deletions

View file

@ -71,7 +71,7 @@ type Issue struct {
IsLocked bool `xorm:"NOT NULL DEFAULT false"` IsLocked bool `xorm:"NOT NULL DEFAULT false"`
// For view issue page. // For view issue page.
ShowTag CommentTag `xorm:"-"` ShowRole RoleDescriptor `xorm:"-"`
} }
var ( var (

View file

@ -105,17 +105,43 @@ const (
CommentTypeDismissReview CommentTypeDismissReview
) )
// CommentTag defines comment tag type // RoleDescriptor defines comment tag type
type CommentTag int type RoleDescriptor int
// Enumerate all the comment tag types // Enumerate all the role tags.
const ( const (
CommentTagNone CommentTag = iota RoleDescriptorNone RoleDescriptor = iota
CommentTagPoster RoleDescriptorPoster
CommentTagWriter RoleDescriptorWriter
CommentTagOwner RoleDescriptorOwner
) )
// WithRole enable a specific tag on the RoleDescriptor.
func (rd RoleDescriptor) WithRole(role RoleDescriptor) RoleDescriptor {
rd |= (1 << role)
return rd
}
func stringToRoleDescriptor(role string) RoleDescriptor {
switch role {
case "Poster":
return RoleDescriptorPoster
case "Writer":
return RoleDescriptorWriter
case "Owner":
return RoleDescriptorOwner
default:
return RoleDescriptorNone
}
}
// HasRole returns if a certain role is enabled on the RoleDescriptor.
func (rd RoleDescriptor) HasRole(role string) bool {
roleDescriptor := stringToRoleDescriptor(role)
bitValue := rd & (1 << roleDescriptor)
return (bitValue > 0)
}
// Comment represents a comment in commit and issue page. // Comment represents a comment in commit and issue page.
type Comment struct { type Comment struct {
ID int64 `xorm:"pk autoincr"` ID int64 `xorm:"pk autoincr"`
@ -174,7 +200,7 @@ type Comment struct {
Reactions ReactionList `xorm:"-"` Reactions ReactionList `xorm:"-"`
// For view issue page. // For view issue page.
ShowTag CommentTag `xorm:"-"` ShowRole RoleDescriptor `xorm:"-"`
Review *Review `xorm:"-"` Review *Review `xorm:"-"`
ReviewID int64 `xorm:"index"` ReviewID int64 `xorm:"index"`

View file

@ -1015,38 +1015,46 @@ func NewIssuePost(ctx *context.Context) {
} }
} }
// commentTag returns the CommentTag for a comment in/with the given repo, poster and issue // roleDescriptor returns the Role Decriptor for a comment in/with the given repo, poster and issue
func commentTag(repo *models.Repository, poster *models.User, issue *models.Issue) (models.CommentTag, error) { func roleDescriptor(repo *models.Repository, poster *models.User, issue *models.Issue) (models.RoleDescriptor, error) {
perm, err := models.GetUserRepoPermission(repo, poster) perm, err := models.GetUserRepoPermission(repo, poster)
if err != nil { if err != nil {
return models.CommentTagNone, err return models.RoleDescriptorNone, err
} }
// By default the poster has no roles on the comment.
roleDescriptor := models.RoleDescriptorNone
// Check if the poster is owner of the repo.
if perm.IsOwner() { if perm.IsOwner() {
// If the poster isn't a admin, enable the owner role.
if !poster.IsAdmin { if !poster.IsAdmin {
return models.CommentTagOwner, nil roleDescriptor = roleDescriptor.WithRole(models.RoleDescriptorOwner)
} } else {
ok, err := models.IsUserRealRepoAdmin(repo, poster) // Otherwise check if poster is the real repo admin.
if err != nil { ok, err := models.IsUserRealRepoAdmin(repo, poster)
return models.CommentTagNone, err if err != nil {
return models.RoleDescriptorNone, err
}
if ok {
roleDescriptor = roleDescriptor.WithRole(models.RoleDescriptorOwner)
}
} }
if ok {
return models.CommentTagOwner, nil
}
if ok, err = repo.IsCollaborator(poster.ID); ok && err == nil {
return models.CommentTagWriter, nil
}
return models.CommentTagNone, err
} }
if perm.CanWriteIssuesOrPulls(issue.IsPull) { // Is the poster can write issues or pulls to the repo, enable the Writer role.
return models.CommentTagWriter, nil // Only enable this if the poster doesn't have the owner role already.
if !roleDescriptor.HasRole("Owner") && perm.CanWriteIssuesOrPulls(issue.IsPull) {
roleDescriptor = roleDescriptor.WithRole(models.RoleDescriptorWriter)
} }
return models.CommentTagNone, nil // If the poster is the actual poster of the issue, enable Poster role.
if issue.IsPoster(poster.ID) {
roleDescriptor = roleDescriptor.WithRole(models.RoleDescriptorPoster)
}
return roleDescriptor, nil
} }
func getBranchData(ctx *context.Context, issue *models.Issue) { func getBranchData(ctx *context.Context, issue *models.Issue) {
@ -1249,9 +1257,9 @@ func ViewIssue(ctx *context.Context) {
} }
var ( var (
tag models.CommentTag role models.RoleDescriptor
ok bool ok bool
marked = make(map[int64]models.CommentTag) marked = make(map[int64]models.RoleDescriptor)
comment *models.Comment comment *models.Comment
participants = make([]*models.User, 1, 10) participants = make([]*models.User, 1, 10)
) )
@ -1298,11 +1306,11 @@ func ViewIssue(ctx *context.Context) {
// check if dependencies can be created across repositories // check if dependencies can be created across repositories
ctx.Data["AllowCrossRepositoryDependencies"] = setting.Service.AllowCrossRepositoryDependencies ctx.Data["AllowCrossRepositoryDependencies"] = setting.Service.AllowCrossRepositoryDependencies
if issue.ShowTag, err = commentTag(repo, issue.Poster, issue); err != nil { if issue.ShowRole, err = roleDescriptor(repo, issue.Poster, issue); err != nil {
ctx.ServerError("commentTag", err) ctx.ServerError("roleDescriptor", err)
return return
} }
marked[issue.PosterID] = issue.ShowTag marked[issue.PosterID] = issue.ShowRole
// Render comments and and fetch participants. // Render comments and and fetch participants.
participants[0] = issue.Poster participants[0] = issue.Poster
@ -1331,18 +1339,18 @@ func ViewIssue(ctx *context.Context) {
return return
} }
// Check tag. // Check tag.
tag, ok = marked[comment.PosterID] role, ok = marked[comment.PosterID]
if ok { if ok {
comment.ShowTag = tag comment.ShowRole = role
continue continue
} }
comment.ShowTag, err = commentTag(repo, comment.Poster, issue) comment.ShowRole, err = roleDescriptor(repo, comment.Poster, issue)
if err != nil { if err != nil {
ctx.ServerError("commentTag", err) ctx.ServerError("roleDescriptor", err)
return return
} }
marked[comment.PosterID] = comment.ShowTag marked[comment.PosterID] = comment.ShowRole
participants = addParticipant(comment.Poster, participants) participants = addParticipant(comment.Poster, participants)
} else if comment.Type == models.CommentTypeLabel { } else if comment.Type == models.CommentTypeLabel {
if err = comment.LoadLabel(); err != nil { if err = comment.LoadLabel(); err != nil {
@ -1430,18 +1438,18 @@ func ViewIssue(ctx *context.Context) {
for _, lineComments := range codeComments { for _, lineComments := range codeComments {
for _, c := range lineComments { for _, c := range lineComments {
// Check tag. // Check tag.
tag, ok = marked[c.PosterID] role, ok = marked[c.PosterID]
if ok { if ok {
c.ShowTag = tag c.ShowRole = role
continue continue
} }
c.ShowTag, err = commentTag(repo, c.Poster, issue) c.ShowRole, err = roleDescriptor(repo, c.Poster, issue)
if err != nil { if err != nil {
ctx.ServerError("commentTag", err) ctx.ServerError("roleDescriptor", err)
return return
} }
marked[c.PosterID] = c.ShowTag marked[c.PosterID] = c.ShowRole
participants = addParticipant(c.Poster, participants) participants = addParticipant(c.Poster, participants)
} }
} }

View file

@ -49,14 +49,17 @@
</div> </div>
<div class="comment-header-right actions df ac"> <div class="comment-header-right actions df ac">
{{if not $.Repository.IsArchived}} {{if not $.Repository.IsArchived}}
{{if gt .Issue.ShowTag 0}} {{if gt .Issue.ShowRole 0}}
<div class="ui basic label"> {{if (.Issue.ShowRole.HasRole "Writer")}}
{{if eq .Issue.ShowTag 2}} <div class="ui basic label">
{{$.i18n.Tr "repo.issues.collaborator"}} {{$.i18n.Tr "repo.issues.collaborator"}}
{{else if eq .Issue.ShowTag 3}} </div>
{{end}}
{{if (.Issue.ShowRole.HasRole "Owner")}}
<div class="ui basic label">
{{$.i18n.Tr "repo.issues.owner"}} {{$.i18n.Tr "repo.issues.owner"}}
{{end}} </div>
</div> {{end}}
{{end}} {{end}}
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index)}} {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index)}}
{{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" .Issue "delete" false "issue" true "diff" false "IsCommentPoster" $.IsIssuePoster}} {{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" .Issue "delete" false "issue" true "diff" false "IsCommentPoster" $.IsIssuePoster}}

View file

@ -44,18 +44,19 @@
</div> </div>
<div class="comment-header-right actions df ac"> <div class="comment-header-right actions df ac">
{{if not $.Repository.IsArchived}} {{if not $.Repository.IsArchived}}
{{if or (and (eq .PosterID .Issue.PosterID) (eq .Issue.OriginalAuthorID 0)) (and (eq .Issue.OriginalAuthorID .OriginalAuthorID) (not (eq .OriginalAuthorID 0))) }} {{if (.ShowRole.HasRole "Poster")}}
<div class="ui basic label"> <div class="ui basic label">
{{$.i18n.Tr "repo.issues.poster"}} {{$.i18n.Tr "repo.issues.poster"}}
</div> </div>
{{end}} {{end}}
{{if gt .ShowTag 0}} {{if (.ShowRole.HasRole "Writer")}}
<div class="ui basic label"> <div class="ui basic label">
{{if eq .ShowTag 2}} {{$.i18n.Tr "repo.issues.collaborator"}}
{{$.i18n.Tr "repo.issues.collaborator"}} </div>
{{else if eq .ShowTag 3}} {{end}}
{{$.i18n.Tr "repo.issues.owner"}} {{if (.ShowRole.HasRole "Owner")}}
{{end}} <div class="ui basic label">
{{$.i18n.Tr "repo.issues.owner"}}
</div> </div>
{{end}} {{end}}
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}} {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
@ -549,24 +550,23 @@
</span> </span>
</div> </div>
<div class="comment-header-right actions df ac"> <div class="comment-header-right actions df ac">
{{if not $.Repository.IsArchived}} {{if (.ShowRole.HasRole "Poster")}}
{{if or (and (eq .PosterID $.Issue.PosterID) (eq $.Issue.OriginalAuthorID 0)) (eq $.Issue.OriginalAuthorID .OriginalAuthorID) }} <div class="ui basic label">
<div class="ui basic label"> {{$.i18n.Tr "repo.issues.poster"}}
{{$.i18n.Tr "repo.issues.poster"}} </div>
</div>
{{end}}
{{if gt .ShowTag 0}}
<div class="ui basic label">
{{if eq .ShowTag 2}}
{{$.i18n.Tr "repo.issues.collaborator"}}
{{else if eq .ShowTag 3}}
{{$.i18n.Tr "repo.issues.owner"}}
{{end}}
</div>
{{end}}
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
{{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" . "delete" true "issue" true "diff" true "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
{{end}} {{end}}
{{if (.ShowRole.HasRole "Writer")}}
<div class="ui basic label">
{{$.i18n.Tr "repo.issues.collaborator"}}
</div>
{{end}}
{{if (.ShowRole.HasRole "Owner")}}
<div class="ui basic label">
{{$.i18n.Tr "repo.issues.owner"}}
</div>
{{end}}
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
{{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" . "delete" true "issue" true "diff" true "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
</div> </div>
</div> </div>
<div class="text comment-content"> <div class="text comment-content">