Skip to content

Commit d2e4039

Browse files
yp05327delvhwxiaoguanglunny
authored
Add member, collaborator, contributor, and first-time contributor roles and tooltips (#26658)
GitHub like role descriptor ![image](https://github.com/go-gitea/gitea/assets/18380374/ceaed92c-6749-47b3-89e8-0e0e7ae65321) ![image](https://github.com/go-gitea/gitea/assets/18380374/8193ec34-cbf0-47f9-b0de-10dbddd66970) ![image](https://github.com/go-gitea/gitea/assets/18380374/56c7ed85-6177-425e-9f2f-926e99770782) --------- Co-authored-by: delvh <[email protected]> Co-authored-by: wxiaoguang <[email protected]> Co-authored-by: Lunny Xiao <[email protected]>
1 parent 0d55f64 commit d2e4039

File tree

5 files changed

+97
-64
lines changed

5 files changed

+97
-64
lines changed

models/issues/comment.go

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"code.gitea.io/gitea/modules/references"
2424
"code.gitea.io/gitea/modules/structs"
2525
"code.gitea.io/gitea/modules/timeutil"
26+
"code.gitea.io/gitea/modules/translation"
2627
"code.gitea.io/gitea/modules/util"
2728

2829
"xorm.io/builder"
@@ -181,40 +182,32 @@ func (t CommentType) HasAttachmentSupport() bool {
181182
return false
182183
}
183184

184-
// RoleDescriptor defines comment tag type
185-
type RoleDescriptor int
185+
// RoleInRepo presents the user's participation in the repo
186+
type RoleInRepo string
187+
188+
// RoleDescriptor defines comment "role" tags
189+
type RoleDescriptor struct {
190+
IsPoster bool
191+
RoleInRepo RoleInRepo
192+
}
186193

187194
// Enumerate all the role tags.
188195
const (
189-
RoleDescriptorNone RoleDescriptor = iota
190-
RoleDescriptorPoster
191-
RoleDescriptorWriter
192-
RoleDescriptorOwner
196+
RoleRepoOwner RoleInRepo = "owner"
197+
RoleRepoMember RoleInRepo = "member"
198+
RoleRepoCollaborator RoleInRepo = "collaborator"
199+
RoleRepoFirstTimeContributor RoleInRepo = "first_time_contributor"
200+
RoleRepoContributor RoleInRepo = "contributor"
193201
)
194202

195-
// WithRole enable a specific tag on the RoleDescriptor.
196-
func (rd RoleDescriptor) WithRole(role RoleDescriptor) RoleDescriptor {
197-
return rd | (1 << role)
198-
}
199-
200-
func stringToRoleDescriptor(role string) RoleDescriptor {
201-
switch role {
202-
case "Poster":
203-
return RoleDescriptorPoster
204-
case "Writer":
205-
return RoleDescriptorWriter
206-
case "Owner":
207-
return RoleDescriptorOwner
208-
default:
209-
return RoleDescriptorNone
210-
}
203+
// LocaleString returns the locale string name of the role
204+
func (r RoleInRepo) LocaleString(lang translation.Locale) string {
205+
return lang.Tr("repo.issues.role." + string(r))
211206
}
212207

213-
// HasRole returns if a certain role is enabled on the RoleDescriptor.
214-
func (rd RoleDescriptor) HasRole(role string) bool {
215-
roleDescriptor := stringToRoleDescriptor(role)
216-
bitValue := rd & (1 << roleDescriptor)
217-
return (bitValue > 0)
208+
// LocaleHelper returns the locale tooltip of the role
209+
func (r RoleInRepo) LocaleHelper(lang translation.Locale) string {
210+
return lang.Tr("repo.issues.role." + string(r) + "_helper")
218211
}
219212

220213
// Comment represents a comment in commit and issue page.

models/issues/pull_list.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,16 @@ func (prs PullRequestList) GetIssueIDs() []int64 {
199199
}
200200
return issueIDs
201201
}
202+
203+
// HasMergedPullRequestInRepo returns whether the user(poster) has merged pull-request in the repo
204+
func HasMergedPullRequestInRepo(ctx context.Context, repoID, posterID int64) (bool, error) {
205+
return db.GetEngine(ctx).
206+
Join("INNER", "pull_request", "pull_request.issue_id = issue.id").
207+
Where("repo_id=?", repoID).
208+
And("poster_id=?", posterID).
209+
And("is_pull=?", true).
210+
And("pull_request.has_merged=?", true).
211+
Select("issue.id").
212+
Limit(1).
213+
Get(new(Issue))
214+
}

options/locale/locale_en-US.ini

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,9 +1480,18 @@ issues.ref_reopening_from = `<a href="%[3]s">referenced a pull request %[4]s tha
14801480
issues.ref_closed_from = `<a href="%[3]s">closed this issue %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
14811481
issues.ref_reopened_from = `<a href="%[3]s">reopened this issue %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
14821482
issues.ref_from = `from %[1]s`
1483-
issues.poster = Poster
1484-
issues.collaborator = Collaborator
1485-
issues.owner = Owner
1483+
issues.author = Author
1484+
issues.author_helper = This user is the author.
1485+
issues.role.owner = Owner
1486+
issues.role.owner_helper = This user is the owner of this repository.
1487+
issues.role.member = Member
1488+
issues.role.member_helper = This user is a member of the organization owning this repository.
1489+
issues.role.collaborator = Collaborator
1490+
issues.role.collaborator_helper = This user has been invited to collaborate on the repository.
1491+
issues.role.first_time_contributor = First-time contributor
1492+
issues.role.first_time_contributor_helper = This is the first contribution of this user to the repository.
1493+
issues.role.contributor = Contributor
1494+
issues.role.contributor_helper = This user has previously committed to the repository.
14861495
issues.re_request_review=Re-request review
14871496
issues.is_stale = There have been changes to this PR since this review
14881497
issues.remove_request_review=Remove review request

routers/web/repo/issue.go

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,47 +1228,70 @@ func NewIssuePost(ctx *context.Context) {
12281228
}
12291229
}
12301230

1231-
// roleDescriptor returns the Role Descriptor for a comment in/with the given repo, poster and issue
1231+
// roleDescriptor returns the role descriptor for a comment in/with the given repo, poster and issue
12321232
func roleDescriptor(ctx stdCtx.Context, repo *repo_model.Repository, poster *user_model.User, issue *issues_model.Issue, hasOriginalAuthor bool) (issues_model.RoleDescriptor, error) {
1233+
roleDescriptor := issues_model.RoleDescriptor{}
1234+
12331235
if hasOriginalAuthor {
1234-
return issues_model.RoleDescriptorNone, nil
1236+
return roleDescriptor, nil
12351237
}
12361238

12371239
perm, err := access_model.GetUserRepoPermission(ctx, repo, poster)
12381240
if err != nil {
1239-
return issues_model.RoleDescriptorNone, err
1241+
return roleDescriptor, err
12401242
}
12411243

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

12451247
// Check if the poster is owner of the repo.
12461248
if perm.IsOwner() {
1247-
// If the poster isn't a admin, enable the owner role.
1249+
// If the poster isn't an admin, enable the owner role.
12481250
if !poster.IsAdmin {
1249-
roleDescriptor = roleDescriptor.WithRole(issues_model.RoleDescriptorOwner)
1250-
} else {
1251+
roleDescriptor.RoleInRepo = issues_model.RoleRepoOwner
1252+
return roleDescriptor, nil
1253+
}
12511254

1252-
// Otherwise check if poster is the real repo admin.
1253-
ok, err := access_model.IsUserRealRepoAdmin(repo, poster)
1254-
if err != nil {
1255-
return issues_model.RoleDescriptorNone, err
1256-
}
1257-
if ok {
1258-
roleDescriptor = roleDescriptor.WithRole(issues_model.RoleDescriptorOwner)
1259-
}
1255+
// Otherwise check if poster is the real repo admin.
1256+
ok, err := access_model.IsUserRealRepoAdmin(repo, poster)
1257+
if err != nil {
1258+
return roleDescriptor, err
1259+
}
1260+
if ok {
1261+
roleDescriptor.RoleInRepo = issues_model.RoleRepoOwner
1262+
return roleDescriptor, nil
12601263
}
12611264
}
12621265

1263-
// Is the poster can write issues or pulls to the repo, enable the Writer role.
1264-
// Only enable this if the poster doesn't have the owner role already.
1265-
if !roleDescriptor.HasRole("Owner") && perm.CanWriteIssuesOrPulls(issue.IsPull) {
1266-
roleDescriptor = roleDescriptor.WithRole(issues_model.RoleDescriptorWriter)
1266+
// If repo is organization, check Member role
1267+
if err := repo.LoadOwner(ctx); err != nil {
1268+
return roleDescriptor, err
1269+
}
1270+
if repo.Owner.IsOrganization() {
1271+
if isMember, err := organization.IsOrganizationMember(ctx, repo.Owner.ID, poster.ID); err != nil {
1272+
return roleDescriptor, err
1273+
} else if isMember {
1274+
roleDescriptor.RoleInRepo = issues_model.RoleRepoMember
1275+
return roleDescriptor, nil
1276+
}
12671277
}
12681278

1269-
// If the poster is the actual poster of the issue, enable Poster role.
1270-
if issue.IsPoster(poster.ID) {
1271-
roleDescriptor = roleDescriptor.WithRole(issues_model.RoleDescriptorPoster)
1279+
// If the poster is the collaborator of the repo
1280+
if isCollaborator, err := repo_model.IsCollaborator(ctx, repo.ID, poster.ID); err != nil {
1281+
return roleDescriptor, err
1282+
} else if isCollaborator {
1283+
roleDescriptor.RoleInRepo = issues_model.RoleRepoCollaborator
1284+
return roleDescriptor, nil
1285+
}
1286+
1287+
hasMergedPR, err := issues_model.HasMergedPullRequestInRepo(ctx, repo.ID, poster.ID)
1288+
if err != nil {
1289+
return roleDescriptor, err
1290+
} else if hasMergedPR {
1291+
roleDescriptor.RoleInRepo = issues_model.RoleRepoContributor
1292+
} else {
1293+
// only display first time contributor in the first opening pull request
1294+
roleDescriptor.RoleInRepo = issues_model.RoleRepoFirstTimeContributor
12721295
}
12731296

12741297
return roleDescriptor, nil
Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
1-
{{if and (.ShowRole.HasRole "Poster") (not .IgnorePoster)}}
2-
<div class="ui basic label role-label">
3-
{{ctx.Locale.Tr "repo.issues.poster"}}
1+
{{if and .ShowRole.IsPoster (not .IgnorePoster)}}
2+
<div class="ui basic label role-label" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.author_helper"}}">
3+
{{ctx.Locale.Tr "repo.issues.author"}}
44
</div>
55
{{end}}
6-
{{if (.ShowRole.HasRole "Writer")}}
7-
<div class="ui basic label role-label">
8-
{{ctx.Locale.Tr "repo.issues.collaborator"}}
9-
</div>
10-
{{end}}
11-
{{if (.ShowRole.HasRole "Owner")}}
12-
<div class="ui basic label role-label">
13-
{{ctx.Locale.Tr "repo.issues.owner"}}
6+
{{if .ShowRole.RoleInRepo}}
7+
<div class="ui basic label role-label" data-tooltip-content="{{.ShowRole.RoleInRepo.LocaleHelper ctx.Locale}}">
8+
{{.ShowRole.RoleInRepo.LocaleString ctx.Locale}}
149
</div>
1510
{{end}}

0 commit comments

Comments
 (0)