diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/privileged_user_monitoring/components/key_insights_panel/common/key_insights_tile.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/privileged_user_monitoring/components/key_insights_panel/common/key_insights_tile.tsx index e4b2168a1b433..079bfda1ccd65 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/privileged_user_monitoring/components/key_insights_panel/common/key_insights_tile.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/privileged_user_monitoring/components/key_insights_panel/common/key_insights_tile.tsx @@ -5,31 +5,26 @@ * 2.0. */ -import React from 'react'; -import { EuiFlexItem, useEuiTheme } from '@elastic/eui'; -import { css } from '@emotion/react'; +import React, { useState, useEffect } from 'react'; +import { EuiFlexItem, EuiFlexGroup, EuiTitle, EuiText, EuiIcon } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; import type { ReactElement } from 'react'; import { createKeyInsightsPanelLensAttributes } from './lens_attributes'; import { VisualizationEmbeddable } from '../../../../../../common/components/visualization_actions/visualization_embeddable'; import { useEsqlGlobalFilterQuery } from '../../../../../../common/hooks/esql/use_esql_global_filter'; import { useGlobalTime } from '../../../../../../common/containers/use_global_time'; import { useSpaceId } from '../../../../../../common/hooks/use_space_id'; +import { useVisualizationResponse } from '../../../../../../common/components/visualization_actions/use_visualization_response'; -const LENS_VISUALIZATION_HEIGHT = 126; -const LENS_VISUALIZATION_MIN_WIDTH = 160; +const LENS_VISUALIZATION_HEIGHT = 150; +const LENS_VISUALIZATION_MIN_WIDTH = 220; interface KeyInsightsTileProps { - /** The title of the tile (i18n FormattedMessage element) */ title: ReactElement; - /** The label for the visualization (i18n FormattedMessage element) */ label: ReactElement; - /** Function that returns the ESQL query for the given namespace */ getEsqlQuery: (namespace: string) => string; - /** Unique ID for the visualization */ id: string; - /** The inspect title element for the visualization */ inspectTitle: ReactElement; - /** Optional override for space ID (if not provided, will use useSpaceId hook) */ spaceId?: string; } @@ -41,7 +36,6 @@ export const KeyInsightsTile: React.FC = ({ inspectTitle, spaceId: propSpaceId, }) => { - const { euiTheme } = useEuiTheme(); const filterQuery = useEsqlGlobalFilterQuery(); const timerange = useGlobalTime(); const hookSpaceId = useSpaceId(); @@ -61,30 +55,77 @@ export const KeyInsightsTile: React.FC = ({ filterQuery, }); - return ( - -
{ + if (visualizationResponse?.loading === true) { + setHasStartedLoading(true); + } + }, [visualizationResponse?.loading]); + + // Reset hasStartedLoading when any filter changes to allow fresh error detection + useEffect(() => { + setHasStartedLoading(false); + }, [timerange.from, timerange.to, filterQuery, effectiveSpaceId]); + + // Only show error state if: + // 1. Loading has started at least once (hasStartedLoading) + // 2. Loading is now complete (loading === false) + // 3. We have no tables (indicating an error) + if ( + hasStartedLoading && + visualizationResponse && + visualizationResponse.loading === false && + !visualizationResponse.tables + ) { + return ( + - -
-
+ + +

{titleString}

+
+
+ + + + + + + + + + + + + + + ); + } + + // If we reach here, either still loading or we have a valid response, so show the embeddable + return ( + ); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/privileged_user_monitoring/components/key_insights_panel/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/privileged_user_monitoring/components/key_insights_panel/index.tsx index 02cd8f47db0b5..130da872a32a5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/privileged_user_monitoring/components/key_insights_panel/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/privileged_user_monitoring/components/key_insights_panel/index.tsx @@ -6,8 +6,7 @@ */ import React from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { css } from '@emotion/react'; +import { EuiFlexGrid, EuiPanel } from '@elastic/eui'; import type { DataViewSpec } from '@kbn/data-views-plugin/public'; import { ActivePrivilegedUsersTile } from './active_privileged_users_tile'; @@ -17,59 +16,30 @@ import { GrantedRightsTile } from './granted_rights_tile'; import { AccountSwitchesTile } from './account_switches_tile'; import { AuthenticationsTile } from './authentications_tile'; -const tileStyles = css` - border: 1px solid #d3dae6; - border-radius: 6px; - padding: 12px; - height: 100%; -`; - export const KeyInsightsPanel: React.FC<{ spaceId: string; sourcerDataView: DataViewSpec }> = ({ spaceId, sourcerDataView, }) => { return ( - * { - min-width: calc(33.33% - 11px) !important; - max-width: calc(33.33% - 11px) !important; - } - `} - > - -
- -
-
- -
- -
-
- -
- -
-
- -
- -
-
- -
- -
-
- -
- -
-
-
+ + + + + + + + + + + + + + + + + + + + ); };