view: added start download button to subreddit details page
This commit is contained in:
parent
fe1ad50670
commit
08d81a2f94
|
@ -28,8 +28,10 @@ func (routes *Routes) Register(router chi.Router) {
|
||||||
router.Get("/hot_reload", routes.CreateHotReloadRoute())
|
router.Get("/hot_reload", routes.CreateHotReloadRoute())
|
||||||
}
|
}
|
||||||
|
|
||||||
router.Group(routes.registerWWWRoutes)
|
router.Route("/htmx", routes.registerHTMXRoutes)
|
||||||
router.Route("/api/v1", routes.registerV1APIRoutes)
|
router.Route("/api/v1", routes.registerV1APIRoutes)
|
||||||
|
|
||||||
|
router.Group(routes.registerWWWRoutes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (routes *Routes) registerV1APIRoutes(router chi.Router) {
|
func (routes *Routes) registerV1APIRoutes(router chi.Router) {
|
||||||
|
@ -51,6 +53,14 @@ func (routes *Routes) registerV1APIRoutes(router chi.Router) {
|
||||||
router.Get("/events", routes.EventsAPI)
|
router.Get("/events", routes.EventsAPI)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (routes *Routes) registerHTMXRoutes(router chi.Router) {
|
||||||
|
router.Use(otelchi.Middleware("redmage"))
|
||||||
|
router.Use(chimiddleware.RequestLogger(middleware.ChiLogger{}))
|
||||||
|
router.Use(chimiddleware.SetHeader("Content-Type", "text/html; charset=utf-8"))
|
||||||
|
|
||||||
|
router.Post("/subreddits/start", routes.SubredditStartDownloadHTMX)
|
||||||
|
}
|
||||||
|
|
||||||
func (routes *Routes) registerWWWRoutes(router chi.Router) {
|
func (routes *Routes) registerWWWRoutes(router chi.Router) {
|
||||||
router.Mount("/public", http.StripPrefix("/public", http.FileServer(http.FS(routes.PublicDir))))
|
router.Mount("/public", http.StripPrefix("/public", http.FileServer(http.FS(routes.PublicDir))))
|
||||||
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
package routes
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/tigorlazuardi/redmage/api"
|
|
||||||
"github.com/tigorlazuardi/redmage/pkg/errs"
|
|
||||||
"github.com/tigorlazuardi/redmage/pkg/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (r *Routes) SubredditStartDownloadAPI(rw http.ResponseWriter, req *http.Request) {
|
|
||||||
enc := json.NewEncoder(rw)
|
|
||||||
if r.Config.String("download.directory") == "" {
|
|
||||||
rw.WriteHeader(http.StatusBadRequest)
|
|
||||||
_ = enc.Encode(map[string]string{"error": "cannot download subreddits when download directory is not configured"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := req.Context()
|
|
||||||
|
|
||||||
var body api.PubsubStartDownloadSubredditParams
|
|
||||||
|
|
||||||
err := json.NewDecoder(req.Body).Decode(&body)
|
|
||||||
if err != nil {
|
|
||||||
rw.WriteHeader(http.StatusBadRequest)
|
|
||||||
_ = enc.Encode(map[string]string{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = r.API.PubsubStartDownloadSubreddit(ctx, body)
|
|
||||||
if err != nil {
|
|
||||||
log.New(ctx).Err(err).Error("failed to start subreddit download", "subreddit", body.Subreddit)
|
|
||||||
code, message := errs.HTTPMessage(err)
|
|
||||||
rw.WriteHeader(code)
|
|
||||||
_ = enc.Encode(map[string]string{"error": message})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = enc.Encode(map[string]string{"message": "subreddit enqueued"})
|
|
||||||
}
|
|
77
server/routes/subreddit_start.go
Normal file
77
server/routes/subreddit_start.go
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/tigorlazuardi/redmage/api"
|
||||||
|
"github.com/tigorlazuardi/redmage/pkg/errs"
|
||||||
|
"github.com/tigorlazuardi/redmage/pkg/log"
|
||||||
|
"github.com/tigorlazuardi/redmage/views/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *Routes) SubredditStartDownloadAPI(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
ctx, span := tracer.Start(req.Context(), "Routes.SubredditStartDownloadAPI")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
enc := json.NewEncoder(rw)
|
||||||
|
if r.Config.String("download.directory") == "" {
|
||||||
|
rw.WriteHeader(http.StatusBadRequest)
|
||||||
|
_ = enc.Encode(map[string]string{"error": "cannot download subreddits when download directory is not configured"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var body api.PubsubStartDownloadSubredditParams
|
||||||
|
|
||||||
|
err := json.NewDecoder(req.Body).Decode(&body)
|
||||||
|
if err != nil {
|
||||||
|
rw.WriteHeader(http.StatusBadRequest)
|
||||||
|
_ = enc.Encode(map[string]string{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = r.API.PubsubStartDownloadSubreddit(ctx, body)
|
||||||
|
if err != nil {
|
||||||
|
log.New(ctx).Err(err).Error("failed to start subreddit download", "subreddit", body.Subreddit)
|
||||||
|
code, message := errs.HTTPMessage(err)
|
||||||
|
rw.WriteHeader(code)
|
||||||
|
_ = enc.Encode(map[string]string{"error": message})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = enc.Encode(map[string]string{"message": "subreddit enqueued"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (routes *Routes) SubredditStartDownloadHTMX(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx, span := tracer.Start(r.Context(), "Routes.SubredditStartDownloadHTMX")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
if routes.Config.String("download.directory") == "" {
|
||||||
|
rw.WriteHeader(http.StatusBadRequest)
|
||||||
|
if err := components.ErrorNotication("Cannot download subreddits when download directory is not configured").Render(ctx, rw); err != nil {
|
||||||
|
log.New(ctx).Err(err).Error("failed to render error notification")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var body api.PubsubStartDownloadSubredditParams
|
||||||
|
body.Subreddit = r.FormValue("subreddit")
|
||||||
|
|
||||||
|
err := routes.API.PubsubStartDownloadSubreddit(ctx, body)
|
||||||
|
if err != nil {
|
||||||
|
log.New(ctx).Err(err).Error("failed to start subreddit download", "subreddit", body.Subreddit)
|
||||||
|
code, message := errs.HTTPMessage(err)
|
||||||
|
rw.WriteHeader(code)
|
||||||
|
if err := components.ErrorNotication(message).Render(ctx, rw); err != nil {
|
||||||
|
log.New(ctx).Err(err).Error("failed to render error notification")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := fmt.Sprintf("Subreddit %s enqueued", body.Subreddit)
|
||||||
|
|
||||||
|
if err := components.SuccessNotification(msg).Render(ctx, rw); err != nil {
|
||||||
|
log.New(ctx).Err(err).Error("failed to render success notification")
|
||||||
|
}
|
||||||
|
}
|
58
views/components/notification.templ
Normal file
58
views/components/notification.templ
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
package components
|
||||||
|
|
||||||
|
const NotificationContainerID = "#notification-container"
|
||||||
|
|
||||||
|
templ NotificationContainer() {
|
||||||
|
<div id="notification-container" class="fixed bottom-4 right-4 z-50"></div>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ InfoNotication(messages ...string) {
|
||||||
|
<div
|
||||||
|
hx-on::load="setTimeout(() => this.remove(), 5000)"
|
||||||
|
class="toast"
|
||||||
|
onclick="this.remove()"
|
||||||
|
>
|
||||||
|
<div class="alert alert-info hover:bg-info-content transition-all">
|
||||||
|
for i, message := range messages {
|
||||||
|
<span>{ message }</span>
|
||||||
|
if i != len(messages) - 1 {
|
||||||
|
<br/>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ ErrorNotication(messages ...string) {
|
||||||
|
<div
|
||||||
|
hx-on::load="setTimeout(() => this.remove(), 5000)"
|
||||||
|
class="toast"
|
||||||
|
onclick="this.remove()"
|
||||||
|
>
|
||||||
|
<div class="alert alert-error hover:bg-error-content transition-all">
|
||||||
|
for i, message := range messages {
|
||||||
|
<span>{ message }</span>
|
||||||
|
if i != len(messages) - 1 {
|
||||||
|
<br/>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ SuccessNotification(messages ...string) {
|
||||||
|
<div
|
||||||
|
hx-on::load="setTimeout(() => this.remove(), 5000)"
|
||||||
|
class="toast"
|
||||||
|
onclick="this.remove()"
|
||||||
|
>
|
||||||
|
<div class="alert alert-success hover:bg-success-content transition-all">
|
||||||
|
for i, message := range messages {
|
||||||
|
<span>{ message }</span>
|
||||||
|
if i != len(messages) - 1 {
|
||||||
|
<br/>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ templ Detailsview(c *views.Context, data Data) {
|
||||||
@components.Head(c, components.HeadTitle("Redmage - Subreddits"))
|
@components.Head(c, components.HeadTitle("Redmage - Subreddits"))
|
||||||
@components.Body(c) {
|
@components.Body(c) {
|
||||||
@DetailsContent(c, data)
|
@DetailsContent(c, data)
|
||||||
|
@components.NotificationContainer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,10 +32,23 @@ templ DetailsContent(c *views.Context, data Data) {
|
||||||
<h1>Error: { data.Error }</h1>
|
<h1>Error: { data.Error }</h1>
|
||||||
} else {
|
} else {
|
||||||
<h1>Subreddit { data.Subreddit.Name }</h1>
|
<h1>Subreddit { data.Subreddit.Name }</h1>
|
||||||
<h2>
|
<div class="flex flex-wrap justify-between content-center">
|
||||||
Total Images:
|
<h2 class="my-auto">
|
||||||
{ strconv.FormatInt(data.TotalImages, 10) }
|
Total Images:
|
||||||
</h2>
|
{ strconv.FormatInt(data.TotalImages, 10) }
|
||||||
|
</h2>
|
||||||
|
<button
|
||||||
|
hx-post="/htmx/subreddits/start"
|
||||||
|
hx-include="this"
|
||||||
|
class="btn btn-info"
|
||||||
|
hx-target={ components.NotificationContainerID }
|
||||||
|
hx-target-error={ components.NotificationContainerID }
|
||||||
|
hx-swap="afterbegin"
|
||||||
|
>
|
||||||
|
Start Download
|
||||||
|
<input type="hidden" name="subreddit" value={ data.Subreddit.Name }/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<div class="flex gap-4 flex-wrap justify-between content-center">
|
<div class="flex gap-4 flex-wrap justify-between content-center">
|
||||||
@FilterBar(c, data)
|
@FilterBar(c, data)
|
||||||
|
|
Loading…
Reference in a new issue