From eb68d427485181cdf464a594d0d7972e7379b336 Mon Sep 17 00:00:00 2001 From: djkato Date: Sun, 16 Apr 2023 20:51:50 +0200 Subject: [PATCH] code restructure --- Cargo.lock | 7 + Cargo.toml | 1 + docker-compose.yml | 2 +- src/backend/backend_manager.rs | 71 ++++----- src/backend/parser.rs | 23 +-- src/main.rs | 4 +- src/ui/db_transaction_window.rs | 1 + src/ui/table_window.rs | 247 ++++++++++++++++++-------------- src/ui/window_manager.rs | 18 ++- 9 files changed, 205 insertions(+), 169 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a2d28f7..f48c5dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -719,6 +719,7 @@ dependencies = [ "egui", "egui_extras", "grid", + "if_chain", "regex", "rfd", "sqlx", @@ -1459,6 +1460,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "if_chain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" + [[package]] name = "indexmap" version = "1.9.2" diff --git a/Cargo.toml b/Cargo.toml index 0bb6649..a14a497 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,3 +21,4 @@ rfd = "0.11.1" grid = "0.9.0" regex = "1.7.1" chrono = "0.4.24" +if_chain = "1.0.2" diff --git a/docker-compose.yml b/docker-compose.yml index 9936093..7cdc2cf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,7 +19,7 @@ volumes: # To connect to mysql, do: # sudo docker exec -it csql-Opencart_dummy_DB-1 /bin/bash -# mysql -p +# mysql -pmauFJcuf5dhRMQrjj # [password] # use quotes; # select * from oc_product; diff --git a/src/backend/backend_manager.rs b/src/backend/backend_manager.rs index 9b927e6..a74c6c2 100644 --- a/src/backend/backend_manager.rs +++ b/src/backend/backend_manager.rs @@ -1,6 +1,7 @@ use super::csv_handler::{DataEntry, ImportedData}; use super::database_handler::{DBLoginData, QueryResult, Table, Tables}; use super::parser::parse; +use if_chain::if_chain; use sqlx::MySqlConnection; use std::sync::Arc; use tokio::sync::mpsc::{Receiver, Sender}; @@ -183,62 +184,52 @@ pub fn try_match_headers_to_fields( if !csv_data.are_headers || csv_data.data.is_empty() { return; } - let final_table_index: usize; - if let Some(i) = table_index { - final_table_index = i; - } else if let Some(cw_table_i) = tables.current_working_table { - final_table_index = cw_table_i; + let new_i: usize; + if let Some(table_index) = table_index.or(tables.current_working_table) { + new_i = table_index; } else { return; } - let table_index = final_table_index; - - let db_fields = tables - .tables - .get_mut(table_index) - .unwrap() - .fields - .as_mut() - .unwrap(); + let table_index = new_i; + println!("Trying to automatch table \"{}\"...", table_index); let mut has_matched_some = false; - for field in db_fields { - for (i, header) in csv_data.data.iter_row(0).into_iter().enumerate() { - if &field.description.field == &header.data { - field.mapped_to_col = Some(i); - has_matched_some = true; + if let Some(db_fields) = tables.tables.get_mut(table_index).unwrap().fields.as_mut() { + for field in db_fields { + for (i, header) in csv_data.data.iter_row(0).into_iter().enumerate() { + if &field.description.field == &header.data { + field.mapped_to_col = Some(i); + has_matched_some = true; + } } } } - - if has_matched_some == false - || tables.current_working_table.is_none() - || tables.tables.is_empty() - { + if !has_matched_some { return; } + println!("Autommapped some!"); /* If some got automapped, try to parse them all */ - if let Some(table_i) = tables.current_working_table { - if let Some(table) = tables.tables.get_mut(table_i) { - if let Some(fields) = table.fields.as_mut() { - for (col_index, field) in fields.iter().enumerate() { + if_chain! { + if let Some(table) = tables.tables.get_mut(table_index); + if let Some(fields) = table.fields.as_mut(); + then { + for (field_index, field) in fields.iter().enumerate() { + if let Some(col_index) = field.mapped_to_col { println!( " > automapping field \"{}\" to col \"{:?}\"", &field.description.field, field.mapped_to_col ); - if let Some(col_index) = field.mapped_to_col { - for cell in csv_data.data.iter_mut() { - cell.curr_field_description = Some(field.description.clone()); - parse(cell); - } - } - if is_whole_col_parsed(csv_data, col_index) { - println!("col \"{}\" is parsed whole!", &col_index); - csv_data.parsed_cols.push(col_index); - } - if is_whole_table_parsed(&csv_data) { - csv_data.is_parsed = true; + for cell in csv_data.data.iter_col_mut(col_index) { + cell.curr_field_description = Some(field.description.clone()); + parse(cell); } } + if is_whole_col_parsed(csv_data, field_index) { + println!("col \"{}\" is parsed whole!", &field_index); + csv_data.parsed_cols.push(field_index); + } + if is_whole_table_parsed(&csv_data) { + csv_data.is_parsed = true; + } } } } diff --git a/src/backend/parser.rs b/src/backend/parser.rs index 52498dd..b57bdb8 100644 --- a/src/backend/parser.rs +++ b/src/backend/parser.rs @@ -158,16 +158,19 @@ fn parse_decimal(cell: &mut DataEntry, args: Option) { if let Some(num_args) = process_args(args) { let num_parse_res: Result = cell.data.parse(); if let Ok(_) = num_parse_res { - let dot_i = cell.data.find(".").unwrap(); - // -1 cuz the dot is there - let count_to_dot = cell.data.chars().count() as u32; - let count_from_dot = cell.data.chars().skip(dot_i + 1).count() as u32; - if count_to_dot - 1 <= num_args[0] && count_from_dot >= num_args[1] { - cell.is_parsed = Some(Ok(())); - } else { - cell.is_parsed = Some(Err(Arc::from(<&str as Into< - Box, - >>::into("too many numbers")))) + if let Some(dot_i) = cell.data.find(".") { + // -1 cuz the dot is there + let count_to_dot = cell.data.chars().count() as u32; + let count_from_dot = cell.data.chars().skip(dot_i + 1).count() as u32; + if count_to_dot - 1 <= num_args[0] && count_from_dot >= num_args[1] { + cell.is_parsed = Some(Ok(())); + } else { + cell.is_parsed = Some(Err(Arc::from(<&str as Into< + Box, + >>::into( + "too many numbers" + )))) + } } } else { cell.is_parsed = Some(Err(Arc::from(<&str as Into< diff --git a/src/main.rs b/src/main.rs index 2d93d9e..9b8fcf8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -#![cfg_attr(not(debug_assertions), deny(dead_code), deny(unused_variables))] -#![cfg_attr(debug_assertions, allow(dead_code), allow(unused_variables))] +//#![cfg_attr(not(debug_assertions), deny(dead_code), deny(unused_variables))] +//#![cfg_attr(debug_assertions, allow(dead_code), allow(unused_variables))] mod backend; mod ui; use backend::backend_manager::BackendManger; diff --git a/src/ui/db_transaction_window.rs b/src/ui/db_transaction_window.rs index 6321205..77fbb6c 100644 --- a/src/ui/db_transaction_window.rs +++ b/src/ui/db_transaction_window.rs @@ -41,6 +41,7 @@ impl CSQLWindow for DBTransactionWindow { ui: &mut Ui, frame: &mut eframe::Frame, ) -> Option>> { + println!("Opening Transaction window..."); egui::Window::new("Database Transactions") .id(egui::Id::new("Database Transactions")) .resizable(false) diff --git a/src/ui/table_window.rs b/src/ui/table_window.rs index 1a73ca4..1d4c055 100644 --- a/src/ui/table_window.rs +++ b/src/ui/table_window.rs @@ -4,6 +4,7 @@ use crate::backend::csv_handler::ImportedData; use crate::backend::database_handler::{TableField, Tables}; use egui::{ComboBox, Context, Ui}; use egui_extras::{Column, TableBuilder}; +use if_chain::if_chain; use std::error::Error; use std::sync::Arc; use tokio::sync::mpsc::Sender; @@ -43,7 +44,7 @@ impl CSQLWindow for SpreadSheetWindow { frame: &mut eframe::Frame, ) -> Option>> { self.ui(ui, ctx); - if let Some(return_status) = self.return_status { + if let Some(return_status) = self.return_status.clone() { self.return_status = None; return Some(Ok(return_status)); } @@ -109,16 +110,119 @@ impl SpreadSheetWindow { } }); SpreadSheetWindow::preview_files_being_dropped(ctx); + /*All the dzum checks before making the window... */ - if self.current_table.is_some() { - ui.group(|ui| { - egui::ScrollArea::horizontal().show(ui, |ui| { - self.table_builder(ui) - .unwrap_or_else(|e| println!("Table un-intd, {:?}", e)); - }); - }); + if_chain! { + if let Some(current_table) = self.current_table; + if let Ok(csv_data) = &mut self.csv_data_handle.try_lock(); + if let Ok(db_table_data) = &mut self.db_table_data_handle.try_lock(); + if !csv_data.data.is_empty(); + if let Some(curr_db_table) = db_table_data.tables.get_mut(current_table); + then { + if let Some(curr_db_table_fields) = curr_db_table.fields.as_mut() { + ui.group(|ui| { + egui::ScrollArea::horizontal().show(ui, |ui| { + SpreadSheetWindow::table_builder( + &mut self.sender, + ui, + csv_data, + curr_db_table_fields, + ) + }); + }); + } else { + if !self.is_table_description_request_sent { + if let Ok(mesg) = self.sender.try_send( + Communication::GetTableDescription(self.current_table.unwrap()), + ) {} + } + } + } else { + ui.centered_and_justified(|ui| ui.heading("Import or Drag and Drop a file...")); + } } } + fn table_builder( + sender: &mut Sender, + ui: &mut Ui, + csv_data: &mut MutexGuard, + curr_db_table_fields: &mut Vec, + ) { + let table = TableBuilder::new(ui) + .striped(true) + .cell_layout(egui::Layout::left_to_right(egui::Align::Center)) + /*First collumn for row actions */ + .column(Column::auto().at_most(30.0).resizable(false).clip(false)); + + table + .columns( + Column::auto().resizable(true).clip(false), + csv_data.data.cols(), + ) + .min_scrolled_height(0.0) + .header(20., |mut header| { + /* First Col for row mutators */ + header.col(|ui| {}); + SpreadSheetWindow::add_header_cols( + &mut header, + csv_data, + curr_db_table_fields, + sender, + ); + }) + .body(|body| { + body.rows( + 15., + csv_data.data.rows() - csv_data.are_headers as usize, + |row_index, mut row| { + let headers_i_offset = csv_data.are_headers as usize; + row.col(|ui| { + if ui.button("x").clicked() { + if let Ok(_) = sender.try_send(Communication::RemoveRow(row_index)) + { + }; + } + }); + for curr_cell in csv_data.data.iter_row_mut(row_index + headers_i_offset) { + /* If cell is bound to a field, color it's bg according to is_parsed */ + row.col(|ui| { + let mut err: Option> = None; + if curr_cell.curr_field_description.is_some() { + match &curr_cell.is_parsed { + Some(parse) => match parse { + Ok(_) => { + ui.style_mut().visuals.extreme_bg_color = + egui::Color32::DARK_GREEN + } + Err(arc) => { + err = Some(arc.clone()); + ui.style_mut().visuals.extreme_bg_color = + egui::Color32::DARK_RED; + } + }, + None => { + ui.style_mut().visuals.extreme_bg_color = + egui::Color32::DARK_GRAY + } + } + } + if let Some(err) = err { + ui.text_edit_singleline(&mut curr_cell.data) + .on_hover_text(format!("{}", err)); + } else { + ui.text_edit_singleline(&mut curr_cell.data); + } + + if curr_cell.curr_field_description.is_some() { + ui.reset_style(); + } + }); + } + }, + ); + }); + } + fn table_options(&mut self, ui: &mut Ui) { /* Create table select option, only enable if the tables are discovered yet*/ if let Ok(db_table_data) = &mut self.db_table_data_handle.try_lock() { @@ -132,115 +236,34 @@ impl SpreadSheetWindow { /* autoselect oc_product in debug mode */ if cfg!(debug_assertions) && self.current_table.is_none() { self.current_table = Some(88); + db_table_data.current_working_table = Some(88); if let Some(table_88) = &db_table_data.tables.get(88) { select_table = select_table.selected_text(table_88.name.clone()); } } ui.vertical(|ui| { select_table.show_ui(ui, |ui| { - for (table_i, table) in db_table_data.tables.iter().enumerate() { - ui.selectable_value( - &mut self.current_table, - Some(table_i.clone()), - &table.name, - ); + let mut current_working_table_i = None; + for (table_i, table) in db_table_data.tables.iter_mut().enumerate() { + if ui + .selectable_value( + &mut self.current_table, + Some(table_i.clone()), + &table.name, + ) + .clicked() + { + current_working_table_i = Some(table_i); + }; + } + if let Some(current_working_table_i) = current_working_table_i { + db_table_data.current_working_table = Some(current_working_table_i); } }); }); }); } } - fn table_builder(&mut self, ui: &mut Ui) -> Result<(), Box> { - if let Ok(csv_data) = &mut self.csv_data_handle.try_lock() { - if let Ok(db_table_data) = &mut self.db_table_data_handle.try_lock() { - //ref to all fields in curr db table - let mut curr_db_table_fields: &mut Vec = match db_table_data - .tables - .get_mut(self.current_table.unwrap()) - .ok_or("no current table")? - .fields - .as_mut() - .ok_or("no fields yet") - { - Ok(val) => val, - Err(e) => { - if !self.is_table_description_request_sent { - self.sender.try_send(Communication::GetTableDescription( - self.current_table.unwrap(), - ))?; - self.is_table_description_request_sent = true; - } - return Err(Box::from( - >>::into(e.to_string()), - )); - } - }; - if csv_data.data.is_empty() { - return Err(>>::into( - "no rows yet".to_string(), - )); - } - let table = TableBuilder::new(ui) - .striped(true) - .cell_layout(egui::Layout::left_to_right(egui::Align::Center)) - /*First collumn for row actions */ - .column(Column::auto().at_most(30.0).resizable(false).clip(false)); - - table - .columns( - Column::auto().resizable(true).clip(false), - csv_data.data.cols(), - ) - .min_scrolled_height(0.0) - .header(20., |mut header| { - /* First Col for row mutators */ - header.col(|ui|{ - }); - SpreadSheetWindow::add_header_cols(&mut header, csv_data,&mut curr_db_table_fields, &mut self.sender); - }) - .body(|body| { - body.rows(15., csv_data.data.rows() - csv_data.are_headers as usize, |row_index, mut row| { - let headers_i_offset = csv_data.are_headers as usize; - row.col(|ui|{ - if ui.button("x").clicked(){} - }); - for curr_cell in - csv_data.data.iter_row_mut(row_index + headers_i_offset) - { - /* If cell is bound to a field, color it's bg according to is_parsed */ - row.col(|ui| { - let mut err: Option> = None; - if curr_cell.curr_field_description.is_some() { - match &curr_cell.is_parsed{ - Some(parse) => match parse{ - Ok(_) => ui.style_mut().visuals.extreme_bg_color = egui::Color32::DARK_GREEN, - Err(arc) => { - err = Some(arc.clone()); - ui.style_mut().visuals.extreme_bg_color = egui::Color32::DARK_RED; - } - } - None => ui.style_mut().visuals.extreme_bg_color = egui::Color32::DARK_GRAY, - } - } - if err.is_some(){ - ui.text_edit_singleline(&mut curr_cell.data).on_hover_text(format!("{}", &err.unwrap())); - } else{ - ui.text_edit_singleline(&mut curr_cell.data); - } - - if curr_cell.curr_field_description.is_some() { - ui.reset_style(); - } - }); - } - }); - }); - } - } else { - ui.centered_and_justified(|ui| ui.heading("Drag and drop or Open a file...")); - } - Ok(()) - } } impl SpreadSheetWindow { @@ -253,7 +276,9 @@ impl SpreadSheetWindow { for i in 0..csv_data.data.cols() { header.col(|ui| { ui.vertical_centered_justified(|ui| { - if ui.button("x").clicked() {} + if ui.button("x").clicked() { + if let Ok(_) = sender.try_send(Communication::RemoveCol(i)) {} + } if csv_data.parsed_cols.contains(&i) { /* If the whole col is parsed, change header bg to green, else normal */ ui.style_mut().visuals.override_text_color = Some(egui::Color32::GREEN); @@ -340,12 +365,12 @@ impl SpreadSheetWindow { } else { return; } - self.sender - .try_send(Communication::LoadImportFilePath( - final_path.display().to_string(), - )) - .unwrap_or_else(|err| println!("failed to send loadimportpath, {}", err)); } + self.sender + .try_send(Communication::LoadImportFilePath( + final_path.display().to_string(), + )) + .unwrap_or_else(|err| println!("failed to send loadimportpath, {}", err)); } pub fn open_dropped_file(&mut self, path: &egui::InputState) { diff --git a/src/ui/window_manager.rs b/src/ui/window_manager.rs index d35ec01..c266d11 100644 --- a/src/ui/window_manager.rs +++ b/src/ui/window_manager.rs @@ -1,15 +1,15 @@ +use super::db_transaction_window::DBTransactionWindow; use crate::backend::backend_manager::Communication; use crate::backend::csv_handler::ImportedData; use crate::backend::database_handler::Tables; use crate::ui::db_login_window::DBLoginWindow; use crate::ui::table_window::SpreadSheetWindow; use eframe::{run_native, App, NativeOptions}; +use if_chain::*; use std::sync::Arc; use tokio::sync::mpsc::{channel, Sender}; use tokio::sync::Mutex; -use super::db_transaction_window::DBTransactionWindow; - pub fn create_ui( sender: Sender, csv_data_handle: Arc>, @@ -60,8 +60,11 @@ impl App for CSQL { if let Some(result) = self.spreadsheet_window.refresh(ctx, ui, frame) { match result { Ok(status) => match status { - ExitStatus::StartLoginWindow => self.should_open_transaction_window = true, - ExitStatus::StartTransactionWindow => self.should_open_login_window = true, + ExitStatus::StartLoginWindow => self.should_open_login_window = true, + ExitStatus::StartTransactionWindow => { + self.should_open_transaction_window = true; + println!("should_open_transaction_window"); + } _ => {} }, _ => (), @@ -83,7 +86,9 @@ impl App for CSQL { self.db_login_window = Some(DBLoginWindow::default(self.sender.clone())); } } + if self.should_open_transaction_window { + println!("inside if.shoud..."); if let Some(db_transaction_window) = self.db_transaction_window.as_mut() { if let Some(result) = db_transaction_window.refresh(ctx, ui, frame) { match result { @@ -95,14 +100,17 @@ impl App for CSQL { } } } else { + println!("No transaction window, creating..."); if let Ok(db_table_data) = self.db_table_data_handle.try_lock() { + println!("got a db_lock"); if let Some(cw_table_i) = db_table_data.current_working_table { + println!("Found a current_working _table"); self.db_transaction_window = Some(DBTransactionWindow::default( self.sender.clone(), cw_table_i, )) } - } + }; } } });