import { useCollection } from "@awsui/collection-hooks"; import { Box, Button, Pagination, Table, TableProps, TextFilter } from "@awsui/components-react"; import StatusIndicator from "@awsui/components-react/status-indicator"; import { MemoryHistory } from "history"; import React, { useMemo } from "react"; import { useSelector } from "react-redux"; import { matchPath, useLocation } from "react-router"; import { useHistory } from "react-router-dom"; import { pathValues } from "../../constants/paths"; import { RuleContribSource } from "../../containers/RuleContribution"; import { usePortingAssistantSelector } from "../../createReduxStore"; import { HistoryState } from "../../models/locationState"; import { Compatibility, NugetPackage } from "../../models/project"; import { selectNugetPackages, selectProjects } from "../../store/selectors/solutionSelectors"; import { selectNugetTableData } from "../../store/selectors/tableSelectors"; import { filteringCountText } from "../../utils/FilteringCountText"; import { isFailed, isLoaded } from "../../utils/Loadable"; import { nugetPackageKey } from "../../utils/NugetPackageKey"; import { InfoLink } from "../InfoLink"; import { LinkComponent } from "../LinkComponent"; import { TableHeader } from "../TableHeader"; export type NugetPackageTableFields = NugetPackage & { frequency: number; sourceFiles: number; sourceFilesList: string[]; apis: number; apiSet: Set; replacement: string; compatible: Compatibility; failed: boolean; deprecated: boolean; }; const NugetPackageTableInternal: React.FC = () => { const location = useLocation(); const history = useHistory() as MemoryHistory; const nugetPackages = useSelector(selectNugetPackages); const nugetPackagesWithFields = usePortingAssistantSelector(state => selectNugetTableData(state, location.pathname)); const projects = usePortingAssistantSelector(state => selectProjects(state, location.pathname)); const [selectedItem, setSelectedItem] = React.useState([]); const canSuggestRule = () => { if (selectedItem.length === 0) { return false; } const item = selectedItem[0]; if (item.compatible === "INCOMPATIBLE") { return true; } return false; }; const getSourceData = () => { if (selectedItem.length === 0) { return; } const item = selectedItem[0]; const sourceData: RuleContribSource = { type: "PACKAGE", packageName: item.packageId, packageVersion: item.version }; return sourceData; }; const isSingleProject = useMemo(() => { const match = matchPath<{ solution: string; project: string }>(location.pathname, { path: pathValues, exact: true, strict: false }); if (match == null || match.params?.project == null) { return false; } return true; }, [location.pathname]); const isTableLoading = useMemo(() => { if (!isLoaded(projects)) { return false; } const allNugetpackages = projects.data.flatMap(p => p.packageReferences || []); if (allNugetpackages.length === 0) { return false; } return ( allNugetpackages.filter( dep => dep.packageId != null && (isLoaded(nugetPackages[nugetPackageKey(dep.packageId, dep.version)]) || isFailed(nugetPackages[nugetPackageKey(dep.packageId, dep.version)])) ).length === 0 ); }, [nugetPackages, projects]); const columnDefinitions: TableProps.ColumnDefinition[] = [ { id: "package-id", header: "Name", cell: item =>
{item.packageId}
, sortingField: "packageId" }, { id: "package-version", header: "Version", cell: item =>
{item.version}
, sortingField: "version" }, { id: "projects", header: "Projects", cell: item =>
{item.frequency}
, sortingField: "frequency" }, { id: "source-files", header: "Source Files", cell: item =>
{item.sourceFiles}
, sortingField: "sourceFiles" }, { id: "apis", header: "APIs", cell: item =>
{item.apis}
, sortingField: "apis" }, { id: "status", header: "Status", cell: item => (
{item.failed ? ( Failed ) : item.compatible === "COMPATIBLE" ? ( Compatible ) : item.compatible === "UNKNOWN" ? ( Unknown ) : item.deprecated ? ( Deprecated ) : ( Incompatible )}
), sortingField: "compatible" // minWidth: "150px" }, { id: "suggested-replacement", header: "Suggested replacement", cell: item => (
{item.replacement}
), sortingField: "replacement" } ]; const columnDefinitionWithProject = columnDefinitions.filter( definition => definition.id !== "projects" || !isSingleProject ); const { items, filteredItemsCount, collectionProps, filterProps, paginationProps } = useCollection( nugetPackagesWithFields, { filtering: { empty: empty }, pagination: {}, sorting: {} } ); const ruleContributeButton = ( ); return ( {...collectionProps} loadingText="Loading packages" columnDefinitions={columnDefinitionWithProject} loading={isTableLoading} items={items} selectedItems={selectedItem} selectionType="single" onSelectionChange={({ detail }) => setSelectedItem(detail.selectedItems)} filter={ } pagination={} header={ A NuGet package is a single .zip file that includes compiled code, files related to the code, and a descriptive manifest. Columns Name - Name of the NuGet package. Version - The package version. Projects - The number of projects that include the NuGet package. Source files - The number of source files that include APIs from the Nuget package. APIs - The number of instances of API calls from the package within the project. Status - Compatibility status of the NuGet package. Suggested replacements - Suggested replacements for compatiblity. Notes: Porting Assistant does not support assessing the compatibility of private NuGet packages. Private NuGet packages will have the compatibility result of unknown. To assess the compatibility of private NuGet packages, add the solution of the package as a separate assessment. } learnMoreLinks={[ { externalUrl: "https://docs.microsoft.com/en-us/nuget/what-is-nuget", text: "An introduction to NuGet" } ]} /> } /> } empty={empty} > ); }; const empty = ( No NuGet packages No NuGet packages to display. ); const escapeNonAlphaNumeric = (solutionPath: string) => { return solutionPath.replace(/[^0-9a-zA-Z]/gi, ""); }; export const NugetPackageTable = React.memo(NugetPackageTableInternal);