From 71997176b799f81ca985bffe8dd845ce9515cd87 Mon Sep 17 00:00:00 2001 From: Andrea Fazzi Date: Wed, 13 Nov 2019 15:54:17 +0100 Subject: [PATCH] Complete first iteration of question/answer MVC --- orm/answer.go | 90 +++++++++++++++++++-- orm/question.go | 41 +++++++++- renderer/funcmap.go | 13 +++ renderer/renderer.go | 8 +- template_generator/templates/add_update.tpl | 3 + template_generator/templates/show.tpl | 68 ++++------------ templates/answers.html.tpl | 2 +- templates/answers_add_update.html.tpl | 15 +++- templates/answers_show.html.tpl | 70 +++++----------- templates/error.html.tpl | 3 +- templates/layout/error.html.tpl | 32 ++++++++ templates/questions_add_update.html.tpl | 2 +- templates/questions_show.html.tpl | 69 ++++------------ 13 files changed, 242 insertions(+), 174 deletions(-) create mode 100644 templates/layout/error.html.tpl diff --git a/orm/answer.go b/orm/answer.go index 9c586370..539f5c4a 100644 --- a/orm/answer.go +++ b/orm/answer.go @@ -1,8 +1,10 @@ package orm import ( - "github.com/jinzhu/gorm" "net/http" + + "git.andreafazzi.eu/andrea/oef/renderer" + "github.com/jinzhu/gorm" ) type Answer struct { @@ -11,7 +13,11 @@ type Answer struct { Text string Correct bool - QuestionID uint + Question *Question + QuestionID uint `schema:"question_id"` + + AllQuestions []*Question `gorm:"-"` + Selected map[uint]string `gorm:"-"` } func (a *Answer) GetID() uint { return a.ID } @@ -21,11 +27,37 @@ func (a *Answer) String() string { } func (a *Answer) Create(args map[string]string, r *http.Request) (interface{}, error) { - return nil, nil + if r.Method == "GET" { + answer := new(Answer) + if err := DB().Find(&answer.AllQuestions).Error; err != nil { + return nil, err + } + + return answer, nil + } else { + answer := new(Answer) + err := renderer.Decode(answer, r) + if err != nil { + return nil, err + } + answer, err = CreateAnswer(answer) + if err != nil { + return nil, err + } + return answer, nil + } } func (a *Answer) Read(args map[string]string, r *http.Request) (interface{}, error) { - return nil, nil + var answer Answer + + id := args["id"] + + if err := DB().Preload("Question").First(&answer, id).Error; err != nil { + return nil, err + } + + return &answer, nil } func (a *Answer) ReadAll(args map[string]string, r *http.Request) (interface{}, error) { @@ -37,9 +69,57 @@ func (a *Answer) ReadAll(args map[string]string, r *http.Request) (interface{}, } func (a *Answer) Update(args map[string]string, r *http.Request) (interface{}, error) { - return nil, nil + if r.Method == "GET" { + result, err := a.Read(args, r) + if err != nil { + return nil, err + } + + answer := result.(*Answer) + + if err := DB().Find(&answer.AllQuestions).Error; err != nil { + return nil, err + } + + answer.Selected = make(map[uint]string) + answer.Selected[answer.QuestionID] = "selected" + + return answer, nil + } else { + answer, err := a.Read(args, nil) + if err != nil { + return nil, err + } + err = renderer.Decode(answer, r) + if err != nil { + return nil, err + } + _, err = SaveAnswer(answer) + if err != nil { + return nil, err + } + answer, err = a.Read(args, nil) + if err != nil { + return nil, err + } + return answer.(*Answer), nil + } } func (a *Answer) Delete(args map[string]string, r *http.Request) (interface{}, error) { return nil, nil } + +func CreateAnswer(answer *Answer) (*Answer, error) { + if err := DB().Create(answer).Error; err != nil { + return nil, err + } + return answer, nil +} + +func SaveAnswer(answer interface{}) (interface{}, error) { + if err := DB().Omit("Answers").Save(answer).Error; err != nil { + return nil, err + } + return answer, nil +} diff --git a/orm/question.go b/orm/question.go index 2715dd59..437b1949 100644 --- a/orm/question.go +++ b/orm/question.go @@ -11,6 +11,8 @@ type Question struct { gorm.Model Text string + + Answers []*Answer } func (q *Question) GetID() uint { return q.ID } @@ -37,7 +39,15 @@ func (q *Question) Create(args map[string]string, r *http.Request) (interface{}, } func (q *Question) Read(args map[string]string, r *http.Request) (interface{}, error) { - return nil, nil + var question Question + + id := args["id"] + + if err := DB().Preload("Answers").Where("id = ?", id).Find(&question).Error; err != nil { + return nil, err + } + + return &question, nil } func (q *Question) ReadAll(args map[string]string, r *http.Request) (interface{}, error) { @@ -49,7 +59,27 @@ func (q *Question) ReadAll(args map[string]string, r *http.Request) (interface{} } func (q *Question) Update(args map[string]string, r *http.Request) (interface{}, error) { - return nil, nil + if r.Method == "GET" { + return q.Read(args, r) + } else { + question, err := q.Read(args, nil) + if err != nil { + return nil, err + } + err = renderer.Decode(question, r) + if err != nil { + return nil, err + } + _, err = SaveQuestion(question) + if err != nil { + return nil, err + } + question, err = q.Read(args, nil) + if err != nil { + return nil, err + } + return question.(*Question), nil + } } func (q *Question) Delete(args map[string]string, r *http.Request) (interface{}, error) { @@ -62,3 +92,10 @@ func CreateQuestion(question *Question) (*Question, error) { } return question, nil } + +func SaveQuestion(question interface{}) (interface{}, error) { + if err := DB().Omit("Answers").Save(question).Error; err != nil { + return nil, err + } + return question, nil +} diff --git a/renderer/funcmap.go b/renderer/funcmap.go index 3e05c271..f55a9a53 100644 --- a/renderer/funcmap.go +++ b/renderer/funcmap.go @@ -13,6 +13,10 @@ import ( yml "gopkg.in/yaml.v2" ) +const ( + MaxTextLength = 20 +) + var ( funcMap = template.FuncMap{ "query": query, @@ -39,9 +43,18 @@ var ( "active": active, "pluralize": pluralize, "lower": lower, + "trim": trim, } ) +func trim(text string) string { + var result string + if len(text) > MaxTextLength { + result = text[0:MaxTextLength] + } + return result + "…" +} + func modelName(value interface{}) string { t := reflect.TypeOf(value) switch t.Kind() { diff --git a/renderer/renderer.go b/renderer/renderer.go index ee0cbcb6..c1e2c357 100644 --- a/renderer/renderer.go +++ b/renderer/renderer.go @@ -229,7 +229,7 @@ func (rend *HTMLRenderer) writeError(w http.ResponseWriter, r *http.Request, dat log.Println(data.(*htmlTemplateData).Data.(error)) w.Header().Set("Content-Type", "text/html; charset=utf-8") - e := t.ExecuteTemplate(w, "base", data) + e := t.ExecuteTemplate(w, "error", data) if e != nil { panic(e) } @@ -237,17 +237,17 @@ func (rend *HTMLRenderer) writeError(w http.ResponseWriter, r *http.Request, dat func (rend *HTMLRenderer) Render(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) { if data != nil && isErrorType(data) { - rend.writeError(w, r, &htmlTemplateData{data.(error), options[0]}) + rend.writeError(w, r, &htmlTemplateData{data.(error), nil}) } else { t, ok := rend.templates[options[0]["tpl_content"][0]] if !ok { err := fmt.Errorf("Template %s not found", options[0]["tpl_content"][0]) - rend.writeError(w, r, &htmlTemplateData{err, options[0]}) + rend.writeError(w, r, &htmlTemplateData{err, nil}) } w.Header().Set("Content-Type", "text/html; charset=utf-8") err := t.ExecuteTemplate(w, options[0]["tpl_layout"][0], &htmlTemplateData{data, options[0]}) if err != nil { - rend.writeError(w, r, &htmlTemplateData{err, options[0]}) + rend.writeError(w, r, &htmlTemplateData{err, nil}) } } } diff --git a/template_generator/templates/add_update.tpl b/template_generator/templates/add_update.tpl index b6597939..e1322f8b 100644 --- a/template_generator/templates/add_update.tpl +++ b/template_generator/templates/add_update.tpl @@ -19,6 +19,9 @@ role="form" {{" id={{$form}}>"}} +{{" {{$options := ` { cancelTitle: \"Annulla\", saveTitle: \"Salva\", model: "}}"{{.Model}}"{{" `}} "}} +{{" {{template \"submit_cancel_buttons\" dict \"options\" ($options|yaml) \"id\" (.Data|field \"ID\") \"update\" $update}} "}} + diff --git a/template_generator/templates/show.tpl b/template_generator/templates/show.tpl index 3ed3da40..e3dbc677 100644 --- a/template_generator/templates/show.tpl +++ b/template_generator/templates/show.tpl @@ -2,62 +2,26 @@
- - -
-
-
-

{{"{{.Data.Name}}"}}

-
-
- -
- - - Crea - - - - - Modifica - - -
- -
-
-
+{{" {{template \"breadcrumb\" toSlice \"ELEMENTS\" (all "}}"{{.Model}}"){{" (.Data|string) \"current\"}}"}} +{{" {{template \"show_header\" dict \"title\" (.Data|string) \"updatePath\" (.Data.ID|update "}} "{{.Model}}"){{" \"deletePath\" (.Data.ID|delete "}}"{{.Model}}"){{ "}}" }} +

GENERAL SECTION

+
- -

sub items

- {{"{{if .Data.Items}}"}} - - {{"{{else}}"}} -

All'attività non è associata alcuna materia - didattica. Clicca qui per - modificare questa attività didattica.

- {{"{{end}}"}} -
- -
+{{" {{$options := `"}} +{{" title: \"RELATIONS\""}} +{{" model: \"MODEL\""}} +{{" icon: \"ICON_CLASS\""}} +{{" `}}"}} + +{{" {{$noElements := \"NO ELEMENTS\"}}"}} +{{" {{template \"relation_list\" dict \"options\" ($options|yaml) \"data\" .Data.RELATIONS \"noElements\" $noElements}} "}} + +
+ + {{"{{ end }}"}} diff --git a/templates/answers.html.tpl b/templates/answers.html.tpl index 7ef350b4..55a349e5 100644 --- a/templates/answers.html.tpl +++ b/templates/answers.html.tpl @@ -16,7 +16,7 @@
{{range $element := .Data}} - + {{$element|string}}
{{$options := `noElements: "no subelements"`}} diff --git a/templates/answers_add_update.html.tpl b/templates/answers_add_update.html.tpl index 7863f113..e81c8712 100644 --- a/templates/answers_add_update.html.tpl +++ b/templates/answers_add_update.html.tpl @@ -5,12 +5,12 @@ {{if $update}} -{{template "breadcrumb" toSlice "Answers" (all "Answer") (.Data|string) (.Data.ID|show "Answer") "Aggiorna" "current"}} +{{template "breadcrumb" toSlice "Risposte" (all "Answer") (.Data|string) (.Data.ID|show "Answer") "Aggiorna" "current"}} {{else}} -{{template "breadcrumb" toSlice "Answers" (all "Answer") "Aggiungi" "current"}} +{{template "breadcrumb" toSlice "Risposte" (all "Answer") "Aggiungi" "current"}} {{end}} -{{template "add_update_header" dict "update" $update "addTitle" "Crea nuovo ELEMENTO" "updateTitle" (printf "Aggiorna ELEMENTO %s" (.Data|string))}} +{{template "add_update_header" dict "update" $update "addTitle" "Crea nuova risposta" "updateTitle" (printf "Aggiorna risposta %s" (.Data|string|trim))}} {{$form := "form_add_update"}}
+ {{$options := ` { name: "Text",id: "answer_text",label: "Testo della risposta",placeholder: "Inserire il testo della risposta",type: "text",required: "true"} `}} + {{template "input" dict "options" ($options|yaml) "value" (.Data|field "Text") "update" $update}} + + {{$options := ` { name: "question_id", id: "question_id", label: "Domanda relativa a questa risposta", title: "Seleziona la domanda"}`}} + {{template "select" dict "options" ($options|yaml) "data" (.Data|field "AllQuestions") "selected" (.Data|field "Selected") "update" $update "form" $form}} + + {{$options := ` { cancelTitle: "Annulla", saveTitle: "Salva", model: "Answer"} `}} + {{template "submit_cancel_buttons" dict "options" ($options|yaml) "id" (.Data|field "ID") "update" $update}} +
diff --git a/templates/answers_show.html.tpl b/templates/answers_show.html.tpl index 4ce85882..9613bd5f 100644 --- a/templates/answers_show.html.tpl +++ b/templates/answers_show.html.tpl @@ -2,62 +2,28 @@
- - -
-
-
-

{{.Data.Name}}

-
-
- -
- - - Crea - - - - - Modifica - - -
- -
-
-
+ {{template "breadcrumb" toSlice "Risposte" (all "Answer") (.Data|string|trim) "current"}} + {{template "show_header" dict "title" (.Data|string|trim) "updatePath" (.Data.ID|update "Answer") "deletePath" (.Data.ID|delete "Answer")}} +

Testo della risposta

+

+ {{.Data.Text}} +

- -

sub items

- {{if .Data.Items}} - - {{else}} -

All'attività non è associata alcuna materia - didattica. Clicca qui per - modificare questa attività didattica.

- {{end}} -
- -
+ {{$options := ` + title: "Domanda relativa alla risposta" + model: "Question" + icon: "fa fa-question-circle" + `}} + + {{$noElements := "nessuna domanda relativa a questa risposta"}} + {{template "relation_list" dict "options" ($options|yaml) "data" .Data.Question "noElements" $noElements}} + +
+
+ {{ end }} diff --git a/templates/error.html.tpl b/templates/error.html.tpl index 6d22c749..d46d787b 100644 --- a/templates/error.html.tpl +++ b/templates/error.html.tpl @@ -1,10 +1,9 @@ {{ define "content" }} -

Errore

- {{.}} + {{.Data}}

diff --git a/templates/layout/error.html.tpl b/templates/layout/error.html.tpl new file mode 100644 index 00000000..5a6bdb0b --- /dev/null +++ b/templates/layout/error.html.tpl @@ -0,0 +1,32 @@ +{{define "error"}} + + + + + + + + Olimpiadi di Economia e Finanza - Piattaforma di gara + + + + + + +
+ {{ template "content" . }} +
+ + + + + +{{end}} diff --git a/templates/questions_add_update.html.tpl b/templates/questions_add_update.html.tpl index 13810ea3..f57ec984 100644 --- a/templates/questions_add_update.html.tpl +++ b/templates/questions_add_update.html.tpl @@ -10,7 +10,7 @@ {{template "breadcrumb" toSlice "Domande" (all "Question") "Aggiungi" "current"}} {{end}} -{{template "add_update_header" dict "update" $update "addTitle" "Crea nuova domanda" "updateTitle" (printf "Aggiorna domanda %s" (.Data|string))}} +{{template "add_update_header" dict "update" $update "addTitle" "Crea nuova domanda" "updateTitle" (printf "Aggiorna domanda \"%s\"" (.Data|string|trim))}} {{$form := "form_add_update"}}
- - -
-
-
-

{{.Data.Name}}

-
-
- -
- - - Crea - - - - - Modifica - - -
- -
-
-
+ {{template "breadcrumb" toSlice "Domande" (all "Question") (.Data|string|trim) "current"}} + {{template "show_header" dict "title" (.Data|string|trim) "updatePath" (.Data.ID|update "Question") "deletePath" (.Data.ID|delete "Question")}} +

Testo della domanda

+

{{.Data.Text}}

+
- -

sub items

- {{if .Data.Items}} - - {{else}} -

All'attività non è associata alcuna materia - didattica. Clicca qui per - modificare questa attività didattica.

- {{end}} -
- -
+ {{$options := ` + title: "Risposte alla domanda" + model: "Answer" + icon: "fa fa-reply" + `}} + + {{$noElements := "Alla domanda non è associata alcuna risposta."}} + {{template "relation_list" dict "options" ($options|yaml) "data" .Data.Answers "noElements" $noElements}} + + + + {{ end }}