Kasianov Nikolai Alekseevich
2 years ago
9 changed files with 12039 additions and 55 deletions
@ -0,0 +1,75 @@
|
||||
package dashboard |
||||
|
||||
import ( |
||||
"embed" |
||||
"encoding/json" |
||||
"fmt" |
||||
"html/template" |
||||
"io/fs" |
||||
"net/http" |
||||
"unbewohnte/wecr/config" |
||||
"unbewohnte/wecr/worker" |
||||
) |
||||
|
||||
type Dashboard struct { |
||||
Server *http.Server |
||||
} |
||||
|
||||
//go:embed res
|
||||
var resFS embed.FS |
||||
|
||||
type PageData struct { |
||||
Conf config.Conf |
||||
Stats worker.Statistics |
||||
} |
||||
|
||||
func NewDashboard(port uint16, webConf *config.Conf, statistics *worker.Statistics) *Dashboard { |
||||
mux := http.NewServeMux() |
||||
res, err := fs.Sub(resFS, "res") |
||||
if err != nil { |
||||
return nil |
||||
} |
||||
|
||||
mux.Handle("/static/", http.FileServer(http.FS(res))) |
||||
mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { |
||||
template, err := template.ParseFS(res, "*.html") |
||||
if err != nil { |
||||
return |
||||
} |
||||
|
||||
template.ExecuteTemplate(w, "index.html", nil) |
||||
}) |
||||
|
||||
mux.HandleFunc("/stats", func(w http.ResponseWriter, req *http.Request) { |
||||
jsonStats, err := json.MarshalIndent(statistics, "", " ") |
||||
if err != nil { |
||||
http.Error(w, "Failed to marshal statistics", http.StatusInternalServerError) |
||||
return |
||||
} |
||||
w.Header().Add("Content-type", "application/json") |
||||
w.Write(jsonStats) |
||||
}) |
||||
|
||||
mux.HandleFunc("/conf", func(w http.ResponseWriter, req *http.Request) { |
||||
jsonConf, err := json.MarshalIndent(webConf, "", " ") |
||||
if err != nil { |
||||
http.Error(w, "Failed to marshal configuration", http.StatusInternalServerError) |
||||
return |
||||
} |
||||
w.Header().Add("Content-type", "application/json") |
||||
w.Write(jsonConf) |
||||
}) |
||||
|
||||
server := &http.Server{ |
||||
Addr: fmt.Sprintf(":%d", port), |
||||
Handler: mux, |
||||
} |
||||
|
||||
return &Dashboard{ |
||||
Server: server, |
||||
} |
||||
} |
||||
|
||||
func (board *Dashboard) Launch() error { |
||||
return board.Server.ListenAndServe() |
||||
} |
@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<title>Wecr dashboard</title> |
||||
<!-- <link rel="icon" href="/static/icon.png"> --> |
||||
<link rel="stylesheet" href="/static/bootstrap.css"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
</head> |
||||
|
||||
<body class="d-flex flex-column h-100"> |
||||
<div class="container"> |
||||
<header class="d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom"> |
||||
<a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none"> |
||||
<svg class="bi me-2" width="40" height="32"> |
||||
<use xlink:href="#bootstrap"></use> |
||||
</svg> |
||||
<strong class="fs-4">Wecr</strong> |
||||
</a> |
||||
|
||||
<ul class="nav nav-pills"> |
||||
<li class="nav-item"><a href="/stats" class="nav-link">Stats</a></li> |
||||
<li class="nav-item"><a href="/conf" class="nav-link">Config</a></li> |
||||
</ul> |
||||
</header> |
||||
</div> |
||||
|
||||
<div class="container"> |
||||
<h1>Dashboard</h1> |
||||
|
||||
<h2>Statistics</h2> |
||||
<div id="statistics"> |
||||
<ol class="list-group list-group-numbered"> |
||||
<li class="list-group-item d-flex justify-content-between align-items-start"> |
||||
<div class="ms-2 me-auto"> |
||||
<div class="fw-bold">Pages visited</div> |
||||
</div> |
||||
<span class="badge bg-primary rounded-pill" id="pages_visited">0</span> |
||||
</li> |
||||
<li class="list-group-item d-flex justify-content-between align-items-start"> |
||||
<div class="ms-2 me-auto"> |
||||
<div class="fw-bold">Matches found</div> |
||||
</div> |
||||
<span class="badge bg-primary rounded-pill" id="matches_found">0</span> |
||||
</li> |
||||
<li class="list-group-item d-flex justify-content-between align-items-start"> |
||||
<div class="ms-2 me-auto"> |
||||
<div class="fw-bold">Pages saved</div> |
||||
</div> |
||||
<span class="badge bg-primary rounded-pill" id="pages_saved">0</span> |
||||
</li> |
||||
<li class="list-group-item d-flex justify-content-between align-items-start"> |
||||
<div class="ms-2 me-auto"> |
||||
<div class="fw-bold">Start time</div> |
||||
</div> |
||||
<span class="badge bg-primary rounded-pill" id="start_time_unix">0</span> |
||||
</li> |
||||
<li class="list-group-item d-flex justify-content-between align-items-start"> |
||||
<div class="ms-2 me-auto"> |
||||
<div class="fw-bold">Stopped</div> |
||||
</div> |
||||
<span class="badge bg-primary rounded-pill" id="stopped">false</span> |
||||
</li> |
||||
</ol> |
||||
</div> |
||||
|
||||
<!-- <h2>Configuration</h2> |
||||
<pre id="configuration"></pre> --> |
||||
</div> |
||||
</body> |
||||
|
||||
<script> |
||||
window.onload = function () { |
||||
let confOutput = document.getElementById("configuration"); |
||||
let pagesVisitedOut = document.getElementById("pages_visited"); |
||||
let matchesFoundOut = document.getElementById("matches_found"); |
||||
let pagesSavedOut = document.getElementById("pages_saved"); |
||||
let startTimeOut = document.getElementById("start_time_unix"); |
||||
let stoppedOut = document.getElementById("stopped"); |
||||
|
||||
const interval = setInterval(function () { |
||||
// update statistics |
||||
fetch("/stats") |
||||
.then((response) => response.json()) |
||||
.then((statistics) => { |
||||
pagesVisitedOut.innerText = statistics.pages_visited; |
||||
matchesFoundOut.innerText = statistics.matches_found; |
||||
pagesSavedOut.innerText = statistics.pages_saved; |
||||
startTimeOut.innerText = new Date(1000 * statistics.start_time_unix); |
||||
stoppedOut.innerText = statistics.stopped; |
||||
}); |
||||
// // update config just in case |
||||
// fetch("/conf") |
||||
// .then((response) => response.text()) |
||||
// .then((response_text) => JSON.parse(response_text)) |
||||
// .then((config) => { |
||||
// confOutput.innerText = "Configuration: \n" + JSON.stringify(config); |
||||
// }); |
||||
}, 650); |
||||
}(); |
||||
</script> |
||||
|
||||
</html> |
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue