Skip to content

Commit

Permalink
Refactor single and multi-cell range selection masks into components
Browse files Browse the repository at this point in the history
  • Loading branch information
rowanhill committed Jul 24, 2018
1 parent 80e49e1 commit 8ea34d7
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 62 deletions.
120 changes: 76 additions & 44 deletions packages/react-data-grid/src/masks/InteractionMasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -558,52 +558,31 @@ class InteractionMasks extends React.Component {
this.closeEditor();
};

getSingleCellSelectView = (rowData) => {
const { rowHeight, columns } = this.props;
const { selectedPosition } = this.state;

return (
!this.state.isEditorEnabled && this.isGridSelected() && (
<SelectionMask
selectedPosition={selectedPosition}
rowHeight={rowHeight}
columns={columns}
isGroupedRow={rowData && rowData.__metaData ? rowData.__metaData.isGroup : false}
>
{this.dragEnabled() && (
<DragHandle
onDragStart={this.handleDragStart}
onDragEnd={this.handleDragEnd}
onDoubleClick={this.onDragHandleDoubleClick}
/>
)}
</SelectionMask>
)
);
};

getCellRangeSelectView = () => {
const { rowHeight, columns } = this.props;
return [
<SelectionRangeMask
key="range-mask"
selectedRange={this.state.selectedRange}
columns={columns}
rowHeight={rowHeight}
/>,
<SelectionMask
key="selection-mask"
selectedPosition={this.state.selectedRange.startCell}
columns={columns}
rowHeight={rowHeight}
/>
];
};

render() {
const { rowHeight, rowGetter, columns, contextMenu } = this.props;
const { isEditorEnabled, firstEditorKeyPress, selectedPosition, draggedPosition, copiedPosition } = this.state;
const rowData = getSelectedRow({ selectedPosition, rowGetter });

const singleCellSelectViewProps = {
visible: !this.state.isEditorEnabled && this.isGridSelected(),
selectedPosition: this.state.selectedPosition,
rowHeight: this.props.rowHeight,
columns: this.props.columns,
rowData: rowData,
dragEnabled: this.dragEnabled(),
dragHandleEventHandlers: {
onDragStart: this.handleDragStart,
onDragEnd: this.handleDragEnd,
onDoubleClick: this.onDragHandleDoubleClick
}
};
const cellRangeSelectViewProps = {
selectedRange: this.state.selectedRange,
selectedPosition: this.state.selectedRange.startCell,
columns: this.props.columns,
rowHeight: this.props.rowHeight
};

return (
<div
ref={node => {
Expand All @@ -628,8 +607,8 @@ class InteractionMasks extends React.Component {
/>
)}
{selectedRangeIsSingleCell(this.state.selectedRange) ?
this.getSingleCellSelectView(rowData) :
this.getCellRangeSelectView()
<SingleCellSelectView {...singleCellSelectViewProps} /> :
<CellRangeSelectView {...cellRangeSelectViewProps} />
}
{isEditorEnabled && <EditorContainer
firstEditorKeyPress={firstEditorKeyPress}
Expand All @@ -647,4 +626,57 @@ class InteractionMasks extends React.Component {
}
}

export const SingleCellSelectView = (props) => {
return (
props.visible && (
<SelectionMask
selectedPosition={props.selectedPosition}
rowHeight={props.rowHeight}
columns={props.columns}
isGroupedRow={props.rowData && props.rowData.__metaData ? props.rowData.__metaData.isGroup : false}
>
{props.dragEnabled && (
<DragHandle {...props.dragHandleEventHandlers} />
)}
</SelectionMask>
)
);
};
SingleCellSelectView.propTypes = {
visible: PropTypes.bool.isRequired,
selectedPosition: PropTypes.object.isRequired,
rowHeight: PropTypes.number.isRequired,
columns: PropTypes.array.isRequired,
rowData: PropTypes.object.isRequired,
dragEnabled: PropTypes.bool.isRequired,
dragHandleEventHandlers: PropTypes.shape({
onDragStart: PropTypes.func.isRequired,
onDragEnd: PropTypes.func.isRequired,
onDoubleClick: PropTypes.func.isRequired
}).isRequired
};

export const CellRangeSelectView = (props) => {
return [
<SelectionRangeMask
key="range-mask"
selectedRange={props.selectedRange}
columns={props.columns}
rowHeight={props.rowHeight}
/>,
<SelectionMask
key="selection-mask"
selectedPosition={props.selectedPosition}
columns={props.columns}
rowHeight={props.rowHeight}
/>
];
};
CellRangeSelectView.propTypes = {
selectedRange: PropTypes.object.isRequired,
selectedPosition: PropTypes.object.isRequired,
columns: PropTypes.array.isRequired,
rowHeight: PropTypes.number.isRequired
};

export default InteractionMasks;
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React from 'react';
import { shallow, mount } from 'enzyme';

import InteractionMasks from '../InteractionMasks';
import InteractionMasks, { SingleCellSelectView, CellRangeSelectView } from '../InteractionMasks';
import SelectionMask from '../SelectionMask';
import SelectionRangeMask from '../SelectionRangeMask';
import CopyMask from '../CopyMask';
import DragMask from '../DragMask';
import DragHandle from '../DragHandle';
Expand Down Expand Up @@ -67,33 +66,39 @@ describe('<InteractionMasks/>', () => {
describe('Rendered masks', () => {
describe('When a single cell is selected', () => {
describe('within grid bounds', () => {
it('should render a SelectionMask component', () => {
it('should render a SingleCellSelectView component with visible true', () => {
const { wrapper } = setup({}, { selectedPosition: { idx: 0, rowIdx: 0 } });
expect(wrapper.find(SelectionMask).length).toBe(1);
expect(wrapper.find(SingleCellSelectView).length).toBe(1);
expect(wrapper.find(SingleCellSelectView).props().visible).toBeTruthy();
});
});

describe('outside grid bounds', () => {
it('should not render a SelectionMask component', () => {
it('should not render a SingleCellSelectView component with visible false', () => {
const { wrapper } = setup();
expect(wrapper.find(SelectionMask).length).toBe(0);
expect(wrapper.find(SingleCellSelectView).length).toBe(1);
expect(wrapper.find(SingleCellSelectView).props().visible).toBeFalsy();
});
});
});

describe('When a cell range is selected', () => {
it('should render a SelectionRangeMask component', () => {
it('should render a CellRangeSelectView component, passing relevant props', () => {
const range = {
startCell: { idx: 0, rowIdx: 0 },
topLeft: { idx: 0, rowIdx: 0 },
bottomRight: { idx: 1, rowIdx: 1 }
};
const { wrapper } = setup({}, {
selectedPosition: { idx: 0, rowIdx: 0 },
selectedRange: {
topLeft: { idx: 0, rowIdx: 0 },
bottomRight: { idx: 1, rowIdx: 1 }
}
selectedRange: range
});
expect(wrapper.find(SelectionRangeMask).length).toBe(1);
expect(wrapper.find(CellRangeSelectView).length).toBe(1);
expect(wrapper.find(CellRangeSelectView).props().selectedPosition).toEqual({ idx: 0, rowIdx: 0 });
expect(wrapper.find(CellRangeSelectView).props().selectedRange).toEqual(range);
});

it('should render a SelectionMask component on the range\'s start cell', () => {
it('should render a CellRangeSelectView component on the range\'s start cell', () => {
const { wrapper } = setup({}, {
selectedPosition: { idx: 0, rowIdx: 0 },
selectedRange: {
Expand All @@ -102,8 +107,8 @@ describe('<InteractionMasks/>', () => {
startCell: { idx: 0, rowIdx: 0 }
}
});
expect(wrapper.find(SelectionMask).length).toBe(1);
expect(wrapper.find(SelectionMask).props().selectedPosition).toEqual({ idx: 0, rowIdx: 0 });
expect(wrapper.find(CellRangeSelectView).length).toBe(1);
expect(wrapper.find(CellRangeSelectView).props().selectedPosition).toEqual({ idx: 0, rowIdx: 0 });
});
});
});
Expand Down Expand Up @@ -735,10 +740,12 @@ describe('<InteractionMasks/>', () => {
it('should render the DragMask component on cell drag', () => {
const { wrapper } = setupDrag();
const setData = jasmine.createSpy();
wrapper.find(DragHandle).simulate('dragstart', {
const dragHandlers = wrapper.find(SingleCellSelectView).props().dragHandleEventHandlers;
dragHandlers.onDragStart({
target: { className: 'test' },
dataTransfer: { setData }
});
wrapper.update();

expect(wrapper.find(DragMask).length).toBe(1);
expect(setData).toHaveBeenCalled();
Expand All @@ -747,12 +754,14 @@ describe('<InteractionMasks/>', () => {
it('should update the dragged over cells on drag end', () => {
const { wrapper, props } = setupDrag();
const setData = jasmine.createSpy();
wrapper.find(DragHandle).simulate('dragstart', {
const dragHandlers = wrapper.find(SingleCellSelectView).props().dragHandleEventHandlers;
dragHandlers.onDragStart({
target: { className: 'test' },
dataTransfer: { setData }
});
props.eventBus.dispatch(EventTypes.DRAG_ENTER, { overRowIdx: 6 });
wrapper.find(DragHandle).simulate('dragEnd');
dragHandlers.onDragEnd();
wrapper.update();

expect(props.onGridRowsUpdated).toHaveBeenCalledWith('Column1', 2, 6, { Column1: '3' }, AppConstants.UpdateActions.CELL_DRAG);
});
Expand All @@ -768,3 +777,47 @@ describe('<InteractionMasks/>', () => {
});
});
});

describe('SingleCellSelectView', () => {
const setup = (overrideProps, render = shallow) => {
const props = {
visible: true,
selectedPosition: { idx: 0, rowIdx: 0 },
rowHeight: 10,
columns: [],
rowData: { __meta: { isGroup: false } },
dragEnabled: true,
...overrideProps
};
const wrapper = render(<SingleCellSelectView {...props} />, { disableLifecycleMethods: false });
return { wrapper, props };
};

describe('with visible true', () => {
it('displays a SelectionMask', () => {
const { wrapper } = setup({ visible: true });
expect(wrapper.find(SelectionMask).length).toBe(1);
});
});

describe('with visible false', () => {
it('displays a SelectionMask', () => {
const { wrapper } = setup({ visible: false });
expect(wrapper.find(SelectionMask).length).toBe(0);
});
});

describe('with drag enabled', () => {
it('displays the DragHandle', () => {
const { wrapper } = setup({ dragEnabled: true });
expect(wrapper.find(DragHandle).length).toBe(1);
});
});

describe('with drag disabled', () => {
it('does not display the DragHandle', () => {
const { wrapper } = setup({ dragEnabled: false });
expect(wrapper.find(DragHandle).length).toBe(0);
});
});
});

0 comments on commit 8ea34d7

Please sign in to comment.