From 37a78b14be206bba8b1fdc2b65fdd46875e55c4b Mon Sep 17 00:00:00 2001 From: Ville Brofeldt <33317356+villebro@users.noreply.github.com> Date: Tue, 18 Apr 2023 18:56:15 +0300 Subject: [PATCH] feat(sqllab): add headers when copying results to clipboard (#23720) --- .../test/DataTablesPane.test.tsx | 2 +- superset-frontend/src/utils/common.js | 10 ++++++-- superset-frontend/src/utils/common.test.jsx | 24 +++++++++---------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx b/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx index 4a4a5203f..34dcf01bc 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx @@ -108,7 +108,7 @@ describe('DataTablesPane', () => { userEvent.click(screen.getByLabelText('Copy')); expect(copyToClipboardSpy).toHaveBeenCalledTimes(1); const value = await copyToClipboardSpy.mock.calls[0][0](); - expect(value).toBe('2009-01-01 00:00:00\tAction\n'); + expect(value).toBe('__timestamp\tgenre\n2009-01-01 00:00:00\tAction\n'); copyToClipboardSpy.mockRestore(); fetchMock.restore(); }); diff --git a/superset-frontend/src/utils/common.js b/superset-frontend/src/utils/common.js index 4bc702d44..e9418f9d3 100644 --- a/superset-frontend/src/utils/common.js +++ b/superset-frontend/src/utils/common.js @@ -78,14 +78,20 @@ export function optionFromValue(opt) { return { value: optionValue(opt), label: optionLabel(opt) }; } +function getColumnName(column) { + return column.name || column; +} + export function prepareCopyToClipboardTabularData(data, columns) { - let result = ''; + let result = columns.length + ? `${columns.map(getColumnName).join('\t')}\n` + : ''; for (let i = 0; i < data.length; i += 1) { const row = {}; for (let j = 0; j < columns.length; j += 1) { // JavaScript does not maintain the order of a mixed set of keys (i.e integers and strings) // the below function orders the keys based on the column names. - const key = columns[j].name || columns[j]; + const key = getColumnName(columns[j]); if (key in data[i]) { row[j] = data[i][key]; } else { diff --git a/superset-frontend/src/utils/common.test.jsx b/superset-frontend/src/utils/common.test.jsx index 59cba6e7b..a334b342c 100644 --- a/superset-frontend/src/utils/common.test.jsx +++ b/superset-frontend/src/utils/common.test.jsx @@ -50,28 +50,28 @@ describe('utils/common', () => { }); describe('prepareCopyToClipboardTabularData', () => { it('converts empty array', () => { - const array = []; - const column = []; - expect(prepareCopyToClipboardTabularData(array, column)).toEqual(''); + const data = []; + const columns = []; + expect(prepareCopyToClipboardTabularData(data, columns)).toEqual(''); }); it('converts non empty array', () => { - const array = [ + const data = [ { column1: 'lorem', column2: 'ipsum' }, { column1: 'dolor', column2: 'sit', column3: 'amet' }, ]; - const column = ['column1', 'column2', 'column3']; - expect(prepareCopyToClipboardTabularData(array, column)).toEqual( - 'lorem\tipsum\t\ndolor\tsit\tamet\n', + const columns = ['column1', 'column2', 'column3']; + expect(prepareCopyToClipboardTabularData(data, columns)).toEqual( + 'column1\tcolumn2\tcolumn3\nlorem\tipsum\t\ndolor\tsit\tamet\n', ); }); - it('includes 0 values', () => { - const array = [ + it('includes 0 values and handle column objects', () => { + const data = [ { column1: 0, column2: 0 }, { column1: 1, column2: -1, 0: 0 }, ]; - const column = ['column1', 'column2', '0']; - expect(prepareCopyToClipboardTabularData(array, column)).toEqual( - '0\t0\t\n1\t-1\t0\n', + const columns = [{ name: 'column1' }, { name: 'column2' }, { name: '0' }]; + expect(prepareCopyToClipboardTabularData(data, columns)).toEqual( + 'column1\tcolumn2\t0\n0\t0\t\n1\t-1\t0\n', ); }); });