feat: api for restore all pages from trash
This commit is contained in:
parent
4c024ac479
commit
f3604edf2e
|
|
@ -58,6 +58,23 @@ impl Client {
|
||||||
AppResponse::<()>::from_response(resp).await?.into_error()
|
AppResponse::<()>::from_response(resp).await?.into_error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn restore_all_workspace_page_views_from_trash(
|
||||||
|
&self,
|
||||||
|
workspace_id: Uuid,
|
||||||
|
) -> Result<(), AppResponseError> {
|
||||||
|
let url = format!(
|
||||||
|
"{}/api/workspace/{}/restore-all-pages-from-trash",
|
||||||
|
self.base_url, workspace_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 update_workspace_page_view(
|
pub async fn update_workspace_page_view(
|
||||||
&self,
|
&self,
|
||||||
workspace_id: Uuid,
|
workspace_id: Uuid,
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,8 @@ use crate::biz::workspace::ops::{
|
||||||
get_reactions_on_published_view, remove_comment_on_published_view, remove_reaction_on_comment,
|
get_reactions_on_published_view, remove_comment_on_published_view, remove_reaction_on_comment,
|
||||||
};
|
};
|
||||||
use crate::biz::workspace::page_view::{
|
use crate::biz::workspace::page_view::{
|
||||||
create_page, get_page_view_collab, move_page_to_trash, restore_page_from_trash, update_page,
|
create_page, get_page_view_collab, move_page_to_trash, restore_all_pages_from_trash,
|
||||||
update_page_collab_data,
|
restore_page_from_trash, update_page, update_page_collab_data,
|
||||||
};
|
};
|
||||||
use crate::biz::workspace::publish::get_workspace_default_publish_view_info_meta;
|
use crate::biz::workspace::publish::get_workspace_default_publish_view_info_meta;
|
||||||
use crate::domain::compression::{
|
use crate::domain::compression::{
|
||||||
|
|
@ -143,6 +143,10 @@ pub fn workspace_scope() -> Scope {
|
||||||
web::resource("/{workspace_id}/page-view/{view_id}/restore-from-trash")
|
web::resource("/{workspace_id}/page-view/{view_id}/restore-from-trash")
|
||||||
.route(web::post().to(restore_page_from_trash_handler)),
|
.route(web::post().to(restore_page_from_trash_handler)),
|
||||||
)
|
)
|
||||||
|
.service(
|
||||||
|
web::resource("/{workspace_id}/restore-all-pages-from-trash")
|
||||||
|
.route(web::post().to(restore_all_pages_from_trash_handler)),
|
||||||
|
)
|
||||||
.service(
|
.service(
|
||||||
web::resource("/{workspace_id}/batch/collab")
|
web::resource("/{workspace_id}/batch/collab")
|
||||||
.route(web::post().to(batch_create_collab_handler)),
|
.route(web::post().to(batch_create_collab_handler)),
|
||||||
|
|
@ -941,6 +945,23 @@ async fn restore_page_from_trash_handler(
|
||||||
Ok(Json(AppResponse::Ok()))
|
Ok(Json(AppResponse::Ok()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn restore_all_pages_from_trash_handler(
|
||||||
|
user_uuid: UserUuid,
|
||||||
|
path: web::Path<Uuid>,
|
||||||
|
state: Data<AppState>,
|
||||||
|
) -> Result<Json<AppResponse<()>>> {
|
||||||
|
let uid = state.user_cache.get_user_uid(&user_uuid).await?;
|
||||||
|
let workspace_uuid = path.into_inner();
|
||||||
|
restore_all_pages_from_trash(
|
||||||
|
&state.pg_pool,
|
||||||
|
&state.collab_access_control_storage,
|
||||||
|
uid,
|
||||||
|
workspace_uuid,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(Json(AppResponse::Ok()))
|
||||||
|
}
|
||||||
|
|
||||||
async fn update_page_view_handler(
|
async fn update_page_view_handler(
|
||||||
user_uuid: UserUuid,
|
user_uuid: UserUuid,
|
||||||
path: web::Path<(Uuid, String)>,
|
path: web::Path<(Uuid, String)>,
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,25 @@ async fn move_view_out_from_trash(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn move_all_views_out_from_trash(folder: &mut Folder) -> Result<FolderUpdate, AppError> {
|
||||||
|
let encoded_update = {
|
||||||
|
let mut txn = folder.collab.transact_mut();
|
||||||
|
if let Some(op) = folder
|
||||||
|
.body
|
||||||
|
.section
|
||||||
|
.section_op(&txn, collab_folder::Section::Trash)
|
||||||
|
{
|
||||||
|
op.clear(&mut txn);
|
||||||
|
};
|
||||||
|
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> {
|
fn folder_to_encoded_collab(folder: &Folder) -> Result<Vec<u8>, AppError> {
|
||||||
let collab_type = CollabType::Folder;
|
let collab_type = CollabType::Folder;
|
||||||
let encoded_folder_collab = folder
|
let encoded_folder_collab = folder
|
||||||
|
|
@ -297,6 +316,29 @@ pub async fn restore_page_from_trash(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn restore_all_pages_from_trash(
|
||||||
|
pg_pool: &PgPool,
|
||||||
|
collab_storage: &CollabAccessControlStorage,
|
||||||
|
uid: i64,
|
||||||
|
workspace_id: Uuid,
|
||||||
|
) -> 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 folder_update = move_all_views_out_from_trash(&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(())
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub async fn update_page(
|
pub async fn update_page(
|
||||||
pg_pool: &PgPool,
|
pg_pool: &PgPool,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::time::Duration;
|
use std::{collections::HashSet, time::Duration};
|
||||||
|
|
||||||
use client_api::entity::{QueryCollab, QueryCollabParams};
|
use client_api::entity::{QueryCollab, QueryCollabParams};
|
||||||
use client_api_test::{
|
use client_api_test::{
|
||||||
|
|
@ -146,40 +146,49 @@ async fn move_page_to_trash() {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.find(|v| v.name == "General")
|
.find(|v| v.name == "General")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let view_id_to_be_deleted = general_space.children[0].view_id.clone();
|
let view_ids_to_be_deleted = [
|
||||||
|
general_space.children[0].view_id.clone(),
|
||||||
|
general_space.children[1].view_id.clone(),
|
||||||
|
];
|
||||||
app_client.open_workspace_collab(&workspace_id).await;
|
app_client.open_workspace_collab(&workspace_id).await;
|
||||||
app_client
|
app_client
|
||||||
.wait_object_sync_complete(&workspace_id)
|
.wait_object_sync_complete(&workspace_id)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
web_client
|
for view_id in view_ids_to_be_deleted.iter() {
|
||||||
.api_client
|
app_client
|
||||||
.move_workspace_page_view_to_trash(
|
.api_client
|
||||||
Uuid::parse_str(&workspace_id).unwrap(),
|
.move_workspace_page_view_to_trash(Uuid::parse_str(&workspace_id).unwrap(), view_id.clone())
|
||||||
view_id_to_be_deleted.clone(),
|
.await
|
||||||
)
|
.unwrap();
|
||||||
.await
|
}
|
||||||
.unwrap();
|
|
||||||
let folder = get_latest_folder(&app_client, &workspace_id).await;
|
let folder = get_latest_folder(&app_client, &workspace_id).await;
|
||||||
assert!(folder
|
let views_in_trash_for_app = folder
|
||||||
.get_my_trash_sections()
|
.get_my_trash_sections()
|
||||||
.iter()
|
.iter()
|
||||||
.any(|v| v.id == view_id_to_be_deleted.clone()));
|
.map(|v| v.id.clone())
|
||||||
let view_found = web_client
|
.collect::<HashSet<String>>();
|
||||||
|
for view_id in view_ids_to_be_deleted.iter() {
|
||||||
|
assert!(views_in_trash_for_app.contains(view_id));
|
||||||
|
}
|
||||||
|
let views_in_trash_for_web = web_client
|
||||||
.api_client
|
.api_client
|
||||||
.get_workspace_trash(&workspace_id)
|
.get_workspace_trash(&workspace_id)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.views
|
.views
|
||||||
.iter()
|
.iter()
|
||||||
.any(|v| v.view.view_id == view_id_to_be_deleted.clone());
|
.map(|v| v.view.view_id.clone())
|
||||||
assert!(view_found);
|
.collect::<HashSet<String>>();
|
||||||
|
for view_id in view_ids_to_be_deleted.iter() {
|
||||||
|
assert!(views_in_trash_for_web.contains(view_id));
|
||||||
|
}
|
||||||
|
|
||||||
web_client
|
web_client
|
||||||
.api_client
|
.api_client
|
||||||
.restore_workspace_page_view_from_trash(
|
.restore_workspace_page_view_from_trash(
|
||||||
Uuid::parse_str(&workspace_id).unwrap(),
|
Uuid::parse_str(&workspace_id).unwrap(),
|
||||||
&view_id_to_be_deleted,
|
&view_ids_to_be_deleted[0],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -187,7 +196,7 @@ async fn move_page_to_trash() {
|
||||||
assert!(!folder
|
assert!(!folder
|
||||||
.get_my_trash_sections()
|
.get_my_trash_sections()
|
||||||
.iter()
|
.iter()
|
||||||
.any(|v| v.id == view_id_to_be_deleted.clone()));
|
.any(|v| v.id == view_ids_to_be_deleted[0]));
|
||||||
let view_found = web_client
|
let view_found = web_client
|
||||||
.api_client
|
.api_client
|
||||||
.get_workspace_trash(&workspace_id)
|
.get_workspace_trash(&workspace_id)
|
||||||
|
|
@ -195,7 +204,26 @@ async fn move_page_to_trash() {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.views
|
.views
|
||||||
.iter()
|
.iter()
|
||||||
.any(|v| v.view.view_id == view_id_to_be_deleted.clone());
|
.any(|v| v.view.view_id == view_ids_to_be_deleted[0]);
|
||||||
|
assert!(!view_found);
|
||||||
|
web_client
|
||||||
|
.api_client
|
||||||
|
.restore_all_workspace_page_views_from_trash(Uuid::parse_str(&workspace_id).unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let folder = get_latest_folder(&app_client, &workspace_id).await;
|
||||||
|
assert!(!folder
|
||||||
|
.get_my_trash_sections()
|
||||||
|
.iter()
|
||||||
|
.any(|v| v.id == view_ids_to_be_deleted[1]));
|
||||||
|
let view_found = web_client
|
||||||
|
.api_client
|
||||||
|
.get_workspace_trash(&workspace_id)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.views
|
||||||
|
.iter()
|
||||||
|
.any(|v| v.view.view_id == view_ids_to_be_deleted[1]);
|
||||||
assert!(!view_found);
|
assert!(!view_found);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue