#1692 APIs: Users Followers
- User profile un/follow - List user's followers/followingtokarchuk/v1.17
parent
c62a6b7a12
commit
a49af93faf
File diff suppressed because one or more lines are too long
@ -0,0 +1,121 @@ |
|||||||
|
// Copyright 2015 The Gogs 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 ( |
||||||
|
api "github.com/gogits/go-gogs-client" |
||||||
|
|
||||||
|
"github.com/gogits/gogs/models" |
||||||
|
"github.com/gogits/gogs/modules/middleware" |
||||||
|
"github.com/gogits/gogs/routers/api/v1/convert" |
||||||
|
) |
||||||
|
|
||||||
|
func responseApiUsers(ctx *middleware.Context, users []*models.User) { |
||||||
|
apiUsers := make([]*api.User, len(users)) |
||||||
|
for i := range users { |
||||||
|
apiUsers[i] = convert.ToApiUser(users[i]) |
||||||
|
} |
||||||
|
ctx.JSON(200, &apiUsers) |
||||||
|
} |
||||||
|
|
||||||
|
func listUserFollowers(ctx *middleware.Context, u *models.User) { |
||||||
|
users, err := u.GetFollowers(ctx.QueryInt("page")) |
||||||
|
if err != nil { |
||||||
|
ctx.APIError(500, "GetUserFollowers", err) |
||||||
|
return |
||||||
|
} |
||||||
|
responseApiUsers(ctx, users) |
||||||
|
} |
||||||
|
|
||||||
|
func ListMyFollowers(ctx *middleware.Context) { |
||||||
|
listUserFollowers(ctx, ctx.User) |
||||||
|
} |
||||||
|
|
||||||
|
// https://github.com/gogits/go-gogs-client/wiki/Users-Followers#list-followers-of-a-user
|
||||||
|
func ListFollowers(ctx *middleware.Context) { |
||||||
|
u := GetUserByParams(ctx) |
||||||
|
if ctx.Written() { |
||||||
|
return |
||||||
|
} |
||||||
|
listUserFollowers(ctx, u) |
||||||
|
} |
||||||
|
|
||||||
|
func listUserFollowing(ctx *middleware.Context, u *models.User) { |
||||||
|
users, err := u.GetFollowing(ctx.QueryInt("page")) |
||||||
|
if err != nil { |
||||||
|
ctx.APIError(500, "GetFollowing", err) |
||||||
|
return |
||||||
|
} |
||||||
|
responseApiUsers(ctx, users) |
||||||
|
} |
||||||
|
|
||||||
|
func ListMyFollowing(ctx *middleware.Context) { |
||||||
|
listUserFollowing(ctx, ctx.User) |
||||||
|
} |
||||||
|
|
||||||
|
// https://github.com/gogits/go-gogs-client/wiki/Users-Followers#list-users-followed-by-another-user
|
||||||
|
func ListFollowing(ctx *middleware.Context) { |
||||||
|
u := GetUserByParams(ctx) |
||||||
|
if ctx.Written() { |
||||||
|
return |
||||||
|
} |
||||||
|
listUserFollowing(ctx, u) |
||||||
|
} |
||||||
|
|
||||||
|
func checkUserFollowing(ctx *middleware.Context, u *models.User, followID int64) { |
||||||
|
if u.IsFollowing(followID) { |
||||||
|
ctx.Status(204) |
||||||
|
} else { |
||||||
|
ctx.Error(404) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// https://github.com/gogits/go-gogs-client/wiki/Users-Followers#check-if-you-are-following-a-user
|
||||||
|
func CheckMyFollowing(ctx *middleware.Context) { |
||||||
|
target := GetUserByParams(ctx) |
||||||
|
if ctx.Written() { |
||||||
|
return |
||||||
|
} |
||||||
|
checkUserFollowing(ctx, ctx.User, target.Id) |
||||||
|
} |
||||||
|
|
||||||
|
// https://github.com/gogits/go-gogs-client/wiki/Users-Followers#check-if-one-user-follows-another
|
||||||
|
func CheckFollowing(ctx *middleware.Context) { |
||||||
|
u := GetUserByParams(ctx) |
||||||
|
if ctx.Written() { |
||||||
|
return |
||||||
|
} |
||||||
|
target := GetUserByParamsName(ctx, ":target") |
||||||
|
if ctx.Written() { |
||||||
|
return |
||||||
|
} |
||||||
|
checkUserFollowing(ctx, u, target.Id) |
||||||
|
} |
||||||
|
|
||||||
|
// https://github.com/gogits/go-gogs-client/wiki/Users-Followers#follow-a-user
|
||||||
|
func Follow(ctx *middleware.Context) { |
||||||
|
target := GetUserByParams(ctx) |
||||||
|
if ctx.Written() { |
||||||
|
return |
||||||
|
} |
||||||
|
if err := models.FollowUser(ctx.User.Id, target.Id); err != nil { |
||||||
|
ctx.APIError(500, "FollowUser", err) |
||||||
|
return |
||||||
|
} |
||||||
|
ctx.Status(204) |
||||||
|
} |
||||||
|
|
||||||
|
// https://github.com/gogits/go-gogs-client/wiki/Users-Followers#unfollow-a-user
|
||||||
|
func Unfollow(ctx *middleware.Context) { |
||||||
|
target := GetUserByParams(ctx) |
||||||
|
if ctx.Written() { |
||||||
|
return |
||||||
|
} |
||||||
|
if err := models.UnfollowUser(ctx.User.Id, target.Id); err != nil { |
||||||
|
ctx.APIError(500, "UnfollowUser", err) |
||||||
|
return |
||||||
|
} |
||||||
|
ctx.Status(204) |
||||||
|
} |
@ -0,0 +1,145 @@ |
|||||||
|
// Copyright 2015 The Gogs 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 ( |
||||||
|
"fmt" |
||||||
|
"strings" |
||||||
|
|
||||||
|
"github.com/gogits/gogs/models" |
||||||
|
"github.com/gogits/gogs/modules/base" |
||||||
|
"github.com/gogits/gogs/modules/middleware" |
||||||
|
"github.com/gogits/gogs/modules/setting" |
||||||
|
"github.com/gogits/gogs/routers/repo" |
||||||
|
) |
||||||
|
|
||||||
|
const ( |
||||||
|
FOLLOWERS base.TplName = "user/meta/followers" |
||||||
|
STARS base.TplName = "user/meta/stars" |
||||||
|
) |
||||||
|
|
||||||
|
// GetUserByParams returns user whose name is presented in URL paramenter.
|
||||||
|
func GetUserByParams(ctx *middleware.Context) *models.User { |
||||||
|
user, err := models.GetUserByName(ctx.Params(":username")) |
||||||
|
if err != nil { |
||||||
|
if models.IsErrUserNotExist(err) { |
||||||
|
ctx.Error(404) |
||||||
|
} else { |
||||||
|
ctx.Handle(500, "GetUserByName", err) |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
return user |
||||||
|
} |
||||||
|
|
||||||
|
func Profile(ctx *middleware.Context) { |
||||||
|
uname := ctx.Params(":username") |
||||||
|
// Special handle for FireFox requests favicon.ico.
|
||||||
|
if uname == "favicon.ico" { |
||||||
|
ctx.Redirect(setting.AppSubUrl + "/img/favicon.png") |
||||||
|
return |
||||||
|
} else if strings.HasSuffix(uname, ".png") { |
||||||
|
ctx.Error(404) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
isShowKeys := false |
||||||
|
if strings.HasSuffix(uname, ".keys") { |
||||||
|
isShowKeys = true |
||||||
|
} |
||||||
|
|
||||||
|
u := GetUserByParams(ctx) |
||||||
|
if ctx.Written() { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// Show SSH keys.
|
||||||
|
if isShowKeys { |
||||||
|
ShowSSHKeys(ctx, u.Id) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
if u.IsOrganization() { |
||||||
|
showOrgProfile(ctx) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
ctx.Data["Title"] = u.DisplayName() |
||||||
|
ctx.Data["PageIsUserProfile"] = true |
||||||
|
ctx.Data["Owner"] = u |
||||||
|
|
||||||
|
tab := ctx.Query("tab") |
||||||
|
ctx.Data["TabName"] = tab |
||||||
|
switch tab { |
||||||
|
case "activity": |
||||||
|
retrieveFeeds(ctx, u.Id, 0, true) |
||||||
|
if ctx.Written() { |
||||||
|
return |
||||||
|
} |
||||||
|
default: |
||||||
|
var err error |
||||||
|
ctx.Data["Repos"], err = models.GetRepositories(u.Id, ctx.IsSigned && ctx.User.Id == u.Id) |
||||||
|
if err != nil { |
||||||
|
ctx.Handle(500, "GetRepositories", err) |
||||||
|
return |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ctx.HTML(200, PROFILE) |
||||||
|
} |
||||||
|
|
||||||
|
func Followers(ctx *middleware.Context) { |
||||||
|
u := GetUserByParams(ctx) |
||||||
|
if ctx.Written() { |
||||||
|
return |
||||||
|
} |
||||||
|
ctx.Data["Title"] = u.DisplayName() |
||||||
|
ctx.Data["CardsTitle"] = ctx.Tr("user.followers") |
||||||
|
ctx.Data["PageIsFollowers"] = true |
||||||
|
ctx.Data["Owner"] = u |
||||||
|
repo.RenderUserCards(ctx, u.NumFollowers, u.GetFollowers, FOLLOWERS) |
||||||
|
} |
||||||
|
|
||||||
|
func Following(ctx *middleware.Context) { |
||||||
|
u := GetUserByParams(ctx) |
||||||
|
if ctx.Written() { |
||||||
|
return |
||||||
|
} |
||||||
|
ctx.Data["Title"] = u.DisplayName() |
||||||
|
ctx.Data["CardsTitle"] = ctx.Tr("user.following") |
||||||
|
ctx.Data["PageIsFollowing"] = true |
||||||
|
ctx.Data["Owner"] = u |
||||||
|
repo.RenderUserCards(ctx, u.NumFollowing, u.GetFollowing, FOLLOWERS) |
||||||
|
} |
||||||
|
|
||||||
|
func Stars(ctx *middleware.Context) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
func Action(ctx *middleware.Context) { |
||||||
|
u := GetUserByParams(ctx) |
||||||
|
if ctx.Written() { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
var err error |
||||||
|
switch ctx.Params(":action") { |
||||||
|
case "follow": |
||||||
|
err = models.FollowUser(ctx.User.Id, u.Id) |
||||||
|
case "unfollow": |
||||||
|
err = models.UnfollowUser(ctx.User.Id, u.Id) |
||||||
|
} |
||||||
|
|
||||||
|
if err != nil { |
||||||
|
ctx.Handle(500, fmt.Sprintf("Action (%s)", ctx.Params(":action")), err) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
redirectTo := ctx.Query("redirect_to") |
||||||
|
if len(redirectTo) == 0 { |
||||||
|
redirectTo = u.HomeLink() |
||||||
|
} |
||||||
|
ctx.Redirect(redirectTo) |
||||||
|
} |
@ -1 +1 @@ |
|||||||
0.8.12.1219 |
0.8.13.1221 |
@ -0,0 +1,47 @@ |
|||||||
|
<div class="ui container user-cards"> |
||||||
|
<h2 class="ui dividing header"> |
||||||
|
{{.CardsTitle}} |
||||||
|
</h2> |
||||||
|
<ul class="list"> |
||||||
|
{{range .Cards}} |
||||||
|
<li class="item ui segment"> |
||||||
|
<a href="{{.HomeLink}}"> |
||||||
|
<img class="avatar" src="{{.AvatarLink}}"/> |
||||||
|
</a> |
||||||
|
<h3 class="name"><a href="{{.HomeLink}}">{{.DisplayName}}</a></h3> |
||||||
|
|
||||||
|
<div class="meta"> |
||||||
|
{{if .Website}} |
||||||
|
<span class="icon octicon octicon-link"></span> <a href="{{.Website}}" target="_blank">{{.Website}}</a> |
||||||
|
{{else if .Location}} |
||||||
|
<span class="icon octicon octicon-location"></span> {{.Location}} |
||||||
|
{{else}} |
||||||
|
<span class="icon octicon octicon-clock"></span> {{$.i18n.Tr "user.join_on"}} {{DateFmtShort .Created}} |
||||||
|
{{end}} |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
{{end}} |
||||||
|
</ul> |
||||||
|
|
||||||
|
{{with .Page}} |
||||||
|
{{if gt .TotalPages 1}} |
||||||
|
<div class="center page buttons"> |
||||||
|
<div class="ui borderless pagination menu"> |
||||||
|
<a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?page={{.Previous}}"{{end}}> |
||||||
|
<i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}} |
||||||
|
</a> |
||||||
|
{{range .Pages}} |
||||||
|
{{if eq .Num -1}} |
||||||
|
<a class="disabled item">...</a> |
||||||
|
{{else}} |
||||||
|
<a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.Link}}?page={{.Num}}"{{end}}>{{.Num}}</a> |
||||||
|
{{end}} |
||||||
|
{{end}} |
||||||
|
<a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?page={{.Next}}"{{end}}> |
||||||
|
{{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{{end}} |
||||||
|
{{end}} |
||||||
|
</div> |
@ -1,56 +1,6 @@ |
|||||||
{{template "base/head" .}} |
{{template "base/head" .}} |
||||||
<div class="repository watchers"> |
<div class="repository watchers"> |
||||||
{{template "repo/header" .}} |
{{template "repo/header" .}} |
||||||
<div class="ui container"> |
{{template "repo/user_cards" .}} |
||||||
<h2 class="ui dividing header"> |
|
||||||
{{if .PageIsWatchers}} |
|
||||||
{{.i18n.Tr "repo.watchers"}} |
|
||||||
{{else}} |
|
||||||
{{.i18n.Tr "repo.stargazers"}} |
|
||||||
{{end}} |
|
||||||
</h2> |
|
||||||
<ul class="list"> |
|
||||||
{{range .Watchers}} |
|
||||||
<li class="item ui segment"> |
|
||||||
<a href="{{.HomeLink}}"> |
|
||||||
<img class="avatar" src="{{.AvatarLink}}"/> |
|
||||||
</a> |
|
||||||
<h3 class="name"><a href="{{.HomeLink}}">{{.DisplayName}}</a></h3> |
|
||||||
|
|
||||||
<div class="meta"> |
|
||||||
{{if .Website}} |
|
||||||
<span class="icon octicon octicon-link"></span> <a href="{{.Website}}" target="_blank">{{.Website}}</a> |
|
||||||
{{else if .Location}} |
|
||||||
<span class="icon octicon octicon-location"></span> {{.Location}} |
|
||||||
{{else}} |
|
||||||
<span class="icon octicon octicon-clock"></span> {{$.i18n.Tr "user.join_on"}} {{DateFmtShort .Created}} |
|
||||||
{{end}} |
|
||||||
</div> |
|
||||||
</li> |
|
||||||
{{end}} |
|
||||||
</ul> |
|
||||||
|
|
||||||
{{with .Page}} |
|
||||||
{{if gt .TotalPages 1}} |
|
||||||
<div class="center page buttons"> |
|
||||||
<div class="ui borderless pagination menu"> |
|
||||||
<a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?page={{.Previous}}"{{end}}> |
|
||||||
<i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}} |
|
||||||
</a> |
|
||||||
{{range .Pages}} |
|
||||||
{{if eq .Num -1}} |
|
||||||
<a class="disabled item">...</a> |
|
||||||
{{else}} |
|
||||||
<a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.Link}}?page={{.Num}}"{{end}}>{{.Num}}</a> |
|
||||||
{{end}} |
|
||||||
{{end}} |
|
||||||
<a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?page={{.Next}}"{{end}}> |
|
||||||
{{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i> |
|
||||||
</a> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
{{end}} |
|
||||||
{{end}} |
|
||||||
</div> |
|
||||||
</div> |
</div> |
||||||
{{template "base/footer" .}} |
{{template "base/footer" .}} |
||||||
|
@ -0,0 +1,6 @@ |
|||||||
|
{{template "base/head" .}} |
||||||
|
<div class="user followers"> |
||||||
|
{{template "user/meta/header" .}} |
||||||
|
{{template "repo/user_cards" .}} |
||||||
|
</div> |
||||||
|
{{template "base/footer" .}} |
@ -0,0 +1,25 @@ |
|||||||
|
{{with .Owner}} |
||||||
|
<div class="ui container"> |
||||||
|
<img class="ui avatar image" src="{{.AvatarLink}}"> |
||||||
|
<span class="header name"> |
||||||
|
<a href="{{.HomeLink}}">{{.Name}}</a> |
||||||
|
{{with .FullName}}({{.}}){{end}} |
||||||
|
</span> |
||||||
|
|
||||||
|
<div class="ui right"> |
||||||
|
|
||||||
|
{{if or $.PageIsFollowers $.PageIsFollowing}} |
||||||
|
{{if and $.IsSigned (ne $.SignedUserName .Name)}} |
||||||
|
<div class="follow"> |
||||||
|
{{if $.SignedUser.IsFollowing .Id}} |
||||||
|
<a class="ui small basic red button" href="{{.HomeLink}}/action/unfollow?redirect_to={{$.Link}}"><i class="octicon octicon-person"></i> {{$.i18n.Tr "user.unfollow"}}</a> |
||||||
|
{{else}} |
||||||
|
<a class="ui small basic green button" href="{{.HomeLink}}/action/follow?redirect_to={{$.Link}}"><i class="octicon octicon-person"></i> {{$.i18n.Tr "user.follow"}}</a> |
||||||
|
{{end}} |
||||||
|
</div> |
||||||
|
{{end}} |
||||||
|
{{end}} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{{end}} |
||||||
|
<div class="ui divider"></div> |
Loading…
Reference in new issue