Skip to content

Commit

Permalink
[Inventory] Enable elastic entity model from inventory
Browse files Browse the repository at this point in the history
  • Loading branch information
kpatticha committed Sep 20, 2024
1 parent 9765f73 commit 857db67
Show file tree
Hide file tree
Showing 8 changed files with 441 additions and 0 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* 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 { EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useState } from 'react';
import { EntityManagerUnauthorizedError } from '@kbn/entityManager-plugin/public';
import type { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public';
import { useKibana } from '../../hooks/use_kibana';
import { Unauthorized } from './unauthorized_modal';

export function EnableEntityModelButton({ onSuccess }: { onSuccess: () => void }) {
const {
dependencies: {
start: { entityManager },
},
core: { notifications },
} = useKibana();

const [isLoading, setIsLoading] = useState(false);
const [showModal, setModalVisible] = useState(false);

const handleEnablement = async () => {
setIsLoading(true);
try {
const response = await entityManager.entityClient.enableManagedEntityDiscovery();

if (response.success) {
setIsLoading(false);
onSuccess();
} else {
throw new Error(response.message);
}
} catch (error) {
setIsLoading(false);

if (error instanceof EntityManagerUnauthorizedError) {
setModalVisible(true);
return;
}

const err = error as Error | IHttpFetchError<ResponseErrorBody>;
notifications.toasts.addDanger({
title: i18n.translate('xpack.inventory.eemEnablement.errorTitle', {
defaultMessage: 'Error while enabling the new entity model',
}),
text: 'response' in err ? err.body?.message ?? err.response?.statusText : err.message,
});
}
};

return (
<>
<EuiButton
isLoading={isLoading}
data-test-subj="inventoryInventoryPageTemplateFilledButton"
fill
onClick={handleEnablement}
>
{i18n.translate('xpack.inventory.noData.card.button', {
defaultMessage: 'Enable',
})}
</EuiButton>
<Unauthorized showModal={showModal} onClose={() => setModalVisible(false)} />
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* 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.
*/

/*
/*
* 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 { i18n } from '@kbn/i18n';
import {
EuiButton,
EuiConfirmModal,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiImage,
EuiLink,
EuiPanel,
EuiSpacer,
EuiText,
EuiTitle,
} from '@elastic/eui';
import inventoryLight from '../../assets/entities_intentory_light.png';

export function Unauthorized({
showModal = false,
onClose,
}: {
showModal?: boolean;
onClose: () => void;
}) {
return (
<>
{showModal && (
<EuiConfirmModal
style={{
width: '630px',
}}
onCancel={onClose}
onConfirm={onClose}
confirmButtonText={
<EuiButton data-test-subj="xpack.inventory.unauthorised.button.open" fill size="s">
{i18n.translate('xpack.inventory.unauthorised.button.openSurvey', {
defaultMessage: 'OK',
})}
</EuiButton>
}
cancelButtonText={
<EuiLink
target="_blank"
data-test-subj="inventoryUnauthorizedLinkExternal"
href="https://ela.st/docs-entity-inventory"
external
>
{i18n.translate('xpack.inventory.unauthorized.linkLinkLabel', {
defaultMessage: 'Learn more',
})}
</EuiLink>
}
defaultFocusedButton="confirm"
>
<EuiPanel hasShadow={false}>
<EuiFlexGroup
direction="column"
justifyContent="center"
alignItems="center"
gutterSize="m"
>
<EuiFlexItem>
<EuiIcon type="lock" size="l" />
</EuiFlexItem>
<EuiFlexItem>
<EuiTitle>
<h2>
{i18n.translate('xpack.inventory.unauthorised.title', {
defaultMessage: 'Insufficient permissions',
})}
</h2>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>

<EuiPanel hasShadow={false} paddingSize="s">
<EuiText grow={false} textAlign="center">
<p>
{i18n.translate('xpack.inventory.unauthorised.body', {
defaultMessage:
"You don't have permissions to turn on the Elastic Entity Model. Please ask your administrator to enable this for you so you can see everything you have in one place.",
})}
</p>
</EuiText>
</EuiPanel>
<EuiSpacer size="m" />
<EuiPanel hasBorder paddingSize="none">
<EuiImage
allowFullScreen
size="xl"
src={inventoryLight} // FIXME need dark version of this image
alt={i18n.translate('xpack.inventory.unauthorised.image.at,', {
defaultMessage:
'Image of the new experience of the entities inventory, showing services, hosts and containers',
})}
/>
</EuiPanel>
</EuiConfirmModal>
)}
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* 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.
*/

/*
/*
* 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 { i18n } from '@kbn/i18n';
import {
EuiButton,
EuiConfirmModal,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiImage,
EuiLink,
EuiPanel,
EuiSpacer,
EuiText,
EuiTitle,
} from '@elastic/eui';
import inventoryLight from '../../assets/entities_intentory_light.png';

export function Welcome({
showModal = false,
onClose,
onConfirm,
}: {
showModal: boolean;
onClose: () => void;
onConfirm: () => void;
}) {
if (!showModal) {
return null;
}

return (
<EuiConfirmModal
style={{
width: '630px',
}}
onCancel={onClose}
onConfirm={onConfirm}
confirmButtonText={
<EuiButton data-test-subj="xpack.inventory.welcome.button.open" fill size="s">
{i18n.translate('xpack.inventory.welcome.button.openSurvey', {
defaultMessage: 'OK',
})}
</EuiButton>
}
cancelButtonText={
<EuiLink
target="_blank"
data-test-subj="inventoryWelcomeLinkExternal"
href="https://ela.st/docs-entity-inventory"
external
>
{i18n.translate('xpack.inventory.welcome.linkLabel', {
defaultMessage: 'Learn more',
})}
</EuiLink>
}
defaultFocusedButton="confirm"
>
<EuiPanel hasShadow={false}>
<EuiFlexGroup direction="column" justifyContent="center" alignItems="center" gutterSize="m">
<EuiFlexItem>
<EuiIcon type="logoElastic" size="l" />
</EuiFlexItem>
<EuiFlexItem>
<EuiTitle>
<h2>
{i18n.translate('xpack.inventory.welcome.title', {
defaultMessage: 'See everything you have in one place!',
})}
</h2>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>

<EuiPanel hasShadow={false} paddingSize="s">
<EuiText grow={false} textAlign="center">
<p>
{i18n.translate('xpack.inventory.welcome.body', {
defaultMessage:
'The inventory will show all of your observed entities in one place so you can detect and resolve problems with them faster.',
})}
</p>
</EuiText>
</EuiPanel>
<EuiSpacer size="m" />
<EuiPanel hasBorder paddingSize="none">
<EuiImage
size="xl"
src={inventoryLight}
allowFullScreen
alt={i18n.translate('xpack.inventory.welcome.image.alt', {
defaultMessage:
'Image of the new experience of the entities inventory, showing services, hosts and containers',
})}
/>
</EuiPanel>
</EuiConfirmModal>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import { i18n } from '@kbn/i18n';
import React from 'react';
import { useKibana } from '../../hooks/use_kibana';
import { getEntityManagerEnablement } from './no_data_config';
import { useEntityManager } from '../../hooks/use_entity_manager';
import { Welcome } from '../entity_enablement/welcome_modal';

export function InventoryPageTemplate({ children }: { children: React.ReactNode }) {
const {
Expand All @@ -16,16 +19,38 @@ export function InventoryPageTemplate({ children }: { children: React.ReactNode
} = useKibana();

const { PageTemplate: ObservabilityPageTemplate } = observabilityShared.navigation;
const {
isEntityManagerEnabled,
isEnablementPending,
refresh,
showWelcomedModal,
toggleWelcomedModal,
} = useEntityManager();

const handleSuccess = () => {
refresh();
toggleWelcomedModal();
};

return (
<ObservabilityPageTemplate
noDataConfig={getEntityManagerEnablement({
enabled: isEntityManagerEnabled,
loading: isEnablementPending,
onSuccess: handleSuccess,
})}
pageHeader={{
pageTitle: i18n.translate('xpack.inventory.inventoryPageHeaderLabel', {
defaultMessage: 'Inventory',
}),
}}
>
{children}
<Welcome
showModal={showWelcomedModal}
onClose={toggleWelcomedModal}
onConfirm={toggleWelcomedModal}
/>
</ObservabilityPageTemplate>
);
}
Loading

0 comments on commit 857db67

Please sign in to comment.