From b86eee27ce5514556e32dd1352ad5aa8db0fb56f Mon Sep 17 00:00:00 2001 From: Niko Abeler Date: Tue, 13 Feb 2024 21:43:52 +0100 Subject: [PATCH 1/6] WIP, large refactoring to allow custom form code per type --- domain/model/binary_service.go | 5 +++ domain/model/entry.go | 10 ++++-- domain/model/form_data.go | 15 +++++++++ entry_types/article.go | 6 ++-- entry_types/bookmark.go | 7 ++-- entry_types/image.go | 7 ++-- entry_types/note.go | 7 ++-- entry_types/page.go | 7 ++-- entry_types/recipe.go | 7 ++-- entry_types/reply.go | 7 ++-- infra/entry_repository.go | 2 +- test/mock_entry.go | 7 ++-- tmp/build-errors.log | 2 +- web/forms/form.go | 58 ++++++++++++++++++---------------- web/forms/widget.go | 13 ++++++++ 15 files changed, 112 insertions(+), 48 deletions(-) create mode 100644 domain/model/binary_service.go create mode 100644 domain/model/form_data.go diff --git a/domain/model/binary_service.go b/domain/model/binary_service.go new file mode 100644 index 0000000..5d33e34 --- /dev/null +++ b/domain/model/binary_service.go @@ -0,0 +1,5 @@ +package model + +type BinaryStorageInterface interface { + Create(name string, file []byte) (*BinaryFile, error) +} diff --git a/domain/model/entry.go b/domain/model/entry.go index b9372c2..84a4a57 100644 --- a/domain/model/entry.go +++ b/domain/model/entry.go @@ -1,6 +1,8 @@ package model -import "time" +import ( + "time" +) type EntryContent string @@ -9,18 +11,20 @@ type Entry interface { Content() EntryContent PublishedAt() *time.Time AuthorId() string - MetaData() interface{} + MetaData() EntryMetaData // Optional: can return empty string Title() string SetID(id string) SetPublishedAt(publishedAt *time.Time) - SetMetaData(metaData interface{}) + SetMetaData(metaData EntryMetaData) SetAuthorId(authorId string) } type EntryMetaData interface { + Form(binSvc BinaryStorageInterface) string + ParseFormData(data HttpFormData, binSvc BinaryStorageInterface) (EntryMetaData, error) } type EntryBase struct { diff --git a/domain/model/form_data.go b/domain/model/form_data.go new file mode 100644 index 0000000..396120b --- /dev/null +++ b/domain/model/form_data.go @@ -0,0 +1,15 @@ +package model + +import "mime/multipart" + +type HttpFormData interface { + // FormFile returns the first file by key from a MultipartForm. + FormFile(key string) (*multipart.FileHeader, error) + // FormValue returns the first value by key from a MultipartForm. + // Search is performed in QueryArgs, PostArgs, MultipartForm and FormFile in this particular order. + // Defaults to the empty string "" if the form value doesn't exist. + // If a default value is given, it will return that value if the form value does not exist. + // Returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting instead. + FormValue(key string, defaultValue ...string) string +} diff --git a/entry_types/article.go b/entry_types/article.go index 9849a24..d2c57ee 100644 --- a/entry_types/article.go +++ b/entry_types/article.go @@ -4,6 +4,7 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" + "owl-blogs/web/forms" ) type Article struct { @@ -12,6 +13,7 @@ type Article struct { } type ArticleMetaData struct { + forms.DefaultForm Title string `owl:"inputType=text"` Content string `owl:"inputType=text widget=textarea"` } @@ -28,10 +30,10 @@ func (e *Article) Content() model.EntryContent { return model.EntryContent(str) } -func (e *Article) MetaData() interface{} { +func (e *Article) MetaData() model.EntryMetaData { return &e.meta } -func (e *Article) SetMetaData(metaData interface{}) { +func (e *Article) SetMetaData(metaData model.EntryMetaData) { e.meta = *metaData.(*ArticleMetaData) } diff --git a/entry_types/bookmark.go b/entry_types/bookmark.go index 2002bd0..45b6aab 100644 --- a/entry_types/bookmark.go +++ b/entry_types/bookmark.go @@ -4,6 +4,7 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" + "owl-blogs/web/forms" ) type Bookmark struct { @@ -12,6 +13,8 @@ type Bookmark struct { } type BookmarkMetaData struct { + forms.DefaultForm + Title string `owl:"inputType=text"` Url string `owl:"inputType=text"` Content string `owl:"inputType=text widget=textarea"` @@ -29,10 +32,10 @@ func (e *Bookmark) Content() model.EntryContent { return model.EntryContent(str) } -func (e *Bookmark) MetaData() interface{} { +func (e *Bookmark) MetaData() model.EntryMetaData { return &e.meta } -func (e *Bookmark) SetMetaData(metaData interface{}) { +func (e *Bookmark) SetMetaData(metaData model.EntryMetaData) { e.meta = *metaData.(*BookmarkMetaData) } diff --git a/entry_types/image.go b/entry_types/image.go index bd23e37..5bdf251 100644 --- a/entry_types/image.go +++ b/entry_types/image.go @@ -4,6 +4,7 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" + "owl-blogs/web/forms" ) type Image struct { @@ -12,6 +13,8 @@ type Image struct { } type ImageMetaData struct { + forms.DefaultForm + ImageId string `owl:"inputType=file"` Title string `owl:"inputType=text"` Content string `owl:"inputType=text widget=textarea"` @@ -29,10 +32,10 @@ func (e *Image) Content() model.EntryContent { return model.EntryContent(str) } -func (e *Image) MetaData() interface{} { +func (e *Image) MetaData() model.EntryMetaData { return &e.meta } -func (e *Image) SetMetaData(metaData interface{}) { +func (e *Image) SetMetaData(metaData model.EntryMetaData) { e.meta = *metaData.(*ImageMetaData) } diff --git a/entry_types/note.go b/entry_types/note.go index 590e9a5..7dd4157 100644 --- a/entry_types/note.go +++ b/entry_types/note.go @@ -4,6 +4,7 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" + "owl-blogs/web/forms" ) type Note struct { @@ -12,6 +13,8 @@ type Note struct { } type NoteMetaData struct { + forms.DefaultForm + Content string `owl:"inputType=text widget=textarea"` } @@ -27,10 +30,10 @@ func (e *Note) Content() model.EntryContent { return model.EntryContent(str) } -func (e *Note) MetaData() interface{} { +func (e *Note) MetaData() model.EntryMetaData { return &e.meta } -func (e *Note) SetMetaData(metaData interface{}) { +func (e *Note) SetMetaData(metaData model.EntryMetaData) { e.meta = *metaData.(*NoteMetaData) } diff --git a/entry_types/page.go b/entry_types/page.go index 78faece..6952de4 100644 --- a/entry_types/page.go +++ b/entry_types/page.go @@ -4,6 +4,7 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" + "owl-blogs/web/forms" ) type Page struct { @@ -12,6 +13,8 @@ type Page struct { } type PageMetaData struct { + forms.DefaultForm + Title string `owl:"inputType=text"` Content string `owl:"inputType=text widget=textarea"` } @@ -28,10 +31,10 @@ func (e *Page) Content() model.EntryContent { return model.EntryContent(str) } -func (e *Page) MetaData() interface{} { +func (e *Page) MetaData() model.EntryMetaData { return &e.meta } -func (e *Page) SetMetaData(metaData interface{}) { +func (e *Page) SetMetaData(metaData model.EntryMetaData) { e.meta = *metaData.(*PageMetaData) } diff --git a/entry_types/recipe.go b/entry_types/recipe.go index d6c8a51..7442592 100644 --- a/entry_types/recipe.go +++ b/entry_types/recipe.go @@ -4,6 +4,7 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" + "owl-blogs/web/forms" ) type Recipe struct { @@ -12,6 +13,8 @@ type Recipe struct { } type RecipeMetaData struct { + forms.DefaultForm + Title string `owl:"inputType=text"` Yield string `owl:"inputType=text"` Duration string `owl:"inputType=text"` @@ -31,10 +34,10 @@ func (e *Recipe) Content() model.EntryContent { return model.EntryContent(str) } -func (e *Recipe) MetaData() interface{} { +func (e *Recipe) MetaData() model.EntryMetaData { return &e.meta } -func (e *Recipe) SetMetaData(metaData interface{}) { +func (e *Recipe) SetMetaData(metaData model.EntryMetaData) { e.meta = *metaData.(*RecipeMetaData) } diff --git a/entry_types/reply.go b/entry_types/reply.go index de2f751..ef23467 100644 --- a/entry_types/reply.go +++ b/entry_types/reply.go @@ -4,6 +4,7 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" + "owl-blogs/web/forms" ) type Reply struct { @@ -12,6 +13,8 @@ type Reply struct { } type ReplyMetaData struct { + forms.DefaultForm + Title string `owl:"inputType=text"` Url string `owl:"inputType=text"` Content string `owl:"inputType=text widget=textarea"` @@ -29,10 +32,10 @@ func (e *Reply) Content() model.EntryContent { return model.EntryContent(str) } -func (e *Reply) MetaData() interface{} { +func (e *Reply) MetaData() model.EntryMetaData { return &e.meta } -func (e *Reply) SetMetaData(metaData interface{}) { +func (e *Reply) SetMetaData(metaData model.EntryMetaData) { e.meta = *metaData.(*ReplyMetaData) } diff --git a/infra/entry_repository.go b/infra/entry_repository.go index e4fc563..bde324a 100644 --- a/infra/entry_repository.go +++ b/infra/entry_repository.go @@ -151,7 +151,7 @@ func (r *DefaultEntryRepo) sqlEntryToEntry(entry sqlEntry) (model.Entry, error) if err != nil { return nil, errors.New("entry type not registered") } - metaData := reflect.New(reflect.TypeOf(e.MetaData()).Elem()).Interface() + metaData := reflect.New(reflect.TypeOf(e.MetaData()).Elem()).Interface().(model.EntryMetaData) json.Unmarshal([]byte(*entry.MetaData), metaData) e.SetID(entry.Id) e.SetPublishedAt(entry.PublishedAt) diff --git a/test/mock_entry.go b/test/mock_entry.go index 1b0373e..e9f9301 100644 --- a/test/mock_entry.go +++ b/test/mock_entry.go @@ -2,10 +2,13 @@ package test import ( "owl-blogs/domain/model" + "owl-blogs/web/forms" "time" ) type MockEntryMetaData struct { + forms.DefaultForm + Str string Number int Date time.Time @@ -21,11 +24,11 @@ func (e *MockEntry) Content() model.EntryContent { return model.EntryContent(e.metaData.Str) } -func (e *MockEntry) MetaData() interface{} { +func (e *MockEntry) MetaData() model.EntryMetaData { return e.metaData } -func (e *MockEntry) SetMetaData(metaData interface{}) { +func (e *MockEntry) SetMetaData(metaData model.EntryMetaData) { e.metaData = metaData.(*MockEntryMetaData) } diff --git a/tmp/build-errors.log b/tmp/build-errors.log index 05e5985..6c6d080 100644 --- a/tmp/build-errors.log +++ b/tmp/build-errors.log @@ -1 +1 @@ -exit status 1 \ No newline at end of file +exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1 \ No newline at end of file diff --git a/web/forms/form.go b/web/forms/form.go index 1deab80..3737bfd 100644 --- a/web/forms/form.go +++ b/web/forms/form.go @@ -2,27 +2,27 @@ package forms import ( "fmt" - "mime/multipart" - "owl-blogs/app" + "owl-blogs/domain/model" "reflect" "strings" ) -type HttpFormData interface { - // FormFile returns the first file by key from a MultipartForm. - FormFile(key string) (*multipart.FileHeader, error) - // FormValue returns the first value by key from a MultipartForm. - // Search is performed in QueryArgs, PostArgs, MultipartForm and FormFile in this particular order. - // Defaults to the empty string "" if the form value doesn't exist. - // If a default value is given, it will return that value if the form value does not exist. - // Returned value is only valid within the handler. Do not store any references. - // Make copies or use the Immutable setting instead. - FormValue(key string, defaultValue ...string) string +type DefaultForm struct{} + +func (meta *DefaultForm) Form(binSvc model.BinaryStorageInterface) string { + form := NewForm(meta, nil) + htmlForm, _ := form.HtmlForm() + return htmlForm } -type Form struct { - data interface{} - binSvc *app.BinaryService +func (meta *DefaultForm) ParseFormData(data model.HttpFormData, binSvc model.BinaryStorageInterface) (model.EntryMetaData, error) { + form := NewForm(meta, binSvc) + return form.Parse(data) +} + +type Form[T interface{}] struct { + data T + binSvc model.BinaryStorageInterface } type FormFieldParams struct { @@ -36,8 +36,8 @@ type FormField struct { Params FormFieldParams } -func NewForm(data interface{}, binaryService *app.BinaryService) *Form { - return &Form{ +func NewForm[T interface{}](data T, binaryService model.BinaryStorageInterface) *Form[T] { + return &Form[T]{ data: data, binSvc: binaryService, } @@ -63,8 +63,10 @@ func (s *FormField) ToWidget() Widget { return &TextListWidget{*s} case "password": return &PasswordWidget{*s} - default: + case "text": return &TextWidget{*s} + default: + return &OmitWidget{*s} } } @@ -118,7 +120,7 @@ func StructToFormFields(data interface{}) ([]FormField, error) { return fields, nil } -func (s *Form) HtmlForm() (string, error) { +func (s *Form[T]) HtmlForm() (string, error) { fields, err := StructToFormFields(s.data) if err != nil { return "", err @@ -132,17 +134,19 @@ func (s *Form) HtmlForm() (string, error) { return html, nil } -func (s *Form) Parse(ctx HttpFormData) (interface{}, error) { +func (s *Form[T]) Parse(ctx model.HttpFormData) (T, error) { + var empty T + if ctx == nil { - return nil, fmt.Errorf("nil context") + return empty, fmt.Errorf("nil context") } dataVal := reflect.ValueOf(s.data) if dataVal.Kind() != reflect.Ptr { - return nil, fmt.Errorf("meta data is not a pointer") + return empty, fmt.Errorf("meta data is not a pointer") } fields, err := StructToFormFields(s.data) if err != nil { - return nil, err + return empty, err } for _, field := range fields { fieldName := field.Name @@ -158,22 +162,22 @@ func (s *Form) Parse(ctx HttpFormData) (interface{}, error) { } continue } - return nil, err + return empty, err } fileData, err := file.Open() if err != nil { - return nil, err + return empty, err } defer fileData.Close() fileBytes := make([]byte, file.Size) _, err = fileData.Read(fileBytes) if err != nil { - return nil, err + return empty, err } binaryFile, err := s.binSvc.Create(file.Filename, fileBytes) if err != nil { - return nil, err + return empty, err } metaField := dataVal.Elem().FieldByName(fieldName) diff --git a/web/forms/widget.go b/web/forms/widget.go index 0c0c2e6..18f38b1 100644 --- a/web/forms/widget.go +++ b/web/forms/widget.go @@ -26,6 +26,19 @@ func (s *TextWidget) ParseValue(value string, output reflect.Value) error { return nil } +type OmitWidget struct { + FormField +} + +func (s *OmitWidget) Html() string { + html := "" + return html +} + +func (s *OmitWidget) ParseValue(value string, output reflect.Value) error { + return nil +} + type PasswordWidget struct { FormField } -- 2.40.1 From fcc0132758d6f21c8277ef8a871e360919e750bc Mon Sep 17 00:00:00 2001 From: Niko Abeler Date: Wed, 14 Feb 2024 19:53:49 +0100 Subject: [PATCH 2/6] first custom form --- entry_types/article.go | 16 ++++++++++++++-- render/templates/forms/Article.tmpl | 7 +++++++ tmp/build-errors.log | 2 +- web/editor_handler.go | 21 ++++----------------- 4 files changed, 26 insertions(+), 20 deletions(-) create mode 100644 render/templates/forms/Article.tmpl diff --git a/entry_types/article.go b/entry_types/article.go index d2c57ee..15a6198 100644 --- a/entry_types/article.go +++ b/entry_types/article.go @@ -4,7 +4,6 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" - "owl-blogs/web/forms" ) type Article struct { @@ -13,11 +12,24 @@ type Article struct { } type ArticleMetaData struct { - forms.DefaultForm Title string `owl:"inputType=text"` Content string `owl:"inputType=text widget=textarea"` } +// Form implements model.EntryMetaData. +func (meta *ArticleMetaData) Form(binSvc model.BinaryStorageInterface) string { + f, _ := render.RenderTemplateToString("forms/Article", meta) + return f +} + +// ParseFormData implements model.EntryMetaData. +func (*ArticleMetaData) ParseFormData(data model.HttpFormData, binSvc model.BinaryStorageInterface) (model.EntryMetaData, error) { + return &ArticleMetaData{ + Title: data.FormValue("title"), + Content: data.FormValue("content"), + }, nil +} + func (e *Article) Title() string { return e.meta.Title } diff --git a/render/templates/forms/Article.tmpl b/render/templates/forms/Article.tmpl new file mode 100644 index 0000000..65aaedd --- /dev/null +++ b/render/templates/forms/Article.tmpl @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/tmp/build-errors.log b/tmp/build-errors.log index 6c6d080..9ba0172 100644 --- a/tmp/build-errors.log +++ b/tmp/build-errors.log @@ -1 +1 @@ -exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1 \ No newline at end of file +exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1 \ No newline at end of file diff --git a/web/editor_handler.go b/web/editor_handler.go index 86e1be8..710ae85 100644 --- a/web/editor_handler.go +++ b/web/editor_handler.go @@ -5,7 +5,6 @@ import ( "owl-blogs/app/repository" "owl-blogs/domain/model" "owl-blogs/render" - "owl-blogs/web/forms" "time" "github.com/gofiber/fiber/v2" @@ -48,12 +47,7 @@ func (h *EditorHandler) HandleGetNew(c *fiber.Ctx) error { if err != nil { return err } - - form := forms.NewForm(entryType.MetaData(), h.binSvc) - htmlForm, err := form.HtmlForm() - if err != nil { - return err - } + htmlForm := entryType.MetaData().Form(h.binSvc) return render.RenderTemplateWithBase(c, getSiteConfig(h.configRepo), "views/editor", htmlForm) } @@ -65,9 +59,7 @@ func (h *EditorHandler) HandlePostNew(c *fiber.Ctx) error { return err } - form := forms.NewForm(entry.MetaData(), h.binSvc) - // get form data - entryMeta, err := form.Parse(c) + entryMeta, err := entry.MetaData().ParseFormData(c, h.binSvc) if err != nil { return err } @@ -100,11 +92,7 @@ func (h *EditorHandler) HandleGetEdit(c *fiber.Ctx) error { return err } - form := forms.NewForm(entry.MetaData(), h.binSvc) - htmlForm, err := form.HtmlForm() - if err != nil { - return err - } + htmlForm := entry.MetaData().Form(h.binSvc) return render.RenderTemplateWithBase(c, getSiteConfig(h.configRepo), "views/editor", htmlForm) } @@ -117,9 +105,8 @@ func (h *EditorHandler) HandlePostEdit(c *fiber.Ctx) error { return err } - form := forms.NewForm(entry.MetaData(), h.binSvc) // get form data - meta, err := form.Parse(c) + meta, err := entry.MetaData().ParseFormData(c, h.binSvc) if err != nil { return err } -- 2.40.1 From eee2131a76f29bc88e4161d4fe8310ac177266c8 Mon Sep 17 00:00:00 2001 From: Niko Abeler Date: Wed, 14 Feb 2024 20:43:43 +0100 Subject: [PATCH 3/6] more custom forms --- entry_types/bookmark.go | 18 ++++++++++-- entry_types/image.go | 41 ++++++++++++++++++++++++++-- render/templates/forms/Bookmark.tmpl | 10 +++++++ render/templates/forms/Image.tmpl | 10 +++++++ tmp/build-errors.log | 1 - web/forms/form_test.go | 4 +-- 6 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 render/templates/forms/Bookmark.tmpl create mode 100644 render/templates/forms/Image.tmpl delete mode 100644 tmp/build-errors.log diff --git a/entry_types/bookmark.go b/entry_types/bookmark.go index 45b6aab..e5ca2d8 100644 --- a/entry_types/bookmark.go +++ b/entry_types/bookmark.go @@ -4,7 +4,6 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" - "owl-blogs/web/forms" ) type Bookmark struct { @@ -13,13 +12,26 @@ type Bookmark struct { } type BookmarkMetaData struct { - forms.DefaultForm - Title string `owl:"inputType=text"` Url string `owl:"inputType=text"` Content string `owl:"inputType=text widget=textarea"` } +// Form implements model.EntryMetaData. +func (meta *BookmarkMetaData) Form(binSvc model.BinaryStorageInterface) string { + f, _ := render.RenderTemplateToString("forms/Bookmark", meta) + return f +} + +// ParseFormData implements model.EntryMetaData. +func (*BookmarkMetaData) ParseFormData(data model.HttpFormData, binSvc model.BinaryStorageInterface) (model.EntryMetaData, error) { + return &BookmarkMetaData{ + Title: data.FormValue("title"), + Url: data.FormValue("url"), + Content: data.FormValue("content"), + }, nil +} + func (e *Bookmark) Title() string { return e.meta.Title } diff --git a/entry_types/image.go b/entry_types/image.go index 5bdf251..7d7b0aa 100644 --- a/entry_types/image.go +++ b/entry_types/image.go @@ -4,7 +4,6 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" - "owl-blogs/web/forms" ) type Image struct { @@ -13,13 +12,49 @@ type Image struct { } type ImageMetaData struct { - forms.DefaultForm - ImageId string `owl:"inputType=file"` Title string `owl:"inputType=text"` Content string `owl:"inputType=text widget=textarea"` } +// Form implements model.EntryMetaData. +func (meta *ImageMetaData) Form(binSvc model.BinaryStorageInterface) string { + f, _ := render.RenderTemplateToString("forms/Image", meta) + return f +} + +// ParseFormData implements model.EntryMetaData. +func (meta *ImageMetaData) ParseFormData(data model.HttpFormData, binSvc model.BinaryStorageInterface) (model.EntryMetaData, error) { + file, err := data.FormFile("image") + var imgId = meta.ImageId + if err != nil && imgId == "" { + return nil, err + } else if err == nil { + fileData, err := file.Open() + if err != nil { + return nil, err + } + defer fileData.Close() + + fileBytes := make([]byte, file.Size) + _, err = fileData.Read(fileBytes) + if err != nil { + return nil, err + } + bin, err := binSvc.Create(file.Filename, fileBytes) + if err != nil { + return nil, err + } + imgId = bin.Id + } + + return &ImageMetaData{ + ImageId: imgId, + Title: data.FormValue("title"), + Content: data.FormValue("content"), + }, nil +} + func (e *Image) Title() string { return e.meta.Title } diff --git a/render/templates/forms/Bookmark.tmpl b/render/templates/forms/Bookmark.tmpl new file mode 100644 index 0000000..e482759 --- /dev/null +++ b/render/templates/forms/Bookmark.tmpl @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/render/templates/forms/Image.tmpl b/render/templates/forms/Image.tmpl new file mode 100644 index 0000000..1c78f6c --- /dev/null +++ b/render/templates/forms/Image.tmpl @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/tmp/build-errors.log b/tmp/build-errors.log deleted file mode 100644 index 9ba0172..0000000 --- a/tmp/build-errors.log +++ /dev/null @@ -1 +0,0 @@ -exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1 \ No newline at end of file diff --git a/web/forms/form_test.go b/web/forms/form_test.go index bd1bb56..eb011ce 100644 --- a/web/forms/form_test.go +++ b/web/forms/form_test.go @@ -103,6 +103,6 @@ func TestFormParse(t *testing.T) { form := forms.NewForm(&MockData{}, binService) data, err := form.Parse(NewMockFormData()) require.NoError(t, err) - require.NotZero(t, data.(*MockData).Image) - require.Equal(t, "Content", data.(*MockData).Content) + require.NotZero(t, data.Image) + require.Equal(t, "Content", data.Content) } -- 2.40.1 From 1fdcdff41d8c117ef9758f4813a84dd5e0798246 Mon Sep 17 00:00:00 2001 From: Niko Abeler Date: Wed, 14 Feb 2024 21:05:50 +0100 Subject: [PATCH 4/6] all entry types with custom forms --- entry_types/note.go | 16 +++++++++++++--- entry_types/page.go | 17 ++++++++++++++--- entry_types/recipe.go | 28 +++++++++++++++++++++++++--- entry_types/reply.go | 18 +++++++++++++++--- render/templates/forms/Article.tmpl | 4 +--- render/templates/forms/Bookmark.tmpl | 4 +--- render/templates/forms/Image.tmpl | 4 +--- render/templates/forms/Note.tmpl | 2 ++ render/templates/forms/Page.tmpl | 5 +++++ render/templates/forms/Recipe.tmpl | 15 +++++++++++++++ render/templates/forms/Reply.tmpl | 8 ++++++++ test/mock_entry.go | 13 ++++++++++--- web/forms/form.go | 13 ------------- 13 files changed, 110 insertions(+), 37 deletions(-) create mode 100644 render/templates/forms/Note.tmpl create mode 100644 render/templates/forms/Page.tmpl create mode 100644 render/templates/forms/Recipe.tmpl create mode 100644 render/templates/forms/Reply.tmpl diff --git a/entry_types/note.go b/entry_types/note.go index 7dd4157..7e1bcf6 100644 --- a/entry_types/note.go +++ b/entry_types/note.go @@ -4,7 +4,6 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" - "owl-blogs/web/forms" ) type Note struct { @@ -13,11 +12,22 @@ type Note struct { } type NoteMetaData struct { - forms.DefaultForm - Content string `owl:"inputType=text widget=textarea"` } +// Form implements model.EntryMetaData. +func (meta *NoteMetaData) Form(binSvc model.BinaryStorageInterface) string { + f, _ := render.RenderTemplateToString("forms/Note", meta) + return f +} + +// ParseFormData implements model.EntryMetaData. +func (*NoteMetaData) ParseFormData(data model.HttpFormData, binSvc model.BinaryStorageInterface) (model.EntryMetaData, error) { + return &NoteMetaData{ + Content: data.FormValue("content"), + }, nil +} + func (e *Note) Title() string { return "" } diff --git a/entry_types/page.go b/entry_types/page.go index 6952de4..9e088bf 100644 --- a/entry_types/page.go +++ b/entry_types/page.go @@ -4,7 +4,6 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" - "owl-blogs/web/forms" ) type Page struct { @@ -13,12 +12,24 @@ type Page struct { } type PageMetaData struct { - forms.DefaultForm - Title string `owl:"inputType=text"` Content string `owl:"inputType=text widget=textarea"` } +// Form implements model.EntryMetaData. +func (meta *PageMetaData) Form(binSvc model.BinaryStorageInterface) string { + f, _ := render.RenderTemplateToString("forms/Page", meta) + return f +} + +// ParseFormData implements model.EntryMetaData. +func (*PageMetaData) ParseFormData(data model.HttpFormData, binSvc model.BinaryStorageInterface) (model.EntryMetaData, error) { + return &PageMetaData{ + Title: data.FormValue("title"), + Content: data.FormValue("content"), + }, nil +} + func (e *Page) Title() string { return e.meta.Title } diff --git a/entry_types/recipe.go b/entry_types/recipe.go index 7442592..daa8a57 100644 --- a/entry_types/recipe.go +++ b/entry_types/recipe.go @@ -4,7 +4,7 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" - "owl-blogs/web/forms" + "strings" ) type Recipe struct { @@ -13,8 +13,6 @@ type Recipe struct { } type RecipeMetaData struct { - forms.DefaultForm - Title string `owl:"inputType=text"` Yield string `owl:"inputType=text"` Duration string `owl:"inputType=text"` @@ -22,6 +20,30 @@ type RecipeMetaData struct { Content string `owl:"inputType=text widget=textarea"` } +// Form implements model.EntryMetaData. +func (meta *RecipeMetaData) Form(binSvc model.BinaryStorageInterface) string { + f, _ := render.RenderTemplateToString("forms/Recipe", meta) + return f +} + +// ParseFormData implements model.EntryMetaData. +func (*RecipeMetaData) ParseFormData(data model.HttpFormData, binSvc model.BinaryStorageInterface) (model.EntryMetaData, error) { + ings := strings.Split(data.FormValue("ingredients"), "\n") + clean := make([]string, 0) + for _, ing := range ings { + if strings.TrimSpace(ing) != "" { + clean = append(clean, strings.TrimSpace(ing)) + } + } + return &RecipeMetaData{ + Title: data.FormValue("title"), + Yield: data.FormValue("yield"), + Duration: data.FormValue("duration"), + Ingredients: clean, + Content: data.FormValue("content"), + }, nil +} + func (e *Recipe) Title() string { return e.meta.Title } diff --git a/entry_types/reply.go b/entry_types/reply.go index ef23467..e82d0da 100644 --- a/entry_types/reply.go +++ b/entry_types/reply.go @@ -4,7 +4,6 @@ import ( "fmt" "owl-blogs/domain/model" "owl-blogs/render" - "owl-blogs/web/forms" ) type Reply struct { @@ -13,13 +12,26 @@ type Reply struct { } type ReplyMetaData struct { - forms.DefaultForm - Title string `owl:"inputType=text"` Url string `owl:"inputType=text"` Content string `owl:"inputType=text widget=textarea"` } +// Form implements model.EntryMetaData. +func (meta *ReplyMetaData) Form(binSvc model.BinaryStorageInterface) string { + f, _ := render.RenderTemplateToString("forms/Reply", meta) + return f +} + +// ParseFormData implements model.EntryMetaData. +func (*ReplyMetaData) ParseFormData(data model.HttpFormData, binSvc model.BinaryStorageInterface) (model.EntryMetaData, error) { + return &ReplyMetaData{ + Title: data.FormValue("title"), + Url: data.FormValue("url"), + Content: data.FormValue("content"), + }, nil +} + func (e *Reply) Title() string { return "Re: " + e.meta.Title } diff --git a/render/templates/forms/Article.tmpl b/render/templates/forms/Article.tmpl index 65aaedd..3b5e9ce 100644 --- a/render/templates/forms/Article.tmpl +++ b/render/templates/forms/Article.tmpl @@ -2,6 +2,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/render/templates/forms/Bookmark.tmpl b/render/templates/forms/Bookmark.tmpl index e482759..6e69609 100644 --- a/render/templates/forms/Bookmark.tmpl +++ b/render/templates/forms/Bookmark.tmpl @@ -5,6 +5,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/render/templates/forms/Image.tmpl b/render/templates/forms/Image.tmpl index 1c78f6c..9286c42 100644 --- a/render/templates/forms/Image.tmpl +++ b/render/templates/forms/Image.tmpl @@ -5,6 +5,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/render/templates/forms/Note.tmpl b/render/templates/forms/Note.tmpl new file mode 100644 index 0000000..63cb09d --- /dev/null +++ b/render/templates/forms/Note.tmpl @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/render/templates/forms/Page.tmpl b/render/templates/forms/Page.tmpl new file mode 100644 index 0000000..3b5e9ce --- /dev/null +++ b/render/templates/forms/Page.tmpl @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/render/templates/forms/Recipe.tmpl b/render/templates/forms/Recipe.tmpl new file mode 100644 index 0000000..bcf27bc --- /dev/null +++ b/render/templates/forms/Recipe.tmpl @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/render/templates/forms/Reply.tmpl b/render/templates/forms/Reply.tmpl new file mode 100644 index 0000000..aaca489 --- /dev/null +++ b/render/templates/forms/Reply.tmpl @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/test/mock_entry.go b/test/mock_entry.go index e9f9301..a21754f 100644 --- a/test/mock_entry.go +++ b/test/mock_entry.go @@ -2,19 +2,26 @@ package test import ( "owl-blogs/domain/model" - "owl-blogs/web/forms" "time" ) type MockEntryMetaData struct { - forms.DefaultForm - Str string Number int Date time.Time Title string } +// Form implements model.EntryMetaData. +func (*MockEntryMetaData) Form(binSvc model.BinaryStorageInterface) string { + panic("unimplemented") +} + +// ParseFormData implements model.EntryMetaData. +func (*MockEntryMetaData) ParseFormData(data model.HttpFormData, binSvc model.BinaryStorageInterface) (model.EntryMetaData, error) { + panic("unimplemented") +} + type MockEntry struct { model.EntryBase metaData *MockEntryMetaData diff --git a/web/forms/form.go b/web/forms/form.go index 3737bfd..2d2f5f3 100644 --- a/web/forms/form.go +++ b/web/forms/form.go @@ -7,19 +7,6 @@ import ( "strings" ) -type DefaultForm struct{} - -func (meta *DefaultForm) Form(binSvc model.BinaryStorageInterface) string { - form := NewForm(meta, nil) - htmlForm, _ := form.HtmlForm() - return htmlForm -} - -func (meta *DefaultForm) ParseFormData(data model.HttpFormData, binSvc model.BinaryStorageInterface) (model.EntryMetaData, error) { - form := NewForm(meta, binSvc) - return form.Parse(data) -} - type Form[T interface{}] struct { data T binSvc model.BinaryStorageInterface -- 2.40.1 From bd11b88338578a27f695a51d37eb62fbbaa03f87 Mon Sep 17 00:00:00 2001 From: Niko Abeler Date: Wed, 21 Feb 2024 20:03:18 +0100 Subject: [PATCH 5/6] removal of forms --- app/config_register.go | 17 +- cmd/owl/editor_test.go | 4 +- plugings/instagram.go | 15 ++ render/templates/forms/ActivityPubConfig.tmpl | 8 + render/templates/forms/InstagramConfig.tmpl | 5 + web/activity_pub_handler.go | 16 ++ web/admin_handler.go | 9 +- web/forms/form.go | 185 ------------------ web/forms/form_test.go | 108 ---------- web/forms/widget.go | 100 ---------- 10 files changed, 61 insertions(+), 406 deletions(-) create mode 100644 render/templates/forms/ActivityPubConfig.tmpl create mode 100644 render/templates/forms/InstagramConfig.tmpl delete mode 100644 web/forms/form.go delete mode 100644 web/forms/form_test.go delete mode 100644 web/forms/widget.go diff --git a/app/config_register.go b/app/config_register.go index 22d5f8c..01765a3 100644 --- a/app/config_register.go +++ b/app/config_register.go @@ -1,19 +1,26 @@ package app +import "owl-blogs/domain/model" + +type AppConfig interface { + Form(binSvc model.BinaryStorageInterface) string + ParseFormData(data model.HttpFormData, binSvc model.BinaryStorageInterface) (AppConfig, error) +} + type ConfigRegister struct { - configs map[string]interface{} + configs map[string]AppConfig } type RegisteredConfig struct { Name string - Config interface{} + Config AppConfig } func NewConfigRegister() *ConfigRegister { - return &ConfigRegister{configs: map[string]interface{}{}} + return &ConfigRegister{configs: map[string]AppConfig{}} } -func (r *ConfigRegister) Register(name string, config interface{}) { +func (r *ConfigRegister) Register(name string, config AppConfig) { r.configs[name] = config } @@ -28,6 +35,6 @@ func (r *ConfigRegister) Configs() []RegisteredConfig { return configs } -func (r *ConfigRegister) GetConfig(name string) interface{} { +func (r *ConfigRegister) GetConfig(name string) AppConfig { return r.configs[name] } diff --git a/cmd/owl/editor_test.go b/cmd/owl/editor_test.go index d7e4a56..7d570b6 100644 --- a/cmd/owl/editor_test.go +++ b/cmd/owl/editor_test.go @@ -77,9 +77,9 @@ func TestEditorFormPost(t *testing.T) { body := &bytes.Buffer{} writer := multipart.NewWriter(body) - part, _ := writer.CreateFormFile("ImageId", filepath.Base(file.Name())) + part, _ := writer.CreateFormFile("image", filepath.Base(file.Name())) io.Copy(part, file) - part, _ = writer.CreateFormField("Content") + part, _ = writer.CreateFormField("content") io.WriteString(part, "test content") writer.Close() diff --git a/plugings/instagram.go b/plugings/instagram.go index 2e52dba..c95611f 100644 --- a/plugings/instagram.go +++ b/plugings/instagram.go @@ -6,6 +6,7 @@ import ( "owl-blogs/app/repository" "owl-blogs/domain/model" entrytypes "owl-blogs/entry_types" + "owl-blogs/render" "github.com/Davincible/goinsta/v3" ) @@ -20,6 +21,20 @@ type InstagramConfig struct { Password string `owl:"widget=password"` } +// Form implements app.AppConfig. +func (cfg *InstagramConfig) Form(binSvc model.BinaryStorageInterface) string { + f, _ := render.RenderTemplateToString("forms/InstagramConfig", cfg) + return f +} + +// ParseFormData implements app.AppConfig. +func (*InstagramConfig) ParseFormData(data model.HttpFormData, binSvc model.BinaryStorageInterface) (app.AppConfig, error) { + return &InstagramConfig{ + User: data.FormValue("User"), + Password: data.FormValue("Password"), + }, nil +} + func RegisterInstagram( configRepo repository.ConfigRepository, configRegister *app.ConfigRegister, diff --git a/render/templates/forms/ActivityPubConfig.tmpl b/render/templates/forms/ActivityPubConfig.tmpl new file mode 100644 index 0000000..596bebc --- /dev/null +++ b/render/templates/forms/ActivityPubConfig.tmpl @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/render/templates/forms/InstagramConfig.tmpl b/render/templates/forms/InstagramConfig.tmpl new file mode 100644 index 0000000..c131350 --- /dev/null +++ b/render/templates/forms/InstagramConfig.tmpl @@ -0,0 +1,5 @@ + + + + + diff --git a/web/activity_pub_handler.go b/web/activity_pub_handler.go index d5d5eec..da9ae92 100644 --- a/web/activity_pub_handler.go +++ b/web/activity_pub_handler.go @@ -6,6 +6,7 @@ import ( "owl-blogs/app/repository" "owl-blogs/config" "owl-blogs/domain/model" + "owl-blogs/render" vocab "github.com/go-ap/activitypub" @@ -25,6 +26,21 @@ type ActivityPubConfig struct { PrivateKeyPem string `owl:"inputType=text widget=textarea"` } +// Form implements app.AppConfig. +func (cfg *ActivityPubConfig) Form(binSvc model.BinaryStorageInterface) string { + f, _ := render.RenderTemplateToString("forms/ActivityPubConfig", cfg) + return f +} + +// ParseFormData implements app.AppConfig. +func (*ActivityPubConfig) ParseFormData(data model.HttpFormData, binSvc model.BinaryStorageInterface) (app.AppConfig, error) { + return &ActivityPubConfig{ + PreferredUsername: data.FormValue("PreferredUsername"), + PublicKeyPem: data.FormValue("PublicKeyPem"), + PrivateKeyPem: data.FormValue("PrivateKeyPem"), + }, nil +} + type WebfingerResponse struct { Subject string `json:"subject"` Links []WebfingerLink `json:"links"` diff --git a/web/admin_handler.go b/web/admin_handler.go index 126a750..eb249f5 100644 --- a/web/admin_handler.go +++ b/web/admin_handler.go @@ -4,7 +4,6 @@ import ( "owl-blogs/app" "owl-blogs/app/repository" "owl-blogs/render" - "owl-blogs/web/forms" "sort" "github.com/gofiber/fiber/v2" @@ -14,6 +13,7 @@ type adminHandler struct { configRepo repository.ConfigRepository configRegister *app.ConfigRegister typeRegistry *app.EntryTypeRegistry + binSvc *app.BinaryService } type adminContet struct { @@ -75,8 +75,7 @@ func (h *adminHandler) HandleConfigGet(c *fiber.Ctx) error { } siteConfig := getSiteConfig(h.configRepo) - form := forms.NewForm(config, nil) - htmlForm, err := form.HtmlForm() + htmlForm := config.Form(h.binSvc) if err != nil { return err } @@ -93,9 +92,7 @@ func (h *adminHandler) HandleConfigPost(c *fiber.Ctx) error { return c.SendStatus(404) } - form := forms.NewForm(config, nil) - - newConfig, err := form.Parse(c) + newConfig, err := config.ParseFormData(c, h.binSvc) if err != nil { return err } diff --git a/web/forms/form.go b/web/forms/form.go deleted file mode 100644 index 2d2f5f3..0000000 --- a/web/forms/form.go +++ /dev/null @@ -1,185 +0,0 @@ -package forms - -import ( - "fmt" - "owl-blogs/domain/model" - "reflect" - "strings" -) - -type Form[T interface{}] struct { - data T - binSvc model.BinaryStorageInterface -} - -type FormFieldParams struct { - InputType string - Widget string -} - -type FormField struct { - Name string - Value reflect.Value - Params FormFieldParams -} - -func NewForm[T interface{}](data T, binaryService model.BinaryStorageInterface) *Form[T] { - return &Form[T]{ - data: data, - binSvc: binaryService, - } -} - -func (s *FormFieldParams) ApplyTag(tagKey string, tagValue string) error { - switch tagKey { - case "inputType": - s.InputType = tagValue - case "widget": - s.Widget = tagValue - default: - return fmt.Errorf("unknown tag key: %v", tagKey) - } - return nil -} - -func (s *FormField) ToWidget() Widget { - switch s.Params.Widget { - case "textarea": - return &TextareaWidget{*s} - case "textlist": - return &TextListWidget{*s} - case "password": - return &PasswordWidget{*s} - case "text": - return &TextWidget{*s} - default: - return &OmitWidget{*s} - } -} - -func (s *FormField) Html() string { - html := "" - html += fmt.Sprintf("\n", s.Name, s.Name) - if s.Params.InputType == "file" { - html += fmt.Sprintf("\n", s.Params.InputType, s.Name, s.Name, s.Value) - } else { - html += s.ToWidget().Html() - html += "\n" - } - return html -} - -func FieldToFormField(field reflect.StructField, value reflect.Value) (FormField, error) { - formField := FormField{ - Name: field.Name, - Value: value, - Params: FormFieldParams{}, - } - tag := field.Tag.Get("owl") - for _, param := range strings.Split(tag, " ") { - parts := strings.Split(param, "=") - if len(parts) != 2 { - continue - } - err := formField.Params.ApplyTag(parts[0], parts[1]) - if err != nil { - return FormField{}, err - } - } - return formField, nil -} - -func StructToFormFields(data interface{}) ([]FormField, error) { - dataValue := reflect.Indirect(reflect.ValueOf(data)) - dataType := reflect.TypeOf(data).Elem() - numFields := dataType.NumField() - fields := []FormField{} - for i := 0; i < numFields; i++ { - field, err := FieldToFormField( - dataType.Field(i), - dataValue.FieldByIndex([]int{i}), - ) - if err != nil { - return nil, err - } - fields = append(fields, field) - } - return fields, nil -} - -func (s *Form[T]) HtmlForm() (string, error) { - fields, err := StructToFormFields(s.data) - if err != nil { - return "", err - } - - html := "" - for _, field := range fields { - html += field.Html() - } - - return html, nil -} - -func (s *Form[T]) Parse(ctx model.HttpFormData) (T, error) { - var empty T - - if ctx == nil { - return empty, fmt.Errorf("nil context") - } - dataVal := reflect.ValueOf(s.data) - if dataVal.Kind() != reflect.Ptr { - return empty, fmt.Errorf("meta data is not a pointer") - } - fields, err := StructToFormFields(s.data) - if err != nil { - return empty, err - } - for _, field := range fields { - fieldName := field.Name - - if field.Params.InputType == "file" { - file, err := ctx.FormFile(fieldName) - if err != nil { - // If field already has a value, we can ignore the error - if field.Value != reflect.Zero(field.Value.Type()) { - metaField := dataVal.Elem().FieldByName(fieldName) - if metaField.IsValid() { - metaField.SetString(field.Value.String()) - } - continue - } - return empty, err - } - fileData, err := file.Open() - if err != nil { - return empty, err - } - defer fileData.Close() - fileBytes := make([]byte, file.Size) - _, err = fileData.Read(fileBytes) - if err != nil { - return empty, err - } - - binaryFile, err := s.binSvc.Create(file.Filename, fileBytes) - if err != nil { - return empty, err - } - - metaField := dataVal.Elem().FieldByName(fieldName) - if metaField.IsValid() { - metaField.SetString(binaryFile.Id) - } - } else { - formValue := ctx.FormValue(fieldName) - metaField := dataVal.Elem().FieldByName(fieldName) - if metaField.IsValid() { - field.ToWidget().ParseValue(formValue, metaField) - } - } - - } - - return s.data, nil -} diff --git a/web/forms/form_test.go b/web/forms/form_test.go deleted file mode 100644 index eb011ce..0000000 --- a/web/forms/form_test.go +++ /dev/null @@ -1,108 +0,0 @@ -package forms_test - -import ( - "bytes" - "io" - "mime/multipart" - "os" - "owl-blogs/app" - "owl-blogs/infra" - "owl-blogs/test" - "owl-blogs/web/forms" - "path" - "path/filepath" - "reflect" - "testing" - - "github.com/stretchr/testify/require" -) - -type MockData struct { - Image string `owl:"inputType=file"` - Content string `owl:"inputType=text"` -} - -type MockFormData struct { - fileHeader *multipart.FileHeader -} - -func NewMockFormData() *MockFormData { - fileDir, _ := os.Getwd() - fileName := "../../test/fixtures/test.png" - filePath := path.Join(fileDir, fileName) - - file, err := os.Open(filePath) - if err != nil { - panic(err) - } - defer file.Close() - - body := &bytes.Buffer{} - writer := multipart.NewWriter(body) - part, err := writer.CreateFormFile("ImagePath", filepath.Base(file.Name())) - if err != nil { - panic(err) - } - io.Copy(part, file) - writer.Close() - - multipartForm := multipart.NewReader(body, writer.Boundary()) - formData, err := multipartForm.ReadForm(0) - if err != nil { - panic(err) - } - fileHeader := formData.File["ImagePath"][0] - - return &MockFormData{fileHeader: fileHeader} -} - -func (f *MockFormData) FormFile(key string) (*multipart.FileHeader, error) { - return f.fileHeader, nil -} - -func (f *MockFormData) FormValue(key string, defaultValue ...string) string { - return key -} - -func TestFieldToFormField(t *testing.T) { - field := reflect.TypeOf(&MockData{}).Elem().Field(0) - formField, err := forms.FieldToFormField(field, reflect.Value{}) - require.NoError(t, err) - require.Equal(t, "Image", formField.Name) - require.Equal(t, "file", formField.Params.InputType) -} - -func TestStructToFields(t *testing.T) { - fields, err := forms.StructToFormFields(&MockData{}) - require.NoError(t, err) - require.Len(t, fields, 2) - require.Equal(t, "Image", fields[0].Name) - require.Equal(t, "file", fields[0].Params.InputType) - require.Equal(t, "Content", fields[1].Name) - require.Equal(t, "text", fields[1].Params.InputType) -} - -func TestForm_HtmlForm(t *testing.T) { - form := forms.NewForm(&MockData{}, nil) - html, err := form.HtmlForm() - require.NoError(t, err) - require.Contains(t, html, "\n", s.Name, s.Value.String()) - return html -} - -func (s *TextWidget) ParseValue(value string, output reflect.Value) error { - output.SetString(value) - return nil -} - -type OmitWidget struct { - FormField -} - -func (s *OmitWidget) Html() string { - html := "" - return html -} - -func (s *OmitWidget) ParseValue(value string, output reflect.Value) error { - return nil -} - -type PasswordWidget struct { - FormField -} - -func (s *PasswordWidget) Html() string { - html := "" - html += fmt.Sprintf("\n", s.Name, s.Value.String()) - return html -} - -func (s *PasswordWidget) 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("\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("\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 -} -- 2.40.1 From 1613d3dd112b74bd734c763d527566225bc3893a Mon Sep 17 00:00:00 2001 From: Niko Abeler Date: Wed, 21 Feb 2024 20:04:22 +0100 Subject: [PATCH 6/6] remove owl annotations --- entry_types/article.go | 4 ++-- entry_types/bookmark.go | 6 +++--- entry_types/image.go | 6 +++--- entry_types/note.go | 2 +- entry_types/page.go | 4 ++-- entry_types/recipe.go | 10 +++++----- entry_types/reply.go | 6 +++--- plugings/instagram.go | 4 ++-- web/activity_pub_handler.go | 6 +++--- 9 files changed, 24 insertions(+), 24 deletions(-) diff --git a/entry_types/article.go b/entry_types/article.go index 15a6198..8cd10ad 100644 --- a/entry_types/article.go +++ b/entry_types/article.go @@ -12,8 +12,8 @@ type Article struct { } type ArticleMetaData struct { - Title string `owl:"inputType=text"` - Content string `owl:"inputType=text widget=textarea"` + Title string + Content string } // Form implements model.EntryMetaData. diff --git a/entry_types/bookmark.go b/entry_types/bookmark.go index e5ca2d8..19b5d3e 100644 --- a/entry_types/bookmark.go +++ b/entry_types/bookmark.go @@ -12,9 +12,9 @@ type Bookmark struct { } type BookmarkMetaData struct { - Title string `owl:"inputType=text"` - Url string `owl:"inputType=text"` - Content string `owl:"inputType=text widget=textarea"` + Title string + Url string + Content string } // Form implements model.EntryMetaData. diff --git a/entry_types/image.go b/entry_types/image.go index 7d7b0aa..acb9cdc 100644 --- a/entry_types/image.go +++ b/entry_types/image.go @@ -12,9 +12,9 @@ type Image struct { } type ImageMetaData struct { - ImageId string `owl:"inputType=file"` - Title string `owl:"inputType=text"` - Content string `owl:"inputType=text widget=textarea"` + ImageId string + Title string + Content string } // Form implements model.EntryMetaData. diff --git a/entry_types/note.go b/entry_types/note.go index 7e1bcf6..f828465 100644 --- a/entry_types/note.go +++ b/entry_types/note.go @@ -12,7 +12,7 @@ type Note struct { } type NoteMetaData struct { - Content string `owl:"inputType=text widget=textarea"` + Content string } // Form implements model.EntryMetaData. diff --git a/entry_types/page.go b/entry_types/page.go index 9e088bf..37a7c97 100644 --- a/entry_types/page.go +++ b/entry_types/page.go @@ -12,8 +12,8 @@ type Page struct { } type PageMetaData struct { - Title string `owl:"inputType=text"` - Content string `owl:"inputType=text widget=textarea"` + Title string + Content string } // Form implements model.EntryMetaData. diff --git a/entry_types/recipe.go b/entry_types/recipe.go index daa8a57..f0eb117 100644 --- a/entry_types/recipe.go +++ b/entry_types/recipe.go @@ -13,11 +13,11 @@ type Recipe struct { } type RecipeMetaData struct { - Title string `owl:"inputType=text"` - Yield string `owl:"inputType=text"` - Duration string `owl:"inputType=text"` - Ingredients []string `owl:"inputType=text widget=textlist"` - Content string `owl:"inputType=text widget=textarea"` + Title string + Yield string + Duration string + Ingredients []string + Content string } // Form implements model.EntryMetaData. diff --git a/entry_types/reply.go b/entry_types/reply.go index e82d0da..1e088f6 100644 --- a/entry_types/reply.go +++ b/entry_types/reply.go @@ -12,9 +12,9 @@ type Reply struct { } type ReplyMetaData struct { - Title string `owl:"inputType=text"` - Url string `owl:"inputType=text"` - Content string `owl:"inputType=text widget=textarea"` + Title string + Url string + Content string } // Form implements model.EntryMetaData. diff --git a/plugings/instagram.go b/plugings/instagram.go index c95611f..5e045c4 100644 --- a/plugings/instagram.go +++ b/plugings/instagram.go @@ -17,8 +17,8 @@ type Instagram struct { } type InstagramConfig struct { - User string `owl:"widget=text"` - Password string `owl:"widget=password"` + User string + Password string } // Form implements app.AppConfig. diff --git a/web/activity_pub_handler.go b/web/activity_pub_handler.go index da9ae92..6783184 100644 --- a/web/activity_pub_handler.go +++ b/web/activity_pub_handler.go @@ -21,9 +21,9 @@ type ActivityPubServer struct { } type ActivityPubConfig struct { - PreferredUsername string `owl:"inputType=text"` - PublicKeyPem string `owl:"inputType=text widget=textarea"` - PrivateKeyPem string `owl:"inputType=text widget=textarea"` + PreferredUsername string + PublicKeyPem string + PrivateKeyPem string } // Form implements app.AppConfig. -- 2.40.1