Skip to content

Commit

Permalink
Merge pull request #965 from AppFlowy-IO/move-to-trash
Browse files Browse the repository at this point in the history
feat: api for moving page to trash
  • Loading branch information
khorshuheng authored Nov 7, 2024
2 parents 5cec0b0 + 3b37112 commit a35e806
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 2 deletions.
19 changes: 19 additions & 0 deletions libs/client-api/src/http_view.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use client_api_entity::workspace_dto::{CreatePageParams, Page, PageCollab};
use reqwest::Method;
use serde_json::json;
use shared_entity::response::{AppResponse, AppResponseError};
use uuid::Uuid;

Expand All @@ -21,6 +22,24 @@ impl Client {
AppResponse::<Page>::from_response(resp).await?.into_data()
}

pub async fn move_workspace_page_view_to_trash(
&self,
workspace_id: Uuid,
view_id: String,
) -> Result<(), AppResponseError> {
let url = format!(
"{}/api/workspace/{}/page-view/{}/move-to-trash",
self.base_url, workspace_id, view_id
);
let resp = self
.http_client_with_auth(Method::POST, &url)
.await?
.json(&json!({}))
.send()
.await?;
AppResponse::<()>::from_response(resp).await?.into_error()
}

pub async fn get_workspace_page_view(
&self,
workspace_id: Uuid,
Expand Down
24 changes: 23 additions & 1 deletion src/api/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ use crate::biz::workspace::ops::{
get_reactions_on_published_view, remove_comment_on_published_view, remove_reaction_on_comment,
};
use crate::biz::workspace::page_view::{
create_page, get_page_view_collab, update_page_collab_data,
create_page, get_page_view_collab, move_page_to_trash, update_page_collab_data,
};
use crate::biz::workspace::publish::get_workspace_default_publish_view_info_meta;
use crate::domain::compression::{
Expand Down Expand Up @@ -133,6 +133,10 @@ pub fn workspace_scope() -> Scope {
web::resource("/{workspace_id}/page-view/{view_id}")
.route(web::get().to(get_page_view_handler)),
)
.service(
web::resource("/{workspace_id}/page-view/{view_id}/move-to-trash")
.route(web::post().to(move_page_to_trash_handler)),
)
.service(
web::resource("/{workspace_id}/batch/collab")
.route(web::post().to(batch_create_collab_handler)),
Expand Down Expand Up @@ -895,6 +899,24 @@ async fn post_page_view_handler(
Ok(Json(AppResponse::Ok().with_data(page)))
}

async fn move_page_to_trash_handler(
user_uuid: UserUuid,
path: web::Path<(Uuid, String)>,
state: Data<AppState>,
) -> Result<Json<AppResponse<()>>> {
let uid = state.user_cache.get_user_uid(&user_uuid).await?;
let (workspace_uuid, view_id) = path.into_inner();
move_page_to_trash(
&state.pg_pool,
&state.collab_access_control_storage,
uid,
workspace_uuid,
&view_id,
)
.await?;
Ok(Json(AppResponse::Ok()))
}

async fn get_page_view_handler(
user_uuid: UserUuid,
path: web::Path<(Uuid, String)>,
Expand Down
53 changes: 53 additions & 0 deletions src/biz/workspace/page_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use database::collab::{select_workspace_database_oid, CollabStorage, GetCollabOr
use database::publish::select_published_view_ids_for_workspace;
use database::user::select_web_user_from_uid;
use database_entity::dto::{CollabParams, QueryCollab, QueryCollabParams, QueryCollabResult};
use itertools::Itertools;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use shared_entity::dto::workspace_dto::{FolderView, Page, PageCollab, PageCollabData, ViewLayout};
use sqlx::{PgPool, Transaction};
Expand Down Expand Up @@ -93,6 +94,30 @@ async fn add_new_view_to_folder(
})
}

async fn move_view_to_trash(view_id: &str, folder: &mut Folder) -> Result<FolderUpdate, AppError> {
let mut current_view_and_descendants = folder
.get_views_belong_to(view_id)
.iter()
.map(|v| v.id.clone())
.collect_vec();
current_view_and_descendants.push(view_id.to_string());

let encoded_update = {
let mut txn = folder.collab.transact_mut();
current_view_and_descendants.iter().for_each(|view_id| {
folder.body.views.update_view(&mut txn, view_id, |update| {
update.set_favorite(false).set_trash(true).done()
});
});
txn.encode_update_v1()
};

Ok(FolderUpdate {
updated_encoded_collab: folder_to_encoded_collab(folder)?,
encoded_updates: encoded_update,
})
}

fn folder_to_encoded_collab(folder: &Folder) -> Result<Vec<u8>, AppError> {
let collab_type = CollabType::Folder;
let encoded_folder_collab = folder
Expand Down Expand Up @@ -174,6 +199,34 @@ async fn create_document_page(
Ok(Page { view_id })
}

pub async fn move_page_to_trash(
pg_pool: &PgPool,
collab_storage: &CollabAccessControlStorage,
uid: i64,
workspace_id: Uuid,
view_id: &str,
) -> Result<(), AppError> {
let collab_origin = GetCollabOrigin::User { uid };
let mut folder =
get_latest_collab_folder(collab_storage, collab_origin, &workspace_id.to_string()).await?;
let trash_info = folder.get_my_trash_info();
if trash_info.into_iter().any(|info| info.id == view_id) {
return Ok(());
}
let folder_update = move_view_to_trash(view_id, &mut folder).await?;
let mut transaction = pg_pool.begin().await?;
insert_and_broadcast_workspace_folder_update(
uid,
workspace_id,
folder_update,
collab_storage,
&mut transaction,
)
.await?;
transaction.commit().await?;
Ok(())
}

pub async fn get_page_view_collab(
pg_pool: &PgPool,
collab_access_control_storage: &CollabAccessControlStorage,
Expand Down
74 changes: 73 additions & 1 deletion tests/workspace/page_view.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use std::time::Duration;

use client_api::entity::{QueryCollab, QueryCollabParams};
use client_api_test::generate_unique_registered_user_client;
use client_api_test::{
generate_unique_registered_user, generate_unique_registered_user_client, TestClient,
};
use collab::{core::origin::CollabClient, preclude::Collab};
use collab_entity::CollabType;
use collab_folder::{CollabOrigin, Folder};
use shared_entity::dto::workspace_dto::{CreatePageParams, ViewLayout};
use tokio::time::sleep;
use uuid::Uuid;
Expand Down Expand Up @@ -96,3 +100,71 @@ async fn create_new_document_page() {
.await
.unwrap();
}

#[tokio::test]
async fn move_page_to_trash() {
let registered_user = generate_unique_registered_user().await;
let mut app_client = TestClient::user_with_new_device(registered_user.clone()).await;
let web_client = TestClient::user_with_new_device(registered_user.clone()).await;
let workspace_id = app_client.workspace_id().await;
app_client.open_workspace_collab(&workspace_id).await;
app_client
.wait_object_sync_complete(&workspace_id)
.await
.unwrap();
let folder_view = web_client
.api_client
.get_workspace_folder(&workspace_id.to_string(), Some(2), None)
.await
.unwrap();
let general_space = &folder_view
.children
.into_iter()
.find(|v| v.name == "General")
.unwrap();
let view_id_to_be_deleted = general_space.children[0].view_id.clone();
web_client
.api_client
.move_workspace_page_view_to_trash(
Uuid::parse_str(&workspace_id).unwrap(),
view_id_to_be_deleted.clone(),
)
.await
.unwrap();

// Wait for websocket to receive update
sleep(Duration::from_secs(1)).await;
let lock = app_client
.collabs
.get(&workspace_id)
.unwrap()
.collab
.read()
.await;
let collab: &Collab = (*lock).borrow();
let collab_type = CollabType::Folder;
let encoded_collab = collab
.encode_collab_v1(|collab| collab_type.validate_require_data(collab))
.unwrap();
let uid = app_client.uid().await;
let folder = Folder::from_collab_doc_state(
uid,
CollabOrigin::Client(CollabClient::new(uid, app_client.device_id.clone())),
encoded_collab.into(),
&workspace_id,
vec![],
)
.unwrap();
assert!(folder
.get_my_trash_sections()
.iter()
.any(|v| v.id == view_id_to_be_deleted.clone()));
web_client
.api_client
.get_workspace_trash(&workspace_id)
.await
.unwrap()
.views
.iter()
.any(|v| v.view.view_id == view_id_to_be_deleted.clone());
}

0 comments on commit a35e806

Please sign in to comment.