Skip to content

Commit

Permalink
Web dashboard foundation
Browse files Browse the repository at this point in the history
  • Loading branch information
Unbewohnte committed Feb 11, 2023
1 parent fd484c6 commit 6fab903
Show file tree
Hide file tree
Showing 9 changed files with 12,039 additions and 55 deletions.
30 changes: 20 additions & 10 deletions src/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,24 @@ type Logging struct {
LogsFile string `json:"logs_file"`
}

type WebDashboard struct {
UseDashboard bool `json:"launch_dashboard"`
Port uint16 `json:"port"`
}

// Configuration file structure
type Conf struct {
Search Search `json:"search"`
Requests Requests `json:"requests"`
Depth uint `json:"depth"`
Workers uint `json:"workers"`
InitialPages []string `json:"initial_pages"`
AllowedDomains []string `json:"allowed_domains"`
BlacklistedDomains []string `json:"blacklisted_domains"`
InMemoryVisitQueue bool `json:"in_memory_visit_queue"`
Save Save `json:"save"`
Logging Logging `json:"logging"`
Search Search `json:"search"`
Requests Requests `json:"requests"`
Depth uint `json:"depth"`
Workers uint `json:"workers"`
InitialPages []string `json:"initial_pages"`
AllowedDomains []string `json:"allowed_domains"`
BlacklistedDomains []string `json:"blacklisted_domains"`
InMemoryVisitQueue bool `json:"in_memory_visit_queue"`
Dashboard WebDashboard `json:"web_dashboard"`
Save Save `json:"save"`
Logging Logging `json:"logging"`
}

// Default configuration file structure
Expand All @@ -102,6 +108,10 @@ func Default() *Conf {
AllowedDomains: []string{""},
BlacklistedDomains: []string{""},
InMemoryVisitQueue: false,
Dashboard: WebDashboard{
UseDashboard: true,
Port: 13370,
},
Logging: Logging{
OutputLogs: true,
LogsFile: "logs.log",
Expand Down
75 changes: 75 additions & 0 deletions src/dashboard/dashboard.go
Original file line number Diff line number Diff line change
@@ -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()
}
104 changes: 104 additions & 0 deletions src/dashboard/res/index.html
Original file line number Diff line number Diff line change
@@ -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>
Loading

0 comments on commit 6fab903

Please sign in to comment.