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:
parent
a4dc0c5a82
commit
492e1c2fbd
|
@ -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 (
|
||||||
|
|
|
@ -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"`
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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}}
|
||||||
|
|
|
@ -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">
|
||||||
|
|
Loading…
Reference in a new issue