~hokiegeek/seculardb

ref: 7dd2adc13a694996b1db0b1011bb29acbd3549c3 seculardb/serve.go -rw-r--r-- 3.3 KiB
7dd2adc1HokieGeek Added colors to the Rating column in the HTML page as a finishing touch 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package seculardb

import (
	"fmt"
	"html/template"
	"io"
	"log"
	"net/http"
	"strconv"
	"strings"
)

var pageTmpl = `<html>
	<head>
		<title>Filterable Secular Homeschooler Guide</title>
		<style>
		th {
			border-bottom: 3px solid #777;
		}
		tr:nth-child(even) {
			background-color: #c0c0c0;
		}

		.ratingNotSecular {
			background-color: #f54646;
		}
		.ratingNeutral {
			background-color: #f9ac63;
		}
		.ratingMostlySecular {
			background-color: #ecec58;
		}
		.ratingSecular {
			background-color: #d0f172;
		}
		.ratingSuperSecular {
			background-color: #60bd60;
		}
		</style>
	</head>
	<body>
		<div><a href="` + GuideURL + `">` + GuideURL + `</a><span style="float: right">Displaying {{ len .Entries }} entries</span></div>
		<br />
		<table>
			<thead>
				<tr>
					<th class="column-1">Name</th>
					<th class="column-2">Secular Rating</th>
					<th class="column-3">Grade Level(s)</th>
					<th class="column-4">Subject(s)</th>
					<th class="column-5">Description &amp; Notes</th>
				</tr>
			</thead>
			<tbody>
				{{range $index, $entry := .Entries}}
				<tr>
					{{if .URL}}
					<td><a href="{{.URL}}">{{.Name}}</a></td>
					{{else}}
					<td>{{.Name}}</td>
					{{end}}
					<td class="{{.Rating | ratingClass}}">{{.Rating}}</td>
					<td>{{join .GradeLevels}}</td>
					<td>{{joinbr .Subjects}}</td>
					<td>{{.Description}}</td>
				</tr>
				{{end}}
			</tbody>
		</table>
	</body>
</html>`

// WriteHTML writes the given DB to an io.Writer after applying an HTML template
func WriteHTML(w io.Writer, db DB) error {
	t := template.Must(template.New("sb").Funcs(
		template.FuncMap{
			"join": func(v []string) string {
				return strings.Join(v, ",")
			},
			"joinbr": func(v []string) template.HTML {
				return template.HTML(strings.Join(v, "<br />"))
			},
			"ratingClass": func(v Rating) string {
				switch v {
				case RatingNotSecular:
					return "ratingNotSecular"
				case RatingNeutral:
					return "ratingNeutral"
				case RatingMostlySecular:
					return "ratingMostlySecular"
				case RatingSecular:
					return "ratingSecular"
				case RatingSuperSecular:
					return "ratingSuperSecular"
				}
				return ""
			},
		}).Parse(pageTmpl))
	if err := t.Execute(w, db); err != nil {
		return fmt.Errorf("could not generate page: %v", err)
	}

	return nil
}

// Serve renders the database as an html table
func Serve(w http.ResponseWriter, r *http.Request) {
	db, err := Build()
	if err != nil {
		log.Printf("could not serve page: %v\n", err)
		w.WriteHeader(http.StatusInternalServerError)
	}

	matcher := NewMatcher()
	for k, v := range r.URL.Query() {
		switch k {
		case "rating":
			rating, err := strconv.Atoi(v[0])
			if err != nil {
				log.Printf("error: could not parse rating '%s': %v\n", v[0], err)
				w.WriteHeader(http.StatusBadRequest)
				return
			}
			matcher.Rating(rating)
		case "grades":
			for _, str := range v {
				val, err := strconv.Atoi(str)
				if err != nil {
					log.Printf("error: could not parse grade '%s': %v\n", str, err)
					w.WriteHeader(http.StatusBadRequest)
					return
				}
				matcher.Grade(val)
			}
		case "name":
			matcher.Names(v)
		case "subject":
			matcher.Subjects(v)
		}
	}

	filtered, err := Filter(db, matcher)
	if err == nil {
		err = WriteHTML(w, filtered)
	}

	if err != nil {
		log.Printf("could not serve page: %v\n", err)
		w.WriteHeader(http.StatusInternalServerError)
	}
}