#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" .}} |
||||
<div class="repository watchers"> |
||||
{{template "repo/header" .}} |
||||
<div class="ui container"> |
||||
<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> |
||||
{{template "repo/user_cards" .}} |
||||
</div> |
||||
{{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