diff --git a/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx b/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx index 56b6cf738f..cf05a18ba5 100644 --- a/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx +++ b/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx @@ -2,9 +2,9 @@ import React from "react"; import { useTranslation } from "react-i18next"; import { Spinner } from "@patternfly/react-core"; import { EmptyTextMessage } from "@app/components/EmptyTextMessage"; -import { Application } from "@app/api/models"; +import { Application, Assessment } from "@app/api/models"; import { IconedStatus, IconedStatusPreset } from "@app/components/IconedStatus"; -import { useFetchAssessmentsByItemId } from "@app/queries/assessments"; +import { useFetchAssessments } from "@app/queries/assessments"; import { useFetchArchetypes } from "@app/queries/archetypes"; interface ApplicationAssessmentStatusProps { application: Application; @@ -16,58 +16,103 @@ export const ApplicationAssessmentStatus: React.FC< > = ({ application }) => { const { t } = useTranslation(); - const { archetypes, isFetching } = useFetchArchetypes(); + const { archetypes, isFetching } = useFetchArchetypes(application); + const { assessments, fetchError } = useFetchAssessments(); - const applicationArchetypes = application.archetypes?.map((archetypeRef) => { - return archetypes?.find((archetype) => archetype.id === archetypeRef.id); - }); - - const someArchetypesAssessed = applicationArchetypes?.some( - (archetype) => !!archetype?.assessments?.length ?? 0 > 0 + const filteredAssessments = assessments?.filter( + (assessment: Assessment) => assessment.application?.id === application.id ); - const areAllArchetypesAssessed = - applicationArchetypes?.every( - (archetype) => archetype?.assessments?.length ?? 0 > 0 - ) ?? false; + const assessmentStatusInfo = React.useMemo(() => { + const assessmentsWithArchetypes = archetypes.map((archetype) => ({ + archetype, + assessments: assessments.filter( + (assessment) => assessment.archetype?.id === archetype.id + ), + })); - const { - assessments, - isFetching: isFetchingAssessmentsById, - fetchError, - } = useFetchAssessmentsByItemId(false, application.id); + const someArchetypesAssessed = assessmentsWithArchetypes.some( + ({ assessments }) => assessments.length > 0 + ); + + const allArchetypesAssessed = + assessmentsWithArchetypes.length > 0 && + assessmentsWithArchetypes.every(({ archetype, assessments }) => { + const requiredAssessments = assessments.filter( + (assessment) => assessment.required + ); + return ( + archetype.assessed && + assessments.length > 0 && + requiredAssessments.length > 0 && + requiredAssessments.every( + (assessment) => assessment.status === "complete" + ) + ); + }); + + const hasInProgressOrNotStartedRequiredAssessments = + assessmentsWithArchetypes.some(({ assessments }) => + assessments.some( + (assessment) => + assessment.required && + ["empty", "started"].includes(assessment.status) + ) + ); + + const assessedArchetypesWithARequiredAssessment = + assessmentsWithArchetypes.filter(({ assessments, archetype }) => + assessments.some( + (assessment) => + assessment.required && + assessment.status === "complete" && + archetype.assessed + ) + ); + const assessedArchetypeCount = + archetypes?.filter( + (archetype) => + archetype?.assessments?.length ?? (0 > 0 && archetype.assessed) + ).length || 0; + + return { + assessmentsWithArchetypes, + someArchetypesAssessed, + allArchetypesAssessed, + hasInProgressOrNotStartedRequiredAssessments, + assessedArchetypesWithARequiredAssessment, + assessedArchetypeCount, + }; + }, [archetypes, assessments]); if (fetchError) { return ; } - if (isFetching || isFetchingAssessmentsById) { + if (isFetching || isFetching) { return ; } let statusPreset: IconedStatusPreset = "NotStarted"; // Default status let tooltipCount: number = 0; - const assessedArchetypeCount = - applicationArchetypes?.filter( - (archetype) => archetype?.assessments?.length ?? 0 > 0 - ).length || 0; - const isDirectlyAssessed = application.assessed && (application.assessments?.length ?? 0) > 0; + const { + allArchetypesAssessed, + assessedArchetypesWithARequiredAssessment, + hasInProgressOrNotStartedRequiredAssessments, + } = assessmentStatusInfo; if (isDirectlyAssessed) { statusPreset = "Completed"; - } else if (areAllArchetypesAssessed) { + } else if (allArchetypesAssessed) { statusPreset = "InheritedAssessments"; - tooltipCount = assessedArchetypeCount; - } else if (someArchetypesAssessed) { + tooltipCount = assessedArchetypesWithARequiredAssessment.length; + } else if (hasInProgressOrNotStartedRequiredAssessments) { statusPreset = "InProgressInheritedAssessments"; - tooltipCount = assessedArchetypeCount; + tooltipCount = assessedArchetypesWithARequiredAssessment.length; } else if ( - assessments?.some( - (assessment) => - assessment.status === "started" || assessment.status === "complete" - ) + filteredAssessments?.some((assessment) => assessment.status === "started") ) { statusPreset = "InProgress"; } diff --git a/client/src/app/pages/applications/components/application-detail-drawer/components/assessed-archetypes.tsx b/client/src/app/pages/applications/components/application-detail-drawer/components/assessed-archetypes.tsx index 89503af756..03da85083e 100644 --- a/client/src/app/pages/applications/components/application-detail-drawer/components/assessed-archetypes.tsx +++ b/client/src/app/pages/applications/components/application-detail-drawer/components/assessed-archetypes.tsx @@ -1,10 +1,10 @@ import React from "react"; -import { Application } from "@app/api/models"; +import { Application, AssessmentWithSectionOrder } from "@app/api/models"; import { Label, LabelGroup, Spinner } from "@patternfly/react-core"; import { EmptyTextMessage } from "@app/components/EmptyTextMessage"; import { useTranslation } from "react-i18next"; import { useFetchArchetypes } from "@app/queries/archetypes"; -import { useFetchAllAssessmentsWithArchetypes } from "@app/queries/assessments"; +import { useFetchAssessments } from "@app/queries/assessments"; interface IAssessedArchetypesProps { application: Application | null; @@ -14,35 +14,33 @@ export const AssessedArchetypes: React.FC = ({ application, }) => { const { t } = useTranslation(); - const { - archetypes: applicationArchetypes, - isFetching: isFetchingArchetypes, - } = useFetchArchetypes(application); + const { archetypes, isFetching: isFetchingArchetypes } = + useFetchArchetypes(application); + const { assessments, isFetching: isFetchingAssessments } = + useFetchAssessments(); - const { - assessmentsWithArchetypes, - isLoading: isFetchingAllAssessmentsWithArchetypesLoading, - } = useFetchAllAssessmentsWithArchetypes(applicationArchetypes); + const assessedArchetypes = React.useMemo(() => { + if (!archetypes || !assessments) return []; - const assessedArchetypesWithARequiredAssessment = assessmentsWithArchetypes - ?.filter((assessmentsWithArchetype) => { - return ( - assessmentsWithArchetype.archetype.assessed && - assessmentsWithArchetype.assessments.some( - (assessment) => assessment?.required === true - ) - ); - }) - .map((assessmentsWithArchetype) => assessmentsWithArchetype.archetype); + return archetypes.filter((archetype) => + assessments.some( + (assessment: AssessmentWithSectionOrder) => + assessment.archetype?.id === archetype.id && + assessment.required && + archetype.assessed + ) + ); + }, [archetypes, assessments]); - if (isFetchingArchetypes || isFetchingAllAssessmentsWithArchetypesLoading) { + if (isFetchingArchetypes || isFetchingAssessments) { return ; } + return ( - {assessedArchetypesWithARequiredAssessment?.length ? ( - assessedArchetypesWithARequiredAssessment?.map((archetype) => ( - + {assessedArchetypes.length ? ( + assessedArchetypes.map((archetype) => ( + )) ) : ( diff --git a/client/src/app/queries/archetypes.ts b/client/src/app/queries/archetypes.ts index 7cd3b45051..a740d564d2 100644 --- a/client/src/app/queries/archetypes.ts +++ b/client/src/app/queries/archetypes.ts @@ -27,7 +27,6 @@ export const useFetchArchetypes = (forApplication?: Application | null) => { initialData: [], queryKey: [ARCHETYPES_QUERY_KEY, forApplication?.id], queryFn: getArchetypes, - refetchInterval: 5000, onSuccess: (fetchedArchetypes) => { if (!forApplication) { setFilteredArchetypes(fetchedArchetypes); @@ -42,6 +41,7 @@ export const useFetchArchetypes = (forApplication?: Application | null) => { } else { setFilteredArchetypes([]); } + queryClient.invalidateQueries([reviewsQueryKey]); queryClient.invalidateQueries([assessmentsQueryKey]); queryClient.invalidateQueries([assessmentsByItemIdQueryKey]); diff --git a/client/src/app/queries/assessments.ts b/client/src/app/queries/assessments.ts index 77cd04d579..8b6cfab07b 100644 --- a/client/src/app/queries/assessments.ts +++ b/client/src/app/queries/assessments.ts @@ -17,11 +17,9 @@ import { } from "@app/api/rest"; import { AxiosError } from "axios"; import { - Archetype, Assessment, AssessmentWithArchetypeApplications, AssessmentWithSectionOrder, - AssessmentsWithArchetype, InitialAssessment, } from "@app/api/models"; import { QuestionnairesQueryKey } from "./questionnaires"; @@ -264,33 +262,3 @@ export const useFetchAssessmentsWithArchetypeApplications = () => { isLoading: assessmentsLoading || isArchetypesLoading, }; }; - -export const useFetchAllAssessmentsWithArchetypes = ( - archetypes: Archetype[] = [] -) => { - const assessmentQueries = useQueries({ - queries: archetypes.map((archetype) => ({ - queryKey: ["assessmentsForArchetype", archetype.id], - queryFn: () => getAssessmentsByItemId(true, archetype.id), - })), - }); - - const assessmentsWithArchetypes: AssessmentsWithArchetype[] = - assessmentQueries - .map((query, index) => { - if (query.isSuccess) { - return { - archetype: archetypes[index], - assessments: query.data, - }; - } - return null; - }) - .filter(Boolean); - - return { - assessmentsWithArchetypes, - isLoading: assessmentQueries.some((query) => query.isLoading), - isError: assessmentQueries.some((query) => query.isError), - }; -};