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

Tracking range clipboardPasteActions in history with new spreadsheet mode #4398

Open
nmih opened this issue Feb 14, 2024 · 6 comments
Open
Labels
Suggested Feature A suggested feature that is waiting review

Comments

@nmih
Copy link

nmih commented Feb 14, 2024

Is your feature request related to a problem? Please describe.
The new cell range selection mode combined with the clipboard enhancements makes for an amazing spreadsheet mode, many thanks for getting that released. I am hoping that it is possible for the history module to subscribe to changes to user edits when in this new mode, so undo and redo actions are available to revert edits.

Describe the solution you'd like

  • When user copies one cell range, and pastes it to another, the history module should capture these cell changes in the history.
  • Undo should revert all edited cells in the cell range to previous values, while redo should do the opposite.

Describe alternatives you've considered
I don't see a way to capture this action and inject it into the history stack that Tabulator maintains, so the only alternative I see would be to manage history on our own, or develop a new module that tracks clipboard actions history.

Additional context

@nmih nmih added the Suggested Feature A suggested feature that is waiting review label Feb 14, 2024
@nmih
Copy link
Author

nmih commented Mar 22, 2024

A follow up on this - I realized that this is not as simple as using the cell-value-updated event to track this, because what we are really looking for is to undo/redo the entire range of edits at once. Thus, this request is more about a new function to track history of edited ranges, very much like Excel/Google Sheets does.

tabulator feature req clipboard history

@nmih nmih changed the title Tracking cell edit history with new spreadsheet mode Tracking range clipboardPasteActions in history with new spreadsheet mode Mar 22, 2024
@diego-palumbo
Copy link

Hello, I have the same requirements to fullfill.
Thanks!

@LeeGrobler
Copy link

Any updates on this?

@olifolkerd
Copy link
Owner

Nope, will get round to it at some point but it is a complex feature requirement that only applies to a small subset of user so is not the top of the to-do list.

Very happy to accept a PR of someone wants to add it sooner

@nmih
Copy link
Author

nmih commented Apr 27, 2024

Given the complexity of this request I would like to present a workaround, but note that it depends on a much smaller feature request which I just opened up a PR for (#4485). It doesn't get us exactly to Excel/Sheets-like undo/redo functionality because it will only undo/redo edits one-by-one, instead of as a large chunk of changes. Screengrab:

demo clipboard history

With the aforementioned PR we would be able to manually mark a cell as edited (cell.setEdited()) and override the default clipboardPasteAction as documented in https://tabulator.info/docs/6.2/clipboard#paste-action. The only change that needs to be made to the default is the way cell data is updated. Right now it is using the row.updateData function. My workaround is to grab the cell data for that row then trigger cell.setValue function in the loop instead, and set the cell as edited like so:

    rows.forEach((row, i) => {
      const cellsNewData = data[i % dataLength];
      Object.entries(cellsNewData).forEach(([field, value]) => {
        const cell = row.getCell(field);
        if (cell) {
          cell.setValue(value);
          cell.component.setEdited();  // Requires https://github.com/olifolkerd/tabulator/pull/4485
        }
      });
    });

All together it looks like this as a tabulator config option:

clipboardPasteAction: function(data){
	var rows = [],
	range = this.table.modules.selectRange.activeRange,
	singleCell = false,
	bounds, startCell, startRow, rowWidth, dataLength;

	dataLength = data.length;
	
	if(range){
		bounds = range.getBounds();
		startCell = bounds.start;
		
		if(bounds.start === bounds.end){
			singleCell = true;
		}
		
		if(startCell){
			rows = this.table.rowManager.activeRows.slice();
			startRow = rows.indexOf(startCell.row);

			if(singleCell){
				rowWidth = data.length;
			}else{
				rowWidth = (rows.indexOf(bounds.end.row) - startRow) + 1;
			}
			
			
			if(startRow >-1){
				this.table.blockRedraw();
				
				rows = rows.slice(startRow, startRow + rowWidth);
				
				rows.forEach((row, i) => {
					const cellsNewData = data[i % dataLength];
					Object.entries(cellsNewData).forEach(([field, value]) => {
						const cell = row.getCell(field);
						if (cell) {
							cell.setValue(value);
							cell.component.setEdited();  // Requires https://github.com/olifolkerd/tabulator/pull/4485
						}
					});
				});
				
				this.table.restoreRedraw();
			}
		}
	}
	
	return rows;
}

@LeeGrobler
Copy link

@nmih Thanks for that, it seems to work as you described, even with that cell.component.setEdited(); line removed so I'm super psyched about this 😁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Suggested Feature A suggested feature that is waiting review
Projects
None yet
Development

No branches or pull requests

4 participants