Compare commits
No commits in common. "7defd8ff08aed1552ee2754fbbeef421d58f6ba9" and "ad57482dea986eddfc83c49023314e3201e4568f" have entirely different histories.
7defd8ff08
...
ad57482dea
|
@ -633,7 +633,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "plate-tool-lib"
|
name = "plate-tool-lib"
|
||||||
version = "0.4.0"
|
version = "0.3.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"csv",
|
"csv",
|
||||||
"getrandom",
|
"getrandom",
|
||||||
|
@ -648,7 +648,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "plate-tool-web"
|
name = "plate-tool-web"
|
||||||
version = "0.4.0"
|
version = "0.3.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"csv",
|
"csv",
|
||||||
"getrandom",
|
"getrandom",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "plate-tool-lib"
|
name = "plate-tool-lib"
|
||||||
version = "0.4.0"
|
version = "0.3.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
use serde::Serialize;
|
|
||||||
|
|
||||||
use super::TransferRecord;
|
|
||||||
|
|
||||||
// Format preferred by the Echo Client when using the Pick-List function.
|
|
||||||
// Note that this does not export plate info!
|
|
||||||
// Exports of this type should combine all transfers between the two actively selected plates.
|
|
||||||
#[derive(Serialize, Debug)]
|
|
||||||
pub struct EchoClientTransferRecord {
|
|
||||||
#[serde(rename = "SrcWell")]
|
|
||||||
pub source_well: String,
|
|
||||||
#[serde(rename = "DestWell")]
|
|
||||||
pub destination_well: String,
|
|
||||||
#[serde(rename = "XferVol")]
|
|
||||||
pub volume: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<TransferRecord> for EchoClientTransferRecord {
|
|
||||||
fn from(value: TransferRecord) -> Self {
|
|
||||||
EchoClientTransferRecord {
|
|
||||||
source_well: value.source_well,
|
|
||||||
destination_well: value.destination_well,
|
|
||||||
volume: value.volume,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,10 @@
|
||||||
use crate::transfer::Transfer;
|
use crate::transfer::Transfer;
|
||||||
use crate::util::*;
|
use crate::util::*;
|
||||||
|
|
||||||
use super::{alternative_formats::EchoClientTransferRecord, mangle_headers::mangle_headers, transfer_record::TransferRecordDeserializeIntermediate, TransferRecord};
|
use super::{TransferRecord, transfer_record::TransferRecordDeserializeIntermediate, mangle_headers::mangle_headers};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
pub fn transfer_to_records(
|
pub fn transfer_to_records(
|
||||||
|
@ -43,15 +44,6 @@ pub fn records_to_csv(trs: Vec<TransferRecord>) -> Result<String, Box<dyn Error>
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn records_to_echo_client_csv(trs: Vec<TransferRecord>) -> Result<String, Box<dyn Error>> {
|
|
||||||
let mut wtr = csv::WriterBuilder::new().from_writer(vec![]);
|
|
||||||
for record in trs {
|
|
||||||
wtr.serialize(Into::<EchoClientTransferRecord>::into(record))?
|
|
||||||
}
|
|
||||||
let data = String::from_utf8(wtr.into_inner()?)?;
|
|
||||||
Ok(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn string_well_to_pt(input: &str) -> Option<(u8, u8)> {
|
pub fn string_well_to_pt(input: &str) -> Option<(u8, u8)> {
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref REGEX: Regex = Regex::new(r"([A-Z,a-z]+)(\d+)").unwrap();
|
static ref REGEX: Regex = Regex::new(r"([A-Z,a-z]+)(\d+)").unwrap();
|
||||||
|
|
|
@ -5,8 +5,6 @@ pub fn mangle_headers(data: &str) -> String {
|
||||||
for field in fields {
|
for field in fields {
|
||||||
if let Some(f) = detect_field(field) {
|
if let Some(f) = detect_field(field) {
|
||||||
modified_headers.push(f.to_string());
|
modified_headers.push(f.to_string());
|
||||||
} else {
|
|
||||||
log::debug!("Unk field: {:?}", field)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,25 +12,22 @@ pub fn mangle_headers(data: &str) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detect_field(field: &str) -> Option<Field> {
|
fn detect_field(field: &str) -> Option<Field> {
|
||||||
// NOTE: Don't return none! Consider refactor to -> Field later on.
|
|
||||||
// Returning none means a field will be dropped, which requires the user to manually drop
|
|
||||||
// columns from their picklist.
|
|
||||||
match field.trim().to_lowercase() {
|
match field.trim().to_lowercase() {
|
||||||
x if x.contains("source") || x.contains("src") => match x {
|
x if x.contains("source") || x.contains("src") => match x {
|
||||||
_ if x.contains("plate") || x.contains("barcode") => Some(Field::SourcePlate),
|
_ if x.contains("plate") => Some(Field::SourcePlate),
|
||||||
_ if x.contains("well") => Some(Field::SourceWell),
|
_ if x.contains("well") => Some(Field::SourceWell),
|
||||||
_ if x.contains("format") || x.contains("fmt") => Some(Field::SourceFormat),
|
_ if x.contains("format") || x.contains("fmt") => Some(Field::SourceFormat),
|
||||||
_ => Some(Field::Other(x)), // Retain unknown fields
|
_ => None,
|
||||||
},
|
},
|
||||||
x if x.contains("destination") || x.contains("dest") => match x {
|
x if x.contains("destination") || x.contains("dest") => match x {
|
||||||
_ if x.contains("plate") || x.contains("barcode") => Some(Field::DestinationPlate),
|
_ if x.contains("plate") => Some(Field::DestinationPlate),
|
||||||
_ if x.contains("well") => Some(Field::DestinationWell),
|
_ if x.contains("well") => Some(Field::DestinationWell),
|
||||||
_ if x.contains("format") || x.contains("fmt") => Some(Field::DestinationFormat),
|
_ if x.contains("format") || x.contains("fmt") => Some(Field::DestinationFormat),
|
||||||
_ => Some(Field::Other(x)), // Retain unknown fields
|
_ => None,
|
||||||
},
|
},
|
||||||
x if x.contains("volume") => Some(Field::Volume),
|
x if x.contains("volume") => Some(Field::Volume),
|
||||||
x if x.contains("concentration") => Some(Field::Concentration),
|
x if x.contains("concentration") => Some(Field::Concentration),
|
||||||
x => Some(Field::Other(x)), // Retain unknown fields
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +40,6 @@ enum Field {
|
||||||
DestinationFormat,
|
DestinationFormat,
|
||||||
Volume,
|
Volume,
|
||||||
Concentration,
|
Concentration,
|
||||||
Other(String),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for Field {
|
impl ToString for Field {
|
||||||
|
@ -59,7 +53,6 @@ impl ToString for Field {
|
||||||
Field::DestinationFormat => "destinationformat".to_string(),
|
Field::DestinationFormat => "destinationformat".to_string(),
|
||||||
Field::Volume => "volume".to_string(),
|
Field::Volume => "volume".to_string(),
|
||||||
Field::Concentration => "concentration".to_string(),
|
Field::Concentration => "concentration".to_string(),
|
||||||
Field::Other(x) => x.to_string(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ mod transfer_record;
|
||||||
mod conversion;
|
mod conversion;
|
||||||
mod auto;
|
mod auto;
|
||||||
mod mangle_headers;
|
mod mangle_headers;
|
||||||
mod alternative_formats;
|
|
||||||
|
|
||||||
pub use transfer_record::volume_default;
|
pub use transfer_record::volume_default;
|
||||||
pub use transfer_record::TransferRecord;
|
pub use transfer_record::TransferRecord;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "plate-tool-web"
|
name = "plate-tool-web"
|
||||||
version = "0.4.0"
|
version = "0.3.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
|
@ -7,8 +7,6 @@ dialog {
|
||||||
|
|
||||||
color: $color-dark;
|
color: $color-dark;
|
||||||
background: $color-white;
|
background: $color-white;
|
||||||
|
|
||||||
padding-right: 5%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog > form[method="dialog"] {
|
dialog > form[method="dialog"] {
|
||||||
|
|
|
@ -30,7 +30,6 @@ div.upper_menu {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: calc($menu-height*0.7);
|
font-size: calc($menu-height*0.7);
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
|
|
||||||
use js_sys::Array;
|
use js_sys::Array;
|
||||||
|
|
||||||
use wasm_bindgen::{JsCast, JsValue};
|
use wasm_bindgen::{prelude::*, JsCast, JsValue};
|
||||||
use web_sys::{
|
use web_sys::{
|
||||||
Blob, HtmlAnchorElement, Url,
|
Blob, HtmlAnchorElement, HtmlDialogElement, HtmlElement, HtmlFormElement, HtmlInputElement, Url,
|
||||||
};
|
};
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
|
use yewdux::prelude::*;
|
||||||
|
|
||||||
|
use crate::components::states::{CurrentTransfer, MainState};
|
||||||
use crate::components::states::MainState;
|
|
||||||
|
|
||||||
use crate::state_to_csv;
|
use crate::state_to_csv;
|
||||||
|
|
||||||
// type NoParamsCallback = Box<dyn Fn(())>;
|
type NoParamsCallback = Box<dyn Fn(())>;
|
||||||
|
|
||||||
pub fn export_csv_button_callback(main_state: std::rc::Rc<MainState>) -> Callback<MouseEvent> {
|
pub fn export_csv_button_callback(main_state: std::rc::Rc<MainState>) -> Callback<MouseEvent> {
|
||||||
Callback::from(move |_| {
|
Callback::from(move |_| {
|
||||||
|
@ -24,6 +24,7 @@ pub fn export_csv_button_callback(main_state: std::rc::Rc<MainState>) -> Callbac
|
||||||
.unwrap();
|
.unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
web_sys::window().unwrap().alert_with_message("CSV export is currently not importable. Export as JSON if you'd like to back up your work!").unwrap();
|
||||||
if let Ok(csv) = state_to_csv(&main_state) {
|
if let Ok(csv) = state_to_csv(&main_state) {
|
||||||
save_str(&csv, "transfers.csv");
|
save_str(&csv, "transfers.csv");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,9 @@
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use js_sys::Function;
|
|
||||||
use wasm_bindgen::{prelude::*, JsCast};
|
|
||||||
use web_sys::{
|
|
||||||
FileReader, HtmlButtonElement, HtmlDialogElement, HtmlElement, HtmlFormElement,
|
|
||||||
HtmlInputElement, HtmlOptionElement, HtmlSelectElement,
|
|
||||||
};
|
|
||||||
|
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
use yewdux::prelude::*;
|
use yewdux::prelude::*;
|
||||||
|
|
||||||
use crate::components::states::{CsvExportType, MainState};
|
use crate::components::states::MainState;
|
||||||
|
|
||||||
use super::create_close_button;
|
|
||||||
|
|
||||||
type NoParamsCallback = Box<dyn Fn(())>;
|
type NoParamsCallback = Box<dyn Fn(())>;
|
||||||
|
|
||||||
|
@ -37,72 +28,3 @@ pub fn toggle_volume_heatmap_callback(
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn change_csv_export_type_callback(
|
|
||||||
main_dispatch: Dispatch<MainState>,
|
|
||||||
) -> Callback<web_sys::MouseEvent> {
|
|
||||||
let main_dispatch = main_dispatch.clone();
|
|
||||||
Callback::from(move |_| {
|
|
||||||
let window = web_sys::window().unwrap();
|
|
||||||
let document = window.document().unwrap();
|
|
||||||
let body = document.body().unwrap();
|
|
||||||
let modal = document
|
|
||||||
.create_element("dialog")
|
|
||||||
.unwrap()
|
|
||||||
.dyn_into::<HtmlDialogElement>()
|
|
||||||
.unwrap();
|
|
||||||
let onclose_callback = {
|
|
||||||
let modal = modal.clone();
|
|
||||||
Closure::<dyn FnMut(_)>::new(move |_: Event| {
|
|
||||||
modal.remove();
|
|
||||||
})
|
|
||||||
};
|
|
||||||
modal.set_onclose(Some(onclose_callback.as_ref().unchecked_ref()));
|
|
||||||
modal.set_text_content(Some("CSV Export Type"));
|
|
||||||
|
|
||||||
let close_button = create_close_button(&onclose_callback);
|
|
||||||
onclose_callback.forget();
|
|
||||||
modal.append_child(&close_button).unwrap();
|
|
||||||
|
|
||||||
let form = document
|
|
||||||
.create_element("form")
|
|
||||||
.unwrap()
|
|
||||||
.dyn_into::<HtmlFormElement>()
|
|
||||||
.unwrap();
|
|
||||||
let export_type = document
|
|
||||||
.create_element("select")
|
|
||||||
.unwrap()
|
|
||||||
.dyn_into::<HtmlSelectElement>()
|
|
||||||
.unwrap();
|
|
||||||
for t in [CsvExportType::Normal, CsvExportType::EchoClient] {
|
|
||||||
let option = document
|
|
||||||
.create_element("option")
|
|
||||||
.unwrap()
|
|
||||||
.dyn_into::<HtmlOptionElement>()
|
|
||||||
.unwrap();
|
|
||||||
option.set_value(&t.to_string());
|
|
||||||
option.set_text(&t.to_string());
|
|
||||||
option.set_selected(t == main_dispatch.get().preferences.csv_export_type);
|
|
||||||
|
|
||||||
export_type.append_child(&option).unwrap();
|
|
||||||
}
|
|
||||||
form.append_child(&export_type).unwrap();
|
|
||||||
|
|
||||||
let form_change_callback = {
|
|
||||||
let export_type = export_type.clone();
|
|
||||||
let main_dispatch = main_dispatch.clone();
|
|
||||||
Closure::<dyn FnMut(_)>::new(move |_: Event| {
|
|
||||||
let current: CsvExportType = export_type.value().as_str().into();
|
|
||||||
main_dispatch.reduce_mut(|state| {
|
|
||||||
state.preferences.csv_export_type = current;
|
|
||||||
});
|
|
||||||
})};
|
|
||||||
form.set_onchange(Some(form_change_callback.as_ref().unchecked_ref()));
|
|
||||||
form_change_callback.forget();
|
|
||||||
|
|
||||||
modal.append_child(&form).unwrap();
|
|
||||||
|
|
||||||
body.append_child(&modal).unwrap();
|
|
||||||
modal.show_modal().unwrap();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -48,11 +48,6 @@ pub fn MainWindow() -> Html {
|
||||||
main_window_callbacks::toggle_volume_heatmap_callback(main_dispatch)
|
main_window_callbacks::toggle_volume_heatmap_callback(main_dispatch)
|
||||||
};
|
};
|
||||||
|
|
||||||
let change_csv_export_type_callback = {
|
|
||||||
let main_dispatch = main_dispatch.clone();
|
|
||||||
main_window_callbacks::change_csv_export_type_callback(main_dispatch)
|
|
||||||
};
|
|
||||||
|
|
||||||
let new_plate_dialog_is_open = use_state_eq(|| false);
|
let new_plate_dialog_is_open = use_state_eq(|| false);
|
||||||
let new_plate_dialog_callback =
|
let new_plate_dialog_callback =
|
||||||
main_window_callbacks::new_plate_dialog_callback(new_plate_dialog_is_open.clone());
|
main_window_callbacks::new_plate_dialog_callback(new_plate_dialog_is_open.clone());
|
||||||
|
@ -111,12 +106,6 @@ pub fn MainWindow() -> Html {
|
||||||
<button onclick={toggle_volume_heatmap_callback}>{"Toggle volume heatmap"}</button>
|
<button onclick={toggle_volume_heatmap_callback}>{"Toggle volume heatmap"}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown-sub">
|
|
||||||
<button>{"Export"}</button>
|
|
||||||
<div>
|
|
||||||
<button onclick={change_csv_export_type_callback}>{"Change CSV export type"}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="main_container">
|
<div class="main_container">
|
||||||
|
|
|
@ -65,6 +65,7 @@ pub fn Plate(props: &PlateProps) -> Html {
|
||||||
if let Some(val) = volume_map_temp.get_mut(&well) {
|
if let Some(val) = volume_map_temp.get_mut(&well) {
|
||||||
*val += transfer.volume;
|
*val += transfer.volume;
|
||||||
} else {
|
} else {
|
||||||
|
log::info!("well: {:?}, vol: {:?}", well, transfer.volume);
|
||||||
volume_map_temp.insert(well, transfer.volume);
|
volume_map_temp.insert(well, transfer.volume);
|
||||||
}
|
}
|
||||||
volume_max_temp = f32::max(volume_max_temp, transfer.volume);
|
volume_max_temp = f32::max(volume_max_temp, transfer.volume);
|
||||||
|
|
|
@ -19,40 +19,11 @@ pub struct Preferences {
|
||||||
pub in_transfer_hashes: bool,
|
pub in_transfer_hashes: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub volume_heatmap: bool,
|
pub volume_heatmap: bool,
|
||||||
#[serde(default)]
|
|
||||||
pub csv_export_type: CsvExportType,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Preferences {
|
impl Default for Preferences {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self { in_transfer_hashes: true, volume_heatmap: false, csv_export_type: CsvExportType::Normal }
|
Self { in_transfer_hashes: true, volume_heatmap: false }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy, Serialize, Deserialize, Default)]
|
|
||||||
pub enum CsvExportType {
|
|
||||||
#[default]
|
|
||||||
Normal,
|
|
||||||
|
|
||||||
EchoClient,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for CsvExportType {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
CsvExportType::Normal => write!(f, "Normal"),
|
|
||||||
CsvExportType::EchoClient => write!(f, "Echo Client"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for CsvExportType {
|
|
||||||
fn from(value: &str) -> Self {
|
|
||||||
match value.trim().to_lowercase().as_str() {
|
|
||||||
"normal" => CsvExportType::Normal,
|
|
||||||
"echo client" => CsvExportType::EchoClient,
|
|
||||||
_ => CsvExportType::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,13 +40,6 @@ pub fn plate_test() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn state_to_csv(state: &MainState) -> Result<String, Box<dyn Error>> {
|
pub fn state_to_csv(state: &MainState) -> Result<String, Box<dyn Error>> {
|
||||||
match state.preferences.csv_export_type {
|
|
||||||
components::states::CsvExportType::Normal => state_to_csv_regular(state),
|
|
||||||
components::states::CsvExportType::EchoClient => state_to_csv_echo_client(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn state_to_csv_regular(state: &MainState) -> Result<String, Box<dyn Error>> {
|
|
||||||
let mut records: Vec<TransferRecord> = Vec::new();
|
let mut records: Vec<TransferRecord> = Vec::new();
|
||||||
for transfer in &state.transfers {
|
for transfer in &state.transfers {
|
||||||
let src_barcode = state
|
let src_barcode = state
|
||||||
|
@ -67,33 +60,3 @@ fn state_to_csv_regular(state: &MainState) -> Result<String, Box<dyn Error>> {
|
||||||
}
|
}
|
||||||
records_to_csv(records)
|
records_to_csv(records)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn state_to_csv_echo_client(state: &MainState) -> Result<String, Box<dyn Error>> {
|
|
||||||
let current_src = state.selected_source_plate;
|
|
||||||
let current_dst = state.selected_dest_plate;
|
|
||||||
|
|
||||||
let mut records: Vec<TransferRecord> = Vec::new();
|
|
||||||
for transfer in &state.transfers {
|
|
||||||
|
|
||||||
let src_barcode = state
|
|
||||||
.source_plates
|
|
||||||
.iter()
|
|
||||||
.find(|spi| spi.get_uuid() == transfer.source_id)
|
|
||||||
.ok_or("Found unpurged transfer")?;
|
|
||||||
|
|
||||||
let dest_barcode = state
|
|
||||||
.destination_plates
|
|
||||||
.iter()
|
|
||||||
.find(|dpi| dpi.get_uuid() == transfer.dest_id)
|
|
||||||
.ok_or("Found unpurged transfer")?;
|
|
||||||
|
|
||||||
if src_barcode.get_uuid() == current_src && dest_barcode.get_uuid() == current_dst {
|
|
||||||
records.append(&mut transfer_to_records(
|
|
||||||
transfer,
|
|
||||||
&src_barcode.name,
|
|
||||||
&dest_barcode.name,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
records_to_echo_client_csv(records)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue