From 21e3e9faf6e86359d055a57fbaa2178c0a491869 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Thu, 14 Dec 2023 20:00:10 -0500 Subject: [PATCH 1/8] :bug: Add risk description when available (#1617) Resolves https://issues.redhat.com/browse/MTA-1868 Signed-off-by: ibolton336 --- client/src/app/pages/reports/components/donut/donut.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/src/app/pages/reports/components/donut/donut.tsx b/client/src/app/pages/reports/components/donut/donut.tsx index 60b0ef040a..6d5c72eb29 100644 --- a/client/src/app/pages/reports/components/donut/donut.tsx +++ b/client/src/app/pages/reports/components/donut/donut.tsx @@ -10,6 +10,7 @@ import { StackItem, Text, TextContent, + TextVariants, } from "@patternfly/react-core"; export interface IDonutProps { @@ -31,6 +32,7 @@ export const Donut: React.FC = ({ riskLabel, isAssessment, riskTitle, + riskDescription, }) => { const { t } = useTranslation(); @@ -63,6 +65,12 @@ export const Donut: React.FC = ({ {riskLabel} + + {riskDescription} + From bb0d2a529e11e98677c133001b0cdc1c52473336 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Thu, 14 Dec 2023 20:01:24 -0500 Subject: [PATCH 2/8] :ghost: Improve spacing for spinner (#1619) - Add margin for the actions spinner Signed-off-by: ibolton336 --- .../components/dynamic-assessment-actions-row.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 ac6f1f474f..5c928916e0 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 @@ -28,6 +28,7 @@ import { } from "@tanstack/react-query"; import { TrashIcon } from "@patternfly/react-icons"; import useIsArchetype from "@app/hooks/useIsArchetype"; +import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing"; enum AssessmentAction { Take = "Take", @@ -222,7 +223,7 @@ const DynamicAssessmentActionsRow: FunctionComponent< {action} ) : ( - + Loading... )} From 863773346c5919be329afefb09cf1dc78ef215fe Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Thu, 14 Dec 2023 20:02:44 -0500 Subject: [PATCH 3/8] :bug: Address missing archetype name in delete assessment notification (#1620) https://issues.redhat.com/browse/MTA-1894 Signed-off-by: ibolton336 --- .../components/dynamic-assessment-actions-row.tsx | 2 ++ .../components/assessment-wizard/assessment-wizard.tsx | 2 ++ client/src/app/queries/assessments.ts | 6 ++++-- 3 files changed, 8 insertions(+), 2 deletions(-) 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 5c928916e0..bf77aa71fc 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 @@ -190,6 +190,7 @@ const DynamicAssessmentActionsRow: FunctionComponent< assessmentId: assessment.id, applicationName: application?.name, applicationId: application?.id, + archetypeName: archetype?.name, archetypeId: archetype?.id, }).then(() => { createAssessment(); @@ -263,6 +264,7 @@ const DynamicAssessmentActionsRow: FunctionComponent< assessmentId: assessment.id, applicationName: application?.name, applicationId: application?.id, + archetypeName: archetype?.name, archetypeId: archetype?.id, }); }} 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 ed8e3140a7..9a06372c86 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 @@ -447,6 +447,7 @@ export const AssessmentWizard: React.FC = ({ assessmentId: assessment.id, applicationName: assessment.application?.name, applicationId: assessment.application?.id, + archetypeName: assessment.archetype?.name, archetypeId: assessment.archetype?.id, }); } else { @@ -455,6 +456,7 @@ export const AssessmentWizard: React.FC = ({ assessmentId: assessment.id, applicationName: assessment.application?.name, applicationId: assessment.application?.id, + archetypeName: assessment.archetype?.name, archetypeId: assessment.archetype?.id, }); } diff --git a/client/src/app/queries/assessments.ts b/client/src/app/queries/assessments.ts index b3796cbe07..8128ba75b4 100644 --- a/client/src/app/queries/assessments.ts +++ b/client/src/app/queries/assessments.ts @@ -107,7 +107,7 @@ export const useUpdateAssessmentMutation = ( }; export const useDeleteAssessmentMutation = ( - onSuccess?: (applicationName: string) => void, + onSuccess?: (name: string) => void, onError?: (err: AxiosError) => void ) => { const queryClient = useQueryClient(); @@ -117,6 +117,7 @@ export const useDeleteAssessmentMutation = ( assessmentId: number; applicationName?: string; applicationId?: number; + archetypeName?: string; archetypeId?: number; }) => { const deletedAssessment = deleteAssessment(args.assessmentId); @@ -138,7 +139,8 @@ export const useDeleteAssessmentMutation = ( return deletedAssessment; }, onSuccess: (_, args) => { - onSuccess && onSuccess(args?.applicationName || "Unknown"); + onSuccess && + onSuccess(args?.applicationName || args?.archetypeName || "Unknown"); }, onError: onError, }); From fa6abfe8d979494fd6ed2063ce9e3210946b15e1 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Thu, 14 Dec 2023 20:03:10 -0500 Subject: [PATCH 4/8] :bug: Hide non required questionnaires from view in view archetypes page (#1621) https://issues.redhat.com/browse/MTA-1895 Signed-off-by: ibolton336 --- .../components/view-archetypes-table.tsx | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/client/src/app/pages/assessment/components/view-archetypes/components/view-archetypes-table.tsx b/client/src/app/pages/assessment/components/view-archetypes/components/view-archetypes-table.tsx index c6b741f9e5..c8235eed27 100644 --- a/client/src/app/pages/assessment/components/view-archetypes/components/view-archetypes-table.tsx +++ b/client/src/app/pages/assessment/components/view-archetypes/components/view-archetypes-table.tsx @@ -24,6 +24,24 @@ const ViewArchetypesTable: React.FC = ({ const archivedQuestionnaires = questionnaires.filter( (questionnaire) => !questionnaire.required ); + + const nonRequiredQuestionnaireIds = questionnaires + .filter((q) => !q.required) + .map((q) => q.id); + + const relevantAssessmentIds = (archetype?.assessments || []).map((a) => a.id); + + const filteredArchivedAssessments = assessments.filter( + (assessment) => + nonRequiredQuestionnaireIds.includes(assessment.questionnaire.id) && + relevantAssessmentIds.includes(assessment.id) + ); + const filteredArchivedQuestionnaires = archivedQuestionnaires.filter( + (questionnaire) => + filteredArchivedAssessments.some( + (assessment) => assessment.questionnaire.id === questionnaire.id + ) + ); return ( <> = ({ isFetching={isFetchingQuestionnaires || isFetchingAssessmentsById} tableName="Required questionnaires" /> - - + {filteredArchivedAssessments.length === 0 ? null : ( + + )} ); }; From 0c9dfb09367810548fa5ebd733f86ff1f23ff7ac Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Thu, 14 Dec 2023 20:03:57 -0500 Subject: [PATCH 5/8] :bug: lengthen term width to fit associated archetypes text (#1623) Resolves https://issues.redhat.com/browse/MTA-1900 Signed-off-by: ibolton336 --- .../application-detail-drawer.tsx | 2 +- .../application-review-status.tsx | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/src/app/pages/applications/components/application-detail-drawer/application-detail-drawer.tsx b/client/src/app/pages/applications/components/application-detail-drawer/application-detail-drawer.tsx index 12887de1d3..e53940ab5e 100644 --- a/client/src/app/pages/applications/components/application-detail-drawer/application-detail-drawer.tsx +++ b/client/src/app/pages/applications/components/application-detail-drawer/application-detail-drawer.tsx @@ -189,7 +189,7 @@ export const ApplicationDetailDrawer: React.FC< isCompact columnModifier={{ default: "1Col" }} horizontalTermWidthModifier={{ - default: "14ch", + default: "15ch", }} > diff --git a/client/src/app/pages/applications/components/application-review-status/application-review-status.tsx b/client/src/app/pages/applications/components/application-review-status/application-review-status.tsx index fccb89c46f..bf118dbbac 100644 --- a/client/src/app/pages/applications/components/application-review-status/application-review-status.tsx +++ b/client/src/app/pages/applications/components/application-review-status/application-review-status.tsx @@ -16,7 +16,7 @@ export const ApplicationReviewStatus: React.FC< > = ({ application }) => { const { t } = useTranslation(); - const { archetypes, isFetching } = useFetchArchetypes(); + const { archetypes, isFetching, error } = useFetchArchetypes(); const isAppReviewed = !!application.review; const applicationArchetypes = application.archetypes?.map((archetypeRef) => { @@ -27,6 +27,10 @@ export const ApplicationReviewStatus: React.FC< applicationArchetypes?.filter((archetype) => !!archetype?.review).length || 0; + if (error) { + return ; + } + if (isFetching) { return ; } @@ -43,9 +47,5 @@ export const ApplicationReviewStatus: React.FC< statusPreset = "NotStarted"; } - if (!applicationArchetypes || applicationArchetypes.length === 0) { - return ; - } - return ; }; From 469e0b15f80cd33e5e5b5a0b297e7a0437709233 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Thu, 14 Dec 2023 20:04:46 -0500 Subject: [PATCH 6/8] :bug: Disable pagination for questionnaire summary (#1622) https://issues.redhat.com/browse/MTA-1881 Signed-off-by: ibolton336 --- client/src/app/components/questions-table/questions-table.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/app/components/questions-table/questions-table.tsx b/client/src/app/components/questions-table/questions-table.tsx index ec5cabd597..81a6f9a101 100644 --- a/client/src/app/components/questions-table/questions-table.tsx +++ b/client/src/app/components/questions-table/questions-table.tsx @@ -45,6 +45,7 @@ const QuestionsTable: React.FC<{ section: "Section", }, isExpansionEnabled: true, + isPaginationEnabled: false, expandableVariant: "single", forceNumRenderedColumns: isAllQuestionsTab ? 3 : 2, // columns+1 for expand control }); From 045cc713b08cccfe209d9406071fa4a30c4b520a Mon Sep 17 00:00:00 2001 From: Mike Turley Date: Thu, 14 Dec 2023 20:06:12 -0500 Subject: [PATCH 7/8] :bug: Fix pagination effects - for client tables, use `filteredItems` instead of `items` length for `totalItemCount` (#1625) Made the same fix in the new react-table-batteries code as well. Note to self: Perhaps we should rename the `totalItemCount` to `filteredItemCount` in the new version, since it really should be the count of all items just before pagination (after filtering), not the total number of items in the unfiltered collection. For client-side tables, the `totalItemCount` is derived internally inside `getLocalTableControlDerivedState`, and it was incorrectly using `items.length`. Changing that to `filteredItems.length` makes the logic in `usePaginationEffects` behave as intended, which means if the user ends up on an invalid pagination page (e.g. they are on page 2 and they apply a filter that has results on one page), it will kick them back to the last valid page. cc @ibolton336 Signed-off-by: Mike Turley Co-authored-by: Ian Bolton --- .../hooks/table-controls/getLocalTableControlDerivedState.ts | 2 +- client/src/app/hooks/table-controls/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/app/hooks/table-controls/getLocalTableControlDerivedState.ts b/client/src/app/hooks/table-controls/getLocalTableControlDerivedState.ts index 9128b1d598..ec98ee9359 100644 --- a/client/src/app/hooks/table-controls/getLocalTableControlDerivedState.ts +++ b/client/src/app/hooks/table-controls/getLocalTableControlDerivedState.ts @@ -48,7 +48,7 @@ export const getLocalTableControlDerivedState = < items: sortedItems, }); return { - totalItemCount: items.length, + totalItemCount: filteredItems.length, currentPageItems: isPaginationEnabled ? currentPageItems : sortedItems, }; }; diff --git a/client/src/app/hooks/table-controls/types.ts b/client/src/app/hooks/table-controls/types.ts index 256166ac2e..a96829c6a1 100644 --- a/client/src/app/hooks/table-controls/types.ts +++ b/client/src/app/hooks/table-controls/types.ts @@ -231,7 +231,7 @@ export type ITableControlDerivedState = { */ currentPageItems: TItem[]; /** - * The total number of items in the entire un-filtered, un-paginated table (the size of the entire API collection being tabulated). + * The total number of items after filtering but before pagination. */ totalItemCount: number; }; From bd965f197c20561aa8b37d7c510d673be90d4c2c Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Thu, 14 Dec 2023 20:07:06 -0500 Subject: [PATCH 8/8] :bug: Update archetype rbac scopes (#1624) https://issues.redhat.com/browse/MTA-1893 Signed-off-by: ibolton336 --- .../app/pages/archetypes/archetypes-page.tsx | 88 +++++++++++++------ client/src/app/rbac.ts | 6 ++ 2 files changed, 68 insertions(+), 26 deletions(-) diff --git a/client/src/app/pages/archetypes/archetypes-page.tsx b/client/src/app/pages/archetypes/archetypes-page.tsx index 82eefd106b..1174837001 100644 --- a/client/src/app/pages/archetypes/archetypes-page.tsx +++ b/client/src/app/pages/archetypes/archetypes-page.tsx @@ -59,6 +59,13 @@ import { SimplePagination } from "@app/components/SimplePagination"; import { TablePersistenceKeyPrefix } from "@app/Constants"; import { useDeleteAssessmentMutation } from "@app/queries/assessments"; import { useDeleteReviewMutation } from "@app/queries/reviews"; +import { + assessmentWriteScopes, + reviewsWriteScopes, + archetypesWriteScopes, +} from "@app/rbac"; +import { checkAccess } from "@app/utils/rbac-utils"; +import keycloak from "@app/keycloak"; const Archetypes: React.FC = () => { const { t } = useTranslation(); @@ -272,6 +279,12 @@ const Archetypes: React.FC = () => { } }; + const token = keycloak.tokenParsed; + const userScopes: string[] = token?.scope.split(" ") || [], + archetypeWriteAccess = checkAccess(userScopes, archetypesWriteScopes), + assessmentWriteAccess = checkAccess(userScopes, assessmentWriteScopes), + reviewsWriteAccess = checkAccess(userScopes, reviewsWriteScopes); + return ( <> @@ -367,26 +380,44 @@ const Archetypes: React.FC = () => { - setArchetypeToDuplicate(archetype), - }, - { - title: t("actions.assess"), - onClick: () => - assessSelectedArchetype(archetype), - }, - { - title: t("actions.review"), - onClick: () => - reviewSelectedArchetype(archetype), - }, - { - title: t("actions.edit"), - onClick: () => setArchetypeToEdit(archetype), - }, - ...(archetype?.assessments?.length + ...(archetypeWriteAccess + ? [ + { + title: t("actions.duplicate"), + onClick: () => + setArchetypeToDuplicate(archetype), + }, + ] + : []), + ...(assessmentWriteAccess + ? [ + { + title: t("actions.assess"), + onClick: () => + assessSelectedArchetype(archetype), + }, + ] + : []), + ...(reviewsWriteAccess + ? [ + { + title: t("actions.review"), + onClick: () => + reviewSelectedArchetype(archetype), + }, + ] + : []), + ...(archetypeWriteAccess + ? [ + { + title: t("actions.edit"), + onClick: () => + setArchetypeToEdit(archetype), + }, + ] + : []), + ...(archetype?.assessments?.length && + assessmentWriteAccess ? [ { title: t("actions.discardAssessment"), @@ -395,7 +426,7 @@ const Archetypes: React.FC = () => { }, ] : []), - ...(archetype?.review + ...(archetype?.review && reviewsWriteAccess ? [ { title: t("actions.discardReview"), @@ -405,11 +436,16 @@ const Archetypes: React.FC = () => { ] : []), { isSeparator: true }, - { - title: t("actions.delete"), - onClick: () => setArchetypeToDelete(archetype), - isDanger: true, - }, + ...(archetypeWriteAccess + ? [ + { + title: t("actions.delete"), + onClick: () => + setArchetypeToDelete(archetype), + isDanger: true, + }, + ] + : []), ]} /> diff --git a/client/src/app/rbac.ts b/client/src/app/rbac.ts index aa4845c7d4..cf136ff19e 100644 --- a/client/src/app/rbac.ts +++ b/client/src/app/rbac.ts @@ -104,6 +104,12 @@ export const applicationsWriteScopes = [ "applications:delete", ]; +export const archetypesWriteScopes = [ + "archetypes:put", + "archetypes:post", + "archetypes:delete", +]; + export const analysisWriteScopes = [ "applications.analysis:put", "applications.analysis:post",