Skip to content

Commit 1b17c85

Browse files
committed
Merge branch 'quick-notes-api' into stateless
2 parents 9d6b272 + 8128c2f commit 1b17c85

15 files changed

+590
-2
lines changed

.sqlx/query-5cce5f82c0fb9237f724478e2167243bc772c092910f07b8226431a6dd70a7da.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.sqlx/query-770a4979e137ca08c5ea625259221f9d397a56defb8e498eb92da7b3a8af612b.json

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.sqlx/query-fba0b66b63ae9561c4868891770821abe34953a6ed21fd25639beab9a76780dd.json

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use client_api_entity::{
2+
CreateQuickNoteParams, ListQuickNotesQueryParams, QuickNotes, UpdateQuickNoteParams,
3+
};
4+
use reqwest::Method;
5+
use shared_entity::response::{AppResponse, AppResponseError};
6+
use uuid::Uuid;
7+
8+
use crate::Client;
9+
10+
fn quick_note_resources_url(base_url: &str, workspace_id: Uuid) -> String {
11+
format!("{base_url}/api/workspace/{workspace_id}/quick-note")
12+
}
13+
14+
fn quick_note_resource_url(base_url: &str, workspace_id: Uuid, quick_note_id: Uuid) -> String {
15+
let quick_note_resources_prefix = quick_note_resources_url(base_url, workspace_id);
16+
format!("{quick_note_resources_prefix}/{quick_note_id}")
17+
}
18+
19+
// Quick Note API
20+
impl Client {
21+
pub async fn create_quick_note(&self, workspace_id: Uuid) -> Result<(), AppResponseError> {
22+
let url = quick_note_resources_url(&self.base_url, workspace_id);
23+
let resp = self
24+
.http_client_with_auth(Method::POST, &url)
25+
.await?
26+
.json(&CreateQuickNoteParams {})
27+
.send()
28+
.await?;
29+
AppResponse::<()>::from_response(resp).await?.into_error()
30+
}
31+
32+
pub async fn list_quick_notes(
33+
&self,
34+
workspace_id: Uuid,
35+
search_term: Option<String>,
36+
offset: Option<i32>,
37+
limit: Option<i32>,
38+
) -> Result<QuickNotes, AppResponseError> {
39+
let url = quick_note_resources_url(&self.base_url, workspace_id);
40+
let resp = self
41+
.http_client_with_auth(Method::GET, &url)
42+
.await?
43+
.query(&ListQuickNotesQueryParams {
44+
search_term,
45+
offset,
46+
limit,
47+
})
48+
.send()
49+
.await?;
50+
AppResponse::<QuickNotes>::from_response(resp)
51+
.await?
52+
.into_data()
53+
}
54+
55+
pub async fn update_quick_note(
56+
&self,
57+
workspace_id: Uuid,
58+
quick_note_id: Uuid,
59+
data: serde_json::Value,
60+
) -> Result<(), AppResponseError> {
61+
let url = quick_note_resource_url(&self.base_url, workspace_id, quick_note_id);
62+
let resp = self
63+
.http_client_with_auth(Method::PUT, &url)
64+
.await?
65+
.json(&UpdateQuickNoteParams { data })
66+
.send()
67+
.await?;
68+
AppResponse::<()>::from_response(resp).await?.into_error()
69+
}
70+
71+
pub async fn delete_quick_note(
72+
&self,
73+
workspace_id: Uuid,
74+
quick_note_id: Uuid,
75+
) -> Result<(), AppResponseError> {
76+
let url = quick_note_resource_url(&self.base_url, workspace_id, quick_note_id);
77+
let resp = self
78+
.http_client_with_auth(Method::DELETE, &url)
79+
.await?
80+
.send()
81+
.await?;
82+
AppResponse::<()>::from_response(resp).await?.into_error()
83+
}
84+
}

libs/client-api/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod http_collab;
88
mod http_history;
99
mod http_member;
1010
mod http_publish;
11+
mod http_quick_note;
1112
mod http_search;
1213
mod http_template;
1314
mod http_view;

libs/database-entity/src/dto.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,35 @@ pub struct WorkspaceNamespace {
11671167
pub is_original: bool,
11681168
}
11691169

1170+
#[derive(Clone, Serialize, Deserialize, Debug)]
1171+
pub struct QuickNote {
1172+
pub id: Uuid,
1173+
pub data: serde_json::Value,
1174+
pub created_at: DateTime<Utc>,
1175+
pub last_updated_at: DateTime<Utc>,
1176+
}
1177+
1178+
#[derive(Clone, Serialize, Deserialize, Debug)]
1179+
pub struct QuickNotes {
1180+
pub quick_notes: Vec<QuickNote>,
1181+
pub has_more: bool,
1182+
}
1183+
1184+
#[derive(Serialize, Deserialize, Debug)]
1185+
pub struct CreateQuickNoteParams {}
1186+
1187+
#[derive(Serialize, Deserialize, Debug)]
1188+
pub struct UpdateQuickNoteParams {
1189+
pub data: serde_json::Value,
1190+
}
1191+
1192+
#[derive(Serialize, Deserialize, Debug)]
1193+
pub struct ListQuickNotesQueryParams {
1194+
pub search_term: Option<String>,
1195+
pub offset: Option<i32>,
1196+
pub limit: Option<i32>,
1197+
}
1198+
11701199
#[cfg(test)]
11711200
mod test {
11721201
use crate::dto::{CollabParams, CollabParamsV0};

libs/database/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub mod index;
77
pub mod listener;
88
pub mod pg_row;
99
pub mod publish;
10+
pub mod quick_note;
1011
pub mod resource_usage;
1112
pub mod template;
1213
pub mod user;

libs/database/src/pg_row.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ use chrono::{DateTime, Utc};
55
use database_entity::dto::{
66
AFAccessLevel, AFRole, AFUserProfile, AFWebUser, AFWorkspace, AFWorkspaceInvitationStatus,
77
AccessRequestMinimal, AccessRequestStatus, AccessRequestWithViewId, AccessRequesterInfo,
8-
AccountLink, GlobalComment, Reaction, Template, TemplateCategory, TemplateCategoryMinimal,
9-
TemplateCategoryType, TemplateCreator, TemplateCreatorMinimal, TemplateGroup, TemplateMinimal,
8+
AccountLink, GlobalComment, QuickNote, Reaction, Template, TemplateCategory,
9+
TemplateCategoryMinimal, TemplateCategoryType, TemplateCreator, TemplateCreatorMinimal,
10+
TemplateGroup, TemplateMinimal,
1011
};
1112
use serde::{Deserialize, Serialize};
1213
use sqlx::FromRow;
@@ -647,3 +648,22 @@ impl TryFrom<AFAccessRequestWithViewIdColumn> for AccessRequestWithViewId {
647648
})
648649
}
649650
}
651+
652+
#[derive(FromRow, Serialize, Debug)]
653+
pub struct AFQuickNoteRow {
654+
pub quick_note_id: Uuid,
655+
pub data: serde_json::Value,
656+
pub created_at: DateTime<Utc>,
657+
pub updated_at: DateTime<Utc>,
658+
}
659+
660+
impl From<AFQuickNoteRow> for QuickNote {
661+
fn from(value: AFQuickNoteRow) -> Self {
662+
Self {
663+
id: value.quick_note_id,
664+
data: value.data,
665+
created_at: value.created_at,
666+
last_updated_at: value.updated_at,
667+
}
668+
}
669+
}

libs/database/src/quick_note.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
use app_error::AppError;
2+
use database_entity::dto::QuickNote;
3+
use sqlx::{Executor, Postgres, QueryBuilder};
4+
use uuid::Uuid;
5+
6+
use crate::pg_row::AFQuickNoteRow;
7+
8+
pub async fn insert_new_quick_note<'a, E: Executor<'a, Database = Postgres>>(
9+
executor: E,
10+
workspace_id: Uuid,
11+
uid: i64,
12+
data: &serde_json::Value,
13+
) -> Result<(), AppError> {
14+
sqlx::query!(
15+
"INSERT INTO af_quick_note (workspace_id, uid, data) VALUES ($1, $2, $3)",
16+
workspace_id,
17+
uid,
18+
data
19+
)
20+
.execute(executor)
21+
.await?;
22+
Ok(())
23+
}
24+
25+
pub async fn select_quick_notes_with_one_more_than_limit<
26+
'a,
27+
E: Executor<'a, Database = Postgres>,
28+
>(
29+
executor: E,
30+
workspace_id: Uuid,
31+
uid: i64,
32+
search_term: Option<String>,
33+
offset: Option<i32>,
34+
limit: Option<i32>,
35+
) -> Result<Vec<QuickNote>, AppError> {
36+
let mut query_builder: QueryBuilder<Postgres> = QueryBuilder::new(
37+
r#"
38+
SELECT
39+
quick_note_id,
40+
data,
41+
created_at,
42+
updated_at
43+
FROM af_quick_note WHERE workspace_id =
44+
"#,
45+
);
46+
query_builder.push_bind(workspace_id);
47+
query_builder.push(" AND uid = ");
48+
query_builder.push_bind(uid);
49+
if let Some(search_term) = search_term {
50+
query_builder.push(" AND data @? ");
51+
let json_path_query = format!("'$.**.insert ? (@ like_regex \".*{}.*\")'", search_term);
52+
query_builder.push(json_path_query);
53+
}
54+
query_builder.push(" ORDER BY created_at DESC");
55+
if let Some(limit) = limit {
56+
query_builder.push(" LIMIT ");
57+
query_builder.push_bind(limit);
58+
query_builder.push(" + 1 ");
59+
}
60+
if let Some(offset) = offset {
61+
query_builder.push(" OFFSET ");
62+
query_builder.push_bind(offset);
63+
}
64+
let query = query_builder.build_query_as::<AFQuickNoteRow>();
65+
let quick_notes_with_one_more_than_limit = query
66+
.fetch_all(executor)
67+
.await?
68+
.into_iter()
69+
.map(Into::into)
70+
.collect();
71+
Ok(quick_notes_with_one_more_than_limit)
72+
}
73+
74+
pub async fn update_quick_note_by_id<'a, E: Executor<'a, Database = Postgres>>(
75+
executor: E,
76+
quick_note_id: Uuid,
77+
data: &serde_json::Value,
78+
) -> Result<(), AppError> {
79+
sqlx::query!(
80+
"UPDATE af_quick_note SET data = $1, updated_at = NOW() WHERE quick_note_id = $2",
81+
data,
82+
quick_note_id
83+
)
84+
.execute(executor)
85+
.await?;
86+
Ok(())
87+
}
88+
89+
pub async fn delete_quick_note_by_id<'a, E: Executor<'a, Database = Postgres>>(
90+
executor: E,
91+
quick_note_id: Uuid,
92+
) -> Result<(), AppError> {
93+
sqlx::query!(
94+
"DELETE FROM af_quick_note WHERE quick_note_id = $1",
95+
quick_note_id
96+
)
97+
.execute(executor)
98+
.await?;
99+
Ok(())
100+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CREATE TABLE IF NOT EXISTS af_quick_note (
2+
quick_note_id UUID NOT NULL DEFAULT gen_random_uuid (),
3+
workspace_id UUID NOT NULL,
4+
uid BIGINT NOT NULL REFERENCES af_user (uid) ON DELETE CASCADE,
5+
updated_at TIMESTAMP
6+
WITH
7+
TIME ZONE DEFAULT CURRENT_TIMESTAMP,
8+
created_at TIMESTAMP
9+
WITH
10+
TIME ZONE DEFAULT CURRENT_TIMESTAMP,
11+
data JSONB NOT NULL,
12+
PRIMARY KEY (quick_note_id)
13+
);
14+
15+
CREATE INDEX IF NOT EXISTS idx_workspace_id_on_af_quick_note ON af_quick_note (workspace_id);
16+
17+
CREATE INDEX IF NOT EXISTS idx_uid_on_af_quick_note ON af_quick_note (uid);

0 commit comments

Comments
 (0)