view(home): add device filter and pagination to home view
Some checks failed
/ push (push) Has been cancelled

This commit is contained in:
Tigor Hutasuhut 2024-05-29 19:39:02 +07:00
parent 8a0a139e50
commit f07b1f4bf9
5 changed files with 67 additions and 5 deletions

View file

@ -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 {

View file

@ -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))

View file

@ -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()

View file

@ -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>
}

View file

@ -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