Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you describe what the effect of this change to the height/weight is?

Copy link
Copy Markdown
Contributor Author

@abhishekbhatia1710 abhishekbhatia1710 Jul 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, with the EUIGroup and EuiPanel coming into play, the space of EuiFlex became more and the tiles occupied 4 columns and 2 rows in the (usual monitor size window) instead of 2 columns and 2 rows as below :

image

So the height and width brings the tile in 2x3 frame (for usual monitor size window)

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;
}

Expand All @@ -41,7 +36,6 @@ export const KeyInsightsTile: React.FC<KeyInsightsTileProps> = ({
inspectTitle,
spaceId: propSpaceId,
}) => {
const { euiTheme } = useEuiTheme();
const filterQuery = useEsqlGlobalFilterQuery();
const timerange = useGlobalTime();
const hookSpaceId = useSpaceId();
Expand All @@ -61,30 +55,77 @@ export const KeyInsightsTile: React.FC<KeyInsightsTileProps> = ({
filterQuery,
});

return (
<EuiFlexItem grow={false}>
<div
css={css`
height: ${LENS_VISUALIZATION_HEIGHT}px;
min-width: ${LENS_VISUALIZATION_MIN_WIDTH}px;
width: auto;
display: inline-block;
background: ${euiTheme.colors.lightestShade};
border-radius: ${euiTheme.border.radius.medium};
`}
const visualizationResponse = useVisualizationResponse({
visualizationId: id,
});

// Track whether loading has started at least once
const [hasStartedLoading, setHasStartedLoading] = useState(false);

useEffect(() => {
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 (
<EuiFlexGroup
direction="column"
justifyContent="spaceBetween"
style={{ height: '100%' }} // ensures it uses the full height so 'space-between' works
>
<VisualizationEmbeddable
applyGlobalQueriesAndFilters={true}
applyPageAndTabsFilters={true}
lensAttributes={lensAttributes}
id={id}
timerange={timerange}
width="auto"
height={LENS_VISUALIZATION_HEIGHT}
disableOnClickFilter
inspectTitle={inspectTitle}
/>
</div>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiTitle size="xs">
<h4>{titleString}</h4>
</EuiTitle>
</EuiFlexItem>

<EuiFlexItem grow={false} style={{ alignSelf: 'flex-end' }}>
<EuiFlexGroup gutterSize="s" alignItems="center" responsive={false}>
<EuiFlexItem grow={false}>
<EuiIcon type="alert" color="warning" />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText size="s">
<FormattedMessage
id="xpack.securitySolution.keyInsightsTile.dataNotAvailable"
defaultMessage="Data not available"
/>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
);
}

// If we reach here, either still loading or we have a valid response, so show the embeddable
return (
<VisualizationEmbeddable
applyGlobalQueriesAndFilters={true}
applyPageAndTabsFilters={true}
lensAttributes={lensAttributes}
id={id}
timerange={timerange}
width={LENS_VISUALIZATION_MIN_WIDTH}
height={LENS_VISUALIZATION_HEIGHT}
disableOnClickFilter
inspectTitle={inspectTitle}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import React from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui';
import { EuiPanel, EuiFlexGrid } from '@elastic/eui';
import type { DataViewSpec } from '@kbn/data-views-plugin/public';

import { ActivePrivilegedUsersTile } from './active_privileged_users_tile';
Expand All @@ -21,37 +21,25 @@ export const KeyInsightsPanel: React.FC<{ spaceId: string; sourcerDataView: Data
sourcerDataView,
}) => {
return (
<EuiFlexGroup wrap gutterSize="l" responsive={false}>
<EuiFlexItem>
<EuiPanel hasBorder>
<ActivePrivilegedUsersTile spaceId={spaceId} sourcerDataView={sourcerDataView} />
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem>
<EuiPanel hasBorder>
<AlertsTriggeredTile spaceId={spaceId} />
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem>
<EuiPanel hasBorder>
<AnomaliesDetectedTile spaceId={spaceId} />
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem>
<EuiPanel hasBorder>
<GrantedRightsTile spaceId={spaceId} sourcerDataView={sourcerDataView} />
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem>
<EuiPanel hasBorder>
<AccountSwitchesTile spaceId={spaceId} sourcerDataView={sourcerDataView} />
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem>
<EuiPanel hasBorder>
<AuthenticationsTile spaceId={spaceId} sourcerDataView={sourcerDataView} />
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGrid columns={3} data-test-subj="key-insights-panel">
<EuiPanel hasBorder>
<ActivePrivilegedUsersTile spaceId={spaceId} sourcerDataView={sourcerDataView} />
</EuiPanel>
<EuiPanel hasBorder>
<AlertsTriggeredTile spaceId={spaceId} />
</EuiPanel>
<EuiPanel hasBorder>
<AnomaliesDetectedTile spaceId={spaceId} />
</EuiPanel>
<EuiPanel hasBorder>
<GrantedRightsTile spaceId={spaceId} sourcerDataView={sourcerDataView} />
</EuiPanel>
<EuiPanel hasBorder>
<AccountSwitchesTile spaceId={spaceId} sourcerDataView={sourcerDataView} />
</EuiPanel>
<EuiPanel hasBorder>
<AuthenticationsTile spaceId={spaceId} sourcerDataView={sourcerDataView} />
</EuiPanel>
</EuiFlexGrid>
);
};