Implemented group image upload
This commit is contained in:
parent
f8be03d4c5
commit
1c7e4d0290
9
pages/groups/fetch.go
Normal file
9
pages/groups/fetch.go
Normal file
@ -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
|
||||||
|
})
|
||||||
|
}
|
@ -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))
|
|
||||||
}
|
|
@ -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
|
.tabs
|
||||||
Tab("Groups", "users", "/groups")
|
Tab("Groups", "users", "/groups")
|
||||||
|
|
||||||
@ -16,17 +16,20 @@ component Groups(groups []*arn.Group, groupsPerPage int, user *arn.User)
|
|||||||
span Edit draft
|
span Edit draft
|
||||||
|
|
||||||
#load-more-target.groups
|
#load-more-target.groups
|
||||||
each group in groups
|
GroupsScrollable(groups, user)
|
||||||
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
|
if nextIndex != -1
|
||||||
h3.group-name= group.Name
|
|
||||||
.group-tagline= group.Tagline
|
|
||||||
.group-member-count
|
|
||||||
Icon("user")
|
|
||||||
span= len(group.Members)
|
|
||||||
|
|
||||||
if len(groups) == groupsPerPage
|
|
||||||
.buttons
|
.buttons
|
||||||
LoadMore(groupsPerPage)
|
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)
|
@ -14,8 +14,6 @@ const group-padding-x = 0.75rem
|
|||||||
horizontal
|
horizontal
|
||||||
ui-element
|
ui-element
|
||||||
position relative
|
position relative
|
||||||
// width 100%
|
|
||||||
// max-width 520px
|
|
||||||
padding group-padding-y group-padding-x
|
padding group-padding-y group-padding-x
|
||||||
color text-color
|
color text-color
|
||||||
|
|
||||||
@ -29,8 +27,6 @@ const group-padding-x = 0.75rem
|
|||||||
overflow hidden
|
overflow hidden
|
||||||
|
|
||||||
.group-name
|
.group-name
|
||||||
// horizontal
|
|
||||||
// align-items center
|
|
||||||
clip-long-text
|
clip-long-text
|
||||||
|
|
||||||
.group-tagline
|
.group-tagline
|
||||||
|
18
pages/groups/latest.go
Normal file
18
pages/groups/latest.go
Normal file
@ -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)
|
||||||
|
}
|
22
pages/groups/popular.go
Normal file
22
pages/groups/popular.go
Normal file
@ -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)
|
||||||
|
}
|
43
pages/groups/render.go
Normal file
43
pages/groups/render.go
Normal file
@ -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))
|
||||||
|
}
|
@ -60,6 +60,7 @@ func Register(l *layout.Layout, app *aero.Application) {
|
|||||||
app.Post("/api/upload/cover", upload.Cover)
|
app.Post("/api/upload/cover", upload.Cover)
|
||||||
app.Post("/api/upload/anime/:id/image", upload.AnimeImage)
|
app.Post("/api/upload/anime/:id/image", upload.AnimeImage)
|
||||||
app.Post("/api/upload/character/:id/image", upload.CharacterImage)
|
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)
|
app.Post("/api/upload/amv/:id/file", upload.AMVFile)
|
||||||
|
|
||||||
// Import anime
|
// Import anime
|
||||||
|
@ -9,7 +9,10 @@ import (
|
|||||||
// Register registers the page routes.
|
// Register registers the page routes.
|
||||||
func Register(l *layout.Layout) {
|
func Register(l *layout.Layout) {
|
||||||
// Groups
|
// 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", group.Feed)
|
||||||
l.Page("/group/:id/info", group.Info)
|
l.Page("/group/:id/info", group.Info)
|
||||||
l.Page("/group/:id/members", group.Members)
|
l.Page("/group/:id/members", group.Members)
|
||||||
|
48
pages/upload/group.go
Normal file
48
pages/upload/group.go
Normal file
@ -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"
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user