Skip to content

Commit

Permalink
Merge branch 'main' into mta-1578-fix
Browse files Browse the repository at this point in the history
  • Loading branch information
sjd78 authored Mar 15, 2024
2 parents 4b030c9 + 161fba8 commit 675c84d
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,8 @@ export const MultiselectFilterControl = <TItem,>({
newSelectOptions = [
{
key: "no-results",
isDisabled: false,
isDisabled: true,
hasCheckbox: false,
children: `No results found for "${inputValue}"`,
value: "No results",
},
Expand Down
125 changes: 85 additions & 40 deletions client/src/app/pages/archetypes/archetypes-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import {
useLocalTableControls,
} from "@app/hooks/table-controls";
import {
ARCHETYPES_QUERY_KEY,
ARCHETYPE_QUERY_KEY,
useDeleteArchetypeMutation,
useFetchArchetypes,
} from "@app/queries/archetypes";
Expand All @@ -69,11 +71,14 @@ import {
} from "@app/rbac";
import { checkAccess } from "@app/utils/rbac-utils";
import keycloak from "@app/keycloak";
import { IconedStatus } from "@app/components/IconedStatus";
import { useQueryClient } from "@tanstack/react-query";

const Archetypes: React.FC = () => {
const { t } = useTranslation();
const history = useHistory();
const { pushNotification } = React.useContext(NotificationsContext);
const queryClient = useQueryClient();

const [openCreateArchetype, setOpenCreateArchetype] =
useState<boolean>(false);
Expand Down Expand Up @@ -115,34 +120,37 @@ const Archetypes: React.FC = () => {
onError
);

const { mutate: deleteAssessment } = useDeleteAssessmentMutation();

const discardAssessment = async (archetype: Archetype) => {
try {
if (archetype.assessments) {
await Promise.all(
archetype.assessments.map(async (assessment) => {
await deleteAssessment({
assessmentId: assessment.id,
archetypeId: archetype.id,
});
})
).then(() => {
pushNotification({
title: t("toastr.success.assessmentDiscarded", {
application: archetype.name,
}),
variant: "success",
});
const { mutateAsync: deleteAssessment } = useDeleteAssessmentMutation();

const discardAssessment = (archetype: Archetype) => {
if (!archetype.assessments) {
return;
}
Promise.all(
archetype.assessments.map((assessment) =>
deleteAssessment({
assessmentId: assessment.id,
archetypeId: archetype.id,
})
)
)
.then(() => {
pushNotification({
title: t("toastr.success.assessmentDiscarded", {
application: archetype.name,
}),
variant: "success",
});
queryClient.invalidateQueries([ARCHETYPES_QUERY_KEY]);
queryClient.invalidateQueries([ARCHETYPE_QUERY_KEY, archetype.id]);
})
.catch((error) => {
console.error("Error while deleting assessments:", error);
pushNotification({
title: getAxiosErrorMessage(error as AxiosError),
variant: "danger",
});
}
} catch (error) {
console.error("Error while deleting assessments:", error);
pushNotification({
title: getAxiosErrorMessage(error as AxiosError),
variant: "danger",
});
}
};

const onDeleteReviewSuccess = (name: string) => {
Expand All @@ -154,25 +162,29 @@ const Archetypes: React.FC = () => {
});
};

const { mutate: deleteReview } = useDeleteReviewMutation(
const { mutateAsync: deleteReview } = useDeleteReviewMutation(
onDeleteReviewSuccess
);

const discardReview = async (archetype: Archetype) => {
try {
if (archetype.review?.id) {
await deleteReview({
id: archetype.review.id,
name: archetype.name,
const discardReview = (archetype: Archetype) => {
if (!archetype.review?.id) {
return;
}
deleteReview({
id: archetype.review.id,
name: archetype.name,
})
.then(() => {
queryClient.invalidateQueries([ARCHETYPES_QUERY_KEY]);
queryClient.invalidateQueries([ARCHETYPE_QUERY_KEY, archetype.id]);
})
.catch((error) => {
console.error("Error while deleting review:", error);
pushNotification({
title: getAxiosErrorMessage(error as AxiosError),
variant: "danger",
});
}
} catch (error) {
console.error("Error while deleting review:", error);
pushNotification({
title: getAxiosErrorMessage(error as AxiosError),
variant: "danger",
});
}
};
const urlParams = new URLSearchParams(window.location.search);
const filters = urlParams.get("filters");
Expand All @@ -193,6 +205,8 @@ const Archetypes: React.FC = () => {
tags: t("terms.tags"),
maintainers: t("terms.maintainers"),
applications: t("terms.applications"),
assessment: t("terms.assessment"),
review: t("terms.review"),
},

isFilterEnabled: true,
Expand Down Expand Up @@ -380,6 +394,11 @@ const Archetypes: React.FC = () => {
<Th {...getThProps({ columnKey: "tags" })} />
<Th {...getThProps({ columnKey: "maintainers" })} />
<Th {...getThProps({ columnKey: "applications" })} />
<Th
{...getThProps({ columnKey: "assessment" })}
width={10}
/>
<Th {...getThProps({ columnKey: "review" })} width={10} />
</TableHeaderContentWithControls>
</Tr>
</Thead>
Expand Down Expand Up @@ -427,6 +446,32 @@ const Archetypes: React.FC = () => {
<Td {...getTdProps({ columnKey: "applications" })}>
<ArchetypeApplicationsColumn archetype={archetype} />
</Td>
<Td
width={15}
modifier="truncate"
{...getTdProps({ columnKey: "assessment" })}
>
<IconedStatus
preset={
archetype.assessed
? "Completed"
: archetype?.assessments?.length
? "InProgress"
: "NotStarted"
}
/>
</Td>
<Td
width={15}
modifier="truncate"
{...getTdProps({ columnKey: "review" })}
>
<IconedStatus
preset={
archetype.review ? "Completed" : "NotStarted"
}
/>
</Td>
<Td isActionCell>
{(archetypeWriteAccess ||
assessmentWriteAccess ||
Expand Down
16 changes: 14 additions & 2 deletions client/src/app/pages/issues/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ import { useFetchBusinessServices } from "@app/queries/businessservices";
import { useFetchTagsWithTagItems } from "@app/queries/tags";
import { useTranslation } from "react-i18next";
import { useFetchArchetypes } from "@app/queries/archetypes";
import { useFetchApplications } from "@app/queries/applications";
import { localeNumericCompare } from "@app/utils/utils";
import i18n from "@app/i18n";

// Certain filters are shared between the Issues page and the Affected Applications Page.
// We carry these filter values between the two pages when determining the URLs to navigate between them.
Expand All @@ -41,18 +44,27 @@ export const useSharedAffectedApplicationFilterCategories = <
const { businessServices } = useFetchBusinessServices();
const { tagCategories, tags, tagItems } = useFetchTagsWithTagItems();
const { archetypes } = useFetchArchetypes();
const { data: applications } = useFetchApplications();

return [
{
key: "application.name",
title: t("terms.applicationName"),
filterGroup: IssueFilterGroups.ApplicationInventory,
type: FilterType.search,
type: FilterType.multiselect,
placeholderText:
t("actions.filterBy", {
what: t("terms.applicationName").toLowerCase(),
}) + "...",
getServerFilterValue: (value) => (value ? [`*${value[0]}*`] : []),
selectOptions: applications
.map(({ name }) => name)
.sort((a, b) => localeNumericCompare(a, b, i18n.language))
.map((name) => ({
key: name,
value: name,
})),
getServerFilterValue: (selectedOptions) =>
selectedOptions?.filter(Boolean) ?? [],
},
{
key: "application.id",
Expand Down
11 changes: 11 additions & 0 deletions client/src/app/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,14 @@ export const collapseSpacesAndCompare = (

export const capitalizeFirstLetter = (str: string) =>
str.charAt(0).toUpperCase() + str.slice(1);

/**
* Uses native string localCompare method with numeric option enabled.
*
* @param locale to be used by string compareFn
*/
export const localeNumericCompare = (
a: string,
b: string,
locale: string
): number => a.localeCompare(b, locale, { numeric: true });

0 comments on commit 675c84d

Please sign in to comment.