Add badge capabilities to users (#20607)

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: John Olheiser <john.olheiser@gmail.com>
tokarchuk/v1.18
techknowlogick 2 years ago committed by GitHub
parent 208b4ee417
commit d8e6c99125
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .golangci.yml
  2. 3
      models/migrations/migrations.go
  3. 28
      models/migrations/v999.go
  4. 1
      models/user.go
  5. 42
      models/user/badge.go
  6. 7
      routers/web/user/profile.go
  7. 11
      templates/user/profile.tmpl
  8. 9
      web_src/less/_user.less

@ -171,3 +171,7 @@ issues:
- path: models/user/openid.go - path: models/user/openid.go
linters: linters:
- golint - 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"

@ -406,6 +406,9 @@ var migrations = []Migration{
NewMigration("Drop old CredentialID column", dropOldCredentialIDColumn), NewMigration("Drop old CredentialID column", dropOldCredentialIDColumn),
// v223 -> v224 // v223 -> v224
NewMigration("Rename CredentialIDBytes column to CredentialID", renameCredentialIDBytes), NewMigration("Rename CredentialIDBytes column to CredentialID", renameCredentialIDBytes),
// v999
NewMigration("Add badges to users", creatUserBadgesTable),
} }
// GetCurrentDBVersion returns the current db version // GetCurrentDBVersion returns the current db version

@ -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))
}

@ -85,6 +85,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
&organization.TeamUser{UID: u.ID}, &organization.TeamUser{UID: u.ID},
&issues_model.Stopwatch{UserID: u.ID}, &issues_model.Stopwatch{UserID: u.ID},
&user_model.Setting{UserID: u.ID}, &user_model.Setting{UserID: u.ID},
&user_model.UserBadge{UserID: u.ID},
&pull_model.AutoMerge{DoerID: u.ID}, &pull_model.AutoMerge{DoerID: u.ID},
&pull_model.ReviewState{UserID: u.ID}, &pull_model.ReviewState{UserID: u.ID},
); err != nil { ); err != nil {

@ -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
}

@ -105,6 +105,13 @@ func Profile(ctx *context.Context) {
ctx.Data["Orgs"] = orgs ctx.Data["Orgs"] = orgs
ctx.Data["HasOrgsVisible"] = organization.HasOrgsVisible(orgs, ctx.Doer) 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") tab := ctx.FormString("tab")
ctx.Data["TabName"] = tab ctx.Data["TabName"] = tab

@ -69,6 +69,17 @@
</ul> </ul>
</li> </li>
{{end}} {{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)}} {{if and .IsSigned (ne .SignedUserName .Owner.Name)}}
<li class="follow"> <li class="follow">
{{if $.IsFollowing}} {{if $.IsFollowing}}

@ -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 { #notification_div .tab.segment {
overflow-x: auto; overflow-x: auto;
} }

Loading…
Cancel
Save