mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
fix(slo): timestamp field was allowing mutliple values (#194311)
This commit is contained in:
parent
ed9f9883d8
commit
c4e2a7256b
4 changed files with 124 additions and 71 deletions
|
@ -5,16 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ALL_VALUE, QuerySchema } from '@kbn/slo-schema';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiIconTip } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { DataView, FieldSpec } from '@kbn/data-views-plugin/common';
|
||||
import { QuerySchema } from '@kbn/slo-schema';
|
||||
import React from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import { OptionalText } from './optional_text';
|
||||
import { CreateSLOForm } from '../../types';
|
||||
import { IndexFieldSelector } from './index_field_selector';
|
||||
import { GroupByCardinality } from './group_by_cardinality';
|
||||
import { GroupByFieldSelector } from './group_by_field_selector';
|
||||
|
||||
export function GroupByField({
|
||||
dataView,
|
||||
|
@ -32,27 +29,8 @@ export function GroupByField({
|
|||
|
||||
return (
|
||||
<>
|
||||
<IndexFieldSelector
|
||||
<GroupByFieldSelector
|
||||
indexFields={groupByFields}
|
||||
name="groupBy"
|
||||
defaultValue={ALL_VALUE}
|
||||
label={
|
||||
<span>
|
||||
{i18n.translate('xpack.slo.sloEdit.groupBy.label', {
|
||||
defaultMessage: 'Group by',
|
||||
})}{' '}
|
||||
<EuiIconTip
|
||||
content={i18n.translate('xpack.slo.sloEdit.groupBy.tooltip', {
|
||||
defaultMessage: 'Create individual SLOs for each value of the selected field.',
|
||||
})}
|
||||
position="top"
|
||||
/>
|
||||
</span>
|
||||
}
|
||||
labelAppend={<OptionalText />}
|
||||
placeholder={i18n.translate('xpack.slo.sloEdit.groupBy.placeholder', {
|
||||
defaultMessage: 'Select an optional field to group by',
|
||||
})}
|
||||
isLoading={!!index && isLoading}
|
||||
isDisabled={!index}
|
||||
/>
|
||||
|
|
|
@ -5,35 +5,27 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui';
|
||||
import React, { useEffect, useState, ReactNode } from 'react';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow, EuiIconTip } from '@elastic/eui';
|
||||
import { FieldSpec } from '@kbn/data-views-plugin/common';
|
||||
import { createOptionsFromFields, Option } from '../../helpers/create_options';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ALL_VALUE } from '@kbn/slo-schema';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { Option, createOptionsFromFields } from '../../helpers/create_options';
|
||||
import { CreateSLOForm } from '../../types';
|
||||
import { OptionalText } from './optional_text';
|
||||
|
||||
interface Props {
|
||||
indexFields: FieldSpec[];
|
||||
name: 'groupBy' | 'indicator.params.timestampField';
|
||||
label: ReactNode | string;
|
||||
placeholder: string;
|
||||
isDisabled: boolean;
|
||||
isLoading: boolean;
|
||||
isRequired?: boolean;
|
||||
defaultValue?: string;
|
||||
labelAppend?: ReactNode;
|
||||
}
|
||||
export function IndexFieldSelector({
|
||||
indexFields,
|
||||
name,
|
||||
label,
|
||||
labelAppend,
|
||||
placeholder,
|
||||
isDisabled,
|
||||
isLoading,
|
||||
isRequired = false,
|
||||
defaultValue = '',
|
||||
}: Props) {
|
||||
|
||||
const placeholder = i18n.translate('xpack.slo.sloEdit.groupBy.placeholder', {
|
||||
defaultMessage: 'Select an optional field to group by',
|
||||
});
|
||||
|
||||
export function GroupByFieldSelector({ indexFields, isDisabled, isLoading }: Props) {
|
||||
const { control, getFieldState } = useFormContext<CreateSLOForm>();
|
||||
const [options, setOptions] = useState<Option[]>(createOptionsFromFields(indexFields));
|
||||
|
||||
|
@ -41,10 +33,10 @@ export function IndexFieldSelector({
|
|||
setOptions(createOptionsFromFields(indexFields));
|
||||
}, [indexFields]);
|
||||
|
||||
const getSelectedItems = (value: string | string[], fields: FieldSpec[]) => {
|
||||
const getSelectedItems = (value: string | string[]) => {
|
||||
const values = [value].flat();
|
||||
const selectedItems: Array<EuiComboBoxOptionOption<string>> = [];
|
||||
fields.forEach((field) => {
|
||||
indexFields.forEach((field) => {
|
||||
if (values.includes(field.name)) {
|
||||
selectedItems.push({ value: field.name, label: field.name });
|
||||
}
|
||||
|
@ -53,12 +45,27 @@ export function IndexFieldSelector({
|
|||
};
|
||||
|
||||
return (
|
||||
<EuiFormRow label={label} isInvalid={getFieldState(name).invalid} labelAppend={labelAppend}>
|
||||
<EuiFormRow
|
||||
label={
|
||||
<span>
|
||||
{i18n.translate('xpack.slo.sloEdit.groupBy.label', {
|
||||
defaultMessage: 'Group by',
|
||||
})}{' '}
|
||||
<EuiIconTip
|
||||
content={i18n.translate('xpack.slo.sloEdit.groupBy.tooltip', {
|
||||
defaultMessage: 'Create individual SLOs for each value of the selected field.',
|
||||
})}
|
||||
position="top"
|
||||
/>
|
||||
</span>
|
||||
}
|
||||
isInvalid={getFieldState('groupBy').invalid}
|
||||
labelAppend={<OptionalText />}
|
||||
>
|
||||
<Controller
|
||||
defaultValue={[defaultValue].flat()}
|
||||
name={name}
|
||||
defaultValue={[ALL_VALUE]}
|
||||
name={'groupBy'}
|
||||
control={control}
|
||||
rules={{ required: isRequired && !isDisabled }}
|
||||
render={({ field, fieldState }) => {
|
||||
return (
|
||||
<EuiComboBox<string>
|
||||
|
@ -75,7 +82,7 @@ export function IndexFieldSelector({
|
|||
return field.onChange(selected.map((selection) => selection.value));
|
||||
}
|
||||
|
||||
field.onChange(defaultValue);
|
||||
field.onChange([ALL_VALUE]);
|
||||
}}
|
||||
options={options}
|
||||
onSearchChange={(searchValue: string) => {
|
||||
|
@ -83,9 +90,7 @@ export function IndexFieldSelector({
|
|||
createOptionsFromFields(indexFields, ({ value }) => value.includes(searchValue))
|
||||
);
|
||||
}}
|
||||
selectedOptions={
|
||||
!!indexFields && !!field.value ? getSelectedItems(field.value, indexFields) : []
|
||||
}
|
||||
selectedOptions={!!indexFields && !!field.value ? getSelectedItems(field.value) : []}
|
||||
/>
|
||||
);
|
||||
}}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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 { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui';
|
||||
import { FieldSpec } from '@kbn/data-views-plugin/common';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { Option, createOptionsFromFields } from '../../helpers/create_options';
|
||||
import { CreateSLOForm } from '../../types';
|
||||
|
||||
interface Props {
|
||||
fields: FieldSpec[];
|
||||
isDisabled: boolean;
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
const placeholder = i18n.translate('xpack.slo.sloEdit.timestampField.placeholder', {
|
||||
defaultMessage: 'Select a timestamp field',
|
||||
});
|
||||
|
||||
export function TimestampFieldSelector({ fields, isDisabled, isLoading }: Props) {
|
||||
const { control, getFieldState } = useFormContext<CreateSLOForm>();
|
||||
const [options, setOptions] = useState<Option[]>(createOptionsFromFields(fields));
|
||||
|
||||
useEffect(() => {
|
||||
setOptions(createOptionsFromFields(fields));
|
||||
}, [fields]);
|
||||
|
||||
return (
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.slo.sloEdit.timestampField.label', {
|
||||
defaultMessage: 'Timestamp field',
|
||||
})}
|
||||
isInvalid={getFieldState('indicator.params.timestampField').invalid}
|
||||
>
|
||||
<Controller
|
||||
name={'indicator.params.timestampField'}
|
||||
control={control}
|
||||
rules={{ required: !isDisabled }}
|
||||
render={({ field, fieldState }) => {
|
||||
return (
|
||||
<EuiComboBox<string>
|
||||
{...field}
|
||||
async
|
||||
placeholder={placeholder}
|
||||
aria-label={placeholder}
|
||||
isClearable
|
||||
isDisabled={isLoading || isDisabled}
|
||||
isInvalid={fieldState.invalid}
|
||||
isLoading={isLoading}
|
||||
onChange={(selected: EuiComboBoxOptionOption[]) => {
|
||||
if (selected.length) {
|
||||
return field.onChange(selected[0].value);
|
||||
}
|
||||
|
||||
field.onChange('');
|
||||
}}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
options={options}
|
||||
onSearchChange={(searchValue: string) => {
|
||||
setOptions(
|
||||
createOptionsFromFields(fields, ({ value }) => value.includes(searchValue))
|
||||
);
|
||||
}}
|
||||
selectedOptions={
|
||||
!!fields && !!field.value ? [{ value: field.value, label: field.value }] : []
|
||||
}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
}
|
|
@ -6,13 +6,12 @@
|
|||
*/
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import { DataView } from '@kbn/data-views-plugin/public';
|
||||
import React from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import { IndexSelection } from './index_selection';
|
||||
import { IndexFieldSelector } from '../common/index_field_selector';
|
||||
import { CreateSLOForm } from '../../types';
|
||||
import { TimestampFieldSelector } from '../common/timestamp_field_selector';
|
||||
import { IndexSelection } from './index_selection';
|
||||
|
||||
export function IndexAndTimestampField({
|
||||
dataView,
|
||||
|
@ -32,18 +31,10 @@ export function IndexAndTimestampField({
|
|||
<IndexSelection selectedDataView={dataView} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={2}>
|
||||
<IndexFieldSelector
|
||||
indexFields={timestampFields}
|
||||
name="indicator.params.timestampField"
|
||||
label={i18n.translate('xpack.slo.sloEdit.timestampField.label', {
|
||||
defaultMessage: 'Timestamp field',
|
||||
})}
|
||||
placeholder={i18n.translate('xpack.slo.sloEdit.timestampField.placeholder', {
|
||||
defaultMessage: 'Select a timestamp field',
|
||||
})}
|
||||
<TimestampFieldSelector
|
||||
fields={timestampFields}
|
||||
isLoading={!!index && isLoading}
|
||||
isDisabled={!index}
|
||||
isRequired
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue