Compare commits

..

No commits in common. "d60b715d9679f4288c1486fc1f9bc916259bb9ab" and "c737818ce4a137d5bcb0572b614b5ee0ae09d5b1" have entirely different histories.

24 changed files with 208 additions and 221 deletions

View file

@ -2,6 +2,7 @@ package controllers
import ( import (
"fmt" "fmt"
"log"
"net/http" "net/http"
"net/mail" "net/mail"
"officeHours/config" "officeHours/config"
@ -148,12 +149,12 @@ func (b *BaseHandler) AddOfficeHourHandler(w http.ResponseWriter, req *http.Requ
id, err := b.officeHourRepo.Add(officeHour) id, err := b.officeHourRepo.Add(officeHour)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
b.serveTemplate(w, "addFailure", err) Templates.ExecuteTemplate(w, "addFailure.html", err)
return return
} }
officeHour, _ = b.officeHourRepo.FindById(id) officeHour, _ = b.officeHourRepo.FindById(id)
b.requestRepo.Add(officeHour, models.RequestActivate) b.requestRepo.Add(officeHour, models.RequestActivate)
b.serveTemplate(w, "addSuccess", nil) Templates.ExecuteTemplate(w, "addSuccess.html", struct{}{})
} }
} }
@ -164,5 +165,10 @@ func (b *BaseHandler) writeAddOfficeHourMask(w http.ResponseWriter, req *http.Re
if len(data.Errors) != 0 { if len(data.Errors) != 0 {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
} }
b.serveTemplate(w, "addMask", data) err := Templates.ExecuteTemplate(w, "addMask.html", data)
if err != nil {
log.Printf("Template addMask.html could not be parsed: %s", err.Error())
w.Write([]byte(fmt.Sprintf("Template konnte nicht geparst werden : %s", err.Error())))
return
}
} }

View file

@ -9,15 +9,17 @@ func (b *BaseHandler) ConfirmRequestHandler(w http.ResponseWriter, req *http.Req
request, err := b.requestRepo.FindBySecret(secret) request, err := b.requestRepo.FindBySecret(secret)
if err != nil { if err != nil {
b.serveTemplate(w, "requestNotFound", nil) w.WriteHeader(http.StatusNotFound)
Templates.ExecuteTemplate(w, "requestNotFound.html", struct{}{})
return return
} }
err = b.requestRepo.Execute(request) err = b.requestRepo.Execute(request)
if err != nil { if err != nil {
b.serveTemplate(w, "executeFailure", err.Error()) w.WriteHeader(http.StatusInternalServerError)
Templates.ExecuteTemplate(w, "executeFailure.html", err.Error())
return return
} }
b.serveTemplate(w, "executeSuccess", nil) Templates.ExecuteTemplate(w, "executeSuccess.html", struct{}{})
} }

View file

@ -18,7 +18,7 @@ func (b *BaseHandler) DeleteOfficeHourHandler(w http.ResponseWriter, req *http.R
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
} }
_, err = b.requestRepo.Add(officeHour, models.RequestDelete) _, err = b.requestRepo.Add(officeHour, models.RequestDelete)
b.serveTemplate(w, "deleteSuccess", nil) Templates.ExecuteTemplate(w, "deleteSuccess.html", struct{}{})
} else { } else {
officeHours, _ := b.officeHourRepo.GetAll(true) officeHours, _ := b.officeHourRepo.GetAll(true)
timetable, slots := b.GetTimetable(officeHours) timetable, slots := b.GetTimetable(officeHours)

View file

@ -1,6 +1,7 @@
package controllers package controllers
import ( import (
"fmt"
"html/template" "html/template"
"net/http" "net/http"
"officeHours/models" "officeHours/models"
@ -27,7 +28,6 @@ func (b *BaseHandler) GetByCourseHandler(w http.ResponseWriter, req *http.Reques
courseid, err := strconv.Atoi(req.FormValue("veranstaltung")) courseid, err := strconv.Atoi(req.FormValue("veranstaltung"))
if err != nil { if err != nil {
b.RootHandler(w, req) b.RootHandler(w, req)
return
} }
course, err := b.courseRepo.FindById(courseid) course, err := b.courseRepo.FindById(courseid)
if err != nil { if err != nil {
@ -51,5 +51,9 @@ func (b *BaseHandler) writeTimetablePage(w http.ResponseWriter, req *http.Reques
SelectedRoom int SelectedRoom int
SelectedCourse int SelectedCourse int
}{courses, rooms, timetable, selectedRoom, selectedCourse} }{courses, rooms, timetable, selectedRoom, selectedCourse}
b.serveTemplate(w, "index", data) err := Templates.ExecuteTemplate(w, "index.html", data)
if err != nil {
w.Write([]byte(fmt.Sprintf("Template konnte nicht geparst werden : %s", err.Error())))
return
}
} }

View file

@ -1,47 +1,21 @@
package controllers package controllers
import ( import (
"fmt"
"html/template" "html/template"
"net/http"
"officeHours/models" "officeHours/models"
"os"
) )
var funcs = template.FuncMap{ var Templates, _ = template.Must(template.ParseFiles(
"DayName": models.DayName, "templates/addFailure.html",
"divide": func(i int, j int) int { return i / j }, "templates/addMask.html",
} "templates/addSuccess.html",
var baseTemplate = template.Must(template.ParseFiles("templates/base.html")).New("base.html").Funcs(funcs) "templates/deleteSuccess.html",
"templates/executeFailure.html",
func (b *BaseHandler) serveTemplate(w http.ResponseWriter, name string, data any) { "templates/executeSuccess.html",
full_name := "templates/" + name + ".html" "templates/footer.html",
// check that template exists "templates/head.html",
info, err := os.Stat(full_name) "templates/index.html",
if (err != nil && os.IsNotExist(err)) || info.IsDir() { "templates/officeHourTable.html",
w.WriteHeader(http.StatusNotFound) "templates/requestNotFound.html")).
w.Write([]byte("404: Template nicht gefunden.")) New("").Funcs(template.FuncMap{"DayName": models.DayName,
return "divide": func(i int, j int) int { return i / j }}).ParseFiles("templates/confirmationMail", "templates/td.html")
}
tmpl, err := baseTemplate.ParseFiles(full_name)
if err != nil {
// TODO: log.Printf
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("500: Template "+full_name+" konnte nicht geparst werden : %s", err.Error())))
return
}
// TODO: cache templates in parsed state, but not executed
err = template.Must(tmpl.Clone()).Execute(w, data)
if err != nil {
// TODO: log.Printf
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("500: Template "+full_name+" konnte nicht ausgeführt werden : %s", err.Error())))
return
}
}
var RawTemplates = template.Must(template.New("").Funcs(funcs).ParseFiles(
"templates/confirmationMail",
"templates/td.html",
"templates/officeHourTable.html"))

View file

@ -84,7 +84,7 @@ func (b *BaseHandler) printTimetable(timetable map[models.Date]map[int]models.Of
MinuteGranularity int MinuteGranularity int
DeleteIcons bool DeleteIcons bool
}{OfficeHour: current, MinuteGranularity: b.config.Date.MinuteGranularity, DeleteIcons: deleteIcons} }{OfficeHour: current, MinuteGranularity: b.config.Date.MinuteGranularity, DeleteIcons: deleteIcons}
RawTemplates.ExecuteTemplate(&celldata, "td.html", data) Templates.ExecuteTemplate(&celldata, "td.html", data)
tableBody += celldata.String() tableBody += celldata.String()
} }
} else { } else {
@ -116,6 +116,6 @@ func (b *BaseHandler) printTimetable(timetable map[models.Date]map[int]models.Of
slots[4], slots[4],
template.HTML(tableBody), template.HTML(tableBody),
} }
RawTemplates.ExecuteTemplate(&table, "officeHourTable.html", tableData) Templates.ExecuteTemplate(&table, "officeHourTable.html", tableData)
return template.HTML(table.String()) return template.HTML(table.String())
} }

View file

@ -7,11 +7,11 @@ import (
"log" "log"
"log/syslog" "log/syslog"
"net/http" "net/http"
"os"
"officeHours/config" "officeHours/config"
"officeHours/controllers" "officeHours/controllers"
"officeHours/repositories" "officeHours/repositories"
"officeHours/sqldb" "officeHours/sqldb"
"os"
) )
func main() { func main() {
@ -35,9 +35,6 @@ func main() {
log.Fatalf("%s: %s", "Reading JSON config file into config structure", err) log.Fatalf("%s: %s", "Reading JSON config file into config structure", err)
} }
// serve static files
staticHandler := http.FileServer(http.Dir("./static"))
db := sqldb.Connect(conf) db := sqldb.Connect(conf)
// Create repos // Create repos
roomRepo := repositories.NewRoomRepo(db) roomRepo := repositories.NewRoomRepo(db)
@ -53,7 +50,6 @@ func main() {
http.HandleFunc("/confirmRequest", h.ConfirmRequestHandler) http.HandleFunc("/confirmRequest", h.ConfirmRequestHandler)
http.HandleFunc("/deleteOfficeHour", h.DeleteOfficeHourHandler) http.HandleFunc("/deleteOfficeHour", h.DeleteOfficeHourHandler)
http.HandleFunc("/", h.RootHandler) http.HandleFunc("/", h.RootHandler)
http.Handle("/static/", http.StripPrefix("/static/", staticHandler))
err = http.ListenAndServe(fmt.Sprintf("%s:%d", conf.Server.ListenAddress, conf.Server.ListenPort), nil) err = http.ListenAndServe(fmt.Sprintf("%s:%d", conf.Server.ListenAddress, conf.Server.ListenPort), nil)
log.Println(err.Error()) log.Println(err.Error())

View file

@ -128,7 +128,7 @@ func (r *RequestRepo) sendConfirmationMail(request models.Request) error {
Config config.Config Config config.Config
Request models.Request Request models.Request
}{r.config, request} }{r.config, request}
err := controllers.RawTemplates.ExecuteTemplate(&message, "confirmationMail", data) err := controllers.Templates.ExecuteTemplate(&message, "confirmationMail", data)
if err != nil { if err != nil {
log.Printf("Error parsing confirmation Mail: %s", err.Error()) log.Printf("Error parsing confirmation Mail: %s", err.Error())
return err return err

View file

@ -1 +0,0 @@
bootstrap-5.2.1-dist/

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,7 +1,13 @@
{{define "title"}}Fehler{{end}} <!DOCTYPE html>
<html lang="de">
{{define "content"}} <head>
<title>Sprechstunde anlegen</title>
{{template "head.html" .}}
</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. 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 /> <br />
{{.}} {{.}}
{{end}} {{template "footer.html" .}}
</body>
</html>

View file

@ -1,15 +1,17 @@
<{{define "title"}}Sprechstunde anlegen{{end}} <!DOCTYPE html>
<html lang="de">
{{define "content"}} <head>
<title>Sprechstunde anlegen</title>
{{template "head.html" .}}
</head>
<body>
<p> <p>
{{range .Errors}}{{.}}<br />{{end}} {{range .Errors}}{{.}}<br />{{end}}
</p> </p>
<form method="POST" action="addOfficeHour"> <form method="POST" action="addOfficeHour">
<label for="veranstaltung">Veranstaltung</label>: <label for="veranstaltung">Veranstaltung</label>:
<select name="veranstaltung" id="veranstaltung"> <select name="veranstaltung" id="veranstaltung">{{range $course := .Courses}}
{{range $course := .Courses}} <option value="{{$course.Id}}"{{if eq $course.Id $.SelectedCourse}} selected{{end}}>{{$course.Name}}</option>{{end}}
<option value="{{$course.Id}}"{{if eq $course.Id $.SelectedCourse}} selected{{end}}>{{$course.Name}}</option>
{{end}}
</select><br /> </select><br />
<label for="woche">Woche</label>: <label for="woche">Woche</label>:
<select name="woche" id="woche"> <select name="woche" id="woche">
@ -27,10 +29,8 @@
<label for="startzeit">Startzeit</label>: <input type="time" name="startzeit" id="startzeit" min="08:00" max="17:30" {{if gt $.Date.Hour 7}}value="{{printf "%02d" $.Date.Hour}}:{{printf "%02d" $.Date.Minute}}"{{end}} required/><br /> <label for="startzeit">Startzeit</label>: <input type="time" name="startzeit" id="startzeit" min="08:00" max="17:30" {{if gt $.Date.Hour 7}}value="{{printf "%02d" $.Date.Hour}}:{{printf "%02d" $.Date.Minute}}"{{end}} required/><br />
<label for="dauer">Dauer in Minuten</label>: <input name="dauer" id="dauer" type="number" min="{{.MinuteGranularity}}" max="120" step="{{.MinuteGranularity}}" value="{{.Duration}}" required/><br /> <label for="dauer">Dauer in Minuten</label>: <input name="dauer" id="dauer" type="number" min="{{.MinuteGranularity}}" max="120" step="{{.MinuteGranularity}}" value="{{.Duration}}" required/><br />
<label for="raum">Raum</label>: <label for="raum">Raum</label>:
<select name="raum" id="raum"> <select name="raum" id="raum">{{range $room := .Rooms}}
{{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><br /> </select><br />
<label for="raumname">Raumname (für Sonderräume)</label>: <input type="text" name="raumname" id="raumname" value="{{.Roomname}}"/><br /> <label for="raumname">Raumname (für Sonderräume)</label>: <input type="text" name="raumname" id="raumname" value="{{.Roomname}}"/><br />
<label for="name">Name</label>: <input name="name" id="name" type="text" size="50" value="{{.Name}}" required/><br /> <label for="name">Name</label>: <input name="name" id="name" type="text" size="50" value="{{.Name}}" required/><br />
@ -39,14 +39,12 @@
<label for="info">Info</label>: <input name="info" id="info" type="text" size="50" value="{{.Info}}"/><br /> <label for="info">Info</label>: <input name="info" id="info" type="text" size="50" value="{{.Info}}"/><br />
<input type="submit"> <input type="submit">
</form> </form>
{{if ne .Config.Tutor.MailSuffix ""}} {{if ne .Config.Tutor.MailSuffix ""}}Du musst hier eine Email-Adresse angeben, die auf „{{.Config.Tutor.MailSuffix}}“ endet.<br />{{end}}
Du musst hier eine Email-Adresse angeben, die auf „{{.Config.Tutor.MailSuffix}}“ endet.<br />
{{end}}
Außerdem dürfen in Räumen nur begrenzt viele Sprechstunden gleichzeitig stattfinden, nämlich Außerdem dürfen in Räumen nur begrenzt viele Sprechstunden gleichzeitig stattfinden, nämlich
<dl> <dl>
{{range $room := .Rooms}} {{range $room := .Rooms}}
<dt>{{$room.Name}}</dt> <dt>{{$room.Name}}</dt><dd>{{$room.MaxOccupy}} Sprechstunde{{if gt $room.MaxOccupy 1}}n{{end}}</dd>{{end}}
<dd>{{$room.MaxOccupy}} Sprechstunde{{if gt $room.MaxOccupy 1}}n{{end}}</dd>
{{end}}
</dl> </dl>
{{end}} {{template "footer.html" .}}
</body>
</html>

View file

@ -1,5 +1,12 @@
{{define "title"}}Sprechstunde anlegen{{end}} <!DOCTYPE html>
<html lang="de">
{{define "content"}} <head>
<title>Sprechstunde anlegen</title>
{{template "head.html" .}}
</head>
<body>
Die Sprechstunde wurde angelegt. Du solltest eine Mail mit einem Aktivierungslink erhalten haben. Die Sprechstunde wurde angelegt. Du solltest eine Mail mit einem Aktivierungslink erhalten haben.
{{end}} <br />
{{template "footer.html" .}}
</body>
</html>

View file

@ -1,27 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="keywords" content="Mathebau, Sprechstunde, Sprechstunden, Mathe, Mathematik, technische, Universität, Darmstadt, TU, Fachschaft">
<meta name="description" content="Eine Übersicht der Sprechstunden, die in den offenen Arbeitsräumen der Fachschaft Mathematik, TU Darmstadt, angeboten werden">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
<title>{{block "title" .}}Start{{end}} Sprechstunden</title>
</head>
<body>
<div class="container">
{{block "content" .}}Du solltest dies nicht sehen.{{end}}
</div>
<footer class="container">
<a href="/">Startseite</a><br />
<a href="/addOfficeHour">Sprechstunde anlegen</a><br />
<a href="/deleteOfficeHour">Sprechstunde löschen</a><br />
Technische Fragen an <a href="mailto:sprechstundentool@mathebau.de">sprechstundentool@mathebau.de</a>
</footer>
<script src="/static/bootstrap/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View file

@ -1,7 +1,13 @@
{{define "title"}}Sprechstunde löschen{{end}} <!DOCTYPE html>
<html lang="de">
{{define "content"}} <head>
<title>Sprechstunde löschen</title>
{{template "head.html" .}}
</head>
<body>
Du solltest eine Mail mit einem Bestätigungslink erhalten haben. <br /> Du solltest eine Mail mit einem Bestätigungslink erhalten haben. <br />
Sie wurde an die Adresse geschickt, mit der die Sprechstunde angelegt wurde. Sie wurde an die Adresse geschickt, mit der die Sprechstunde angelegt wurde.
<br /> <br />
{{end}} {{template "footer.html" .}}
</body>
</html>

View file

@ -1,7 +1,13 @@
{{define "title"}}Anfrage ausführen fehlgeschlagen{{end}} <!DOCTYPE html>
<html lang="de">
{{define "content"}} <head>
<title>Anfrage ausführen fehlgeschlagen</title>
{{template "head.html" .}}
</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. 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 /> <br />
{{.}} {{.}}
{{end}} {{template "footer.html" .}}
</body>
</html>

View file

@ -1,5 +1,11 @@
{{define "title"}}Anfrage ausgeführt{{end}} <!DOCTYPE html>
<html lang="de">
{{define "content"}} <head>
Deine Anfrage wurde ausgeführt. <title>Anfrage ausgeführt</title>
{{end}} {{template "head.html" .}}
</head>
<body>
Deine Anfrage wurde ausgeführt. <br />
{{template "footer.html" .}}
</body>
</html>

6
templates/footer.html Normal file
View file

@ -0,0 +1,6 @@
<footer>
<a href="/">Startseite</a><br />
<a href="/addOfficeHour">Sprechstunde anlegen</a><br />
<a href="/deleteOfficeHour">Sprechstunde löschen</a><br />
Technische Fragen an <a href="mailto:sprechstundentool@mathebau.de">sprechstundentool@mathebau.de</a>
</footer>

4
templates/head.html Normal file
View file

@ -0,0 +1,4 @@
<meta charset="UTF-8">
<meta name="keywords" content="Mathebau, Sprechstunde, Sprechstunden, Mathe, Mathematik, technische, Universität, Darmstadt, TU, Fachschaft">
<meta name="description" content="Eine Übersicht der Sprechstunden, die in den offenen Arbeitsräumen der Fachschaft Mathematik, TU Darmstadt, angeboten werden">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

View file

@ -1,13 +1,16 @@
{{define "title"}}Übersicht{{end}} <!DOCTYPE html>
<html lang="de">
{{define "content"}} <head>
<title>Sprechstunden</title>
{{template "head.html" .}}
</head>
<body>
<form method="GET" action="/getByCourse"> <form method="GET" action="/getByCourse">
<label for="veranstaltung">Veranstaltung: </label> <label for="veranstaltung">Veranstaltung: </label>
<select name="veranstaltung" id="veranstaltung" size="1" onchange="document.forms[0].submit()"> <select name="veranstaltung" id="veranstaltung" size="1" onchange="document.forms[0].submit()">
<option value="">Alle</option> <option value="">Alle</option>
{{range $course := .Courses}} {{range $course := .Courses}}
<option value="{{$course.Id}}"{{if eq $course.Id $.SelectedCourse}} selected{{end}}>{{$course.Name}}</option> <option value="{{$course.Id}}"{{if eq $course.Id $.SelectedCourse}} selected{{end}}>{{$course.Name}}</option>{{end}}
{{end}}
</select> </select>
<input type="submit" value="Auswählen" /> <input type="submit" value="Auswählen" />
</form> </form>
@ -16,10 +19,11 @@
<select name="raum" id="raum" size="1" onchange="document.forms[1].submit()"> <select name="raum" id="raum" size="1" onchange="document.forms[1].submit()">
<option value="">Alle</option> <option value="">Alle</option>
{{range $room := .Rooms}} {{range $room := .Rooms}}
<option value="{{$room.Id}}"{{if eq $room.Id $.SelectedRoom}} selected{{end}}>{{$room.Name}}</option> <option value="{{$room.Id}}"{{if eq $room.Id $.SelectedRoom}} selected{{end}}>{{$room.Name}}</option>{{end}}
{{end}}
</select> </select>
<input type="submit" value="Auswählen" /> <input type="submit" value="Auswählen" />
</form> </form>
{{.Timetable}} {{.Timetable}}
{{end}} {{template "footer.html" .}}
</body>
</html>

View file

@ -1,6 +1,10 @@
{{define "title"}}Anfrage bestätigen fehlgeschlagen{{end}} <!DOCTYPE html>
<html lang="de">
{{define "content"}} <head>
<title>Anfrage bestätigen fehlgeschlagen</title>
{{template "head.html" .}}
</head>
<body>
<p> <p>
Dieser Bestätigungscode ist nicht verfügbar. <br /> Dieser Bestätigungscode ist nicht verfügbar. <br />
Bitte gib deinen Bestätigungscode hier ein. Bitte gib deinen Bestätigungscode hier ein.
@ -9,4 +13,6 @@
<label for="code">Bestätigungscode</label>: <input type="text" name="code" id="code"/> <label for="code">Bestätigungscode</label>: <input type="text" name="code" id="code"/>
<input type="submit" /> <input type="submit" />
</form> </form>
{{end}} {{template "footer.html" .}}
</body>
</html>