diff --git a/client/public/locales/en/translation.json b/client/public/locales/en/translation.json index 73e78cd41e..f170b96306 100644 --- a/client/public/locales/en/translation.json +++ b/client/public/locales/en/translation.json @@ -42,6 +42,7 @@ "manageDependencies": "Manage dependencies", "manageImports": "Manage imports", "next": "Next", + "override": "Override", "review": "Review", "save": "Save", "saveAndReview": "Save and review", @@ -51,7 +52,8 @@ "selectPage": "Select page", "submitReview": "Submit review", "view": "View", - "viewErrorReport": "View error report" + "viewErrorReport": "View error report", + "viewArchetypes": "View archetypes" }, "colors": { "black": "Black", @@ -168,8 +170,8 @@ "noDataAvailableTitle": "No data available", "noResultsFoundBody": "No results match the filter criteria. Remove all filters or clear all filters to show results.", "noResultsFoundTitle": "No results found", - "overrideAssessmentConfirmation": "This application has already been assessed. Do you want to continue?", - "overrideArchetypeConfirmation": "The archetype for this application already has an assessment. Do you want to create a dedicated assessment for this application?", + "overrideAssessmentDescription": "The archetype for {{what}} already has an assessment.", + "overrideAssessmentConfirmation": "Do you want to create a dedicated assessment for this application?", "overrideReviewConfirmation": "This application has already been reviewed. Do you want to continue?", "reasonForError": "The reported reason for the error:", "reviewInstructions": "Use this section to provide your assessment of the possible migration/modernization plan and effort estimation.", diff --git a/client/src/app/Paths.ts b/client/src/app/Paths.ts index 01875abfb4..d293facac0 100644 --- a/client/src/app/Paths.ts +++ b/client/src/app/Paths.ts @@ -12,7 +12,8 @@ export enum Paths { applicationsAssessment = "/applications/assessment/:assessmentId", applicationAssessmentActions = "/applications/assessment-actions/:applicationId", archetypeAssessmentActions = "/archetypes/assessment-actions/:archetypeId", - assessmentSummary = "/applications/assessment-summary/:assessmentId", + applicationAssessmentSummary = "/applications/assessment-summary/:assessmentId", + archetypeAssessmentSummary = "/archetypes/assessment-summary/:assessmentId", applicationsReview = "/applications/:applicationId/review", applicationsAnalysis = "/applications/analysis", archetypes = "/archetypes", diff --git a/client/src/app/Routes.tsx b/client/src/app/Routes.tsx index e98bcb483a..25a700720c 100644 --- a/client/src/app/Routes.tsx +++ b/client/src/app/Routes.tsx @@ -102,7 +102,12 @@ export const devRoutes: IRoute[] = [ exact: false, }, { - path: Paths.assessmentSummary, + path: Paths.applicationAssessmentSummary, + comp: AssessmentSummary, + exact: false, + }, + { + path: Paths.archetypeAssessmentSummary, comp: AssessmentSummary, exact: false, }, diff --git a/client/src/app/api/models.ts b/client/src/app/api/models.ts index b9524cc588..78983090a6 100644 --- a/client/src/app/api/models.ts +++ b/client/src/app/api/models.ts @@ -128,6 +128,7 @@ export interface Application { migrationWave: Ref | null; assessments?: Ref[]; assessed?: boolean; + archetypes?: Ref[]; } export interface Review { @@ -749,6 +750,6 @@ export interface Archetype { assessmentTags?: Tag[]; stakeholders?: Ref[]; stakeholderGroups?: Ref[]; - applications?: Application[]; + applications?: Ref[]; assessments?: Ref[]; } diff --git a/client/src/app/components/ConfirmDialog.tsx b/client/src/app/components/ConfirmDialog.tsx index f42e046c44..a5aeada809 100644 --- a/client/src/app/components/ConfirmDialog.tsx +++ b/client/src/app/components/ConfirmDialog.tsx @@ -4,6 +4,7 @@ import { Modal, ButtonVariant, ModalVariant, + Alert, } from "@patternfly/react-core"; export interface ConfirmDialogProps { @@ -20,13 +21,17 @@ export interface ConfirmDialogProps { confirmBtnLabel: string; cancelBtnLabel: string; + customActionLabel?: string; inProgress?: boolean; confirmBtnVariant: ButtonVariant; + alertMessage?: string; + onClose: () => void; onConfirm: () => void; onCancel?: () => void; + onCustomAction?: () => void; } export const ConfirmDialog: React.FC = ({ @@ -36,11 +41,14 @@ export const ConfirmDialog: React.FC = ({ message, confirmBtnLabel, cancelBtnLabel, + customActionLabel, inProgress, confirmBtnVariant, onClose, onConfirm, onCancel, + onCustomAction, + alertMessage, }) => { const confirmBtn = ( ) : undefined; + const customActionBtn = onCustomAction ? ( + + ) : undefined; + + const actions = [confirmBtn, customActionBtn, cancelBtn].filter(Boolean); + return ( = ({ isOpen={isOpen} onClose={onClose} aria-label="Confirm dialog" - actions={onCancel ? [confirmBtn, cancelBtn] : [confirmBtn]} + actions={actions} > + {alertMessage ? ( + + ) : null} {message} ); diff --git a/client/src/app/components/questionnaire-summary/questionnaire-summary.tsx b/client/src/app/components/questionnaire-summary/questionnaire-summary.tsx index 186687f97f..aea4bf63dc 100644 --- a/client/src/app/components/questionnaire-summary/questionnaire-summary.tsx +++ b/client/src/app/components/questionnaire-summary/questionnaire-summary.tsx @@ -16,7 +16,6 @@ import { } from "@patternfly/react-core"; import AngleLeftIcon from "@patternfly/react-icons/dist/esm/icons/angle-left-icon"; import { Link } from "react-router-dom"; -import { useTranslation } from "react-i18next"; import { Paths } from "@app/Paths"; import { ConditionalRender } from "@app/components/ConditionalRender"; import { AppPlaceholder } from "@app/components/AppPlaceholder"; @@ -25,6 +24,7 @@ import { Assessment, Questionnaire } from "@app/api/models"; import QuestionnaireSectionTabTitle from "./components/questionnaire-section-tab-title"; import { AxiosError } from "axios"; import { formatPath } from "@app/utils/utils"; +import useIsArchetype from "@app/hooks/useIsArchetype"; export enum SummaryType { Assessment = "Assessment", @@ -36,7 +36,6 @@ interface QuestionnaireSummaryProps { fetchError?: AxiosError | null; summaryData: Assessment | Questionnaire | undefined; summaryType: SummaryType; - isArchetype?: boolean; } const QuestionnaireSummary: React.FC = ({ @@ -44,9 +43,8 @@ const QuestionnaireSummary: React.FC = ({ summaryType, isFetching = false, fetchError = null, - isArchetype, }) => { - const { t } = useTranslation(); + const isArchetype = useIsArchetype(); const [activeSectionIndex, setActiveSectionIndex] = useState<"all" | number>( "all" @@ -86,17 +84,20 @@ const QuestionnaireSummary: React.FC = ({ if (!summaryData) { return
No data available.
; } + + const dynamicPath = isArchetype + ? formatPath(Paths.archetypeAssessmentActions, { + archetypeId: (summaryData as Assessment)?.archetype?.id, + }) + : formatPath(Paths.applicationAssessmentActions, { + applicationId: (summaryData as Assessment)?.application?.id, + }); + const BreadcrumbPath = summaryType === SummaryType.Assessment ? ( - - Assessment - + Assessment {summaryData?.name} diff --git a/client/src/app/hooks/useIsArchetype.ts b/client/src/app/hooks/useIsArchetype.ts new file mode 100644 index 0000000000..f735e4a96e --- /dev/null +++ b/client/src/app/hooks/useIsArchetype.ts @@ -0,0 +1,5 @@ +import { useLocation } from "react-router-dom"; + +const useIsArchetype = () => useLocation().pathname.includes("/archetypes/"); + +export default useIsArchetype; diff --git a/client/src/app/pages/applications/applications-table-assessment/applications-table-assessment.tsx b/client/src/app/pages/applications/applications-table-assessment/applications-table-assessment.tsx index ea74048810..09c3dedb33 100644 --- a/client/src/app/pages/applications/applications-table-assessment/applications-table-assessment.tsx +++ b/client/src/app/pages/applications/applications-table-assessment/applications-table-assessment.tsx @@ -669,6 +669,15 @@ export const ApplicationsTable: React.FC = () => { title: t("actions.review"), onClick: () => reviewSelectedApp(application), }, + ...(application?.review + ? [ + { + title: t("actions.discardAssessment"), + onClick: () => + setAssessmentOrReviewToDiscard(application), + }, + ] + : []), { title: t("actions.delete"), onClick: () => 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 0bc7b28536..b510c997a6 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 @@ -32,7 +32,7 @@ export const ApplicationAssessmentStatus: React.FC< > = ({ assessments, isLoading = false, fetchError = null }) => { const { t } = useTranslation(); //TODO: remove this once we have a proper assessment status - const { assessment } = useFetchAssessmentById(assessments?.[0]?.id || 0); + const { assessment } = useFetchAssessmentById(assessments?.[0]?.id); if (fetchError) { return ; diff --git a/client/src/app/pages/assessment-management/import-questionnaire-form/questionnaire-upload-test-file.yml b/client/src/app/pages/assessment-management/import-questionnaire-form/questionnaire-upload-test-file.yml index a6d56e66a7..a18ddbc0ba 100644 --- a/client/src/app/pages/assessment-management/import-questionnaire-form/questionnaire-upload-test-file.yml +++ b/client/src/app/pages/assessment-management/import-questionnaire-form/questionnaire-upload-test-file.yml @@ -1,6 +1,5 @@ name: Test questionnaire description: This is a sample questionnaire in YAML format -revision: 1 required: true sections: - order: 1 @@ -22,7 +21,6 @@ sections: applyTags: [] autoAnswerFor: [{ category: Category1, tag: Tag1 }] selected: false - autoAnswered: false - order: 2 text: Blue risk: green @@ -31,14 +29,12 @@ sections: applyTags: [] autoAnswerFor: [] selected: false - autoAnswered: false - order: 2 text: What is your favorite sport? explanation: Please select your favorite sport. - includeFor: + excludeFor: - category: Category1 tag: Tag1 - excludeFor: [] answers: - order: 1 text: Soccer @@ -48,7 +44,6 @@ sections: applyTags: [] autoAnswerFor: [] selected: false - autoAnswered: false - order: 2 text: Cycling risk: red @@ -57,7 +52,6 @@ sections: applyTags: [] autoAnswerFor: [] selected: false - autoAnswered: false - order: 3 text: Climbing risk: yellow @@ -66,7 +60,6 @@ sections: applyTags: [] autoAnswerFor: [] selected: false - autoAnswered: false - order: 4 text: Swimming risk: yellow @@ -75,7 +68,6 @@ sections: applyTags: [] autoAnswerFor: [] selected: false - autoAnswered: false - order: 5 text: Running risk: red @@ -84,7 +76,6 @@ sections: applyTags: [] autoAnswerFor: [] selected: false - autoAnswered: false thresholds: red: 5 yellow: 10 diff --git a/client/src/app/pages/assessment/assessment-page.tsx b/client/src/app/pages/assessment/assessment-page.tsx index 406e59e10c..cbfb5652ae 100644 --- a/client/src/app/pages/assessment/assessment-page.tsx +++ b/client/src/app/pages/assessment/assessment-page.tsx @@ -23,6 +23,7 @@ const AssessmentPage: React.FC = () => { const { t } = useTranslation(); const { assessmentId } = useParams(); + const { assessment, isFetching, fetchError } = useFetchAssessmentById(assessmentId); diff --git a/client/src/app/pages/assessment/components/assessment-actions/assessment-actions-page.tsx b/client/src/app/pages/assessment/components/assessment-actions/assessment-actions-page.tsx index bc9fe22bbe..bcb97d9ab3 100644 --- a/client/src/app/pages/assessment/components/assessment-actions/assessment-actions-page.tsx +++ b/client/src/app/pages/assessment/components/assessment-actions/assessment-actions-page.tsx @@ -11,19 +11,18 @@ import { Link, useParams } from "react-router-dom"; import { AssessmentActionsRoute, Paths } from "@app/Paths"; import { ConditionalRender } from "@app/components/ConditionalRender"; import { AppPlaceholder } from "@app/components/AppPlaceholder"; -import { useFetchApplicationByID } from "@app/queries/applications"; import AssessmentActionsTable from "./components/assessment-actions-table"; import { useFetchArchetypeById } from "@app/queries/archetypes"; +import { useFetchApplicationById } from "@app/queries/applications"; +import useIsArchetype from "@app/hooks/useIsArchetype"; const AssessmentActions: React.FC = () => { const { applicationId, archetypeId } = useParams(); - const isArchetype = location.pathname.includes("/archetypes/"); - console.log("isArchetype", isArchetype); + const isArchetype = useIsArchetype(); - const { application } = useFetchApplicationByID(applicationId || ""); - const { archetype } = useFetchArchetypeById(archetypeId || ""); + const { archetype } = useFetchArchetypeById(archetypeId); + const { application } = useFetchApplicationById(applicationId); - console.log("archetype", archetype); return ( <> @@ -41,7 +40,7 @@ const AssessmentActions: React.FC = () => { )} - Assessment + {isArchetype ? archetype?.name : application?.name} diff --git a/client/src/app/pages/assessment/components/assessment-actions/components/dynamic-assessment-actions-row.tsx b/client/src/app/pages/assessment/components/assessment-actions/components/dynamic-assessment-actions-row.tsx index c444501d3d..e718baf9c4 100644 --- a/client/src/app/pages/assessment/components/assessment-actions/components/dynamic-assessment-actions-row.tsx +++ b/client/src/app/pages/assessment/components/assessment-actions/components/dynamic-assessment-actions-row.tsx @@ -5,13 +5,14 @@ import { Assessment, InitialAssessment, Questionnaire, + Ref, } from "@app/api/models"; import { assessmentsByItemIdQueryKey, useCreateAssessmentMutation, useDeleteAssessmentMutation, } from "@app/queries/assessments"; -import { Button } from "@patternfly/react-core"; +import { Button, ButtonVariant } from "@patternfly/react-core"; import React, { FunctionComponent } from "react"; import { useHistory } from "react-router-dom"; import "./dynamic-assessment-actions-row.css"; @@ -22,6 +23,9 @@ import { NotificationsContext } from "@app/components/NotificationsContext"; import { useTranslation } from "react-i18next"; import { useQueryClient } from "@tanstack/react-query"; import { TrashIcon } from "@patternfly/react-icons"; +import { ConfirmDialog } from "@app/components/ConfirmDialog"; +import { getAssessmentsByItemId } from "@app/api/rest"; +import useIsArchetype from "@app/hooks/useIsArchetype"; enum AssessmentAction { Take = "Take", @@ -31,7 +35,6 @@ enum AssessmentAction { interface DynamicAssessmentActionsRowProps { questionnaire: Questionnaire; - isArchetype: boolean; application?: Application; archetype?: Archetype; assessment?: Assessment; @@ -39,13 +42,17 @@ interface DynamicAssessmentActionsRowProps { const DynamicAssessmentActionsRow: FunctionComponent< DynamicAssessmentActionsRowProps -> = ({ questionnaire, application, archetype, assessment, isArchetype }) => { +> = ({ questionnaire, application, archetype, assessment }) => { + const isArchetype = useIsArchetype(); const history = useHistory(); const { t } = useTranslation(); const queryClient = useQueryClient(); const { pushNotification } = React.useContext(NotificationsContext); + const [archetypeRefToOverride, setArchetypeRefToOverride] = + React.useState(null); + const onSuccessHandler = () => {}; const onErrorHandler = () => {}; @@ -100,6 +107,7 @@ const DynamicAssessmentActionsRow: FunctionComponent< return "retake-button"; } }; + const createAssessment = async () => { const newAssessment: InitialAssessment = { questionnaire: { name: questionnaire.name, id: questionnaire.id }, @@ -129,18 +137,59 @@ const DynamicAssessmentActionsRow: FunctionComponent< } } catch (error) { console.error("Error while creating assessment:", error); + pushNotification({ + title: t("terms.error"), + variant: "danger", + }); } }; + + const takeAssessment = async () => { + if (!isArchetype && application?.archetypes?.length) { + for (const archetypeRef of application.archetypes) { + try { + const assessments = await getAssessmentsByItemId( + true, + archetypeRef.id + ); + + if (assessments && assessments.length > 0) { + setArchetypeRefToOverride(archetypeRef); + break; + } else { + createAssessment(); + } + } catch (error) { + console.error( + `Error fetching archetype with ID ${archetypeRef.id}:`, + error + ); + pushNotification({ + title: t("terms.error"), + variant: "danger", + }); + } + } + } else { + createAssessment(); + } + }; + const onHandleAssessmentAction = async () => { const action = determineAction(); if (action === AssessmentAction.Take) { - createAssessment(); + takeAssessment(); } else if (action === AssessmentAction.Continue) { history.push( - formatPath(Paths.applicationsAssessment, { - assessmentId: assessment?.id, - }) + formatPath( + isArchetype + ? Paths.archetypesAssessment + : Paths.applicationsAssessment, + { + assessmentId: assessment?.id, + } + ) ); } else if (action === AssessmentAction.Retake) { if (assessment) { @@ -152,11 +201,20 @@ const DynamicAssessmentActionsRow: FunctionComponent< createAssessment(); }); history.push( - formatPath(Paths.applicationsAssessment, { - assessmentId: assessment?.id, - }) + formatPath( + isArchetype + ? Paths.archetypesAssessment + : Paths.applicationsAssessment, + { + assessmentId: assessment?.id, + } + ) ); } catch (error) { + pushNotification({ + title: t("terms.error"), + variant: "danger", + }); console.error("Error while deleting assessment:", error); } } @@ -185,9 +243,14 @@ const DynamicAssessmentActionsRow: FunctionComponent< variant="secondary" onClick={() => { history.push( - formatPath(Paths.assessmentSummary, { - assessmentId: assessment.id, - }) + formatPath( + isArchetype + ? Paths.archetypeAssessmentSummary + : Paths.applicationAssessmentSummary, + { + assessmentId: assessment.id, + } + ) ); }} > @@ -212,6 +275,37 @@ const DynamicAssessmentActionsRow: FunctionComponent< ) : null} + setArchetypeRefToOverride(null)} + onClose={() => setArchetypeRefToOverride(null)} + //TODO + // onCustomAction={() => { + // //nav to view archetypes + // console.log("nav to view archetypes"); + // }} + onConfirm={() => { + history.push( + formatPath(Paths.applicationsAssessment, { + assessmentId: archetypeRefToOverride?.id, + }) + ); + setArchetypeRefToOverride(null); + createAssessment(); + }} + /> ); }; diff --git a/client/src/app/pages/assessment/components/assessment-actions/components/questionnaires-table.tsx b/client/src/app/pages/assessment/components/assessment-actions/components/questionnaires-table.tsx index 9eaaa5f221..77acd47bd3 100644 --- a/client/src/app/pages/assessment/components/assessment-actions/components/questionnaires-table.tsx +++ b/client/src/app/pages/assessment/components/assessment-actions/components/questionnaires-table.tsx @@ -74,8 +74,16 @@ const QuestionnairesTable: React.FC = ({ > {currentPageItems?.map((questionnaire, rowIndex) => { - const matchingAssessment = assessments?.find( - (assessment) => assessment.questionnaire.id === questionnaire.id + const matchingArchetypeAssessment = assessments?.find( + (assessment) => + assessment.questionnaire.id === questionnaire.id && + assessment?.archetype?.id === archetype?.id + ); + + const matchingApplicationAssessment = assessments?.find( + (assessment) => + assessment.questionnaire.id === questionnaire.id && + assessment?.application?.id === application?.id ); return ( @@ -93,9 +101,12 @@ const QuestionnairesTable: React.FC = ({ {application || archetype ? ( diff --git a/client/src/app/pages/assessment/components/assessment-page-header.tsx b/client/src/app/pages/assessment/components/assessment-page-header.tsx index c587b96679..6644d0e3f8 100644 --- a/client/src/app/pages/assessment/components/assessment-page-header.tsx +++ b/client/src/app/pages/assessment/components/assessment-page-header.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React from "react"; import { useHistory } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { Button, ButtonVariant, Modal, Text } from "@patternfly/react-core"; @@ -8,7 +8,9 @@ import { PageHeader } from "@app/components/PageHeader"; import { ApplicationDependenciesFormContainer } from "@app/components/ApplicationDependenciesFormContainer"; import { Paths } from "@app/Paths"; import { Application, Assessment } from "@app/api/models"; -import { getApplicationById } from "@app/api/rest"; +import { useFetchApplicationById } from "@app/queries/applications"; +import { useFetchArchetypeById } from "@app/queries/archetypes"; +import useIsArchetype from "@app/hooks/useIsArchetype"; export interface AssessmentPageHeaderProps { assessment?: Assessment; @@ -19,20 +21,14 @@ export const AssessmentPageHeader: React.FC = ({ }) => { const { t } = useTranslation(); const history = useHistory(); + const isArchetype = useIsArchetype(); + + const { archetype } = useFetchArchetypeById(assessment?.archetype?.id); + const { application } = useFetchApplicationById(assessment?.application?.id); const [isConfirmDialogOpen, setIsConfirmDialogOpen] = React.useState(false); - const [application, setApplication] = useState(); - - useEffect(() => { - if (assessment?.application?.id) { - getApplicationById(assessment?.application?.id).then((data) => { - setApplication(data); - }); - } - }, [assessment]); - const [applicationDependenciesToManage, setApplicationDependenciesToManage] = React.useState(null); @@ -40,17 +36,23 @@ export const AssessmentPageHeader: React.FC = ({ <> {application?.name}} + description={ + + {isArchetype ? archetype?.name : application?.name} + + } breadcrumbs={[ { - title: t("terms.applications"), + title: isArchetype ? t("terms.archetype") : t("terms.applications"), path: () => { setIsConfirmDialogOpen(true); }, }, { title: t("terms.assessment"), - path: Paths.applicationsAssessment, + path: isArchetype + ? Paths.archetypesAssessment + : Paths.applicationsAssessment, }, ]} btnActions={ @@ -92,7 +94,9 @@ export const AssessmentPageHeader: React.FC = ({ cancelBtnLabel={t("actions.cancel")} onCancel={() => setIsConfirmDialogOpen(false)} onClose={() => setIsConfirmDialogOpen(false)} - onConfirm={() => history.push(Paths.applications)} + onConfirm={() => + history.push(isArchetype ? Paths.archetypes : Paths.applications) + } /> )} diff --git a/client/src/app/pages/assessment/components/assessment-wizard/assessment-wizard.tsx b/client/src/app/pages/assessment/components/assessment-wizard/assessment-wizard.tsx index b7353d8e56..2c9c2a8589 100644 --- a/client/src/app/pages/assessment/components/assessment-wizard/assessment-wizard.tsx +++ b/client/src/app/pages/assessment/components/assessment-wizard/assessment-wizard.tsx @@ -18,7 +18,6 @@ import { NotificationsContext } from "@app/components/NotificationsContext"; import { WizardStepNavDescription } from "../wizard-step-nav-description"; import { QuestionnaireForm } from "../questionnaire-form"; import { ConfirmDialog } from "@app/components/ConfirmDialog"; -import { useFetchQuestionnaires } from "@app/queries/questionnaires"; import { COMMENTS_KEY, QUESTIONS_KEY, @@ -34,6 +33,7 @@ import { formatPath, getAxiosErrorMessage } from "@app/utils/utils"; import { Paths } from "@app/Paths"; import { yupResolver } from "@hookform/resolvers/yup"; import { AssessmentStakeholdersForm } from "../assessment-stakeholders-form/assessment-stakeholders-form"; +import useIsArchetype from "@app/hooks/useIsArchetype"; export const SAVE_ACTION_KEY = "saveAction"; @@ -58,16 +58,15 @@ export interface AssessmentWizardValues { export interface AssessmentWizardProps { assessment?: Assessment; isOpen: boolean; - isArchetype?: boolean; } export const AssessmentWizard: React.FC = ({ assessment, isOpen, - isArchetype, }) => { + const isArchetype = useIsArchetype(); const queryClient = useQueryClient(); - const { questionnaires } = useFetchQuestionnaires(); + const onHandleUpdateAssessmentSuccess = () => { queryClient.invalidateQueries([ assessmentsByItemIdQueryKey, @@ -78,10 +77,6 @@ export const AssessmentWizard: React.FC = ({ onHandleUpdateAssessmentSuccess ); - const matchingQuestionnaire = questionnaires.find( - (questionnaire) => questionnaire.id === assessment?.questionnaire?.id - ); - const { t } = useTranslation(); const [currentStep, setCurrentStep] = useState(0); @@ -94,10 +89,10 @@ export const AssessmentWizard: React.FC = ({ const { pushNotification } = React.useContext(NotificationsContext); const sortedSections = useMemo(() => { - return (matchingQuestionnaire ? matchingQuestionnaire.sections : []).sort( + return (assessment ? assessment.sections : []).sort( (a, b) => a.order - b.order ); - }, [matchingQuestionnaire]); + }, [assessment]); //TODO: Add comments to the sections when/if available from api // const initialComments = useMemo(() => { @@ -112,8 +107,8 @@ export const AssessmentWizard: React.FC = ({ const initialQuestions = useMemo(() => { const questions: { [key: string]: string | undefined } = {}; - if (assessment && matchingQuestionnaire) { - matchingQuestionnaire.sections + if (assessment) { + assessment.sections .flatMap((f) => f.questions) .forEach((question) => { const existingAnswer = assessment.sections @@ -126,17 +121,21 @@ export const AssessmentWizard: React.FC = ({ }); } return questions; - }, [assessment, matchingQuestionnaire]); + }, [assessment]); useEffect(() => { methods.reset({ - // stakeholders: assessment?.stakeholders || [], - // stakeholderGroups: assessment?.stakeholderGroups || [], + stakeholders: + assessment?.stakeholders.map((stakeholder) => stakeholder.name) || [], + stakeholderGroups: + assessment?.stakeholderGroups.map( + (stakeholderGroup) => stakeholderGroup.name + ) || [], // comments: initialComments, questions: initialQuestions, [SAVE_ACTION_KEY]: SAVE_ACTION_VALUE.SAVE_AS_DRAFT, }); - }, [initialQuestions]); + }, [initialQuestions, assessment]); const validationSchema = yup.object().shape({ stakeholders: yup.array().of(yup.string()), @@ -235,7 +234,7 @@ export const AssessmentWizard: React.FC = ({ // Create an array of sections based on the questionsData const sections: Section[] = - matchingQuestionnaire?.sections?.map((section) => { + assessment?.sections?.map((section) => { //TODO: Add comments to the sections // const commentValues = values["comments"]; // const fieldName = getCommentFieldName(category, false); @@ -263,7 +262,7 @@ export const AssessmentWizard: React.FC = ({ const handleSaveAsDraft = async (formValues: AssessmentWizardValues) => { try { - if (!assessment?.application?.id) { + if (!assessment?.application?.id && !assessment?.archetype?.id) { console.log("An assessment must exist in order to save as draft"); return; } @@ -307,7 +306,7 @@ export const AssessmentWizard: React.FC = ({ const handleSave = async (formValues: AssessmentWizardValues) => { try { - if (!assessment?.application?.id) { + if (!assessment?.application?.id && !assessment?.archetype?.id) { console.log("An assessment must exist in order to save."); return; } @@ -352,7 +351,7 @@ export const AssessmentWizard: React.FC = ({ const handleSaveAndReview = async (formValues: AssessmentWizardValues) => { try { - if (!assessment?.application?.id) { + if (!assessment?.application?.id && !assessment?.archetype?.id) { console.log("An assessment must exist in order to save."); return; } @@ -375,22 +374,41 @@ export const AssessmentWizard: React.FC = ({ title: "Assessment has been saved.", variant: "success", }); - - assessment?.application?.id && - getApplicationById(assessment.application.id) - .then((data) => { - history.push( - formatPath(Paths.applicationsReview, { - applicationId: data.id, - }) - ); - }) - .catch((error) => { - pushNotification({ - title: getAxiosErrorMessage(error), - variant: "danger", + if (isArchetype) { + //TODO: Review Archetype? + // assessment?.archetype?.id && + // getArchetypeById(assessment.archetype.id) + // .then((data) => { + // history.push( + // formatPath(Paths.a, { + // applicationId: data.id, + // }) + // ); + // }) + // .catch((error) => { + // pushNotification({ + // title: getAxiosErrorMessage(error), + // variant: "danger", + // }); + // }); + // } + } else { + assessment?.application?.id && + getApplicationById(assessment.application.id) + .then((data) => { + history.push( + formatPath(Paths.applicationsReview, { + applicationId: data.id, + }) + ); + }) + .catch((error) => { + pushNotification({ + title: getAxiosErrorMessage(error), + variant: "danger", + }); }); - }); + } } catch (error) { pushNotification({ title: "Failed to save.", @@ -401,7 +419,7 @@ export const AssessmentWizard: React.FC = ({ }; const onSubmit = async (formValues: AssessmentWizardValues) => { - if (!assessment?.application?.id) { + if (!assessment?.application?.id && !assessment?.archetype?.id) { console.log("An assessment must exist in order to save the form"); return; } @@ -453,6 +471,7 @@ export const AssessmentWizard: React.FC = ({ const wizardFooter = ( void; onSaveAsDraft: () => void; } @@ -21,6 +22,7 @@ export const CustomWizardFooter: React.FC = ({ isLastStep, isDisabled, isFormInvalid, + isArchetype, onSave, onSaveAsDraft, }) => { @@ -47,14 +49,16 @@ export const CustomWizardFooter: React.FC = ({ > {t("actions.save")} - + {!isArchetype && ( + + )} ) : (