Skip to content

Commit

Permalink
feat(form): add a form system (Experimental)
Browse files Browse the repository at this point in the history
  • Loading branch information
rande committed Aug 29, 2023
1 parent 5614dee commit 7a4de0e
Show file tree
Hide file tree
Showing 17 changed files with 754 additions and 2 deletions.
2 changes: 2 additions & 0 deletions app/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/rande/gonode/core/commands"
"github.com/rande/gonode/core/config"
"github.com/rande/gonode/core/embed"
"github.com/rande/gonode/core/form"
"github.com/rande/gonode/core/logger"
"github.com/rande/gonode/core/router"
"github.com/rande/gonode/core/security"
Expand Down Expand Up @@ -40,6 +41,7 @@ func Configure(configFile string) *goapp.Lifecycle {

base.Configure(l, conf)
embed.Configure(l, conf)
form.Configure(l, conf)
debug.Configure(l, conf)
user.Configure(l, conf)
raw.Configure(l, conf)
Expand Down
9 changes: 9 additions & 0 deletions core/form/__snapshots__/form_pongo_test.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

[Test_Form_Rendering - 1]
<form action="POST" action="" encoding="">
<label class="" style="" for="name">name</label>
<input name="name" type="text" value="John Doe" id="name" placeholder="Enter the name" required readonly autofocus size="10" maxlength="100" minlength="10" max="100" min="10" step="10" pattern="^[a-z]+$" autocomplete="on">
<label class="" style="" for="email">email</label>
<input name="email" type="email" value="john.doe@gmail.com" id="email">
</form>
---
6 changes: 6 additions & 0 deletions core/form/form.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright © 2014-2023 Thomas Rabaix <thomas.rabaix@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package form
28 changes: 28 additions & 0 deletions core/form/form_app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright © 2014-2023 Thomas Rabaix <thomas.rabaix@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package form

import (
"github.com/flosch/pongo2"
"github.com/rande/goapp"
"github.com/rande/gonode/core/config"
"github.com/rande/gonode/core/embed"
)

func Configure(l *goapp.Lifecycle, conf *config.Config) {

l.Prepare(func(app *goapp.App) error {
app.Get("gonode.embeds").(*embed.Embeds).Add("form", GetEmbedFS())

pongo := app.Get("gonode.pongo").(*pongo2.TemplateSet)

pongo.Globals["form_field"] = createPongoField(pongo)
pongo.Globals["form_label"] = createPongoLabel(pongo)
pongo.Globals["form_input"] = createPongoInput(pongo)

return nil
})
}
17 changes: 17 additions & 0 deletions core/form/form_embed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright © 2014-2023 Thomas Rabaix <thomas.rabaix@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package form

import (
"embed"
)

//go:embed all:templates
var content embed.FS

func GetEmbedFS() embed.FS {
return content
}
80 changes: 80 additions & 0 deletions core/form/form_pongo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright © 2014-2023 Thomas Rabaix <thomas.rabaix@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package form

import (
"fmt"

"github.com/flosch/pongo2"
"github.com/rande/gonode/core/helper"
)

type AttributOption struct {
Name string
Value interface{}
}

func createPongoField(pongo *pongo2.TemplateSet) func(field *FormField, form *Form) *pongo2.Value {

return func(field *FormField, form *Form) *pongo2.Value {
tpl, err := pongo.FromFile("form:field.tpl")

helper.PanicOnError(err)

data, err := tpl.Execute(pongo2.Context{
"form": form,
"field": field,
"input": field.Input,
"label": field.Label,
})

helper.PanicOnError(err)

return pongo2.AsSafeValue(data)
}
}

func createPongoLabel(pongo *pongo2.TemplateSet) func(field *FormField, form *Form) *pongo2.Value {

return func(field *FormField, form *Form) *pongo2.Value {

tpl, err := pongo.FromFile(field.Label.Template)

helper.PanicOnError(err)

data, err := tpl.Execute(pongo2.Context{
"form": form,
"field": field,
"input": field.Input,
"label": field.Label,
})

helper.PanicOnError(err)

return pongo2.AsSafeValue(data)
}
}

func createPongoInput(pongo *pongo2.TemplateSet) func(field *FormField, form *Form) *pongo2.Value {

return func(field *FormField, form *Form) *pongo2.Value {

tpl, err := pongo.FromFile(fmt.Sprintf("%s:fields/input.%s.tpl", field.Module, field.Input.Type))

helper.PanicOnError(err)

data, err := tpl.Execute(pongo2.Context{
"form": form,
"field": field,
"input": field.Input,
"label": field.Label,
})

helper.PanicOnError(err)

return pongo2.AsSafeValue(data)
}
}
92 changes: 92 additions & 0 deletions core/form/form_pongo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright © 2014-2023 Thomas Rabaix <thomas.rabaix@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package form

import (
"fmt"
"os"
"testing"

"github.com/flosch/pongo2"
"github.com/gkampitakis/go-snaps/snaps"
"github.com/stretchr/testify/assert"

"github.com/rande/gonode/core/embed"
)

func TestMain(t *testing.M) {

fmt.Println("Setup")
v := t.Run()

// After all tests have run `go-snaps` can check for not used snapshots
snaps.Clean(t)

os.Exit(v)
}

func GetPongo() *pongo2.TemplateSet {
embeds := embed.NewEmbeds()
embeds.Add("form", GetEmbedFS())

pongo := pongo2.NewSet("gonode.embeds", &embed.PongoTemplateLoader{
Embeds: embeds,
BasePath: "",
})
pongo.Options = &pongo2.Options{
TrimBlocks: true,
LStripBlocks: true,
}

pongo.Globals["form_field"] = createPongoField(pongo)
pongo.Globals["form_label"] = createPongoLabel(pongo)
pongo.Globals["form_input"] = createPongoInput(pongo)

return pongo
}
func Test_Form_Rendering(t *testing.T) {

form := &Form{}
form.Add("name", "text", "John Doe")
form.Add("email", "email", "john.doe@gmail.com")

PrepareForm(form)

assert.False(t, form.HasErrors)

pongo := GetPongo()
template, err := pongo.FromFile("form:form.tpl")

assert.Equal(t, "John Doe", form.Get("name").InitialValue)
assert.Equal(t, "John Doe", form.Get("name").Input.Value)

form.Get("name").Input.Pattern = "^[a-z]+$"
form.Get("name").Input.Placeholder = "Enter the name"
form.Get("name").Input.Placeholder = "Enter the name"
form.Get("name").Input.Readonly = true
form.Get("name").Input.Required = true
form.Get("name").Input.Size = 10
form.Get("name").Input.Autofocus = true
form.Get("name").Input.Autocomplete = "on"
form.Get("name").Input.Min = 10
form.Get("name").Input.Max = 100
form.Get("name").Input.Step = 10

form.Get("name").Input.MinLength = 10
form.Get("name").Input.MaxLength = 100

assert.Nil(t, err)
assert.NotNil(t, template)

html, err := template.Execute(pongo2.Context{
"form": form,
})

// fmt.Printf("%s", err.Error())
assert.Nil(t, err)

snaps.MatchSnapshot(t, html)
}
Loading

0 comments on commit 7a4de0e

Please sign in to comment.