Erstelle Maske, um Sprechstunden hinzuzufügen
This commit is contained in:
parent
c7a9522c2c
commit
369f4ebcec
15 changed files with 357 additions and 50 deletions
174
controllers/addOfficeHourHandlers.go
Normal file
174
controllers/addOfficeHourHandlers.go
Normal file
|
@ -0,0 +1,174 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"net/mail"
|
||||
"sprechstundentool/models"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type maskData struct {
|
||||
Courses []models.Course
|
||||
Rooms []models.Room
|
||||
MinuteGranularity int
|
||||
SelectedCourse int
|
||||
SelectedRoom int
|
||||
Week int
|
||||
Day int
|
||||
Hour int
|
||||
Minute int
|
||||
Duration int
|
||||
Roomname string
|
||||
Name string
|
||||
Email string
|
||||
Info string
|
||||
Errors []string
|
||||
}
|
||||
|
||||
func (b *BaseHandler) AddOfficeHourHandler(w http.ResponseWriter, req *http.Request) {
|
||||
var errors []string
|
||||
courses, err := b.courseRepo.GetAll()
|
||||
if err != nil {
|
||||
errors = append(errors, err.Error())
|
||||
}
|
||||
rooms, err := b.roomRepo.GetAll()
|
||||
if err != nil {
|
||||
errors = append(errors, err.Error())
|
||||
}
|
||||
//Parse course
|
||||
courseid, err := strconv.Atoi(req.FormValue("veranstaltung"))
|
||||
if err != nil {
|
||||
errors = append(errors, "Die Veranstaltung muss eine ganze Zahl sein.")
|
||||
}
|
||||
course, err := b.courseRepo.FindById(courseid)
|
||||
if err != nil {
|
||||
errors = append(errors, "Die Veranstaltung muss existieren.")
|
||||
}
|
||||
//Parse room
|
||||
roomid, err := strconv.Atoi(req.FormValue("raum"))
|
||||
if err != nil {
|
||||
errors = append(errors, "Der Raum muss eine ganze Zahl sein.")
|
||||
}
|
||||
room, err := b.roomRepo.FindById(roomid)
|
||||
if err != nil {
|
||||
errors = append(errors, "Der Raum muss existieren.")
|
||||
}
|
||||
//Parse date
|
||||
week, err := strconv.Atoi(req.FormValue("woche"))
|
||||
if err != nil {
|
||||
errors = append(errors, "Die Woche muss eine ganze Zahl sein.")
|
||||
}
|
||||
if !(week >= 0 && week <= 2) {
|
||||
errors = append(errors, "Sprechstunden müssen jede, jede gerade oder jede ungerade Woche stattfinden.")
|
||||
}
|
||||
day, err := strconv.Atoi(req.FormValue("tag"))
|
||||
if err != nil {
|
||||
errors = append(errors, "Der Tag muss eine ganze Zahl sein.")
|
||||
}
|
||||
if !(day >= 0 && day <= 4) {
|
||||
errors = append(errors, "Sprechstunden müssen von Montag bis Freitag stattfinden.")
|
||||
}
|
||||
time := strings.SplitN(req.FormValue("startzeit"), ":", 2)
|
||||
var hour, minute int
|
||||
if len(time) != 2 {
|
||||
errors = append(errors, "Die Zeit muss im Format HH:MM sein.")
|
||||
} else {
|
||||
hour, err = strconv.Atoi(time[0])
|
||||
if err != nil {
|
||||
errors = append(errors, "Die Stunde muss eine ganze Zahl sein.")
|
||||
}
|
||||
if !(hour >= 8 && hour <= 17) {
|
||||
errors = append(errors, fmt.Sprintf("Sprechstunden müssen zwischen 08:00 Uhr und 17:%d starten.", 60-models.MinuteGranularity))
|
||||
}
|
||||
minute, err = strconv.Atoi(time[1])
|
||||
if err != nil {
|
||||
errors = append(errors, "Die Minute muss eine ganze Zahl sein.")
|
||||
}
|
||||
if !(minute >= 0 && minute <= 60-models.MinuteGranularity && minute%models.MinuteGranularity == 0) {
|
||||
errors = append(errors, fmt.Sprintf("Sprechstunden dürfen nur alle %d Minuten starten.", models.MinuteGranularity))
|
||||
}
|
||||
}
|
||||
duration, err := strconv.Atoi(req.FormValue("dauer"))
|
||||
if err != nil {
|
||||
errors = append(errors, "Die Dauer muss eine ganze Zahl sein.")
|
||||
}
|
||||
if !(duration >= models.MinuteGranularity && duration <= 120 && duration%models.MinuteGranularity == 0) {
|
||||
errors = append(errors, fmt.Sprintf("Sprechstunden müssen zwischen %d und 120 Minuten lang sein.", models.MinuteGranularity))
|
||||
}
|
||||
|
||||
roomname := req.FormValue("raumname")
|
||||
name := req.FormValue("name")
|
||||
if name == "" {
|
||||
errors = append(errors, "Der Name darf nicht leer sein.")
|
||||
}
|
||||
email, err := mail.ParseAddress(req.FormValue("email"))
|
||||
if err != nil {
|
||||
email = &mail.Address{"", req.FormValue("email")}
|
||||
errors = append(errors, "Mailaddresse konnte nicht geparst werden.")
|
||||
} else if !strings.HasSuffix(email.Address, "tu-darmstadt.de") {
|
||||
errors = append(errors, "Mailaddresse muss auf „tu-darmstadt.de“ enden.")
|
||||
}
|
||||
info := req.FormValue("info")
|
||||
|
||||
if len(errors) != 0 {
|
||||
var data maskData = maskData{
|
||||
courses,
|
||||
rooms,
|
||||
models.MinuteGranularity,
|
||||
courseid,
|
||||
roomid,
|
||||
week,
|
||||
day,
|
||||
hour,
|
||||
minute,
|
||||
duration,
|
||||
roomname,
|
||||
name,
|
||||
email.Address,
|
||||
info,
|
||||
errors,
|
||||
}
|
||||
b.writeAddOfficeHourMask(w, req, data)
|
||||
} else {
|
||||
officeHour := models.OfficeHour{0,
|
||||
models.Tutor{0, name, email.Address},
|
||||
models.Date{week, day, hour, minute},
|
||||
room,
|
||||
course,
|
||||
info,
|
||||
false,
|
||||
duration,
|
||||
}
|
||||
err := b.officeHourRepo.Add(officeHour)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
failureTemplate, parseErr := template.ParseFiles("templates/addFailure.html")
|
||||
if parseErr != nil {
|
||||
w.Write([]byte(fmt.Sprintf("Template konnte nicht geparst werden : %s", string(err.Error()))))
|
||||
return
|
||||
}
|
||||
failureTemplate.Execute(w, err)
|
||||
}
|
||||
http.Redirect(w, req, "/", http.StatusTemporaryRedirect)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BaseHandler) writeAddOfficeHourMask(w http.ResponseWriter, req *http.Request, data maskData) {
|
||||
tmpl, err := template.ParseFiles("templates/addMask.html")
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(fmt.Sprintf("Template konnte nicht geparst werden : %s", string(err.Error()))))
|
||||
return
|
||||
}
|
||||
if len(data.Errors) != 0 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
}
|
||||
err = tmpl.Execute(w, data)
|
||||
if err != nil {
|
||||
w.Write([]byte(fmt.Sprintf("Template konnte nicht geparst werden : %s", string(err.Error()))))
|
||||
return
|
||||
}
|
||||
}
|
16
controllers/baseHandler.go
Normal file
16
controllers/baseHandler.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package controllers
|
||||
|
||||
import "sprechstundentool/models"
|
||||
|
||||
// BaseHandler will hold everything that controller needs
|
||||
type BaseHandler struct {
|
||||
roomRepo models.RoomRepository
|
||||
officeHourRepo models.OfficeHourRepository
|
||||
courseRepo models.CourseRepository
|
||||
tutorRepo models.TutorRepository
|
||||
}
|
||||
|
||||
// NewBaseHandler returns a new BaseHandler
|
||||
func NewBaseHandler(roomRepo models.RoomRepository, officeHourRepo models.OfficeHourRepository, courseRepo models.CourseRepository, tutorRepo models.TutorRepository) *BaseHandler {
|
||||
return &BaseHandler{roomRepo, officeHourRepo, courseRepo, tutorRepo}
|
||||
}
|
|
@ -8,19 +8,6 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
// BaseHandler will hold everything that controller needs
|
||||
type BaseHandler struct {
|
||||
roomRepo models.RoomRepository
|
||||
officeHourRepo models.OfficeHourRepository
|
||||
courseRepo models.CourseRepository
|
||||
tutorRepo models.TutorRepository
|
||||
}
|
||||
|
||||
// NewBaseHandler returns a new BaseHandler
|
||||
func NewBaseHandler(roomRepo models.RoomRepository, officeHourRepo models.OfficeHourRepository, courseRepo models.CourseRepository, tutorRepo models.TutorRepository) *BaseHandler {
|
||||
return &BaseHandler{roomRepo, officeHourRepo, courseRepo, tutorRepo}
|
||||
}
|
||||
|
||||
func (b *BaseHandler) RootHandler(w http.ResponseWriter, req *http.Request) {
|
||||
b.writeTimetablePage(w, req, template.HTML(""))
|
||||
}
|
||||
|
@ -33,7 +20,7 @@ func (b *BaseHandler) GetByRoomHandler(w http.ResponseWriter, req *http.Request)
|
|||
b.RootHandler(w, req)
|
||||
return
|
||||
}
|
||||
officeHours, _ := b.officeHourRepo.FindByRoom(room)
|
||||
officeHours, _ := b.officeHourRepo.FindByRoom(room, true)
|
||||
b.writeTimetablePage(w, req, printTimetable(GetTimetable(officeHours)))
|
||||
}
|
||||
|
||||
|
@ -47,7 +34,7 @@ func (b *BaseHandler) GetByCourseHandler(w http.ResponseWriter, req *http.Reques
|
|||
b.RootHandler(w, req)
|
||||
return
|
||||
}
|
||||
officeHours, _ := b.officeHourRepo.FindByCourse(course)
|
||||
officeHours, _ := b.officeHourRepo.FindByCourse(course, true)
|
||||
b.writeTimetablePage(w, req, printTimetable(GetTimetable(officeHours)))
|
||||
}
|
||||
|
|
@ -13,20 +13,20 @@ func GetTimetable(officeHours []models.OfficeHour) (timetable map[models.Date]ma
|
|||
for _, officeHour := range officeHours {
|
||||
var slot int = 0
|
||||
for minute := 0; minute < officeHour.Duration; minute += models.MinuteGranularity { // find slot id
|
||||
_, exists := fullTimetable[models.Date{officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}]
|
||||
_, exists := fullTimetable[models.Date{0, officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}]
|
||||
if exists {
|
||||
_, exists := fullTimetable[models.Date{officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}][slot]
|
||||
_, exists := fullTimetable[models.Date{0, officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}][slot]
|
||||
if exists {
|
||||
slot += 1
|
||||
minute = 0
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
fullTimetable[models.Date{officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}] = make(map[int]models.OfficeHour)
|
||||
fullTimetable[models.Date{0, officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}] = make(map[int]models.OfficeHour)
|
||||
}
|
||||
}
|
||||
for minute := 0; minute < officeHour.Duration; minute += models.MinuteGranularity { // write officeHour id to timetable
|
||||
fullTimetable[models.Date{officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}][slot] = officeHour
|
||||
fullTimetable[models.Date{0, officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}][slot] = officeHour
|
||||
}
|
||||
}
|
||||
slots = []int{1, 1, 1, 1, 1}
|
||||
|
@ -61,16 +61,16 @@ func printTimetable(timetable map[models.Date]map[int]models.OfficeHour, slots [
|
|||
}
|
||||
for day := 0; day < 5; day += 1 {
|
||||
for slot := 0; slot < slots[day]; slot += 1 {
|
||||
current, currentExists := timetable[models.Date{day, hour, minute}][slot]
|
||||
current, currentExists := timetable[models.Date{0, day, hour, minute}][slot]
|
||||
|
||||
if currentExists { // This slot is taken by some office hour
|
||||
var continued bool = false // is this slot occupied by the same office hour the previous minute?
|
||||
var predecessorExists bool
|
||||
var predecessor models.OfficeHour
|
||||
if hour > 0 && minute < models.MinuteGranularity {
|
||||
predecessor, predecessorExists = timetable[models.Date{day, hour - 1, 60 - models.MinuteGranularity}][slot]
|
||||
predecessor, predecessorExists = timetable[models.Date{0, day, hour - 1, 60 - models.MinuteGranularity}][slot]
|
||||
} else {
|
||||
predecessor, predecessorExists = timetable[models.Date{day, hour, minute - models.MinuteGranularity}][slot]
|
||||
predecessor, predecessorExists = timetable[models.Date{0, day, hour, minute - models.MinuteGranularity}][slot]
|
||||
}
|
||||
if predecessorExists {
|
||||
continued = (predecessor == current)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
INSERT INTO `room` (name, max_occupy) VALUES ('S2 15 345',2),('S2 15 415',1),('S2 15 336',2),('S2 15 444',1),('S2 15 333',1),('S2 14 420',1),('Sonstige',1024);
|
||||
INSERT INTO `officeHour` VALUES (0,1,1,12,0,1,1,0,'',true,60),(1,1,1,12,15,2,1,0,'',true,60),(2,1,1,12,30,1,2,0,'',true,60);
|
||||
INSERT INTO `officeHour` (tutor, day, hour, minute, room, course, week, info, active, duration) VALUES (1,1,12,0,1,1,0,'',true,60),(1,1,12,15,2,1,0,'',true,60),(1,1,12,30,1,2,0,'',true,60);
|
||||
INSERT INTO `tutor` (name, email) VALUES ('Dummyname','dummy@example.com');
|
||||
INSERT INTO `course` (name) VALUES ('Integrationstheorie'),('Analysis II (engl.)'),('Analysis II'),('Mathe II für Informatik'),('Mathe II für Bauwesen'),('Diskrete Optimierung'),('Lineare Algebra II'),('Einführung in die Algebra'),('FGdI I&II'),('Algorithmic Discrete Mathematics'),('Einführung in die Stochastik'),('Mathe II für ET'),('Mathe II für Maschinenbau'),('Mathe IV für Maschinenbau'),('Num Mathe für MB (IV)'),('Höhere Mathematik II'),('Elementare PDE'),('LA für Physik und Lehramt'),('Analysis I'),('Mathe III ET'),('Mathe I für Informatik'),('Complex Analysis'),('Mathe & Statistik für Biologen'),('Mathe I für Maschinenbau'),('Mathe I für Bau'),('Nichtlineare Optimierung'),('Einführung in die Numerische Mathematik'),('Differentialgeometrie'),('Mathe I für ET'),('Mathe III (Bau)'),('W. Theorie'),('Gewöhnliche Differentialgleichungen'),('Geometrie für Lehramt'),('Mathe III MB'),('Statistik I für Humanwissenschaftler'),('Einführung in die Optimierung'),('Algebra'),('Lineare Algebra I'),('Höhere Mathematik 1'),('Darstellende Geometrie'),('Statistik 1 für WI'),('Diskrete Mathematik'),('Linear Algebra I (engl.)'),('Introduction to mathematical logic'),('Statistik I für WI'),('Weihnachtsknobelstraße'),('Numerische Lineare Algebra'),('Mathe IV (ET) / Mathe III (Inf) / Praktische Mathe (MEd)'),('Topologie'),('Linear Algebra II (engl.)'),('Einführung in die Finanzmathematik'),('Einführung in die mathematische Software'),('Mathematische Statistik'),('Algebraische Kurven'),('Analysis I (engl.)'),('Funktionalanalysis'),('Lebensversicherungsmathematik'),('Automaten, Formale Sprachen und Entscheidbarkeit (FGdI)'),('Mathematik für Chemiker'),('Numerik gewöhnlicher Differentialgleichungen'),('Darstellungstheorie'),('Aussagen- und Prädikatenlogik'),('Riemannsche Flächen'),('Mathematische Grundlagen der Quantenmechanik'),('Elementare Zahlentheorie'),('Einführung in die mathematische Modellierung'),('Stochastische Prozesse I'),('Mathematik im Kontext'),('Funktionalanalysis II'),('Mathematik IV (für ET) /Mathematik III (für Inf) /PraktischeMathematik (für M.Ed.Math)'),('Differentialgeometrie fuer VI'),('Probability Theory'),('Mathe für MINT'),('Mathematik als gemeinsame Sprache der Naturwissenschaften'),('Lineare Algebra I für Physiker'),('Manifolds'),('Kurvenschätzung'),('Spieltheorie'),('Einführung in die Programmierung'),('Algebraische Topologie'),('Schadenversicherungsmathematik'),('Partial Differential Equations I');
|
||||
|
|
2
main.go
2
main.go
|
@ -20,7 +20,7 @@ func main() {
|
|||
|
||||
http.HandleFunc("/getByRoom", h.GetByRoomHandler)
|
||||
http.HandleFunc("/getByCourse", h.GetByCourseHandler)
|
||||
|
||||
http.HandleFunc("/addOfficeHour", h.AddOfficeHourHandler)
|
||||
http.HandleFunc("/", h.RootHandler)
|
||||
|
||||
http.ListenAndServe(":8080", nil)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
package models
|
||||
|
||||
type Date struct {
|
||||
Week int
|
||||
Day int
|
||||
Hour int
|
||||
Minute int
|
||||
|
|
|
@ -4,7 +4,6 @@ package models
|
|||
type OfficeHour struct {
|
||||
Id int
|
||||
Tutor Tutor
|
||||
Week int
|
||||
Date
|
||||
Room Room
|
||||
Course Course
|
||||
|
@ -15,9 +14,9 @@ type OfficeHour struct {
|
|||
|
||||
type OfficeHourRepository interface {
|
||||
FindById(id int) (OfficeHour, error)
|
||||
FindByCourse(course Course) ([]OfficeHour, error)
|
||||
FindByRoom(room Room) ([]OfficeHour, error)
|
||||
GetAll() ([]OfficeHour, error)
|
||||
FindByCourse(course Course, activeOnly bool) ([]OfficeHour, error)
|
||||
FindByRoom(room Room, activatedOnly bool) ([]OfficeHour, error)
|
||||
GetAll(activatedOnly bool) ([]OfficeHour, error)
|
||||
Delete(officeHour OfficeHour) error
|
||||
Add(officeHour OfficeHour) error
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ type Tutor struct {
|
|||
|
||||
type TutorRepository interface {
|
||||
FindByEmail(Email string) ([]Tutor, error)
|
||||
FindByNameAndEmail(name string, email string) (Tutor, error)
|
||||
FindById(Id int) (Tutor, error)
|
||||
GetAll() ([]Tutor, error)
|
||||
Add(tutor Tutor) error
|
||||
|
|
|
@ -22,8 +22,14 @@ func NewOfficeHourRepo(db *sql.DB, roomRepo *RoomRepo, tutorRepo *TutorRepo, cou
|
|||
}
|
||||
}
|
||||
|
||||
func (r *OfficeHourRepo) GetAll() ([]models.OfficeHour, error) {
|
||||
rows, err := r.db.Query("SELECT * FROM officeHour")
|
||||
func (r *OfficeHourRepo) GetAll(activeOnly bool) ([]models.OfficeHour, error) {
|
||||
var rows *sql.Rows
|
||||
var err error
|
||||
if activeOnly {
|
||||
rows, err = r.db.Query("SELECT * FROM officeHour WHERE active")
|
||||
} else {
|
||||
rows, err = r.db.Query("SELECT * FROM officeHour")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -31,8 +37,14 @@ func (r *OfficeHourRepo) GetAll() ([]models.OfficeHour, error) {
|
|||
return r.getFromRows(rows)
|
||||
}
|
||||
|
||||
func (r *OfficeHourRepo) FindByCourse(course models.Course) ([]models.OfficeHour, error) {
|
||||
rows, err := r.db.Query("SELECT * FROM officeHour WHERE course=?", course.Id)
|
||||
func (r *OfficeHourRepo) FindByCourse(course models.Course, activeOnly bool) ([]models.OfficeHour, error) {
|
||||
var rows *sql.Rows
|
||||
var err error
|
||||
if activeOnly {
|
||||
rows, err = r.db.Query("SELECT * FROM officeHour WHERE course=? and active", course.Id)
|
||||
} else {
|
||||
rows, err = r.db.Query("SELECT * FROM officeHour WHERE course=?", course.Id)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -40,8 +52,14 @@ func (r *OfficeHourRepo) FindByCourse(course models.Course) ([]models.OfficeHour
|
|||
return r.getFromRows(rows)
|
||||
}
|
||||
|
||||
func (r *OfficeHourRepo) FindByRoom(room models.Room) ([]models.OfficeHour, error) {
|
||||
rows, err := r.db.Query("SELECT * FROM officeHour WHERE room=?", room.Id)
|
||||
func (r *OfficeHourRepo) FindByRoom(room models.Room, activeOnly bool) ([]models.OfficeHour, error) {
|
||||
var rows *sql.Rows
|
||||
var err error
|
||||
if activeOnly {
|
||||
rows, err = r.db.Query("SELECT * FROM officeHour WHERE room=? AND active", room.Id)
|
||||
} else {
|
||||
rows, err = r.db.Query("SELECT * FROM officeHour WHERE room=?", room.Id)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -55,7 +73,43 @@ func (r *OfficeHourRepo) FindById(id int) (models.OfficeHour, error) {
|
|||
}
|
||||
|
||||
func (r *OfficeHourRepo) Add(officeHour models.OfficeHour) error {
|
||||
return nil
|
||||
// Find correct tutor or add if not existent
|
||||
r.tutorRepo.Add(officeHour.Tutor)
|
||||
var err error
|
||||
officeHour.Tutor, err = r.tutorRepo.FindByNameAndEmail(officeHour.Tutor.Name, officeHour.Tutor.Email)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//Don't add identical officeHours
|
||||
officeHours, err := r.FindByCourse(officeHour.Course, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, oldOfficeHour := range officeHours {
|
||||
if officeHour.Tutor == oldOfficeHour.Tutor &&
|
||||
officeHour.Date == oldOfficeHour.Date &&
|
||||
officeHour.Room == oldOfficeHour.Room &&
|
||||
// officeHour.Course == oldOfficeHour.Course && already filtered above
|
||||
officeHour.Info == oldOfficeHour.Info &&
|
||||
officeHour.Active == oldOfficeHour.Active &&
|
||||
officeHour.Duration == oldOfficeHour.Duration {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
_, err = r.db.Exec("INSERT INTO `officeHour` (tutor, day, hour, minute, room, course, week, info, active, duration) VALUES (?,?,?,?,?,?,?,?,?,?)",
|
||||
officeHour.Tutor.Id,
|
||||
officeHour.Date.Day,
|
||||
officeHour.Date.Hour,
|
||||
officeHour.Date.Minute,
|
||||
officeHour.Room.Id,
|
||||
officeHour.Course.Id,
|
||||
officeHour.Date.Week,
|
||||
officeHour.Info,
|
||||
officeHour.Active,
|
||||
officeHour.Duration)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *OfficeHourRepo) Delete(officeHour models.OfficeHour) error {
|
||||
|
@ -64,13 +118,13 @@ func (r *OfficeHourRepo) Delete(officeHour models.OfficeHour) error {
|
|||
|
||||
func (r *OfficeHourRepo) getFromRow(row *sql.Row) (models.OfficeHour, error) {
|
||||
var officeHour models.OfficeHour
|
||||
var day, hour, minute, tutorid int
|
||||
var week, day, hour, minute, tutorid int
|
||||
var roomName, courseName string
|
||||
err := row.Scan(&officeHour.Id, &tutorid, &day, &hour, &minute, &roomName, &courseName, &officeHour.Week, &officeHour.Info, &officeHour.Active, &officeHour.Duration)
|
||||
err := row.Scan(&officeHour.Id, &tutorid, &day, &hour, &minute, &roomName, &courseName, &week, &officeHour.Info, &officeHour.Active, &officeHour.Duration)
|
||||
if err != nil {
|
||||
return models.OfficeHour{}, err
|
||||
}
|
||||
officeHour.Date = models.Date{day, hour, minute}
|
||||
officeHour.Date = models.Date{week, day, hour, minute}
|
||||
officeHour.Room, _ = r.roomRepo.FindByName(roomName)
|
||||
officeHour.Tutor, _ = r.tutorRepo.FindById(tutorid)
|
||||
officeHour.Course, _ = r.courseRepo.FindByName(courseName)
|
||||
|
@ -81,11 +135,11 @@ func (r *OfficeHourRepo) getFromRows(rows *sql.Rows) ([]models.OfficeHour, error
|
|||
var officeHours []models.OfficeHour
|
||||
for rows.Next() {
|
||||
var officeHour models.OfficeHour
|
||||
var day, hour, minute, tutorId, roomId, courseId int
|
||||
if err := rows.Scan(&officeHour.Id, &tutorId, &day, &hour, &minute, &roomId, &courseId, &officeHour.Week, &officeHour.Info, &officeHour.Active, &officeHour.Duration); err != nil {
|
||||
var week, day, hour, minute, tutorId, roomId, courseId int
|
||||
if err := rows.Scan(&officeHour.Id, &tutorId, &day, &hour, &minute, &roomId, &courseId, &week, &officeHour.Info, &officeHour.Active, &officeHour.Duration); err != nil {
|
||||
return officeHours, err
|
||||
}
|
||||
officeHour.Date = models.Date{day, hour, minute}
|
||||
officeHour.Date = models.Date{week, day, hour, minute}
|
||||
officeHour.Room, _ = r.roomRepo.FindById(roomId)
|
||||
officeHour.Tutor, _ = r.tutorRepo.FindById(tutorId)
|
||||
officeHour.Course, _ = r.courseRepo.FindById(courseId)
|
||||
|
|
|
@ -43,6 +43,15 @@ func (r *TutorRepo) FindById(id int) (models.Tutor, error) {
|
|||
return tutor, nil
|
||||
}
|
||||
|
||||
func (r *TutorRepo) FindByNameAndEmail(name string, email string) (models.Tutor, error) {
|
||||
row := r.db.QueryRow("SELECT * FROM tutor WHERE email=? AND name=?", email, name)
|
||||
var tutor models.Tutor
|
||||
if err := row.Scan(&tutor.Id, &tutor.Name, &tutor.Email); err != nil {
|
||||
return models.Tutor{}, err
|
||||
}
|
||||
return tutor, nil
|
||||
}
|
||||
|
||||
func (r *TutorRepo) GetAll() ([]models.Tutor, error) {
|
||||
rows, err := r.db.Query("SELECT * FROM tutor")
|
||||
if err != nil {
|
||||
|
@ -64,5 +73,12 @@ func (r *TutorRepo) Save(tutor models.Tutor) error {
|
|||
return nil
|
||||
}
|
||||
func (r *TutorRepo) Add(tutor models.Tutor) error {
|
||||
return nil
|
||||
//Don't add identical tutors
|
||||
_, err := r.FindByNameAndEmail(tutor.Name, tutor.Email)
|
||||
if err == sql.ErrNoRows {
|
||||
_, err = r.db.Exec("INSERT INTO `tutor` (name, email) VALUES (?,?);", tutor.Name, tutor.Email)
|
||||
return err
|
||||
}
|
||||
return err
|
||||
|
||||
}
|
||||
|
|
10
templates/addFailure.html
Normal file
10
templates/addFailure.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sprechstunde anlegen</title>
|
||||
</head>
|
||||
<body>
|
||||
Irgendetwas ist schief gegangen. Bitte sende folgende Daten an <a href="mailto:sprechstundentool@mathebau.de">sprechstundentool@mathebau.de</a> mit einer Beschreibung, was du tun wolltest.
|
||||
<br />
|
||||
{{.}}
|
||||
</body>
|
||||
</html>
|
49
templates/addMask.html
Normal file
49
templates/addMask.html
Normal file
|
@ -0,0 +1,49 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Sprechstunde anlegen</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
{{range .Errors}}{{.}}<br />{{end}}
|
||||
</p>
|
||||
<p>
|
||||
<form method="POST" action="addOfficeHour">
|
||||
<label for="veranstaltung">Veranstaltung</label>:
|
||||
<select name="veranstaltung">{{range $course := .Courses}}
|
||||
<option value="{{$course.Id}}"{{if eq $course.Id $.SelectedCourse}} selected{{end}}>{{$course.Name}}</option>{{end}}
|
||||
</select><br />
|
||||
<label for="woche">Woche</label>:
|
||||
<select name="woche">
|
||||
<option value="0"{{if eq 0 $.Week}} selected{{end}}>Jede</option>
|
||||
<option value="1"{{if eq 1 $.Week}} selected{{end}}>Gerade</option>
|
||||
<option value="2"{{if eq 2 $.Week}} selected{{end}}>Ungerade</option>
|
||||
</select><br />
|
||||
<label for="tag">Tag</label>: <select name="tag">
|
||||
<option value="0"{{if eq 0 $.Day}} selected{{end}}>Montag</option>
|
||||
<option value="1"{{if eq 1 $.Day}} selected{{end}}>Dienstag</option>
|
||||
<option value="2"{{if eq 2 $.Day}} selected{{end}}>Mittwoch</option>
|
||||
<option value="3"{{if eq 3 $.Day}} selected{{end}}>Donnerstag</option>
|
||||
<option value="4"{{if eq 4 $.Day}} selected{{end}}>Freitag</option>
|
||||
</select><br />
|
||||
<label for="startzeit">Startzeit</label>: <input type="time" name="startzeit" min="08:00" max="17:30" /><br />
|
||||
<label for="dauer">Dauer in Minuten</label>: <input name="dauer" type="number" min="{{.MinuteGranularity}}" max="120" step="{{.MinuteGranularity}}" value="{{.Duration}}"/><br />
|
||||
<label for="raum">Raum</label>:
|
||||
<select name="raum">{{range $room := .Rooms}}
|
||||
<option value="{{$room.Id}}"{{if eq $room.Id $.SelectedRoom}} selected{{end}}>{{$room.Name}}</option>{{end}}
|
||||
</select><br />
|
||||
<label for="raumname">Raumname (für Sonderräume)</label>: <input type="text" name="raumname" value="{{.Roomname}}"/><br />
|
||||
<label for="name">Name</label>: <input name="name" type="text" size="50" value="{{.Name}}"/><br />
|
||||
<label for="email">Email-Adresse</label>:
|
||||
<input name="email" type="email" size="50" value="{{.Email}}"/><br />
|
||||
<label for="info">Info</label>: <input name="info" type="text" size="50" value="{{.Info}}"/><br />
|
||||
<input type="submit">
|
||||
</form>
|
||||
</p>
|
||||
Du musst hier eine Email-Adresse angeben, die auf „tu-darmstadt.de“ endet.<br />
|
||||
Außerdem dürfen in Räumen nur begrenzt viele Sprechstunden gleichzeitig stattfinden, nämlich
|
||||
<dl>
|
||||
{{range $room := .Rooms}}
|
||||
<dt>{{$room.Name}}</dt><dl>{{$room.MaxOccupy}} Sprechstunde{{if gt $room.MaxOccupy 1}}n{{end}}</dl><br />{{end}}
|
||||
</dl>
|
||||
</body>
|
||||
</html>
|
|
@ -10,18 +10,18 @@
|
|||
{{range $course := .Courses}}
|
||||
<option value="{{$course.Id}}"{{if eq $course.Id $.SelectedCourse}} selected{{end}}>{{$course.Name}}</option>{{end}}
|
||||
</select>
|
||||
<input type="submit" value="Auswählen" />
|
||||
<input type="submit" value="Auswählen" />
|
||||
</form>
|
||||
<form method="GET" action="/getByRoom">
|
||||
<label for="raum">Raum: </label>
|
||||
<select name="raum" size="1" onchange="document.forms[1].submit()">
|
||||
<option value="">Alle</option>
|
||||
{{range $room := .Rooms}}
|
||||
<option value="{{$room.Id}}"{{if eq $room.Id $.SelectedRoom}} selected{{end}}>{{$room.Name}}</option>{{end}}
|
||||
<option value="{{$room.Id}}"{{if eq $room.Id $.SelectedRoom}} selected{{end}}>{{$room.Name}}</option>{{end}}
|
||||
</select>
|
||||
<input type="submit" value="Auswählen" />
|
||||
</form>
|
||||
{{.Timetable}}
|
||||
Technische Fragen an <a href="mailto:sprechstundentool@mathebau.de">sprechstundentool@mathebau.de</a>
|
||||
</body>
|
||||
<input type="submit" value="Auswählen" />
|
||||
</form>
|
||||
{{.Timetable}}
|
||||
Technische Fragen an <a href="mailto:sprechstundentool@mathebau.de">sprechstundentool@mathebau.de</a>
|
||||
</body>
|
||||
</html>
|
|
@ -7,5 +7,5 @@
|
|||
<th colspan="{{.ColspanThu}}" style="padding-left: 10px; padding-right: 10px; border-right: 1px dotted">Donnerstag</th>
|
||||
<th colspan="{{.ColspanFri}}" style="padding-left: 10px; padding-right: 10px; border-right: 1px dotted">Freitag</th>
|
||||
</tr>
|
||||
{{.TableBody}}
|
||||
{{.TableBody}}
|
||||
</table>
|
Loading…
Reference in a new issue