From e81acb84b9ab76fab71d6b6edca3dc57b579930b Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Thu, 17 Jun 2021 11:04:04 +0200
Subject: [PATCH 01/20] very wip
* added new assets screen
* added routes to new assets view on the package details view
---
.../plugins/fleet/common/types/models/epm.ts | 2 +-
.../epm/screens/detail/assets/assets.tsx | 144 ++++++++++++++++++
.../epm/screens/detail/assets/index.ts | 7 +
.../sections/epm/screens/detail/index.tsx | 22 +++
.../fleet/public/constants/page_paths.ts | 6 +
5 files changed, 180 insertions(+), 1 deletion(-)
create mode 100644 x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
create mode 100644 x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/index.ts
diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts
index f19684b0445e2a..58f9903eeea3a7 100644
--- a/x-pack/plugins/fleet/common/types/models/epm.ts
+++ b/x-pack/plugins/fleet/common/types/models/epm.ts
@@ -45,7 +45,7 @@ export type InstallSource = 'registry' | 'upload';
export type EpmPackageInstallStatus = 'installed' | 'installing';
-export type DetailViewPanelName = 'overview' | 'policies' | 'settings' | 'custom';
+export type DetailViewPanelName = 'overview' | 'policies' | 'assets' | 'settings' | 'custom';
export type ServiceName = 'kibana' | 'elasticsearch';
export type AgentAssetType = typeof agentAssetTypes;
export type DocAssetType = 'doc' | 'notice';
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
new file mode 100644
index 00000000000000..6f8a5bd45c4d10
--- /dev/null
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
@@ -0,0 +1,144 @@
+/*
+ * 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 React, { useEffect, useState } from 'react';
+import { Redirect } from 'react-router-dom';
+import type { SimpleSavedObject } from 'src/core/public';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiAccordion } from '@elastic/eui';
+
+import { Loading } from '../../../../../components';
+
+import type { PackageInfo } from '../../../../../types';
+import { InstallStatus, KibanaAssetType } from '../../../../../types';
+
+import { useGetPackageInstallStatus, useLink, useStartServices } from '../../../../../hooks';
+
+import { AssetTitleMap } from '../../../../../constants';
+
+interface AssetsPanelProps {
+ packageInfo: PackageInfo;
+}
+
+const allowedAssetTypes: KibanaAssetType[] = [
+ KibanaAssetType.dashboard,
+ KibanaAssetType.search,
+ KibanaAssetType.visualization,
+];
+
+export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
+ const { name, version } = packageInfo;
+ const {
+ savedObjects: { client: savedObjectsClient },
+ http,
+ } = useStartServices();
+
+ const { getPath } = useLink();
+ const getPackageInstallStatus = useGetPackageInstallStatus();
+ const packageInstallStatus = getPackageInstallStatus(packageInfo.name);
+
+ const [assetSavedObjects, setAssetsSavedObjects] = useState();
+ const [fetchError, setFetchError] = useState();
+ const [isLoading, setIsLoading] = useState(true);
+
+ useEffect(() => {
+ const fetchAssetSavedObjects = async () => {
+ if ('savedObject' in packageInfo) {
+ const {
+ savedObject: { attributes: packageAttributes },
+ } = packageInfo;
+
+ if (
+ !packageAttributes.installed_kibana ||
+ packageAttributes.installed_kibana.length === 0
+ ) {
+ setIsLoading(false);
+ return;
+ }
+
+ try {
+ const { savedObjects } = await savedObjectsClient.bulkGet(
+ packageAttributes.installed_kibana.map(({ id, type }) => ({
+ id,
+ type,
+ }))
+ );
+ setAssetsSavedObjects(savedObjects);
+ } catch (e) {
+ setFetchError(e);
+ } finally {
+ setIsLoading(false);
+ }
+ } else {
+ setIsLoading(false);
+ }
+ };
+ fetchAssetSavedObjects();
+ }, [savedObjectsClient, packageInfo]);
+
+ // if they arrive at this page and the package is not installed, send them to overview
+ // this happens if they arrive with a direct url or they uninstall while on this tab
+ if (packageInstallStatus.status !== InstallStatus.installed) {
+ return (
+
+ );
+ }
+
+ let content: JSX.Element;
+
+ if (isLoading) {
+ content = ;
+ } else if (fetchError) {
+ content = TODO HANDLE ERROR
;
+ } else if (assetSavedObjects === undefined) {
+ content = (
+
+
+
+
+
+ );
+ } else {
+ content = (
+ <>
+ {allowedAssetTypes.map((assetType) => {
+ const sectionAssetSavedObjects = assetSavedObjects.filter((so) => so.type === assetType);
+ if (!sectionAssetSavedObjects.length) {
+ return null;
+ }
+
+ return (
+
+ {AssetTitleMap[assetType]} {sectionAssetSavedObjects.length}
+
+ }
+ id={assetType}
+ >
+ {sectionAssetSavedObjects.map(({ attributes }) => attributes.title)}
+
+ );
+ })}
+ >
+ );
+ }
+
+ return (
+
+
+ {content}
+
+ );
+};
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/index.ts b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/index.ts
new file mode 100644
index 00000000000000..ceb030b7ce02eb
--- /dev/null
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/index.ts
@@ -0,0 +1,7 @@
+/*
+ * 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.
+ */
+export { AssetsPage } from './assets';
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx
index 99a29a8194f9b0..fb47d66df5f94d 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx
@@ -56,6 +56,7 @@ import { WithHeaderLayout } from '../../../../layouts';
import { RELEASE_BADGE_DESCRIPTION, RELEASE_BADGE_LABEL } from '../../components/release_badge';
import { IntegrationAgentPolicyCount, UpdateIcon, IconPanel, LoadingIconPanel } from './components';
+import { AssetsPage } from './assets';
import { OverviewPage } from './overview';
import { PackagePoliciesPage } from './policies';
import { SettingsPage } from './settings';
@@ -408,6 +409,24 @@ export function Detail() {
});
}
+ if (packageInfo.assets) {
+ tabs.push({
+ id: 'assets',
+ name: (
+
+ ),
+ isSelected: panel === 'assets',
+ 'data-test-subj': `tab-assets`,
+ href: getHref('integration_details_assets', {
+ pkgkey: packageInfoKey,
+ ...(integration ? { integration } : {}),
+ }),
+ });
+ }
+
tabs.push({
id: 'settings',
name: (
@@ -476,6 +495,9 @@ export function Detail() {
+
+
+
diff --git a/x-pack/plugins/fleet/public/constants/page_paths.ts b/x-pack/plugins/fleet/public/constants/page_paths.ts
index 3c9c0e57596151..97f04b41d2cb9e 100644
--- a/x-pack/plugins/fleet/public/constants/page_paths.ts
+++ b/x-pack/plugins/fleet/public/constants/page_paths.ts
@@ -20,6 +20,7 @@ export type StaticPage =
export type DynamicPage =
| 'integration_details_overview'
| 'integration_details_policies'
+ | 'integration_details_assets'
| 'integration_details_settings'
| 'integration_details_custom'
| 'integration_policy_edit'
@@ -65,6 +66,7 @@ export const INTEGRATIONS_ROUTING_PATHS = {
integration_details: '/detail/:pkgkey/:panel?',
integration_details_overview: '/detail/:pkgkey/overview',
integration_details_policies: '/detail/:pkgkey/policies',
+ integration_details_assets: '/detail/:pkgkey/assets',
integration_details_settings: '/detail/:pkgkey/settings',
integration_details_custom: '/detail/:pkgkey/custom',
integration_policy_edit: '/edit-integration/:packagePolicyId',
@@ -89,6 +91,10 @@ export const pagePathGetters: {
INTEGRATIONS_BASE_PATH,
`/detail/${pkgkey}/policies${integration ? `?integration=${integration}` : ''}`,
],
+ integration_details_assets: ({ pkgkey, integration }) => [
+ INTEGRATIONS_BASE_PATH,
+ `/detail/${pkgkey}/assets${integration ? `?integration=${integration}` : ''}`,
+ ],
integration_details_settings: ({ pkgkey, integration }) => [
INTEGRATIONS_BASE_PATH,
`/detail/${pkgkey}/settings${integration ? `?integration=${integration}` : ''}`,
From 2c45e7d09578c2ca25b0f20f23b9ff5be4260991 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Thu, 17 Jun 2021 11:57:30 +0200
Subject: [PATCH 02/20] Finished styling the assets page layout, need to work
on adding links
---
.../epm/screens/detail/assets/assets.scss | 3 +
.../epm/screens/detail/assets/assets.tsx | 85 ++++++++++++++++---
2 files changed, 74 insertions(+), 14 deletions(-)
create mode 100644 x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.scss
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.scss b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.scss
new file mode 100644
index 00000000000000..a430f0d22943ba
--- /dev/null
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.scss
@@ -0,0 +1,3 @@
+.customOuterSplitPanel {
+ --childBorders: #{$euiBorderThin};
+}
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
index 6f8a5bd45c4d10..79b536e3dfce17 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
@@ -9,7 +9,17 @@ import React, { useEffect, useState } from 'react';
import { Redirect } from 'react-router-dom';
import type { SimpleSavedObject } from 'src/core/public';
import { FormattedMessage } from '@kbn/i18n/react';
-import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiAccordion } from '@elastic/eui';
+import styled from 'styled-components';
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiTitle,
+ EuiText,
+ EuiAccordion,
+ EuiSpacer,
+ EuiBadge,
+ EuiSplitPanel,
+} from '@elastic/eui';
import { Loading } from '../../../../../components';
@@ -20,28 +30,39 @@ import { useGetPackageInstallStatus, useLink, useStartServices } from '../../../
import { AssetTitleMap } from '../../../../../constants';
+import './assets.scss';
+
interface AssetsPanelProps {
packageInfo: PackageInfo;
}
+const CustomSplitPanelInner = styled(EuiSplitPanel.Inner)``;
+
+const CustomSplitPanelOuter = styled(EuiSplitPanel.Outer)`
+ ${CustomSplitPanelInner}:not(:last-child) {
+ border-bottom: var(--childBorders);
+ }
+`;
+
const allowedAssetTypes: KibanaAssetType[] = [
KibanaAssetType.dashboard,
KibanaAssetType.search,
KibanaAssetType.visualization,
];
+type AssetSavedObject = SimpleSavedObject<{ title: string; description?: string }>;
+
export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
const { name, version } = packageInfo;
const {
savedObjects: { client: savedObjectsClient },
- http,
} = useStartServices();
const { getPath } = useLink();
const getPackageInstallStatus = useGetPackageInstallStatus();
const packageInstallStatus = getPackageInstallStatus(packageInfo.name);
- const [assetSavedObjects, setAssetsSavedObjects] = useState();
+ const [assetSavedObjects, setAssetsSavedObjects] = useState();
const [fetchError, setFetchError] = useState();
const [isLoading, setIsLoading] = useState(true);
@@ -67,7 +88,7 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
type,
}))
);
- setAssetsSavedObjects(savedObjects);
+ setAssetsSavedObjects(savedObjects as AssetSavedObject[]);
} catch (e) {
setFetchError(e);
} finally {
@@ -119,16 +140,52 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
}
return (
-
- {AssetTitleMap[assetType]} {sectionAssetSavedObjects.length}
-
- }
- id={assetType}
- >
- {sectionAssetSavedObjects.map(({ attributes }) => attributes.title)}
-
+ <>
+
+
+
+ {AssetTitleMap[assetType]}
+
+
+
+ {sectionAssetSavedObjects.length}
+
+
+ }
+ id={assetType}
+ >
+ <>
+
+
+ {sectionAssetSavedObjects.map(({ attributes: { title, description } }, idx) => (
+
+
+ {title}
+
+
+ {description && (
+
+ {description}
+
+ )}
+
+ ))}
+
+ >
+
+
+ >
);
})}
>
From 815d0b62edabb3603a1d0adbe6cce4bef71a329a Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Thu, 17 Jun 2021 12:10:36 +0200
Subject: [PATCH 03/20] rather use EuiHorizontalRule
---
.../epm/screens/detail/assets/assets.scss | 3 --
.../epm/screens/detail/assets/assets.tsx | 37 +++++++++----------
2 files changed, 17 insertions(+), 23 deletions(-)
delete mode 100644 x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.scss
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.scss b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.scss
deleted file mode 100644
index a430f0d22943ba..00000000000000
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.customOuterSplitPanel {
- --childBorders: #{$euiBorderThin};
-}
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
index 79b536e3dfce17..9626be3cab71b3 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
@@ -9,7 +9,6 @@ import React, { useEffect, useState } from 'react';
import { Redirect } from 'react-router-dom';
import type { SimpleSavedObject } from 'src/core/public';
import { FormattedMessage } from '@kbn/i18n/react';
-import styled from 'styled-components';
import {
EuiFlexGroup,
EuiFlexItem,
@@ -19,6 +18,7 @@ import {
EuiSpacer,
EuiBadge,
EuiSplitPanel,
+ EuiHorizontalRule,
} from '@elastic/eui';
import { Loading } from '../../../../../components';
@@ -36,14 +36,6 @@ interface AssetsPanelProps {
packageInfo: PackageInfo;
}
-const CustomSplitPanelInner = styled(EuiSplitPanel.Inner)``;
-
-const CustomSplitPanelOuter = styled(EuiSplitPanel.Outer)`
- ${CustomSplitPanelInner}:not(:last-child) {
- border-bottom: var(--childBorders);
- }
-`;
-
const allowedAssetTypes: KibanaAssetType[] = [
KibanaAssetType.dashboard,
KibanaAssetType.search,
@@ -163,25 +155,30 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
>
<>
-
{sectionAssetSavedObjects.map(({ attributes: { title, description } }, idx) => (
-
-
- {title}
-
-
- {description && (
-
- {description}
+ <>
+
+
+ {title}
+
+ {description && (
+
+ {description}
+
+ )}
+
+ {idx + 1 < sectionAssetSavedObjects.length && (
+
)}
-
+ >
))}
-
+
>
From 3c9912b401526a0e285ffb82aaf6d3b237b43673 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Thu, 17 Jun 2021 12:48:58 +0200
Subject: [PATCH 04/20] only show the assets tab if installed
---
.../integrations/sections/epm/screens/detail/index.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx
index fb47d66df5f94d..6d6286932c237f 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx
@@ -409,7 +409,7 @@ export function Detail() {
});
}
- if (packageInfo.assets) {
+ if (packageInfo.assets && packageInstallStatus === InstallStatus.installed) {
tabs.push({
id: 'assets',
name: (
From 3dfd692663a0d60decfe1812a5f4f97eb5708c92 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Thu, 17 Jun 2021 13:43:20 +0200
Subject: [PATCH 05/20] Added hacky version of linking to assets.
---
.../epm/screens/detail/assets/assets.tsx | 98 ++++++++++++++-----
x-pack/plugins/fleet/public/hooks/index.ts | 2 +-
.../fleet/public/hooks/use_kibana_link.ts | 9 +-
3 files changed, 84 insertions(+), 25 deletions(-)
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
index 9626be3cab71b3..b8dad865078ab8 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
@@ -13,6 +13,7 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiTitle,
+ EuiLink,
EuiText,
EuiAccordion,
EuiSpacer,
@@ -26,17 +27,26 @@ import { Loading } from '../../../../../components';
import type { PackageInfo } from '../../../../../types';
import { InstallStatus, KibanaAssetType } from '../../../../../types';
-import { useGetPackageInstallStatus, useLink, useStartServices } from '../../../../../hooks';
+import {
+ useGetPackageInstallStatus,
+ useLink,
+ useStartServices,
+ getKibanaLink,
+} from '../../../../../hooks';
import { AssetTitleMap } from '../../../../../constants';
-import './assets.scss';
-
interface AssetsPanelProps {
packageInfo: PackageInfo;
}
-const allowedAssetTypes: KibanaAssetType[] = [
+type AllowedAssetTypes = [
+ KibanaAssetType.dashboard,
+ KibanaAssetType.search,
+ KibanaAssetType.visualization
+];
+
+const allowedAssetTypes: AllowedAssetTypes = [
KibanaAssetType.dashboard,
KibanaAssetType.search,
KibanaAssetType.visualization,
@@ -44,10 +54,38 @@ const allowedAssetTypes: KibanaAssetType[] = [
type AssetSavedObject = SimpleSavedObject<{ title: string; description?: string }>;
+/**
+ * TODO: This is a temporary solution for getting links to various assets. It is very risky because:
+ *
+ * 1. The plugin might not exist/be enabled
+ * 2. URLs and paths might not always be supported
+ *
+ * We should migrate to using the new URL service locators.
+ */
+const getPathToObjectInApp = ({
+ type,
+ id,
+}: {
+ type: KibanaAssetType;
+ id: string;
+}): undefined | string => {
+ switch (type) {
+ case KibanaAssetType.dashboard:
+ return `/dashboard/${id}`;
+ case KibanaAssetType.search:
+ return `/discover/${id}`;
+ case KibanaAssetType.visualization:
+ return `/visualize/edit/${id}`;
+ default:
+ return undefined;
+ }
+};
+
export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
const { name, version } = packageInfo;
const {
savedObjects: { client: savedObjectsClient },
+ http,
} = useStartServices();
const { getPath } = useLink();
@@ -160,24 +198,40 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
hasBorder
hasShadow={false}
>
- {sectionAssetSavedObjects.map(({ attributes: { title, description } }, idx) => (
- <>
-
-
- {title}
-
-
- {description && (
-
- {description}
-
- )}
-
- {idx + 1 < sectionAssetSavedObjects.length && (
-
- )}
- >
- ))}
+ {sectionAssetSavedObjects.map(
+ ({ id, type, attributes: { title, description } }, idx) => {
+ const pathToObjectInApp = getPathToObjectInApp({
+ id,
+ type: type as KibanaAssetType,
+ });
+ return (
+ <>
+ {}} grow={false} key={idx}>
+
+
+ {pathToObjectInApp ? (
+
+ {title}
+
+ ) : (
+ title
+ )}
+
+
+
+ {description && (
+
+ {description}
+
+ )}
+
+ {idx + 1 < sectionAssetSavedObjects.length && (
+
+ )}
+ >
+ );
+ }
+ )}
>
diff --git a/x-pack/plugins/fleet/public/hooks/index.ts b/x-pack/plugins/fleet/public/hooks/index.ts
index 9f41e5c7cc92b5..1258a47f95015e 100644
--- a/x-pack/plugins/fleet/public/hooks/index.ts
+++ b/x-pack/plugins/fleet/public/hooks/index.ts
@@ -11,7 +11,7 @@ export { useConfig, ConfigContext } from './use_config';
export { useKibanaVersion, KibanaVersionContext } from './use_kibana_version';
export { licenseService, useLicense } from './use_license';
export { useLink } from './use_link';
-export { useKibanaLink } from './use_kibana_link';
+export { useKibanaLink, getKibanaLink } from './use_kibana_link';
export { usePackageIconType, UsePackageIconType } from './use_package_icon_type';
export { usePagination, Pagination, PAGE_SIZE_OPTIONS } from './use_pagination';
export { useUrlPagination } from './use_url_pagination';
diff --git a/x-pack/plugins/fleet/public/hooks/use_kibana_link.ts b/x-pack/plugins/fleet/public/hooks/use_kibana_link.ts
index 29f4f8748d1a0e..815de79374453a 100644
--- a/x-pack/plugins/fleet/public/hooks/use_kibana_link.ts
+++ b/x-pack/plugins/fleet/public/hooks/use_kibana_link.ts
@@ -4,12 +4,17 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
+import type { HttpStart } from 'src/core/public';
import { useStartServices } from './';
const KIBANA_BASE_PATH = '/app/kibana';
+export const getKibanaLink = (http: HttpStart, path: string) => {
+ return http.basePath.prepend(`${KIBANA_BASE_PATH}#${path}`);
+};
+
export function useKibanaLink(path: string = '/') {
- const core = useStartServices();
- return core.http.basePath.prepend(`${KIBANA_BASE_PATH}#${path}`);
+ const { http } = useStartServices();
+ return getKibanaLink(http, path);
}
From 8669f7e855e2684788a847f989d3d5a0eb12de30 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Thu, 17 Jun 2021 14:32:28 +0200
Subject: [PATCH 06/20] added comment about deprecation of current linking
functionality
---
x-pack/plugins/fleet/kibana.json | 8 +-------
x-pack/plugins/fleet/public/hooks/use_kibana_link.ts | 7 +++++++
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/x-pack/plugins/fleet/kibana.json b/x-pack/plugins/fleet/kibana.json
index 4a4019e3e9e47f..2fcbef75b9832b 100644
--- a/x-pack/plugins/fleet/kibana.json
+++ b/x-pack/plugins/fleet/kibana.json
@@ -5,13 +5,7 @@
"ui": true,
"configPath": ["xpack", "fleet"],
"requiredPlugins": ["licensing", "data", "encryptedSavedObjects"],
- "optionalPlugins": [
- "security",
- "features",
- "cloud",
- "usageCollection",
- "home"
- ],
+ "optionalPlugins": ["security", "features", "cloud", "usageCollection", "home"],
"extraPublicDirs": ["common"],
"requiredBundles": ["kibanaReact", "esUiShared", "home", "infra", "kibanaUtils"]
}
diff --git a/x-pack/plugins/fleet/public/hooks/use_kibana_link.ts b/x-pack/plugins/fleet/public/hooks/use_kibana_link.ts
index 815de79374453a..e8ecc9cf5492f4 100644
--- a/x-pack/plugins/fleet/public/hooks/use_kibana_link.ts
+++ b/x-pack/plugins/fleet/public/hooks/use_kibana_link.ts
@@ -10,10 +10,17 @@ import { useStartServices } from './';
const KIBANA_BASE_PATH = '/app/kibana';
+/**
+ * @deprecated See comment on {@link useKibanaLink}
+ */
export const getKibanaLink = (http: HttpStart, path: string) => {
return http.basePath.prepend(`${KIBANA_BASE_PATH}#${path}`);
};
+/**
+ * TODO: This functionality needs to be replaced with use of the new URL service locators
+ * @deprecated
+ */
export function useKibanaLink(path: string = '/') {
const { http } = useStartServices();
return getKibanaLink(http, path);
From 646c5836a420c03c1002ab4d044830c99e815402 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Thu, 17 Jun 2021 15:35:22 +0200
Subject: [PATCH 07/20] added an initial version of the success toast with a
link to the agent flyout
---
.../create_package_policy_page/index.tsx | 66 +++++++++++++++----
.../epm/screens/detail/assets/assets.tsx | 2 +-
.../sections/epm/screens/detail/index.tsx | 2 +-
.../detail/policies/package_policies.tsx | 11 +++-
.../agent_enrollment_flyout/steps.tsx | 34 ++++++++++
.../fleet/public/constants/page_paths.ts | 10 +--
6 files changed, 103 insertions(+), 22 deletions(-)
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
index 75fc06c1a44945..0f3463a45fa0ae 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
@@ -19,10 +19,12 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiSpacer,
+ EuiLink,
} from '@elastic/eui';
import type { EuiStepProps } from '@elastic/eui/src/components/steps/step';
import type { ApplicationStart } from 'kibana/public';
+import { toMountPoint } from '../../../../../../../../../src/plugins/kibana_react/public';
import type {
AgentPolicy,
PackageInfo,
@@ -43,6 +45,7 @@ import { useIntraAppState, useUIExtension } from '../../../hooks';
import { ExtensionWrapper } from '../../../components';
import type { PackagePolicyEditExtensionComponentProps } from '../../../types';
import { PLUGIN_ID } from '../../../../../../common/constants';
+import { pagePathGetters } from '../../../../../constants';
import { pkgKeyFromPackageInfo } from '../../../services';
import { CreatePackagePolicyPageLayout } from './components';
@@ -60,7 +63,7 @@ const StepsWithLessPadding = styled(EuiSteps)`
`;
const CustomEuiBottomBar = styled(EuiBottomBar)`
- // Set a relatively _low_ z-index value here to account for EuiComboBox popover that might appear under the bottom bar
+ /* A relatively _low_ z-index value here to account for EuiComboBox popover that might appear under the bottom bar */
z-index: 50;
`;
@@ -280,6 +283,13 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
);
}
+ const fromPolicyWithoutAgentsAssigned = from === 'policy' && agentPolicy && agentCount === 0;
+
+ const fromPackageWithoutAgentsAssigned =
+ from === 'package' && packageInfo && agentPolicy && agentCount === 0;
+
+ const hasAgentsAssigned = agentCount && agentPolicy;
+
notifications.toasts.addSuccess({
title: i18n.translate('xpack.fleet.createPackagePolicy.addedNotificationTitle', {
defaultMessage: `'{packagePolicyName}' integration added.`,
@@ -287,22 +297,48 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
packagePolicyName: packagePolicy.name,
},
}),
- text:
- agentCount && agentPolicy
- ? i18n.translate('xpack.fleet.createPackagePolicy.addedNotificationMessage', {
- defaultMessage: `Fleet will deploy updates to all agents that use the '{agentPolicyName}' policy.`,
- values: {
- agentPolicyName: agentPolicy.name,
- },
- })
- : (params as AddToPolicyParams)?.policyId && agentPolicy && agentCount === 0
- ? i18n.translate('xpack.fleet.createPackagePolicy.addAgentNextNotification', {
+ text: fromPolicyWithoutAgentsAssigned
+ ? i18n.translate(
+ 'xpack.fleet.createPackagePolicy.policyContextAddAgentNextNotificationMessage',
+ {
defaultMessage: `The policy has been updated. Add an agent to the '{agentPolicyName}' policy to deploy this policy.`,
values: {
- agentPolicyName: agentPolicy.name,
+ agentPolicyName: agentPolicy!.name,
},
- })
- : undefined,
+ }
+ )
+ : fromPackageWithoutAgentsAssigned
+ ? toMountPoint(
+
+ {i18n.translate(
+ 'xpack.fleet.createPackagePolicy.integrationsContextAddAgentLinkMessage',
+ { defaultMessage: 'add an agent' }
+ )}
+
+ ),
+ }}
+ />
+ )
+ : hasAgentsAssigned
+ ? i18n.translate('xpack.fleet.createPackagePolicy.addedNotificationMessage', {
+ defaultMessage: `Fleet will deploy updates to all agents that use the '{agentPolicyName}' policy.`,
+ values: {
+ agentPolicyName: agentPolicy!.name,
+ },
+ })
+ : undefined,
'data-test-subj': 'packagePolicyCreateSuccessToast',
});
} else {
@@ -312,6 +348,8 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
setFormState('VALID');
}
}, [
+ from,
+ packageInfo,
agentCount,
agentPolicy,
formState,
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
index b8dad865078ab8..5f50ecb223ade0 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
@@ -206,7 +206,7 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
});
return (
<>
- {}} grow={false} key={idx}>
+
{pathToObjectInApp ? (
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx
index 6d6286932c237f..cf6007026afebc 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx
@@ -409,7 +409,7 @@ export function Detail() {
});
}
- if (packageInfo.assets && packageInstallStatus === InstallStatus.installed) {
+ if (packageInstallStatus === InstallStatus.installed && packageInfo.assets) {
tabs.push({
id: 'assets',
name: (
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx
index 7da7328fdebbca..cb6c896cd92691 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx
@@ -6,7 +6,7 @@
*/
import React, { memo, useCallback, useMemo, useState } from 'react';
-import { Redirect } from 'react-router-dom';
+import { Redirect, useLocation } from 'react-router-dom';
import type { CriteriaWithPagination, EuiTableFieldDataColumnType } from '@elastic/eui';
import {
EuiButtonIcon,
@@ -66,7 +66,14 @@ interface PackagePoliciesPanelProps {
version: string;
}
export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps) => {
- const [flyoutOpenForPolicyId, setFlyoutOpenForPolicyId] = useState(null);
+ const { search } = useLocation();
+ const queryParams = useMemo(() => new URLSearchParams(search), [search]);
+ const agentPolicyIdFromParams = useMemo(() => queryParams.get('addAgentToPolicyId'), [
+ queryParams,
+ ]);
+ const [flyoutOpenForPolicyId, setFlyoutOpenForPolicyId] = useState(
+ agentPolicyIdFromParams
+ );
const { getPath } = useLink();
const getPackageInstallStatus = useGetPackageInstallStatus();
const packageInstallStatus = getPackageInstallStatus(name);
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx
index ea4fa626afbb6a..a8b8d0b8a57805 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx
@@ -138,3 +138,37 @@ export const AgentEnrollmentKeySelectionStep = ({
),
};
};
+
+/**
+ * Send users to assets installed by the package in Kibana so they can
+ * view their data.
+ */
+export const ViewDataStep = () => {
+ return {
+ title: i18n.translate('xpack.fleet.agentEnrollment.stepViewDataTitle', {
+ defaultMessage: 'View your data',
+ }),
+ children: (
+ <>
+
+
+ {i18n.translate(
+ 'xpack.fleet.agentEnrollment.viewDataDescription.pleaseNoteLabel',
+ { defaultMessage: 'Please note' }
+ )}
+
+ ),
+ }}
+ />
+
+
+
+ >
+ ),
+ };
+};
diff --git a/x-pack/plugins/fleet/public/constants/page_paths.ts b/x-pack/plugins/fleet/public/constants/page_paths.ts
index 97f04b41d2cb9e..78dd176aa05dea 100644
--- a/x-pack/plugins/fleet/public/constants/page_paths.ts
+++ b/x-pack/plugins/fleet/public/constants/page_paths.ts
@@ -5,6 +5,8 @@
* 2.0.
*/
+import { stringify } from 'query-string';
+
export type StaticPage =
| 'base'
| 'overview'
@@ -87,10 +89,10 @@ export const pagePathGetters: {
INTEGRATIONS_BASE_PATH,
`/detail/${pkgkey}/overview${integration ? `?integration=${integration}` : ''}`,
],
- integration_details_policies: ({ pkgkey, integration }) => [
- INTEGRATIONS_BASE_PATH,
- `/detail/${pkgkey}/policies${integration ? `?integration=${integration}` : ''}`,
- ],
+ integration_details_policies: ({ pkgkey, integration, addAgentToPolicyId }) => {
+ const qs = stringify({ integration, addAgentToPolicyId });
+ return [INTEGRATIONS_BASE_PATH, `/detail/${pkgkey}/policies${qs ? `?${qs}` : ''}`];
+ },
integration_details_assets: ({ pkgkey, integration }) => [
INTEGRATIONS_BASE_PATH,
`/detail/${pkgkey}/assets${integration ? `?integration=${integration}` : ''}`,
From f381f9100b0e6c134d8966606acd021a9e2d7aee Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Thu, 17 Jun 2021 16:38:08 +0200
Subject: [PATCH 08/20] First iteration of end-to-end UX working. Need to add a
lot of tests!
---
.../create_package_policy_page/index.tsx | 11 +-
.../detail/policies/package_policies.tsx | 64 +++++--
.../agent_enrollment_flyout/index.tsx | 13 +-
.../managed_instructions.tsx | 167 ++++++++++--------
.../agent_enrollment_flyout/steps.tsx | 25 +--
.../agent_enrollment_flyout/types.ts | 12 +-
.../package_policy_actions_menu.tsx | 9 +-
7 files changed, 178 insertions(+), 123 deletions(-)
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
index 0f3463a45fa0ae..fc6ef809139615 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
@@ -315,12 +315,10 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
values={{
link: (
{i18n.translate(
'xpack.fleet.createPackagePolicy.integrationsContextAddAgentLinkMessage',
@@ -348,6 +346,7 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
setFormState('VALID');
}
}, [
+ getHref,
from,
packageInfo,
agentCount,
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx
index cb6c896cd92691..c672abeb1c9036 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx
@@ -4,9 +4,9 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-
+import { stringify, parse } from 'query-string';
import React, { memo, useCallback, useMemo, useState } from 'react';
-import { Redirect, useLocation } from 'react-router-dom';
+import { Redirect, useLocation, useHistory } from 'react-router-dom';
import type { CriteriaWithPagination, EuiTableFieldDataColumnType } from '@elastic/eui';
import {
EuiButtonIcon,
@@ -15,6 +15,9 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiToolTip,
+ EuiText,
+ EuiButton,
+ EuiSpacer,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedRelative, FormattedMessage } from '@kbn/i18n/react';
@@ -67,6 +70,7 @@ interface PackagePoliciesPanelProps {
}
export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps) => {
const { search } = useLocation();
+ const history = useHistory();
const queryParams = useMemo(() => new URLSearchParams(search), [search]);
const agentPolicyIdFromParams = useMemo(() => queryParams.get('addAgentToPolicyId'), [
queryParams,
@@ -74,7 +78,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
const [flyoutOpenForPolicyId, setFlyoutOpenForPolicyId] = useState(
agentPolicyIdFromParams
);
- const { getPath } = useLink();
+ const { getPath, getHref } = useLink();
const getPackageInstallStatus = useGetPackageInstallStatus();
const packageInstallStatus = getPackageInstallStatus(name);
const { pagination, pageSizeOptions, setPagination } = useUrlPagination();
@@ -94,6 +98,36 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
[setPagination]
);
+ const renderViewDataStepContent = useCallback(
+ () => (
+ <>
+
+
+ {i18n.translate(
+ 'xpack.fleet.epm.agentEnrollment.viewDataDescription.pleaseNoteLabel',
+ { defaultMessage: 'Please note' }
+ )}
+
+ ),
+ }}
+ />
+
+
+
+ {i18n.translate('xpack.fleet.epm.agentEnrollment.viewDataAssetsLabel', {
+ defaultMessage: 'View assets',
+ })}
+
+ >
+ ),
+ [name, version, getHref]
+ );
+
const columns: Array> = useMemo(
() => [
{
@@ -193,12 +227,16 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
align: 'right',
render({ agentPolicy, packagePolicy }) {
return (
-
+
);
},
},
],
- []
+ [renderViewDataStepContent]
);
const noItemsMessage = useMemo(() => {
@@ -243,14 +281,18 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
/>
- {flyoutOpenForPolicyId && (
+ {flyoutOpenForPolicyId && !isLoading && (
setFlyoutOpenForPolicyId(null)}
- agentPolicies={
- data?.items
- .filter(({ agentPolicy }) => agentPolicy.id === flyoutOpenForPolicyId)
- .map(({ agentPolicy }) => agentPolicy) ?? []
+ onClose={() => {
+ setFlyoutOpenForPolicyId(null);
+ const { addAgentToPolicyId, ...rest } = parse(search);
+ history.replace({ search: stringify(rest) });
+ }}
+ agentPolicy={
+ data?.items.find(({ agentPolicy }) => agentPolicy.id === flyoutOpenForPolicyId)
+ ?.agentPolicy
}
+ viewDataStepContent={renderViewDataStepContent()}
/>
)}
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx
index b91af80691033e..58362d85e2fb32 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx
@@ -42,6 +42,7 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({
onClose,
agentPolicy,
agentPolicies,
+ viewDataStepContent,
}) => {
const [mode, setMode] = useState<'managed' | 'standalone'>('managed');
@@ -109,9 +110,17 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({
}
>
{fleetServerHosts.length === 0 && mode === 'managed' ? null : mode === 'managed' ? (
-
+
) : (
-
+
)}
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/managed_instructions.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/managed_instructions.tsx
index 2bb8586a11503d..d6888ae76fe87b 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/managed_instructions.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/managed_instructions.tsx
@@ -21,7 +21,12 @@ import {
useFleetServerInstructions,
} from '../../applications/fleet/sections/agents/agent_requirements_page';
-import { DownloadStep, AgentPolicySelectionStep, AgentEnrollmentKeySelectionStep } from './steps';
+import {
+ DownloadStep,
+ AgentPolicySelectionStep,
+ AgentEnrollmentKeySelectionStep,
+ ViewDataStep,
+} from './steps';
import type { BaseProps } from './types';
type Props = BaseProps;
@@ -53,83 +58,91 @@ const FleetServerMissingRequirements = () => {
return ;
};
-export const ManagedInstructions = React.memo(({ agentPolicy, agentPolicies }) => {
- const fleetStatus = useFleetStatus();
+export const ManagedInstructions = React.memo(
+ ({ agentPolicy, agentPolicies, viewDataStepContent }) => {
+ const fleetStatus = useFleetStatus();
- const [selectedAPIKeyId, setSelectedAPIKeyId] = useState();
- const [isFleetServerPolicySelected, setIsFleetServerPolicySelected] = useState(false);
+ const [selectedAPIKeyId, setSelectedAPIKeyId] = useState();
+ const [isFleetServerPolicySelected, setIsFleetServerPolicySelected] = useState(false);
- const apiKey = useGetOneEnrollmentAPIKey(selectedAPIKeyId);
- const settings = useGetSettings();
- const fleetServerInstructions = useFleetServerInstructions(apiKey?.data?.item?.policy_id);
+ const apiKey = useGetOneEnrollmentAPIKey(selectedAPIKeyId);
+ const settings = useGetSettings();
+ const fleetServerInstructions = useFleetServerInstructions(apiKey?.data?.item?.policy_id);
- const steps = useMemo(() => {
- const {
- serviceToken,
- getServiceToken,
- isLoadingServiceToken,
- installCommand,
- platform,
- setPlatform,
- } = fleetServerInstructions;
- const fleetServerHosts = settings.data?.item?.fleet_server_hosts || [];
- const baseSteps: EuiContainedStepProps[] = [
- DownloadStep(),
- !agentPolicy
- ? AgentPolicySelectionStep({
- agentPolicies,
- setSelectedAPIKeyId,
- setIsFleetServerPolicySelected,
- })
- : AgentEnrollmentKeySelectionStep({ agentPolicy, setSelectedAPIKeyId }),
- ];
- if (isFleetServerPolicySelected) {
- baseSteps.push(
- ...[
- ServiceTokenStep({ serviceToken, getServiceToken, isLoadingServiceToken }),
- FleetServerCommandStep({ serviceToken, installCommand, platform, setPlatform }),
- ]
- );
- } else {
- baseSteps.push({
- title: i18n.translate('xpack.fleet.agentEnrollment.stepEnrollAndRunAgentTitle', {
- defaultMessage: 'Enroll and start the Elastic Agent',
- }),
- children: selectedAPIKeyId && apiKey.data && (
-
- ),
- });
- }
- return baseSteps;
- }, [
- agentPolicy,
- agentPolicies,
- selectedAPIKeyId,
- apiKey.data,
- isFleetServerPolicySelected,
- settings.data?.item?.fleet_server_hosts,
- fleetServerInstructions,
- ]);
+ const steps = useMemo(() => {
+ const {
+ serviceToken,
+ getServiceToken,
+ isLoadingServiceToken,
+ installCommand,
+ platform,
+ setPlatform,
+ } = fleetServerInstructions;
+ const fleetServerHosts = settings.data?.item?.fleet_server_hosts || [];
+ const baseSteps: EuiContainedStepProps[] = [
+ DownloadStep(),
+ !agentPolicy
+ ? AgentPolicySelectionStep({
+ agentPolicies,
+ setSelectedAPIKeyId,
+ setIsFleetServerPolicySelected,
+ })
+ : AgentEnrollmentKeySelectionStep({ agentPolicy, setSelectedAPIKeyId }),
+ ];
+ if (isFleetServerPolicySelected) {
+ baseSteps.push(
+ ...[
+ ServiceTokenStep({ serviceToken, getServiceToken, isLoadingServiceToken }),
+ FleetServerCommandStep({ serviceToken, installCommand, platform, setPlatform }),
+ ]
+ );
+ } else {
+ baseSteps.push({
+ title: i18n.translate('xpack.fleet.agentEnrollment.stepEnrollAndRunAgentTitle', {
+ defaultMessage: 'Enroll and start the Elastic Agent',
+ }),
+ children: selectedAPIKeyId && apiKey.data && (
+
+ ),
+ });
+ }
- return (
- <>
- {fleetStatus.isReady ? (
- <>
-
-
-
-
-
- >
- ) : fleetStatus.missingRequirements?.length === 1 &&
- fleetStatus.missingRequirements[0] === 'fleet_server' ? (
-
- ) : (
-
- )}
- >
- );
-});
+ if (viewDataStepContent) {
+ baseSteps.push(ViewDataStep(viewDataStepContent));
+ }
+
+ return baseSteps;
+ }, [
+ agentPolicy,
+ agentPolicies,
+ selectedAPIKeyId,
+ apiKey.data,
+ isFleetServerPolicySelected,
+ settings.data?.item?.fleet_server_hosts,
+ fleetServerInstructions,
+ viewDataStepContent,
+ ]);
+
+ return (
+ <>
+ {fleetStatus.isReady ? (
+ <>
+
+
+
+
+
+ >
+ ) : fleetStatus.missingRequirements?.length === 1 &&
+ fleetStatus.missingRequirements[0] === 'fleet_server' ? (
+
+ ) : (
+
+ )}
+ >
+ );
+ }
+);
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx
index a8b8d0b8a57805..03cff88e639695 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx
@@ -143,32 +143,11 @@ export const AgentEnrollmentKeySelectionStep = ({
* Send users to assets installed by the package in Kibana so they can
* view their data.
*/
-export const ViewDataStep = () => {
+export const ViewDataStep = (content: JSX.Element) => {
return {
title: i18n.translate('xpack.fleet.agentEnrollment.stepViewDataTitle', {
defaultMessage: 'View your data',
}),
- children: (
- <>
-
-
- {i18n.translate(
- 'xpack.fleet.agentEnrollment.viewDataDescription.pleaseNoteLabel',
- { defaultMessage: 'Please note' }
- )}
-
- ),
- }}
- />
-
-
-
- >
- ),
+ children: content,
};
};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts
index b9bcf8fb3e4b27..e0c5b040a61fb2 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts
@@ -9,12 +9,20 @@ import type { AgentPolicy } from '../../types';
export interface BaseProps {
/**
- * The user selected policy to be used
+ * The user selected policy to be used. If this value is `undefined` a value must be provided for `agentPolicies`.
*/
agentPolicy?: AgentPolicy;
/**
- * A selection of policies for the user to choose from, will be ignored if `agentPolicy` has been provided
+ * A selection of policies for the user to choose from, will be ignored if `agentPolicy` has been provided.
+ *
+ * If this value is `undefined` a value must be provided for `agentPolicy`.
*/
agentPolicies?: AgentPolicy[];
+
+ /**
+ * There is a step in the agent enrollment process that allows users to see the data from an integration represented in the UI
+ * in some way. This is an area for consumers to render a button and text explaining how data can be viewed.
+ */
+ viewDataStepContent?: JSX.Element;
}
diff --git a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx
index 03bf2095f7f3e0..1f64de27fce392 100644
--- a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx
+++ b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx
@@ -21,7 +21,8 @@ import { PackagePolicyDeleteProvider } from './package_policy_delete_provider';
export const PackagePolicyActionsMenu: React.FunctionComponent<{
agentPolicy: AgentPolicy;
packagePolicy: PackagePolicy;
-}> = ({ agentPolicy, packagePolicy }) => {
+ viewDataStepContent?: JSX.Element;
+}> = ({ agentPolicy, packagePolicy, viewDataStepContent }) => {
const [isEnrollmentFlyoutOpen, setIsEnrollmentFlyoutOpen] = useState(false);
const { getHref } = useLink();
const hasWriteCapabilities = useCapabilities().write;
@@ -103,7 +104,11 @@ export const PackagePolicyActionsMenu: React.FunctionComponent<{
<>
{isEnrollmentFlyoutOpen && (
-
+
)}
From 38ec56a49b71d2c7b5b1d5adc9f0cb086517fea3 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Thu, 17 Jun 2021 17:28:22 +0200
Subject: [PATCH 09/20] fixed navigation bug and added a comment
---
.../create_package_policy_page/index.tsx | 13 ++++++++-----
.../package_policies/no_package_policies.tsx | 12 +++++++++---
x-pack/plugins/fleet/public/constants/page_paths.ts | 1 +
3 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
index fc6ef809139615..7d68e060b616a7 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
@@ -45,7 +45,6 @@ import { useIntraAppState, useUIExtension } from '../../../hooks';
import { ExtensionWrapper } from '../../../components';
import type { PackagePolicyEditExtensionComponentProps } from '../../../types';
import { PLUGIN_ID } from '../../../../../../common/constants';
-import { pagePathGetters } from '../../../../../constants';
import { pkgKeyFromPackageInfo } from '../../../services';
import { CreatePackagePolicyPageLayout } from './components';
@@ -87,11 +86,15 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
const history = useHistory();
const handleNavigateTo = useNavigateToCallback();
const routeState = useIntraAppState();
- const from: CreatePackagePolicyFrom = 'policyId' in params ? 'policy' : 'package';
const { search } = useLocation();
const queryParams = useMemo(() => new URLSearchParams(search), [search]);
- const policyId = useMemo(() => queryParams.get('policyId') ?? undefined, [queryParams]);
+ const queryParamsPolicyId = useMemo(() => queryParams.get('policyId') ?? undefined, [
+ queryParams,
+ ]);
+
+ const from: CreatePackagePolicyFrom =
+ 'policyId' in params || queryParamsPolicyId ? 'policy' : 'package';
// Agent policy and package info states
const [agentPolicy, setAgentPolicy] = useState();
@@ -390,13 +393,13 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
),
- [params, updatePackageInfo, agentPolicy, updateAgentPolicy, policyId]
+ [params, updatePackageInfo, agentPolicy, updateAgentPolicy, queryParamsPolicyId]
);
const ExtensionView = useUIExtension(packagePolicy.package?.name ?? '', 'package-policy-create');
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx
index 54adbd78ab75aa..39340a21d349bd 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx
@@ -9,10 +9,11 @@ import React, { memo } from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiButton, EuiEmptyPrompt } from '@elastic/eui';
-import { useCapabilities, useLink } from '../../../../../hooks';
+import { useCapabilities, useStartServices } from '../../../../../hooks';
+import { pagePathGetters, INTEGRATIONS_PLUGIN_ID } from '../../../../../constants';
export const NoPackagePolicies = memo<{ policyId: string }>(({ policyId }) => {
- const { getHref } = useLink();
+ const { application } = useStartServices();
const hasWriteCapabilities = useCapabilities().write;
return (
@@ -36,7 +37,12 @@ export const NoPackagePolicies = memo<{ policyId: string }>(({ policyId }) => {
+ application.navigateToApp(INTEGRATIONS_PLUGIN_ID, {
+ path: `#${pagePathGetters.integrations_all()[1]}`,
+ state: { forAgentPolicyId: policyId },
+ })
+ }
>
[
FLEET_BASE_PATH,
`/policies/${policyId}/add-integration`,
From 363e749763bc6a01952ed6dc13dbfee3ded53693 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Thu, 17 Jun 2021 17:33:26 +0200
Subject: [PATCH 10/20] added a lot more padding to bottom of form
---
.../sections/agent_policy/create_package_policy_page/index.tsx | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
index 7d68e060b616a7..e0dcd1496e74a7 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
@@ -495,7 +495,8 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
)}
-
+
+
From 756a871873ef3b37f6e51f86ec9ab4814ebc8fb9 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Fri, 18 Jun 2021 10:59:35 +0200
Subject: [PATCH 11/20] restructured code for clarity, updated deprecation
comments and moved relevant code closer together
---
.../epm/screens/detail/assets/assets.tsx | 47 ++++---------------
x-pack/plugins/fleet/public/hooks/index.ts | 2 +-
.../fleet/public/hooks/use_kibana_link.ts | 46 ++++++++++++++++--
3 files changed, 52 insertions(+), 43 deletions(-)
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
index 5f50ecb223ade0..554f8bf1a07743 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
@@ -31,7 +31,7 @@ import {
useGetPackageInstallStatus,
useLink,
useStartServices,
- getKibanaLink,
+ getHrefToObjectInKibanaApp,
} from '../../../../../hooks';
import { AssetTitleMap } from '../../../../../constants';
@@ -54,33 +54,6 @@ const allowedAssetTypes: AllowedAssetTypes = [
type AssetSavedObject = SimpleSavedObject<{ title: string; description?: string }>;
-/**
- * TODO: This is a temporary solution for getting links to various assets. It is very risky because:
- *
- * 1. The plugin might not exist/be enabled
- * 2. URLs and paths might not always be supported
- *
- * We should migrate to using the new URL service locators.
- */
-const getPathToObjectInApp = ({
- type,
- id,
-}: {
- type: KibanaAssetType;
- id: string;
-}): undefined | string => {
- switch (type) {
- case KibanaAssetType.dashboard:
- return `/dashboard/${id}`;
- case KibanaAssetType.search:
- return `/discover/${id}`;
- case KibanaAssetType.visualization:
- return `/visualize/edit/${id}`;
- default:
- return undefined;
- }
-};
-
export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
const { name, version } = packageInfo;
const {
@@ -112,12 +85,11 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
}
try {
- const { savedObjects } = await savedObjectsClient.bulkGet(
- packageAttributes.installed_kibana.map(({ id, type }) => ({
- id,
- type,
- }))
- );
+ const objectsToGet = packageAttributes.installed_kibana.map(({ id, type }) => ({
+ id,
+ type,
+ }));
+ const { savedObjects } = await savedObjectsClient.bulkGet(objectsToGet);
setAssetsSavedObjects(savedObjects as AssetSavedObject[]);
} catch (e) {
setFetchError(e);
@@ -200,7 +172,8 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
>
{sectionAssetSavedObjects.map(
({ id, type, attributes: { title, description } }, idx) => {
- const pathToObjectInApp = getPathToObjectInApp({
+ const pathToObjectInApp = getHrefToObjectInKibanaApp({
+ http,
id,
type: type as KibanaAssetType,
});
@@ -210,9 +183,7 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
{pathToObjectInApp ? (
-
- {title}
-
+ {title}
) : (
title
)}
diff --git a/x-pack/plugins/fleet/public/hooks/index.ts b/x-pack/plugins/fleet/public/hooks/index.ts
index 1258a47f95015e..a00c0c5dacf111 100644
--- a/x-pack/plugins/fleet/public/hooks/index.ts
+++ b/x-pack/plugins/fleet/public/hooks/index.ts
@@ -11,7 +11,7 @@ export { useConfig, ConfigContext } from './use_config';
export { useKibanaVersion, KibanaVersionContext } from './use_kibana_version';
export { licenseService, useLicense } from './use_license';
export { useLink } from './use_link';
-export { useKibanaLink, getKibanaLink } from './use_kibana_link';
+export { useKibanaLink, getHrefToObjectInKibanaApp } from './use_kibana_link';
export { usePackageIconType, UsePackageIconType } from './use_package_icon_type';
export { usePagination, Pagination, PAGE_SIZE_OPTIONS } from './use_pagination';
export { useUrlPagination } from './use_url_pagination';
diff --git a/x-pack/plugins/fleet/public/hooks/use_kibana_link.ts b/x-pack/plugins/fleet/public/hooks/use_kibana_link.ts
index e8ecc9cf5492f4..3ad01620b9780f 100644
--- a/x-pack/plugins/fleet/public/hooks/use_kibana_link.ts
+++ b/x-pack/plugins/fleet/public/hooks/use_kibana_link.ts
@@ -6,20 +6,58 @@
*/
import type { HttpStart } from 'src/core/public';
+import { KibanaAssetType } from '../types';
+
import { useStartServices } from './';
const KIBANA_BASE_PATH = '/app/kibana';
+const getKibanaLink = (http: HttpStart, path: string) => {
+ return http.basePath.prepend(`${KIBANA_BASE_PATH}#${path}`);
+};
+
/**
- * @deprecated See comment on {@link useKibanaLink}
+ * TODO: This is a temporary solution for getting links to various assets. It is very risky because:
+ *
+ * 1. The plugin might not exist/be enabled
+ * 2. URLs and paths might not always be supported
+ *
+ * We should migrate to using the new URL service locators.
+ *
+ * @deprecated {@link Locators} from the new URL service need to be used instead.
+
*/
-export const getKibanaLink = (http: HttpStart, path: string) => {
- return http.basePath.prepend(`${KIBANA_BASE_PATH}#${path}`);
+export const getHrefToObjectInKibanaApp = ({
+ type,
+ id,
+ http,
+}: {
+ type: KibanaAssetType;
+ id: string;
+ http: HttpStart;
+}): undefined | string => {
+ let kibanaAppPath: undefined | string;
+ switch (type) {
+ case KibanaAssetType.dashboard:
+ kibanaAppPath = `/dashboard/${id}`;
+ break;
+ case KibanaAssetType.search:
+ kibanaAppPath = `/discover/${id}`;
+ break;
+ case KibanaAssetType.visualization:
+ kibanaAppPath = `/visualize/edit/${id}`;
+ break;
+ default:
+ return undefined;
+ }
+
+ return getKibanaLink(http, kibanaAppPath);
};
/**
* TODO: This functionality needs to be replaced with use of the new URL service locators
- * @deprecated
+ *
+ * @deprecated {@link Locators} from the new URL service need to be used instead.
*/
export function useKibanaLink(path: string = '/') {
const { http } = useStartServices();
From 2bf99e0304c843c31a39eb5a5781e7ee5a4ce0ac Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Fri, 18 Jun 2021 11:07:25 +0200
Subject: [PATCH 12/20] added a longer form comment about the origin policyId
---
.../agent_policy/create_package_policy_page/index.tsx | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
index e0dcd1496e74a7..d3a31c3828b3f0 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
@@ -93,6 +93,17 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
queryParams,
]);
+ /**
+ * Please note: policyId can come from one of two sources. The URL param (in the URL path) or
+ * in the query params (?policyId=foo).
+ *
+ * Either way, we take this as an indication that a user is "coming from" the fleet policy UI
+ * since we link them out to packages (a.k.a. integrations) UI when choosing a new package. It is
+ * no longer possible to choose a package directly in the create package form.
+ *
+ * We may want to deprecate the ability to pass in policyId from URL params since there is no package
+ * creation possible if a user has not chosen one from the packages UI.
+ */
const from: CreatePackagePolicyFrom =
'policyId' in params || queryParamsPolicyId ? 'policy' : 'package';
From 8f255facdaab6c634ed3acb7de590aae9fd148d6 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Fri, 18 Jun 2021 11:13:46 +0200
Subject: [PATCH 13/20] added logic for handling load error
---
.../sections/epm/screens/detail/assets/assets.tsx | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
index 554f8bf1a07743..3e8eaf99fe19f4 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx
@@ -22,7 +22,7 @@ import {
EuiHorizontalRule,
} from '@elastic/eui';
-import { Loading } from '../../../../../components';
+import { Loading, Error } from '../../../../../components';
import type { PackageInfo } from '../../../../../types';
import { InstallStatus, KibanaAssetType } from '../../../../../types';
@@ -120,7 +120,17 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
if (isLoading) {
content = ;
} else if (fetchError) {
- content = TODO HANDLE ERROR
;
+ content = (
+
+ }
+ error={fetchError}
+ />
+ );
} else if (assetSavedObjects === undefined) {
content = (
From fdd6fc056f5423a60a503b69dd873351e4dc3090 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Fri, 18 Jun 2021 11:41:41 +0200
Subject: [PATCH 14/20] refactor assets accordions out of assets page component
---
.../create_package_policy_page/index.tsx | 1 +
.../epm/screens/detail/assets/assets.tsx | 137 +++---------------
.../detail/assets/assets_accordion.tsx | 89 ++++++++++++
.../epm/screens/detail/assets/constants.ts | 16 ++
.../epm/screens/detail/assets/types.ts | 20 +++
5 files changed, 147 insertions(+), 116 deletions(-)
create mode 100644 x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
create mode 100644 x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/constants.ts
create mode 100644 x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/types.ts
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
index d3a31c3828b3f0..b3b0d6ed51cb4d 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx
@@ -323,6 +323,7 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
)
: fromPackageWithoutAgentsAssigned
? toMountPoint(
+ // To render the link below we need to mount this JSX in the success toast
;
-
export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
const { name, version } = packageInfo;
const {
savedObjects: { client: savedObjectsClient },
- http,
} = useStartServices();
const { getPath } = useLink();
@@ -115,7 +85,7 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
);
}
- let content: JSX.Element;
+ let content: JSX.Element | Array;
if (isLoading) {
content = ;
@@ -143,85 +113,20 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => {
);
} else {
- content = (
- <>
- {allowedAssetTypes.map((assetType) => {
- const sectionAssetSavedObjects = assetSavedObjects.filter((so) => so.type === assetType);
- if (!sectionAssetSavedObjects.length) {
- return null;
- }
-
- return (
- <>
-
-
-
- {AssetTitleMap[assetType]}
-
-
-
- {sectionAssetSavedObjects.length}
-
-
- }
- id={assetType}
- >
- <>
-
-
- {sectionAssetSavedObjects.map(
- ({ id, type, attributes: { title, description } }, idx) => {
- const pathToObjectInApp = getHrefToObjectInKibanaApp({
- http,
- id,
- type: type as KibanaAssetType,
- });
- return (
- <>
-
-
-
- {pathToObjectInApp ? (
- {title}
- ) : (
- title
- )}
-
-
-
- {description && (
-
- {description}
-
- )}
-
- {idx + 1 < sectionAssetSavedObjects.length && (
-
- )}
- >
- );
- }
- )}
-
- >
-
-
- >
- );
- })}
- >
- );
+ content = allowedAssetTypes.map((assetType) => {
+ const sectionAssetSavedObjects = assetSavedObjects.filter((so) => so.type === assetType);
+
+ if (!sectionAssetSavedObjects.length) {
+ return null;
+ }
+
+ return (
+ <>
+
+
+ >
+ );
+ });
}
return (
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
new file mode 100644
index 00000000000000..b9bc53e09982d4
--- /dev/null
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
@@ -0,0 +1,89 @@
+/*
+ * 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 React from 'react';
+import type { FunctionComponent } from 'react';
+
+import {
+ EuiAccordion,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiSplitPanel,
+ EuiBadge,
+ EuiSpacer,
+ EuiTitle,
+ EuiText,
+ EuiLink,
+ EuiHorizontalRule,
+} from '@elastic/eui';
+
+import { AssetTitleMap } from '../../../../../constants';
+
+import { getHrefToObjectInKibanaApp, useStartServices } from '../../../../../hooks';
+
+import type { AllowedAssetType, AssetSavedObject } from './types';
+
+interface Props {
+ type: AllowedAssetType;
+ savedObjects: AssetSavedObject[];
+}
+
+export const AssetsAccordion: FunctionComponent = ({ savedObjects, type }) => {
+ const { http } = useStartServices();
+ return (
+
+
+
+ {AssetTitleMap[type]}
+
+
+
+ {savedObjects.length}
+
+
+ }
+ id={type}
+ >
+ <>
+
+
+ {savedObjects.map(({ id, attributes: { title, description } }, idx) => {
+ const pathToObjectInApp = getHrefToObjectInKibanaApp({
+ http,
+ id,
+ type,
+ });
+ return (
+ <>
+
+
+
+ {pathToObjectInApp ? (
+ {title}
+ ) : (
+ title
+ )}
+
+
+
+ {description && (
+
+ {description}
+
+ )}
+
+ {idx + 1 < savedObjects.length && }
+ >
+ );
+ })}
+
+ >
+
+ );
+};
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/constants.ts b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/constants.ts
new file mode 100644
index 00000000000000..d6d88f7935eb44
--- /dev/null
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/constants.ts
@@ -0,0 +1,16 @@
+/*
+ * 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 { KibanaAssetType } from '../../../../../types';
+
+import type { AllowedAssetTypes } from './types';
+
+export const allowedAssetTypes: AllowedAssetTypes = [
+ KibanaAssetType.dashboard,
+ KibanaAssetType.search,
+ KibanaAssetType.visualization,
+];
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/types.ts b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/types.ts
new file mode 100644
index 00000000000000..21efd1cd562e80
--- /dev/null
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/types.ts
@@ -0,0 +1,20 @@
+/*
+ * 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 type { SimpleSavedObject } from 'src/core/public';
+
+import type { KibanaAssetType } from '../../../../../types';
+
+export type AssetSavedObject = SimpleSavedObject<{ title: string; description?: string }>;
+
+export type AllowedAssetTypes = [
+ KibanaAssetType.dashboard,
+ KibanaAssetType.search,
+ KibanaAssetType.visualization
+];
+
+export type AllowedAssetType = AllowedAssetTypes[number];
From 8a1170ddc49f6867aea3587d033a3932c5429312 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Fri, 18 Jun 2021 11:43:03 +0200
Subject: [PATCH 15/20] slightly larger text in badge
---
.../sections/epm/screens/detail/assets/assets_accordion.tsx | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
index b9bc53e09982d4..b7d3b0454c9d03 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
@@ -44,7 +44,9 @@ export const AssetsAccordion: FunctionComponent = ({ savedObjects, type }
- {savedObjects.length}
+
+ {savedObjects.length}
+
}
From 38e836f6f5e98a5a0ae799637cce24ce75db43ea Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Fri, 18 Jun 2021 11:54:48 +0200
Subject: [PATCH 16/20] added some basic jest test for view data step in
enrollment flyout
---
.../agent_enrollment_flyout.test.mocks.ts | 1 +
.../agent_enrollment_flyout.test.tsx | 42 ++++++++++++++++++-
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.mocks.ts b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.mocks.ts
index f1055e7e2583ee..fcf10785664986 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.mocks.ts
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.mocks.ts
@@ -37,6 +37,7 @@ jest.mock('./steps', () => {
...module,
AgentPolicySelectionStep: jest.fn(),
AgentEnrollmentKeySelectionStep: jest.fn(),
+ ViewDataStep: jest.fn(),
};
});
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx
index db9245b11b0f99..65118044e98c56 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx
@@ -21,7 +21,7 @@ import { FleetStatusProvider, ConfigContext } from '../../hooks';
import { useFleetServerInstructions } from '../../applications/fleet/sections/agents/agent_requirements_page';
-import { AgentEnrollmentKeySelectionStep, AgentPolicySelectionStep } from './steps';
+import { AgentEnrollmentKeySelectionStep, AgentPolicySelectionStep, ViewDataStep } from './steps';
import type { Props } from '.';
import { AgentEnrollmentFlyout } from '.';
@@ -128,6 +128,46 @@ describe('', () => {
expect(AgentEnrollmentKeySelectionStep).toHaveBeenCalled();
});
});
+
+ describe('"View data" extension point', () => {
+ it('calls the "View data" step when UI extension is provided', async () => {
+ jest.clearAllMocks();
+ await act(async () => {
+ testBed = await setup({
+ agentPolicies: [],
+ onClose: jest.fn(),
+ viewDataStepContent: ,
+ });
+ testBed.component.update();
+ });
+ const { exists, actions } = testBed;
+ expect(exists('agentEnrollmentFlyout')).toBe(true);
+ expect(ViewDataStep).toHaveBeenCalled();
+
+ jest.clearAllMocks();
+ actions.goToStandaloneTab();
+ expect(ViewDataStep).not.toHaveBeenCalled();
+ });
+
+ it('does not call the "View data" step when UI extension is not provided', async () => {
+ jest.clearAllMocks();
+ await act(async () => {
+ testBed = await setup({
+ agentPolicies: [],
+ onClose: jest.fn(),
+ viewDataStepContent: undefined,
+ });
+ testBed.component.update();
+ });
+ const { exists, actions } = testBed;
+ expect(exists('agentEnrollmentFlyout')).toBe(true);
+ expect(ViewDataStep).not.toHaveBeenCalled();
+
+ jest.clearAllMocks();
+ actions.goToStandaloneTab();
+ expect(ViewDataStep).not.toHaveBeenCalled();
+ });
+ });
});
describe('standalone instructions', () => {
From f5db4277a85921203c29ad7daaf73e7df62c5b2f Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Fri, 18 Jun 2021 11:59:35 +0200
Subject: [PATCH 17/20] adjusted sizing of numbers in badges again, EuiText
does not know about size="l"
---
.../sections/epm/screens/detail/assets/assets_accordion.tsx | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
index b7d3b0454c9d03..ae06a1a77d9686 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
@@ -45,7 +45,9 @@ export const AssetsAccordion: FunctionComponent = ({ savedObjects, type }
- {savedObjects.length}
+
+ {savedObjects.length}
+
From 96e1d14c08de9c6028205b564a59c963614af608 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Mon, 21 Jun 2021 09:48:46 +0200
Subject: [PATCH 18/20] updated size limits for fleet
---
packages/kbn-optimizer/limits.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml
index 9adc075a7983f8..f9127e4629f43e 100644
--- a/packages/kbn-optimizer/limits.yml
+++ b/packages/kbn-optimizer/limits.yml
@@ -34,7 +34,7 @@ pageLoadAssetSize:
indexManagement: 140608
indexPatternManagement: 28222
infra: 184320
- fleet: 450005
+ fleet: 465774
ingestPipelines: 58003
inputControlVis: 172675
inspector: 148711
From dabcb2d62f3c426552014795d8a43b5b9e76b220 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Mon, 21 Jun 2021 16:00:36 +0200
Subject: [PATCH 19/20] updated styling and layout of assets accordion based on
original designs
---
.../detail/assets/assets_accordion.tsx | 26 +++++++++----------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
index ae06a1a77d9686..85a3710f3518fa 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
@@ -13,12 +13,12 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiSplitPanel,
- EuiBadge,
EuiSpacer,
EuiTitle,
EuiText,
EuiLink,
EuiHorizontalRule,
+ EuiNotificationBadge,
} from '@elastic/eui';
import { AssetTitleMap } from '../../../../../constants';
@@ -39,23 +39,21 @@ export const AssetsAccordion: FunctionComponent = ({ savedObjects, type }
buttonContent={
-
+
{AssetTitleMap[type]}
-
+
-
-
- {savedObjects.length}
-
-
+
+ {savedObjects.length}
+
}
id={type}
>
<>
-
+
{savedObjects.map(({ id, attributes: { title, description } }, idx) => {
const pathToObjectInApp = getHrefToObjectInKibanaApp({
@@ -75,11 +73,13 @@ export const AssetsAccordion: FunctionComponent = ({ savedObjects, type }
)}
-
{description && (
-
- {description}
-
+ <>
+
+
+ {description}
+
+ >
)}
{idx + 1 < savedObjects.length && }
From 7ebf29160f0ef9f3a7f8f85130939354a9326b01 Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Mon, 21 Jun 2021 16:54:26 +0200
Subject: [PATCH 20/20] remove unused EuiTitle
---
.../sections/epm/screens/detail/assets/assets_accordion.tsx | 1 -
1 file changed, 1 deletion(-)
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
index 85a3710f3518fa..abfdd88d271622 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx
@@ -14,7 +14,6 @@ import {
EuiFlexItem,
EuiSplitPanel,
EuiSpacer,
- EuiTitle,
EuiText,
EuiLink,
EuiHorizontalRule,