feat: add web guide as part of getting started guide (#1142)

This commit is contained in:
Khor Shu Heng 2025-01-10 16:30:05 +08:00 committed by GitHub
parent ee84464e82
commit fa9d53461b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 544 additions and 6 deletions

View File

@ -62,6 +62,24 @@
]
}
},
{
"type": "heading",
"data": {
"level": 4,
"delta": [
{
"insert": "$",
"attributes": {
"mention": {
"type": "page",
"page_id": "<web_guide_id>"
},
"bold": true
}
}
]
}
},
{
"type": "heading",
"data": {

View File

@ -0,0 +1,479 @@
{
"type": "page",
"children": [
{
"type": "heading",
"data": {
"level": 1,
"delta": [
{
"insert": "AppFlowy is right in "
},
{
"insert": "your browser",
"attributes": {
"href": "https://appflowy.com/"
}
}
]
}
},
{
"type": "paragraph",
"data": {
"delta": []
}
},
{
"type": "heading",
"data": {
"level": 3,
"delta": [
{
"insert": "Basics"
}
]
}
},
{
"type": "todo_list",
"data": {
"checked": true,
"delta": [
{
"insert": "Click "
},
{
"insert": "+",
"attributes": {
"code": true
}
},
{
"insert": " button next to a Space name to quickly add a new page."
}
]
}
},
{
"type": "todo_list",
"data": {
"checked": false,
"delta": [
{
"insert": "Click anywhere and just start typing."
}
]
}
},
{
"type": "todo_list",
"data": {
"checked": false,
"delta": [
{
"insert": "Highlight ",
"attributes": {
"bg_color": "0x4dffeb3b"
}
},
{
"insert": "any text, and use the editing menu to "
},
{
"insert": "style",
"attributes": {
"italic": true
}
},
{
"insert": " "
},
{
"insert": "your",
"attributes": {
"bold": true
}
},
{
"insert": " "
},
{
"insert": "writing",
"attributes": {
"underline": true
}
},
{
"insert": " "
},
{
"insert": "however",
"attributes": {
"code": true
}
},
{
"insert": " you "
},
{
"insert": "like.",
"attributes": {
"strikethrough": true
}
}
]
}
},
{
"type": "todo_list",
"children": [
{
"type": "todo_list",
"data": {
"checked": false,
"delta": [
{
"insert": "Type "
},
{
"insert": "/",
"attributes": {
"code": true
}
},
{
"insert": " followed by "
},
{
"insert": "/bullet",
"attributes": {
"code": true
}
},
{
"insert": " or "
},
{
"insert": "/num",
"attributes": {
"code": true
}
},
{
"insert": " to create a list. ",
"attributes": {
"code": false
}
}
]
}
}
],
"data": {
"checked": false,
"delta": [
{
"insert": "As soon as you type "
},
{
"insert": "/",
"attributes": {
"font_color": "0xff00b5ff",
"code": true
}
},
{
"insert": " a menu will pop up. Select "
},
{
"insert": "different types",
"attributes": {
"bg_color": "0x4d9c27b0"
}
},
{
"insert": " of content blocks you can add."
}
]
}
},
{
"type": "todo_list",
"data": {
"checked": false,
"delta": [
{
"insert": "Click "
},
{
"insert": "+",
"attributes": {
"code": true
}
},
{
"insert": " next to any page title or space name in the sidebar to add a new page/subpage."
}
]
}
},
{
"type": "paragraph",
"data": {
"delta": []
}
},
{
"type": "heading",
"data": {
"level": 3,
"delta": [
{
"insert": "Quick Note"
}
]
}
},
{
"type": "callout",
"data": {
"bgColor": "0x0",
"icon": "📌",
"delta": [
{
"insert": "Use Quick Note to save anything you want to remember—such as meeting notes, ideas, or to-dos."
}
]
}
},
{
"type": "paragraph",
"data": {
"delta": []
}
},
{
"type": "paragraph",
"data": {
"delta": [
{
"insert": "CMD",
"attributes": {
"code": true
}
},
{
"insert": " / "
},
{
"insert": "CTRL",
"attributes": {
"code": true
}
},
{
"insert": " + "
},
{
"insert": "/",
"attributes": {
"code": true
}
},
{
"insert": " to quickly add a quick note ✍️"
}
]
}
},
{
"type": "image",
"data": {
"image_type": 1,
"width": 553.7578125,
"align": "left",
"url": "https://beta.appflowy.cloud/api/file_storage/c29fafc4-b7c0-4549-8702-71339b0fd9ea/v1/blob/735c7c28%2D33a0%2D4e9f%2D92e6%2D089630656063/P5aRDW-HGm6vk4gjZg8w6jgD_z2yE402OuI1uutNN3A=.png"
}
},
{
"type": "paragraph",
"data": {
"delta": []
}
},
{
"type": "paragraph",
"data": {
"delta": [
{
"insert": "Drag the notepad to the desired location."
}
]
}
},
{
"type": "image",
"data": {
"url": "https://beta.appflowy.cloud/api/file_storage/c29fafc4-b7c0-4549-8702-71339b0fd9ea/v1/blob/735c7c28%2D33a0%2D4e9f%2D92e6%2D089630656063/TRYYtsRlWsmEYPSsIkpYs0uawhrtj3W52kg0VgwZ2J0=.png",
"align": "center",
"image_type": 1
}
},
{
"type": "paragraph",
"data": {
"delta": []
}
},
{
"type": "paragraph",
"data": {
"delta": [
{
"insert": "Expand the notepad into a larger window to get more editing space."
}
]
}
},
{
"type": "image",
"data": {
"image_type": 1,
"url": "https://beta.appflowy.cloud/api/file_storage/c29fafc4-b7c0-4549-8702-71339b0fd9ea/v1/blob/735c7c28%2D33a0%2D4e9f%2D92e6%2D089630656063/JimDFWOY8_ATw20LkDuBg68TwkwtmSysbRbMd2eNjZ0=.png",
"align": "center"
}
},
{
"type": "paragraph",
"data": {
"delta": []
}
},
{
"type": "heading",
"data": {
"level": 3,
"delta": [
{
"insert": "Keyboard shortcuts, markdown, and code block"
}
]
}
},
{
"type": "numbered_list",
"data": {
"delta": [
{
"insert": "Keyboard shortcuts "
},
{
"insert": "guide",
"attributes": {
"href": "https://appflowy.gitbook.io/docs/essential-documentation/shortcuts"
}
}
]
}
},
{
"type": "numbered_list",
"data": {
"delta": [
{
"insert": "Markdown "
},
{
"insert": "reference",
"attributes": {
"href": "https://appflowy.gitbook.io/docs/essential-documentation/markdown"
}
}
]
}
},
{
"type": "numbered_list",
"data": {
"delta": [
{
"insert": "Type "
},
{
"insert": "/code",
"attributes": {
"code": true
}
},
{
"insert": " or "
},
{
"insert": "```",
"attributes": {
"code": true
}
},
{
"insert": " to insert a code block (Mermaid"
},
{
"insert": " is supported in our web app 🧜‍♀️)"
}
]
}
},
{
"type": "code",
"data": {
"language": "mermaid",
"delta": [
{
"insert": "graph LR\n A[Square Rect] -- Link text --> B((Circle))\n A --> C(Round Rect)\n B --> D{Rhombus}\n C --> D"
}
]
}
},
{
"type": "paragraph",
"data": {
"delta": []
}
},
{
"type": "heading",
"data": {
"level": 2,
"delta": [
{
"insert": "Have a question❓"
}
]
}
},
{
"type": "quote",
"data": {
"delta": [
{
"insert": "Click "
},
{
"insert": "?",
"attributes": {
"code": true
}
},
{
"insert": " at the bottom right for help and support"
}
]
}
}
],
"data": {
"selected_icon": "{\"groupName\":\"Recent\",\"iconContent\":\"<svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 14 14\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n<g clip-path=\\\"url(#clip0_1068_189559)\\\">\\n<path fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\" d=\\\"M9.81502 0.666197C9.9981 -0.170135 11.189 -0.175341 11.3793 0.65936L11.3883 0.698818C11.3944 0.725719 11.4 0.75057 11.4061 0.776468C11.6254 1.71056 12.3814 2.4243 13.3276 2.58893C14.2 2.74069 14.2 3.99292 13.3276 4.14468C12.3763 4.31019 11.6174 5.03067 11.4026 5.97212L11.3793 6.07425C11.189 6.90896 9.99809 6.90374 9.81502 6.06741L9.79583 5.97977C9.58899 5.03487 8.83104 4.30902 7.87808 4.14323C7.0074 3.99176 7.00739 2.74185 7.87808 2.59038C8.82772 2.42516 9.58371 1.70378 9.79365 0.763705L9.80781 0.699221L9.81502 0.666197ZM7.69172 5.21435C5.81589 4.88801 5.63841 2.41899 7.1594 1.68728C7.0236 1.44232 6.87994 1.20164 6.72859 0.965667C6.64978 0.962837 6.57062 0.961411 6.49113 0.961411C6.41169 0.961411 6.33258 0.962835 6.25382 0.965661C5.12844 2.72022 4.42868 4.7349 4.22016 6.83759H8.76225C8.7325 6.53763 8.69276 6.23947 8.64321 5.9436C8.46716 5.56473 8.11481 5.28796 7.69172 5.21435ZM0.0195433 6.83765C0.274572 4.16392 2.14899 1.96256 4.65082 1.22555C3.72044 2.95001 3.14382 4.86059 2.96455 6.83759H0.0284221L0.0195433 6.83765ZM0.0284221 8.08759H2.96451C3.1437 10.0646 3.72025 11.9752 4.65057 13.6997C2.14882 12.9626 0.274503 10.7612 0.0195312 8.08752L0.0284221 8.08759ZM4.22011 8.08759C4.42855 10.1903 5.12824 12.205 6.25357 13.9596C6.3324 13.9625 6.4116 13.9639 6.49113 13.9639C6.57071 13.9639 6.64996 13.9625 6.72885 13.9596C7.85417 12.205 8.55386 10.1903 8.7623 8.08759H4.22011ZM12.9628 8.08753C12.7078 10.7612 10.8336 12.9625 8.33187 13.6996C9.26217 11.9751 9.83871 10.0646 10.0179 8.08759H12.9542L12.9628 8.08753Z\\\" fill=\\\"black\\\"/>\\n</g>\\n<defs>\\n<clipPath id=\\\"clip0_1068_189559\\\">\\n<rect width=\\\"14\\\" height=\\\"14\\\" fill=\\\"white\\\"/>\\n</clipPath>\\n</defs>\\n</svg>\\n\",\"iconName\":\"ai-network-spark\",\"color\":\"0xFF808080\"}",
"image_type": "1"
}
}

View File

@ -23,6 +23,7 @@ use crate::{gen_view_id, TemplateData, TemplateObjectId, WorkspaceTemplate};
// |-- Getting started (document)
// |-- Desktop guide (document)
// |-- Mobile guide (document)
// |-- Web guide (document)
// |-- To-dos (board)
// |-- Shared (space)
// |-- ... (empty)
@ -99,6 +100,7 @@ impl GettingStartedTemplate {
Ok(template_data)
}
#[allow(clippy::too_many_arguments)]
async fn create_document_and_database_data(
&self,
general_view_uuid: String,
@ -106,6 +108,7 @@ impl GettingStartedTemplate {
getting_started_view_uuid: String,
desktop_guide_view_uuid: String,
mobile_guide_view_uuid: String,
web_guide_view_uuid: String,
todos_view_uuid: String,
) -> anyhow::Result<(
TemplateData,
@ -113,6 +116,7 @@ impl GettingStartedTemplate {
TemplateData,
TemplateData,
TemplateData,
TemplateData,
Vec<TemplateData>,
)> {
let default_space_json = include_str!("../../assets/default_space.json");
@ -135,6 +139,7 @@ impl GettingStartedTemplate {
"mobile_guide_id".to_string(),
mobile_guide_view_uuid.clone(),
);
replacements.insert("web_guide_id".to_string(), web_guide_view_uuid.clone());
replacements.insert("todos_id".to_string(), todos_view_uuid.clone());
replace_json_placeholders(&mut getting_started_json, &replacements);
let getting_started_data = self
@ -154,6 +159,11 @@ impl GettingStartedTemplate {
.create_document_from_json(mobile_guide_view_uuid.clone(), mobile_guide_json)
.await?;
let web_guide_json = include_str!("../../assets/web_guide.json");
let web_guide_data = self
.create_document_from_json(web_guide_view_uuid.clone(), web_guide_json)
.await?;
let todos_json = include_str!("../../assets/to-dos.json");
let database_data = serde_json::from_str::<DatabaseData>(todos_json)?;
let database_view_id = database_data.views[0].id.clone();
@ -169,6 +179,7 @@ impl GettingStartedTemplate {
getting_started_data,
desktop_guide_data,
mobile_guide_data,
web_guide_data,
todos_data,
))
}
@ -179,6 +190,7 @@ impl GettingStartedTemplate {
getting_started_view_uuid: String,
desktop_guide_view_uuid: String,
mobile_guide_view_uuid: String,
web_guide_view_uuid: String,
) -> ViewBuilder {
// getting started view
let mut view_builder = view_builder
@ -214,6 +226,19 @@ impl GettingStartedTemplate {
})
.await;
view_builder = view_builder
.with_child_view_builder({
|child_view_builder| async {
// web guide view
let web_guide_view_uuid = web_guide_view_uuid.clone();
child_view_builder
.with_name("Web guide")
.with_view_id(web_guide_view_uuid)
.build()
}
})
.await;
view_builder
}
}
@ -238,6 +263,7 @@ impl WorkspaceTemplate for GettingStartedTemplate {
let getting_started_view_uuid = gen_view_id().to_string();
let desktop_guide_view_uuid = gen_view_id().to_string();
let mobile_guide_view_uuid = gen_view_id().to_string();
let web_guide_view_uuid = gen_view_id().to_string();
let todos_view_uuid = gen_view_id().to_string();
let (
@ -246,6 +272,7 @@ impl WorkspaceTemplate for GettingStartedTemplate {
getting_started_data,
desktop_guide_data,
mobile_guide_data,
web_guide_data,
todos_data,
) = self
.create_document_and_database_data(
@ -254,6 +281,7 @@ impl WorkspaceTemplate for GettingStartedTemplate {
getting_started_view_uuid.clone(),
desktop_guide_view_uuid.clone(),
mobile_guide_view_uuid.clone(),
web_guide_view_uuid.clone(),
todos_view_uuid.clone(),
)
.await?;
@ -277,7 +305,8 @@ impl WorkspaceTemplate for GettingStartedTemplate {
let getting_started_view_uuid = getting_started_view_uuid.clone();
let desktop_guide_view_uuid = desktop_guide_view_uuid.clone();
let mobile_guide_view_uuid = mobile_guide_view_uuid.clone();
let child_view_builder = self.build_getting_started_view(child_view_builder, getting_started_view_uuid, desktop_guide_view_uuid, mobile_guide_view_uuid).await;
let web_guide_view_uuid = web_guide_view_uuid.clone();
let child_view_builder = self.build_getting_started_view(child_view_builder, getting_started_view_uuid, desktop_guide_view_uuid, mobile_guide_view_uuid, web_guide_view_uuid).await;
child_view_builder.build()
}
).await;
@ -319,6 +348,7 @@ impl WorkspaceTemplate for GettingStartedTemplate {
getting_started_data,
desktop_guide_data,
mobile_guide_data,
web_guide_data,
];
template_data.extend(todos_data);
Ok(template_data)

View File

@ -11,7 +11,7 @@ fn document_plain_text() {
let collab = Collab::new_with_origin(CollabOrigin::Server, "1", vec![], false);
let document = Document::create_with_data(collab, doc).unwrap();
let text = document.to_plain_text(false, true).unwrap();
let expected = "Welcome to AppFlowy $ Download for macOS, Windows, and Linux link $ $ quick start Ask AI powered by advanced AI models: chat, search, write, and much more ✨ ❤\u{fe0f}Love AppFlowy and open source? Follow our latest product updates: Twitter : @appflowy Reddit : r/appflowy Github ";
let expected = "Welcome to AppFlowy $ Download for macOS, Windows, and Linux link $ $ $ quick start Ask AI powered by advanced AI models: chat, search, write, and much more ✨ ❤\u{fe0f}Love AppFlowy and open source? Follow our latest product updates: Twitter : @appflowy Reddit : r/appflowy Github ";
assert_eq!(&text, expected);
}

View File

@ -410,8 +410,8 @@ async fn insert_folder_data_success_test() {
.await
.unwrap();
// 2 spaces, 3 documents, 2 databases, 5 rows
assert_eq!(templates.len(), 12);
// 2 spaces, 4 documents, 2 databases, 5 rows
assert_eq!(templates.len(), 13);
for template in templates.into_iter() {
let data = template.encoded_collab.encode_to_bytes().unwrap();

View File

@ -27,6 +27,7 @@ async fn get_document_collab_from_remote(
// |-- Getting started (document)
// |-- Desktop guide (document)
// |-- Mobile guide (document)
// |-- Web guide (document)
// |-- To-dos (board)
// |-- Shared (space)
// |-- ... (empty)
@ -80,10 +81,10 @@ async fn get_user_default_workspace_test() {
)
.await;
let document_data = getting_started_document.get_document_data().unwrap();
assert_eq!(document_data.blocks.len(), 15);
assert_eq!(document_data.blocks.len(), 16);
let getting_started_sub_views = folder.get_views_belong_to(&getting_started_view.id);
assert_eq!(getting_started_sub_views.len(), 2);
assert_eq!(getting_started_sub_views.len(), 3);
let desktop_guide_view = getting_started_sub_views[0].clone();
assert_eq!(desktop_guide_view.name, "Desktop guide");
@ -116,6 +117,16 @@ async fn get_user_default_workspace_test() {
.await;
let mobile_guide_document_data = mobile_guide_document.get_document_data().unwrap();
assert_eq!(mobile_guide_document_data.blocks.len(), 33);
let web_guide_view = getting_started_sub_views[2].clone();
assert_eq!(web_guide_view.name, "Web guide");
assert_eq!(web_guide_view.layout, ViewLayout::Document);
assert_eq!(web_guide_view.icon, None);
let web_guide_document =
get_document_collab_from_remote(&mut test_client, workspace_id.clone(), &web_guide_view.id)
.await;
let web_guide_document_data = web_guide_document.get_document_data().unwrap();
assert_eq!(web_guide_document_data.blocks.len(), 31);
}
// the second view is the to-dos board, and contains 0 sub views