package api import ( "encoding/json" "fmt" "html/template" "io/ioutil" "net/http" "sort" "strings" "github.com/gorilla/mux" "github.com/gorilla/schema" "gogs.carducci-dante.gov.it/karmen/core/orm" "gogs.carducci-dante.gov.it/karmen/core/renderer" "gogs.carducci-dante.gov.it/karmen/datasource/edt" ) var ( selectUniqueTeacherClasses = ` SELECT DISTINCT classes.* FROM activities INNER JOIN classes on classes.id=activities.class_id WHERE teacher_id=?` selectUniqueTeacherSubjects = ` SELECT DISTINCT subjects.* FROM activities INNER JOIN subjects on subjects.id=activities.subject_id WHERE activities.teacher_id=?` ) func teachersHandler() http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { var teachers []*orm.Teacher if err := orm.DB().Find(&teachers).Error; err != nil { panic(err) } for _, teacher := range teachers { orm.DB().Raw(selectUniqueTeacherClasses, teacher.ID).Scan(&teacher.Classes) orm.DB().Raw(selectUniqueTeacherSubjects, teacher.ID).Scan(&teacher.Subjects) } sort.Slice(teachers, func(i, j int) bool { return strings.ToLower(teachers[i].Surname) < strings.ToLower(teachers[j].Surname) }) if err := renderer.Render(w, "base", "teachers", teachers); err != nil { panic(err) } } return http.HandlerFunc(fn) } func teacherShowHandler() http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { var teacher orm.Teacher if err := orm.DB().First(&teacher, mux.Vars(r)["id"]).Error; err != nil { panic(err) } orm.DB().Raw(selectUniqueTeacherClasses, mux.Vars(r)["id"]).Scan(&teacher.Classes) sort.Slice(teacher.Classes, func(i, j int) bool { return strings.ToLower(teacher.Classes[i].Name) < strings.ToLower(teacher.Classes[j].Name) }) orm.DB().Raw(selectUniqueTeacherSubjects, mux.Vars(r)["id"]).Scan(&teacher.Subjects) sort.Slice(teacher.Subjects, func(i, j int) bool { return strings.ToLower(teacher.Subjects[i].Name) < strings.ToLower(teacher.Subjects[j].Name) }) orm.DB().Table("activities").Select("*").Where("teacher_id = ?", mux.Vars(r)["id"]).Scan(&teacher.Activities) sort.Slice(teacher.Activities, func(i, j int) bool { return teacher.Activities[i].Hours < teacher.Activities[j].Hours }) if err := renderer.Render(w, "base", "teachers_show", teacher); err != nil { panic(err) } } return http.HandlerFunc(fn) } func teachersAddHandler() http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { var data struct { Update bool SubmitUrl template.URL } data.SubmitUrl = template.URL(fmt.Sprintf("/teachers/add")) if err := renderer.Render(w, "base", "teachers_add_update", data); err != nil { panic(err) } } else if r.Method == "POST" { var teacher orm.Teacher if err := r.ParseForm(); err != nil { panic(err) } decoder := schema.NewDecoder() if err := decoder.Decode(&teacher, r.PostForm); err != nil { panic(err) } // Generate username and initial password teacher.Username = teacher.GenerateUsername() teacher.Password = teacher.GenerateSaltedPassword(teacher.Username) orm.DB().NewRecord(teacher) if err := orm.DB().Create(&teacher).Error; err != nil { panic(err) } http.Redirect(w, r, fmt.Sprintf("/teachers/%d", teacher.ID), http.StatusSeeOther) } } return http.HandlerFunc(fn) } func teachersDeleteHandler() http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { var teacher orm.Teacher if err := orm.DB().First(&teacher, mux.Vars(r)["id"]).Error; err != nil { panic(err) } if err := orm.DB().Delete(&teacher).Error; err != nil { panic(err) } var data struct { RedirectUrl string `json:"redirect_url"` } data.RedirectUrl = "/teachers" w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(data) } return http.HandlerFunc(fn) } func teacherUpdateHandler() http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { var data struct { Update bool SubmitUrl template.URL Teacher orm.Teacher } if err := orm.DB().First(&data.Teacher, mux.Vars(r)["id"]).Error; err != nil { panic(err) } data.Update = true data.SubmitUrl = template.URL(fmt.Sprintf("/teachers/%d/update", data.Teacher.ID)) if err := renderer.Render(w, "base", "teachers_add_update", data); err != nil { panic(err) } } else if r.Method == "POST" { var ( teacher orm.Teacher oldPassword string ) if err := orm.DB().First(&teacher, mux.Vars(r)["id"]).Error; err != nil { panic(err) } oldPassword = teacher.Password if err := r.ParseForm(); err != nil { panic(err) } decoder := schema.NewDecoder() if err := decoder.Decode(&teacher, r.PostForm); err != nil { panic(err) } if oldPassword != teacher.Password { teacher.Password = teacher.GenerateSaltedPassword(teacher.Password) } if err := orm.DB().Save(&teacher).Error; err != nil { panic(err) } var data struct { Teachers []orm.Teacher } data.Teachers = make([]orm.Teacher, 0) if err := orm.DB().Find(&data.Teachers).Error; err != nil { panic(err) } http.Redirect(w, r, fmt.Sprintf("/teachers/%d", teacher.ID), http.StatusSeeOther) } } return http.HandlerFunc(fn) } func teachersCheckUsernameHandler() http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { var teacher orm.Teacher var data struct { Exists bool `json:"exists"` } if orm.DB().Where("username = ?", mux.Vars(r)["username"]).Find(&teacher).RecordNotFound() { data.Exists = false } else { data.Exists = true } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(data) } return http.HandlerFunc(fn) } func teachersImportHandler() http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { r.ParseMultipartForm(32 << 20) file, _, err := r.FormFile("teachers_import") if err != nil { panic(err) } defer file.Close() data, err := ioutil.ReadAll(file) if err != nil { panic(err) } if importer, err := edt.NewImporter( string(data), map[string]string{ "COGNOME": "surname", "NOME": "name", }, ); err != nil { panic(err) } else { if err := orm.Import(&orm.Teacher{}, importer); err != nil { panic(err) } http.Redirect(w, r, "/teachers", http.StatusSeeOther) } } return http.HandlerFunc(fn) }