1use crate::data_sources::SelectedDataSource;
2use crate::formatting::Formatting;
3use crate::notebooks::{Cell, FrontMatter, Label};
4use crate::timestamps::TimeRange;
5#[cfg(feature = "fp-bindgen")]
6use fp_bindgen::prelude::*;
7use serde::{Deserialize, Serialize};
8use typed_builder::TypedBuilder;
9
10#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
18#[cfg_attr(
19 feature = "fp-bindgen",
20 derive(Serializable),
21 fp(rust_module = "fiberplane_models::notebooks::operations")
22)]
23#[non_exhaustive]
24#[serde(tag = "type", rename_all = "snake_case")]
25pub enum Operation {
26 MoveCells(MoveCellsOperation),
27 ReplaceCells(ReplaceCellsOperation),
28 ReplaceText(ReplaceTextOperation),
29 UpdateNotebookTimeRange(UpdateNotebookTimeRangeOperation),
30 UpdateNotebookTitle(UpdateNotebookTitleOperation),
31 SetSelectedDataSource(SetSelectedDataSourceOperation),
32 AddLabel(AddLabelOperation),
33 ReplaceLabel(ReplaceLabelOperation),
34 RemoveLabel(RemoveLabelOperation),
35 UpdateFrontMatter(UpdateFrontMatterOperation),
36 ClearFrontMatter(ClearFrontMatterOperation),
37}
38
39#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
41#[cfg_attr(
42 feature = "fp-bindgen",
43 derive(Serializable),
44 fp(rust_module = "fiberplane_models::notebooks::operations")
45)]
46#[non_exhaustive]
47#[serde(rename_all = "camelCase")]
48pub struct MoveCellsOperation {
49 pub cell_ids: Vec<String>,
53
54 pub from_index: u32,
56
57 pub to_index: u32,
59}
60
61#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize, TypedBuilder)]
72#[cfg_attr(
73 feature = "fp-bindgen",
74 derive(Serializable),
75 fp(rust_module = "fiberplane_models::notebooks::operations")
76)]
77#[non_exhaustive]
78#[serde(rename_all = "camelCase")]
79pub struct ReplaceCellsOperation {
80 #[builder(default)]
90 #[serde(default, skip_serializing_if = "Vec::is_empty")]
91 pub new_cells: Vec<CellWithIndex>,
92
93 #[builder(default)]
103 #[serde(default, skip_serializing_if = "Vec::is_empty")]
104 pub old_cells: Vec<CellWithIndex>,
105
106 #[builder(default)]
115 #[serde(default, skip_serializing_if = "Option::is_none")]
116 pub split_offset: Option<u32>,
117
118 #[builder(default)]
127 #[serde(default, skip_serializing_if = "Option::is_none")]
128 pub merge_offset: Option<u32>,
129
130 #[builder(default)]
141 #[serde(default, skip_serializing_if = "Vec::is_empty")]
142 pub new_referencing_cells: Vec<CellWithIndex>,
143
144 #[builder(default)]
155 #[serde(default, skip_serializing_if = "Vec::is_empty")]
156 pub old_referencing_cells: Vec<CellWithIndex>,
157}
158
159impl ReplaceCellsOperation {
160 pub fn all_newly_inserted_cells(&self) -> impl Iterator<Item = &CellWithIndex> {
163 self.newly_inserted_cells()
164 .chain(self.newly_inserted_referencing_cells())
165 }
166
167 pub fn all_old_cells(&self) -> impl Iterator<Item = &CellWithIndex> {
170 self.old_cells
171 .iter()
172 .chain(self.old_referencing_cells.iter())
173 }
174
175 pub fn all_old_removed_cells(&self) -> impl Iterator<Item = &CellWithIndex> {
178 self.old_removed_cells()
179 .chain(self.old_removed_referencing_cells())
180 }
181
182 pub fn newly_inserted_cells(&self) -> impl Iterator<Item = &CellWithIndex> {
184 self.new_cells.iter().filter(move |new_cell| {
185 !self
186 .old_cells
187 .iter()
188 .any(|old_cell| old_cell.id() == new_cell.id())
189 })
190 }
191
192 pub fn newly_inserted_referencing_cells(&self) -> impl Iterator<Item = &CellWithIndex> {
194 self.new_referencing_cells.iter().filter(move |new_cell| {
195 !self
196 .old_referencing_cells
197 .iter()
198 .any(|old_cell| old_cell.id() == new_cell.id())
199 })
200 }
201
202 pub fn old_removed_cells(&self) -> impl Iterator<Item = &CellWithIndex> {
204 self.old_cells.iter().filter(move |old_cell| {
205 !self
206 .new_cells
207 .iter()
208 .any(|new_cell| new_cell.id() == old_cell.id())
209 })
210 }
211
212 pub fn old_removed_referencing_cells(&self) -> impl Iterator<Item = &CellWithIndex> {
214 self.old_referencing_cells.iter().filter(move |old_cell| {
215 !self
216 .new_referencing_cells
217 .iter()
218 .any(|new_cell| new_cell.id() == old_cell.id())
219 })
220 }
221}
222
223#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
225#[cfg_attr(
226 feature = "fp-bindgen",
227 derive(Serializable),
228 fp(rust_module = "fiberplane_models::notebooks::operations")
229)]
230#[non_exhaustive]
231#[serde(rename_all = "camelCase")]
232pub struct ReplaceTextOperation {
233 #[builder(setter(into))]
235 pub cell_id: String,
236
237 #[builder(default, setter(into))]
239 pub field: Option<String>,
240
241 pub offset: u32,
246
247 #[builder(default, setter(into))]
249 pub new_text: String,
250
251 #[builder(default)]
255 #[serde(skip_serializing_if = "Option::is_none")]
256 pub new_formatting: Option<Formatting>,
257
258 #[builder(default, setter(into))]
260 pub old_text: String,
261
262 #[builder(default)]
269 #[serde(skip_serializing_if = "Option::is_none")]
270 pub old_formatting: Option<Formatting>,
271}
272
273#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
275#[cfg_attr(
276 feature = "fp-bindgen",
277 derive(Serializable),
278 fp(rust_module = "fiberplane_models::notebooks::operations")
279)]
280#[non_exhaustive]
281#[serde(rename_all = "camelCase")]
282pub struct UpdateNotebookTimeRangeOperation {
283 pub old_time_range: TimeRange,
284 pub time_range: TimeRange,
285}
286
287#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
289#[cfg_attr(
290 feature = "fp-bindgen",
291 derive(Serializable),
292 fp(rust_module = "fiberplane_models::notebooks::operations")
293)]
294#[non_exhaustive]
295#[serde(rename_all = "camelCase")]
296pub struct UpdateNotebookTitleOperation {
297 pub old_title: String,
298 pub title: String,
299}
300
301#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
302#[cfg_attr(
303 feature = "fp-bindgen",
304 derive(Serializable),
305 fp(rust_module = "fiberplane_models::notebooks::operations")
306)]
307#[non_exhaustive]
308#[serde(rename_all = "camelCase")]
309pub struct SetSelectedDataSourceOperation {
310 #[builder(setter(into))]
311 pub provider_type: String,
312 #[builder(default)]
313 #[serde(default, skip_serializing_if = "Option::is_none")]
314 pub old_selected_data_source: Option<SelectedDataSource>,
315 #[builder(default)]
316 #[serde(default, skip_serializing_if = "Option::is_none")]
317 pub new_selected_data_source: Option<SelectedDataSource>,
318}
319
320#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, TypedBuilder)]
321#[cfg_attr(
322 feature = "fp-bindgen",
323 derive(Serializable),
324 fp(rust_module = "fiberplane_models::notebooks::operations")
325)]
326#[non_exhaustive]
327#[serde(rename_all = "camelCase")]
328pub struct CellWithIndex {
329 pub cell: Cell,
330 pub index: u32,
331}
332
333impl CellWithIndex {
334 pub fn new(cell: Cell, index: u32) -> CellWithIndex {
335 CellWithIndex { cell, index }
336 }
337
338 pub fn formatting(&self) -> Option<&Formatting> {
339 self.cell.formatting()
340 }
341
342 pub fn id(&self) -> &str {
343 self.cell.id()
344 }
345
346 pub fn text(&self) -> Option<&str> {
347 self.cell.text()
348 }
349}
350
351#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
353#[cfg_attr(
354 feature = "fp-bindgen",
355 derive(Serializable),
356 fp(rust_module = "fiberplane_models::notebooks::operations")
357)]
358#[non_exhaustive]
359#[serde(rename_all = "camelCase")]
360pub struct AddLabelOperation {
361 pub label: Label,
363}
364
365#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
367#[cfg_attr(
368 feature = "fp-bindgen",
369 derive(Serializable),
370 fp(rust_module = "fiberplane_models::notebooks::operations")
371)]
372#[non_exhaustive]
373#[serde(rename_all = "camelCase")]
374pub struct ReplaceLabelOperation {
375 pub old_label: Label,
377
378 pub new_label: Label,
380}
381
382#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
384#[cfg_attr(
385 feature = "fp-bindgen",
386 derive(Serializable),
387 fp(rust_module = "fiberplane_models::notebooks::operations")
388)]
389#[non_exhaustive]
390#[serde(rename_all = "camelCase")]
391pub struct RemoveLabelOperation {
392 pub label: Label,
393}
394
395#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
397#[cfg_attr(
398 feature = "fp-bindgen",
399 derive(Serializable),
400 fp(rust_module = "fiberplane_models::notebooks::operations")
401)]
402#[non_exhaustive]
403#[serde(rename_all = "camelCase")]
404pub struct UpdateFrontMatterOperation {
405 pub old_front_matter: FrontMatter,
406 pub new_front_matter: FrontMatter,
407}
408
409#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
411#[cfg_attr(
412 feature = "fp-bindgen",
413 derive(Serializable),
414 fp(rust_module = "fiberplane_models::notebooks::operations")
415)]
416#[non_exhaustive]
417#[serde(rename_all = "camelCase")]
418pub struct ClearFrontMatterOperation {
419 pub front_matter: FrontMatter,
420}
421
422#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
423#[cfg_attr(
424 feature = "fp-bindgen",
425 derive(Serializable),
426 fp(rust_module = "fiberplane_models::notebooks::operations")
427)]
428#[non_exhaustive]
429#[serde(rename_all = "camelCase")]
430pub struct CellAppendText {
431 #[builder(setter(into))]
432 pub content: String,
433 #[builder(default)]
434 #[serde(default)]
435 pub formatting: Formatting,
436}
437
438#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
439#[cfg_attr(
440 feature = "fp-bindgen",
441 derive(Serializable),
442 fp(rust_module = "fiberplane_models::notebooks::operations")
443)]
444#[non_exhaustive]
445#[serde(rename_all = "camelCase")]
446pub struct CellReplaceText {
447 pub offset: u32,
452
453 #[builder(setter(into))]
455 pub new_text: String,
456
457 #[builder(default, setter(into))]
461 #[serde(skip_serializing_if = "Option::is_none")]
462 pub new_formatting: Option<Formatting>,
463
464 #[builder(setter(into))]
466 pub old_text: String,
467
468 #[builder(default, setter(into))]
475 #[serde(skip_serializing_if = "Option::is_none")]
476 pub old_formatting: Option<Formatting>,
477}