field_entities.rs 17 KB

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