From b95b9b32810af86d61fd2644656cccd79c201cc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 2 Aug 2019 13:02:45 -0400 Subject: [PATCH 1/9] add dropdown visual test (failing) --- .../visual/percy-storybook/Dropdown.percy.tsx | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/visual/percy-storybook/Dropdown.percy.tsx b/tests/visual/percy-storybook/Dropdown.percy.tsx index a5d7864d7..7569b4ae3 100644 --- a/tests/visual/percy-storybook/Dropdown.percy.tsx +++ b/tests/visual/percy-storybook/Dropdown.percy.tsx @@ -30,6 +30,48 @@ const columns2 = R.map( ); storiesOf('DashTable/Dropdown', module) + .add('readonly dropdown shows label', () => ({ label: `label: ${i}`, value: i }), + ['Sunny', 'Snowy', 'Rainy'] + ) + }, + city: { + options: R.map( + i => ({ label: `label: ${i}`, value: i }), + ['NYC', 'Montreal', 'Miami'] + ) + } + }} + />) + .add('editable dropdown shows label', () => ({ label: `label: ${i}`, value: i }), + ['Sunny', 'Snowy', 'Rainy'] + ) + }, + city: { + options: R.map( + i => ({ label: `label: ${i}`, value: i }), + ['NYC', 'Montreal', 'Miami'] + ) + } + }} + />) .add('dropdown by column', () => ( Date: Fri, 2 Aug 2019 13:40:27 -0400 Subject: [PATCH 2/9] resolve label when dropdown is shown as label --- src/dash-table/derived/cell/contents.tsx | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/dash-table/derived/cell/contents.tsx b/src/dash-table/derived/cell/contents.tsx index 3539546f2..c52101734 100644 --- a/src/dash-table/derived/cell/contents.tsx +++ b/src/dash-table/derived/cell/contents.tsx @@ -26,6 +26,7 @@ const mapRow = R.addIndex(R.map); enum CellType { Dropdown, + DropdownLabel, Input, Label } @@ -40,7 +41,7 @@ function getCellType( case Presentation.Input: return (!active || !editable) ? CellType.Label : CellType.Input; case Presentation.Dropdown: - return (!dropdown || !editable) ? CellType.Label : CellType.Dropdown; + return (!dropdown || !editable) ? CellType.DropdownLabel : CellType.Dropdown; default: return (!active || !editable) ? CellType.Label : CellType.Input; } @@ -124,7 +125,9 @@ class Contents { 'dash-cell-value' ].join(' '); - switch (getCellType(active, column.editable, dropdown && dropdown.options, column.presentation)) { + const cellType = getCellType(active, column.editable, dropdown && dropdown.options, column.presentation); + + switch (cellType) { case CellType.Dropdown: return (); + case CellType.DropdownLabel: case CellType.Label: default: + const resolvedValue = cellType === CellType.DropdownLabel ? + this.resolveDropdownLabel(dropdown, datum[column.id]) : + formatters[columnIndex](datum[column.id]); + return (); } } + + private resolveDropdownLabel(dropdown: IDropdown | undefined, value: any) { + const dropdownValue = dropdown && dropdown.options && dropdown.options.find(option => option.value === value); + + return dropdownValue ? dropdownValue.label : value; + } } From f1ad4d25aa51030055ff4509163995a7359f8f48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 2 Aug 2019 13:41:27 -0400 Subject: [PATCH 3/9] update changelog --- CHANGELOG.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8dc950fa..9164f96be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,9 +26,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Additionally clearing the column will reset the filter for the affected column(s) [#318](https://github.com/plotly/dash-table/issues/318) -- Headers are included when copying from the table to different -tabs and elsewhere. They are ignored when copying from the table onto itself and -between two tables within the same tab. +- Headers are included when copying from the table to different +tabs and elsewhere. They are ignored when copying from the table onto itself and +between two tables within the same tab. ### Changed [#497](https://github.com/plotly/dash-table/pull/497) @@ -36,6 +36,9 @@ between two tables within the same tab. reset the filter for the affected column(s) ### Fixed +[#524](https://github.com/plotly/dash-table/issues/524) +- Fixed readonly dropdown cells content (display label, not value) + [#491](https://github.com/plotly/dash-table/issues/491) - Fixed inconsistent behaviors when editing cell headers From b5de56cd38ad8253d7c99a2bc6e64b02d844832a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 2 Aug 2019 13:57:08 -0400 Subject: [PATCH 4/9] update standalone app dropdowns (label != value) --- demo/AppMode.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/demo/AppMode.ts b/demo/AppMode.ts index 788823a74..0dd4715aa 100644 --- a/demo/AppMode.ts +++ b/demo/AppMode.ts @@ -56,7 +56,14 @@ function getBaseTableProps(mock: IDataMock) { bbb: { clearable: true, options: ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'].map(i => ({ - label: i, + label: `label: ${i}`, + value: i + })) + }, + 'bbb-readonly': { + clearable: true, + options: ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'].map(i => ({ + label: `label: ${i}`, value: i })) } From 234f87c4a14dcb98ca716ada0fe0352b69ebc697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 2 Aug 2019 14:26:12 -0400 Subject: [PATCH 5/9] - update tests for new labels - test both the editable and readonly versions of the dropdown --- .../tests/standalone/readonly_sorting_test.ts | 26 +++++++++++++------ .../standalone/readwrite_sorting_test.ts | 26 +++++++++++++------ 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/tests/cypress/tests/standalone/readonly_sorting_test.ts b/tests/cypress/tests/standalone/readonly_sorting_test.ts index 716905e9a..65e7241e3 100644 --- a/tests/cypress/tests/standalone/readonly_sorting_test.ts +++ b/tests/cypress/tests/standalone/readonly_sorting_test.ts @@ -10,15 +10,25 @@ Object.values([AppMode.ReadOnly]).forEach(mode => { }); it('can sort', () => { - DashTable.getCell(0, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'Wet')); - DashTable.getCell(1, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'Snowy')); - DashTable.getCell(2, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'Tropical Beaches')); - DashTable.getCell(3, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'Humid')); + DashTable.getCell(0, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Wet')); + DashTable.getCell(1, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Snowy')); + DashTable.getCell(2, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Tropical Beaches')); + DashTable.getCell(3, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); + + DashTable.getCell(0, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Wet')); + DashTable.getCell(1, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Snowy')); + DashTable.getCell(2, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Tropical Beaches')); + DashTable.getCell(3, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); cy.get('tr th.column-6 .sort').last().click(); - DashTable.getCell(0, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'Humid')); - DashTable.getCell(1, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'Humid')); - DashTable.getCell(2, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'Humid')); - DashTable.getCell(3, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'Humid')); + DashTable.getCell(0, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); + DashTable.getCell(1, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); + DashTable.getCell(2, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); + DashTable.getCell(3, 6).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); + + DashTable.getCell(0, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); + DashTable.getCell(1, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); + DashTable.getCell(2, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); + DashTable.getCell(3, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); }); }); }); \ No newline at end of file diff --git a/tests/cypress/tests/standalone/readwrite_sorting_test.ts b/tests/cypress/tests/standalone/readwrite_sorting_test.ts index ce53b99d1..512b1d429 100644 --- a/tests/cypress/tests/standalone/readwrite_sorting_test.ts +++ b/tests/cypress/tests/standalone/readwrite_sorting_test.ts @@ -10,15 +10,25 @@ Object.values(ReadWriteModes).forEach(mode => { }); it('can sort', () => { - DashTable.getCell(0, 6).within(() => cy.get('.Select-value-label').should('have.html', 'Wet')); - DashTable.getCell(1, 6).within(() => cy.get('.Select-value-label').should('have.html', 'Snowy')); - DashTable.getCell(2, 6).within(() => cy.get('.Select-value-label').should('have.html', 'Tropical Beaches')); - DashTable.getCell(3, 6).within(() => cy.get('.Select-value-label').should('have.html', 'Humid')); + DashTable.getCell(0, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Wet')); + DashTable.getCell(1, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Snowy')); + DashTable.getCell(2, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Tropical Beaches')); + DashTable.getCell(3, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); + + DashTable.getCell(0, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Wet')); + DashTable.getCell(1, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Snowy')); + DashTable.getCell(2, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Tropical Beaches')); + DashTable.getCell(3, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); cy.get('tr th.column-6 .sort').last().click(); - DashTable.getCell(0, 6).within(() => cy.get('.Select-value-label').should('have.html', 'Humid')); - DashTable.getCell(1, 6).within(() => cy.get('.Select-value-label').should('have.html', 'Humid')); - DashTable.getCell(2, 6).within(() => cy.get('.Select-value-label').should('have.html', 'Humid')); - DashTable.getCell(3, 6).within(() => cy.get('.Select-value-label').should('have.html', 'Humid')); + DashTable.getCell(0, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); + DashTable.getCell(1, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); + DashTable.getCell(2, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); + DashTable.getCell(3, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); + + DashTable.getCell(0, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); + DashTable.getCell(1, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); + DashTable.getCell(2, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); + DashTable.getCell(3, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); }); }); }); \ No newline at end of file From 0a98f3e1669c64bf68b58e03fb392b3407de1b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 2 Aug 2019 14:37:43 -0400 Subject: [PATCH 6/9] fix test selector --- .../tests/standalone/readwrite_sorting_test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/cypress/tests/standalone/readwrite_sorting_test.ts b/tests/cypress/tests/standalone/readwrite_sorting_test.ts index 512b1d429..3a21e18cc 100644 --- a/tests/cypress/tests/standalone/readwrite_sorting_test.ts +++ b/tests/cypress/tests/standalone/readwrite_sorting_test.ts @@ -15,20 +15,20 @@ Object.values(ReadWriteModes).forEach(mode => { DashTable.getCell(2, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Tropical Beaches')); DashTable.getCell(3, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); - DashTable.getCell(0, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Wet')); - DashTable.getCell(1, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Snowy')); - DashTable.getCell(2, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Tropical Beaches')); - DashTable.getCell(3, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); + DashTable.getCell(0, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Wet')); + DashTable.getCell(1, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Snowy')); + DashTable.getCell(2, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Tropical Beaches')); + DashTable.getCell(3, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); cy.get('tr th.column-6 .sort').last().click(); DashTable.getCell(0, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); DashTable.getCell(1, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); DashTable.getCell(2, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); DashTable.getCell(3, 6).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); - DashTable.getCell(0, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); - DashTable.getCell(1, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); - DashTable.getCell(2, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); - DashTable.getCell(3, 7).within(() => cy.get('.Select-value-label').should('have.html', 'label: Humid')); + DashTable.getCell(0, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); + DashTable.getCell(1, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); + DashTable.getCell(2, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); + DashTable.getCell(3, 7).within(() => cy.get('.dash-cell-value').should('have.html', 'label: Humid')); }); }); }); \ No newline at end of file From 1605c116efb89ec294222743e85cd18d93cb5310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 2 Aug 2019 15:16:02 -0400 Subject: [PATCH 7/9] readonly dropdowns, for real --- demo/data.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/demo/data.ts b/demo/data.ts index 0b3df6de5..42f2f13d3 100644 --- a/demo/data.ts +++ b/demo/data.ts @@ -68,6 +68,7 @@ export const generateMockData = (rows: number) => unpackIntoColumnsAndData([ id: 'bbb-readonly', name: ['', 'Weather', 'Climate-RO'], type: ColumnType.Text, + presentation: 'dropdown', editable: false, data: gendata( i => ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'][i % 4], @@ -86,6 +87,7 @@ export const generateMockData = (rows: number) => unpackIntoColumnsAndData([ id: 'aaa-readonly', name: ['', 'Weather', 'Temperature-RO'], type: ColumnType.Numeric, + presentation: 'dropdown', editable: false, data: gendata(i => i + 1, rows) } From 776062b4d6aa4d34dc8dab15e8730b234c999fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 2 Aug 2019 15:30:20 -0400 Subject: [PATCH 8/9] update for new labels --- tests/cypress/tests/standalone/filtering_test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/cypress/tests/standalone/filtering_test.ts b/tests/cypress/tests/standalone/filtering_test.ts index a6bbb6053..08812dd15 100644 --- a/tests/cypress/tests/standalone/filtering_test.ts +++ b/tests/cypress/tests/standalone/filtering_test.ts @@ -12,7 +12,7 @@ describe(`filter special characters`, () => { it('can filter on special column id', () => { DashTable.getFilterById('b+bb').click(); - DOM.focused.type(`Wet${Key.Enter}`); + DOM.focused.type(`label: Wet${Key.Enter}`); DashTable.getFilterById('c cc').click(); DOM.focused.type(`gt 90${Key.Enter}`); @@ -32,7 +32,7 @@ describe(`filter special characters`, () => { DashTable.getCellById(0, 'rows').within(() => cy.get('.dash-cell-value').should('have.html', '101')); DashTable.getCellById(1, 'rows').should('not.exist'); - DashTable.getFilterById('b+bb').within(() => cy.get('input').should('have.value', 'Wet')); + DashTable.getFilterById('b+bb').within(() => cy.get('input').should('have.value', 'label: Wet')); DashTable.getFilterById('c cc').within(() => cy.get('input').should('have.value', 'gt 90')); DashTable.getFilterById('d:dd').within(() => cy.get('input').should('have.value', 'lt 12500')); DashTable.getFilterById('e-ee').within(() => cy.get('input').should('have.value', 'is prime')); @@ -143,13 +143,13 @@ describe('filter', () => { DashTable.getFilterById('eee').click(); DOM.focused.type('is prime'); DashTable.getFilterById('bbb').click(); - DOM.focused.type(`Wet`); + DOM.focused.type(`label: Wet`); DashTable.getFilterById('ccc').click(); DashTable.getCellById(0, 'ccc').within(() => cy.get('.dash-cell-value').should('have.html', '101')); DashTable.getCellById(1, 'ccc').within(() => cy.get('.dash-cell-value').should('have.html', '109')); - DashTable.getFilterById('bbb').within(() => cy.get('input').should('have.value', 'Wet')); + DashTable.getFilterById('bbb').within(() => cy.get('input').should('have.value', 'label: Wet')); DashTable.getFilterById('ccc').within(() => cy.get('input').should('have.value', 'gt 100')); DashTable.getFilterById('ddd').within(() => cy.get('input').should('have.value', 'lt 20000')); DashTable.getFilterById('eee').within(() => cy.get('input').should('have.value', 'is prime')); From 60b3fd7de960d3f854c87836420d7c671c38b55c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 2 Aug 2019 15:50:10 -0400 Subject: [PATCH 9/9] fix test usage (again) --- tests/cypress/tests/standalone/filtering_test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/cypress/tests/standalone/filtering_test.ts b/tests/cypress/tests/standalone/filtering_test.ts index 08812dd15..490303d56 100644 --- a/tests/cypress/tests/standalone/filtering_test.ts +++ b/tests/cypress/tests/standalone/filtering_test.ts @@ -12,7 +12,7 @@ describe(`filter special characters`, () => { it('can filter on special column id', () => { DashTable.getFilterById('b+bb').click(); - DOM.focused.type(`label: Wet${Key.Enter}`); + DOM.focused.type(`Wet${Key.Enter}`); DashTable.getFilterById('c cc').click(); DOM.focused.type(`gt 90${Key.Enter}`); @@ -32,7 +32,7 @@ describe(`filter special characters`, () => { DashTable.getCellById(0, 'rows').within(() => cy.get('.dash-cell-value').should('have.html', '101')); DashTable.getCellById(1, 'rows').should('not.exist'); - DashTable.getFilterById('b+bb').within(() => cy.get('input').should('have.value', 'label: Wet')); + DashTable.getFilterById('b+bb').within(() => cy.get('input').should('have.value', 'Wet')); DashTable.getFilterById('c cc').within(() => cy.get('input').should('have.value', 'gt 90')); DashTable.getFilterById('d:dd').within(() => cy.get('input').should('have.value', 'lt 12500')); DashTable.getFilterById('e-ee').within(() => cy.get('input').should('have.value', 'is prime')); @@ -101,7 +101,7 @@ describe('filter', () => { DashTable.getFilterById('ccc').click(); DashTable.getFilterById('bbb').within(() => cy.get('input').should('have.value', 'Tr')); - DashTable.getCellById(0, 'bbb-readonly').within(() => cy.get('.dash-cell-value').should('have.html', 'Tropical Beaches')); + DashTable.getCellById(0, 'bbb-readonly').within(() => cy.get('.dash-cell-value').should('have.html', 'label: Tropical Beaches')); }); it('filters `Numeric` columns with `equal` without operator', () => { @@ -143,13 +143,13 @@ describe('filter', () => { DashTable.getFilterById('eee').click(); DOM.focused.type('is prime'); DashTable.getFilterById('bbb').click(); - DOM.focused.type(`label: Wet`); + DOM.focused.type(`Wet`); DashTable.getFilterById('ccc').click(); DashTable.getCellById(0, 'ccc').within(() => cy.get('.dash-cell-value').should('have.html', '101')); DashTable.getCellById(1, 'ccc').within(() => cy.get('.dash-cell-value').should('have.html', '109')); - DashTable.getFilterById('bbb').within(() => cy.get('input').should('have.value', 'label: Wet')); + DashTable.getFilterById('bbb').within(() => cy.get('input').should('have.value', 'Wet')); DashTable.getFilterById('ccc').within(() => cy.get('input').should('have.value', 'gt 100')); DashTable.getFilterById('ddd').within(() => cy.get('input').should('have.value', 'lt 20000')); DashTable.getFilterById('eee').within(() => cy.get('input').should('have.value', 'is prime'));