add toast and start adding postgres

This commit is contained in:
2026-04-10 20:45:53 +02:00
parent 9b65c5f62b
commit 23ccd3f793
16 changed files with 425 additions and 36 deletions

View File

@ -1,58 +1,62 @@
use dioxus::{
fullstack::{ByteStream, FileStream},
fullstack::{FileStream},
prelude::*,
};
use dioxus_html::{FileData, HasFileData};
#[cfg(feature = "server")]
use crate::config::ServerConfig;
use crate::config::ClientConfig;
use std::time::Duration;
use std::fs;
use std::fs::File;
use std::io::Write;
use futures::StreamExt;
use std::{ env, fs, io::Write };
use random_string;
use dioxus_primitives::toast::{
ToastOptions,
consume_toast
};
pub fn byte_to_human_size(size: u64) -> String {
let sizes = vec!["B", "KB", "MB", "GB", "TB", "WTFAREYOUDOINGB"];
let mut current = 0;
let mut res_size: f64 = size as f64;
let mut res: String;
while (res_size >= 1000.0 && current < sizes.len()) {
while res_size >= 1000.0 && current < sizes.len() {
res_size /= 1000.0;
current += 1;
}
res = ((res_size * 100.0).round() / 100.0).to_string() + " " + sizes[current];
res
((res_size * 100.0).round() / 100.0).to_string() + " " + sizes[current]
}
#[post("/api/upload")]
async fn upload_file(mut upload: FileStream) -> Result<String, HttpError> {
let UPLOAD_SIZE_LIMIT: u64 = 1024 * 1024 * 1024 * 1;
let UPLOAD_FOLDER: String = match env::var("UPLOAD_FOLDER") {
Ok(value) => { value },
Err(_) => { return HttpError::internal_server_error("UPLOAD_FOLDER not set"); }
};
let s_config = ServerConfig::load();
let c_config = ClientConfig::load();
let mut total_len: u64 = 0;
let mut error: Option<&str> = None;
let filename: String = loop {
let cur = random_string::generate(20, "ABCDEFGHIJKLMNOPQRTSTUVWXYZ0123456789");
if (!fs::exists(UPLOAD_FOLDER.clone() + &cur).expect("can't check if file exists")) {
if (!fs::exists(s_config.upload_folder.clone() + &cur).expect("can't check if file exists")) {
break cur;
}
};
if let Some(size) = upload.size() {
if size > UPLOAD_SIZE_LIMIT {
if size > c_config.upload_max_size.try_into().unwrap() {
return HttpError::payload_too_large("this file is too large");
}
}
let mut file = match fs::File::create(UPLOAD_FOLDER.clone() + &filename) {
let mut file = match fs::File::create(s_config.upload_folder.clone() + &filename) {
Ok(val) => { val },
Err(_) => { return HttpError::internal_server_error("failed to open the output file") }
};
@ -61,7 +65,7 @@ async fn upload_file(mut upload: FileStream) -> Result<String, HttpError> {
match chunk {
Ok(bytes) => {
total_len += bytes.len() as u64;
if total_len > UPLOAD_SIZE_LIMIT {
if total_len > c_config.upload_max_size.try_into().unwrap() {
error = Some("Uploaded file too large");
break;
}
@ -75,7 +79,7 @@ async fn upload_file(mut upload: FileStream) -> Result<String, HttpError> {
match error {
Some(err)=> {
file.sync_data();
fs::remove_file(UPLOAD_FOLDER.clone() + &filename);
fs::remove_file(s_config.upload_folder.clone() + &filename);
HttpError::internal_server_error(err)?
}
None => { Ok(filename) }
@ -101,7 +105,18 @@ pub fn build_table(files: Vec<(String, String, Option<Result<String, HttpError>>
Some(res) => { match res {
Ok(file_url) => {let url = file_url.clone(); rsx! { input {
type:"button",
onclick: move |_| { web_sys::window().unwrap().navigator().clipboard().write_text(&url); },
onclick: move |_| {
let toast_api = consume_toast();
toast_api
.success(
"Success".to_string(),
ToastOptions::new()
.description("The url has been copied successfully")
.duration(Duration::from_secs(5))
.permanent(false),
);
let _ = web_sys::window().unwrap().navigator().clipboard().write_text(&url);
},
value: "{file_url}"
} } },
Err(e) => {
@ -120,13 +135,12 @@ pub fn build_table(files: Vec<(String, String, Option<Result<String, HttpError>>
#[component]
pub fn Upload() -> Element {
//TODO: global config struct
let UPLOAD_SIZE_LIMIT: u64 = 1024 * 1024 * 1024 * 1;
let config = ClientConfig::load();
let mut selected : Signal<Vec<(String, String, Option<Result<String, HttpError>>)>> = use_signal(|| vec![]);
rsx! {
div { class : "p-2",
div { class : "p-2 h-full w-full",
p { class: "text-4xl font-bold p-1", "Upload a file" }
form {
@ -144,7 +158,7 @@ pub fn Upload() -> Element {
selected.with_mut(|files| {files.push((file.name(), byte_to_human_size(file.size()), None)); } );
let idx = selected().len() - 1;
if (file.size() > UPLOAD_SIZE_LIMIT) {
if file.size() > config.upload_max_size as u64 {
//messy but firefox can't handle when server returns early
selected.with_mut(|files| { files[idx].2 = Some(HttpError::payload_too_large("This file is too large")) });
return ;
@ -152,8 +166,10 @@ pub fn Upload() -> Element {
let res = match upload_file(file.clone().into()).await {
Ok(file_id) => {
let host = web_sys::window().unwrap().location().host().expect("unknown_host");
Ok(host + "/upload/" + &file_id)
let location = web_sys::window().unwrap().location();
let host = location.host().expect("unknown host");
let protocol = location.protocol().expect("unknown protocol");
Ok(protocol + "//" + &host + "/upload/" + &file_id)
},
Err(err) => { Err(err) }
};