view(home): add device filter and pagination to home view
Some checks failed
/ push (push) Has been cancelled
Some checks failed
/ push (push) Has been cancelled
This commit is contained in:
parent
8a0a139e50
commit
f07b1f4bf9
|
@ -37,8 +37,10 @@ func (ilp *ImageListParams) FillFromQuery(query Queryable) {
|
||||||
ilp.OrderBy = query.Get("order_by")
|
ilp.OrderBy = query.Get("order_by")
|
||||||
ilp.Sort = strings.ToLower(query.Get("sort"))
|
ilp.Sort = strings.ToLower(query.Get("sort"))
|
||||||
ilp.Offset, _ = strconv.ParseInt(query.Get("offset"), 10, 64)
|
ilp.Offset, _ = strconv.ParseInt(query.Get("offset"), 10, 64)
|
||||||
ilp.Limit, _ = strconv.ParseInt(query.Get("limit"), 10, 64)
|
limit := query.Get("limit")
|
||||||
if ilp.Limit < 1 {
|
var err error
|
||||||
|
ilp.Limit, err = strconv.ParseInt(limit, 10, 64)
|
||||||
|
if err != nil || ilp.Limit < 0 {
|
||||||
ilp.Limit = 25
|
ilp.Limit = 25
|
||||||
}
|
}
|
||||||
ilp.Device = query.Get("device")
|
ilp.Device = query.Get("device")
|
||||||
|
@ -88,6 +90,8 @@ func (ilp ImageListParams) Query() (expr []bob.Mod[*dialect.SelectQuery]) {
|
||||||
expr = append(expr, ilp.CountQuery()...)
|
expr = append(expr, ilp.CountQuery()...)
|
||||||
if ilp.Limit > 0 {
|
if ilp.Limit > 0 {
|
||||||
expr = append(expr, sm.Limit(ilp.Limit))
|
expr = append(expr, sm.Limit(ilp.Limit))
|
||||||
|
} else if ilp.Offset > 0 {
|
||||||
|
expr = append(expr, sm.Limit(-1))
|
||||||
}
|
}
|
||||||
|
|
||||||
if ilp.Offset > 0 {
|
if ilp.Offset > 0 {
|
||||||
|
|
|
@ -51,6 +51,8 @@ func (l ListSubredditsParams) Query() (expr []bob.Mod[*dialect.SelectQuery]) {
|
||||||
}
|
}
|
||||||
if l.Limit > 0 {
|
if l.Limit > 0 {
|
||||||
expr = append(expr, sm.Limit(l.Limit))
|
expr = append(expr, sm.Limit(l.Limit))
|
||||||
|
} else if l.Offset > 0 {
|
||||||
|
expr = append(expr, sm.Limit(-1))
|
||||||
}
|
}
|
||||||
if l.Offset > 0 {
|
if l.Offset > 0 {
|
||||||
expr = append(expr, sm.Offset(l.Offset))
|
expr = append(expr, sm.Offset(l.Offset))
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/tigorlazuardi/redmage/api"
|
||||||
"github.com/tigorlazuardi/redmage/pkg/errs"
|
"github.com/tigorlazuardi/redmage/pkg/errs"
|
||||||
"github.com/tigorlazuardi/redmage/pkg/log"
|
"github.com/tigorlazuardi/redmage/pkg/log"
|
||||||
"github.com/tigorlazuardi/redmage/views"
|
"github.com/tigorlazuardi/redmage/views"
|
||||||
|
@ -20,6 +21,7 @@ func (routes *Routes) PageHome(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
data.ListSubredditParams.FillFromQuery(r.URL.Query())
|
data.ListSubredditParams.FillFromQuery(r.URL.Query())
|
||||||
data.ListSubredditParams.Limit = 0
|
data.ListSubredditParams.Limit = 0
|
||||||
|
data.ListSubredditParams.Offset = 0
|
||||||
list, err := routes.API.ListSubreddits(ctx, data.ListSubredditParams)
|
list, err := routes.API.ListSubreddits(ctx, data.ListSubredditParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.New(ctx).Err(err).Error("failed to list subreddits")
|
log.New(ctx).Err(err).Error("failed to list subreddits")
|
||||||
|
@ -36,7 +38,9 @@ func (routes *Routes) PageHome(rw http.ResponseWriter, r *http.Request) {
|
||||||
if data.ImageListParams.CreatedAt.IsZero() {
|
if data.ImageListParams.CreatedAt.IsZero() {
|
||||||
data.ImageListParams.CreatedAt = time.Now().Add(-time.Hour * 24) // images in the last 24 hours
|
data.ImageListParams.CreatedAt = time.Now().Add(-time.Hour * 24) // images in the last 24 hours
|
||||||
}
|
}
|
||||||
data.ImageListParams.Limit = 0
|
if r.URL.Query().Get("limit") == "" {
|
||||||
|
data.ImageListParams.Limit = 100
|
||||||
|
}
|
||||||
|
|
||||||
imageList, err := routes.API.ImagesListWithDevicesAndSubreddits(ctx, data.ImageListParams)
|
imageList, err := routes.API.ImagesListWithDevicesAndSubreddits(ctx, data.ImageListParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -50,6 +54,17 @@ func (routes *Routes) PageHome(rw http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.Devices, err = routes.API.GetDevices(ctx, api.DevicesListParams{Status: -1})
|
||||||
|
if err != nil {
|
||||||
|
log.New(ctx).Err(err).Error("failed to list subreddits")
|
||||||
|
code, message := errs.HTTPMessage(err)
|
||||||
|
data := homeview.Data{Error: message}
|
||||||
|
rw.WriteHeader(code)
|
||||||
|
if err := homeview.Home(vc, data).Render(ctx, rw); err != nil {
|
||||||
|
log.New(ctx).Err(err).Error("failed to render home view")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
data.SubredditsList = list
|
data.SubredditsList = list
|
||||||
data.RecentlyAddedImages = homeview.NewRecentlyAddedImages(imageList.Images)
|
data.RecentlyAddedImages = homeview.NewRecentlyAddedImages(imageList.Images)
|
||||||
data.Now = time.Now()
|
data.Now = time.Now()
|
||||||
|
|
|
@ -31,13 +31,22 @@ templ HomeContent(c *views.Context, data Data) {
|
||||||
<h1 class="mb-4">Recently Added</h1>
|
<h1 class="mb-4">Recently Added</h1>
|
||||||
@filterBar(c, data)
|
@filterBar(c, data)
|
||||||
<div id="recently-added-images">
|
<div id="recently-added-images">
|
||||||
if data.TotalImages == 0 {
|
if data.TotalImages <= 0 {
|
||||||
<h2 class="mt-4">There are no recently added images in the current time range.</h2>
|
<h2 class="mt-4">There are no recently added images in the current time range.</h2>
|
||||||
} else {
|
} else {
|
||||||
<h2 class="mt-4">
|
<h2 class="mt-4 text-center">
|
||||||
{ strconv.FormatInt(data.TotalImages, 10) } Images
|
{ strconv.FormatInt(data.TotalImages, 10) } Images
|
||||||
</h2>
|
</h2>
|
||||||
|
@showingImageFromTo(data)
|
||||||
}
|
}
|
||||||
|
<div class="grid justify-center">
|
||||||
|
@components.Pagination(c, components.PaginationData{
|
||||||
|
Limit: data.ImageListParams.Limit,
|
||||||
|
Total: data.TotalImages,
|
||||||
|
Offset: data.ImageListParams.Offset,
|
||||||
|
BaseURL: "/",
|
||||||
|
})
|
||||||
|
</div>
|
||||||
for _, recently := range data.RecentlyAddedImages {
|
for _, recently := range data.RecentlyAddedImages {
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<h2 class="mt-4">{ recently.Device.Name }</h2>
|
<h2 class="mt-4">{ recently.Device.Name }</h2>
|
||||||
|
@ -71,6 +80,22 @@ templ HomeContent(c *views.Context, data Data) {
|
||||||
</main>
|
</main>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
templ showingImageFromTo(data Data) {
|
||||||
|
if data.TotalImages > 1 {
|
||||||
|
<p class="text-center my-4">{ showingFromToImages(data) }</p>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func showingFromToImages(data Data) string {
|
||||||
|
params := data.ImageListParams
|
||||||
|
start := params.Offset + 1
|
||||||
|
end := params.Limit + params.Offset
|
||||||
|
if end > data.TotalImages {
|
||||||
|
end = data.TotalImages
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Showing from %d to %d", start, end)
|
||||||
|
}
|
||||||
|
|
||||||
templ filterBar(c *views.Context, data Data) {
|
templ filterBar(c *views.Context, data Data) {
|
||||||
<div
|
<div
|
||||||
id="filter-bar"
|
id="filter-bar"
|
||||||
|
@ -84,6 +109,7 @@ templ filterBar(c *views.Context, data Data) {
|
||||||
class="grid grid-cols-[1fr,4fr] sm:grid-cols-[1fr,4fr,1fr,4fr] items-center gap-4"
|
class="grid grid-cols-[1fr,4fr] sm:grid-cols-[1fr,4fr,1fr,4fr] items-center gap-4"
|
||||||
>
|
>
|
||||||
@nsfwToggle(data)
|
@nsfwToggle(data)
|
||||||
|
@deviceFilterInput(data)
|
||||||
@limitInput(data.ImageListParams)
|
@limitInput(data.ImageListParams)
|
||||||
@recentRangeInput(c.Query.Get("created_at"))
|
@recentRangeInput(c.Query.Get("created_at"))
|
||||||
</div>
|
</div>
|
||||||
|
@ -136,3 +162,17 @@ templ nsfwToggle(data Data) {
|
||||||
<option value="1" selected?={ data.ImageListParams.NSFW == 1 }>Show Only</option>
|
<option value="1" selected?={ data.ImageListParams.NSFW == 1 }>Show Only</option>
|
||||||
</select>
|
</select>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
templ deviceFilterInput(data Data) {
|
||||||
|
<label for="device" class="label">Device</label>
|
||||||
|
<select
|
||||||
|
id="device"
|
||||||
|
name="device"
|
||||||
|
class="select select-ghost select-bordered w-full"
|
||||||
|
>
|
||||||
|
<option value="" selected?={ data.ImageListParams.Device == "" }>*All Devices</option>
|
||||||
|
for _, device := range data.Devices {
|
||||||
|
<option value={ device.Slug } selected?={ data.ImageListParams.Device == device.Slug }>{ device.Name }</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ type Data struct {
|
||||||
Now time.Time
|
Now time.Time
|
||||||
ListSubredditParams api.ListSubredditsParams
|
ListSubredditParams api.ListSubredditsParams
|
||||||
ImageListParams api.ImageListParams
|
ImageListParams api.ImageListParams
|
||||||
|
Devices models.DeviceSlice
|
||||||
}
|
}
|
||||||
|
|
||||||
type RecentlyAddedImages = []RecentlyAddedImage
|
type RecentlyAddedImages = []RecentlyAddedImage
|
||||||
|
|
Loading…
Reference in a new issue