node_launchpad/components/popup/
remove_node.rs

1// Copyright 2024 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
4// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
5// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
6// KIND, either express or implied. Please review the Licences for the specific language governing
7// permissions and limitations relating to use of the SAFE Network Software.
8
9use super::super::utils::centered_rect_fixed;
10use super::super::Component;
11use crate::{
12    action::{Action, StatusActions},
13    mode::{InputMode, Scene},
14    style::{clear_area, EUCALYPTUS, GHOST_WHITE, LIGHT_PERIWINKLE, VIVID_SKY_BLUE},
15};
16use color_eyre::Result;
17use crossterm::event::{KeyCode, KeyEvent};
18use ratatui::{prelude::*, widgets::*};
19
20#[derive(Default)]
21pub struct RemoveNodePopUp {
22    /// Whether the component is active right now, capturing keystrokes + draw things.
23    active: bool,
24}
25
26impl Component for RemoveNodePopUp {
27    fn handle_key_events(&mut self, key: KeyEvent) -> Result<Vec<Action>> {
28        if !self.active {
29            return Ok(vec![]);
30        }
31        // while in entry mode, keybinds are not captured, so gotta exit entry mode from here
32        let send_back = match key.code {
33            KeyCode::Enter => {
34                debug!("Got Enter, Removing node...");
35                vec![
36                    Action::StatusActions(StatusActions::RemoveNodes),
37                    Action::SwitchScene(Scene::Status),
38                ]
39            }
40            KeyCode::Esc => {
41                debug!("Got Esc, Not removing node.");
42                vec![Action::SwitchScene(Scene::Status)]
43            }
44            _ => vec![],
45        };
46        Ok(send_back)
47    }
48
49    fn update(&mut self, action: Action) -> Result<Option<Action>> {
50        let send_back = match action {
51            Action::SwitchScene(scene) => match scene {
52                Scene::RemoveNodePopUp => {
53                    self.active = true;
54                    Some(Action::SwitchInputMode(InputMode::Entry))
55                }
56                _ => {
57                    self.active = false;
58                    None
59                }
60            },
61            _ => None,
62        };
63        Ok(send_back)
64    }
65
66    fn draw(&mut self, f: &mut crate::tui::Frame<'_>, area: Rect) -> Result<()> {
67        if !self.active {
68            return Ok(());
69        }
70
71        let layer_zero = centered_rect_fixed(52, 15, area);
72
73        let layer_one = Layout::new(
74            Direction::Vertical,
75            [
76                // for the pop_up_border
77                Constraint::Length(2),
78                // for the input field
79                Constraint::Min(1),
80                // for the pop_up_border
81                Constraint::Length(1),
82            ],
83        )
84        .split(layer_zero);
85
86        // layer zero
87        let pop_up_border = Paragraph::new("").block(
88            Block::default()
89                .borders(Borders::ALL)
90                .title(" Remove Node ")
91                .bold()
92                .title_style(Style::new().fg(VIVID_SKY_BLUE))
93                .padding(Padding::uniform(2))
94                .border_style(Style::new().fg(VIVID_SKY_BLUE)),
95        );
96        clear_area(f, layer_zero);
97
98        // split the area into 3 parts, for the lines, hypertext,  buttons
99        let layer_two = Layout::new(
100            Direction::Vertical,
101            [
102                // for the text
103                Constraint::Length(9),
104                // gap
105                Constraint::Length(4),
106                // for the buttons
107                Constraint::Length(1),
108            ],
109        )
110        .split(layer_one[1]);
111
112        let text = Paragraph::new(vec![
113            Line::from(Span::styled("\n\n", Style::default())),
114            Line::from(Span::styled("\n\n", Style::default())),
115            Line::from(vec![Span::styled(
116                "Removing this node will stop it, and delete all its data.",
117                Style::default().fg(LIGHT_PERIWINKLE),
118            )]),
119            Line::from(Span::styled("\n\n", Style::default())),
120            Line::from(Span::styled(
121                "Press Enter to confirm.",
122                Style::default().fg(LIGHT_PERIWINKLE),
123            )),
124            Line::from(Span::styled("\n\n", Style::default())),
125        ])
126        .block(Block::default().padding(Padding::horizontal(2)))
127        .alignment(Alignment::Center)
128        .wrap(Wrap { trim: true });
129
130        f.render_widget(text, layer_two[0]);
131
132        let dash = Block::new()
133            .borders(Borders::BOTTOM)
134            .border_style(Style::new().fg(GHOST_WHITE));
135        f.render_widget(dash, layer_two[1]);
136
137        let buttons_layer =
138            Layout::horizontal(vec![Constraint::Percentage(45), Constraint::Percentage(55)])
139                .split(layer_two[2]);
140
141        let button_no = Line::from(vec![Span::styled(
142            "  No, Cancel [Esc]",
143            Style::default().fg(LIGHT_PERIWINKLE),
144        )]);
145        f.render_widget(button_no, buttons_layer[0]);
146
147        let button_yes = Paragraph::new(Line::from(vec![Span::styled(
148            "Yes, Remove Node [Enter]  ",
149            Style::default().fg(EUCALYPTUS),
150        )]))
151        .alignment(Alignment::Right);
152        f.render_widget(button_yes, buttons_layer[1]);
153        f.render_widget(pop_up_border, layer_zero);
154
155        Ok(())
156    }
157}