headless_lms_models/
course_page_markdown_content.rs1use serde_json::Value;
2
3use crate::prelude::*;
4
5#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
6pub struct CoursePageMarkdownContent {
7 pub id: Uuid,
8 pub created_at: DateTime<Utc>,
9 pub updated_at: DateTime<Utc>,
10 pub deleted_at: Option<DateTime<Utc>>,
11 pub markdown_content: String,
12 pub page_history_id: Uuid,
13 pub page_id: Uuid,
14}
15
16pub struct CoursePageContent {
18 pub page_id: Uuid,
19 pub course_id: Uuid,
20 pub title: String,
21 pub json_content: Value,
22 pub markdown_content: Option<String>,
24}
25
26pub async fn insert(
27 conn: &mut PgConnection,
28 content: &str,
29 page_history_id: &Uuid,
30 page_id: &Uuid,
31) -> ModelResult<CoursePageMarkdownContent> {
32 let res = sqlx::query_as!(
33 CoursePageMarkdownContent,
34 r#"
35INSERT INTO course_page_markdown_content (markdown_content, page_history_id, page_id)
36VALUES ($1, $2, $3)
37RETURNING *
38 "#,
39 content,
40 page_history_id,
41 page_id
42 )
43 .fetch_one(conn)
44 .await?;
45
46 Ok(res)
47}
48
49pub async fn insert_batch(
50 conn: &mut PgConnection,
51 page_id_history_id_contents: Vec<(Uuid, (Uuid, String))>,
52) -> ModelResult<Vec<CoursePageMarkdownContent>> {
53 let (page_ids, history_ids_contents): (Vec<Uuid>, Vec<(Uuid, String)>) =
54 page_id_history_id_contents.into_iter().unzip();
55 let (history_ids, contents): (Vec<Uuid>, Vec<String>) =
56 history_ids_contents.into_iter().unzip();
57
58 let res = sqlx::query_as!(
59 CoursePageMarkdownContent,
60 r#"
61
62INSERT INTO course_page_markdown_content (markdown_content, page_history_id, page_id)
63SELECT data.content, data.page_history_id, data.page_id
64FROM (
65 SELECT unnest($1::text []) AS content,
66 unnest($2::uuid []) AS page_history_id,
67 unnest($3::uuid []) AS page_id
68 ) AS data
69RETURNING *
70 "#,
71 &contents,
72 &history_ids,
73 &page_ids
74 )
75 .fetch_all(conn)
76 .await?;
77
78 Ok(res)
79}
80
81pub async fn get(conn: &mut PgConnection, id: Uuid) -> ModelResult<CoursePageMarkdownContent> {
82 let res = sqlx::query_as!(
83 CoursePageMarkdownContent,
84 r#"
85SELECT * FROM course_page_markdown_content
86WHERE id = $1
87AND deleted_at IS NULL
88 "#,
89 id
90 )
91 .fetch_one(conn)
92 .await?;
93
94 Ok(res)
95}
96
97pub async fn get_many(
98 conn: &mut PgConnection,
99 ids: &[Uuid],
100) -> ModelResult<Vec<CoursePageMarkdownContent>> {
101 let res = sqlx::query_as!(
102 CoursePageMarkdownContent,
103 r#"
104SELECT * FROM course_page_markdown_content
105WHERE id = ANY($1)
106AND deleted_at IS NULL
107 "#,
108 ids
109 )
110 .fetch_all(conn)
111 .await?;
112
113 Ok(res)
114}
115
116pub async fn get_course_page_content_by_page_id(
118 conn: &mut PgConnection,
119 page_id: Uuid,
120) -> ModelResult<CoursePageContent> {
121 let content = sqlx::query_as!(
122 CoursePageContent,
123 r#"
124SELECT pages.content AS json_content,
125 pages.title,
126 pages.id AS page_id,
127 cpmc.markdown_content,
128 cps.course_id
129FROM pages
130 JOIN page_history AS ph ON pages.id = ph.page_id
131 JOIN chatbot_page_sync_statuses AS cps ON pages.id = cps.page_id
132 JOIN course_page_markdown_content AS cpmc ON cps.converted_markdown_content_id = cpmc.id
133WHERE ph.id IN (
134 SELECT synced_page_revision_id
135 FROM chatbot_page_sync_statuses
136 WHERE page_id = $1
137 AND deleted_at IS NULL
138 ORDER BY updated_at DESC
139 LIMIT 1
140 )
141 AND pages.id = $1
142 AND pages.deleted_at IS NULL
143 AND ph.deleted_at IS NULL
144 AND cps.deleted_at IS NULL
145 AND cpmc.deleted_at IS NULL
146 "#,
147 page_id,
148 )
149 .fetch_optional(&mut *conn)
150 .await?;
151
152 if let Some(s) = content {
153 Ok(s)
154 } else {
155 let fallback_content = sqlx::query_as!(
158 CoursePageContent,
159 r#"
160SELECT pages.content AS json_content,
161 pages.title,
162 pages.id AS page_id,
163 null as markdown_content,
164 pages.course_id as "course_id!"
165FROM pages
166 WHERE pages.course_id IS NOT NULL
167 AND pages.id = $1
168 AND pages.deleted_at IS NULL
169 "#,
170 page_id,
171 )
172 .fetch_one(&mut *conn)
173 .await?;
174
175 Ok(fallback_content)
176 }
177}