Skip to content

Commit 9864199

Browse files
authored
feat(expore): Generalize drag n drop context for any type (#92142)
For use with the aggregate fields column editor. Allow not just list of strings.
1 parent 6a4e926 commit 9864199

File tree

5 files changed

+55
-34
lines changed

5 files changed

+55
-34
lines changed

static/app/views/explore/contexts/dragNDropContext.tsx

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,35 @@ import {
1717
useDragNDropColumns,
1818
} from 'sentry/views/explore/hooks/useDragNDropColumns';
1919

20-
interface DragNDropContextProps {
20+
interface DragNDropContextProps<T> {
2121
children: (props: {
2222
deleteColumnAtIndex: (i: number) => void;
23-
editableColumns: Column[];
23+
editableColumns: Array<Column<T>>;
2424
insertColumn: () => void;
25-
updateColumnAtIndex: (i: number, column: string) => void;
25+
updateColumnAtIndex: (i: number, column: T) => void;
2626
}) => React.ReactNode;
27-
columns: string[];
28-
setColumns: (columns: string[], op: 'insert' | 'update' | 'delete' | 'reorder') => void;
27+
columns: T[];
28+
defaultColumn: () => T;
29+
setColumns: (columns: T[], op: 'insert' | 'update' | 'delete' | 'reorder') => void;
2930
}
3031

31-
export function DragNDropContext({columns, setColumns, children}: DragNDropContextProps) {
32+
export function DragNDropContext<T>({
33+
columns,
34+
defaultColumn,
35+
setColumns,
36+
children,
37+
}: DragNDropContextProps<T>) {
3238
const {
3339
editableColumns,
3440
insertColumn,
3541
updateColumnAtIndex,
3642
deleteColumnAtIndex,
3743
onDragEnd,
38-
} = useDragNDropColumns({columns, setColumns});
44+
} = useDragNDropColumns({
45+
columns,
46+
defaultColumn,
47+
setColumns,
48+
});
3949

4050
const sensors = useSensors(
4151
useSensor(PointerSensor),

static/app/views/explore/hooks/useDragNDropColumns.spec.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@ import {useDragNDropColumns} from './useDragNDropColumns';
77
describe('useDragNDropColumns', () => {
88
const initialColumns = ['span.op', 'span_id', 'timestamp'];
99

10+
function defaultColumn(): string {
11+
return '';
12+
}
13+
1014
it('should insert a column', () => {
1115
let columns!: string[];
1216
let setColumns: (columns: string[]) => void;
1317
let insertColumn: ReturnType<typeof useDragNDropColumns>['insertColumn'];
1418

1519
function TestPage() {
1620
[columns, setColumns] = useState(initialColumns);
17-
({insertColumn} = useDragNDropColumns({columns, setColumns}));
21+
({insertColumn} = useDragNDropColumns({columns, defaultColumn, setColumns}));
1822
return null;
1923
}
2024

@@ -30,13 +34,11 @@ describe('useDragNDropColumns', () => {
3034
it('should update a column at a specific index', () => {
3135
let columns!: string[];
3236
let setColumns: (columns: string[]) => void;
33-
let updateColumnAtIndex: ReturnType<
34-
typeof useDragNDropColumns
35-
>['updateColumnAtIndex'];
37+
let updateColumnAtIndex: (i: number, column: string) => void;
3638

3739
function TestPage() {
3840
[columns, setColumns] = useState(initialColumns);
39-
({updateColumnAtIndex} = useDragNDropColumns({columns, setColumns}));
41+
({updateColumnAtIndex} = useDragNDropColumns({columns, defaultColumn, setColumns}));
4042
return null;
4143
}
4244

@@ -56,7 +58,7 @@ describe('useDragNDropColumns', () => {
5658

5759
function TestPage() {
5860
[columns, setColumns] = useState(initialColumns);
59-
({deleteColumnAtIndex} = useDragNDropColumns({columns, setColumns}));
61+
({deleteColumnAtIndex} = useDragNDropColumns({columns, defaultColumn, setColumns}));
6062
return null;
6163
}
6264

@@ -76,7 +78,7 @@ describe('useDragNDropColumns', () => {
7678

7779
function TestPage() {
7880
[columns, setColumns] = useState(initialColumns);
79-
({onDragEnd} = useDragNDropColumns({columns, setColumns}));
81+
({onDragEnd} = useDragNDropColumns({columns, defaultColumn, setColumns}));
8082
return null;
8183
}
8284

static/app/views/explore/hooks/useDragNDropColumns.tsx

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,31 @@ import {useEffect, useMemo, useState} from 'react';
22
import type {DragEndEvent} from '@dnd-kit/core';
33
import {arrayMove} from '@dnd-kit/sortable';
44

5-
export type Column = {
6-
column: string | undefined;
5+
export type Column<T> = {
6+
column: T | undefined;
77
id: number;
88
};
99

10-
interface UseDragAndDropColumnsProps {
11-
columns: string[];
12-
setColumns: (columns: string[], op: 'insert' | 'update' | 'delete' | 'reorder') => void;
10+
interface UseDragAndDropColumnsProps<T> {
11+
columns: T[];
12+
defaultColumn: () => T;
13+
setColumns: (columns: T[], op: 'insert' | 'update' | 'delete' | 'reorder') => void;
1314
}
1415

15-
const extractColumns = (editableColumns: Column[]) => {
16-
return editableColumns.map(({column}) => column ?? '');
17-
};
16+
function extractColumns<T>(editableColumns: Array<Column<T>>, defaultColumn: () => T) {
17+
return editableColumns.map(({column}) => column ?? defaultColumn());
18+
}
1819

19-
export function useDragNDropColumns({columns, setColumns}: UseDragAndDropColumnsProps) {
20+
export function useDragNDropColumns<T>({
21+
columns,
22+
defaultColumn,
23+
setColumns,
24+
}: UseDragAndDropColumnsProps<T>) {
2025
const mappedColumns = useMemo(() => {
2126
return columns.map((column, i) => ({id: i + 1, column}));
2227
}, [columns]);
2328

24-
const [editableColumns, setEditableColumns] = useState<Column[]>(mappedColumns);
29+
const [editableColumns, setEditableColumns] = useState<Array<Column<T>>>(mappedColumns);
2530

2631
useEffect(() => {
2732
setEditableColumns(prevEditableColumns => {
@@ -44,18 +49,18 @@ export function useDragNDropColumns({columns, setColumns}: UseDragAndDropColumns
4449

4550
setNextId(nextId + 1); // make sure to increment the id for the next time
4651

47-
setColumns(extractColumns(newEditableColumns), 'insert');
52+
setColumns(extractColumns(newEditableColumns, defaultColumn), 'insert');
4853

4954
return newEditableColumns;
5055
});
5156
}
5257

53-
function updateColumnAtIndex(i: number, column: string) {
58+
function updateColumnAtIndex(i: number, column: T) {
5459
setEditableColumns(oldEditableColumns => {
5560
const newEditableColumns = [...oldEditableColumns];
5661
newEditableColumns[i]!.column = column;
5762

58-
setColumns(extractColumns(newEditableColumns), 'update');
63+
setColumns(extractColumns(newEditableColumns, defaultColumn), 'update');
5964

6065
return newEditableColumns;
6166
});
@@ -64,7 +69,7 @@ export function useDragNDropColumns({columns, setColumns}: UseDragAndDropColumns
6469
function deleteColumnAtIndex(i: number) {
6570
setEditableColumns(oldEditableColumns => {
6671
if (oldEditableColumns.length === 1) {
67-
setColumns([''], 'delete');
72+
setColumns([defaultColumn()], 'delete');
6873
return [{id: 1, column: undefined}];
6974
}
7075

@@ -73,7 +78,7 @@ export function useDragNDropColumns({columns, setColumns}: UseDragAndDropColumns
7378
...oldEditableColumns.slice(i + 1),
7479
];
7580

76-
setColumns(extractColumns(newEditableColumns), 'delete');
81+
setColumns(extractColumns(newEditableColumns, defaultColumn), 'delete');
7782

7883
return newEditableColumns;
7984
});
@@ -89,7 +94,7 @@ export function useDragNDropColumns({columns, setColumns}: UseDragAndDropColumns
8994
setEditableColumns(oldEditableColumns => {
9095
const newEditableColumns = arrayMove(oldEditableColumns, oldIndex, newIndex);
9196

92-
setColumns(extractColumns(newEditableColumns), 'reorder');
97+
setColumns(extractColumns(newEditableColumns, defaultColumn), 'reorder');
9398

9499
return newEditableColumns;
95100
});

static/app/views/explore/tables/columnEditorModal.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,11 @@ export function ColumnEditorModal({
131131
}
132132

133133
return (
134-
<DragNDropContext columns={tempColumns} setColumns={setTempColumns}>
134+
<DragNDropContext
135+
columns={tempColumns}
136+
setColumns={setTempColumns}
137+
defaultColumn={() => ''}
138+
>
135139
{({insertColumn, updateColumnAtIndex, deleteColumnAtIndex, editableColumns}) => (
136140
<Fragment>
137141
<Header closeButton data-test-id="editor-header">
@@ -194,7 +198,7 @@ export function ColumnEditorModal({
194198

195199
interface ColumnEditorRowProps {
196200
canDelete: boolean;
197-
column: Column;
201+
column: Column<string>;
198202
onColumnChange: (column: string) => void;
199203
onColumnDelete: () => void;
200204
options: Array<SelectOption<string>>;

static/app/views/explore/toolbar/toolbarGroupBy.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export function ToolbarGroupBy({autoSwitchToAggregates}: ToolbarGroupBy) {
9191
}, [groupBys, tags]);
9292

9393
return (
94-
<DragNDropContext columns={groupBys} setColumns={setColumns}>
94+
<DragNDropContext columns={groupBys} setColumns={setColumns} defaultColumn={() => ''}>
9595
{({editableColumns, insertColumn, updateColumnAtIndex, deleteColumnAtIndex}) => {
9696
return (
9797
<ToolbarSection data-test-id="section-group-by">
@@ -136,7 +136,7 @@ export function ToolbarGroupBy({autoSwitchToAggregates}: ToolbarGroupBy) {
136136

137137
interface ColumnEditorRowProps {
138138
canDelete: boolean;
139-
column: Column;
139+
column: Column<string>;
140140
onColumnChange: (column: string) => void;
141141
onColumnDelete: () => void;
142142
options: Array<SelectOption<string>>;

0 commit comments

Comments
 (0)