[Security Solution] Fix sorting on unmapped fields in Timeline Events… (#87241)
* [Security Solution] Fix sorting on unmapped fields in Timeline Events table * set unmapped_type to the column type * add missing types * Update saved_object_mappings.ts Co-authored-by: Xavier Mouligneau <189600+XavierM@users.noreply.github.com>
This commit is contained in:
parent
7cd1fa3167
commit
1e7c3f88ec
|
@ -28,10 +28,14 @@ export interface TimelineRequestBasicOptions extends IEsSearchRequest {
|
|||
factoryQueryType?: TimelineFactoryQueryTypes;
|
||||
}
|
||||
|
||||
export interface TimelineRequestSortField<Field = string> extends SortField<Field> {
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface TimelineRequestOptionsPaginated<Field = string>
|
||||
extends TimelineRequestBasicOptions {
|
||||
pagination: Pick<PaginationInputPaginated, 'activePage' | 'querySize'>;
|
||||
sort: Array<SortField<Field>>;
|
||||
sort: Array<TimelineRequestSortField<Field>>;
|
||||
}
|
||||
|
||||
export type TimelineStrategyResponseType<
|
||||
|
|
|
@ -146,6 +146,7 @@ const SavedFavoriteRuntimeType = runtimeTypes.partial({
|
|||
|
||||
const SavedSortObject = runtimeTypes.partial({
|
||||
columnId: unionWithNullType(runtimeTypes.string),
|
||||
columnType: unionWithNullType(runtimeTypes.string),
|
||||
sortDirection: unionWithNullType(runtimeTypes.string),
|
||||
});
|
||||
const SavedSortRuntimeType = runtimeTypes.union([
|
||||
|
|
|
@ -104,6 +104,7 @@ const eventsViewerDefaultProps = {
|
|||
sort: [
|
||||
{
|
||||
columnId: 'foo',
|
||||
columnType: 'number',
|
||||
sortDirection: 'asc' as SortDirection,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -216,8 +216,9 @@ const EventsViewerComponent: React.FC<Props> = ({
|
|||
|
||||
const sortField = useMemo(
|
||||
() =>
|
||||
sort.map(({ columnId, sortDirection }) => ({
|
||||
sort.map(({ columnId, columnType, sortDirection }) => ({
|
||||
field: columnId,
|
||||
type: columnType,
|
||||
direction: sortDirection as Direction,
|
||||
})),
|
||||
[sort]
|
||||
|
|
|
@ -26,6 +26,11 @@ SecuritySolutionAppWrapper.displayName = 'SecuritySolutionAppWrapper';
|
|||
and `EuiPopover`, `EuiToolTip` global styles
|
||||
*/
|
||||
export const AppGlobalStyle = createGlobalStyle<{ theme: { eui: { euiColorPrimary: string } } }>`
|
||||
// fixes double scrollbar on views with EventsTable
|
||||
#kibana-body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div.app-wrapper {
|
||||
background-color: rgba(0,0,0,0);
|
||||
}
|
||||
|
|
|
@ -238,7 +238,7 @@ export const mockGlobalState: State = {
|
|||
pinnedEventIds: {},
|
||||
pinnedEventsSaveObject: {},
|
||||
itemsPerPageOptions: [5, 10, 20],
|
||||
sort: [{ columnId: '@timestamp', sortDirection: Direction.desc }],
|
||||
sort: [{ columnId: '@timestamp', columnType: 'number', sortDirection: Direction.desc }],
|
||||
isSaving: false,
|
||||
version: null,
|
||||
status: TimelineStatus.active,
|
||||
|
|
|
@ -2150,6 +2150,7 @@ export const mockTimelineModel: TimelineModel = {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
],
|
||||
|
@ -2184,7 +2185,7 @@ export const mockTimelineResult: TimelineResult = {
|
|||
templateTimelineId: null,
|
||||
templateTimelineVersion: null,
|
||||
savedQueryId: null,
|
||||
sort: [{ columnId: '@timestamp', sortDirection: 'desc' }],
|
||||
sort: [{ columnId: '@timestamp', columnType: 'number', sortDirection: 'desc' }],
|
||||
version: '1',
|
||||
};
|
||||
|
||||
|
@ -2202,7 +2203,7 @@ export const defaultTimelineProps: CreateTimelineProps = {
|
|||
timeline: {
|
||||
activeTab: TimelineTabs.query,
|
||||
columns: [
|
||||
{ columnHeaderType: 'not-filtered', id: '@timestamp', width: 190 },
|
||||
{ columnHeaderType: 'not-filtered', id: '@timestamp', type: 'number', width: 190 },
|
||||
{ columnHeaderType: 'not-filtered', id: 'message', width: 180 },
|
||||
{ columnHeaderType: 'not-filtered', id: 'event.category', width: 180 },
|
||||
{ columnHeaderType: 'not-filtered', id: 'event.action', width: 180 },
|
||||
|
@ -2254,7 +2255,7 @@ export const defaultTimelineProps: CreateTimelineProps = {
|
|||
selectedEventIds: {},
|
||||
show: false,
|
||||
showCheckboxes: false,
|
||||
sort: [{ columnId: '@timestamp', sortDirection: Direction.desc }],
|
||||
sort: [{ columnId: '@timestamp', columnType: 'number', sortDirection: Direction.desc }],
|
||||
status: TimelineStatus.draft,
|
||||
title: '',
|
||||
timelineType: TimelineType.default,
|
||||
|
|
|
@ -111,6 +111,7 @@ describe('alert actions', () => {
|
|||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
id: '@timestamp',
|
||||
type: 'number',
|
||||
width: 190,
|
||||
},
|
||||
{
|
||||
|
@ -207,6 +208,7 @@ describe('alert actions', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
],
|
||||
|
|
|
@ -151,6 +151,7 @@ export const mockTimeline = {
|
|||
savedQueryId: null,
|
||||
sort: {
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
__typename: 'SortTimelineResult',
|
||||
},
|
||||
|
@ -403,6 +404,7 @@ export const mockTemplate = {
|
|||
savedQueryId: null,
|
||||
sort: {
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
__typename: 'SortTimelineResult',
|
||||
},
|
||||
|
|
|
@ -246,6 +246,7 @@ describe('helpers', () => {
|
|||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
id: '@timestamp',
|
||||
type: 'number',
|
||||
width: 190,
|
||||
},
|
||||
{
|
||||
|
@ -319,6 +320,7 @@ describe('helpers', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
],
|
||||
|
@ -347,6 +349,7 @@ describe('helpers', () => {
|
|||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
id: '@timestamp',
|
||||
type: 'number',
|
||||
width: 190,
|
||||
},
|
||||
{
|
||||
|
@ -420,6 +423,7 @@ describe('helpers', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
],
|
||||
|
@ -448,6 +452,7 @@ describe('helpers', () => {
|
|||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
id: '@timestamp',
|
||||
type: 'number',
|
||||
width: 190,
|
||||
},
|
||||
{
|
||||
|
@ -521,6 +526,7 @@ describe('helpers', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
],
|
||||
|
@ -547,6 +553,7 @@ describe('helpers', () => {
|
|||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
id: '@timestamp',
|
||||
type: 'number',
|
||||
width: 190,
|
||||
},
|
||||
{
|
||||
|
@ -620,6 +627,7 @@ describe('helpers', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
],
|
||||
|
@ -652,7 +660,7 @@ describe('helpers', () => {
|
|||
example: undefined,
|
||||
id: '@timestamp',
|
||||
placeholder: undefined,
|
||||
type: undefined,
|
||||
type: 'number',
|
||||
width: 190,
|
||||
},
|
||||
{
|
||||
|
@ -760,6 +768,7 @@ describe('helpers', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
],
|
||||
|
@ -815,6 +824,7 @@ describe('helpers', () => {
|
|||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
id: '@timestamp',
|
||||
type: 'number',
|
||||
width: 190,
|
||||
},
|
||||
{
|
||||
|
@ -929,6 +939,7 @@ describe('helpers', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
],
|
||||
|
@ -953,6 +964,7 @@ describe('helpers', () => {
|
|||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
id: '@timestamp',
|
||||
type: 'number',
|
||||
width: 190,
|
||||
},
|
||||
{
|
||||
|
@ -1026,6 +1038,7 @@ describe('helpers', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
],
|
||||
|
@ -1054,6 +1067,7 @@ describe('helpers', () => {
|
|||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
id: '@timestamp',
|
||||
type: 'number',
|
||||
width: 190,
|
||||
},
|
||||
{
|
||||
|
@ -1127,6 +1141,7 @@ describe('helpers', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
],
|
||||
|
|
|
@ -421,6 +421,7 @@ exports[`ColumnHeaders rendering renders correctly against snapshot 1`] = `
|
|||
Object {
|
||||
"columnHeaderType": "not-filtered",
|
||||
"id": "@timestamp",
|
||||
"type": "number",
|
||||
"width": 190,
|
||||
},
|
||||
Object {
|
||||
|
@ -468,6 +469,7 @@ exports[`ColumnHeaders rendering renders correctly against snapshot 1`] = `
|
|||
Array [
|
||||
Object {
|
||||
"columnId": "@timestamp",
|
||||
"columnType": "number",
|
||||
"sortDirection": "desc",
|
||||
},
|
||||
]
|
||||
|
|
|
@ -13,6 +13,7 @@ export const defaultHeaders: ColumnHeaderOptions[] = [
|
|||
{
|
||||
columnHeaderType: defaultColumnHeaderType,
|
||||
id: '@timestamp',
|
||||
type: 'number',
|
||||
width: DEFAULT_DATE_COLUMN_MIN_WIDTH,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@ exports[`Header renders correctly against snapshot 1`] = `
|
|||
Object {
|
||||
"columnHeaderType": "not-filtered",
|
||||
"id": "@timestamp",
|
||||
"type": "number",
|
||||
"width": 190,
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +18,7 @@ exports[`Header renders correctly against snapshot 1`] = `
|
|||
Array [
|
||||
Object {
|
||||
"columnId": "@timestamp",
|
||||
"columnType": "number",
|
||||
"sortDirection": "desc",
|
||||
},
|
||||
]
|
||||
|
@ -27,6 +29,7 @@ exports[`Header renders correctly against snapshot 1`] = `
|
|||
Object {
|
||||
"columnHeaderType": "not-filtered",
|
||||
"id": "@timestamp",
|
||||
"type": "number",
|
||||
"width": 190,
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +39,7 @@ exports[`Header renders correctly against snapshot 1`] = `
|
|||
Array [
|
||||
Object {
|
||||
"columnId": "@timestamp",
|
||||
"columnType": "number",
|
||||
"sortDirection": "desc",
|
||||
},
|
||||
]
|
||||
|
@ -47,6 +51,7 @@ exports[`Header renders correctly against snapshot 1`] = `
|
|||
Object {
|
||||
"columnHeaderType": "not-filtered",
|
||||
"id": "@timestamp",
|
||||
"type": "number",
|
||||
"width": 190,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ describe('Header', () => {
|
|||
const sort: Sort[] = [
|
||||
{
|
||||
columnId: columnHeader.id,
|
||||
columnType: columnHeader.type ?? 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
];
|
||||
|
@ -124,6 +125,7 @@ describe('Header', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: columnHeader.id,
|
||||
columnType: columnHeader.type ?? 'number',
|
||||
sortDirection: Direction.asc, // (because the previous state was Direction.desc)
|
||||
},
|
||||
],
|
||||
|
@ -191,6 +193,7 @@ describe('Header', () => {
|
|||
const nonMatching: Sort[] = [
|
||||
{
|
||||
columnId: 'differentSocks',
|
||||
columnType: columnHeader.type ?? 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
];
|
||||
|
@ -201,7 +204,11 @@ describe('Header', () => {
|
|||
|
||||
describe('getNextSortDirection', () => {
|
||||
test('it returns "asc" when the current direction is "desc"', () => {
|
||||
const sortDescending: Sort = { columnId: columnHeader.id, sortDirection: Direction.desc };
|
||||
const sortDescending: Sort = {
|
||||
columnId: columnHeader.id,
|
||||
columnType: columnHeader.type ?? 'number',
|
||||
sortDirection: Direction.desc,
|
||||
};
|
||||
|
||||
expect(getNextSortDirection(sortDescending)).toEqual('asc');
|
||||
});
|
||||
|
@ -209,6 +216,7 @@ describe('Header', () => {
|
|||
test('it returns "desc" when the current direction is "asc"', () => {
|
||||
const sortAscending: Sort = {
|
||||
columnId: columnHeader.id,
|
||||
columnType: columnHeader.type ?? 'number',
|
||||
sortDirection: Direction.asc,
|
||||
};
|
||||
|
||||
|
@ -218,6 +226,7 @@ describe('Header', () => {
|
|||
test('it returns "desc" by default', () => {
|
||||
const sortNone: Sort = {
|
||||
columnId: columnHeader.id,
|
||||
columnType: columnHeader.type ?? 'number',
|
||||
sortDirection: 'none',
|
||||
};
|
||||
|
||||
|
@ -230,6 +239,7 @@ describe('Header', () => {
|
|||
const sortMatches: Sort[] = [
|
||||
{
|
||||
columnId: columnHeader.id,
|
||||
columnType: columnHeader.type ?? 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
];
|
||||
|
@ -246,6 +256,7 @@ describe('Header', () => {
|
|||
const sortDoesNotMatch: Sort[] = [
|
||||
{
|
||||
columnId: 'someOtherColumn',
|
||||
columnType: columnHeader.type ?? 'number',
|
||||
sortDirection: 'none',
|
||||
},
|
||||
];
|
||||
|
|
|
@ -35,6 +35,7 @@ export const HeaderComponent: React.FC<Props> = ({
|
|||
|
||||
const onColumnSort = useCallback(() => {
|
||||
const columnId = header.id;
|
||||
const columnType = header.type ?? 'text';
|
||||
const sortDirection = getNewSortDirectionOnClick({
|
||||
clickedHeader: header,
|
||||
currentSort: sort,
|
||||
|
@ -46,6 +47,7 @@ export const HeaderComponent: React.FC<Props> = ({
|
|||
...sort,
|
||||
{
|
||||
columnId,
|
||||
columnType,
|
||||
sortDirection,
|
||||
},
|
||||
];
|
||||
|
@ -54,6 +56,7 @@ export const HeaderComponent: React.FC<Props> = ({
|
|||
...sort.slice(0, headerIndex),
|
||||
{
|
||||
columnId,
|
||||
columnType,
|
||||
sortDirection,
|
||||
},
|
||||
...sort.slice(headerIndex + 1),
|
||||
|
|
|
@ -38,6 +38,7 @@ describe('ColumnHeaders', () => {
|
|||
const sort: Sort[] = [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
];
|
||||
|
@ -108,10 +109,12 @@ describe('ColumnHeaders', () => {
|
|||
let mockSort: Sort[] = [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
{
|
||||
columnId: 'host.name',
|
||||
columnType: 'text',
|
||||
sortDirection: Direction.asc,
|
||||
},
|
||||
];
|
||||
|
@ -126,10 +129,12 @@ describe('ColumnHeaders', () => {
|
|||
mockSort = [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
{
|
||||
columnId: 'host.name',
|
||||
columnType: 'text',
|
||||
sortDirection: Direction.asc,
|
||||
},
|
||||
];
|
||||
|
@ -162,13 +167,15 @@ describe('ColumnHeaders', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
{
|
||||
columnId: 'host.name',
|
||||
columnType: 'text',
|
||||
sortDirection: Direction.asc,
|
||||
},
|
||||
{ columnId: 'event.category', sortDirection: Direction.desc },
|
||||
{ columnId: 'event.category', columnType: 'text', sortDirection: Direction.desc },
|
||||
],
|
||||
})
|
||||
);
|
||||
|
@ -201,9 +208,10 @@ describe('ColumnHeaders', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.asc,
|
||||
},
|
||||
{ columnId: 'host.name', sortDirection: Direction.asc },
|
||||
{ columnId: 'host.name', columnType: 'text', sortDirection: Direction.asc },
|
||||
],
|
||||
})
|
||||
);
|
||||
|
@ -236,9 +244,10 @@ describe('ColumnHeaders', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
{ columnId: 'host.name', sortDirection: Direction.desc },
|
||||
{ columnId: 'host.name', columnType: 'text', sortDirection: Direction.desc },
|
||||
],
|
||||
})
|
||||
);
|
||||
|
|
|
@ -230,11 +230,12 @@ export const ColumnHeadersComponent = ({
|
|||
id: timelineId,
|
||||
sort: cols.map(({ id, direction }) => ({
|
||||
columnId: id,
|
||||
columnType: columnHeaders.find((ch) => ch.id === id)?.type ?? 'text',
|
||||
sortDirection: direction as SortDirection,
|
||||
})),
|
||||
})
|
||||
),
|
||||
[dispatch, timelineId]
|
||||
[columnHeaders, dispatch, timelineId]
|
||||
);
|
||||
const sortedColumns = useMemo(
|
||||
() => ({
|
||||
|
|
|
@ -22,6 +22,7 @@ import { TimelineTabs } from '../../../../../common/types/timeline';
|
|||
const mockSort: Sort[] = [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -13,5 +13,6 @@ export type SortDirection = 'none' | Direction;
|
|||
/** Specifies which column the timeline is sorted on */
|
||||
export interface Sort {
|
||||
columnId: ColumnId;
|
||||
columnType: string;
|
||||
sortDirection: SortDirection;
|
||||
}
|
||||
|
|
|
@ -140,6 +140,7 @@ In other use cases the message field can be used to concatenate different values
|
|||
Array [
|
||||
Object {
|
||||
"columnId": "@timestamp",
|
||||
"columnType": "number",
|
||||
"sortDirection": "desc",
|
||||
},
|
||||
]
|
||||
|
|
|
@ -66,6 +66,7 @@ describe('PinnedTabContent', () => {
|
|||
const sort: Sort[] = [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -143,8 +143,9 @@ export const PinnedTabContentComponent: React.FC<Props> = ({
|
|||
|
||||
const timelineQuerySortField = useMemo(
|
||||
() =>
|
||||
sort.map(({ columnId, sortDirection }) => ({
|
||||
sort.map(({ columnId, columnType, sortDirection }) => ({
|
||||
field: columnId,
|
||||
type: columnType,
|
||||
direction: sortDirection as Direction,
|
||||
})),
|
||||
[sort]
|
||||
|
|
|
@ -283,6 +283,7 @@ In other use cases the message field can be used to concatenate different values
|
|||
Array [
|
||||
Object {
|
||||
"columnId": "@timestamp",
|
||||
"columnType": "number",
|
||||
"sortDirection": "desc",
|
||||
},
|
||||
]
|
||||
|
|
|
@ -67,6 +67,7 @@ describe('Timeline', () => {
|
|||
const sort: Sort[] = [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -211,9 +211,10 @@ export const QueryTabContentComponent: React.FC<Props> = ({
|
|||
|
||||
const timelineQuerySortField = useMemo(
|
||||
() =>
|
||||
sort.map(({ columnId, sortDirection }) => ({
|
||||
sort.map(({ columnId, columnType, sortDirection }) => ({
|
||||
field: columnId,
|
||||
direction: sortDirection as Direction,
|
||||
type: columnType,
|
||||
})),
|
||||
[sort]
|
||||
);
|
||||
|
|
|
@ -26,7 +26,7 @@ import {
|
|||
TimelineEventsAllRequestOptions,
|
||||
TimelineEdges,
|
||||
TimelineItem,
|
||||
SortField,
|
||||
TimelineRequestSortField,
|
||||
} from '../../../common/search_strategy';
|
||||
import { InspectResponse } from '../../types';
|
||||
import * as i18n from './translations';
|
||||
|
@ -56,7 +56,7 @@ export interface UseTimelineEventsProps {
|
|||
fields: string[];
|
||||
indexNames: string[];
|
||||
limit: number;
|
||||
sort: SortField[];
|
||||
sort: TimelineRequestSortField[];
|
||||
startDate: string;
|
||||
timerangeKind?: 'absolute' | 'relative';
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ export const initSortDefault = [
|
|||
{
|
||||
field: '@timestamp',
|
||||
direction: Direction.asc,
|
||||
type: 'number',
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ export const timelineDefaults: SubsetTimelineModel & Pick<TimelineModel, 'filter
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -149,7 +149,7 @@ describe('Epic Timeline', () => {
|
|||
selectedEventIds: {},
|
||||
show: true,
|
||||
showCheckboxes: false,
|
||||
sort: [{ columnId: '@timestamp', sortDirection: Direction.desc }],
|
||||
sort: [{ columnId: '@timestamp', columnType: 'number', sortDirection: Direction.desc }],
|
||||
status: TimelineStatus.active,
|
||||
version: 'WzM4LDFd',
|
||||
id: '11169110-fc22-11e9-8ca9-072f15ce2685',
|
||||
|
@ -289,6 +289,7 @@ describe('Epic Timeline', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
],
|
||||
|
|
|
@ -61,6 +61,7 @@ describe('epicLocalStorage', () => {
|
|||
const sort: Sort[] = [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
];
|
||||
|
@ -168,6 +169,7 @@ describe('epicLocalStorage', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: 'event.severity',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -103,6 +103,7 @@ const basicTimeline: TimelineModel = {
|
|||
sort: [
|
||||
{
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
],
|
||||
|
@ -932,6 +933,7 @@ describe('Timeline', () => {
|
|||
sort: [
|
||||
{
|
||||
columnId: 'some column',
|
||||
columnType: 'text',
|
||||
sortDirection: Direction.desc,
|
||||
},
|
||||
],
|
||||
|
@ -943,7 +945,9 @@ describe('Timeline', () => {
|
|||
});
|
||||
|
||||
test('should update the sort attribute', () => {
|
||||
expect(update.foo.sort).toEqual([{ columnId: 'some column', sortDirection: Direction.desc }]);
|
||||
expect(update.foo.sort).toEqual([
|
||||
{ columnId: 'some column', columnType: 'text', sortDirection: Direction.desc },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ describe('pickSavedTimeline', () => {
|
|||
templateTimelineVersion: null,
|
||||
eventType: 'all',
|
||||
filters: [],
|
||||
sort: { sortDirection: 'desc', columnId: '@timestamp' },
|
||||
sort: { sortDirection: 'desc', columnType: 'number', columnId: '@timestamp' },
|
||||
title: 'title',
|
||||
kqlMode: 'filter',
|
||||
timelineType: TimelineType.default,
|
||||
|
|
|
@ -212,6 +212,6 @@ export const mockTimeline = {
|
|||
templateTimelineId: null,
|
||||
dateRange: { start: '2020-11-03T13:34:40.339Z', end: '2020-11-04T13:34:40.339Z' },
|
||||
savedQueryId: null,
|
||||
sort: { columnId: '@timestamp', sortDirection: 'desc' },
|
||||
sort: { columnId: '@timestamp', columnType: 'number', sortDirection: 'desc' },
|
||||
status: 'draft',
|
||||
};
|
||||
|
|
|
@ -23,7 +23,7 @@ export const mockParsedObjects = [
|
|||
title: 'My duplicate timeline',
|
||||
dateRange: { start: '2020-03-18T09:31:47.294Z', end: '2020-03-19T09:31:47.294Z' },
|
||||
savedQueryId: null,
|
||||
sort: { columnId: '@timestamp', sortDirection: 'desc' },
|
||||
sort: { columnId: '@timestamp', columnType: 'number', sortDirection: 'desc' },
|
||||
created: 1584828930463,
|
||||
createdBy: 'angela',
|
||||
updated: 1584868346013,
|
||||
|
@ -698,6 +698,7 @@ export const mockCheckTimelinesStatusBeforeInstallResult = {
|
|||
savedQueryId: null,
|
||||
sort: {
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
created: 1588162404153,
|
||||
|
@ -870,6 +871,7 @@ export const mockCheckTimelinesStatusAfterInstallResult = {
|
|||
savedQueryId: null,
|
||||
sort: {
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
timelineType: 'template',
|
||||
|
@ -1052,6 +1054,7 @@ export const mockCheckTimelinesStatusAfterInstallResult = {
|
|||
savedQueryId: null,
|
||||
sort: {
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
timelineType: 'template',
|
||||
|
@ -1172,6 +1175,7 @@ export const mockCheckTimelinesStatusAfterInstallResult = {
|
|||
savedQueryId: null,
|
||||
sort: {
|
||||
columnId: '@timestamp',
|
||||
columnType: 'number',
|
||||
sortDirection: 'desc',
|
||||
},
|
||||
timelineType: 'template',
|
||||
|
|
|
@ -73,7 +73,7 @@ export const inputTimeline: SavedTimeline = {
|
|||
templateTimelineVersion: 1,
|
||||
dateRange: { start: '2020-03-26T12:50:05.527Z', end: '2020-03-27T12:50:05.527Z' },
|
||||
savedQueryId: null,
|
||||
sort: { columnId: '@timestamp', sortDirection: 'desc' },
|
||||
sort: { columnId: '@timestamp', columnType: 'number', sortDirection: 'desc' },
|
||||
};
|
||||
|
||||
export const inputTemplateTimeline = {
|
||||
|
@ -289,7 +289,7 @@ export const mockTimelines = () => ({
|
|||
title: 'test no.2',
|
||||
dateRange: { start: '2020-02-24T10:09:11.145Z', end: '2020-02-25T10:09:11.145Z' },
|
||||
savedQueryId: null,
|
||||
sort: { columnId: '@timestamp', sortDirection: 'desc' },
|
||||
sort: { columnId: '@timestamp', columnType: 'number', sortDirection: 'desc' },
|
||||
created: 1582625382448,
|
||||
createdBy: 'elastic',
|
||||
updated: 1583741197521,
|
||||
|
@ -371,7 +371,7 @@ export const mockTimelines = () => ({
|
|||
title: 'test no.3',
|
||||
dateRange: { start: '2020-02-24T10:09:11.145Z', end: '2020-02-25T10:09:11.145Z' },
|
||||
savedQueryId: null,
|
||||
sort: { columnId: '@timestamp', sortDirection: 'desc' },
|
||||
sort: { columnId: '@timestamp', columnType: 'number', sortDirection: 'desc' },
|
||||
created: 1582642817439,
|
||||
createdBy: 'elastic',
|
||||
updated: 1583741175216,
|
||||
|
|
|
@ -266,10 +266,14 @@ export const timelineSavedObjectMappings: SavedObjectsType['mappings'] = {
|
|||
type: 'keyword',
|
||||
},
|
||||
sort: {
|
||||
dynamic: false,
|
||||
properties: {
|
||||
columnId: {
|
||||
type: 'keyword',
|
||||
},
|
||||
columnType: {
|
||||
type: 'keyword',
|
||||
},
|
||||
sortDirection: {
|
||||
type: 'keyword',
|
||||
},
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
import { isEmpty } from 'lodash/fp';
|
||||
|
||||
import {
|
||||
SortField,
|
||||
TimerangeFilter,
|
||||
TimerangeInput,
|
||||
TimelineEventsAllRequestOptions,
|
||||
TimelineRequestSortField,
|
||||
} from '../../../../../../common/search_strategy';
|
||||
import { createQueryFilterClauses } from '../../../../../utils/build_query';
|
||||
|
||||
|
@ -46,10 +46,15 @@ export const buildTimelineEventsAllQuery = ({
|
|||
|
||||
const filter = [...filterClause, ...getTimerangeFilter(timerange), { match_all: {} }];
|
||||
|
||||
const getSortField = (sortFields: SortField[]) =>
|
||||
const getSortField = (sortFields: TimelineRequestSortField[]) =>
|
||||
sortFields.map((item) => {
|
||||
const field: string = item.field === 'timestamp' ? '@timestamp' : item.field;
|
||||
return { [field]: item.direction };
|
||||
return {
|
||||
[field]: {
|
||||
order: item.direction,
|
||||
unmapped_type: item.type,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const dslQuery = {
|
||||
|
|
Loading…
Reference in a new issue