subreddit-add: enhanced subreddit check and add form
This commit is contained in:
parent
15f9634187
commit
4e7f91d098
|
@ -39,7 +39,18 @@ func (reddit *Reddit) CheckSubreddit(ctx context.Context, params CheckSubredditP
|
|||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
return actual, errs.Wrapw(err, "user or subreddit not found", "url", url, "params", params).Code(http.StatusNotFound)
|
||||
var msg string
|
||||
if params.SubredditType == SubredditTypeUser {
|
||||
msg = "user not found"
|
||||
}
|
||||
if params.SubredditType == SubredditTypeSub {
|
||||
msg = "subreddit not found"
|
||||
}
|
||||
return actual, errs.Wrapw(err, msg, "url", url, "params", params).Code(http.StatusNotFound)
|
||||
}
|
||||
|
||||
if params.SubredditType == SubredditTypeUser && resp.StatusCode == http.StatusOK {
|
||||
return params.Subreddit, nil
|
||||
}
|
||||
|
||||
if resp.StatusCode >= 400 {
|
||||
|
|
|
@ -4,6 +4,8 @@ import (
|
|||
"context"
|
||||
|
||||
"github.com/tigorlazuardi/redmage/api/reddit"
|
||||
"github.com/tigorlazuardi/redmage/models"
|
||||
"github.com/tigorlazuardi/redmage/pkg/errs"
|
||||
)
|
||||
|
||||
type SubredditCheckParam = reddit.CheckSubredditParams
|
||||
|
@ -14,3 +16,18 @@ func (api *API) SubredditCheck(ctx context.Context, params SubredditCheckParam)
|
|||
|
||||
return api.reddit.CheckSubreddit(ctx, params)
|
||||
}
|
||||
|
||||
func (api *API) SubredditRegistered(ctx context.Context, params SubredditCheckParam) (registered bool, err error) {
|
||||
ctx, span := tracer.Start(ctx, "*API.SubredditRegistered")
|
||||
defer span.End()
|
||||
|
||||
registered, err = models.Subreddits.Query(ctx, api.db,
|
||||
models.SelectWhere.Subreddits.Name.EQ(params.Subreddit),
|
||||
models.SelectWhere.Subreddits.Subtype.EQ(int32(params.SubredditType)),
|
||||
).Exists()
|
||||
if err != nil {
|
||||
return registered, errs.Wrapw(err, "failed to check subreddit registered state", "params", params)
|
||||
}
|
||||
|
||||
return registered, err
|
||||
}
|
||||
|
|
|
@ -52,6 +52,11 @@ func (routes *Routes) SubredditCheckHTMX(rw http.ResponseWriter, r *http.Request
|
|||
name := r.FormValue("name")
|
||||
data.Value = name
|
||||
|
||||
var subtype reddit.SubredditType
|
||||
_ = subtype.Parse(r.FormValue("type"))
|
||||
|
||||
data.Type = subtype
|
||||
|
||||
if name == "" {
|
||||
if err := addview.SubredditInputForm(data).Render(r.Context(), rw); err != nil {
|
||||
log.New(r.Context()).Err(err).Error("failed to render subreddit input form")
|
||||
|
@ -62,12 +67,9 @@ func (routes *Routes) SubredditCheckHTMX(rw http.ResponseWriter, r *http.Request
|
|||
ctx, span := tracer.Start(r.Context(), "*Routes.SubredditCheckHTMX")
|
||||
defer span.End()
|
||||
|
||||
var t reddit.SubredditType
|
||||
_ = t.Parse(r.FormValue("type"))
|
||||
|
||||
params := api.SubredditCheckParam{
|
||||
Subreddit: name,
|
||||
SubredditType: t,
|
||||
SubredditType: subtype,
|
||||
}
|
||||
|
||||
actual, err := routes.API.SubredditCheck(ctx, params)
|
||||
|
@ -81,7 +83,30 @@ func (routes *Routes) SubredditCheckHTMX(rw http.ResponseWriter, r *http.Request
|
|||
}
|
||||
return
|
||||
}
|
||||
params.Subreddit = actual
|
||||
data.Value = actual
|
||||
|
||||
exist, err := routes.API.SubredditRegistered(ctx, params)
|
||||
if err != nil {
|
||||
log.New(ctx).Err(err).Error("failed to check subreddit")
|
||||
code, message := errs.HTTPMessage(err)
|
||||
rw.WriteHeader(code)
|
||||
data.Error = message
|
||||
if err := addview.SubredditInputForm(data).Render(r.Context(), rw); err != nil {
|
||||
log.New(r.Context()).Err(err).Error("failed to render subreddit input form")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if exist {
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
data.Error = "subreddit already registered"
|
||||
if err := addview.SubredditInputForm(data).Render(r.Context(), rw); err != nil {
|
||||
log.New(r.Context()).Err(err).Error("failed to render subreddit input form")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
data.Valid = true
|
||||
|
||||
if err := addview.SubredditInputForm(data).Render(r.Context(), rw); err != nil {
|
||||
|
|
|
@ -2,7 +2,6 @@ package addview
|
|||
|
||||
import "github.com/tigorlazuardi/redmage/views"
|
||||
import "github.com/tigorlazuardi/redmage/views/components"
|
||||
import "github.com/tigorlazuardi/redmage/views/utils"
|
||||
|
||||
templ Addview(c *views.Context) {
|
||||
@components.Doctype() {
|
||||
|
@ -19,73 +18,18 @@ templ AddviewContent(c *views.Context) {
|
|||
@components.Container() {
|
||||
<h1>Add Subreddit</h1>
|
||||
<div class="divider"></div>
|
||||
<form hx-post="/htmx/subreddit/add" class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<form
|
||||
onkeydown="return event.key !== 'Enter'"
|
||||
hx-post="/htmx/subreddit/add"
|
||||
class="grid grid-cols-1 sm:grid-cols-2 gap-4"
|
||||
>
|
||||
<label id="subreddit-input" class="form-control w-full">
|
||||
@SubredditInputForm(SubredditInputData{})
|
||||
</label>
|
||||
<label id="subreddit-type-input" class="form-control w-full">
|
||||
@SubredditTypeInput(SubredditTypeData{})
|
||||
</label>
|
||||
</form>
|
||||
}
|
||||
</main>
|
||||
}
|
||||
|
||||
type SubredditInputData struct {
|
||||
Value string
|
||||
Error string
|
||||
Valid bool
|
||||
}
|
||||
|
||||
templ SubredditInputForm(data SubredditInputData) {
|
||||
<div class="label">
|
||||
<span
|
||||
class={ utils.CX(map[string]bool{
|
||||
"label-text": true,
|
||||
"text-error": data.Error != "",
|
||||
"text-success": data.Valid,
|
||||
"text-base": true,
|
||||
}) }
|
||||
>Subreddit Name</span>
|
||||
</div>
|
||||
@subredditInputField("/htmx/subreddits/check", data)
|
||||
<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 {
|
||||
Subreddit / User target is valid
|
||||
} else {
|
||||
{ data.Error }
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
templ subredditInputField(target string, data SubredditInputData) {
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
hx-post={ target }
|
||||
hx-target="#subreddit-input"
|
||||
hx-target-4xx="#subreddit-input"
|
||||
hx-trigger="keyup changed delay:1s, on-demand"
|
||||
hx-target-5x={ components.NotificationContainerID }
|
||||
value={ data.Value }
|
||||
placeholder="e.g. 'wallpaper' or 'EarthPorn'"
|
||||
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,
|
||||
}) }
|
||||
required
|
||||
data-error={ data.Error }
|
||||
hx-on::load="this.setCustomValidity(this.getAttribute('data-error'))"
|
||||
/>
|
||||
}
|
||||
|
|
73
views/subredditsview/addview/subreddit_name_input.templ
Normal file
73
views/subredditsview/addview/subreddit_name_input.templ
Normal file
|
@ -0,0 +1,73 @@
|
|||
package addview
|
||||
|
||||
import "github.com/tigorlazuardi/redmage/views/components"
|
||||
import "github.com/tigorlazuardi/redmage/views/utils"
|
||||
import "github.com/tigorlazuardi/redmage/api/reddit"
|
||||
|
||||
type SubredditInputData struct {
|
||||
Value string
|
||||
Error string
|
||||
Valid bool
|
||||
Type reddit.SubredditType
|
||||
}
|
||||
|
||||
templ SubredditInputForm(data SubredditInputData) {
|
||||
<div class="label">
|
||||
<span
|
||||
class={ utils.CX(map[string]bool{
|
||||
"label-text": true,
|
||||
"text-error": data.Error != "",
|
||||
"text-success": data.Valid,
|
||||
"text-base": true,
|
||||
}) }
|
||||
>Subreddit Name</span>
|
||||
</div>
|
||||
@subredditInputField("/htmx/subreddits/check", data)
|
||||
<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 {
|
||||
if data.Type == reddit.SubredditTypeUser {
|
||||
Username target is valid
|
||||
} else {
|
||||
Subreddit is valid
|
||||
}
|
||||
} else {
|
||||
{ data.Error }
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
templ subredditInputField(target string, data SubredditInputData) {
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
hx-post={ target }
|
||||
hx-target="#subreddit-input"
|
||||
hx-target-4xx="#subreddit-input"
|
||||
hx-trigger="keyup changed delay:1s, on-demand"
|
||||
hx-include="[name='type']"
|
||||
hx-target-5x={ components.NotificationContainerID }
|
||||
value={ data.Value }
|
||||
placeholder="e.g. 'wallpaper' or 'EarthPorn'"
|
||||
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,
|
||||
}) }
|
||||
required
|
||||
data-error={ data.Error }
|
||||
hx-on::load="this.setCustomValidity(this.getAttribute('data-error'))"
|
||||
/>
|
||||
}
|
27
views/subredditsview/addview/subreddit_type_input.templ
Normal file
27
views/subredditsview/addview/subreddit_type_input.templ
Normal file
|
@ -0,0 +1,27 @@
|
|||
package addview
|
||||
|
||||
type SubredditTypeData struct {
|
||||
Value string
|
||||
}
|
||||
|
||||
templ SubredditTypeInput(data SubredditTypeData) {
|
||||
<div class="label">
|
||||
<span class="label-text text-base">Subreddit Type</span>
|
||||
</div>
|
||||
<select
|
||||
onchange="htmx.trigger('#name', 'on-demand')"
|
||||
name="type"
|
||||
value={ data.Value }
|
||||
class="select select-bordered"
|
||||
>
|
||||
if data.Value == "1" {
|
||||
<option value="0">Subreddit</option>
|
||||
<option selected value="1">User</option>
|
||||
} else {
|
||||
<option selected value="0">Subreddit</option>
|
||||
<option value="1">User</option>
|
||||
}
|
||||
</select>
|
||||
<div class="min-h-4"></div>
|
||||
<script>document.addEventListener('DOMContentLoaded', () => htmx.trigger('#name', 'on-demand')) </script>
|
||||
}
|
Loading…
Reference in a new issue