Skip to content

Commit 298ae63

Browse files
authored
feat: Highlight row of selected cell in data browser (#3270)
1 parent ec4234d commit 298ae63

4 files changed

Lines changed: 127 additions & 6 deletions

File tree

src/components/BrowserRow/BrowserRow.react.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export default class BrowserRow extends Component {
5656
onMouseOverRow,
5757
stickyLefts,
5858
freezeIndex,
59+
isHighlighted,
5960
} = this.props;
6061
const attributes = obj.attributes;
6162
let requiredCols = [];
@@ -74,8 +75,15 @@ export default class BrowserRow extends Component {
7475
} else if (obj.className === '_User' && obj.get('authData') !== undefined) {
7576
requiredCols = ['authData'];
7677
}
77-
const rowBackground = row % 2 ? '#F4F5F7' : '#fdfafb';
78+
const highlightColor = '#eef4fb';
79+
const stickyHighlightColor = '#d6e4f0';
80+
const defaultRowBackground = '#ffffff';
81+
const rowBackground = isHighlighted ? highlightColor : defaultRowBackground;
82+
const stickyBackground = isHighlighted ? stickyHighlightColor : defaultRowBackground;
7883
const rowStyle = { minWidth: rowWidth };
84+
if (isHighlighted) {
85+
rowStyle.background = highlightColor;
86+
}
7987
return (
8088
<div className={styles.tableRow} style={rowStyle} onMouseOver={() => onMouseOverRow(obj.id)}>
8189
<span
@@ -86,7 +94,7 @@ export default class BrowserRow extends Component {
8694
position: 'sticky',
8795
left: 0,
8896
zIndex: 1,
89-
background: rowBackground,
97+
background: stickyBackground,
9098
borderBottom: '1px solid #e3e3ea',
9199
}}
92100
>
@@ -104,7 +112,7 @@ export default class BrowserRow extends Component {
104112
position: 'sticky',
105113
left: 30,
106114
zIndex: 1,
107-
background: rowBackground,
115+
background: stickyBackground,
108116
borderBottom: '1px solid #e3e3ea',
109117
width: rowNumberWidth,
110118
}}

src/dashboard/Data/Browser/Browser.scss

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,6 @@ body:global(.expanded) {
9696
border-bottom: 1px solid #e3e3ea;
9797
will-change: transform;
9898

99-
&:nth-child(odd) {
100-
background: #f4f5f7;
101-
}
10299
}
103100

104101
.checkCell {

src/dashboard/Data/Browser/BrowserTable.react.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ export default class BrowserTable extends React.Component {
135135
});
136136
}
137137
let editor = null;
138+
const isRowHighlighted = (rowIndex) =>
139+
(this.props.current && this.props.current.row === rowIndex) ||
140+
(this.props.selectedCells &&
141+
this.props.selectedCells.rowStart >= 0 &&
142+
rowIndex >= this.props.selectedCells.rowStart &&
143+
rowIndex <= this.props.selectedCells.rowEnd);
138144
let table = <div ref={this.tableRef} />;
139145
if (this.props.data) {
140146
const rowWidth =
@@ -160,6 +166,7 @@ export default class BrowserTable extends React.Component {
160166
appId={this.props.appId}
161167
key={index}
162168
isEditing={isEditingRow}
169+
isHighlighted={isRowHighlighted(index)}
163170
className={this.props.className}
164171
columns={this.props.columns}
165172
schema={this.props.schema}
@@ -255,6 +262,7 @@ export default class BrowserTable extends React.Component {
255262
<BrowserRow
256263
appId={this.props.appId}
257264
key={-1}
265+
isHighlighted={isRowHighlighted(-1)}
258266
className={this.props.className}
259267
columns={this.props.columns}
260268
currentCol={currentCol}
@@ -349,6 +357,7 @@ export default class BrowserTable extends React.Component {
349357
appId={this.props.appId}
350358
key={index}
351359
isEditing={isEditingRow}
360+
isHighlighted={isRowHighlighted(i)}
352361
className={this.props.className}
353362
columns={this.props.columns}
354363
schema={this.props.schema}

src/lib/tests/BrowserRow.test.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
jest.dontMock('../../components/BrowserRow/BrowserRow.react');
2+
jest.mock('idb-keyval');
3+
4+
import React from 'react';
5+
import renderer from 'react-test-renderer';
6+
const BrowserRow = require('../../components/BrowserRow/BrowserRow.react').default;
7+
8+
const defaultProps = {
9+
className: 'TestClass',
10+
columns: {
11+
objectId: { type: 'String' },
12+
name: { type: 'String' },
13+
},
14+
currentCol: undefined,
15+
isUnique: false,
16+
obj: {
17+
id: 'abc123',
18+
className: 'TestClass',
19+
attributes: { objectId: 'abc123', name: 'Test' },
20+
get: function(key) { return this.attributes[key]; },
21+
},
22+
order: [
23+
{ name: 'objectId', width: 150, visible: true },
24+
{ name: 'name', width: 150, visible: true },
25+
],
26+
readOnlyFields: ['objectId'],
27+
row: 0,
28+
rowWidth: 330,
29+
showRowNumber: true,
30+
rowNumberWidth: 30,
31+
skip: 0,
32+
selection: {},
33+
selectRow: () => {},
34+
setCopyableValue: () => {},
35+
selectedObjectId: undefined,
36+
setSelectedObjectId: () => {},
37+
callCloudFunction: () => {},
38+
isPanelVisible: false,
39+
setCurrent: () => {},
40+
setEditing: () => {},
41+
setRelation: () => {},
42+
onEditSelectedRow: () => {},
43+
setContextMenu: () => {},
44+
onFilterChange: () => {},
45+
markRequiredFieldRow: undefined,
46+
onMouseDownRowCheckBox: () => {},
47+
onMouseUpRowCheckBox: () => {},
48+
onMouseOverRowCheckBox: () => {},
49+
onMouseOverRow: () => {},
50+
onPointerClick: () => {},
51+
onPointerCmdClick: () => {},
52+
rowValue: undefined,
53+
stickyLefts: [],
54+
freezeIndex: -1,
55+
};
56+
57+
describe('BrowserRow', () => {
58+
describe('Row highlight', () => {
59+
it('should not apply highlight styles when isHighlighted is false', () => {
60+
const component = renderer
61+
.create(<BrowserRow {...defaultProps} isHighlighted={false} />)
62+
.toJSON();
63+
// Row div should not have highlight background
64+
expect(component.props.style.background).toBeUndefined();
65+
});
66+
67+
it('should not apply highlight styles when isHighlighted is undefined', () => {
68+
const component = renderer
69+
.create(<BrowserRow {...defaultProps} />)
70+
.toJSON();
71+
expect(component.props.style.background).toBeUndefined();
72+
});
73+
74+
it('should apply subtle blue tint to row div when isHighlighted is true', () => {
75+
const component = renderer
76+
.create(<BrowserRow {...defaultProps} isHighlighted={true} />)
77+
.toJSON();
78+
expect(component.props.style.background).toBe('#eef4fb');
79+
});
80+
81+
it('should apply stronger blue to checkbox cell when isHighlighted is true', () => {
82+
const component = renderer
83+
.create(<BrowserRow {...defaultProps} isHighlighted={true} />)
84+
.toJSON();
85+
// First child is the checkbox span
86+
const checkboxCell = component.children[0];
87+
expect(checkboxCell.props.style.background).toBe('#d6e4f0');
88+
});
89+
90+
it('should apply stronger blue to row number cell when isHighlighted is true', () => {
91+
const component = renderer
92+
.create(<BrowserRow {...defaultProps} isHighlighted={true} showRowNumber={true} />)
93+
.toJSON();
94+
// Second child is the row number span (when showRowNumber is true)
95+
const rowNumberCell = component.children[1];
96+
expect(rowNumberCell.props.style.background).toBe('#d6e4f0');
97+
});
98+
99+
it('should use default background on checkbox cell when not highlighted', () => {
100+
const component = renderer
101+
.create(<BrowserRow {...defaultProps} row={1} isHighlighted={false} />)
102+
.toJSON();
103+
const checkboxCell = component.children[0];
104+
expect(checkboxCell.props.style.background).toBe('#ffffff');
105+
});
106+
});
107+
});

0 commit comments

Comments
 (0)