import { Box, ColumnLayout, Container, Header, SpaceBetween, Spinner } from "@awsui/components-react"; import React, { useEffect, useMemo, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useLocation } from "react-router"; import { v4 as uuid } from "uuid"; import { usePortingAssistantSelector } from "../../createReduxStore"; import { Project } from "../../models/project"; import { SolutionDetails } from "../../models/solution"; import { pushCurrentMessageUpdate, removeCurrentMessageUpdate } from "../../store/actions/error"; import { selectCurrentSolutionApiAnalysis, selectCurrentSolutionDetails, selectCurrentSolutionPath, selectCurrentSolutionStatus, selectNugetPackages } from "../../store/selectors/solutionSelectors"; import { getActionCounts, getErrorCounts } from "../../store/selectors/tableSelectors"; import { API_COMPATABILITIES, API_LOADING_AGGREGATE, getCompatibleApi } from "../../utils/getCompatibleApi"; import { getCompatibleNugetsAgg, LOADING_AGGREGATES, NUGET_COMPATABILITIES } from "../../utils/getCompatibleNugets"; import { getTargetFramework } from "../../utils/getTargetFramework"; import { hasNewData, isLoaded, isLoading, isLoadingWithData, Loadable } from "../../utils/Loadable"; import { CompatiblePackage } from "../AssessShared/CompatiblePackage"; import { SummaryItem } from "../AssessShared/SummaryItem"; import { InfoLink } from "../InfoLink"; interface Props { solution: Loadable; projects: Loadable; } const SolutionSummaryInternal: React.FC = ({ solution, projects }) => { const location = useLocation(); const dispatch = useDispatch(); const nugetPackages = useSelector(selectNugetPackages); const solutionProjects = usePortingAssistantSelector(state => selectCurrentSolutionDetails(state, location.pathname)); const apiAnalysis = usePortingAssistantSelector(state => selectCurrentSolutionApiAnalysis(state, location.pathname)); const targetFramework = getTargetFramework(); const solutionPath = usePortingAssistantSelector(state => selectCurrentSolutionPath(state, location.pathname)) const solutionStatus = usePortingAssistantSelector(state => selectCurrentSolutionStatus(state, location.pathname)); const cancel = solutionStatus.isCancelled; const nugetCompatibilities = useMemo(() => { if (!hasNewData(projects)) { console.log("Does not have new data"); return LOADING_AGGREGATES; } return getCompatibleNugetsAgg( projects.data.flatMap(p => p.packageReferences || []), nugetPackages ); }, [nugetPackages, projects]); const apiCompatibilities = useMemo(() => { if (!hasNewData(projects)) { return API_LOADING_AGGREGATE; } if (projects.data.length === 0) { return { failureCount: 0, isApisLoading: false, values: [0, 0] }; } return getCompatibleApi(solutionProjects, apiAnalysis, null, null, targetFramework); }, [apiAnalysis, projects, solutionProjects, targetFramework]); const buildErrors = useMemo(() => { if (!hasNewData(projects)) { return 0; } if (projects.data.length === 0) { return 0; } return getErrorCounts(apiAnalysis); }, [apiAnalysis, projects]); const portingActions = useMemo(() => { if (!hasNewData(projects)) { return 0; } if (projects.data.length === 0) { return 0; } return getActionCounts(apiAnalysis); }, [apiAnalysis, projects]); const [shownLoadingMessage, setShownLoadingMessage] = useState(false); useEffect(() => { if ((!nugetCompatibilities.isAllNugetLoaded || apiCompatibilities.isApisLoading) && !cancel) { dispatch( pushCurrentMessageUpdate({ messageId: uuid(), groupId: "assess", type: "success", loading: true, content: `Assessing your source code. This can take a few minutes.`, dismissible: false }) ); setShownLoadingMessage(true); } else if (shownLoadingMessage) { dispatch(removeCurrentMessageUpdate({ groupId: "assess" })); setShownLoadingMessage(false); if (cancel) { dispatch(removeCurrentMessageUpdate({ groupId: "cancel-assessment" })); dispatch( pushCurrentMessageUpdate({ messageId: uuid(), groupId: "assessSuccess", type: "success", content: `Successfully cancelled assessment.`, dismissible: true }) ); } else { dispatch( pushCurrentMessageUpdate({ messageId: uuid(), groupId: "assessSuccess", type: "success", content: `Successfully assessed your source code.`, dismissible: true }) ); } } }, [apiCompatibilities.isApisLoading, dispatch, nugetCompatibilities.isAllNugetLoaded, shownLoadingMessage, cancel, solutionPath]); return ( The level of compatibility will affect the effort required to port your solution to .NET Core. } > Assessment overview } >
Porting Assistant for .NET parses package reference files for each project in the .NET Framework solution and iterates through each referenced public and private NuGet package to check whether the latest version of the package that is compatible with .NET Core is available. To speed up the process, Porting Assistant for .NET includes a precompiled database of all public NuGet packages and their compatibility status. For private packages, Porting Assistant for .NET uses dotnet tools to determine the compatibility of a package. } learnMoreLinks={[ { externalUrl: "https://docs.microsoft.com/en-us/nuget/what-is-nuget", text: "An introduction to NuGet" } ]} /> } />
Porting Assistant for .NET analyzes source code of your .NET application. It identifies incompatible API calls made from each NuGet package and checks whether a NuGet package is compatible with .NET Core. } learnMoreLinks={[]} /> } />
The number of build errors in the assessed solution.} learnMoreLinks={[]} /> } content={apiCompatibilities.isApisLoading?
{buildErrors}
: buildErrors} />
The number of porting actions in the assessed solution.} learnMoreLinks={[]} /> } content={apiCompatibilities.isApisLoading?
{portingActions}
: portingActions} />
); }; export const SolutionSummary = React.memo(SolutionSummaryInternal);