From 1c7e4d0290f5c97c374fe58dc163126c4ab414dc Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Thu, 22 Nov 2018 10:27:53 +0900 Subject: [PATCH] Implemented group image upload --- pages/groups/fetch.go | 9 +++++ pages/groups/groups.go | 40 --------------------- pages/groups/groups.pixy | 29 +++++++++------- pages/groups/groups.scarlet | 4 --- pages/groups/latest.go | 18 ++++++++++ pages/groups/popular.go | 22 ++++++++++++ pages/groups/render.go | 43 +++++++++++++++++++++++ pages/index/apiroutes/apiroutes.go | 1 + pages/index/grouproutes/grouproutes.go | 5 ++- pages/upload/group.go | 48 ++++++++++++++++++++++++++ 10 files changed, 161 insertions(+), 58 deletions(-) create mode 100644 pages/groups/fetch.go delete mode 100644 pages/groups/groups.go create mode 100644 pages/groups/latest.go create mode 100644 pages/groups/popular.go create mode 100644 pages/groups/render.go create mode 100644 pages/upload/group.go diff --git a/pages/groups/fetch.go b/pages/groups/fetch.go new file mode 100644 index 00000000..7dab0e3c --- /dev/null +++ b/pages/groups/fetch.go @@ -0,0 +1,9 @@ +package groups + +import "github.com/animenotifier/arn" + +func fetchGroups() []*arn.Group { + return arn.FilterGroups(func(group *arn.Group) bool { + return !group.IsDraft + }) +} diff --git a/pages/groups/groups.go b/pages/groups/groups.go deleted file mode 100644 index 04082165..00000000 --- a/pages/groups/groups.go +++ /dev/null @@ -1,40 +0,0 @@ -package groups - -import ( - "net/http" - "sort" - - "github.com/aerogo/aero" - "github.com/animenotifier/arn" - "github.com/animenotifier/notify.moe/components" - "github.com/animenotifier/notify.moe/utils" -) - -const groupsPerPage = 12 - -// Get ... -func Get(ctx *aero.Context) string { - user := utils.GetUser(ctx) - - groups, err := arn.FilterGroups(func(group *arn.Group) bool { - return !group.IsDraft - }) - - sort.Slice(groups, func(i, j int) bool { - if len(groups[i].Members) == len(groups[j].Members) { - return groups[i].Created > groups[j].Created - } - - return len(groups[i].Members) > len(groups[j].Members) - }) - - if len(groups) > groupsPerPage { - groups = groups[:groupsPerPage] - } - - if err != nil { - return ctx.Error(http.StatusInternalServerError, "Error fetching groups", err) - } - - return ctx.HTML(components.Groups(groups, groupsPerPage, user)) -} diff --git a/pages/groups/groups.pixy b/pages/groups/groups.pixy index 67fab353..321e2c4a 100644 --- a/pages/groups/groups.pixy +++ b/pages/groups/groups.pixy @@ -1,4 +1,4 @@ -component Groups(groups []*arn.Group, groupsPerPage int, user *arn.User) +component Groups(groups []*arn.Group, nextIndex int, user *arn.User) .tabs Tab("Groups", "users", "/groups") @@ -16,17 +16,20 @@ component Groups(groups []*arn.Group, groupsPerPage int, user *arn.User) span Edit draft #load-more-target.groups - each group in groups - a.group.mountable(href=group.Link()) - img.group-image.lazy(data-src=group.ImageLink("small"), data-webp="true", data-color=group.AverageColor(), alt=group.Name) - - .group-info - h3.group-name= group.Name - .group-tagline= group.Tagline - .group-member-count - Icon("user") - span= len(group.Members) + GroupsScrollable(groups, user) - if len(groups) == groupsPerPage + if nextIndex != -1 .buttons - LoadMore(groupsPerPage) \ No newline at end of file + LoadMore(nextIndex) + +component GroupsScrollable(groups []*arn.Group, user *arn.User) + each group in groups + a.group.mountable(href=group.Link()) + img.group-image.lazy(data-src=group.ImageLink("small"), data-webp="true", data-color=group.AverageColor(), alt=group.Name) + + .group-info + h3.group-name= group.Name + .group-tagline= group.Tagline + .group-member-count + Icon("user") + span= len(group.Members) \ No newline at end of file diff --git a/pages/groups/groups.scarlet b/pages/groups/groups.scarlet index b5dbfa9d..d985a5fa 100644 --- a/pages/groups/groups.scarlet +++ b/pages/groups/groups.scarlet @@ -14,8 +14,6 @@ const group-padding-x = 0.75rem horizontal ui-element position relative - // width 100% - // max-width 520px padding group-padding-y group-padding-x color text-color @@ -29,8 +27,6 @@ const group-padding-x = 0.75rem overflow hidden .group-name - // horizontal - // align-items center clip-long-text .group-tagline diff --git a/pages/groups/latest.go b/pages/groups/latest.go new file mode 100644 index 00000000..ac9e24d4 --- /dev/null +++ b/pages/groups/latest.go @@ -0,0 +1,18 @@ +package groups + +import ( + "sort" + + "github.com/aerogo/aero" +) + +// Latest shows the latest groups. +func Latest(ctx *aero.Context) string { + groups := fetchGroups() + + sort.Slice(groups, func(i, j int) bool { + return groups[i].Created > groups[j].Created + }) + + return render(ctx, groups) +} diff --git a/pages/groups/popular.go b/pages/groups/popular.go new file mode 100644 index 00000000..1547cf54 --- /dev/null +++ b/pages/groups/popular.go @@ -0,0 +1,22 @@ +package groups + +import ( + "sort" + + "github.com/aerogo/aero" +) + +// Popular shows the most popular groups. +func Popular(ctx *aero.Context) string { + groups := fetchGroups() + + sort.Slice(groups, func(i, j int) bool { + if len(groups[i].Members) == len(groups[j].Members) { + return groups[i].Created > groups[j].Created + } + + return len(groups[i].Members) > len(groups[j].Members) + }) + + return render(ctx, groups) +} diff --git a/pages/groups/render.go b/pages/groups/render.go new file mode 100644 index 00000000..d507738f --- /dev/null +++ b/pages/groups/render.go @@ -0,0 +1,43 @@ +package groups + +import ( + "github.com/aerogo/aero" + "github.com/animenotifier/arn" + "github.com/animenotifier/notify.moe/components" + "github.com/animenotifier/notify.moe/utils" + "github.com/animenotifier/notify.moe/utils/infinitescroll" +) + +const ( + groupsFirstLoad = 12 + groupsPerScroll = 9 +) + +// render renders the groups page with the given groups. +func render(ctx *aero.Context, allGroups []*arn.Group) string { + user := utils.GetUser(ctx) + index, _ := ctx.GetInt("index") + + // Slice the part that we need + groups := allGroups[index:] + maxLength := groupsFirstLoad + + if index > 0 { + maxLength = groupsPerScroll + } + + if len(groups) > maxLength { + groups = groups[:maxLength] + } + + // Next index + nextIndex := infinitescroll.NextIndex(ctx, len(allGroups), maxLength, index) + + // In case we're scrolling, send groups only (without the page frame) + if index > 0 { + return ctx.HTML(components.GroupsScrollable(groups, user)) + } + + // Otherwise, send the full page + return ctx.HTML(components.Groups(groups, nextIndex, user)) +} diff --git a/pages/index/apiroutes/apiroutes.go b/pages/index/apiroutes/apiroutes.go index c9140c92..c64994ac 100644 --- a/pages/index/apiroutes/apiroutes.go +++ b/pages/index/apiroutes/apiroutes.go @@ -60,6 +60,7 @@ func Register(l *layout.Layout, app *aero.Application) { app.Post("/api/upload/cover", upload.Cover) app.Post("/api/upload/anime/:id/image", upload.AnimeImage) app.Post("/api/upload/character/:id/image", upload.CharacterImage) + app.Post("/api/upload/group/:id/image", upload.GroupImage) app.Post("/api/upload/amv/:id/file", upload.AMVFile) // Import anime diff --git a/pages/index/grouproutes/grouproutes.go b/pages/index/grouproutes/grouproutes.go index 673ea7ce..2975bf11 100644 --- a/pages/index/grouproutes/grouproutes.go +++ b/pages/index/grouproutes/grouproutes.go @@ -9,7 +9,10 @@ import ( // Register registers the page routes. func Register(l *layout.Layout) { // Groups - l.Page("/groups", groups.Get) + l.Page("/groups", groups.Latest) + l.Page("/groups/from/:index", groups.Latest) + l.Page("/groups/popular", groups.Popular) + l.Page("/groups/popular/from/:index", groups.Popular) l.Page("/group/:id", group.Feed) l.Page("/group/:id/info", group.Info) l.Page("/group/:id/members", group.Members) diff --git a/pages/upload/group.go b/pages/upload/group.go new file mode 100644 index 00000000..924f7773 --- /dev/null +++ b/pages/upload/group.go @@ -0,0 +1,48 @@ +package upload + +import ( + "net/http" + + "github.com/aerogo/aero" + "github.com/animenotifier/arn" + "github.com/animenotifier/notify.moe/utils" +) + +// GroupImage handles the group image upload. +func GroupImage(ctx *aero.Context) string { + user := utils.GetUser(ctx) + groupID := ctx.Get("id") + + if user == nil || (user.Role != "editor" && user.Role != "admin") { + return ctx.Error(http.StatusUnauthorized, "Not authorized") + } + + group, err := arn.GetGroup(groupID) + + if err != nil { + return ctx.Error(http.StatusNotFound, "Group not found", err) + } + + // Retrieve file from post body + data, err := ctx.Request().Body().Bytes() + + if err != nil { + return ctx.Error(http.StatusInternalServerError, "Reading request body failed", err) + } + + // Set group image file + err = group.SetImageBytes(data) + + if err != nil { + return ctx.Error(http.StatusInternalServerError, "Invalid image format", err) + } + + // Save image information + group.Save() + + // Write log entry + logEntry := arn.NewEditLogEntry(user.ID, "edit", "Group", group.ID, "Image", "", "") + logEntry.Save() + + return "ok" +}