config + ui: node server config ui, node restart reminder modal and message
This commit is contained in:
parent
92972fbbd9
commit
fc27b77142
6 changed files with 167 additions and 109 deletions
|
@ -87,11 +87,16 @@ network_settings:
|
|||
api_secret: Rest API and V2 Owner API token
|
||||
foreign_api_secret: Foreign API token
|
||||
disabled: Disabled
|
||||
enabled: Enabled
|
||||
copy: Copy
|
||||
paste: Paste
|
||||
ftl: The Future Time Limit (FTL)
|
||||
ftl_description: Limit on how far into the future, relative to a node's local time in seconds, the timestamp on a new block can be, in order for the block to be accepted.
|
||||
not_valid_value: Entered value is not valid
|
||||
full_validation: Full validation
|
||||
full_validation_description: Whether to run a full chain validation when processing each block (except during synchronization).
|
||||
archive_mode: Archive mode
|
||||
archive_mode_desc: Run the node in full archive mode (more disk space and time will be required for synchronization).
|
||||
modal:
|
||||
cancel: Cancel
|
||||
save: Save
|
||||
|
|
|
@ -87,11 +87,16 @@ network_settings:
|
|||
api_secret: Rest и V2 Owner API токен
|
||||
foreign_api_secret: Foreign API токен
|
||||
disabled: Отключен
|
||||
enabled: Включен
|
||||
copy: Копировать
|
||||
paste: Вставить
|
||||
ftl: Предел Будущего Времени (FTL)
|
||||
ftl_description: Ограничение на то, насколько далеко в будущем, относительно локального времени узла в секундах, находится временная метка на новом блоке для его принятия.
|
||||
ftl_description: Насколько далеко в будущем, относительно локального времени узла в секундах, может находиться временная метка на новом блоке для его принятия.
|
||||
not_valid_value: Введено недопустимое значение
|
||||
full_validation: Полная валидация
|
||||
full_validation_description: Запускать ли полную проверку цепи при обработке каждого блока (за исключением синхронизации).
|
||||
archive_mode: Архивный режим
|
||||
archive_mode_desc: Запустить узел в режиме полного архива (потребуется больше места и времени для синхронизации).
|
||||
modal:
|
||||
cancel: Отмена
|
||||
save: Сохранить
|
||||
|
|
|
@ -37,7 +37,8 @@ impl NetworkTab for NetworkMetrics {
|
|||
fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
|
||||
let server_stats = Node::get_stats();
|
||||
// Show message when node is not running or loading spinner when metrics are not available.
|
||||
if server_stats.is_none() || server_stats.as_ref().unwrap().diff_stats.height == 0 {
|
||||
if server_stats.is_none() || Node::is_restarting()
|
||||
|| server_stats.as_ref().unwrap().diff_stats.height == 0 {
|
||||
if !Node::is_running() {
|
||||
Network::disabled_node_ui(ui);
|
||||
} else {
|
||||
|
|
|
@ -17,9 +17,9 @@ use std::str::FromStr;
|
|||
|
||||
use egui::{RichText, ScrollArea};
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Modal, NetworkTab, NetworkTabType, View};
|
||||
use crate::gui::views::{Modal, ModalPosition, NetworkTab, NetworkTabType, View};
|
||||
use crate::gui::views::settings_node::NodeSetup;
|
||||
use crate::node::Node;
|
||||
|
||||
|
@ -67,8 +67,30 @@ impl NetworkTab for NetworkSettings {
|
|||
impl NetworkSettings {
|
||||
pub const NODE_RESTART_REQUIRED_MODAL: &'static str = "node_restart_required";
|
||||
|
||||
/// Reminder to restart enabled node to show on edit setting at [`Modal`].
|
||||
pub fn node_restart_required_ui(ui: &mut egui::Ui) {
|
||||
if Node::is_running() {
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(t!("network_settings.restart_node_required"))
|
||||
.size(16.0)
|
||||
.color(Colors::GREEN)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Show [`Modal`] to ask node restart if setting is changed on enabled node.
|
||||
pub fn show_node_restart_required_modal() {
|
||||
if Node::is_running() {
|
||||
// Show modal to apply changes by node restart.
|
||||
let port_modal = Modal::new(NetworkSettings::NODE_RESTART_REQUIRED_MODAL)
|
||||
.position(ModalPosition::Center)
|
||||
.title(t!("network.settings"));
|
||||
Navigator::show_modal(port_modal);
|
||||
}
|
||||
}
|
||||
|
||||
/// Node restart reminder modal content.
|
||||
pub fn node_restart_required_modal(&self, ui: &mut egui::Ui, modal: &Modal) {
|
||||
fn node_restart_required_modal(&self, ui: &mut egui::Ui, modal: &Modal) {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_settings.restart_node_required"))
|
||||
|
|
|
@ -17,7 +17,7 @@ use egui::{Id, Layout, RichText, TextStyle, Widget};
|
|||
use grin_core::global::ChainTypes;
|
||||
use crate::AppConfig;
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::icons::{ASTERISK, CLIPBOARD_TEXT, COMPUTER_TOWER, COPY, POWER};
|
||||
use crate::gui::icons::{CLIPBOARD_TEXT, COMPUTER_TOWER, COPY, POWER, SHIELD, SHIELD_SLASH};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Modal, ModalPosition, Network, View};
|
||||
use crate::gui::views::network_settings::NetworkSettings;
|
||||
|
@ -138,6 +138,9 @@ impl NodeSetup {
|
|||
let api_available = NodeConfig::is_api_port_available(selected_ip, &api_port);
|
||||
self.is_api_port_available = api_available;
|
||||
NodeConfig::save_api_address(selected_ip, &api_port);
|
||||
if api_available {
|
||||
NetworkSettings::show_node_restart_required_modal();
|
||||
}
|
||||
});
|
||||
|
||||
ui.label(RichText::new(t!("network_settings.api_port"))
|
||||
|
@ -165,16 +168,6 @@ impl NodeSetup {
|
|||
ui.add_space(6.0);
|
||||
// Show Foreign API secret setup.
|
||||
self.secret_ui(Self::FOREIGN_API_SECRET_MODAL, ui, cb);
|
||||
|
||||
if Node::is_running() {
|
||||
ui.add_space(2.0);
|
||||
// Show reminder to restart node if settings are changed.
|
||||
ui.label(RichText::new(t!("network_settings.restart_node_required"))
|
||||
.size(16.0)
|
||||
.color(Colors::GREEN)
|
||||
);
|
||||
ui.add_space(2.0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -191,6 +184,21 @@ impl NodeSetup {
|
|||
// Show FTL setup.
|
||||
self.ftl_ui(ui, cb);
|
||||
|
||||
ui.add_space(6.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Validation setup.
|
||||
self.validation_mode_ui(ui);
|
||||
|
||||
ui.add_space(6.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Archive mode setup.
|
||||
self.archive_mode_ui(ui);
|
||||
|
||||
ui.add_space(6.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
|
@ -215,13 +223,7 @@ impl NodeSetup {
|
|||
|
||||
if saved_chain_type != selected_chain_type {
|
||||
AppConfig::change_chain_type(&selected_chain_type);
|
||||
if Node::is_running() {
|
||||
// Show modal to apply changes by node restart.
|
||||
let port_modal = Modal::new(NetworkSettings::NODE_RESTART_REQUIRED_MODAL)
|
||||
.position(ModalPosition::Center)
|
||||
.title(t!("network.settings"));
|
||||
Navigator::show_modal(port_modal);
|
||||
}
|
||||
NetworkSettings::show_node_restart_required_modal();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,7 +265,7 @@ impl NodeSetup {
|
|||
ui.label(RichText::new(t!("network_settings.api_port"))
|
||||
.size(18.0)
|
||||
.color(Colors::GRAY));
|
||||
ui.add_space(8.0);
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Draw API port text edit.
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.api_port_edit)
|
||||
|
@ -276,51 +278,52 @@ impl NodeSetup {
|
|||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
// Show error when specified port is unavailable.
|
||||
// Show error when specified port is unavailable or reminder to restart enabled node.
|
||||
if !self.api_port_available_edit {
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(t!("network_settings.port_unavailable"))
|
||||
.size(16.0)
|
||||
.color(Colors::RED));
|
||||
} else {
|
||||
NetworkSettings::node_restart_required_ui(ui);
|
||||
}
|
||||
|
||||
ui.add_space(12.0);
|
||||
});
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0);
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0);
|
||||
|
||||
// Save button callback.
|
||||
let on_save = || {
|
||||
// Check if port is available.
|
||||
let (api_ip, _) = NodeConfig::get_api_address();
|
||||
let available = NodeConfig::is_api_port_available(&api_ip, &self.api_port_edit);
|
||||
self.api_port_available_edit = available;
|
||||
// Save button callback.
|
||||
let on_save = || {
|
||||
// Check if port is available.
|
||||
let (api_ip, _) = NodeConfig::get_api_address();
|
||||
let available = NodeConfig::is_api_port_available(&api_ip, &self.api_port_edit);
|
||||
self.api_port_available_edit = available;
|
||||
|
||||
if available {
|
||||
// Save port at config if it's available.
|
||||
NodeConfig::save_api_address(&api_ip, &self.api_port_edit);
|
||||
if available {
|
||||
// Save port at config if it's available.
|
||||
NodeConfig::save_api_address(&api_ip, &self.api_port_edit);
|
||||
|
||||
self.is_api_port_available = true;
|
||||
self.is_api_port_available = true;
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
};
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
};
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.save"), Colors::WHITE, on_save);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.save"), Colors::WHITE, on_save);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -333,10 +336,9 @@ impl NodeSetup {
|
|||
};
|
||||
|
||||
let secret_text = if secret_value.is_some() {
|
||||
format!("{}{}{}{}{}{}{}{}{}{}", ASTERISK, ASTERISK, ASTERISK, ASTERISK,
|
||||
ASTERISK, ASTERISK, ASTERISK, ASTERISK, ASTERISK, ASTERISK)
|
||||
format!("{} {}", SHIELD, t!("network_settings.enabled"))
|
||||
} else {
|
||||
t!("network_settings.disabled")
|
||||
format!("{} {}", SHIELD_SLASH, t!("network_settings.disabled"))
|
||||
};
|
||||
|
||||
// Show button to open secret modal.
|
||||
|
@ -373,8 +375,6 @@ impl NodeSetup {
|
|||
.color(Colors::GRAY));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// let Self { api_secret_edit, foreign_api_secret_edit, .. } = self;
|
||||
|
||||
// Draw API port text edit.
|
||||
let edit_text = match modal.id {
|
||||
Self::API_SECRET_MODAL => &mut self.api_secret_edit,
|
||||
|
@ -389,6 +389,7 @@ impl NodeSetup {
|
|||
if text_edit_resp.clicked() {
|
||||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
ui.add_space(12.0);
|
||||
|
||||
// Show buttons to copy/paste text.
|
||||
|
@ -397,10 +398,9 @@ impl NodeSetup {
|
|||
ui.spacing_mut().item_spacing = egui::Vec2::new(12.0, 0.0);
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
// Setup spacing between buttons.
|
||||
columns[0].with_layout(Layout::right_to_left(Align::TOP), |ui| {
|
||||
let copy_text = format!("{} {}", COPY, t!("network_settings.copy"));
|
||||
View::button(ui, copy_text, Colors::WHITE, || {
|
||||
let copy_title = format!("{} {}", COPY, t!("network_settings.copy"));
|
||||
View::button(ui, copy_title, Colors::WHITE, || {
|
||||
match modal.id {
|
||||
Self::API_SECRET_MODAL => {
|
||||
cb.copy_string_to_buffer(self.api_secret_edit.clone());
|
||||
|
@ -413,8 +413,10 @@ impl NodeSetup {
|
|||
});
|
||||
});
|
||||
columns[1].with_layout(Layout::left_to_right(Align::TOP), |ui| {
|
||||
let copy_text = format!("{} {}", CLIPBOARD_TEXT, t!("network_settings.paste"));
|
||||
View::button(ui, copy_text, Colors::WHITE, || {
|
||||
let paste_title = format!("{} {}",
|
||||
CLIPBOARD_TEXT,
|
||||
t!("network_settings.paste"));
|
||||
View::button(ui, paste_title, Colors::WHITE, || {
|
||||
let text = cb.get_string_from_buffer();
|
||||
match modal.id {
|
||||
Self::API_SECRET_MODAL => self.api_secret_edit = text,
|
||||
|
@ -423,43 +425,47 @@ impl NodeSetup {
|
|||
});
|
||||
});
|
||||
});
|
||||
ui.add_space(12.0);
|
||||
});
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0);
|
||||
// Show reminder to restart enabled node.
|
||||
NetworkSettings::node_restart_required_ui(ui);
|
||||
|
||||
// Save button callback.
|
||||
let on_save = || {
|
||||
match modal.id {
|
||||
Self::API_SECRET_MODAL => {
|
||||
let api_secret = &self.api_secret_edit.clone();
|
||||
NodeConfig::save_api_secret(api_secret);
|
||||
}
|
||||
_ => {
|
||||
let foreign_api_secret = &self.foreign_api_secret_edit.clone();
|
||||
NodeConfig::save_foreign_api_secret(foreign_api_secret);
|
||||
}
|
||||
};
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
ui.add_space(12.0);
|
||||
});
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0);
|
||||
|
||||
// Save button callback.
|
||||
let on_save = || {
|
||||
match modal.id {
|
||||
Self::API_SECRET_MODAL => {
|
||||
let api_secret = &self.api_secret_edit.clone();
|
||||
NodeConfig::save_api_secret(api_secret);
|
||||
}
|
||||
_ => {
|
||||
let foreign_api_secret = &self.foreign_api_secret_edit.clone();
|
||||
NodeConfig::save_foreign_api_secret(foreign_api_secret);
|
||||
}
|
||||
};
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
};
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.save"), Colors::WHITE, on_save);
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.save"), Colors::WHITE, on_save);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -482,16 +488,6 @@ impl NodeSetup {
|
|||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
|
||||
if Node::is_running() {
|
||||
ui.add_space(2.0);
|
||||
// Show reminder to restart node if settings are changed.
|
||||
ui.label(RichText::new(t!("network_settings.restart_node_required"))
|
||||
.size(16.0)
|
||||
.color(Colors::GREEN)
|
||||
);
|
||||
ui.add_space(2.0);
|
||||
}
|
||||
ui.add_space(6.0);
|
||||
}
|
||||
|
||||
|
@ -508,7 +504,7 @@ impl NodeSetup {
|
|||
let text_edit_resp = egui::TextEdit::singleline(&mut self.ftl_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(34.0)
|
||||
.desired_width(46.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
|
@ -516,17 +512,18 @@ impl NodeSetup {
|
|||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
// Show error when specified value is not valid.
|
||||
// Show error when specified value is not valid or reminder to restart enabled node.
|
||||
if self.ftl_edit.parse::<u64>().is_err() {
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(t!("network_settings.not_valid_value"))
|
||||
.size(18.0)
|
||||
.color(Colors::RED));
|
||||
} else {
|
||||
NetworkSettings::node_restart_required_ui(ui);
|
||||
}
|
||||
ui.add_space(12.0);
|
||||
});
|
||||
|
||||
ui.add_space(12.0);
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
|
@ -556,4 +553,32 @@ impl NodeSetup {
|
|||
ui.add_space(6.0);
|
||||
});
|
||||
}
|
||||
|
||||
/// Draw chain validation mode setup ui.
|
||||
pub fn validation_mode_ui(&mut self, ui: &mut egui::Ui) {
|
||||
let validate = NodeConfig::is_full_chain_validation();
|
||||
View::checkbox(ui, validate, t!("network_settings.full_validation"), || {
|
||||
NodeConfig::toggle_full_chain_validation();
|
||||
NetworkSettings::show_node_restart_required_modal();
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
ui.label(RichText::new(t!("network_settings.full_validation_description"))
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
}
|
||||
|
||||
/// Draw archive mode setup ui.
|
||||
pub fn archive_mode_ui(&mut self, ui: &mut egui::Ui) {
|
||||
let archive_mode = NodeConfig::is_archive_mode();
|
||||
View::checkbox(ui, archive_mode, t!("network_settings.archive_mode"), || {
|
||||
NodeConfig::toggle_archive_mode();
|
||||
NetworkSettings::show_node_restart_required_modal();
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
ui.label(RichText::new(t!("network_settings.archive_mode_desc"))
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -340,9 +340,9 @@ impl NodeConfig {
|
|||
}
|
||||
|
||||
/// Toggle full chain validation.
|
||||
pub fn toggle_chain_validation() {
|
||||
let mode = Settings::node_config_to_read().members.clone().server.chain_validation_mode;
|
||||
let new_mode = if mode == ChainValidationMode::Disabled {
|
||||
pub fn toggle_full_chain_validation() {
|
||||
let validation_enabled = Self::is_full_chain_validation();
|
||||
let new_mode = if validation_enabled {
|
||||
ChainValidationMode::Disabled
|
||||
} else {
|
||||
ChainValidationMode::EveryBlock
|
||||
|
|
Loading…
Reference in a new issue