From d5cc6592c4961fc24f30539f6df24f985b45b372 Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Thu, 8 Feb 2024 17:25:58 -0500 Subject: [PATCH] fix(slo): Optimistic updates (#176548) --- .../public/hooks/slo/use_create_slo.ts | 34 +--- .../public/hooks/slo/use_delete_slo.ts | 37 +---- .../public/hooks/slo/use_fetch_slo_inspect.ts | 60 +++++++ .../public/hooks/slo/use_inspect_slo.ts | 41 ----- .../public/hooks/slo/use_reset_slo.ts | 8 +- .../public/hooks/slo/use_update_slo.ts | 50 +----- .../common/equivalent_api_request.tsx | 32 ++-- .../components/common/inspect_slo_portal.tsx | 26 --- .../components/common/slo_inspect.tsx | 153 +++++++++--------- .../slo_edit/components/slo_edit_form.tsx | 9 +- .../public/pages/slo_edit/slo_edit.tsx | 19 +-- .../public/pages/slos/components/slo_list.tsx | 2 +- 12 files changed, 185 insertions(+), 286 deletions(-) create mode 100644 x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_inspect.ts delete mode 100644 x-pack/plugins/observability/public/hooks/slo/use_inspect_slo.ts delete mode 100644 x-pack/plugins/observability/public/pages/slo_edit/components/common/inspect_slo_portal.tsx diff --git a/x-pack/plugins/observability/public/hooks/slo/use_create_slo.ts b/x-pack/plugins/observability/public/hooks/slo/use_create_slo.ts index 6921c1f68cb15..b702e153fba5b 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_create_slo.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_create_slo.ts @@ -10,7 +10,6 @@ import { i18n } from '@kbn/i18n'; import { encode } from '@kbn/rison'; import type { CreateSLOInput, CreateSLOResponse, FindSLOResponse } from '@kbn/slo-schema'; import { QueryKey, useMutation, useQueryClient } from '@tanstack/react-query'; -import { v4 as uuidv4 } from 'uuid'; import { paths } from '../../../common/locators/paths'; import { useKibana } from '../../utils/kibana_react'; import { sloKeys } from './query_key_factory'; @@ -37,46 +36,17 @@ export function useCreateSlo() { return http.post(`/api/observability/slos`, { body }); }, { - onMutate: async ({ slo }) => { - await queryClient.cancelQueries({ queryKey: sloKeys.lists(), exact: false }); - - const queriesData = queryClient.getQueriesData({ - queryKey: sloKeys.lists(), - exact: false, - }); - - const [queryKey, previousData] = queriesData?.at(0) ?? []; - - const newItem = { ...slo, id: uuidv4(), summary: undefined }; - - const optimisticUpdate = { - page: previousData?.page ?? 1, - perPage: previousData?.perPage ?? 25, - total: previousData?.total ? previousData.total + 1 : 1, - results: [...(previousData?.results ?? []), newItem], - }; - - if (queryKey) { - queryClient.setQueryData(queryKey, optimisticUpdate); - } - - return { queryKey, previousData }; - }, onSuccess: (_data, { slo }) => { + queryClient.invalidateQueries({ queryKey: sloKeys.lists(), exact: false }); + toasts.addSuccess( i18n.translate('xpack.observability.slo.create.successNotification', { defaultMessage: 'Successfully created {name}', values: { name: slo.name }, }) ); - - queryClient.invalidateQueries({ queryKey: sloKeys.lists(), exact: false }); }, onError: (error, { slo }, context) => { - if (context?.previousData && context?.queryKey) { - queryClient.setQueryData(context.queryKey, context.previousData); - } - toasts.addError(new Error(error.body?.message ?? error.message), { title: i18n.translate('xpack.observability.slo.create.errorNotification', { defaultMessage: 'Something went wrong while creating {name}', diff --git a/x-pack/plugins/observability/public/hooks/slo/use_delete_slo.ts b/x-pack/plugins/observability/public/hooks/slo/use_delete_slo.ts index 0ba0c93266bda..2e77623fc991f 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_delete_slo.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_delete_slo.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { QueryKey, useMutation, useQueryClient } from '@tanstack/react-query'; +import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { FindSLOResponse } from '@kbn/slo-schema'; -import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public'; +import { QueryKey, useMutation, useQueryClient } from '@tanstack/react-query'; import { useKibana } from '../../utils/kibana_react'; import { sloKeys } from './query_key_factory'; @@ -36,38 +36,7 @@ export function useDeleteSlo() { } }, { - onMutate: async (slo) => { - await queryClient.cancelQueries({ queryKey: sloKeys.lists(), exact: false }); - - const queriesData = queryClient.getQueriesData({ - queryKey: sloKeys.lists(), - exact: false, - }); - const [queryKey, previousData] = queriesData?.at(0) ?? []; - - // taking into account partitioned slo - const matchingSloCount = - previousData?.results?.filter((result) => result.id === slo.id)?.length ?? 0; - - const optimisticUpdate = { - page: previousData?.page ?? 1, - perPage: previousData?.perPage ?? 25, - total: previousData?.total ? previousData.total - matchingSloCount : 0, - results: previousData?.results?.filter((result) => result.id !== slo.id) ?? [], - }; - - if (queryKey) { - queryClient.setQueryData(queryKey, optimisticUpdate); - } - - return { previousData, queryKey }; - }, - // If the mutation fails, use the context returned from onMutate to roll back onError: (error, { name }, context) => { - if (context?.previousData && context?.queryKey) { - queryClient.setQueryData(context.queryKey, context.previousData); - } - toasts.addError(new Error(error.body?.message ?? error.message), { title: i18n.translate('xpack.observability.slo.slo.delete.errorNotification', { defaultMessage: 'Failed to delete {name}', @@ -76,6 +45,8 @@ export function useDeleteSlo() { }); }, onSuccess: (_data, { name }) => { + queryClient.invalidateQueries({ queryKey: sloKeys.lists(), exact: false }); + toasts.addSuccess( i18n.translate('xpack.observability.slo.slo.delete.successNotification', { defaultMessage: 'Deleted {name}', diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_inspect.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_inspect.ts new file mode 100644 index 0000000000000..c83b398a8fb3b --- /dev/null +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_inspect.ts @@ -0,0 +1,60 @@ +/* + * 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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { CreateSLOInput, SLOResponse } from '@kbn/slo-schema'; +import { useQuery } from '@tanstack/react-query'; +import { useKibana } from '../../utils/kibana_react'; + +interface SLOInspectResponse { + slo: SLOResponse; + pipeline: Record; + rollUpTransform: TransformPutTransformRequest; + summaryTransform: TransformPutTransformRequest; + temporaryDoc: Record; +} + +export interface UseInspectSLOResponse { + data: SLOInspectResponse | undefined; + isLoading: boolean; + isSuccess: boolean; + isError: boolean; +} + +export function useFetchSloInspect(slo: CreateSLOInput, shouldInspect: boolean) { + const { http } = useKibana().services; + + const { isLoading, isError, isSuccess, data } = useQuery({ + queryKey: ['slo', 'inspect'], + queryFn: async ({ signal }) => { + try { + const body = JSON.stringify(slo); + const response = await http.post( + '/internal/api/observability/slos/_inspect', + { + body, + signal, + } + ); + + return response; + } catch (error) { + // ignore error + } + }, + enabled: shouldInspect, + refetchOnWindowFocus: false, + keepPreviousData: true, + }); + + return { + data, + isLoading, + isSuccess, + isError, + }; +} diff --git a/x-pack/plugins/observability/public/hooks/slo/use_inspect_slo.ts b/x-pack/plugins/observability/public/hooks/slo/use_inspect_slo.ts deleted file mode 100644 index 6eaa3165aee77..0000000000000 --- a/x-pack/plugins/observability/public/hooks/slo/use_inspect_slo.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public'; -import type { FindSLOResponse, SLOResponse } from '@kbn/slo-schema'; -import { QueryKey, useMutation } from '@tanstack/react-query'; -import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { CreateSLOInput } from '@kbn/slo-schema'; -import { useKibana } from '../../utils/kibana_react'; - -type ServerError = IHttpFetchError; - -interface SLOInspectResponse { - slo: SLOResponse; - pipeline: Record; - rollUpTransform: TransformPutTransformRequest; - summaryTransform: TransformPutTransformRequest; - temporaryDoc: Record; -} - -export function useInspectSlo() { - const { http } = useKibana().services; - - return useMutation< - SLOInspectResponse, - ServerError, - { slo: CreateSLOInput }, - { previousData?: FindSLOResponse; queryKey?: QueryKey } - >( - ['inspectSlo'], - ({ slo }) => { - const body = JSON.stringify(slo); - return http.post(`/internal/api/observability/slos/_inspect`, { body }); - }, - {} - ); -} diff --git a/x-pack/plugins/observability/public/hooks/slo/use_reset_slo.ts b/x-pack/plugins/observability/public/hooks/slo/use_reset_slo.ts index 35f166e89b766..9f67c5efe3972 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_reset_slo.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_reset_slo.ts @@ -4,10 +4,11 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { useMutation } from '@tanstack/react-query'; -import { i18n } from '@kbn/i18n'; import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public'; +import { i18n } from '@kbn/i18n'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useKibana } from '../../utils/kibana_react'; +import { sloKeys } from './query_key_factory'; type ServerError = IHttpFetchError; @@ -16,6 +17,8 @@ export function useResetSlo() { http, notifications: { toasts }, } = useKibana().services; + const queryClient = useQueryClient(); + return useMutation( ['resetSlo'], ({ id, name }) => { @@ -40,6 +43,7 @@ export function useResetSlo() { }); }, onSuccess: (_data, { name }) => { + queryClient.invalidateQueries({ queryKey: sloKeys.lists(), exact: false }); toasts.addSuccess( i18n.translate('xpack.observability.slo.slo.reset.successNotification', { defaultMessage: '{name} reset successfully', diff --git a/x-pack/plugins/observability/public/hooks/slo/use_update_slo.ts b/x-pack/plugins/observability/public/hooks/slo/use_update_slo.ts index 8f81075f0f2df..ff12ab2acdfe2 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_update_slo.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_update_slo.ts @@ -7,11 +7,11 @@ import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; +import { encode } from '@kbn/rison'; import type { FindSLOResponse, UpdateSLOInput, UpdateSLOResponse } from '@kbn/slo-schema'; import { QueryKey, useMutation, useQueryClient } from '@tanstack/react-query'; -import { encode } from '@kbn/rison'; -import { useKibana } from '../../utils/kibana_react'; import { paths } from '../../../common/locators/paths'; +import { useKibana } from '../../utils/kibana_react'; import { sloKeys } from './query_key_factory'; type ServerError = IHttpFetchError; @@ -36,47 +36,17 @@ export function useUpdateSlo() { return http.put(`/api/observability/slos/${sloId}`, { body }); }, { - onMutate: async ({ sloId, slo }) => { - await queryClient.cancelQueries({ queryKey: sloKeys.lists(), exact: false }); - - const queriesData = queryClient.getQueriesData({ - queryKey: sloKeys.lists(), - exact: false, - }); - const [queryKey, previousData] = queriesData?.at(0) ?? []; - - const updatedItem = { ...slo, id: sloId }; - const optimisticUpdate = { - page: previousData?.page ?? 1, - perPage: previousData?.perPage ?? 25, - total: previousData?.total ? previousData.total : 1, - results: [ - ...(previousData?.results?.filter((result) => result.id !== sloId) ?? []), - updatedItem, - ], - }; - - if (queryKey) { - queryClient.setQueryData(queryKey, optimisticUpdate); - } - - return { previousData, queryKey, sloId }; - }, onSuccess: (_data, { slo: { name } }) => { + queryClient.invalidateQueries({ queryKey: sloKeys.lists(), exact: false }); + toasts.addSuccess( i18n.translate('xpack.observability.slo.update.successNotification', { defaultMessage: 'Successfully updated {name}', values: { name }, }) ); - - queryClient.invalidateQueries({ queryKey: sloKeys.lists(), exact: false }); }, - onError: (error, { slo }, context) => { - if (context?.previousData && context?.queryKey) { - queryClient.setQueryData(context.queryKey, context.previousData); - } - + onError: (error, { slo, sloId }, context) => { toasts.addError(new Error(error.body?.message ?? error.message), { title: i18n.translate('xpack.observability.slo.update.errorNotification', { defaultMessage: 'Something went wrong when updating {name}', @@ -84,13 +54,9 @@ export function useUpdateSlo() { }), }); - if (context?.sloId) { - navigateToUrl( - http.basePath.prepend( - paths.observability.sloEditWithEncodedForm(context.sloId, encode(slo)) - ) - ); - } + navigateToUrl( + http.basePath.prepend(paths.observability.sloEditWithEncodedForm(sloId, encode(slo))) + ); }, } ); diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/common/equivalent_api_request.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/common/equivalent_api_request.tsx index 6bf597b12d9a9..3f76c0df540e5 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/common/equivalent_api_request.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/common/equivalent_api_request.tsx @@ -4,9 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { i18n } from '@kbn/i18n'; - -import React, { useEffect, useState } from 'react'; import { EuiButtonEmpty, EuiCodeBlock, @@ -18,29 +15,30 @@ import { EuiText, EuiTitle, } from '@elastic/eui'; -import { useFormContext } from 'react-hook-form'; +import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { CreateSLOInput } from '@kbn/slo-schema'; -import { CreateSLOForm } from '../../types'; +import { CreateSLOInput, GetSLOResponse } from '@kbn/slo-schema'; +import React, { useEffect, useState } from 'react'; +import { useFormContext } from 'react-hook-form'; import { transformCreateSLOFormToCreateSLOInput } from '../../helpers/process_slo_form_values'; +import { CreateSLOForm } from '../../types'; -export function EquivalentApiRequest({ - isCreateSloLoading, - isUpdateSloLoading, -}: { - isCreateSloLoading: boolean; - isUpdateSloLoading: boolean; -}) { - const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); +interface Props { + isEditMode: boolean; + disabled: boolean; + slo?: GetSLOResponse; +} +export function EquivalentApiRequest({ disabled, isEditMode, slo }: Props) { + const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); const { getValues, trigger } = useFormContext(); - const [sloData, setSloData] = useState(); useEffect(() => { if (!isFlyoutVisible) { return; } + trigger().then((isValid) => { if (isValid) { setSloData(transformCreateSLOFormToCreateSLOInput(getValues())); @@ -72,7 +70,7 @@ export function EquivalentApiRequest({ - {'POST /api/observability/slos'} + {isEditMode ? `PUT /api/observability/slos/${slo!.id}` : 'POST /api/observability/slos'} @@ -115,7 +113,7 @@ export function EquivalentApiRequest({ color="primary" iconType="copyClipboard" data-test-subj="sloFormCopyJsonButton" - disabled={isCreateSloLoading || isUpdateSloLoading} + disabled={disabled} onClick={() => setIsFlyoutVisible(true)} > {i18n.translate('xpack.observability.slo.sloEdit.equivalentApiRequest', { diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/common/inspect_slo_portal.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/common/inspect_slo_portal.tsx deleted file mode 100644 index d03772c9bf4ce..0000000000000 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/common/inspect_slo_portal.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 React from 'react'; -import { InPortal } from 'react-reverse-portal'; -import { GetSLOResponse } from '@kbn/slo-schema'; -import { CreateSLOForm } from '../../types'; -import { SLOInspectWrapper } from './slo_inspect'; -import { InspectSLOPortalNode } from '../../slo_edit'; - -export interface SloInspectPortalProps { - getValues: () => CreateSLOForm; - trigger: () => Promise; - slo?: GetSLOResponse; -} -export function InspectSLOPortal(props: SloInspectPortalProps) { - return ( - - - - ); -} diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/common/slo_inspect.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/common/slo_inspect.tsx index 2c96c0d2d05bc..9f911bb1787ea 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/common/slo_inspect.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/common/slo_inspect.tsx @@ -4,109 +4,114 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { i18n } from '@kbn/i18n'; - -import React, { ReactNode, useState } from 'react'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { useFetcher } from '@kbn/observability-shared-plugin/public'; import { - EuiFlyout, + EuiAccordion, EuiButton, + EuiButtonEmpty, + EuiButtonIcon, EuiCodeBlock, - EuiFlyoutHeader, - EuiTitle, - EuiFlyoutFooter, - EuiSpacer, - EuiFlyoutBody, - EuiToolTip, EuiFlexGroup, EuiFlexItem, + EuiFlyout, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, EuiLoadingSpinner, - EuiAccordion, - EuiButtonIcon, + EuiSpacer, + EuiTitle, + EuiToolTip, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { + IngestPipelinesListParams, INGEST_PIPELINES_APP_LOCATOR, INGEST_PIPELINES_PAGES, - IngestPipelinesListParams, } from '@kbn/ingest-pipelines-plugin/public'; -import { SloInspectPortalProps } from './inspect_slo_portal'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useFetcher } from '@kbn/observability-shared-plugin/public'; +import { GetSLOResponse } from '@kbn/slo-schema'; +import React, { ReactNode, useState } from 'react'; +import { useFormContext } from 'react-hook-form'; import { ObservabilityPublicPluginsStart } from '../../../..'; -import { useInspectSlo } from '../../../../hooks/slo/use_inspect_slo'; -import { transformCreateSLOFormToCreateSLOInput } from '../../helpers/process_slo_form_values'; import { enableInspectEsQueries } from '../../../../../common'; +import { useFetchSloInspect } from '../../../../hooks/slo/use_fetch_slo_inspect'; import { usePluginContext } from '../../../../hooks/use_plugin_context'; +import { transformCreateSLOFormToCreateSLOInput } from '../../helpers/process_slo_form_values'; +import { CreateSLOForm } from '../../types'; + +interface Props { + slo?: GetSLOResponse; + disabled: boolean; +} -export function SLOInspectWrapper(props: SloInspectPortalProps) { +export function SLOInspectWrapper({ slo, disabled }: Props) { const { services: { uiSettings }, } = useKibana(); const { isDev } = usePluginContext(); - const isInspectorEnabled = uiSettings?.get(enableInspectEsQueries); - return isDev || isInspectorEnabled ? : null; + return isDev || isInspectorEnabled ? : null; } -function SLOInspect({ getValues, trigger, slo }: SloInspectPortalProps) { +function SLOInspect({ slo, disabled }: Props) { const { share, http } = useKibana().services; + const { trigger, getValues } = useFormContext(); + const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); - const { mutateAsync: inspectSlo, data, isLoading } = useInspectSlo(); + const [isFormValid, setFormValid] = useState(false); - const { data: sloData } = useFetcher(async () => { - if (!isFlyoutVisible) { - return; - } - const isValid = await trigger(); - if (!isValid) { - return; - } - const sloForm = transformCreateSLOFormToCreateSLOInput(getValues()); - inspectSlo({ slo: { ...sloForm, id: slo?.id, revision: slo?.revision } }); - return sloForm; - }, [isFlyoutVisible, trigger, getValues, inspectSlo, slo]); + const sloFormValues = transformCreateSLOFormToCreateSLOInput(getValues()); + const { data: inspectSloData, isLoading } = useFetchSloInspect( + { ...sloFormValues, id: slo?.id, revision: slo?.revision }, + isFlyoutVisible && isFormValid + ); const { data: pipeLineUrl } = useFetcher(async () => { const ingestPipeLocator = share.url.locators.get( INGEST_PIPELINES_APP_LOCATOR ); - const ingestPipeLineId = data?.pipeline?.id; + const ingestPipeLineId = inspectSloData?.pipeline?.id; return ingestPipeLocator?.getUrl({ pipelineId: ingestPipeLineId, page: INGEST_PIPELINES_PAGES.LIST, }); - }, [data?.pipeline?.id, share.url.locators]); + }, [inspectSloData?.pipeline?.id, share.url.locators]); const closeFlyout = () => { setIsFlyoutVisible(false); - setIsInspecting(false); + setFormValid(false); }; - const [isInspecting, setIsInspecting] = useState(false); - const onButtonClick = () => { - trigger().then((isValid) => { - if (isValid) { - setIsInspecting(() => !isInspecting); - setIsFlyoutVisible(() => !isFlyoutVisible); - } - }); + const handleInspectButtonClick = async () => { + const valid = await trigger(); + if (!valid) { + setFormValid(false); + return; + } + + setFormValid(true); + setIsFlyoutVisible(true); }; let flyout; - if (isFlyoutVisible) { flyout = ( -

{CONFIG_LABEL}

+

+ {i18n.translate('xpack.observability.monitorInspect.configLabel', { + defaultMessage: 'SLO Configurations', + })} +

{isLoading && } - {data && ( + {inspectSloData && ( <> } - json={data.pipeline} + json={inspectSloData.pipeline} /> @@ -174,7 +179,7 @@ function SLOInspect({ getValues, trigger, slo }: SloInspectPortalProps) { 'xpack.observability.sLOInspect.codeBlockAccordion.temporaryDocumentLabel', { defaultMessage: 'Temporary document' } )} - json={data.temporaryDoc} + json={inspectSloData.temporaryDoc} /> )} @@ -193,20 +198,33 @@ function SLOInspect({ getValues, trigger, slo }: SloInspectPortalProps) {
); } + return ( <> - - {SLO_INSPECT_LABEL} - + {i18n.translate('xpack.observability.sLOInspect.sLOInspectButtonLabel', { + defaultMessage: 'SLO Inspect', + })} + {flyout} @@ -251,20 +269,3 @@ export function LoadingState() { ); } - -const SLO_INSPECT_LABEL = i18n.translate('xpack.observability.sLOInspect.sLOInspectButtonLabel', { - defaultMessage: 'SLO Inspect', -}); - -const VIEW_FORMATTED_CONFIG_LABEL = i18n.translate( - 'xpack.observability.slo.viewFormattedResourcesConfigsButtonLabel', - { defaultMessage: 'View formatted resources configs for SLO' } -); - -const VALID_CONFIG_LABEL = i18n.translate('xpack.observability.slo.formattedConfigLabel.valid', { - defaultMessage: 'Only valid form configurations can be inspected.', -}); - -const CONFIG_LABEL = i18n.translate('xpack.observability.monitorInspect.configLabel', { - defaultMessage: 'SLO Configurations', -}); diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx index dfc5fb1a6f563..9b5ddfc29b07d 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx @@ -10,7 +10,6 @@ import { i18n } from '@kbn/i18n'; import type { GetSLOResponse } from '@kbn/slo-schema'; import React, { useCallback } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; -import { InspectSLOPortal } from './common/inspect_slo_portal'; import { EquivalentApiRequest } from './common/equivalent_api_request'; import { paths } from '../../../../common/locators/paths'; import { useCreateSlo } from '../../../hooks/slo/use_create_slo'; @@ -32,6 +31,7 @@ import { SloEditFormObjectiveSection } from './slo_edit_form_objective_section'; import { useCreateRule } from '../../../hooks/use_create_rule'; import { createBurnRateRuleRequestBody } from '../helpers/create_burn_rate_rule_request_body'; import { BurnRateRuleParams } from '../../../typings'; +import { SLOInspectWrapper } from './common/slo_inspect'; export interface Props { slo?: GetSLOResponse; @@ -165,12 +165,13 @@ export function SloEditForm({ slo }: Props) { + - ); diff --git a/x-pack/plugins/observability/public/pages/slo_edit/slo_edit.tsx b/x-pack/plugins/observability/public/pages/slo_edit/slo_edit.tsx index f14f1d7a1446e..09eafbfdcc8c7 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/slo_edit.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/slo_edit.tsx @@ -5,23 +5,19 @@ * 2.0. */ -import React from 'react'; -import { useParams } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { useBreadcrumbs } from '@kbn/observability-shared-plugin/public'; - -import { createHtmlPortalNode, OutPortal } from 'react-reverse-portal'; +import React from 'react'; +import { useParams } from 'react-router-dom'; import { paths } from '../../../common/locators/paths'; -import { useKibana } from '../../utils/kibana_react'; -import { usePluginContext } from '../../hooks/use_plugin_context'; -import { useFetchSloDetails } from '../../hooks/slo/use_fetch_slo_details'; -import { useLicense } from '../../hooks/use_license'; import { useCapabilities } from '../../hooks/slo/use_capabilities'; import { useFetchSloGlobalDiagnosis } from '../../hooks/slo/use_fetch_global_diagnosis'; -import { SloEditForm } from './components/slo_edit_form'; +import { useFetchSloDetails } from '../../hooks/slo/use_fetch_slo_details'; +import { useLicense } from '../../hooks/use_license'; +import { usePluginContext } from '../../hooks/use_plugin_context'; +import { useKibana } from '../../utils/kibana_react'; import { HeaderMenu } from '../overview/components/header_menu/header_menu'; - -export const InspectSLOPortalNode = createHtmlPortalNode(); +import { SloEditForm } from './components/slo_edit_form'; export function SloEditPage() { const { @@ -78,7 +74,6 @@ export function SloEditPage() { : i18n.translate('xpack.observability.sloCreatePageTitle', { defaultMessage: 'Create new SLO', }), - rightSideItems: [], bottomBorder: false, }} data-test-subj="slosEditPage" diff --git a/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx b/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx index 19617273659b1..66a8ea84fcce8 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx @@ -76,7 +76,7 @@ export function SloList() { itemsPerPage={perPage} itemsPerPageOptions={[10, 25, 50, 100]} onChangeItemsPerPage={(newPerPage) => { - storeState({ perPage: newPerPage, page: 0 }); + onStateChange({ perPage: newPerPage }); }} />