Skip to content

Commit

Permalink
Update count to reflect apps inheriting assessments from archetypes
Browse files Browse the repository at this point in the history
Port over initial filter values change

Properly serialize & deserialize filters to match server side implementation

Signed-off-by: ibolton336 <[email protected]>
  • Loading branch information
ibolton336 committed Nov 27, 2023
1 parent 9bbc35e commit 7a6667b
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,6 @@ export const MultiselectFilterControl = <TItem,>({
const input = textInput?.toLowerCase();

return renderSelectOptions((optionProps, groupName) => {
if (!input) return false;

// TODO: Checking for a filter match against the key or the value may not be desirable.
return (
groupName?.toLowerCase().includes(input) ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export type IFilterStateArgs<
* Definitions of the filters to be used (must include `getItemValue` functions for each category when performing filtering locally)
*/
filterCategories: FilterCategory<TItem, TFilterCategoryKey>[];
initialFilterValues?: IFilterValues<TFilterCategoryKey>;
}
>;

Expand All @@ -62,6 +63,8 @@ export const useFilterState = <
IFeaturePersistenceArgs<TPersistenceKeyPrefix>
): IFilterState<TFilterCategoryKey> => {
const { isFilterEnabled, persistTo = "state", persistenceKeyPrefix } = args;
const initialFilterValues: IFilterValues<TFilterCategoryKey> =
(isFilterEnabled && args.initialFilterValues) || {};

// We won't need to pass the latter two type params here if TS adds support for partial inference.
// See https://github.com/konveyor/tackle2-ui/issues/1456
Expand All @@ -71,7 +74,7 @@ export const useFilterState = <
"filters"
>({
isEnabled: !!isFilterEnabled,
defaultValue: {},
defaultValue: initialFilterValues,
persistenceKeyPrefix,
// Note: For the discriminated union here to work without TypeScript getting confused
// (e.g. require the urlParams-specific options when persistTo === "urlParams"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,11 @@ import { checkAccess } from "@app/utils/rbac-utils";
import WarningTriangleIcon from "@patternfly/react-icons/dist/esm/icons/warning-triangle-icon";

// Hooks
import { useQueryClient } from "@tanstack/react-query";
import { useLocalTableControls } from "@app/hooks/table-controls";
import { useIsFetching, useQueryClient } from "@tanstack/react-query";
import {
deserializeFilterUrlParams,
useLocalTableControls,
} from "@app/hooks/table-controls";

// Queries
import { Application, Assessment, Ref, Task } from "@app/api/models";
Expand Down Expand Up @@ -111,6 +114,8 @@ export const ApplicationsTable: React.FC = () => {
const history = useHistory();
const token = keycloak.tokenParsed;

const isFetching = useIsFetching();

const { pushNotification } = React.useContext(NotificationsContext);

const { identities } = useFetchIdentities();
Expand Down Expand Up @@ -303,6 +308,11 @@ export const ApplicationsTable: React.FC = () => {
}
};

const urlParams = new URLSearchParams(window.location.search);
const filters = urlParams.get("filters");

const deserializedFilterValues = deserializeFilterUrlParams({ filters });

const tableControls = useLocalTableControls({
idProperty: "id",
items: applications || [],
Expand All @@ -321,6 +331,7 @@ export const ApplicationsTable: React.FC = () => {
isActiveItemEnabled: true,
sortableColumns: ["name", "businessService", "tags", "effort"],
initialSort: { columnKey: "name", direction: "asc" },
initialFilterValues: deserializedFilterValues,
getSortValues: (app) => ({
name: app.name,
businessService: app.businessService?.name || "",
Expand All @@ -331,12 +342,17 @@ export const ApplicationsTable: React.FC = () => {
{
key: "name",
title: t("terms.name"),
type: FilterType.search,
type: FilterType.multiselect,
placeholderText:
t("actions.filterBy", {
what: t("terms.name").toLowerCase(),
}) + "...",
getItemValue: (item) => item?.name || "",
selectOptions: [
...new Set(
applications.map((application) => application.name).filter(Boolean)
),
].map((name) => ({ key: name, value: name })),
},
{
key: "archetypes",
Expand Down Expand Up @@ -690,7 +706,7 @@ export const ApplicationsTable: React.FC = () => {

return (
<ConditionalRender
when={isFetchingApplications && !(applications || applicationsFetchError)}
when={!!isFetching && !(applications || applicationsFetchError)}
then={<AppPlaceholder />}
>
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ import {
ConditionalTableBody,
TableRowContentWithControls,
} from "@app/components/TableControls";
import { useLocalTableControls } from "@app/hooks/table-controls";
import {
serializeFilterUrlParams,
useLocalTableControls,
} from "@app/hooks/table-controls";
import { SimplePagination } from "@app/components/SimplePagination";
import { Toolbar, ToolbarContent, ToolbarItem } from "@patternfly/react-core";
import { Link } from "react-router-dom";
import { Paths } from "@app/Paths";

export interface IIdentifiedRisksTableProps {}

Expand Down Expand Up @@ -47,7 +52,6 @@ export const IdentifiedRisksTable: React.FC<
const uniqueApplications = combinedApplications.reduce(
(acc: Ref[], current) => {
if (!acc.find((item) => item?.id === current.id)) {
// Assuming 'id' is the unique identifier
acc.push(current);
}
return acc;
Expand Down Expand Up @@ -85,9 +89,7 @@ export const IdentifiedRisksTable: React.FC<
section: section.name,
question: question.text,
answer: answer.text,
applications: assessment.application
? [assessment.application]
: [],
applications: uniqueApplications ? uniqueApplications : [],
assessmentName: assessment.questionnaire.name,
questionId: itemId,
});
Expand Down Expand Up @@ -200,7 +202,13 @@ export const IdentifiedRisksTable: React.FC<
{item.answer ?? "N/A"}
</Td>
<Td {...getTdProps({ columnKey: "applications" })}>
{item?.applications.length ?? "N/A"}
{item?.applications.length ? (
<Link to={getApplicationsUrl(item?.applications)}>
{item.applications.length}
</Link>
) : (
"N/A"
)}
</Td>
</TableRowContentWithControls>
</Tr>
Expand All @@ -212,3 +220,16 @@ export const IdentifiedRisksTable: React.FC<
</>
);
};

const getApplicationsUrl = (applications: Ref[]) => {
const filterValues = {
name: applications.map((app) => app.name),
};

const serializedParams = serializeFilterUrlParams(filterValues);

const queryString = serializedParams.filters
? `filters=${serializedParams.filters}`
: "";
return `${Paths.applications}?${queryString}`;
};
32 changes: 18 additions & 14 deletions client/src/app/queries/assessments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { AxiosError } from "axios";
import {
Assessment,
AssessmentWithSectionOrder,
AssessmentWithArchetypeApplications,
InitialAssessment,
} from "@app/api/models";
import { QuestionnairesQueryKey } from "./questionnaires";
Expand Down Expand Up @@ -234,20 +233,25 @@ export const useFetchAssessmentsWithArchetypeApplications = () => {
});

const isArchetypesLoading = archetypeQueries.some((query) => query.isLoading);

Check warning on line 235 in client/src/app/queries/assessments.ts

View check run for this annotation

Codecov / codecov/patch

client/src/app/queries/assessments.ts#L235

Added line #L235 was not covered by tests
const archetypesData = archetypeQueries
.map((query) => query.data)
.filter(Boolean);

const assessmentsWithArchetypeApplications: AssessmentWithArchetypeApplications[] =
assessments.map((assessment, index) => {
const archetypeInfo = archetypesData[index];
return {
...assessment,
archetypeApplications: archetypeInfo.applications
? archetypeInfo.applications
: [],
};
});
const archetypeApplicationsMap = new Map();
archetypeQueries.forEach((query, index) => {

Check warning on line 238 in client/src/app/queries/assessments.ts

View check run for this annotation

Codecov / codecov/patch

client/src/app/queries/assessments.ts#L237-L238

Added lines #L237 - L238 were not covered by tests
if (query.data && assessments[index].archetype?.id) {
archetypeApplicationsMap.set(

Check warning on line 240 in client/src/app/queries/assessments.ts

View check run for this annotation

Codecov / codecov/patch

client/src/app/queries/assessments.ts#L240

Added line #L240 was not covered by tests
assessments[index]?.archetype?.id,
query.data.applications
);
}
});

const assessmentsWithArchetypeApplications = assessments.map(
(assessment) => ({

Check warning on line 248 in client/src/app/queries/assessments.ts

View check run for this annotation

Codecov / codecov/patch

client/src/app/queries/assessments.ts#L247-L248

Added lines #L247 - L248 were not covered by tests
...assessment,
archetypeApplications: assessment.archetype?.id
? archetypeApplicationsMap.get(assessment.archetype.id) || []
: [],

Check warning on line 252 in client/src/app/queries/assessments.ts

View check run for this annotation

Codecov / codecov/patch

client/src/app/queries/assessments.ts#L252

Added line #L252 was not covered by tests
})
);

return {

Check warning on line 256 in client/src/app/queries/assessments.ts

View check run for this annotation

Codecov / codecov/patch

client/src/app/queries/assessments.ts#L256

Added line #L256 was not covered by tests
assessmentsWithArchetypeApplications,
Expand Down

0 comments on commit 7a6667b

Please sign in to comment.