From 0fd6f9641fd307cbc41aefff190e7ead10758cf0 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Thu, 11 Jul 2019 09:43:45 -0400 Subject: [PATCH 01/25] add merge_duplicate_headers parameter --- src/dash-table/components/HeaderFactory.tsx | 5 +-- src/dash-table/derived/header/content.tsx | 9 +++--- src/dash-table/utils/actions.js | 36 +++++++++++++++++---- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/dash-table/components/HeaderFactory.tsx b/src/dash-table/components/HeaderFactory.tsx index b11df1182..1f7b17b7e 100644 --- a/src/dash-table/components/HeaderFactory.tsx +++ b/src/dash-table/components/HeaderFactory.tsx @@ -50,7 +50,7 @@ export default class HeaderFactory { style_cell, style_cell_conditional, style_header, - style_header_conditional + style_header_conditional, } = props; const headerRows = getHeaderRows(columns); @@ -96,7 +96,8 @@ export default class HeaderFactory { sort_mode, sort_by, page_action, - setProps + setProps, + merge_duplicate_headers ); const ops = this.getHeaderOpCells( diff --git a/src/dash-table/derived/header/content.tsx b/src/dash-table/derived/header/content.tsx index 11fce31b5..947a4348f 100644 --- a/src/dash-table/derived/header/content.tsx +++ b/src/dash-table/derived/header/content.tsx @@ -55,9 +55,9 @@ function doSort(columnId: ColumnId, sortBy: SortBy, mode: SortMode, setProps: Se }; } -function editColumnName(column: IVisibleColumn, columns: VisibleColumns, columnRowIndex: any, setProps: SetProps) { +function editColumnName(column: IVisibleColumn, columns: VisibleColumns, columnRowIndex: any, setProps: SetProps, mergeDuplicateHeaders: boolean) { return () => { - setProps(actions.editColumnName(column, columns, columnRowIndex)); + setProps(actions.editColumnName(column, columns, columnRowIndex, mergeDuplicateHeaders)); }; } @@ -87,7 +87,8 @@ function getter( mode: SortMode, sortBy: SortBy, paginationMode: TableAction, - setProps: SetProps + setProps: SetProps, + merge_duplicate_headers: boolean ): JSX.Element[][] { return R.addIndex, JSX.Element[]>(R.map)( ([labels, indices], headerRowIndex) => { @@ -121,7 +122,7 @@ function getter( {renamable ? ( {`✎`} ) : diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index 3e1241d50..70f5f7eab 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -1,12 +1,20 @@ import * as R from 'ramda'; +import merge from 'ramda/es/merge'; -function getGroupedColumnIndices(column, columns, headerRowIndex) { +function findMaxLength(array) { + let maxLength = 0; + R.forEach(row => { if (row instanceof Array && row.length > maxLength) { + maxLength = row.length; + }}, array); + return maxLength; +} + +function getGroupedColumnIndices(column, columns, headerRowIndex, mergeDuplicateHeaders) { const columnIndex = columns.indexOf(column); - if (!column.name || (Array.isArray(column.name) && column.name.length < headerRowIndex)) { + if (!column.name || (Array.isArray(column.name) && column.name.length < headerRowIndex) || !mergeDuplicateHeaders) { return { groupIndexFirst: columnIndex, groupIndexLast: columnIndex }; } - let lastColumnIndex = columnIndex; for (let i = columnIndex; i < columns.length; ++i) { @@ -53,16 +61,30 @@ export const clearSelection = { selected_cells: [] }; -export function editColumnName(column, columns, headerRowIndex) { +export function editColumnName(column, columns, headerRowIndex, mergeDuplicateHeaders) { + let cloneColumn = Object.assign({}, column); + if ((typeof column.name === 'string') || (column.name instanceof String)) { + const columnHeaders = columns.map(col => col.name); + const maxLength = findMaxLength(columnHeaders); + const newColumnNames = Array(maxLength).fill(column.name); + cloneColumn = Object.assign(column, {name: newColumnNames}); + } + const transformedColumn = columns.map(col => { + if (col.name === column.name){ + return cloneColumn; + } else { + return col; + } + }) const { groupIndexFirst, groupIndexLast } = getGroupedColumnIndices( - column, columns, headerRowIndex + column, columns, headerRowIndex, mergeDuplicateHeaders ); /* eslint no-alert: 0 */ const newColumnName = window.prompt('Enter a new column name'); - let newColumns = R.clone(columns); + let newColumns = R.clone(transformedColumn); R.range(groupIndexFirst, groupIndexLast + 1).map(i => { let namePath; - if (R.type(columns[i].name) === 'Array') { + if (R.type(transformedColumn[i].name) === 'Array') { namePath = [i, 'name', headerRowIndex]; } else { namePath = [i, 'name']; From 4145c5c02f41ddf5a5fd76cddf4dc239bc2dca20 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Thu, 11 Jul 2019 14:32:29 -0400 Subject: [PATCH 02/25] refactor --- src/dash-table/utils/actions.js | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index 70f5f7eab..7fba32e82 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -10,7 +10,7 @@ function findMaxLength(array) { } function getGroupedColumnIndices(column, columns, headerRowIndex, mergeDuplicateHeaders) { - const columnIndex = columns.indexOf(column); + const columnIndex = columns.findIndex(col => col.id === column.id); if (!column.name || (Array.isArray(column.name) && column.name.length < headerRowIndex) || !mergeDuplicateHeaders) { return { groupIndexFirst: columnIndex, groupIndexLast: columnIndex }; @@ -61,16 +61,16 @@ export const clearSelection = { selected_cells: [] }; -export function editColumnName(column, columns, headerRowIndex, mergeDuplicateHeaders) { +export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplicateHeaders, newColumnName){ let cloneColumn = Object.assign({}, column); if ((typeof column.name === 'string') || (column.name instanceof String)) { const columnHeaders = columns.map(col => col.name); const maxLength = findMaxLength(columnHeaders); const newColumnNames = Array(maxLength).fill(column.name); - cloneColumn = Object.assign(column, {name: newColumnNames}); + cloneColumn = Object.assign({}, column, {name: newColumnNames}); } const transformedColumn = columns.map(col => { - if (col.name === column.name){ + if (((typeof column.name === 'string') || (column.name instanceof String)) && col.id === column.id) { return cloneColumn; } else { return col; @@ -79,19 +79,18 @@ export function editColumnName(column, columns, headerRowIndex, mergeDuplicateHe const { groupIndexFirst, groupIndexLast } = getGroupedColumnIndices( column, columns, headerRowIndex, mergeDuplicateHeaders ); - /* eslint no-alert: 0 */ - const newColumnName = window.prompt('Enter a new column name'); let newColumns = R.clone(transformedColumn); R.range(groupIndexFirst, groupIndexLast + 1).map(i => { let namePath; if (R.type(transformedColumn[i].name) === 'Array') { namePath = [i, 'name', headerRowIndex]; - } else { - namePath = [i, 'name']; } newColumns = R.set(R.lensPath(namePath), newColumnName, newColumns); }); - return { - columns: newColumns - }; + return { columns: newColumns} ; +} + +export function editColumnName(column, columns, headerRowIndex, mergeDuplicateHeaders) { + const newColumnName = window.prompt('Enter a new column name'); + return changeColumnHeader(column, columns, headerRowIndex, mergeDuplicateHeaders, newColumnName); } From 0cb825e39136b16f761f688a3da0c5b7d5f884ae Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Thu, 11 Jul 2019 14:32:36 -0400 Subject: [PATCH 03/25] unit testing --- tests/cypress/tests/unit/editColumnNames.ts | 117 ++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 tests/cypress/tests/unit/editColumnNames.ts diff --git a/tests/cypress/tests/unit/editColumnNames.ts b/tests/cypress/tests/unit/editColumnNames.ts new file mode 100644 index 000000000..34682e212 --- /dev/null +++ b/tests/cypress/tests/unit/editColumnNames.ts @@ -0,0 +1,117 @@ +import { changeColumnHeader } from 'dash-table/utils/actions'; + +describe('changeColumnHeader', () => { + const columns = [ + {id: 'rows', type: 'numeric', name: 'rows', renamable: true}, + {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, + {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, + {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, + {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + ]; + describe('merge_duplicate_headers = false', () => { + const merge_duplicate_headers = false; + + it('change a header name with column names as array, name[1] of column[1] should be AAA', () => { + const column = {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}; + const returnColumn = changeColumnHeader(column, columns, 1, merge_duplicate_headers, 'AAA'); + const expectedColumn = {columns :[ + {id: 'rows', type: 'numeric', name: 'rows', renamable: true}, + {id: 'aaaa', type: 'numeric', name: ['City', 'AAA', 'Toronto'], renamable: true}, + {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, + {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, + {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + ]}; + expect(expectedColumn).to.deep.equal(returnColumn); + }); + it('change a header name with column names as string, column[0] name should be array and name[0] should be BBB', () => { + const column = {id: 'rows', type: 'numeric', name: 'rows', renamable: true}; + const returnColumn = changeColumnHeader(column, columns, 0, merge_duplicate_headers, 'BBB'); + const expectedColumn = {columns :[ + {id: 'rows', type: 'numeric', name: ['BBB', 'rows', 'rows'], renamable: true}, + {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, + {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, + {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, + {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + ]}; + expect(expectedColumn).to.deep.equal(returnColumn); + }); + it('change a header name with column names as string, column[3] name should be array and name[2] should be CCC', () => { + const column = {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}; + const returnColumn = changeColumnHeader(column, columns, 2, merge_duplicate_headers, 'CCC'); + const expectedColumn = {columns :[ + {id: 'rows', type: 'numeric', name: 'rows', renamable: true}, + {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, + {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, + {id: 'cccc', type: 'numeric', name: ['City', 'America', 'CCC'], renamable: true}, + {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + ]}; + expect(expectedColumn).to.deep.equal(returnColumn); + }); + }); + + describe('merge_duplicate_headers = true', () => { + const merge_duplicate_headers = true; + + it('change a header name with column names as array, all City should change to Ville', () => { + const column = {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}; + const returnColumn = changeColumnHeader(column, columns, 0, merge_duplicate_headers, 'Ville'); + const expectedColumn = {columns :[ + {id: 'rows', type: 'numeric', name: 'rows', renamable: true}, + {id: 'aaaa', type: 'numeric', name: ['Ville', 'Canada', 'Toronto'], renamable: true}, + {id: 'bbbb', type: 'numeric', name: ['Ville', 'Canada', 'Montreal'], renamable: true}, + {id: 'cccc', type: 'numeric', name: ['Ville', 'America', 'Boston'], renamable: true}, + {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + ]}; + expect(expectedColumn).to.deep.equal(returnColumn); + }); + it('change a header name with column names as array, all Canada should change to Kanada', () => { + const column = {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}; + const returnColumn = changeColumnHeader(column, columns, 1, merge_duplicate_headers, 'Kanada'); + const expectedColumn = {columns :[ + {id: 'rows', type: 'numeric', name: 'rows', renamable: true}, + {id: 'aaaa', type: 'numeric', name: ['City', 'Kanada', 'Toronto'], renamable: true}, + {id: 'bbbb', type: 'numeric', name: ['City', 'Kanada', 'Montreal'], renamable: true}, + {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, + {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + ]}; + expect(expectedColumn).to.deep.equal(returnColumn); + }); + it('change a header name with column names as array, New York should change to Maui', () => { + const column = {id: 'dddd', type: 'numeric', name: ['', 'America', 'New York'], renamable: true}; + const returnColumn = changeColumnHeader(column, columns, 2, merge_duplicate_headers, 'Maui'); + const expectedColumn = {columns :[ + {id: 'rows', type: 'numeric', name: 'rows', renamable: true}, + {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, + {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, + {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, + {id: 'dddd', type: 'text', name: ['', 'America', 'Maui'], renamable: true} + ]}; + expect(expectedColumn).to.deep.equal(returnColumn); + }); + it('change a header name with column names as string, column[0] name should be [City, rows, rows ]', () => { + const column = {id: 'rows', type: 'numeric', name: 'rows', renamable: true}; + const returnColumn = changeColumnHeader(column, columns, 0, merge_duplicate_headers, 'City'); + const expectedColumn = {columns :[ + {id: 'rows', type: 'numeric', name: ['City', 'rows', 'rows'], renamable: true}, + {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, + {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, + {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, + {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + ]}; + expect(expectedColumn).to.deep.equal(returnColumn); + }); + it('change a header name with column names as string, column[0] name should be [rows, ABC, rows ]', () => { + const column = {id: 'rows', type: 'numeric', name: 'rows', renamable: true}; + const returnColumn = changeColumnHeader(column, columns, 1, merge_duplicate_headers, 'ABC'); + const expectedColumn = {columns :[ + {id: 'rows', type: 'numeric', name: ['rows', 'ABC', 'rows'], renamable: true}, + {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, + {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, + {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, + {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + ]}; + expect(expectedColumn).to.deep.equal(returnColumn); + }); + }); +}); + From a40c4fdf6b7f1195e847a2d43a292fbb50e7d009 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Thu, 11 Jul 2019 16:45:46 -0400 Subject: [PATCH 04/25] sanity tests for merged and unmerged mode --- .../tests/standalone/edit_cell_test.ts | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/cypress/tests/standalone/edit_cell_test.ts b/tests/cypress/tests/standalone/edit_cell_test.ts index 7f298f452..5f8633e2e 100644 --- a/tests/cypress/tests/standalone/edit_cell_test.ts +++ b/tests/cypress/tests/standalone/edit_cell_test.ts @@ -206,7 +206,58 @@ describe(`edit, mode=${AppMode.Typed}`, () => { ); }); }); + + }); +}); + +describe.only(`edit headers, mode=${AppMode.Typed}`, () => { + beforeEach(() => { + cy.visit(`http://localhost:8080?mode=${AppMode.Typed}`); + DashTable.toggleScroll(false); + }); + + it('changing the column 0 header should not change any column 0 headers below it ', () => { + cy.window().then((win: any) => { + cy.stub(win, 'prompt').returns('Hello'); + }); + cy.get('.dash-header.column-0 .column-header--edit').eq(0).click(); + cy.get('.dash-header.column-0 > div > span:last-child').should('have.html', `Hello`); + cy.get('table > tbody > tr:nth-child(2) > th.dash-header.column-0 > div > span:last-child').should('have.html', `rows`); }); + + it('changing the column 1 header should not change any other headers', () => { + cy.window().then((win: any) => { + cy.stub(win, 'prompt').returns('Aloha'); + }); + cy.get('.dash-header.column-1 .column-header--edit').eq(0).click(); + cy.get('.dash-header.column-1 > div > span:last-child').should('have.html', `Aloha`); + cy.get('.dash-header.column-2 > div > span:last-child').should('have.html', `City`); + }); +}); + +describe(`edit headers, mode=${AppMode.MergeDuplicateHeaders}`, () => { + beforeEach(() => { + cy.visit(`http://localhost:8080?mode=${AppMode.MergeDuplicateHeaders}`); + DashTable.toggleScroll(false); + }); + it('changing the column 0 header should not change any column 0 headers below it ', () => { + cy.window().then((win: any) => { + cy.stub(win, 'prompt').returns('Otter'); + }); + cy.get('.dash-header.column-0 .column-header--edit').eq(0).click(); + cy.get('.dash-header.column-0 > div > span:last-child').should('have.html', `Otter`); + cy.get('table > tbody > tr:nth-child(2) > th.dash-header.column-0 > div > span:last-child').should('have.html', `rows`); + }); + it('changing the column 1 header should not change any other headers', () => { + cy.window().then((win: any) => { + cy.stub(win, 'prompt').returns('Aloha'); + }); + cy.get('.dash-header.column-1 .column-header--edit').eq(0).click(); + cy.get('.dash-header.column-0 > div > span:last-child').should('have.html', `rows`); + cy.get('.dash-header.column-1 > div > span:last-child').should('have.html', `Aloha`); + cy.get('.dash-header.column-6 > div > span:last-child').should('have.html', ``); + }); + }); describe(`edit, mode=${AppMode.Date}`, () => { From a81d2e982f36640949bdf15f5d7a6a443279d855 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Thu, 11 Jul 2019 16:47:41 -0400 Subject: [PATCH 05/25] comma typo --- src/dash-table/components/HeaderFactory.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dash-table/components/HeaderFactory.tsx b/src/dash-table/components/HeaderFactory.tsx index 1f7b17b7e..c9ebfd26f 100644 --- a/src/dash-table/components/HeaderFactory.tsx +++ b/src/dash-table/components/HeaderFactory.tsx @@ -50,7 +50,7 @@ export default class HeaderFactory { style_cell, style_cell_conditional, style_header, - style_header_conditional, + style_header_conditional } = props; const headerRows = getHeaderRows(columns); From 0a681179e6b34bc12561f825df86bdaba0ec79b4 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Thu, 11 Jul 2019 17:00:45 -0400 Subject: [PATCH 06/25] add CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a16c4452..f6416f935 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +#[Unreleased] +### Fixed +[#491](https://github.com/plotly/dash-table/issues/491) +- Fixed unconsistent behaviors when editing cell headers + ## [4.0.1] - 2019-07-09 ### Changed [#488](https://github.com/plotly/dash-table/pull/488) From 1854d3f8b9fccbbce0e251442d1f42d89dfa6cb9 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Thu, 11 Jul 2019 17:07:42 -0400 Subject: [PATCH 07/25] linting --- tests/cypress/tests/unit/editColumnNames.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tests/cypress/tests/unit/editColumnNames.ts b/tests/cypress/tests/unit/editColumnNames.ts index 34682e212..5560213a4 100644 --- a/tests/cypress/tests/unit/editColumnNames.ts +++ b/tests/cypress/tests/unit/editColumnNames.ts @@ -14,7 +14,7 @@ describe('changeColumnHeader', () => { it('change a header name with column names as array, name[1] of column[1] should be AAA', () => { const column = {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}; const returnColumn = changeColumnHeader(column, columns, 1, merge_duplicate_headers, 'AAA'); - const expectedColumn = {columns :[ + const expectedColumn = {columns : [ {id: 'rows', type: 'numeric', name: 'rows', renamable: true}, {id: 'aaaa', type: 'numeric', name: ['City', 'AAA', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, @@ -26,7 +26,7 @@ describe('changeColumnHeader', () => { it('change a header name with column names as string, column[0] name should be array and name[0] should be BBB', () => { const column = {id: 'rows', type: 'numeric', name: 'rows', renamable: true}; const returnColumn = changeColumnHeader(column, columns, 0, merge_duplicate_headers, 'BBB'); - const expectedColumn = {columns :[ + const expectedColumn = {columns : [ {id: 'rows', type: 'numeric', name: ['BBB', 'rows', 'rows'], renamable: true}, {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, @@ -38,7 +38,7 @@ describe('changeColumnHeader', () => { it('change a header name with column names as string, column[3] name should be array and name[2] should be CCC', () => { const column = {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}; const returnColumn = changeColumnHeader(column, columns, 2, merge_duplicate_headers, 'CCC'); - const expectedColumn = {columns :[ + const expectedColumn = {columns : [ {id: 'rows', type: 'numeric', name: 'rows', renamable: true}, {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, @@ -55,7 +55,7 @@ describe('changeColumnHeader', () => { it('change a header name with column names as array, all City should change to Ville', () => { const column = {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}; const returnColumn = changeColumnHeader(column, columns, 0, merge_duplicate_headers, 'Ville'); - const expectedColumn = {columns :[ + const expectedColumn = {columns : [ {id: 'rows', type: 'numeric', name: 'rows', renamable: true}, {id: 'aaaa', type: 'numeric', name: ['Ville', 'Canada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['Ville', 'Canada', 'Montreal'], renamable: true}, @@ -67,7 +67,7 @@ describe('changeColumnHeader', () => { it('change a header name with column names as array, all Canada should change to Kanada', () => { const column = {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}; const returnColumn = changeColumnHeader(column, columns, 1, merge_duplicate_headers, 'Kanada'); - const expectedColumn = {columns :[ + const expectedColumn = {columns : [ {id: 'rows', type: 'numeric', name: 'rows', renamable: true}, {id: 'aaaa', type: 'numeric', name: ['City', 'Kanada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Kanada', 'Montreal'], renamable: true}, @@ -79,7 +79,7 @@ describe('changeColumnHeader', () => { it('change a header name with column names as array, New York should change to Maui', () => { const column = {id: 'dddd', type: 'numeric', name: ['', 'America', 'New York'], renamable: true}; const returnColumn = changeColumnHeader(column, columns, 2, merge_duplicate_headers, 'Maui'); - const expectedColumn = {columns :[ + const expectedColumn = {columns : [ {id: 'rows', type: 'numeric', name: 'rows', renamable: true}, {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, @@ -91,7 +91,7 @@ describe('changeColumnHeader', () => { it('change a header name with column names as string, column[0] name should be [City, rows, rows ]', () => { const column = {id: 'rows', type: 'numeric', name: 'rows', renamable: true}; const returnColumn = changeColumnHeader(column, columns, 0, merge_duplicate_headers, 'City'); - const expectedColumn = {columns :[ + const expectedColumn = {columns : [ {id: 'rows', type: 'numeric', name: ['City', 'rows', 'rows'], renamable: true}, {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, @@ -103,7 +103,7 @@ describe('changeColumnHeader', () => { it('change a header name with column names as string, column[0] name should be [rows, ABC, rows ]', () => { const column = {id: 'rows', type: 'numeric', name: 'rows', renamable: true}; const returnColumn = changeColumnHeader(column, columns, 1, merge_duplicate_headers, 'ABC'); - const expectedColumn = {columns :[ + const expectedColumn = {columns : [ {id: 'rows', type: 'numeric', name: ['rows', 'ABC', 'rows'], renamable: true}, {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, @@ -113,5 +113,4 @@ describe('changeColumnHeader', () => { expect(expectedColumn).to.deep.equal(returnColumn); }); }); -}); - +}); \ No newline at end of file From 7f0a3bb85cb2cf15d9fc2bd9824431cf03455a72 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Thu, 11 Jul 2019 21:54:42 -0400 Subject: [PATCH 08/25] linting --- src/dash-table/utils/actions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index 7fba32e82..c6f85d628 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -61,7 +61,7 @@ export const clearSelection = { selected_cells: [] }; -export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplicateHeaders, newColumnName){ +export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplicateHeaders, newColumnName) { let cloneColumn = Object.assign({}, column); if ((typeof column.name === 'string') || (column.name instanceof String)) { const columnHeaders = columns.map(col => col.name); @@ -75,7 +75,7 @@ export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplica } else { return col; } - }) + }); const { groupIndexFirst, groupIndexLast } = getGroupedColumnIndices( column, columns, headerRowIndex, mergeDuplicateHeaders ); From cbdfe1478df88695d9aa5dfe98205f62d7087322 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Thu, 11 Jul 2019 21:56:03 -0400 Subject: [PATCH 09/25] add merge duplicate headers mode --- demo/AppMode.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/demo/AppMode.ts b/demo/AppMode.ts index 06f3fa470..c92b5a2f7 100644 --- a/demo/AppMode.ts +++ b/demo/AppMode.ts @@ -20,6 +20,7 @@ export enum AppMode { FixedTooltips = 'fixed,tooltips', FixedVirtualized = 'fixed,virtualized', Formatting = 'formatting', + MergeDuplicateHeaders = 'mergeDuplicateHeaders', ReadOnly = 'readonly', ColumnsInSpace = 'columnsInSpace', TaleOfTwoTables = 'taleOfTwoTables', @@ -312,6 +313,13 @@ function getFormattingState() { return state; } +function getMergeDuplicateHeadersState() { + const state = getDefaultState(); + state.tableProps.merge_duplicate_headers = true; + return state; +} + + function getState() { const mode = Environment.searchParams.get('mode'); @@ -330,6 +338,8 @@ function getState() { return getReadonlyState(); case AppMode.ColumnsInSpace: return getSpaceInColumn(); + case AppMode.MergeDuplicateHeaders: + return getMergeDuplicateHeadersState(); case AppMode.Tooltips: return getTooltipsState(); case AppMode.Virtualized: From eed1e4c2124941608c35cab95d8034503083ba1f Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Thu, 11 Jul 2019 21:56:23 -0400 Subject: [PATCH 10/25] linting --- demo/AppMode.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/demo/AppMode.ts b/demo/AppMode.ts index c92b5a2f7..a23e6e55d 100644 --- a/demo/AppMode.ts +++ b/demo/AppMode.ts @@ -319,7 +319,6 @@ function getMergeDuplicateHeadersState() { return state; } - function getState() { const mode = Environment.searchParams.get('mode'); From f69106e5a9639ab1f7831f4cdabb0860bd1579f0 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Fri, 12 Jul 2019 11:00:51 -0400 Subject: [PATCH 11/25] semantic --- src/dash-table/utils/actions.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index c6f85d628..e37ffb6a2 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -69,7 +69,7 @@ export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplica const newColumnNames = Array(maxLength).fill(column.name); cloneColumn = Object.assign({}, column, {name: newColumnNames}); } - const transformedColumn = columns.map(col => { + const transformedColumns = columns.map(col => { if (((typeof column.name === 'string') || (column.name instanceof String)) && col.id === column.id) { return cloneColumn; } else { @@ -79,10 +79,10 @@ export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplica const { groupIndexFirst, groupIndexLast } = getGroupedColumnIndices( column, columns, headerRowIndex, mergeDuplicateHeaders ); - let newColumns = R.clone(transformedColumn); + let newColumns = R.clone(transformedColumns); R.range(groupIndexFirst, groupIndexLast + 1).map(i => { let namePath; - if (R.type(transformedColumn[i].name) === 'Array') { + if (R.type(transformedColumns[i].name) === 'Array') { namePath = [i, 'name', headerRowIndex]; } newColumns = R.set(R.lensPath(namePath), newColumnName, newColumns); From 9e4c3ab5437b2e369d6306e98bfd018dbcacc298 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Mon, 15 Jul 2019 11:06:03 -0400 Subject: [PATCH 12/25] remove merge --- dash-main | 1 + src/dash-table/utils/actions.js | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) create mode 160000 dash-main diff --git a/dash-main b/dash-main new file mode 160000 index 000000000..9819e5eb6 --- /dev/null +++ b/dash-main @@ -0,0 +1 @@ +Subproject commit 9819e5eb6f7dcdd1c828c5e070af41f76214b6ff diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index e37ffb6a2..88b7106e4 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -1,5 +1,4 @@ import * as R from 'ramda'; -import merge from 'ramda/es/merge'; function findMaxLength(array) { let maxLength = 0; From 641c6dca710b574bc17576e92e064362936ba895 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Mon, 15 Jul 2019 11:38:59 -0400 Subject: [PATCH 13/25] remove object.assign and use R.merge --- src/dash-table/utils/actions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index 88b7106e4..77442cde1 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -61,12 +61,12 @@ export const clearSelection = { }; export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplicateHeaders, newColumnName) { - let cloneColumn = Object.assign({}, column); + let cloneColumn = R.merge({}, column); if ((typeof column.name === 'string') || (column.name instanceof String)) { const columnHeaders = columns.map(col => col.name); const maxLength = findMaxLength(columnHeaders); const newColumnNames = Array(maxLength).fill(column.name); - cloneColumn = Object.assign({}, column, {name: newColumnNames}); + cloneColumn = R.merge(column, {name: newColumnNames}); } const transformedColumns = columns.map(col => { if (((typeof column.name === 'string') || (column.name instanceof String)) && col.id === column.id) { From fe03464250693401b9004b554a204e3e6218d6e1 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Mon, 15 Jul 2019 11:39:46 -0400 Subject: [PATCH 14/25] remove instanceof string --- src/dash-table/utils/actions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index 77442cde1..a2d5cd14c 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -62,7 +62,7 @@ export const clearSelection = { export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplicateHeaders, newColumnName) { let cloneColumn = R.merge({}, column); - if ((typeof column.name === 'string') || (column.name instanceof String)) { + if (typeof column.name === 'string') { const columnHeaders = columns.map(col => col.name); const maxLength = findMaxLength(columnHeaders); const newColumnNames = Array(maxLength).fill(column.name); From 8069962d50e383617b9ba9027a72f125ee5b5b09 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Mon, 15 Jul 2019 11:46:56 -0400 Subject: [PATCH 15/25] remove max length function --- src/dash-table/utils/actions.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index a2d5cd14c..b136c4578 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -1,12 +1,5 @@ import * as R from 'ramda'; - -function findMaxLength(array) { - let maxLength = 0; - R.forEach(row => { if (row instanceof Array && row.length > maxLength) { - maxLength = row.length; - }}, array); - return maxLength; -} +import getHeaderRows from 'dash-table/derived/header/headerRows'; function getGroupedColumnIndices(column, columns, headerRowIndex, mergeDuplicateHeaders) { const columnIndex = columns.findIndex(col => col.id === column.id); @@ -63,8 +56,7 @@ export const clearSelection = { export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplicateHeaders, newColumnName) { let cloneColumn = R.merge({}, column); if (typeof column.name === 'string') { - const columnHeaders = columns.map(col => col.name); - const maxLength = findMaxLength(columnHeaders); + const maxLength = getHeaderRows(columns); const newColumnNames = Array(maxLength).fill(column.name); cloneColumn = R.merge(column, {name: newColumnNames}); } From 1ca78e4a40bfaece4f48c5cab1a28c61564a6caa Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Mon, 15 Jul 2019 11:48:07 -0400 Subject: [PATCH 16/25] remove instanceof string --- src/dash-table/utils/actions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index b136c4578..e6ecf5589 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -61,7 +61,7 @@ export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplica cloneColumn = R.merge(column, {name: newColumnNames}); } const transformedColumns = columns.map(col => { - if (((typeof column.name === 'string') || (column.name instanceof String)) && col.id === column.id) { + if ((typeof column.name === 'string') && col.id === column.id) { return cloneColumn; } else { return col; From e4b98008597a2d0e5591c1774242ee5251ae5486 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Mon, 15 Jul 2019 12:03:11 -0400 Subject: [PATCH 17/25] dont need to transform if max length = 1 --- src/dash-table/utils/actions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index e6ecf5589..95a3df5ac 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -55,8 +55,8 @@ export const clearSelection = { export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplicateHeaders, newColumnName) { let cloneColumn = R.merge({}, column); - if (typeof column.name === 'string') { - const maxLength = getHeaderRows(columns); + const maxLength = getHeaderRows(columns); + if (typeof column.name === 'string' && maxLength > 1) { const newColumnNames = Array(maxLength).fill(column.name); cloneColumn = R.merge(column, {name: newColumnNames}); } From 6abfb1c334558b90f3435c9ea30c874d3939e311 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Mon, 15 Jul 2019 12:05:54 -0400 Subject: [PATCH 18/25] different way to create a column --- src/dash-table/utils/actions.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index 95a3df5ac..e9d4716a3 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -60,13 +60,8 @@ export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplica const newColumnNames = Array(maxLength).fill(column.name); cloneColumn = R.merge(column, {name: newColumnNames}); } - const transformedColumns = columns.map(col => { - if ((typeof column.name === 'string') && col.id === column.id) { - return cloneColumn; - } else { - return col; - } - }); + const transformedColumns = columns.slice(0); + transformedColumns[transformedColumns.indexOf(column)] = cloneColumn; const { groupIndexFirst, groupIndexLast } = getGroupedColumnIndices( column, columns, headerRowIndex, mergeDuplicateHeaders ); From 5aa1e73085125fd514229eed31a3c9097d46f50e Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Mon, 15 Jul 2019 14:04:15 -0400 Subject: [PATCH 19/25] add seperate edit headers --- .../tests/standalone/edit_cell_test.ts | 50 ---------------- .../cypress/tests/standalone/edit_headers.ts | 59 +++++++++++++++++++ 2 files changed, 59 insertions(+), 50 deletions(-) create mode 100644 tests/cypress/tests/standalone/edit_headers.ts diff --git a/tests/cypress/tests/standalone/edit_cell_test.ts b/tests/cypress/tests/standalone/edit_cell_test.ts index 5f8633e2e..45dfe086d 100644 --- a/tests/cypress/tests/standalone/edit_cell_test.ts +++ b/tests/cypress/tests/standalone/edit_cell_test.ts @@ -210,56 +210,6 @@ describe(`edit, mode=${AppMode.Typed}`, () => { }); }); -describe.only(`edit headers, mode=${AppMode.Typed}`, () => { - beforeEach(() => { - cy.visit(`http://localhost:8080?mode=${AppMode.Typed}`); - DashTable.toggleScroll(false); - }); - - it('changing the column 0 header should not change any column 0 headers below it ', () => { - cy.window().then((win: any) => { - cy.stub(win, 'prompt').returns('Hello'); - }); - cy.get('.dash-header.column-0 .column-header--edit').eq(0).click(); - cy.get('.dash-header.column-0 > div > span:last-child').should('have.html', `Hello`); - cy.get('table > tbody > tr:nth-child(2) > th.dash-header.column-0 > div > span:last-child').should('have.html', `rows`); - }); - - it('changing the column 1 header should not change any other headers', () => { - cy.window().then((win: any) => { - cy.stub(win, 'prompt').returns('Aloha'); - }); - cy.get('.dash-header.column-1 .column-header--edit').eq(0).click(); - cy.get('.dash-header.column-1 > div > span:last-child').should('have.html', `Aloha`); - cy.get('.dash-header.column-2 > div > span:last-child').should('have.html', `City`); - }); -}); - -describe(`edit headers, mode=${AppMode.MergeDuplicateHeaders}`, () => { - beforeEach(() => { - cy.visit(`http://localhost:8080?mode=${AppMode.MergeDuplicateHeaders}`); - DashTable.toggleScroll(false); - }); - it('changing the column 0 header should not change any column 0 headers below it ', () => { - cy.window().then((win: any) => { - cy.stub(win, 'prompt').returns('Otter'); - }); - cy.get('.dash-header.column-0 .column-header--edit').eq(0).click(); - cy.get('.dash-header.column-0 > div > span:last-child').should('have.html', `Otter`); - cy.get('table > tbody > tr:nth-child(2) > th.dash-header.column-0 > div > span:last-child').should('have.html', `rows`); - }); - it('changing the column 1 header should not change any other headers', () => { - cy.window().then((win: any) => { - cy.stub(win, 'prompt').returns('Aloha'); - }); - cy.get('.dash-header.column-1 .column-header--edit').eq(0).click(); - cy.get('.dash-header.column-0 > div > span:last-child').should('have.html', `rows`); - cy.get('.dash-header.column-1 > div > span:last-child').should('have.html', `Aloha`); - cy.get('.dash-header.column-6 > div > span:last-child').should('have.html', ``); - }); - -}); - describe(`edit, mode=${AppMode.Date}`, () => { beforeEach(() => { cy.visit(`http://localhost:8080?mode=${AppMode.Date}`); diff --git a/tests/cypress/tests/standalone/edit_headers.ts b/tests/cypress/tests/standalone/edit_headers.ts new file mode 100644 index 000000000..9276dc059 --- /dev/null +++ b/tests/cypress/tests/standalone/edit_headers.ts @@ -0,0 +1,59 @@ +import DashTable from 'cypress/DashTable'; + +import { AppMode } from 'demo/AppMode'; + +describe(`edit, mode=${AppMode.Typed}`, () => { + beforeEach(() => { + cy.visit(`http://localhost:8080?mode=${AppMode.Typed}`); + DashTable.toggleScroll(false); + }); + + describe(`edit headers, mode=${AppMode.Typed}`, () => { + beforeEach(() => { + cy.visit(`http://localhost:8080?mode=${AppMode.Typed}`); + DashTable.toggleScroll(false); + }); + + it('changing the column 0 header should not change any column 0 headers below it ', () => { + cy.window().then((win: any) => { + cy.stub(win, 'prompt').returns('Hello'); + }); + cy.get('.dash-header.column-0 .column-header--edit').eq(0).click(); + cy.get('.dash-header.column-0 > div > span:last-child').should('have.html', `Hello`); + cy.get('table > tbody > tr:nth-child(2) > th.dash-header.column-0 > div > span:last-child').should('have.html', `rows`); + }); + + it('changing the column 1 header should not change any other headers', () => { + cy.window().then((win: any) => { + cy.stub(win, 'prompt').returns('Aloha'); + }); + cy.get('.dash-header.column-1 .column-header--edit').eq(0).click(); + cy.get('.dash-header.column-1 > div > span:last-child').should('have.html', `Aloha`); + cy.get('.dash-header.column-2 > div > span:last-child').should('have.html', `City`); + }); + }); + + describe(`edit headers, mode=${AppMode.MergeDuplicateHeaders}`, () => { + beforeEach(() => { + cy.visit(`http://localhost:8080?mode=${AppMode.MergeDuplicateHeaders}`); + DashTable.toggleScroll(false); + }); + it('changing the column 0 header should not change any column 0 headers below it ', () => { + cy.window().then((win: any) => { + cy.stub(win, 'prompt').returns('Otter'); + }); + cy.get('.dash-header.column-0 .column-header--edit').eq(0).click(); + cy.get('.dash-header.column-0 > div > span:last-child').should('have.html', `Otter`); + cy.get('table > tbody > tr:nth-child(2) > th.dash-header.column-0 > div > span:last-child').should('have.html', `rows`); + }); + it('changing the column 1 header should not change any other headers', () => { + cy.window().then((win: any) => { + cy.stub(win, 'prompt').returns('Aloha'); + }); + cy.get('.dash-header.column-1 .column-header--edit').eq(0).click(); + cy.get('.dash-header.column-0 > div > span:last-child').should('have.html', `rows`); + cy.get('.dash-header.column-1 > div > span:last-child').should('have.html', `Aloha`); + cy.get('.dash-header.column-6 > div > span:last-child').should('have.html', ``); + }); + }); +}); \ No newline at end of file From 257ff50341e9fdaf8ff1d5dec94f5ed3c33f6b25 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Mon, 15 Jul 2019 14:07:25 -0400 Subject: [PATCH 20/25] merge right instead of merge --- src/dash-table/utils/actions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index e9d4716a3..2fe118943 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -54,11 +54,11 @@ export const clearSelection = { }; export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplicateHeaders, newColumnName) { - let cloneColumn = R.merge({}, column); + let cloneColumn = R.mergeRight({}, column); const maxLength = getHeaderRows(columns); if (typeof column.name === 'string' && maxLength > 1) { const newColumnNames = Array(maxLength).fill(column.name); - cloneColumn = R.merge(column, {name: newColumnNames}); + cloneColumn = R.mergeRight(column, {name: newColumnNames}); } const transformedColumns = columns.slice(0); transformedColumns[transformedColumns.indexOf(column)] = cloneColumn; From a5f96abdbee9423a2abb11b118a4a2d2395c7e86 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Mon, 15 Jul 2019 14:10:10 -0400 Subject: [PATCH 21/25] linting --- tests/cypress/tests/standalone/edit_cell_test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cypress/tests/standalone/edit_cell_test.ts b/tests/cypress/tests/standalone/edit_cell_test.ts index 45dfe086d..7f298f452 100644 --- a/tests/cypress/tests/standalone/edit_cell_test.ts +++ b/tests/cypress/tests/standalone/edit_cell_test.ts @@ -206,7 +206,6 @@ describe(`edit, mode=${AppMode.Typed}`, () => { ); }); }); - }); }); From c4c2cb435d6ed564dd31a86c63568b3c5237f2a3 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Mon, 15 Jul 2019 15:26:50 -0400 Subject: [PATCH 22/25] change type in testing suite --- tests/cypress/tests/unit/editColumnNames.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/cypress/tests/unit/editColumnNames.ts b/tests/cypress/tests/unit/editColumnNames.ts index 5560213a4..304328703 100644 --- a/tests/cypress/tests/unit/editColumnNames.ts +++ b/tests/cypress/tests/unit/editColumnNames.ts @@ -6,7 +6,7 @@ describe('changeColumnHeader', () => { {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, - {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + {id: 'dddd', type: 'numeric', name: ['', 'America', 'New York'], renamable: true} ]; describe('merge_duplicate_headers = false', () => { const merge_duplicate_headers = false; @@ -19,7 +19,7 @@ describe('changeColumnHeader', () => { {id: 'aaaa', type: 'numeric', name: ['City', 'AAA', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, - {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + {id: 'dddd', type: 'numeric', name: ['', 'America', 'New York'], renamable: true} ]}; expect(expectedColumn).to.deep.equal(returnColumn); }); @@ -31,7 +31,7 @@ describe('changeColumnHeader', () => { {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, - {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + {id: 'dddd', type: 'numeric', name: ['', 'America', 'New York'], renamable: true} ]}; expect(expectedColumn).to.deep.equal(returnColumn); }); @@ -43,7 +43,7 @@ describe('changeColumnHeader', () => { {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, {id: 'cccc', type: 'numeric', name: ['City', 'America', 'CCC'], renamable: true}, - {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + {id: 'dddd', type: 'numeric', name: ['', 'America', 'New York'], renamable: true} ]}; expect(expectedColumn).to.deep.equal(returnColumn); }); @@ -60,7 +60,7 @@ describe('changeColumnHeader', () => { {id: 'aaaa', type: 'numeric', name: ['Ville', 'Canada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['Ville', 'Canada', 'Montreal'], renamable: true}, {id: 'cccc', type: 'numeric', name: ['Ville', 'America', 'Boston'], renamable: true}, - {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + {id: 'dddd', type: 'numeric', name: ['', 'America', 'New York'], renamable: true} ]}; expect(expectedColumn).to.deep.equal(returnColumn); }); @@ -72,7 +72,7 @@ describe('changeColumnHeader', () => { {id: 'aaaa', type: 'numeric', name: ['City', 'Kanada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Kanada', 'Montreal'], renamable: true}, {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, - {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + {id: 'dddd', type: 'numeric', name: ['', 'America', 'New York'], renamable: true} ]}; expect(expectedColumn).to.deep.equal(returnColumn); }); @@ -84,7 +84,7 @@ describe('changeColumnHeader', () => { {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, - {id: 'dddd', type: 'text', name: ['', 'America', 'Maui'], renamable: true} + {id: 'dddd', type: 'numeric', name: ['', 'America', 'Maui'], renamable: true} ]}; expect(expectedColumn).to.deep.equal(returnColumn); }); @@ -96,7 +96,7 @@ describe('changeColumnHeader', () => { {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, - {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + {id: 'dddd', type: 'numeric', name: ['', 'America', 'New York'], renamable: true} ]}; expect(expectedColumn).to.deep.equal(returnColumn); }); @@ -108,7 +108,7 @@ describe('changeColumnHeader', () => { {id: 'aaaa', type: 'numeric', name: ['City', 'Canada', 'Toronto'], renamable: true}, {id: 'bbbb', type: 'numeric', name: ['City', 'Canada', 'Montreal'], renamable: true}, {id: 'cccc', type: 'numeric', name: ['City', 'America', 'Boston'], renamable: true}, - {id: 'dddd', type: 'text', name: ['', 'America', 'New York'], renamable: true} + {id: 'dddd', type: 'numeric', name: ['', 'America', 'New York'], renamable: true} ]}; expect(expectedColumn).to.deep.equal(returnColumn); }); From 2f89274b8764d65e9c56fd97d1fe81ff8f8d3ed1 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Mon, 15 Jul 2019 15:28:20 -0400 Subject: [PATCH 23/25] columnIndex --- src/dash-table/utils/actions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index 2fe118943..b50eff159 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -61,7 +61,8 @@ export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplica cloneColumn = R.mergeRight(column, {name: newColumnNames}); } const transformedColumns = columns.slice(0); - transformedColumns[transformedColumns.indexOf(column)] = cloneColumn; + const columnIndex = columns.findIndex(col => col.id === column.id); + transformedColumns[columnIndex] = cloneColumn; const { groupIndexFirst, groupIndexLast } = getGroupedColumnIndices( column, columns, headerRowIndex, mergeDuplicateHeaders ); From 0de0a2b16b8ef4c25fe2d65e22a34c7f2c1fc883 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Tue, 16 Jul 2019 11:11:18 -0400 Subject: [PATCH 24/25] algorithm refactor --- src/dash-table/utils/actions.js | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index b50eff159..cdd84f4f3 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -1,9 +1,7 @@ import * as R from 'ramda'; import getHeaderRows from 'dash-table/derived/header/headerRows'; -function getGroupedColumnIndices(column, columns, headerRowIndex, mergeDuplicateHeaders) { - const columnIndex = columns.findIndex(col => col.id === column.id); - +function getGroupedColumnIndices(column, columns, headerRowIndex, mergeDuplicateHeaders, columnIndex) { if (!column.name || (Array.isArray(column.name) && column.name.length < headerRowIndex) || !mergeDuplicateHeaders) { return { groupIndexFirst: columnIndex, groupIndexLast: columnIndex }; } @@ -18,7 +16,6 @@ function getGroupedColumnIndices(column, columns, headerRowIndex, mergeDuplicate break; } } - return { groupIndexFirst: columnIndex, groupIndexLast: lastColumnIndex }; } @@ -54,22 +51,22 @@ export const clearSelection = { }; export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplicateHeaders, newColumnName) { - let cloneColumn = R.mergeRight({}, column); const maxLength = getHeaderRows(columns); + const columnIndex = columns.findIndex(col => col.id === column.id); + let newColumns = columns; if (typeof column.name === 'string' && maxLength > 1) { const newColumnNames = Array(maxLength).fill(column.name); - cloneColumn = R.mergeRight(column, {name: newColumnNames}); + const cloneColumn = R.mergeRight(column, {name: newColumnNames}); + newColumns = columns.slice(0); + newColumns[columnIndex] = cloneColumn; } - const transformedColumns = columns.slice(0); - const columnIndex = columns.findIndex(col => col.id === column.id); - transformedColumns[columnIndex] = cloneColumn; + const { groupIndexFirst, groupIndexLast } = getGroupedColumnIndices( - column, columns, headerRowIndex, mergeDuplicateHeaders + column, columns, headerRowIndex, mergeDuplicateHeaders, columnIndex ); - let newColumns = R.clone(transformedColumns); R.range(groupIndexFirst, groupIndexLast + 1).map(i => { let namePath; - if (R.type(transformedColumns[i].name) === 'Array') { + if (R.type(newColumns[i].name) === 'Array') { namePath = [i, 'name', headerRowIndex]; } newColumns = R.set(R.lensPath(namePath), newColumnName, newColumns); From 6634d59e5656a4243cad8899792a5fe1213cde10 Mon Sep 17 00:00:00 2001 From: alinastarkov Date: Tue, 16 Jul 2019 11:32:10 -0400 Subject: [PATCH 25/25] refactor --- src/dash-table/utils/actions.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/dash-table/utils/actions.js b/src/dash-table/utils/actions.js index cdd84f4f3..76affd6d0 100644 --- a/src/dash-table/utils/actions.js +++ b/src/dash-table/utils/actions.js @@ -51,19 +51,21 @@ export const clearSelection = { }; export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplicateHeaders, newColumnName) { - const maxLength = getHeaderRows(columns); - const columnIndex = columns.findIndex(col => col.id === column.id); let newColumns = columns; + const maxLength = getHeaderRows(newColumns); + const columnIndex = newColumns.findIndex(col => col.id === column.id); + if (typeof column.name === 'string' && maxLength > 1) { - const newColumnNames = Array(maxLength).fill(column.name); - const cloneColumn = R.mergeRight(column, {name: newColumnNames}); - newColumns = columns.slice(0); - newColumns[columnIndex] = cloneColumn; + const newColumnNames = Array(maxLength).fill(column.name); + const cloneColumn = R.mergeRight(column, {name: newColumnNames}); + newColumns = newColumns.slice(0); + newColumns[columnIndex] = cloneColumn; } const { groupIndexFirst, groupIndexLast } = getGroupedColumnIndices( - column, columns, headerRowIndex, mergeDuplicateHeaders, columnIndex + column, newColumns, headerRowIndex, mergeDuplicateHeaders, columnIndex ); + R.range(groupIndexFirst, groupIndexLast + 1).map(i => { let namePath; if (R.type(newColumns[i].name) === 'Array') { @@ -71,6 +73,7 @@ export function changeColumnHeader(column, columns, headerRowIndex, mergeDuplica } newColumns = R.set(R.lensPath(namePath), newColumnName, newColumns); }); + return { columns: newColumns} ; }