field_entities.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. #![allow(clippy::upper_case_acronyms)]
  2. use std::fmt::{Display, Formatter};
  3. use std::sync::Arc;
  4. use collab_database::fields::Field;
  5. use collab_database::views::FieldOrder;
  6. use serde_repr::*;
  7. use strum_macros::{EnumCount as EnumCountMacro, EnumIter};
  8. use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
  9. use flowy_error::ErrorCode;
  10. use crate::entities::parser::NotEmptyStr;
  11. use crate::impl_into_field_type;
  12. /// [FieldPB] defines a Field's attributes. Such as the name, field_type, and width. etc.
  13. #[derive(Debug, Clone, Default, ProtoBuf)]
  14. pub struct FieldPB {
  15. #[pb(index = 1)]
  16. pub id: String,
  17. #[pb(index = 2)]
  18. pub name: String,
  19. #[pb(index = 3)]
  20. pub field_type: FieldType,
  21. #[pb(index = 4)]
  22. pub visibility: bool,
  23. #[pb(index = 5)]
  24. pub width: i32,
  25. #[pb(index = 6)]
  26. pub is_primary: bool,
  27. }
  28. impl std::convert::From<Field> for FieldPB {
  29. fn from(field: Field) -> Self {
  30. Self {
  31. id: field.id,
  32. name: field.name,
  33. field_type: FieldType::from(field.field_type),
  34. visibility: field.visibility,
  35. width: field.width as i32,
  36. is_primary: field.is_primary,
  37. }
  38. }
  39. }
  40. /// [FieldIdPB] id of the [Field]
  41. #[derive(Debug, Clone, Default, ProtoBuf)]
  42. pub struct FieldIdPB {
  43. #[pb(index = 1)]
  44. pub field_id: String,
  45. }
  46. impl std::convert::From<&str> for FieldIdPB {
  47. fn from(s: &str) -> Self {
  48. FieldIdPB {
  49. field_id: s.to_owned(),
  50. }
  51. }
  52. }
  53. impl std::convert::From<String> for FieldIdPB {
  54. fn from(s: String) -> Self {
  55. FieldIdPB { field_id: s }
  56. }
  57. }
  58. impl From<FieldOrder> for FieldIdPB {
  59. fn from(field_order: FieldOrder) -> Self {
  60. Self {
  61. field_id: field_order.id,
  62. }
  63. }
  64. }
  65. impl std::convert::From<&Arc<Field>> for FieldIdPB {
  66. fn from(field_rev: &Arc<Field>) -> Self {
  67. Self {
  68. field_id: field_rev.id.clone(),
  69. }
  70. }
  71. }
  72. #[derive(Debug, Clone, Default, ProtoBuf)]
  73. pub struct DatabaseFieldChangesetPB {
  74. #[pb(index = 1)]
  75. pub view_id: String,
  76. #[pb(index = 2)]
  77. pub inserted_fields: Vec<IndexFieldPB>,
  78. #[pb(index = 3)]
  79. pub deleted_fields: Vec<FieldIdPB>,
  80. #[pb(index = 4)]
  81. pub updated_fields: Vec<FieldPB>,
  82. }
  83. impl DatabaseFieldChangesetPB {
  84. pub fn insert(database_id: &str, inserted_fields: Vec<IndexFieldPB>) -> Self {
  85. Self {
  86. view_id: database_id.to_owned(),
  87. inserted_fields,
  88. deleted_fields: vec![],
  89. updated_fields: vec![],
  90. }
  91. }
  92. pub fn delete(database_id: &str, deleted_fields: Vec<FieldIdPB>) -> Self {
  93. Self {
  94. view_id: database_id.to_string(),
  95. inserted_fields: vec![],
  96. deleted_fields,
  97. updated_fields: vec![],
  98. }
  99. }
  100. pub fn update(database_id: &str, updated_fields: Vec<FieldPB>) -> Self {
  101. Self {
  102. view_id: database_id.to_string(),
  103. inserted_fields: vec![],
  104. deleted_fields: vec![],
  105. updated_fields,
  106. }
  107. }
  108. }
  109. #[derive(Debug, Clone, Default, ProtoBuf)]
  110. pub struct IndexFieldPB {
  111. #[pb(index = 1)]
  112. pub field: FieldPB,
  113. #[pb(index = 2)]
  114. pub index: i32,
  115. }
  116. impl IndexFieldPB {
  117. pub fn from_field(field: Field, index: usize) -> Self {
  118. Self {
  119. field: FieldPB::from(field),
  120. index: index as i32,
  121. }
  122. }
  123. }
  124. #[derive(Debug, Default, ProtoBuf)]
  125. pub struct CreateFieldPayloadPB {
  126. #[pb(index = 1)]
  127. pub view_id: String,
  128. #[pb(index = 2)]
  129. pub field_type: FieldType,
  130. /// If the type_option_data is not empty, it will be used to create the field.
  131. /// Otherwise, the default value will be used.
  132. #[pb(index = 3, one_of)]
  133. pub type_option_data: Option<Vec<u8>>,
  134. }
  135. #[derive(Clone)]
  136. pub struct CreateFieldParams {
  137. pub view_id: String,
  138. pub field_type: FieldType,
  139. /// If the type_option_data is not empty, it will be used to create the field.
  140. /// Otherwise, the default value will be used.
  141. pub type_option_data: Option<Vec<u8>>,
  142. }
  143. impl TryInto<CreateFieldParams> for CreateFieldPayloadPB {
  144. type Error = ErrorCode;
  145. fn try_into(self) -> Result<CreateFieldParams, Self::Error> {
  146. let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::DatabaseIdIsEmpty)?;
  147. Ok(CreateFieldParams {
  148. view_id: view_id.0,
  149. field_type: self.field_type,
  150. type_option_data: self.type_option_data,
  151. })
  152. }
  153. }
  154. #[derive(Debug, Default, ProtoBuf)]
  155. pub struct UpdateFieldTypePayloadPB {
  156. #[pb(index = 1)]
  157. pub view_id: String,
  158. #[pb(index = 2)]
  159. pub field_id: String,
  160. #[pb(index = 3)]
  161. pub field_type: FieldType,
  162. }
  163. pub struct EditFieldParams {
  164. pub view_id: String,
  165. pub field_id: String,
  166. pub field_type: FieldType,
  167. }
  168. impl TryInto<EditFieldParams> for UpdateFieldTypePayloadPB {
  169. type Error = ErrorCode;
  170. fn try_into(self) -> Result<EditFieldParams, Self::Error> {
  171. let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::DatabaseIdIsEmpty)?;
  172. let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
  173. Ok(EditFieldParams {
  174. view_id: view_id.0,
  175. field_id: field_id.0,
  176. field_type: self.field_type,
  177. })
  178. }
  179. }
  180. #[derive(Debug, Default, ProtoBuf)]
  181. pub struct TypeOptionPathPB {
  182. #[pb(index = 1)]
  183. pub view_id: String,
  184. #[pb(index = 2)]
  185. pub field_id: String,
  186. #[pb(index = 3)]
  187. pub field_type: FieldType,
  188. }
  189. pub struct TypeOptionPathParams {
  190. pub view_id: String,
  191. pub field_id: String,
  192. pub field_type: FieldType,
  193. }
  194. impl TryInto<TypeOptionPathParams> for TypeOptionPathPB {
  195. type Error = ErrorCode;
  196. fn try_into(self) -> Result<TypeOptionPathParams, Self::Error> {
  197. let database_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::DatabaseIdIsEmpty)?;
  198. let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
  199. Ok(TypeOptionPathParams {
  200. view_id: database_id.0,
  201. field_id: field_id.0,
  202. field_type: self.field_type,
  203. })
  204. }
  205. }
  206. #[derive(Debug, Default, ProtoBuf)]
  207. pub struct TypeOptionPB {
  208. #[pb(index = 1)]
  209. pub view_id: String,
  210. #[pb(index = 2)]
  211. pub field: FieldPB,
  212. #[pb(index = 3)]
  213. pub type_option_data: Vec<u8>,
  214. }
  215. /// Collection of the [FieldPB]
  216. #[derive(Debug, Default, ProtoBuf)]
  217. pub struct RepeatedFieldPB {
  218. #[pb(index = 1)]
  219. pub items: Vec<FieldPB>,
  220. }
  221. impl std::ops::Deref for RepeatedFieldPB {
  222. type Target = Vec<FieldPB>;
  223. fn deref(&self) -> &Self::Target {
  224. &self.items
  225. }
  226. }
  227. impl std::ops::DerefMut for RepeatedFieldPB {
  228. fn deref_mut(&mut self) -> &mut Self::Target {
  229. &mut self.items
  230. }
  231. }
  232. impl std::convert::From<Vec<FieldPB>> for RepeatedFieldPB {
  233. fn from(items: Vec<FieldPB>) -> Self {
  234. Self { items }
  235. }
  236. }
  237. #[derive(Debug, Clone, Default, ProtoBuf)]
  238. pub struct RepeatedFieldIdPB {
  239. #[pb(index = 1)]
  240. pub items: Vec<FieldIdPB>,
  241. }
  242. impl std::ops::Deref for RepeatedFieldIdPB {
  243. type Target = Vec<FieldIdPB>;
  244. fn deref(&self) -> &Self::Target {
  245. &self.items
  246. }
  247. }
  248. impl std::convert::From<Vec<FieldIdPB>> for RepeatedFieldIdPB {
  249. fn from(items: Vec<FieldIdPB>) -> Self {
  250. RepeatedFieldIdPB { items }
  251. }
  252. }
  253. impl std::convert::From<String> for RepeatedFieldIdPB {
  254. fn from(s: String) -> Self {
  255. RepeatedFieldIdPB {
  256. items: vec![FieldIdPB::from(s)],
  257. }
  258. }
  259. }
  260. /// [TypeOptionChangesetPB] is used to update the type-option data.
  261. #[derive(ProtoBuf, Default)]
  262. pub struct TypeOptionChangesetPB {
  263. #[pb(index = 1)]
  264. pub view_id: String,
  265. #[pb(index = 2)]
  266. pub field_id: String,
  267. /// Check out [TypeOptionPB] for more details.
  268. #[pb(index = 3)]
  269. pub type_option_data: Vec<u8>,
  270. }
  271. #[derive(Clone)]
  272. pub struct TypeOptionChangesetParams {
  273. pub view_id: String,
  274. pub field_id: String,
  275. pub type_option_data: Vec<u8>,
  276. }
  277. impl TryInto<TypeOptionChangesetParams> for TypeOptionChangesetPB {
  278. type Error = ErrorCode;
  279. fn try_into(self) -> Result<TypeOptionChangesetParams, Self::Error> {
  280. let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::DatabaseIdIsEmpty)?;
  281. let _ = NotEmptyStr::parse(self.field_id.clone()).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
  282. Ok(TypeOptionChangesetParams {
  283. view_id: view_id.0,
  284. field_id: self.field_id,
  285. type_option_data: self.type_option_data,
  286. })
  287. }
  288. }
  289. #[derive(ProtoBuf, Default)]
  290. pub struct GetFieldPayloadPB {
  291. #[pb(index = 1)]
  292. pub view_id: String,
  293. #[pb(index = 2, one_of)]
  294. pub field_ids: Option<RepeatedFieldIdPB>,
  295. }
  296. pub struct GetFieldParams {
  297. pub view_id: String,
  298. pub field_ids: Option<Vec<String>>,
  299. }
  300. impl TryInto<GetFieldParams> for GetFieldPayloadPB {
  301. type Error = ErrorCode;
  302. fn try_into(self) -> Result<GetFieldParams, Self::Error> {
  303. let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::DatabaseIdIsEmpty)?;
  304. let field_ids = self.field_ids.map(|repeated| {
  305. repeated
  306. .items
  307. .into_iter()
  308. .map(|item| item.field_id)
  309. .collect::<Vec<String>>()
  310. });
  311. Ok(GetFieldParams {
  312. view_id: view_id.0,
  313. field_ids,
  314. })
  315. }
  316. }
  317. /// [FieldChangesetPB] is used to modify the corresponding field. It defines which properties of
  318. /// the field can be modified.
  319. ///
  320. /// Pass in None if you don't want to modify a property
  321. /// Pass in Some(Value) if you want to modify a property
  322. ///
  323. #[derive(Debug, Clone, Default, ProtoBuf)]
  324. pub struct FieldChangesetPB {
  325. #[pb(index = 1)]
  326. pub field_id: String,
  327. #[pb(index = 2)]
  328. pub view_id: String,
  329. #[pb(index = 3, one_of)]
  330. pub name: Option<String>,
  331. #[pb(index = 4, one_of)]
  332. pub desc: Option<String>,
  333. #[pb(index = 5, one_of)]
  334. pub frozen: Option<bool>,
  335. #[pb(index = 6, one_of)]
  336. pub visibility: Option<bool>,
  337. #[pb(index = 7, one_of)]
  338. pub width: Option<i32>,
  339. }
  340. impl TryInto<FieldChangesetParams> for FieldChangesetPB {
  341. type Error = ErrorCode;
  342. fn try_into(self) -> Result<FieldChangesetParams, Self::Error> {
  343. let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::DatabaseIdIsEmpty)?;
  344. let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
  345. // if let Some(type_option_data) = self.type_option_data.as_ref() {
  346. // if type_option_data.is_empty() {
  347. // return Err(ErrorCode::TypeOptionDataIsEmpty);
  348. // }
  349. // }
  350. Ok(FieldChangesetParams {
  351. field_id: field_id.0,
  352. view_id: view_id.0,
  353. name: self.name,
  354. desc: self.desc,
  355. frozen: self.frozen,
  356. visibility: self.visibility,
  357. width: self.width,
  358. // type_option_data: self.type_option_data,
  359. })
  360. }
  361. }
  362. #[derive(Debug, Clone, Default)]
  363. pub struct FieldChangesetParams {
  364. pub field_id: String,
  365. pub view_id: String,
  366. pub name: Option<String>,
  367. pub desc: Option<String>,
  368. pub frozen: Option<bool>,
  369. pub visibility: Option<bool>,
  370. pub width: Option<i32>,
  371. // pub type_option_data: Option<Vec<u8>>,
  372. }
  373. /// Certain field types have user-defined options such as color, date format, number format,
  374. /// or a list of values for a multi-select list. These options are defined within a specialization
  375. /// of the FieldTypeOption class.
  376. ///
  377. /// You could check [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid#fieldtype)
  378. /// for more information.
  379. ///
  380. /// The order of the enum can't be changed. If you want to add a new type,
  381. /// it would be better to append it to the end of the list.
  382. #[derive(
  383. Debug,
  384. Clone,
  385. PartialEq,
  386. Hash,
  387. Eq,
  388. ProtoBuf_Enum,
  389. EnumCountMacro,
  390. EnumIter,
  391. Serialize_repr,
  392. Deserialize_repr,
  393. )]
  394. #[repr(u8)]
  395. #[derive(Default)]
  396. pub enum FieldType {
  397. #[default]
  398. RichText = 0,
  399. Number = 1,
  400. DateTime = 2,
  401. SingleSelect = 3,
  402. MultiSelect = 4,
  403. Checkbox = 5,
  404. URL = 6,
  405. Checklist = 7,
  406. LastEditedTime = 8,
  407. CreatedTime = 9,
  408. }
  409. impl Display for FieldType {
  410. fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  411. let value: i64 = self.clone().into();
  412. f.write_fmt(format_args!("{}", value))
  413. }
  414. }
  415. impl AsRef<FieldType> for FieldType {
  416. fn as_ref(&self) -> &FieldType {
  417. self
  418. }
  419. }
  420. impl From<&FieldType> for FieldType {
  421. fn from(field_type: &FieldType) -> Self {
  422. field_type.clone()
  423. }
  424. }
  425. impl FieldType {
  426. pub fn value(&self) -> i64 {
  427. self.clone().into()
  428. }
  429. pub fn default_cell_width(&self) -> i32 {
  430. match self {
  431. FieldType::DateTime | FieldType::LastEditedTime | FieldType::CreatedTime => 180,
  432. _ => 150,
  433. }
  434. }
  435. pub fn default_name(&self) -> String {
  436. let s = match self {
  437. FieldType::RichText => "Text",
  438. FieldType::Number => "Number",
  439. FieldType::DateTime => "Date",
  440. FieldType::SingleSelect => "Single Select",
  441. FieldType::MultiSelect => "Multi Select",
  442. FieldType::Checkbox => "Checkbox",
  443. FieldType::URL => "URL",
  444. FieldType::Checklist => "Checklist",
  445. FieldType::LastEditedTime => "Last edited time",
  446. FieldType::CreatedTime => "Created time",
  447. };
  448. s.to_string()
  449. }
  450. pub fn is_number(&self) -> bool {
  451. matches!(self, FieldType::Number)
  452. }
  453. pub fn is_text(&self) -> bool {
  454. matches!(self, FieldType::RichText)
  455. }
  456. pub fn is_checkbox(&self) -> bool {
  457. matches!(self, FieldType::Checkbox)
  458. }
  459. pub fn is_date(&self) -> bool {
  460. matches!(self, FieldType::DateTime)
  461. || matches!(self, FieldType::LastEditedTime)
  462. || matches!(self, FieldType::CreatedTime)
  463. }
  464. pub fn is_single_select(&self) -> bool {
  465. matches!(self, FieldType::SingleSelect)
  466. }
  467. pub fn is_multi_select(&self) -> bool {
  468. matches!(self, FieldType::MultiSelect)
  469. }
  470. pub fn is_last_edited_time(&self) -> bool {
  471. matches!(self, FieldType::LastEditedTime)
  472. }
  473. pub fn is_created_time(&self) -> bool {
  474. matches!(self, FieldType::CreatedTime)
  475. }
  476. pub fn is_url(&self) -> bool {
  477. matches!(self, FieldType::URL)
  478. }
  479. pub fn is_select_option(&self) -> bool {
  480. self.is_single_select() || self.is_multi_select()
  481. }
  482. pub fn is_checklist(&self) -> bool {
  483. matches!(self, FieldType::Checklist)
  484. }
  485. pub fn can_be_group(&self) -> bool {
  486. self.is_select_option() || self.is_checkbox() || self.is_url()
  487. }
  488. pub fn is_auto_update(&self) -> bool {
  489. self.is_last_edited_time()
  490. }
  491. }
  492. impl_into_field_type!(i64);
  493. impl_into_field_type!(u8);
  494. impl From<FieldType> for i64 {
  495. fn from(ty: FieldType) -> Self {
  496. (ty as u8) as i64
  497. }
  498. }
  499. impl From<&FieldType> for i64 {
  500. fn from(ty: &FieldType) -> Self {
  501. i64::from(ty.clone())
  502. }
  503. }
  504. #[derive(Debug, Clone, Default, ProtoBuf)]
  505. pub struct DuplicateFieldPayloadPB {
  506. #[pb(index = 1)]
  507. pub field_id: String,
  508. #[pb(index = 2)]
  509. pub view_id: String,
  510. }
  511. // #[derive(Debug, Clone, Default, ProtoBuf)]
  512. // pub struct GridFieldIdentifierPayloadPB {
  513. // #[pb(index = 1)]
  514. // pub field_id: String,
  515. //
  516. // #[pb(index = 2)]
  517. // pub view_id: String,
  518. // }
  519. impl TryInto<FieldIdParams> for DuplicateFieldPayloadPB {
  520. type Error = ErrorCode;
  521. fn try_into(self) -> Result<FieldIdParams, Self::Error> {
  522. let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::DatabaseIdIsEmpty)?;
  523. let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
  524. Ok(FieldIdParams {
  525. view_id: view_id.0,
  526. field_id: field_id.0,
  527. })
  528. }
  529. }
  530. #[derive(Debug, Clone, Default, ProtoBuf)]
  531. pub struct DeleteFieldPayloadPB {
  532. #[pb(index = 1)]
  533. pub field_id: String,
  534. #[pb(index = 2)]
  535. pub view_id: String,
  536. }
  537. impl TryInto<FieldIdParams> for DeleteFieldPayloadPB {
  538. type Error = ErrorCode;
  539. fn try_into(self) -> Result<FieldIdParams, Self::Error> {
  540. let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::DatabaseIdIsEmpty)?;
  541. let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
  542. Ok(FieldIdParams {
  543. view_id: view_id.0,
  544. field_id: field_id.0,
  545. })
  546. }
  547. }
  548. pub struct FieldIdParams {
  549. pub field_id: String,
  550. pub view_id: String,
  551. }