Add disk usage statistics to index & API.

Update README.md

Add disk usage statistics to index & API.
This commit is contained in:
Gabriel Simmer 2019-04-01 22:43:57 -07:00
parent a2a1e0e573
commit 88e0d6c7b1
No known key found for this signature in database
GPG key ID: 0394452F45EF2817
8 changed files with 128 additions and 18 deletions

View file

@ -21,8 +21,10 @@ then navigate to `localhost:3000`
initially the heavy lifting was done by the server, but the need for a better frontend was clear.
full documentation coming soon once actual functionality has been nailed down.
## credits
svg icons via https://iconsvg.xyz
raspberry pi svg via https://www.vectorlogo.zone/logos/raspberrypi/index.html
raspberry pi svg via https://www.vectorlogo.zone/logos/raspberrypi/index.html

View file

@ -3,14 +3,17 @@
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta content="utf-8" http-equiv="encoding">
<title>Home | PiNas</title>
<title>Home | GoNAS</title>
<link rel="stylesheet" href="/assets/styles.css">
</head>
<body>
<main>
<div>
<img src="/assets/svgs/pi.svg" alt="">
<h1 style="display: inline-block">PiNas</h1>
<h1 style="display: inline-block">GoNAS</h1>
<p>Hot Storage Usage (<span id="hotUsagePercent"></span>%)</p>
<progress max="100" id="hotUsage"></progress>
<p>Cold Storage Usage (<span id="coldUsagePercent"></span>%)</p>
<progress max="100" id="coldUsage"></progress>
</div>
<div class="content index">
<a href="/files/">
@ -19,5 +22,31 @@
<img src="/assets/svgs/coldfiles.svg" alt="">Cold Files</a>
</div>
</main>
<script>
const $ = selector => document.querySelector(selector);
const init = event => {
getUsages();
}
const getUsages = () => {
fetch('/api/diskusage')
.then(function (response) {
return response.json();
})
.then(function (jsonResult) {
console.log(jsonResult);
let hot = (jsonResult.HotStorage.Free) / (jsonResult.HotStorage.Total) * 100;
let cold = (jsonResult.ColdStorage.Free) / (jsonResult.ColdStorage.Total) * 100;
// Flip values to reflect % used rather than % free.
$("#hotUsage").value = 100 - hot;
$("#hotUsagePercent").innerText = Math.floor(100 - hot);
$("#coldUsage").value = 100 - cold;
$("#coldUsagePercent").innerText = Math.floor(100 - cold);
});
}
window.addEventListener('load', init);
</script>
</body>
</html>

View file

@ -3,7 +3,7 @@
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta content="utf-8" http-equiv="encoding">
<title>| PiNas</title>
<title>| GoNAS</title>
<link rel="stylesheet" href="/assets/styles.css">
<script type="text/javascript" src="/assets/app.js"></script>
</head>
@ -16,7 +16,7 @@
<a href="/" class="back-button">
<img src="/assets/svgs/back.svg" alt="" data-dismiss-context="false">
</a>
<h1 style="display: inline-block">PiNas</h1>
<h1 style="display: inline-block">GoNAS</h1>
</header>
<main>
<div>
@ -31,7 +31,7 @@
<div class="content" id="filelist">
<form action="/upload" method="post" enctype="multipart/form-data">
<input id="path" type="value" name="path">
<input type="file" data-multiple-caption="{count} files selected" multiple name="file">
<input type="file" multiple name="file">
<input type="submit" value="Upload">
</form>
<p class="directory"><a href="#" id="previous-dir">..</a></p>

View file

@ -1,4 +1,4 @@
const $ = element => document.getElementById(element);
const $ = selector => document.querySelector(selector);
const init = event => {
var path = window.location.pathname;
@ -12,9 +12,9 @@ const init = event => {
buildList(json);
});
$("path-header").innerText = path;
document.querySelector("body").addEventListener('contextmenu', function(ev) {
$("#path-header").innerText = path;
$("#path").value = path;
document.querySelector("body").addEventListener('contextmenu', function (ev) {
if (ev.target.localName == "a") {
ev.preventDefault();
@ -28,13 +28,13 @@ const init = event => {
return false;
}, false);
document.querySelector("body").addEventListener('click', function(ev) {
$("body").addEventListener('click', function (ev) {
let shouldDismiss = ev.target.dataset.dismissContext == undefined && ev.target.parentElement.classList.contains("context-actions") == false && ev.target.localName != 'a';
if (ev.which == 1 && shouldDismiss) {
ev.preventDefault();
var d = document.getElementById('context');
var d = $('#context');
d.classList.add("hidden");
return false;
}
@ -58,20 +58,19 @@ const buildList = data => {
if (data.Files[i].IsDirectory == true) {
fileItem.classList.add("directory");
fileLink.href = "/" + data.Prefix + "/" + data.Path + "/" + data.Files[i].Name;
}
else {
} else {
fileItem.classList.add("file");
fileLink.href = "/" + data.SinglePrefix + "/" + data.Path + "/" + data.Files[i].Name;
}
fileLink.innerText = data.Files[i].Name;
fileItem.appendChild(fileLink);
document.getElementById("filelist").appendChild(fileItem);
$("#filelist").appendChild(fileItem);
}
}
const upload = (file, path) => {
var formData = new FormData();
var formData = new FormData();
formData.append("path", path);
formData.append("file", file);
fetch('/upload', { // Your POST endpoint

View file

@ -96,4 +96,8 @@ a.back-button {
.context-actions li {
border-bottom: 1px solid black;
cursor: pointer;
}
progress[value] {
height: 20px;
}

View file

@ -44,7 +44,7 @@ func Listing(tier string) common.Handler {
panic(err)
}
var config Config;
var config Config
err = json.Unmarshal(d, &config)
if err != nil {
panic(err)

View file

@ -7,6 +7,7 @@ import (
"github.com/gmemstr/nas/common"
"github.com/gmemstr/nas/files"
"github.com/gmemstr/nas/system"
"github.com/gorilla/mux"
)
@ -61,6 +62,9 @@ func Init() *mux.Router {
fileList(),
)).Methods("GET")
r.Handle("/api/diskusage", Handle(
system.DiskUsages(),
)).Methods("GET")
r.Handle("/api/files/", Handle(
files.Listing("hot"),

72
system/system.go Normal file
View file

@ -0,0 +1,72 @@
package system
import (
"encoding/json"
"github.com/gmemstr/nas/common"
"io/ioutil"
"net/http"
"syscall"
)
type Config struct {
ColdStorage string
HotStorage string
}
type UsageStat struct {
Available int64
Free int64
Total int64
}
type UsageStats struct {
ColdStorage UsageStat
HotStorage UsageStat
}
func DiskUsages() common.Handler {
return func(rc *common.RouterContext, w http.ResponseWriter, r *http.Request) *common.HTTPError {
var statHot syscall.Statfs_t
var statCold syscall.Statfs_t
d, err := ioutil.ReadFile("assets/config/config.json")
if err != nil {
panic(err)
}
var config Config
err = json.Unmarshal(d, &config)
if err != nil {
panic(err)
}
// Default to hot storage
storage := config.HotStorage
err = syscall.Statfs(storage, &statHot)
if err != nil {
panic(err)
}
hotStats := UsageStat{
Free: statHot.Bsize * int64(statHot.Bfree),
Total: statHot.Bsize * int64(statHot.Blocks),
}
storage = config.ColdStorage
err = syscall.Statfs(storage, &statCold)
if err != nil {
panic(err)
}
coldStats := UsageStat{
Free: statCold.Bsize * int64(statCold.Bfree),
Total: statCold.Bsize * int64(statCold.Blocks),
}
usages := UsageStats{
HotStorage: hotStats,
ColdStorage: coldStats,
}
// Available blocks * size per block = available space in bytes
resultJson, err := json.Marshal(usages)
w.Write(resultJson)
return nil
}
}