Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implements explorer data grid column reordering #1221

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions common/constants/explorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,11 +337,19 @@ export const DEFAULT_TIMESTAMP_COLUMN = {
display: 'Time',
schema: 'datetime',
initialWidth: 200,
actions: {
showMoveLeft: false,
showMoveRight: false,
},
};

export const DEFAULT_SOURCE_COLUMN = {
id: '_source',
isSortable: false,
display: 'Source',
schema: '_source',
actions: {
showMoveLeft: false,
showMoveRight: false,
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,21 @@ exports[`Datagrid component Renders data grid component 1`] = `
columns={
Array [
Object {
"actions": Object {
"showMoveLeft": false,
"showMoveRight": false,
},
"display": "Time",
"id": "timestamp",
"initialWidth": 200,
"isSortable": true,
"schema": "datetime",
},
Object {
"actions": Object {
"showMoveLeft": false,
"showMoveRight": false,
},
"display": "Source",
"id": "_source",
"isSortable": false,
Expand Down Expand Up @@ -300,7 +308,7 @@ exports[`Datagrid component Renders data grid component 1`] = `
Object {
"showColumnSelector": Object {
"allowHide": false,
"allowReorder": true,
"allowReorder": false,
},
"showFullScreenSelector": false,
"showStyleSelector": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,21 @@ import {
} from '@elastic/eui';
import moment from 'moment';
import { MutableRefObject } from 'react';
import { useDispatch } from 'react-redux';
import { IExplorerFields, IField } from '../../../../../common/types/explorer';
import {
DATE_DISPLAY_FORMAT,
DEFAULT_EMPTY_EXPLORER_FIELDS,
DEFAULT_SOURCE_COLUMN,
DEFAULT_TIMESTAMP_COLUMN,
SELECTED_FIELDS,
} from '../../../../../common/constants/explorer';
import { HttpSetup } from '../../../../../../../src/core/public';
import PPLService from '../../../../services/requests/ppl';
import { FlyoutButton } from './docViewRow';
import { useFetchEvents } from '../../hooks';
import { redoQuery } from '../../utils/utils';
import { redoQuery, getFieldTypes } from '../../utils/utils';
import { updateFields } from '../../redux/slices/field_slice';

interface DataGridProps {
http: HttpSetup;
Expand All @@ -41,6 +44,7 @@ interface DataGridProps {
startTime: string;
endTime: string;
storedSelectedColumns: IField[];
tabId: string;
}

export function DataGrid(props: DataGridProps) {
Expand All @@ -56,11 +60,13 @@ export function DataGrid(props: DataGridProps) {
requestParams,
startTime,
endTime,
tabId,
} = props;
const { fetchEvents } = useFetchEvents({
pplService,
requestParams,
});
const dispatch = useDispatch();
const selectedColumns =
explorerFields.selectedFields.length > 0
? explorerFields.selectedFields
Expand Down Expand Up @@ -131,7 +137,22 @@ export function DataGrid(props: DataGridProps) {
return {
visibleColumns: columns,
setVisibleColumns: (visibleColumns: string[]) => {
// TODO: implement with sidebar field order (dragability) changes
if (explorerFields.selectedFields.length > 0) {
const fields: IField[] = [];
// fields within visibleColumns are re-created to be of type IField
visibleColumns.forEach((col) => {
fields.push({ name: col, type: getFieldTypes(col, explorerFields) });
});
dispatch(
updateFields({
tabId,
data: {
...explorerFields,
[SELECTED_FIELDS]: fields,
},
})
);
}
},
};
}
Expand Down Expand Up @@ -262,7 +283,7 @@ export function DataGrid(props: DataGridProps) {
toolbarVisibility={{
showColumnSelector: {
allowHide: false,
allowReorder: true,
allowReorder: explorerFields.selectedFields.length > 0,
Copy link
Collaborator

@mengweieric mengweieric Nov 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If by default only have timestamp and _source for initial state, then there's no selected field explorerFields.selectedFields, but datagrid should still allow user to reorder timnestamp and _source is it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here i'm actually disabling reordering when no fields are selected, so that no reordering is done when the default columns appear in data grid. The reason I do this is because the default columns are 'artificial fields' and I don't want them to appear as objects in the sidebar.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then it doesn't match with existing behavior in discover

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

existing behavior is discover is bugged a little bit, the default columns don't get reordered when done through the data grid even though the names move and the sidebar also has some inconsistencies. I extrapolated that since the default columns don't actually move themselves, then I should disable the ability to attempt at doing so.

},
showFullScreenSelector: false,
showStyleSelector: false,
Expand Down
5 changes: 3 additions & 2 deletions public/components/event_analytics/explorer/explorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,7 @@ export const Explorer = ({
requestParams={requestParams}
startTime={appLogEvents ? startTime : dateRange[0]}
endTime={appLogEvents ? endTime : dateRange[1]}
tabId={tabId}
/>
)}
<a tabIndex={0} id="discoverBottomMarker">
Expand Down Expand Up @@ -899,12 +900,12 @@ export const Explorer = ({
<EuiSplitPanel.Outer className="eui-yScroll" hasBorder={true} borderRadius="none">
{!appLogEvents && (
<EuiSplitPanel.Inner paddingSize="s" color="subdued" grow={false}>
<DataSourceSelection tabId={initialTabId} />
<DataSourceSelection tabId={tabId} />
paulstn marked this conversation as resolved.
Show resolved Hide resolved
</EuiSplitPanel.Inner>
)}
<EuiSplitPanel.Inner paddingSize="none" color="subdued" className="eui-yScroll">
<ObservabilitySideBar
tabId={initialTabId}
tabId={tabId}
pplService={pplService}
notifications={notifications}
/>
Expand Down
89 changes: 54 additions & 35 deletions public/components/event_analytics/explorer/sidebar/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { AVAILABLE_FIELDS, SELECTED_FIELDS } from '../../../../../common/constan
import { ExplorerFields, IExplorerFields, IField } from '../../../../../common/types/explorer';
import { sortFields, updateFields } from '../../redux/slices/field_slice';
import { Field } from './field';
import { getFieldTypes } from '../../utils/utils';

interface ISidebarProps {
query: string;
Expand Down Expand Up @@ -55,79 +56,80 @@ export const Sidebar = (props: ISidebarProps) => {
const [showFields, setShowFields] = useState<boolean>(false);
const [searchTerm, setSearchTerm] = useState<string>('');

// method to return the type of a field from its name
const getFieldTypes = (newFieldName: string) => {
let fieldType: string = '';
explorerFields.availableFields.map((field) => {
if (field.name === newFieldName) fieldType = field.type;
});
explorerFields.selectedFields.map((field) => {
if (field.name === newFieldName) fieldType = field.type;
});
return fieldType;
};

/**
* Toggle fields between selected and unselected sets
* @param fieldState all fields in store
* @param field field to be toggled
* @param FieldSetToRemove the set where this field to be removed from
* @param FieldSetToAdd the set where this field to be added to
* returns new fields state
* @param indexPos position in which field should be added, default value is 0
* @returns new fields state
*/
const toggleFields = (
fieldState: ExplorerFields,
field: IField,
fieldSetToRemove: string,
fieldSetToAdd: string
fieldSetToAdd: string,
indexPos: number = 0
): ExplorerFields => {
const nextFields = { ...fieldState };

// find and remove field
nextFields[fieldSetToRemove] = nextFields[fieldSetToRemove].filter(
(fd: IField) => fd.name !== field.name
);
nextFields[fieldSetToAdd] = [...nextFields[fieldSetToAdd], field];

// add field at specified index, will resolve to 0 if not specified
const addedFieldSet = [...nextFields[fieldSetToAdd]]; // copies value, not reference
addedFieldSet.splice(indexPos, 0, field);
nextFields[fieldSetToAdd] = addedFieldSet;

return nextFields;
};

const updateStoreFields = (fieldsData: ExplorerFields, tabID: string, modifiedField: string) => {
batch(() => {
const updateStoreFields = useCallback(
(fieldsData: ExplorerFields) => {
dispatch(
updateFields({
tabId: tabID,
tabId,
data: {
...fieldsData,
},
})
);
},
[explorerFields, tabId]
);

const sortStoreFields = useCallback(
(fieldName: string) => {
dispatch(
sortFields({
tabId: tabID,
data: [modifiedField],
tabId,
data: [fieldName],
})
);
});
};
},
[explorerFields, tabId]
);

// handling moving a field from available to selected
const handleAddField = useCallback(
(field: IField) => {
(field: IField, indexPos?: number) => {
updateStoreFields(
toggleFields(explorerFields, field, AVAILABLE_FIELDS, SELECTED_FIELDS),
tabId,
SELECTED_FIELDS
toggleFields(explorerFields, field, AVAILABLE_FIELDS, SELECTED_FIELDS, indexPos)
);
},
[explorerFields, tabId]
[explorerFields, tabId, updateStoreFields]
);

const handleRemoveField = useCallback(
(field: IField) => {
updateStoreFields(
toggleFields(explorerFields, field, SELECTED_FIELDS, AVAILABLE_FIELDS),
tabId,
AVAILABLE_FIELDS
);
// update to remove from selected fields and sort available fields
updateStoreFields(toggleFields(explorerFields, field, SELECTED_FIELDS, AVAILABLE_FIELDS));
sortStoreFields(AVAILABLE_FIELDS);
},
[explorerFields, tabId]
[explorerFields, tabId, updateStoreFields, sortStoreFields]
);

const onDragEnd = ({
Expand All @@ -143,10 +145,27 @@ export const Sidebar = (props: ISidebarProps) => {
if (destination.droppableId !== source.droppableId) {
// if dropped into the selected fields: add, if dropped into available: remove
if (destination.droppableId === 'SELECTED FIELDS') {
handleAddField({ name: draggableId, type: getFieldTypes(draggableId) });
handleAddField(
{ name: draggableId, type: getFieldTypes(draggableId, explorerFields) },
destination.index
);
} else if (destination.droppableId === 'AVAILABLE FIELDS') {
handleRemoveField({ name: draggableId, type: getFieldTypes(draggableId) });
handleRemoveField({ name: draggableId, type: getFieldTypes(draggableId, explorerFields) });
}
} else if (
destination.droppableId === 'SELECTED FIELDS' &&
source.droppableId === 'SELECTED FIELDS'
) {
// removes from selected and adds back into selected at specified index position
updateStoreFields(
toggleFields(
explorerFields,
{ name: draggableId, type: getFieldTypes(draggableId, explorerFields) },
SELECTED_FIELDS,
SELECTED_FIELDS,
destination.index
)
);
}
};

Expand Down
11 changes: 11 additions & 0 deletions public/components/event_analytics/utils/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -442,3 +442,14 @@ export const redoQuery = (
setData(res.jsonData);
});
};

// method to return the type of a field from its name
export const getFieldTypes = (newFieldName: string, explorerFields: IExplorerFields) => {
for (const field of explorerFields.availableFields) {
if (field.name === newFieldName) return field.type;
}
for (const field of explorerFields.selectedFields) {
if (field.name === newFieldName) return field.type;
}
return '';
};
Loading