Skip to content

Commit

Permalink
WIP: feat(Table): support inline editing in PF4
Browse files Browse the repository at this point in the history
  • Loading branch information
suomiy committed Feb 4, 2019
1 parent 043958c commit 18067b4
Show file tree
Hide file tree
Showing 32 changed files with 8,646 additions and 306 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const defaultProps = {
isDisabled: false,
isReadOnly: false,
type: 'text',
value: null,
value: undefined,
onChange: () => undefined,
'aria-label': null
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ exports[`disabled text input 1`] = `
readOnly={false}
required={false}
type="text"
value={null}
/>
`;

Expand Down
8 changes: 8 additions & 0 deletions packages/patternfly-4/react-table/internal/util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// TODO: better sharing util components between modules
export function debounce(func, wait) {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import { CloseIcon } from '@patternfly/react-icons';
import { Button } from '@patternfly/react-core';

const CancelButton = props => (
<Button {...props}>
<CloseIcon />
</Button>
);

CancelButton.propTypes = {
...Button.propTypes
};

CancelButton.defaultProps = {
...Button.defaultProps,
variant: 'plain'
};

export default CancelButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';
import { shallow } from 'enzyme';
import { CancelButton } from './index';

test('it renders properly', () => {
const component = shallow(<CancelButton />);

expect(component).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`it renders properly 1`] = `
<Button
aria-label={null}
className=""
component="button"
isActive={false}
isBlock={false}
isDisabled={false}
isFocus={false}
isHover={false}
type="button"
variant="plain"
>
<CloseIcon
color="currentColor"
size="sm"
title={null}
/>
</Button>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as CancelButton } from './CancelButton';
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import { CheckIcon } from '@patternfly/react-icons';
import { Button } from '@patternfly/react-core';

const ConfirmButton = props => (
<Button {...props}>
<CheckIcon />
</Button>
);

ConfirmButton.propTypes = {
...Button.propTypes
};

ConfirmButton.defaultProps = {
...Button.defaultProps,
variant: 'primary'
};

export default ConfirmButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';
import { shallow } from 'enzyme';
import { ConfirmButton } from './index';

test('it renders properly', () => {
const component = shallow(<ConfirmButton />);

expect(component).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`it renders properly 1`] = `
<Button
aria-label={null}
className=""
component="button"
isActive={false}
isBlock={false}
isDisabled={false}
isFocus={false}
isHover={false}
type="button"
variant="primary"
>
<CheckIcon
color="currentColor"
size="sm"
title={null}
/>
</Button>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as ConfirmButton } from './ConfirmButton';
63 changes: 50 additions & 13 deletions packages/patternfly-4/react-table/src/components/Table/Body.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const propTypes = {
className: PropTypes.string,
/** Specify key which should be used for labeling each row. */
rowKey: PropTypes.string,
/** Function that is fired when user clicks on row. */
/** Function that is fired when user clicks on a row if not editing. */
onRowClick: PropTypes.func
};

Expand All @@ -18,37 +18,70 @@ const defaultProps = {
onRowClick: () => undefined
};

class ContextBody extends React.Component {
onRow = (row, props) => {
const { onRowClick } = this.props;
return ({
isExpanded: row.isExpanded,
isOpen: row.isOpen,
onClick: (event) => onRowClick(event, row, props)
});
const onMouseDown = (event, row, rowProps, { onRowClick, editConfig }) => {
const cell = event.target.closest('[data-key]');
const cellNumber = parseInt(cell && cell.getAttribute('data-key'));
const hasCellNumber = !Number.isNaN(cellNumber);

let onEditCellChanged;
let targetsAlreadyEditedCell = false;

if (hasCellNumber && editConfig && typeof editConfig.onEditCellChanged === 'function') {
targetsAlreadyEditedCell = cellNumber === row.activeEditCell;
onEditCellChanged = () => {
editConfig.onEditCellChanged(event, row, {
rowIndex: rowProps.rowIndex,
columnIndex: cellNumber
});
};
}

// give priority to fire onChange/onBlur callbacks

setTimeout(() => {
if (!row.isEditing) {
onRowClick(event, row, rowProps);
if (onEditCellChanged) {
// edit cell after rerender
setTimeout(onEditCellChanged, 0);
}
} else if (onEditCellChanged && !targetsAlreadyEditedCell) {
onEditCellChanged();
}
}, 0);
};

class ContextBody extends React.Component {
onRow = (row, rowProps) => ({
row,
rowProps,
onMouseDown: event => onMouseDown(event, row, rowProps, this.props)
});

parentsExpanded(parentId) {
const { rows } = this.props;
return rows[parentId].hasOwnProperty('parent') ? this.parentsExpanded(rows[parentId].parent) : rows[parentId].isOpen;
}

render() {
const { className, headerData, rows, rowKey, children, onRowClick, ...props } = this.props;
const { className, headerData, rows, rowKey, children, editConfig, onRowClick, ...props } = this.props;
let shiftKey = 0;
shiftKey += headerData[0] && headerData[0].extraParams.onSelect ? 1 : 0;
shiftKey += headerData[0] && headerData[0].extraParams.onCollapse ? 1 : 0;
const isTableEditing = rows.some(oneRow => oneRow.isEditing);

const mappedRows = headerData.length !== 0 && rows.map((oneRow, oneRowKey) => {
return {
...oneRow,
...oneRow && (oneRow.cells || oneRow).reduce(
(acc, curr, key) => {
const isCurrObject = curr === Object(curr);
return ({
...acc,
...{
[headerData[shiftKey + key].property]: {
title: curr.title || curr,
props: curr.props
title: isCurrObject ? curr.title : curr,
props: isCurrObject ? curr.props : undefined
}
}
})
Expand All @@ -57,6 +90,10 @@ class ContextBody extends React.Component {
...oneRow.parent !== undefined ? {
isExpanded: this.parentsExpanded(oneRow.parent) && rows[oneRow.parent].isOpen
} : {},
isFirst: oneRowKey === 0,
isLast: oneRowKey === rows.length -1,
editConfig,
isTableEditing,
}
});
return (
Expand All @@ -69,7 +106,7 @@ class ContextBody extends React.Component {

const TableBody = props => (
<TableContext.Consumer>
{({ headerData, rows }) => <ContextBody {...props} headerData={headerData} rows={rows} />}
{({ headerData, editConfig, rows }) => <ContextBody {...props} headerData={headerData} rows={rows} editConfig={editConfig} />}
</TableContext.Consumer>
)

Expand Down
Loading

0 comments on commit 18067b4

Please sign in to comment.