mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Cloud Security] add compliance dashboard ui tab persistence (#173853)
## Summary
Summarize your PR. If it involves visual changes include a screenshot or
gif.
Add UI tab persistence to the Compliance Dashboard. The selected posture
type tab is persisted in local storage. Here are some of the test cases
for Compliance Dashboard Tab Persistence.
- Test case: Changing url in the same tab will persist tab
- Test case: Logging in and out of Kibana and going a back to Kibana
will persist tab
- Test Case: Navigating to Cloud Security Dashboard within Kibana will
persist tab
- Test Case: Dashboard recovery mode witching from the onboarding state
to generating a Dashboard with findings still works and tab will
persist.
- Test Case: Refreshing url tab continues to persist.
- Test Case: If no tab is selected, then CSPM dashboard will show.
- Test Case: Redirect subscribes to the persisted selected tab in the
url.
1ce156f6
-6d0c-4436-be78-d76aba19e8f5
This commit is contained in:
parent
442bd13b52
commit
06d4b3e246
5 changed files with 161 additions and 144 deletions
|
@ -7,7 +7,6 @@
|
|||
|
||||
import { Journey } from '@kbn/journeys';
|
||||
import expect from '@kbn/expect';
|
||||
import { subj } from '@kbn/test-subj-selector';
|
||||
|
||||
export const journey = new Journey({
|
||||
beforeSteps: async ({ kibanaServer, retry }) => {
|
||||
|
@ -48,6 +47,7 @@ export const journey = new Journey({
|
|||
// maxDuration: '10m',
|
||||
// },
|
||||
}).step('Go to cloud security dashboards Page', async ({ page, kbnUrl }) => {
|
||||
await page.goto(kbnUrl.get(`/app/security/cloud_security_posture/dashboard`));
|
||||
await page.waitForSelector(subj('csp:dashboard-sections-table-header-score'));
|
||||
// Skip the journey test until we are able to fix the dashboard csp:dashboard-sections-table-header-score timeout issue
|
||||
// await page.goto(kbnUrl.get(`/app/security/cloud_security_posture/dashboard`));
|
||||
// await page.waitForSelector(subj('csp:dashboard-sections-table-header-score'));
|
||||
});
|
||||
|
|
|
@ -37,12 +37,25 @@ const NAV_ITEMS_NAMES = {
|
|||
/** The base path for all cloud security posture pages. */
|
||||
export const CLOUD_SECURITY_POSTURE_BASE_PATH = '/cloud_security_posture';
|
||||
|
||||
const CSPM_DASHBOARD_TAB_NAME = 'Cloud';
|
||||
const KSPM_DASHBOARD_TAB_NAME = 'Kubernetes';
|
||||
|
||||
export const cloudPosturePages: Record<CspPage, CspPageNavigationItem> = {
|
||||
dashboard: {
|
||||
name: NAV_ITEMS_NAMES.DASHBOARD,
|
||||
path: `${CLOUD_SECURITY_POSTURE_BASE_PATH}/dashboard`,
|
||||
id: 'cloud_security_posture-dashboard',
|
||||
},
|
||||
cspm_dashboard: {
|
||||
name: CSPM_DASHBOARD_TAB_NAME,
|
||||
path: `${CLOUD_SECURITY_POSTURE_BASE_PATH}/dashboard/${CSPM_POLICY_TEMPLATE}`,
|
||||
id: 'cloud_security_posture-cspm-dashboard',
|
||||
},
|
||||
kspm_dashboard: {
|
||||
name: KSPM_DASHBOARD_TAB_NAME,
|
||||
path: `${CLOUD_SECURITY_POSTURE_BASE_PATH}/dashboard/${KSPM_POLICY_TEMPLATE}`,
|
||||
id: 'cloud_security_posture-kspm-dashboard',
|
||||
},
|
||||
vulnerability_dashboard: {
|
||||
name: NAV_ITEMS_NAMES.VULNERABILITY_DASHBOARD,
|
||||
path: `${CLOUD_SECURITY_POSTURE_BASE_PATH}/vulnerability_dashboard`,
|
||||
|
|
|
@ -14,7 +14,13 @@ export interface CspPageNavigationItem extends CspNavigationItem {
|
|||
id: CloudSecurityPosturePageId;
|
||||
}
|
||||
|
||||
export type CspPage = 'dashboard' | 'vulnerability_dashboard' | 'findings' | 'benchmarks';
|
||||
export type CspPage =
|
||||
| 'dashboard'
|
||||
| 'cspm_dashboard'
|
||||
| 'kspm_dashboard'
|
||||
| 'vulnerability_dashboard'
|
||||
| 'findings'
|
||||
| 'benchmarks';
|
||||
export type CspBenchmarksPage = 'rules';
|
||||
|
||||
/**
|
||||
|
@ -23,6 +29,8 @@ export type CspBenchmarksPage = 'rules';
|
|||
*/
|
||||
export type CloudSecurityPosturePageId =
|
||||
| 'cloud_security_posture-dashboard'
|
||||
| 'cloud_security_posture-cspm-dashboard'
|
||||
| 'cloud_security_posture-kspm-dashboard'
|
||||
| 'cloud_security_posture-vulnerability_dashboard'
|
||||
| 'cloud_security_posture-findings'
|
||||
| 'cloud_security_posture-benchmarks'
|
||||
|
|
|
@ -37,6 +37,8 @@ import {
|
|||
ComplianceDashboardDataV2,
|
||||
CspStatusCode,
|
||||
} from '../../../common/types_old';
|
||||
import { cloudPosturePages } from '../../common/navigation/constants';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
jest.mock('../../common/api/use_setup_status_api');
|
||||
jest.mock('../../common/api/use_stats_api');
|
||||
|
@ -48,6 +50,7 @@ jest.mock('../../common/navigation/use_csp_integration_link');
|
|||
describe('<ComplianceDashboard />', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
|
||||
(useCspSetupStatusApi as jest.Mock).mockImplementation(() =>
|
||||
createReactQueryResponse({
|
||||
status: 'success',
|
||||
|
@ -80,7 +83,7 @@ describe('<ComplianceDashboard />', () => {
|
|||
);
|
||||
});
|
||||
|
||||
const ComplianceDashboardWithTestProviders = () => {
|
||||
const ComplianceDashboardWithTestProviders = (route: string) => {
|
||||
const mockCore = coreMock.createStart();
|
||||
|
||||
return (
|
||||
|
@ -97,13 +100,15 @@ describe('<ComplianceDashboard />', () => {
|
|||
},
|
||||
}}
|
||||
>
|
||||
<ComplianceDashboard />
|
||||
<MemoryRouter initialEntries={[route]}>
|
||||
<ComplianceDashboard />
|
||||
</MemoryRouter>
|
||||
</TestProvider>
|
||||
);
|
||||
};
|
||||
|
||||
const renderComplianceDashboardPage = () => {
|
||||
return render(<ComplianceDashboardWithTestProviders />);
|
||||
const renderComplianceDashboardPage = (route = cloudPosturePages.dashboard.path) => {
|
||||
return render(ComplianceDashboardWithTestProviders(route));
|
||||
};
|
||||
|
||||
it('shows package not installed page instead of tabs', () => {
|
||||
|
@ -412,7 +417,7 @@ describe('<ComplianceDashboard />', () => {
|
|||
data: undefined,
|
||||
}));
|
||||
|
||||
renderComplianceDashboardPage();
|
||||
renderComplianceDashboardPage(cloudPosturePages.kspm_dashboard.path);
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [KUBERNETES_DASHBOARD_TAB, KUBERNETES_DASHBOARD_CONTAINER],
|
||||
|
@ -451,7 +456,7 @@ describe('<ComplianceDashboard />', () => {
|
|||
data: mockDashboardData,
|
||||
}));
|
||||
|
||||
renderComplianceDashboardPage();
|
||||
renderComplianceDashboardPage(cloudPosturePages.cspm_dashboard.path);
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [CLOUD_DASHBOARD_TAB, CLOUD_DASHBOARD_CONTAINER],
|
||||
|
@ -530,7 +535,7 @@ describe('<ComplianceDashboard />', () => {
|
|||
data: { stats: { totalFindings: 0 } },
|
||||
}));
|
||||
|
||||
renderComplianceDashboardPage();
|
||||
renderComplianceDashboardPage(cloudPosturePages.kspm_dashboard.path);
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [KUBERNETES_DASHBOARD_CONTAINER, NO_FINDINGS_STATUS_TEST_SUBJ.NO_FINDINGS],
|
||||
|
@ -610,7 +615,7 @@ describe('<ComplianceDashboard />', () => {
|
|||
data: mockDashboardData,
|
||||
}));
|
||||
|
||||
renderComplianceDashboardPage();
|
||||
renderComplianceDashboardPage(cloudPosturePages.cspm_dashboard.path);
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [CLOUD_DASHBOARD_CONTAINER],
|
||||
|
@ -650,12 +655,10 @@ describe('<ComplianceDashboard />', () => {
|
|||
data: { stats: { totalFindings: 0 } },
|
||||
}));
|
||||
|
||||
const { rerender } = renderComplianceDashboardPage();
|
||||
renderComplianceDashboardPage(cloudPosturePages.kspm_dashboard.path);
|
||||
|
||||
screen.getByTestId(CLOUD_DASHBOARD_TAB).click();
|
||||
|
||||
rerender(<ComplianceDashboardWithTestProviders />);
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [CSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT],
|
||||
notToBe: [
|
||||
|
@ -709,61 +712,6 @@ describe('<ComplianceDashboard />', () => {
|
|||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should not select default tab is user has already selected one themselves', () => {
|
||||
(useCspSetupStatusApi as jest.Mock).mockImplementation(() =>
|
||||
createReactQueryResponse({
|
||||
status: 'success',
|
||||
data: {
|
||||
kspm: { status: 'not-installed' },
|
||||
cspm: { status: 'indexed' },
|
||||
installedPackageVersion: '1.2.13',
|
||||
indicesDetails: [
|
||||
{ index: 'logs-cloud_security_posture.findings_latest-default', status: 'not-empty' },
|
||||
{ index: 'logs-cloud_security_posture.findings-default*', status: 'empty' },
|
||||
],
|
||||
},
|
||||
})
|
||||
);
|
||||
(useKspmStatsApi as jest.Mock).mockImplementation(() => ({
|
||||
isSuccess: true,
|
||||
isLoading: false,
|
||||
data: { stats: { totalFindings: 0 } },
|
||||
}));
|
||||
(useCspmStatsApi as jest.Mock).mockImplementation(() => ({
|
||||
isSuccess: true,
|
||||
isLoading: false,
|
||||
data: mockDashboardData,
|
||||
}));
|
||||
|
||||
const { rerender } = renderComplianceDashboardPage();
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [CLOUD_DASHBOARD_CONTAINER],
|
||||
notToBe: [
|
||||
KUBERNETES_DASHBOARD_CONTAINER,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED,
|
||||
],
|
||||
});
|
||||
|
||||
screen.getByTestId(KUBERNETES_DASHBOARD_TAB).click();
|
||||
|
||||
rerender(<ComplianceDashboardWithTestProviders />);
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [KSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT],
|
||||
notToBe: [
|
||||
CLOUD_DASHBOARD_CONTAINER,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED,
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDefaultTab', () => {
|
||||
|
@ -836,21 +784,21 @@ describe('getDefaultTab', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('returns CSPM tab is plugin status and kspm status is not provided', () => {
|
||||
it('should returns undefined when plugin status and cspm stats is not provided', () => {
|
||||
const cspmStats = getStatsMock(1) as ComplianceDashboardDataV2;
|
||||
|
||||
expect(getDefaultTab(undefined, cspmStats, undefined)).toEqual('cspm');
|
||||
expect(getDefaultTab(undefined, cspmStats, undefined)).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('returns KSPM tab is plugin status and csp status is not provided', () => {
|
||||
it('should return undefined is plugin status and csp status is not provided ', () => {
|
||||
const kspmStats = getStatsMock(1) as ComplianceDashboardDataV2;
|
||||
|
||||
expect(getDefaultTab(undefined, undefined, kspmStats)).toEqual('kspm');
|
||||
expect(getDefaultTab(undefined, undefined, kspmStats)).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('returns CSPM tab when only plugins status data is provided', () => {
|
||||
it('should return undefined when plugins status or cspm stats data is not provided', () => {
|
||||
const pluginStatus = getPluginStatusMock('indexed', 'indexed') as BaseCspSetupStatus;
|
||||
|
||||
expect(getDefaultTab(pluginStatus, undefined, undefined)).toEqual('cspm');
|
||||
expect(getDefaultTab(pluginStatus, undefined, undefined)).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,12 +5,14 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { UseQueryResult } from '@tanstack/react-query';
|
||||
import { EuiEmptyPrompt, EuiIcon, EuiLink, EuiPageHeader, EuiSpacer } from '@elastic/eui';
|
||||
import { css } from '@emotion/react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { Route, Routes } from '@kbn/shared-ux-router';
|
||||
import { Redirect, useHistory, useLocation } from 'react-router-dom';
|
||||
import { NO_FINDINGS_STATUS_TEST_SUBJ } from '../../components/test_subjects';
|
||||
import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link';
|
||||
import type {
|
||||
|
@ -40,8 +42,10 @@ import { NoFindingsStates } from '../../components/no_findings_states';
|
|||
import { SummarySection } from './dashboard_sections/summary_section';
|
||||
import { BenchmarksSection } from './dashboard_sections/benchmarks_section';
|
||||
import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../../common/constants';
|
||||
import { cspIntegrationDocsNavigation } from '../../common/navigation/constants';
|
||||
import { cloudPosturePages, cspIntegrationDocsNavigation } from '../../common/navigation/constants';
|
||||
import { NO_FINDINGS_STATUS_REFRESH_INTERVAL_MS } from '../../common/constants';
|
||||
import { encodeQuery } from '../../common/navigation/query_utils';
|
||||
import { useKibana } from '../../common/hooks/use_kibana';
|
||||
|
||||
const POSTURE_TYPE_CSPM = CSPM_POLICY_TEMPLATE;
|
||||
const POSTURE_TYPE_KSPM = KSPM_POLICY_TEMPLATE;
|
||||
|
@ -195,8 +199,11 @@ export const getDefaultTab = (
|
|||
const kspmTotalFindings = kspmStats?.stats.totalFindings;
|
||||
const installedPolicyTemplatesCspm = pluginStatus?.cspm?.status;
|
||||
const installedPolicyTemplatesKspm = pluginStatus?.kspm?.status;
|
||||
let preferredDashboard = POSTURE_TYPE_CSPM;
|
||||
let preferredDashboard: PosturePolicyTemplate = POSTURE_TYPE_CSPM;
|
||||
|
||||
if (!cspmStats || !pluginStatus) {
|
||||
return;
|
||||
}
|
||||
// cspm has findings
|
||||
if (!!cspmTotalFindings) {
|
||||
preferredDashboard = POSTURE_TYPE_CSPM;
|
||||
|
@ -231,10 +238,14 @@ const determineDashboardDataRefetchInterval = (data: ComplianceDashboardDataV2 |
|
|||
return false;
|
||||
};
|
||||
|
||||
const TabContent = ({ posturetype }: { posturetype: PosturePolicyTemplate }) => {
|
||||
const TabContent = ({
|
||||
selectedPostureTypeTab,
|
||||
}: {
|
||||
selectedPostureTypeTab: PosturePolicyTemplate;
|
||||
}) => {
|
||||
const { data: getSetupStatus } = useCspSetupStatusApi({
|
||||
refetchInterval: (data) => {
|
||||
if (data?.[posturetype]?.status === 'indexed') {
|
||||
if (data?.[selectedPostureTypeTab]?.status === 'indexed') {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -243,14 +254,14 @@ const TabContent = ({ posturetype }: { posturetype: PosturePolicyTemplate }) =>
|
|||
});
|
||||
const isCloudSecurityPostureInstalled = !!getSetupStatus?.installedPackageVersion;
|
||||
const getCspmDashboardData = useCspmStatsApi({
|
||||
enabled: isCloudSecurityPostureInstalled && posturetype === POSTURE_TYPE_CSPM,
|
||||
enabled: isCloudSecurityPostureInstalled && selectedPostureTypeTab === POSTURE_TYPE_CSPM,
|
||||
refetchInterval: determineDashboardDataRefetchInterval,
|
||||
});
|
||||
const getKspmDashboardData = useKspmStatsApi({
|
||||
enabled: isCloudSecurityPostureInstalled && posturetype === POSTURE_TYPE_KSPM,
|
||||
enabled: isCloudSecurityPostureInstalled && selectedPostureTypeTab === POSTURE_TYPE_KSPM,
|
||||
refetchInterval: determineDashboardDataRefetchInterval,
|
||||
});
|
||||
const setupStatus = getSetupStatus?.[posturetype]?.status;
|
||||
const setupStatus = getSetupStatus?.[selectedPostureTypeTab]?.status;
|
||||
const isStatusManagedInDashboard = setupStatus === 'indexed' || setupStatus === 'not-installed';
|
||||
const shouldRenderNoFindings = !isCloudSecurityPostureInstalled || !isStatusManagedInDashboard;
|
||||
const cspmIntegrationLink = useCspIntegrationLink(CSPM_POLICY_TEMPLATE);
|
||||
|
@ -260,7 +271,7 @@ const TabContent = ({ posturetype }: { posturetype: PosturePolicyTemplate }) =>
|
|||
let policyTemplate: PosturePolicyTemplate;
|
||||
let getDashboardData: UseQueryResult<ComplianceDashboardDataV2>;
|
||||
|
||||
switch (posturetype) {
|
||||
switch (selectedPostureTypeTab) {
|
||||
case POSTURE_TYPE_CSPM:
|
||||
integrationLink = cspmIntegrationLink;
|
||||
dataTestSubj = CLOUD_DASHBOARD_CONTAINER;
|
||||
|
@ -276,26 +287,37 @@ const TabContent = ({ posturetype }: { posturetype: PosturePolicyTemplate }) =>
|
|||
}
|
||||
|
||||
if (shouldRenderNoFindings) {
|
||||
return <NoFindingsStates postureType={posturetype} />;
|
||||
return <NoFindingsStates postureType={selectedPostureTypeTab} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<CloudPosturePage query={getDashboardData}>
|
||||
<div data-test-subj={dataTestSubj}>
|
||||
<IntegrationPostureDashboard
|
||||
dashboardType={policyTemplate}
|
||||
complianceData={getDashboardData.data}
|
||||
notInstalledConfig={getNotInstalledConfig(policyTemplate, integrationLink)}
|
||||
isIntegrationInstalled={setupStatus !== 'not-installed'}
|
||||
/>
|
||||
<Routes>
|
||||
<Route path={cloudPosturePages.cspm_dashboard.path}>
|
||||
<IntegrationPostureDashboard
|
||||
dashboardType={policyTemplate}
|
||||
complianceData={getDashboardData.data}
|
||||
notInstalledConfig={getNotInstalledConfig(policyTemplate, integrationLink)}
|
||||
isIntegrationInstalled={setupStatus !== 'not-installed'}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path={cloudPosturePages.kspm_dashboard.path}>
|
||||
<IntegrationPostureDashboard
|
||||
dashboardType={policyTemplate}
|
||||
complianceData={getDashboardData.data}
|
||||
notInstalledConfig={getNotInstalledConfig(policyTemplate, integrationLink)}
|
||||
isIntegrationInstalled={setupStatus !== 'not-installed'}
|
||||
/>
|
||||
</Route>
|
||||
</Routes>
|
||||
</div>
|
||||
</CloudPosturePage>
|
||||
);
|
||||
};
|
||||
|
||||
export const ComplianceDashboard = () => {
|
||||
const [selectedTab, setSelectedTab] = useState(POSTURE_TYPE_CSPM);
|
||||
const [hasUserSelectedTab, setHasUserSelectedTab] = useState(false);
|
||||
const { data: getSetupStatus } = useCspSetupStatusApi();
|
||||
const isCloudSecurityPostureInstalled = !!getSetupStatus?.installedPackageVersion;
|
||||
const getCspmDashboardData = useCspmStatsApi({
|
||||
|
@ -305,61 +327,76 @@ export const ComplianceDashboard = () => {
|
|||
enabled: isCloudSecurityPostureInstalled,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (hasUserSelectedTab) {
|
||||
return;
|
||||
const location = useLocation();
|
||||
const history = useHistory();
|
||||
const { services } = useKibana();
|
||||
|
||||
const currentTabUrlState: PosturePolicyTemplate | undefined = useMemo(() => {
|
||||
let tab: PosturePolicyTemplate | undefined;
|
||||
if (location.pathname === cloudPosturePages.kspm_dashboard.path) {
|
||||
tab = POSTURE_TYPE_KSPM;
|
||||
}
|
||||
|
||||
const preferredDashboard = getDefaultTab(
|
||||
getSetupStatus,
|
||||
getCspmDashboardData.data,
|
||||
getKspmDashboardData.data
|
||||
);
|
||||
setSelectedTab(preferredDashboard);
|
||||
}, [
|
||||
getCspmDashboardData.data,
|
||||
getCspmDashboardData.data?.stats.totalFindings,
|
||||
getKspmDashboardData.data,
|
||||
getKspmDashboardData.data?.stats.totalFindings,
|
||||
getSetupStatus,
|
||||
getSetupStatus?.cspm?.status,
|
||||
getSetupStatus?.kspm?.status,
|
||||
hasUserSelectedTab,
|
||||
]);
|
||||
if (location.pathname === cloudPosturePages.cspm_dashboard.path) {
|
||||
tab = POSTURE_TYPE_CSPM;
|
||||
}
|
||||
|
||||
const tabs = useMemo(
|
||||
() =>
|
||||
isCloudSecurityPostureInstalled
|
||||
? [
|
||||
{
|
||||
label: i18n.translate('xpack.csp.dashboardTabs.cloudTab.tabTitle', {
|
||||
defaultMessage: 'Cloud',
|
||||
}),
|
||||
'data-test-subj': CLOUD_DASHBOARD_TAB,
|
||||
isSelected: selectedTab === POSTURE_TYPE_CSPM,
|
||||
onClick: () => {
|
||||
setSelectedTab(POSTURE_TYPE_CSPM);
|
||||
setHasUserSelectedTab(true);
|
||||
},
|
||||
content: <TabContent posturetype={POSTURE_TYPE_CSPM} />,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.csp.dashboardTabs.kubernetesTab.tabTitle', {
|
||||
defaultMessage: 'Kubernetes',
|
||||
}),
|
||||
'data-test-subj': KUBERNETES_DASHBOARD_TAB,
|
||||
isSelected: selectedTab === POSTURE_TYPE_KSPM,
|
||||
onClick: () => {
|
||||
setSelectedTab(POSTURE_TYPE_KSPM);
|
||||
setHasUserSelectedTab(true);
|
||||
},
|
||||
content: <TabContent posturetype={POSTURE_TYPE_KSPM} />,
|
||||
},
|
||||
]
|
||||
: [],
|
||||
[selectedTab, isCloudSecurityPostureInstalled]
|
||||
// if the location is /dashboard or cloudPosturePages.dashboard.path, then return undefined
|
||||
return tab;
|
||||
}, [location.pathname]);
|
||||
|
||||
const preferredTabUrlState = useMemo(
|
||||
() => getDefaultTab(getSetupStatus, getCspmDashboardData.data, getKspmDashboardData.data),
|
||||
[getCspmDashboardData.data, getKspmDashboardData.data, getSetupStatus]
|
||||
);
|
||||
|
||||
const tabs = useMemo(() => {
|
||||
const navigateToPostureTypeDashboardTab = (pathname: string) => {
|
||||
history.push({
|
||||
pathname,
|
||||
search: encodeQuery({
|
||||
// Set query language from user's preference
|
||||
query: services.data.query.queryString.getDefaultQuery(),
|
||||
filters: services.data.query.filterManager.getFilters(),
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
const selectedTab = currentTabUrlState ?? preferredTabUrlState;
|
||||
return isCloudSecurityPostureInstalled
|
||||
? [
|
||||
{
|
||||
label: i18n.translate('xpack.csp.dashboardTabs.cloudTab.tabTitle', {
|
||||
defaultMessage: 'Cloud',
|
||||
}),
|
||||
'data-test-subj': CLOUD_DASHBOARD_TAB,
|
||||
isSelected: selectedTab === POSTURE_TYPE_CSPM,
|
||||
onClick: () => {
|
||||
navigateToPostureTypeDashboardTab(cloudPosturePages.cspm_dashboard.path);
|
||||
},
|
||||
content: <TabContent selectedPostureTypeTab={selectedTab || POSTURE_TYPE_CSPM} />,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.csp.dashboardTabs.kubernetesTab.tabTitle', {
|
||||
defaultMessage: 'Kubernetes',
|
||||
}),
|
||||
'data-test-subj': KUBERNETES_DASHBOARD_TAB,
|
||||
isSelected: selectedTab === POSTURE_TYPE_KSPM,
|
||||
onClick: () => {
|
||||
navigateToPostureTypeDashboardTab(cloudPosturePages.kspm_dashboard.path);
|
||||
},
|
||||
content: <TabContent selectedPostureTypeTab={selectedTab || POSTURE_TYPE_KSPM} />,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
}, [
|
||||
isCloudSecurityPostureInstalled,
|
||||
preferredTabUrlState,
|
||||
currentTabUrlState,
|
||||
history,
|
||||
services,
|
||||
]);
|
||||
|
||||
return (
|
||||
<CloudPosturePage>
|
||||
<EuiPageHeader
|
||||
|
@ -383,7 +420,18 @@ export const ComplianceDashboard = () => {
|
|||
height: 100%;
|
||||
`}
|
||||
>
|
||||
{!currentTabUrlState && preferredTabUrlState && (
|
||||
<Redirect
|
||||
to={
|
||||
preferredTabUrlState === POSTURE_TYPE_CSPM
|
||||
? cloudPosturePages.cspm_dashboard.path
|
||||
: cloudPosturePages.kspm_dashboard.path
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
{tabs.find((t) => t.isSelected)?.content}
|
||||
|
||||
{!isCloudSecurityPostureInstalled && <NoFindingsStates postureType={POSTURE_TYPE_CSPM} />}
|
||||
</div>
|
||||
</CloudPosturePage>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue