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
Expand Up @@ -2,6 +2,7 @@
pub enum Id {
Toolbar,
WorkloadList,
WorkloadLogs,
GlobalListener,
Menu,
InfoPopup,
Expand Down
7 changes: 6 additions & 1 deletion coman/src/app/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ pub enum CscsMsg {
SelectSystem,
SystemSelected(String),
}

#[derive(Debug, PartialEq)]
pub enum JobMsg {
ShowLog(usize),
CloseLog,
}
#[derive(Debug, PartialEq)]
pub enum Msg {
AppClose,
Expand All @@ -50,5 +54,6 @@ pub enum Msg {
Error(String),
Info(String),
Cscs(CscsMsg),
Job(JobMsg),
None,
}
63 changes: 60 additions & 3 deletions coman/src/app/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ use crate::{
app::{
ids::Id,
messages::{
CscsMsg, ErrorPopupMsg, InfoPopupMsg, LoginPopupMsg, MenuMsg, Msg, SystemSelectMsg,
CscsMsg, ErrorPopupMsg, InfoPopupMsg, JobMsg, LoginPopupMsg, MenuMsg, Msg,
SystemSelectMsg,
},
user_events::UserEvent,
},
components::{
error_popup::ErrorPopup, info_popup::InfoPopup, login_popup::LoginPopup,
system_select_popup::SystemSelectPopup, workload_menu::WorkloadMenu,
system_select_popup::SystemSelectPopup, workload_list::WorkloadList,
workload_log::WorkloadLog, workload_menu::WorkloadMenu,
},
cscs::{cli::cscs_login, handlers::cscs_system_set},
trace_dbg,
Expand All @@ -42,6 +44,10 @@ where

/// Triggers async request to select current system
pub select_system_tx: mpsc::Sender<()>,

/// Triggers watching job logs
/// sending None stops watching
pub job_log_tx: mpsc::Sender<Option<usize>>,
}

impl<T> Model<T>
Expand All @@ -53,6 +59,7 @@ where
bridge: TerminalBridge<T>,
error_tx: mpsc::Sender<String>,
select_system_tx: mpsc::Sender<()>,
job_log_tx: mpsc::Sender<Option<usize>>,
) -> Self {
Self {
app,
Expand All @@ -61,6 +68,7 @@ where
terminal: bridge,
error_tx,
select_system_tx,
job_log_tx,
}
}

Expand All @@ -79,7 +87,11 @@ where
.as_ref(),
)
.split(f.area());
self.app.view(&Id::WorkloadList, f, chunks[0]);
if self.app.mounted(&Id::WorkloadList) {
self.app.view(&Id::WorkloadList, f, chunks[0]);
} else if self.app.mounted(&Id::WorkloadLogs) {
self.app.view(&Id::WorkloadLogs, f, chunks[0]);
}
self.app.view(&Id::Toolbar, f, chunks[1]);

if self.app.mounted(&Id::Menu) {
Expand Down Expand Up @@ -157,6 +169,9 @@ where
fn handle_error_popup_msg(&mut self, msg: ErrorPopupMsg) -> Option<Msg> {
match msg {
ErrorPopupMsg::Opened(error_msg) => {
if self.app.mounted(&Id::ErrorPopup) {
assert!(self.app.umount(&Id::ErrorPopup).is_ok());
}
assert!(
self.app
.mount(Id::ErrorPopup, Box::new(ErrorPopup::new(error_msg)), vec![])
Expand Down Expand Up @@ -217,6 +232,47 @@ where
}
}
}
fn handle_job_msg(&mut self, msg: JobMsg) -> Option<Msg> {
match msg {
JobMsg::ShowLog(jobid) => {
if self.app.mounted(&Id::WorkloadList) {
assert!(self.app.umount(&Id::WorkloadList).is_ok());
}
if !self.app.mounted(&Id::WorkloadLogs) {
assert!(
self.app
.mount(Id::WorkloadLogs, Box::new(WorkloadLog::new()), vec![])
.is_ok()
);
}
assert!(self.app.active(&Id::WorkloadLogs).is_ok());
let job_log_tx = self.job_log_tx.clone();
tokio::spawn(async move {
job_log_tx.send(Some(jobid)).await.unwrap();
});
None
}
JobMsg::CloseLog => {
if self.app.mounted(&Id::WorkloadLogs) {
assert!(self.app.umount(&Id::WorkloadLogs).is_ok());
}
if !self.app.mounted(&Id::WorkloadList) {
assert!(
self.app
.mount(Id::WorkloadList, Box::new(WorkloadList::default()), vec![])
.is_ok()
);
}
assert!(self.app.active(&Id::WorkloadList).is_ok());
Comment thread
olevski marked this conversation as resolved.
let job_log_tx = self.job_log_tx.clone();
tokio::spawn(async move {
// stopp polling for logs
job_log_tx.send(None).await.unwrap();
});
None
}
}
}
}

// Let's implement Update for model
Expand Down Expand Up @@ -284,6 +340,7 @@ where
}
Msg::LoginPopup(msg) => self.handle_login_popup_msg(msg),
Msg::SystemSelectPopup(msg) => self.handle_system_select_popup_msg(msg),
Msg::Job(msg) => self.handle_job_msg(msg),
Msg::None => None,
}
} else {
Expand Down
1 change: 1 addition & 0 deletions coman/src/app/user_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::cscs::api_client::{Job, System};
pub enum CscsEvent {
LoggedIn,
GotWorkloadData(Vec<Job>),
GotJobLog(String),
SelectSystemList(Vec<System>),
}

Expand Down
12 changes: 10 additions & 2 deletions coman/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,13 @@ pub enum CscsJobCommands {
#[clap(alias("ls"))]
List,
#[clap(alias("g"))]
Get { job_id: i64 },
Get {
job_id: i64,
},
Log {
job_id: i64,
},

#[clap(alias("s"))]
Submit {
#[clap(short, long, help = "the path to the srun script file to use")]
Expand All @@ -59,7 +65,9 @@ pub enum CscsJobCommands {
command: Option<Vec<String>>,
},
#[clap(alias("c"))]
Cancel { job_id: i64 },
Cancel {
job_id: i64,
},
}
#[derive(Subcommand, Debug)]
pub enum CscsSystemCommands {
Expand Down
6 changes: 5 additions & 1 deletion coman/src/components/error_popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ impl ErrorPopup {
.color(Color::Red),
)
.title("Error", Alignment::Left)
.text(vec![TextSpan::from(msg)]),
.text(
std::convert::Into::<String>::into(msg)
.lines()
.map(TextSpan::from),
),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion coman/src/components/login_popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use tui_realm_stdlib::Input;
use tuirealm::{
Component, Event, Frame, MockComponent, State,
command::{Cmd, CmdResult, Direction, Position},
event::{Key, KeyEvent, KeyModifiers},
event::{Key, KeyEvent},
props::{
Alignment, AttrValue, Attribute, BorderType, Borders, Color, InputType, Layout, Props,
Style,
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,4 +5,5 @@ pub(crate) mod login_popup;
pub(crate) mod system_select_popup;
pub(crate) mod toolbar;
pub(crate) mod workload_list;
pub(crate) mod workload_log;
pub(crate) mod workload_menu;
11 changes: 3 additions & 8 deletions coman/src/components/system_select_popup.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
use tui_realm_stdlib::List;
use tuirealm::{
Component, Event, Frame, MockComponent, State, StateValue,
Component, Event, MockComponent, State, StateValue,
command::{Cmd, CmdResult, Direction, Position},
event::{Key, KeyEvent, KeyModifiers},
event::{Key, KeyEvent},
props::{
Alignment, AttrValue, Attribute, BorderType, Borders, Color, InputType, Layout, Props,
Style, TableBuilder, TextSpan,
},
ratatui::{
layout::{Constraint, Direction as LayoutDirection, Rect},
widgets::Block,
Alignment, BorderType, Borders, Color, TableBuilder, TextSpan,
},
};

Expand Down
2 changes: 1 addition & 1 deletion coman/src/components/toolbar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ impl Toolbar {
pub fn new() -> Self {
Self {
component: Label::default()
.text("q: quit, tab/shift+tab: change focus, x: menu, ?: help"),
.text("q: quit, l: logs, tab/shift+tab: change focus, x: menu, ?: help"),
}
}
}
Expand Down
31 changes: 25 additions & 6 deletions coman/src/components/workload_list.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
use tui_realm_stdlib::List;
use tuirealm::{
AttrValue, Attribute, Component, Event, MockComponent,
AttrValue, Attribute, Component, Event, MockComponent, State, StateValue,
command::{Cmd, CmdResult, Direction, Position},
event::{Key, KeyEvent},
event::{Key, KeyEvent, KeyModifiers},
props::{Alignment, BorderType, Borders, Color, TableBuilder, TextSpan},
};

use crate::app::{
messages::Msg,
user_events::{CscsEvent, UserEvent},
use crate::{
app::{
messages::{JobMsg, Msg},
user_events::{CscsEvent, UserEvent},
},
cscs::api_client::Job,
};

#[derive(MockComponent)]
pub(crate) struct WorkloadList {
component: List,
jobs: Vec<Job>,
}

impl Default for WorkloadList {
Expand All @@ -31,6 +35,7 @@ impl Default for WorkloadList {
.highlighted_str("-")
.rewind(true)
.step(4),
jobs: vec![],
}
}
}
Expand Down Expand Up @@ -58,9 +63,11 @@ impl Component<Msg, UserEvent> for WorkloadList {
self.perform(Cmd::GoTo(Position::End))
}
Event::User(UserEvent::Cscs(CscsEvent::GotWorkloadData(data))) => {
if data.len() == 0 {
if data.is_empty() {
self.jobs = vec![];
self.attr(Attribute::Content, AttrValue::Table(vec![]));
} else {
self.jobs = data.clone();
let mut table = TableBuilder::default();
for (idx, job) in data.iter().enumerate() {
if idx > 0 {
Expand All @@ -77,6 +84,18 @@ impl Component<Msg, UserEvent> for WorkloadList {
}
self.perform(Cmd::Change)
}
Event::Keyboard(KeyEvent {
code: Key::Char('l'),
modifiers: KeyModifiers::NONE,
}) => {
if let State::One(StateValue::Usize(index)) = self.state()
&& !self.jobs.is_empty()
{
let job = self.jobs[index].clone();
return Some(Msg::Job(JobMsg::ShowLog(job.id)));
}
CmdResult::None
}
_ => CmdResult::None,
};
Some(Msg::None)
Expand Down
80 changes: 80 additions & 0 deletions coman/src/components/workload_log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use tui_realm_stdlib::Textarea;
use tuirealm::{
AttrValue, Attribute, Component, Event, MockComponent,
command::{Cmd, CmdResult, Direction, Position},
event::{Key, KeyEvent},
props::{
Alignment, BorderType, Borders, Color, PropPayload, PropValue, TextSpan,
},
};

use crate::{
app::{
messages::{JobMsg, Msg},
user_events::{CscsEvent, UserEvent},
},
trace_dbg,
};

#[derive(MockComponent)]
pub struct WorkloadLog {
component: Textarea,
}

impl WorkloadLog {
pub fn new() -> Self {
Self {
component: Textarea::default()
.borders(
Borders::default()
.modifiers(BorderType::Rounded)
.color(Color::Yellow),
)
.title("Workload Log", Alignment::Center)
.step(4),
}
}
}
impl Component<Msg, UserEvent> for WorkloadLog {
fn on(&mut self, ev: tuirealm::Event<UserEvent>) -> Option<Msg> {
let _ = match ev {
Event::User(UserEvent::Cscs(CscsEvent::GotJobLog(log))) => {
let _ = trace_dbg!("got log component");
let log = trace_dbg!(log);
self.attr(
Attribute::Text,
AttrValue::Payload(PropPayload::Vec(
log.lines()
.map(|l| PropValue::TextSpan(TextSpan::from(l)))
.collect(),
)),
);
self.perform(Cmd::Change)
}
Event::Keyboard(KeyEvent {
code: Key::Down, ..
}) => self.perform(Cmd::Move(Direction::Down)),
Event::Keyboard(KeyEvent { code: Key::Up, .. }) => {
self.perform(Cmd::Move(Direction::Up))
}
Event::Keyboard(KeyEvent {
code: Key::PageDown,
..
}) => self.perform(Cmd::Scroll(Direction::Down)),
Event::Keyboard(KeyEvent {
code: Key::PageUp, ..
}) => self.perform(Cmd::Scroll(Direction::Up)),
Event::Keyboard(KeyEvent {
code: Key::Home, ..
}) => self.perform(Cmd::GoTo(Position::Begin)),
Event::Keyboard(KeyEvent { code: Key::End, .. }) => {
self.perform(Cmd::GoTo(Position::End))
}
Event::Keyboard(KeyEvent { code: Key::Esc, .. }) => {
return Some(Msg::Job(JobMsg::CloseLog));
}
_ => CmdResult::None,
};
Some(Msg::None)
}
}
Loading