Merge pull request 'Separate network settings and status templates' (#30) from cleanup_network_settings into main

Reviewed-on: PeachCloud/peach-workspace#30
This commit is contained in:
glyph 2021-11-18 09:49:16 +00:00
commit c3917d0f0f
17 changed files with 424 additions and 239 deletions

View File

@ -41,6 +41,7 @@ use crate::routes::catchers::*;
use crate::routes::index::*;
use crate::routes::scuttlebutt::*;
use crate::routes::status::device::*;
use crate::routes::status::network::*;
use crate::routes::status::ping::*;
use crate::routes::settings::admin::*;
@ -58,7 +59,6 @@ fn init_rocket() -> Rocket<Build> {
.mount(
"/",
routes![
device_status,
help,
home,
login,
@ -70,6 +70,8 @@ fn init_rocket() -> Rocket<Build> {
settings_menu,
],
)
// STATUS HTML ROUTES
.mount("/status", routes![device_status, network_status])
// ADMIN SETTINGS HTML ROUTES
.mount(
"/settings/admin",

View File

@ -102,7 +102,7 @@ pub fn wifi_password(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticat
context.flash_msg = Some(flash.message().to_string());
};
// template_dir is set in Rocket.toml
Template::render("settings/network/network_modify", &context)
Template::render("settings/network/modify_ap", &context)
}
#[post("/wifi/modify", data = "<wifi>")]
@ -288,7 +288,7 @@ pub fn network_home(flash: Option<FlashMessage>, _auth: Authenticated) -> Templa
context.flash_msg = Some(flash.message().to_string());
};
// template_dir is set in Rocket.toml
Template::render("settings/network/network_card", &context)
Template::render("settings/network/menu", &context)
}
// HELPERS AND ROUTES FOR /settings/network/ap/activate
@ -391,7 +391,7 @@ pub fn wifi_list(flash: Option<FlashMessage>, _auth: Authenticated) -> Template
context.flash_msg = Some(flash.message().to_string());
};
// template_dir is set in Rocket.toml
Template::render("settings/network/network_list", &context)
Template::render("settings/network/list_aps", &context)
}
// HELPERS AND ROUTES FOR /settings/network/wifi<ssid>
@ -557,7 +557,7 @@ pub fn network_detail(ssid: &str, flash: Option<FlashMessage>, _auth: Authentica
context.flash_msg = Some(flash.message().to_string());
};
// template_dir is set in Rocket.toml
Template::render("settings/network/network_detail", &context)
Template::render("settings/network/ap_details", &context)
}
// HELPERS AND ROUTES FOR /settings/network/wifi/activate
@ -590,7 +590,7 @@ pub fn add_wifi(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
context.flash_msg = Some(flash.message().to_string());
};
// template_dir is set in Rocket.toml
Template::render("settings/network/network_add", &context)
Template::render("settings/network/add_ap", &context)
}
// used in /settings/network/wifi/add?<ssid>
@ -628,7 +628,7 @@ pub fn add_ssid(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticated) -
context.flash_msg = Some(flash.message().to_string());
};
// template_dir is set in Rocket.toml
Template::render("settings/network/network_add", &context)
Template::render("settings/network/add_ap", &context)
}
#[post("/wifi/add", data = "<wifi>")]
@ -646,7 +646,7 @@ pub fn add_credentials(wifi: Form<WiFi>, _auth: Authenticated) -> Template {
Some("Network credentials already exist for this access point".to_string());
context.title = Some("Add WiFi Network".to_string());
// return early from handler with "creds already exist" message
return Template::render("settings/network/network_add", &context);
return Template::render("settings/network/add_ap", &context);
};
// if credentials not found, generate and write wifi config to wpa_supplicant
@ -663,7 +663,7 @@ pub fn add_credentials(wifi: Form<WiFi>, _auth: Authenticated) -> Template {
context.flash_name = Some("success".to_string());
context.flash_msg = Some("Added WiFi credentials".to_string());
context.title = Some("Add WiFi Network".to_string());
Template::render("settings/network/network_add", &context)
Template::render("settings/network/add_ap", &context)
}
Err(_) => {
debug!("Failed to add WiFi credentials.");
@ -672,7 +672,7 @@ pub fn add_credentials(wifi: Form<WiFi>, _auth: Authenticated) -> Template {
context.flash_name = Some("error".to_string());
context.flash_msg = Some("Failed to add WiFi credentials".to_string());
context.title = Some("Add WiFi Network".to_string());
Template::render("settings/network/network_add", &context)
Template::render("settings/network/add_ap", &context)
}
}
}
@ -738,7 +738,7 @@ pub fn wifi_usage(flash: Option<FlashMessage>, _auth: Authenticated) -> Template
context.flash_msg = Some(flash.message().to_string());
};
// template_dir is set in Rocket.toml
Template::render("settings/network/network_usage", &context)
Template::render("settings/network/data_usage_limits", &context)
}
#[post("/wifi/usage", data = "<thresholds>")]

View File

@ -150,7 +150,7 @@ impl StatusContext {
}
}
#[get("/status")]
#[get("/")]
pub fn device_status(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// assign context through context_builder call
let mut context = StatusContext::build();
@ -163,7 +163,7 @@ pub fn device_status(flash: Option<FlashMessage>, _auth: Authenticated) -> Templ
context.flash_msg = Some(flash.message().to_string());
};
// template_dir is set in Rocket.toml
Template::render("device", &context)
Template::render("status/device", &context)
}
// HELPERS AND ROUTES FOR /power/reboot

View File

@ -1,2 +1,3 @@
pub mod device;
pub mod network;
pub mod ping;

View File

@ -0,0 +1,164 @@
use rocket::{get, request::FlashMessage};
use rocket_dyn_templates::Template;
use serde::Serialize;
use peach_lib::network_client;
use peach_lib::stats_client::Traffic;
use crate::routes::authentication::Authenticated;
// HELPERS AND ROUTES FOR /status/network
#[derive(Debug, Serialize)]
pub struct NetworkContext {
pub ap_ip: String,
pub ap_ssid: String,
pub ap_state: String,
pub ap_traffic: Option<Traffic>,
pub wlan_ip: String,
pub wlan_rssi: Option<String>,
pub wlan_ssid: String,
pub wlan_state: String,
pub wlan_status: String,
pub wlan_traffic: Option<Traffic>,
pub flash_name: Option<String>,
pub flash_msg: Option<String>,
// page title for header in navbar
pub title: Option<String>,
// url for back-arrow link
pub back: Option<String>,
}
impl NetworkContext {
pub fn build() -> NetworkContext {
let ap_ip = match network_client::ip("ap0") {
Ok(ip) => ip,
Err(_) => "x.x.x.x".to_string(),
};
let ap_ssid = match network_client::ssid("ap0") {
Ok(ssid) => ssid,
Err(_) => "Not currently activated".to_string(),
};
let ap_state = match network_client::state("ap0") {
Ok(state) => state,
Err(_) => "Interface unavailable".to_string(),
};
let ap_traffic = match network_client::traffic("ap0") {
Ok(traffic) => {
let mut t = traffic;
// modify traffic values & assign measurement unit
// based on received and transmitted values
// if received > 999 MB, convert it to GB
if t.received > 1_047_527_424 {
t.received /= 1_073_741_824;
t.rx_unit = Some("GB".to_string());
} else if t.received > 0 {
// otherwise, convert it to MB
t.received = (t.received / 1024) / 1024;
t.rx_unit = Some("MB".to_string());
} else {
t.received = 0;
t.rx_unit = Some("MB".to_string());
}
if t.transmitted > 1_047_527_424 {
t.transmitted /= 1_073_741_824;
t.tx_unit = Some("GB".to_string());
} else if t.transmitted > 0 {
t.transmitted = (t.transmitted / 1024) / 1024;
t.tx_unit = Some("MB".to_string());
} else {
t.transmitted = 0;
t.tx_unit = Some("MB".to_string());
}
Some(t)
}
Err(_) => None,
};
let wlan_ip = match network_client::ip("wlan0") {
Ok(ip) => ip,
Err(_) => "x.x.x.x".to_string(),
};
let wlan_rssi = match network_client::rssi_percent("wlan0") {
Ok(rssi) => Some(rssi),
Err(_) => None,
};
let wlan_ssid = match network_client::ssid("wlan0") {
Ok(ssid) => ssid,
Err(_) => "Not connected".to_string(),
};
let wlan_state = match network_client::state("wlan0") {
Ok(state) => state,
Err(_) => "Interface unavailable".to_string(),
};
let wlan_status = match network_client::status("wlan0") {
Ok(status) => status,
Err(_) => "Interface unavailable".to_string(),
};
let wlan_traffic = match network_client::traffic("wlan0") {
Ok(traffic) => {
let mut t = traffic;
// modify traffic values & assign measurement unit
// based on received and transmitted values
// if received > 999 MB, convert it to GB
if t.received > 1_047_527_424 {
t.received /= 1_073_741_824;
t.rx_unit = Some("GB".to_string());
} else if t.received > 0 {
// otherwise, convert it to MB
t.received = (t.received / 1024) / 1024;
t.rx_unit = Some("MB".to_string());
} else {
t.received = 0;
t.rx_unit = Some("MB".to_string());
}
if t.transmitted > 1_047_527_424 {
t.transmitted /= 1_073_741_824;
t.tx_unit = Some("GB".to_string());
} else if t.transmitted > 0 {
t.transmitted = (t.transmitted / 1024) / 1024;
t.tx_unit = Some("MB".to_string());
} else {
t.transmitted = 0;
t.tx_unit = Some("MB".to_string());
}
Some(t)
}
Err(_) => None,
};
NetworkContext {
ap_ip,
ap_ssid,
ap_state,
ap_traffic,
wlan_ip,
wlan_rssi,
wlan_ssid,
wlan_state,
wlan_status,
wlan_traffic,
flash_name: None,
flash_msg: None,
title: None,
back: None,
}
}
}
#[get("/network")]
pub fn network_status(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// assign context through context_builder call
let mut context = NetworkContext::build();
context.back = Some("/status".to_string());
context.title = Some("Network Status".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string());
};
// template_dir is set in Rocket.toml
Template::render("status/network", &context)
}

View File

@ -53,25 +53,17 @@ fn index_html() {
}
#[test]
fn network_card_html() {
fn network_settings_menu_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
let response = client.get("/settings/network").dispatch();
assert_eq!(response.status(), Status::Ok);
assert_eq!(response.content_type(), Some(ContentType::HTML));
let body = response.into_string().unwrap();
assert!(body.contains("MODE"));
assert!(body.contains("SSID"));
assert!(body.contains("IP"));
assert!(body.contains("Add WiFi Network"));
assert!(body.contains("Deploy Access Point"));
assert!(body.contains("List WiFi Networks"));
assert!(body.contains("SIGNAL"));
assert!(body.contains("DOWNLOAD"));
assert!(body.contains("UPLOAD"));
assert!(body.contains("Network Configuration"));
}
#[test]
fn network_list_html() {
fn list_aps_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
let response = client.get("/settings/network/wifi").dispatch();
assert_eq!(response.status(), Status::Ok);
@ -83,7 +75,7 @@ fn network_list_html() {
// TODO: needs further testing once template has been refactored
#[test]
fn network_detail_html() {
fn ap_details_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
let response = client.get("/settings/network/wifi?ssid=Home").dispatch();
assert_eq!(response.status(), Status::Ok);
@ -93,7 +85,7 @@ fn network_detail_html() {
}
#[test]
fn network_add_html() {
fn add_ap_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
let response = client.get("/settings/network/wifi/add").dispatch();
assert_eq!(response.status(), Status::Ok);
@ -107,7 +99,7 @@ fn network_add_html() {
}
#[test]
fn network_add_ssid_html() {
fn add_ap_ssid_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
let response = client
.get("/settings/network/wifi/add?ssid=Home")
@ -281,7 +273,7 @@ fn power_html() {
}
#[test]
fn network_usage_html() {
fn data_usage_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
let response = client.get("/settings/network/wifi/usage").dispatch();
assert_eq!(response.status(), Status::Ok);

View File

@ -215,14 +215,14 @@ body {
border: var(--border-width-1) solid;
border-radius: var(--border-radius-3);
background-color: var(--light-gray);
margin-top: 1rem;
margin-bottom: 1rem;
/* margin-top: 1rem; */
/* margin-bottom: 1rem; */
}
.capsule-profile {
.capsule-container {
margin-left: 2rem;
margin-right: 2rem;
padding-top: 1.5rem;
padding-top: 1rem;
padding-bottom: 1rem;
}
@ -247,8 +247,9 @@ body {
.card-container {
justify-content: center;
padding-top: 1rem;
padding-bottom: 1rem;
padding: 0.5rem;
/* padding-top: 1rem; */
/* padding-bottom: 1rem; */
}
.form-container {
@ -433,10 +434,16 @@ body {
align-items: center;
justify-content: center;
justify-items: center;
margin-right: 2rem;
margin-left: 2rem;
padding-top: 1.5rem;
padding-bottom: 1rem;
/* margin-right: 2rem; */
/* margin-left: 2rem; */
/* padding-top: 1.5rem; */
}
.two-grid-top-right {
grid-column: 2;
justify-self: right;
padding: 0;
}
.three-grid {
@ -822,7 +829,6 @@ meter::-moz-meter-bar {
*/
.nav-bar {
background-color: var(--moon-gray);
display: flex;
align-items: center;
width: 100%;

View File

@ -1,132 +0,0 @@
{%- extends "nav" -%}
{%- block card -%}
{# ASSIGN VARIABLES #}
{# ---------------- #}
{%- if mem_stats -%}
{% set mem_usage_percent = mem_stats.used / mem_stats.total * 100 | round -%}
{% set mem_used = mem_stats.used / 1024 | round -%}
{% set mem_free = mem_stats.free / 1024 | round -%}
{% set mem_total = mem_stats.total / 1024 | round -%}
{% endif -%}
{% if cpu_stat_percent -%}
{% set cpu_usage_percent = cpu_stat_percent.nice + cpu_stat_percent.system + cpu_stat_percent.user | round -%}
{%- endif -%}
{%- if disk_stats -%}
{%- for disk in disk_stats -%}
{%- set_global disk_usage_percent = disk.used_percentage -%}
{# Calculate free disk space in megabytes #}
{%- set_global disk_free = disk.one_k_blocks_free / 1024 | round -%}
{%- endfor -%}
{%- endif -%}
<!-- DEVICE STATUS VIEW -->
<div class="card center">
<div class="card-container">
{# Display microservice status for network, oled & stats #}
<div class="three-grid" style="padding-top: 1rem;">
<!-- PEACH-NETWORK STATUS STACK -->
<div class="stack capsule{% if network_ping == "ONLINE" %} success-border{% else %} warning-border{% endif %}">
<img id="networkIcon" class="icon{% if network_ping == "OFFLINE" %} icon-inactive{% endif %} icon-medium" alt="Network" title="Network microservice status" src="/icons/wifi.svg">
<div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Networking</label>
<label class="label-small font-near-black">{{ network_ping }}</label>
</div>
</div>
<!-- PEACH-OLED STATUS STACK -->
<div class="stack capsule{% if oled_ping == "ONLINE" %} success-border{% else %} warning-border{% endif %}">
<img id="oledIcon" class="icon{% if oled_ping == "OFFLINE" %} icon-inactive{% endif %} icon-medium" alt="Display" title="OLED display microservice status" src="/icons/lcd.svg">
<div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Display</label>
<label class="label-small font-near-black">{{ oled_ping }}</label>
</div>
</div>
<!-- PEACH-STATS STATUS STACK -->
<div class="stack capsule{% if stats_ping == "ONLINE" %} success-border{% else %} warning-border{% endif %}">
<img id="statsIcon" class="icon{% if stats_ping == "OFFLINE" %} icon-inactive{% endif %} icon-medium" alt="Stats" title="System statistics microservice status" src="/icons/chart.svg">
<div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Statistics</label>
<label class="label-small font-near-black">{{ stats_ping }}</label>
</div>
</div>
</div>
<div class="three-grid" style="padding-bottom: 1rem; margin-top: 0px;">
<!-- DYNDNS STATUS STACK -->
<div class="stack capsule{% if dyndns_is_online %} success-border{% else %} warning-border{% endif %}">
<img id="networkIcon" class="icon{% if dyndns_is_online != true %} icon-inactive{% endif %} icon-medium" alt="Dyndns" title="Dyndns status" src="/icons/dns.png">
<div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Dyn DNS</label>
<label class="label-small font-near-black">{% if dyndns_is_online %} ONLINE {% else %} OFFLINE {% endif %} </label>
</div>
</div>
<!-- CONFIG STATUS STACK -->
<div class="stack capsule{% if config_is_valid %} success-border{% else %} warning-border{% endif %}">
<img id="networkIcon" class="icon{% if config_is_valid != true %} icon-inactive{% endif %} icon-medium" alt="Config" title="Config status" src="/icons/clipboard.png">
<div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Config</label>
<label class="label-small font-near-black">{% if config_is_valid %} LOADED {% else %} INVALID {% endif %} </label>
</div>
</div>
<!-- SBOT STATUS STACK -->
<div class="stack capsule{% if sbot_is_online %} success-border{% else %} warning-border{% endif %}">
<img id="networkIcon" class="icon{% if sbot_is_online != true %} icon-inactive{% endif %} icon-medium" alt="Sbot" title="Sbot status" src="/icons/hermies.svg">
<div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Sbot</label>
<label class="label-small font-near-black">{% if sbot_is_online %} ONLINE {% else %} OFFLINE {% endif %} </label>
</div>
</div>
</div>
{# Display CPU usage meter #}
{%- if cpu_stat_percent -%}
<div class="flex-grid">
<span class="card-text">CPU</span>
<span class="label-small push-right">{{ cpu_usage_percent }}%</span>
</div>
<meter value="{{ cpu_usage_percent }}" min="0" max="100" title="CPU usage">
<div class="meter-gauge">
<span style="width: {{ cpu_usage_percent }}%;">CPU Usage</span>
</div>
</meter>
{%- else -%}
<p class="card-text">CPU usage data unavailable</p>
{% endif -%}
{# Display memory usage meter #}
{%- if mem_stats %}
<div class="flex-grid">
<span class="card-text">Memory</span>
<span class="label-small push-right">{{ mem_usage_percent }}% ({{ mem_free }} MB free)</span>
</div>
<meter value="{{ mem_used }}" min="0" max="{{ mem_total }}" title="Memory usage">
<div class="meter-gauge">
<span style="width: {{ mem_usage_percent }}%;">Memory Usage</span>
</div>
</meter>
{%- else -%}
<p class="card-text">Memory usage data unavailable</p>
{% endif -%}
{# Display disk usage meter #}
{%- if disk_stats %}
<div class="flex-grid">
<span class="card-text">Disk</span>
<span class="label-small push-right">{{ disk_usage_percent }}% ({% if disk_free > 1024 %}{{ disk_free / 1024 | round }} GB{% else %}{{ disk_free }} MB{% endif %} free)</span>
</div>
<meter value="{{ disk_usage_percent }}" min="0" max="100" title="Disk usage">
<div class="meter-gauge">
<span style="width: {{ disk_usage_percent }}%;">Disk Usage</span>
</div>
</meter>
{%- else -%}
<p class="card-text">Disk usage data unavailable</p>
{%- endif %}
{# Display system uptime in minutes #}
{%- if uptime and uptime < 60 %}
<p class="capsule center-text">Uptime: {{ uptime }} minutes</p>
{# Display system uptime in hours & minutes #}
{%- elif uptime and uptime > 60 -%}
<p class="capsule center-text">Uptime: {{ uptime / 60 | round(method="floor") }} hours, {{ uptime % 60 }} minutes</p>
{%- else -%}
<p class="card-text">Uptime data unavailable</p>
{%- endif %}
<!-- FLASH MESSAGE -->
{% include "snippets/flash_message" %}
</div>
</div>
{%- endblock card %}

View File

@ -7,7 +7,6 @@
<div id="buttonDiv">
<a id="rebootBtn" class="button button-primary center" href="/power/reboot" title="Reboot Device">Reboot</a>
<a id="shutdownBtn" class="button button-warning center" href="/power/shutdown" title="Shutdown Device">Shutdown</a>
<a id="cancelBtn" class="button button-secondary center" href="/" title="Cancel">Cancel</a>
</div>
<!-- FLASH MESSAGE -->
{% include "snippets/flash_message" %}

View File

@ -0,0 +1,24 @@
{%- extends "nav" -%}
{%- block card %}
<!-- NETWORK SETTINGS CARD -->
<div class="card center">
<!-- BUTTONS -->
<div id="buttons">
<a class="button button-primary center" href="/settings/network/wifi/add" title="Add WiFi Network">Add WiFi Network</a>
<a id="configureDNS" class="button button-primary center" href="/settings/network/dns" title="Configure DNS">Configure DNS</a>
<!-- if ap is up, show "Enable WiFi" button, else show "Deplay Access Point" -->
{%- if ap_state == "up" %}
<a id="connectWifi" class="button button-primary center" href="/settings/network/wifi/activate" title="Enable WiFi">Enable WiFi</a>
{%- else %}
<a id="deployAccessPoint" class="button button-primary center" href="/settings/network/ap/activate" title="Deploy Access Point">Deploy Access Point</a>
{%- endif -%}
<a id="listWifi" class="button button-primary center" href="/settings/network/wifi" title="List WiFi Networks">List WiFi Networks</a>
<a id="viewUsage" class="button button-primary center" href="/settings/network/wifi/usage" title="View Data Usage">View Data Usage</a>
<a id="viewStatus" class="button button-primary center" href="/status/network" title="View Network Status">View Network Status</a>
</div>
<!-- FLASH MESSAGE -->
{% include "snippets/flash_message" %}
</div>
<script type="text/javascript" src="/js/network_card.js"></script>
{%- endblock card -%}

View File

@ -0,0 +1,135 @@
{%- extends "nav" -%}
{%- block card -%}
{# ASSIGN VARIABLES #}
{# ---------------- #}
{%- if mem_stats -%}
{% set mem_usage_percent = mem_stats.used / mem_stats.total * 100 | round -%}
{% set mem_used = mem_stats.used / 1024 | round -%}
{% set mem_free = mem_stats.free / 1024 | round -%}
{% set mem_total = mem_stats.total / 1024 | round -%}
{% endif -%}
{% if cpu_stat_percent -%}
{% set cpu_usage_percent = cpu_stat_percent.nice + cpu_stat_percent.system + cpu_stat_percent.user | round -%}
{%- endif -%}
{%- if disk_stats -%}
{%- for disk in disk_stats -%}
{%- set_global disk_usage_percent = disk.used_percentage -%}
{# Calculate free disk space in megabytes #}
{%- set_global disk_free = disk.one_k_blocks_free / 1024 | round -%}
{%- endfor -%}
{%- endif -%}
<!-- DEVICE STATUS VIEW -->
<div class="card center">
<div class="card-container">
<div class="three-grid">
{# Display microservice status for network, oled & stats #}
<!-- PEACH-NETWORK STATUS STACK -->
<a class="link" href="/status/network">
<div class="stack capsule{% if network_ping == "ONLINE" %} success-border{% else %} warning-border{% endif %}">
<img id="networkIcon" class="icon{% if network_ping == "OFFLINE" %} icon-inactive{% endif %} icon-medium" alt="Network" title="Network microservice status" src="/icons/wifi.svg">
<div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Networking</label>
<label class="label-small font-near-black">{{ network_ping }}</label>
</div>
</div>
</a>
<!-- PEACH-OLED STATUS STACK -->
<div class="stack capsule{% if oled_ping == "ONLINE" %} success-border{% else %} warning-border{% endif %}">
<img id="oledIcon" class="icon{% if oled_ping == "OFFLINE" %} icon-inactive{% endif %} icon-medium" alt="Display" title="OLED display microservice status" src="/icons/lcd.svg">
<div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Display</label>
<label class="label-small font-near-black">{{ oled_ping }}</label>
</div>
</div>
<!-- PEACH-STATS STATUS STACK -->
<div class="stack capsule{% if stats_ping == "ONLINE" %} success-border{% else %} warning-border{% endif %}">
<img id="statsIcon" class="icon{% if stats_ping == "OFFLINE" %} icon-inactive{% endif %} icon-medium" alt="Stats" title="System statistics microservice status" src="/icons/chart.svg">
<div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Statistics</label>
<label class="label-small font-near-black">{{ stats_ping }}</label>
</div>
</div>
{# Display status for dynsdns, config & sbot #}
<!-- DYNDNS STATUS STACK -->
<div class="stack capsule{% if dyndns_is_online %} success-border{% else %} warning-border{% endif %}">
<img id="networkIcon" class="icon{% if dyndns_is_online != true %} icon-inactive{% endif %} icon-medium" alt="Dyndns" title="Dyndns status" src="/icons/dns.png">
<div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Dyn DNS</label>
<label class="label-small font-near-black">{% if dyndns_is_online %} ONLINE {% else %} OFFLINE {% endif %} </label>
</div>
</div>
<!-- CONFIG STATUS STACK -->
<div class="stack capsule{% if config_is_valid %} success-border{% else %} warning-border{% endif %}">
<img id="networkIcon" class="icon{% if config_is_valid != true %} icon-inactive{% endif %} icon-medium" alt="Config" title="Config status" src="/icons/clipboard.png">
<div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Config</label>
<label class="label-small font-near-black">{% if config_is_valid %} LOADED {% else %} INVALID {% endif %} </label>
</div>
</div>
<!-- SBOT STATUS STACK -->
<div class="stack capsule{% if sbot_is_online %} success-border{% else %} warning-border{% endif %}">
<img id="networkIcon" class="icon{% if sbot_is_online != true %} icon-inactive{% endif %} icon-medium" alt="Sbot" title="Sbot status" src="/icons/hermies.svg">
<div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Sbot</label>
<label class="label-small font-near-black">{% if sbot_is_online %} ONLINE {% else %} OFFLINE {% endif %} </label>
</div>
</div>
</div>
<div class="card-container">
{# Display CPU usage meter #}
{%- if cpu_stat_percent -%}
<div class="flex-grid">
<span class="card-text">CPU</span>
<span class="label-small push-right">{{ cpu_usage_percent }}%</span>
</div>
<meter value="{{ cpu_usage_percent }}" min="0" max="100" title="CPU usage">
<div class="meter-gauge">
<span style="width: {{ cpu_usage_percent }}%;">CPU Usage</span>
</div>
</meter>
{%- else -%}
<p class="card-text">CPU usage data unavailable</p>
{% endif -%}
{# Display memory usage meter #}
{%- if mem_stats %}
<div class="flex-grid">
<span class="card-text">Memory</span>
<span class="label-small push-right">{{ mem_usage_percent }}% ({{ mem_free }} MB free)</span>
</div>
<meter value="{{ mem_used }}" min="0" max="{{ mem_total }}" title="Memory usage">
<div class="meter-gauge">
<span style="width: {{ mem_usage_percent }}%;">Memory Usage</span>
</div>
</meter>
{%- else -%}
<p class="card-text">Memory usage data unavailable</p>
{% endif -%}
{# Display disk usage meter #}
{%- if disk_stats %}
<div class="flex-grid">
<span class="card-text">Disk</span>
<span class="label-small push-right">{{ disk_usage_percent }}% ({% if disk_free > 1024 %}{{ disk_free / 1024 | round }} GB{% else %}{{ disk_free }} MB{% endif %} free)</span>
</div>
<meter value="{{ disk_usage_percent }}" min="0" max="100" title="Disk usage">
<div class="meter-gauge">
<span style="width: {{ disk_usage_percent }}%;">Disk Usage</span>
</div>
</meter>
{%- else -%}
<p class="card-text">Disk usage data unavailable</p>
{%- endif %}
{# Display system uptime in minutes #}
{%- if uptime and uptime < 60 %}
<p class="capsule center-text">Uptime: {{ uptime }} minutes</p>
{# Display system uptime in hours & minutes #}
{%- elif uptime and uptime > 60 -%}
<p class="capsule center-text">Uptime: {{ uptime / 60 | round(method="floor") }} hours, {{ uptime % 60 }} minutes</p>
{%- else -%}
<p class="card-text">Uptime data unavailable</p>
{%- endif %}
</div>
<!-- FLASH MESSAGE -->
{% include "snippets/flash_message" %}
</div>
</div>
{%- endblock card %}

View File

@ -6,37 +6,34 @@
<!-- NETWORK CARD -->
<div class="card center">
<!-- NETWORK INFO BOX -->
<div class="two-grid capsule success-border" title="PeachCloud network mode and status">
<!-- NETWORK STATUS -->
<!-- left column -->
<!-- network mode icon with label -->
<div class="grid-column-1">
<img id="netModeIcon" class="center icon icon-active" src="/icons/router.svg" alt="WiFi router">
<label id="netModeLabel" for="netModeIcon" class="center label-small font-gray" title="Access Point Online">ONLINE</label>
<div class="capsule capsule-container success-border">
<!-- NETWORK STATUS GRID -->
<div class="two-grid" title="PeachCloud network mode and status">
<!-- top-right config icon -->
<a class="link two-grid-top-right" href="/settings/network" title="Configure network settings">
<img id="configureNetworking" class="icon-small" src="/icons/cog.svg" alt="Configure">
</a>
<!-- left column -->
<!-- network mode icon with label -->
<div class="grid-column-1">
<img id="netModeIcon" class="center icon icon-active" src="/icons/router.svg" alt="WiFi router">
<label id="netModeLabel" for="netModeIcon" class="center label-small font-gray" title="Access Point Online">ONLINE</label>
</div>
<!-- right column -->
<!-- network mode, ssid & ip with labels -->
<div class="grid-column-2">
<label class="label-small font-gray" for="netMode" title="Network Mode">MODE</label>
<p id="netMode" class="card-text" title="Network Mode">Access Point</p>
<label class="label-small font-gray" for="netSsid" title="Access Point SSID">SSID</label>
<p id="netSsid" class="card-text" title="SSID">peach</p>
<label class="label-small font-gray" for="netIp" title="Access Point IP Address">IP</label>
<p id="netIp" class="card-text" title="IP">{{ ap_ip }}</p>
</div>
</div>
<!-- right column -->
<!-- network mode, ssid & ip with labels -->
<div class="grid-column-2">
<label class="label-small font-gray" for="netMode" title="Network Mode">MODE</label>
<p id="netMode" class="card-text" title="Network Mode">Access Point</p>
<label class="label-small font-gray" for="netSsid" title="Access Point SSID">SSID</label>
<p id="netSsid" class="card-text" title="SSID">peach</p>
<label class="label-small font-gray" for="netIp" title="Access Point IP Address">IP</label>
<p id="netIp" class="card-text" title="IP">{{ ap_ip }}</p>
</div>
</div>
<!-- BUTTONS -->
<div id="buttons">
<a class="button button-primary center" href="/settings/network/wifi/add" title="Add WiFi Network">Add WiFi Network</a>
<a id="connectWifi" class="button button-primary center" href="/settings/network/wifi/activate" title="Enable WiFi">Enable WiFi</a>
<a id="listWifi" class="button button-primary center" href="/settings/network/wifi" title="List WiFi Networks">List WiFi Networks</a>
<a id="viewUsage" class="button button-primary center" href="/settings/network/wifi/usage" title="View Data Usage">View Data Usage</a>
</div>
<!-- FLASH MESSAGE -->
{% include "snippets/flash_message" %}
<!-- CARD GRID -->
<div class="card-container">
<div class="three-grid">
<!-- horizontal dividing line -->
<hr>
<!-- DEVICES AND TRAFFIC GRID -->
<div class="three-grid card-container">
<div class="stack">
<img id="devices" class="icon icon-medium" title="Connected devices" src="/icons/devices.svg" alt="Digital devices">
<div class="flex-grid" style="padding-top: 0.5rem;">
@ -78,47 +75,45 @@
<div class="card center">
<!-- NETWORK INFO BOX -->
{%- if wlan_state == "up" %}
<div id="netInfoBox" class="two-grid capsule success-border" title="PeachCloud network mode and status">
<!-- NETWORK STATUS -->
<!-- left column -->
<!-- network mode icon with label -->
<div class="grid-column-1">
<img id="netModeIcon" class="center icon icon-active" src="/icons/wifi.svg" alt="WiFi online">
<label id="netModeLabel" for="netModeIcon" class="center label-small font-gray" title="WiFi Client Status">ONLINE</label>
<div class="capsule capsule-container success-border">
<!-- NETWORK STATUS GRID -->
<div id="netInfoBox" class="two-grid" title="PeachCloud network mode and status">
<a class="link two-grid-top-right" href="/settings/network" title="Configure network settings">
<img id="configureNetworking" class="icon-small" src="/icons/cog.svg" alt="Configure">
</a>
<!-- NETWORK STATUS -->
<!-- left column -->
<!-- network mode icon with label -->
<div class="grid-column-1">
<img id="netModeIcon" class="center icon icon-active" src="/icons/wifi.svg" alt="WiFi online">
<label id="netModeLabel" for="netModeIcon" class="center label-small font-gray" title="WiFi Client Status">ONLINE</label>
{%- else %}
<div id="netInfoBox" class="two-grid capsule warning-border" title="PeachCloud network mode and status">
<div class="grid-column-1">
<img id="netModeIcon" class="center icon icon-inactive" src="/icons/wifi.svg" alt="WiFi offline">
<label id="netModeLabel" for="netModeIcon" class="center label-small font-gray" title="WiFi Client Status">OFFLINE</label>
<div class="capsule capsule-container warning-border">
<div id="netInfoBox" class="two-grid" title="PeachCloud network mode and status">
<a class="link two-grid-top-right" href="/settings/network" title="Configure network settings">
<img id="configureNetworking" class="icon-small" src="/icons/cog.svg" alt="Configure">
</a>
<div class="grid-column-1">
<img id="netModeIcon" class="center icon icon-inactive" src="/icons/wifi.svg" alt="WiFi offline">
<label id="netModeLabel" for="netModeIcon" class="center label-small font-gray" title="WiFi Client Status">OFFLINE</label>
{%- endif %}
</div>
<div class="grid-column-2">
<!-- right column -->
<!-- network mode, ssid & ip with labels -->
<label class="label-small font-gray" for="netMode" title="Network Mode">MODE</label>
<p id="netMode" class="card-text" title="Network Mode">WiFi Client</p>
<label class="label-small font-gray" for="netSsid" title="WiFi SSID">SSID</label>
<p id="netSsid" class="card-text" title="SSID">{{ wlan_ssid }}</p>
<label class="label-small font-gray" for="netIp" title="WiFi Client IP Address">IP</label>
<p id="netIp" class="card-text" title="IP">{{ wlan_ip }}</p>
</div>
</div>
<div class="grid-column-2">
<!-- right column -->
<!-- network mode, ssid & ip with labels -->
<label class="label-small font-gray" for="netMode" title="Network Mode">MODE</label>
<p id="netMode" class="card-text" title="Network Mode">WiFi Client</p>
<label class="label-small font-gray" for="netSsid" title="WiFi SSID">SSID</label>
<p id="netSsid" class="card-text" title="SSID">{{ wlan_ssid }}</p>
<label class="label-small font-gray" for="netIp" title="WiFi Client IP Address">IP</label>
<p id="netIp" class="card-text" title="IP">{{ wlan_ip }}</p>
</div>
</div>
<!-- BUTTONS -->
<div id="buttons">
<a class="button button-primary center" href="/settings/network/wifi/add" title="Add WiFi Network">Add WiFi Network</a>
<a id="deployAccessPoint" class="button button-primary center" href="/settings/network/ap/activate" title="Deploy Access Point">Deploy Access Point</a>
<a id="listWifi" class="button button-primary center" href="/settings/network/wifi" title="List WiFi Networks">List WiFi Networks</a>
<a id="viewUsage" class="button button-primary center" href="/settings/network/wifi/usage" title="View Data Usage">View Data Usage</a>
<a id="configureDNS" class="button button-primary center" href="/settings/network/dns" title="Configure DNS">Configure DNS</a>
<a id="changePassword" class="button button-primary center" href="/settings/admin/change_password" title="Change Password">Change Password</a>
<a id="configureAdmin" class="button button-primary center" href="/settings/admin/configure_admin" title="Configure Admin">Configure Admin</a>
</div>
<!-- FLASH MESSAGE -->
{% include "snippets/flash_message" %}
<div id="gridDiv" class="card-container">
<!-- CARD GRID -->
<!-- horizontal dividing line -->
<hr>
<!-- SIGNAL AND TRAFFIC GRID -->
<!-- row of icons representing network statistics -->
<div class="three-grid">
<div class="three-grid card-container">
<div class="stack">
<img id="netSignal" class="icon icon-medium" alt="Signal" title="WiFi Signal (%)" src="/icons/low-signal.svg">
<div class="flex-grid" style="padding-top: 0.5rem;">
@ -159,6 +154,5 @@
</div>
</div>
</div>
<script type="text/javascript" src="/js/network_card.js"></script>
{%- endif -%}
{%- endblock card -%}