backend
This commit is contained in:
@@ -62,12 +62,24 @@ const QUICKWIT_MAX_HITS: usize = 200;
|
||||
pub struct DocumentListQuery {
|
||||
pub folder_id: Option<Uuid>,
|
||||
#[serde(default)]
|
||||
pub include_deleted: bool,
|
||||
#[serde(default)]
|
||||
pub include_descendants: Option<bool>,
|
||||
pub query: Option<String>,
|
||||
pub tags: Option<String>,
|
||||
pub correspondents: Option<String>,
|
||||
#[serde(default = "default_document_status_filter")]
|
||||
pub status: DocumentStatusFilter,
|
||||
}
|
||||
|
||||
fn default_document_status_filter() -> DocumentStatusFilter {
|
||||
DocumentStatusFilter::Active
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Deserialize, Serialize, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum DocumentStatusFilter {
|
||||
Active,
|
||||
Deleted,
|
||||
All,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, IntoParams, ToSchema)]
|
||||
@@ -380,6 +392,12 @@ pub struct MoveDocumentRequest {
|
||||
pub folder_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct RestoreDocumentRequest {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub folder_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct AssignTagsRequest {
|
||||
pub tag_ids: Vec<Uuid>,
|
||||
@@ -406,19 +424,25 @@ pub async fn list_documents(
|
||||
) -> AppResult<Json<Vec<DocumentResponse>>> {
|
||||
let DocumentListQuery {
|
||||
folder_id,
|
||||
include_deleted,
|
||||
include_descendants,
|
||||
query,
|
||||
tags,
|
||||
correspondents,
|
||||
status,
|
||||
} = params;
|
||||
|
||||
let mut docs_query = documents::table
|
||||
.filter(documents::tenant_id.eq(tenant_id))
|
||||
.into_boxed();
|
||||
|
||||
if !include_deleted {
|
||||
docs_query = docs_query.filter(documents::deleted_at.is_null());
|
||||
match status {
|
||||
DocumentStatusFilter::Active => {
|
||||
docs_query = docs_query.filter(documents::deleted_at.is_null());
|
||||
}
|
||||
DocumentStatusFilter::Deleted => {
|
||||
docs_query = docs_query.filter(documents::deleted_at.is_not_null());
|
||||
}
|
||||
DocumentStatusFilter::All => {}
|
||||
}
|
||||
|
||||
let search_text = query
|
||||
@@ -1387,6 +1411,56 @@ pub async fn update_document(
|
||||
}))
|
||||
}
|
||||
|
||||
pub async fn restore_document(
|
||||
Path(document_id): Path<Uuid>,
|
||||
TenantScopedConn {
|
||||
mut conn,
|
||||
tenant_id,
|
||||
..
|
||||
}: TenantScopedConn,
|
||||
Json(payload): Json<RestoreDocumentRequest>,
|
||||
) -> AppResult<StatusCode> {
|
||||
let mut document: Document = documents::table
|
||||
.find(document_id)
|
||||
.filter(documents::tenant_id.eq(tenant_id))
|
||||
.first(&mut conn)?;
|
||||
|
||||
if document.deleted_at.is_none() {
|
||||
return Ok(StatusCode::NO_CONTENT);
|
||||
}
|
||||
|
||||
if let Some(folder_id) = payload.folder_id {
|
||||
ensure_folder_exists_on_conn(&mut conn, tenant_id, folder_id)?;
|
||||
document.folder_id = Some(folder_id);
|
||||
} else if let Some(folder_id) = document.folder_id {
|
||||
let exists: bool = diesel::select(exists(
|
||||
folders::table
|
||||
.filter(folders::id.eq(folder_id))
|
||||
.filter(folders::tenant_id.eq(tenant_id)),
|
||||
))
|
||||
.get_result(&mut conn)?;
|
||||
|
||||
if !exists {
|
||||
document.folder_id = None;
|
||||
}
|
||||
}
|
||||
|
||||
let now = Utc::now().naive_utc();
|
||||
diesel::update(
|
||||
documents::table
|
||||
.find(document_id)
|
||||
.filter(documents::tenant_id.eq(tenant_id)),
|
||||
)
|
||||
.set((
|
||||
documents::deleted_at.eq::<Option<NaiveDateTime>>(None),
|
||||
documents::folder_id.eq(document.folder_id),
|
||||
documents::updated_at.eq(now),
|
||||
))
|
||||
.execute(&mut conn)?;
|
||||
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
fn merge_document_metadata(existing: Value, updates: Value) -> AppResult<Value> {
|
||||
let mut base = match existing {
|
||||
Value::Object(map) => map,
|
||||
|
||||
Reference in New Issue
Block a user