Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions coman/src/app/ids.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub enum Id {
StatusBar,
Toolbar,
WorkloadList,
WorkloadLogs,
Expand Down
11 changes: 11 additions & 0 deletions coman/src/app/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ pub enum View {
Workloads,
Files,
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, strum::Display)]
pub enum StatusMsg {
#[allow(dead_code)]
Progress(String, usize),
Info(String),
#[allow(dead_code)]
Warning(String),
}

#[derive(Debug, PartialEq)]
pub enum Msg {
AppClose,
Expand All @@ -72,6 +82,7 @@ pub enum Msg {
Info(String),
Cscs(CscsMsg),
Job(JobMsg),
Status(StatusMsg),
ChangeView(View),
CreateEvent(UserEvent),
None,
Expand Down
32 changes: 25 additions & 7 deletions coman/src/app/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ use crate::{
app::{
ids::Id,
messages::{
CscsMsg, DownloadPopupMsg, ErrorPopupMsg, InfoPopupMsg, JobMsg, LoginPopupMsg, MenuMsg, Msg,
CscsMsg, DownloadPopupMsg, ErrorPopupMsg, InfoPopupMsg, JobMsg, LoginPopupMsg, MenuMsg, Msg, StatusMsg,
SystemSelectMsg, View,
},
user_events::{CscsEvent, UserEvent},
user_events::{CscsEvent, StatusEvent, UserEvent},
},
components::{
context_menu::ContextMenu, download_popup::DownloadTargetInput, error_popup::ErrorPopup, info_popup::InfoPopup,
Expand Down Expand Up @@ -104,17 +104,19 @@ where
.margin(1)
.constraints(
[
Constraint::Max(3), //Statusbar
Constraint::Min(10), //content
Constraint::Max(1), //Toolbar
]
.as_ref(),
)
.split(f.area());
app.view(&Id::StatusBar, f, chunks[0]);
match current_view {
View::Workloads => Self::view_workloads(app, f, chunks[0]),
View::Files => Self::view_files(app, f, chunks[0]),
View::Workloads => Self::view_workloads(app, f, chunks[1]),
View::Files => Self::view_files(app, f, chunks[1]),
}
app.view(&Id::Toolbar, f, chunks[1]);
app.view(&Id::Toolbar, f, chunks[2]);

if app.mounted(&Id::Menu) {
let popup = draw_area_in_absolute(f.area(), 10);
Expand Down Expand Up @@ -188,7 +190,6 @@ where
.is_ok()
);
assert!(self.app.active(&Id::SystemSelectPopup).is_ok());
trace_dbg!("mounted system select popup");
None
}
SystemSelectMsg::Closed => {
Expand Down Expand Up @@ -408,9 +409,10 @@ where
None
}
Msg::Cscs(CscsMsg::SystemSelected(system)) => {
let event_tx = self.user_event_tx.clone();
let error_tx = self.error_tx.clone();
tokio::spawn(async move {
match cscs_system_set(system, true).await {
match cscs_system_set(system.clone(), true).await {
Ok(_) => {}
Err(e) => error_tx
.send(format!(
Expand All @@ -420,6 +422,10 @@ where
.await
.unwrap(),
};
event_tx
.send(UserEvent::Cscs(CscsEvent::SystemSelected(system)))
.await
.unwrap();
});
None
}
Expand All @@ -441,6 +447,18 @@ where
});
None
}
Msg::Status(status) => {
let event_tx = self.user_event_tx.clone();
let event = match status {
StatusMsg::Progress(msg, progress) => StatusEvent::Progress(msg, progress),
StatusMsg::Info(msg) => StatusEvent::Info(msg),
StatusMsg::Warning(msg) => StatusEvent::Warning(msg),
};
tokio::spawn(async move {
event_tx.send(UserEvent::Status(event)).await.unwrap();
});
None
}
Msg::None => None,
}
} else {
Expand Down
10 changes: 10 additions & 0 deletions coman/src/app/user_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub enum CscsEvent {
GotWorkloadData(Vec<Job>),
GotJobLog(String),
SelectSystemList(Vec<System>),
SystemSelected(String),
}

#[derive(Debug, Eq, Clone, PartialEq, PartialOrd, Ord)]
Expand All @@ -17,12 +18,21 @@ pub enum FileEvent {
DownloadCurrentFile,
DownloadSuccessful,
}

#[derive(Debug, Eq, Clone, PartialEq, PartialOrd, Ord)]
pub enum StatusEvent {
Progress(String, usize),
Info(String),
Warning(String),
}

#[derive(Debug, Eq, Clone, PartialOrd, Ord)]
pub enum UserEvent {
Cscs(CscsEvent),
File(FileEvent),
Error(String),
Info(String),
Status(StatusEvent),
SwitchedToView(View),
}

Expand Down
4 changes: 0 additions & 4 deletions coman/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,6 @@ pub struct Cli {
#[arg(short, long, value_name = "FLOAT", default_value_t = 4.0)]
pub tick_rate: f64,

/// Frame rate, i.e. number of frames per second
#[arg(short, long, value_name = "FLOAT", default_value_t = 60.0)]
pub frame_rate: f64,

#[command(subcommand)]
pub command: Option<CliCommands>,
}
Expand Down
12 changes: 7 additions & 5 deletions coman/src/components/global_listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use tuirealm::{
};

use crate::app::{
messages::{InfoPopupMsg, MenuMsg, Msg, SystemSelectMsg, View},
messages::{MenuMsg, Msg, StatusMsg, SystemSelectMsg, View},
user_events::{CscsEvent, FileEvent, UserEvent},
};

Expand Down Expand Up @@ -42,13 +42,15 @@ impl Component<Msg, UserEvent> for GlobalListener {
}
Event::User(UserEvent::Error(msg)) => Some(Msg::Error(msg)),
Event::User(UserEvent::Info(msg)) => Some(Msg::Info(msg)),
Event::User(UserEvent::Cscs(CscsEvent::LoggedIn)) => Some(Msg::Info("Successfully logged in".to_string())),
Event::User(UserEvent::Cscs(CscsEvent::LoggedIn)) => {
Some(Msg::Status(StatusMsg::Info("Successfully logged in".to_string())))
}
Event::User(UserEvent::Cscs(CscsEvent::SelectSystemList(systems))) => {
Some(Msg::SystemSelectPopup(SystemSelectMsg::Opened(systems)))
}
Event::User(UserEvent::File(FileEvent::DownloadSuccessful)) => Some(Msg::InfoPopup(InfoPopupMsg::Opened(
"File successfully downloaded".to_owned(),
))),
Event::User(UserEvent::File(FileEvent::DownloadSuccessful)) => {
Some(Msg::Status(StatusMsg::Info("File successfully downloaded".to_owned())))
}
_ => None,
}
}
Expand Down
1 change: 1 addition & 0 deletions coman/src/components/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub(crate) mod file_tree;
pub(crate) mod global_listener;
pub(crate) mod info_popup;
pub(crate) mod login_popup;
pub(crate) mod status_bar;
pub(crate) mod system_select_popup;
pub(crate) mod toolbar;
pub(crate) mod workload_list;
Expand Down
133 changes: 133 additions & 0 deletions coman/src/components/status_bar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
use std::time::{Duration, Instant};

use ratatui::{
text::{Line, Span},
widgets::{LineGauge, Paragraph},
};
use tuirealm::{
AttrValue, Attribute, Component, Event, MockComponent, Props, State,
command::CmdResult,
props::{BorderType, Borders, Layout},
ratatui::{
Frame,
layout::{Constraint, Direction},
prelude::Rect,
style::{Color, Style},
widgets::Block,
},
};

use crate::{
app::{
messages::Msg,
user_events::{CscsEvent, StatusEvent, UserEvent},
},
config::Config,
};

pub struct StatusBar {
props: Props,
last_updated: Instant,
current_status: Option<StatusEvent>,
status_clear_time: Duration,
current_platform: String,
current_system: String,
}

impl StatusBar {
pub fn new() -> Self {
let config = Config::new().unwrap();
Self {
props: Props::default(),
last_updated: Instant::now(),
current_status: None,
status_clear_time: Duration::from_secs(10),
current_platform: config.cscs.current_platform.to_string(),
current_system: config.cscs.current_system,
}
}
}

impl MockComponent for StatusBar {
fn query(&self, attr: Attribute) -> Option<AttrValue> {
self.props.get(attr)
}

fn attr(&mut self, attr: Attribute, value: AttrValue) {
self.props.set(attr, value);
}

fn state(&self) -> State {
State::None
}

fn perform(&mut self, _cmd: tuirealm::command::Cmd) -> CmdResult {
CmdResult::None
}
fn view(&mut self, frame: &mut Frame, area: Rect) {
if self.props.get_or(Attribute::Display, AttrValue::Flag(true)) == AttrValue::Flag(true) {
let borders = Borders::default().modifiers(BorderType::Rounded);
let div = Block::default()
.borders(borders.sides)
.border_style(borders.style())
.border_type(borders.modifiers);
let layout = Layout::default()
.constraints(&[Constraint::Percentage(30), Constraint::Percentage(70)])
.direction(Direction::Horizontal)
.margin(1);
frame.render_widget(div, area);

let highlight_style = Style::default().fg(Color::Yellow);
let info_style = Style::default().fg(Color::Blue);
let warn_style = Style::default().fg(Color::Red);
let system_status = Paragraph::new(Line::from(vec![
Span::styled("Platform: ", highlight_style),
Span::raw(self.current_platform.clone().to_uppercase()),
Span::raw(" "),
Span::styled("System: ", highlight_style),
Span::raw(self.current_system.clone()),
]));
let chunks = layout.chunks(area);
frame.render_widget(system_status, chunks[0]);
if let Some(status) = self.current_status.clone() {
match status {
StatusEvent::Progress(msg, progress) => {
let gauge = LineGauge::default()
.filled_style(Style::default().fg(Color::DarkGray))
.label(msg)
.ratio((progress as f64) / 100.0);
frame.render_widget(gauge, chunks[1]);
}
StatusEvent::Info(info) => {
let notification_status = Paragraph::new(info).style(info_style);
frame.render_widget(notification_status, chunks[1]);
}
StatusEvent::Warning(warning) => {
let notification_status = Paragraph::new(warning).style(warn_style);
frame.render_widget(notification_status, chunks[1]);
}
}
}
}
}
}
impl Component<Msg, UserEvent> for StatusBar {
fn on(&mut self, ev: Event<UserEvent>) -> Option<Msg> {
match ev {
Event::Tick => {
if self.last_updated.elapsed() > self.status_clear_time {
self.current_status = None;
}
}
Event::User(UserEvent::Status(status)) => {
self.current_status = Some(status);
self.last_updated = Instant::now();
}
Event::User(UserEvent::Cscs(CscsEvent::SystemSelected(system))) => {
self.current_system = system;
}
_ => {}
}
None
}
}
10 changes: 3 additions & 7 deletions coman/src/components/toolbar.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
use tui_realm_stdlib::Label;
use tuirealm::{AttrValue, Attribute, Component, Event, MockComponent};

use crate::{
app::{
messages::{Msg, View},
user_events::UserEvent,
},
trace_dbg,
use crate::app::{
messages::{Msg, View},
user_events::UserEvent,
};
const WORKLOAD_TOOLTIP: &str = "q: quit, Esc: close/back, l: logs, f: File view, x: menu, tab: switch view, ?: help";
const FILETREE_TOOLTIP: &str = "q: quit, ↑↓: navigate,←→: collapse/expand, x: menu, ?: help";
Expand All @@ -30,7 +27,6 @@ impl Component<Msg, UserEvent> for Toolbar {
fn on(&mut self, ev: tuirealm::Event<UserEvent>) -> Option<Msg> {
match ev {
Event::User(UserEvent::SwitchedToView(view)) => {
let view = trace_dbg!(view);
self.current_view = view;
match self.current_view {
View::Workloads => self.attr(Attribute::Text, AttrValue::String(WORKLOAD_TOOLTIP.to_owned())),
Expand Down
4 changes: 1 addition & 3 deletions coman/src/cscs/api_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ impl CscsApi {
) -> Result<()> {
let workingdir = script_path.clone();
let workingdir = workingdir.parent();
let result = post_compute_system_job(
let _result = post_compute_system_job(
&self.client,
system_name,
account,
Expand All @@ -399,7 +399,6 @@ impl CscsApi {
envvars,
)
.await?;
let _ = trace_dbg!(result);

Ok(())
}
Expand Down Expand Up @@ -523,7 +522,6 @@ impl CscsApi {
let result = get_filesystem_ops_ls(&self.client, system_name, path)
.await
.wrap_err("couldn't list path")?;
let result = trace_dbg!(result);
match result.output {
Some(entries) => Ok(entries.into_iter().map(|e| e.into()).collect()),
None => Ok(vec![]),
Expand Down
Loading