Expose submissions in API
This commit is contained in:
parent
e29990a29a
commit
fccd3e9a3c
177
main.go
177
main.go
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/csv"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@ -11,6 +12,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -29,39 +31,160 @@ func Serve(w http.ResponseWriter, r *http.Request) {
|
||||
<title>` + title + `</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
<style>.table > tbody > tr > th, .table > tbody > tr > td { vertical-align: middle; }
|
||||
td.danger { text-align: center; }
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
function disp(rendus) {
|
||||
Object.keys(rendus).map(function(login) {
|
||||
student = rendus[login];
|
||||
|
||||
var row = document.createElement("tr");
|
||||
|
||||
var col = document.createElement("th");
|
||||
col.innerHTML = login;
|
||||
row.appendChild(col);
|
||||
|
||||
Object.keys(student).map(function(wn) {
|
||||
work = student[wn];
|
||||
if (work) {
|
||||
var col = document.createElement("td");
|
||||
col.className = "success";
|
||||
col.innerHTML = work["date"] + "<br>" + work["hash"];
|
||||
row.appendChild(col);
|
||||
} else {
|
||||
var col = document.createElement("td");
|
||||
col.className = "danger";
|
||||
col.innerHTML = "<span class=\"glyphicon glyphicon-remove\" aria-hidden=\"true\"></span>";
|
||||
row.appendChild(col);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById("students").appendChild(row);
|
||||
});
|
||||
Object.keys(student).map(function(wn) {
|
||||
var col = document.createElement("th");
|
||||
col.innerHTML = wn;
|
||||
document.getElementById("head").appendChild(col);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body class="container">
|
||||
<h1>` + title + `</h1>
|
||||
<table class="table table-striped table-hover table-condensed">`))
|
||||
if dirs, err := ioutil.ReadDir(rendusDir); err == nil {
|
||||
w.Write([]byte(`<thead><tr><td></td>`))
|
||||
for _, dir := range dirs {
|
||||
if dir.IsDir() {
|
||||
w.Write([]byte(`<th>` + dir.Name() + `</th>`))
|
||||
}
|
||||
}
|
||||
w.Write([]byte(`</tr></thead><tbody>`))
|
||||
for _, student := range students {
|
||||
login := student[2]
|
||||
w.Write([]byte(`<tr><th>` + login + `</th>`))
|
||||
for _, dir := range dirs {
|
||||
if dir.IsDir() {
|
||||
if fi, err := os.Stat(path.Join(rendusDir, dir.Name(), login)); err == nil {
|
||||
w.Write([]byte(`<td class="success">` + fi.ModTime().Format(time.UnixDate) + `</td>`))
|
||||
} else {
|
||||
w.Write([]byte(`<td class="danger"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></td>`))
|
||||
}
|
||||
}
|
||||
}
|
||||
w.Write([]byte(`</tr>`))
|
||||
}
|
||||
}
|
||||
w.Write([]byte(` </tbody></table>
|
||||
<table class="table table-striped table-hover table-condensed">
|
||||
<thead>
|
||||
<tr id="head"><th></th></tr>
|
||||
</thead>
|
||||
<tbody id="students">
|
||||
</tbody>
|
||||
</table>
|
||||
<script src="rendus.json?func=disp"></script>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
}
|
||||
|
||||
func genStudents() map[string]map[string]*Submission {
|
||||
ret := map[string]map[string]*Submission{}
|
||||
|
||||
for _, student := range students {
|
||||
login := student[2]
|
||||
ret[login] = genStudent(login)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func ServeJSON(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("Handling %s request from %s: %s [%s]\n", r.Method, r.RemoteAddr, r.URL.Path, r.UserAgent())
|
||||
|
||||
q := r.URL.Query()
|
||||
varname := q.Get("var")
|
||||
funcname := q.Get("func")
|
||||
|
||||
if funcname == "" && varname == "" {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
} else {
|
||||
w.Header().Set("Content-Type", "application/javascript")
|
||||
}
|
||||
|
||||
if j, err := json.Marshal(genStudents()); err != nil {
|
||||
http.Error(w, fmt.Sprintf("{errmsg:%q}", err), http.StatusInternalServerError)
|
||||
} else {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if varname != "" {
|
||||
w.Write([]byte("var "))
|
||||
w.Write([]byte(varname))
|
||||
w.Write([]byte(" = "))
|
||||
}
|
||||
if funcname != "" {
|
||||
w.Write([]byte(funcname))
|
||||
w.Write([]byte("("))
|
||||
}
|
||||
w.Write(j)
|
||||
if funcname != "" {
|
||||
w.Write([]byte(")"))
|
||||
} else if varname != "" {
|
||||
w.Write([]byte(";"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Submission struct {
|
||||
Date time.Time `json:"date"`
|
||||
Hash string `json:"hash"`
|
||||
}
|
||||
|
||||
func genStudent(login string) map[string]*Submission {
|
||||
ret := map[string]*Submission{}
|
||||
|
||||
if dirs, err := ioutil.ReadDir(rendusDir); err == nil {
|
||||
for _, dir := range dirs {
|
||||
if dir.IsDir() {
|
||||
p := path.Join(rendusDir, dir.Name(), login)
|
||||
if fi, err := os.Stat(p); err == nil {
|
||||
ret[dir.Name()] = new(Submission)
|
||||
ret[dir.Name()].Date = fi.ModTime()
|
||||
if lnk, err := os.Readlink(p); err == nil {
|
||||
ret[dir.Name()].Hash = strings.TrimPrefix(lnk, login + ".")
|
||||
}
|
||||
} else {
|
||||
ret[dir.Name()] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func ServeJSONStudent(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("Handling %s request from %s: %s [%s]\n", r.Method, r.RemoteAddr, r.URL.Path, r.UserAgent())
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
login := strings.TrimSuffix(strings.TrimPrefix(r.URL.Path, "/"), ".json")
|
||||
|
||||
q := r.URL.Query()
|
||||
varname := q.Get("var")
|
||||
|
||||
if j, err := json.Marshal(genStudent(login)); err != nil {
|
||||
http.Error(w, fmt.Sprintf("{errmsg:%q}", err), http.StatusInternalServerError)
|
||||
} else {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if varname != "" {
|
||||
w.Write([]byte("var "))
|
||||
w.Write([]byte(varname))
|
||||
w.Write([]byte(" = "))
|
||||
}
|
||||
w.Write(j)
|
||||
if varname != "" {
|
||||
w.Write([]byte(";"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var studentsFile string
|
||||
|
||||
@ -105,6 +228,10 @@ func main() {
|
||||
|
||||
log.Println("Registering handlers...")
|
||||
http.HandleFunc("/", Serve)
|
||||
http.HandleFunc("/rendus.json", ServeJSON)
|
||||
for _, student := range students {
|
||||
http.HandleFunc("/" + student[2] + ".json", ServeJSONStudent)
|
||||
}
|
||||
log.Println(fmt.Sprintf("Ready, listening on %s", *bind))
|
||||
if err := http.ListenAndServe(*bind, nil); err != nil {
|
||||
log.Fatal("Unable to listen and serve: ", err)
|
||||
|
Reference in New Issue
Block a user