From: Olaf Wintermann Date: Sat, 22 Aug 2026 20:53:52 +0000 (+0200) Subject: add backend function for adding new note attachments X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=ff372595c31b150fcc60adc3d7ce33a216ada0dd;p=note.git add backend function for adding new note attachments --- diff --git a/application/backend/src/backend.rs b/application/backend/src/backend.rs index 9685d1b..e6add72 100644 --- a/application/backend/src/backend.rs +++ b/application/backend/src/backend.rs @@ -31,18 +31,19 @@ use std::future::Future; use std::io::{Error, ErrorKind}; use std::path::{Path, PathBuf}; use std::pin::Pin; -use sea_orm::{ActiveModelTrait, Database, DatabaseConnection, EntityTrait, QueryFilter, ColumnTrait, Set, QueryOrder, DbErr, ExprTrait, QuerySelect}; +use sea_orm::{ActiveModelTrait, Database, DatabaseConnection, EntityTrait, QueryFilter, ColumnTrait, Set, QueryOrder, DbErr, ExprTrait, QuerySelect, NotSet}; use tokio::runtime::Runtime; use std::sync::{Arc}; use std::thread::JoinHandle; use std::time::SystemTime; use notify::Event; +use sea_orm::prelude::DateTimeWithTimeZone; use tokio::fs; use tokio::sync::{broadcast, mpsc}; use tokio::sync::broadcast::error::SendError; use migration::{Expr, Migrator, MigratorTrait}; -use entity::{attachment, collection, filecontent, note, notecontent, profile, repository}; +use entity::{attachment, attachmentcontent, collection, filecontent, note, notecontent, profile, repository}; use entity::profile::Entity as Profile; use entity::collection::{create_notebook_hierarchy, CollectionType, Entity as Collection, Node}; use entity::note::{Column, Entity as Note, NoteType}; @@ -899,6 +900,52 @@ impl BackendHandle { let _ = self.tx.send(cmd); } + pub fn add_note_attachment(&self, note_id: i32, path: &Path, callback: F) + where F: FnOnce(Result<(attachment::Model, attachmentcontent::Model), DbErr>) + Send + 'static { + let backend = self.backend.clone(); + let pathbuf = path.to_path_buf(); + let name = pathbuf.file_name(); + let Some(name) = pathbuf.file_name() else { + callback(Err(DbErr::Custom("invalid path".to_string()))); + return; + }; + let file_name = name.to_string_lossy().to_string(); + let cmd = Box::pin(async move { + let result = async { + let collection_id = note::Entity::find_by_id(note_id) + .select_only() + .column(note::Column::CollectionId) + .into_tuple::() + .one(&backend.db).await?.ok_or(DbErr::Custom("note not found".to_string()))?; + + let now: DateTimeWithTimeZone = Utc::now().into(); + let new_attachment = attachment::ActiveModel { + attachment_id: Default::default(), + note_id: Set(note_id), + collection_id: Set(collection_id), + nodename: Set(file_name.clone()), + title: Set(file_name.clone()), + content_type: Set(nodename_to_contenttype(file_name.as_str()).to_string()), + lastmodified: Set(now.clone()), + created: Set(now), + }; + let attachment = new_attachment.insert(&backend.db).await?; + + let content = fs::read(pathbuf).await.map_err(|e| DbErr::Custom(e.to_string()))?; + let new_attachment_content = attachmentcontent::ActiveModel { + id: Default::default(), + attachment_id: Set(attachment.attachment_id), + content: Set(content) + }; + let attachment_content = new_attachment_content.insert(&backend.db).await?; + + Ok((attachment, attachment_content)) + }.await; + callback(result); + }); + let _ = self.tx.send(cmd); + } + pub fn open_extern(&self, note_id: i32, callback: F) where F: FnOnce(OpenExternResult) + Send + 'static { let backend = self.backend.clone();