diff --git a/mixins/Avatar.pixy b/mixins/Avatar.pixy index 990191cf..eef0393a 100644 --- a/mixins/Avatar.pixy +++ b/mixins/Avatar.pixy @@ -9,10 +9,14 @@ component AvatarNoLink(user *arn.User) if user.HasAvatar() img.user-image.lazy(data-src=user.SmallAvatar(), data-webp="true", alt=user.Nick) else - SVGAvatar + SVGAvatar(user) -component SVGAvatar +component SVGAvatar(user *arn.User) svg.user-image(viewBox="0 0 50 50") circle.head(cx="25", cy="19", r="10") circle.body(cx="25", cy="50", r="20") - //- text(x="25", y="44", text-anchor="middle") TODO \ No newline at end of file + + if len(user.Nick) <= 6 + text.svg-nick(x="25", y="44", text-anchor="middle")= user.Nick + else + text.svg-nick(x="25", y="44", text-anchor="middle")= user.Nick[:6] \ No newline at end of file diff --git a/pages/index.go b/pages/index.go index 809234b5..532da9f4 100644 --- a/pages/index.go +++ b/pages/index.go @@ -80,7 +80,9 @@ func Configure(app *aero.Application) { // User lists l.Page("/users", users.Active) + l.Page("/users/noavatar", users.ActiveNoAvatar) l.Page("/users/osu", users.Osu) + l.Page("/users/overwatch", users.Overwatch) l.Page("/users/staff", users.Staff) // Statistics diff --git a/pages/users/overwatch.pixy b/pages/users/overwatch.pixy new file mode 100644 index 00000000..975f4b08 --- /dev/null +++ b/pages/users/overwatch.pixy @@ -0,0 +1,22 @@ +component OverwatchRankingList(users []*arn.User) + h1.page-title Overwatch ranking list + + UsersTabs + + table.osu-ranking-list + thead + tr.mountable + th # + th Player + th Name + th.osu-ranking-pp Skill Rating + tbody + for index, user := range users + tr.osu-ranking.mountable + td= toString(index + 1) + "." + td + Avatar(user) + td + a.ajax(href=user.Link())= user.Nick + td.osu-ranking-pp= strconv.Itoa(user.Accounts.Overwatch.SkillRating) + " SR" + \ No newline at end of file diff --git a/pages/users/users.go b/pages/users/users.go index b087b39f..0973ecf1 100644 --- a/pages/users/users.go +++ b/pages/users/users.go @@ -6,6 +6,7 @@ import ( "github.com/aerogo/aero" "github.com/animenotifier/arn" "github.com/animenotifier/notify.moe/components" + "github.com/animenotifier/notify.moe/utils" ) // Active ... @@ -21,6 +22,14 @@ func Active(ctx *aero.Context) string { } sort.Slice(users, func(i, j int) bool { + if users[i].HasAvatar() != users[j].HasAvatar() { + if users[i].HasAvatar() { + return true + } + + return false + } + followersA := followCount[users[i]] followersB := followCount[users[j]] @@ -31,7 +40,39 @@ func Active(ctx *aero.Context) string { return followersA > followersB }) - // arn.SortUsersLastSeen(users) + return ctx.HTML(components.Users(users)) +} + +// ActiveNoAvatar ... +func ActiveNoAvatar(ctx *aero.Context) string { + users := arn.FilterUsers(func(user *arn.User) bool { + return user.IsActive() && !user.HasAvatar() + }) + + followCount := map[*arn.User]int{} + + for _, user := range users { + followCount[user] = user.FollowersCount() + } + + sort.Slice(users, func(i, j int) bool { + if users[i].HasAvatar() != users[j].HasAvatar() { + if users[i].HasAvatar() { + return true + } + + return false + } + + followersA := followCount[users[i]] + followersB := followCount[users[j]] + + if followersA == followersB { + return users[i].Nick < users[j].Nick + } + + return followersA > followersB + }) return ctx.HTML(components.Users(users)) } @@ -54,23 +95,74 @@ func Osu(ctx *aero.Context) string { return ctx.HTML(components.OsuRankingList(users)) } +// Overwatch ... +func Overwatch(ctx *aero.Context) string { + users := arn.FilterUsers(func(user *arn.User) bool { + return user.IsActive() && user.HasAvatar() && user.Accounts.Overwatch.SkillRating > 0 + }) + + // Sort by Skill Ratings + sort.Slice(users, func(i, j int) bool { + return users[i].Accounts.Overwatch.SkillRating > users[j].Accounts.Overwatch.SkillRating + }) + + if len(users) > 50 { + users = users[:50] + } + + return ctx.HTML(components.OverwatchRankingList(users)) +} + // Staff ... func Staff(ctx *aero.Context) string { users := arn.FilterUsers(func(user *arn.User) bool { return user.IsActive() && user.HasAvatar() && user.Role != "" }) + // Make order deterministic sort.Slice(users, func(i, j int) bool { - if users[i].Role == "" { - return false - } - - if users[j].Role == "" { - return true - } - - return users[i].Role == "admin" + return users[i].Nick < users[j].Nick }) - return ctx.HTML(components.Users(users)) + admins := &utils.UserList{ + Name: "Developer", + Users: []*arn.User{}, + } + + contributors := &utils.UserList{ + Name: "Contributors", + Users: []*arn.User{}, + } + + // contributors.Users = append(contributors.Users, ) + + editors := &utils.UserList{ + Name: "Editors", + Users: []*arn.User{}, + } + + for _, user := range users { + if user.Role == "admin" { + admins.Users = append(admins.Users, user) + continue + } + + if user.ID == "VJOK1ckvx" || user.ID == "SUQOAFFkR" { + contributors.Users = append(contributors.Users, user) + continue + } + + if user.Role == "editor" { + editors.Users = append(editors.Users, user) + continue + } + } + + userLists := []*utils.UserList{ + admins, + contributors, + editors, + } + + return ctx.HTML(components.UserLists(userLists)) } diff --git a/pages/users/users.pixy b/pages/users/users.pixy index 4a12d8f5..4b59ac19 100644 --- a/pages/users/users.pixy +++ b/pages/users/users.pixy @@ -8,8 +8,23 @@ component Users(users []*arn.User) .mountable Avatar(user) +component UserLists(groups []*utils.UserList) + h1.page-title Users + + UsersTabs + + each group in groups + h3.user-list-name.mountable= group.Name + + .user-avatars + each user in group.Users + .mountable + Avatar(user) + component UsersTabs .tabs Tab("Active", "users", "/users") + Tab("No Avatar", "users", "/users/noavatar") Tab("Osu", "gamepad", "/users/osu") + Tab("Overwatch", "overwatch", "/users/overwatch") Tab("Staff", "user-secret", "/users/staff") \ No newline at end of file diff --git a/pages/users/users.scarlet b/pages/users/users.scarlet index 141ac59d..7df23240 100644 --- a/pages/users/users.scarlet +++ b/pages/users/users.scarlet @@ -7,4 +7,7 @@ margin 0.4rem .user - display flex \ No newline at end of file + display flex + +.user-list-name + text-align center \ No newline at end of file diff --git a/styles/svg.scarlet b/styles/svg.scarlet index a2b035ad..314c5405 100644 --- a/styles/svg.scarlet +++ b/styles/svg.scarlet @@ -2,4 +2,8 @@ fill text-color .body - fill text-color \ No newline at end of file + fill text-color + +.svg-nick + fill bg-color + font-size 50% \ No newline at end of file diff --git a/utils/FilterCapitalLetters.go b/utils/FilterCapitalLetters.go new file mode 100644 index 00000000..3cbe49af --- /dev/null +++ b/utils/FilterCapitalLetters.go @@ -0,0 +1,20 @@ +package utils + +// import ( +// "strings" +// "unicode" +// ) + +// // FilterCapitalLetters returns the capital letters of a name. +// func FilterCapitalLetters(nick string) string { +// return strings.Map( +// func(r rune) rune { +// if !unicode.IsUpper(r) { +// return -1 +// } + +// return r +// }, +// nick, +// ) +// } diff --git a/utils/UserList.go b/utils/UserList.go new file mode 100644 index 00000000..b4a98f4d --- /dev/null +++ b/utils/UserList.go @@ -0,0 +1,9 @@ +package utils + +import "github.com/animenotifier/arn" + +// UserList is a named list of users. +type UserList struct { + Name string + Users []*arn.User +}