Skip to content

Commit

Permalink
refactor: switch SimpleTable to JSX
Browse files Browse the repository at this point in the history
  • Loading branch information
fboulnois committed Nov 13, 2023
1 parent cf91edf commit 7e51213
Showing 1 changed file with 81 additions and 76 deletions.
157 changes: 81 additions & 76 deletions src/components/SimpleTable.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { isNil } from 'lodash/fp';
import { div, h } from 'react-hyperscript-helpers';
import React from 'react';
import { Styles } from '../libs/theme';
import ReactTooltip from 'react-tooltip';
import { ArrowDropUp, ArrowDropDown } from '@mui/icons-material';
Expand All @@ -8,89 +8,95 @@ import loadingImage from '../images/loading-indicator.svg';

// Renders spinning circle while table loading
const TableLoading = () => {
return div({className: 'table-loading-placeholder'},
[
h(SpinnerComponent, {
show: true,
name: 'loadingSpinner',
loadingImage
}, [])
]
return (
<div className='table-loading-placeholder'>
<SpinnerComponent show={true} name='loadingSpinner' loadingImage={loadingImage} />
</div>
);
};

//Simple cell text display
// Simple cell text display
const SimpleTextCell = ({ text, style, keyProp }) => {
text = isNil(text) ? '- -' : text;
return div({ style, role: 'cell', key: keyProp }, [text]);
text = text ?? '- -';
return <div style={style} role='cell' key={keyProp}>{text}</div>;
};

//Simple cell text that carries onClick functionality
// Simple cell text that carries onClick functionality
const OnClickTextCell = ({ text, style, onClick, keyProp }) => {
text = isNil(text) ? '- -' : text;
return div({ style, onClick, role: 'cell', key: keyProp }, [text]);
text = text ?? '- -';
return <div style={style} onClick={onClick} role='cell' key={keyProp}>{text}</div>;
};

//Column component that renders the column row based on column headers
const ColumnRow = ({columnHeaders, baseStyle, columnStyle, sort, onSort}) => {
const rowStyle = Object.assign({}, baseStyle, columnStyle);
return div({style: rowStyle, key: 'column-row-container', role:'row'}, columnHeaders.map((header, colIndex) => {
const {cellStyle, label} = header;
//style here pertains to styling for individual cells
//should be used to set dimensions of specific columns
return div({style: cellStyle, key: `column-row-${label}`, className: 'column-header'}, [
header.sortable && onSort
? div({
style: Styles.TABLE.HEADER_SORT,
key: 'data_id_cell',
className: 'cell-sort',
onClick: () => {
onSort({
colIndex: colIndex,
dir: sort.colIndex === colIndex ? sort.dir * -1 : 1
});
}
}, [
label,
div({className: 'sort-container'}, [
h(ArrowDropUp, { className: `sort-icon sort-icon-up ${sort.colIndex === colIndex && sort.dir === -1 ? 'active' : ''}` }),
h(ArrowDropDown, { className: `sort-icon sort-icon-down ${sort.colIndex === colIndex && sort.dir === 1 ? 'active': ''}` })
])
])
: label
]);
}));
const rowStyle = { ...baseStyle, ...columnStyle };
return (
<div style={rowStyle} key='column-row-container' role='row'>
{columnHeaders.map((header, colIndex) => {
const {cellStyle, label} = header;
return (
<div style={cellStyle} key={`column-row-${label}`} className='column-header'>
{header.sortable && onSort
? <div
style={Styles.TABLE.HEADER_SORT}
key='data_id_cell'
className='cell-sort'
onClick={() => {
onSort({
colIndex: colIndex,
dir: sort.colIndex === colIndex ? sort.dir * -1 : 1
});
}}
>
{label}
<div className='sort-container'>
<ArrowDropUp className={`sort-icon sort-icon-up ${sort.colIndex === colIndex && sort.dir === -1 ? 'active' : ''}`} />
<ArrowDropDown className={`sort-icon sort-icon-down ${sort.colIndex === colIndex && sort.dir === 1 ? 'active': ''}`} />
</div>
</div>
: label
}
</div>
);
})}
</div>
);
};

//Row component that renders out rows for each element in the provided data collection
const DataRows = ({rowData, baseStyle, columnHeaders, rowWrapper = ({renderedRow}) => renderedRow}) => {
return rowData.map((row, index) => {
const id = rowData[index][0].id;
const mapKey = id || `noId-index-${index}`;
const renderedRow = div({style: Object.assign({borderTop: '1px solid #f3f6f7'}, baseStyle), key: `row-data-${mapKey}`, role: 'row', className: `row-data-${index}`},
row.map(({data, style, onClick, isComponent, id, label}, cellIndex) => {
let output;
//columnHeaders determine width of the columns,
//therefore extract width from columnHeader and apply to cell style
const columnWidthStyle = columnHeaders[cellIndex].cellStyle;
const appliedStyle = Object.assign({}, style, columnWidthStyle);
//assume component is in hyperscript format
//wrap component in dive with columnWidth applied
if (isComponent) {
output = div({role: 'cell', style: columnWidthStyle, key: `${!isNil(data) && !isNil(data.key) ? data.key : 'component-' + index + '-' + cellIndex}-container`}, [data]);
//if there is no onClick function, render as simple cell
} else if (isNil(onClick)) {
output = h(SimpleTextCell, { text: data, style: appliedStyle, keyProp: `filtered-list-${id}-${label}`, cellIndex });
} else {
const renderedRow = (
<div style={{...{borderTop: '1px solid #f3f6f7'}, ...baseStyle}} key={`row-data-${mapKey}`} role='row' className={`row-data-${index}`}>
{row.map(({data, style, onClick, isComponent, id, label}, cellIndex) => {
let output;
//columnHeaders determine width of the columns,
//therefore extract width from columnHeader and apply to cell style
const columnWidthStyle = columnHeaders[cellIndex].cellStyle;
//assume component is in hyperscript format
//wrap component in dive with columnWidth applied
const appliedStyle = {...style, ...columnWidthStyle};
if (isComponent) {
output = (
<div role='cell' style={columnWidthStyle} key={`${data && data.key ? data.key : 'component-' + index + '-' + cellIndex}-container`}>
{data}
</div>
);
//if there is no onClick function, render as simple cell
} else if (isNil(onClick)) {
output = <SimpleTextCell text={data} style={appliedStyle} keyProp={`filtered-list-${id}-${label}`} cellIndex={cellIndex} />;
//otherwise render as on click cell
output = h(OnClickTextCell, { text: data, style: appliedStyle, onClick: () => onClick(index), keyProp: `filtered-list-${id}-${label}`, cellIndex });
}
return output;
}));

} else {
output = <OnClickTextCell text={data} style={appliedStyle} onClick={() => onClick(index)} keyProp={`filtered-list-${id}-${label}`} cellIndex={cellIndex} />;
}
return output;
})}
</div>
);
return rowWrapper({renderedRow, rowData: row});
});

};

//Simple table component, can be used alone, can be built on top of (like with LibraryCardTable)
Expand All @@ -112,17 +118,16 @@ export default function SimpleTable(props) {
} = props;

const {baseStyle, columnStyle, containerOverride} = styles;
const columnRow = h(ColumnRow, {key: 'column-row-container', columnHeaders, baseStyle, columnStyle, sort, onSort});
const tableTemplate = [columnRow, h(DataRows, {rowData, baseStyle, columnHeaders, rowWrapper, key: 'table-data-rows'})];
const output = isLoading ? h(TableLoading, {}) : tableTemplate;
return div([
div({className: 'table-data', style: containerOverride || Styles.TABLE.CONTAINER, role: 'table'},
[output, isNil(paginationBar) ? div() : paginationBar]),
h(ReactTooltip, {
place: 'left',
effect: 'solid',
multiline: true,
className: 'tooltip-wrapper'
})
]);
const columnRow = <ColumnRow key='column-row-container' columnHeaders={columnHeaders} baseStyle={baseStyle} columnStyle={columnStyle} sort={sort} onSort={onSort} />;
const tableTemplate = [columnRow, <DataRows rowData={rowData} baseStyle={baseStyle} columnHeaders={columnHeaders} rowWrapper={rowWrapper} key='table-data-rows' />];
const output = isLoading ? <TableLoading /> : tableTemplate;
return (
<div>
<div className='table-data' style={containerOverride || Styles.TABLE.CONTAINER} role='table'>
{output}
{!paginationBar ? <div /> : paginationBar}
</div>
<ReactTooltip place='left' effect='solid' multiline={true} className='tooltip-wrapper' />
</div>
);
}

0 comments on commit 7e51213

Please sign in to comment.