From 44a40e8e7d52817d8cccff91b7d3ce2b092ce761 Mon Sep 17 00:00:00 2001 From: Gilles Dubreuil Date: Thu, 21 Sep 2023 19:39:32 +0200 Subject: [PATCH] :sparkles: Reports: select Questionnaires (#1374) Shows selection of possible questionnaires of current assessments Pass to ``: - If "All questionnaires" option has been selected then the whole assessments list is passed - When a specific questionnaire is selected then only the assessments bound to that questionnaire are passed. The consolidation of the risks is left to be handled by the Landscape component in following PR. https://github.com/konveyor/tackle2-ui/issues/1305 ![image](https://github.com/konveyor/tackle2-ui/assets/1901741/c48b117f-7f5a-46e9-ac83-22cb7b14d85f) --------- Signed-off-by: Gilles Dubreuil Co-authored-by: Scott Dickerson --- client/public/locales/en/translation.json | 7 +- client/public/locales/es/translation.json | 7 +- client/src/app/api/models.ts | 5 - client/src/app/api/rest.ts | 3 + .../reports/components/landscape/donut.tsx | 2 +- .../components/landscape/landscape.tsx | 30 +++-- client/src/app/pages/reports/reports.tsx | 115 +++++++++++++++++- client/src/app/queries/assessments.ts | 13 ++ 8 files changed, 149 insertions(+), 33 deletions(-) diff --git a/client/public/locales/en/translation.json b/client/public/locales/en/translation.json index c64b5bc8af..fc6872bb39 100644 --- a/client/public/locales/en/translation.json +++ b/client/public/locales/en/translation.json @@ -71,7 +71,8 @@ "orange": "Orange", "purple": "Purple", "red": "Red", - "teal": "Teal" + "teal": "Teal", + "yellow": "Yellow" }, "composed": { "add": "Add {{what}}", @@ -243,7 +244,6 @@ "businessServices": "Business services", "canceled": "Canceled", "category": "Category", - "cloudNativeReady": "Cloud-native ready", "color": "Color", "comments": "Comments", "completed": "Completed", @@ -311,7 +311,6 @@ "member(s)": "Member(s)", "memberCount": "Member count", "message": "Message", - "modernizable": "Modernizable", "migrationWave": "Migration wave", "migrationWaves": "Migration waves", "migrationWave(s)": "Migration wave(s)", @@ -322,7 +321,6 @@ "notConnected": "Not connected", "notReviewed": "Not reviewed", "notStarted": "Not started", - "notYetAssessed": "Not yet assessed", "notYetReviewed": "Not yet reviewed", "other": "Other", "owner": "Owner", @@ -384,7 +382,6 @@ "unassessed": "Unassessed", "unassigned": "Not yet assigned", "unknown": "Unknown", - "unsuitableForContainers": "Unsuitable for containers", "uploadApplicationFile": "Upload your application file", "uploadYamlFile": "Upload your YAML file", "url": "URL", diff --git a/client/public/locales/es/translation.json b/client/public/locales/es/translation.json index 5bfde9d167..12f96255f9 100644 --- a/client/public/locales/es/translation.json +++ b/client/public/locales/es/translation.json @@ -55,7 +55,8 @@ "green": "Verde", "orange": "Naranja", "purple": "Morado", - "red": "Rojo" + "red": "Rojo", + "yellow": "Amarillo" }, "composed": { "add": "Agregar {{what}}", @@ -194,7 +195,6 @@ "businessServices": "Servicios de negocio", "canceled": "Cancelado", "category": "Categoría", - "cloudNativeReady": "Listo para Cloud-native", "color": "Color", "comments": "Comentarios", "completed": "Completado", @@ -247,13 +247,11 @@ "member(s)": "Miembro(s)", "memberCount": "Número de miembros", "message": "Mensaje", - "modernizable": "Modernizable", "name": "Nombre", "northboundDependencies": "Dependencias del norte", "notAvailable": "No disponible", "notReviewed": "No revisado", "notStarted": "No empezado", - "notYetAssessed": "No evaluado todavía", "notYetReviewed": "No revisado todavía", "other": "Otro", "owner": "Propietario", @@ -304,7 +302,6 @@ "trivialButMigratable": "Trivial pero migrable", "unassessed": "No evaluado", "unknown": "Desconocido", - "unsuitableForContainers": "No apto para contenedores", "uploadApplicationFile": "Carga tu archivo con aplicaciones", "user": "Usuario", "version": "Versión", diff --git a/client/src/app/api/models.ts b/client/src/app/api/models.ts index d4ad356db9..4df69028ae 100644 --- a/client/src/app/api/models.ts +++ b/client/src/app/api/models.ts @@ -723,11 +723,6 @@ export interface AssessmentRisk { applicationId: number; risk: Risk; } -export interface AssessmentRisk { - assessmentId: number; - applicationId: number; - risk: Risk; -} export interface AssessmentQuestionRisk { category: string; diff --git a/client/src/app/api/rest.ts b/client/src/app/api/rest.ts index 18e803352f..e9b06be9e9 100644 --- a/client/src/app/api/rest.ts +++ b/client/src/app/api/rest.ts @@ -205,6 +205,9 @@ export const getApplicationSummaryCSV = (id: string): AxiosPromise => { }); }; +export const getAssessments = (): Promise => + axios.get(ASSESSMENTS).then((response) => response.data); + export const getAssessmentsByItemId = ( isArchetype: boolean, itemId?: number | string diff --git a/client/src/app/pages/reports/components/landscape/donut.tsx b/client/src/app/pages/reports/components/landscape/donut.tsx index b3612229b1..5c0f4bacce 100644 --- a/client/src/app/pages/reports/components/landscape/donut.tsx +++ b/client/src/app/pages/reports/components/landscape/donut.tsx @@ -11,7 +11,7 @@ export interface IDonutProps { total: number; color: string; riskLabel: string; - riskDescription: string; + riskDescription?: string; } export const Donut: React.FC = ({ diff --git a/client/src/app/pages/reports/components/landscape/landscape.tsx b/client/src/app/pages/reports/components/landscape/landscape.tsx index c21b229fda..7c500cd922 100644 --- a/client/src/app/pages/reports/components/landscape/landscape.tsx +++ b/client/src/app/pages/reports/components/landscape/landscape.tsx @@ -7,7 +7,7 @@ import { ConditionalRender } from "@app/components/ConditionalRender"; import { StateError } from "@app/components/StateError"; import { RISK_LIST } from "@app/Constants"; -import { AssessmentRisk } from "@app/api/models"; +import { Assessment, AssessmentRisk } from "@app/api/models"; import { ApplicationSelectionContext } from "../../application-selection-context"; import { NoApplicationSelectedEmptyState } from "../no-application-selected-empty-state"; @@ -48,7 +48,11 @@ const extractLandscapeData = ( return { low, medium, high, unassessed }; }; -export const Landscape: React.FC = () => { +interface ILandscapeProps { + assessments: Assessment[]; +} + +export const Landscape: React.FC = ({ assessments }) => { const { t } = useTranslation(); // Context @@ -89,11 +93,11 @@ export const Landscape: React.FC = () => { @@ -101,17 +105,17 @@ export const Landscape: React.FC = () => { value={landscapeData.medium} total={applications.length} color={RISK_LIST["yellow"].hexColor} - riskLabel={t("terms.mediumRisk")} - riskDescription={t("terms.modernizable")} + riskLabel={t("colors.yellow")} + // riskDescription={} /> @@ -119,8 +123,8 @@ export const Landscape: React.FC = () => { value={landscapeData.unassessed} total={applications.length} color={RISK_LIST["unknown"].hexColor} - riskLabel={t("terms.unassessed")} - riskDescription={t("terms.notYetAssessed")} + riskLabel={`${t("terms.unassessed")}/${t("terms.unknown")}`} + // riskDescription={} /> diff --git a/client/src/app/pages/reports/reports.tsx b/client/src/app/pages/reports/reports.tsx index 5b5aa4b2ea..3a085a639d 100644 --- a/client/src/app/pages/reports/reports.tsx +++ b/client/src/app/pages/reports/reports.tsx @@ -9,9 +9,15 @@ import { CardExpandableContent, CardHeader, CardTitle, + Flex, + FlexItem, + MenuToggle, + MenuToggleElement, PageSection, PageSectionVariants, Popover, + Select, + SelectOption, Split, SplitItem, Stack, @@ -31,11 +37,27 @@ import { Landscape } from "./components/landscape"; import { AdoptionPlan } from "./components/adoption-plan"; import { IdentifiedRisksTable } from "./components/identified-risks-table"; import { useFetchApplications } from "@app/queries/applications"; +import { useFetchAssessments } from "@app/queries/assessments"; +import { Ref } from "@app/api/models"; + +const ALL_QUESTIONNAIRES = "All questionnaires"; export const Reports: React.FC = () => { // i18 const { t } = useTranslation(); + const [isQuestionnaireSelectOpen, setIsQuestionnaireSelectOpen] = + React.useState(false); + + const [selectedQuestionnaire, setSelectedQuestionnaire] = + React.useState("All questionnaires"); + + const { + assessments, + isFetching: isAssessmentsFetching, + fetchError: assessmentsFetchError, + } = useFetchAssessments(); + // Cards const [isAdoptionCandidateTable, setIsAdoptionCandidateTable] = useState(true); @@ -66,6 +88,48 @@ export const Reports: React.FC = () => { ); } + const toggleQuestionnaire = (toggleRef: React.Ref) => ( + { + setIsQuestionnaireSelectOpen(!isQuestionnaireSelectOpen); + }} + isExpanded={isQuestionnaireSelectOpen} + > + {selectedQuestionnaire} + + ); + + const onSelectQuestionnaire = ( + _event: React.MouseEvent | undefined, + value: string | number | undefined + ) => { + setSelectedQuestionnaire(value as string); + setIsQuestionnaireSelectOpen(false); + }; + + const answeredQuestionnaires: Ref[] = + isAssessmentsFetching || assessmentsFetchError + ? [] + : assessments + .reduce((questionnaires: Ref[], assessment) => { + if ( + !questionnaires + .map((ref) => ref.id) + .includes(assessment.questionnaire.id) + ) { + assessment.questionnaire && + questionnaires.push(assessment.questionnaire); + } + return questionnaires; + }, []) + .sort((a, b) => { + if (a.name > b.name) return 1; + if (b.name > a.name) return -1; + return 0; + }); + return ( <> {pageHeaderSection} @@ -78,13 +142,56 @@ export const Reports: React.FC = () => { - - {t("terms.currentLandscape")} - + + + + + {t("terms.currentLandscape")} + + + + + + + - + + assessment.questionnaire.name === + selectedQuestionnaire + ) + } + /> diff --git a/client/src/app/queries/assessments.ts b/client/src/app/queries/assessments.ts index a443d337f1..5fec63ace5 100644 --- a/client/src/app/queries/assessments.ts +++ b/client/src/app/queries/assessments.ts @@ -4,6 +4,7 @@ import { createAssessment, deleteAssessment, getAssessmentById, + getAssessments, getAssessmentsByItemId, updateAssessment, } from "@app/api/rest"; @@ -15,6 +16,18 @@ export const assessmentsQueryKey = "assessments"; export const assessmentQueryKey = "assessment"; export const assessmentsByItemIdQueryKey = "assessmentsByItemId"; +export const useFetchAssessments = () => { + const { isLoading, data, error } = useQuery({ + queryKey: [QuestionnairesQueryKey], + queryFn: getAssessments, + onError: (error: AxiosError) => console.log("error, ", error), + }); + return { + assessments: data || [], + isFetching: isLoading, + fetchError: error, + }; +}; export const useCreateAssessmentMutation = ( isArchetype: boolean, onSuccess: (name: string) => void,