Import json and csv
plus the worlds dumbest boolean logic
This commit is contained in:
parent
9fff3608d6
commit
7e55ad033e
|
|
@ -11,6 +11,7 @@ eframe = { version = "0.33", default-features = false, features = [
|
|||
"wayland",
|
||||
"persistence",
|
||||
]}
|
||||
poll-promise = "0.3"
|
||||
|
||||
log = "0.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@ pub struct MainWindowState {
|
|||
pub plate_display_options: PlateDisplayOptions,
|
||||
pub csv_export_type: CsvExportType,
|
||||
pub show_plates_horizontal: bool,
|
||||
#[serde(skip)]
|
||||
pub json_upload_promise: Option<FileUploadPromise>,
|
||||
#[serde(skip)]
|
||||
pub csv_upload_promise: Option<FileUploadPromise>,
|
||||
}
|
||||
|
||||
impl Default for MainWindowState {
|
||||
|
|
@ -32,6 +36,8 @@ impl Default for MainWindowState {
|
|||
plate_display_options: PlateDisplayOptions::default(),
|
||||
csv_export_type: CsvExportType::default(),
|
||||
show_plates_horizontal: false,
|
||||
json_upload_promise: None,
|
||||
csv_upload_promise: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -53,6 +59,14 @@ impl std::fmt::Display for CsvExportType {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct FileUploadPromise(pub poll_promise::Promise<Option<Vec<u8>>>);
|
||||
|
||||
impl std::fmt::Debug for FileUploadPromise {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("FileUploadPromise").finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct PlateToolEframe {
|
||||
|
|
@ -276,5 +290,51 @@ impl eframe::App for PlateToolEframe {
|
|||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
process_promises(
|
||||
&mut self.main_state,
|
||||
&mut self.modal_state,
|
||||
&mut self.current_transfer_state,
|
||||
&mut self.main_window_state,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn process_promises(
|
||||
main_state: &mut MainState,
|
||||
_modal_state: &mut ModalState,
|
||||
_current_transfer_state: &mut CurrentTransferState,
|
||||
main_window_state: &mut MainWindowState,
|
||||
) {
|
||||
if let Some(promise) = &main_window_state.json_upload_promise {
|
||||
if let Some(result) = promise.0.ready() {
|
||||
if let Some(data) = result {
|
||||
match serde_json::from_slice::<MainState>(data) {
|
||||
Ok(new_main_state) => {
|
||||
log::info!("Loaded new main state from file.");
|
||||
*main_state = new_main_state
|
||||
}
|
||||
Err(e) => log::error!("Failed loading imported state JSON: {}", e),
|
||||
}
|
||||
}
|
||||
main_window_state.json_upload_promise = None;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(promise) = &main_window_state.csv_upload_promise {
|
||||
if let Some(result) = promise.0.ready() {
|
||||
log::info!("csv file read");
|
||||
if let Some(data) = result {
|
||||
if let Ok(data) = String::from_utf8(data.to_vec()) {
|
||||
let auto_output = plate_tool_lib::csv::read_csv_auto(&data);
|
||||
main_state.source_plates.extend(auto_output.sources);
|
||||
main_state
|
||||
.destination_plates
|
||||
.extend(auto_output.destinations);
|
||||
main_state.transfers.extend(auto_output.transfers);
|
||||
}
|
||||
}
|
||||
main_window_state.csv_upload_promise = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ where
|
|||
response
|
||||
}
|
||||
|
||||
// literally why is this not given in the emath::Numeric definition
|
||||
fn clamp_partial<T: PartialOrd + Copy + std::fmt::Debug>(val: T, min: T, max: T) -> T {
|
||||
if val < min { min }
|
||||
else if val > max { max }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use crate::app;
|
||||
|
||||
// Native case, use rfd
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn save_file(data: &[u8], default_filename: Option<&str>) {
|
||||
|
|
@ -20,27 +23,51 @@ pub fn save_file(data: &[u8], default_filename: Option<&str>) {
|
|||
});
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn upload_file(filetype: &str, extension: &str) -> app::FileUploadPromise {
|
||||
use poll_promise;
|
||||
use rfd::FileDialog;
|
||||
|
||||
let filetype: String = filetype.to_owned();
|
||||
let extension: String = extension.to_owned();
|
||||
|
||||
app::FileUploadPromise(poll_promise::Promise::spawn_thread(
|
||||
"file_upload",
|
||||
move || {
|
||||
FileDialog::new()
|
||||
.add_filter(filetype, &[extension])
|
||||
.pick_file()
|
||||
.and_then(|path| {
|
||||
let data = std::fs::read(path).ok()?;
|
||||
log::info!("Read {} bytes", data.len());
|
||||
Some(data)
|
||||
})
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
// Web case, use web_sys
|
||||
// Not tested yet!!
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn save_file(default_filename: Option<&str>, data: &[u8]) {
|
||||
use wasm_bindgen::JsCast;
|
||||
use web_sys::{Blob, HtmlAnchorElement, Url};
|
||||
|
||||
|
||||
let array = js_sys::Uint8Array::from(data);
|
||||
let blob = Blob::new_with_u8_array_sequence(
|
||||
&js_sys::Array::from_iter([array])
|
||||
).unwrap();
|
||||
|
||||
let blob = Blob::new_with_u8_array_sequence(&js_sys::Array::from_iter([array])).unwrap();
|
||||
|
||||
let url = Url::create_object_url_with_blob(&blob).unwrap();
|
||||
|
||||
|
||||
let document = web_sys::window().unwrap().document().unwrap();
|
||||
let anchor = document.create_element("a").unwrap()
|
||||
.dyn_into::<HtmlAnchorElement>().unwrap();
|
||||
|
||||
let anchor = document
|
||||
.create_element("a")
|
||||
.unwrap()
|
||||
.dyn_into::<HtmlAnchorElement>()
|
||||
.unwrap();
|
||||
|
||||
anchor.set_href(&url);
|
||||
anchor.set_download(default_filename.unwrap_or("download.csv"));
|
||||
anchor.click();
|
||||
|
||||
|
||||
Url::revoke_object_url(&url).unwrap();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::app::{CsvExportType, MainWindowState};
|
||||
use crate::file_handling::save_file;
|
||||
use crate::main_state::MainState;
|
||||
use crate::file_handling::{self, save_file};
|
||||
use crate::main_state::{self, MainState};
|
||||
use crate::modals::ModalState;
|
||||
use crate::transfer_menu::CurrentTransferState;
|
||||
|
||||
|
|
@ -100,11 +100,11 @@ fn render_export_menu(
|
|||
.iter()
|
||||
.find(|dpi| dpi.get_uuid() == transfer.dest_id)?;
|
||||
|
||||
if main_window_state.csv_export_type != CsvExportType::EchoClient
|
||||
|| main_state
|
||||
if main_window_state.csv_export_type == CsvExportType::EchoClient
|
||||
&& main_state
|
||||
.get_current_source_uuid()
|
||||
.is_some_and(|x| x != src_barcode.get_uuid())
|
||||
|| main_state
|
||||
&& main_state
|
||||
.get_current_destination_uuid()
|
||||
.is_some_and(|x| x != dest_barcode.get_uuid())
|
||||
{
|
||||
|
|
@ -119,6 +119,7 @@ fn render_export_menu(
|
|||
})
|
||||
.flatten()
|
||||
.collect();
|
||||
log::info!("There are {} TransferRecords to write", records.len());
|
||||
|
||||
let data = match main_window_state.csv_export_type {
|
||||
CsvExportType::Normal => records_to_csv(records),
|
||||
|
|
@ -126,6 +127,7 @@ fn render_export_menu(
|
|||
};
|
||||
if let Ok(data) = data {
|
||||
let bytes: &[u8] = data.as_bytes();
|
||||
log::info!("There are {} bytes to be written to chosen file", bytes.len());
|
||||
save_file(bytes, Some("transfers.csv"));
|
||||
}
|
||||
}
|
||||
|
|
@ -140,13 +142,47 @@ fn render_export_menu(
|
|||
|
||||
fn render_import_menu(
|
||||
ui: &mut egui::Ui,
|
||||
_main_state: &mut MainState,
|
||||
main_state: &mut MainState,
|
||||
_modal_state: &mut ModalState,
|
||||
_current_transfer_state: &mut CurrentTransferState,
|
||||
_main_window_state: &mut MainWindowState,
|
||||
main_window_state: &mut MainWindowState,
|
||||
) {
|
||||
if ui.button("Import from JSON").clicked() {}
|
||||
if ui.button("Import transfer from CSV").clicked() {}
|
||||
if ui.button("Import from JSON").clicked() {
|
||||
main_window_state.json_upload_promise = Some(file_handling::upload_file("JSON", "json"));
|
||||
}
|
||||
|
||||
if let Some(promise) = &main_window_state.json_upload_promise {
|
||||
if let Some(result) = promise.0.ready() {
|
||||
if let Some(data) = result {
|
||||
match serde_json::from_slice::<MainState>(data) {
|
||||
Ok(new_main_state) => {
|
||||
log::info!("Loaded new main state from file.");
|
||||
*main_state = new_main_state
|
||||
},
|
||||
Err(e) => log::error!("Failed loading imported state JSON: {}", e),
|
||||
}
|
||||
}
|
||||
main_window_state.json_upload_promise = None;
|
||||
}
|
||||
}
|
||||
|
||||
if ui.button("Import transfer from CSV").clicked() {
|
||||
main_window_state.csv_upload_promise = Some(file_handling::upload_file("CSV", "csv"));
|
||||
}
|
||||
|
||||
if let Some(promise) = &main_window_state.csv_upload_promise {
|
||||
if let Some(result) = promise.0.ready() {
|
||||
if let Some(data) = result {
|
||||
if let Ok(data) = String::from_utf8(data.to_vec()) {
|
||||
let auto_output = plate_tool_lib::csv::read_csv_auto(&data);
|
||||
main_state.source_plates.extend(auto_output.sources);
|
||||
main_state.destination_plates.extend(auto_output.destinations);
|
||||
main_state.transfers.extend(auto_output.transfers);
|
||||
}
|
||||
}
|
||||
main_window_state.json_upload_promise = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_options_menu(
|
||||
|
|
@ -186,6 +222,9 @@ fn render_options_menu(
|
|||
});
|
||||
ui.menu_button("Windows", |ui| {
|
||||
ui.toggle_value(&mut main_window_state.show_side_panel, "Toggle side panel");
|
||||
ui.toggle_value(&mut main_window_state.show_plates_horizontal, "Show plates horizontally");
|
||||
ui.toggle_value(
|
||||
&mut main_window_state.show_plates_horizontal,
|
||||
"Show plates horizontally",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue