refactor: renamed add device to put

This commit is contained in:
Tigor Hutasuhut 2024-05-08 10:10:23 +07:00
parent 90babf685d
commit bfff9a698f
14 changed files with 146 additions and 94 deletions

View file

@ -6,16 +6,16 @@ import (
"github.com/gosimple/slug"
"github.com/tigorlazuardi/redmage/pkg/errs"
"github.com/tigorlazuardi/redmage/pkg/log"
"github.com/tigorlazuardi/redmage/views/devicesview/adddevice"
"github.com/tigorlazuardi/redmage/views/devicesview/put"
)
func (routes *Routes) DevicesValidateNameHTMX(rw http.ResponseWriter, req *http.Request) {
ctx, span := tracer.Start(req.Context(), "*Routes.ValidateName")
defer span.End()
var nameData adddevice.NameInputData
var nameData put.NameInputData
nameData.Value = req.FormValue("name")
nameComponent := adddevice.NameInput(nameData)
nameComponent := put.NameInput(nameData)
s := req.FormValue("slug")
if s != "" || nameData.Value == "" {
if err := nameComponent.Render(ctx, rw); err != nil {
@ -25,7 +25,7 @@ func (routes *Routes) DevicesValidateNameHTMX(rw http.ResponseWriter, req *http.
}
s = slug.Make(nameData.Value)
slugData := adddevice.SlugInputData{
slugData := put.SlugInputData{
Value: s,
HXSwapOOB: true,
}
@ -33,7 +33,7 @@ func (routes *Routes) DevicesValidateNameHTMX(rw http.ResponseWriter, req *http.
if s == "" {
slugData.Error = "Identifier resolves to empty value. Please set a valid identifier manually."
_ = nameComponent.Render(ctx, rw)
if err := adddevice.SlugInput(slugData).Render(ctx, rw); err != nil {
if err := put.SlugInput(slugData).Render(ctx, rw); err != nil {
log.New(ctx).Err(err).Error("failed to render name input")
}
return
@ -44,7 +44,7 @@ func (routes *Routes) DevicesValidateNameHTMX(rw http.ResponseWriter, req *http.
_, message := errs.HTTPMessage(err)
slugData.Error = message
_ = nameComponent.Render(ctx, rw)
if err := adddevice.SlugInput(slugData).Render(ctx, rw); err != nil {
if err := put.SlugInput(slugData).Render(ctx, rw); err != nil {
log.New(ctx).Err(err).Error("failed to render name input")
}
}
@ -52,7 +52,7 @@ func (routes *Routes) DevicesValidateNameHTMX(rw http.ResponseWriter, req *http.
if exist {
slugData.Error = "Device with this identifier already exist. Please change the value manually."
_ = nameComponent.Render(ctx, rw)
if err := adddevice.SlugInput(slugData).Render(ctx, rw); err != nil {
if err := put.SlugInput(slugData).Render(ctx, rw); err != nil {
log.New(ctx).Err(err).Error("failed to render name input")
}
return
@ -61,7 +61,7 @@ func (routes *Routes) DevicesValidateNameHTMX(rw http.ResponseWriter, req *http.
slugData.Valid = "Identifier is available."
_ = nameComponent.Render(ctx, rw)
if err := adddevice.SlugInput(slugData).Render(ctx, rw); err != nil {
if err := put.SlugInput(slugData).Render(ctx, rw); err != nil {
log.New(ctx).Err(err).Error("failed to render name input")
}
}

View file

@ -6,17 +6,17 @@ import (
"github.com/gosimple/slug"
"github.com/tigorlazuardi/redmage/pkg/errs"
"github.com/tigorlazuardi/redmage/pkg/log"
"github.com/tigorlazuardi/redmage/views/devicesview/adddevice"
"github.com/tigorlazuardi/redmage/views/devicesview/put"
)
func (routes *Routes) DevicesValidateSlugHTMX(rw http.ResponseWriter, req *http.Request) {
ctx, span := tracer.Start(req.Context(), "*Routes.ValidateSlugHTMX")
defer span.End()
var data adddevice.SlugInputData
var data put.SlugInputData
data.Value = slug.Make(req.FormValue("slug"))
if data.Value == "" {
if err := adddevice.SlugInput(data).Render(ctx, rw); err != nil {
if err := put.SlugInput(data).Render(ctx, rw); err != nil {
log.New(ctx).Err(err).Error("failed to render slug input")
}
return
@ -28,7 +28,7 @@ func (routes *Routes) DevicesValidateSlugHTMX(rw http.ResponseWriter, req *http.
code, message := errs.HTTPMessage(err)
rw.WriteHeader(code)
data.Error = message
if err := adddevice.SlugInput(data).Render(ctx, rw); err != nil {
if err := put.SlugInput(data).Render(ctx, rw); err != nil {
log.New(ctx).Err(err).Error("failed to render slug input")
}
return
@ -37,14 +37,14 @@ func (routes *Routes) DevicesValidateSlugHTMX(rw http.ResponseWriter, req *http.
if exist {
data.Error = "Device with this identifier already exist"
rw.WriteHeader(http.StatusConflict)
if err := adddevice.SlugInput(data).Render(ctx, rw); err != nil {
if err := put.SlugInput(data).Render(ctx, rw); err != nil {
log.New(ctx).Err(err).Error("failed to render slug input")
}
return
}
data.Valid = "Identifier is available"
if err := adddevice.SlugInput(data).Render(ctx, rw); err != nil {
if err := put.SlugInput(data).Render(ctx, rw); err != nil {
log.New(ctx).Err(err).Error("failed to render slug input")
}
}

View file

@ -5,7 +5,7 @@ import (
"github.com/tigorlazuardi/redmage/pkg/log"
"github.com/tigorlazuardi/redmage/views"
"github.com/tigorlazuardi/redmage/views/devicesview/adddevice"
"github.com/tigorlazuardi/redmage/views/devicesview/put"
)
func (routes *Routes) PageDevicesAdd(rw http.ResponseWriter, req *http.Request) {
@ -14,7 +14,15 @@ func (routes *Routes) PageDevicesAdd(rw http.ResponseWriter, req *http.Request)
c := views.NewContext(routes.Config, req)
if err := adddevice.View(c).Render(ctx, rw); err != nil {
data := put.Data{
PageTitle: "Add Device",
PostAction: "/devices/add",
AspectRatioTolerance: put.AspectRatioToleranceData{
Value: 0.2,
},
}
if err := put.View(c, data).Render(ctx, rw); err != nil {
log.New(ctx).Err(err).Error("failed to render add device page")
}
}

View file

@ -0,0 +1,12 @@
package components
import "github.com/tigorlazuardi/redmage/views"
templ Page404(c *views.Context, text string) {
@Doctype() {
@Head(c, HeadTitle(text))
@Body(c) {
<h1>{ text }</h1>
}
}
}

View file

@ -1,46 +0,0 @@
package adddevice
import "github.com/tigorlazuardi/redmage/views"
import "github.com/tigorlazuardi/redmage/views/components"
templ View(c *views.Context) {
@components.Doctype() {
@components.Head(c, components.HeadTitle("Device - Add"))
@components.Body(c) {
@Content(c)
}
}
}
templ Content(c *views.Context) {
<main class="prose min-w-full">
@components.Container() {
<h1>Add Device</h1>
<div class="divider"></div>
<form
method="post"
hx-post="/htmx/devices/add"
action="/htmx/devices/add"
class="grid sm:grid-cols-2 gap-4"
hx-target={ components.NotificationContainerID }
hx-target-error={ components.NotificationContainerID }
hx-swap="afterbegin"
>
@NameInput(NameInputData{})
@SlugInput(SlugInputData{})
@ResolutionXInput(ResolutionData{})
@ResolutionYInput(ResolutionData{})
<div class="divider my-auto sm:col-span-2"><h3 class="m-0 p-0">Filter</h3></div>
@AspectRatioToleranceInput(AspectRatioToleranceData{Value: 0.2})
@NSFWCheckbox(NSFWCheckboxData{Checked: true})
@WindowsWallpaperCheckbox(WindowsWallpaperCheckboxData{})
@MinImageResolutionXInput(ResolutionData{})
@MinImageResolutionYInput(ResolutionData{})
@MaxImageResolutionXInput(ResolutionData{})
@MaxImageResolutionYInput(ResolutionData{})
<button type="submit" class="btn btn-primary sm:col-span-2">Add</button>
</form>
}
</main>
@components.NotificationContainer()
}

View file

@ -1,4 +1,4 @@
package adddevice
package put
import "fmt"
import "github.com/tigorlazuardi/redmage/views/utils"

View file

@ -1,4 +1,4 @@
package adddevice
package put
import "fmt"
import "github.com/tigorlazuardi/redmage/views/utils"

View file

@ -1,4 +1,4 @@
package adddevice
package put
import "github.com/tigorlazuardi/redmage/views/utils"
import "fmt"
@ -6,6 +6,7 @@ import "fmt"
type NameInputData struct {
Error string
Value string
DisableValidation bool
}
templ NameInput(data NameInputData) {
@ -17,18 +18,20 @@ templ NameInput(data NameInputData) {
</div>
<input
id="name-input-field"
if !data.DisableValidation {
required
x-data={ fmt.Sprintf(`{ init() { $el.setCustomValidity(%q) } }`, data.Error) }
hx-post="/htmx/devices/add/validate/name"
hx-include="[name='slug']"
hx-trigger="change"
hx-target="#name-input-form"
hx-swap="outerHTML"
placeholder="My Awesome Device"
}
name="name"
type="text"
class={ utils.CXX("input input-bordered", true, "input-error", data.Error != "") }
value={ data.Value }
placeholder="My Awesome Device"
required
/>
<div class="label">
if data.Error != "" {

View file

@ -1,4 +1,4 @@
package adddevice
package put
import "fmt"

View file

@ -1,4 +1,4 @@
package adddevice
package put
import "github.com/tigorlazuardi/redmage/views/utils"
import "fmt"

View file

@ -1,4 +1,4 @@
package adddevice
package put
import "github.com/tigorlazuardi/redmage/views/utils"
import "fmt"
@ -8,6 +8,8 @@ type SlugInputData struct {
Value string
Valid string
HXSwapOOB bool
Disabled bool
DisabledText string
}
templ SlugInput(data SlugInputData) {
@ -29,10 +31,14 @@ templ SlugInput(data SlugInputData) {
</div>
<input
id="slug-input-field"
if !data.Disabled {
x-data={ fmt.Sprintf(`{ init() { $el.setCustomValidity(%q) } }`, data.Error) }
}
name="slug"
type="text"
if !data.Disabled {
@change="$el.setCustomValidity('')"
}
class={ utils.CXX(
"input input-bordered", true,
"text-error", data.Error != "",
@ -40,15 +46,19 @@ templ SlugInput(data SlugInputData) {
"input-error", data.Error != "",
"input-success", data.Valid != "",
) }
if data.Disabled {
disabled
} else {
hx-post="/htmx/devices/add/validate/slug"
hx-trigger="change, input delay:2s"
hx-target="#slug-input-form"
hx-target-409="#slug-input-form"
hx-swap="outerHTML"
value={ data.Value }
placeholder="my-awesome-device"
title="Url Friendly Characters Only"
required
}
value={ data.Value }
/>
<div class="label">
<span class={ utils.CXX("label-text", true, "text-error", data.Error != "", "text-success", data.Valid != "") }>
@ -56,6 +66,8 @@ templ SlugInput(data SlugInputData) {
{ data.Valid }
} else if data.Error != "" {
{ data.Error }
} else if data.DisabledText != "" {
{ data.DisabledText }
} else {
URL friendly Unique identifier for the device.
Value must be lowercase english alphabet and supported separator is only 'dash' (-) and 'underscores' (_).

View file

@ -0,0 +1,63 @@
package put
import "github.com/tigorlazuardi/redmage/views"
import "github.com/tigorlazuardi/redmage/views/components"
type Data struct {
PageTitle string
PostAction string
NameInput NameInputData
SlugInput SlugInputData
ResolutionX ResolutionData
ResolutionY ResolutionData
AspectRatioTolerance AspectRatioToleranceData
NSFWCheckbox NSFWCheckboxData
WindowsWallpaperCheckbox WindowsWallpaperCheckboxData
MinImageResolutionXInput ResolutionData
MinImageResolutionYInput ResolutionData
MaxImageResolutionXInput ResolutionData
MaxImageResolutionYInput ResolutionData
}
templ View(c *views.Context, data Data) {
@components.Doctype() {
@components.Head(c, components.HeadTitle(data.PageTitle))
@components.Body(c) {
@Content(c, data)
}
}
}
templ Content(c *views.Context, data Data) {
<main class="prose min-w-full">
@components.Container() {
<h1>{ data.PageTitle }</h1>
<div class="divider"></div>
<form
method="post"
hx-post={ data.PostAction }
action={ templ.SafeURL(data.PostAction) }
class="grid sm:grid-cols-2 gap-4"
hx-target={ components.NotificationContainerID }
hx-target-error={ components.NotificationContainerID }
hx-swap="afterbegin"
>
@NameInput(data.NameInput)
@SlugInput(data.SlugInput)
@ResolutionXInput(data.ResolutionX)
@ResolutionYInput(data.ResolutionY)
<div class="divider my-auto sm:col-span-2"><h3 class="m-0 p-0">Filter</h3></div>
@AspectRatioToleranceInput(data.AspectRatioTolerance)
@NSFWCheckbox(data.NSFWCheckbox)
@WindowsWallpaperCheckbox(data.WindowsWallpaperCheckbox)
@MinImageResolutionXInput(data.MinImageResolutionXInput)
@MinImageResolutionYInput(data.MinImageResolutionYInput)
@MaxImageResolutionXInput(data.MaxImageResolutionXInput)
@MaxImageResolutionYInput(data.MaxImageResolutionYInput)
<button type="submit" class="btn btn-primary sm:col-span-2">Add</button>
</form>
}
</main>
@components.NotificationContainer()
}