From 9f319a3d45ddb860f5495238ed867bdbfbb1bfe9 Mon Sep 17 00:00:00 2001 From: CD Cabrera Date: Tue, 16 Aug 2022 10:26:08 -0400 Subject: [PATCH] fix(table): discovery-154 key generation (#140) --- .../__snapshots__/table.test.js.snap | 116 +++++++------ .../__snapshots__/tableHelpers.test.js.snap | 162 ++++++++++++++++-- .../table/__tests__/tableHelpers.test.js | 27 +-- src/components/table/table.js | 48 ++---- src/components/table/tableHelpers.js | 97 ++++------- 5 files changed, 285 insertions(+), 165 deletions(-) diff --git a/src/components/table/__tests__/__snapshots__/table.test.js.snap b/src/components/table/__tests__/__snapshots__/table.test.js.snap index d2c1d68f..21fb29c9 100644 --- a/src/components/table/__tests__/__snapshots__/table.test.js.snap +++ b/src/components/table/__tests__/__snapshots__/table.test.js.snap @@ -9,6 +9,7 @@ Array [ Object { "content": "dolor", "expandedContent": "dolor expandable content", + "key": "cell--0", "props": Object { "compoundExpand": Object { "isExpanded": true, @@ -17,6 +18,7 @@ Array [ "dataLabel": undefined, "isActionCell": undefined, "noPadding": undefined, + "style": undefined, "width": undefined, }, }, @@ -56,7 +58,7 @@ exports[`Table Component should allow expandable cell content: expandable cell c > 'lorem'", - "nan": "table-generatedid-", - "null": "table-generatedid-", - "number": "table-200", - "obj": "table-{\\"lorem\\":\\"ipsum\\"}", - "repeatNumber": "generatedid-", - "string": "table-lorem", - "undefined": "table-generatedid-", + "func": "lorem ipsum", + "node": + dolor sit + , + "null": "null", + "obj": "[object Object]", + "undefined": "", } `; exports[`TableHelpers should have specific functions: tableHelpers 1`] = ` Object { - "generateTableKey": [Function], + "parseContent": [Function], "tableHeader": [Function], "tableRows": [Function], } @@ -37,18 +36,22 @@ Object { "columnHeaders": Array [ Object { "content": "lorem", + "key": "head--0", }, Object { "content": "dolor", + "key": "head--1", "props": Object {}, }, Object { "content": "hello world", + "key": "head--2", }, Object { "content": hello world , + "key": "head--3", }, ], "headerSelectProps": Object {}, @@ -58,9 +61,11 @@ Object { "columnHeaders": Array [ Object { "content": "lorem", + "key": "head--0", }, Object { "content": "dolor", + "key": "head--1", "props": Object { "sort": Object { "columnIndex": 2, @@ -73,6 +78,7 @@ Object { }, Object { "content": "hello world", + "key": "head--2", }, ], "headerSelectProps": Object {}, @@ -82,13 +88,16 @@ Object { "columnHeaders": Array [ Object { "content": "lorem", + "key": "head--0", }, Object { "content": "dolor", + "key": "head--1", "props": Object {}, }, Object { "content": "hello world", + "key": "head--2", }, ], "headerSelectProps": Object { @@ -103,9 +112,11 @@ Object { "columnHeaders": Array [ Object { "content": "lorem", + "key": "head--0", }, Object { "content": "dolor", + "key": "head--1", "props": Object { "sort": Object { "columnIndex": 1, @@ -118,6 +129,7 @@ Object { }, Object { "content": "hello world", + "key": "head--2", }, ], "headerSelectProps": Object {}, @@ -145,10 +157,12 @@ Object { "cells": Array [ Object { "content": "lorem", + "key": "cell--0", }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--0", "rowIndex": 0, "select": undefined, }, @@ -158,6 +172,7 @@ Object { "content": "dolor", "expandedContent": "sit", "isExpanded": true, + "key": "cell--0", "props": Object { "compoundExpand": Object { "isExpanded": true, @@ -166,12 +181,14 @@ Object { "dataLabel": undefined, "isActionCell": undefined, "noPadding": undefined, + "style": undefined, "width": undefined, }, }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--1", "rowIndex": 1, "select": undefined, }, @@ -179,10 +196,12 @@ Object { "cells": Array [ Object { "content": "hello world", + "key": "cell--0", }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--2", "rowIndex": 2, "select": undefined, }, @@ -192,10 +211,12 @@ Object { "content": hello world , + "key": "cell--0", }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--3", "rowIndex": 3, "select": undefined, }, @@ -211,6 +232,7 @@ Object { "cells": Array [ Object { "content": "lorem", + "key": "cell--0", }, ], "expand": Object { @@ -219,6 +241,7 @@ Object { "rowIndex": 0, }, "expandedContent": "ipsum", + "key": "row--0", "rowIndex": 0, "select": undefined, }, @@ -226,16 +249,19 @@ Object { "cells": Array [ Object { "content": "dolor", + "key": "cell--0", "props": Object { "dataLabel": undefined, "isActionCell": undefined, "noPadding": undefined, + "style": undefined, "width": undefined, }, }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--1", "rowIndex": 1, "select": undefined, }, @@ -243,10 +269,12 @@ Object { "cells": Array [ Object { "content": "hello world", + "key": "cell--0", }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--2", "rowIndex": 2, "select": undefined, }, @@ -256,10 +284,12 @@ Object { "content": hello world , + "key": "cell--0", }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--3", "rowIndex": 3, "select": undefined, }, @@ -275,10 +305,12 @@ Object { "cells": Array [ Object { "content": "lorem", + "key": "cell--0", }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--0", "rowIndex": 0, "select": Object { "cells": Array [ @@ -294,16 +326,19 @@ Object { "cells": Array [ Object { "content": "dolor", + "key": "cell--0", "props": Object { "dataLabel": undefined, "isActionCell": undefined, "noPadding": undefined, + "style": undefined, "width": undefined, }, }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--1", "rowIndex": 1, "select": Object { "cells": Array [ @@ -321,10 +356,12 @@ Object { "cells": Array [ Object { "content": "hello world", + "key": "cell--0", }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--2", "rowIndex": 2, "select": Object { "cells": Array [ @@ -342,10 +379,12 @@ Object { "content": hello world , + "key": "cell--0", }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--3", "rowIndex": 3, "select": Object { "cells": Array [ @@ -371,10 +410,12 @@ Object { "cells": Array [ Object { "content": "lorem", + "key": "cell--0", }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--0", "rowIndex": 0, "select": undefined, }, @@ -382,16 +423,19 @@ Object { "cells": Array [ Object { "content": "dolor", + "key": "cell--0", "props": Object { "dataLabel": undefined, "isActionCell": undefined, "noPadding": undefined, + "style": undefined, "width": undefined, }, }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--1", "rowIndex": 1, "select": undefined, }, @@ -399,10 +443,12 @@ Object { "cells": Array [ Object { "content": "hello world", + "key": "cell--0", }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--2", "rowIndex": 2, "select": undefined, }, @@ -412,10 +458,106 @@ Object { "content": hello world , + "key": "cell--0", }, ], "expand": undefined, "expandedContent": undefined, + "key": "row--3", + "rowIndex": 3, + "select": undefined, + }, + ], + }, + "styling": Object { + "allRowsSelected": false, + "isExpandableCell": false, + "isExpandableRow": false, + "isSelectTable": false, + "rows": Array [ + Object { + "cells": Array [ + Object { + "content": "lorem", + "key": "cell--0", + "props": Object { + "dataLabel": undefined, + "isActionCell": undefined, + "noPadding": undefined, + "style": Object { + "width": "9px", + }, + }, + }, + ], + "expand": undefined, + "expandedContent": undefined, + "key": "row--0", + "rowIndex": 0, + "select": undefined, + }, + Object { + "cells": Array [ + Object { + "content": "dolor", + "key": "cell--0", + "props": Object { + "dataLabel": undefined, + "isActionCell": undefined, + "noPadding": undefined, + "style": Object { + "backgroundColor": "red", + "width": "50em", + }, + }, + }, + ], + "expand": undefined, + "expandedContent": undefined, + "key": "row--1", + "rowIndex": 1, + "select": undefined, + }, + Object { + "cells": Array [ + Object { + "content": "hello world", + "key": "cell--0", + "props": Object { + "dataLabel": undefined, + "isActionCell": undefined, + "noPadding": undefined, + "style": Object { + "width": "1%", + }, + }, + }, + ], + "expand": undefined, + "expandedContent": undefined, + "key": "row--2", + "rowIndex": 2, + "select": undefined, + }, + Object { + "cells": Array [ + Object { + "content": + hello world + , + "key": "cell--0", + "props": Object { + "dataLabel": undefined, + "isActionCell": undefined, + "noPadding": undefined, + "style": undefined, + "width": 11, + }, + }, + ], + "expand": undefined, + "expandedContent": undefined, + "key": "row--3", "rowIndex": 3, "select": undefined, }, diff --git a/src/components/table/__tests__/tableHelpers.test.js b/src/components/table/__tests__/tableHelpers.test.js index 8c8074d9..0b8e084a 100644 --- a/src/components/table/__tests__/tableHelpers.test.js +++ b/src/components/table/__tests__/tableHelpers.test.js @@ -1,22 +1,19 @@ import React from 'react'; -import { tableHelpers, generateTableKey, tableHeader, tableRows } from '../tableHelpers'; +import { tableHelpers, parseContent, tableHeader, tableRows } from '../tableHelpers'; describe('TableHelpers', () => { it('should have specific functions', () => { expect(tableHelpers).toMatchSnapshot('tableHelpers'); }); - it('generateTableKey should generate a variety of unique keys', () => { + it('parseContent should return a consistent output from multiple types', () => { expect({ - string: generateTableKey('lorem'), - func: generateTableKey(() => 'lorem'), - obj: generateTableKey({ lorem: 'ipsum' }), - null: generateTableKey(null), - undefined: generateTableKey(undefined), - nan: generateTableKey(NaN), - number: generateTableKey(200), - repeatNumber: generateTableKey(200) - }).toMatchSnapshot('keys'); + func: parseContent(() => 'lorem ipsum'), + node: parseContent(dolor sit), + null: parseContent(null), + obj: parseContent({ hello: 'world' }), + undefined: parseContent(undefined) + }).toMatchSnapshot('multiple types'); }); it('tableHeader should return parsed table header settings, props', () => { @@ -58,6 +55,14 @@ describe('TableHelpers', () => { { cells: [hello world] } ] }), + styling: tableRows({ + rows: [ + { cells: [{ content: 'lorem', width: '9px' }] }, + { cells: [{ content: 'dolor', style: { backgroundColor: 'red' }, width: '50em' }] }, + { cells: [{ content: () => 'hello world', width: 1 }] }, + { cells: [{ content: hello world, width: 11 }] } + ] + }), onExpandCells: tableRows({ onExpand: () => {}, rows: [ diff --git a/src/components/table/table.js b/src/components/table/table.js index d6e526d6..2ff7086e 100644 --- a/src/components/table/table.js +++ b/src/components/table/table.js @@ -257,13 +257,8 @@ const Table = ({ {updatedIsExpandableRow && } {updatedIsSelectTable && } - {updatedHeaders.map(({ content, props, sort }) => ( - + {updatedHeaders.map(({ key: cellKey, content, props, sort }) => ( + {content} ))} @@ -282,7 +277,7 @@ const Table = ({ return ( - {updatedRows.map(({ cells, expand, select, expandedContent }) => { + {updatedRows.map(({ key: rowKey, cells, expand, select, expandedContent }) => { const expandedCell = (updatedIsExpandableCell && cells.find(cell => cell?.props?.compoundExpand?.isExpanded === true)) || undefined; @@ -295,38 +290,22 @@ const Table = ({ undefined; return ( - - - {expand && ( - - )} - {select && ( - - )} - {cells.map(({ content, isTHeader, props: cellProps }) => { + + + {expand && } + {select && } + {cells.map(({ key: cellKey, content, isTHeader, props: cellProps }) => { const WrapperCell = (isTHeader && Th) || Td; return ( - + {content} ); })} {updatedIsExpandableRow && expandedRow && ( - + )} {updatedIsExpandableCell && expandedCell && ( - + - {expandedCell.expandedContent} + + {(typeof expandedCell.expandedContent === 'function' && expandedCell.expandedContent()) || + expandedCell.expandedContent} + )} diff --git a/src/components/table/tableHelpers.js b/src/components/table/tableHelpers.js index 81f5d103..72d5fca8 100644 --- a/src/components/table/tableHelpers.js +++ b/src/components/table/tableHelpers.js @@ -2,53 +2,18 @@ import React from 'react'; import { SortByDirection } from '@patternfly/react-table'; import { helpers } from '../../common'; -// ToDo: evaluate potential storage issues. /** - * Store generated keys, check for repeats. + * Allow additional content to display in cells. * - * @type {{}} + * @param {React.ReactNode|Function|object|*} content + * @returns {*|string} */ -const tableKeyCache = {}; - -/** - * Generate table keys, avoid potential repeats. - * - * @param {*} value - * @param {string} prefix - * @returns {string} - */ -const generateTableKey = (value, prefix = 'table') => { - let updatedValue = helpers.generateId(); - - if (value === undefined || value === null || Number.isNaN(value)) { - return `${prefix}-${updatedValue}`; - } - - switch (typeof value) { - case 'string': - updatedValue = value; - break; - case 'object': - try { - updatedValue = JSON.stringify(value); - } catch (e) { - // - } - break; - default: - updatedValue = value.toString(); - } - - let key = `${prefix}-${updatedValue}`; - - if (tableKeyCache[key]) { - key = helpers.generateId(); - } - - tableKeyCache[key] = true; - - return key; -}; +const parseContent = content => + (React.isValidElement(content) && content) || + (typeof content === 'function' && content()) || + (typeof content === 'object' && `${content}`) || + content || + ''; /** * Parse table header settings, props. @@ -75,10 +40,13 @@ const tableHeader = ({ allRowsSelected = false, columnHeaders = [], isRowExpand, } columnHeaders.forEach((columnHeader, index) => { + const key = `${helpers.generateId('head')}-${index}`; + if (columnHeader?.content !== undefined) { const { isSort, isSortActive, sortDirection = SortByDirection.asc, content, ...props } = columnHeader; const tempColumnHeader = { - content, + key, + content: parseContent(content), props }; @@ -111,11 +79,8 @@ const tableHeader = ({ allRowsSelected = false, columnHeaders = [], isRowExpand, updatedColumnHeaders.push(tempColumnHeader); } else { updatedColumnHeaders.push({ - content: - (React.isValidElement(columnHeader) && columnHeader) || - (typeof columnHeader === 'function' && columnHeader()) || - (typeof columnHeader === 'object' && `${columnHeader}`) || - columnHeader + key, + content: parseContent(columnHeader) }); } }); @@ -145,6 +110,7 @@ const tableRows = ({ onExpand, onSelect, rows = [] } = {}) => { rows.forEach(({ cells, isDisabled = false, isExpanded = false, isSelected = false, expandedContent }) => { const rowObj = { + key: undefined, cells: [], select: undefined, expand: undefined, @@ -152,6 +118,7 @@ const tableRows = ({ onExpand, onSelect, rows = [] } = {}) => { }; updatedRows.push(rowObj); rowObj.rowIndex = updatedRows.length - 1; + rowObj.key = `${helpers.generateId('row')}-${rowObj.rowIndex}`; if (typeof onSelect === 'function') { const updatedIsSelected = isSelected ?? false; @@ -185,9 +152,22 @@ const tableRows = ({ onExpand, onSelect, rows = [] } = {}) => { } cells.forEach((cell, cellIndex) => { + const cellKey = `${helpers.generateId('cell')}-${cellIndex}`; if (cell?.content !== undefined) { - const { dataLabel, isActionCell, noPadding, width, ...remainingProps } = cell; - const cellProps = { dataLabel, isActionCell, noPadding, width }; + const { content, dataLabel, isActionCell, noPadding, width, style, ...remainingProps } = cell; + const cellProps = { dataLabel, isActionCell, noPadding, style }; + let updatedWidth = width; + + // FixMe: PF doesn't appear to allow cell widths less than 10 + if (width < 10) { + updatedWidth = `${width}%`; + } + + if (typeof updatedWidth === 'string' || style) { + cellProps.style = { ...style, width: updatedWidth }; + } else { + cellProps.width = width; + } if (!isExpandableRow && cell?.expandedContent && typeof onExpand === 'function') { isExpandableCell = true; @@ -204,14 +184,11 @@ const tableRows = ({ onExpand, onSelect, rows = [] } = {}) => { }; } - rowObj.cells.push({ ...remainingProps, props: cellProps }); + rowObj.cells.push({ ...remainingProps, content: parseContent(content), key: cellKey, props: cellProps }); } else { rowObj.cells.push({ - content: - (React.isValidElement(cell) && cell) || - (typeof cell === 'function' && cell()) || - (typeof cell === 'object' && `${cell}`) || - cell + key: cellKey, + content: parseContent(cell) }); } }); @@ -227,9 +204,9 @@ const tableRows = ({ onExpand, onSelect, rows = [] } = {}) => { }; const tableHelpers = { - generateTableKey, + parseContent, tableHeader, tableRows }; -export { tableHelpers as default, tableHelpers, generateTableKey, tableHeader, tableRows }; +export { tableHelpers as default, tableHelpers, parseContent, tableHeader, tableRows };