Conversation
dash_table/package.json
Outdated
| "preprivate::opentests": "run-s private::wait*", | ||
| "preprivate::runtests": "run-s private::wait*", | ||
| "private::build": "webpack --display-reasons --bail", | ||
| "private::build_test": "webpack --display-reasons --bail --config webpack.test.config.js", |
There was a problem hiding this comment.
A special 'test' build with a slightly different configuration for webpack
| export default class Clipboard { | ||
| /*#if TEST_COPY_PASTE*/ | ||
| private static value: string; | ||
| /*#endif*/ |
There was a problem hiding this comment.
Webpack-preprocessor allows for conditional/build based code. This sometimes makes for pretty involved code.. but is a lot more flexible than, say, having an alias to some folder in dev vs test vs prod.
There was a problem hiding this comment.
Have to be careful though.. for the editor there is no if..else.. so all the code co-exists
| let value; | ||
|
|
||
| /*#if TEST_COPY_PASTE*/ | ||
| value = Clipboard.value; |
There was a problem hiding this comment.
Keep the copy value in a variable.. there's no event clipboard value in the test environment.. return the stored value instead!
| // if paste event onPaste handler registered in Table jsx handles it | ||
| if (ctrlDown && e.keyCode === KEY_CODES.V) { | ||
| /*#if TEST_COPY_PASTE*/ | ||
| this.onPaste({} as any); |
There was a problem hiding this comment.
Normally the paste event is handled on its own, but here we need to call it from onkeydown instead
| (row_deletable ? 1 : 0) + | ||
| (row_selectable ? 1 : 0); | ||
|
|
||
| const noOffsetSelectedCells: [number, number][] = R.map( |
There was a problem hiding this comment.
Actual offset fix. These offsets are creeping up everywhere.. once we have coverage we should refactor them out, they are useless and complicate everything.
There was a problem hiding this comment.
Agreed, this is kind of confusing and perhaps a culprit for regressions. Not especially a fan of this const columnIndexOffset being repeated in switchCell, deleteCell, getNextCell, onCopy, onPaste etc..
| module.exports = (on) => { | ||
| const options = { | ||
| webpackOptions: require('../../../../webpack.config'), | ||
| webpackOptions: require('../../../../webpack.test.config.js'), |
There was a problem hiding this comment.
Cypress uses the test configuration
| { | ||
| definitions: ['TEST_COPY_PASTE'] | ||
| }, | ||
| 'development' |
There was a problem hiding this comment.
preprocessor and mode overrides
| - run: | ||
| name: Run build:js | ||
| command: npm run build:js | ||
| command: npm run build:js-test |
There was a problem hiding this comment.
Build the test version..
| }); | ||
|
|
||
| // Commenting this test as Cypress team is having issues with the copy/paste scenario | ||
| // https://github.com/cypress-io/cypress/issues/2386 |
There was a problem hiding this comment.
@Marc-Andre-Rivet maybe we want to add a TODO and keep a link to this issue in the code so we can rework this test if/when the above issue is resolved.
|
@Marc-Andre-Rivet copy and pasting works well for me initially, but it does not work if I sort a column: lmk if I can provide more information |
|
@cldougl Thanks, will test it out.. guessing that if you remove the sorting, the data has been copied at the beginning of the dataframe -- behavior confirmed |
- delete cell with and w/o sorting - additional tests for copy/paste
| ## RC11 - Fix copy/paste regression, fix delete regression | ||
|
|
||
| Issue: https://github.com/plotly/dash-table/issues/64 | ||
| Issue: https://github.com/plotly/dash-table/issues/67 No newline at end of file |
There was a problem hiding this comment.
Ended up working on both celle delete and copy/paste as it's the same issue
| selected_cell | ||
| ); | ||
|
|
||
| realCells.forEach(cell => { |
There was a problem hiding this comment.
Since we need to work on the real dataframe and the viewport is showing a virtualized subsection of the whole df, we need to map between the virtualized df and the real one to modify the correct indices.
| } | ||
|
|
||
| const realActiveRow = virtual_dataframe_indices[activeCell[0]]; | ||
| if (overflowRows && values.length + realActiveRow >= dataframe.length) { |
There was a problem hiding this comment.
We normally add rows if the copy/paste requires more entries, but with sorting or filtering on, it's not obvious what the behavior should be. Preventing this from happening for now.
| // let newDataframe = dataframe; | ||
| const col = newColumns[jOffset]; | ||
| if (colIsEditable(true, col)) { | ||
| if (col && colIsEditable(true, col)) { |
There was a problem hiding this comment.
It's possible now that the column was not created, checking for it
| row.forEach((cell: string, j: number) => { | ||
| const iOffset = activeCell[0] + i; | ||
| if (virtual_dataframe_indices.length <= activeCell[0] + i) { | ||
| return; |
There was a problem hiding this comment.
row may not exist bc of the overflow toggle
| .within(() => cy.get('.cell-value').should('have.value', 'MODIFIED')); | ||
| }); | ||
|
|
||
| it('BE rountrip with sorted, unfiltered data', () => { |
There was a problem hiding this comment.
new test case for sorted data + copy/paste
|
💃 this looks a lot better to me! |
wbrgss
left a comment
There was a problem hiding this comment.
Tests look good to me. Too bad about having to hack around the Cypress issue but I agree better there than not! 💃
| (row_deletable ? 1 : 0) + | ||
| (row_selectable ? 1 : 0); | ||
|
|
||
| const realCells: [number, number][] = R.map( |
There was a problem hiding this comment.
Performance consideration: might be worth checking alternatives to R.map for mapping between many virtual => real cells if this is executing a lot. Same goes for noOffsetSelectedCells. Benchmark (higher is better):
https://www.measurethat.net/Benchmarks/ShowResult/32960
There was a problem hiding this comment.
I know Ramda use is encouraged, but if you're looking to squeeze out some better UX responsiveness..
| (row_deletable ? 1 : 0) + | ||
| (row_selectable ? 1 : 0); | ||
|
|
||
| const noOffsetSelectedCells: [number, number][] = R.map( |
There was a problem hiding this comment.
Agreed, this is kind of confusing and perhaps a culprit for regressions. Not especially a fan of this const columnIndexOffset being repeated in switchCell, deleteCell, getNextCell, onCopy, onPaste etc..

This review is pretty big and divided in two parts
So, the special test version will handle the paste event through the onKeyDown event and call the onPaste handler. Copy will keep the copied value cached as it will be required -- there's no onPaste event -- and that's the only place where the clipboard data is made available.