Skip to content

Commit

Permalink
Merge branch '8.12' into backport/8.12/pr-174185
Browse files Browse the repository at this point in the history
  • Loading branch information
jpdjere authored Jan 15, 2024
2 parents 686026a + d1d01cf commit 14b22ea
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const IntegrationPreference = () => {
<Component
initialType="recommended"
onChange={action('onChange')}
onPrereleaseEnabledChange={() => {}}
prereleaseIntegrationsEnabled={false}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { useCallback, useEffect } from 'react';
import React, { useCallback } from 'react';
import styled from 'styled-components';

import { i18n } from '@kbn/i18n';
Expand All @@ -23,7 +23,7 @@ import {
EuiSwitch,
} from '@elastic/eui';

import { sendPutSettings, useGetSettings, useStartServices } from '../../../hooks';
import { usePutSettingsMutation, useStartServices } from '../../../hooks';

export type IntegrationPreferenceType = 'recommended' | 'beats' | 'agent';

Expand All @@ -35,7 +35,7 @@ interface Option {
export interface Props {
initialType: IntegrationPreferenceType;
onChange: (type: IntegrationPreferenceType) => void;
onPrereleaseEnabledChange: (prerelease: boolean) => void;
prereleaseIntegrationsEnabled: boolean;
}

const recommendedTooltip = (
Expand Down Expand Up @@ -86,42 +86,39 @@ const options: Option[] = [
export const IntegrationPreference = ({
initialType,
onChange,
onPrereleaseEnabledChange,
prereleaseIntegrationsEnabled,
}: Props) => {
const [idSelected, setIdSelected] = React.useState<IntegrationPreferenceType>(initialType);

const { docLinks } = useStartServices();

const [prereleaseIntegrationsEnabled, setPrereleaseIntegrationsEnabled] = React.useState<
const [prereleaseIntegrationsChecked, setPrereleaseIntegrationsChecked] = React.useState<
boolean | undefined
>(undefined);

const { data: settings, error: settingsError } = useGetSettings();

useEffect(() => {
const isEnabled = Boolean(settings?.item.prerelease_integrations_enabled);
if (settings?.item) {
setPrereleaseIntegrationsEnabled(isEnabled);
} else if (settingsError) {
setPrereleaseIntegrationsEnabled(false);
}
}, [settings?.item, settingsError]);

useEffect(() => {
if (prereleaseIntegrationsEnabled !== undefined) {
onPrereleaseEnabledChange(prereleaseIntegrationsEnabled);
}
}, [onPrereleaseEnabledChange, prereleaseIntegrationsEnabled]);

const updateSettings = useCallback(async (prerelease: boolean) => {
const res = await sendPutSettings({
prerelease_integrations_enabled: prerelease,
});

if (res.error) {
throw res.error;
}
}, []);
const { docLinks, notifications } = useStartServices();

const { mutateAsync: mutateSettingsAsync } = usePutSettingsMutation();

const updateSettings = useCallback(
async (prerelease: boolean) => {
try {
setPrereleaseIntegrationsChecked(prerelease);
const res = await mutateSettingsAsync({
prerelease_integrations_enabled: prerelease,
});

if (res.error) {
throw res.error;
}
} catch (error) {
setPrereleaseIntegrationsChecked(!prerelease);
notifications.toasts.addError(error, {
title: i18n.translate('xpack.fleet.errorUpdatingSettings', {
defaultMessage: 'Error updating settings',
}),
});
}
},
[mutateSettingsAsync, notifications.toasts]
);

const link = (
<EuiLink href={docLinks.links.fleet.beatsAgentComparison}>
Expand Down Expand Up @@ -153,16 +150,18 @@ export const IntegrationPreference = ({
EventTarget & { checked: boolean }
>
) => {
const isChecked = event.target.checked;
setPrereleaseIntegrationsEnabled(isChecked);
updateSettings(isChecked);
updateSettings(event.target.checked);
};

return (
<EuiPanel hasShadow={false} paddingSize="none">
<EuiSwitchNoWrap
label="Display beta integrations"
checked={!!prereleaseIntegrationsEnabled}
checked={
typeof prereleaseIntegrationsChecked !== 'undefined'
? prereleaseIntegrationsChecked
: prereleaseIntegrationsEnabled
}
onChange={onPrereleaseSwitchChange}
/>
<EuiSpacer size="l" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ function OnPremLink() {
);
}

export const AvailablePackages: React.FC<{
setPrereleaseEnabled: (isEnabled: boolean) => void;
}> = ({ setPrereleaseEnabled }) => {
export const AvailablePackages: React.FC<{ prereleaseIntegrationsEnabled: boolean }> = ({
prereleaseIntegrationsEnabled,
}) => {
useBreadcrumbs('integrations_all');

const {
Expand All @@ -121,11 +121,10 @@ export const AvailablePackages: React.FC<{
setUrlandPushHistory,
setUrlandReplaceHistory,
filteredCards,
setPrereleaseIntegrationsEnabled,
availableSubCategories,
selectedSubCategory,
setSelectedSubCategory,
} = useAvailablePackages();
} = useAvailablePackages({ prereleaseIntegrationsEnabled });

const onCategoryChange = useCallback(
({ id }: { id: string }) => {
Expand All @@ -137,14 +136,6 @@ export const AvailablePackages: React.FC<{
[setCategory, setSearchTerm, setSelectedSubCategory, setUrlandPushHistory]
);

const onPrereleaseEnabledChange = useCallback(
(isEnabled: boolean) => {
setPrereleaseIntegrationsEnabled(isEnabled);
setPrereleaseEnabled(isEnabled);
},
[setPrereleaseIntegrationsEnabled, setPrereleaseEnabled]
);

if (!isLoading && !categoryExists(initialSelectedCategory, allCategories)) {
setUrlandReplaceHistory({ searchString: searchTerm, categoryId: '', subCategoryId: '' });
return null;
Expand All @@ -155,8 +146,8 @@ export const AvailablePackages: React.FC<{
<EuiHorizontalRule margin="m" />
<IntegrationPreference
initialType={preference}
prereleaseIntegrationsEnabled={prereleaseIntegrationsEnabled}
onChange={setPreference}
onPrereleaseEnabledChange={onPrereleaseEnabledChange}
/>
</EuiFlexItem>,
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,83 @@ import React from 'react';

import { createIntegrationsTestRendererMock } from '../../../../../../mock';
import type { PackageListItem } from '../../../../types';
import { ExperimentalFeaturesService } from '../../../../services';

import { getIntegrationLabels } from './card_utils';
import { getIntegrationLabels, mapToCard } from './card_utils';

function renderIntegrationLabels(item: Partial<PackageListItem>) {
const renderer = createIntegrationsTestRendererMock();

return renderer.render(<>{getIntegrationLabels(item as any)}</>);
}

const addBasePath = (s: string) => s;
const getHref = (k: string) => k;

describe('Card utils', () => {
describe('mapToCard', () => {
beforeEach(() => {
ExperimentalFeaturesService.init({});
});

it('should use the installed version if available, without prelease', () => {
const cardItem = mapToCard({
item: {
id: 'test',
version: '2.0.0-preview-1',
installationInfo: {
version: '1.0.0',
},
},
addBasePath,
getHref,
} as any);

expect(cardItem).toMatchObject({
release: 'ga',
version: '1.0.0',
isUpdateAvailable: true,
extraLabelsBadges: undefined,
});
});

it('should use the installed version if available, with prelease ', () => {
const cardItem = mapToCard({
item: {
id: 'test',
version: '2.0.0',
installationInfo: {
version: '1.0.0-preview-1',
},
},
addBasePath,
getHref,
} as any);

expect(cardItem).toMatchObject({
release: 'preview',
version: '1.0.0-preview-1',
isUpdateAvailable: true,
});
});

it('should use the registry version if no installation is available ', () => {
const cardItem = mapToCard({
item: {
id: 'test',
version: '2.0.0-preview-1',
},
addBasePath,
getHref,
} as any);

expect(cardItem).toMatchObject({
release: 'preview',
version: '2.0.0-preview-1',
isUpdateAvailable: false,
});
});
});
describe('getIntegrationLabels', () => {
it('should return an empty list for an integration without errors', () => {
const res = renderIntegrationLabels({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const mapToCard = ({

let isUnverified = false;

const version = 'version' in item ? item.version || '' : '';
let version = 'version' in item ? item.version || '' : '';

let isUpdateAvailable = false;
let isReauthorizationRequired = false;
Expand All @@ -84,17 +84,16 @@ export const mapToCard = ({
? addBasePath(item.uiInternalPath)
: item.uiExternalLink || getAbsolutePath(item.uiInternalPath);
} else {
let urlVersion = item.version;
if (item?.installationInfo?.version) {
urlVersion = item.installationInfo.version || item.version;
version = item.installationInfo.version || item.version;
isUnverified = isPackageUnverified(item, packageVerificationKeyId);
isUpdateAvailable = isPackageUpdatable(item);

isReauthorizationRequired = hasDeferredInstallations(item);
}

const url = getHref('integration_details_overview', {
pkgkey: `${item.name}-${urlVersion}`,
pkgkey: `${item.name}-${version}`,
...(item.integration ? { integration: item.integration } : {}),
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { useState, useMemo } from 'react';
import { useState, useMemo } from 'react';

import { uniq } from 'lodash';

Expand Down Expand Up @@ -103,11 +103,13 @@ const packageListToIntegrationsList = (packages: PackageList): PackageList => {
}, []);
};

export const useAvailablePackages = () => {
export const useAvailablePackages = ({
prereleaseIntegrationsEnabled,
}: {
prereleaseIntegrationsEnabled: boolean;
}) => {
const [preference, setPreference] = useState<IntegrationPreferenceType>('recommended');
const [prereleaseIntegrationsEnabled, setPrereleaseIntegrationsEnabled] = React.useState<
boolean | undefined
>(undefined);

const { showIntegrationsSubcategories } = ExperimentalFeaturesService.get();

const {
Expand Down Expand Up @@ -245,6 +247,5 @@ export const useAvailablePackages = () => {
eprPackageLoadingError,
eprCategoryLoadingError,
filteredCards,
setPrereleaseIntegrationsEnabled,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@
* 2.0.
*/

import React, { useState, useMemo } from 'react';
import React, { useMemo } from 'react';
import { Routes, Route } from '@kbn/shared-ux-router';
import { EuiLoadingSpinner } from '@elastic/eui';

import { installationStatuses } from '../../../../../../../common/constants';

import { INTEGRATIONS_ROUTING_PATHS, INTEGRATIONS_SEARCH_QUERYPARAM } from '../../../../constants';
import { DefaultLayout } from '../../../../layouts';
import { isPackageUpdatable } from '../../../../services';

import { useGetPackagesQuery } from '../../../../hooks';
import { useAuthz, useGetPackagesQuery, useGetSettingsQuery } from '../../../../hooks';

import type { CategoryFacet, ExtendedIntegrationCategory } from './category_facets';

Expand All @@ -41,12 +42,23 @@ export const categoryExists = (category: string, categories: CategoryFacet[]) =>
};

export const EPMHomePage: React.FC = () => {
const [prereleaseEnabled, setPrereleaseEnabled] = useState<boolean>(false);
const authz = useAuthz();
const isAuthorizedToFetchSettings = authz.fleet.all;
const { data: settings, isFetchedAfterMount: isSettingsFetched } = useGetSettingsQuery({
enabled: isAuthorizedToFetchSettings,
});

const prereleaseIntegrationsEnabled = settings?.item.prerelease_integrations_enabled ?? false;
const shouldFetchPackages = !isAuthorizedToFetchSettings || isSettingsFetched;
// loading packages to find installed ones
const { data: allPackages, isLoading } = useGetPackagesQuery({
prerelease: prereleaseEnabled,
});
const { data: allPackages, isLoading } = useGetPackagesQuery(
{
prerelease: prereleaseIntegrationsEnabled,
},
{
enabled: shouldFetchPackages,
}
);

const installedPackages = useMemo(
() =>
Expand Down Expand Up @@ -76,6 +88,11 @@ export const EPMHomePage: React.FC = () => {
const notificationsBySection = {
manage: unverifiedPackageCount + upgradeablePackageCount,
};

if (!shouldFetchPackages) {
return <EuiLoadingSpinner />;
}

return (
<Routes>
<Route path={INTEGRATIONS_ROUTING_PATHS.integrations_installed}>
Expand All @@ -85,7 +102,7 @@ export const EPMHomePage: React.FC = () => {
</Route>
<Route path={INTEGRATIONS_ROUTING_PATHS.integrations_all}>
<DefaultLayout section="browse" notificationsBySection={notificationsBySection}>
<AvailablePackages setPrereleaseEnabled={setPrereleaseEnabled} />
<AvailablePackages prereleaseIntegrationsEnabled={prereleaseIntegrationsEnabled} />
</DefaultLayout>
</Route>
</Routes>
Expand Down
Loading

0 comments on commit 14b22ea

Please sign in to comment.