Webgui
This commit is contained in:
parent
c4f1d60dca
commit
b3c6569b6c
14 changed files with 387 additions and 71 deletions
4
Makefile
4
Makefile
|
|
@ -2,7 +2,7 @@ DUSER=aceberg
|
||||||
DNAME=watchyourlan
|
DNAME=watchyourlan
|
||||||
|
|
||||||
IFACE=virbr-bw
|
IFACE=virbr-bw
|
||||||
DBPATH=data/hosts.db
|
DBPATH=/data/hosts.db
|
||||||
SHOUTRRR_URL=gotify://192.168.2.1:8083/AwQqpAae.rrl5Ob/?title=Unknown host detected&DisableTLS=yes
|
SHOUTRRR_URL=gotify://192.168.2.1:8083/AwQqpAae.rrl5Ob/?title=Unknown host detected&DisableTLS=yes
|
||||||
THEME=darkly
|
THEME=darkly
|
||||||
|
|
||||||
|
|
@ -13,7 +13,7 @@ mod:
|
||||||
go mod tidy
|
go mod tidy
|
||||||
|
|
||||||
run:
|
run:
|
||||||
cd src && \
|
cd cmd/WatchYourLAN/ && \
|
||||||
sudo \
|
sudo \
|
||||||
env IFACE=$(IFACE) DBPATH=$(DBPATH) THEME=$(THEME) \
|
env IFACE=$(IFACE) DBPATH=$(DBPATH) THEME=$(THEME) \
|
||||||
go run .
|
go run .
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,12 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
// "time"
|
// "time"
|
||||||
"github.com/aceberg/WatchYourLAN/pkg/conf"
|
"github.com/aceberg/WatchYourLAN/pkg/conf"
|
||||||
. "github.com/aceberg/WatchYourLAN/pkg/models"
|
"github.com/aceberg/WatchYourLAN/pkg/db"
|
||||||
|
"github.com/aceberg/WatchYourLAN/pkg/web"
|
||||||
|
// . "github.com/aceberg/WatchYourLAN/pkg/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
var AppConfig Conf
|
// var AppConfig Conf
|
||||||
|
|
||||||
// var AllHosts []Host
|
// var AllHosts []Host
|
||||||
|
|
||||||
// func scan_and_compare() {
|
// func scan_and_compare() {
|
||||||
|
|
@ -26,14 +27,13 @@ var AppConfig Conf
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// AllHosts = []Host{}
|
appConfig := conf.GetConfig() // Get config from Defaults, Config file, Env
|
||||||
AppConfig = conf.GetConfig() // Get config from Defaults, Config file, Env
|
|
||||||
|
|
||||||
fmt.Println("CONF =", AppConfig)
|
fmt.Println("CONF =", appConfig)
|
||||||
|
|
||||||
// db_create() // Check if DB exists. Create if not
|
db.CreateDB(appConfig.DbPath) // Check if DB exists. Create if not
|
||||||
|
|
||||||
// go scan_and_compare()
|
// go scan_and_compare()
|
||||||
|
|
||||||
// webgui() // Start web GUI
|
web.Webgui(appConfig) // Start web GUI
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
go.mod
5
go.mod
|
|
@ -2,7 +2,10 @@ module github.com/aceberg/WatchYourLAN
|
||||||
|
|
||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
require github.com/spf13/viper v1.14.0
|
require (
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.16
|
||||||
|
github.com/spf13/viper v1.14.0
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -133,6 +133,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||||
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,9 @@ func GetConfig() (config Conf) {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteConfig() {
|
func WriteConfig(theme string) {
|
||||||
viper.SetConfigFile(configPath)
|
viper.SetConfigFile(configPath)
|
||||||
viper.SetConfigType("env")
|
viper.SetConfigType("env")
|
||||||
viper.Set("THEME", AppConfig.Theme)
|
viper.Set("THEME", theme)
|
||||||
viper.WriteConfig()
|
viper.WriteConfig()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,44 +2,44 @@ package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
//"fmt"
|
//"fmt"
|
||||||
"log"
|
|
||||||
"database/sql"
|
"database/sql"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func db_exec(sqlStatement string) {
|
func dbExec(path, sqlStatement string) {
|
||||||
db, _ := sql.Open("sqlite3", AppConfig.DbPath)
|
db, _ := sql.Open("sqlite3", path)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err := db.Exec(sqlStatement)
|
_, err := db.Exec(sqlStatement)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("ERROR: db_exec: ", err)
|
log.Fatal("ERROR: db_exec: ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func db_select() (dbHosts []Host) {
|
// func db_select() (dbHosts []Host) {
|
||||||
db, _ := sql.Open("sqlite3", AppConfig.DbPath)
|
// db, _ := sql.Open("sqlite3", AppConfig.DbPath)
|
||||||
defer db.Close()
|
// defer db.Close()
|
||||||
|
|
||||||
sqlStatement := `SELECT * FROM "now" ORDER BY DATE DESC`
|
// sqlStatement := `SELECT * FROM "now" ORDER BY DATE DESC`
|
||||||
|
|
||||||
res, err := db.Query(sqlStatement)
|
// res, err := db.Query(sqlStatement)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
log.Fatal("ERROR: db_select: ", err)
|
// log.Fatal("ERROR: db_select: ", err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
dbHosts = []Host{}
|
// dbHosts = []Host{}
|
||||||
for res.Next() {
|
// for res.Next() {
|
||||||
var oneHost Host
|
// var oneHost Host
|
||||||
err = res.Scan(&oneHost.Id, &oneHost.Name, &oneHost.Ip, &oneHost.Mac, &oneHost.Hw, &oneHost.Date, &oneHost.Known, &oneHost.Now)
|
// err = res.Scan(&oneHost.Id, &oneHost.Name, &oneHost.Ip, &oneHost.Mac, &oneHost.Hw, &oneHost.Date, &oneHost.Known, &oneHost.Now)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
log.Fatal(err)
|
// log.Fatal(err)
|
||||||
}
|
// }
|
||||||
oneHost.Name = unquote_str(oneHost.Name)
|
// oneHost.Name = unquote_str(oneHost.Name)
|
||||||
oneHost.Hw = unquote_str(oneHost.Hw)
|
// oneHost.Hw = unquote_str(oneHost.Hw)
|
||||||
dbHosts = append(dbHosts, oneHost)
|
// dbHosts = append(dbHosts, oneHost)
|
||||||
}
|
// }
|
||||||
|
|
||||||
//fmt.Println("Select all:", dbHosts)
|
// //fmt.Println("Select all:", dbHosts)
|
||||||
return dbHosts
|
// return dbHosts
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"log"
|
"log"
|
||||||
"fmt"
|
"os"
|
||||||
|
// "fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func db_create() {
|
func CreateDB(path string) {
|
||||||
if _, err := os.Stat(AppConfig.DbPath); err == nil {
|
if _, err := os.Stat(path); err == nil {
|
||||||
log.Println("INFO: DB exists")
|
log.Println("INFO: DB exists")
|
||||||
} else {
|
} else {
|
||||||
sqlStatement := `CREATE TABLE "now" (
|
sqlStatement := `CREATE TABLE "now" (
|
||||||
"ID" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
"ID" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||||
"NAME" TEXT NOT NULL,
|
"NAME" TEXT NOT NULL,
|
||||||
|
|
@ -20,34 +20,34 @@ func db_create() {
|
||||||
"KNOWN" INTEGER DEFAULT 0,
|
"KNOWN" INTEGER DEFAULT 0,
|
||||||
"NOW" INTEGER DEFAULT 0
|
"NOW" INTEGER DEFAULT 0
|
||||||
);`
|
);`
|
||||||
db_exec(sqlStatement)
|
dbExec(path, sqlStatement)
|
||||||
log.Println("INFO: Table created!")
|
log.Println("INFO: Table created!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func db_insert(oneHost Host) {
|
// func db_insert(oneHost Host) {
|
||||||
oneHost.Name = quote_str(oneHost.Name)
|
// oneHost.Name = quote_str(oneHost.Name)
|
||||||
oneHost.Hw = quote_str(oneHost.Hw)
|
// oneHost.Hw = quote_str(oneHost.Hw)
|
||||||
sqlStatement := `INSERT INTO "now" (NAME, IP, MAC, HW, DATE, KNOWN, NOW)
|
// sqlStatement := `INSERT INTO "now" (NAME, IP, MAC, HW, DATE, KNOWN, NOW)
|
||||||
VALUES ('%s','%s','%s','%s','%s','%d','%d');`
|
// VALUES ('%s','%s','%s','%s','%s','%d','%d');`
|
||||||
sqlStatement = fmt.Sprintf(sqlStatement, oneHost.Name, oneHost.Ip, oneHost.Mac, oneHost.Hw, oneHost.Date, oneHost.Known, oneHost.Now)
|
// sqlStatement = fmt.Sprintf(sqlStatement, oneHost.Name, oneHost.Ip, oneHost.Mac, oneHost.Hw, oneHost.Date, oneHost.Known, oneHost.Now)
|
||||||
//fmt.Println("Insert statement:", sqlStatement)
|
// //fmt.Println("Insert statement:", sqlStatement)
|
||||||
db_exec(sqlStatement)
|
// db_exec(sqlStatement)
|
||||||
}
|
// }
|
||||||
|
|
||||||
func db_update(oneHost Host) {
|
// func db_update(oneHost Host) {
|
||||||
oneHost.Name = quote_str(oneHost.Name)
|
// oneHost.Name = quote_str(oneHost.Name)
|
||||||
oneHost.Hw = quote_str(oneHost.Hw)
|
// oneHost.Hw = quote_str(oneHost.Hw)
|
||||||
sqlStatement := `UPDATE "now" set
|
// sqlStatement := `UPDATE "now" set
|
||||||
NAME = '%s', IP = '%s', MAC = '%s', HW = '%s', DATE = '%s',
|
// NAME = '%s', IP = '%s', MAC = '%s', HW = '%s', DATE = '%s',
|
||||||
KNOWN = '%d', NOW = '%d'
|
// KNOWN = '%d', NOW = '%d'
|
||||||
WHERE ID = '%d';`
|
// WHERE ID = '%d';`
|
||||||
sqlStatement = fmt.Sprintf(sqlStatement, oneHost.Name, oneHost.Ip, oneHost.Mac, oneHost.Hw, oneHost.Date, oneHost.Known, oneHost.Now, oneHost.Id)
|
// sqlStatement = fmt.Sprintf(sqlStatement, oneHost.Name, oneHost.Ip, oneHost.Mac, oneHost.Hw, oneHost.Date, oneHost.Known, oneHost.Now, oneHost.Id)
|
||||||
//fmt.Println("Update statement:", sqlStatement)
|
// //fmt.Println("Update statement:", sqlStatement)
|
||||||
db_exec(sqlStatement)
|
// db_exec(sqlStatement)
|
||||||
}
|
// }
|
||||||
|
|
||||||
func db_setnow() {
|
// func db_setnow() {
|
||||||
sqlStatement := `UPDATE "now" set NOW = '0';`
|
// sqlStatement := `UPDATE "now" set NOW = '0';`
|
||||||
db_exec(sqlStatement)
|
// db_exec(sqlStatement)
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,8 @@ type Conf struct {
|
||||||
ShoutUrl string
|
ShoutUrl string
|
||||||
Theme string
|
Theme string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GuiData struct {
|
||||||
|
Config Conf
|
||||||
|
Hosts []Host
|
||||||
|
}
|
||||||
|
|
|
||||||
45
pkg/web/index.go
Normal file
45
pkg/web/index.go
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
// "fmt"
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
|
// "strconv"
|
||||||
|
. "github.com/aceberg/WatchYourLAN/pkg/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func index(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var guiData GuiData
|
||||||
|
guiData.Config = AppConfig
|
||||||
|
guiData.Hosts = []Host{}
|
||||||
|
|
||||||
|
tmpl, _ := template.ParseFS(TemplHTML, "templates/index.html", "templates/header.html", "templates/footer.html")
|
||||||
|
tmpl.ExecuteTemplate(w, "index", guiData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// func update_host(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// idStr := r.FormValue("id")
|
||||||
|
// name := r.FormValue("name")
|
||||||
|
// knownStr := r.FormValue("known")
|
||||||
|
|
||||||
|
// if idStr == "" {
|
||||||
|
// fmt.Fprintf(w, "No data!")
|
||||||
|
// } else {
|
||||||
|
// var known uint16
|
||||||
|
// id, _ := strconv.Atoi(idStr)
|
||||||
|
// known = 0
|
||||||
|
// if knownStr == "on" {
|
||||||
|
// known = 1
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for i, oneHost := range AllHosts {
|
||||||
|
// if oneHost.Id == uint16(id) {
|
||||||
|
// AllHosts[i].Name = name
|
||||||
|
// AllHosts[i].Known = known
|
||||||
|
// db_update(AllHosts[i])
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// http.Redirect(w, r, r.Header.Get("Referer"), 302)
|
||||||
|
// }
|
||||||
4
pkg/web/templates/footer.html
Normal file
4
pkg/web/templates/footer.html
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{{ define "footer"}}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
{{ end }}
|
||||||
72
pkg/web/templates/header.html
Normal file
72
pkg/web/templates/header.html
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
{{ define "header"}}
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Watch Your LAN</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<!--Favicon-->
|
||||||
|
<link href="data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAA/6k7AP+uSQD/z50A7urjAD85MgAAOO8AWlpaAADIawAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADEREQAAAAAzEREREQAAAzEREREREAAzFxEREVERADN3d3VVVREDM3d3dYVlERMzd3d1VVUREzM3ERESERETMzcRESERERMzNxESMREREzM3ESNEQREwMzcSMxEREwAzNyM0REQzAAMzMzMzMzAAADMzMzMzAAAAADMzMwAAD4HwAA4AcAAMADAACAAQAAgAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAACAAQAAwAMAAOAHAAD4HwAA" rel="icon" type="image/x-icon" />
|
||||||
|
<!-- Bootstrap and theme -->
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootswatch@5.2.0/dist/{{ .Config.Theme }}/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<!-- Font for icons -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css">
|
||||||
|
<!-- JavaScript Bundle with Popper -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-expand-sm navbar-dark bg-primary">
|
||||||
|
<div class="container">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="/online/">Online</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="/offline/">Offline</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link active dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">Theme</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a class="dropdown-item" href="/theme/cerulean">Cerulean</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/cosmo">Cosmo</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/cyborg">Cyborg</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/darkly">Darkly</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/flatly">Flatly</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/journal">Journal</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/litera">Litera</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/lumen">Lumen</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/lux">Lux</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/materia">Materia</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/minty">Minty</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/morph">Morph</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/pulse">Pulse</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/quartz">Quartz</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/sandstone">Sandstone</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/simplex">Simplex</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/sketchy">Sketchy</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/slate">Slate</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/solar">Solar</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/spacelab">Spacelab</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/superhero">Superhero</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/united">United</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/vapor">Vapor</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/yeti">Yeti</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/theme/zephyr">Zephyr</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav navbar-nav navbar-right">
|
||||||
|
<form action="/search_hosts/" method="post">
|
||||||
|
<li class="input-group nav-item">
|
||||||
|
<input name="search" type="text" class="form-control text-dark" placeholder="Search">
|
||||||
|
<button type="submit" class="btn btn-primary">Search</button>
|
||||||
|
</li>
|
||||||
|
</form>
|
||||||
|
<li class="nav-item"><a class="nav-link active" href="https://github.com/aceberg/WatchYourLAN">
|
||||||
|
<h3> <i class="bi bi-github"></i></h3>
|
||||||
|
</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
{{ end }}
|
||||||
74
pkg/web/templates/index.html
Normal file
74
pkg/web/templates/index.html
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
{{ define "index"}}
|
||||||
|
|
||||||
|
{{ template "header" }}
|
||||||
|
<!--Auto refresh (seconds)-->
|
||||||
|
<meta http-equiv="refresh" content="{{ .Config.Timeout }}">
|
||||||
|
<!--Bootstrap theme-->
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootswatch@5.2.0/dist/{{ .Config.Theme }}/bootstrap.min.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container mt-3">
|
||||||
|
<h2>Online</h2>
|
||||||
|
<p>Scanning interfaces: {{ .Config.Iface }}</p>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Ip</th>
|
||||||
|
<th>Mac</th>
|
||||||
|
<th>Hardware</th>
|
||||||
|
<th>Known</th>
|
||||||
|
</tr>
|
||||||
|
{{ range .Hosts }}
|
||||||
|
{{ if eq .Now 1 }}
|
||||||
|
<tr>
|
||||||
|
<td>{{ .Name }}</td>
|
||||||
|
<td><a href="http://{{ .Ip }}" target="_blank">{{ .Ip }}</a></td>
|
||||||
|
<td>{{ .Mac }}</td>
|
||||||
|
<td>{{ .Hw }}</td>
|
||||||
|
<td>
|
||||||
|
{{ if eq .Known 1 }}
|
||||||
|
<button type="button" class="btn btn-success" disabled>Yes</button>
|
||||||
|
{{ else }}
|
||||||
|
<button type="button" class="btn btn-warning" disabled>No</button>
|
||||||
|
{{ end }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</table>
|
||||||
|
<h2>Log</h2>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Ip</th>
|
||||||
|
<th>Mac</th>
|
||||||
|
<th>Hardware</th>
|
||||||
|
<th>Last seen</th>
|
||||||
|
<th>Known</th>
|
||||||
|
</tr>
|
||||||
|
{{ range .Hosts }}
|
||||||
|
<form action="/update_host/" method="post">
|
||||||
|
<input name="id" type="hidden" class="form-control" value="{{ .Id }}">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input name="name" type="text" class="form-control text-dark" value="{{ .Name }}">
|
||||||
|
</td>
|
||||||
|
<td>{{ .Ip }}</td>
|
||||||
|
<td>{{ .Mac }}</td>
|
||||||
|
<td>{{ .Hw }}</td>
|
||||||
|
<td>{{ .Date }}</td>
|
||||||
|
<td>
|
||||||
|
{{ if eq .Known 1 }}
|
||||||
|
<button value="off" name="known" type="submit" class="btn btn-success">Yes</button>
|
||||||
|
{{ else }}
|
||||||
|
<button value="on" name="known" type="submit" class="btn btn-warning">No</button>
|
||||||
|
{{ end }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</form>
|
||||||
|
{{ end }}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ template "footer" }}
|
||||||
|
{{ end }}
|
||||||
75
pkg/web/templates/offline.html
Normal file
75
pkg/web/templates/offline.html
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
{{ define "offline"}}
|
||||||
|
|
||||||
|
{{ template "header" }}
|
||||||
|
<!--Auto refresh (seconds)-->
|
||||||
|
<!-- <meta http-equiv="refresh" content="{{ .Config.Timeout }}"> -->
|
||||||
|
<!--Bootstrap theme-->
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootswatch@5.2.0/dist/{{ .Config.Theme }}/bootstrap.min.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container mt-3">
|
||||||
|
<table class="table table-striped">
|
||||||
|
<tr>
|
||||||
|
<form action="/sort_hosts/" method="post">
|
||||||
|
<th>Name<br>
|
||||||
|
<button type="submit" name="sort_method" value="name-up" class="btn btn-primary btn-sm">
|
||||||
|
<i class="bi bi-caret-up"></i>
|
||||||
|
</button>
|
||||||
|
<button type="submit" name="sort_method" value="name-down" class="btn btn-primary btn-sm">
|
||||||
|
<i class="bi bi-caret-down"></i>
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
|
<th>Ip<br>
|
||||||
|
<button type="submit" name="sort_method" value="ip-up" class="btn btn-primary btn-sm">
|
||||||
|
<i class="bi bi-caret-up"></i>
|
||||||
|
</button>
|
||||||
|
<button type="submit" name="sort_method" value="ip-down" class="btn btn-primary btn-sm">
|
||||||
|
<i class="bi bi-caret-down"></i>
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
|
<th>Mac</th>
|
||||||
|
<th>Hardware</th>
|
||||||
|
<th>Last seen<br>
|
||||||
|
<button type="submit" name="sort_method" value="date-up" class="btn btn-primary btn-sm">
|
||||||
|
<i class="bi bi-caret-up"></i>
|
||||||
|
</button>
|
||||||
|
<button type="submit" name="sort_method" value="date-down" class="btn btn-primary btn-sm">
|
||||||
|
<i class="bi bi-caret-down"></i>
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
|
<th>Known<br>
|
||||||
|
<button type="submit" name="sort_method" value="known-up" class="btn btn-primary btn-sm">
|
||||||
|
<i class="bi bi-caret-up"></i>
|
||||||
|
</button>
|
||||||
|
<button type="submit" name="sort_method" value="known-down" class="btn btn-primary btn-sm">
|
||||||
|
<i class="bi bi-caret-down"></i>
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
|
</form>
|
||||||
|
</tr>
|
||||||
|
{{ range .Hosts }}
|
||||||
|
<form action="/update_host/" method="post">
|
||||||
|
<input name="id" type="hidden" class="form-control" value="{{ .Id }}">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input name="name" type="text" class="form-control text-dark" value="{{ .Name }}">
|
||||||
|
</td>
|
||||||
|
<td><a href="http://{{ .Ip }}" target="_blank">{{ .Ip }}</a></td>
|
||||||
|
<td>{{ .Mac }}</td>
|
||||||
|
<td>{{ .Hw }}</td>
|
||||||
|
<td>{{ .Date }}</td>
|
||||||
|
<td>
|
||||||
|
{{ if eq .Known 1 }}
|
||||||
|
<button value="off" name="known" type="submit" class="btn btn-success">Yes</button>
|
||||||
|
{{ else }}
|
||||||
|
<button value="on" name="known" type="submit" class="btn btn-warning">No</button>
|
||||||
|
{{ end }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</form>
|
||||||
|
{{ end }}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ template "footer" }}
|
||||||
|
{{ end }}
|
||||||
36
pkg/web/webgui.go
Normal file
36
pkg/web/webgui.go
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
. "github.com/aceberg/WatchYourLAN/pkg/models"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
var AppConfig Conf
|
||||||
|
|
||||||
|
// var AllHosts []Host
|
||||||
|
|
||||||
|
//go:embed templates/*
|
||||||
|
var TemplHTML embed.FS
|
||||||
|
|
||||||
|
func Webgui(appConfig Conf) {
|
||||||
|
|
||||||
|
AppConfig = appConfig
|
||||||
|
address := AppConfig.GuiIP + ":" + AppConfig.GuiPort
|
||||||
|
|
||||||
|
log.Println("=================================== ")
|
||||||
|
log.Println(fmt.Sprintf("Web GUI at http://%s", address))
|
||||||
|
log.Println("=================================== ")
|
||||||
|
|
||||||
|
http.HandleFunc("/", index)
|
||||||
|
http.HandleFunc("/home/", index)
|
||||||
|
// http.HandleFunc("/offline/", offline)
|
||||||
|
// http.HandleFunc("/online/", online)
|
||||||
|
// http.HandleFunc("/search_hosts/", search_hosts)
|
||||||
|
// http.HandleFunc("/sort_hosts/", sort_hosts)
|
||||||
|
// http.HandleFunc("/theme/", theme)
|
||||||
|
// http.HandleFunc("/update_host/", update_host)
|
||||||
|
http.ListenAndServe(address, nil)
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue