Skip to content

Commit 2f0ba8c

Browse files
3.1 issue132 readonly tests (#134)
* 3.1 props refactoring (#106) * refactor virtualization, virtualization settings, and derived props * refactor renaming paging / pagination props * refactor virtual, viewport and pagination into adapters * isolate derived props * build update * fix regression * improve typing * fix test regression * simplify pagination adapter / refactor * lint * clean up unused props * - change factory - clean up props / build update * fix lint * bump version * add dash level props for virtual_dataframe * refactor fp / derived props * derived props * refactor viewport and virtual controlled props * fix fp regression * fix fp regression * refactor controlled table / table fp * controlled table purecomponent * fix test (rebrake it!) * fix selection regression for be paging/sorting/filtering * improve re-renders & controlled props * fix test regressions * update inner-selection fixture * remove useless spy * - fix pr comment - fix for IE/Edge * clean up * 3.0 clean offsets (#110) * refactor virtualization, virtualization settings, and derived props * refactor renaming paging / pagination props * refactor virtual, viewport and pagination into adapters * isolate derived props * build update * fix regression * improve typing * fix test regression * simplify pagination adapter / refactor * lint * clean up unused props * - change factory - clean up props / build update * fix lint * bump version * add dash level props for virtual_dataframe * cleaup offsets * triad validation * - define external facing classes and attributes * fix regression, update build * fix test regression (invalid props) * update test name * refactor fp / derived props * derived props * refactor viewport and virtual controlled props * fix fp regression * fix fp regression * refactor controlled table / table fp * controlled table purecomponent * fix test (rebrake it!) * fix selection regression for be paging/sorting/filtering * improve re-renders & controlled props * fix test regressions * update inner-selection fixture * remove useless spy * - control columns into visible columns - cleanup "hidden" conditional processing * update changelog * clean up header factory * apply style on first controlled table render * typo/merge miss * derived visible columns * - visual tests for hidden columns * rename functions * - fix dropdown styling regression * lint * 3.1 props fixes (#112) * props fixes * update changelog * bump version * filter typing * Update derivedViewport_test.ts Add basic viewport test with |df| > page_size * ☝️ 3 new review / documentation / target apps see discussion in plotly/dash-table#108 * 🙈 forgot file * 📝 incorporate @cldougl suggestions 🙇 * 3.1 refactor tests (#113) * props fixes * update changelog * bump version * filter typing * - delete unused usage files - restructure tests folder * - separate cypress and visual tests into 2 ci jobs * - build before tests! * add browsers to the node image for visual-test * 💯 add percent examples * 📝 title/example clarification * reformat sizing test app for failing tests (#125) * Removed .only from dash_test.ts * Production build instead of dev 🙈 * Fix failing tests * 3.1 refactor cells rendering (#123) * WIP - memoize cell event handlers as derived values - isolate cell event handlers * wip - attempt to isolate cell logic from input logic for individual datum * wip - celan up cell wrapper - isolate input logic a bit more * further down the rabbit hole.. - separating operation cells from content * fix dropdown navigation regression * fix selected row regression * renaming / restructuring * rename/restructure * - clean up zipping - separate wrappers from styles * rework style/ast cache * clean up * clean up * build update * improve rendering perf * optimize wrappers generation * build config * - fix typing regression - fix rendering perf regression * - fix navigation regression * simplify slightly the derived props / ui * fix copy/paste regressions * clean up wrapper props * clean up * fix regression on conditional dropdowns * wip, fp the headers * fp content, wrappers, labels, indices from header factory * fix regressions * fp the table itself * fix typing and behavior for table fp * fix sorting icon regression * fix regression * regression * fix column name regression with only 1 header row * fix header actions regression * fix style application on mount * fix regression edit cell in n-th page * fix editing on non-first page (continued) * fix test * 3.1 issue118 width behavior (#130) * WIP - memoize cell event handlers as derived values - isolate cell event handlers * wip - attempt to isolate cell logic from input logic for individual datum * wip - celan up cell wrapper - isolate input logic a bit more * further down the rabbit hole.. - separating operation cells from content * fix dropdown navigation regression * fix selected row regression * renaming / restructuring * rename/restructure * - clean up zipping - separate wrappers from styles * rework style/ast cache * clean up * clean up * build update * improve rendering perf * optimize wrappers generation * build config * - fix typing regression - fix rendering perf regression * - fix navigation regression * simplify slightly the derived props / ui * fix copy/paste regressions * clean up wrapper props * clean up * fix regression on conditional dropdowns * wip, fp the headers * fp content, wrappers, labels, indices from header factory * fix regressions * fp the table itself * fix typing and behavior for table fp * fix sorting icon regression * fix regression * regression * fix column name regression with only 1 header row * fix header actions regression * add width percentage support + content_style * fix style application on mount * fix visual regression with empty df * only apply row style when necessary * fix tab test (no offset) * clean up header styling * use dash-* classes * support default column width (override input behavior) * fix regression edit cell in n-th page * fix editing on non-first page (continued) * fix test * fit to content behavior * fix regressions * fix lint * add column width visual tests * fix dropdown minimum size when using default width * sizing examples * black * fix navigation test regression * fix regressions in visual tests * default column width - fix dropdown width eval * default width columns - fix width when first content row is search filter * percy - add delay before screenshot (attempt to fix FF visual tests) * debugging selenium * fix black * debug selenium * debug selenium * fix black * debug selenium * debug selenium * debug selenium * undo all selenium modifications * default column width - filter inputs behave like cell inputs (do not affect width) * - fixed rows+columns height evaluated correctly * remove dead code * remove .only from tests * add data-dash-column to filter cells * styling examples (#117) * 🌈 styling examples examples that represent of the level of customization that we need in dash-table. The examples are implemented with HTML tables to demonstrate the intended behaviour. I’d like to see each of these examples implemented with the `dash_table` syntax. We’ll use these examples as our `dash-table` documentation * ❌ removing black and pylint this keeps tripping us up and I don’t think it’s worth the pain right now. * Backend examples (#119) * 🏭 backend computed data usage examples * 📊 tying it together w a graph * ❓ not sure what `displayed_pages` does? * Dropdown usage examples (#120) * ⬇️ dropdown usage examples * add conditional dropdown example * - additional tests for editable/readonly - fixes for editable/readonly * bump version * remove useless test column * add editable prop to fixtures * update tests to take into account readonly 'rows' column * - refactor column isEditable calculation
1 parent e67f58c commit 2f0ba8c

File tree

16 files changed

+112
-37
lines changed

16 files changed

+112
-37
lines changed

packages/dash-table/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,7 @@ Derived properties allow the component to expose complex state that can be usefu
308308
### Interaction between width, min-width and max-width
309309

310310
Column min-width and max-width do not default to width value is not defined.
311+
312+
## RC5 - Tests and fixes for editable/readonly
313+
314+
Issue: https://github.com/plotly/dash-table/issues/132

packages/dash-table/dash_table/bundle.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/dash-table/dash_table/demo.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/dash-table/dash_table/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "dash-table",
3-
"version": "3.1.0rc4",
3+
"version": "3.1.0rc5",
44
"description": "Dash table",
55
"main": "build/index.js",
66
"scripts": {

packages/dash-table/demo/data.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,32 @@ export const mockData = unpackIntoColumnsAndDataFrames([
6464
)
6565
},
6666

67+
{
68+
id: 'bbb-readonly',
69+
name: ['', 'Weather', 'Climate-RO'],
70+
type: 'dropdown',
71+
editable: false,
72+
width: 200,
73+
data: gendata(
74+
i => ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'][i % 4]
75+
)
76+
},
77+
6778
{
6879
id: 'aaa',
6980
name: ['', 'Weather', 'Temperature'],
7081
type: 'numeric',
7182
width: 150,
7283
data: gendata(i => i + 1),
84+
},
85+
86+
{
87+
id: 'aaa-readonly',
88+
name: ['', 'Weather', 'Temperature-RO'],
89+
type: 'numeric',
90+
editable: false,
91+
width: 150,
92+
data: gendata(i => i + 1),
7393
}
7494
]);
7595

packages/dash-table/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "dash-table",
3-
"version": "3.1.0rc4",
3+
"version": "3.1.0rc5",
44
"description": "Dash table",
55
"main": "build/index.js",
66
"scripts": {

packages/dash-table/src/dash-table/components/CellInput/index.tsx

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,33 @@ export default class CellInput extends PureComponent<ICellProps, ICellState> {
4040

4141
private renderDropdown() {
4242
const {
43+
active,
4344
clearable,
4445
dropdown,
46+
editable,
47+
focused,
4548
onChange,
49+
onClick,
50+
onDoubleClick,
4651
value
4752
} = this.propsWithDefaults;
4853

49-
return !dropdown ?
50-
this.renderValue() :
54+
const classes = [
55+
...(active ? ['input-active'] : []),
56+
...(focused ? ['focused'] : ['unfocused']),
57+
...['dash-cell-value']
58+
];
59+
60+
const attributes = {
61+
className: classes.join(' '),
62+
onClick: onClick,
63+
onDoubleClick: onDoubleClick
64+
};
65+
66+
const readonly = !editable;
67+
68+
return !dropdown || readonly ?
69+
this.renderValue(attributes) :
5170
(<div className='dash-dropdown-cell-value-container dash-cell-value-container'>
5271
{this.renderValue(
5372
{ className: 'dropdown-cell-value-shadow cell-value-shadow' },
@@ -70,6 +89,7 @@ export default class CellInput extends PureComponent<ICellProps, ICellState> {
7089
private renderInput() {
7190
const {
7291
active,
92+
editable,
7393
focused,
7494
onClick,
7595
onDoubleClick,
@@ -88,7 +108,7 @@ export default class CellInput extends PureComponent<ICellProps, ICellState> {
88108
onDoubleClick: onDoubleClick
89109
};
90110

91-
const readonly = !active && this.state.value === this.props.value;
111+
const readonly = (!active && this.state.value === this.props.value) || !editable;
92112

93113
return readonly ?
94114
this.renderValue(attributes) :

packages/dash-table/src/dash-table/components/ControlledTable/index.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React, { PureComponent } from 'react';
22
import * as R from 'ramda';
33
import Stylesheet from 'core/Stylesheet';
4-
import { colIsEditable } from 'dash-table/components/derivedState';
54
import {
65
KEY_CODES,
76
isCtrlMetaKey,
@@ -21,6 +20,7 @@ import dropdownHelper from 'dash-table/components/dropdownHelper';
2120

2221
import derivedTable from 'dash-table/derived/table';
2322
import derivedTableFragments from 'dash-table/derived/table/fragments';
23+
import isEditable from 'dash-table/derived/cell/isEditable';
2424

2525
const sortNumerical = R.sort<number>((a, b) => a - b);
2626

@@ -208,7 +208,7 @@ export default class ControlledTable extends PureComponent<ControlledTableProps,
208208
if (
209209
e.keyCode === KEY_CODES.ENTER &&
210210
!is_focused &&
211-
colIsEditable(editable, columns[active_cell[1]])
211+
isEditable(editable, columns[active_cell[1]])
212212
) {
213213
setProps({ is_focused: true });
214214
return;
@@ -235,7 +235,7 @@ export default class ControlledTable extends PureComponent<ControlledTableProps,
235235
// if we have any non-meta key enter editable mode
236236

237237
!this.props.is_focused &&
238-
colIsEditable(editable, columns[active_cell[1]]) &&
238+
isEditable(editable, columns[active_cell[1]]) &&
239239
!isMetaKey(e.keyCode)
240240
) {
241241
setProps({ is_focused: true });
@@ -378,7 +378,7 @@ export default class ControlledTable extends PureComponent<ControlledTableProps,
378378
);
379379

380380
realCells.forEach(cell => {
381-
if (colIsEditable(editable, columns[cell[1]])) {
381+
if (isEditable(editable, columns[cell[1]])) {
382382
newDataframe = R.set(
383383
R.lensPath([cell[0], columns[cell[1]].id]),
384384
'',
@@ -620,7 +620,7 @@ export default class ControlledTable extends PureComponent<ControlledTableProps,
620620
id,
621621
content_style,
622622
n_fixed_columns,
623-
n_fixed_rows,
623+
n_fixed_rows
624624
} = this.props;
625625

626626
const classes = [

packages/dash-table/src/dash-table/components/derivedState.js

Lines changed: 0 additions & 5 deletions
This file was deleted.

packages/dash-table/src/dash-table/derived/cell/inputs.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
import CellInput from 'dash-table/components/CellInput';
1515
import derivedCellEventHandlerProps from 'dash-table/derived/cell/eventHandlerProps';
1616
import isActiveCell from 'dash-table/derived/cell/isActive';
17+
import isEditable from './isEditable';
1718

1819
const mapDataframe = R.addIndex<Datum, JSX.Element[]>(R.map);
1920
const mapRow = R.addIndex<IVisibleColumn, JSX.Element>(R.map);
@@ -43,7 +44,7 @@ const getter = (
4344
clearable={column.clearable}
4445
datum={datum}
4546
dropdown={dropdown}
46-
editable={editable}
47+
editable={isEditable(editable, column)}
4748
focused={isFocused}
4849
property={column.id}
4950
tableId={tableId}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { IVisibleColumn } from 'dash-table/components/Table/props';
2+
3+
export default (
4+
editable: boolean,
5+
column: IVisibleColumn
6+
): boolean => editable && (column.editable === undefined || column.editable);

packages/dash-table/src/dash-table/derived/cell/wrappers.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Cell from 'dash-table/components/Cell';
77
import isActiveCell from 'dash-table/derived/cell/isActive';
88
import isSelectedCell from 'dash-table/derived/cell/isSelected';
99
import memoizerCache from 'core/memoizerCache';
10+
import isEditable from './isEditable';
1011

1112
type Key = [number, number];
1213
type ElementCacheFn = (
@@ -35,7 +36,7 @@ function getter(
3536
'dash-cell' +
3637
` column-${columnIndex}` +
3738
(active ? ' focused' : '') +
38-
(!editable ? ' cell--uneditable' : '') +
39+
(!isEditable(editable, column) ? ' cell--uneditable' : '') +
3940
(selected ? ' cell--selected' : '') +
4041
(column.type === ColumnType.Dropdown ? ' dropdown' : '');
4142

@@ -44,7 +45,7 @@ function getter(
4445
columns
4546
),
4647
dataframe
47-
)
48+
);
4849
}
4950

5051
function decorator(_id: string): ((

packages/dash-table/src/dash-table/utils/TableClipboardHelper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import SheetClip from 'sheetclip';
44
import Clipboard from 'core/Clipboard';
55
import Logger from 'core/Logger';
66

7-
import { colIsEditable } from 'dash-table/components/derivedState';
87
import { ActiveCell, Columns, Dataframe, SelectedCells, ColumnType } from 'dash-table/components/Table/props';
8+
import isEditable from 'dash-table/derived/cell/isEditable';
99

1010
export default class TableClipboardHelper {
1111
public static toClipboard(e: any, selectedCells: SelectedCells, columns: Columns, dataframe: Dataframe) {
@@ -94,7 +94,7 @@ export default class TableClipboardHelper {
9494

9595
const jOffset = activeCell[1] + j;
9696
const col = newColumns[jOffset];
97-
if (col && colIsEditable(true, col)) {
97+
if (col && isEditable(true, col)) {
9898
newDataframe = R.set(
9999
R.lensPath([iRealCell, col.id]),
100100
cell,

packages/dash-table/tests/cypress/src/DashTable.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ export default class DashTable {
33
return cy.get(`#table tbody tr td.column-${column}`).eq(row);
44
}
55

6+
static getCellById(row: number, column: number | string) {
7+
return cy.get(`#table tbody tr td[data-dash-column="${column}"]`).eq(row);
8+
}
9+
610
static getDelete(row: number) {
711
return cy.get(`#table tbody tr td.dash-delete-cell`).eq(row);
812
}

packages/dash-table/tests/cypress/tests/standalone/edit_cell_test.ts

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,31 @@ import DashTable from 'cypress/DashTable';
22
import DOM from 'cypress/DOM';
33
import Key from 'cypress/Key';
44

5-
describe('edit cell', () => {
5+
describe('edit', () => {
66
beforeEach(() => {
77
cy.visit('http://localhost:8080');
88
});
99

10+
describe('readonly cell', () => {
11+
describe('with input', () => {
12+
it('does not modify value', () => {
13+
DashTable.getCellById(0, 'aaa-readonly').click();
14+
DashTable.getCellById(0, 'aaa-readonly').within(() => {
15+
cy.get('input').should('not.exist');
16+
});
17+
});
18+
});
19+
20+
describe('with dropdown', () => {
21+
it('does not modify value', () => {
22+
DashTable.getCellById(0, 'bbb-readonly').click();
23+
DashTable.getCellById(0, 'bbb-readonly').within(() => {
24+
cy.get('.Select-value-label').should('not.exist');
25+
});
26+
});
27+
});
28+
});
29+
1030
it('can delete dropdown', () => {
1131
DashTable.getCell(0, 6).trigger('mouseover');
1232
DashTable.getCell(0, 6).within(() => cy.get('.Select-clear').click());
@@ -63,27 +83,27 @@ describe('edit cell', () => {
6383
});
6484

6585
it('can edit on 2nd page', () => {
66-
DashTable.getCell(0, 0).click();
67-
DashTable.getCell(0, 0).within(() => cy.get('input').should('have.value', '1'));
86+
DashTable.getCell(0, 1).click();
87+
DashTable.getCell(0, 1).within(() => cy.get('input').should('have.value', '1'));
6888
cy.get('button.next-page').click();
69-
DashTable.getCell(0, 0).within(() => cy.get('input').should('have.value', '251'));
89+
DashTable.getCell(0, 1).within(() => cy.get('input').should('have.value', '251'));
7090

7191
DOM.focused.type(`abc${Key.Enter}`);
72-
DashTable.getCell(0, 0).click();
73-
DashTable.getCell(0, 0).within(() => cy.get('input').should('have.value', 'abc'));
92+
DashTable.getCell(0, 1).click();
93+
DashTable.getCell(0, 1).within(() => cy.get('input').should('have.value', 'abc'));
7494
});
7595

7696
it('can delete then edit on 2nd page', () => {
77-
DashTable.getCell(0, 0).click();
78-
DashTable.getCell(0, 0).within(() => cy.get('input').should('have.value', '1'));
97+
DashTable.getCell(0, 1).click();
98+
DashTable.getCell(0, 1).within(() => cy.get('input').should('have.value', '1'));
7999
cy.get('button.next-page').click();
80-
DashTable.getCell(0, 0).within(() => cy.get('input').should('have.value', '251'));
100+
DashTable.getCell(0, 1).within(() => cy.get('input').should('have.value', '251'));
81101
DashTable.getDelete(0).click();
82-
DashTable.getCell(0, 0).within(() => cy.get('input').should('have.value', '252'));
102+
DashTable.getCell(0, 1).within(() => cy.get('input').should('have.value', '252'));
83103

84104
DOM.focused.type(`abc${Key.Enter}`);
85-
DashTable.getCell(0, 0).click();
86-
DashTable.getCell(0, 0).within(() => cy.get('input').should('have.value', 'abc'));
105+
DashTable.getCell(0, 1).click();
106+
DashTable.getCell(0, 1).within(() => cy.get('input').should('have.value', 'abc'));
87107
});
88108

89109
// https://github.com/plotly/dash-table/issues/50

packages/dash-table/tests/visual/percy-storybook/fixtures.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export default [
2727
{'column-1': 'boston'}
2828
],
2929
n_fixed_rows: 1,
30+
editable: true,
3031
table_style: [{
3132
selector: '.dash-spreadsheet.dash-freeze-top',
3233
rule: 'height: 100px;'
@@ -150,6 +151,7 @@ export default [
150151
{'column-1': 'mtl'},
151152
{'column-1': 'boston'}
152153
],
154+
editable: true,
153155
id: 'table'
154156
}
155157
},
@@ -211,6 +213,7 @@ export default [
211213
{'column-1': 'mtl', 'column-2': 'mtl', 'column-3': 'mtl'},
212214
{'column-1': 'mtl', 'column-2': 'mtl', 'column-3': 'mtl'}
213215
],
216+
editable: true,
214217
id: 'table'
215218
}
216219
},
@@ -274,6 +277,7 @@ export default [
274277
region: 'costa-rica'
275278
}
276279
],
280+
editable: true,
277281
id: 'table'
278282
}
279283
},

0 commit comments

Comments
 (0)