Skip to content

Commit

Permalink
Merge pull request #2388 from mazzi/feat_lp_upgrade_nodes
Browse files Browse the repository at this point in the history
feat(launchpad): upgrade nodes version
  • Loading branch information
jacderida authored Nov 5, 2024
2 parents 05bfe18 + 45336ad commit 41382e0
Show file tree
Hide file tree
Showing 12 changed files with 414 additions and 44 deletions.
2 changes: 2 additions & 0 deletions node-launchpad/.config/config.json5
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
"<Ctrl-l>": {"OptionsActions":"TriggerAccessLogs"},
"<Ctrl-L>": {"OptionsActions":"TriggerAccessLogs"},
"<Ctrl-Shift-l>": {"OptionsActions":"TriggerAccessLogs"},
"<Ctrl-u>": {"OptionsActions":"TriggerUpdateNodes"},
"<Ctrl-U>": {"OptionsActions":"TriggerUpdateNodes"},
"<Ctrl-r>": {"OptionsActions":"TriggerResetNodes"},
"<Ctrl-R>": {"OptionsActions":"TriggerResetNodes"},
"<Ctrl-Shift-r>": {"OptionsActions":"TriggerResetNodes"},
Expand Down
4 changes: 4 additions & 0 deletions node-launchpad/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@ pub enum StatusActions {
StartNodesCompleted,
StopNodesCompleted,
ResetNodesCompleted { trigger_start_node: bool },
UpdateNodesCompleted,
SuccessfullyDetectedNatStatus,
ErrorWhileRunningNatDetection,
ErrorLoadingNodeRegistry { raw_error: String },
ErrorGettingNodeRegistryPath { raw_error: String },
ErrorScalingUpNodes { raw_error: String },
ErrorStoppingNodes { raw_error: String },
ErrorResettingNodes { raw_error: String },
ErrorUpdatingNodes { raw_error: String },
NodesStatsObtained(NodeStats),

TriggerManageNodes,
Expand All @@ -67,11 +69,13 @@ pub enum StatusActions {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Display, Deserialize)]
pub enum OptionsActions {
ResetNodes,
UpdateNodes,

TriggerChangeDrive,
TriggerChangeConnectionMode,
TriggerChangePortRange,
TriggerRewardsAddress,
TriggerUpdateNodes,
TriggerResetNodes,
TriggerAccessLogs,
UpdateConnectionMode(ConnectionMode),
Expand Down
4 changes: 3 additions & 1 deletion node-launchpad/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
popup::{
change_drive::ChangeDrivePopup, connection_mode::ChangeConnectionModePopUp,
manage_nodes::ManageNodes, port_range::PortRangePopUp, reset_nodes::ResetNodesPopup,
rewards_address::RewardsAddress,
rewards_address::RewardsAddress, upgrade_nodes::UpgradeNodesPopUp,
},
status::{Status, StatusConfig},
Component,
Expand Down Expand Up @@ -120,6 +120,7 @@ impl App {
let change_connection_mode = ChangeConnectionModePopUp::new(connection_mode)?;
let port_range = PortRangePopUp::new(connection_mode, port_from, port_to);
let rewards_address = RewardsAddress::new(app_data.discord_username.clone());
let upgrade_nodes = UpgradeNodesPopUp::default();

Ok(Self {
config,
Expand All @@ -146,6 +147,7 @@ impl App {
Box::new(rewards_address),
Box::new(reset_nodes),
Box::new(manage_nodes),
Box::new(upgrade_nodes),
],
should_quit: false,
should_suspend: false,
Expand Down
73 changes: 50 additions & 23 deletions node-launchpad/src/components/options.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::path::PathBuf;
use std::{cmp::max, path::PathBuf};

use color_eyre::eyre::{eyre, Result};
use color_eyre::eyre::{eyre, Ok, Result};
use ratatui::{
layout::{Alignment, Constraint, Direction, Layout, Rect},
style::{Style, Stylize},
Expand Down Expand Up @@ -74,7 +74,7 @@ impl Component for Options {
Constraint::Length(7),
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(4),
Constraint::Length(3),
]
.as_ref(),
Expand Down Expand Up @@ -271,35 +271,58 @@ impl Component for Options {
.block(block3)
.style(Style::default().fg(GHOST_WHITE));

// Reset All Nodes
// Update Nodes
let reset_legend = " Begin Reset ";
let reset_key = " [Ctrl+R] ";
let upgrade_legend = " Begin Upgrade ";
let upgrade_key = " [Ctrl+U] ";
let block4 = Block::default()
.title(" Reset All Nodes ")
.title(" Update Nodes ")
.title_style(Style::default().bold().fg(GHOST_WHITE))
.style(Style::default().fg(GHOST_WHITE))
.borders(Borders::ALL)
.border_style(Style::default().fg(EUCALYPTUS));
let reset_nodes = Table::new(
vec![Row::new(vec![
Cell::from(
Line::from(vec![Span::styled(
" Remove and Reset all Nodes on this device ",
Style::default().fg(LIGHT_PERIWINKLE),
)])
.alignment(Alignment::Left),
),
Cell::from(
Line::from(vec![
Span::styled(reset_legend, Style::default().fg(EUCALYPTUS)),
Span::styled(reset_key, Style::default().fg(GHOST_WHITE)),
])
.alignment(Alignment::Right),
),
])],
vec![
Row::new(vec![
Cell::from(
Line::from(vec![Span::styled(
" Upgrade all Nodes ",
Style::default().fg(LIGHT_PERIWINKLE),
)])
.alignment(Alignment::Left),
),
Cell::from(
Line::from(vec![
Span::styled(upgrade_legend, Style::default().fg(EUCALYPTUS)),
Span::styled(upgrade_key, Style::default().fg(GHOST_WHITE)),
])
.alignment(Alignment::Right),
),
]),
Row::new(vec![
Cell::from(
Line::from(vec![Span::styled(
" Reset all Nodes on this device ",
Style::default().fg(LIGHT_PERIWINKLE),
)])
.alignment(Alignment::Left),
),
Cell::from(
Line::from(vec![
Span::styled(reset_legend, Style::default().fg(EUCALYPTUS)),
Span::styled(reset_key, Style::default().fg(GHOST_WHITE)),
])
.alignment(Alignment::Right),
),
]),
],
&[
Constraint::Fill(1),
Constraint::Length((reset_legend.len() + reset_key.len()) as u16),
Constraint::Length(
(max(reset_legend.len(), upgrade_legend.len())
+ max(reset_key.len(), upgrade_key.len())) as u16,
),
],
)
.block(block4)
Expand Down Expand Up @@ -355,7 +378,8 @@ impl Component for Options {
| Scene::ChangeConnectionModePopUp
| Scene::ChangePortsPopUp { .. }
| Scene::OptionsRewardsAddressPopUp
| Scene::ResetNodesPopUp => {
| Scene::ResetNodesPopUp
| Scene::UpgradeNodesPopUp => {
self.active = true;
// make sure we're in navigation mode
return Ok(Some(Action::SwitchInputMode(InputMode::Navigation)));
Expand Down Expand Up @@ -402,6 +426,9 @@ impl Component for Options {
error!("Failed to open folder: {}", e);
}
}
OptionsActions::TriggerUpdateNodes => {
return Ok(Some(Action::SwitchScene(Scene::UpgradeNodesPopUp)));
}
OptionsActions::TriggerResetNodes => {
return Ok(Some(Action::SwitchScene(Scene::ResetNodesPopUp)))
}
Expand Down
1 change: 1 addition & 0 deletions node-launchpad/src/components/popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ pub mod manage_nodes;
pub mod port_range;
pub mod reset_nodes;
pub mod rewards_address;
pub mod upgrade_nodes;
1 change: 0 additions & 1 deletion node-launchpad/src/components/popup/rewards_address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ pub struct RewardsAddress {
can_save: bool,
}

#[allow(dead_code)]
enum RewardsAddressState {
RewardsAddressAlreadySet,
ShowTCs,
Expand Down
182 changes: 182 additions & 0 deletions node-launchpad/src/components/popup/upgrade_nodes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// Copyright 2024 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

use super::super::utils::centered_rect_fixed;
use super::super::Component;
use crate::{
action::{Action, OptionsActions},
mode::{InputMode, Scene},
style::{clear_area, EUCALYPTUS, GHOST_WHITE, LIGHT_PERIWINKLE, VIVID_SKY_BLUE},
};
use color_eyre::Result;
use crossterm::event::{KeyCode, KeyEvent};
use ratatui::{prelude::*, widgets::*};

pub struct UpgradeNodesPopUp {
/// Whether the component is active right now, capturing keystrokes + draw things.
active: bool,
}

impl UpgradeNodesPopUp {
pub fn new() -> Self {
Self { active: false }
}
}

impl Default for UpgradeNodesPopUp {
fn default() -> Self {
Self::new()
}
}

impl Component for UpgradeNodesPopUp {
fn handle_key_events(&mut self, key: KeyEvent) -> Result<Vec<Action>> {
if !self.active {
return Ok(vec![]);
}
// while in entry mode, keybinds are not captured, so gotta exit entry mode from here
let send_back = match key.code {
KeyCode::Enter => {
debug!("Got Enter, Upgrading nodes...");
vec![
Action::OptionsActions(OptionsActions::UpdateNodes),
Action::SwitchScene(Scene::Status),
]
}
KeyCode::Esc => {
debug!("Got Esc, Not upgrading nodes.");
vec![Action::SwitchScene(Scene::Options)]
}
_ => vec![],
};
Ok(send_back)
}

fn update(&mut self, action: Action) -> Result<Option<Action>> {
let send_back = match action {
Action::SwitchScene(scene) => match scene {
Scene::UpgradeNodesPopUp => {
self.active = true;
Some(Action::SwitchInputMode(InputMode::Entry))
}
_ => {
self.active = false;
None
}
},
_ => None,
};
Ok(send_back)
}

fn draw(&mut self, f: &mut crate::tui::Frame<'_>, area: Rect) -> Result<()> {
if !self.active {
return Ok(());
}

let layer_zero = centered_rect_fixed(52, 15, area);

let layer_one = Layout::new(
Direction::Vertical,
[
// for the pop_up_border
Constraint::Length(2),
// for the input field
Constraint::Min(1),
// for the pop_up_border
Constraint::Length(1),
],
)
.split(layer_zero);

// layer zero
let pop_up_border = Paragraph::new("").block(
Block::default()
.borders(Borders::ALL)
.title(" Upgrade all nodes ")
.bold()
.title_style(Style::new().fg(VIVID_SKY_BLUE))
.padding(Padding::uniform(2))
.border_style(Style::new().fg(VIVID_SKY_BLUE)),
);
clear_area(f, layer_zero);

// split the area into 3 parts, for the lines, hypertext, buttons
let layer_two = Layout::new(
Direction::Vertical,
[
// for the text
Constraint::Length(9),
// gap
Constraint::Length(4),
// for the buttons
Constraint::Length(1),
],
)
.split(layer_one[1]);

let text = Paragraph::new(vec![
Line::from(Span::styled("\n\n", Style::default())),
Line::from(vec![
Span::styled("This will ", Style::default().fg(LIGHT_PERIWINKLE)),
Span::styled(
"stop and upgrade all nodes. ",
Style::default().fg(GHOST_WHITE),
),
]),
Line::from(Span::styled(
"No data will be lost.",
Style::default().fg(LIGHT_PERIWINKLE),
)),
Line::from(Span::styled("\n\n", Style::default())),
Line::from(Span::styled("\n\n", Style::default())),
Line::from(vec![
Span::styled("You’ll need to ", Style::default().fg(LIGHT_PERIWINKLE)),
Span::styled("Start ", Style::default().fg(GHOST_WHITE)),
Span::styled(
"them again afterwards.",
Style::default().fg(LIGHT_PERIWINKLE),
),
]),
Line::from(Span::styled(
"Are you sure you want to continue?",
Style::default(),
)),
])
.block(Block::default().padding(Padding::horizontal(2)))
.alignment(Alignment::Center)
.wrap(Wrap { trim: true });

f.render_widget(text, layer_two[0]);

let dash = Block::new()
.borders(Borders::BOTTOM)
.border_style(Style::new().fg(GHOST_WHITE));
f.render_widget(dash, layer_two[1]);

let buttons_layer =
Layout::horizontal(vec![Constraint::Percentage(45), Constraint::Percentage(55)])
.split(layer_two[2]);

let button_no = Line::from(vec![Span::styled(
" No, Cancel [Esc]",
Style::default().fg(LIGHT_PERIWINKLE),
)]);
f.render_widget(button_no, buttons_layer[0]);

let button_yes = Paragraph::new(Line::from(vec![Span::styled(
"Yes, Upgrade [Enter] ",
Style::default().fg(EUCALYPTUS),
)]))
.alignment(Alignment::Right);
f.render_widget(button_yes, buttons_layer[1]);
f.render_widget(pop_up_border, layer_zero);

Ok(())
}
}
Loading

0 comments on commit 41382e0

Please sign in to comment.