Skip to content

Commit

Permalink
Merge branch 'data-tables-v1' of github.com:quadratichq/quadratic int…
Browse files Browse the repository at this point in the history
…o data-tables-v1
  • Loading branch information
jimniels committed Jan 28, 2025
2 parents 19571a1 + f02e246 commit df6c427
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 28 deletions.
102 changes: 83 additions & 19 deletions quadratic-core/src/controller/operations/clipboard.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::HashMap;

use anyhow::{Error, Result};
use indexmap::IndexMap;
use regex::Regex;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
Expand All @@ -15,6 +16,7 @@ use crate::grid::js_types::JsClipboard;
use crate::grid::js_types::JsSnackbarSeverity;
use crate::grid::sheet::borders::BordersUpdates;
use crate::grid::sheet::validations::validation::Validation;
use crate::grid::DataTable;
use crate::grid::{CodeCellLanguage, DataTableKind};
use crate::{a1::A1Selection, CellValue, Pos, Rect, SheetPos, SheetRect};

Expand Down Expand Up @@ -83,6 +85,9 @@ pub struct Clipboard {
#[serde(skip_serializing_if = "Option::is_none", default)]
pub validations: Option<ClipboardValidations>,

#[serde(with = "crate::util::indexmap_serde")]
pub data_tables: IndexMap<Pos, DataTable>,

pub operation: ClipboardOperation,
}

Expand Down Expand Up @@ -223,7 +228,6 @@ impl GridController {
|(output_rect, intersection_rect, data_table)| {
let contains_source_cell =
intersection_rect.contains(output_rect.min);

// there is no pasting on top of code cell output
if !data_table.readonly && !contains_source_cell {
let adjusted_rect = Rect::from_numbers(
Expand Down Expand Up @@ -330,16 +334,24 @@ impl GridController {
y: clipboard.origin.y + *y as i64,
};

if let Some(data_table) = sheet.data_table(source_pos) {
if matches!(data_table.kind, DataTableKind::Import(_)) {
ops.push(Operation::SetDataTable {
sheet_pos,
data_table: Some(data_table.to_owned()),
index: 0,
});
}
if let Some(data_table) = clipboard.data_tables.get(&source_pos) {
ops.push(Operation::SetDataTable {
sheet_pos,
data_table: Some(data_table.to_owned()),
index: 0,
});
}

// if let Some(data_table) = sheet.data_table(source_pos) {
// if matches!(data_table.kind, DataTableKind::Import(_)) {
// ops.push(Operation::SetDataTable {
// sheet_pos,
// data_table: Some(data_table.to_owned()),
// index: 0,
// });
// }
// }

ops.push(Operation::ComputeCode { sheet_pos });
});
}
Expand Down Expand Up @@ -447,7 +459,6 @@ impl GridController {
special: PasteSpecial,
) -> Result<Vec<Operation>> {
let error = |e, msg| Error::msg(format!("Clipboard Paste {:?}: {:?}", msg, e));

let insert_at = selection.cursor;

// use regex to find data-quadratic
Expand Down Expand Up @@ -521,7 +532,7 @@ mod test {
use serial_test::{parallel, serial};

use super::{PasteSpecial, *};
use crate::a1::A1Selection;
use crate::a1::{A1Context, A1Selection, CellRefRange, TableRef};
use crate::controller::active_transactions::transaction_name::TransactionName;
use crate::controller::user_actions::import::tests::{simple_csv, simple_csv_at};
use crate::grid::js_types::JsClipboard;
Expand Down Expand Up @@ -737,7 +748,7 @@ mod test {

#[test]
#[parallel]
fn paste_clipboard_with_data_table() {
fn copy_paste_clipboard_with_data_table() {
let (mut gc, sheet_id, _, _) = simple_csv();
let paste = |gc: &mut GridController, x, y, html| {
gc.paste_from_clipboard(
Expand All @@ -749,20 +760,73 @@ mod test {
);
};

let table_ref = TableRef::new("simple.csv");
let cell_ref_range = CellRefRange::Table { range: table_ref };
let context = A1Context::test(
&[("Sheet1", sheet_id)],
&[(
"simple.csv",
&["city", "region", "country", "population"],
Rect::test_a1("A1:D11"),
)],
);
let selection = A1Selection::from_range(cell_ref_range, sheet_id, &context);

let JsClipboard { html, .. } = gc
.sheet(sheet_id)
.copy_to_clipboard(
&A1Selection::from_xy(0, 0, sheet_id),
ClipboardOperation::Copy,
)
.copy_to_clipboard(&selection, ClipboardOperation::Copy)
.unwrap();

let expected_row1 = vec!["city", "region", "country", "population"];

// paste side by side
paste(&mut gc, 4, 0, html.clone());
print_table(&gc, sheet_id, Rect::from_numbers(0, 0, 8, 10));
assert_cell_value_row(&gc, sheet_id, 4, 0, 0, expected_row1);
paste(&mut gc, 10, 1, html.clone());
print_table(&gc, sheet_id, Rect::from_numbers(10, 1, 4, 11));
assert_cell_value_row(&gc, sheet_id, 10, 13, 0, expected_row1);
}

#[test]
#[parallel]
fn cut_paste_clipboard_with_data_table() {
let (mut gc, sheet_id, _, _) = simple_csv();
let paste = |gc: &mut GridController, x, y, html| {
gc.paste_from_clipboard(
&A1Selection::from_xy(x, y, sheet_id),
None,
Some(html),
PasteSpecial::None,
None,
);
};

let table_ref = TableRef::new("simple.csv");
let cell_ref_range = CellRefRange::Table { range: table_ref };
let context = A1Context::test(
&[("Sheet1", sheet_id)],
&[(
"simple.csv",
&["city", "region", "country", "population"],
Rect::test_a1("A1:BV11"),
)],
);
let selection = A1Selection::from_range(cell_ref_range, sheet_id, &context);

// let selection = A1Selection::test_a1("A1:B4");

let (ops, js_clipboard) = gc.cut_to_clipboard_operations(&selection).unwrap();
gc.start_user_transaction(ops, None, TransactionName::CutClipboard);

// let js_clipboard = gc
// .sheet(sheet_id)
// .copy_to_clipboard(&selection, ClipboardOperation::Copy)
// .unwrap();

let expected_row1 = vec!["city", "region", "country", "population"];

// paste side by side
paste(&mut gc, 10, 1, js_clipboard.html.clone());
print_table(&gc, sheet_id, Rect::from_numbers(10, 1, 4, 11));
assert_cell_value_row(&gc, sheet_id, 10, 13, 0, expected_row1);
}

#[test]
Expand Down
1 change: 1 addition & 0 deletions quadratic-core/src/controller/user_actions/clipboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ impl GridController {
) -> Result<JsClipboard, String> {
let (ops, js_clipboard) = self.cut_to_clipboard_operations(selection)?;
self.start_user_transaction(ops, cursor, TransactionName::CutClipboard);

Ok(js_clipboard)
}

Expand Down
12 changes: 9 additions & 3 deletions quadratic-core/src/grid/sheet/clipboard.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use indexmap::IndexMap;

use crate::a1::A1Selection;
use crate::cell_values::CellValues;
use crate::color::Rgba;
Expand All @@ -21,10 +23,10 @@ impl Sheet {
let mut html_body = String::from("<tbody>");
let mut cells = CellValues::default();
let mut values = CellValues::default();
let mut data_tables = IndexMap::new();
let mut sheet_bounds: Option<Rect> = None;
let context = self.a1_context();

// TODO(ddimaria): this doesn't work properly for TableRefs
if let Some(bounds) = self.selection_bounds(selection, true) {
clipboard_origin.x = bounds.min.x;
clipboard_origin.y = bounds.min.y;
Expand Down Expand Up @@ -249,6 +251,11 @@ impl Sheet {
// add the CellValue to cells if the code is not included in the clipboard
let include_in_cells = !bounds.contains(data_table_pos);

// if the source cell is included in the clipboard, add the data_table to the clipboard
if !include_in_cells {
data_tables.insert(data_table_pos, data_table.clone());
}

// add the code_run output to clipboard.values
for y in y_start..=y_end {
for x in x_start..=x_end {
Expand All @@ -274,9 +281,7 @@ impl Sheet {
}

let formats = self.formats.to_clipboard(self, selection);

let borders = self.borders.to_clipboard(self, selection);

let validations = self
.validations
.to_clipboard(selection, &clipboard_origin, &context);
Expand All @@ -291,6 +296,7 @@ impl Sheet {
origin: clipboard_origin,
selection: selection.clone(),
validations,
data_tables,
operation: clipboard_operation,
};

Expand Down
2 changes: 1 addition & 1 deletion quadratic-core/src/test_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ pub fn assert_cell_value_row(
if let Some(cell_value) = value.get(index) {
assert_display_cell_value(grid_controller, sheet_id, x, y, cell_value);
} else {
println!("No value at position ({},{})", index, y);
panic!("No value at position ({},{})", index, y);
}
}
}
Expand Down
1 change: 0 additions & 1 deletion quadratic-core/src/values/cellvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,6 @@ impl CellValue {
pub fn code_cell_value_mut(&mut self) -> Option<&mut CodeCellValue> {
match self {
CellValue::Code(code) => Some(code),
CellValue::Import(_) => None,
_ => None,
}
}
Expand Down
8 changes: 4 additions & 4 deletions quadratic-files/src/state/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ pub(crate) struct StatsResponse {
pub(crate) last_processed_file_time: String,
pub(crate) last_processed_file_elapsed: String,
pub(crate) files_to_process_in_pubsub: u64,
pub(crate) last_processed_transaction_time: String,
pub(crate) last_processed_transaction_elapsed: String,
pub(crate) last_truncated_transaction_time: String,
pub(crate) last_truncated_transaction_elapsed: String,
pub(crate) channels_to_truncate_in_pubsub: u64,
}

Expand All @@ -32,8 +32,8 @@ impl From<&Stats> for StatsResponse {
last_processed_file_time: to_rfc3339(stats.last_processed_file_time),
last_processed_file_elapsed: last_processed_file_elapsed,
files_to_process_in_pubsub: stats.files_to_process_in_pubsub,
last_processed_transaction_time: to_rfc3339(stats.last_truncated_transaction_time),
last_processed_transaction_elapsed: last_processed_transaction_elapsed,
last_truncated_transaction_time: to_rfc3339(stats.last_truncated_transaction_time),
last_truncated_transaction_elapsed: last_processed_transaction_elapsed,
channels_to_truncate_in_pubsub: stats.channels_to_truncate_in_pubsub,
}
}
Expand Down

0 comments on commit df6c427

Please sign in to comment.