chore(slo): improve SLO form index selector field (#168726)

This commit is contained in:
Kevin Delemme 2023-10-17 08:49:15 -04:00 committed by GitHub
parent 9cc7b8cda5
commit ad82e98220
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 109 additions and 132 deletions

View file

@ -0,0 +1,25 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { DataView } from '@kbn/data-views-plugin/public';
import { UseFetchDataViewsResponse } from '../use_fetch_data_views';
export const useFetchDataViews = (): UseFetchDataViewsResponse => {
return {
isLoading: false,
isError: false,
isSuccess: true,
data: Array(20)
.fill(0)
.map((_, i) => ({
title: `dataview-${i}`,
type: 'foo',
getName: () => `dataview-${i}`,
getIndexPattern: () => `.index-pattern-dataview-${i}`,
})) as DataView[],
};
};

View file

@ -60,21 +60,17 @@ export function useFetchSloList({
{
queryKey: sloKeys.list({ kqlQuery, page, sortBy, sortDirection }),
queryFn: async ({ signal }) => {
try {
const response = await http.get<FindSLOResponse>(`/api/observability/slos`, {
query: {
...(kqlQuery && { kqlQuery }),
...(sortBy && { sortBy }),
...(sortDirection && { sortDirection }),
...(page && { page }),
},
signal,
});
const response = await http.get<FindSLOResponse>(`/api/observability/slos`, {
query: {
...(kqlQuery && { kqlQuery }),
...(sortBy && { sortBy }),
...(sortDirection && { sortDirection }),
...(page && { page }),
},
signal,
});
return response;
} catch (error) {
throw error;
}
return response;
},
keepPreviousData: true,
refetchOnWindowFocus: false,

View file

@ -5,12 +5,7 @@
* 2.0.
*/
import {
QueryObserverResult,
RefetchOptions,
RefetchQueryFilters,
useQuery,
} from '@tanstack/react-query';
import { useQuery } from '@tanstack/react-query';
import { DataView } from '@kbn/data-views-plugin/public';
import { useKibana } from '../utils/kibana_react';
@ -19,9 +14,6 @@ export interface UseFetchDataViewsResponse {
isSuccess: boolean;
isError: boolean;
data: DataView[] | undefined;
refetch: <TPageData>(
options?: (RefetchOptions & RefetchQueryFilters<TPageData>) | undefined
) => Promise<QueryObserverResult<DataView[], unknown>>;
}
interface Params {
@ -33,16 +25,15 @@ export function useFetchDataViews({ name = '', size = 10 }: Params): UseFetchDat
const { dataViews } = useKibana().services;
const search = name.endsWith('*') ? name : `${name}*`;
const { isLoading, isError, isSuccess, data, refetch } = useQuery({
const { isLoading, isError, isSuccess, data } = useQuery({
queryKey: ['fetchDataViews', search],
queryFn: async () => {
try {
return await dataViews.find(search, size);
} catch (error) {
throw new Error(`Something went wrong. Error: ${error}`);
}
return dataViews.find(search, size);
},
retry: false,
keepPreviousData: true,
refetchOnWindowFocus: false,
});
return { isLoading, isError, isSuccess, data, refetch };
return { isLoading, isError, isSuccess, data };
}

View file

@ -32,18 +32,15 @@ export function useFetchIndices({ search }: Params): UseFetchIndicesResponse {
queryKey: ['fetchIndices', search],
queryFn: async () => {
const searchPattern = search?.endsWith('*') ? search : `${search}*`;
try {
const response = await http.get<ResolveIndexReponse>(
`/internal/index-pattern-management/resolve_index/${searchPattern}`
);
return response.indices.map((index) => index.name);
} catch (error) {
throw new Error(`Something went wrong. Error: ${error}`);
}
const response = await http.get<ResolveIndexReponse>(
`/internal/index-pattern-management/resolve_index/${searchPattern}`
);
return response.indices.map((index) => index.name);
},
retry: false,
enabled: Boolean(search),
refetchOnWindowFocus: false,
keepPreviousData: true,
});
return { isLoading, isError, isSuccess, data };

View file

@ -15,7 +15,7 @@ import { SLO_EDIT_FORM_DEFAULT_VALUES } from '../../constants';
export default {
component: Component,
title: 'app/SLO/EditPage/CustomKQL/IndexSelection',
title: 'app/SLO/EditPage/Common/IndexSelection',
decorators: [KibanaReactStorybookDecorator],
};

View file

@ -9,7 +9,7 @@ import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui';
import { DataView } from '@kbn/data-views-plugin/public';
import { i18n } from '@kbn/i18n';
import { debounce } from 'lodash';
import React, { useEffect, useMemo, useState } from 'react';
import React, { useState } from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import { useFetchDataViews } from '../../../../hooks/use_fetch_data_views';
import { useFetchIndices } from '../../../../hooks/use_fetch_indices';
@ -22,10 +22,7 @@ interface Option {
export function IndexSelection() {
const { control, getFieldState } = useFormContext<CreateSLOForm>();
const [searchValue, setSearchValue] = useState<string>('');
const [dataViewOptions, setDataViewOptions] = useState<Option[]>([]);
const [indexPatternOption, setIndexPatternOption] = useState<Option | undefined>();
const { isLoading: isIndicesLoading, data: indices = [] } = useFetchIndices({
search: searchValue,
@ -34,54 +31,19 @@ export function IndexSelection() {
name: searchValue,
});
useEffect(() => {
if (dataViews.length > 0) {
setDataViewOptions(createDataViewOptions(dataViews));
}
}, [dataViews]);
const options: Option[] = [];
if (!isDataViewsLoading && dataViews.length > 0) {
options.push(createDataViewsOption(dataViews));
}
if (!isIndicesLoading && !!searchValue) {
options.push(createIndexPatternOption(searchValue, indices));
}
useEffect(() => {
if (indices.length === 0) {
setIndexPatternOption(undefined);
} else if (!!searchValue) {
const searchPattern = searchValue.endsWith('*') ? searchValue : `${searchValue}*`;
const onSearchChange = debounce((value: string) => setSearchValue(value), 300);
setIndexPatternOption({
label: i18n.translate(
'xpack.observability.slo.sloEdit.customKql.indexSelection.indexPatternLabel',
{ defaultMessage: 'Use the index pattern' }
),
options: [
{
value: searchPattern,
label: i18n.translate(
'xpack.observability.slo.sloEdit.customKql.indexSelection.indexPatternFoundLabel',
{
defaultMessage:
'{searchPattern} (match {num, plural, one {# index} other {# indices}})',
values: {
searchPattern,
num: indices.length,
},
}
),
},
],
});
}
}, [indices.length, searchValue]);
const onDataViewSearchChange = useMemo(
() => debounce((value: string) => setSearchValue(value), 300),
[]
);
const placeholder = i18n.translate(
'xpack.observability.slo.sloEdit.customKql.indexSelection.placeholder',
{
defaultMessage: 'Select a Data View or use an index pattern',
}
);
const placeholder = i18n.translate('xpack.observability.slo.sloEdit.indexSelection.placeholder', {
defaultMessage: 'Select an index pattern',
});
return (
<EuiFormRow
@ -90,9 +52,7 @@ export function IndexSelection() {
})}
helpText={i18n.translate(
'xpack.observability.slo.sloEdit.customKql.indexSelection.helpText',
{
defaultMessage: 'Use * to broaden your query.',
}
{ defaultMessage: 'Use * to broaden your query.' }
)}
isInvalid={getFieldState('indicator.params.index').invalid}
>
@ -110,6 +70,7 @@ export function IndexSelection() {
isClearable
isInvalid={fieldState.invalid}
isLoading={isIndicesLoading && isDataViewsLoading}
placeholder={placeholder}
onChange={(selected: EuiComboBoxOptionOption[]) => {
if (selected.length) {
return field.onChange(selected[0].value);
@ -117,13 +78,18 @@ export function IndexSelection() {
field.onChange('');
}}
onSearchChange={onDataViewSearchChange}
options={
indexPatternOption ? [...dataViewOptions, indexPatternOption] : dataViewOptions
}
placeholder={placeholder}
options={options}
onSearchChange={onSearchChange}
selectedOptions={
!!field.value ? [findSelectedIndexPattern(dataViews, field.value)] : []
!!field.value
? [
{
value: field.value,
label: field.value,
'data-test-subj': 'indexSelectionSelectedValue',
},
]
: []
}
singleSelection
/>
@ -133,42 +99,50 @@ export function IndexSelection() {
);
}
function findSelectedIndexPattern(dataViews: DataView[], indexPattern: string) {
const selectedDataView = dataViews.find((view) => view.getIndexPattern() === indexPattern);
if (selectedDataView) {
return {
value: selectedDataView.getIndexPattern(),
label: createDataViewLabel(selectedDataView),
'data-test-subj': 'indexSelectionSelectedValue',
};
}
return {
value: indexPattern,
label: indexPattern,
'data-test-subj': 'indexSelectionSelectedValue',
};
}
function createDataViewLabel(dataView: DataView) {
return `${dataView.getName()} (${dataView.getIndexPattern()})`;
}
function createDataViewOptions(dataViews: DataView[]): Option[] {
const options = [];
options.push({
label: i18n.translate(
'xpack.observability.slo.sloEdit.customKql.indexSelection.dataViewOptionsLabel',
{ defaultMessage: 'Select an existing Data View' }
),
function createDataViewsOption(dataViews: DataView[]): Option {
return {
label: i18n.translate('xpack.observability.slo.sloEdit.indexSelection.dataViewOptionsLabel', {
defaultMessage: 'Select an index pattern from an existing Data View',
}),
options: dataViews
.map((view) => ({
label: createDataViewLabel(view),
value: view.getIndexPattern(),
}))
.sort((a, b) => String(a.label).localeCompare(b.label)),
});
return options;
};
}
function createIndexPatternOption(searchValue: string, indices: string[]): Option {
const indexPattern = searchValue.endsWith('*') ? searchValue : `${searchValue}*`;
const hasMatchingIndices = indices.length > 0;
return {
label: i18n.translate(
'xpack.observability.slo.sloEdit.customKql.indexSelection.indexPatternLabel',
{ defaultMessage: 'Use the index pattern' }
),
options: [
{
value: indexPattern,
label: hasMatchingIndices
? i18n.translate(
'xpack.observability.slo.sloEdit.customKql.indexSelection.indexPatternFoundLabel',
{
defaultMessage:
'{searchPattern} (match {num, plural, one {# index} other {# indices}})',
values: { searchPattern: indexPattern, num: indices.length },
}
)
: i18n.translate(
'xpack.observability.slo.sloEdit.indexSelection.indexPatternNoMatchLabel',
{ defaultMessage: '{searchPattern}', values: { searchPattern: indexPattern } }
),
},
],
};
}

View file

@ -27273,11 +27273,9 @@
"xpack.observability.slo.sloEdit.createAlert.ruleName": "Règle d'alerte de taux d'avancement du SLO",
"xpack.observability.slo.sloEdit.createAlert.title": "Créer",
"xpack.observability.slo.sloEdit.createSloButton": "Créer un SLO",
"xpack.observability.slo.sloEdit.customKql.indexSelection.dataViewOptionsLabel": "Sélectionner une vue de données existante",
"xpack.observability.slo.sloEdit.customKql.indexSelection.helpText": "Utilisez le caractère * pour élargir votre recherche.",
"xpack.observability.slo.sloEdit.customKql.indexSelection.indexPatternLabel": "Utiliser le modèle d'indexation",
"xpack.observability.slo.sloEdit.customKql.indexSelection.label": "Index",
"xpack.observability.slo.sloEdit.customKql.indexSelection.placeholder": "Sélectionner une vue de données ou utiliser un modèle dindexation",
"xpack.observability.slo.sloEdit.dataPreviewChart.xTitle": "Dernière heure",
"xpack.observability.slo.sloEdit.dataPreviewChart.yTitle": "SLI",
"xpack.observability.slo.sloEdit.definition.sliType": "Choisir le type de SLI",

View file

@ -27273,11 +27273,9 @@
"xpack.observability.slo.sloEdit.createAlert.ruleName": "SLOバーンレートアラートルール",
"xpack.observability.slo.sloEdit.createAlert.title": "作成",
"xpack.observability.slo.sloEdit.createSloButton": "SLOの作成",
"xpack.observability.slo.sloEdit.customKql.indexSelection.dataViewOptionsLabel": "既存のデータビューを選択",
"xpack.observability.slo.sloEdit.customKql.indexSelection.helpText": "* で検索クエリの範囲を広げます。",
"xpack.observability.slo.sloEdit.customKql.indexSelection.indexPatternLabel": "インデックスパターンを使用",
"xpack.observability.slo.sloEdit.customKql.indexSelection.label": "インデックス",
"xpack.observability.slo.sloEdit.customKql.indexSelection.placeholder": "データビューを選択するか、インデックスパターンを使用してください。",
"xpack.observability.slo.sloEdit.dataPreviewChart.xTitle": "過去 1 時間",
"xpack.observability.slo.sloEdit.dataPreviewChart.yTitle": "SLI",
"xpack.observability.slo.sloEdit.definition.sliType": "SLIタイプを選択",

View file

@ -27271,11 +27271,9 @@
"xpack.observability.slo.sloEdit.createAlert.ruleName": "SLO 消耗速度告警规则",
"xpack.observability.slo.sloEdit.createAlert.title": "创建",
"xpack.observability.slo.sloEdit.createSloButton": "创建 SLO",
"xpack.observability.slo.sloEdit.customKql.indexSelection.dataViewOptionsLabel": "选择现有数据视图",
"xpack.observability.slo.sloEdit.customKql.indexSelection.helpText": "使用 * 可扩大您的查询范围。",
"xpack.observability.slo.sloEdit.customKql.indexSelection.indexPatternLabel": "使用索引模式",
"xpack.observability.slo.sloEdit.customKql.indexSelection.label": "索引",
"xpack.observability.slo.sloEdit.customKql.indexSelection.placeholder": "选择数据视图或使用索引模式",
"xpack.observability.slo.sloEdit.dataPreviewChart.xTitle": "过去一小时",
"xpack.observability.slo.sloEdit.dataPreviewChart.yTitle": "SLI",
"xpack.observability.slo.sloEdit.definition.sliType": "选择 SLI 类型",