use super::*;
pub fn on_upload_files_change(
on_files: Option<Rc<dyn Fn(&'static str)>>,
) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |event: Event| {
let Some(callback) = &on_files else {
return;
};
let Some(target) = event.target() else {
return;
};
let Ok(input) = target.dyn_into::<HtmlInputElement>() else {
return;
};
let Some(file_list) = input.files() else {
callback("No files selected");
return;
};
let count: u32 = file_list.length();
if count == 0 {
callback("No files selected");
return;
}
let names: Vec<String> = (0..count)
.filter_map(|index: u32| file_list.get(index).map(|file: File| file.name()))
.collect();
if names.is_empty() {
callback("No files selected");
return;
}
let summary: &'static str = Box::leak(
format!("{} file(s) selected: {}", names.len(), names.join(", ")).into_boxed_str(),
);
callback(summary);
}))
}
pub fn on_upload_drag_over(drag_active: Signal<bool>) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |event: Event| {
event.prevent_default();
drag_active.set(true);
}))
}
pub fn on_upload_drag_leave(drag_active: Signal<bool>) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |event: Event| {
event.prevent_default();
drag_active.set(false);
}))
}
fn upload_file_row(file: EuvUploadFile) -> VirtualNode {
let status_class: fn() -> &'static Css = match file.status {
EuvUploadStatus::Pending => c_euv_upload_file_status_pending,
EuvUploadStatus::Uploading => c_euv_upload_file_status_uploading,
EuvUploadStatus::Done => c_euv_upload_file_status_done,
EuvUploadStatus::Failed => c_euv_upload_file_status_failed,
};
let status_label: &'static str = match file.status {
EuvUploadStatus::Pending => "Pending",
EuvUploadStatus::Uploading => "Uploading",
EuvUploadStatus::Done => "Done",
EuvUploadStatus::Failed => "Failed",
};
html! {
div {
class: c_euv_upload_file()
key: file.name
span {
class: c_euv_upload_file_name()
{
file.name
}
}
span {
class: c_euv_upload_file_size()
{
file.size
}
}
span {
class: status_class()
{
status_label
}
}
}
}
}
#[component]
pub fn euv_upload(node: VirtualNode<EuvUploadProps>) -> VirtualNode {
let EuvUploadProps {
accept,
multiple,
files,
drag_active,
on_files,
}: EuvUploadProps = node.try_get_props().unwrap_or_default();
let file_rows: Vec<EuvUploadFile> = files.get();
let row_nodes: Vec<VirtualNode> = file_rows
.iter()
.map(|file: &EuvUploadFile| upload_file_row(*file))
.collect();
html! {
div {
class: c_euv_upload()
label {
class: if { drag_active.get() } {
c_euv_upload_drop_active()
} else {
c_euv_upload()
}
ondragover: on_upload_drag_over(drag_active)
ondragleave: on_upload_drag_leave(drag_active)
input {
type: INPUT_TYPE_FILE
class: c_euv_upload_input()
accept: accept
multiple: multiple.get()
onchange: on_upload_files_change(on_files)
}
span {
"Drop files here or click to browse"
}
}
div {
class: c_euv_upload_list()
row_nodes
}
}
}
}