add the refactored template for network status
This commit is contained in:
parent
0fab57d94f
commit
4e7fbd5fdf
@ -1,3 +1,3 @@
|
||||
//pub mod device;
|
||||
//pub mod network;
|
||||
pub mod network;
|
||||
pub mod scuttlebutt;
|
||||
|
@ -1,21 +1,285 @@
|
||||
use rocket::{get, request::FlashMessage};
|
||||
use rocket_dyn_templates::Template;
|
||||
use maud::{html, Markup, PreEscaped};
|
||||
use peach_network::network;
|
||||
use vnstat_parse::Vnstat;
|
||||
|
||||
use crate::context::network::NetworkStatusContext;
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::{templates, utils::theme, AP_IFACE, WLAN_IFACE};
|
||||
|
||||
// HELPERS AND ROUTES FOR /status/network
|
||||
enum NetworkState {
|
||||
AccessPoint,
|
||||
WiFiClient,
|
||||
}
|
||||
|
||||
#[get("/network")]
|
||||
pub fn network_status(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
let mut context = NetworkStatusContext::build();
|
||||
context.back = Some("/status".to_string());
|
||||
context.title = Some("Network Status".to_string());
|
||||
// ROUTE: /status/network
|
||||
|
||||
if let Some(flash) = flash {
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
/// Render the cog icon which is used as a link to the network settings page.
|
||||
fn render_network_config_icon() -> Markup {
|
||||
html! {
|
||||
(PreEscaped("<!-- 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the network mode icon, either a WiFi signal or router, based
|
||||
/// on the state of the AP and WiFi interfaces.
|
||||
///
|
||||
/// A router icon is shown if the AP is online (interface is "up").
|
||||
///
|
||||
/// A WiFi signal icon is shown if the AP interface is down. The colour of
|
||||
/// the icon is black if the WLAN interface is up and gray if it's down.
|
||||
fn render_network_mode_icon(state: &NetworkState) -> Markup {
|
||||
// TODO: make this DRYer
|
||||
let (icon_class, icon_src, icon_alt, label_title, label_value) = match state {
|
||||
NetworkState::AccessPoint => (
|
||||
"center icon icon-active",
|
||||
"/icons/router.svg",
|
||||
"WiFi router",
|
||||
"Access Point Online",
|
||||
"ONLINE",
|
||||
),
|
||||
NetworkState::WiFiClient => match network::state(WLAN_IFACE) {
|
||||
Ok(Some(state)) if state == "up" => (
|
||||
"center icon icon-active",
|
||||
"/icons/wifi.svg",
|
||||
"WiFi signal",
|
||||
"WiFi Client Online",
|
||||
"ONLINE",
|
||||
),
|
||||
_ => (
|
||||
"center icon icon-inactive",
|
||||
"/icons/wifi.svg",
|
||||
"WiFi signal",
|
||||
"WiFi Client Offline",
|
||||
"OFFLINE",
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
Template::render("status/network", &context)
|
||||
html! {
|
||||
(PreEscaped("<!-- network mode icon with label -->"))
|
||||
div class="grid-column-1" {
|
||||
img id="netModeIcon" class=(icon_class) src=(icon_src) alt=(icon_alt);
|
||||
label id="netModeLabel" for="netModeIcon" class="center label-small font-gray" title=(label_title) { (label_value) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the network data associated with the deployed access point or
|
||||
/// connected WiFi client depending on active mode.
|
||||
///
|
||||
/// Data includes the network mode (access point or WiFi client), SSID and IP
|
||||
/// address.
|
||||
fn render_network_data(state: &NetworkState, ssid: String, ip: String) -> Markup {
|
||||
let (mode_value, mode_title, ssid_value, ip_title) = match state {
|
||||
NetworkState::AccessPoint => (
|
||||
"Access Point",
|
||||
"Access Point SSID",
|
||||
// TODO: remove hardcoding of this value (query interface instead)
|
||||
"peach",
|
||||
"Access Point IP Address",
|
||||
),
|
||||
NetworkState::WiFiClient => (
|
||||
"WiFi Client",
|
||||
"WiFi SSID",
|
||||
ssid.as_str(),
|
||||
"WiFi Client IP Address",
|
||||
),
|
||||
};
|
||||
|
||||
html! {
|
||||
(PreEscaped("<!-- network mode, ssid & ip with labels -->"))
|
||||
div class="grid-column-2" {
|
||||
label class="label-small font-gray" for="netMode" title="Network Mode" { "MODE" }
|
||||
p id="netMode" class="card-text" title="Network Mode" { (mode_value) }
|
||||
label class="label-small font-gray" for="netSsid" title=(mode_title) { "SSID" }
|
||||
p id="netSsid" class="card-text" title="SSID" { (ssid_value) }
|
||||
label class="label-small font-gray" for="netIp" title=(ip_title) { "IP" }
|
||||
p id="netIp" class="card-text" title="IP" { (ip) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the network status grid comprised of the network config icon,
|
||||
/// network mode icon and network data text.
|
||||
fn render_network_status_grid(state: &NetworkState, ssid: String, ip: String) -> Markup {
|
||||
html! {
|
||||
(PreEscaped("<!-- NETWORK STATUS GRID -->"))
|
||||
div class="two-grid" title="PeachCloud network mode and status" {
|
||||
(render_network_config_icon())
|
||||
(PreEscaped("<!-- left column -->"))
|
||||
(render_network_mode_icon(state))
|
||||
(PreEscaped("<!-- right column -->"))
|
||||
(render_network_data(state, ssid, ip))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the signal strength stack comprised of a signal icon, RSSI value
|
||||
/// and label.
|
||||
///
|
||||
/// This stack is displayed when the network mode is set to WiFi
|
||||
/// client (ie. the value reported is the strength of the connection of the
|
||||
/// local WiFi interface to a remote access point).
|
||||
fn render_signal_strength_stack() -> Markup {
|
||||
let wlan_rssi = match network::rssi(WLAN_IFACE) {
|
||||
Ok(Some(rssi)) => rssi,
|
||||
_ => 0.to_string(),
|
||||
};
|
||||
|
||||
html! {
|
||||
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;" {
|
||||
label class="label-medium" for="netSignal" style="padding-right: 3px;" title="Signal strength of WiFi connection (%)" { (wlan_rssi) }
|
||||
}
|
||||
label class="label-small font-gray" { "SIGNAL" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the connected devices stack comprised of a devices icon, value
|
||||
/// of connected devices and label.
|
||||
///
|
||||
/// This stack is displayed when the network mode is set to access point
|
||||
/// (ie. the value reported is the number of remote devices connected to the
|
||||
/// local access point).
|
||||
fn render_connected_devices_stack() -> Markup {
|
||||
html! {
|
||||
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;" {
|
||||
label class="label-medium" for="devices" style="padding-right: 3px;" title="Number of connected devices";
|
||||
}
|
||||
label class="label-small font-gray" { "DEVICES" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the data download stack comprised of a download icon, traffic value
|
||||
/// and label.
|
||||
///
|
||||
/// A zero value is displayed if no interface traffic is available for the
|
||||
/// WLAN interface.
|
||||
fn render_data_download_stack(iface_traffic: &Option<Vnstat>) -> Markup {
|
||||
html! {
|
||||
div class="stack" {
|
||||
img id="dataDownload" class="icon icon-medium" title="Download" src="/icons/down-arrow.svg" alt="Download";
|
||||
div class="flex-grid" style="padding-top: 0.5rem;" {
|
||||
@if let Some(traffic) = iface_traffic {
|
||||
label class="label-medium" for="dataDownload" style="padding-right: 3px;" title={ "Data download total in " (traffic.all_time_rx_unit) } { (traffic.all_time_rx) }
|
||||
label class="label-small font-near-black" { (traffic.all_time_rx_unit) }
|
||||
} @else {
|
||||
label class="label-medium" for="dataDownload" style="padding-right: 3px;" title="Data download total" { "0" }
|
||||
label class="label-small font-near-black";
|
||||
}
|
||||
}
|
||||
label class="label-small font-gray" { "DOWNLOAD" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the data upload stack comprised of an upload icon, traffic value
|
||||
/// and label.
|
||||
///
|
||||
/// A zero value is displayed if no interface traffic is available for the
|
||||
/// WLAN interface.
|
||||
fn render_data_upload_stack(iface_traffic: Option<Vnstat>) -> Markup {
|
||||
html! {
|
||||
div class="stack" {
|
||||
img id="dataUpload" class="icon icon-medium" title="Upload" src="/icons/up-arrow.svg" alt="Upload";
|
||||
div class="flex-grid" style="padding-top: 0.5rem;" {
|
||||
@if let Some(traffic) = iface_traffic {
|
||||
label class="label-medium" for="dataUpload" style="padding-right: 3px;" title={ "Data upload total in " (traffic.all_time_tx_unit) } { (traffic.all_time_tx) }
|
||||
label class="label-small font-near-black" { (traffic.all_time_tx_unit) }
|
||||
} @else {
|
||||
label class="label-medium" for="dataUpload" style="padding-right: 3px;" title="Data upload total" { "0" }
|
||||
label class="label-small font-near-black";
|
||||
}
|
||||
}
|
||||
label class="label-small font-gray" { "UPLOAD" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the device / signal and traffic grid.
|
||||
///
|
||||
/// The connected devices stack is displayed if the network mode is set to
|
||||
/// access point and the signal strength stack is displayed if the network
|
||||
/// mode is set to WiFi client.
|
||||
fn render_device_and_traffic_grid(state: NetworkState, iface_traffic: Option<Vnstat>) -> Markup {
|
||||
html! {
|
||||
div class="three-grid card-container" {
|
||||
@match state {
|
||||
NetworkState::AccessPoint => (render_connected_devices_stack()),
|
||||
NetworkState::WiFiClient => (render_signal_strength_stack()),
|
||||
}
|
||||
(render_data_download_stack(&iface_traffic))
|
||||
(render_data_upload_stack(iface_traffic))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Network state data retrieval.
|
||||
///
|
||||
/// This data is injected into the template rendering functions.
|
||||
fn retrieve_network_data() -> (NetworkState, Option<Vnstat>, String, String) {
|
||||
// if the access point interface is "up",
|
||||
// retrieve the traffic stats, ip and ssidfor the ap interface.
|
||||
// otherwise retrieve the stats and ip for the wlan interface.
|
||||
let (state, traffic, ip, ssid) = match network::state(AP_IFACE) {
|
||||
Ok(Some(state)) if state == "up" => {
|
||||
let ap_traffic = Vnstat::get(AP_IFACE).ok();
|
||||
|
||||
let ap_ip = match network::ip(AP_IFACE) {
|
||||
Ok(Some(ip)) => ip,
|
||||
_ => String::from("x.x.x.x"),
|
||||
};
|
||||
|
||||
let ap_ssid = String::from("peach");
|
||||
|
||||
(NetworkState::AccessPoint, ap_traffic, ap_ip, ap_ssid)
|
||||
}
|
||||
_ => {
|
||||
let wlan_traffic = Vnstat::get(WLAN_IFACE).ok();
|
||||
|
||||
let wlan_ip = match network::ip(WLAN_IFACE) {
|
||||
Ok(Some(ip)) => ip,
|
||||
_ => String::from("x.x.x.x"),
|
||||
};
|
||||
|
||||
let wlan_ssid = match network::ssid(WLAN_IFACE) {
|
||||
Ok(Some(ssid)) => ssid,
|
||||
_ => String::from("Not connected"),
|
||||
};
|
||||
|
||||
(NetworkState::WiFiClient, wlan_traffic, wlan_ip, wlan_ssid)
|
||||
}
|
||||
};
|
||||
|
||||
(state, traffic, ip, ssid)
|
||||
}
|
||||
|
||||
/// Network status template builder.
|
||||
pub fn build_template() -> PreEscaped<String> {
|
||||
let (state, traffic, ip, ssid) = retrieve_network_data();
|
||||
|
||||
let network_status_template = html! {
|
||||
(PreEscaped("<!-- NETWORK STATUS CARD -->"))
|
||||
div class="card center" {
|
||||
(PreEscaped("<!-- NETWORK INFO BOX -->"))
|
||||
div class="capsule capsule-container success-border" {
|
||||
(render_network_status_grid(&state, ssid, ip))
|
||||
hr style="color: var(--light-gray);";
|
||||
(render_device_and_traffic_grid(state, traffic))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let body =
|
||||
templates::nav::build_template(network_status_template, "Network Status", Some("/status"));
|
||||
|
||||
let theme = theme::get_theme();
|
||||
|
||||
templates::base::build_template(body, theme)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user