mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Tab on user profile to show starred repos (#519)
* Tab on user profile to show starred repos * Make golint happy and use transactions on StarRepo function * x -> sess * Use sess.Close() instead of sess.Rollback() * Add copyright * Fix lint
This commit is contained in:
		
				
					committed by
					
						
						Lunny Xiao
					
				
			
			
				
	
			
			
			
						parent
						
							2d1a1fce93
						
					
				
				
					commit
					b992858883
				
			@@ -273,7 +273,6 @@ func runWeb(ctx *cli.Context) error {
 | 
			
		||||
			m.Get("", user.Profile)
 | 
			
		||||
			m.Get("/followers", user.Followers)
 | 
			
		||||
			m.Get("/following", user.Following)
 | 
			
		||||
			m.Get("/stars", user.Stars)
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		m.Get("/attachments/:uuid", func(ctx *context.Context) {
 | 
			
		||||
 
 | 
			
		||||
@@ -2146,66 +2146,6 @@ func NotifyWatchers(act *Action) error {
 | 
			
		||||
	return notifyWatchers(x, act)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//   _________ __
 | 
			
		||||
//  /   _____//  |______ _______
 | 
			
		||||
//  \_____  \\   __\__  \\_  __ \
 | 
			
		||||
//  /        \|  |  / __ \|  | \/
 | 
			
		||||
// /_______  /|__| (____  /__|
 | 
			
		||||
//         \/           \/
 | 
			
		||||
 | 
			
		||||
// Star contains the star information
 | 
			
		||||
type Star struct {
 | 
			
		||||
	ID     int64 `xorm:"pk autoincr"`
 | 
			
		||||
	UID    int64 `xorm:"UNIQUE(s)"`
 | 
			
		||||
	RepoID int64 `xorm:"UNIQUE(s)"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StarRepo star or unstar repository.
 | 
			
		||||
func StarRepo(userID, repoID int64, star bool) (err error) {
 | 
			
		||||
	if star {
 | 
			
		||||
		if IsStaring(userID, repoID) {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		if _, err = x.Insert(&Star{UID: userID, RepoID: repoID}); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		} else if _, err = x.Exec("UPDATE `repository` SET num_stars = num_stars + 1 WHERE id = ?", repoID); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		_, err = x.Exec("UPDATE `user` SET num_stars = num_stars + 1 WHERE id = ?", userID)
 | 
			
		||||
	} else {
 | 
			
		||||
		if !IsStaring(userID, repoID) {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		if _, err = x.Delete(&Star{0, userID, repoID}); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		} else if _, err = x.Exec("UPDATE `repository` SET num_stars = num_stars - 1 WHERE id = ?", repoID); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		_, err = x.Exec("UPDATE `user` SET num_stars = num_stars - 1 WHERE id = ?", userID)
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsStaring checks if user has starred given repository.
 | 
			
		||||
func IsStaring(userID, repoID int64) bool {
 | 
			
		||||
	has, _ := x.Get(&Star{0, userID, repoID})
 | 
			
		||||
	return has
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetStargazers returns the users who gave stars to this repository
 | 
			
		||||
func (repo *Repository) GetStargazers(page int) ([]*User, error) {
 | 
			
		||||
	users := make([]*User, 0, ItemsPerPage)
 | 
			
		||||
	sess := x.
 | 
			
		||||
		Limit(ItemsPerPage, (page-1)*ItemsPerPage).
 | 
			
		||||
		Where("star.repo_id=?", repo.ID)
 | 
			
		||||
	if setting.UsePostgreSQL {
 | 
			
		||||
		sess = sess.Join("LEFT", "star", `"user".id=star.uid`)
 | 
			
		||||
	} else {
 | 
			
		||||
		sess = sess.Join("LEFT", "star", "user.id=star.uid")
 | 
			
		||||
	}
 | 
			
		||||
	return users, sess.Find(&users)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ___________           __
 | 
			
		||||
// \_   _____/__________|  | __
 | 
			
		||||
//  |    __)/  _ \_  __ \  |/ /
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										87
									
								
								models/star.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								models/star.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
			
		||||
// Copyright 2016 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 models
 | 
			
		||||
 | 
			
		||||
// Star represents a starred repo by an user.
 | 
			
		||||
type Star struct {
 | 
			
		||||
	ID     int64 `xorm:"pk autoincr"`
 | 
			
		||||
	UID    int64 `xorm:"UNIQUE(s)"`
 | 
			
		||||
	RepoID int64 `xorm:"UNIQUE(s)"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StarRepo or unstar repository.
 | 
			
		||||
func StarRepo(userID, repoID int64, star bool) error {
 | 
			
		||||
	sess := x.NewSession()
 | 
			
		||||
 | 
			
		||||
	defer sess.Close()
 | 
			
		||||
 | 
			
		||||
	if err := sess.Begin(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if star {
 | 
			
		||||
		if IsStaring(userID, repoID) {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if _, err := sess.Insert(&Star{UID: userID, RepoID: repoID}); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if _, err := sess.Exec("UPDATE `repository` SET num_stars = num_stars + 1 WHERE id = ?", repoID); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if _, err := sess.Exec("UPDATE `user` SET num_stars = num_stars + 1 WHERE id = ?", userID); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if !IsStaring(userID, repoID) {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if _, err := sess.Delete(&Star{0, userID, repoID}); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if _, err := sess.Exec("UPDATE `repository` SET num_stars = num_stars - 1 WHERE id = ?", repoID); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if _, err := sess.Exec("UPDATE `user` SET num_stars = num_stars - 1 WHERE id = ?", userID); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sess.Commit()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsStaring checks if user has starred given repository.
 | 
			
		||||
func IsStaring(userID, repoID int64) bool {
 | 
			
		||||
	has, _ := x.Get(&Star{0, userID, repoID})
 | 
			
		||||
	return has
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetStargazers returns the users that starred the repo.
 | 
			
		||||
func (repo *Repository) GetStargazers(page int) ([]*User, error) {
 | 
			
		||||
	users := make([]*User, 0, ItemsPerPage)
 | 
			
		||||
	err := x.
 | 
			
		||||
		Limit(ItemsPerPage, (page-1)*ItemsPerPage).
 | 
			
		||||
		Where("star.repo_id = ?", repo.ID).
 | 
			
		||||
		Join("LEFT", "star", "`user`.id = star.uid").
 | 
			
		||||
		Find(&users)
 | 
			
		||||
	return users, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetStarredRepos returns the repos the user starred.
 | 
			
		||||
func (u *User) GetStarredRepos(private bool) (repos []*Repository, err error) {
 | 
			
		||||
	sess := x.
 | 
			
		||||
		Join("INNER", "star", "star.repo_id = repository.id").
 | 
			
		||||
		Where("star.uid = ?", u.ID)
 | 
			
		||||
 | 
			
		||||
	if !private {
 | 
			
		||||
		sess = sess.And("is_private = ?", false)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = sess.
 | 
			
		||||
		Find(&repos)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
@@ -36,6 +36,7 @@ admin_panel = Admin Panel
 | 
			
		||||
account_settings = Account Settings
 | 
			
		||||
settings = Settings
 | 
			
		||||
your_profile = Your Profile
 | 
			
		||||
your_starred = Your starred
 | 
			
		||||
your_settings = Your Settings
 | 
			
		||||
 | 
			
		||||
activities = Activities
 | 
			
		||||
 
 | 
			
		||||
@@ -95,6 +95,14 @@ func Profile(ctx *context.Context) {
 | 
			
		||||
		if ctx.Written() {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	case "stars":
 | 
			
		||||
		showPrivateRepos := ctx.IsSigned && ctx.User.ID == ctxUser.ID
 | 
			
		||||
		starredRepos, err := ctxUser.GetStarredRepos(showPrivateRepos)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.Handle(500, "GetStarredRepos", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		ctx.Data["Repos"] = starredRepos
 | 
			
		||||
	default:
 | 
			
		||||
		page := ctx.QueryInt("page")
 | 
			
		||||
		if page <= 0 {
 | 
			
		||||
@@ -138,11 +146,6 @@ func Following(ctx *context.Context) {
 | 
			
		||||
	repo.RenderUserCards(ctx, u.NumFollowing, u.GetFollowing, tplFollowers)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Stars show repositories user starred
 | 
			
		||||
func Stars(ctx *context.Context) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Action response for follow/unfollow user request
 | 
			
		||||
func Action(ctx *context.Context) {
 | 
			
		||||
	u := GetUserByParams(ctx)
 | 
			
		||||
 
 | 
			
		||||
@@ -116,6 +116,10 @@
 | 
			
		||||
													<i class="octicon octicon-person"></i>
 | 
			
		||||
													{{.i18n.Tr "your_profile"}}<!-- Your profile -->
 | 
			
		||||
												</a>
 | 
			
		||||
												<a class="item" href="{{AppSubUrl}}/{{.SignedUser.Name}}?tab=stars">
 | 
			
		||||
													<i class="octicon octicon-star"></i>
 | 
			
		||||
													{{.i18n.Tr "your_starred"}}
 | 
			
		||||
												</a>
 | 
			
		||||
												<a class="{{if .PageIsUserSettings}}active{{end}} item" href="{{AppSubUrl}}/user/settings">
 | 
			
		||||
													<i class="octicon octicon-settings"></i>
 | 
			
		||||
													{{.i18n.Tr "your_settings"}}<!-- Your settings -->
 | 
			
		||||
 
 | 
			
		||||
@@ -75,23 +75,28 @@
 | 
			
		||||
			</div>
 | 
			
		||||
			<div class="ui eleven wide column">
 | 
			
		||||
				<div class="ui secondary pointing menu">
 | 
			
		||||
					<a class="{{if ne .TabName "activity"}}active{{end}} item" href="{{.Owner.HomeLink}}">
 | 
			
		||||
					<a class='{{if and (ne .TabName "activity") (ne .TabName "stars")}}active{{end}} item' href="{{.Owner.HomeLink}}">
 | 
			
		||||
						<i class="octicon octicon-repo"></i> {{.i18n.Tr "user.repositories"}}
 | 
			
		||||
					</a>
 | 
			
		||||
					<a class="item">
 | 
			
		||||
						<a class="{{if eq .TabName "activity"}}active{{end}} item" href="{{.Owner.HomeLink}}?tab=activity">
 | 
			
		||||
							<i class="octicon octicon-rss"></i> {{.i18n.Tr "user.activity"}}
 | 
			
		||||
						</a>
 | 
			
		||||
					<a class='{{if eq .TabName "activity"}}active{{end}} item' href="{{.Owner.HomeLink}}?tab=activity">
 | 
			
		||||
						<i class="octicon octicon-rss"></i> {{.i18n.Tr "user.activity"}}
 | 
			
		||||
					</a>
 | 
			
		||||
					<a class='{{if eq .TabName "stars"}}active{{end}} item' href="{{.Owner.HomeLink}}?tab=stars">
 | 
			
		||||
						<i class="octicon octicon-star"></i> {{.i18n.Tr "user.starred"}}
 | 
			
		||||
					</a>
 | 
			
		||||
				</div>
 | 
			
		||||
				{{if ne .TabName "activity"}}
 | 
			
		||||
					{{template "explore/repo_list" .}}
 | 
			
		||||
					{{template "base/paginate" .}}
 | 
			
		||||
				{{else}}
 | 
			
		||||
					<br>
 | 
			
		||||
 | 
			
		||||
				{{if eq .TabName "activity"}}
 | 
			
		||||
					<div class="feeds">
 | 
			
		||||
						{{template "user/dashboard/feeds" .}}
 | 
			
		||||
					</div>
 | 
			
		||||
				{{else if eq .TabName "stars"}}
 | 
			
		||||
					<div class="stars">
 | 
			
		||||
						{{template "explore/repo_list" .}}
 | 
			
		||||
					</div>
 | 
			
		||||
				{{else}}
 | 
			
		||||
					{{template "explore/repo_list" .}}
 | 
			
		||||
					{{template "base/paginate" .}}
 | 
			
		||||
				{{end}}
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user