+ {i18n.translate('xpack.investigateApp.investigationEditForm.h2.unableToLoadTheLabel', {
+ defaultMessage: 'Unable to load the investigation form',
+ })}
+
+ }
+ body={
+
+ {i18n.translate('xpack.investigateApp.investigationEditForm.p.thereWasAnErrorLabel', {
+ defaultMessage:
+ 'There was an error loading the Investigation. Contact your administrator for help.',
+ })}
+
+ }
+ />
+ );
+}
diff --git a/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_create_investigation.tsx b/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_create_investigation.tsx
new file mode 100644
index 0000000000000..31fda25640224
--- /dev/null
+++ b/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_create_investigation.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 { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public';
+import {
+ CreateInvestigationParams,
+ CreateInvestigationResponse,
+ FindInvestigationsResponse,
+} from '@kbn/investigation-shared';
+import { QueryKey, useMutation } from '@tanstack/react-query';
+import { useKibana } from './use_kibana';
+
+type ServerError = IHttpFetchError;
+
+export function useCreateInvestigation() {
+ const {
+ core: {
+ http,
+ notifications: { toasts },
+ },
+ } = useKibana();
+
+ return useMutation<
+ CreateInvestigationResponse,
+ ServerError,
+ CreateInvestigationParams,
+ { previousData?: FindInvestigationsResponse; queryKey?: QueryKey }
+ >(
+ ['createInvestigation'],
+ (investigation) => {
+ const body = JSON.stringify(investigation);
+ return http.post(`/api/observability/investigations`, {
+ body,
+ version: '2023-10-31',
+ });
+ },
+
+ {
+ onSuccess: (response, investigation, context) => {
+ toasts.addSuccess('Investigation created');
+ },
+ onError: (error, investigation, context) => {
+ toasts.addError(new Error(error.body?.message ?? 'An error occurred'), { title: 'Error' });
+ },
+ }
+ );
+}
diff --git a/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_fetch_investigation.ts b/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_fetch_investigation.ts
index 19b12364fd034..d9f2379593df4 100644
--- a/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_fetch_investigation.ts
+++ b/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_fetch_investigation.ts
@@ -16,7 +16,7 @@ import { investigationKeys } from './query_key_factory';
import { useKibana } from './use_kibana';
export interface Params {
- id: string;
+ id?: string;
initialInvestigation?: GetInvestigationResponse;
}
@@ -45,13 +45,14 @@ export function useFetchInvestigation({
const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data, refetch } = useQuery(
{
- queryKey: investigationKeys.fetch({ id }),
+ queryKey: investigationKeys.fetch({ id: id! }),
queryFn: async ({ signal }) => {
return await http.get(`/api/observability/investigations/${id}`, {
version: '2023-10-31',
signal,
});
},
+ enabled: Boolean(id),
initialData: initialInvestigation,
refetchOnWindowFocus: false,
refetchInterval: 15 * 1000,
diff --git a/x-pack/plugins/observability_solution/investigate_app/public/items/esql_item/register_esql_item.tsx b/x-pack/plugins/observability_solution/investigate_app/public/items/esql_item/register_esql_item.tsx
index 695daf1f48cb2..6ecab29020eba 100644
--- a/x-pack/plugins/observability_solution/investigate_app/public/items/esql_item/register_esql_item.tsx
+++ b/x-pack/plugins/observability_solution/investigate_app/public/items/esql_item/register_esql_item.tsx
@@ -8,7 +8,6 @@ import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';
import { css } from '@emotion/css';
import type { DataView } from '@kbn/data-views-plugin/common';
import type { ESQLSearchResponse } from '@kbn/es-types';
-import { ESQLDataGrid } from '@kbn/esql-datagrid/public';
import { i18n } from '@kbn/i18n';
import { type GlobalWidgetParameters } from '@kbn/investigate-plugin/public';
import type { Suggestion } from '@kbn/lens-plugin/public';
@@ -30,9 +29,6 @@ interface Props {
suggestion: Suggestion;
dataView: DataView;
esqlQuery: string;
- columns: ESQLSearchResponse['columns'];
- allColumns: ESQLSearchResponse['all_columns'];
- values: ESQLSearchResponse['values'];
dateHistogramResults?: {
query: string;
columns: ESQLSearchResponse['columns'];
@@ -48,8 +44,6 @@ interface EsqlItemParams {
interface EsqlItemData {
dataView: DataView;
- columns: ESQLSearchResponse['columns'];
- values: ESQLSearchResponse['values'];
suggestion: Suggestion;
dateHistoResponse?: {
query: string;
@@ -61,60 +55,20 @@ interface EsqlItemData {
export const ESQL_ITEM_TYPE = 'esql';
-export function EsqlWidget({
- suggestion,
- dataView,
- esqlQuery,
- columns,
- allColumns,
- values,
- dateHistogramResults,
-}: Props) {
+export function EsqlWidget({ suggestion, dataView, esqlQuery, dateHistogramResults }: Props) {
const {
dependencies: {
start: { lens },
},
} = useKibana();
- const datatable = useMemo(() => {
- return getDatatableFromEsqlResponse({
- columns,
- values,
- all_columns: allColumns,
- });
- }, [columns, values, allColumns]);
-
const input = useMemo(() => {
return getLensAttrsForSuggestion({
suggestion,
dataView,
query: esqlQuery,
- table: datatable,
});
- }, [suggestion, dataView, esqlQuery, datatable]);
-
- const memoizedQueryObject = useMemo(() => {
- return { esql: esqlQuery };
- }, [esqlQuery]);
-
- const initialColumns = useMemo(() => {
- const timestampColumn = datatable.columns.find((column) => column.name === '@timestamp');
- const messageColumn = datatable.columns.find((column) => column.name === 'message');
-
- if (datatable.columns.length > 20 && timestampColumn && messageColumn) {
- const hasDataForBothColumns = datatable.rows.every((row) => {
- const timestampValue = row['@timestamp'];
- const messageValue = row.message;
-
- return timestampValue !== null && timestampValue !== undefined && !!messageValue;
- });
-
- if (hasDataForBothColumns) {
- return [timestampColumn, messageColumn];
- }
- }
- return datatable.columns;
- }, [datatable.columns, datatable.rows]);
+ }, [suggestion, dataView, esqlQuery]);
const previewInput = useAbortableAsync(
async ({ signal }) => {
@@ -188,23 +142,12 @@ export function EsqlWidget({
grow={false}
className={css`
> div {
- height: 128px;
+ height: 196px;
}
`}
>
{innerElement}
-
-
-
);
}
@@ -214,7 +157,7 @@ export function EsqlWidget({
grow={true}
className={css`
> div {
- height: 128px;
+ height: 196px;
}
`}
>
@@ -273,8 +216,6 @@ export function registerEsqlItem({
return {
dataView: mainResponse.meta.dataView,
- columns: mainResponse.query.columns,
- values: mainResponse.query.values,
suggestion,
dateHistoResponse,
};
@@ -288,9 +229,6 @@ export function registerEsqlItem({
return (
(false);
+
return (
-
-
-
-
+ ,
+ rightSideItems: [
+
+ {i18n.translate('xpack.investigateApp.investigationDetails.escalateButtonLabel', {
+ defaultMessage: 'Escalate',
+ })}
+ ,
+ setEditFormFlyoutVisible(true)}
+ >
+ {i18n.translate('xpack.investigateApp.investigationDetails.editButtonLabel', {
+ defaultMessage: 'Edit',
+ })}
+ ,
+ ],
+ }}
+ >
+
+
+
+
-
-
-
-
+
+
+
+
+ {isEditFormFlyoutVisible && investigation && (
+ setEditFormFlyoutVisible(false)}
+ />
+ )}
+
);
}
diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_header/investigation_header.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_header/investigation_header.tsx
new file mode 100644
index 0000000000000..dd27039cac27e
--- /dev/null
+++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_header/investigation_header.tsx
@@ -0,0 +1,45 @@
+/*
+ * 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 { EuiButtonEmpty, EuiText } from '@elastic/eui';
+import { alertOriginSchema } from '@kbn/investigation-shared';
+import { ALERT_RULE_CATEGORY } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names';
+import React from 'react';
+import { useFetchAlert } from '../../../../hooks/use_get_alert_details';
+import { useKibana } from '../../../../hooks/use_kibana';
+import { useInvestigation } from '../../contexts/investigation_context';
+
+export function InvestigationHeader() {
+ const {
+ core: {
+ http: { basePath },
+ },
+ } = useKibana();
+
+ const { investigation } = useInvestigation();
+
+ const alertId = alertOriginSchema.is(investigation?.origin)
+ ? investigation?.origin.id
+ : undefined;
+ const { data: alertDetails } = useFetchAlert({ id: alertId });
+
+ return (
+ <>
+ {alertDetails && (
+
+ {`[Alert] ${alertDetails?.[ALERT_RULE_CATEGORY]} breached`}
+
+ )}
+ {investigation && {investigation.title}
}
+ >
+ );
+}
diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/investigation_details_page.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/investigation_details_page.tsx
index 559d8c32628b1..8eadd0de879bd 100644
--- a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/investigation_details_page.tsx
+++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/investigation_details_page.tsx
@@ -5,121 +5,44 @@
* 2.0.
*/
-import { EuiButton, EuiButtonEmpty, EuiText } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
-import { alertOriginSchema } from '@kbn/investigation-shared';
-import { ALERT_RULE_CATEGORY } from '@kbn/rule-data-utils/src/default_alerts_as_data';
+import { EuiLoadingSpinner } from '@elastic/eui';
import React from 'react';
import { useParams } from 'react-router-dom';
import useAsync from 'react-use/lib/useAsync';
-import { paths } from '../../../common/paths';
+import { InvestigationNotFound } from '../../components/investigation_not_found/investigation_not_found';
import { useFetchInvestigation } from '../../hooks/use_fetch_investigation';
-import { useFetchAlert } from '../../hooks/use_get_alert_details';
import { useKibana } from '../../hooks/use_kibana';
import { InvestigationDetails } from './components/investigation_details/investigation_details';
-import { InvestigationProvider } from './contexts/investigation_context';
import { InvestigationDetailsPathParams } from './types';
+import { InvestigationProvider } from './contexts/investigation_context';
export function InvestigationDetailsPage() {
const {
- core: {
- http: { basePath },
- security,
- },
- dependencies: {
- start: { observabilityShared },
- },
+ core: { security },
} = useKibana();
+ const { investigationId } = useParams();
const user = useAsync(() => {
return security.authc.getCurrentUser();
}, [security]);
- const { investigationId } = useParams();
-
- const ObservabilityPageTemplate = observabilityShared.navigation.PageTemplate;
-
const {
data: investigation,
isLoading: isFetchInvestigationLoading,
isError: isFetchInvestigationError,
} = useFetchInvestigation({ id: investigationId });
- const alertId = alertOriginSchema.is(investigation?.origin)
- ? investigation?.origin.id
- : undefined;
-
- const { data: alertDetails } = useFetchAlert({ id: alertId });
-
- if (!user.value) {
- return null;
- }
-
- if (isFetchInvestigationLoading || investigation === undefined) {
- return (
-
- {i18n.translate('xpack.investigateApp.fetchInvestigation.loadingLabel', {
- defaultMessage: 'Loading...',
- })}
-
- );
+ if (isFetchInvestigationLoading || user.loading) {
+ return ;
}
- if (isFetchInvestigationError) {
- return (
-
- {i18n.translate('xpack.investigateApp.fetchInvestigation.errorLabel', {
- defaultMessage: 'Error while fetching investigation',
- })}
-
- );
+ if (isFetchInvestigationError || !investigation || !user.value) {
+ return ;
}
return (
-
- {alertDetails && (
-
-
- {`[Alert] ${alertDetails?.[ALERT_RULE_CATEGORY]} breached`}
-
-
- )}
- {investigation && {investigation.title}
}
- >
- ),
- rightSideItems: [
-
- {i18n.translate('xpack.investigateApp.investigationDetails.escalateButtonLabel', {
- defaultMessage: 'Escalate',
- })}
- ,
- ],
- }}
- >
-
-
+
);
}
diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/list/investigation_list_page.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/list/investigation_list_page.tsx
index fa83cb4e1be54..74bdac54073a0 100644
--- a/x-pack/plugins/observability_solution/investigate_app/public/pages/list/investigation_list_page.tsx
+++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/list/investigation_list_page.tsx
@@ -6,22 +6,20 @@
*/
import { EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import React from 'react';
+import React, { useState } from 'react';
+import { InvestigationEditForm } from '../../components/investigation_edit_form/investigation_edit_form';
import { useKibana } from '../../hooks/use_kibana';
import { InvestigationList } from './components/investigation_list';
-import { paths } from '../../../common/paths';
export function InvestigationListPage() {
const {
- core: {
- http: { basePath },
- },
dependencies: {
start: { observabilityShared },
},
} = useKibana();
const ObservabilityPageTemplate = observabilityShared.navigation.PageTemplate;
+ const [isCreateFormFlyoutVisible, setCreateFormFlyoutVisible] = useState(false);
return (
setCreateFormFlyoutVisible(true)}
>
{i18n.translate('xpack.investigateApp.investigationListPage.createButtonLabel', {
defaultMessage: 'Create',
@@ -50,6 +48,9 @@ export function InvestigationListPage() {
}}
>
+ {isCreateFormFlyoutVisible && (
+ setCreateFormFlyoutVisible(false)} />
+ )}
);
}
diff --git a/x-pack/plugins/observability_solution/investigate_app/tsconfig.json b/x-pack/plugins/observability_solution/investigate_app/tsconfig.json
index b452b80b821ca..d689dd6086473 100644
--- a/x-pack/plugins/observability_solution/investigate_app/tsconfig.json
+++ b/x-pack/plugins/observability_solution/investigate_app/tsconfig.json
@@ -48,11 +48,9 @@
"@kbn/server-route-repository",
"@kbn/security-plugin",
"@kbn/ui-actions-plugin",
- "@kbn/esql-datagrid",
"@kbn/server-route-repository-utils",
"@kbn/core-saved-objects-server",
"@kbn/rule-registry-plugin",
- "@kbn/rule-data-utils",
"@kbn/shared-ux-router",
"@kbn/investigation-shared",
"@kbn/core-security-common",