start refactoring forms. Allow list for recipe ingredients
This commit is contained in:
parent
349aa0dd5d
commit
74760707dd
|
@ -15,7 +15,7 @@ type RecipeMetaData struct {
|
||||||
Title string `owl:"inputType=text"`
|
Title string `owl:"inputType=text"`
|
||||||
Yield string `owl:"inputType=text"`
|
Yield string `owl:"inputType=text"`
|
||||||
Duration string `owl:"inputType=text"`
|
Duration string `owl:"inputType=text"`
|
||||||
Ingredients []string `owl:"inputType=text widget=textarea"`
|
Ingredients []string `owl:"inputType=text widget=textlist"`
|
||||||
Content string `owl:"inputType=text widget=textarea"`
|
Content string `owl:"inputType=text widget=textarea"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
<small>
|
||||||
|
{{ if .MetaData.Yield }}
|
||||||
|
Servings: <span class="p-yield">{{ .MetaData.Yield }}</span>
|
||||||
|
{{ if .MetaData.Duration }}, {{end}}
|
||||||
|
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if .MetaData.Duration }}
|
||||||
|
Prep Time: <time class="dt-duration" value="{{ .MetaData.Duration }}">
|
||||||
|
{{ .MetaData.Duration }}
|
||||||
|
</time>
|
||||||
|
{{ end }}
|
||||||
|
</small>
|
||||||
|
<br> <br>
|
||||||
|
|
||||||
|
<h2>Ingredients</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{{ range $ingredient := .MetaData.Ingredients }}
|
||||||
|
<li class="p-ingredient">
|
||||||
|
{{ $ingredient }}
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Instructions</h2>
|
||||||
|
{{.MetaData.Content | markdown }}
|
|
@ -32,7 +32,7 @@ type FormFieldParams struct {
|
||||||
|
|
||||||
type FormField struct {
|
type FormField struct {
|
||||||
Name string
|
Name string
|
||||||
Value string
|
Value reflect.Value
|
||||||
Params FormFieldParams
|
Params FormFieldParams
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,18 +55,30 @@ func (s *FormFieldParams) ApplyTag(tagKey string, tagValue string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *FormField) ToWidget() Widget {
|
||||||
|
switch s.Params.Widget {
|
||||||
|
case "textarea":
|
||||||
|
return &TextareaWidget{*s}
|
||||||
|
case "textlist":
|
||||||
|
return &TextListWidget{*s}
|
||||||
|
default:
|
||||||
|
return &TextWidget{*s}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *FormField) Html() string {
|
func (s *FormField) Html() string {
|
||||||
html := ""
|
html := ""
|
||||||
html += fmt.Sprintf("<label for=\"%v\">%v</label>\n", s.Name, s.Name)
|
html += fmt.Sprintf("<label for=\"%v\">%v</label>\n", s.Name, s.Name)
|
||||||
if s.Params.InputType == "text" && s.Params.Widget == "textarea" {
|
if s.Params.InputType == "file" {
|
||||||
html += fmt.Sprintf("<textarea name=\"%v\" id=\"%v\" rows=\"20\">%v</textarea>\n", s.Name, s.Name, s.Value)
|
|
||||||
} else {
|
|
||||||
html += fmt.Sprintf("<input type=\"%v\" name=\"%v\" id=\"%v\" value=\"%v\" />\n", s.Params.InputType, s.Name, s.Name, s.Value)
|
html += fmt.Sprintf("<input type=\"%v\" name=\"%v\" id=\"%v\" value=\"%v\" />\n", s.Params.InputType, s.Name, s.Name, s.Value)
|
||||||
|
} else {
|
||||||
|
html += s.ToWidget().Html()
|
||||||
|
html += "\n"
|
||||||
}
|
}
|
||||||
return html
|
return html
|
||||||
}
|
}
|
||||||
|
|
||||||
func FieldToFormField(field reflect.StructField, value string) (FormField, error) {
|
func FieldToFormField(field reflect.StructField, value reflect.Value) (FormField, error) {
|
||||||
formField := FormField{
|
formField := FormField{
|
||||||
Name: field.Name,
|
Name: field.Name,
|
||||||
Value: value,
|
Value: value,
|
||||||
|
@ -92,7 +104,10 @@ func StructToFormFields(data interface{}) ([]FormField, error) {
|
||||||
numFields := dataType.NumField()
|
numFields := dataType.NumField()
|
||||||
fields := []FormField{}
|
fields := []FormField{}
|
||||||
for i := 0; i < numFields; i++ {
|
for i := 0; i < numFields; i++ {
|
||||||
field, err := FieldToFormField(dataType.Field(i), dataValue.FieldByIndex([]int{i}).String())
|
field, err := FieldToFormField(
|
||||||
|
dataType.Field(i),
|
||||||
|
dataValue.FieldByIndex([]int{i}),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -134,10 +149,10 @@ func (s *Form) Parse(ctx HttpFormData) (interface{}, error) {
|
||||||
file, err := ctx.FormFile(fieldName)
|
file, err := ctx.FormFile(fieldName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If field already has a value, we can ignore the error
|
// If field already has a value, we can ignore the error
|
||||||
if field.Value != "" {
|
if field.Value != reflect.Zero(field.Value.Type()) {
|
||||||
metaField := dataVal.Elem().FieldByName(fieldName)
|
metaField := dataVal.Elem().FieldByName(fieldName)
|
||||||
if metaField.IsValid() {
|
if metaField.IsValid() {
|
||||||
metaField.SetString(field.Value)
|
metaField.SetString(field.Value.String())
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -167,7 +182,7 @@ func (s *Form) Parse(ctx HttpFormData) (interface{}, error) {
|
||||||
formValue := ctx.FormValue(fieldName)
|
formValue := ctx.FormValue(fieldName)
|
||||||
metaField := dataVal.Elem().FieldByName(fieldName)
|
metaField := dataVal.Elem().FieldByName(fieldName)
|
||||||
if metaField.IsValid() {
|
if metaField.IsValid() {
|
||||||
metaField.SetString(formValue)
|
field.ToWidget().ParseValue(formValue, metaField)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package forms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Widget interface {
|
||||||
|
Html() string
|
||||||
|
ParseValue(value string, output reflect.Value) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type TextWidget struct {
|
||||||
|
FormField
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *TextWidget) Html() string {
|
||||||
|
html := ""
|
||||||
|
html += fmt.Sprintf("<input type=\"text\" name=\"%v\" value=\"%v\">\n", s.Name, s.Value.String())
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *TextWidget) ParseValue(value string, output reflect.Value) error {
|
||||||
|
output.SetString(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type TextareaWidget struct {
|
||||||
|
FormField
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *TextareaWidget) Html() string {
|
||||||
|
html := ""
|
||||||
|
html += fmt.Sprintf("<textarea name=\"%v\" rows=\"20\">%v</textarea>\n", s.Name, s.Value.String())
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *TextareaWidget) ParseValue(value string, output reflect.Value) error {
|
||||||
|
output.SetString(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type TextListWidget struct {
|
||||||
|
FormField
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *TextListWidget) Html() string {
|
||||||
|
valueList := s.Value.Interface().([]string)
|
||||||
|
value := strings.Join(valueList, "\n")
|
||||||
|
|
||||||
|
html := ""
|
||||||
|
html += fmt.Sprintf("<textarea name=\"%v\" rows=\"20\">%v</textarea>\n", s.Name, value)
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *TextListWidget) ParseValue(value string, output reflect.Value) error {
|
||||||
|
list := strings.Split(value, "\n")
|
||||||
|
// trim entries
|
||||||
|
for i, item := range list {
|
||||||
|
list[i] = strings.TrimSpace(item)
|
||||||
|
}
|
||||||
|
// remove empty entries
|
||||||
|
for i := len(list) - 1; i >= 0; i-- {
|
||||||
|
if list[i] == "" {
|
||||||
|
list = append(list[:i], list[i+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output.Set(reflect.ValueOf(list))
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue