From 10ab20eedb44a234e74b63e03c655f05c25942f5 Mon Sep 17 00:00:00 2001 From: neptunian Date: Thu, 23 Apr 2020 20:38:16 -0400 Subject: [PATCH 01/10] link to installed version of detail page --- .../sections/epm/components/package_card.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_card.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_card.tsx index 8ad081cbbabe40..ab7e87b3ad06cb 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_card.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_card.tsx @@ -30,9 +30,15 @@ export function PackageCard({ showInstalledBadge, status, icons, + ...restProps }: PackageCardProps) { const { toDetailView } = useLinks(); - const url = toDetailView({ name, version }); + let urlVersion = version; + // if this is an installed package, link to the version installed + if ('savedObject' in restProps) { + urlVersion = restProps.savedObject.attributes.version || version; + } + const url = toDetailView({ name, version: urlVersion }); return ( Date: Mon, 27 Apr 2020 10:53:33 -0400 Subject: [PATCH 02/10] add latestVersion property to EPM get package endpoint --- .../ingest_manager/common/services/package_to_config.test.ts | 1 + x-pack/plugins/ingest_manager/common/types/models/epm.ts | 1 + .../ingest_manager/server/services/epm/packages/get.ts | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/ingest_manager/common/services/package_to_config.test.ts b/x-pack/plugins/ingest_manager/common/services/package_to_config.test.ts index cb290e61b17e51..a977a1a66e059a 100644 --- a/x-pack/plugins/ingest_manager/common/services/package_to_config.test.ts +++ b/x-pack/plugins/ingest_manager/common/services/package_to_config.test.ts @@ -11,6 +11,7 @@ describe('Ingest Manager - packageToConfig', () => { name: 'mock-package', title: 'Mock package', version: '0.0.0', + latestVersion: '0.0.0', description: 'description', type: 'mock', categories: [], diff --git a/x-pack/plugins/ingest_manager/common/types/models/epm.ts b/x-pack/plugins/ingest_manager/common/types/models/epm.ts index fb6bf235d1e26b..5311abcb20b6a5 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/epm.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/epm.ts @@ -203,6 +203,7 @@ export interface RegistryVarsEntry { // internal until we need them interface PackageAdditions { title: string; + latestVersion: string; assets: AssetsGroupedByServiceByType; } diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts index d76584225877c2..da8d79a04b97cd 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts @@ -67,9 +67,10 @@ export async function getPackageInfo(options: { pkgVersion: string; }): Promise { const { savedObjectsClient, pkgName, pkgVersion } = options; - const [item, savedObject, assets] = await Promise.all([ + const [item, savedObject, latestPackage, assets] = await Promise.all([ Registry.fetchInfo(pkgName, pkgVersion), getInstallationObject({ savedObjectsClient, pkgName }), + Registry.fetchFindLatestPackage(pkgName), Registry.getArchiveInfo(pkgName, pkgVersion), ] as const); // adding `as const` due to regression in TS 3.7.2 @@ -79,6 +80,7 @@ export async function getPackageInfo(options: { // add properties that aren't (or aren't yet) on Registry response const updated = { ...item, + latestVersion: latestPackage.version, title: item.title || nameAsTitle(item.name), assets: Registry.groupPathsByService(assets || []), }; From 91995fc94843799486aec76b009a9cf409d1d08a Mon Sep 17 00:00:00 2001 From: neptunian Date: Mon, 27 Apr 2020 16:53:46 -0400 Subject: [PATCH 03/10] add updates available notices --- .../sections/epm/components/icons.tsx | 15 ++++ .../sections/epm/screens/detail/content.tsx | 3 +- .../sections/epm/screens/detail/header.tsx | 17 +++-- .../epm/screens/detail/settings_panel.tsx | 72 ++++++++++++++++++- 4 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/icons.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/icons.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/icons.tsx new file mode 100644 index 00000000000000..64223efefaab8c --- /dev/null +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/icons.tsx @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { EuiIcon } from '@elastic/eui'; +import React from 'react'; +import styled from 'styled-components'; + +export const StyledAlert = styled(EuiIcon)` + color: ${props => props.theme.eui.euiColorWarning}; + padding: 0 5px; +`; + +export const UpdateIcon = () => ; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx index a3d24e7806f343..96aebb08e0c636 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx @@ -50,7 +50,7 @@ export function Content(props: ContentProps) { type ContentPanelProps = PackageInfo & Pick; export function ContentPanel(props: ContentPanelProps) { - const { panel, name, version, assets, title, removable } = props; + const { panel, name, version, assets, title, removable, latestVersion } = props; switch (panel) { case 'settings': return ( @@ -60,6 +60,7 @@ export function ContentPanel(props: ContentPanelProps) { assets={assets} title={title} removable={removable} + latestVersion={latestVersion} /> ); case 'data-sources': diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/header.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/header.tsx index d83910f29f1a78..bb7a342bd5768d 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/header.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/header.tsx @@ -13,9 +13,9 @@ import { EPM_PATH } from '../../../../constants'; import { useCapabilities, useLink } from '../../../../hooks'; import { IconPanel } from '../../components/icon_panel'; import { NavButtonBack } from '../../components/nav_button_back'; -import { Version } from '../../components/version'; import { useLinks } from '../../hooks'; import { CenterColumn, LeftColumn, RightColumn } from './layout'; +import { UpdateIcon } from '../../components/icons'; const FullWidthNavRow = styled(EuiPage)` /* no left padding so link is against column left edge */ @@ -26,19 +26,14 @@ const Text = styled.span` margin-right: ${props => props.theme.eui.euiSizeM}; `; -const StyledVersion = styled(Version)` - font-size: ${props => props.theme.eui.euiFontSizeS}; - color: ${props => props.theme.eui.euiColorDarkShade}; -`; - type HeaderProps = PackageInfo & { iconType?: IconType }; export function Header(props: HeaderProps) { - const { iconType, name, title, version } = props; + const { iconType, name, title, version, latestVersion } = props; const hasWriteCapabilites = useCapabilities().write; const { toListView } = useLinks(); const ADD_DATASOURCE_URI = useLink(`${EPM_PATH}/${name}-${version}/add-datasource`); - + const updateAvailable = latestVersion > version ? true : false; return ( @@ -59,7 +54,11 @@ export function Header(props: HeaderProps) {

{title} - + + + {version} {updateAvailable && } + +

diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx index 3589a1a9444e1b..133ad07a3522f2 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx @@ -8,11 +8,22 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiTitle, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; import { EuiSpacer } from '@elastic/eui'; +import styled from 'styled-components'; import { InstallStatus, PackageInfo } from '../../../../types'; import { useGetDatasources } from '../../../../hooks'; import { DATASOURCE_SAVED_OBJECT_TYPE } from '../../../../constants'; import { useGetPackageInstallStatus } from '../../hooks'; import { InstallationButton } from './installation_button'; +import { UpdateIcon } from '../../components/icons'; + +const SettingsTitleCell = styled.td` + padding-right: ${props => props.theme.eui.spacerSizes.xl}; + padding-bottom: ${props => props.theme.eui.spacerSizes.m}; +`; + +const UpdatesAvailableMsgContainer = styled.span` + padding-left: ${props => props.theme.eui.spacerSizes.s}; +`; const NoteLabel = () => ( ( defaultMessage="Note:" /> ); +const UpdatesAvailableMsg = () => ( + + + + +); + export const SettingsPanel = ( - props: Pick + props: Pick ) => { const getPackageInstallStatus = useGetPackageInstallStatus(); const { data: datasourcesData } = useGetDatasources({ @@ -29,9 +50,10 @@ export const SettingsPanel = ( page: 1, kuery: `${DATASOURCE_SAVED_OBJECT_TYPE}.package.name:${props.name}`, }); - const { name, title, removable } = props; + const { name, title, removable, version, latestVersion } = props; const packageInstallStatus = getPackageInstallStatus(name); const packageHasDatasources = !!datasourcesData?.total; + const updatesAvailable = latestVersion > version; return ( @@ -43,6 +65,52 @@ export const SettingsPanel = ( +
+ +

+ +

+
+ + + + + + + + + + + + + + + +
+ + {props.version} + + {updatesAvailable && } +
+ + {props.latestVersion} + +
+
+
+ {packageInstallStatus === InstallStatus.notInstalled || packageInstallStatus === InstallStatus.installing ? (
From 872681642772453436377485b1fca703d2913dff Mon Sep 17 00:00:00 2001 From: neptunian Date: Mon, 27 Apr 2020 19:59:12 -0400 Subject: [PATCH 04/10] add update package button --- .../epm/hooks/use_package_install.tsx | 19 +++++++++++---- .../screens/detail/installation_button.tsx | 24 ++++++++++++++++--- .../epm/screens/detail/settings_panel.tsx | 18 ++++++++++---- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx index 0c5f45cdc47a71..70289c94b9a304 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx @@ -11,6 +11,7 @@ import { NotificationsStart } from 'src/core/public'; import { toMountPoint } from '../../../../../../../../../src/plugins/kibana_react/public'; import { PackageInfo } from '../../../types'; import { sendInstallPackage, sendRemovePackage } from '../../../hooks'; +import { useLinks } from '.'; import { InstallStatus } from '../../../types'; interface PackagesInstall { @@ -21,9 +22,12 @@ interface PackageInstallItem { status: InstallStatus; } -type InstallPackageProps = Pick; +type InstallPackageProps = Pick & { + fromUpdate?: boolean; +}; function usePackageInstall({ notifications }: { notifications: NotificationsStart }) { + const { toDetailView } = useLinks(); const [packages, setPackage] = useState({}); const setPackageInstallStatus = useCallback( @@ -37,7 +41,7 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar ); const installPackage = useCallback( - async ({ name, version, title }: InstallPackageProps) => { + async ({ name, version, title, fromUpdate = false }: InstallPackageProps) => { setPackageInstallStatus({ name, status: InstallStatus.installing }); const pkgkey = `${name}-${version}`; @@ -62,7 +66,14 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar }); } else { setPackageInstallStatus({ name, status: InstallStatus.installed }); - + if (fromUpdate) { + const settingsUrl = toDetailView({ + name, + version, + panel: 'settings', + }); + window.location.href = settingsUrl; + } notifications.toasts.addSuccess({ title: toMountPoint( & { - disabled: boolean; + disabled?: boolean; + isUpdate?: boolean; }; export function InstallationButton(props: InstallationButtonProps) { - const { assets, name, title, version, disabled = true } = props; + const { assets, name, title, version, disabled = true, isUpdate = false } = props; const hasWriteCapabilites = useCapabilities().write; const installPackage = useInstallPackage(); const uninstallPackage = useUninstallPackage(); @@ -26,6 +27,7 @@ export function InstallationButton(props: InstallationButtonProps) { const isInstalling = installationStatus === InstallStatus.installing; const isRemoving = installationStatus === InstallStatus.uninstalling; const isInstalled = installationStatus === InstallStatus.installed; + const showUninstallButton = isInstalled || isInstalling || isRemoving; const [isModalVisible, setModalVisible] = useState(false); const toggleModal = useCallback(() => { setModalVisible(!isModalVisible); @@ -36,6 +38,10 @@ export function InstallationButton(props: InstallationButtonProps) { toggleModal(); }, [installPackage, name, title, toggleModal, version]); + const handleClickUpdate = useCallback(() => { + installPackage({ name, version, title, fromUpdate: true }); + }, [installPackage, name, title, version]); + const handleClickUninstall = useCallback(() => { uninstallPackage({ name, version, title }); toggleModal(); @@ -78,6 +84,18 @@ export function InstallationButton(props: InstallationButtonProps) { ); + const updateButton = ( + + + + ); + const uninstallButton = ( - {isInstalled || isRemoving ? uninstallButton : installButton} + {isUpdate ? updateButton : showUninstallButton ? uninstallButton : installButton} {isModalVisible && (isInstalled ? uninstallModal : installModal)} ) : null; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx index 133ad07a3522f2..861eb4fc4aee07 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx @@ -78,8 +78,8 @@ export const SettingsPanel = ( - - +
+ -
-
+ + + {updatesAvailable && ( +

+ +

+ )}
{packageInstallStatus === InstallStatus.notInstalled || From ce3c1e97ac04d03944e85b8121b6fbfe5633df47 Mon Sep 17 00:00:00 2001 From: neptunian Date: Tue, 28 Apr 2020 10:00:20 -0400 Subject: [PATCH 05/10] handle various states and send installedVersion from package endpoint --- .../ingest_manager/common/types/models/epm.ts | 1 + .../epm/hooks/use_package_install.tsx | 26 +- .../sections/epm/screens/detail/header.tsx | 4 +- .../sections/epm/screens/detail/index.tsx | 4 +- .../screens/detail/installation_button.tsx | 2 +- .../epm/screens/detail/settings_panel.tsx | 269 +++++++++--------- .../server/services/epm/packages/index.ts | 1 + 7 files changed, 164 insertions(+), 143 deletions(-) diff --git a/x-pack/plugins/ingest_manager/common/types/models/epm.ts b/x-pack/plugins/ingest_manager/common/types/models/epm.ts index 5311abcb20b6a5..e77fc13dcf95ed 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/epm.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/epm.ts @@ -204,6 +204,7 @@ export interface RegistryVarsEntry { interface PackageAdditions { title: string; latestVersion: string; + installedVersion?: string; assets: AssetsGroupedByServiceByType; } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx index 70289c94b9a304..59ec348669421b 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx @@ -20,21 +20,27 @@ interface PackagesInstall { interface PackageInstallItem { status: InstallStatus; + version: string | null; } type InstallPackageProps = Pick & { fromUpdate?: boolean; }; +type SetPackageInstallStatusProps = Pick & PackageInstallItem; function usePackageInstall({ notifications }: { notifications: NotificationsStart }) { const { toDetailView } = useLinks(); const [packages, setPackage] = useState({}); const setPackageInstallStatus = useCallback( - ({ name, status }: { name: PackageInfo['name']; status: InstallStatus }) => { + ({ name, status, version }: SetPackageInstallStatusProps) => { + const packageProps: PackageInstallItem = { + status, + version, + }; setPackage((prev: PackagesInstall) => ({ ...prev, - [name]: { status }, + [name]: packageProps, })); }, [] @@ -42,12 +48,12 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar const installPackage = useCallback( async ({ name, version, title, fromUpdate = false }: InstallPackageProps) => { - setPackageInstallStatus({ name, status: InstallStatus.installing }); + setPackageInstallStatus({ name, status: InstallStatus.installing, version }); const pkgkey = `${name}-${version}`; const res = await sendInstallPackage(pkgkey); if (res.error) { - setPackageInstallStatus({ name, status: InstallStatus.notInstalled }); + setPackageInstallStatus({ name, status: InstallStatus.notInstalled, version }); notifications.toasts.addWarning({ title: toMountPoint( { - return packages[pkg].status; + (pkg: string): PackageInstallItem => { + return packages[pkg]; }, [packages] ); const uninstallPackage = useCallback( async ({ name, version, title }: Pick) => { - setPackageInstallStatus({ name, status: InstallStatus.uninstalling }); + setPackageInstallStatus({ name, status: InstallStatus.uninstalling, version }); const pkgkey = `${name}-${version}`; const res = await sendRemovePackage(pkgkey); if (res.error) { - setPackageInstallStatus({ name, status: InstallStatus.installed }); + setPackageInstallStatus({ name, status: InstallStatus.installed, version }); notifications.toasts.addWarning({ title: toMountPoint( version ? true : false; + const updateAvailable = installedVersion && installedVersion < latestVersion ? true : false; return ( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/index.tsx index 3239d7b90e3c3c..1f3eb2cc9362e5 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/index.tsx @@ -32,11 +32,12 @@ export function Detail() { const packageInfo = response.data?.response; const title = packageInfo?.title; const name = packageInfo?.name; + const installedVersion = packageInfo?.installedVersion; const status: InstallStatus = packageInfo?.status as any; // track install status state if (name) { - setPackageInstallStatus({ name, status }); + setPackageInstallStatus({ name, status, version: installedVersion || null }); } if (packageInfo) { setInfo({ ...packageInfo, title: title || '' }); @@ -64,7 +65,6 @@ type LayoutProps = PackageInfo & Pick & Pick diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx index 1c23444b24adaa..c01c655a84f7bb 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx @@ -22,7 +22,7 @@ export function InstallationButton(props: InstallationButtonProps) { const installPackage = useInstallPackage(); const uninstallPackage = useUninstallPackage(); const getPackageInstallStatus = useGetPackageInstallStatus(); - const installationStatus = getPackageInstallStatus(name); + const { status: installationStatus } = getPackageInstallStatus(name); const isInstalling = installationStatus === InstallStatus.installing; const isRemoving = installationStatus === InstallStatus.uninstalling; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx index 861eb4fc4aee07..c1a99d96c82804 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx @@ -44,16 +44,23 @@ const UpdatesAvailableMsg = () => ( export const SettingsPanel = ( props: Pick ) => { + const { name, title, removable, latestVersion, version } = props; const getPackageInstallStatus = useGetPackageInstallStatus(); const { data: datasourcesData } = useGetDatasources({ perPage: 0, page: 1, kuery: `${DATASOURCE_SAVED_OBJECT_TYPE}.package.name:${props.name}`, }); - const { name, title, removable, version, latestVersion } = props; - const packageInstallStatus = getPackageInstallStatus(name); + const { status: installationStatus, version: installedVersion } = getPackageInstallStatus(name); const packageHasDatasources = !!datasourcesData?.total; - const updatesAvailable = latestVersion > version; + const updateAvailable = installedVersion && installedVersion < latestVersion ? true : false; + const isViewingOldPackage = version < latestVersion; + + // hide install/remove options if the user has version of the package is installed + // and this package is out of date or if they do have a version installed but it's not this one + const hideInstallOptions = + (installationStatus === InstallStatus.notInstalled && isViewingOldPackage) || + (installationStatus === InstallStatus.installed && installedVersion !== version); return ( @@ -65,70 +72,13 @@ export const SettingsPanel = ( -
- -

- -

-
- - - - - - - - - - - - - - - - -
- - {props.version} - - {updatesAvailable && } -
- - {props.latestVersion} - -
- {updatesAvailable && ( -

- -

- )} -
- - {packageInstallStatus === InstallStatus.notInstalled || - packageInstallStatus === InstallStatus.installing ? ( + {installationStatus === InstallStatus.installed && (

-

- -

+ + + + + + + + + + + + + + + +
+ + {installedVersion} + + {updateAvailable && } +
+ + {latestVersion} + +
+ {updateAvailable && ( +

+ +

+ )}

- ) : ( + )} + {!hideInstallOptions && (
- -

+ + {installationStatus === InstallStatus.notInstalled || + installationStatus === InstallStatus.installing ? ( +
+ +

+ +

+
+ +

+ +

+
+ ) : ( +
+ +

+ +

+
+ +

+ +

+
+ )} + + +

+ +

+
+
+ {packageHasDatasources && removable === true && ( +

+ + + ), }} /> -

-
- -

- -

+

+ )} + {removable === false && ( +

+ + + + ), + }} + /> +

+ )}
)} - - -

- -

-
-
- {packageHasDatasources && removable === true && ( -

- - - - ), - }} - /> -

- )} - {removable === false && ( -

- - - - ), - }} - /> -

- )}
); }; diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts index d49e0e661440f3..c67cccd044bf5e 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts @@ -43,6 +43,7 @@ export function createInstallableFrom( ? { ...from, status: InstallationStatus.installed, + installedVersion: savedObject.attributes.version, savedObject, } : { From d01fa2b5cafdcb2314cb87ef67ce47b9a1690985 Mon Sep 17 00:00:00 2001 From: neptunian Date: Tue, 28 Apr 2020 10:10:00 -0400 Subject: [PATCH 06/10] fix type errors --- .../sections/epm/screens/detail/data_sources_panel.tsx | 2 +- .../sections/epm/screens/detail/side_nav_links.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/data_sources_panel.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/data_sources_panel.tsx index fa3245aec02c5b..c82b7ed2297a7c 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/data_sources_panel.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/data_sources_panel.tsx @@ -20,7 +20,7 @@ export const DataSourcesPanel = ({ name, version }: DataSourcesPanelProps) => { const packageInstallStatus = getPackageInstallStatus(name); // 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 !== InstallStatus.installed) + if (packageInstallStatus.status !== InstallStatus.installed) return ( Date: Tue, 28 Apr 2020 11:15:18 -0400 Subject: [PATCH 07/10] fix install error because not returning promises --- .../server/services/epm/packages/install.ts | 2 +- .../ingest_manager/server/services/epm/packages/remove.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts index 06f3decdbbe6f2..8f51c4d78305c0 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts @@ -106,7 +106,7 @@ export async function installPackage(options: { try { await deleteKibanaSavedObjectsAssets(savedObjectsClient, installedPkg.attributes.installed); } catch (err) { - // some assets may not exist if deleting during a failed update + // log these errors, some assets may not exist if deleted during a failed update } } diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts index ac2c869f3b9e9f..befb4722b6504f 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts @@ -121,8 +121,12 @@ export async function deleteKibanaSavedObjectsAssets( const deletePromises = installedObjects.map(({ id, type }) => { const assetType = type as AssetType; if (savedObjectTypes.includes(assetType)) { - savedObjectsClient.delete(assetType, id); + return savedObjectsClient.delete(assetType, id); } }); - await Promise.all(deletePromises); + try { + await Promise.all(deletePromises); + } catch (err) { + throw new Error('error deleting saved object asset'); + } } From b7bef4f75b808b6d1a940b85101e6a29c3187fed Mon Sep 17 00:00:00 2001 From: neptunian Date: Tue, 28 Apr 2020 13:34:59 -0400 Subject: [PATCH 08/10] track version in state --- .../epm/hooks/use_package_install.tsx | 22 ++++++++++--------- .../screens/detail/installation_button.tsx | 2 +- .../epm/screens/detail/settings_panel.tsx | 7 +++--- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx index 59ec348669421b..78e960dab488df 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx @@ -46,9 +46,18 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar [] ); + const getPackageInstallStatus = useCallback( + (pkg: string): PackageInstallItem => { + return packages[pkg]; + }, + [packages] + ); + const installPackage = useCallback( async ({ name, version, title, fromUpdate = false }: InstallPackageProps) => { - setPackageInstallStatus({ name, status: InstallStatus.installing, version }); + const currStatus = getPackageInstallStatus(name); + const newStatus = { ...currStatus, name, status: InstallStatus.installing }; + setPackageInstallStatus(newStatus); const pkgkey = `${name}-${version}`; const res = await sendInstallPackage(pkgkey); @@ -98,14 +107,7 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar }); } }, - [notifications.toasts, setPackageInstallStatus, toDetailView] - ); - - const getPackageInstallStatus = useCallback( - (pkg: string): PackageInstallItem => { - return packages[pkg]; - }, - [packages] + [getPackageInstallStatus, notifications.toasts, setPackageInstallStatus, toDetailView] ); const uninstallPackage = useCallback( @@ -133,7 +135,7 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar iconType: 'alert', }); } else { - setPackageInstallStatus({ name, status: InstallStatus.notInstalled, version }); + setPackageInstallStatus({ name, status: InstallStatus.notInstalled, version: null }); notifications.toasts.addSuccess({ title: toMountPoint( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx index c01c655a84f7bb..e418b2d1555baa 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx @@ -27,7 +27,7 @@ export function InstallationButton(props: InstallationButtonProps) { const isInstalling = installationStatus === InstallStatus.installing; const isRemoving = installationStatus === InstallStatus.uninstalling; const isInstalled = installationStatus === InstallStatus.installed; - const showUninstallButton = isInstalled || isInstalling || isRemoving; + const showUninstallButton = isInstalled || isRemoving; const [isModalVisible, setModalVisible] = useState(false); const toggleModal = useCallback(() => { setModalVisible(!isModalVisible); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx index c1a99d96c82804..4d4dba2a64e5a6 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx @@ -55,12 +55,13 @@ export const SettingsPanel = ( const packageHasDatasources = !!datasourcesData?.total; const updateAvailable = installedVersion && installedVersion < latestVersion ? true : false; const isViewingOldPackage = version < latestVersion; - // hide install/remove options if the user has version of the package is installed // and this package is out of date or if they do have a version installed but it's not this one const hideInstallOptions = (installationStatus === InstallStatus.notInstalled && isViewingOldPackage) || (installationStatus === InstallStatus.installed && installedVersion !== version); + + const isUpdating = installationStatus === InstallStatus.installing && installedVersion; return ( @@ -72,7 +73,7 @@ export const SettingsPanel = ( - {installationStatus === InstallStatus.installed && ( + {installedVersion !== null && (

@@ -129,7 +130,7 @@ export const SettingsPanel = ( )}

)} - {!hideInstallOptions && ( + {!hideInstallOptions && !isUpdating && (
{installationStatus === InstallStatus.notInstalled || From 0efa9403c4318aabfdadcaccab2487bc8035ccb0 Mon Sep 17 00:00:00 2001 From: neptunian Date: Tue, 28 Apr 2020 14:43:48 -0400 Subject: [PATCH 09/10] handle unsuccessful update attempt --- .../sections/epm/hooks/use_package_install.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx index 78e960dab488df..244a9a2c7426e8 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx @@ -62,7 +62,13 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar const res = await sendInstallPackage(pkgkey); if (res.error) { - setPackageInstallStatus({ name, status: InstallStatus.notInstalled, version }); + if (fromUpdate) { + // if there is an error during update, set it back to the previous version + // as handling of bad update is not implemented yet + setPackageInstallStatus({ ...currStatus, name }); + } else { + setPackageInstallStatus({ name, status: InstallStatus.notInstalled, version }); + } notifications.toasts.addWarning({ title: toMountPoint( Date: Tue, 28 Apr 2020 16:52:42 -0400 Subject: [PATCH 10/10] remove unused variable --- .../sections/epm/screens/detail/installation_button.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx index e418b2d1555baa..cdad67fd875483 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx @@ -89,9 +89,6 @@ export function InstallationButton(props: InstallationButtonProps) { );