Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into fips-agent-test
Browse files Browse the repository at this point in the history
  • Loading branch information
Ikuni17 committed Jun 10, 2024
2 parents 76e2373 + 2c76ad0 commit 91f1425
Show file tree
Hide file tree
Showing 50 changed files with 1,230 additions and 694 deletions.
40 changes: 22 additions & 18 deletions packages/kbn-text-based-editor/src/text_based_languages_editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,24 +238,28 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({
}, [language, onTextLangQuerySubmit, abortController, isQueryLoading, allowQueryCancellation]);

const onCommentLine = useCallback(() => {
const currentPosition = editor1.current?.getPosition();
const lineNumber = currentPosition?.lineNumber;
if (lineNumber) {
const lineContent = editorModel.current?.getLineContent(lineNumber) ?? '';
const hasComment = lineContent?.startsWith('//');
const commentedLine = hasComment ? lineContent?.replace('//', '') : `//${lineContent}`;
// executeEdits allows to keep edit in history
editor1.current?.executeEdits('comment', [
{
range: {
startLineNumber: lineNumber,
startColumn: 0,
endLineNumber: lineNumber,
endColumn: (lineContent?.length ?? 0) + 1,
const currentSelection = editor1?.current?.getSelection();
const startLineNumber = currentSelection?.startLineNumber;
const endLineNumber = currentSelection?.endLineNumber;
if (startLineNumber && endLineNumber) {
for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {
const lineContent = editorModel.current?.getLineContent(lineNumber) ?? '';
const hasComment = lineContent?.startsWith('//');
const commentedLine = hasComment ? lineContent?.replace('//', '') : `//${lineContent}`;

// executeEdits allows to keep edit in history
editor1.current?.executeEdits('comment', [
{
range: {
startLineNumber: lineNumber,
startColumn: 0,
endLineNumber: lineNumber,
endColumn: (lineContent?.length ?? 0) + 1,
},
text: commentedLine,
},
text: commentedLine,
},
]);
]);
}
}
}, []);

Expand Down Expand Up @@ -466,7 +470,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({

useEffect(() => {
const validateQuery = async () => {
if (editorModel?.current) {
if (editor1?.current) {
const parserMessages = await parseMessages();
setClientParserMessages({
errors: parserMessages?.errors ?? [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import React, { memo, FC, useMemo, useState, useCallback, useRef } from 'react';
import { ESQL_TABLE_TYPE } from '@kbn/data-plugin/common';
import {
Chart,
ElementClickListener,
Expand Down Expand Up @@ -253,7 +254,9 @@ export const HeatmapComponent: FC<HeatmapRenderProps> = memo(
datatables: [formattedTable.table],
});

const hasTooltipActions = interactive;
const isEsqlMode = table?.meta?.type === ESQL_TABLE_TYPE;

const hasTooltipActions = interactive && !isEsqlMode;

const onElementClick = useCallback(
(e: HeatmapElementEvent[]) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
Tooltip,
TooltipValue,
} from '@elastic/charts';
import { ESQL_TABLE_TYPE } from '@kbn/data-plugin/common';
import { i18n } from '@kbn/i18n';
import { useEuiTheme } from '@elastic/eui';
import type { PaletteRegistry } from '@kbn/coloring';
Expand Down Expand Up @@ -409,8 +410,9 @@ const PartitionVisComponent = (props: PartitionVisComponentProps) => {
? getColumnByAccessor(splitRow[0], visData.columns)
: undefined;

const isEsqlMode = originalVisData?.meta?.type === ESQL_TABLE_TYPE;
const hasTooltipActions =
interactive && bucketAccessors.filter((a) => a !== 'metric-name').length > 0;
interactive && !isEsqlMode && bucketAccessors.filter((a) => a !== 'metric-name').length > 0;

const tooltip: TooltipProps = {
...(fixedViewPort ? { boundary: fixedViewPort } : {}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,7 @@ export function XYChart({
xDomain={xDomain}
// enable brushing only for time charts, for both ES|QL and DSL queries
onBrushEnd={interactive ? (brushHandler as BrushEndListener) : undefined}
onElementClick={interactive && !isEsqlMode ? clickHandler : undefined}
onElementClick={interactive ? clickHandler : undefined}
legendAction={
interactive
? getLegendAction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,97 +9,167 @@
import { DataViewsContract } from '@kbn/data-views-plugin/common';
import { dataPluginMock } from '../../mocks';
import { setIndexPatterns, setSearchService } from '../../services';
import { createFiltersFromValueClickAction } from './create_filters_from_value_click';
import {
createFiltersFromValueClickAction,
appendFilterToESQLQueryFromValueClickAction,
} from './create_filters_from_value_click';
import { FieldFormatsGetConfigFn, BytesFormat } from '@kbn/field-formats-plugin/common';
import { RangeFilter } from '@kbn/es-query';

const mockField = {
name: 'bytes',
filterable: true,
};
describe('createFiltersFromClickEvent', () => {
const dataStart = dataPluginMock.createStartContract();
setSearchService(dataStart.search);
setIndexPatterns({
...dataStart.indexPatterns,
get: async () => ({
id: 'logstash-*',
fields: {
getByName: () => mockField,
filter: () => [mockField],
},
getFormatterForField: () => new BytesFormat({}, (() => {}) as FieldFormatsGetConfigFn),
}),
} as unknown as DataViewsContract);
describe('createFiltersFromValueClick', () => {
let dataPoints: Parameters<typeof createFiltersFromValueClickAction>[0]['data'];

describe('createFiltersFromValueClick', () => {
let dataPoints: Parameters<typeof createFiltersFromValueClickAction>[0]['data'];

beforeEach(() => {
dataPoints = [
{
table: {
columns: [
{
name: 'test',
id: '1-1',
meta: {
type: 'date',
source: 'esaggs',
sourceParams: {
indexPatternId: 'logstash-*',
type: 'histogram',
params: {
field: 'bytes',
interval: 30,
otherBucket: true,
beforeEach(() => {
dataPoints = [
{
table: {
columns: [
{
name: 'test',
id: '1-1',
meta: {
type: 'date',
source: 'esaggs',
sourceParams: {
indexPatternId: 'logstash-*',
type: 'histogram',
params: {
field: 'bytes',
interval: 30,
otherBucket: true,
},
},
},
},
},
],
rows: [
{
'1-1': '2048',
},
],
},
column: 0,
row: 0,
value: 'test',
},
];

const dataStart = dataPluginMock.createStartContract();
setSearchService(dataStart.search);
setIndexPatterns({
...dataStart.indexPatterns,
get: async () => ({
id: 'logstash-*',
fields: {
getByName: () => mockField,
filter: () => [mockField],
],
rows: [
{
'1-1': '2048',
},
],
},
column: 0,
row: 0,
value: 'test',
},
getFormatterForField: () => new BytesFormat({}, (() => {}) as FieldFormatsGetConfigFn),
}),
} as unknown as DataViewsContract);
});
];
});
test('ignores event when value for rows is not provided', async () => {
dataPoints[0].table.rows[0]['1-1'] = null;
const filters = await createFiltersFromValueClickAction({ data: dataPoints });

test('ignores event when value for rows is not provided', async () => {
dataPoints[0].table.rows[0]['1-1'] = null;
const filters = await createFiltersFromValueClickAction({ data: dataPoints });
expect(filters.length).toEqual(0);
});

expect(filters.length).toEqual(0);
});
test('handles an event when aggregations type is a terms', async () => {
(dataPoints[0].table.columns[0].meta.sourceParams as any).type = 'terms';
const filters = await createFiltersFromValueClickAction({ data: dataPoints });

test('handles an event when aggregations type is a terms', async () => {
(dataPoints[0].table.columns[0].meta.sourceParams as any).type = 'terms';
const filters = await createFiltersFromValueClickAction({ data: dataPoints });
expect(filters.length).toEqual(1);
expect(filters[0].query?.match_phrase?.bytes).toEqual('2048');
});

expect(filters.length).toEqual(1);
expect(filters[0].query?.match_phrase?.bytes).toEqual('2048');
});
test('handles an event when aggregations type is not terms', async () => {
const filters = await createFiltersFromValueClickAction({ data: dataPoints });

test('handles an event when aggregations type is not terms', async () => {
const filters = await createFiltersFromValueClickAction({ data: dataPoints });
expect(filters.length).toEqual(1);

expect(filters.length).toEqual(1);
const [rangeFilter] = filters as RangeFilter[];
expect(rangeFilter.query.range.bytes.gte).toEqual(2048);
expect(rangeFilter.query.range.bytes.lt).toEqual(2078);
});

const [rangeFilter] = filters as RangeFilter[];
expect(rangeFilter.query.range.bytes.gte).toEqual(2048);
expect(rangeFilter.query.range.bytes.lt).toEqual(2078);
test('handles non-unique filters', async () => {
const [point] = dataPoints;
const filters = await createFiltersFromValueClickAction({ data: [point, point] });

expect(filters.length).toEqual(1);
});
});
describe('appendFilterToESQLQueryFromValueClickAction', () => {
let dataPoints: Parameters<typeof appendFilterToESQLQueryFromValueClickAction>[0]['data'];
beforeEach(() => {
dataPoints = [
{
table: {
columns: [
{
name: 'columnA',
id: 'columnA',
meta: {
type: 'date',
},
},
],
rows: [
{
columnA: '2048',
},
],
},
column: 0,
row: 0,
value: 'test',
},
];
});
test('should return null for date fields', async () => {
const queryString = await appendFilterToESQLQueryFromValueClickAction({
data: dataPoints,
query: { esql: 'from meow' },
});

expect(queryString).toBeUndefined();
});

test('handles non-unique filters', async () => {
const [point] = dataPoints;
const filters = await createFiltersFromValueClickAction({ data: [point, point] });
test('should return null if no aggregate query is present', async () => {
dataPoints[0].table.columns[0] = {
name: 'test',
id: '1-1',
meta: {
type: 'string',
},
};
const queryString = await appendFilterToESQLQueryFromValueClickAction({
data: dataPoints,
});

expect(queryString).toBeUndefined();
});

test('should return the update query string', async () => {
dataPoints[0].table.columns[0] = {
name: 'columnA',
id: 'columnA',
meta: {
type: 'string',
},
};
const queryString = await appendFilterToESQLQueryFromValueClickAction({
data: dataPoints,
query: { esql: 'from meow' },
});

expect(filters.length).toEqual(1);
expect(queryString).toEqual(`from meow
| where \`columnA\`=="2048"`);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@

import _ from 'lodash';
import { Datatable } from '@kbn/expressions-plugin/public';
import { compareFilters, COMPARE_ALL_OPTIONS, Filter, toggleFilterNegated } from '@kbn/es-query';
import {
compareFilters,
COMPARE_ALL_OPTIONS,
Filter,
toggleFilterNegated,
type AggregateQuery,
} from '@kbn/es-query';
import { appendWhereClauseToESQLQuery } from '@kbn/esql-utils';
import { getIndexPatterns, getSearchService } from '../../services';
import { AggConfigSerialized } from '../../../common/search/aggs';
import { mapAndFlattenFilters } from '../../query';
Expand All @@ -22,6 +29,7 @@ interface ValueClickDataContext {
}>;
timeFieldName?: string;
negate?: boolean;
query?: AggregateQuery;
}

/**
Expand Down Expand Up @@ -148,3 +156,32 @@ export const createFiltersFromValueClickAction = async ({
compareFilters(a, b, COMPARE_ALL_OPTIONS)
);
};

/** @public */
export const appendFilterToESQLQueryFromValueClickAction = ({
data,
query,
}: ValueClickDataContext) => {
if (!query) {
return;
}
// Do not append in case of time series, for now. We need to find a way to compute the interval
// to create the time range filter correctly. The users can brush to update the time filter instead.
const dataPoints = data.filter((point) => {
return point && point.table?.columns?.[point.column]?.meta?.type !== 'date';
});

if (!dataPoints.length) {
return;
}
const { table, column: columnIndex, row: rowIndex } = dataPoints[dataPoints.length - 1];

if (table?.columns?.[columnIndex]) {
const column = table.columns[columnIndex];
const value: unknown = rowIndex > -1 ? table.rows[rowIndex][column.id] : null;
if (value == null) {
return;
}
return appendWhereClauseToESQLQuery(query.esql, column.name, value, '+', column.meta?.type);
}
};
Loading

0 comments on commit 91f1425

Please sign in to comment.