Skip to content

Commit d8e6c99

Browse files
techknowlogicksilverwindzeripathjolheiser
authored
Add badge capabilities to users (#20607)
Co-authored-by: silverwind <[email protected]> Co-authored-by: zeripath <[email protected]> Co-authored-by: John Olheiser <[email protected]>
1 parent 208b4ee commit d8e6c99

File tree

8 files changed

+105
-0
lines changed

8 files changed

+105
-0
lines changed

Diff for: .golangci.yml

+4
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,7 @@ issues:
171171
- path: models/user/openid.go
172172
linters:
173173
- golint
174+
- path: models/user/badge.go
175+
linters:
176+
- revive
177+
text: "exported: type name will be used as user.UserBadge by other packages, and that stutters; consider calling this Badge"

Diff for: models/migrations/migrations.go

+3
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,9 @@ var migrations = []Migration{
406406
NewMigration("Drop old CredentialID column", dropOldCredentialIDColumn),
407407
// v223 -> v224
408408
NewMigration("Rename CredentialIDBytes column to CredentialID", renameCredentialIDBytes),
409+
410+
// v999
411+
NewMigration("Add badges to users", creatUserBadgesTable),
409412
}
410413

411414
// GetCurrentDBVersion returns the current db version

Diff for: models/migrations/v999.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"xorm.io/xorm"
9+
)
10+
11+
func creatUserBadgesTable(x *xorm.Engine) error {
12+
type Badge struct {
13+
ID int64 `xorm:"pk autoincr"`
14+
Description string
15+
ImageURL string
16+
}
17+
18+
type userBadge struct {
19+
ID int64 `xorm:"pk autoincr"`
20+
BadgeID int64
21+
UserID int64 `xorm:"INDEX"`
22+
}
23+
24+
if err := x.Sync2(new(Badge)); err != nil {
25+
return err
26+
}
27+
return x.Sync2(new(userBadge))
28+
}

Diff for: models/user.go

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
8585
&organization.TeamUser{UID: u.ID},
8686
&issues_model.Stopwatch{UserID: u.ID},
8787
&user_model.Setting{UserID: u.ID},
88+
&user_model.UserBadge{UserID: u.ID},
8889
&pull_model.AutoMerge{DoerID: u.ID},
8990
&pull_model.ReviewState{UserID: u.ID},
9091
); err != nil {

Diff for: models/user/badge.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package user
6+
7+
import (
8+
"context"
9+
10+
"code.gitea.io/gitea/models/db"
11+
)
12+
13+
// Badge represents a user badge
14+
type Badge struct {
15+
ID int64 `xorm:"pk autoincr"`
16+
Description string
17+
ImageURL string
18+
}
19+
20+
// UserBadge represents a user badge
21+
type UserBadge struct {
22+
ID int64 `xorm:"pk autoincr"`
23+
BadgeID int64
24+
UserID int64 `xorm:"INDEX"`
25+
}
26+
27+
func init() {
28+
db.RegisterModel(new(Badge))
29+
db.RegisterModel(new(UserBadge))
30+
}
31+
32+
// GetUserBadges returns the user's badges.
33+
func GetUserBadges(ctx context.Context, u *User) ([]*Badge, int64, error) {
34+
sess := db.GetEngine(ctx).
35+
Select("`badge`.*").
36+
Join("INNER", "user_badge", "`user_badge`.badge_id=badge.id").
37+
Where("user_badge.user_id=?", u.ID)
38+
39+
badges := make([]*Badge, 0, 8)
40+
count, err := sess.FindAndCount(&badges)
41+
return badges, count, err
42+
}

Diff for: routers/web/user/profile.go

+7
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ func Profile(ctx *context.Context) {
105105
ctx.Data["Orgs"] = orgs
106106
ctx.Data["HasOrgsVisible"] = organization.HasOrgsVisible(orgs, ctx.Doer)
107107

108+
badges, _, err := user_model.GetUserBadges(ctx, ctx.ContextUser)
109+
if err != nil {
110+
ctx.ServerError("GetUserBadges", err)
111+
return
112+
}
113+
ctx.Data["Badges"] = badges
114+
108115
tab := ctx.FormString("tab")
109116
ctx.Data["TabName"] = tab
110117

Diff for: templates/user/profile.tmpl

+11
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@
6969
</ul>
7070
</li>
7171
{{end}}
72+
{{if .Badges}}
73+
<li>
74+
<ul class="user-badges">
75+
{{range .Badges}}
76+
<li>
77+
<img width="64" height="64" src="{{.ImageURL}}" alt="{{.Description}}" data-content="{{.Description}}" class="tooltip"/>
78+
</li>
79+
{{end}}
80+
</ul>
81+
</li>
82+
{{end}}
7283
{{if and .IsSigned (ne .SignedUserName .Owner.Name)}}
7384
<li class="follow">
7485
{{if $.IsFollowing}}

Diff for: web_src/less/_user.less

+9
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,15 @@
169169
}
170170
}
171171

172+
.user-badges {
173+
display: grid;
174+
grid-template-columns: repeat(auto-fill, 64px);
175+
gap: 2px;
176+
}
177+
178+
.user-badges img {
179+
object-fit: contain;
180+
}
172181
#notification_div .tab.segment {
173182
overflow-x: auto;
174183
}

0 commit comments

Comments
 (0)