diff --git a/src/components/file_drop.rs b/src/components/file_drop.rs index ac09fdc..66f72d7 100644 --- a/src/components/file_drop.rs +++ b/src/components/file_drop.rs @@ -18,12 +18,12 @@ pub fn FileDrop(#[prop(into)] name: String, #[prop(into)] form_id: String) -> im let form_id = StoredValue::new(form_id); let auth = expect_context::(); - let upload_action = StoredValue::new(Action::new(|form_data: &FormData| { + let upload_action = Action::new(|form_data: &FormData| { let form_data = form_data.clone(); async move { upload_file(form_data.into()).await } - })); + }); - let uploading = upload_action.get_value().pending(); + let uploading = upload_action.pending(); let upload_files = Callback::new(move |files: Vec| { let form_data = FormData::new().unwrap(); @@ -52,7 +52,7 @@ pub fn FileDrop(#[prop(into)] name: String, #[prop(into)] form_id: String) -> im } // Upload file to server. - upload_action.get_value().dispatch(form_data); + upload_action.dispatch(form_data); }); let UseDropZoneReturn { @@ -64,11 +64,6 @@ pub fn FileDrop(#[prop(into)] name: String, #[prop(into)] form_id: String) -> im .on_drop(move |ev| { let file = ev.files.first().unwrap(); - // Update file list - file_name_list.update(|list| { - list.push(file.name()); - }); - upload_files.run(vec![file.to_owned()]); }), ); @@ -88,20 +83,18 @@ pub fn FileDrop(#[prop(into)] name: String, #[prop(into)] form_id: String) -> im }) .unwrap_or_default(); - file_name_list.update({ - let files = files.clone(); - |list| { - for file in files { - if !list.iter().any(|f| *f == file.name()) { - list.push(file.name()); - } - } - } - }); - upload_files.run(files); }; + // Add file names to the list when upload_action is successful. + Effect::new(move || { + if let Some(Ok(uploaded_file_name)) = upload_action.value().get() { + file_name_list.update(|list| { + list.push(uploaded_file_name); + }); + } + }); + // let on_click_file_delete = move |file_name, form_id| { // // }; diff --git a/src/pages/api/files.rs b/src/pages/api/files.rs index 3aa6d88..a46b9ae 100644 --- a/src/pages/api/files.rs +++ b/src/pages/api/files.rs @@ -3,7 +3,7 @@ use leptos::prelude::*; use server_fn::codec::{MultipartData, MultipartFormData}; #[server(input = MultipartFormData)] -pub async fn upload_file(data: MultipartData) -> Result<(), ServerFnError> { +pub async fn upload_file(data: MultipartData) -> Result { use super::{MAIN_TABLE_NAME, S3_BUCKET_NAME}; use crate::pages::api::tokens::validate_and_get_token_info; use crate::utils::server::create_aws_config; @@ -89,31 +89,39 @@ pub async fn upload_file(data: MultipartData) -> Result<(), ServerFnError> { "SK".to_string(), AttributeValue::S(format!("FILE#{form_id}#{input_name}")), ) - .item("file_name".to_string(), AttributeValue::S(file_name)) + .item( + "file_name".to_string(), + AttributeValue::S(file_name.clone()), + ) .item("file_key".to_string(), AttributeValue::S(key.clone())) .send() .await - .map(|_| ()) - .map_err(|e| ServerFnError::new(format!("Couldn't put file to Dynamo: {}", e.to_string()))); + .map_err(|e| { + ServerFnError::new(format!( + "Couldn't put file to Dynamo, file rolled back: {}", + e.to_string() + )) + }); - if let Err(_) = dynamo_result { - // Roll back file insertion to S3. Only attempted on Dynamo insertion failure. + // If Dynamo fails, we want to handle the error by rolling back the file. Then, we return a failure. + if let Err(err) = dynamo_result { s3_client .delete_object() .bucket("leptos-scholarships") .key(&key) .send() .await - .map(|_| ()) .map_err(|e| { ServerFnError::new(format!( "Couldn't roll back S3 operation: {}", e.to_string() )) - }) - } else { - dynamo_result + })?; + + return Err(err); } + + Ok(file_name) } #[server]