Skip to content

Commit

Permalink
✨ Add app name filter to archetypes page & drawer link (#1673)
Browse files Browse the repository at this point in the history
There was a suggestion to update the drawer chips to a link since as the
list of chips grows, it will not be sustainable to show all chips in
drawer. The change here moves to a pre-filter for the archetypes
category in the applications table which is linkable from the archetype
drawer.
https://issues.redhat.com/browse/MTA-2283

<img width="1677" alt="Screenshot 2024-02-21 at 4 51 48 PM"
src="https://github.com/konveyor/tackle2-ui/assets/11218376/f787e32b-df98-48de-92a8-91521059df69">

---------

Signed-off-by: ibolton336 <ibolton@redhat.com>
Signed-off-by: Ian Bolton <ibolton@redhat.com>
  • Loading branch information
ibolton336 authored Feb 22, 2024
1 parent ce3cab5 commit 4cdd553
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 17 deletions.
4 changes: 3 additions & 1 deletion client/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,17 @@
"analysis": "Analysis",
"answer": "Answer",
"application": "Application",
"application_plural": "Applications",
"applicationReview": "Application review",
"application(s)": "Application(s)",
"applications": "Applications",
"applicationImports": "Application imports",
"applicationName": "Application name",
"archetypeName": "Archetype name",
"applicationInformation": "Application information",
"applications": "Applications",
"archetype": "Archetype",
"archetypes": "Archetypes",
"archetypes_plural": "Archetypes",
"artifact": "Artifact",
"artifactAssociated": "Associated artifact",
"artifactNotAssociated": "No associated artifact",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,9 @@ export const ApplicationsTable: React.FC = () => {
selectOptions: [
...new Set(
applications
.flatMap((application) =>
application?.archetypes?.map((archetype) => archetype.name)
.flatMap(
(application) =>
application?.archetypes?.map((archetype) => archetype.name)
)
.filter(Boolean)
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,24 @@ export const ApplicationDetailDrawer: React.FC<
{t("terms.associatedArchetypes")}
</DescriptionListTerm>
<DescriptionListDescription>
{application?.archetypes?.length ?? 0 > 0 ? (
<ArchetypeLabels
archetypeRefs={application?.archetypes}
/>
{application?.archetypes?.length ? (
<>
<DescriptionListDescription>
{application.archetypes.length ?? 0 > 0 ? (
<ArchetypeLabels
archetypeRefs={application.archetypes as Ref[]}
/>
) : (
<EmptyTextMessage message={t("terms.none")} />
)}
</DescriptionListDescription>
</>
) : (
<EmptyTextMessage message={t("terms.none")} />
)}
</DescriptionListDescription>
</DescriptionListGroup>

<DescriptionListGroup>
<DescriptionListTerm>
{t("terms.archetypesAssessed")}
Expand Down
51 changes: 49 additions & 2 deletions client/src/app/pages/archetypes/archetypes-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ import {
TableHeaderContentWithControls,
TableRowContentWithControls,
} from "@app/components/TableControls";
import { useLocalTableControls } from "@app/hooks/table-controls";
import {
deserializeFilterUrlParams,
useLocalTableControls,
} from "@app/hooks/table-controls";
import {
useDeleteArchetypeMutation,
useFetchArchetypes,
Expand Down Expand Up @@ -171,6 +174,10 @@ const Archetypes: React.FC = () => {
});
}
};
const urlParams = new URLSearchParams(window.location.search);
const filters = urlParams.get("filters");

const deserializedFilterValues = deserializeFilterUrlParams({ filters });

const tableControls = useLocalTableControls({
persistTo: "urlParams",
Expand Down Expand Up @@ -206,15 +213,47 @@ const Archetypes: React.FC = () => {
return archetype?.name ?? "";
},
},
{
key: "application.name",
title: t("terms.applicationName"),
type: FilterType.multiselect,
logicOperator: "OR",
selectOptions: [
...new Set(
archetypes.flatMap(
(archetype) =>
archetype?.applications
?.map((app) => app.name)
.filter(Boolean) || []
)
),
].map((applicationName) => ({
key: applicationName,
value: applicationName,
})),
placeholderText:
t("actions.filterBy", {
what: t("terms.application").toLowerCase(),
}) + "...",
getItemValue: (archetype) => {
const appNames = archetype.applications
?.map((app) => app.name)
.join("");
return appNames || "";
},
},

// TODO: Add filter for archetype tags
],

sortableColumns: ["name"],
initialFilterValues: deserializedFilterValues,
getSortValues: (archetype) => ({
name: archetype.name ?? "",
}),
initialSort: { columnKey: "name", direction: "asc" },
});

const {
currentPageItems,
numRenderedColumns,
Expand Down Expand Up @@ -285,6 +324,14 @@ const Archetypes: React.FC = () => {
assessmentWriteAccess = checkAccess(userScopes, assessmentWriteScopes),
reviewsWriteAccess = checkAccess(userScopes, reviewsWriteScopes);

const clearFilters = () => {
const currentPath = history.location.pathname;
const newSearch = new URLSearchParams(history.location.search);
newSearch.delete("filters");
history.push(`${currentPath}`);
filterToolbarProps.setFilterValues({});
};

return (
<>
<PageSection variant={PageSectionVariants.light}>
Expand All @@ -302,7 +349,7 @@ const Archetypes: React.FC = () => {
backgroundColor: "var(--pf-v5-global--BackgroundColor--100)",
}}
>
<Toolbar {...toolbarProps}>
<Toolbar {...toolbarProps} clearAllFilters={clearFilters}>
<ToolbarContent>
<FilterToolbar {...filterToolbarProps} />
<ToolbarGroup variant="button-group">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import { LabelsFromItems } from "@app/components/labels/labels-from-items/labels
import { ReviewFields } from "@app/pages/applications/components/application-detail-drawer/review-fields";
import { RiskLabel } from "@app/components/RiskLabel";
import { LabelsFromTags } from "@app/components/labels/labels-from-tags/labels-from-tags";
import { serializeFilterUrlParams } from "@app/hooks/table-controls";
import { Paths } from "@app/Paths";
import { Link } from "react-router-dom";

export interface IArchetypeDetailDrawerProps {
onCloseClick: () => void;
Expand Down Expand Up @@ -103,10 +106,19 @@ const ArchetypeDetailDrawer: React.FC<IArchetypeDetailDrawerProps> = ({
{t("terms.applications")}
</DescriptionListTerm>
<DescriptionListDescription>
{archetype?.applications?.length ?? 0 > 0 ? (
<ApplicationLabels
applicationRefs={archetype?.applications}
/>
{archetype?.applications?.length ? (
<>
<Link to={getApplicationsUrl(archetype?.name)}>
{archetype.applications.length}{" "}
{t("terms.application", {
count: archetype.applications.length,
context:
archetype.applications.length > 1
? "plural"
: "singular",
}).toLocaleLowerCase()}{" "}
</Link>
</>
) : (
<EmptyTextMessage message={t("terms.none")} />
)}
Expand Down Expand Up @@ -223,10 +235,6 @@ const ArchetypeDetailDrawer: React.FC<IArchetypeDetailDrawerProps> = ({
);
};

const ApplicationLabels: React.FC<{ applicationRefs?: Ref[] }> = ({
applicationRefs,
}) => <LabelsFromItems items={applicationRefs as Ref[]} />;

const TagLabels: React.FC<{ tags?: Tag[] }> = ({ tags }) => (
<LabelsFromTags tags={tags} />
);
Expand All @@ -240,3 +248,16 @@ const StakeholderGroupsLabels: React.FC<{ archetype: Archetype }> = ({
}) => <LabelsFromItems items={archetype.stakeholderGroups as Ref[]} />;

export default ArchetypeDetailDrawer;

const getApplicationsUrl = (archetypeName: string) => {
const filterValues = {
archetypes: [archetypeName],
};

const serializedParams = serializeFilterUrlParams(filterValues);

const queryString = serializedParams.filters
? `filters=${serializedParams.filters}`
: "";
return `${Paths.applications}?${queryString}`;
};

0 comments on commit 4cdd553

Please sign in to comment.