aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.golangci.yml4
-rw-r--r--models/migrations/migrations.go3
-rw-r--r--models/migrations/v999.go28
-rw-r--r--models/user.go1
-rw-r--r--models/user/badge.go42
-rw-r--r--routers/web/user/profile.go7
-rw-r--r--templates/user/profile.tmpl11
-rw-r--r--web_src/less/_user.less9
8 files changed, 105 insertions, 0 deletions
diff --git a/.golangci.yml b/.golangci.yml
index 6e80af8c0e..982ab06f0b 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -171,3 +171,7 @@ issues:
- path: models/user/openid.go
linters:
- golint
+ - path: models/user/badge.go
+ linters:
+ - revive
+ text: "exported: type name will be used as user.UserBadge by other packages, and that stutters; consider calling this Badge"
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 2719f45efb..aa08f055d3 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -406,6 +406,9 @@ var migrations = []Migration{
NewMigration("Drop old CredentialID column", dropOldCredentialIDColumn),
// v223 -> v224
NewMigration("Rename CredentialIDBytes column to CredentialID", renameCredentialIDBytes),
+
+ // v999
+ NewMigration("Add badges to users", creatUserBadgesTable),
}
// GetCurrentDBVersion returns the current db version
diff --git a/models/migrations/v999.go b/models/migrations/v999.go
new file mode 100644
index 0000000000..d684d538df
--- /dev/null
+++ b/models/migrations/v999.go
@@ -0,0 +1,28 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package migrations
+
+import (
+ "xorm.io/xorm"
+)
+
+func creatUserBadgesTable(x *xorm.Engine) error {
+ type Badge struct {
+ ID int64 `xorm:"pk autoincr"`
+ Description string
+ ImageURL string
+ }
+
+ type userBadge struct {
+ ID int64 `xorm:"pk autoincr"`
+ BadgeID int64
+ UserID int64 `xorm:"INDEX"`
+ }
+
+ if err := x.Sync2(new(Badge)); err != nil {
+ return err
+ }
+ return x.Sync2(new(userBadge))
+}
diff --git a/models/user.go b/models/user.go
index 86a714e746..4afbb9bea5 100644
--- a/models/user.go
+++ b/models/user.go
@@ -85,6 +85,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
&organization.TeamUser{UID: u.ID},
&issues_model.Stopwatch{UserID: u.ID},
&user_model.Setting{UserID: u.ID},
+ &user_model.UserBadge{UserID: u.ID},
&pull_model.AutoMerge{DoerID: u.ID},
&pull_model.ReviewState{UserID: u.ID},
); err != nil {
diff --git a/models/user/badge.go b/models/user/badge.go
new file mode 100644
index 0000000000..5ff840cb8c
--- /dev/null
+++ b/models/user/badge.go
@@ -0,0 +1,42 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package user
+
+import (
+ "context"
+
+ "code.gitea.io/gitea/models/db"
+)
+
+// Badge represents a user badge
+type Badge struct {
+ ID int64 `xorm:"pk autoincr"`
+ Description string
+ ImageURL string
+}
+
+// UserBadge represents a user badge
+type UserBadge struct {
+ ID int64 `xorm:"pk autoincr"`
+ BadgeID int64
+ UserID int64 `xorm:"INDEX"`
+}
+
+func init() {
+ db.RegisterModel(new(Badge))
+ db.RegisterModel(new(UserBadge))
+}
+
+// GetUserBadges returns the user's badges.
+func GetUserBadges(ctx context.Context, u *User) ([]*Badge, int64, error) {
+ sess := db.GetEngine(ctx).
+ Select("`badge`.*").
+ Join("INNER", "user_badge", "`user_badge`.badge_id=badge.id").
+ Where("user_badge.user_id=?", u.ID)
+
+ badges := make([]*Badge, 0, 8)
+ count, err := sess.FindAndCount(&badges)
+ return badges, count, err
+}
diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go
index 6f23d239e2..c804be3c5f 100644
--- a/routers/web/user/profile.go
+++ b/routers/web/user/profile.go
@@ -105,6 +105,13 @@ func Profile(ctx *context.Context) {
ctx.Data["Orgs"] = orgs
ctx.Data["HasOrgsVisible"] = organization.HasOrgsVisible(orgs, ctx.Doer)
+ badges, _, err := user_model.GetUserBadges(ctx, ctx.ContextUser)
+ if err != nil {
+ ctx.ServerError("GetUserBadges", err)
+ return
+ }
+ ctx.Data["Badges"] = badges
+
tab := ctx.FormString("tab")
ctx.Data["TabName"] = tab
diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl
index 947c8fcebe..2a973c2d5b 100644
--- a/templates/user/profile.tmpl
+++ b/templates/user/profile.tmpl
@@ -69,6 +69,17 @@
</ul>
</li>
{{end}}
+ {{if .Badges}}
+ <li>
+ <ul class="user-badges">
+ {{range .Badges}}
+ <li>
+ <img width="64" height="64" src="{{.ImageURL}}" alt="{{.Description}}" data-content="{{.Description}}" class="tooltip"/>
+ </li>
+ {{end}}
+ </ul>
+ </li>
+ {{end}}
{{if and .IsSigned (ne .SignedUserName .Owner.Name)}}
<li class="follow">
{{if $.IsFollowing}}
diff --git a/web_src/less/_user.less b/web_src/less/_user.less
index a9b6c02fb7..eb9e791d86 100644
--- a/web_src/less/_user.less
+++ b/web_src/less/_user.less
@@ -169,6 +169,15 @@
}
}
+.user-badges {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, 64px);
+ gap: 2px;
+}
+
+.user-badges img {
+ object-fit: contain;
+}
#notification_div .tab.segment {
overflow-x: auto;
}