Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Array Output Resize #307

Merged
merged 4 commits into from
Feb 23, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 20 additions & 18 deletions src/grid/actions/updateCellAndDCells.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@ export const updateCellAndDCells = async (args: ArgsType) => {
let seen = Array<string>();
for (let i = 0; i < cells_to_update.length; null) {
let string_id = cells_to_update[i].join(',');

if (seen.includes(string_id)) {
cells_to_update.splice(i, 1);
} else {
i++;
}

seen.push(string_id);
}

Expand All @@ -49,17 +47,18 @@ export const updateCellAndDCells = async (args: ArgsType) => {
let cell = sheetController.sheet.getCellCopy(ref_current_cell[0], ref_current_cell[1]);
let old_array_cells: Coordinate[] = [];

// keep track of previous array cells for this cell
old_array_cells =
cell?.array_cells?.map((cell) => {
return { x: cell[0], y: cell[1] };
}) || [];
old_array_cells.unshift(); // remove this cell

// ref_current_cell is in starting_cells
if (starting_cells.some((c) => c.x === ref_current_cell[0] && c.y === ref_current_cell[1])) {
// if the ref_cell_to_update is the starting_cell
// then we need to update the cell with data from the starting_cell
if (cell !== undefined) {
old_array_cells =
cell.array_cells?.map((cell) => {
return { x: cell[0], y: cell[1] };
}) || [];
old_array_cells.unshift(); // remove this cell
}

const passed_in_cell = starting_cells.find((c) => c.x === ref_current_cell[0] && c.y === ref_current_cell[1]);
if (passed_in_cell === undefined) continue;
cell = { ...passed_in_cell };
Expand Down Expand Up @@ -158,14 +157,6 @@ export const updateCellAndDCells = async (args: ArgsType) => {
cell.value = would_override_og_cell?.value || '';
array_cells_to_output.unshift(cell);

// if any updated cells have other cells depending on them, add to list to update
for (const array_cell of array_cells_to_output) {
// add array cells to list to update
let deps = sheetController.sheet.cell_dependency.getDependencies([array_cell.x, array_cell.y]);

if (deps) cells_to_update.push(...deps);
}

// keep track of array cells updated by this cell
cell.array_cells = array_cells_to_output.map((a_cell) => [a_cell.x, a_cell.y]);

Expand Down Expand Up @@ -223,9 +214,20 @@ export const updateCellAndDCells = async (args: ArgsType) => {
});
});

// if any updated cells have other cells depending on them, add to list to update
for (const array_cell of array_cells_to_output) {
let deps = sheetController.sheet.cell_dependency.getDependencies([array_cell.x, array_cell.y]);
if (deps) cells_to_update.push(...deps);
}

// any deleted cells have other cells depending on them, add to list to update
for (const array_cell of array_cells_to_delete) {
let deps = sheetController.sheet.cell_dependency.getDependencies([array_cell.x, array_cell.y]);
if (deps) cells_to_update.push(...deps);
}

// if this cell updates other cells add them to the list to update
let deps = sheetController.sheet.cell_dependency.getDependencies([cell.x, cell.y]);

if (deps) cells_to_update.push(...deps);
}

Expand Down
127 changes: 127 additions & 0 deletions src/grid/controller/tests/cell_evaluation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,130 @@ test('SheetController - test array formula', async () => {
expect(cell.type).toEqual('COMPUTED');
});
});

test('SheetController - test DataFrame resizing', async () => {
const sc = new SheetController();
GetCellsDBSetSheet(sc.sheet);

const cell_0_0 = {
x: 0,
y: 0,
value: '10',
type: 'TEXT',
last_modified: '2023-01-19T19:12:21.745Z',
} as Cell;

await updateCellAndDCells({ starting_cells: [cell_0_0], sheetController: sc, pyodide });

const cell_0_1 = {
x: 0,
y: 1,
value: '10',
type: 'PYTHON',
python_code: `result = []
repeat = int(c(0,0))
for x in range(0, repeat):
result.append(x + repeat)`,
last_modified: '2023-01-19T19:12:21.745Z',
} as Cell;

await updateCellAndDCells({ starting_cells: [cell_0_1], sheetController: sc, pyodide });

// Validate the dataframe is sized
const code_cell_first_run = sc.sheet.grid.getNakedCells(0, 1, 0, 1)[0];
expect(code_cell_first_run?.value).toBe('10');
expect(code_cell_first_run?.array_cells?.length).toBe(10);
expect(code_cell_first_run?.array_cells).toEqual([
[0, 1],
[0, 2],
[0, 3],
[0, 4],
[0, 5],
[0, 6],
[0, 7],
[0, 8],
[0, 9],
[0, 10],
]);

// Now resize the dataframe
const cell_0_0_update = {
x: 0,
y: 0,
value: '5',
type: 'TEXT',
last_modified: '2023-01-19T19:12:21.745Z',
} as Cell;

await updateCellAndDCells({ starting_cells: [cell_0_0_update], sheetController: sc, pyodide });

// Validate the dataframe is resized
const code_cell_after_run = sc.sheet.grid.getNakedCells(0, 1, 0, 1)[0];
expect(code_cell_after_run?.value).toBe('5');
expect(code_cell_after_run?.array_cells?.length).toBe(5);
expect(code_cell_after_run?.array_cells).toEqual([
[0, 1],
[0, 2],
[0, 3],
[0, 4],
[0, 5],
]);

// validate the dataframe is resized and old data is cleared
const after_code_run_cells = sc.sheet.grid.getNakedCells(0, 1, 0, 10);
expect(after_code_run_cells.length).toBe(5);
after_code_run_cells.forEach((cell, index) => {
expect(cell.value).toEqual((cell.y - 1 + 5).toString());
if (index === 0) return;
expect(cell.type).toEqual('COMPUTED');
});
});

test('SheetController - test deleted array cells update dependent cells', async () => {
const sc = new SheetController();
GetCellsDBSetSheet(sc.sheet);

const cell_1_2_dependent = {
x: 1,
y: 2,
value: '10',
type: 'PYTHON',
python_code: `c(0,2) + 100`,
} as Cell;

await updateCellAndDCells({ starting_cells: [cell_1_2_dependent], sheetController: sc, pyodide });

const cell_0_0 = {
x: 0,
y: 0,
value: '',
type: 'PYTHON',
python_code: `[1,2,3,4,5,6,7,8,9,10]`,
} as Cell;

await updateCellAndDCells({ starting_cells: [cell_0_0], sheetController: sc, pyodide });

// validate that the dependent cell is updated
const after_code_run_cell = sc.sheet.grid.getNakedCells(1, 2, 1, 2);
expect(after_code_run_cell.length).toBe(1);
expect(after_code_run_cell[0]?.value).toBe('103');

// Now shorten the array output
const cell_0_0_update = {
x: 0,
y: 0,
value: '',
type: 'PYTHON',
python_code: `[1,2]`,
} as Cell;

await updateCellAndDCells({ starting_cells: [cell_0_0_update], sheetController: sc, pyodide });

// validate that the dependent cell is updated
const after_code_run_cell_update = sc.sheet.grid.getNakedCells(1, 2, 1, 2);
expect(after_code_run_cell_update.length).toBe(1);
expect(after_code_run_cell_update[0]?.evaluation_result?.success).toBe(false);
expect(after_code_run_cell_update[0]?.evaluation_result?.std_err).toBe(
"TypeError on line 1: unsupported operand type(s) for +: 'NoneType' and 'int'"
);
});