mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
Onboarding integration flow fleet (#203443)
## Summary Summarize your PR. If it involves visual changes include a screenshot or gif. ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This was checked for breaking HTTP API changes, and any breaking changes have been approved by the breaking-change committee. The `release_note:breaking` label should be applied in these situations. - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [ ] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) ### Identify risks Does this PR introduce any risks? For example, consider risks like hard to test bugs, performance regression, potential of data loss. Describe the risk, its severity, and mitigation for each identified risk. Invite stakeholders and evaluate how to proceed before merging. - [ ] [See some risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) - [ ] ...
This commit is contained in:
parent
637369f012
commit
4bed69c657
40 changed files with 1073 additions and 216 deletions
|
@ -22,11 +22,13 @@ import {
|
|||
interface AdvancedTabProps {
|
||||
onClose: () => void;
|
||||
selectedPolicyId?: string;
|
||||
handleContinueAddingAgentClick?: () => void;
|
||||
}
|
||||
|
||||
export const AdvancedTab: React.FunctionComponent<AdvancedTabProps> = ({
|
||||
selectedPolicyId,
|
||||
onClose,
|
||||
handleContinueAddingAgentClick,
|
||||
}) => {
|
||||
const {
|
||||
isSelectFleetServerPolicyLoading,
|
||||
|
@ -81,6 +83,7 @@ export const AdvancedTab: React.FunctionComponent<AdvancedTabProps> = ({
|
|||
getConfirmFleetServerConnectionStep({
|
||||
hasRecentlyEnrolledFleetServers,
|
||||
disabled: !Boolean(serviceToken),
|
||||
handleContinueAddingAgentClick,
|
||||
}),
|
||||
];
|
||||
|
||||
|
|
|
@ -39,20 +39,33 @@ interface Props {
|
|||
onClose: () => void;
|
||||
}
|
||||
|
||||
const useFleetServerTabs = (onClose: () => void) => {
|
||||
export const useFleetServerTabs = (
|
||||
onClose: () => void,
|
||||
handleContinueAddingAgentClick?: () => void
|
||||
) => {
|
||||
const [currentTab, setCurrentTab] = useState('quickStart');
|
||||
|
||||
const quickStartTab = {
|
||||
id: 'quickStart',
|
||||
label: 'Quick Start',
|
||||
content: <QuickStartTab onClose={onClose} />,
|
||||
content: (
|
||||
<QuickStartTab
|
||||
onClose={onClose}
|
||||
handleContinueAddingAgentClick={handleContinueAddingAgentClick}
|
||||
/>
|
||||
),
|
||||
'data-test-subj': 'fleetServerFlyoutTab-quickStart',
|
||||
};
|
||||
|
||||
const advancedTab = {
|
||||
id: 'advanced',
|
||||
label: 'Advanced',
|
||||
content: <AdvancedTab onClose={onClose} />,
|
||||
content: (
|
||||
<AdvancedTab
|
||||
onClose={onClose}
|
||||
handleContinueAddingAgentClick={handleContinueAddingAgentClick}
|
||||
/>
|
||||
),
|
||||
'data-test-subj': 'fleetServerFlyoutTab-advanced',
|
||||
};
|
||||
|
||||
|
@ -62,7 +75,7 @@ const useFleetServerTabs = (onClose: () => void) => {
|
|||
return { tabs: [quickStartTab, advancedTab], currentTab, setCurrentTab, currentTabContent };
|
||||
};
|
||||
|
||||
const Header: React.FunctionComponent<{
|
||||
export const Header: React.FunctionComponent<{
|
||||
isFlyout?: boolean;
|
||||
currentTab: string;
|
||||
tabs: Array<{ id: string; label: string; content: React.ReactNode }>;
|
||||
|
|
|
@ -19,9 +19,13 @@ import { useLatestFleetServers } from './hooks/use_latest_fleet_servers';
|
|||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
handleContinueAddingAgentClick?: () => void;
|
||||
}
|
||||
|
||||
export const QuickStartTab: React.FunctionComponent<Props> = ({ onClose }) => {
|
||||
export const QuickStartTab: React.FunctionComponent<Props> = ({
|
||||
onClose,
|
||||
handleContinueAddingAgentClick,
|
||||
}) => {
|
||||
const {
|
||||
fleetServerHost,
|
||||
setFleetServerHost,
|
||||
|
@ -62,6 +66,7 @@ export const QuickStartTab: React.FunctionComponent<Props> = ({ onClose }) => {
|
|||
getConfirmFleetServerConnectionStep({
|
||||
hasRecentlyEnrolledFleetServers,
|
||||
disabled: status !== 'success',
|
||||
handleContinueAddingAgentClick,
|
||||
}),
|
||||
];
|
||||
|
||||
|
|
|
@ -18,9 +18,11 @@ import { useFleetStatus, useFlyoutContext } from '../../../hooks';
|
|||
export function getConfirmFleetServerConnectionStep({
|
||||
disabled,
|
||||
hasRecentlyEnrolledFleetServers,
|
||||
handleContinueAddingAgentClick,
|
||||
}: {
|
||||
disabled: boolean;
|
||||
hasRecentlyEnrolledFleetServers: boolean;
|
||||
handleContinueAddingAgentClick?: () => void;
|
||||
}): EuiStepProps {
|
||||
return {
|
||||
title: hasRecentlyEnrolledFleetServers
|
||||
|
@ -34,6 +36,7 @@ export function getConfirmFleetServerConnectionStep({
|
|||
children: !disabled && (
|
||||
<ConfirmFleetServerConnectionStepContent
|
||||
hasRecentlyEnrolledFleetServers={hasRecentlyEnrolledFleetServers}
|
||||
handleContinueAddingAgentClick={handleContinueAddingAgentClick}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
@ -41,7 +44,8 @@ export function getConfirmFleetServerConnectionStep({
|
|||
|
||||
const ConfirmFleetServerConnectionStepContent: React.FunctionComponent<{
|
||||
hasRecentlyEnrolledFleetServers: boolean;
|
||||
}> = ({ hasRecentlyEnrolledFleetServers }) => {
|
||||
handleContinueAddingAgentClick?: () => void;
|
||||
}> = ({ handleContinueAddingAgentClick, hasRecentlyEnrolledFleetServers }) => {
|
||||
const flyoutContext = useFlyoutContext();
|
||||
const fleetStatus = useFleetStatus();
|
||||
|
||||
|
@ -64,7 +68,7 @@ const ConfirmFleetServerConnectionStepContent: React.FunctionComponent<{
|
|||
|
||||
<EuiButton
|
||||
color="primary"
|
||||
onClick={handleContinueClick}
|
||||
onClick={handleContinueAddingAgentClick ?? handleContinueClick}
|
||||
data-test-subj="fleetServerFlyoutContinueEnrollingButton"
|
||||
>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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 { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
import { Error } from '../../../../components';
|
||||
|
||||
import type { EmbeddedIntegrationStepsLayoutProps } from './types';
|
||||
|
||||
export const EmbeddedIntegrationStepsLayout: React.FunctionComponent<
|
||||
EmbeddedIntegrationStepsLayoutProps
|
||||
> = (props) => {
|
||||
const { steps, currentStep, error } = props;
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<Error
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.createPackagePolicy.errorLoadingPackageTitle"
|
||||
defaultMessage="Error loading package information"
|
||||
/>
|
||||
}
|
||||
error={error}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const StepComponent = steps[currentStep].component;
|
||||
|
||||
return <StepComponent {...props} />;
|
||||
};
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* 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, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { splitPkgKey } from '../../../../../../../common/services';
|
||||
|
||||
import {
|
||||
useGetPackageInfoByKeyQuery,
|
||||
useFleetServerHostsForPolicy,
|
||||
useStartServices,
|
||||
} from '../../../../hooks';
|
||||
|
||||
import { useIntegrationsStateContext } from '../../../../../integrations/hooks';
|
||||
|
||||
import type { AgentPolicy } from '../../../../types';
|
||||
import { useGetAgentPolicyOrDefault } from '../multi_page_layout/hooks';
|
||||
import { Loading } from '../../../../components';
|
||||
|
||||
import { onboardingManagedSteps } from './onboarding_steps';
|
||||
|
||||
import { EmbeddedIntegrationStepsLayout } from './embedded_integration_steps_layout';
|
||||
import type { EmbeddedIntegrationFlowProps } from './types';
|
||||
|
||||
export const EmbeddedIntegrationFlow: React.FC<EmbeddedIntegrationFlowProps> = ({
|
||||
prerelease,
|
||||
integrationName: integration,
|
||||
onStepNext,
|
||||
onCancel,
|
||||
handleViewAssets,
|
||||
from,
|
||||
}) => {
|
||||
const { notifications } = useStartServices();
|
||||
|
||||
const { pkgkey: pkgKeyContext } = useIntegrationsStateContext();
|
||||
const pkgkey = pkgKeyContext || '';
|
||||
const { pkgName, pkgVersion } = splitPkgKey(pkgkey);
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const [isManaged, setIsManaged] = useState(true);
|
||||
const [enrolledAgentIds, setEnrolledAgentIds] = useState<string[]>([]);
|
||||
const [selectedAgentPolicies, setSelectedAgentPolicies] = useState<AgentPolicy[]>();
|
||||
const toggleIsManaged = (newIsManaged: boolean) => {
|
||||
setIsManaged(newIsManaged);
|
||||
setCurrentStep(0);
|
||||
};
|
||||
|
||||
const agentPolicyId = useMemo(() => selectedAgentPolicies?.[0]?.id, [selectedAgentPolicies]);
|
||||
const {
|
||||
data: packageInfoData,
|
||||
error: packageInfoError,
|
||||
isLoading: isPackageInfoLoading,
|
||||
} = useGetPackageInfoByKeyQuery(pkgName, pkgVersion, { prerelease, full: true });
|
||||
|
||||
const {
|
||||
agentPolicy,
|
||||
enrollmentAPIKey,
|
||||
error: agentPolicyError,
|
||||
isLoading: isAgentPolicyLoading,
|
||||
} = useGetAgentPolicyOrDefault(agentPolicyId);
|
||||
|
||||
const packageInfo = useMemo(() => packageInfoData?.item, [packageInfoData]);
|
||||
|
||||
const integrationInfo = useMemo(() => {
|
||||
if (!integration) return;
|
||||
return packageInfo?.policy_templates?.find(
|
||||
(policyTemplate) => policyTemplate.name === integration
|
||||
);
|
||||
}, [packageInfo?.policy_templates, integration]);
|
||||
|
||||
const { fleetServerHost, fleetProxy, downloadSource } = useFleetServerHostsForPolicy(agentPolicy);
|
||||
|
||||
const stepsNext = useCallback(
|
||||
(props?: { selectedAgentPolicies?: AgentPolicy[]; toStep?: number }) => {
|
||||
if (currentStep === onboardingManagedSteps.length - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
setCurrentStep(props?.toStep ?? currentStep + 1);
|
||||
onStepNext?.(props?.toStep ?? currentStep + 1);
|
||||
|
||||
// selected agent policy is set after integration is configured
|
||||
if (props?.selectedAgentPolicies) {
|
||||
setSelectedAgentPolicies(props?.selectedAgentPolicies);
|
||||
}
|
||||
},
|
||||
[currentStep, onStepNext]
|
||||
);
|
||||
|
||||
const stepsBack = () => {
|
||||
if (currentStep === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
setCurrentStep(currentStep - 1);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isPackageInfoLoading && packageInfoError) {
|
||||
notifications.toasts.addError(packageInfoError, {
|
||||
title: i18n.translate('xpack.fleet.createPackagePolicy.errorLoadingPackageTitle', {
|
||||
defaultMessage: 'Error loading package information',
|
||||
}),
|
||||
toastMessage: packageInfoError.message,
|
||||
});
|
||||
}
|
||||
}, [isPackageInfoLoading, notifications.toasts, packageInfoError]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isAgentPolicyLoading && agentPolicyError) {
|
||||
notifications.toasts.addError(agentPolicyError, {
|
||||
title: i18n.translate('xpack.fleet.createPackagePolicy.errorLoadingAgentPolicyTitle', {
|
||||
defaultMessage: 'Error loading agent policy information',
|
||||
}),
|
||||
toastMessage: agentPolicyError.message,
|
||||
});
|
||||
}
|
||||
}, [isAgentPolicyLoading, notifications.toasts, agentPolicyError]);
|
||||
|
||||
return !isPackageInfoLoading && packageInfo ? (
|
||||
<EmbeddedIntegrationStepsLayout
|
||||
fleetServerHost={fleetServerHost}
|
||||
fleetProxy={fleetProxy}
|
||||
downloadSource={downloadSource}
|
||||
agentPolicy={selectedAgentPolicies?.[0] ?? agentPolicy}
|
||||
enrollmentAPIKey={enrollmentAPIKey}
|
||||
currentStep={currentStep}
|
||||
steps={onboardingManagedSteps}
|
||||
packageInfo={packageInfo}
|
||||
integrationInfo={integrationInfo}
|
||||
onNext={stepsNext}
|
||||
onBack={stepsBack}
|
||||
isManaged={isManaged}
|
||||
setIsManaged={toggleIsManaged}
|
||||
setEnrolledAgentIds={setEnrolledAgentIds}
|
||||
enrolledAgentIds={enrolledAgentIds}
|
||||
onCancel={onCancel}
|
||||
prerelease={prerelease}
|
||||
handleViewAssets={handleViewAssets}
|
||||
from={from}
|
||||
selectedAgentPolicies={selectedAgentPolicies}
|
||||
/>
|
||||
) : (
|
||||
<Loading />
|
||||
);
|
||||
};
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 { EuiSpacer } from '@elastic/eui';
|
||||
|
||||
import { useCheckPermissions } from '../../../../../hooks';
|
||||
|
||||
import { useFleetServerTabs } from '../../../../../components';
|
||||
import { Header } from '../../../../../components/fleet_server_instructions';
|
||||
import { FleetServerMissingESPrivileges } from '../../../../agents/components';
|
||||
import type { EmbeddedIntegrationStepsLayoutProps } from '../types';
|
||||
|
||||
export const AddFleetServerStepFromOnboardingHub: React.FC<EmbeddedIntegrationStepsLayoutProps> = ({
|
||||
onCancel,
|
||||
onNext,
|
||||
}) => {
|
||||
const { tabs, currentTab, setCurrentTab, currentTabContent } = useFleetServerTabs(
|
||||
onCancel,
|
||||
onNext
|
||||
);
|
||||
|
||||
const { permissionsError, isPermissionsLoading } = useCheckPermissions();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header tabs={tabs} currentTab={currentTab} onTabClick={(id) => setCurrentTab(id)} />
|
||||
{!isPermissionsLoading && permissionsError === 'MISSING_FLEET_SERVER_SETUP_PRIVILEGES' ? (
|
||||
<FleetServerMissingESPrivileges />
|
||||
) : (
|
||||
<>
|
||||
<EuiSpacer size="xl" />
|
||||
{currentTabContent}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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 { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import type {
|
||||
FlyoutMode,
|
||||
SelectionType,
|
||||
} from '../../../../../../../components/agent_enrollment_flyout/types';
|
||||
import { useAgentEnrollmentFlyoutData, useFleetServerHostsForPolicy } from '../../../../../hooks';
|
||||
import {
|
||||
useAgentPolicyWithPackagePolicies,
|
||||
useCloudSecurityIntegration,
|
||||
useIsK8sPolicy,
|
||||
} from '../../../../../../../components/agent_enrollment_flyout/hooks';
|
||||
import { usePollingAgentCount } from '../../../../../../../components/agent_enrollment_flyout/confirm_agent_enrollment';
|
||||
import type { PackagePolicy } from '../../../../../types';
|
||||
import { FLEET_SERVER_PACKAGE } from '../../../../../constants';
|
||||
import { Instructions, Loading } from '../../../../../components';
|
||||
import type { EmbeddedIntegrationStepsLayoutProps } from '../types';
|
||||
|
||||
export const AgentEnrollmentFromOnboardingHub = ({
|
||||
agentPolicy,
|
||||
selectedAgentPolicies,
|
||||
isManaged,
|
||||
from,
|
||||
onNext,
|
||||
setEnrolledAgentIds,
|
||||
steps,
|
||||
}: EmbeddedIntegrationStepsLayoutProps) => {
|
||||
const [selectedPolicyId, setSelectedPolicyId] = useState(agentPolicy?.id);
|
||||
const [isFleetServerPolicySelected, setIsFleetServerPolicySelected] = useState<boolean>(false);
|
||||
const [selectedApiKeyId, setSelectedAPIKeyId] = useState<string | undefined>();
|
||||
const [mode, setMode] = useState<FlyoutMode>(isManaged ? 'managed' : 'standalone');
|
||||
const [selectionType, setSelectionType] = useState<SelectionType>();
|
||||
|
||||
const {
|
||||
agentPolicies: fetchedAgentPolicies,
|
||||
isLoadingInitialAgentPolicies,
|
||||
isLoadingAgentPolicies,
|
||||
refreshAgentPolicies,
|
||||
} = useAgentEnrollmentFlyoutData();
|
||||
|
||||
// Have the option to pass agentPolicies from props, otherwise use the fetched ones
|
||||
const agentPolicies = selectedAgentPolicies ? selectedAgentPolicies : fetchedAgentPolicies;
|
||||
|
||||
const { agentPolicyWithPackagePolicies } = useAgentPolicyWithPackagePolicies(selectedPolicyId);
|
||||
|
||||
const { fleetServerHost, fleetProxy, downloadSource, downloadSourceProxy } =
|
||||
useFleetServerHostsForPolicy(agentPolicyWithPackagePolicies);
|
||||
|
||||
const selectedPolicy = agentPolicyWithPackagePolicies
|
||||
? agentPolicyWithPackagePolicies
|
||||
: undefined;
|
||||
|
||||
const { enrolledAgentIds } = usePollingAgentCount(selectedPolicyId || '', {
|
||||
noLowerTimeLimit: true,
|
||||
pollImmediately: true,
|
||||
});
|
||||
|
||||
const onClickViewIncomingData = useCallback(() => {
|
||||
setEnrolledAgentIds(enrolledAgentIds);
|
||||
onNext({ toStep: steps.length - 1 });
|
||||
}, [enrolledAgentIds, onNext, setEnrolledAgentIds, steps.length]);
|
||||
|
||||
const handleAddFleetServer = useCallback(() => {
|
||||
setEnrolledAgentIds(enrolledAgentIds);
|
||||
onNext();
|
||||
}, [enrolledAgentIds, onNext, setEnrolledAgentIds]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedPolicy) {
|
||||
if (
|
||||
(selectedPolicy.package_policies as PackagePolicy[]).some(
|
||||
(packagePolicy) => packagePolicy.package?.name === FLEET_SERVER_PACKAGE
|
||||
)
|
||||
) {
|
||||
setIsFleetServerPolicySelected(true);
|
||||
} else {
|
||||
setIsFleetServerPolicySelected(false);
|
||||
}
|
||||
}
|
||||
}, [selectedPolicy, isFleetServerPolicySelected]);
|
||||
|
||||
const { isK8s } = useIsK8sPolicy(selectedPolicy ?? undefined);
|
||||
const { cloudSecurityIntegration } = useCloudSecurityIntegration(selectedPolicy ?? undefined);
|
||||
|
||||
return isLoadingInitialAgentPolicies || isLoadingAgentPolicies ? (
|
||||
<Loading size="l" />
|
||||
) : (
|
||||
<Instructions
|
||||
fleetServerHost={fleetServerHost}
|
||||
fleetProxy={fleetProxy}
|
||||
downloadSource={downloadSource}
|
||||
downloadSourceProxy={downloadSourceProxy}
|
||||
setSelectedPolicyId={setSelectedPolicyId}
|
||||
agentPolicy={agentPolicy}
|
||||
selectedPolicy={selectedPolicy}
|
||||
agentPolicies={agentPolicies}
|
||||
isFleetServerPolicySelected={isFleetServerPolicySelected}
|
||||
isK8s={isK8s}
|
||||
cloudSecurityIntegration={cloudSecurityIntegration}
|
||||
refreshAgentPolicies={refreshAgentPolicies}
|
||||
isLoadingAgentPolicies={isLoadingAgentPolicies}
|
||||
mode={mode}
|
||||
setMode={setMode}
|
||||
selectionType={selectionType}
|
||||
setSelectionType={setSelectionType}
|
||||
selectedApiKeyId={selectedApiKeyId}
|
||||
setSelectedAPIKeyId={setSelectedAPIKeyId}
|
||||
onClickViewIncomingData={onClickViewIncomingData}
|
||||
from={from}
|
||||
handleAddFleetServer={handleAddFleetServer}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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 {
|
||||
useFleetServerStandalone,
|
||||
useFleetStatus,
|
||||
useGetEnrollmentSettings,
|
||||
} from '../../../../../hooks';
|
||||
|
||||
import { shouldShowFleetServerEnrollment } from '../../../../../components';
|
||||
import type { EmbeddedIntegrationStepsLayoutProps } from '../types';
|
||||
import { useAgentPolicyWithPackagePolicies } from '../../../../../../../components/agent_enrollment_flyout/hooks';
|
||||
import { FleetServerRequirementPage } from '../../../../agents/agent_requirements_page';
|
||||
import type { PackagePolicy } from '../../../../../types';
|
||||
import { FLEET_SERVER_PACKAGE } from '../../../../../constants';
|
||||
|
||||
export const CheckFleetServerRequiredFromOnboardingHub: React.FC<
|
||||
EmbeddedIntegrationStepsLayoutProps
|
||||
> = ({ agentPolicy, isManaged, setIsManaged, onNext, currentStep }) => {
|
||||
const [isFleetServerPolicySelected, setIsFleetServerPolicySelected] = useState<boolean>(false);
|
||||
|
||||
const fleetStatus = useFleetStatus();
|
||||
const { isFleetServerStandalone } = useFleetServerStandalone();
|
||||
const { data: enrollmentSettings } = useGetEnrollmentSettings();
|
||||
|
||||
const showFleetServerEnrollment = shouldShowFleetServerEnrollment({
|
||||
isFleetServerStandalone,
|
||||
isFleetServerPolicySelected,
|
||||
enrollmentSettings,
|
||||
fleetStatusMissingRequirements: fleetStatus.missingRequirements,
|
||||
});
|
||||
|
||||
const { agentPolicyWithPackagePolicies } = useAgentPolicyWithPackagePolicies(agentPolicy?.id);
|
||||
|
||||
const selectedPolicy = agentPolicyWithPackagePolicies
|
||||
? agentPolicyWithPackagePolicies
|
||||
: undefined;
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedPolicy) {
|
||||
if (
|
||||
(selectedPolicy.package_policies as PackagePolicy[]).some(
|
||||
(packagePolicy) => packagePolicy.package?.name === FLEET_SERVER_PACKAGE
|
||||
)
|
||||
) {
|
||||
setIsFleetServerPolicySelected(true);
|
||||
} else {
|
||||
setIsFleetServerPolicySelected(false);
|
||||
}
|
||||
}
|
||||
}, [selectedPolicy, isFleetServerPolicySelected]);
|
||||
|
||||
useEffect(() => {
|
||||
// If the user is standalone, skip the Fleet Server enrollment step
|
||||
// If the user is managed and the Fleet Server enrollment is done, skip the Fleet Server enrollment step
|
||||
if ((!isManaged && showFleetServerEnrollment) || (isManaged && !showFleetServerEnrollment)) {
|
||||
onNext({ toStep: currentStep + 2 });
|
||||
}
|
||||
}, [currentStep, isManaged, onNext, showFleetServerEnrollment]);
|
||||
|
||||
if (isManaged && showFleetServerEnrollment) {
|
||||
return (
|
||||
<FleetServerRequirementPage
|
||||
showStandaloneTab={() => {
|
||||
setIsManaged(false);
|
||||
onNext({ toStep: currentStep + 2 });
|
||||
}}
|
||||
handleAddFleetServer={() => {
|
||||
onNext();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* 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, { useCallback, useState } from 'react';
|
||||
|
||||
import { EuiButton, EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
import { DASHBOARD_APP_ID, createDashboardEditUrl } from '@kbn/dashboard-plugin/public';
|
||||
|
||||
import { useIntraAppState, useStartServices } from '../../../../../hooks';
|
||||
|
||||
import {
|
||||
ConfirmIncomingDataWithPreview,
|
||||
ConfirmIncomingDataStandalone,
|
||||
} from '../../multi_page_layout/components';
|
||||
import type { EmbeddedIntegrationStepsLayoutProps } from '../types';
|
||||
import { FLEET_KUBERNETES_PACKAGE } from '../../../../../../../../common';
|
||||
import type { AgentPolicyDetailsDeployAgentAction } from '../../../../../types';
|
||||
|
||||
export const FinalBottomBar: React.FC<{
|
||||
pkgkey: string;
|
||||
handleAddAnotherIntegration: () => void;
|
||||
handleViewAssets: () => void;
|
||||
viewKubernetesMetricsDashboards: () => void;
|
||||
}> = ({
|
||||
pkgkey,
|
||||
handleAddAnotherIntegration,
|
||||
handleViewAssets,
|
||||
viewKubernetesMetricsDashboards,
|
||||
}) => {
|
||||
const isK8s = pkgkey.includes(FLEET_KUBERNETES_PACKAGE);
|
||||
return (
|
||||
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty color="text" size="s" onClick={handleAddAnotherIntegration}>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.createPackagePolicyBottomBar.addAnotherIntegration"
|
||||
defaultMessage="Add another integration"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexItem>
|
||||
{!isK8s && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton color="success" fill size="m" onClick={handleViewAssets}>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.confirmIncomingData.viewDataAssetsButtonText'"
|
||||
defaultMessage="View assets"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{isK8s && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
color="success"
|
||||
fill
|
||||
size="m"
|
||||
// href={getAbsolutePath(
|
||||
// '/app/dashboards#/view/kubernetes-f4dc26db-1b53-4ea2-a78b-1bfab8ea267c'
|
||||
// )}
|
||||
onClick={viewKubernetesMetricsDashboards}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.confirmIncomingData. '"
|
||||
defaultMessage="View Kubernetes metrics dashboards"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
export const ConfirmDataStepFromOnboardingHub: React.FC<EmbeddedIntegrationStepsLayoutProps> = (
|
||||
props
|
||||
) => {
|
||||
const { enrolledAgentIds, packageInfo, isManaged, onCancel, handleViewAssets } = props;
|
||||
const core = useStartServices();
|
||||
|
||||
const [agentDataConfirmed, setAgentDataConfirmed] = useState(false);
|
||||
const {
|
||||
docLinks: {
|
||||
links: {
|
||||
fleet: { troubleshooting: troubleshootLink },
|
||||
},
|
||||
},
|
||||
application: { navigateToApp },
|
||||
} = core;
|
||||
const routeState = useIntraAppState<AgentPolicyDetailsDeployAgentAction>();
|
||||
|
||||
const handleAddAnotherIntegration = () => {
|
||||
// Close the modal
|
||||
onCancel();
|
||||
};
|
||||
|
||||
const viewKubernetesMetricsDashboards = useCallback(() => {
|
||||
// Open the Kubernetes metrics dashboards in security solution
|
||||
// href={getAbsolutePath(
|
||||
// '/app/dashboards#/view/kubernetes-f4dc26db-1b53-4ea2-a78b-1bfab8ea267c'
|
||||
// )}
|
||||
if (routeState && routeState.onDoneNavigateTo) {
|
||||
const [appId] = routeState.onDoneNavigateTo;
|
||||
return () => {
|
||||
navigateToApp(appId === 'securitySolutionUI' ? appId : DASHBOARD_APP_ID, {
|
||||
path: createDashboardEditUrl(`kubernetes-f4dc26db-1b53-4ea2-a78b-1bfab8ea267c`),
|
||||
});
|
||||
};
|
||||
}
|
||||
}, [navigateToApp, routeState]);
|
||||
|
||||
if (!isManaged) {
|
||||
return (
|
||||
<ConfirmIncomingDataStandalone troubleshootLink={troubleshootLink}>
|
||||
<FinalBottomBar
|
||||
pkgkey={`${packageInfo.name}-${packageInfo.version}`}
|
||||
handleAddAnotherIntegration={handleAddAnotherIntegration}
|
||||
handleViewAssets={handleViewAssets}
|
||||
viewKubernetesMetricsDashboards={viewKubernetesMetricsDashboards}
|
||||
/>
|
||||
</ConfirmIncomingDataStandalone>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ConfirmIncomingDataWithPreview
|
||||
agentIds={enrolledAgentIds}
|
||||
packageInfo={packageInfo}
|
||||
agentDataConfirmed={agentDataConfirmed}
|
||||
setAgentDataConfirmed={setAgentDataConfirmed}
|
||||
troubleshootLink={troubleshootLink}
|
||||
>
|
||||
{!!agentDataConfirmed && (
|
||||
<FinalBottomBar
|
||||
pkgkey={`${packageInfo.name}-${packageInfo.version}`}
|
||||
handleAddAnotherIntegration={handleAddAnotherIntegration}
|
||||
handleViewAssets={handleViewAssets}
|
||||
viewKubernetesMetricsDashboards={viewKubernetesMetricsDashboards}
|
||||
/>
|
||||
)}
|
||||
</ConfirmIncomingDataWithPreview>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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 { EmbeddedIntegrationStepsLayoutProps } from '../types';
|
||||
import { CreatePackagePolicySinglePage } from '../../single_page_layout';
|
||||
|
||||
export const CreatePackagePolicyFromOnboardingHub: React.FC<EmbeddedIntegrationStepsLayoutProps> = (
|
||||
props
|
||||
) => {
|
||||
return (
|
||||
<CreatePackagePolicySinglePage
|
||||
{...props}
|
||||
onAddAgent={props.onNext}
|
||||
from="onboarding-hub"
|
||||
withHeader={false}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
|
||||
import { CreatePackagePolicyFromOnboardingHub } from './create_package_policy';
|
||||
import { AgentEnrollmentFromOnboardingHub } from './agent_enrollment';
|
||||
import { AddFleetServerStepFromOnboardingHub } from './add_fleet_server';
|
||||
import { ConfirmDataStepFromOnboardingHub } from './confirm_incoming_data';
|
||||
import { CheckFleetServerRequiredFromOnboardingHub } from './check_fleet_server_required';
|
||||
|
||||
const addIntegrationFromOnboardingHub = {
|
||||
title: i18n.translate('xpack.fleet.createFirstPackagePolicy.addIntegrationStepTitle', {
|
||||
defaultMessage: 'Add the integration',
|
||||
}),
|
||||
component: CreatePackagePolicyFromOnboardingHub,
|
||||
};
|
||||
|
||||
const agentEnrollmentStepFromOnboardingHub = {
|
||||
title: i18n.translate('xpack.fleet.createFirstPackagePolicy.agentEnrollmentStepTitle', {
|
||||
defaultMessage: 'Add agent',
|
||||
}),
|
||||
component: AgentEnrollmentFromOnboardingHub,
|
||||
};
|
||||
|
||||
const addFleetServerStepFromOnboardingHub = {
|
||||
title: i18n.translate('xpack.fleet.createFirstPackagePolicy.addFleetServerStepTitle', {
|
||||
defaultMessage: 'Add Fleet Server',
|
||||
}),
|
||||
component: AddFleetServerStepFromOnboardingHub,
|
||||
};
|
||||
|
||||
const confirmDataStepFromOnboardingHub = {
|
||||
title: i18n.translate('xpack.fleet.createFirstPackagePolicy.confirmDataStepTitle', {
|
||||
defaultMessage: 'Confirm incoming data',
|
||||
}),
|
||||
component: ConfirmDataStepFromOnboardingHub,
|
||||
};
|
||||
|
||||
const checkFleetServerRequirementsStep = {
|
||||
title: i18n.translate(
|
||||
'xpack.fleet.createFirstPackagePolicy.checkFleetServerRequirementsStepTitle',
|
||||
{
|
||||
defaultMessage: 'Check Fleet Server requirements',
|
||||
}
|
||||
),
|
||||
component: CheckFleetServerRequiredFromOnboardingHub,
|
||||
};
|
||||
|
||||
export const onboardingManagedSteps = [
|
||||
addIntegrationFromOnboardingHub,
|
||||
checkFleetServerRequirementsStep,
|
||||
addFleetServerStepFromOnboardingHub,
|
||||
agentEnrollmentStepFromOnboardingHub,
|
||||
confirmDataStepFromOnboardingHub,
|
||||
];
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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 {
|
||||
FleetProxy,
|
||||
DownloadSource,
|
||||
AgentPolicy,
|
||||
EnrollmentAPIKey,
|
||||
PackageInfo,
|
||||
RegistryPolicyTemplate,
|
||||
} from '../../../../types';
|
||||
import type { EditPackagePolicyFrom } from '../types';
|
||||
|
||||
export interface EmbeddedIntegrationStepsLayoutProps {
|
||||
fleetServerHost: string;
|
||||
fleetProxy?: FleetProxy;
|
||||
downloadSource?: DownloadSource;
|
||||
agentPolicy?: AgentPolicy;
|
||||
error?: Error;
|
||||
enrollmentAPIKey?: EnrollmentAPIKey;
|
||||
packageInfo: PackageInfo;
|
||||
integrationInfo?: RegistryPolicyTemplate;
|
||||
cancelClickHandler?: React.ReactEventHandler;
|
||||
onBack: React.ReactEventHandler;
|
||||
steps: EmbeddedFlowStep[];
|
||||
currentStep: number;
|
||||
onNext: (params?: { selectedAgentPolicies?: AgentPolicy[]; toStep?: number }) => void;
|
||||
setIsManaged: (isManaged: boolean) => void;
|
||||
isManaged: boolean;
|
||||
setEnrolledAgentIds: (agentIds: string[]) => void;
|
||||
enrolledAgentIds: string[];
|
||||
onCancel: () => void;
|
||||
prerelease: boolean;
|
||||
handleViewAssets: () => void;
|
||||
from: EditPackagePolicyFrom;
|
||||
selectedAgentPolicies?: AgentPolicy[];
|
||||
}
|
||||
|
||||
export interface EmbeddedIntegrationFlowProps {
|
||||
from: EditPackagePolicyFrom;
|
||||
queryParamsPolicyId?: string;
|
||||
integrationName?: string;
|
||||
prerelease: boolean;
|
||||
onCancel: () => void;
|
||||
onStepNext?: (step: number) => void;
|
||||
handleViewAssets: () => void;
|
||||
}
|
||||
|
||||
export interface EmbeddedFlowStep {
|
||||
title: string;
|
||||
component: React.FC<EmbeddedIntegrationStepsLayoutProps>;
|
||||
}
|
|
@ -8,27 +8,30 @@ import React, { useEffect } from 'react';
|
|||
import { useMemo } from 'react';
|
||||
import { useLocation, useRouteMatch } from 'react-router-dom';
|
||||
|
||||
import { noop } from 'lodash/fp';
|
||||
|
||||
import { useGetSettings } from '../../../hooks';
|
||||
|
||||
import type { AddToPolicyParams, EditPackagePolicyFrom } from './types';
|
||||
|
||||
import { CreatePackagePolicySinglePage } from './single_page_layout';
|
||||
import { CreatePackagePolicyMultiPage } from './multi_page_layout';
|
||||
import { EmbeddedIntegrationFlow } from './embedded_integration_flow';
|
||||
|
||||
export const CreatePackagePolicyPage: React.FC<{
|
||||
useMultiPageLayoutProp?: boolean;
|
||||
originFrom?: EditPackagePolicyFrom;
|
||||
propPolicyId?: string;
|
||||
integrationName?: string;
|
||||
setIntegrationStep?: (step: number) => void;
|
||||
onCanceled?: () => void;
|
||||
onStepNext?: (step: number) => void;
|
||||
onCancel?: () => void;
|
||||
handleViewAssets?: () => void;
|
||||
}> = ({
|
||||
useMultiPageLayoutProp,
|
||||
originFrom,
|
||||
propPolicyId,
|
||||
integrationName,
|
||||
setIntegrationStep,
|
||||
onCanceled,
|
||||
onStepNext,
|
||||
onCancel = noop,
|
||||
handleViewAssets = noop,
|
||||
}) => {
|
||||
const { search } = useLocation();
|
||||
const { params } = useRouteMatch<AddToPolicyParams>();
|
||||
|
@ -69,13 +72,21 @@ export const CreatePackagePolicyPage: React.FC<{
|
|||
const pageParams = {
|
||||
from,
|
||||
queryParamsPolicyId,
|
||||
propPolicyId,
|
||||
integrationName,
|
||||
prerelease,
|
||||
setIntegrationStep,
|
||||
onCanceled,
|
||||
};
|
||||
|
||||
if (from === 'onboarding-hub') {
|
||||
return (
|
||||
<EmbeddedIntegrationFlow
|
||||
{...pageParams}
|
||||
onCancel={onCancel}
|
||||
handleViewAssets={handleViewAssets}
|
||||
onStepNext={onStepNext}
|
||||
integrationName={integrationName}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (useMultiPageLayout) {
|
||||
return <CreatePackagePolicyMultiPage {...pageParams} />;
|
||||
}
|
||||
|
|
|
@ -123,60 +123,68 @@ export const AgentStandaloneBottomBar: React.FC<{
|
|||
);
|
||||
};
|
||||
|
||||
export const CreatePackagePolicyFinalBottomBar: React.FC<{
|
||||
const FinalBottomBar: React.FC<{
|
||||
pkgkey: string;
|
||||
}> = ({ pkgkey }) => {
|
||||
const isK8s = pkgkey.includes(FLEET_KUBERNETES_PACKAGE);
|
||||
const { getHref } = useLink();
|
||||
const { getAbsolutePath } = useLink();
|
||||
return (
|
||||
<CenteredRoundedBottomBar>
|
||||
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
|
||||
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty color="text" size="s" href={getHref('integrations_all')}>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.createPackagePolicyBottomBar.addAnotherIntegration"
|
||||
defaultMessage="Add another integration"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
<EuiButtonEmpty color="text" size="s" href={getHref('integrations_all')}>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.createPackagePolicyBottomBar.addAnotherIntegration"
|
||||
defaultMessage="Add another integration"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
{!isK8s && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
color="success"
|
||||
fill
|
||||
size="m"
|
||||
href={getHref('integration_details_assets', {
|
||||
pkgkey,
|
||||
})}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.confirmIncomingData.viewDataAssetsButtonText'"
|
||||
defaultMessage="View assets"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{isK8s && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
color="success"
|
||||
fill
|
||||
size="m"
|
||||
href={getAbsolutePath(
|
||||
'/app/dashboards#/view/kubernetes-f4dc26db-1b53-4ea2-a78b-1bfab8ea267c'
|
||||
)}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.confirmIncomingData. '"
|
||||
defaultMessage="View Kubernetes metrics dashboards"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
{!isK8s && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
color="success"
|
||||
fill
|
||||
size="m"
|
||||
href={getHref('integration_details_assets', {
|
||||
pkgkey,
|
||||
})}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.confirmIncomingData.viewDataAssetsButtonText'"
|
||||
defaultMessage="View assets"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{isK8s && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
color="success"
|
||||
fill
|
||||
size="m"
|
||||
href={getAbsolutePath(
|
||||
'/app/dashboards#/view/kubernetes-f4dc26db-1b53-4ea2-a78b-1bfab8ea267c'
|
||||
)}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.confirmIncomingData. '"
|
||||
defaultMessage="View Kubernetes metrics dashboards"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
export const CreatePackagePolicyFinalBottomBar: React.FC<{
|
||||
pkgkey: string;
|
||||
}> = ({ pkgkey }) => {
|
||||
return (
|
||||
<CenteredRoundedBottomBar>
|
||||
<FinalBottomBar pkgkey={pkgkey} />
|
||||
</CenteredRoundedBottomBar>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import React from 'react';
|
||||
import {
|
||||
EuiCallOut,
|
||||
|
@ -124,12 +125,13 @@ const AgentDataPreview: React.FC<{ dataPreview: SearchHit[] }> = ({ dataPreview
|
|||
);
|
||||
};
|
||||
|
||||
export const ConfirmIncomingDataWithPreview: React.FunctionComponent<Props> = ({
|
||||
export const ConfirmIncomingDataWithPreview: React.FunctionComponent<PropsWithChildren<Props>> = ({
|
||||
agentIds,
|
||||
packageInfo,
|
||||
agentDataConfirmed,
|
||||
setAgentDataConfirmed,
|
||||
troubleshootLink,
|
||||
children,
|
||||
}) => {
|
||||
const { incomingData, dataPreview, isLoading, hasReachedTimeout } = usePollingIncomingData({
|
||||
agentIds,
|
||||
|
@ -218,6 +220,7 @@ export const ConfirmIncomingDataWithPreview: React.FunctionComponent<Props> = ({
|
|||
</EuiText>
|
||||
<EuiSpacer size="m" />
|
||||
<AgentDataPreview dataPreview={dataPreview} />
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import React from 'react';
|
||||
import { EuiCallOut, EuiText, EuiLink } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
@ -13,8 +14,9 @@ interface Props {
|
|||
troubleshootLink: string;
|
||||
}
|
||||
|
||||
export const ConfirmIncomingDataStandalone: React.FunctionComponent<Props> = ({
|
||||
export const ConfirmIncomingDataStandalone: React.FunctionComponent<PropsWithChildren<Props>> = ({
|
||||
troubleshootLink,
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
|
@ -45,6 +47,7 @@ export const ConfirmIncomingDataStandalone: React.FunctionComponent<Props> = ({
|
|||
/>
|
||||
</EuiCallOut>
|
||||
</EuiText>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -57,6 +57,7 @@ export const MultiPageStepsLayout: React.FunctionComponent<MultiPageStepLayoutPr
|
|||
);
|
||||
|
||||
const maxWidth = 866;
|
||||
|
||||
return (
|
||||
<WithHeaderLayout
|
||||
topContent={topContent}
|
||||
|
|
|
@ -17,6 +17,16 @@ import {
|
|||
NotObscuredByBottomBar,
|
||||
} from '..';
|
||||
|
||||
const BottomBar: React.FC<{
|
||||
packageInfoName: string;
|
||||
packageInfoVersion: string;
|
||||
}> = ({ packageInfoName, packageInfoVersion }) => (
|
||||
<>
|
||||
<NotObscuredByBottomBar />
|
||||
<CreatePackagePolicyFinalBottomBar pkgkey={`${packageInfoName}-${packageInfoVersion}`} />
|
||||
</>
|
||||
);
|
||||
|
||||
export const ConfirmDataPageStep: React.FC<MultiPageStepLayoutProps> = (props) => {
|
||||
const { enrolledAgentIds, packageInfo, isManaged } = props;
|
||||
const core = useStartServices();
|
||||
|
@ -25,18 +35,11 @@ export const ConfirmDataPageStep: React.FC<MultiPageStepLayoutProps> = (props) =
|
|||
const { docLinks } = core;
|
||||
const troubleshootLink = docLinks.links.fleet.troubleshooting;
|
||||
|
||||
const bottomBar = (
|
||||
<>
|
||||
<NotObscuredByBottomBar />
|
||||
<CreatePackagePolicyFinalBottomBar pkgkey={`${packageInfo.name}-${packageInfo.version}`} />
|
||||
</>
|
||||
);
|
||||
|
||||
if (!isManaged) {
|
||||
return (
|
||||
<>
|
||||
<ConfirmIncomingDataStandalone troubleshootLink={troubleshootLink} />
|
||||
{bottomBar}
|
||||
<BottomBar packageInfoName={packageInfo.name} packageInfoVersion={packageInfo.version} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -51,7 +54,9 @@ export const ConfirmDataPageStep: React.FC<MultiPageStepLayoutProps> = (props) =
|
|||
troubleshootLink={troubleshootLink}
|
||||
/>
|
||||
|
||||
{!!agentDataConfirmed && bottomBar}
|
||||
{!!agentDataConfirmed && (
|
||||
<BottomBar packageInfoName={packageInfo.name} packageInfoVersion={packageInfo.version} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -5,9 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useEffect, useState, useMemo, useRef } from 'react';
|
||||
import { useEffect, useState, useMemo } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { generateNewAgentPolicyWithDefaults } from '../../../../../../../../common/services/generate_new_agent_policy';
|
||||
|
||||
|
|
|
@ -18,12 +18,6 @@ import {
|
|||
|
||||
import type { AddToPolicyParams, CreatePackagePolicyParams } from '../types';
|
||||
|
||||
import { useIntegrationsStateContext } from '../../../../../integrations/hooks';
|
||||
|
||||
import { CreatePackagePolicySinglePage } from '../single_page_layout';
|
||||
|
||||
import type { AgentPolicy } from '../../../../types';
|
||||
|
||||
import { useGetAgentPolicyOrDefault } from './hooks';
|
||||
|
||||
import {
|
||||
|
@ -48,13 +42,6 @@ const addIntegrationStep = {
|
|||
component: AddIntegrationPageStep,
|
||||
};
|
||||
|
||||
const addIntegrationSingleLayoutStep = {
|
||||
title: i18n.translate('xpack.fleet.createFirstPackagePolicy.addIntegrationStepTitle', {
|
||||
defaultMessage: 'Add the integration',
|
||||
}),
|
||||
component: CreatePackagePolicySinglePage,
|
||||
};
|
||||
|
||||
const confirmDataStep = {
|
||||
title: i18n.translate('xpack.fleet.createFirstPackagePolicy.confirmDataStepTitle', {
|
||||
defaultMessage: 'Confirm incoming data',
|
||||
|
@ -66,35 +53,25 @@ const fleetManagedSteps = [installAgentStep, addIntegrationStep, confirmDataStep
|
|||
|
||||
const standaloneSteps = [addIntegrationStep, installAgentStep, confirmDataStep];
|
||||
|
||||
const onboardingSteps = [addIntegrationSingleLayoutStep, installAgentStep, confirmDataStep];
|
||||
|
||||
export const CreatePackagePolicyMultiPage: CreatePackagePolicyParams = ({
|
||||
export const CreatePackagePolicyMultiPage: React.FC<CreatePackagePolicyParams> = ({
|
||||
queryParamsPolicyId,
|
||||
prerelease,
|
||||
from,
|
||||
integrationName,
|
||||
setIntegrationStep,
|
||||
onCanceled,
|
||||
}) => {
|
||||
const { params } = useRouteMatch<AddToPolicyParams>();
|
||||
// fixme
|
||||
const { pkgkey: pkgkeyParam, policyId, integration: integrationParam } = params;
|
||||
const { pkgkey: pkgKeyContext } = useIntegrationsStateContext();
|
||||
const pkgkey = pkgkeyParam || pkgKeyContext;
|
||||
const { pkgkey, policyId, integration } = params;
|
||||
const { pkgName, pkgVersion } = splitPkgKey(pkgkey);
|
||||
const [onSplash, setOnSplash] = useState(from !== 'onboarding-integration');
|
||||
const [onSplash, setOnSplash] = useState(true);
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const [isManaged, setIsManaged] = useState(true);
|
||||
const { getHref } = useLink();
|
||||
const [enrolledAgentIds, setEnrolledAgentIds] = useState<string[]>([]);
|
||||
const [selectedAgentPolicies, setSelectedAgentPolicies] = useState<AgentPolicy[]>();
|
||||
|
||||
const toggleIsManaged = (newIsManaged: boolean) => {
|
||||
setIsManaged(newIsManaged);
|
||||
setCurrentStep(0);
|
||||
};
|
||||
|
||||
const integration = integrationName || integrationParam;
|
||||
const agentPolicyId = selectedAgentPolicies?.[0]?.id || policyId || queryParamsPolicyId;
|
||||
const agentPolicyId = policyId || queryParamsPolicyId;
|
||||
const {
|
||||
data: packageInfoData,
|
||||
error: packageInfoError,
|
||||
|
@ -131,6 +108,8 @@ export const CreatePackagePolicyMultiPage: CreatePackagePolicyParams = ({
|
|||
...(agentPolicyId ? { agentPolicyId } : {}),
|
||||
});
|
||||
|
||||
const steps = isManaged ? fleetManagedSteps : standaloneSteps;
|
||||
|
||||
if (onSplash || !packageInfo) {
|
||||
return (
|
||||
<AddFirstIntegrationSplashScreen
|
||||
|
@ -144,23 +123,12 @@ export const CreatePackagePolicyMultiPage: CreatePackagePolicyParams = ({
|
|||
);
|
||||
}
|
||||
|
||||
const steps =
|
||||
from === 'onboarding-integration'
|
||||
? onboardingSteps
|
||||
: isManaged
|
||||
? fleetManagedSteps
|
||||
: standaloneSteps;
|
||||
|
||||
const stepsNext = (props?: { selectedAgentPolicies: AgentPolicy[] }) => {
|
||||
const stepsNext = () => {
|
||||
if (currentStep === steps.length - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
setCurrentStep(currentStep + 1);
|
||||
setIntegrationStep(currentStep + 1);
|
||||
if (props?.selectedAgentPolicies) {
|
||||
setSelectedAgentPolicies(props?.selectedAgentPolicies);
|
||||
}
|
||||
};
|
||||
|
||||
const stepsBack = () => {
|
||||
|
@ -189,7 +157,6 @@ export const CreatePackagePolicyMultiPage: CreatePackagePolicyParams = ({
|
|||
setIsManaged={toggleIsManaged}
|
||||
setEnrolledAgentIds={setEnrolledAgentIds}
|
||||
enrolledAgentIds={enrolledAgentIds}
|
||||
onCanceled={onCanceled}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -48,6 +48,7 @@ export const CreatePackagePolicySinglePageLayout: React.FunctionComponent<{
|
|||
onClick: React.ReactEventHandler;
|
||||
}>;
|
||||
children: React.ReactNode;
|
||||
withHeader?: boolean;
|
||||
}> = memo(
|
||||
({
|
||||
from,
|
||||
|
@ -59,6 +60,7 @@ export const CreatePackagePolicySinglePageLayout: React.FunctionComponent<{
|
|||
children,
|
||||
'data-test-subj': dataTestSubj,
|
||||
tabs = [],
|
||||
withHeader = true,
|
||||
}) => {
|
||||
const isAdd = useMemo(() => ['package', 'policy'].includes(from), [from]);
|
||||
const isEdit = useMemo(() => ['edit', 'package-edit'].includes(from), [from]);
|
||||
|
@ -252,7 +254,8 @@ export const CreatePackagePolicySinglePageLayout: React.FunctionComponent<{
|
|||
) : undefined;
|
||||
|
||||
const maxWidth = 800;
|
||||
return (
|
||||
|
||||
return withHeader ? (
|
||||
<WithHeaderLayout
|
||||
restrictHeaderWidth={maxWidth}
|
||||
restrictWidth={maxWidth}
|
||||
|
@ -264,6 +267,8 @@ export const CreatePackagePolicySinglePageLayout: React.FunctionComponent<{
|
|||
>
|
||||
{children}
|
||||
</WithHeaderLayout>
|
||||
) : (
|
||||
children
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -133,6 +133,17 @@ const DEFAULT_PACKAGE_POLICY = {
|
|||
inputs: [],
|
||||
};
|
||||
|
||||
export interface UseOnSubmitProps {
|
||||
agentCount: number;
|
||||
selectedPolicyTab: SelectedPolicyTab;
|
||||
newAgentPolicy: NewAgentPolicy;
|
||||
withSysMonitoring: boolean;
|
||||
queryParamsPolicyId: string | undefined;
|
||||
packageInfo?: PackageInfo;
|
||||
integrationToEnable?: string;
|
||||
hasFleetAddAgentsPrivileges: boolean;
|
||||
}
|
||||
|
||||
export function useOnSubmit({
|
||||
agentCount,
|
||||
selectedPolicyTab,
|
||||
|
@ -142,16 +153,7 @@ export function useOnSubmit({
|
|||
packageInfo,
|
||||
integrationToEnable,
|
||||
hasFleetAddAgentsPrivileges,
|
||||
}: {
|
||||
packageInfo?: PackageInfo;
|
||||
newAgentPolicy: NewAgentPolicy;
|
||||
withSysMonitoring: boolean;
|
||||
selectedPolicyTab: SelectedPolicyTab;
|
||||
agentCount: number;
|
||||
queryParamsPolicyId: string | undefined;
|
||||
integrationToEnable?: string;
|
||||
hasFleetAddAgentsPrivileges: boolean;
|
||||
}) {
|
||||
}: UseOnSubmitProps) {
|
||||
const { notifications } = useStartServices();
|
||||
const confirmForceInstall = useConfirmForceInstall();
|
||||
const spaceSettings = useSpaceSettingsContext();
|
||||
|
|
|
@ -103,12 +103,13 @@ const CustomEuiBottomBar = styled(EuiBottomBar)`
|
|||
z-index: 50;
|
||||
`;
|
||||
|
||||
export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
|
||||
export const CreatePackagePolicySinglePage: React.FC<CreatePackagePolicyParams> = ({
|
||||
from,
|
||||
queryParamsPolicyId,
|
||||
prerelease,
|
||||
onNext,
|
||||
onCanceled,
|
||||
onAddAgent,
|
||||
onCancel,
|
||||
withHeader = true,
|
||||
}) => {
|
||||
const {
|
||||
agents: { enabled: isFleetEnabled },
|
||||
|
@ -116,7 +117,7 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
|
|||
const hasFleetAddAgentsPrivileges = useAuthz().fleet.addAgents;
|
||||
const { params } = useRouteMatch<AddToPolicyParams>();
|
||||
const { pkgkey: pkgKeyContext } = useIntegrationsStateContext();
|
||||
const pkgkey = params.pkgkey || pkgKeyContext;
|
||||
const pkgkey = params.pkgkey || pkgKeyContext || '';
|
||||
|
||||
const fleetStatus = useFleetStatus();
|
||||
const { docLinks } = useStartServices();
|
||||
|
@ -195,22 +196,24 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
|
|||
});
|
||||
|
||||
const handleNavigateAddAgent = useCallback(() => {
|
||||
if (onNext) {
|
||||
onNext({ selectedAgentPolicies: agentPolicies });
|
||||
if (onAddAgent) {
|
||||
onAddAgent({ selectedAgentPolicies: agentPolicies });
|
||||
} else {
|
||||
if (savedPackagePolicy) {
|
||||
navigateAddAgent(savedPackagePolicy);
|
||||
}
|
||||
}
|
||||
}, [onNext, agentPolicies, savedPackagePolicy, navigateAddAgent]);
|
||||
}, [onAddAgent, agentPolicies, savedPackagePolicy, navigateAddAgent]);
|
||||
|
||||
const handleCancellation = useCallback(() => {
|
||||
if (onCanceled) {
|
||||
onCanceled();
|
||||
if (onCancel) {
|
||||
onCancel();
|
||||
} else {
|
||||
navigateAddAgentHelp(savedPackagePolicy);
|
||||
if (savedPackagePolicy) {
|
||||
navigateAddAgentHelp(savedPackagePolicy);
|
||||
}
|
||||
}
|
||||
}, [onCanceled, savedPackagePolicy, navigateAddAgentHelp]);
|
||||
}, [onCancel, savedPackagePolicy, navigateAddAgentHelp]);
|
||||
|
||||
const setPolicyValidation = useCallback(
|
||||
(selectedTab: SelectedPolicyTab, updatedAgentPolicy: NewAgentPolicy) => {
|
||||
|
@ -307,12 +310,22 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
|
|||
() => ({
|
||||
from,
|
||||
cancelUrl,
|
||||
onCancel: cancelClickHandler,
|
||||
onCancel: onCancel ?? cancelClickHandler,
|
||||
agentPolicies,
|
||||
packageInfo,
|
||||
integrationInfo,
|
||||
withHeader,
|
||||
}),
|
||||
[agentPolicies, cancelClickHandler, cancelUrl, from, integrationInfo, packageInfo]
|
||||
[
|
||||
agentPolicies,
|
||||
cancelClickHandler,
|
||||
cancelUrl,
|
||||
from,
|
||||
integrationInfo,
|
||||
onCancel,
|
||||
packageInfo,
|
||||
withHeader,
|
||||
]
|
||||
);
|
||||
|
||||
const stepSelectAgentPolicy = useMemo(
|
||||
|
@ -531,7 +544,7 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
|
|||
onConfirm={onSubmit}
|
||||
onCancel={() => {
|
||||
setFormState('VALID');
|
||||
onCanceled?.();
|
||||
onCancel?.();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
@ -649,11 +662,10 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd">
|
||||
<EuiFlexItem grow={false}>
|
||||
{/* eslint-disable-next-line @elastic/eui/href-or-on-click */}
|
||||
<EuiButtonEmpty
|
||||
color="text"
|
||||
href={cancelUrl}
|
||||
onClick={cancelClickHandler}
|
||||
{...(onCancel ? {} : { href: cancelUrl })}
|
||||
onClick={onCancel ?? cancelClickHandler}
|
||||
data-test-subj="createPackagePolicyCancelButton"
|
||||
>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type React from 'react';
|
||||
import type { AgentPolicy } from '../../../types';
|
||||
|
||||
export type EditPackagePolicyFrom =
|
||||
| 'package'
|
||||
| 'package-edit'
|
||||
|
@ -14,7 +15,7 @@ export type EditPackagePolicyFrom =
|
|||
| 'upgrade-from-fleet-policy-list'
|
||||
| 'upgrade-from-integrations-policy-list'
|
||||
| 'upgrade-from-extension'
|
||||
| 'onboarding-integration';
|
||||
| 'onboarding-hub';
|
||||
|
||||
export type PackagePolicyFormState =
|
||||
| 'VALID'
|
||||
|
@ -33,11 +34,11 @@ export interface AddToPolicyParams {
|
|||
policyId?: string;
|
||||
}
|
||||
|
||||
export type CreatePackagePolicyParams = React.FunctionComponent<{
|
||||
export interface CreatePackagePolicyParams {
|
||||
from: EditPackagePolicyFrom;
|
||||
queryParamsPolicyId?: string;
|
||||
propPolicyId?: string;
|
||||
integrationName?: string;
|
||||
prerelease: boolean;
|
||||
onNext?: () => void;
|
||||
}>;
|
||||
onAddAgent: (param?: { selectedAgentPolicies: AgentPolicy[] }) => void;
|
||||
onCancel: () => void;
|
||||
withHeader?: boolean;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,8 @@ import { useFlyoutContext, useStartServices } from '../../../../hooks';
|
|||
|
||||
export const EnrollmentRecommendation: React.FunctionComponent<{
|
||||
showStandaloneTab: () => void;
|
||||
}> = ({ showStandaloneTab }) => {
|
||||
handleAddFleetServer?: () => void;
|
||||
}> = ({ showStandaloneTab, handleAddFleetServer }) => {
|
||||
const flyoutContext = useFlyoutContext();
|
||||
|
||||
const { docLinks } = useStartServices();
|
||||
|
@ -80,7 +81,7 @@ export const EnrollmentRecommendation: React.FunctionComponent<{
|
|||
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton onClick={flyoutContext?.openFleetServerFlyout}>
|
||||
<EuiButton onClick={handleAddFleetServer ?? flyoutContext?.openFleetServerFlyout}>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.enrollment.addFleetServerButton"
|
||||
defaultMessage="Add Fleet Server"
|
||||
|
|
|
@ -36,12 +36,18 @@ export const FleetServerRequirementPage: React.FunctionComponent<
|
|||
| {
|
||||
showEnrollmentRecommendation?: false;
|
||||
showStandaloneTab?: never;
|
||||
handleAddFleetServer?: () => void;
|
||||
}
|
||||
| {
|
||||
showEnrollmentRecommendation?: true;
|
||||
showStandaloneTab: () => void;
|
||||
handleAddFleetServer?: () => void;
|
||||
}
|
||||
> = ({ showStandaloneTab = () => {}, showEnrollmentRecommendation = true }) => {
|
||||
> = ({
|
||||
showStandaloneTab = () => {},
|
||||
showEnrollmentRecommendation = true,
|
||||
handleAddFleetServer,
|
||||
}) => {
|
||||
const startService = useStartServices();
|
||||
const deploymentUrl = startService.cloud?.deploymentUrl;
|
||||
const authz = useAuthz();
|
||||
|
@ -61,7 +67,10 @@ export const FleetServerRequirementPage: React.FunctionComponent<
|
|||
) : permissionsError ? (
|
||||
<FleetServerMissingESPrivileges />
|
||||
) : showEnrollmentRecommendation ? (
|
||||
<EnrollmentRecommendation showStandaloneTab={showStandaloneTab} />
|
||||
<EnrollmentRecommendation
|
||||
showStandaloneTab={showStandaloneTab}
|
||||
handleAddFleetServer={handleAddFleetServer}
|
||||
/>
|
||||
) : (
|
||||
<AddFleetServerLanding />
|
||||
)}
|
||||
|
|
|
@ -8,6 +8,7 @@ import React, { createContext } from 'react';
|
|||
|
||||
import {
|
||||
FleetStatusProvider,
|
||||
FlyoutContextProvider,
|
||||
KibanaVersionContext,
|
||||
UIExtensionsContextProvider,
|
||||
} from '../../../hooks';
|
||||
|
@ -38,7 +39,9 @@ export const FleetIntegrationsStateContextProvider: React.FC<{
|
|||
<UIExtensionsContextProvider values={{}}>
|
||||
<FleetStatusProvider>
|
||||
<PackageInstallProvider startServices={startServices}>
|
||||
<IntegrationsStateContextProvider>{children}</IntegrationsStateContextProvider>
|
||||
<FlyoutContextProvider>
|
||||
<IntegrationsStateContextProvider>{children}</IntegrationsStateContextProvider>
|
||||
</FlyoutContextProvider>
|
||||
</PackageInstallProvider>
|
||||
</FleetStatusProvider>
|
||||
</UIExtensionsContextProvider>
|
||||
|
|
|
@ -13,6 +13,8 @@ import { useIntraAppState } from '../../../hooks';
|
|||
|
||||
interface IntegrationsStateContextValue {
|
||||
getFromIntegrations(): string | undefined;
|
||||
pkgkey?: string;
|
||||
panel?: string;
|
||||
}
|
||||
|
||||
const IntegrationsStateContext = createContext<IntegrationsStateContextValue>({
|
||||
|
@ -24,7 +26,6 @@ export const IntegrationsStateContextProvider: FunctionComponent<{
|
|||
}> = ({ children }) => {
|
||||
const maybeState = useIntraAppState<undefined | IntegrationsAppBrowseRouteState>();
|
||||
const stateRef = useRef(maybeState);
|
||||
console.log('myState---', maybeState);
|
||||
const getFromIntegrations = useCallback(() => {
|
||||
return stateRef.current?.fromIntegrations;
|
||||
}, []);
|
||||
|
@ -33,7 +34,6 @@ export const IntegrationsStateContextProvider: FunctionComponent<{
|
|||
value={{
|
||||
getFromIntegrations,
|
||||
pkgkey: maybeState?.pkgkey,
|
||||
panel: maybeState?.panel,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -134,21 +134,21 @@ export function Detail({
|
|||
originFrom,
|
||||
routesEnabled = true,
|
||||
onAddIntegrationPolicyClick,
|
||||
onDetailsTabClick,
|
||||
selectedDetailsTab = 'overview',
|
||||
}: {
|
||||
originFrom?: string;
|
||||
routesEnabled?: boolean;
|
||||
onAddIntegrationPolicyClick?: () => void;
|
||||
onDetailsTabClick?: (tabId: DetailViewPanelName) => void;
|
||||
selectedDetailsTab?: DetailViewPanelName;
|
||||
}) {
|
||||
const { getId: getAgentPolicyId } = useAgentPolicyContext();
|
||||
const {
|
||||
getFromIntegrations,
|
||||
pkgkey: pkgKeyContext,
|
||||
panel: panelContext,
|
||||
} = useIntegrationsStateContext();
|
||||
const [selectedPanel, setSelectedPanel] = useState<DetailViewPanelName>(panelContext);
|
||||
const { getFromIntegrations, pkgkey: pkgKeyContext } = useIntegrationsStateContext();
|
||||
|
||||
const { pkgkey: pkgkeyParam, panel: panelParam } = useParams<DetailParams>();
|
||||
const pkgkey = pkgkeyParam || pkgKeyContext;
|
||||
const panel = panelParam || selectedPanel;
|
||||
const panel = panelParam || selectedDetailsTab;
|
||||
const { getHref, getPath } = useLink();
|
||||
const history = useHistory();
|
||||
const { pathname, search, hash } = useLocation();
|
||||
|
@ -656,7 +656,7 @@ export function Detail({
|
|||
isSelected: panel === 'overview',
|
||||
'data-test-subj': `tab-overview`,
|
||||
href:
|
||||
originFrom !== 'onboarding-integration'
|
||||
originFrom !== 'onboarding-hub'
|
||||
? getHref('integration_details_overview', {
|
||||
pkgkey: packageInfoKey,
|
||||
...(integration ? { integration } : {}),
|
||||
|
@ -664,7 +664,7 @@ export function Detail({
|
|||
: undefined,
|
||||
onClick: (e: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
e.preventDefault();
|
||||
setSelectedPanel('overview');
|
||||
onDetailsTabClick?.('overview');
|
||||
},
|
||||
},
|
||||
];
|
||||
|
@ -680,7 +680,7 @@ export function Detail({
|
|||
),
|
||||
isSelected: panel === 'policies',
|
||||
'data-test-subj': `tab-policies`,
|
||||
href: routesEnabled
|
||||
href: onDetailsTabClick
|
||||
? getHref('integration_details_policies', {
|
||||
pkgkey: packageInfoKey,
|
||||
...(integration ? { integration } : {}),
|
||||
|
@ -688,7 +688,7 @@ export function Detail({
|
|||
: undefined,
|
||||
onClick: (e: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
e.preventDefault();
|
||||
setSelectedPanel('policies');
|
||||
onDetailsTabClick?.('policies');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -710,7 +710,7 @@ export function Detail({
|
|||
),
|
||||
isSelected: panel === 'assets',
|
||||
'data-test-subj': `tab-assets`,
|
||||
href: routesEnabled
|
||||
href: onDetailsTabClick
|
||||
? getHref('integration_details_assets', {
|
||||
pkgkey: packageInfoKey,
|
||||
...(integration ? { integration } : {}),
|
||||
|
@ -718,7 +718,7 @@ export function Detail({
|
|||
: undefined,
|
||||
onClick: (e: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
e.preventDefault();
|
||||
setSelectedPanel('assets');
|
||||
onDetailsTabClick?.('assets');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -734,7 +734,7 @@ export function Detail({
|
|||
),
|
||||
isSelected: panel === 'settings',
|
||||
'data-test-subj': `tab-settings`,
|
||||
href: routesEnabled
|
||||
href: onDetailsTabClick
|
||||
? getHref('integration_details_settings', {
|
||||
pkgkey: packageInfoKey,
|
||||
...(integration ? { integration } : {}),
|
||||
|
@ -742,7 +742,7 @@ export function Detail({
|
|||
: undefined,
|
||||
onClick: (e: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
e.preventDefault();
|
||||
setSelectedPanel('settings');
|
||||
onDetailsTabClick?.('settings');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -758,7 +758,7 @@ export function Detail({
|
|||
),
|
||||
isSelected: panel === 'configs',
|
||||
'data-test-subj': `tab-configs`,
|
||||
href: routesEnabled
|
||||
href: onDetailsTabClick
|
||||
? getHref('integration_details_configs', {
|
||||
pkgkey: packageInfoKey,
|
||||
...(integration ? { integration } : {}),
|
||||
|
@ -766,7 +766,7 @@ export function Detail({
|
|||
: undefined,
|
||||
onClick: (e: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
e.preventDefault();
|
||||
setSelectedPanel('configs');
|
||||
onDetailsTabClick?.('configs');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -782,7 +782,7 @@ export function Detail({
|
|||
),
|
||||
isSelected: panel === 'custom',
|
||||
'data-test-subj': `tab-custom`,
|
||||
href: routesEnabled
|
||||
href: onDetailsTabClick
|
||||
? getHref('integration_details_custom', {
|
||||
pkgkey: packageInfoKey,
|
||||
...(integration ? { integration } : {}),
|
||||
|
@ -790,7 +790,7 @@ export function Detail({
|
|||
: undefined,
|
||||
onClick: (e: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
e.preventDefault();
|
||||
setSelectedPanel('custom');
|
||||
onDetailsTabClick?.('custom');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -806,7 +806,7 @@ export function Detail({
|
|||
),
|
||||
isSelected: panel === 'api-reference',
|
||||
'data-test-subj': `tab-api-reference`,
|
||||
href: routesEnabled
|
||||
href: onDetailsTabClick
|
||||
? getHref('integration_details_api_reference', {
|
||||
pkgkey: packageInfoKey,
|
||||
...(integration ? { integration } : {}),
|
||||
|
@ -814,7 +814,7 @@ export function Detail({
|
|||
: undefined,
|
||||
onClick: (e: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
e.preventDefault();
|
||||
setSelectedPanel('api-reference');
|
||||
onDetailsTabClick?.('api-reference');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -833,7 +833,7 @@ export function Detail({
|
|||
showConfigTab,
|
||||
showCustomTab,
|
||||
showDocumentationTab,
|
||||
routesEnabled,
|
||||
onDetailsTabClick,
|
||||
numOfDeferredInstallations,
|
||||
]);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ interface Props {
|
|||
policyId?: string;
|
||||
troubleshootLink: string;
|
||||
onClickViewAgents?: () => void;
|
||||
onClickViewIncomingData?: () => void;
|
||||
agentCount: number;
|
||||
showLoading?: boolean;
|
||||
isLongEnrollment?: boolean;
|
||||
|
@ -99,6 +100,7 @@ export const ConfirmAgentEnrollment: React.FunctionComponent<Props> = ({
|
|||
policyId,
|
||||
troubleshootLink,
|
||||
onClickViewAgents,
|
||||
onClickViewIncomingData,
|
||||
agentCount,
|
||||
showLoading = false,
|
||||
isLongEnrollment = false,
|
||||
|
@ -198,6 +200,17 @@ export const ConfirmAgentEnrollment: React.FunctionComponent<Props> = ({
|
|||
})}
|
||||
</EuiButton>
|
||||
)}
|
||||
{onClickViewIncomingData && (
|
||||
<EuiButton
|
||||
onClick={onClickViewIncomingData}
|
||||
color="success"
|
||||
data-test-subj="ViewIncomingDataButton"
|
||||
>
|
||||
{i18n.translate('xpack.fleet.agentEnrollment.confirmation.button', {
|
||||
defaultMessage: 'View incoming data',
|
||||
})}
|
||||
</EuiButton>
|
||||
)}
|
||||
</EuiCallOut>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@ import React, { useEffect } from 'react';
|
|||
import { EuiText, EuiSpacer } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
import type { FleetStatus } from '../../hooks';
|
||||
import { useFleetStatus, useFleetServerStandalone, useGetEnrollmentSettings } from '../../hooks';
|
||||
import { FleetServerRequirementPage } from '../../applications/fleet/sections/agents/agent_requirements_page';
|
||||
import { FLEET_SERVER_PACKAGE } from '../../constants';
|
||||
|
@ -19,6 +20,22 @@ import type { InstructionProps } from './types';
|
|||
import { ManagedSteps, StandaloneSteps } from './steps';
|
||||
import { DefaultMissingRequirements } from './default_missing_requirements';
|
||||
|
||||
export const shouldShowFleetServerEnrollment = ({
|
||||
isFleetServerStandalone,
|
||||
isFleetServerPolicySelected,
|
||||
enrollmentSettings,
|
||||
fleetStatusMissingRequirements,
|
||||
}: {
|
||||
isFleetServerStandalone: boolean;
|
||||
isFleetServerPolicySelected: boolean | undefined;
|
||||
enrollmentSettings: any;
|
||||
fleetStatusMissingRequirements: FleetStatus['missingRequirements'];
|
||||
}) =>
|
||||
!isFleetServerStandalone &&
|
||||
!isFleetServerPolicySelected &&
|
||||
(!enrollmentSettings?.fleet_server.has_active ||
|
||||
(fleetStatusMissingRequirements ?? []).some((r) => r === FLEET_SERVER_PACKAGE));
|
||||
|
||||
export const Instructions = (props: InstructionProps) => {
|
||||
const {
|
||||
isFleetServerPolicySelected,
|
||||
|
@ -28,7 +45,8 @@ export const Instructions = (props: InstructionProps) => {
|
|||
setSelectionType,
|
||||
mode,
|
||||
setMode,
|
||||
isIntegrationFlow,
|
||||
from,
|
||||
handleAddFleetServer,
|
||||
} = props;
|
||||
const fleetStatus = useFleetStatus();
|
||||
const { isFleetServerStandalone } = useFleetServerStandalone();
|
||||
|
@ -42,11 +60,12 @@ export const Instructions = (props: InstructionProps) => {
|
|||
isFleetServerStandalone ||
|
||||
(fleetStatus.isReady && enrollmentSettings?.fleet_server.has_active && fleetServerHost);
|
||||
|
||||
const showFleetServerEnrollment =
|
||||
!isFleetServerStandalone &&
|
||||
!isFleetServerPolicySelected &&
|
||||
(!enrollmentSettings?.fleet_server.has_active ||
|
||||
(fleetStatus.missingRequirements ?? []).some((r) => r === FLEET_SERVER_PACKAGE));
|
||||
const showFleetServerEnrollment = shouldShowFleetServerEnrollment({
|
||||
isFleetServerStandalone,
|
||||
isFleetServerPolicySelected,
|
||||
enrollmentSettings,
|
||||
fleetStatusMissingRequirements: fleetStatus.missingRequirements,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// If we detect a CloudFormation integration, we want to hide the selection type
|
||||
|
@ -56,12 +75,12 @@ export const Instructions = (props: InstructionProps) => {
|
|||
props.cloudSecurityIntegration?.cloudShellUrl
|
||||
) {
|
||||
setSelectionType(undefined);
|
||||
} else if (!isIntegrationFlow && showAgentEnrollment) {
|
||||
} else if (showAgentEnrollment) {
|
||||
setSelectionType('radio');
|
||||
} else {
|
||||
setSelectionType('tabs');
|
||||
}
|
||||
}, [isIntegrationFlow, showAgentEnrollment, setSelectionType, props.cloudSecurityIntegration]);
|
||||
}, [from, showAgentEnrollment, setSelectionType, props.cloudSecurityIntegration]);
|
||||
|
||||
if (isLoadingEnrollmentSettings || isLoadingAgentPolicies) return <Loading size="l" />;
|
||||
|
||||
|
@ -71,7 +90,12 @@ export const Instructions = (props: InstructionProps) => {
|
|||
|
||||
if (mode === 'managed') {
|
||||
if (showFleetServerEnrollment) {
|
||||
return <FleetServerRequirementPage showStandaloneTab={() => setMode('standalone')} />;
|
||||
return (
|
||||
<FleetServerRequirementPage
|
||||
showStandaloneTab={() => setMode('standalone')}
|
||||
handleAddFleetServer={handleAddFleetServer}
|
||||
/>
|
||||
);
|
||||
} else if (showAgentEnrollment) {
|
||||
return (
|
||||
<>
|
||||
|
|
|
@ -43,6 +43,7 @@ export const AgentEnrollmentConfirmationStep = ({
|
|||
selectedPolicyId,
|
||||
troubleshootLink,
|
||||
onClickViewAgents,
|
||||
onClickViewIncomingData,
|
||||
agentCount,
|
||||
showLoading,
|
||||
poll = true,
|
||||
|
@ -51,6 +52,7 @@ export const AgentEnrollmentConfirmationStep = ({
|
|||
selectedPolicyId?: string;
|
||||
troubleshootLink: string;
|
||||
onClickViewAgents?: () => void;
|
||||
onClickViewIncomingData?: () => void;
|
||||
agentCount: number;
|
||||
poll?: boolean;
|
||||
showLoading?: boolean;
|
||||
|
@ -72,6 +74,7 @@ export const AgentEnrollmentConfirmationStep = ({
|
|||
policyId={selectedPolicyId}
|
||||
troubleshootLink={troubleshootLink}
|
||||
onClickViewAgents={onClickViewAgents}
|
||||
onClickViewIncomingData={onClickViewIncomingData}
|
||||
agentCount={agentCount}
|
||||
showLoading={!isComplete || showLoading}
|
||||
isLongEnrollment={isLongEnrollment}
|
||||
|
|
|
@ -157,9 +157,11 @@ export const ManagedSteps: React.FunctionComponent<InstructionProps> = ({
|
|||
setMode,
|
||||
selectionType,
|
||||
onClickViewAgents,
|
||||
onClickViewIncomingData,
|
||||
isK8s,
|
||||
cloudSecurityIntegration,
|
||||
installedPackagePolicy,
|
||||
from,
|
||||
}) => {
|
||||
const core = useStartServices();
|
||||
const { docLinks } = core;
|
||||
|
@ -265,13 +267,14 @@ export const ManagedSteps: React.FunctionComponent<InstructionProps> = ({
|
|||
AgentEnrollmentConfirmationStep({
|
||||
selectedPolicyId: selectedPolicy?.id,
|
||||
onClickViewAgents,
|
||||
onClickViewIncomingData,
|
||||
troubleshootLink: link,
|
||||
agentCount: enrolledAgentIds.length,
|
||||
isLongEnrollment: cloudSecurityIntegration !== undefined,
|
||||
})
|
||||
);
|
||||
}
|
||||
if (selectedPolicy) {
|
||||
if (selectedPolicy && from !== 'onboarding-hub') {
|
||||
steps.push(
|
||||
IncomingDataConfirmationStep({
|
||||
agentIds: enrolledAgentIds,
|
||||
|
@ -295,18 +298,20 @@ export const ManagedSteps: React.FunctionComponent<InstructionProps> = ({
|
|||
selectionType,
|
||||
cloudSecurityIntegration,
|
||||
apiKeyData,
|
||||
from,
|
||||
mode,
|
||||
setMode,
|
||||
enrollToken,
|
||||
installManagedCommands,
|
||||
isK8s,
|
||||
fleetServerHost,
|
||||
installManagedCommands,
|
||||
gcpProjectId,
|
||||
isK8s,
|
||||
onClickViewAgents,
|
||||
onClickViewIncomingData,
|
||||
link,
|
||||
enrolledAgentIds,
|
||||
agentDataConfirmed,
|
||||
installedPackagePolicy,
|
||||
gcpProjectId,
|
||||
]);
|
||||
|
||||
if (!agentVersion) {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { EditPackagePolicyFrom } from '../../applications/fleet/sections/agent_policy/create_package_policy_page/types';
|
||||
import type { AgentPolicy, DownloadSource, FleetProxy } from '../../types';
|
||||
|
||||
import type { InstalledIntegrationPolicy } from './use_get_agent_incoming_data';
|
||||
|
@ -67,13 +68,21 @@ export interface FlyOutProps extends BaseProps {
|
|||
selectedAgentPolicies?: AgentPolicy[];
|
||||
}
|
||||
|
||||
export interface AgentPolicySelectionProps extends BaseProps {
|
||||
onCancel?: () => void;
|
||||
defaultMode?: FlyoutMode;
|
||||
selectedAgentPolicies?: AgentPolicy[];
|
||||
onNext: () => void;
|
||||
setEnrolledAgentIds: (ids: string[]) => void;
|
||||
}
|
||||
export interface InstructionProps extends BaseProps {
|
||||
agentPolicies: AgentPolicy[];
|
||||
selectedPolicy: AgentPolicy | undefined;
|
||||
setSelectedPolicyId: (policyId?: string) => void;
|
||||
refreshAgentPolicies: () => void;
|
||||
isLoadingAgentPolicies?: boolean;
|
||||
onClickViewAgents: () => void;
|
||||
onClickViewAgents?: () => void;
|
||||
onClickViewIncomingData?: () => void;
|
||||
mode: FlyoutMode;
|
||||
setMode: (v: FlyoutMode) => void;
|
||||
selectionType: SelectionType;
|
||||
|
@ -84,4 +93,7 @@ export interface InstructionProps extends BaseProps {
|
|||
fleetProxy?: FleetProxy;
|
||||
downloadSource?: DownloadSource;
|
||||
downloadSourceProxy?: FleetProxy;
|
||||
hasIncomingDataStep?: boolean;
|
||||
handleAddFleetServer?: () => void;
|
||||
from?: EditPackagePolicyFrom;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ export interface FleetStatusProviderProps {
|
|||
spaceId?: string;
|
||||
}
|
||||
|
||||
interface FleetStatus extends FleetStatusProviderProps {
|
||||
export interface FleetStatus extends FleetStatusProviderProps {
|
||||
refetch: () => Promise<unknown>;
|
||||
|
||||
// This flag allows us to opt into displaying the Fleet Server enrollment instructions even if
|
||||
|
|
|
@ -10,7 +10,6 @@ import type { PluginInitializerContext } from '@kbn/core/public';
|
|||
import { lazy } from 'react';
|
||||
|
||||
import { FleetPlugin } from './plugin';
|
||||
import type { UIExtensionsStorage } from './types';
|
||||
export type { GetPackagesResponse } from './types';
|
||||
export { installationStatuses } from '../common/constants';
|
||||
|
||||
|
|
|
@ -35,6 +35,9 @@ export interface CreatePackagePolicyRouteState {
|
|||
onSaveQueryParams?: {
|
||||
[key in OnSaveQueryParamKeys]?: OnSaveQueryParamOpts;
|
||||
};
|
||||
pkgkey?: string;
|
||||
|
||||
panel?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,6 +61,10 @@ export interface IntegrationsAppBrowseRouteState {
|
|||
forAgentPolicyId: string;
|
||||
/** The integration tab the user navigated to details from */
|
||||
fromIntegrations: 'installed' | 'updates_available' | undefined;
|
||||
|
||||
pkgkey?: string;
|
||||
|
||||
panel?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,13 +7,11 @@
|
|||
import React, { lazy, Suspense, useMemo, useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import {
|
||||
EuiButton,
|
||||
EuiButtonGroup,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiModal,
|
||||
EuiModalBody,
|
||||
EuiModalFooter,
|
||||
EuiModalHeader,
|
||||
EuiPortal,
|
||||
EuiSkeletonText,
|
||||
|
@ -24,6 +22,7 @@ import { noop } from 'lodash';
|
|||
|
||||
import { css } from '@emotion/react';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import type { DetailViewPanelName } from '@kbn/fleet-plugin/public/applications/integrations/sections/epm/screens/detail';
|
||||
import { withLazyHook } from '../../../../../common/components/with_lazy_hook';
|
||||
import {
|
||||
useStoredIntegrationSearchTerm,
|
||||
|
@ -77,11 +76,13 @@ const FleetIntegrationsStateContextProvider = lazy(async () => ({
|
|||
.then((pkg) => pkg.FleetIntegrationsStateContextProvider),
|
||||
}));
|
||||
|
||||
const integrationStepMap = {
|
||||
0: 'Add integration',
|
||||
1: 'Install Elastic Agent',
|
||||
2: 'Confirm incoming data',
|
||||
}
|
||||
const integrationStepMap = [
|
||||
'Add integration',
|
||||
'Check fleet server requirement',
|
||||
'Add Fleet server',
|
||||
'Install Elastic Agent',
|
||||
'Confirm incoming data',
|
||||
];
|
||||
|
||||
export const IntegrationsCardGridTabsComponent = React.memo<IntegrationsCardGridTabsProps>(
|
||||
({ installedIntegrationsCount, isAgentRequired, useAvailablePackages }) => {
|
||||
|
@ -108,18 +109,19 @@ export const IntegrationsCardGridTabsComponent = React.memo<IntegrationsCardGrid
|
|||
);
|
||||
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
const [integrationName, setIntegrationName] = useState();
|
||||
const [integrationName, setIntegrationName] = useState<string>();
|
||||
const [modalView, setModalView] = useState<'overview' | 'configure-integration' | 'add-agent'>(
|
||||
'overview'
|
||||
);
|
||||
const [integrationStep, setIntegrationStep] = useState(0);
|
||||
const [integrationStep, onStepNext] = useState(0);
|
||||
const onAddIntegrationPolicyClick = useCallback(() => {
|
||||
setModalView('configure-integration');
|
||||
}, []);
|
||||
const closeModal = useCallback(() => {
|
||||
setIsModalVisible(false);
|
||||
setModalView('overview');
|
||||
setIntegrationStep(0);
|
||||
setSelectedDetailsTab('overview');
|
||||
onStepNext(0);
|
||||
}, []);
|
||||
const onCardClicked = useCallback((name: string) => {
|
||||
setIsModalVisible(true);
|
||||
|
@ -138,6 +140,7 @@ export const IntegrationsCardGridTabsComponent = React.memo<IntegrationsCardGrid
|
|||
});
|
||||
|
||||
const selectedTab = useMemo(() => INTEGRATION_TABS_BY_ID[toggleIdSelected], [toggleIdSelected]);
|
||||
const [selectedDetailsTab, setSelectedDetailsTab] = useState<DetailViewPanelName>('overview');
|
||||
const onSearchTermChanged = useCallback(
|
||||
(searchQuery: string) => {
|
||||
setSearchTerm(searchQuery);
|
||||
|
@ -150,6 +153,15 @@ export const IntegrationsCardGridTabsComponent = React.memo<IntegrationsCardGrid
|
|||
[selectedTab.showSearchTools, setSearchTerm, setSearchTermToStorage]
|
||||
);
|
||||
|
||||
const handleViewAssets = useCallback(() => {
|
||||
setModalView('overview');
|
||||
setSelectedDetailsTab('assets');
|
||||
}, []);
|
||||
|
||||
const onDetailsTabClick = useCallback((detailsTab: DetailViewPanelName) => {
|
||||
setSelectedDetailsTab(detailsTab);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setCategory(selectedTab.category ?? '');
|
||||
setSelectedSubCategory(selectedTab.subCategory);
|
||||
|
@ -261,30 +273,33 @@ export const IntegrationsCardGridTabsComponent = React.memo<IntegrationsCardGrid
|
|||
aria-labelledby={modalTitleId}
|
||||
onClose={closeModal}
|
||||
css={css`
|
||||
width: 85%;
|
||||
width: 1024px;
|
||||
`}
|
||||
maxWidth="90%"
|
||||
>
|
||||
{modalView === 'configure-integration' && (<EuiModalHeader>{`step indicator place holder. Integration step: ${integrationStepMap[integrationStep]}`}</EuiModalHeader>)}
|
||||
{modalView === 'configure-integration' && (
|
||||
<EuiModalHeader>{`step indicator place holder. Integration step: ${integrationStepMap[integrationStep]}`}</EuiModalHeader>
|
||||
)}
|
||||
<EuiModalBody>
|
||||
<FleetIntegrationsStateContextProvider
|
||||
values={{ startServices, useMultiPageLayoutProp: true }}
|
||||
values={{ startServices, useMultiPageLayoutProp: true, kibanaVersion: '9.0.0' }}
|
||||
>
|
||||
{modalView === 'overview' && (
|
||||
<Detail
|
||||
onAddIntegrationPolicyClick={onAddIntegrationPolicyClick}
|
||||
originFrom="onboarding-integration"
|
||||
originFrom="onboarding-hub"
|
||||
routesEnabled={false}
|
||||
onDetailsTabClick={onDetailsTabClick}
|
||||
selectedDetailsTab={selectedDetailsTab}
|
||||
/>
|
||||
)}
|
||||
{modalView === 'configure-integration' && (
|
||||
<CreatePackagePolicyPage
|
||||
useMultiPageLayoutProp={true}
|
||||
originFrom="onboarding-integration"
|
||||
propPolicyId=""
|
||||
originFrom="onboarding-hub"
|
||||
integrationName={integrationName}
|
||||
setIntegrationStep={setIntegrationStep}
|
||||
onCanceled={closeModal}
|
||||
onStepNext={onStepNext}
|
||||
onCancel={closeModal}
|
||||
handleViewAssets={handleViewAssets}
|
||||
/>
|
||||
)}
|
||||
</FleetIntegrationsStateContextProvider>
|
||||
|
|
|
@ -101,6 +101,7 @@ const addSecuritySpecificProps = ({
|
|||
APP_UI_ID,
|
||||
{ path: ONBOARDING_PATH, state: { pkgkey: card.pkgkey, onCancelUrl: onboardingLink } },
|
||||
],
|
||||
onDoneNavigateTo: [APP_UI_ID, { path: ONBOARDING_PATH, state: { pkgkey: card.pkgkey } }],
|
||||
onCancelUrl: onboardingLink,
|
||||
onSaveNavigateTo: [APP_UI_ID, { path: ONBOARDING_PATH, state: { pkgkey: card.pkgkey } }],
|
||||
pkgkey: card.pkgkey,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue