import { useCollection } from "@awsui/collection-hooks"; import { Box, Container, Header, Link, Modal, Pagination, Select, SelectProps, SpaceBetween, Table, TableProps, TextFilter } from "@awsui/components-react"; import React, { useEffect, useMemo, useState } from "react"; import { FormContextValues } from "react-hook-form"; import { useLocation } from "react-router"; import { usePortingAssistantSelector } from "../../createReduxStore"; import { ApiAnalysisResult, NugetPackage, PackageToPackageAnalysisResult, Project } from "../../models/project"; import { SolutionDetails } from "../../models/solution"; import { selectCurrentSolutionApiAnalysis, selectNugetPackages } from "../../store/selectors/solutionSelectors"; import { compareSemver } from "../../utils/compareSemver"; import { filteringCountText } from "../../utils/FilteringCountText"; import { getTargetFramework } from "../../utils/getTargetFramework"; import { isLoaded } from "../../utils/Loadable"; import { nugetPackageKey } from "../../utils/NugetPackageKey"; import { TableHeader } from "../TableHeader"; import styles from "./NugetPackageUpgrades.module.scss"; import tableStyles from "./Table.module.scss"; interface Props extends Pick { solution: SolutionDetails; projects: Project[]; onChange: (target: { [packageId: string]: SelectProps.Option }) => void; isSubmitting: boolean; value?: { [packageId: string]: SelectProps.Option }; } type DeprecatedApi = { apiName: string; lastVersion?: string }; const escapeNonAlphaNumeric = (solutionPath: string) => { return solutionPath.replace(/[^0-9a-zA-Z]/gi, ""); }; const NugetPackageUpgradesInternal: React.FC = ({ projects, onChange, watch, isSubmitting, value }) => { const location = useLocation(); const nugetPackages = usePortingAssistantSelector(selectNugetPackages); const solutionApiAnalysis = usePortingAssistantSelector(state => selectCurrentSolutionApiAnalysis(state, location.pathname) ); const [selectedNugetPackageVersion, setSelectedNugetPackageVersion] = useState<{ [packageId: string]: SelectProps.Option; }>(value || {}); const target = watch("target"); const [showModal, setShowModal] = useState(false); const [modalItems, setModalItems] = useState([]); const [modalTitle, setModalTitle] = useState(""); const targetFramework = getTargetFramework(); const nugetPackagesInProjects = useMemo( () => Object.values( projects.reduce((agg, cur) => { cur.packageReferences?.forEach(dep => { if (dep.packageId == null) { return; } agg[dep.packageId] = dep; }); return agg; }, {} as { [key: string]: NugetPackage }) ).sort((a, b) => (a.packageId! < b.packageId! ? 0 : 1)), [projects] ); const deprecatedApiByPackageVersion = useMemo(() => { const apisByPackages = projects.reduce((agg, cur) => { const apiAnalysis = solutionApiAnalysis[cur.projectFilePath]; if (!isLoaded(apiAnalysis) || apiAnalysis.data.sourceFileAnalysisResults == null) { return agg; } Object.values(apiAnalysis.data.sourceFileAnalysisResults).forEach(sourceFileAnalysisResult => { sourceFileAnalysisResult.apiAnalysisResults.forEach(api => { const key = api.codeEntityDetails.package?.packageId; const method = api.codeEntityDetails?.originalDefinition; if ( key == null || method == null || !isLoaded( nugetPackages[ nugetPackageKey( api.codeEntityDetails.package?.packageId || "", api.codeEntityDetails.package?.version || "" ) ] ) ) { return; } if ( !nugetPackagesInProjects.some( n => n.packageId.toLocaleLowerCase() === api.codeEntityDetails.package?.packageId.toLocaleLowerCase() && n.version === api.codeEntityDetails.package?.version ) && api.codeEntityDetails != null && api.codeEntityDetails.package?.packageId != null && api.codeEntityDetails.package.packageSourceType === "NUGET" ) { nugetPackagesInProjects.push({ packageId: api.codeEntityDetails.package?.packageId, version: api.codeEntityDetails.package?.version }); } if (agg[key] == null) { agg[key] = []; } agg[key].push(api); }); }); return agg; }, {} as { [nugetPackage: string]: ApiAnalysisResult[] }); const result = {} as { [packageId: string]: { [version: string]: { totalApis: number; deprecatedApis: DeprecatedApi[] } }; }; Object.keys(apisByPackages).forEach(packageId => { result[packageId] = {}; const apis = apisByPackages[packageId]; const packageVersionPair = nugetPackagesInProjects.find( p => p.packageId.toLowerCase() === packageId.toLowerCase() ); const key = nugetPackageKey(packageVersionPair?.packageId || "", packageVersionPair?.version || ""); const nugetPackage = nugetPackages[key]; if (!isLoaded(nugetPackage) || nugetPackage.data.packageVersionPair.version == null) { return; } const apiCompatVersion: { [api: string]: string } = {}; nugetPackage.data.compatibilityResults[targetFramework]?.compatibleVersions .map(v => v) .sort((a, b) => compareSemver(a, b)) .forEach(version => { if (result[packageId][version] === undefined) { result[packageId][version] = { totalApis: 0, deprecatedApis: [] }; } apis .filter(api => api.codeEntityDetails.originalDefinition != null) .forEach(api => { result[packageId][version].totalApis += 1; const apiName = api.codeEntityDetails!.originalDefinition || ""; if (!api.compatibilityResults[targetFramework]?.compatibleVersions?.some(v => v === version)) { result[packageId][version].deprecatedApis.push({ apiName: apiName, lastVersion: apiCompatVersion[apiName] }); } else { apiCompatVersion[apiName] = version; } }); }); }); return result; }, [nugetPackages, nugetPackagesInProjects, projects, solutionApiAnalysis, targetFramework]); useEffect(() => { const defaultupgradetable = nugetPackagesInProjects.reduce( (agg, cur) => { const options = getUpgradeOptions(cur, nugetPackages, target, targetFramework, deprecatedApiByPackageVersion); if (options != null) { agg[cur.packageId] = options[0]; } return agg; }, {} as { [packageId: string]: SelectProps.Option; } ); setSelectedNugetPackageVersion(defaultupgradetable); onChange(defaultupgradetable); }, []); const upgradeTable = useMemo( () => nugetPackagesInProjects .map(nugetPackageInProject => { const nugetPackage = nugetPackages[nugetPackageKey(nugetPackageInProject?.packageId, nugetPackageInProject?.version)]; if (!isLoaded(nugetPackage)) { return null; } const options = getUpgradeOptions( nugetPackageInProject, nugetPackages, target, targetFramework, deprecatedApiByPackageVersion ); if (options == null) { return null; } const selectedApi = getDeprecatedApis( nugetPackageInProject, selectedNugetPackageVersion, deprecatedApiByPackageVersion ); return (
{nugetPackage.data.packageVersionPair.packageId}
Current version: {nugetPackageInProject.version}