implement basic web server for dashboard,
use templates to do basic SSR on head and header
This commit is contained in:
parent
84cbe0e45d
commit
cfceb32134
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
vars.js
|
**/config.json
|
||||||
**/package-lock.json
|
**/package-lock.json
|
||||||
**/node_modules
|
**/node_modules
|
||||||
|
dist/*
|
15
Makefile
Normal file
15
Makefile
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
.PHONY: build test clean
|
||||||
|
|
||||||
|
build: clean
|
||||||
|
@echo "======================== Building Binary ======================="
|
||||||
|
# resolve symbolic links in web by copying it into dist/web/
|
||||||
|
cp -rL web/ dist/web/
|
||||||
|
CGO_ENABLED=0 go build -ldflags="-s -w" -o dist/ .
|
||||||
|
|
||||||
|
test: clean
|
||||||
|
go run .
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo "======================== Cleaning Project ======================"
|
||||||
|
go clean
|
||||||
|
rm -rf dist/*
|
124
app/app.go
Normal file
124
app/app.go
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
embed "proxmoxaas-dashboard/dist/web" // go will complain here until the first build
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
var html map[string]*template.Template
|
||||||
|
|
||||||
|
func ParseTemplates() {
|
||||||
|
html = make(map[string]*template.Template)
|
||||||
|
fs.WalkDir(embed.HTML, ".", func(path string, d fs.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !d.IsDir() { // if it is a html file, parse with all the template files
|
||||||
|
v, err := fs.ReadFile(embed.HTML, path)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error reading html file %s: %s", path, err.Error())
|
||||||
|
}
|
||||||
|
t := template.New(d.Name())
|
||||||
|
t, err = t.Parse(string(v))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error parsing html file %s: %s", path, err.Error())
|
||||||
|
}
|
||||||
|
fs.WalkDir(embed.Templates, ".", func(path string, e fs.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !e.IsDir() { // if it is a template file, parse it
|
||||||
|
v, err = fs.ReadFile(embed.Templates, path)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error reading template file %s: %s", path, err.Error())
|
||||||
|
}
|
||||||
|
t, err = t.Parse(string(v))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error parsing template file %s: %s", path, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
html[d.Name()] = t
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func ServeStatic() {
|
||||||
|
http.Handle("/css/", http.FileServerFS(embed.CSS_fs))
|
||||||
|
http.Handle("/images/", http.FileServerFS(embed.Images_fs))
|
||||||
|
http.Handle("/modules/", http.FileServerFS(embed.Modules_fs))
|
||||||
|
http.Handle("/scripts/", http.FileServerFS(embed.Scripts_fs))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Run() {
|
||||||
|
configPath := flag.String("config", "config.json", "path to config.json file")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
global := GetConfig(*configPath)
|
||||||
|
|
||||||
|
ParseTemplates()
|
||||||
|
|
||||||
|
http.HandleFunc("/account.html", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
global.Page = "account"
|
||||||
|
err := html["account.html"].Execute(w, global)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
global.Page = "index"
|
||||||
|
err := html["index.html"].Execute(w, global)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
http.HandleFunc("/index.html", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
global.Page = "index"
|
||||||
|
err := html["index.html"].Execute(w, global)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
http.HandleFunc("/instance.html", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
global.Page = "instance"
|
||||||
|
err := html["instance.html"].Execute(w, global)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
http.HandleFunc("/login.html", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
global.Page = "login"
|
||||||
|
err := html["login.html"].Execute(w, global)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
http.HandleFunc("/settings.html", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
global.Page = "settings"
|
||||||
|
err := html["settings.html"].Execute(w, global)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ServeStatic()
|
||||||
|
|
||||||
|
log.Printf("Starting HTTP server at port: %d\n", global.Port)
|
||||||
|
err := http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", global.Port), nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
28
app/utils.go
Normal file
28
app/utils.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Port int `json:"listenPort"`
|
||||||
|
Organization string `json:"organization"`
|
||||||
|
PVE string `json:"pveurl"`
|
||||||
|
API string `json:"apiurl"`
|
||||||
|
Page string
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConfig(configPath string) Config {
|
||||||
|
content, err := os.ReadFile(configPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Error when opening config file: ", err)
|
||||||
|
}
|
||||||
|
var config Config
|
||||||
|
err = json.Unmarshal(content, &config)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Error during parsing config file: ", err)
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
8
configs/.htmlvalidate.json
Normal file
8
configs/.htmlvalidate.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"extends": [
|
||||||
|
"html-validate:recommended"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"no-inline-style": "off"
|
||||||
|
}
|
||||||
|
}
|
6
configs/template.config.json
Normal file
6
configs/template.config.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"listenPort": 8080,
|
||||||
|
"organization": "myorg",
|
||||||
|
"apiurl": "https://paas.mydomain.example/api",
|
||||||
|
"pveurl": "https://pve.mydomain.example"
|
||||||
|
}
|
11
init/proxmoxaas-dashboard.service
Normal file
11
init/proxmoxaas-dashboard.service
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=proxmoxaas-dashboard
|
||||||
|
After=network.target
|
||||||
|
[Service]
|
||||||
|
WorkingDirectory=/<path to dir>
|
||||||
|
ExecStart=/<path to dir>/promoxaas-dashboard
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
Type=simple
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
@ -4,8 +4,8 @@
|
|||||||
"description": "Front-end for ProxmoxAAS",
|
"description": "Front-end for ProxmoxAAS",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "html-validator --continue; stylelint --formatter verbose --fix css/*.css; DEBUG=eslint:cli-engine eslint --fix scripts/",
|
"lint": "html-validate --config configs/.htmlvalidate.json web/html/*; stylelint --config configs/.stylelintrc.json --formatter verbose --fix web/css/*.css; DEBUG=eslint:cli-engine eslint --config configs/.eslintrc.json --fix web/scripts/",
|
||||||
"update-modules": "rm -rf modules/wfa.js modules/wfa.wasm; curl https://git.tronnet.net/alu/WFA-JS/releases/download/latest/wfa.js -o modules/wfa.js; curl https://git.tronnet.net/alu/WFA-JS/releases/download/latest/wfa.wasm -o modules/wfa.wasm"
|
"update-modules": "rm -rf web/modules/wfa.js web/modules/wfa.wasm; curl https://git.tronnet.net/alu/WFA-JS/releases/download/latest/wfa.js -o web/modules/wfa.js; curl https://git.tronnet.net/alu/WFA-JS/releases/download/latest/wfa.wasm -o web/modules/wfa.wasm"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^8.43.0",
|
"eslint": "^8.43.0",
|
||||||
@ -15,6 +15,6 @@
|
|||||||
"eslint-plugin-promise": "^6.1.1",
|
"eslint-plugin-promise": "^6.1.1",
|
||||||
"stylelint": "^15.9.0",
|
"stylelint": "^15.9.0",
|
||||||
"stylelint-config-standard": "^33.0.0",
|
"stylelint-config-standard": "^33.0.0",
|
||||||
"w3c-html-validator": "^1.4.0"
|
"html-validate": "^9.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
proxmoxaas-dashboard.go
Normal file
9
proxmoxaas-dashboard.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
app "proxmoxaas-dashboard/app"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app.Run()
|
||||||
|
}
|
43
web/embed.go
Normal file
43
web/embed.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package embed
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed css/*
|
||||||
|
var CSS_fs embed.FS
|
||||||
|
|
||||||
|
//go:embed images/*
|
||||||
|
var Images_fs embed.FS
|
||||||
|
|
||||||
|
//go:embed modules/*
|
||||||
|
var Modules_fs embed.FS
|
||||||
|
|
||||||
|
//go:embed scripts/*
|
||||||
|
var Scripts_fs embed.FS
|
||||||
|
|
||||||
|
//go:embed html/*
|
||||||
|
var HTML embed.FS
|
||||||
|
|
||||||
|
//go:embed templates/*
|
||||||
|
var Templates embed.FS
|
||||||
|
|
||||||
|
/*
|
||||||
|
//go:embed html/account.html
|
||||||
|
var Account string
|
||||||
|
|
||||||
|
//go:embed html/index.html
|
||||||
|
var Index string
|
||||||
|
|
||||||
|
//go:embed html/instance.html
|
||||||
|
var Instance string
|
||||||
|
|
||||||
|
//go:embed html/login.html
|
||||||
|
var Login string
|
||||||
|
|
||||||
|
//go:embed html/settings.html
|
||||||
|
var Settings string
|
||||||
|
|
||||||
|
//go:embed templates/base.html
|
||||||
|
var Base string
|
||||||
|
*/
|
@ -1,15 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
{{template "head" .}}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>{{.Organization}} - dashboard</title>
|
|
||||||
<link rel="icon" href="images/favicon.svg" sizes="any" type="image/svg+xml">
|
|
||||||
<link rel="stylesheet" href="modules/w3.css">
|
|
||||||
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
|
|
||||||
<link rel="stylesheet" href="css/style.css">
|
|
||||||
<link rel="stylesheet" href="css/nav.css">
|
|
||||||
<link rel="stylesheet" href="css/form.css">
|
|
||||||
<script src="scripts/account.js" type="module"></script>
|
<script src="scripts/account.js" type="module"></script>
|
||||||
<script src="modules/chart.js"></script>
|
<script src="modules/chart.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
@ -43,15 +35,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<h1>{{.Organization}}</h1>
|
{{template "header" .}}
|
||||||
<label for="navtoggle">☰</label>
|
|
||||||
<input type="checkbox" id="navtoggle">
|
|
||||||
<nav id="navigation">
|
|
||||||
<a href="index.html">Instances</a>
|
|
||||||
<a href="account.html" aria-current="page">Account</a>
|
|
||||||
<a href="settings.html">Settings</a>
|
|
||||||
<a href="login.html">Logout</a>
|
|
||||||
</nav>
|
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<h2>Account</h2>
|
<h2>Account</h2>
|
||||||
@ -65,7 +49,7 @@
|
|||||||
<section class="w3-card w3-padding">
|
<section class="w3-card w3-padding">
|
||||||
<div class="flex row nowrap">
|
<div class="flex row nowrap">
|
||||||
<h3>Password</h3>
|
<h3>Password</h3>
|
||||||
<button class="w3-button w3-margin" id="change-password">Change Password</button>
|
<button class="w3-button w3-margin" id="change-password" type="button">Change Password</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="w3-card w3-padding">
|
<section class="w3-card w3-padding">
|
||||||
|
@ -1,15 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
{{template "head" .}}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>{{.Organization}} - dashboard</title>
|
|
||||||
<link rel="icon" href="images/favicon.svg" sizes="any" type="image/svg+xml">
|
|
||||||
<link rel="stylesheet" href="modules/w3.css">
|
|
||||||
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
|
|
||||||
<link rel="stylesheet" href="css/style.css">
|
|
||||||
<link rel="stylesheet" href="css/nav.css">
|
|
||||||
<link rel="stylesheet" href="css/form.css">
|
|
||||||
<script src="scripts/index.js" type="module"></script>
|
<script src="scripts/index.js" type="module"></script>
|
||||||
<script src="modules/wfa.js" type="module"></script>
|
<script src="modules/wfa.js" type="module"></script>
|
||||||
<style>
|
<style>
|
||||||
@ -33,15 +25,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<h1>{{.Organization}}</h1>
|
{{template "header" .}}
|
||||||
<label for="navtoggle">☰</label>
|
|
||||||
<input type="checkbox" id="navtoggle">
|
|
||||||
<nav id="navigation">
|
|
||||||
<a href="index.html" aria-current="page">Instances</a>
|
|
||||||
<a href="account.html">Account</a>
|
|
||||||
<a href="settings.html">Settings</a>
|
|
||||||
<a href="login.html">Logout</a>
|
|
||||||
</nav>
|
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<section>
|
<section>
|
||||||
|
@ -1,15 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
{{template "head" .}}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>{{.Organization}} - dashboard</title>
|
|
||||||
<link rel="icon" href="images/favicon.svg" sizes="any" type="image/svg+xml">
|
|
||||||
<link rel="stylesheet" href="modules/w3.css">
|
|
||||||
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
|
|
||||||
<link rel="stylesheet" href="css/style.css">
|
|
||||||
<link rel="stylesheet" href="css/nav.css">
|
|
||||||
<link rel="stylesheet" href="css/form.css">
|
|
||||||
<script src="scripts/instance.js" type="module"></script>
|
<script src="scripts/instance.js" type="module"></script>
|
||||||
<script src="scripts/draggable.js" type="module"></script>
|
<script src="scripts/draggable.js" type="module"></script>
|
||||||
<script src="modules/Sortable.min.js"></script>
|
<script src="modules/Sortable.min.js"></script>
|
||||||
@ -25,15 +17,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<h1>{{.Organization}}</h1>
|
{{template "header" .}}
|
||||||
<label for="navtoggle">☰</label>
|
|
||||||
<input type="checkbox" id="navtoggle">
|
|
||||||
<nav id="navigation">
|
|
||||||
<a href="index.html" aria-current="page">Instances</a>
|
|
||||||
<a href="account.html">Account</a>
|
|
||||||
<a href="settings.html">Settings</a>
|
|
||||||
<a href="login.html">Logout</a>
|
|
||||||
</nav>
|
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<section>
|
<section>
|
||||||
|
@ -1,25 +1,12 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
{{template "head" .}}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>{{.Organization}} - dashboard</title>
|
|
||||||
<link rel="icon" href="images/favicon.svg" sizes="any" type="image/svg+xml">
|
|
||||||
<link rel="stylesheet" href="modules/w3.css">
|
|
||||||
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
|
|
||||||
<link rel="stylesheet" href="css/style.css">
|
|
||||||
<link rel="stylesheet" href="css/nav.css">
|
|
||||||
<link rel="stylesheet" href="css/form.css">
|
|
||||||
<script src="scripts/login.js" type="module"></script>
|
<script src="scripts/login.js" type="module"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<h1>{{.Organization}}</h1>
|
{{template "header" .}}
|
||||||
<label for="navtoggle">☰</label>
|
|
||||||
<input type="checkbox" id="navtoggle">
|
|
||||||
<nav id="navigation">
|
|
||||||
<a href="login.html" aria-current="page">Login</a>
|
|
||||||
</nav>
|
|
||||||
</header>
|
</header>
|
||||||
<main class="flex" style="justify-content: center; align-items: center;">
|
<main class="flex" style="justify-content: center; align-items: center;">
|
||||||
<div class="w3-container w3-card w3-margin w3-padding" style="height: fit-content;">
|
<div class="w3-container w3-card w3-margin w3-padding" style="height: fit-content;">
|
||||||
@ -32,7 +19,7 @@
|
|||||||
<label for="realm">Realm</label>
|
<label for="realm">Realm</label>
|
||||||
<select class="w3-select w3-border" id="realm" name="realm"></select>
|
<select class="w3-select w3-border" id="realm" name="realm"></select>
|
||||||
<div class="w3-center">
|
<div class="w3-center">
|
||||||
<button class="w3-button w3-margin" id="submit">LOGIN</button>
|
<button class="w3-button w3-margin" id="submit" type="submit">LOGIN</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,15 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
{{template "head" .}}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>{{.Organization}} - dashboard</title>
|
|
||||||
<link rel="icon" href="images/favicon.svg" sizes="any" type="image/svg+xml">
|
|
||||||
<link rel="stylesheet" href="modules/w3.css">
|
|
||||||
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
|
|
||||||
<link rel="stylesheet" href="css/style.css">
|
|
||||||
<link rel="stylesheet" href="css/nav.css">
|
|
||||||
<link rel="stylesheet" href="css/form.css">
|
|
||||||
<script src="scripts/settings.js" type="module"></script>
|
<script src="scripts/settings.js" type="module"></script>
|
||||||
<style>
|
<style>
|
||||||
legend {
|
legend {
|
||||||
@ -34,19 +26,11 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<h1>{{.Organization}}</h1>
|
{{template "header" .}}
|
||||||
<label for="navtoggle">☰</label>
|
|
||||||
<input type="checkbox" id="navtoggle">
|
|
||||||
<nav id="navigation">
|
|
||||||
<a href="index.html">Instances</a>
|
|
||||||
<a href="account.html">Account</a>
|
|
||||||
<a href="settings.html" aria-current="page">Settings</a>
|
|
||||||
<a href="login.html">Logout</a>
|
|
||||||
</nav>
|
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<h2>Settings</h2>
|
<h2>Settings</h2>
|
||||||
<form id = "settings">
|
<form id="settings">
|
||||||
<section class="w3-card w3-padding">
|
<section class="w3-card w3-padding">
|
||||||
<h3>Synchronization Settings</h3>
|
<h3>Synchronization Settings</h3>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { getSyncSettings, requestAPI } from "./utils.js";
|
import { getSyncSettings, requestAPI } from "./utils.js";
|
||||||
import { API } from "../vars.js";
|
|
||||||
|
|
||||||
export async function setupClientSync (callback) {
|
export async function setupClientSync (callback) {
|
||||||
const { scheme, rate } = getSyncSettings();
|
const { scheme, rate } = getSyncSettings();
|
||||||
@ -22,7 +21,7 @@ export async function setupClientSync (callback) {
|
|||||||
}
|
}
|
||||||
else if (scheme === "interrupt") {
|
else if (scheme === "interrupt") {
|
||||||
callback();
|
callback();
|
||||||
const socket = new WebSocket(`wss://${API.replace("https://", "")}/sync/interrupt`);
|
const socket = new WebSocket(`wss://${window.API.replace("https://", "")}/sync/interrupt`);
|
||||||
socket.addEventListener("open", (event) => {
|
socket.addEventListener("open", (event) => {
|
||||||
socket.send(`rate ${rate}`);
|
socket.send(`rate ${rate}`);
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,6 @@ import { requestPVE, requestAPI, goToPage, setAppearance, getSearchSettings, goT
|
|||||||
import { alert, dialog } from "./dialog.js";
|
import { alert, dialog } from "./dialog.js";
|
||||||
import { setupClientSync } from "./clientsync.js";
|
import { setupClientSync } from "./clientsync.js";
|
||||||
import wfaInit from "../modules/wfa.js";
|
import wfaInit from "../modules/wfa.js";
|
||||||
import { PVE } from "../vars.js";
|
|
||||||
|
|
||||||
class InstanceCard extends HTMLElement {
|
class InstanceCard extends HTMLElement {
|
||||||
constructor () {
|
constructor () {
|
||||||
@ -220,7 +219,7 @@ class InstanceCard extends HTMLElement {
|
|||||||
if (!this.actionLock && this.status === "running") {
|
if (!this.actionLock && this.status === "running") {
|
||||||
const data = { console: `${this.type === "qemu" ? "kvm" : "lxc"}`, vmid: this.vmid, vmname: this.name, node: this.node.name, resize: "off", cmd: "" };
|
const data = { console: `${this.type === "qemu" ? "kvm" : "lxc"}`, vmid: this.vmid, vmname: this.name, node: this.node.name, resize: "off", cmd: "" };
|
||||||
data[`${this.type === "qemu" ? "novnc" : "xtermjs"}`] = 1;
|
data[`${this.type === "qemu" ? "novnc" : "xtermjs"}`] = 1;
|
||||||
goToURL(PVE, data, true);
|
goToURL(window.PVE, data, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { API } from "../vars.js";
|
|
||||||
|
|
||||||
export const resourcesConfig = {
|
export const resourcesConfig = {
|
||||||
cpu: {
|
cpu: {
|
||||||
name: "CPU Type",
|
name: "CPU Type",
|
||||||
@ -224,7 +222,7 @@ export async function requestPVE (path, method, body = null) {
|
|||||||
content.headers.CSRFPreventionToken = getCookie("CSRFPreventionToken");
|
content.headers.CSRFPreventionToken = getCookie("CSRFPreventionToken");
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await request(`${API}/proxmox${path}`, content);
|
const response = await request(`${window.API}/proxmox${path}`, content);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +243,7 @@ export async function requestAPI (path, method, body = null) {
|
|||||||
content.body = prms.toString();
|
content.body = prms.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await request(`${API}${path}`, content);
|
const response = await request(`${window.API}${path}`, content);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
export const API = "https://paas.mydomain.example/api"; // the proxmox-aas api
|
|
||||||
export const PVE = "https://pve.mydomain.example"; // the proxmox api
|
|
||||||
export const organization = "mydomain"; // org name used in page title and nav bar
|
|
31
web/templates/base.html
Normal file
31
web/templates/base.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{{define "head"}}
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{{.Organization}} - dashboard</title>
|
||||||
|
<link rel="icon" href="images/favicon.svg" sizes="any" type="image/svg+xml">
|
||||||
|
<link rel="stylesheet" href="modules/w3.css">
|
||||||
|
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
|
||||||
|
<script>
|
||||||
|
window.PVE = "{{.PVE}}";
|
||||||
|
window.API = "{{.API}}";
|
||||||
|
</script>
|
||||||
|
<link rel="stylesheet" href="css/style.css">
|
||||||
|
<link rel="stylesheet" href="css/nav.css">
|
||||||
|
<link rel="stylesheet" href="css/form.css">
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{define "header"}}
|
||||||
|
<h1>{{.Organization}}</h1>
|
||||||
|
<label for="navtoggle">☰</label>
|
||||||
|
<input type="checkbox" id="navtoggle">
|
||||||
|
<nav id="navigation">
|
||||||
|
{{if eq .Page "login"}}
|
||||||
|
<a href="login.html" aria-current="page">Login</a>
|
||||||
|
{{else}}
|
||||||
|
<a href="index.html" {{if eq .Page "index"}} aria-current="page" {{end}}>Instances</a>
|
||||||
|
<a href="account.html" {{if eq .Page "account"}} aria-current="page" {{end}}>Account</a>
|
||||||
|
<a href="settings.html" {{if eq .Page "settings"}} aria-current="page" {{end}}>Settings</a>
|
||||||
|
<a href="login.html">Logout</a>
|
||||||
|
{{end}}
|
||||||
|
</nav>
|
||||||
|
{{end}}
|
Loading…
x
Reference in New Issue
Block a user