1 Commits

Author SHA1 Message Date
alu 196cf900cc update readme 2026-07-06 23:28:36 +00:00
10 changed files with 85 additions and 91 deletions
+5 -10
View File
@@ -1,25 +1,20 @@
.PHONY: build test clean wfa-js .PHONY: build test clean wfa-js
build: clean build-wfa-js build: clean wfa-js
@echo "======================== Building Binary =======================" @echo "======================== Building Binary ======================="
mkdir -p dist mkdir -p dist
# resolve symbolic links in web by copying it into dist/web/ # resolve symbolic links in web by copying it into dist/web/
cp -rL web/ dist/web/ cp -rL web/ dist/web/
CGO_ENABLED=0 go build -tags release -ldflags="-s -w" -v -o dist/ . CGO_ENABLED=0 go build -tags release -ldflags="-s -w" -v -o dist/ .
build-wfa-js: wfa-js:
$(MAKE) -C WFA-JS $(MAKE) -C WFA-JS
cp -f WFA-JS/dist/* web/modules cp -f WFA-JS/dist/* web/modules
test: clean test-wfa-js test: clean
go run .
test-wfa-js: clean:
$(MAKE) test -C WFA-JS
clean: clean-wfa-js
@echo "======================== Cleaning Project ======================" @echo "======================== Cleaning Project ======================"
go clean go clean
rm -rf dist/* rm -rf dist/*
clean-wfa-js:
$(MAKE) clean -C WFA-JS
+5 -5
View File
@@ -36,11 +36,11 @@ We will assume different hosts for each component which are accessible by unique
1. Initialize any host, which will be the `ProxmoxAAS-Dashboard` component host 1. Initialize any host, which will be the `ProxmoxAAS-Dashboard` component host
2. Download `proxmoxaas-dashboard` binary and `template.config.json` file from [releases](https://git.tronnet.net/tronnet/ProxmoxAAS-LDAP/releases) 2. Download `proxmoxaas-dashboard` binary and `template.config.json` file from [releases](https://git.tronnet.net/tronnet/ProxmoxAAS-LDAP/releases)
Rename `template.config.json` to `config.json` and modify: Rename `template.config.json` to `config.json` and modify:
- `listenPort`: port for PAAS-Dashboard to bind and listen on - listenPort: port for PAAS-Dashboard to bind and listen on
- `organization`: name of your org which is displayed on the top left corner - organization: name of your org which is displayed on the top left corner
- `dashurl`: url for the dashboard, ie. `https://paas.domain.net` - dashurl: url for the dashboard, ie. `https://paas.domain.net`
- `apiurl`: url for PAAS-API, ie. `https://paas.domain.net/api` - apiurl: url for PAAS-API, ie. `https://paas.domain.net/api`
- `pveurl`: url for the Proxmox endpoint, ie. `https://pve.domain.net` - pveurl: url for the Proxmox endpoint, ie. `https://pve.domain.net`
3. Execute the binary or additionally download `proxmoxaas-dashboard.service` from [releases](https://git.tronnet.net/tronnet/ProxmoxAAS-LDAP/releases) to run using systemd 3. Execute the binary or additionally download `proxmoxaas-dashboard.service` from [releases](https://git.tronnet.net/tronnet/ProxmoxAAS-LDAP/releases) to run using systemd
After this step, the Dashboard should be available on the `ProxmoxAAS-Dashboard` host at the configured `listenPort` After this step, the Dashboard should be available on the `ProxmoxAAS-Dashboard` host at the configured `listenPort`
+1 -1
View File
@@ -1,6 +1,6 @@
module proxmoxaas-dashboard module proxmoxaas-dashboard
go 1.26.5 go 1.26.4
require ( require (
github.com/gerow/go-color v0.0.0-20140219113758-125d37f527f1 github.com/gerow/go-color v0.0.0-20140219113758-125d37f527f1
+2 -1
View File
@@ -4,7 +4,8 @@
"description": "Front-end for ProxmoxAAS", "description": "Front-end for ProxmoxAAS",
"type": "module", "type": "module",
"scripts": { "scripts": {
"lint": "html-validate --config dev_config/.htmlvalidate.json web/html/*; stylelint --config dev_config/.stylelintrc.json --formatter verbose --fix web/css/*.css; DEBUG=eslint:cli-engine eslint --config dev_config/eslint.config.mjs --fix web/scripts/" "lint": "html-validate --config dev_config/.htmlvalidate.json web/html/*; stylelint --config dev_config/.stylelintrc.json --formatter verbose --fix web/css/*.css; DEBUG=eslint:cli-engine eslint --config dev_config/eslint.config.mjs --fix web/scripts/",
"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/eslintrc": "^3.3.5", "@eslint/eslintrc": "^3.3.5",
+1 -7
View File
@@ -20,12 +20,6 @@
p:last-child { p:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
#save.disabled {
display: none;
}
#save.enabled {
display: unset;
}
</style> </style>
</head> </head>
<body> <body>
@@ -76,7 +70,7 @@
</fieldset> </fieldset>
</section> </section>
<div class="w3-container w3-center" id="form-actions"> <div class="w3-container w3-center" id="form-actions">
<button class="w3-button w3-margin disabled" id="save" type="submit">SAVE</button> <button class="w3-button w3-margin" id="save" type="submit">SAVE</button>
</div> </div>
</form> </form>
</main> </main>
+2 -3
View File
@@ -1,8 +1,7 @@
import { getSetting, requestAPI } from "./utils.js"; import { getSyncSettings, requestAPI } from "./utils.js";
export async function setupClientSync (callback) { export async function setupClientSync (callback) {
const scheme = getSetting("sync-scheme"); const { scheme, rate } = getSyncSettings();
const rate = getSetting("sync-rate");
if (scheme === "never") { if (scheme === "never") {
return; return;
} }
+2 -2
View File
@@ -1,4 +1,4 @@
import { requestPVE, requestAPI, setAppearance, getSetting, requestDash, setIconSrc, setIconAlt } from "./utils.js"; import { requestPVE, requestAPI, setAppearance, getSearchSettings, requestDash, setIconSrc, setIconAlt } from "./utils.js";
import { alert, dialog, error } from "./dialog.js"; import { alert, dialog, error } 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";
@@ -243,7 +243,7 @@ function initInstances () {
} }
function sortInstances () { function sortInstances () {
const searchCriteria = getSetting("search-criteria"); const searchCriteria = getSearchSettings();
const searchQuery = document.querySelector("#search").value || null; const searchQuery = document.querySelector("#search").value || null;
let criteria; let criteria;
if (!searchQuery) { if (!searchQuery) {
+19 -45
View File
@@ -1,62 +1,36 @@
import { setAppearance, getSetting, setSetting } from "./utils.js"; import { setAppearance, getSyncSettings, getSearchSettings, getThemeSettings, setSyncSettings, setSearchSettings, setThemeSettings } from "./utils.js";
window.addEventListener("DOMContentLoaded", init); window.addEventListener("DOMContentLoaded", init);
function init () { function init () {
setAppearance(); setAppearance();
document.querySelectorAll("[id^=sync-]").forEach((v) => { const { scheme, rate } = getSyncSettings();
v.addEventListener("change", handleSettingsChange); if (scheme) {
}); document.querySelector(`#sync-${scheme}`).checked = true;
document.querySelector(`#sync-${getSetting("sync-scheme")}`).checked = true; }
document.querySelector("#sync-rate").value = getSetting("sync-rate"); if (rate) {
document.querySelector("#sync-rate").value = rate;
}
document.querySelectorAll("[id^=search-]").forEach((v) => { const search = getSearchSettings();
v.addEventListener("change", handleSettingsChange); if (search) {
}); document.querySelector(`#search-${search}`).checked = true;
document.querySelector(`#search-${getSetting("search-criteria")}`).checked = true; }
document.querySelector("#appearance-theme").addEventListener("change", handleSettingsChange); const theme = getThemeSettings();
document.querySelector("#appearance-theme").value = getSetting("appearance-theme"); if (theme) {
document.querySelector("#appearance-theme").value = theme;
}
document.querySelector("#settings").addEventListener("submit", handleSaveSettings, false); document.querySelector("#settings").addEventListener("submit", handleSaveSettings, false);
} }
function handleSettingsChange (event) {
event.preventDefault();
const form = new FormData(document.querySelector("#settings"));
const saveBtn = document.querySelector("#save");
if (getSetting("sync-scheme") !== form.get("sync-scheme")) {
saveBtn.classList.remove("disabled");
saveBtn.classList.add("enabled");
}
else if (getSetting("sync-rate") !== Number(form.get("sync-rate"))) {
saveBtn.classList.remove("disabled");
saveBtn.classList.add("enabled");
}
else if (getSetting("search-criteria") !== form.get("search-criteria")) {
saveBtn.classList.remove("disabled");
saveBtn.classList.add("enabled");
}
else if (getSetting("appearance-theme") !== form.get("appearance-theme")) {
saveBtn.classList.remove("disabled");
saveBtn.classList.add("enabled");
}
else {
saveBtn.classList.remove("enabled");
saveBtn.classList.add("disabled");
}
}
function handleSaveSettings (event) { function handleSaveSettings (event) {
event.preventDefault(); event.preventDefault();
const form = new FormData(document.querySelector("#settings")); const form = new FormData(document.querySelector("#settings"));
const saveBtn = document.querySelector("#save"); setSyncSettings(form.get("sync-scheme"), form.get("sync-rate"));
setSetting("sync-scheme", form.get("sync-scheme")); setSearchSettings(form.get("search-criteria"));
setSetting("sync-rate", Number(form.get("sync-rate"))); setThemeSettings(form.get("appearance-theme"));
setSetting("search-criteria", form.get("search-criteria"));
setSetting("appearance-theme", form.get("appearance-theme"));
saveBtn.classList.remove("enabled");
saveBtn.classList.add("disabled");
init(); init();
} }
+47 -16
View File
@@ -125,30 +125,60 @@ export function getURIData () {
return Object.fromEntries(url.searchParams); return Object.fromEntries(url.searchParams);
} }
const settings = { const settingsDefault = {
"sync-scheme": {"type": String, "default": "always"}, "sync-scheme": "always",
"sync-rate": {"type": Number, "default": 5}, "sync-rate": 5,
"search-criteria": {"type": String, "default": "fuzzy"}, "search-criteria": "fuzzy",
"appearance-theme": {"type": String, "default": "auto"} "appearance-theme": "auto"
}; };
export function getSetting (key) { export function getSyncSettings () {
const meta = settings[key]; let scheme = localStorage.getItem("sync-scheme");
let value = localStorage.getItem(key); let rate = Number(localStorage.getItem("sync-rate"));
if (value === null || meta === null) { if (!scheme) {
value = meta.default; scheme = settingsDefault["sync-scheme"];
localStorage.setItem(key, meta.default); localStorage.setItem("sync-scheme", scheme);
} }
if (!rate) {
return meta.type(value); rate = settingsDefault["sync-rate"];
localStorage.setItem("sync-rate", rate);
}
return { scheme, rate };
} }
export function setSetting (key, value) { export function getSearchSettings () {
localStorage.setItem(key, value); let searchCriteria = localStorage.getItem("search-criteria");
if (!searchCriteria) {
searchCriteria = settingsDefault["search-criteria"];
localStorage.setItem("search-criteria", searchCriteria);
}
return searchCriteria;
}
export function getThemeSettings () {
let theme = localStorage.getItem("appearance-theme");
if (!theme) {
theme = settingsDefault["appearance-theme"];
localStorage.setItem("appearance-theme", theme);
}
return theme;
}
export function setSyncSettings (scheme, rate) {
localStorage.setItem("sync-scheme", scheme);
localStorage.setItem("sync-rate", rate);
}
export function setSearchSettings (criteria) {
localStorage.setItem("search-criteria", criteria);
}
export function setThemeSettings (theme) {
localStorage.setItem("appearance-theme", theme);
} }
export function setAppearance () { export function setAppearance () {
const theme = getSetting("appearance-theme"); const theme = getThemeSettings();
if (theme === "auto") { if (theme === "auto") {
document.querySelector(":root").classList.remove("dark-theme", "light-theme"); document.querySelector(":root").classList.remove("dark-theme", "light-theme");
} }
@@ -162,6 +192,7 @@ export function setAppearance () {
} }
} }
// assumes href is path to svg, and id to grab is #symb
export function setIconSrc (icon, path) { export function setIconSrc (icon, path) {
icon.setAttribute("src", path); icon.setAttribute("src", path);
} }