Skip to content

Commit 76fbd79

Browse files
authored
feat: support ai meeting block (#432)
1 parent 0dac1d3 commit 76fbd79

File tree

9 files changed

+230
-1
lines changed

9 files changed

+230
-1
lines changed

collab/src/document/block_parser/document_parser.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::{
2+
AiMeetingNotesParser, AiMeetingParser, AiMeetingSummaryParser, AiMeetingTranscriptionParser,
23
BlockParserRegistry, BulletedListParser, CalloutParser, CodeBlockParser, DividerParser,
34
DocumentParserDelegate, FileBlockParser, HeadingParser, ImageParser, LinkPreviewParser,
45
MathEquationParser, NumberedListParser, OutputFormat, PageParser, ParagraphParser, ParseContext,
@@ -82,7 +83,11 @@ impl DocumentParser {
8283
.register(Arc::new(SimpleTableParser))
8384
.register(Arc::new(SimpleTableRowParser))
8485
.register(Arc::new(SimpleTableCellParser))
85-
.register(Arc::new(SubpageParser));
86+
.register(Arc::new(SubpageParser))
87+
.register(Arc::new(AiMeetingParser))
88+
.register(Arc::new(AiMeetingSummaryParser))
89+
.register(Arc::new(AiMeetingNotesParser))
90+
.register(Arc::new(AiMeetingTranscriptionParser));
8691

8792
parser
8893
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use super::super::{BlockParser, ParseContext, ParseResult};
2+
use crate::document::blocks::{Block, BlockType};
3+
use crate::error::CollabError;
4+
5+
pub struct AiMeetingParser;
6+
7+
impl BlockParser for AiMeetingParser {
8+
fn parse(&self, _block: &Block, _context: &ParseContext) -> Result<ParseResult, CollabError> {
9+
Ok(ParseResult::container("".to_string()))
10+
}
11+
12+
fn block_type(&self) -> &'static str {
13+
BlockType::AiMeeting.as_str()
14+
}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use super::super::{BlockParser, ParseContext, ParseResult};
2+
use crate::document::blocks::{Block, BlockType};
3+
use crate::error::CollabError;
4+
5+
pub struct AiMeetingNotesParser;
6+
7+
impl BlockParser for AiMeetingNotesParser {
8+
fn parse(&self, _block: &Block, _context: &ParseContext) -> Result<ParseResult, CollabError> {
9+
Ok(ParseResult::container("".to_string()))
10+
}
11+
12+
fn block_type(&self) -> &'static str {
13+
BlockType::AiMeetingNotes.as_str()
14+
}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use super::super::{BlockParser, ParseContext, ParseResult};
2+
use crate::document::blocks::{Block, BlockType};
3+
use crate::error::CollabError;
4+
5+
pub struct AiMeetingSummaryParser;
6+
7+
impl BlockParser for AiMeetingSummaryParser {
8+
fn parse(&self, _block: &Block, _context: &ParseContext) -> Result<ParseResult, CollabError> {
9+
Ok(ParseResult::container("".to_string()))
10+
}
11+
12+
fn block_type(&self) -> &'static str {
13+
BlockType::AiMeetingSummary.as_str()
14+
}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use super::super::{BlockParser, ParseContext, ParseResult};
2+
use crate::document::blocks::{Block, BlockType};
3+
use crate::error::CollabError;
4+
5+
pub struct AiMeetingTranscriptionParser;
6+
7+
impl BlockParser for AiMeetingTranscriptionParser {
8+
fn parse(&self, _block: &Block, _context: &ParseContext) -> Result<ParseResult, CollabError> {
9+
Ok(ParseResult::container("".to_string()))
10+
}
11+
12+
fn block_type(&self) -> &'static str {
13+
BlockType::AiMeetingTranscription.as_str()
14+
}
15+
}

collab/src/document/block_parser/parsers/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
pub mod ai_meeting;
2+
pub mod ai_meeting_notes;
3+
pub mod ai_meeting_summary;
4+
pub mod ai_meeting_transcription;
15
pub mod bulleted_list;
26
pub mod callout;
37
pub mod code_block;
@@ -20,6 +24,10 @@ pub mod subpage;
2024
pub mod todo_list;
2125
pub mod toggle_list;
2226

27+
pub use ai_meeting::*;
28+
pub use ai_meeting_notes::*;
29+
pub use ai_meeting_summary::*;
30+
pub use ai_meeting_transcription::*;
2331
pub use bulleted_list::*;
2432
pub use callout::*;
2533
pub use code_block::*;

collab/src/document/blocks/block_types.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ pub enum BlockType {
3535
SimpleTableCell,
3636
SimpleColumns,
3737
SimpleColumn,
38+
AiMeeting,
39+
AiMeetingSummary,
40+
AiMeetingNotes,
41+
AiMeetingTranscription,
3842
Custom(String),
3943

4044
// Legacy types
@@ -74,6 +78,10 @@ impl BlockType {
7478
BlockType::SimpleTableCell => "simple_table_cell",
7579
BlockType::SimpleColumns => "simple_columns",
7680
BlockType::SimpleColumn => "simple_column",
81+
BlockType::AiMeeting => "ai_meeting",
82+
BlockType::AiMeetingSummary => "ai_meeting_summary",
83+
BlockType::AiMeetingNotes => "ai_meeting_notes",
84+
BlockType::AiMeetingTranscription => "ai_meeting_transcription",
7785
BlockType::Table => "table",
7886
BlockType::TableCell => "table/cell",
7987
BlockType::Custom(s) => s,
@@ -111,6 +119,10 @@ impl BlockType {
111119
"simple_table_cell" => BlockType::SimpleTableCell,
112120
"simple_columns" => BlockType::SimpleColumns,
113121
"simple_column" => BlockType::SimpleColumn,
122+
"ai_meeting" => BlockType::AiMeeting,
123+
"ai_meeting_summary" => BlockType::AiMeetingSummary,
124+
"ai_meeting_notes" => BlockType::AiMeetingNotes,
125+
"ai_meeting_transcription" => BlockType::AiMeetingTranscription,
114126
"table" => BlockType::Table,
115127
"table/cell" => BlockType::TableCell,
116128
_ => BlockType::Custom(s.to_string()),
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
use crate::blocks::block_test_core::{BlockTestCore, generate_id};
2+
use collab::document::block_parser::parsers::ai_meeting::AiMeetingParser;
3+
use collab::document::block_parser::{BlockParser, DocumentParser, OutputFormat, ParseContext};
4+
use collab::document::blocks::{Block, BlockType};
5+
use serde_json::json;
6+
use std::collections::HashMap;
7+
8+
fn create_ai_meeting_block(test: &mut BlockTestCore, parent_id: &str) -> Block {
9+
create_block(test, BlockType::AiMeeting, parent_id)
10+
}
11+
12+
fn create_ai_meeting_summary_block(test: &mut BlockTestCore, parent_id: &str) -> Block {
13+
create_block(test, BlockType::AiMeetingSummary, parent_id)
14+
}
15+
16+
fn create_ai_meeting_notes_block(test: &mut BlockTestCore, parent_id: &str) -> Block {
17+
create_block(test, BlockType::AiMeetingNotes, parent_id)
18+
}
19+
20+
fn create_ai_meeting_transcription_block(test: &mut BlockTestCore, parent_id: &str) -> Block {
21+
create_block(test, BlockType::AiMeetingTranscription, parent_id)
22+
}
23+
24+
fn create_block(test: &mut BlockTestCore, ty: BlockType, parent_id: &str) -> Block {
25+
let data = HashMap::new();
26+
let actual_parent_id = if parent_id.is_empty() {
27+
test.get_page().id
28+
} else {
29+
parent_id.to_string()
30+
};
31+
32+
let block = Block {
33+
id: generate_id(),
34+
ty: ty.as_str().to_string(),
35+
parent: actual_parent_id,
36+
children: generate_id(),
37+
external_id: None,
38+
external_type: None,
39+
data,
40+
};
41+
42+
test.document.insert_block(block, None).unwrap()
43+
}
44+
45+
fn create_text_block(test: &mut BlockTestCore, text: &str, parent_id: &str) -> Block {
46+
let delta = json!([{ "insert": text }]).to_string();
47+
let external_id = test.create_text(delta);
48+
let data = HashMap::new();
49+
50+
let block = Block {
51+
id: generate_id(),
52+
ty: BlockType::Paragraph.as_str().to_string(),
53+
parent: parent_id.to_string(),
54+
children: generate_id(),
55+
external_id: Some(external_id),
56+
external_type: Some("text".to_string()),
57+
data,
58+
};
59+
test.document.insert_block(block, None).unwrap()
60+
}
61+
62+
fn create_heading_block(
63+
test: &mut BlockTestCore,
64+
text: &str,
65+
level: u32,
66+
parent_id: &str,
67+
) -> Block {
68+
let delta = json!([{ "insert": text }]).to_string();
69+
let external_id = test.create_text(delta);
70+
let mut data = HashMap::new();
71+
data.insert("level".to_string(), json!(level));
72+
73+
let block = Block {
74+
id: generate_id(),
75+
ty: BlockType::Heading.as_str().to_string(),
76+
parent: parent_id.to_string(),
77+
children: generate_id(),
78+
external_id: Some(external_id),
79+
external_type: Some("text".to_string()),
80+
data,
81+
};
82+
test.document.insert_block(block, None).unwrap()
83+
}
84+
85+
#[test]
86+
fn test_ai_meeting_parser() {
87+
let mut test = BlockTestCore::new();
88+
let document_parser = DocumentParser::with_default_parsers();
89+
90+
let ai_meeting = create_ai_meeting_block(&mut test, "");
91+
92+
let transcription = create_ai_meeting_transcription_block(&mut test, &ai_meeting.id);
93+
create_text_block(&mut test, "Transcription content.", &transcription.id);
94+
95+
let notes = create_ai_meeting_notes_block(&mut test, &ai_meeting.id);
96+
create_text_block(&mut test, "Notes content.", &notes.id);
97+
98+
let summary = create_ai_meeting_summary_block(&mut test, &ai_meeting.id);
99+
create_text_block(&mut test, "Summary content.", &summary.id);
100+
create_heading_block(&mut test, "Overview", 4, &summary.id);
101+
102+
let document_data = test.get_document_data();
103+
let context = ParseContext::new(&document_data, &document_parser, OutputFormat::Markdown);
104+
105+
let result = document_parser.parse_block(&ai_meeting, &context).unwrap();
106+
107+
let expected = r#"#### Overview
108+
Summary content.
109+
Notes content.
110+
Transcription content."#;
111+
112+
assert_eq!(result, expected);
113+
}
114+
115+
#[test]
116+
fn test_ai_meeting_parser_plain_text() {
117+
let mut test = BlockTestCore::new();
118+
let document_parser = DocumentParser::with_default_parsers();
119+
120+
let ai_meeting = create_ai_meeting_block(&mut test, "");
121+
122+
let transcription = create_ai_meeting_transcription_block(&mut test, &ai_meeting.id);
123+
create_text_block(&mut test, "Transcription content.", &transcription.id);
124+
125+
let notes = create_ai_meeting_notes_block(&mut test, &ai_meeting.id);
126+
create_text_block(&mut test, "Notes content.", &notes.id);
127+
128+
let summary = create_ai_meeting_summary_block(&mut test, &ai_meeting.id);
129+
create_text_block(&mut test, "Summary content.", &summary.id);
130+
create_heading_block(&mut test, "Overview", 4, &summary.id);
131+
132+
let document_data = test.get_document_data();
133+
let context = ParseContext::new(&document_data, &document_parser, OutputFormat::PlainText);
134+
135+
let result = document_parser.parse_block(&ai_meeting, &context).unwrap();
136+
137+
let expected = r#"Overview
138+
Summary content.
139+
Notes content.
140+
Transcription content."#;
141+
142+
assert_eq!(result, expected);
143+
}

collab/tests/document/block_parser/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod ai_meeting_test;
12
mod bulleted_list_test;
23
mod callout_test;
34
mod code_block_test;

0 commit comments

Comments
 (0)