debian-image-builder-frontend/src/Components/CreateImageWizardV2/steps/Packages/PackageRecommendations.tsx
regexowl 054dc42842 V2Wizard: Add descriptions to package recommendations
After the list of package recommendations is fetched, each of the packages gets queried as a searchTerm against the list of distribution repositories.

This fetched the summary of the package which can be used as a description.
2024-06-06 10:33:26 +03:00

206 lines
6.4 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import {
Alert,
Button,
ExpandableSection,
Icon,
Panel,
PanelMain,
PanelMainBody,
Spinner,
Text,
TextContent,
} from '@patternfly/react-core';
import { OptimizeIcon } from '@patternfly/react-icons';
import { Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table';
import { useDispatch } from 'react-redux';
import PackageRecommendationDescription from './components/PackageRecommendationDescription';
import { RedHatRepository } from './Packages';
import { useListRepositoriesQuery } from '../../../../store/contentSourcesApi';
import { useAppSelector } from '../../../../store/hooks';
import { useRecommendPackageMutation } from '../../../../store/imageBuilderApi';
import {
addPackage,
selectArchitecture,
selectDistribution,
selectPackages,
} from '../../../../store/wizardSlice';
import { releaseToVersion } from '../../../../Utilities/releaseToVersion';
import useDebounce from '../../../../Utilities/useDebounce';
const PackageRecommendations = () => {
const dispatch = useDispatch();
const arch = useAppSelector(selectArchitecture);
const distribution = useAppSelector(selectDistribution);
const version = releaseToVersion(distribution);
const undebouncedPackages = useAppSelector(selectPackages);
const packages = useDebounce(undebouncedPackages);
let distroRepoUrls: string[] = [];
const [isExpanded, setIsExpanded] = useState(true);
const { data: distroRepositories, isSuccess: isSuccessDistroRepositories } =
useListRepositoriesQuery({
availableForArch: arch,
availableForVersion: version,
contentType: 'rpm',
origin: 'red_hat',
limit: 100,
offset: 0,
});
if (isSuccessDistroRepositories && distroRepositories.data) {
distroRepoUrls = distroRepositories.data.map((repo) => repo.url || '');
}
const [fetchRecommendedPackages, { data, isSuccess, isLoading, isError }] =
useRecommendPackageMutation();
useEffect(() => {
if (isExpanded && packages.length > 0) {
(async () => {
await fetchRecommendedPackages({
recommendPackageRequest: {
packages: packages.map((pkg) => pkg.name),
recommendedPackages: 5,
},
});
})();
}
}, [fetchRecommendedPackages, packages, isExpanded]);
const addAllPackages = () => {
if (data?.packages?.length) {
data.packages.forEach((pkg) =>
dispatch(
addPackage({
name: pkg,
summary: 'Added from recommended packages',
repository: 'distro',
})
)
);
}
};
const addRecommendedPackage = (pkg: string) => {
dispatch(
addPackage({
name: pkg,
summary: 'Added from recommended packages',
repository: 'distro',
})
);
};
const isRecommendedPackageSelected = (recPkg: string) => {
const foundInPackages = packages?.some((pkg) => recPkg === pkg.name);
return foundInPackages;
};
return (
<Panel variant="bordered" className="panel-border">
<PanelMain>
<PanelMainBody>
<ExpandableSection
toggleContent={
<>
<Icon>
<OptimizeIcon />
</Icon>{' '}
Recommended Red Hat packages
</>
}
onToggle={(_, bool) => setIsExpanded(bool)}
isExpanded={isExpanded}
>
{packages.length === 0 && (
<>Select packages to generate recommendations.</>
)}
{isLoading && <Spinner size="lg" />}
{isError && (
<Alert
title="Recommendations couldn't be fetched"
variant="danger"
isPlain
isInline
>
There was an error when fetching package recommendations. Try
again by changing your selected packages.
</Alert>
)}
{isSuccess && !data?.packages?.length && (
<>No recommendations found for the set of selected packages</>
)}
{isSuccess && data && data?.packages && (
<>
<TextContent>
<Text>
Other users commonly add these packages with the ones you
selected.
</Text>
</TextContent>
<Table variant="compact">
<Thead>
<Tr>
<Th width={20}>Package name</Th>
<Th width={35}>Description</Th>
<Th width={25}>Package repository</Th>
<Th width={20}>
<Button
variant="link"
component="a"
onClick={() => addAllPackages()}
isInline
data-testid="add-all-recommendations-button"
>
Add all packages
</Button>
</Th>
</Tr>
</Thead>
<Tbody>
{data.packages.map((pkg) => (
<Tr key={pkg}>
<Td>{pkg}</Td>
<Td>
{distroRepoUrls && (
<PackageRecommendationDescription
pkg={pkg}
urls={distroRepoUrls}
/>
)}
</Td>
<Td>
<RedHatRepository />
</Td>
<Td>
<Button
variant="link"
component="a"
onClick={() => addRecommendedPackage(pkg)}
isInline
isDisabled={isRecommendedPackageSelected(pkg)}
data-testid="add-recommendation-button"
>
Add package
</Button>
</Td>
</Tr>
))}
</Tbody>
</Table>
</>
)}
</ExpandableSection>
</PanelMainBody>
</PanelMain>
</Panel>
);
};
export default PackageRecommendations;