update terminal ui to show nested examples
This commit is contained in:
parent
b31651cfeb
commit
0df79e78c6
@ -82,6 +82,70 @@ pub struct ExampleScript {
|
|||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum ExampleTreeNode {
|
||||||
|
File {
|
||||||
|
name: String,
|
||||||
|
path: PathBuf,
|
||||||
|
},
|
||||||
|
Folder {
|
||||||
|
name: String,
|
||||||
|
path: PathBuf,
|
||||||
|
children: Vec<ExampleTreeNode>,
|
||||||
|
expanded: bool,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExampleTreeNode {
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
ExampleTreeNode::File { name, .. } => name,
|
||||||
|
ExampleTreeNode::Folder { name, .. } => name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path(&self) -> &PathBuf {
|
||||||
|
match self {
|
||||||
|
ExampleTreeNode::File { path, .. } => path,
|
||||||
|
ExampleTreeNode::Folder { path, .. } => path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_file(&self) -> bool {
|
||||||
|
matches!(self, ExampleTreeNode::File { .. })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_folder(&self) -> bool {
|
||||||
|
matches!(self, ExampleTreeNode::Folder { .. })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_expanded(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
ExampleTreeNode::File { .. } => false,
|
||||||
|
ExampleTreeNode::Folder { expanded, .. } => *expanded,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toggle_expanded(&mut self) {
|
||||||
|
if let ExampleTreeNode::Folder { expanded, .. } = self {
|
||||||
|
*expanded = !*expanded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_expanded(&mut self, expand: bool) {
|
||||||
|
if let ExampleTreeNode::Folder { expanded, .. } = self {
|
||||||
|
*expanded = expand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ExampleTreeItem {
|
||||||
|
pub node: ExampleTreeNode,
|
||||||
|
pub depth: usize,
|
||||||
|
pub index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct JobInfo {
|
pub struct JobInfo {
|
||||||
pub job: Job,
|
pub job: Job,
|
||||||
@ -108,6 +172,11 @@ pub struct App {
|
|||||||
pub status_message: Option<String>,
|
pub status_message: Option<String>,
|
||||||
pub last_executed_job: Option<JobInfo>,
|
pub last_executed_job: Option<JobInfo>,
|
||||||
pub last_refresh: Instant,
|
pub last_refresh: Instant,
|
||||||
|
// New hierarchical examples system
|
||||||
|
pub example_tree: Vec<ExampleTreeNode>,
|
||||||
|
pub example_tree_items: Vec<ExampleTreeItem>,
|
||||||
|
pub example_tree_state: ListState,
|
||||||
|
pub selected_tree_item: Option<ExampleTreeItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ActorTui;
|
pub struct ActorTui;
|
||||||
@ -138,44 +207,194 @@ impl App {
|
|||||||
status_message: None,
|
status_message: None,
|
||||||
last_executed_job: None,
|
last_executed_job: None,
|
||||||
last_refresh: Instant::now(),
|
last_refresh: Instant::now(),
|
||||||
|
// Initialize new hierarchical examples system
|
||||||
|
example_tree: Vec::new(),
|
||||||
|
example_tree_items: Vec::new(),
|
||||||
|
example_tree_state: ListState::default(),
|
||||||
|
selected_tree_item: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(dir) = example_dir {
|
if let Some(dir) = example_dir {
|
||||||
if let Err(e) = app.load_examples(dir) {
|
if let Err(e) = app.load_examples_tree(dir) {
|
||||||
error!("Failed to load examples: {}", e);
|
error!("Failed to load examples tree: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(app)
|
Ok(app)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_examples(&mut self, dir: PathBuf) -> Result<()> {
|
pub fn load_examples_tree(&mut self, dir: PathBuf) -> Result<()> {
|
||||||
if !dir.exists() {
|
if !dir.exists() {
|
||||||
|
log::warn!("Examples directory does not exist: {:?}", dir);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log::info!("Loading examples tree from: {:?}", dir);
|
||||||
|
|
||||||
|
// Load hierarchical tree structure
|
||||||
|
match self.load_example_tree(&dir) {
|
||||||
|
Ok(tree) => {
|
||||||
|
self.example_tree = tree;
|
||||||
|
log::info!("Successfully loaded {} top-level tree nodes", self.example_tree.len());
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Failed to load example tree: {}", e);
|
||||||
|
// Create a simple fallback structure
|
||||||
|
self.example_tree = vec![
|
||||||
|
ExampleTreeNode::File {
|
||||||
|
name: "Error loading examples".to_string(),
|
||||||
|
path: dir.join("error.rhai"),
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.rebuild_tree_items();
|
||||||
|
log::info!("Rebuilt tree items: {} total items", self.example_tree_items.len());
|
||||||
|
|
||||||
|
if !self.example_tree_items.is_empty() {
|
||||||
|
self.example_tree_state.select(Some(0));
|
||||||
|
self.selected_tree_item = Some(self.example_tree_items[0].clone());
|
||||||
|
|
||||||
|
// Update selected_example for backward compatibility
|
||||||
|
if let Some(first_file) = self.find_first_file_in_tree() {
|
||||||
|
self.selected_example = Some(ExampleScript {
|
||||||
|
name: first_file.name().to_string(),
|
||||||
|
path: first_file.path().clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_example_tree(&self, dir: &PathBuf) -> Result<Vec<ExampleTreeNode>> {
|
||||||
|
let mut nodes = Vec::new();
|
||||||
|
|
||||||
|
log::debug!("Loading directory: {:?}", dir);
|
||||||
|
|
||||||
|
let mut entries: Vec<_> = fs::read_dir(dir)?
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
|
log::debug!("Found {} entries in {:?}", entries.len(), dir);
|
||||||
|
|
||||||
|
// Sort entries: directories first, then files, both alphabetically
|
||||||
|
entries.sort_by(|a, b| {
|
||||||
|
let a_is_dir = a.path().is_dir();
|
||||||
|
let b_is_dir = b.path().is_dir();
|
||||||
|
|
||||||
|
match (a_is_dir, b_is_dir) {
|
||||||
|
(true, false) => std::cmp::Ordering::Less,
|
||||||
|
(false, true) => std::cmp::Ordering::Greater,
|
||||||
|
_ => a.file_name().cmp(&b.file_name()),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for entry in entries {
|
||||||
|
let path = entry.path();
|
||||||
|
let name = entry.file_name().to_string_lossy().to_string();
|
||||||
|
|
||||||
|
if path.is_dir() {
|
||||||
|
log::debug!("Loading folder: {}", name);
|
||||||
|
let children = self.load_example_tree(&path)?;
|
||||||
|
log::debug!("Folder '{}' has {} children", name, children.len());
|
||||||
|
nodes.push(ExampleTreeNode::Folder {
|
||||||
|
name,
|
||||||
|
path,
|
||||||
|
children,
|
||||||
|
expanded: true, // Expand folders by default to show hierarchy
|
||||||
|
});
|
||||||
|
} else if path.extension().map_or(false, |ext| ext == "rhai") {
|
||||||
|
log::debug!("Loading file: {}", name);
|
||||||
|
nodes.push(ExampleTreeNode::File {
|
||||||
|
name: path.file_stem()
|
||||||
|
.and_then(|s| s.to_str())
|
||||||
|
.unwrap_or(&name)
|
||||||
|
.to_string(),
|
||||||
|
path,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(nodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_flat_examples(&mut self, dir: &PathBuf) -> Result<()> {
|
||||||
|
let mut examples = Vec::new();
|
||||||
|
self.collect_all_rhai_files(&mut examples, dir)?;
|
||||||
|
self.examples = examples;
|
||||||
|
|
||||||
|
if !self.examples.is_empty() {
|
||||||
|
self.example_list_state.select(Some(0));
|
||||||
|
if self.selected_example.is_none() {
|
||||||
|
self.selected_example = Some(self.examples[0].clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_all_rhai_files(&self, examples: &mut Vec<ExampleScript>, dir: &PathBuf) -> Result<()> {
|
||||||
for entry in fs::read_dir(dir)? {
|
for entry in fs::read_dir(dir)? {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
|
|
||||||
if path.is_file() && path.extension().map_or(false, |ext| ext == "rhai") {
|
if path.is_dir() {
|
||||||
|
self.collect_all_rhai_files(examples, &path)?;
|
||||||
|
} else if path.extension().map_or(false, |ext| ext == "rhai") {
|
||||||
if let Some(name) = path.file_stem().and_then(|s| s.to_str()) {
|
if let Some(name) = path.file_stem().and_then(|s| s.to_str()) {
|
||||||
self.examples.push(ExampleScript {
|
examples.push(ExampleScript {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
path,
|
path,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.examples.is_empty() {
|
|
||||||
self.example_list_state.select(Some(0));
|
|
||||||
self.selected_example = Some(self.examples[0].clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rebuild_tree_items(&mut self) {
|
||||||
|
self.example_tree_items.clear();
|
||||||
|
log::info!("Rebuilding tree items from {} root nodes", self.example_tree.len());
|
||||||
|
let mut index = 0;
|
||||||
|
let tree_clone = self.example_tree.clone();
|
||||||
|
for node in &tree_clone {
|
||||||
|
log::info!("Processing root node: {:?}", node.name());
|
||||||
|
self.add_tree_items_recursive(node, 0, &mut index);
|
||||||
|
}
|
||||||
|
log::info!("Final tree items count: {}", self.example_tree_items.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_tree_items_recursive(&mut self, node: &ExampleTreeNode, depth: usize, index: &mut usize) {
|
||||||
|
// Always add the current node to the flattened list
|
||||||
|
log::debug!("Adding tree item: {} at depth {}", node.name(), depth);
|
||||||
|
self.example_tree_items.push(ExampleTreeItem {
|
||||||
|
node: node.clone(),
|
||||||
|
depth,
|
||||||
|
index: *index,
|
||||||
|
});
|
||||||
|
*index += 1;
|
||||||
|
|
||||||
|
// For folders, add children only if the folder is expanded
|
||||||
|
if let ExampleTreeNode::Folder { children, expanded, .. } = node {
|
||||||
|
log::debug!("Folder '{}' has {} children, expanded: {}", node.name(), children.len(), expanded);
|
||||||
|
if *expanded {
|
||||||
|
for child in children {
|
||||||
|
self.add_tree_items_recursive(child, depth + 1, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_first_file_in_tree(&self) -> Option<&ExampleTreeNode> {
|
||||||
|
for item in &self.example_tree_items {
|
||||||
|
if item.node.is_file() {
|
||||||
|
return Some(&item.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn refresh_jobs(&mut self) -> Result<()> {
|
pub async fn refresh_jobs(&mut self) -> Result<()> {
|
||||||
let mut conn = self.redis_client.get_multiplexed_async_connection().await?;
|
let mut conn = self.redis_client.get_multiplexed_async_connection().await?;
|
||||||
|
|
||||||
@ -403,13 +622,13 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_example(&mut self) {
|
pub fn next_example(&mut self) {
|
||||||
if self.examples.is_empty() {
|
if self.example_tree_items.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let selected = match self.example_list_state.selected() {
|
let i = match self.example_tree_state.selected() {
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
if i >= self.examples.len() - 1 {
|
if i >= self.example_tree_items.len() - 1 {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
i + 1
|
i + 1
|
||||||
@ -417,27 +636,109 @@ impl App {
|
|||||||
}
|
}
|
||||||
None => 0,
|
None => 0,
|
||||||
};
|
};
|
||||||
self.example_list_state.select(Some(selected));
|
self.example_tree_state.select(Some(i));
|
||||||
self.selected_example = Some(self.examples[selected].clone());
|
self.selected_tree_item = Some(self.example_tree_items[i].clone());
|
||||||
|
|
||||||
|
// Update selected_example for backward compatibility
|
||||||
|
if self.example_tree_items[i].node.is_file() {
|
||||||
|
self.selected_example = Some(ExampleScript {
|
||||||
|
name: self.example_tree_items[i].node.name().to_string(),
|
||||||
|
path: self.example_tree_items[i].node.path().clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn previous_example(&mut self) {
|
pub fn previous_example(&mut self) {
|
||||||
if self.examples.is_empty() {
|
if self.example_tree_items.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let selected = match self.example_list_state.selected() {
|
let i = match self.example_tree_state.selected() {
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
self.examples.len() - 1
|
self.example_tree_items.len() - 1
|
||||||
} else {
|
} else {
|
||||||
i - 1
|
i - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => 0,
|
None => 0,
|
||||||
};
|
};
|
||||||
self.example_list_state.select(Some(selected));
|
self.example_tree_state.select(Some(i));
|
||||||
self.selected_example = Some(self.examples[selected].clone());
|
self.selected_tree_item = Some(self.example_tree_items[i].clone());
|
||||||
|
|
||||||
|
// Update selected_example for backward compatibility
|
||||||
|
if self.example_tree_items[i].node.is_file() {
|
||||||
|
self.selected_example = Some(ExampleScript {
|
||||||
|
name: self.example_tree_items[i].node.name().to_string(),
|
||||||
|
path: self.example_tree_items[i].node.path().clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expand_selected_folder(&mut self) {
|
||||||
|
if let Some(selected_index) = self.example_tree_state.selected() {
|
||||||
|
if selected_index < self.example_tree_items.len() {
|
||||||
|
let item = &self.example_tree_items[selected_index];
|
||||||
|
if item.node.is_folder() {
|
||||||
|
let path = item.node.path().clone();
|
||||||
|
self.expand_folder_by_path(&path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn collapse_selected_folder(&mut self) {
|
||||||
|
if let Some(selected_index) = self.example_tree_state.selected() {
|
||||||
|
if selected_index < self.example_tree_items.len() {
|
||||||
|
let item = &self.example_tree_items[selected_index];
|
||||||
|
if item.node.is_folder() {
|
||||||
|
let path = item.node.path().clone();
|
||||||
|
self.collapse_folder_by_path(&path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toggle_selected_folder(&mut self) {
|
||||||
|
if let Some(selected_index) = self.example_tree_state.selected() {
|
||||||
|
if selected_index < self.example_tree_items.len() {
|
||||||
|
let item = &self.example_tree_items[selected_index];
|
||||||
|
if item.node.is_folder() {
|
||||||
|
let path = item.node.path().clone();
|
||||||
|
let is_expanded = item.node.is_expanded();
|
||||||
|
if is_expanded {
|
||||||
|
self.collapse_folder_by_path(&path);
|
||||||
|
} else {
|
||||||
|
self.expand_folder_by_path(&path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expand_folder_by_path(&mut self, target_path: &PathBuf) {
|
||||||
|
Self::set_folder_expanded_by_path_static(&mut self.example_tree, target_path, true);
|
||||||
|
self.rebuild_tree_items();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collapse_folder_by_path(&mut self, target_path: &PathBuf) {
|
||||||
|
Self::set_folder_expanded_by_path_static(&mut self.example_tree, target_path, false);
|
||||||
|
self.rebuild_tree_items();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_folder_expanded_by_path_static(nodes: &mut Vec<ExampleTreeNode>, target_path: &PathBuf, expanded: bool) {
|
||||||
|
for node in nodes {
|
||||||
|
match node {
|
||||||
|
ExampleTreeNode::Folder { path, children, expanded: node_expanded, .. } => {
|
||||||
|
if path == target_path {
|
||||||
|
*node_expanded = expanded;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Self::set_folder_expanded_by_path_static(children, target_path, expanded);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -868,20 +1169,33 @@ fn render_examples(f: &mut Frame, app: &mut App, area: Rect) {
|
|||||||
.constraints([Constraint::Percentage(40), Constraint::Percentage(60)])
|
.constraints([Constraint::Percentage(40), Constraint::Percentage(60)])
|
||||||
.split(area);
|
.split(area);
|
||||||
|
|
||||||
// Example list
|
// Hierarchical example tree list
|
||||||
let examples: Vec<ListItem> = app.examples
|
let tree_items: Vec<ListItem> = app.example_tree_items
|
||||||
.iter()
|
.iter()
|
||||||
.map(|example| {
|
.map(|item| {
|
||||||
ListItem::new(Line::from(vec![Span::raw(example.name.clone())]))
|
let indent = " ".repeat(item.depth);
|
||||||
|
let (icon, name) = match &item.node {
|
||||||
|
ExampleTreeNode::File { name, .. } => ("📄", name.as_str()),
|
||||||
|
ExampleTreeNode::Folder { name, expanded, .. } => {
|
||||||
|
if *expanded {
|
||||||
|
("📂", name.as_str())
|
||||||
|
} else {
|
||||||
|
("📁", name.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let display_text = format!("{}{} {}", indent, icon, name);
|
||||||
|
ListItem::new(Line::from(vec![Span::raw(display_text)]))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let examples_list = List::new(examples)
|
let examples_list = List::new(tree_items)
|
||||||
.block(Block::default().borders(Borders::ALL).title("Example Scripts"))
|
.block(Block::default().borders(Borders::ALL).title("Example Scripts (→ expand, ← collapse)"))
|
||||||
.highlight_style(Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD))
|
.highlight_style(Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD))
|
||||||
.highlight_symbol("> ");
|
.highlight_symbol("> ");
|
||||||
|
|
||||||
f.render_stateful_widget(examples_list, chunks[0], &mut app.example_list_state);
|
f.render_stateful_widget(examples_list, chunks[0], &mut app.example_tree_state);
|
||||||
|
|
||||||
// Example content
|
// Example content
|
||||||
if let Some(ref example) = app.selected_example {
|
if let Some(ref example) = app.selected_example {
|
||||||
@ -992,14 +1306,41 @@ async fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> Result
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
KeyCode::Left => {
|
||||||
|
if app.current_tab == TabState::Examples {
|
||||||
|
app.collapse_selected_folder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeyCode::Right => {
|
||||||
|
if app.current_tab == TabState::Examples {
|
||||||
|
app.expand_selected_folder();
|
||||||
|
}
|
||||||
|
}
|
||||||
KeyCode::Enter => {
|
KeyCode::Enter => {
|
||||||
if app.current_tab == TabState::Examples {
|
if app.current_tab == TabState::Examples {
|
||||||
if let Some(example) = app.selected_example.clone() {
|
// Handle hierarchical tree navigation
|
||||||
if let Err(e) = app.load_example_to_new_job(&example) {
|
if let Some(selected_index) = app.example_tree_state.selected() {
|
||||||
app.status_message = Some(format!("Error loading example: {}", e));
|
if selected_index < app.example_tree_items.len() {
|
||||||
} else {
|
let item = app.example_tree_items[selected_index].clone();
|
||||||
app.current_tab = TabState::NewJob;
|
match &item.node {
|
||||||
app.status_message = Some(format!("Loaded example '{}' into New Job tab", example.name));
|
ExampleTreeNode::Folder { .. } => {
|
||||||
|
// Toggle folder expand/collapse
|
||||||
|
app.toggle_selected_folder();
|
||||||
|
}
|
||||||
|
ExampleTreeNode::File { path, name, .. } => {
|
||||||
|
// Load file into New Job tab
|
||||||
|
let example = ExampleScript {
|
||||||
|
name: name.clone(),
|
||||||
|
path: path.clone(),
|
||||||
|
};
|
||||||
|
if let Err(e) = app.load_example_to_new_job(&example) {
|
||||||
|
app.status_message = Some(format!("Error loading example: {}", e));
|
||||||
|
} else {
|
||||||
|
app.current_tab = TabState::NewJob;
|
||||||
|
app.status_message = Some(format!("Loaded example '{}' into New Job tab", name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if app.current_tab == TabState::NewJob {
|
} else if app.current_tab == TabState::NewJob {
|
||||||
|
Loading…
Reference in New Issue
Block a user