// Public routes
http.HandleFunc("/login", logInPage)
- http.Handle("/file-downloads/", http.StripPrefix("/file-downloads/", http.FileServer(http.Dir(config.AudioFilesPath))))
+ http.Handle("/file-downloads/", applyDisposition(http.StripPrefix("/file-downloads/", http.FileServer(http.Dir(config.AudioFilesPath)))))
// Authenticated routes
}
}
+type DispositionMiddleware struct {
+ handler http.Handler
+}
+
+func (m DispositionMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ log.Println("path", r.URL.Path)
+ if r.URL.Path != "/file-downloads/" {
+ w.Header().Add("Content-Disposition", "attachment")
+ }
+ m.handler.ServeHTTP(w, r)
+}
+
+func applyDisposition(handler http.Handler) DispositionMiddleware {
+ return DispositionMiddleware{
+ handler: handler,
+ }
+}
+
type authenticatedHandler func(http.ResponseWriter, *http.Request, User)
type AuthMiddleware struct {
type HeaderData struct {
SelectedMenu string
User User
+ Version string
}
func renderHeader(w http.ResponseWriter, selectedMenu string, user User) {
data := HeaderData{
SelectedMenu: selectedMenu,
User: user,
+ Version: version,
}
err := tmpl.Execute(w, data)
if err != nil {
data := PlaylistsPageData{
Playlists: db.GetPlaylists(),
}
+ for i := range data.Playlists {
+ data.Playlists[i].StartTime = strings.Replace(data.Playlists[i].StartTime, "T", " ", -1)
+ }
tmpl := template.Must(template.ParseFS(content, "templates/playlists.html"))
err := tmpl.Execute(w, data)
if err != nil {
data.Playlist = playlist
data.Entries = db.GetEntriesForPlaylist(id)
}
- renderHeader(w, "radios", user)
+ renderHeader(w, "playlists", user)
tmpl := template.Must(template.ParseFS(content, "templates/playlist.html"))
tmpl.Execute(w, data)
renderFooter(w)
<h1>Audio File Management</h1>
<p>All files can be downloaded from the <a href="/file-downloads/">public file listing</a>.</p>
- <table>
+ <table class="listing" border="1">
+ <tr><th>Name</th><th></th></tr>
{{range .Files}}
- <tr>
- <td><b>{{.Name}}</b></td>
+ <tr>
+ <td>{{.Name}}</td>
<td><form action="/files/delete" method="POST"><input type="hidden" name="filename" value="{{.Name}}"><input type="submit" value="Delete"></form></td>
</tr>
{{end}}
table.radio-status, td.outer {
border: 1px solid;
}
+ table.listing td, table.listing th {
+ padding: 0.35em;
+ }
+ td.enabled {
+ text-align: center;
+ }
+ td.token {
+ font-family: monospace;
+ font-size: 80%;
+ }
table.inner {
border-collapse: collapse;
}
- td.clear {
+ td.channel-state {
text-align: center;
+ width: 5em;
+ height: 5em;
+ }
+ td.clear {
background-color: #eeeeee;
}
+ td.cos {
+ background-color: #aaeeaa;
+ }
+ td.ptt {
+ background-color: #eeaaaa;
+ }
+ th {
+ text-align: left;
+ }
+ input.seconds {
+ width: 3em;
+ }
.time-table {
font-size: 90%;
}
{{if .User.Username}}
<div class="logged-in">Logged in as:<br><i>{{.User.Username}}</i></div>
{{end}}
- <div class="menu-tail"><small><i>broadcaster-server vTODO</i></small></div>
+ <div class="menu-tail"><small><i>broadcaster-server {{.Version}}</i></small></div>
</div>
{{end}}
<div class="content">
{{range .Entries}}
<p>
Wait until
- <input type="text" name="delaySeconds" value="{{.DelaySeconds}}">
- seconds from
+ <input type="text" name="delaySeconds" value="{{.DelaySeconds}}" class="seconds">
+ seconds
<select name="isRelative">
- <option value="1">previous item</option>
- <option value="0" {{if not .IsRelative}} selected="selected" {{end}}>start of transmission</option>
+ <option value="1">from previous</option>
+ <option value="0" {{if not .IsRelative}} selected="selected" {{end}}>from start</option>
</select>
then play
<select name="filename">{{$f := .Filename}}
<option value="{{.}}" {{if eq . $f }} selected="selected" {{end}}>{{.}}</option>
{{end}}
</select>
- <a href="#" onclick="deleteItem(this)">(Delete Item)</a>
+ <a href="#" onclick="deleteItem(this)">(Delete)</a>
</p>
{{end}}
<p>
{{end}}
<template id="item-template">
Wait until
- <input type="text" name="delaySeconds" value="0">
- seconds from
+ <input type="text" name="delaySeconds" value="0" class="seconds">
+ seconds
<select name="isRelative">
- <option value="1">previous item</option>
- <option value="0">start of transmission</option>
+ <option value="1">from previous</option>
+ <option value="0">from start</option>
</select>
then play
<select name="filename">
<option value="{{.}}">{{.}}</option>
{{end}}
</select>
- <a href="#" onclick="deleteItem(this)">(Delete Item)</a>
+ <a href="#" onclick="deleteItem(this)">(Delete)</a>
</template>
<h1>Playlist Management</h1>
- <table>
- <tr><th>Name</th><th>Enabled?</th><th>Start Time</th><th></th></tr>
+ <table class="listing" border="1">
+ <tr><th>Name</th><th>Start Time</th><th>Enabled?</th><th></th></tr>
{{range .Playlists}}
- <tr><td>{{.Name}}</td><td>{{if .Enabled}}✅{{else}}❌{{end}}</td><td>{{.StartTime}}</td><td><a href="/playlists/{{.Id}}">(Edit)</a></td></tr>
+ <tr><td>{{.Name}}</td><td>{{.StartTime}}</td><td class="enabled">{{if .Enabled}}✅{{else}}❌{{end}}</td><td><a href="/playlists/{{.Id}}">(Edit)</a></td></tr>
{{end}}
</table>
<p><a href="/playlists/new">Add New Playlist</a></p>
<h1>Radios</h1>
- <ul>
+ <table class="listing" border="1">
+ <tr><th>Name</th><th>Token</th><th></th></tr>
{{range .Radios}}
- <li><b>{{.Name}}</b> {{.Token}} <a href="/radios/{{.Id}}">(Edit)</a></li>
+ <tr><td>{{.Name}}</td><td class="token">{{.Token}}</td><td><a href="/radios/{{.Id}}">(Edit)</a></td></tr>
{{end}}
- </ul>
+ </table>
<p><a href="/radios/new">Register New Radio</a></p>
</td>
</tr>
<tr>
- <td class="outer {{.ChannelClass}}">
+ <td class="outer {{.ChannelClass}} channel-state">
{{.ChannelState}}
</td>
<td class="outer" colspan="2">
<h1>User Management</h1>
- <ul>
+ <table class="listing" border="1">
+ <tr><th>Username</th><th>Is Admin?</th><th></th></tr>
{{range .Users}}
- <li><b>{{.Username}}</b> <a href="/users/{{.Id}}">(Edit)</a></li>
+ <tr><td>{{.Username}}</td><td class="enabled">{{if .IsAdmin}}✅{{else}}❌{{end}}</td><td><a href="/users/{{.Id}}">(Edit)</a></td></tr>
{{end}}
- </ul>
+ </table>
<p><a href="/users/new">Add New User</a></p>