From 92e708ff1c8e0529b5f752326199d4ec32763e47 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 23 Aug 2023 06:00:50 -0400 Subject: [PATCH] [8.10] [Fleet] Only show agent dashboard links if there is more than one non-server agent and if the dashboards exist (#164469) (#164539) # Backport This will backport the following commits from `main` to `8.10`: - [[Fleet] Only show agent dashboard links if there is more than one non-server agent and if the dashboards exist (#164469)](https://github.com/elastic/kibana/pull/164469) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) Co-authored-by: Mark Hopkin --- .../fleet/.storybook/context/index.tsx | 3 ++ x-pack/plugins/fleet/kibana.jsonc | 3 +- .../components/dashboards_buttons.tsx | 36 +++++++++++++++++-- .../components/search_and_filter_bar.tsx | 8 ++++- .../public/mock/fleet_start_services.tsx | 1 + x-pack/plugins/fleet/public/plugin.ts | 4 +++ x-pack/plugins/fleet/tsconfig.json | 1 + 7 files changed, 52 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/fleet/.storybook/context/index.tsx b/x-pack/plugins/fleet/.storybook/context/index.tsx index cd89848008f98..43d3eea74df33 100644 --- a/x-pack/plugins/fleet/.storybook/context/index.tsx +++ b/x-pack/plugins/fleet/.storybook/context/index.tsx @@ -16,6 +16,8 @@ import { I18nProvider } from '@kbn/i18n-react'; import { CoreScopedHistory } from '@kbn/core/public'; import { getStorybookContextProvider } from '@kbn/custom-integrations-plugin/storybook'; +import type { DashboardStart } from '@kbn/dashboard-plugin/public'; + import { IntegrationsAppContext } from '../../public/applications/integrations/app'; import type { FleetConfigType, FleetStartServices } from '../../public/plugin'; import { ExperimentalFeaturesService } from '../../public/services'; @@ -76,6 +78,7 @@ export const StorybookContext: React.FC<{ storyContext?: Parameters languageClientsUiComponents: {}, }, customBranding: getCustomBranding(), + dashboard: {} as unknown as DashboardStart, docLinks: getDocLinks(), http: getHttp(), i18n: { diff --git a/x-pack/plugins/fleet/kibana.jsonc b/x-pack/plugins/fleet/kibana.jsonc index f0b01080db22d..b9f892ba4809d 100644 --- a/x-pack/plugins/fleet/kibana.jsonc +++ b/x-pack/plugins/fleet/kibana.jsonc @@ -23,7 +23,8 @@ "taskManager", "guidedOnboarding", "files", - "uiActions" + "uiActions", + "dashboard" ], "optionalPlugins": [ "features", diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/dashboards_buttons.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/dashboards_buttons.tsx index e42dfd997d241..25c394e2606b0 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/dashboards_buttons.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/dashboards_buttons.tsx @@ -5,13 +5,37 @@ * 2.0. */ -import React from 'react'; +import React, { useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { DASHBOARD_LOCATORS_IDS } from '../../../../../../../common/constants'; -import { useDashboardLocator } from '../../../../hooks'; +import { useDashboardLocator, useStartServices } from '../../../../hooks'; + +const useDashboardExists = (dashboardId: string) => { + const [dashboardExists, setDashboardExists] = React.useState(false); + const [loading, setLoading] = React.useState(true); + const { dashboard: dashboardPlugin } = useStartServices(); + + useEffect(() => { + const fetchDashboard = async () => { + try { + const findDashboardsService = await dashboardPlugin.findDashboardsService(); + const [dashboard] = await findDashboardsService.findByIds([dashboardId]); + setLoading(false); + setDashboardExists(dashboard?.status === 'success'); + } catch (e) { + setLoading(false); + setDashboardExists(false); + } + }; + + fetchDashboard(); + }, [dashboardId, dashboardPlugin]); + + return { dashboardExists, loading }; +}; export const DashboardsButtons: React.FunctionComponent = () => { const dashboardLocator = useDashboardLocator(); @@ -20,6 +44,14 @@ export const DashboardsButtons: React.FunctionComponent = () => { return dashboardLocator?.getRedirectUrl({ dashboardId }) || ''; }; + const { dashboardExists, loading: dashboardLoading } = useDashboardExists( + DASHBOARD_LOCATORS_IDS.ELASTIC_AGENT_OVERVIEW + ); + + if (dashboardLoading || !dashboardExists) { + return null; + } + return ( <> diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx index 437f982bed706..27b62d54bd789 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx @@ -22,6 +22,8 @@ import { import { FormattedMessage } from '@kbn/i18n-react'; import styled from 'styled-components'; +import { useIsFirstTimeAgentUserQuery } from '../../../../../integrations/sections/epm/screens/detail/hooks'; + import type { Agent, AgentPolicy } from '../../../../types'; import { SearchBar } from '../../../../components'; import { AGENTS_INDEX, AGENTS_PREFIX } from '../../../../constants'; @@ -94,6 +96,8 @@ export const SearchAndFilterBar: React.FunctionComponent { const { euiTheme } = useEuiTheme(); const { isFleetServerStandalone } = useFleetServerStandalone(); + const { isFirstTimeAgentUser, isLoading: isFirstTimeAgentUserLoading } = + useIsFirstTimeAgentUserQuery(); const showAddFleetServerBtn = !isFleetServerStandalone; // Policies state for filtering @@ -126,7 +130,9 @@ export const SearchAndFilterBar: React.FunctionComponent {/* Top Buttons and Links */} - {totalAgents > 0 && } + + {!isFirstTimeAgentUserLoading && !isFirstTimeAgentUser && } + , authz: fleetAuthzMock, guidedOnboarding: guidedOnboardingMock.createStart(), diff --git a/x-pack/plugins/fleet/public/plugin.ts b/x-pack/plugins/fleet/public/plugin.ts index bc35914238b58..ecef1c469e954 100644 --- a/x-pack/plugins/fleet/public/plugin.ts +++ b/x-pack/plugins/fleet/public/plugin.ts @@ -49,6 +49,8 @@ import type { SendRequestResponse } from '@kbn/es-ui-shared-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import type { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/public'; +import type { DashboardStart } from '@kbn/dashboard-plugin/public'; + import { PLUGIN_ID, INTEGRATIONS_PLUGIN_ID, setupRouteService, appRoutesService } from '../common'; import { calculateAuthz, calculatePackagePrivilegesFromCapabilities } from '../common/authz'; import { parseExperimentalConfigValue } from '../common/experimental_features'; @@ -115,6 +117,7 @@ export interface FleetSetupDeps { export interface FleetStartDeps { licensing: LicensingPluginStart; data: DataPublicPluginStart; + dashboard: DashboardStart; dataViews: DataViewsPublicPluginStart; unifiedSearch: UnifiedSearchPublicPluginStart; navigation: NavigationPublicPluginStart; @@ -128,6 +131,7 @@ export interface FleetStartDeps { export interface FleetStartServices extends CoreStart, Exclude { storage: Storage; share: SharePluginStart; + dashboard: DashboardStart; cloud?: CloudSetup & CloudStart; discover?: DiscoverStart; spaces?: SpacesPluginStart; diff --git a/x-pack/plugins/fleet/tsconfig.json b/x-pack/plugins/fleet/tsconfig.json index 82b22c90779b7..e0d261d7b7e72 100644 --- a/x-pack/plugins/fleet/tsconfig.json +++ b/x-pack/plugins/fleet/tsconfig.json @@ -100,5 +100,6 @@ "@kbn/core-http-router-server-mocks", "@kbn/core-application-browser", "@kbn/core-saved-objects-base-server-internal", + "@kbn/dashboard-plugin", ] }