Skip to content

Commit b504c0f

Browse files
404-htmlArtur Drozdzmtrezza
authored
feat: add ctrl + arrow key to jump to first/last cell; fix left/right key navigation with hidden columns (#1827)
* Data Browser: skipping invisible column when navigating using keyboard * Data Browser - navigating to the beggining/end when using left/right keys with modifier (ctrl/meta) key pressed * Data Browser: taking hidden columns into account when establishing the left/right edges * Data Browser: safety check to prevent from infinite loop * Data Browser: updating comments * Data Browser - navigating to the first/last row when using up/down keys with modifier (ctrl/meta) key pressed Co-authored-by: Artur Drozdz <[email protected]> Co-authored-by: Manuel <[email protected]>
1 parent e4fb29d commit b504c0f

File tree

1 file changed

+42
-13
lines changed

1 file changed

+42
-13
lines changed

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

+42-13
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export default class DataBrowser extends React.Component {
6767
simplifiedSchema: this.getSimplifiedSchema(props.schema, props.className)
6868
});
6969
} else if (Object.keys(props.columns).length !== Object.keys(this.props.columns).length
70-
|| (props.isUnique && props.uniqueField !== this.props.uniqueField)) {
70+
|| (props.isUnique && props.uniqueField !== this.props.uniqueField)) {
7171
const columnPreferences = context.currentApp.columnPreference || {}
7272
let order = ColumnPreferences.getOrder(
7373
props.columns,
@@ -127,7 +127,7 @@ export default class DataBrowser extends React.Component {
127127
* @param {Number} hoverIndex - index of headerbar moved to left of
128128
*/
129129
handleHeaderDragDrop(dragIndex, hoverIndex) {
130-
const newOrder = [ ...this.state.order ];
130+
const newOrder = [...this.state.order];
131131
const movedIndex = newOrder.splice(dragIndex, 1);
132132
newOrder.splice(hoverIndex, 0, movedIndex[0]);
133133
this.setState({ order: newOrder }, () => {
@@ -154,9 +154,9 @@ export default class DataBrowser extends React.Component {
154154
}
155155
return;
156156
}
157-
if(!this.state.editing && this.props.newObject){
157+
if (!this.state.editing && this.props.newObject) {
158158
// if user is not editing any row but there's new row
159-
if(e.keyCode === 27){
159+
if (e.keyCode === 27) {
160160
this.props.onAbortAddRow();
161161
e.preventDefault();
162162
}
@@ -176,6 +176,14 @@ export default class DataBrowser extends React.Component {
176176
if (!this.state.current) {
177177
return;
178178
}
179+
180+
const visibleColumnIndexes = [];
181+
this.state.order.forEach((column, index) => {
182+
column.visible && visibleColumnIndexes.push(index);
183+
})
184+
const firstVisibleColumnIndex = Math.min(...visibleColumnIndexes);
185+
const lastVisibleColumnIndex = Math.max(...visibleColumnIndexes);
186+
179187
switch (e.keyCode) {
180188
case 8:
181189
case 46:
@@ -191,37 +199,47 @@ export default class DataBrowser extends React.Component {
191199
}
192200
e.preventDefault();
193201
break;
194-
case 37: // Left
202+
case 37:
203+
// Left - standalone (move to the next visible column on the left)
204+
// or with ctrl/meta (excel style - move to the first visible column)
195205
this.setState({
196206
current: {
197207
row: this.state.current.row,
198-
col: Math.max(this.state.current.col - 1, 0)
208+
col: (e.ctrlKey || e.metaKey) ? firstVisibleColumnIndex :
209+
this.getNextVisibleColumnIndex(-1, firstVisibleColumnIndex, lastVisibleColumnIndex)
199210
}
200211
});
201212
e.preventDefault();
202213
break;
203-
case 38: // Up
214+
case 38:
215+
// Up - standalone (move to the previous row)
216+
// or with ctrl/meta (excel style - move to the first row)
204217
this.setState({
205218
current: {
206-
row: Math.max(this.state.current.row - 1, 0),
219+
row: (e.ctrlKey || e.metaKey) ? 0 : Math.max(this.state.current.row - 1, 0),
207220
col: this.state.current.col
208221
}
209222
});
210223
e.preventDefault();
211224
break;
212-
case 39: // Right
225+
case 39:
226+
// Right - standalone (move to the next visible column on the right)
227+
// or with ctrl/meta (excel style - move to the last visible column)
213228
this.setState({
214229
current: {
215230
row: this.state.current.row,
216-
col: Math.min(this.state.current.col + 1, this.state.order.length - 1)
231+
col: (e.ctrlKey || e.metaKey) ? lastVisibleColumnIndex :
232+
this.getNextVisibleColumnIndex(1, firstVisibleColumnIndex, lastVisibleColumnIndex)
217233
}
218234
});
219235
e.preventDefault();
220236
break;
221-
case 40: // Down
237+
case 40:
238+
// Down - standalone (move to the next row)
239+
// or with ctrl/meta (excel style - move to the last row)
222240
this.setState({
223241
current: {
224-
row: Math.min(this.state.current.row + 1, this.props.data.length - 1),
242+
row: (e.ctrlKey || e.metaKey) ? this.props.data.length - 1 : Math.min(this.state.current.row + 1, this.props.data.length - 1),
225243
col: this.state.current.col
226244
}
227245
});
@@ -239,6 +257,17 @@ export default class DataBrowser extends React.Component {
239257
}
240258
}
241259

260+
getNextVisibleColumnIndex(distance = 1, min = 0, max = 0) {
261+
if (distance === 0) { return this.state.current.col; }
262+
let newIndex = this.state.current.col + distance;
263+
while (true) {
264+
if (this.state.order[newIndex]?.visible) { return newIndex; }
265+
if (newIndex <= min) { return min; }
266+
if (newIndex >= max) { return max; }
267+
newIndex += distance;
268+
}
269+
}
270+
242271
setEditing(editing) {
243272
if (this.props.updateRow) {
244273
if (this.state.editing !== editing) {
@@ -264,7 +293,7 @@ export default class DataBrowser extends React.Component {
264293
}
265294

266295
handleColumnsOrder(order, shouldReload) {
267-
this.setState({ order: [ ...order ] }, () => {
296+
this.setState({ order: [...order] }, () => {
268297
this.updatePreferences(order, shouldReload);
269298
});
270299
}

0 commit comments

Comments
 (0)