Merge pull request 'Introduce theme support (plus blobstore size)' (#80) from theme_support into main
Reviewed-on: #80
This commit is contained in:
commit
4709ec77f9
|
@ -1,11 +1,31 @@
|
|||
//! Data types and associated methods for monitoring and configuring go-sbot.
|
||||
|
||||
use std::{fs, fs::File, io::Write, process::Command, str};
|
||||
use std::{fs, fs::File, io, io::Write, path::PathBuf, process::Command, str};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::error::PeachError;
|
||||
|
||||
/* HELPER FUNCTIONS */
|
||||
|
||||
// iterate over the given directory path to determine the size of the directory
|
||||
fn dir_size(path: impl Into<PathBuf>) -> io::Result<u64> {
|
||||
fn dir_size(mut dir: fs::ReadDir) -> io::Result<u64> {
|
||||
dir.try_fold(0, |acc, file| {
|
||||
let file = file?;
|
||||
let size = match file.metadata()? {
|
||||
data if data.is_dir() => dir_size(fs::read_dir(file.path())?)?,
|
||||
data => data.len(),
|
||||
};
|
||||
Ok(acc + size)
|
||||
})
|
||||
}
|
||||
|
||||
dir_size(fs::read_dir(path.into())?)
|
||||
}
|
||||
|
||||
/* SBOT-RELATED TYPES AND METHODS */
|
||||
|
||||
/// go-sbot process status.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct SbotStatus {
|
||||
|
@ -19,6 +39,8 @@ pub struct SbotStatus {
|
|||
pub uptime: Option<String>,
|
||||
/// Downtime for the process (if state is `inactive`).
|
||||
pub downtime: Option<String>,
|
||||
/// Size of the blobs directory in bytes.
|
||||
pub blobstore: Option<u64>,
|
||||
}
|
||||
|
||||
/// Default builder for `SbotStatus`.
|
||||
|
@ -30,6 +52,7 @@ impl Default for SbotStatus {
|
|||
memory: None,
|
||||
uptime: None,
|
||||
downtime: None,
|
||||
blobstore: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +124,15 @@ impl SbotStatus {
|
|||
}
|
||||
}
|
||||
|
||||
// determine path of user's home directory
|
||||
let mut blobstore_path = dirs::home_dir().ok_or(PeachError::HomeDir)?;
|
||||
|
||||
// append the blobstore path
|
||||
blobstore_path.push(".ssb-go/blobs/sha256");
|
||||
|
||||
// determine the size of the blobstore directory in bytes
|
||||
status.blobstore = dir_size(blobstore_path).ok();
|
||||
|
||||
Ok(status)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ maintenance = { status = "actively-developed" }
|
|||
|
||||
[dependencies]
|
||||
env_logger = "0.8"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4"
|
||||
nest = "1.0.0"
|
||||
peach-lib = { path = "../peach-lib" }
|
||||
|
|
|
@ -11,6 +11,7 @@ pub struct ConfigureDNSContext {
|
|||
pub title: Option<String>,
|
||||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
pub theme: Option<String>,
|
||||
}
|
||||
|
||||
impl ConfigureDNSContext {
|
||||
|
@ -31,6 +32,7 @@ impl ConfigureDNSContext {
|
|||
title: None,
|
||||
flash_name: None,
|
||||
flash_msg: None,
|
||||
theme: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,11 +32,14 @@ pub mod routes;
|
|||
mod tests;
|
||||
pub mod utils;
|
||||
|
||||
use std::process;
|
||||
use std::{process, sync::RwLock};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use log::{debug, error, info};
|
||||
use rocket::{fairing::AdHoc, serde::Deserialize, Build, Rocket};
|
||||
|
||||
use utils::Theme;
|
||||
|
||||
pub type BoxError = Box<dyn std::error::Error>;
|
||||
|
||||
/// Application configuration parameters.
|
||||
|
@ -51,6 +54,10 @@ pub struct RocketConfig {
|
|||
standalone_mode: bool,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref THEME: RwLock<Theme> = RwLock::new(Theme::Light);
|
||||
}
|
||||
|
||||
static WLAN_IFACE: &str = "wlan0";
|
||||
static AP_IFACE: &str = "ap0";
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::routes::{
|
|||
catchers::*,
|
||||
index::*,
|
||||
scuttlebutt::*,
|
||||
settings::{admin::*, dns::*, menu::*, network::*, scuttlebutt::*},
|
||||
settings::{admin::*, dns::*, menu::*, network::*, scuttlebutt::*, theme::*},
|
||||
status::{device::*, network::*, scuttlebutt::*},
|
||||
};
|
||||
|
||||
|
@ -28,6 +28,7 @@ pub fn mount_peachpub_routes(rocket: Rocket<Build>) -> Rocket<Build> {
|
|||
shutdown_cmd,
|
||||
power_menu,
|
||||
settings_menu,
|
||||
set_theme,
|
||||
],
|
||||
)
|
||||
.mount(
|
||||
|
|
|
@ -13,8 +13,8 @@ use rocket_dyn_templates::{tera::Context, Template};
|
|||
use peach_lib::{error::PeachError, password_utils};
|
||||
|
||||
use crate::error::PeachWebError;
|
||||
use crate::utils;
|
||||
use crate::utils::TemplateOrRedirect;
|
||||
//use crate::DisableAuth;
|
||||
use crate::RocketConfig;
|
||||
|
||||
// HELPERS AND STRUCTS FOR AUTHENTICATION WITH COOKIES
|
||||
|
@ -72,7 +72,11 @@ impl<'r> FromRequest<'r> for Authenticated {
|
|||
|
||||
#[get("/login")]
|
||||
pub fn login(flash: Option<FlashMessage>) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("theme", &theme);
|
||||
context.insert("back", &Some("/".to_string()));
|
||||
context.insert("title", &Some("Login".to_string()));
|
||||
|
||||
|
@ -166,7 +170,11 @@ pub fn save_reset_password_form(password_form: ResetPasswordForm) -> Result<(),
|
|||
/// and is specifically for users who have forgotten their password.
|
||||
#[get("/reset_password")]
|
||||
pub fn reset_password(flash: Option<FlashMessage>) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("theme", &theme);
|
||||
context.insert("back", &Some("/".to_string()));
|
||||
context.insert("title", &Some("Reset Password".to_string()));
|
||||
|
||||
|
@ -211,7 +219,11 @@ pub fn reset_password_post(reset_password_form: Form<ResetPasswordForm>) -> Temp
|
|||
/// to initiate the sending of a new password reset.
|
||||
#[get("/forgot_password")]
|
||||
pub fn forgot_password_page(flash: Option<FlashMessage>) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("theme", &theme);
|
||||
context.insert("back", &Some("/".to_string()));
|
||||
context.insert("title", &Some("Send Password Reset".to_string()));
|
||||
|
||||
|
@ -281,7 +293,11 @@ pub fn save_password_form(password_form: PasswordForm) -> Result<(), PeachWebErr
|
|||
/// Change password request handler. This is used by a user who is already logged in.
|
||||
#[get("/change_password")]
|
||||
pub fn change_password(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("theme", &theme);
|
||||
context.insert("back", &Some("/settings/admin".to_string()));
|
||||
context.insert("title", &Some("Change Password".to_string()));
|
||||
|
||||
|
|
|
@ -3,16 +3,21 @@ use rocket::{get, request::FlashMessage, State};
|
|||
use rocket_dyn_templates::{tera::Context, Template};
|
||||
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::utils;
|
||||
use crate::RocketConfig;
|
||||
|
||||
// HELPERS AND ROUTES FOR / (HOME PAGE)
|
||||
|
||||
#[get("/")]
|
||||
pub fn home(_auth: Authenticated, config: &State<RocketConfig>) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
// retrieve go-sbot systemd process status
|
||||
let sbot_status = SbotStatus::read().ok();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("theme", &theme);
|
||||
context.insert("sbot_status", &sbot_status);
|
||||
context.insert("flash_name", &None::<()>);
|
||||
context.insert("flash_msg", &None::<()>);
|
||||
|
@ -28,7 +33,11 @@ pub fn home(_auth: Authenticated, config: &State<RocketConfig>) -> Template {
|
|||
|
||||
#[get("/help")]
|
||||
pub fn help(flash: Option<FlashMessage>) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("theme", &theme);
|
||||
context.insert("back", &Some("/".to_string()));
|
||||
context.insert("title", &Some("Help".to_string()));
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ use rocket::{
|
|||
use rocket_dyn_templates::Template;
|
||||
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::utils;
|
||||
|
||||
// HELPERS AND ROUTES FOR /private
|
||||
|
||||
|
@ -20,6 +21,7 @@ pub struct PrivateContext {
|
|||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
pub title: Option<String>,
|
||||
pub theme: Option<String>,
|
||||
}
|
||||
|
||||
impl PrivateContext {
|
||||
|
@ -29,6 +31,7 @@ impl PrivateContext {
|
|||
flash_name: None,
|
||||
flash_msg: None,
|
||||
title: None,
|
||||
theme: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,15 +39,21 @@ impl PrivateContext {
|
|||
/// A private message composition and publication page.
|
||||
#[get("/private")]
|
||||
pub fn private(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = PrivateContext::build();
|
||||
context.back = Some("/".to_string());
|
||||
context.title = Some("Private Messages".to_string());
|
||||
context.theme = Some(theme);
|
||||
|
||||
// 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::render("scuttlebutt/messages", &context)
|
||||
}
|
||||
|
||||
|
@ -56,6 +65,7 @@ pub struct PeerContext {
|
|||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
pub title: Option<String>,
|
||||
pub theme: Option<String>,
|
||||
}
|
||||
|
||||
impl PeerContext {
|
||||
|
@ -65,6 +75,7 @@ impl PeerContext {
|
|||
flash_name: None,
|
||||
flash_msg: None,
|
||||
title: None,
|
||||
theme: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,15 +83,21 @@ impl PeerContext {
|
|||
/// A peer menu which allows navigating to lists of friends, follows, followers and blocks.
|
||||
#[get("/peers")]
|
||||
pub fn peers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = PeerContext::build();
|
||||
context.back = Some("/".to_string());
|
||||
context.title = Some("Scuttlebutt Peers".to_string());
|
||||
context.theme = Some(theme);
|
||||
|
||||
// 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::render("scuttlebutt/peers", &context)
|
||||
}
|
||||
|
||||
|
@ -91,7 +108,10 @@ pub struct Post {
|
|||
pub text: String,
|
||||
}
|
||||
|
||||
/// Publish a public Scuttlebutt post. Redirects to profile page of the PeachCloud local identity with a flash message describing the outcome of the action (may be successful or unsuccessful).
|
||||
/// Publish a public Scuttlebutt post.
|
||||
/// Redirects to profile page of the PeachCloud local identity with a flash
|
||||
/// message describing the outcome of the action (may be successful or
|
||||
/// unsuccessful).
|
||||
#[post("/publish", data = "<post>")]
|
||||
pub fn publish(post: Form<Post>, _auth: Authenticated) -> Flash<Redirect> {
|
||||
let post_text = &post.text;
|
||||
|
@ -101,6 +121,7 @@ pub fn publish(post: Form<Post>, _auth: Authenticated) -> Flash<Redirect> {
|
|||
// redirect to the profile template without public key ("home" / local profile)
|
||||
let pub_key: std::option::Option<&str> = None;
|
||||
let profile_url = uri!(profile(pub_key));
|
||||
|
||||
// consider adding the message reference to the flash message (or render it in the template for
|
||||
// `profile`
|
||||
Flash::success(Redirect::to(profile_url), "Published public post")
|
||||
|
@ -113,7 +134,9 @@ pub struct PublicKey {
|
|||
pub key: String,
|
||||
}
|
||||
|
||||
/// Follow a Scuttlebutt profile specified by the given public key. Redirects to the appropriate profile page with a flash message describing the outcome of the action (may be successful or unsuccessful).
|
||||
/// Follow a Scuttlebutt profile specified by the given public key.
|
||||
/// Redirects to the appropriate profile page with a flash message describing
|
||||
/// the outcome of the action (may be successful or unsuccessful).
|
||||
#[post("/follow", data = "<pub_key>")]
|
||||
pub fn follow(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirect> {
|
||||
let public_key = &pub_key.key;
|
||||
|
@ -123,12 +146,15 @@ pub fn follow(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirect>
|
|||
// redirect to the profile template with provided public key
|
||||
let profile_url = uri!(profile(Some(public_key)));
|
||||
let success_msg = format!("Followed {}", public_key);
|
||||
|
||||
Flash::success(Redirect::to(profile_url), success_msg)
|
||||
}
|
||||
|
||||
// HELPERS AND ROUTES FOR /unfollow
|
||||
|
||||
/// Unfollow a Scuttlebutt profile specified by the given public key. Redirects to the appropriate profile page with a flash message describing the outcome of the action (may be successful or unsuccessful).
|
||||
/// Unfollow a Scuttlebutt profile specified by the given public key.
|
||||
/// Redirects to the appropriate profile page with a flash message describing
|
||||
/// the outcome of the action (may be successful or unsuccessful).
|
||||
#[post("/unfollow", data = "<pub_key>")]
|
||||
pub fn unfollow(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirect> {
|
||||
let public_key = &pub_key.key;
|
||||
|
@ -138,12 +164,15 @@ pub fn unfollow(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirec
|
|||
// redirect to the profile template with provided public key
|
||||
let profile_url = uri!(profile(Some(public_key)));
|
||||
let success_msg = format!("Unfollowed {}", public_key);
|
||||
|
||||
Flash::success(Redirect::to(profile_url), success_msg)
|
||||
}
|
||||
|
||||
// HELPERS AND ROUTES FOR /block
|
||||
|
||||
/// Block a Scuttlebutt profile specified by the given public key. Redirects to the appropriate profile page with a flash message describing the outcome of the action (may be successful or unsuccessful).
|
||||
/// Block a Scuttlebutt profile specified by the given public key.
|
||||
/// Redirects to the appropriate profile page with a flash message describing
|
||||
/// the outcome of the action (may be successful or unsuccessful).
|
||||
#[post("/block", data = "<pub_key>")]
|
||||
pub fn block(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirect> {
|
||||
let public_key = &pub_key.key;
|
||||
|
@ -153,6 +182,7 @@ pub fn block(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirect>
|
|||
// redirect to the profile template with provided public key
|
||||
let profile_url = uri!(profile(Some(public_key)));
|
||||
let success_msg = format!("Blocked {}", public_key);
|
||||
|
||||
Flash::success(Redirect::to(profile_url), success_msg)
|
||||
}
|
||||
|
||||
|
@ -164,6 +194,7 @@ pub struct ProfileContext {
|
|||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
pub title: Option<String>,
|
||||
pub theme: Option<String>,
|
||||
}
|
||||
|
||||
impl ProfileContext {
|
||||
|
@ -173,6 +204,7 @@ impl ProfileContext {
|
|||
flash_name: None,
|
||||
flash_msg: None,
|
||||
title: None,
|
||||
theme: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,15 +216,21 @@ pub fn profile(
|
|||
flash: Option<FlashMessage>,
|
||||
_auth: Authenticated,
|
||||
) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = ProfileContext::build();
|
||||
context.back = Some("/".to_string());
|
||||
context.title = Some("Profile".to_string());
|
||||
context.theme = Some(theme);
|
||||
|
||||
// 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::render("scuttlebutt/profile", &context)
|
||||
}
|
||||
|
||||
|
@ -204,6 +242,7 @@ pub struct FriendsContext {
|
|||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
pub title: Option<String>,
|
||||
pub theme: Option<String>,
|
||||
}
|
||||
|
||||
impl FriendsContext {
|
||||
|
@ -213,6 +252,7 @@ impl FriendsContext {
|
|||
flash_name: None,
|
||||
flash_msg: None,
|
||||
title: None,
|
||||
theme: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -221,9 +261,13 @@ impl FriendsContext {
|
|||
/// key of the peer.
|
||||
#[get("/friends")]
|
||||
pub fn friends(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = FriendsContext::build();
|
||||
context.back = Some("/scuttlebutt/peers".to_string());
|
||||
context.title = Some("Friends".to_string());
|
||||
context.theme = Some(theme);
|
||||
|
||||
// check to see if there is a flash message to display
|
||||
if let Some(flash) = flash {
|
||||
|
@ -231,6 +275,7 @@ pub fn friends(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
|||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
|
||||
Template::render("scuttlebutt/peers_list", &context)
|
||||
}
|
||||
|
||||
|
@ -242,6 +287,7 @@ pub struct FollowsContext {
|
|||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
pub title: Option<String>,
|
||||
pub theme: Option<String>,
|
||||
}
|
||||
|
||||
impl FollowsContext {
|
||||
|
@ -251,6 +297,7 @@ impl FollowsContext {
|
|||
flash_name: None,
|
||||
flash_msg: None,
|
||||
title: None,
|
||||
theme: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -259,9 +306,13 @@ impl FollowsContext {
|
|||
/// key of the peer.
|
||||
#[get("/follows")]
|
||||
pub fn follows(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = FollowsContext::build();
|
||||
context.back = Some("/scuttlebutt/peers".to_string());
|
||||
context.title = Some("Follows".to_string());
|
||||
context.theme = Some(theme);
|
||||
|
||||
// check to see if there is a flash message to display
|
||||
if let Some(flash) = flash {
|
||||
|
@ -269,6 +320,7 @@ pub fn follows(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
|||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
|
||||
Template::render("scuttlebutt/peers_list", &context)
|
||||
}
|
||||
|
||||
|
@ -280,6 +332,7 @@ pub struct FollowersContext {
|
|||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
pub title: Option<String>,
|
||||
pub theme: Option<String>,
|
||||
}
|
||||
|
||||
impl FollowersContext {
|
||||
|
@ -289,6 +342,7 @@ impl FollowersContext {
|
|||
flash_name: None,
|
||||
flash_msg: None,
|
||||
title: None,
|
||||
theme: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -297,9 +351,13 @@ impl FollowersContext {
|
|||
/// key of the peer.
|
||||
#[get("/followers")]
|
||||
pub fn followers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = FollowersContext::build();
|
||||
context.back = Some("/scuttlebutt/peers".to_string());
|
||||
context.title = Some("Followers".to_string());
|
||||
context.theme = Some(theme);
|
||||
|
||||
// check to see if there is a flash message to display
|
||||
if let Some(flash) = flash {
|
||||
|
@ -307,6 +365,7 @@ pub fn followers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template
|
|||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
|
||||
Template::render("scuttlebutt/peers_list", &context)
|
||||
}
|
||||
|
||||
|
@ -318,6 +377,7 @@ pub struct BlocksContext {
|
|||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
pub title: Option<String>,
|
||||
pub theme: Option<String>,
|
||||
}
|
||||
|
||||
impl BlocksContext {
|
||||
|
@ -327,6 +387,7 @@ impl BlocksContext {
|
|||
flash_name: None,
|
||||
flash_msg: None,
|
||||
title: None,
|
||||
theme: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -335,9 +396,13 @@ impl BlocksContext {
|
|||
/// key of the peer.
|
||||
#[get("/blocks")]
|
||||
pub fn blocks(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = BlocksContext::build();
|
||||
context.back = Some("/scuttlebutt/peers".to_string());
|
||||
context.title = Some("Blocks".to_string());
|
||||
context.theme = Some(theme);
|
||||
|
||||
// check to see if there is a flash message to display
|
||||
if let Some(flash) = flash {
|
||||
|
@ -345,5 +410,6 @@ pub fn blocks(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
|||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
|
||||
Template::render("scuttlebutt/peers_list", &context)
|
||||
}
|
||||
|
|
|
@ -12,13 +12,18 @@ use peach_lib::config_manager;
|
|||
|
||||
use crate::error::PeachWebError;
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::utils;
|
||||
|
||||
// HELPERS AND ROUTES FOR /settings/admin
|
||||
|
||||
/// Administrator settings menu.
|
||||
#[get("/")]
|
||||
pub fn admin_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("theme", &theme);
|
||||
context.insert("back", &Some("/settings".to_string()));
|
||||
context.insert("title", &Some("Administrator Settings".to_string()));
|
||||
|
||||
|
@ -36,7 +41,11 @@ pub fn admin_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template
|
|||
/// View and delete currently configured admin.
|
||||
#[get("/configure")]
|
||||
pub fn configure_admin(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("theme", &theme);
|
||||
context.insert("back", &Some("/settings/admin".to_string()));
|
||||
context.insert("title", &Some("Configure Admin".to_string()));
|
||||
|
||||
|
@ -81,7 +90,11 @@ pub fn save_add_admin_form(admin_form: AddAdminForm) -> Result<(), PeachWebError
|
|||
|
||||
#[get("/add")]
|
||||
pub fn add_admin(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("theme", &theme);
|
||||
context.insert("back", &Some("/settings/admin/configure".to_string()));
|
||||
context.insert("title", &Some("Add Admin".to_string()));
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ use peach_lib::{
|
|||
|
||||
use crate::{
|
||||
context::dns::ConfigureDNSContext, error::PeachWebError, routes::authentication::Authenticated,
|
||||
utils,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, FromForm)]
|
||||
|
@ -76,11 +77,14 @@ pub fn save_dns_configuration(dns_form: DnsForm) -> Result<(), PeachWebError> {
|
|||
|
||||
#[get("/dns")]
|
||||
pub fn configure_dns(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
let mut context = ConfigureDNSContext::build();
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = ConfigureDNSContext::build();
|
||||
// set back icon link to network route
|
||||
context.back = Some("/settings/network".to_string());
|
||||
context.title = Some("Configure DNS".to_string());
|
||||
context.theme = Some(theme);
|
||||
|
||||
// check to see if there is a flash message to display
|
||||
if let Some(flash) = flash {
|
||||
|
|
|
@ -2,6 +2,7 @@ use rocket::{get, request::FlashMessage, State};
|
|||
use rocket_dyn_templates::{tera::Context, Template};
|
||||
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::utils;
|
||||
use crate::RocketConfig;
|
||||
|
||||
// HELPERS AND ROUTES FOR /settings
|
||||
|
@ -13,7 +14,11 @@ pub fn settings_menu(
|
|||
flash: Option<FlashMessage>,
|
||||
config: &State<RocketConfig>,
|
||||
) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("theme", &theme);
|
||||
context.insert("back", &Some("/".to_string()));
|
||||
context.insert("title", &Some("Settings".to_string()));
|
||||
|
||||
|
|
|
@ -3,3 +3,4 @@ pub mod dns;
|
|||
pub mod menu;
|
||||
pub mod network;
|
||||
pub mod scuttlebutt;
|
||||
pub mod theme;
|
||||
|
|
|
@ -15,6 +15,7 @@ use rocket::{
|
|||
use rocket_dyn_templates::{tera::Context, Template};
|
||||
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::utils;
|
||||
|
||||
#[derive(Debug, Deserialize, FromForm)]
|
||||
pub struct SbotConfigForm {
|
||||
|
@ -58,10 +59,14 @@ pub struct SbotConfigForm {
|
|||
/// Scuttlebutt settings menu.
|
||||
#[get("/")]
|
||||
pub fn ssb_settings_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
// retrieve go-sbot systemd process status
|
||||
let sbot_status = SbotStatus::read().ok();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("theme", &theme);
|
||||
context.insert("sbot_status", &sbot_status);
|
||||
context.insert("back", &Some("/settings".to_string()));
|
||||
context.insert("title", &Some("Scuttlebutt Settings".to_string()));
|
||||
|
@ -77,6 +82,9 @@ pub fn ssb_settings_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> T
|
|||
/// Sbot configuration page (includes form for updating configuration parameters).
|
||||
#[get("/configure")]
|
||||
pub fn configure_sbot(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
// retrieve go-sbot systemd process status
|
||||
let sbot_status = SbotStatus::read().ok();
|
||||
let run_on_startup = sbot_status.map(|status| status.boot_state);
|
||||
|
@ -85,6 +93,7 @@ pub fn configure_sbot(flash: Option<FlashMessage>, _auth: Authenticated) -> Temp
|
|||
let sbot_config = SbotConfig::read().ok();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("theme", &theme);
|
||||
context.insert("back", &Some("/settings/scuttlebutt".to_string()));
|
||||
context.insert("title", &Some("Sbot Configuration".to_string()));
|
||||
context.insert("sbot_config", &sbot_config);
|
||||
|
@ -135,16 +144,14 @@ pub fn configure_sbot_post(
|
|||
match owned_config.startup {
|
||||
true => {
|
||||
info!("Enabling go-sbot.service");
|
||||
match systemctl_sbot_cmd("enable") {
|
||||
Err(e) => warn!("Failed to enable go-sbot.service: {}", e),
|
||||
_ => (),
|
||||
if let Err(e) = systemctl_sbot_cmd("enable") {
|
||||
warn!("Failed to enable go-sbot.service: {}", e)
|
||||
}
|
||||
}
|
||||
false => {
|
||||
info!("Disabling go-sbot.service");
|
||||
match systemctl_sbot_cmd("disable") {
|
||||
Err(e) => warn!("Failed to disable go-sbot.service: {}", e),
|
||||
_ => (),
|
||||
if let Err(e) = systemctl_sbot_cmd("disable") {
|
||||
warn!("Failed to disable go-sbot.service: {}", e)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
use rocket::{get, response::Redirect};
|
||||
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::{utils, utils::Theme};
|
||||
|
||||
/// Set the user-interface theme according to the query parameter value.
|
||||
#[get("/theme?<theme>")]
|
||||
pub fn set_theme(_auth: Authenticated, theme: &str) -> Redirect {
|
||||
match theme {
|
||||
"light" => utils::set_theme(Theme::Light),
|
||||
"dark" => utils::set_theme(Theme::Dark),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
Redirect::to("/")
|
||||
}
|
|
@ -3,18 +3,24 @@ use rocket::{get, State};
|
|||
use rocket_dyn_templates::{tera::Context, Template};
|
||||
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::utils;
|
||||
use crate::RocketConfig;
|
||||
|
||||
// HELPERS AND ROUTES FOR /status/scuttlebutt
|
||||
|
||||
#[get("/scuttlebutt")]
|
||||
pub fn scuttlebutt_status(_auth: Authenticated, config: &State<RocketConfig>) -> Template {
|
||||
// retrieve current ui theme
|
||||
let theme = utils::get_theme();
|
||||
|
||||
// retrieve go-sbot systemd process status
|
||||
let sbot_status = SbotStatus::read().ok();
|
||||
|
||||
// retrieve go-sbot configuration parameters
|
||||
let sbot_config = SbotConfig::read().ok();
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("theme", &theme);
|
||||
context.insert("sbot_status", &sbot_status);
|
||||
context.insert("sbot_config", &sbot_config);
|
||||
context.insert("flash_name", &None::<()>);
|
||||
|
|
|
@ -1,9 +1,33 @@
|
|||
pub mod monitor;
|
||||
|
||||
use rocket_dyn_templates::Template;
|
||||
|
||||
use log::info;
|
||||
use rocket::response::{Redirect, Responder};
|
||||
use rocket::serde::Serialize;
|
||||
use rocket_dyn_templates::Template;
|
||||
|
||||
use crate::THEME;
|
||||
|
||||
// THEME FUNCTIONS
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum Theme {
|
||||
Light,
|
||||
Dark,
|
||||
}
|
||||
|
||||
pub fn get_theme() -> String {
|
||||
let current_theme = THEME.read().unwrap();
|
||||
match *current_theme {
|
||||
Theme::Dark => "dark".to_string(),
|
||||
_ => "light".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_theme(theme: Theme) {
|
||||
info!("set ui theme to: {:?}", theme);
|
||||
let mut writable_theme = THEME.write().unwrap();
|
||||
*writable_theme = theme;
|
||||
}
|
||||
|
||||
// HELPER FUNCTIONS
|
||||
|
||||
|
|
|
@ -166,6 +166,40 @@
|
|||
--light: var(--light-gray);
|
||||
--dark: var(--near-black);
|
||||
|
||||
/* LIGHT (default) THEME VARIABLES */
|
||||
|
||||
--background: var(--moon-gray);
|
||||
--button-background: var(--light-gray);
|
||||
--circle-background: var(--light-gray);
|
||||
--circle-small-hover-background: var(--white);
|
||||
|
||||
--color-ssb: var(--hot-pink);
|
||||
--color-settings: var(--purple);
|
||||
--color-status: var(--green);
|
||||
--color-info: var(--info);
|
||||
|
||||
--capsule-background: var(--light-gray);
|
||||
|
||||
--text-color-normal: var(--near-black);
|
||||
--text-color-gray: var(--mid-gray);
|
||||
--text-color-light-gray: var(--moon-gray);
|
||||
--text-color-light: var(--white);
|
||||
|
||||
--icon-normal: invert(0%) sepia(1%) saturate(100%) hue-rotate(79deg) brightness(86%) contrast(87%);
|
||||
--icon-gray: invert(72%) sepia(8%) saturate(14%) hue-rotate(316deg) brightness(93%) contrast(92%);
|
||||
--icon-light: invert();
|
||||
|
||||
/* DARK THEME VARIABLES */
|
||||
|
||||
/*--background-dark: var(--dark-gray);*/
|
||||
--background-dark: #222;
|
||||
--button-background-dark: var(--mid-gray);
|
||||
/*--capsule-background-dark: var(--light-gray);*/
|
||||
--capsule-background-dark: #333;
|
||||
--circle-background-dark: var(--silver);
|
||||
--circle-small-hover-background-dark: var(--moon-gray);
|
||||
|
||||
}
|
||||
/* we need to add shades for each accent colour
|
||||
*
|
||||
* --info-100
|
||||
|
@ -174,4 +208,3 @@
|
|||
* --info-400
|
||||
* --info-500
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
* - NAVIGATION
|
||||
* - PARAGRAPHS
|
||||
* - SWITCHES / SLIDERS
|
||||
* - TEXT
|
||||
* - TITLES
|
||||
*
|
||||
\* ------------------------------ */
|
||||
|
||||
|
@ -128,13 +130,57 @@
|
|||
*/
|
||||
|
||||
body {
|
||||
background-color: var(--moon-gray);
|
||||
background-color: var(--background);
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* BORDERS
|
||||
*/
|
||||
|
||||
.border-circle-small {
|
||||
border: 4px solid;
|
||||
}
|
||||
|
||||
.border-settings {
|
||||
border-color: var(--color-settings);
|
||||
}
|
||||
|
||||
.border-ssb {
|
||||
border-color: var(--color-ssb);
|
||||
}
|
||||
|
||||
.border-status {
|
||||
border-color: var(--color-status);
|
||||
}
|
||||
|
||||
.border-primary {
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
.border-success {
|
||||
border-color: var(--success);
|
||||
}
|
||||
|
||||
.border-info {
|
||||
border-color: var(--info);
|
||||
}
|
||||
|
||||
.border-warning {
|
||||
border-color: var(--warning);
|
||||
}
|
||||
|
||||
.border-danger {
|
||||
border-color: var(--danger);
|
||||
}
|
||||
|
||||
.border-dark-gray {
|
||||
border-color: var(--dark-gray);
|
||||
}
|
||||
|
||||
/*
|
||||
* BUTTONS
|
||||
*/
|
||||
|
@ -146,7 +192,7 @@ body {
|
|||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
color: var(--near-black);
|
||||
color: var(--button-text-color);
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
|
@ -169,37 +215,42 @@ body {
|
|||
}
|
||||
|
||||
.button-primary {
|
||||
background-color: var(--light-gray);
|
||||
background-color: var(--button-background);
|
||||
}
|
||||
|
||||
.button-primary:hover {
|
||||
background-color: var(--primary);
|
||||
color: var(--button-text-hover-color);
|
||||
}
|
||||
|
||||
.button-primary:focus {
|
||||
background-color: var(--primary);
|
||||
color: var(--button-text-hover-color);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.button-secondary {
|
||||
background-color: var(--light-gray);
|
||||
background-color: var(--button-background);
|
||||
}
|
||||
|
||||
.button-secondary:hover {
|
||||
background-color: var(--light-silver);
|
||||
color: var(--button-text-hover-color);
|
||||
}
|
||||
|
||||
.button-secondary:focus {
|
||||
background-color: var(--light-silver);
|
||||
color: var(--button-text-hover-color);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.button-warning {
|
||||
background-color: var(--light-gray);
|
||||
background-color: var(--button-background);
|
||||
}
|
||||
|
||||
.button-warning:hover {
|
||||
background-color: var(--light-red);
|
||||
color: var(--button-text-hover-color);
|
||||
}
|
||||
|
||||
.button-warning:focus {
|
||||
|
@ -213,9 +264,9 @@ body {
|
|||
|
||||
.capsule {
|
||||
padding: 1rem;
|
||||
border: var(--border-width-1) solid;
|
||||
border-style: solid;
|
||||
border-radius: var(--border-radius-3);
|
||||
background-color: var(--light-gray);
|
||||
background-color: var(--capsule-background);
|
||||
/* margin-top: 1rem; */
|
||||
/* margin-bottom: 1rem; */
|
||||
}
|
||||
|
@ -272,6 +323,7 @@ body {
|
|||
}
|
||||
|
||||
.card-text {
|
||||
color: var(--text-color);
|
||||
margin: 0;
|
||||
font-size: var(--font-size-5);
|
||||
padding-bottom: 0.3rem;
|
||||
|
@ -294,7 +346,7 @@ body {
|
|||
|
||||
.circle {
|
||||
align-items: center;
|
||||
background: var(--light-gray);
|
||||
background: var(--circle-background);
|
||||
border-radius: 50%;
|
||||
box-shadow: var(--box-shadow-3);
|
||||
display: flex;
|
||||
|
@ -307,6 +359,15 @@ body {
|
|||
width: 5rem;
|
||||
}
|
||||
|
||||
.circle-small:hover {
|
||||
background: var(--circle-small-hover-background);
|
||||
}
|
||||
|
||||
.circle-small:focus {
|
||||
background: var(--circle-small-hover-background);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.circle-medium {
|
||||
height: 8rem;
|
||||
width: 8rem;
|
||||
|
@ -391,30 +452,6 @@ body {
|
|||
background-color: var(--light);
|
||||
}
|
||||
|
||||
.primary-border {
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
.success-border {
|
||||
border-color: var(--success);
|
||||
}
|
||||
|
||||
.info-border {
|
||||
border-color: var(--info);
|
||||
}
|
||||
|
||||
.warning-border {
|
||||
border-color: var(--warning);
|
||||
}
|
||||
|
||||
.danger-border {
|
||||
border-color: var(--danger);
|
||||
}
|
||||
|
||||
.dark-gray-border {
|
||||
border-color: var(--dark-gray);
|
||||
}
|
||||
|
||||
/*
|
||||
* GRIDS
|
||||
*/
|
||||
|
@ -555,6 +592,30 @@ body {
|
|||
|
||||
html {
|
||||
height: 100%;
|
||||
|
||||
--background: var(--background);
|
||||
--button-background: var(--button-background);
|
||||
--button-text-color: var(--text-color-normal);
|
||||
--button-text-hover-color: var(--text-color-normal);
|
||||
--circle-background: var(--circle-background);
|
||||
--circle-small-hover-background: var(--circle-small-hover-background);
|
||||
--icon-color: var(--icon-normal);
|
||||
--nav-icon-color: var(--nav-icon-color);
|
||||
--text-color: var(--text-color-normal);
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
--background: var(--background-dark);
|
||||
--button-background: var(--button-background-dark);
|
||||
--button-text-color: var(--text-color-light);
|
||||
--button-text-hover-color: var(--text-color-normal);
|
||||
--capsule-background: var(--capsule-background-dark);
|
||||
--circle-background: var(--circle-background-dark);
|
||||
--circle-small-hover-background: var(--circle-small-hover-background-dark);
|
||||
--icon-color: var(--icon-light);
|
||||
--nav-icon-color: var(--nav-icon-color-light);
|
||||
--text-color: var(--text-color-light);
|
||||
--text-color-gray: var(--text-color-light-gray);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -573,28 +634,21 @@ html {
|
|||
* FONTS
|
||||
*/
|
||||
|
||||
.font-normal {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.font-near-black {
|
||||
color: var(--near-black);
|
||||
}
|
||||
|
||||
.font-gray {
|
||||
color: var(--mid-gray);
|
||||
color: var(--text-color-gray);
|
||||
}
|
||||
|
||||
.font-light-gray {
|
||||
color: var(--silver);
|
||||
}
|
||||
|
||||
.font-success {
|
||||
color: var(--success);
|
||||
}
|
||||
|
||||
.font-warning {
|
||||
color: var(--warning);
|
||||
}
|
||||
|
||||
.font-failure {
|
||||
color: var(--danger);
|
||||
/* color: var(--silver); */
|
||||
color: var(--text-color-light-gray);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -637,12 +691,12 @@ form {
|
|||
|
||||
/* icon-active: sets color of icon svg to near-black */
|
||||
.icon-active {
|
||||
filter: invert(0%) sepia(1%) saturate(4171%) hue-rotate(79deg) brightness(86%) contrast(87%);
|
||||
filter: var(--icon-color);
|
||||
}
|
||||
|
||||
/* icon-inactive: sets color of icon svg to gray */
|
||||
.icon-inactive {
|
||||
filter: invert(72%) sepia(8%) saturate(14%) hue-rotate(316deg) brightness(93%) contrast(92%);
|
||||
filter: var(--icon-gray);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -699,10 +753,11 @@ form {
|
|||
font-family: var(--sans-serif);
|
||||
font-size: var(--font-size-7);
|
||||
display: block;
|
||||
margin-bottom: 2px;
|
||||
/* margin-bottom: 2px; */
|
||||
}
|
||||
|
||||
.label-medium {
|
||||
color: var(--text-color);
|
||||
font-size: var(--font-size-3);
|
||||
display: block;
|
||||
}
|
||||
|
@ -728,7 +783,7 @@ form {
|
|||
|
||||
.link {
|
||||
text-decoration: none;
|
||||
color: var(--font-near-black);
|
||||
/* color: var(--font-near-black); */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -861,6 +916,7 @@ meter::-moz-meter-bar {
|
|||
}
|
||||
|
||||
.nav-title {
|
||||
color: var(--text-color);
|
||||
font-family: var(--sans-serif);
|
||||
font-size: var(--font-size-4);
|
||||
font-weight: normal;
|
||||
|
@ -976,6 +1032,26 @@ input:checked + .slider:before {
|
|||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/*
|
||||
* TEXT
|
||||
*/
|
||||
|
||||
.text-info {
|
||||
color: var(--info);
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: var(--success);
|
||||
}
|
||||
|
||||
.text-warning {
|
||||
color: var(--warning);
|
||||
}
|
||||
|
||||
/*
|
||||
* TITLES
|
||||
*/
|
||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 57 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 57 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
|
||||
<html lang="en">
|
||||
<html lang="en"{% if theme %} data-theme="{{ theme }}"{% endif %}>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>PeachCloud</title>
|
||||
|
|
|
@ -2,16 +2,9 @@
|
|||
{%- block card %}
|
||||
<!-- HELP MENU -->
|
||||
<div class="card center">
|
||||
<div class="card-container">
|
||||
<div class="capsule capsule-container border-info">
|
||||
<!-- FLASH MESSAGE -->
|
||||
<!-- check for flash message and display accordingly -->
|
||||
{%- if flash_msg and flash_name == "success" %}
|
||||
<!-- display success message -->
|
||||
<div class="center-text flash-message font-success" style="padding-left: 5px;">{{ flash_msg }}.</div>
|
||||
{%- elif flash_msg and flash_name == "error" %}
|
||||
<!-- display error message -->
|
||||
<div class="center-text flash-message font-failure" style="padding-left: 5px;">{{ flash_msg }}.</div>
|
||||
{%- endif %}
|
||||
{% include "snippets/flash_message" %}
|
||||
</div>
|
||||
</div>
|
||||
{%- endblock card -%}
|
||||
|
|
|
@ -5,27 +5,39 @@
|
|||
<!-- top-left -->
|
||||
<!-- PEERS LINK AND ICON -->
|
||||
<a class="top-left" href="/scuttlebutt/peers" title="Scuttlebutt Peers">
|
||||
<div class="circle circle-small">
|
||||
<div class="circle circle-small border-circle-small border-ssb">
|
||||
<img class="icon-medium" src="/icons/users.svg">
|
||||
</div>
|
||||
</a>
|
||||
<!-- top-middle -->
|
||||
<!-- CURRENT USER LINK AND ICON -->
|
||||
<a class="top-middle" href="/scuttlebutt/profile" title="Profile">
|
||||
<div class="circle circle-small">
|
||||
<div class="circle circle-small border-circle-small border-ssb">
|
||||
<img class="icon-medium" src="/icons/user.svg">
|
||||
</div>
|
||||
</a>
|
||||
<!-- top-right -->
|
||||
<!-- MESSAGES LINK AND ICON -->
|
||||
<a class="top-right" href="/scuttlebutt/private" title="Private Messages">
|
||||
<div class="circle circle-small">
|
||||
<div class="circle circle-small border-circle-small border-ssb">
|
||||
<img class="icon-medium" src="/icons/envelope.svg">
|
||||
</div>
|
||||
</a>
|
||||
<!-- middle -->
|
||||
<a class="middle">
|
||||
<div class="circle circle-large {% if sbot_status.state == "active" %}circle-success{% else %}circle-error{% endif %}"></div>
|
||||
{% if sbot_status.state == "active" %}
|
||||
<div class="circle circle-large circle-success">
|
||||
<p style="font-size: 4rem; color: var(--near-black);">^_^</p>
|
||||
</div>
|
||||
{% elif sbot_status.state == "inactive" %}
|
||||
<div class="circle circle-large circle-warning">
|
||||
<p style="font-size: 4rem; color: var(--near-black);">z_z</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="circle circle-large circle-error">
|
||||
<p style="font-size: 4rem; color: var(--near-black);">x_x</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</a>
|
||||
<!-- bottom-left -->
|
||||
<!-- SYSTEM STATUS LINK AND ICON -->
|
||||
|
@ -34,21 +46,21 @@
|
|||
{% else -%}
|
||||
<a class="bottom-left" href="/status" title="Status">
|
||||
{%- endif -%}
|
||||
<div class="circle circle-small">
|
||||
<div class="circle circle-small border-circle-small {% if sbot_status.state == "active" %}border-success{% elif sbot_status.state == "inactive" %}border-warning{% else %}border-danger{% endif %}">
|
||||
<img class="icon-medium" src="/icons/heart-pulse.svg">
|
||||
</div>
|
||||
</a>
|
||||
<!-- bottom-middle -->
|
||||
<!-- PEACHCLOUD GUIDEBOOK LINK AND ICON -->
|
||||
<a class="bottom-middle" href="/help" title="Help Menu">
|
||||
<div class="circle circle-small">
|
||||
<div class="circle circle-small border-circle-small border-info">
|
||||
<img class="icon-medium" src="/icons/book.svg">
|
||||
</div>
|
||||
</a>
|
||||
<!-- bottom-right -->
|
||||
<!-- SYSTEM SETTINGS LINK AND ICON -->
|
||||
<a class="bottom-right" href="/settings" title="Settings Menu">
|
||||
<div class="circle circle-small">
|
||||
<div class="circle circle-small border-circle-small border-settings">
|
||||
<img class="icon-medium" src="/icons/cog.svg">
|
||||
</div>
|
||||
</a>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<!-- LOGIN FORM -->
|
||||
<div class="card center">
|
||||
<div class="card-container">
|
||||
<form id="login_form" action="/login" method="post">
|
||||
<form id="login_form" class="center" action="/login" method="post">
|
||||
<!-- input for username -->
|
||||
<input id="username" name="username" class="center input" type="text" placeholder="Username" title="Username for authentication" autofocus/>
|
||||
<!-- input for password -->
|
||||
|
@ -12,12 +12,10 @@
|
|||
<input id="loginUser" class="button button-primary center" title="Login" type="submit" value="Login">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- FLASH MESSAGE -->
|
||||
{% include "snippets/flash_message" %}
|
||||
|
||||
<div class="center-text" style="margin-top: 25px;">
|
||||
<a href="/settings/admin/forgot_password" class="label-small link">Forgot Password?</a>
|
||||
<a href="/settings/admin/forgot_password" class="label-small link font-gray">Forgot Password?</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -17,13 +17,25 @@
|
|||
<!-- Bottom nav bar -->
|
||||
<nav class="nav-bar">
|
||||
<a class="nav-item" href="https://scuttlebutt.nz/">
|
||||
<img class="icon-medium nav-icon-left" title="Scuttlebutt Website" src="/icons/hermies.png" alt="Secure Scuttlebutt">
|
||||
<img class="icon-medium nav-icon-left" title="Scuttlebutt Website" src="/icons/hermies_hex{% if theme and theme == "dark" %}_light{% endif %}.svg" alt="Secure Scuttlebutt">
|
||||
</a>
|
||||
<a class="nav-item" href="/">
|
||||
<img class="icon nav-icon-left" src="/icons/peach-icon.png" alt="PeachCloud" title="Home">
|
||||
</a>
|
||||
<a class="nav-item" href="/power">
|
||||
<img class="icon-medium nav-icon-right icon-active" title="Shutdown" src="/icons/power.svg" alt="Power switch">
|
||||
{# only render a theme-switcher icon if the `theme` variable has been set #}
|
||||
{% if theme and theme == "light" %}
|
||||
<a class="nav-item" href="/theme?theme=dark">
|
||||
<img class="icon-medium nav-icon-right icon-active" title="Toggle theme" src="/icons/moon.png" alt="Moon">
|
||||
</a>
|
||||
{% elif theme and theme == "dark" %}
|
||||
<a class="nav-item" href="/theme?theme=light">
|
||||
<img class="icon-medium nav-icon-right icon-active" title="Toggle theme" src="/icons/sun.png" alt="Sun">
|
||||
</a>
|
||||
{% else %}
|
||||
{# render hidden element to maintain correctly alignment of other bottom nav icons #}
|
||||
<a class="nav-item" style="visibility: hidden;" href="/theme?theme=light">
|
||||
<img class="icon-medium nav-icon-right icon-active" title="Toggle theme" src="/icons/sun.png" alt="Sun">
|
||||
</a>
|
||||
{% endif %}
|
||||
</nav>
|
||||
{%- endblock nav -%}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{%- block card %}
|
||||
<!-- SCUTTLEBUTT MESSAGES -->
|
||||
<div class="card center">
|
||||
<div class="card-container">
|
||||
<div class="capsule capsule-container border-ssb">
|
||||
<!-- FLASH MESSAGE -->
|
||||
{% include "snippets/flash_message" %}
|
||||
</div>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<!-- PROFILE INFO BOX -->
|
||||
<div class="capsule capsule-profile" title="Scuttlebutt account profile information">
|
||||
<!-- edit profile button -->
|
||||
<img id="editProfile" class="icon-small nav-icon-right" src="/icons/pencil.svg" alt="Profile picture">
|
||||
<img id="editProfile" class="icon-small icon-active nav-icon-right" src="/icons/pencil.svg" alt="Profile picture">
|
||||
<!-- PROFILE BIO -->
|
||||
<!-- profile picture -->
|
||||
<img id="profilePicture" class="icon-large" src="{ image_path }" alt="Profile picture">
|
||||
|
@ -15,14 +15,14 @@
|
|||
<p id="profileDescription" style="margin-top: 1rem" class="card-text" title="Description">{ description }</p>
|
||||
</div>
|
||||
<!-- PUBLIC POST FORM -->
|
||||
<form id="postForm" action="/scuttlebutt/post" method="post">
|
||||
<form id="postForm" class="center" action="/scuttlebutt/post" method="post">
|
||||
<!-- input for message contents -->
|
||||
<textarea id="publicPost" class="center input message-input" title="Compose Public Post"></textarea>
|
||||
<input id="publishPost" class="button button-primary center" title="Publish" type="submit" value="Publish">
|
||||
</form>
|
||||
<!-- BUTTONS -->
|
||||
<!-- TODO: each of these buttons needs to be a form with a public key -->
|
||||
<div id="buttons">
|
||||
<div id="buttons" style="margin-top: 2rem;">
|
||||
<a id="followPeer" class="button button-primary center" href="/scuttlebutt/follow" title="Follow Peer">Follow</a>
|
||||
<a id="blockPeer" class="button button-warning center" href="/scuttlebutt/block" title="Block Peer">Block</a>
|
||||
<a id="privateMessage" class="button button-primary center" href="/scuttlebutt/private_message" title="Private Message">Private Message</a>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{%- block card %}
|
||||
<!-- CHANGE PASSWORD FORM -->
|
||||
<div class="card center">
|
||||
<form id="changePassword" action="/settings/admin/change_password" method="post">
|
||||
<form id="changePassword" class="center" action="/settings/admin/change_password" method="post">
|
||||
<!-- input for current password -->
|
||||
<input id="currentPassword" class="center input" name="current_password" type="password" placeholder="Current password" title="Current password" autofocus>
|
||||
<!-- input for new password -->
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
<!-- CONFIGURE ADMIN PAGE -->
|
||||
<div class="card center">
|
||||
<div class="text-container">
|
||||
<h4> Current Admins </h4>
|
||||
<h4 class="font-normal">Current Admins</h4>
|
||||
{% if not ssb_admin_ids %}
|
||||
<div>
|
||||
<div class="card-text">
|
||||
There are no currently configured admins.
|
||||
</div>
|
||||
{% else %}
|
||||
|
|
|
@ -15,57 +15,59 @@
|
|||
<!-- SBOT CONFIGURATION FORM -->
|
||||
<div class="card center">
|
||||
<form id="sbotConfig" class="center" action="/settings/scuttlebutt/configure" method="post">
|
||||
<div class="center" style="display: flex; flex-direction: column;" title="Number of hops to replicate">
|
||||
<label for="hops" class="label-small">HOPS</label>
|
||||
<div class="center" style="display: flex; flex-direction: column; margin-bottom: 2rem;" title="Number of hops to replicate">
|
||||
<label for="hops" class="label-small font-gray">HOPS</label>
|
||||
<div id="hops" style="display: flex; justify-content: space-evenly;">
|
||||
<div>
|
||||
<input type="radio" id="hops_0" name="hops" value="0"{% if hops == 0 %} checked{% endif %}>
|
||||
<label for="hops_0">0</label>
|
||||
<label class="font-normal" for="hops_0">0</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="hops_1" name="hops" value="1"{% if hops == 1 %} checked{% endif %}>
|
||||
<label for="hops_1">1</label>
|
||||
<label class="font-normal" for="hops_1">1</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="hops_2" name="hops" value="2"{% if hops == 2 %} checked{% endif %}>
|
||||
<label for="hops_2">2</label>
|
||||
<label class="font-normal" for="hops_2">2</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="hops_3" name="hops" value="3"{% if hops == 3 %} checked{% endif %}>
|
||||
<label for="hops_3">3</label>
|
||||
<label class="font-normal" for="hops_3">3</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="hops_4" name="hops" value="4"{% if hops == 4 %} checked{% endif %}>
|
||||
<label for="hops_4">4</label><br>
|
||||
<label class="font-normal" for="hops_4">4</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="center" style="display: flex; justify-content: space-between;">
|
||||
<div style="display: flex; flex-direction: column; width: 60%;" title="IP address on which the sbot runs">
|
||||
<label for="ip" class="label-small">IP ADDRESS</label>
|
||||
<div style="display: flex; flex-direction: column; width: 60%; margin-bottom: 2rem;" title="IP address on which the sbot runs">
|
||||
<label for="ip" class="label-small font-gray">IP ADDRESS</label>
|
||||
<input type="text" id="ip" name="lis_ip" value="{{ listen_addr.0 }}">
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; width: 20%;" title="Port on which the sbot runs">
|
||||
<label for="port" class="label-small">PORT</label>
|
||||
<div style="display: flex; flex-direction: column; width: 20%; margin-bottom: 2rem;" title="Port on which the sbot runs">
|
||||
<label for="port" class="label-small font-gray">PORT</label>
|
||||
<input type="text" id="port" name="lis_port" value="{{ listen_addr.1 }}">
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="center" style="display: flex; flex-direction: column;" title="Network key (aka 'caps key') to define the Scuttleverse in which the sbot operates in">
|
||||
<label for="network_key" class="label-small">NETWORK KEY</label>
|
||||
<div class="center" style="display: flex; flex-direction: column; margin-bottom: 2rem;" title="Network key (aka 'caps key') to define the Scuttleverse in which the sbot operates in">
|
||||
<label for="network_key" class="label-small font-gray">NETWORK KEY</label>
|
||||
<input type="text" id="network_key" name="shscap" value="{{ sbot_config.shscap }}">
|
||||
</div>
|
||||
<br>
|
||||
<div class="center" style="display: flex; flex-direction: column;" title="Directory in which the sbot database is saved">
|
||||
<label for="database_dir" class="label-small">DATABASE DIRECTORY</label>
|
||||
<div class="center" style="display: flex; flex-direction: column; margin-bottom: 2rem;" title="Directory in which the sbot database is saved">
|
||||
<label for="database_dir" class="label-small font-gray">DATABASE DIRECTORY</label>
|
||||
<input type="text" id="database_dir" name="repo" value="{{ sbot_config.repo }}">
|
||||
</div>
|
||||
<br>
|
||||
<div class="center">
|
||||
<input type="checkbox" id="lanBroadcast" name="localadv"{% if sbot_config.localadv == true %} checked{% endif %}>
|
||||
<label for="lanBroadcast" title="Broadcast the IP and port of this sbot instance so that local peers can discovery it and attempt to connect">Enable LAN Broadcasting</label><br>
|
||||
<br>
|
||||
<input type="checkbox" id="lanDiscovery" name="localdiscov"{% if sbot_config.localdiscov == true %} checked{% endif %}>
|
||||
<label for="lanDiscovery" title="Listen for the presence of local peers and attempt to connect if found">Enable LAN Discovery</label><br>
|
||||
<br>
|
||||
<input type="checkbox" id="startup" name="startup"{% if run_on_startup == "enabled" %} checked{% endif %}>
|
||||
<label for="startup" title="Run the pub automatically on system startup">Run pub on system startup</label><br>
|
||||
<br>
|
||||
<input type="checkbox" id="lanBroadcast" style="margin-bottom: 1rem;" name="localadv"{% if sbot_config.localadv == true %} checked{% endif %}>
|
||||
<label class="font-normal" for="lanBroadcast" title="Broadcast the IP and port of this sbot instance so that local peers can discovery it and attempt to connect">Enable LAN Broadcasting</label><br>
|
||||
<input type="checkbox" id="lanDiscovery" style="margin-bottom: 1rem;" name="localdiscov"{% if sbot_config.localdiscov == true %} checked{% endif %}>
|
||||
<label class="font-normal" for="lanDiscovery" title="Listen for the presence of local peers and attempt to connect if found">Enable LAN Discovery</label><br>
|
||||
<input type="checkbox" id="startup" style="margin-bottom: 1rem;" name="startup"{% if run_on_startup == "enabled" %} checked{% endif %}>
|
||||
<label class="font-normal" for="startup" title="Run the pub automatically on system startup">Run pub when computer starts</label><br>
|
||||
<input type="checkbox" id="repair" name="repair"{% if sbot_config.repair == true %} checked{% endif %}>
|
||||
<label for="repair" title="Attempt to repair the filesystem before starting the pub">Attempt filesystem repair when pub starts</label><br>
|
||||
<label class="font-normal" for="repair" title="Attempt to repair the filesystem when starting the pub">Attempt filesystem repair when pub starts</label>
|
||||
</div>
|
||||
<br>
|
||||
<!-- hidden input elements for all other config variables -->
|
||||
<input type="hidden" id="debugdir" name="debugdir" value="{{ sbot_config.debugdir }}">
|
||||
<input type="hidden" id="hmac" name="hmac" value="{{ sbot_config.hmac }}">
|
||||
|
@ -75,7 +77,7 @@
|
|||
<input type="hidden" id="promisc" name="promisc" value="{{ sbot_config.promisc }}">
|
||||
<input type="hidden" id="nounixsock" name="nounixsock" value="{{ sbot_config.nounixsock }}">
|
||||
<!-- BUTTONS -->
|
||||
<input id="saveConfig" class="button button-primary center" type="submit" title="Save configuration parameters to file" value="Save">
|
||||
<input id="saveConfig" class="button button-primary center" style="margin-top: 2rem;" type="submit" title="Save configuration parameters to file" value="Save">
|
||||
<input id="saveRestartConfig" class="button button-primary center" type="submit" title="Save configuration parameters to file and then (re)start the pub" value="Save & Restart" formaction="/settings/scuttlebutt/configure?restart=true">
|
||||
<a id="restoreDefaults" class="button button-warning center" href="/settings/scuttlebutt/configure/default" title="Restore default configuration parameters and save them to file">Restore Defaults</a>
|
||||
</form>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<!-- check for flash message and display accordingly -->
|
||||
{% if flash_msg and flash_name == "success" %}
|
||||
<!-- display success message -->
|
||||
<div class="capsule center-text flash-message font-success">{{ flash_msg }}.</div>
|
||||
<div class="capsule center-text flash-message font-normal border-success">{{ flash_msg }}.</div>
|
||||
{%- elif flash_msg and flash_name == "info" %}
|
||||
<!-- display info message -->
|
||||
<div class="capsule center-text flash-message font-info">{{ flash_msg }}.</div>
|
||||
<div class="capsule center-text flash-message font-normal border-info">{{ flash_msg }}.</div>
|
||||
{%- elif flash_msg and flash_name == "error" %}
|
||||
<!-- display error message -->
|
||||
<div class="capsule center-text flash-message font-failure">{{ flash_msg }}.</div>
|
||||
<div class="capsule center-text flash-message font-normal border-danger">{{ flash_msg }}.</div>
|
||||
{%- endif -%}
|
|
@ -6,21 +6,26 @@
|
|||
{% set mem = sbot_status.memory / 1024 / 1024 | round -%}
|
||||
{%- else -%}
|
||||
{% set mem = "X" -%}
|
||||
{%- endif -%}
|
||||
{%- if sbot_status.blobstore -%}
|
||||
{% set blobs = sbot_status.blobstore / 1024 / 1024 | round -%}
|
||||
{%- else -%}
|
||||
{% set blobs = "X" -%}
|
||||
{%- endif -%}
|
||||
<!-- SCUTTLEBUTT STATUS -->
|
||||
<div class="card center">
|
||||
<!-- SBOT INFO BOX -->
|
||||
<div class="capsule capsule-container {% if sbot_status.state == "active" %}success-border{% else %}warning-border{% endif %}">
|
||||
<div class="capsule capsule-container {% if sbot_status.state == "active" %}border-success{% elif sbot_status.state == "inactive" %}border-warning{% else %}border-danger{% endif %}">
|
||||
<!-- SBOT STATUS GRID -->
|
||||
<div class="two-grid" title="go-sbot process state">
|
||||
<!-- top-right config icon -->
|
||||
<a class="link two-grid-top-right" href="/settings/scuttlebutt" title="Configure Scuttlebutt settings">
|
||||
<img id="configureNetworking" class="icon-small" src="/icons/cog.svg" alt="Configure">
|
||||
<img id="configureNetworking" class="icon-small icon-active" src="/icons/cog.svg" alt="Configure">
|
||||
</a>
|
||||
<!-- left column -->
|
||||
<!-- go-sbot state icon with label -->
|
||||
<div class="grid-column-1">
|
||||
<img id="sbotStateIcon" class="center icon {% if sbot_status.state == "inactive" %}icon-inactive{% endif %}" src="/icons/hermies.svg" alt="Hermies">
|
||||
<img id="sbotStateIcon" class="center icon {% if sbot_status.state == "active" %}icon-active{% else %}icon-inactive{% endif %}" src="/icons/hermies.svg" alt="Hermies">
|
||||
<label id="sbotStateLabel" for="sbotStateIcon" class="center label-small font-gray" style="margin-top: 0.5rem;" title="Sbot state">{{ sbot_status.state | upper }}</label>
|
||||
</div>
|
||||
<!-- right column -->
|
||||
|
@ -78,25 +83,25 @@
|
|||
<!-- THREE-ACROSS STACK -->
|
||||
<div class="three-grid card-container" style="margin-top: 1rem;">
|
||||
<div class="stack">
|
||||
<img class="icon" title="Hops" src="/icons/orbits.png">
|
||||
<img class="icon icon-active" title="Hops" src="/icons/orbits.png">
|
||||
<div class="flex-grid" style="padding-top: 0.5rem;">
|
||||
<label class="label-medium" style="padding-right: 3px;" title="Replication hops">{{ sbot_config.hops }}</label>
|
||||
</div>
|
||||
<label class="label-small font-gray">HOPS</label>
|
||||
</div>
|
||||
<div class="stack">
|
||||
<img class="icon" title="Blobs" src="/icons/image-file.png">
|
||||
<img class="icon icon-active" title="Blobs" src="/icons/image-file.png">
|
||||
<div class="flex-grid" style="padding-top: 0.5rem;">
|
||||
<label class="label-medium" style="padding-right: 3px;" title="Blobstore size in MB">163</label>
|
||||
<label class="label-small font-near-black">MB</label>
|
||||
<label class="label-medium{% if sbot_status.state == "inactive" %} font-gray{% endif %}" style="padding-right: 3px;" title="Blobstore size in MB">{{ blobs }}</label>
|
||||
<label class="label-small{% if sbot_status.state == "inactive" %} font-gray{% else %} font-normal{% endif %}">MB</label>
|
||||
</div>
|
||||
<label class="label-small font-gray">BLOBSTORE</label>
|
||||
</div>
|
||||
<div class="stack">
|
||||
<img class="icon{% if not sbot_status.memory %} icon-inactive{% endif %}" title="Memory" src="/icons/ram.png">
|
||||
<img class="icon{% if sbot_status.memory %} icon-active{% else %} icon-inactive{% endif %}" title="Memory" src="/icons/ram.png">
|
||||
<div class="flex-grid" style="padding-top: 0.5rem;">
|
||||
<label class="label-medium{% if sbot_status.state == "inactive" %} font-gray{% endif %}" style="padding-right: 3px;" title="Memory usage of the go-sbot process in MB">{{ mem }}</label>
|
||||
<label class="label-small {% if sbot_status.state == "inactive" %}font-gray{% else %}font-near-black{% endif %}">MB</label>
|
||||
<label class="label-small{% if sbot_status.state == "inactive" %} font-gray{% else %} font-normal{% endif %}">MB</label>
|
||||
</div>
|
||||
<label class="label-small font-gray">MEMORY</label>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue