subreddit-add: added cron scheduler input
This commit is contained in:
parent
4e7f91d098
commit
f4399555b4
|
@ -60,6 +60,7 @@ func (routes *Routes) registerHTMXRoutes(router chi.Router) {
|
||||||
|
|
||||||
router.Post("/subreddits/start", routes.SubredditStartDownloadHTMX)
|
router.Post("/subreddits/start", routes.SubredditStartDownloadHTMX)
|
||||||
router.Post("/subreddits/check", routes.SubredditCheckHTMX)
|
router.Post("/subreddits/check", routes.SubredditCheckHTMX)
|
||||||
|
router.Get("/subreddits/validate/schedule", routes.SubredditValidateScheduleHTMX)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (routes *Routes) registerWWWRoutes(router chi.Router) {
|
func (routes *Routes) registerWWWRoutes(router chi.Router) {
|
||||||
|
|
|
@ -99,7 +99,7 @@ func (routes *Routes) SubredditCheckHTMX(rw http.ResponseWriter, r *http.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
if exist {
|
if exist {
|
||||||
rw.WriteHeader(http.StatusNotFound)
|
rw.WriteHeader(http.StatusConflict)
|
||||||
data.Error = "subreddit already registered"
|
data.Error = "subreddit already registered"
|
||||||
if err := addview.SubredditInputForm(data).Render(r.Context(), rw); err != nil {
|
if err := addview.SubredditInputForm(data).Render(r.Context(), rw); err != nil {
|
||||||
log.New(r.Context()).Err(err).Error("failed to render subreddit input form")
|
log.New(r.Context()).Err(err).Error("failed to render subreddit input form")
|
||||||
|
|
53
server/routes/subreddit_validate_schedule.go
Normal file
53
server/routes/subreddit_validate_schedule.go
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tigorlazuardi/redmage/pkg/log"
|
||||||
|
"github.com/tigorlazuardi/redmage/views/subredditsview/addview"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (routes *Routes) SubredditValidateScheduleHTMX(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx, span := tracer.Start(r.Context(), "*Routes.SubredditValidateScheduleHTMX")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
var data addview.ScheduleInputData
|
||||||
|
|
||||||
|
enabled, _ := strconv.Atoi(r.FormValue("enable_schedule"))
|
||||||
|
data.Disabled = enabled == 0
|
||||||
|
data.Value = r.FormValue("schedule")
|
||||||
|
|
||||||
|
if data.Value == "" {
|
||||||
|
if err := addview.ScheduleInput(data).Render(ctx, rw); err != nil {
|
||||||
|
log.New(ctx).Err(err).Error("failed to render schedule input")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.Disabled {
|
||||||
|
if err := addview.ScheduleInput(data).Render(ctx, rw); err != nil {
|
||||||
|
log.New(ctx).Err(err).Error("failed to render schedule input")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduler, err := cronParser.Parse(data.Value)
|
||||||
|
if err != nil {
|
||||||
|
data.Error = fmt.Sprintf("Invalid schedule format: %s", err.Error())
|
||||||
|
if err := addview.ScheduleInput(data).Render(ctx, rw); err != nil {
|
||||||
|
log.New(ctx).Err(err).Error("failed to render schedule input")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
next := scheduler.Next(time.Now())
|
||||||
|
|
||||||
|
data.Valid = fmt.Sprintf("Schedule is valid. Next run at: %s", next.Format("Monday, _2 January 2006 15:04:05 MST"))
|
||||||
|
|
||||||
|
if err := addview.ScheduleInput(data).Render(ctx, rw); err != nil {
|
||||||
|
log.New(ctx).Err(err).Error("failed to render schedule input")
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,6 +29,9 @@ templ AddviewContent(c *views.Context) {
|
||||||
<label id="subreddit-type-input" class="form-control w-full">
|
<label id="subreddit-type-input" class="form-control w-full">
|
||||||
@SubredditTypeInput(SubredditTypeData{})
|
@SubredditTypeInput(SubredditTypeData{})
|
||||||
</label>
|
</label>
|
||||||
|
<div class="flex gap-4 content-center">
|
||||||
|
@scheduleInputContainer()
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
}
|
}
|
||||||
</main>
|
</main>
|
||||||
|
|
81
views/subredditsview/addview/subreddit_schedule_input.templ
Normal file
81
views/subredditsview/addview/subreddit_schedule_input.templ
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
package addview
|
||||||
|
|
||||||
|
import "github.com/tigorlazuardi/redmage/views/utils"
|
||||||
|
|
||||||
|
type ScheduleInputData struct {
|
||||||
|
Value string
|
||||||
|
Error string
|
||||||
|
Valid string
|
||||||
|
Disabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
templ scheduleInputContainer() {
|
||||||
|
@ScheduleInput(ScheduleInputData{})
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => htmx.trigger('#schedule-input-group', 'change'))
|
||||||
|
</script>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ ScheduleInput(data ScheduleInputData) {
|
||||||
|
<div
|
||||||
|
id="schedule-input-group"
|
||||||
|
class="form-control w-full my-auto"
|
||||||
|
hx-get="/htmx/subreddits/validate/schedule"
|
||||||
|
hx-trigger="change, input delay:1s"
|
||||||
|
hx-include="this"
|
||||||
|
hx-target="this"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
>
|
||||||
|
<label class="label">
|
||||||
|
<span
|
||||||
|
class={ utils.CX(map[string]bool{
|
||||||
|
"label-text": true,
|
||||||
|
"text-error": data.Error != "",
|
||||||
|
"text-success": data.Valid != "",
|
||||||
|
"text-base": true,
|
||||||
|
}) }
|
||||||
|
>Schedule</span>
|
||||||
|
<div class="tooltip" data-tip="Whether to enable scheduler or not">
|
||||||
|
if data.Disabled {
|
||||||
|
<input type="checkbox" name="enable_schedule" value="1" class="toggle toggle-primary"/>
|
||||||
|
} else {
|
||||||
|
<input type="checkbox" name="enable_schedule" value="1" class="toggle toggle-primary" checked/>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
if data.Disabled {
|
||||||
|
<input name="schedule" type="text" placeholder="e.g. '@daily' or '0 0 * * MON'" class="input input-bordered" disabled/>
|
||||||
|
} else {
|
||||||
|
<input
|
||||||
|
name="schedule"
|
||||||
|
type="text"
|
||||||
|
placeholder="e.g. '@daily' or '0 0 * * MON'"
|
||||||
|
value={ data.Value }
|
||||||
|
class={ utils.CX(map[string]bool{
|
||||||
|
"input": true,
|
||||||
|
"input-bordered": true,
|
||||||
|
"input-error": data.Error != "",
|
||||||
|
"text-error": data.Error != "",
|
||||||
|
"input-success": data.Valid != "",
|
||||||
|
"text-success": data.Valid != "",
|
||||||
|
}) }
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
<div class="label">
|
||||||
|
<span
|
||||||
|
class={ utils.CX(map[string]bool{
|
||||||
|
"label-text": true,
|
||||||
|
"text-error": data.Error != "",
|
||||||
|
"text-success": data.Valid != "",
|
||||||
|
"min-h-[1rem]": true,
|
||||||
|
}) }
|
||||||
|
>
|
||||||
|
if data.Valid != "" {
|
||||||
|
{ data.Valid }
|
||||||
|
} else {
|
||||||
|
{ data.Error }
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
Loading…
Reference in a new issue