1mod table_cell;
2
3use crate::blobs::EncodedBlob;
4use crate::formatting::{Formatting, RichText};
5use crate::query_data::{has_query_data, set_query_field, unset_query_field};
6#[cfg(feature = "fp-bindgen")]
7use fp_bindgen::prelude::Serializable;
8use serde::{Deserialize, Serialize};
9pub use table_cell::*;
10use typed_builder::TypedBuilder;
11
12#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
14#[cfg_attr(
15 feature = "fp-bindgen",
16 derive(Serializable),
17 fp(rust_module = "fiberplane_models::notebooks")
18)]
19#[non_exhaustive]
20#[serde(tag = "type", rename_all = "snake_case")]
21pub enum Cell {
22 Checkbox(CheckboxCell),
23 Code(CodeCell),
24 Discussion(DiscussionCell),
25 Divider(DividerCell),
26 Graph(GraphCell),
27 Heading(HeadingCell),
28 Image(ImageCell),
29 ListItem(ListItemCell),
30 Log(LogCell),
31 Provider(ProviderCell),
32 Table(TableCell),
33 Timeline(TimelineCell),
34 Text(TextCell),
35}
36
37impl Cell {
38 pub fn content(&self) -> Option<&str> {
40 match self {
41 Cell::Checkbox(cell) => Some(&cell.content),
42 Cell::Code(cell) => Some(&cell.content),
43 Cell::Discussion(_) => None,
44 Cell::Divider(_) => None,
45 Cell::Graph(_) => None,
46 Cell::Heading(cell) => Some(&cell.content),
47 Cell::Image(_) => None,
48 Cell::ListItem(cell) => Some(&cell.content),
49 Cell::Log(_) => None,
50 Cell::Provider(_) => None,
51 Cell::Table(_) => None,
52 Cell::Text(cell) => Some(&cell.content),
53 Cell::Timeline(_) => None,
54 }
55 }
56
57 pub fn formatting(&self) -> Option<&Formatting> {
59 match self {
60 Cell::Code(_)
61 | Cell::Discussion(_)
62 | Cell::Divider(_)
63 | Cell::Graph(_)
64 | Cell::Image(_)
65 | Cell::Log(_)
66 | Cell::Provider(_)
67 | Cell::Table(_)
68 | Cell::Timeline(_) => None,
69 Cell::Checkbox(cell) => Some(&cell.formatting),
70 Cell::Heading(cell) => Some(&cell.formatting),
71 Cell::ListItem(cell) => Some(&cell.formatting),
72 Cell::Text(cell) => Some(&cell.formatting),
73 }
74 }
75
76 pub fn supports_formatting(&self) -> bool {
77 match self {
78 Cell::Code(_)
79 | Cell::Discussion(_)
80 | Cell::Divider(_)
81 | Cell::Graph(_)
82 | Cell::Image(_)
83 | Cell::Log(_)
84 | Cell::Table(_)
85 | Cell::Timeline(_) => false,
86 Cell::Checkbox(_)
87 | Cell::Heading(_)
88 | Cell::ListItem(_)
89 | Cell::Provider(_)
90 | Cell::Text(_) => true,
91 }
92 }
93
94 pub fn id(&self) -> &str {
96 match self {
97 Cell::Checkbox(cell) => &cell.id,
98 Cell::Code(cell) => &cell.id,
99 Cell::Discussion(cell) => &cell.id,
100 Cell::Divider(cell) => &cell.id,
101 Cell::Graph(cell) => &cell.id,
102 Cell::Heading(cell) => &cell.id,
103 Cell::Image(cell) => &cell.id,
104 Cell::ListItem(cell) => &cell.id,
105 Cell::Log(cell) => &cell.id,
106 Cell::Provider(cell) => &cell.id,
107 Cell::Table(cell) => &cell.id,
108 Cell::Text(cell) => &cell.id,
109 Cell::Timeline(cell) => &cell.id,
110 }
111 }
112
113 pub fn text(&self) -> Option<&str> {
115 self.content()
116 }
117
118 #[must_use]
120 pub fn with_id(&self, id: &str) -> Self {
121 match self {
122 Cell::Checkbox(cell) => Cell::Checkbox(CheckboxCell {
123 id: id.to_owned(),
124 ..cell.clone()
125 }),
126 Cell::Code(cell) => Cell::Code(CodeCell {
127 id: id.to_owned(),
128 ..cell.clone()
129 }),
130 Cell::Discussion(cell) => Cell::Discussion(DiscussionCell {
131 id: id.to_owned(),
132 ..cell.clone()
133 }),
134 Cell::Divider(cell) => Cell::Divider(DividerCell {
135 id: id.to_owned(),
136 ..cell.clone()
137 }),
138 Cell::Graph(cell) => Cell::Graph(GraphCell {
139 id: id.to_owned(),
140 ..cell.clone()
141 }),
142 Cell::Heading(cell) => Cell::Heading(HeadingCell {
143 id: id.to_owned(),
144 ..cell.clone()
145 }),
146 Cell::Image(cell) => Cell::Image(ImageCell {
147 id: id.to_owned(),
148 ..cell.clone()
149 }),
150 Cell::ListItem(cell) => Cell::ListItem(ListItemCell {
151 id: id.to_owned(),
152 ..cell.clone()
153 }),
154 Cell::Log(cell) => Cell::Log(LogCell {
155 id: id.to_owned(),
156 ..cell.clone()
157 }),
158 Cell::Provider(cell) => Cell::Provider(ProviderCell {
159 id: id.to_owned(),
160 ..cell.clone()
161 }),
162 Cell::Table(cell) => Cell::Table(TableCell {
163 id: id.to_owned(),
164 ..cell.clone()
165 }),
166 Cell::Text(cell) => Cell::Text(TextCell {
167 id: id.to_owned(),
168 ..cell.clone()
169 }),
170 Cell::Timeline(cell) => Cell::Timeline(TimelineCell {
171 id: id.to_owned(),
172 ..cell.clone()
173 }),
174 }
175 }
176
177 #[must_use]
180 pub fn with_text(&self, text: impl Into<String>) -> Self {
181 match self {
182 Cell::Checkbox(cell) => Cell::Checkbox(CheckboxCell {
183 id: cell.id.clone(),
184 content: text.into(),
185 formatting: Formatting::default(),
186 ..*cell
187 }),
188 Cell::Code(cell) => Cell::Code(CodeCell {
189 id: cell.id.clone(),
190 content: text.into(),
191 syntax: cell.syntax.clone(),
192 ..*cell
193 }),
194 Cell::Discussion(cell) => Cell::Discussion(cell.clone()),
195 Cell::Divider(cell) => Cell::Divider(cell.clone()),
196 Cell::Graph(cell) => Cell::Graph(cell.clone()),
197 Cell::Heading(cell) => Cell::Heading(HeadingCell {
198 id: cell.id.clone(),
199 content: text.into(),
200 formatting: Formatting::default(),
201 ..*cell
202 }),
203 Cell::Image(cell) => Cell::Image(cell.clone()),
204 Cell::ListItem(cell) => Cell::ListItem(ListItemCell {
205 id: cell.id.clone(),
206 content: text.into(),
207 formatting: Formatting::default(),
208 ..*cell
209 }),
210 Cell::Log(cell) => Cell::Log(cell.clone()),
211 Cell::Provider(cell) => Cell::Provider(cell.clone()),
212 Cell::Table(cell) => Cell::Table(cell.clone()),
213 Cell::Text(cell) => Cell::Text(TextCell {
214 id: cell.id.clone(),
215 content: text.into(),
216 formatting: Formatting::default(),
217 ..*cell
218 }),
219 Cell::Timeline(cell) => Cell::Timeline(cell.clone()),
220 }
221 }
222
223 #[must_use]
229 pub fn with_rich_text(&self, text: impl Into<String>, formatting: Formatting) -> Self {
230 match self {
231 Cell::Checkbox(cell) => Cell::Checkbox(CheckboxCell {
232 id: cell.id.clone(),
233 content: text.into(),
234 formatting,
235 ..*cell
236 }),
237 Cell::Heading(cell) => Cell::Heading(HeadingCell {
238 id: cell.id.clone(),
239 content: text.into(),
240 formatting,
241 ..*cell
242 }),
243 Cell::ListItem(cell) => Cell::ListItem(ListItemCell {
244 id: cell.id.clone(),
245 content: text.into(),
246 formatting,
247 ..*cell
248 }),
249 Cell::Text(cell) => Cell::Text(TextCell {
250 id: cell.id.clone(),
251 content: text.into(),
252 formatting,
253 ..*cell
254 }),
255 Cell::Code(_)
256 | Cell::Discussion(_)
257 | Cell::Divider(_)
258 | Cell::Graph(_)
259 | Cell::Image(_)
260 | Cell::Log(_)
261 | Cell::Provider(_)
262 | Cell::Table(_)
263 | Cell::Timeline(_) => self.with_text(text),
264 }
265 }
266
267 #[must_use]
277 pub fn with_text_for_field<T>(
278 &self,
279 text: T,
280 formatting: Option<Formatting>,
281 field: Option<impl AsRef<str>>,
282 ) -> Self
283 where
284 T: Into<String> + AsRef<str>,
285 {
286 match (self, field) {
287 (Cell::Provider(cell), Some(field)) => {
288 Cell::Provider(cell.with_query_field(field.as_ref(), text))
289 }
290 (Cell::Table(cell), Some(field)) => Cell::Table(cell.with_row_value(
291 field.as_ref(),
292 TableRowValue::Text(RichText {
293 text: text.into(),
294 formatting: formatting.unwrap_or_default(),
295 }),
296 )),
297 (cell, _) => {
298 if let Some(formatting) = formatting {
299 cell.with_rich_text(text, formatting)
300 } else {
301 cell.with_text(text)
302 }
303 }
304 }
305 }
306
307 pub fn id_mut(&mut self) -> &mut String {
308 match self {
309 Cell::Checkbox(cell) => &mut cell.id,
310 Cell::Code(cell) => &mut cell.id,
311 Cell::Discussion(cell) => &mut cell.id,
312 Cell::Divider(cell) => &mut cell.id,
313 Cell::Graph(cell) => &mut cell.id,
314 Cell::Heading(cell) => &mut cell.id,
315 Cell::Image(cell) => &mut cell.id,
316 Cell::ListItem(cell) => &mut cell.id,
317 Cell::Log(cell) => &mut cell.id,
318 Cell::Provider(cell) => &mut cell.id,
319 Cell::Table(cell) => &mut cell.id,
320 Cell::Text(cell) => &mut cell.id,
321 Cell::Timeline(cell) => &mut cell.id,
322 }
323 }
324
325 pub fn formatting_mut(&mut self) -> Option<&mut Formatting> {
328 match self {
329 Cell::Checkbox(cell) => Some(&mut cell.formatting),
330 Cell::Heading(cell) => Some(&mut cell.formatting),
331 Cell::ListItem(cell) => Some(&mut cell.formatting),
332 Cell::Text(cell) => Some(&mut cell.formatting),
333 Cell::Code(_)
334 | Cell::Discussion(_)
335 | Cell::Divider(_)
336 | Cell::Graph(_)
337 | Cell::Image(_)
338 | Cell::Log(_)
339 | Cell::Provider(_)
340 | Cell::Table(_)
341 | Cell::Timeline(_) => None,
342 }
343 }
344
345 pub fn text_mut(&mut self) -> Option<&mut String> {
347 match self {
348 Cell::Checkbox(cell) => Some(&mut cell.content),
349 Cell::Code(cell) => Some(&mut cell.content),
350 Cell::Discussion(_) => None,
351 Cell::Divider(_) => None,
352 Cell::Image(_) => None,
353 Cell::Graph(_) => None,
354 Cell::Heading(cell) => Some(&mut cell.content),
355 Cell::ListItem(cell) => Some(&mut cell.content),
356 Cell::Log(_) => None,
357 Cell::Provider(_) => None,
358 Cell::Table(_) => None,
359 Cell::Text(cell) => Some(&mut cell.content),
360 Cell::Timeline(_) => None,
361 }
362 }
363
364 pub fn type_str(&self) -> &str {
366 match self {
367 Cell::Checkbox(_) => "checkbox",
368 Cell::Code(_) => "code",
369 Cell::Discussion(_) => "discussion",
370 Cell::Divider(_) => "divider",
371 Cell::Graph(_) => "graph",
372 Cell::Heading(_) => "heading",
373 Cell::Image(_) => "image",
374 Cell::ListItem(_) => "list item",
375 Cell::Log(_) => "log",
376 Cell::Provider(cell) => &cell.intent,
377 Cell::Table(_) => "table",
378 Cell::Text(_) => "text",
379 Cell::Timeline(_) => "timeline",
380 }
381 }
382}
383
384#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
385#[cfg_attr(
386 feature = "fp-bindgen",
387 derive(Serializable),
388 fp(rust_module = "fiberplane_models::notebooks")
389)]
390#[non_exhaustive]
391#[serde(rename_all = "camelCase")]
392pub struct CheckboxCell {
393 #[builder(default, setter(into))]
394 pub id: String,
395
396 #[builder(default)]
397 pub checked: bool,
398
399 #[builder(default, setter(into))]
400 pub content: String,
401
402 #[builder(default)]
404 #[serde(default, skip_serializing_if = "Formatting::is_empty")]
405 pub formatting: Formatting,
406
407 #[builder(default, setter(strip_option))]
408 #[serde(default, skip_serializing_if = "Option::is_none")]
409 pub level: Option<u8>,
410
411 #[builder(default, setter(strip_option))]
412 #[serde(default, skip_serializing_if = "Option::is_none")]
413 pub read_only: Option<bool>,
414}
415
416#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
417#[cfg_attr(
418 feature = "fp-bindgen",
419 derive(Serializable),
420 fp(rust_module = "fiberplane_models::notebooks")
421)]
422#[non_exhaustive]
423#[serde(rename_all = "camelCase")]
424pub struct CodeCell {
425 #[builder(default, setter(into))]
426 pub id: String,
427
428 #[builder(default, setter(into))]
429 pub content: String,
430
431 #[builder(default, setter(strip_option))]
432 #[serde(default, skip_serializing_if = "Option::is_none")]
433 pub read_only: Option<bool>,
434
435 #[builder(default, setter(into, strip_option))]
437 #[serde(default, skip_serializing_if = "Option::is_none")]
438 pub syntax: Option<String>,
439}
440
441#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
442#[cfg_attr(
443 feature = "fp-bindgen",
444 derive(Serializable),
445 fp(rust_module = "fiberplane_models::notebooks")
446)]
447#[non_exhaustive]
448#[serde(rename_all = "camelCase")]
449pub struct DividerCell {
450 #[builder(default, setter(into))]
451 pub id: String,
452
453 #[builder(default, setter(strip_option))]
454 #[serde(default, skip_serializing_if = "Option::is_none")]
455 pub read_only: Option<bool>,
456}
457
458#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
459#[cfg_attr(
460 feature = "fp-bindgen",
461 derive(Serializable),
462 fp(rust_module = "fiberplane_models::notebooks")
463)]
464#[non_exhaustive]
465#[serde(rename_all = "camelCase")]
466pub struct GraphCell {
467 #[builder(default, setter(into))]
468 pub id: String,
469
470 #[builder(default)]
472 #[serde(default, skip_serializing_if = "Vec::is_empty")]
473 pub data_links: Vec<String>,
474
475 pub graph_type: GraphType,
476
477 #[builder(default, setter(strip_option))]
478 #[serde(default, skip_serializing_if = "Option::is_none")]
479 pub read_only: Option<bool>,
480
481 #[builder(default)]
482 pub stacking_type: StackingType,
483}
484
485#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
486#[cfg_attr(
487 feature = "fp-bindgen",
488 derive(Serializable),
489 fp(rust_module = "fiberplane_models::notebooks")
490)]
491#[non_exhaustive]
492#[serde(rename_all = "camelCase")]
493pub struct HeadingCell {
494 #[builder(default, setter(into))]
495 pub id: String,
496
497 pub heading_type: HeadingType,
498
499 #[builder(default, setter(into))]
500 pub content: String,
501
502 #[builder(default)]
504 #[serde(default, skip_serializing_if = "Formatting::is_empty")]
505 pub formatting: Formatting,
506
507 #[builder(default, setter(strip_option))]
508 #[serde(skip_serializing_if = "Option::is_none")]
509 pub read_only: Option<bool>,
510}
511
512#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
513#[cfg_attr(
514 feature = "fp-bindgen",
515 derive(Serializable),
516 fp(rust_module = "fiberplane_models::notebooks")
517)]
518#[non_exhaustive]
519#[serde(rename_all = "camelCase")]
520pub struct LogCell {
521 #[builder(default, setter(into))]
522 pub id: String,
523
524 #[builder(default)]
526 #[serde(default, skip_serializing_if = "Vec::is_empty")]
527 pub data_links: Vec<String>,
528
529 #[builder(default, setter(strip_option))]
530 #[serde(default, skip_serializing_if = "Option::is_none")]
531 pub read_only: Option<bool>,
532
533 #[builder(default, setter(strip_option))]
534 #[serde(default, skip_serializing_if = "Option::is_none")]
535 pub display_fields: Option<Vec<String>>,
536
537 #[builder(default, setter(strip_option))]
538 #[serde(default, skip_serializing_if = "Option::is_none")]
539 pub hide_similar_values: Option<bool>,
540
541 #[builder(default, setter(strip_option))]
542 #[serde(default, skip_serializing_if = "Option::is_none")]
543 pub expanded_indices: Option<Vec<LogRecordIndex>>,
544
545 #[builder(default, setter(strip_option))]
546 #[serde(default, skip_serializing_if = "Option::is_none")]
547 pub visibility_filter: Option<LogVisibilityFilter>,
548
549 #[builder(default, setter(strip_option))]
550 #[serde(default, skip_serializing_if = "Option::is_none")]
551 pub selected_indices: Option<Vec<LogRecordIndex>>,
552
553 #[builder(default, setter(strip_option))]
554 #[serde(default, skip_serializing_if = "Option::is_none")]
555 pub highlighted_indices: Option<Vec<LogRecordIndex>>,
556}
557
558#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
559#[cfg_attr(
560 feature = "fp-bindgen",
561 derive(Serializable),
562 fp(rust_module = "fiberplane_models::notebooks")
563)]
564#[non_exhaustive]
565#[serde(rename_all = "snake_case")]
566pub enum LogVisibilityFilter {
567 All,
568 Selected,
569 Highlighted,
570}
571
572#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, TypedBuilder)]
575#[cfg_attr(
576 feature = "fp-bindgen",
577 derive(Serializable),
578 fp(rust_module = "fiberplane_models::notebooks")
579)]
580#[non_exhaustive]
581#[serde(rename_all = "camelCase")]
582pub struct LogRecordIndex {
583 pub link_index: u8,
585
586 pub record_index: u32,
588}
589
590#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
591#[cfg_attr(
592 feature = "fp-bindgen",
593 derive(Serializable),
594 fp(rust_module = "fiberplane_models::notebooks")
595)]
596#[non_exhaustive]
597#[serde(rename_all = "camelCase")]
598pub struct ListItemCell {
599 #[builder(default, setter(into))]
600 pub id: String,
601
602 #[builder(default, setter(into))]
603 pub content: String,
604
605 #[builder(default)]
607 #[serde(default, skip_serializing_if = "Formatting::is_empty")]
608 pub formatting: Formatting,
609
610 #[builder(default)]
611 pub list_type: ListType,
612
613 #[builder(default, setter(strip_option))]
614 #[serde(skip_serializing_if = "Option::is_none")]
615 pub level: Option<u8>,
616
617 #[builder(default, setter(strip_option))]
618 #[serde(skip_serializing_if = "Option::is_none")]
619 pub read_only: Option<bool>,
620
621 #[builder(default, setter(strip_option))]
622 #[serde(skip_serializing_if = "Option::is_none")]
623 pub start_number: Option<u16>,
624}
625
626#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize, TypedBuilder)]
627#[cfg_attr(
628 feature = "fp-bindgen",
629 derive(Serializable),
630 fp(rust_module = "fiberplane_models::notebooks")
631)]
632#[non_exhaustive]
633#[serde(rename_all = "camelCase")]
634pub struct ProviderCell {
635 #[builder(default, setter(into))]
636 pub id: String,
637
638 #[builder(default, setter(into))]
642 pub intent: String,
643
644 #[builder(default, setter(into, strip_option))]
651 #[serde(default, skip_serializing_if = "Option::is_none")]
652 pub query_data: Option<String>,
653
654 #[builder(default, setter(strip_option))]
656 #[serde(default, skip_serializing_if = "Option::is_none")]
657 pub response: Option<EncodedBlob>,
658
659 #[builder(default, setter(strip_option))]
661 #[serde(default, skip_serializing_if = "Option::is_none")]
662 pub output: Option<Vec<Cell>>,
663
664 #[builder(default, setter(strip_option))]
665 #[serde(default, skip_serializing_if = "Option::is_none")]
666 pub read_only: Option<bool>,
667}
668
669impl ProviderCell {
670 pub fn with_query_field(&self, field_name: impl AsRef<str>, value: impl AsRef<str>) -> Self {
675 let query_data = self.query_data.as_deref().unwrap_or_default();
676 let query_data = if value.as_ref().is_empty() {
677 unset_query_field(query_data, field_name)
678 } else {
679 set_query_field(query_data, field_name, value)
680 };
681 Self {
682 query_data: if has_query_data(&query_data) {
683 Some(query_data)
684 } else {
685 None
686 },
687 ..self.clone()
688 }
689 }
690}
691
692#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
693#[cfg_attr(
694 feature = "fp-bindgen",
695 derive(Serializable),
696 fp(rust_module = "fiberplane_models::notebooks")
697)]
698#[non_exhaustive]
699#[serde(rename_all = "camelCase")]
700pub struct TextCell {
701 #[builder(default, setter(into))]
702 pub id: String,
703
704 #[builder(default, setter(into))]
705 pub content: String,
706
707 #[builder(default)]
709 #[serde(default, skip_serializing_if = "Formatting::is_empty")]
710 pub formatting: Formatting,
711
712 #[builder(default, setter(strip_option))]
713 #[serde(skip_serializing_if = "Option::is_none")]
714 pub read_only: Option<bool>,
715}
716
717#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
718#[cfg_attr(
719 feature = "fp-bindgen",
720 derive(Serializable),
721 fp(rust_module = "fiberplane_models::notebooks")
722)]
723#[serde(rename_all = "camelCase")]
724pub struct TimelineCell {
725 #[builder(default, setter(into))]
726 pub id: String,
727
728 #[builder(default)]
730 #[serde(default, skip_serializing_if = "Vec::is_empty")]
731 pub data_links: Vec<String>,
732
733 #[builder(default, setter(strip_option))]
734 #[serde(skip_serializing_if = "Option::is_none")]
735 pub read_only: Option<bool>,
736}
737
738#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize, TypedBuilder)]
739#[cfg_attr(
740 feature = "fp-bindgen",
741 derive(Serializable),
742 fp(rust_module = "fiberplane_models::notebooks")
743)]
744#[non_exhaustive]
745#[serde(rename_all = "camelCase")]
746pub struct ImageCell {
747 #[builder(default, setter(into))]
748 pub id: String,
749
750 #[builder(default, setter(into, strip_option))]
752 #[serde(skip_serializing_if = "Option::is_none")]
753 pub file_id: Option<String>,
754
755 #[builder(default, setter(strip_option))]
760 #[serde(skip_serializing_if = "Option::is_none")]
761 pub progress: Option<f64>,
762
763 #[builder(default, setter(strip_option))]
764 #[serde(skip_serializing_if = "Option::is_none")]
765 pub read_only: Option<bool>,
766
767 #[builder(default, setter(strip_option))]
768 #[serde(skip_serializing_if = "Option::is_none")]
769 pub width: Option<i32>,
770
771 #[builder(default, setter(strip_option))]
772 #[serde(skip_serializing_if = "Option::is_none")]
773 pub height: Option<i32>,
774
775 #[builder(default, setter(into, strip_option))]
777 #[serde(skip_serializing_if = "Option::is_none")]
778 pub preview: Option<String>,
779
780 #[builder(default, setter(into, strip_option))]
784 #[serde(skip_serializing_if = "Option::is_none")]
785 pub url: Option<String>,
786}
787
788#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize, TypedBuilder)]
789#[cfg_attr(
790 feature = "fp-bindgen",
791 derive(Serializable),
792 fp(rust_module = "fiberplane_models::notebooks")
793)]
794#[non_exhaustive]
795#[serde(rename_all = "camelCase")]
796pub struct DiscussionCell {
797 #[builder(default, setter(into))]
798 pub id: String,
799
800 #[builder(default, setter(into))]
801 pub thread_id: String,
802
803 #[builder(default, setter(strip_option))]
804 #[serde(default, skip_serializing_if = "Option::is_none")]
805 pub read_only: Option<bool>,
806}
807
808#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize)]
809#[cfg_attr(
810 feature = "fp-bindgen",
811 derive(Serializable),
812 fp(rust_module = "fiberplane_models::notebooks")
813)]
814#[non_exhaustive]
815#[serde(rename_all = "snake_case")]
816pub enum GraphType {
817 Bar,
818 Line,
819}
820
821#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
822#[cfg_attr(
823 feature = "fp-bindgen",
824 derive(Serializable),
825 fp(rust_module = "fiberplane_models::notebooks")
826)]
827#[non_exhaustive]
828#[serde(rename_all = "snake_case")]
829pub enum StackingType {
830 #[default]
831 None,
832 Stacked,
833 Percentage,
834}
835
836#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
837#[cfg_attr(
838 feature = "fp-bindgen",
839 derive(Serializable),
840 fp(rust_module = "fiberplane_models::notebooks")
841)]
842#[non_exhaustive]
843#[serde(rename_all = "snake_case")]
844pub enum HeadingType {
845 #[default]
846 H1,
847 H2,
848 H3,
849}
850
851#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
852#[cfg_attr(
853 feature = "fp-bindgen",
854 derive(Serializable),
855 fp(rust_module = "fiberplane_models::notebooks")
856)]
857#[non_exhaustive]
858#[serde(rename_all = "snake_case")]
859pub enum ListType {
860 Ordered,
861 #[default]
862 Unordered,
863}