Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add member, collaborator, contributor, and first-time contributor roles and tooltips #26658

Merged
merged 24 commits into from Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 21 additions & 24 deletions models/issues/comment.go
Expand Up @@ -23,6 +23,7 @@
"code.gitea.io/gitea/modules/references"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/util"

"xorm.io/builder"
Expand Down Expand Up @@ -181,40 +182,36 @@
return false
}

type Role string

// RoleDescriptor defines comment tag type
type RoleDescriptor int
type RoleDescriptor struct {
IsPoster bool
Role Role
}

// Enumerate all the role tags.
const (
RoleDescriptorNone RoleDescriptor = iota
RoleDescriptorPoster
RoleDescriptorWriter
RoleDescriptorOwner
RoleDescriptorOwner Role = "owner"
RoleDescriptorMember Role = "member"
RoleDescriptorCollaborator Role = "collaborator"
RoleDescriptorFirstTimeContributor Role = "first_time_contributor"
RoleDescriptorContributor Role = "contributor"
)

// WithRole enable a specific tag on the RoleDescriptor.
func (rd RoleDescriptor) WithRole(role RoleDescriptor) RoleDescriptor {
return rd | (1 << role)
// HasRole returns if a role is not none
func (r Role) HasRole() bool {
return r.Role != ""

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / backend

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-mysql8

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-sqlite

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-mysql5

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-pgsql

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-unit

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-mssql

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / checks-backend

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-e2e

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-windows

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-windows

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-windows

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-backend

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-backend

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-backend

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-gogit

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-gogit

r.Role undefined (type Role has no field or method Role)

Check failure on line 204 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-gogit

r.Role undefined (type Role has no field or method Role)
wxiaoguang marked this conversation as resolved.
Show resolved Hide resolved
}

func stringToRoleDescriptor(role string) RoleDescriptor {
switch role {
case "Poster":
return RoleDescriptorPoster
case "Writer":
return RoleDescriptorWriter
case "Owner":
return RoleDescriptorOwner
default:
return RoleDescriptorNone
}
// LocaleString returns the locale string name of the Status
func (r Role) LocaleString(lang translation.Locale) string {
return lang.Tr("repo.issues.role." + r.Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / backend

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-mysql8

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-sqlite

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-mysql5

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-pgsql

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-unit

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-mssql

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / checks-backend

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-e2e

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-windows

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-windows

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-windows

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-backend

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-backend

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-backend

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-gogit

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-gogit

r.Role undefined (type Role has no field or method Role)

Check failure on line 209 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-gogit

r.Role undefined (type Role has no field or method Role)
}

// 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)
// LocaleHelper returns the locale string name of the Status
func (r Role) LocaleHelper(lang translation.Locale) string {
return lang.Tr("repo.issues.role." + r.Role + "_helper")

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / backend

r.Role undefined (type Role has no field or method Role)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-mysql8

r.Role undefined (type Role has no field or method Role)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-sqlite

r.Role undefined (type Role has no field or method Role)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-mysql5

r.Role undefined (type Role has no field or method Role)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-pgsql

r.Role undefined (type Role has no field or method Role)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-unit

r.Role undefined (type Role has no field or method Role)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-mssql

r.Role undefined (type Role has no field or method Role)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / checks-backend

r.Role undefined (type Role has no field or method Role)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / test-e2e

r.Role undefined (type Role has no field or method Role)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-windows

r.Role undefined (type Role has no field or method Role) (typecheck)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-windows

r.Role undefined (type Role has no field or method Role)) (typecheck)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-backend

r.Role undefined (type Role has no field or method Role) (typecheck)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-backend

r.Role undefined (type Role has no field or method Role)) (typecheck)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-gogit

r.Role undefined (type Role has no field or method Role) (typecheck)

Check failure on line 214 in models/issues/comment.go

View workflow job for this annotation

GitHub Actions / lint-go-gogit

r.Role undefined (type Role has no field or method Role)) (typecheck)
}

// Comment represents a comment in commit and issue page.
Expand Down
15 changes: 12 additions & 3 deletions options/locale/locale_en-US.ini
Expand Up @@ -1480,9 +1480,18 @@ issues.ref_reopening_from = `<a href="%[3]s">referenced a pull request %[4]s tha
issues.ref_closed_from = `<a href="%[3]s">closed this issue %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_reopened_from = `<a href="%[3]s">reopened this issue %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_from = `from %[1]s`
issues.poster = Poster
issues.collaborator = Collaborator
issues.owner = Owner
issues.author = Author
issues.author_helper = This user is the author.
Comment on lines +1483 to +1484
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we even assign author?
I haven't found it inside roleDescriptor

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Gitea, it is called poster.

issues.role.owner = Owner
issues.role.owner_helper = This user is the owner of this repository.
issues.role.member = Member
issues.role.member_helper = This user is a member of the organization owning this repository.
issues.role.collaborator = Collaborator
issues.role.collaborator_helper = This user has been invited to collaborate on the repository.
issues.role.first_time_contributor = First-time contributor
issues.role.first_time_contributor_helper = This is the first contribution of this user to the repository.
issues.role.contributor = Contributor
issues.role.contributor_helper = This user has previously committed to the repository.
issues.re_request_review=Re-request review
issues.is_stale = There have been changes to this PR since this review
issues.remove_request_review=Remove review request
Expand Down
75 changes: 54 additions & 21 deletions routers/web/repo/issue.go
Expand Up @@ -1230,45 +1230,78 @@ func NewIssuePost(ctx *context.Context) {

// roleDescriptor returns the Role Descriptor for a comment in/with the given repo, poster and issue
func roleDescriptor(ctx stdCtx.Context, repo *repo_model.Repository, poster *user_model.User, issue *issues_model.Issue, hasOriginalAuthor bool) (issues_model.RoleDescriptor, error) {
roleDescriptor := issues_model.RoleDescriptor{}

if hasOriginalAuthor {
return issues_model.RoleDescriptorNone, nil
return roleDescriptor, nil
}

perm, err := access_model.GetUserRepoPermission(ctx, repo, poster)
if err != nil {
return issues_model.RoleDescriptorNone, err
return roleDescriptor, err
}

// By default the poster has no roles on the comment.
roleDescriptor := issues_model.RoleDescriptorNone
// If the poster is the actual poster of the issue, enable Poster role.
roleDescriptor.IsPoster = issue.IsPoster(poster.ID)

// Check if the poster is owner of the repo.
if perm.IsOwner() {
// If the poster isn't a admin, enable the owner role.
if !poster.IsAdmin {
roleDescriptor = roleDescriptor.WithRole(issues_model.RoleDescriptorOwner)
} else {
roleDescriptor.Role = issues_model.RoleDescriptorOwner
return roleDescriptor, nil
}

// Otherwise check if poster is the real repo admin.
ok, err := access_model.IsUserRealRepoAdmin(repo, poster)
if err != nil {
return issues_model.RoleDescriptorNone, err
}
if ok {
roleDescriptor = roleDescriptor.WithRole(issues_model.RoleDescriptorOwner)
}
// Otherwise check if poster is the real repo admin.
ok, err := access_model.IsUserRealRepoAdmin(repo, poster)
if err != nil {
return roleDescriptor, err
}
if ok {
roleDescriptor.Role = issues_model.RoleDescriptorOwner
return roleDescriptor, nil
}
}

// Is the poster can write issues or pulls to the repo, enable the Writer role.
// Only enable this if the poster doesn't have the owner role already.
if !roleDescriptor.HasRole("Owner") && perm.CanWriteIssuesOrPulls(issue.IsPull) {
roleDescriptor = roleDescriptor.WithRole(issues_model.RoleDescriptorWriter)
// If repo is organization, check Member role
if err := repo.LoadOwner(ctx); err != nil {
return roleDescriptor, err
}
if repo.Owner.IsOrganization() {
if isMember, err := organization.IsOrganizationMember(ctx, repo.Owner.ID, poster.ID); err != nil {
return roleDescriptor, err
} else if isMember {
roleDescriptor.Role = issues_model.RoleDescriptorMember
return roleDescriptor, nil
}
}

// If the poster is the actual poster of the issue, enable Poster role.
if issue.IsPoster(poster.ID) {
roleDescriptor = roleDescriptor.WithRole(issues_model.RoleDescriptorPoster)
// If the poster is the collaborator of the repo
if isCollaborator, err := repo_model.IsCollaborator(ctx, repo.ID, poster.ID); err != nil {
return roleDescriptor, err
} else if isCollaborator {
roleDescriptor.Role = issues_model.RoleDescriptorCollaborator
return roleDescriptor, nil
}

// If the poster is the contributor of the repo
searchOpt := &issue_indexer.SearchOptions{
Paginator: &db.ListOptions{
Page: 1,
PageSize: 1,
},
RepoIDs: []int64{repo.ID},
IsClosed: util.OptionalBoolTrue,
wxiaoguang marked this conversation as resolved.
Show resolved Hide resolved
IsPull: util.OptionalBoolTrue,
PosterID: &poster.ID,
}
if _, total, err := issue_indexer.SearchIssues(ctx, searchOpt); err != nil {
return roleDescriptor, err
} else if total > 0 {
roleDescriptor.Role = issues_model.RoleDescriptorContributor
} else if total == 0 && issue.IsPull && !issue.IsClosed {
// only display first time contributor in the first opening pull request
roleDescriptor.Role = issues_model.RoleDescriptorFirstTimeContributor
}

return roleDescriptor, nil
Expand Down
18 changes: 7 additions & 11 deletions templates/repo/issue/view_content/show_role.tmpl
@@ -1,15 +1,11 @@
{{if and (.ShowRole.HasRole "Poster") (not .IgnorePoster)}}
<div class="ui basic label role-label">
{{ctx.Locale.Tr "repo.issues.poster"}}
{{if and .ShowRole.IsPoster (not .IgnorePoster)}}
<div class="ui basic label role-label" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.author_helper"}}">
{{ctx.Locale.Tr "repo.issues.author"}}
</div>
{{end}}
{{if (.ShowRole.HasRole "Writer")}}
<div class="ui basic label role-label">
{{ctx.Locale.Tr "repo.issues.collaborator"}}
</div>
{{end}}
{{if (.ShowRole.HasRole "Owner")}}
<div class="ui basic label role-label">
{{ctx.Locale.Tr "repo.issues.owner"}}

{{if (.ShowRole.Role.HasRole)}}
<div class="ui basic label role-label" data-tooltip-content="{{.ShowRole.Role.LocaleHelper ctx.Locale}}">
{{.ShowRole.Role.LocaleString ctx.Locale}}
</div>
{{end}}