Skip to content

Commit 19bf546

Browse files
authored
Merge pull request #1359 from AppFlowy-IO/add-folder-view
feat: add endpoint to create view without collab
2 parents 1e51364 + e7f58a4 commit 19bf546

File tree

5 files changed

+150
-10
lines changed

5 files changed

+150
-10
lines changed

libs/client-api/src/http_view.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use client_api_entity::workspace_dto::{
2-
AddRecentPagesParams, AppendBlockToPageParams, CreatePageDatabaseViewParams, CreatePageParams,
3-
CreateSpaceParams, DuplicatePageParams, FavoritePageParams, MovePageParams, Page, PageCollab,
4-
PublishPageParams, Space, UpdatePageParams, UpdateSpaceParams,
2+
AddRecentPagesParams, AppendBlockToPageParams, CreateFolderViewParams,
3+
CreatePageDatabaseViewParams, CreatePageParams, CreateSpaceParams, DuplicatePageParams,
4+
FavoritePageParams, MovePageParams, Page, PageCollab, PublishPageParams, Space, UpdatePageParams,
5+
UpdateSpaceParams,
56
};
67
use reqwest::Method;
78
use serde_json::json;
@@ -11,6 +12,24 @@ use uuid::Uuid;
1112
use crate::{process_response_data, process_response_error, Client};
1213

1314
impl Client {
15+
pub async fn create_folder_view(
16+
&self,
17+
workspace_id: Uuid,
18+
params: &CreateFolderViewParams,
19+
) -> Result<Page, AppResponseError> {
20+
let url = format!(
21+
"{}/api/workspace/{}/folder-view",
22+
self.base_url, workspace_id,
23+
);
24+
let resp = self
25+
.http_client_with_auth(Method::POST, &url)
26+
.await?
27+
.json(params)
28+
.send()
29+
.await?;
30+
process_response_data::<Page>(resp).await
31+
}
32+
1433
pub async fn create_workspace_page_view(
1534
&self,
1635
workspace_id: Uuid,

libs/shared-entity/src/dto/workspace_dto.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,15 @@ pub struct CollabResponse {
154154
pub object_id: Uuid,
155155
}
156156

157+
/// Create a view in the folder, without an associated collab
158+
#[derive(Debug, Clone, Serialize, Deserialize)]
159+
pub struct CreateFolderViewParams {
160+
pub parent_view_id: Uuid,
161+
pub layout: ViewLayout,
162+
pub name: Option<String>,
163+
pub view_id: Option<Uuid>,
164+
}
165+
157166
#[derive(Debug, Clone, Serialize, Deserialize)]
158167
pub struct Space {
159168
pub view_id: Uuid,

src/api/workspace.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ use crate::biz::workspace::ops::{
1818
get_reactions_on_published_view, remove_comment_on_published_view, remove_reaction_on_comment,
1919
};
2020
use crate::biz::workspace::page_view::{
21-
add_recent_pages, append_block_at_the_end_of_page, create_database_view, create_page,
22-
create_space, delete_all_pages_from_trash, delete_trash, favorite_page, get_page_view_collab,
23-
move_page, move_page_to_trash, publish_page, reorder_favorite_page, restore_all_pages_from_trash,
24-
restore_page_from_trash, unpublish_page, update_page, update_page_collab_data, update_space,
21+
add_recent_pages, append_block_at_the_end_of_page, create_database_view, create_folder_view,
22+
create_page, create_space, delete_all_pages_from_trash, delete_trash, favorite_page,
23+
get_page_view_collab, move_page, move_page_to_trash, publish_page, reorder_favorite_page,
24+
restore_all_pages_from_trash, restore_page_from_trash, unpublish_page, update_page,
25+
update_page_collab_data, update_space,
2526
};
2627
use crate::biz::workspace::publish::get_workspace_default_publish_view_info_meta;
2728
use crate::biz::workspace::quick_note::{
@@ -184,6 +185,9 @@ pub fn workspace_scope() -> Scope {
184185
.service(
185186
web::resource("/{workspace_id}/space/{view_id}").route(web::patch().to(update_space_handler)),
186187
)
188+
.service(
189+
web::resource("/{workspace_id}/folder-view").route(web::post().to(post_folder_view_handler)),
190+
)
187191
.service(
188192
web::resource("/{workspace_id}/page-view").route(web::post().to(post_page_view_handler)),
189193
)
@@ -1253,6 +1257,32 @@ async fn update_space_handler(
12531257
Ok(Json(AppResponse::Ok()))
12541258
}
12551259

1260+
async fn post_folder_view_handler(
1261+
user_uuid: UserUuid,
1262+
path: web::Path<Uuid>,
1263+
payload: Json<CreateFolderViewParams>,
1264+
state: Data<AppState>,
1265+
server: Data<RealtimeServerAddr>,
1266+
req: HttpRequest,
1267+
) -> Result<Json<AppResponse<Page>>> {
1268+
let uid = state.user_cache.get_user_uid(&user_uuid).await?;
1269+
let workspace_uuid = path.into_inner();
1270+
let user = realtime_user_for_web_request(req.headers(), uid)?;
1271+
let page = create_folder_view(
1272+
&state.metrics.appflowy_web_metrics,
1273+
server,
1274+
user,
1275+
&state.collab_access_control_storage,
1276+
workspace_uuid,
1277+
&payload.parent_view_id,
1278+
payload.layout.clone(),
1279+
payload.name.as_deref(),
1280+
payload.view_id,
1281+
)
1282+
.await?;
1283+
Ok(Json(AppResponse::Ok().with_data(page)))
1284+
}
1285+
12561286
async fn post_page_view_handler(
12571287
user_uuid: UserUuid,
12581288
path: web::Path<Uuid>,

src/biz/workspace/page_view.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,42 @@ pub async fn create_space(
160160
Ok(Space { view_id })
161161
}
162162

163+
// Different from create page as this function does not create an associated collab
164+
#[allow(clippy::too_many_arguments)]
165+
pub async fn create_folder_view(
166+
appflowy_web_metrics: &AppFlowyWebMetrics,
167+
server: Data<RealtimeServerAddr>,
168+
user: RealtimeUser,
169+
collab_storage: &CollabAccessControlStorage,
170+
workspace_id: Uuid,
171+
parent_view_id: &Uuid,
172+
view_layout: ViewLayout,
173+
name: Option<&str>,
174+
view_id: Option<Uuid>,
175+
) -> Result<Page, AppError> {
176+
let view_id = view_id.unwrap_or_else(Uuid::new_v4);
177+
let collab_origin = GetCollabOrigin::User { uid: user.uid };
178+
let mut folder = get_latest_collab_folder(collab_storage, collab_origin, workspace_id).await?;
179+
let folder_update = add_new_view_to_folder(
180+
user.uid,
181+
parent_view_id,
182+
&view_id,
183+
&mut folder,
184+
name,
185+
to_folder_view_layout(view_layout),
186+
)
187+
.await?;
188+
update_workspace_folder_data(
189+
appflowy_web_metrics,
190+
server,
191+
user,
192+
workspace_id,
193+
folder_update,
194+
)
195+
.await?;
196+
Ok(Page { view_id })
197+
}
198+
163199
#[allow(clippy::too_many_arguments)]
164200
pub async fn create_page(
165201
appflowy_web_metrics: &AppFlowyWebMetrics,

tests/workspace/page_view.rs

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ use collab_entity::CollabType;
99
use collab_folder::{CollabOrigin, Folder};
1010
use serde_json::{json, Value};
1111
use shared_entity::dto::workspace_dto::{
12-
AddRecentPagesParams, AppendBlockToPageParams, CreatePageDatabaseViewParams, CreatePageParams,
13-
CreateSpaceParams, DuplicatePageParams, FavoritePageParams, IconType, MovePageParams,
14-
PublishPageParams, SpacePermission, UpdatePageParams, UpdateSpaceParams, ViewIcon, ViewLayout,
12+
AddRecentPagesParams, AppendBlockToPageParams, CreateFolderViewParams,
13+
CreatePageDatabaseViewParams, CreatePageParams, CreateSpaceParams, DuplicatePageParams,
14+
FavoritePageParams, IconType, MovePageParams, PublishPageParams, SpacePermission,
15+
UpdatePageParams, UpdateSpaceParams, ViewIcon, ViewLayout,
1516
};
1617
use tokio::time::sleep;
1718
use uuid::Uuid;
@@ -157,6 +158,51 @@ async fn create_new_page_with_database() {
157158
}
158159
}
159160

161+
#[tokio::test]
162+
async fn create_new_folder_view() {
163+
let (c, _user) = generate_unique_registered_user_client().await;
164+
let workspaces = c.get_workspaces().await.unwrap();
165+
assert_eq!(workspaces.len(), 1);
166+
let workspace_id = workspaces[0].workspace_id;
167+
let folder_view = c
168+
.get_workspace_folder(&workspace_id, Some(2), None)
169+
.await
170+
.unwrap();
171+
let general_space = &folder_view
172+
.children
173+
.into_iter()
174+
.find(|v| v.name == "General")
175+
.unwrap();
176+
let page = c
177+
.create_folder_view(
178+
workspace_id,
179+
&CreateFolderViewParams {
180+
parent_view_id: general_space.view_id,
181+
layout: ViewLayout::Document,
182+
name: Some("New document".to_string()),
183+
view_id: None,
184+
},
185+
)
186+
.await
187+
.unwrap();
188+
sleep(Duration::from_secs(1)).await;
189+
let folder_view = c
190+
.get_workspace_folder(&workspace_id, Some(2), None)
191+
.await
192+
.unwrap();
193+
let general_space = &folder_view
194+
.children
195+
.into_iter()
196+
.find(|v| v.name == "General")
197+
.unwrap();
198+
let view = general_space
199+
.children
200+
.iter()
201+
.find(|v| v.view_id == page.view_id)
202+
.unwrap();
203+
assert_eq!(view.name, "New document");
204+
}
205+
160206
#[tokio::test]
161207
async fn create_new_document_page() {
162208
let (c, _user) = generate_unique_registered_user_client().await;

0 commit comments

Comments
 (0)