From c2a204269af459fc05145d2977493ad975c8df62 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Fri, 27 Sep 2024 13:04:20 +0200 Subject: [PATCH] [SLOs] Slo form little things (#193990) ## Summary Slo form little things !! Will auto add values for APM defaults to all instead of forcing user !! ### Changes Details | Before | After -- | -- | -- Data View component | image | image APM SLI | image | image --- .../dataview_picker/change_dataview.tsx | 38 ++--- .../apm_availability_indicator_type_form.tsx | 11 +- .../apm_common/use_apm_default_values.ts | 46 +++++++ .../apm_latency_indicator_type_form.tsx | 130 ++++++++---------- .../common/index_field_selector.tsx | 78 +++++------ .../index_and_timestamp_field.tsx | 51 +++++++ .../custom_common/index_selection.tsx | 6 +- .../custom_kql_indicator_type_form.tsx | 25 +--- .../custom_metric/custom_metric_type_form.tsx | 26 +--- .../histogram_indicator_type_form.tsx | 26 +--- .../slo_edit/components/slo_edit_form.tsx | 2 +- ...etics_availability_indicator_type_form.tsx | 18 ++- .../timeslice_metric_indicator.tsx | 26 +--- .../public/pages/slo_edit/slo_edit.test.tsx | 4 +- 14 files changed, 254 insertions(+), 233 deletions(-) create mode 100644 x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/apm_common/use_apm_default_values.ts create mode 100644 x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/custom_common/index_and_timestamp_field.tsx diff --git a/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx b/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx index f952c962032ed..ade754004b8ef 100644 --- a/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx +++ b/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx @@ -238,7 +238,7 @@ export function ChangeDataView({ return ( <> - + - setPopoverIsOpen(false)} - panelPaddingSize="none" - initialFocus={`[id="${searchListInputId}"]`} - display="block" - buffer={8} - > -
- -
-
+ + setPopoverIsOpen(false)} + panelPaddingSize="none" + initialFocus={`[id="${searchListInputId}"]`} + display="block" + buffer={8} + > +
+ +
+
+
diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.tsx index 7424db8a448e6..0dcddcdb232b5 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.tsx @@ -8,8 +8,9 @@ import { EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui'; import { APMTransactionErrorRateIndicator } from '@kbn/slo-schema'; import { i18n } from '@kbn/i18n'; -import React, { useEffect } from 'react'; +import React from 'react'; import { useFormContext } from 'react-hook-form'; +import { useApmDefaultValues } from '../apm_common/use_apm_default_values'; import { DATA_VIEW_FIELD } from '../custom_common/index_selection'; import { useCreateDataView } from '../../../../hooks/use_create_data_view'; import { GroupByField } from '../common/group_by_field'; @@ -22,7 +23,7 @@ import { formatAllFilters } from '../../helpers/format_filters'; import { getGroupByCardinalityFilters } from '../apm_common/get_group_by_cardinality_filters'; export function ApmAvailabilityIndicatorTypeForm() { - const { watch, setValue } = useFormContext>(); + const { watch } = useFormContext>(); const { data: apmIndex } = useFetchApmIndex(); const dataViewId = watch(DATA_VIEW_FIELD); @@ -47,11 +48,7 @@ export function ApmAvailabilityIndicatorTypeForm() { }); const allFilters = formatAllFilters(globalFilters, indicatorParamsFilters); - useEffect(() => { - if (apmIndex !== '') { - setValue('indicator.params.index', apmIndex); - } - }, [setValue, apmIndex]); + useApmDefaultValues(); const { dataView, loading: isIndexFieldsLoading } = useCreateDataView({ indexPatternString: apmIndex, diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/apm_common/use_apm_default_values.ts b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/apm_common/use_apm_default_values.ts new file mode 100644 index 0000000000000..d61578bed8594 --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/apm_common/use_apm_default_values.ts @@ -0,0 +1,46 @@ +/* + * 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 { useFormContext } from 'react-hook-form'; +import { ALL_VALUE, APMTransactionErrorRateIndicator } from '@kbn/slo-schema'; +import { useEffect } from 'react'; +import { useFetchApmIndex } from '../../../../hooks/use_fetch_apm_indices'; +import { CreateSLOForm } from '../../types'; + +export const useApmDefaultValues = () => { + const { watch, setValue } = useFormContext>(); + const { data: apmIndex } = useFetchApmIndex(); + + const [serviceName = '', environment = '', transactionType = '', transactionName = ''] = watch([ + 'indicator.params.service', + 'indicator.params.environment', + 'indicator.params.transactionType', + 'indicator.params.transactionName', + ]); + + useEffect(() => { + if (apmIndex !== '') { + setValue('indicator.params.index', apmIndex); + } + }, [setValue, apmIndex]); + + useEffect(() => { + if (serviceName) { + if (!environment) { + setValue('indicator.params.environment', ALL_VALUE); + } + + if (!transactionType) { + setValue('indicator.params.transactionType', ALL_VALUE); + } + + if (!transactionName) { + setValue('indicator.params.transactionName', ALL_VALUE); + } + } + }, [environment, serviceName, setValue, transactionName, transactionType]); +}; diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.tsx index fc2cf6f643c62..03b47aafe4150 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.tsx @@ -5,11 +5,12 @@ * 2.0. */ -import { EuiFieldNumber, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiIconTip } from '@elastic/eui'; +import { EuiFieldNumber, EuiFlexGroup, EuiFormRow, EuiIconTip } from '@elastic/eui'; import { APMTransactionDurationIndicator } from '@kbn/slo-schema'; import { i18n } from '@kbn/i18n'; -import React, { useEffect } from 'react'; +import React from 'react'; import { Controller, useFormContext } from 'react-hook-form'; +import { useApmDefaultValues } from '../apm_common/use_apm_default_values'; import { DATA_VIEW_FIELD } from '../custom_common/index_selection'; import { GroupByField } from '../common/group_by_field'; import { useCreateDataView } from '../../../../hooks/use_create_data_view'; @@ -22,7 +23,7 @@ import { formatAllFilters } from '../../helpers/format_filters'; import { getGroupByCardinalityFilters } from '../apm_common/get_group_by_cardinality_filters'; export function ApmLatencyIndicatorTypeForm() { - const { control, watch, getFieldState, setValue } = + const { control, watch, getFieldState } = useFormContext>(); const { data: apmIndex } = useFetchApmIndex(); @@ -47,11 +48,7 @@ export function ApmLatencyIndicatorTypeForm() { }); const allFilters = formatAllFilters(globalFilters, indicatorParamsFilters); - useEffect(() => { - if (apmIndex !== '') { - setValue('indicator.params.index', apmIndex); - } - }, [setValue, apmIndex]); + useApmDefaultValues(); const dataViewId = watch(DATA_VIEW_FIELD); @@ -124,70 +121,65 @@ export function ApmLatencyIndicatorTypeForm() { />
- - - - {i18n.translate('xpack.slo.sloEdit.apmLatency.threshold.placeholder', { - defaultMessage: 'Threshold (ms)', - })}{' '} - - - } - isInvalid={getFieldState('indicator.params.threshold').invalid} - > - ( - field.onChange(Number(event.target.value))} - /> - )} + + {i18n.translate('xpack.slo.sloEdit.apmLatency.threshold.placeholder', { + defaultMessage: 'Threshold (ms)', + })}{' '} + - - - - + } + isInvalid={getFieldState('indicator.params.threshold').invalid} + > + ( + field.onChange(Number(event.target.value))} + /> + )} + /> + + + - } + position="top" /> - - + } + /> diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/common/index_field_selector.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/common/index_field_selector.tsx index d744968d3bab8..0a277900ac31f 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/common/index_field_selector.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/common/index_field_selector.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiComboBox, EuiComboBoxOptionOption, EuiFlexItem, EuiFormRow } from '@elastic/eui'; +import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui'; import React, { useEffect, useState, ReactNode } from 'react'; import { Controller, useFormContext } from 'react-hook-form'; import { FieldSpec } from '@kbn/data-views-plugin/common'; @@ -53,45 +53,43 @@ export function IndexFieldSelector({ }; return ( - - - { - return ( - - {...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.map((selection) => selection.value)); - } - - field.onChange(defaultValue); - }} - options={options} - onSearchChange={(searchValue: string) => { - setOptions( - createOptionsFromFields(indexFields, ({ value }) => value.includes(searchValue)) - ); - }} - selectedOptions={ - !!indexFields && !!field.value ? getSelectedItems(field.value, indexFields) : [] + + { + return ( + + {...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.map((selection) => selection.value)); } - /> - ); - }} - /> - - + + field.onChange(defaultValue); + }} + options={options} + onSearchChange={(searchValue: string) => { + setOptions( + createOptionsFromFields(indexFields, ({ value }) => value.includes(searchValue)) + ); + }} + selectedOptions={ + !!indexFields && !!field.value ? getSelectedItems(field.value, indexFields) : [] + } + /> + ); + }} + /> + ); } diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/custom_common/index_and_timestamp_field.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/custom_common/index_and_timestamp_field.tsx new file mode 100644 index 0000000000000..b4b5bdd4557d4 --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/custom_common/index_and_timestamp_field.tsx @@ -0,0 +1,51 @@ +/* + * 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 { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { DataView } from '@kbn/data-views-plugin/public'; +import { useFormContext } from 'react-hook-form'; +import { IndexSelection } from './index_selection'; +import { IndexFieldSelector } from '../common/index_field_selector'; +import { CreateSLOForm } from '../../types'; + +export function IndexAndTimestampField({ + dataView, + isLoading, +}: { + dataView?: DataView; + isLoading: boolean; +}) { + const { watch } = useFormContext(); + const index = watch('indicator.params.index'); + + const timestampFields = dataView?.fields?.filter((field) => field.type === 'date') ?? []; + + return ( + + + + + + + + + ); +} diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/custom_common/index_selection.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/custom_common/index_selection.tsx index 526c955f2c6d8..1a33685a6f019 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/custom_common/index_selection.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/custom_common/index_selection.tsx @@ -53,7 +53,7 @@ export function IndexSelection({ selectedDataView }: { selectedDataView?: DataVi ]); return ( - + { setValue( diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.tsx index 43f0648084086..92ba2cac50e7f 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.tsx @@ -9,13 +9,13 @@ import { EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { useFormContext } from 'react-hook-form'; +import { IndexAndTimestampField } from '../custom_common/index_and_timestamp_field'; import { GroupByField } from '../common/group_by_field'; import { useCreateDataView } from '../../../../hooks/use_create_data_view'; import { CreateSLOForm } from '../../types'; import { DataPreviewChart } from '../common/data_preview_chart'; -import { IndexFieldSelector } from '../common/index_field_selector'; import { QueryBuilder } from '../common/query_builder'; -import { DATA_VIEW_FIELD, IndexSelection } from '../custom_common/index_selection'; +import { DATA_VIEW_FIELD } from '../custom_common/index_selection'; export function CustomKqlIndicatorTypeForm() { const { watch } = useFormContext(); @@ -26,29 +26,10 @@ export function CustomKqlIndicatorTypeForm() { indexPatternString: index, dataViewId, }); - const timestampFields = dataView?.fields?.filter((field) => field.type === 'date') ?? []; return ( - - - - - - - + field.type === 'date'); const metricFields = dataView?.fields.filter((field) => SUPPORTED_METRIC_FIELD_TYPES.includes(field.type) ); @@ -57,26 +56,7 @@ export function CustomMetricIndicatorTypeForm() { - - - - - - - - + field.type === 'histogram'); - const timestampFields = dataView?.fields.filter((field) => field.type === 'date'); return ( <> @@ -51,26 +50,7 @@ export function HistogramIndicatorTypeForm() { - - - - - - - - + void; } -export const maxWidth = 775; +export const maxWidth = 900; export function SloEditForm({ slo, initialValues, onSave }: Props) { const isEditMode = slo !== undefined; diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/synthetics_availability/synthetics_availability_indicator_type_form.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/synthetics_availability/synthetics_availability_indicator_type_form.tsx index 417b276cd1b1b..07f2f86663292 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/synthetics_availability/synthetics_availability_indicator_type_form.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/synthetics_availability/synthetics_availability_indicator_type_form.tsx @@ -14,7 +14,7 @@ import { SyntheticsAvailabilityIndicator, } from '@kbn/slo-schema'; import moment from 'moment'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { useFormContext } from 'react-hook-form'; import { DATA_VIEW_FIELD } from '../custom_common/index_selection'; import { useCreateDataView } from '../../../../hooks/use_create_data_view'; @@ -26,7 +26,8 @@ import { QueryBuilder } from '../common/query_builder'; import { FieldSelector } from '../synthetics_common/field_selector'; export function SyntheticsAvailabilityIndicatorTypeForm() { - const { watch } = useFormContext>(); + const { watch, setValue, getValues } = + useFormContext>(); const dataViewId = watch(DATA_VIEW_FIELD); const [monitorIds = [], projects = [], tags = [], index, globalFilters] = watch([ @@ -59,6 +60,19 @@ export function SyntheticsAvailabilityIndicatorTypeForm() { ); const allFilters = formatAllFilters(globalFilters, groupByCardinalityFilters); + const currentMonitors = getValues('indicator.params.monitorIds'); + + useEffect(() => { + if (!currentMonitors || !currentMonitors.length) { + setValue('indicator.params.monitorIds', [ + { + value: '*', + label: 'All', + }, + ]); + } + }, [currentMonitors, setValue]); + return ( diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/timeslice_metric/timeslice_metric_indicator.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/timeslice_metric/timeslice_metric_indicator.tsx index 82736e4e24a25..548f0bd0ab3e5 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/timeslice_metric/timeslice_metric_indicator.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/timeslice_metric/timeslice_metric_indicator.tsx @@ -18,13 +18,13 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; import { useFormContext } from 'react-hook-form'; +import { IndexAndTimestampField } from '../custom_common/index_and_timestamp_field'; import { useKibana } from '../../../../utils/kibana_react'; import { GroupByField } from '../common/group_by_field'; import { CreateSLOForm } from '../../types'; import { DataPreviewChart } from '../common/data_preview_chart'; -import { IndexFieldSelector } from '../common/index_field_selector'; import { QueryBuilder } from '../common/query_builder'; -import { DATA_VIEW_FIELD, IndexSelection } from '../custom_common/index_selection'; +import { DATA_VIEW_FIELD } from '../custom_common/index_selection'; import { MetricIndicator } from './metric_indicator'; import { COMPARATOR_MAPPING } from '../../constants'; import { useCreateDataView } from '../../../../hooks/use_create_data_view'; @@ -41,7 +41,6 @@ export function TimesliceMetricIndicatorTypeForm() { dataViewId, }); - const timestampFields = dataView?.fields.filter((field) => field.type === 'date'); const { uiSettings } = useKibana().services; const threshold = watch('indicator.params.metric.threshold'); const comparator = watch('indicator.params.metric.comparator'); @@ -56,26 +55,7 @@ export function TimesliceMetricIndicatorTypeForm() { - - - - - - - - + { expect(queryByTestId('apmLatencyServiceSelector')).toHaveTextContent('cartService'); expect(queryByTestId('apmLatencyEnvironmentSelector')).toHaveTextContent('prod'); - expect(queryByTestId('sloEditFormObjectiveSection')).toBeFalsy(); - expect(queryByTestId('sloEditFormDescriptionSection')).toBeFalsy(); + expect(queryByTestId('sloEditFormObjectiveSection')).toBeTruthy(); + expect(queryByTestId('sloEditFormDescriptionSection')).toBeTruthy(); }); });