From 9be2ac1f5a3df801179c93bfb2f35f85e57cfa22 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Fri, 16 Feb 2024 13:23:08 -0500 Subject: [PATCH 01/10] :bug: Fix wave subtable pagination (#1689) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves https://issues.redhat.com/browse/MTA-1790 Screenshot 2024-02-15 at 2 09 40 PM Screenshot 2024-02-15 at 2 09 08 PM Screenshot 2024-02-15 at 2 09 01 PM Signed-off-by: Ian Bolton --- .../components/stakeholders-table.tsx | 21 ++++++++++++++----- .../components/wave-applications-table.tsx | 21 ++++++++++++++----- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/client/src/app/pages/migration-waves/components/stakeholders-table.tsx b/client/src/app/pages/migration-waves/components/stakeholders-table.tsx index 7aeae65abf..e40eac74e3 100644 --- a/client/src/app/pages/migration-waves/components/stakeholders-table.tsx +++ b/client/src/app/pages/migration-waves/components/stakeholders-table.tsx @@ -58,11 +58,14 @@ export const WaveStakeholdersTable: React.FC = ({ - + {migrationWave.allStakeholders.length > 9 && ( + + )} @@ -116,6 +119,14 @@ export const WaveStakeholdersTable: React.FC = ({ + {migrationWave.allStakeholders.length > 9 && ( + + )} ); }; diff --git a/client/src/app/pages/migration-waves/components/wave-applications-table.tsx b/client/src/app/pages/migration-waves/components/wave-applications-table.tsx index 94b645a1f1..f56baa1a09 100644 --- a/client/src/app/pages/migration-waves/components/wave-applications-table.tsx +++ b/client/src/app/pages/migration-waves/components/wave-applications-table.tsx @@ -73,11 +73,14 @@ export const WaveApplicationsTable: React.FC = ({ - + {migrationWave.fullApplications.length > 9 && ( + + )} @@ -155,6 +158,14 @@ export const WaveApplicationsTable: React.FC = ({ + {migrationWave.fullApplications.length > 9 && ( + + )} ); }; From 8a630d93c592211f28e62b4550e453b0e92126fd Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Fri, 16 Feb 2024 14:40:00 -0500 Subject: [PATCH 02/10] :bug: Capitalize first letter of source names (#1686) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Screenshot 2024-02-14 at 1 47 42 PM Capitalized source names - previously assessment and archetype sources were lowercase which led to a confusing UX. Motivated by https://github.com/konveyor/tackle2-hub/pull/603 incoming changes. Signed-off-by: Ian Bolton --- .../components/application-tags/application-tags.tsx | 3 ++- client/src/app/utils/utils.ts | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/client/src/app/pages/applications/components/application-tags/application-tags.tsx b/client/src/app/pages/applications/components/application-tags/application-tags.tsx index ae7595e2f2..c33f41a63d 100644 --- a/client/src/app/pages/applications/components/application-tags/application-tags.tsx +++ b/client/src/app/pages/applications/components/application-tags/application-tags.tsx @@ -29,6 +29,7 @@ import { import { useLegacyFilterState } from "@app/hooks/useLegacyFilterState"; import { useHistory } from "react-router-dom"; import { ItemTagLabel } from "../../../../components/labels/item-tag-label/item-tag-label"; +import { capitalizeFirstLetter } from "@app/utils/utils"; interface TagWithSource extends Tag { source?: string; @@ -216,7 +217,7 @@ export const ApplicationTags: React.FC = ({ component="h3" className={`${spacing.mtSm} ${spacing.mbSm} ${textStyles.fontSizeMd}`} > - {source === "" ? "Manual" : source} + {source === "" ? "Manual" : capitalizeFirstLetter(source)} {Array.from(tagCategoriesInThisSource).map((tagCategory) => { diff --git a/client/src/app/utils/utils.ts b/client/src/app/utils/utils.ts index 7e7a9a0e35..607dc0d1c3 100644 --- a/client/src/app/utils/utils.ts +++ b/client/src/app/utils/utils.ts @@ -189,3 +189,6 @@ export const collapseSpacesAndCompare = ( return a.localeCompare(b, locale); }; + +export const capitalizeFirstLetter = (str: string) => + str.charAt(0).toUpperCase() + str.slice(1); From ea6e85908fcfeea5f9a650c23edfb5e5bb3fec4c Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Mon, 19 Feb 2024 13:43:53 -0500 Subject: [PATCH 03/10] :sparkles: Improve documentation for source analysis mode (#1654) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Screenshot 2024-01-04 at 12 05 39 PM Signed-off-by: ibolton336 --- client/public/locales/en/translation.json | 6 ++++++ .../app/pages/applications/analysis-wizard/set-mode.tsx | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/client/public/locales/en/translation.json b/client/public/locales/en/translation.json index f97c91fc29..01fd411fcc 100644 --- a/client/public/locales/en/translation.json +++ b/client/public/locales/en/translation.json @@ -486,6 +486,12 @@ "required": "This field is required." }, "wizard": { + "alert": { + "sourceMode": { + "title": "Source Code Mode", + "description": "This mode focuses on analyzing the source code. Language-specific dependency configurations, like in Java's POM files, are not the primary focus and may not be fully analyzed." + } + }, "composed": { "enable": "Enable {{what}}", "excluded": "Excluded {{what}}", diff --git a/client/src/app/pages/applications/analysis-wizard/set-mode.tsx b/client/src/app/pages/applications/analysis-wizard/set-mode.tsx index 20c837ce87..d3294d44aa 100644 --- a/client/src/app/pages/applications/analysis-wizard/set-mode.tsx +++ b/client/src/app/pages/applications/analysis-wizard/set-mode.tsx @@ -85,6 +85,15 @@ export const SetMode: React.FC = ({ isSingleApp, isModeValid }) => {

{t("wizard.label.notAllAnalyzableDetails")}

)} + {mode === "source-code" && ( + +

{t("wizard.alert.sourceMode.description")}

+
+ )} {mode === "binary-upload" && } ); From 9b8a0ff8ce48ff41aeccdb1d367f2c92e83325fd Mon Sep 17 00:00:00 2001 From: Maayan Hadasi <60384172+mguetta1@users.noreply.github.com> Date: Mon, 19 Feb 2024 23:23:27 +0200 Subject: [PATCH 04/10] :bug: Adding tooltip to PencilAltIcon (#1688) Resolves: https://issues.redhat.com/browse/MTA-1468 --------- Signed-off-by: Maayan Hadasi --- .../applications-table/applications-table.tsx | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/client/src/app/pages/applications/applications-table/applications-table.tsx b/client/src/app/pages/applications/applications-table/applications-table.tsx index de45d031ae..c13ac32e57 100644 --- a/client/src/app/pages/applications/applications-table/applications-table.tsx +++ b/client/src/app/pages/applications/applications-table/applications-table.tsx @@ -17,6 +17,7 @@ import { MenuToggle, MenuToggleElement, Modal, + Tooltip, } from "@patternfly/react-core"; import { PencilAltIcon, TagIcon, EllipsisVIcon } from "@patternfly/react-icons"; import { @@ -359,9 +360,8 @@ 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) ), @@ -948,13 +948,15 @@ export const ApplicationsTable: React.FC = () => { {applicationWriteAccess && ( - + )} + {filterValue?.length ? ( + {filterValue.length} + ) : null} + + + + ); + return ( ({ ); diff --git a/client/src/app/components/FilterToolbar/SelectFilterControl.tsx b/client/src/app/components/FilterToolbar/SelectFilterControl.tsx index 3e0ed1abb1..55d077205b 100644 --- a/client/src/app/components/FilterToolbar/SelectFilterControl.tsx +++ b/client/src/app/components/FilterToolbar/SelectFilterControl.tsx @@ -1,15 +1,14 @@ import * as React from "react"; -import { ToolbarFilter } from "@patternfly/react-core"; import { + MenuToggle, + MenuToggleElement, Select, + SelectList, SelectOption, - SelectOptionObject, -} from "@patternfly/react-core/deprecated"; + ToolbarFilter, +} from "@patternfly/react-core"; import { IFilterControlProps } from "./FilterControl"; -import { - ISelectFilterCategory, - FilterSelectOptionProps, -} from "./FilterToolbar"; +import { ISelectFilterCategory } from "./FilterToolbar"; import { css } from "@patternfly/react-styles"; import "./select-overrides.css"; @@ -34,51 +33,52 @@ export const SelectFilterControl = ({ >): JSX.Element | null => { const [isFilterDropdownOpen, setIsFilterDropdownOpen] = React.useState(false); - const getOptionKeyFromOptionValue = ( - optionValue: string | SelectOptionObject - ) => - category.selectOptions.find( - (optionProps) => optionProps.value === optionValue - )?.key; - - const getChipFromOptionValue = ( - optionValue: string | SelectOptionObject | undefined - ) => (optionValue ? optionValue.toString() : ""); - - const getOptionKeyFromChip = (chip: string) => - category.selectOptions.find( - (optionProps) => optionProps.value.toString() === chip - )?.key; + const getOptionKeyFromOptionValue = (optionValue: string) => + category.selectOptions.find(({ value }) => value === optionValue)?.key; const getOptionValueFromOptionKey = (optionKey: string) => - category.selectOptions.find((optionProps) => optionProps.key === optionKey) - ?.value; + category.selectOptions.find(({ key }) => key === optionKey)?.value; - const onFilterSelect = (value: string | SelectOptionObject) => { + const chips = filterValue?.map((key) => { + const displayValue = getOptionValueFromOptionKey(key); + return displayValue ? displayValue : key; + }); + + const onFilterSelect = (value: string) => { const optionKey = getOptionKeyFromOptionValue(value); setFilterValue(optionKey ? [optionKey] : null); setIsFilterDropdownOpen(false); }; const onFilterClear = (chip: string) => { - const optionKey = getOptionKeyFromChip(chip); - const newValue = filterValue - ? filterValue.filter((val) => val !== optionKey) - : []; - setFilterValue(newValue.length > 0 ? newValue : null); + const newValue = filterValue?.filter((val) => val !== chip); + setFilterValue(newValue?.length ? newValue : null); }; - // Select expects "selections" to be an array of the "value" props from the relevant optionProps - const selections = filterValue - ? filterValue.map(getOptionValueFromOptionKey) - : null; - - const chips = selections ? selections.map(getChipFromOptionValue) : []; + const toggle = (toggleRef: React.Ref) => { + let displayText = "Any"; + if (filterValue && filterValue.length > 0) { + const selectedKey = filterValue[0]; + const selectedDisplayValue = getOptionValueFromOptionKey(selectedKey); + displayText = selectedDisplayValue ? selectedDisplayValue : selectedKey; + } - const renderSelectOptions = (options: FilterSelectOptionProps[]) => - options.map((optionProps) => ( - - )); + return ( + { + setIsFilterDropdownOpen(!isFilterDropdownOpen); + }} + isExpanded={isFilterDropdownOpen} + isDisabled={isDisabled || category.selectOptions.length === 0} + > + {displayText} + + ); + }; return ( ({ ); From 388a442f075ec7789ff6da28706e829d29a82038 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Wed, 21 Feb 2024 16:57:38 -0500 Subject: [PATCH 07/10] :bug: Extend notification delay & fix broken delay customization (#1690) https://issues.redhat.com/browse/MTA-2260 - Previously, the notification delay timeout was being overridden by the timeout set on the alert component itself. This fixes this accidental override. - Lengthens timeout for notification clear globally to 8 seconds. Signed-off-by: Ian Bolton --- client/src/app/components/Notifications.tsx | 5 ++--- .../app/components/NotificationsContext.tsx | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/client/src/app/components/Notifications.tsx b/client/src/app/components/Notifications.tsx index 2d51d05f4e..f74aa0a59b 100644 --- a/client/src/app/components/Notifications.tsx +++ b/client/src/app/components/Notifications.tsx @@ -10,12 +10,12 @@ export const Notifications: React.FunctionComponent = () => { const appContext = React.useContext(NotificationsContext); return ( - {appContext.notifications.map((notification) => { + {appContext.notifications.map((notification, index) => { return ( { /> ), })} - timeout={notification.timeout ? notification.timeout : 4000} > {notification.message} diff --git a/client/src/app/components/NotificationsContext.tsx b/client/src/app/components/NotificationsContext.tsx index e21a8d35c3..51e8ac0979 100644 --- a/client/src/app/components/NotificationsContext.tsx +++ b/client/src/app/components/NotificationsContext.tsx @@ -14,7 +14,10 @@ interface INotificationsProvider { } interface INotificationsContext { - pushNotification: (notification: INotification) => void; + pushNotification: ( + notification: INotification, + clearNotificationDelay?: number + ) => void; dismissNotification: (key: string) => void; notifications: INotification[]; } @@ -38,11 +41,18 @@ export const NotificationsProvider: React.FunctionComponent< notification: INotification, clearNotificationDelay?: number ) => { - setNotifications([ - ...notifications, + setNotifications((prevNotifications) => [ + ...prevNotifications, { ...notificationDefault, ...notification }, ]); - setTimeout(() => setNotifications([]), clearNotificationDelay || 10000); + + setTimeout(() => { + setNotifications((prevNotifications) => { + return prevNotifications.filter( + (notif) => notif.title !== notification.title + ); + }); + }, clearNotificationDelay || 8000); }; const dismissNotification = (title: string) => { From ce3cab5b9de9cc75415ab74fb2d8403bb8d2e0b4 Mon Sep 17 00:00:00 2001 From: David Zager Date: Thu, 22 Feb 2024 09:02:32 -0500 Subject: [PATCH 08/10] :bug: application can only have one review (#1693) https://issues.redhat.com/browse/MTA-1888 It appears that an application can only have a single review. So this changes the Tab title from `Reviews` -> `Review` and drops the redundant header inside. Signed-off-by: David Zager Co-authored-by: Ian Bolton --- .../application-detail-drawer.tsx | 2 +- .../application-detail-drawer/review-fields.tsx | 8 -------- 2 files changed, 1 insertion(+), 9 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 6219a3e0f4..d978ae10a1 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 @@ -425,7 +425,7 @@ export const ApplicationDetailDrawer: React.FC< {t("terms.reviews")}} + title={{t("terms.review")}} > diff --git a/client/src/app/pages/applications/components/application-detail-drawer/review-fields.tsx b/client/src/app/pages/applications/components/application-detail-drawer/review-fields.tsx index 2910035619..f40fdfce1c 100644 --- a/client/src/app/pages/applications/components/application-detail-drawer/review-fields.tsx +++ b/client/src/app/pages/applications/components/application-detail-drawer/review-fields.tsx @@ -4,11 +4,8 @@ import { DescriptionListGroup, DescriptionListTerm, DescriptionListDescription, - Title, - TextContent, } from "@patternfly/react-core"; import { Application, Archetype, Review } from "@app/api/models"; -import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing"; import { useFetchReviewById, useFetchReviews } from "@app/queries/reviews"; import { useFetchArchetypes } from "@app/queries/archetypes"; import { EmptyTextMessage } from "@app/components/EmptyTextMessage"; @@ -75,11 +72,6 @@ export const ReviewFields: React.FC<{ return ( <> - - - {t("terms.review")} - - {t("terms.proposedAction")} From 4cdd553cca048548ef284bd10aff4ae7aa4dfa08 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Thu, 22 Feb 2024 10:18:15 -0500 Subject: [PATCH 09/10] :sparkles: Add app name filter to archetypes page & drawer link (#1673) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Screenshot 2024-02-21 at 4 51 48 PM --------- Signed-off-by: ibolton336 Signed-off-by: Ian Bolton --- client/public/locales/en/translation.json | 4 +- .../applications-table/applications-table.tsx | 5 +- .../application-detail-drawer.tsx | 17 +++++-- .../app/pages/archetypes/archetypes-page.tsx | 51 ++++++++++++++++++- .../components/archetype-detail-drawer.tsx | 37 +++++++++++--- 5 files changed, 97 insertions(+), 17 deletions(-) diff --git a/client/public/locales/en/translation.json b/client/public/locales/en/translation.json index 01fd411fcc..c7b1c840ac 100644 --- a/client/public/locales/en/translation.json +++ b/client/public/locales/en/translation.json @@ -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", diff --git a/client/src/app/pages/applications/applications-table/applications-table.tsx b/client/src/app/pages/applications/applications-table/applications-table.tsx index c13ac32e57..c4306c9e50 100644 --- a/client/src/app/pages/applications/applications-table/applications-table.tsx +++ b/client/src/app/pages/applications/applications-table/applications-table.tsx @@ -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) ), 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 d978ae10a1..7a127d3435 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 @@ -190,15 +190,24 @@ export const ApplicationDetailDrawer: React.FC< {t("terms.associatedArchetypes")} - {application?.archetypes?.length ?? 0 > 0 ? ( - + {application?.archetypes?.length ? ( + <> + + {application.archetypes.length ?? 0 > 0 ? ( + + ) : ( + + )} + + ) : ( )} + {t("terms.archetypesAssessed")} diff --git a/client/src/app/pages/archetypes/archetypes-page.tsx b/client/src/app/pages/archetypes/archetypes-page.tsx index b4c6941e54..0f44e8f1ca 100644 --- a/client/src/app/pages/archetypes/archetypes-page.tsx +++ b/client/src/app/pages/archetypes/archetypes-page.tsx @@ -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, @@ -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", @@ -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, @@ -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 ( <> @@ -302,7 +349,7 @@ const Archetypes: React.FC = () => { backgroundColor: "var(--pf-v5-global--BackgroundColor--100)", }} > - + diff --git a/client/src/app/pages/archetypes/components/archetype-detail-drawer.tsx b/client/src/app/pages/archetypes/components/archetype-detail-drawer.tsx index 648fdd01f3..90b85d0574 100644 --- a/client/src/app/pages/archetypes/components/archetype-detail-drawer.tsx +++ b/client/src/app/pages/archetypes/components/archetype-detail-drawer.tsx @@ -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; @@ -103,10 +106,19 @@ const ArchetypeDetailDrawer: React.FC = ({ {t("terms.applications")} - {archetype?.applications?.length ?? 0 > 0 ? ( - + {archetype?.applications?.length ? ( + <> + + {archetype.applications.length}{" "} + {t("terms.application", { + count: archetype.applications.length, + context: + archetype.applications.length > 1 + ? "plural" + : "singular", + }).toLocaleLowerCase()}{" "} + + ) : ( )} @@ -223,10 +235,6 @@ const ArchetypeDetailDrawer: React.FC = ({ ); }; -const ApplicationLabels: React.FC<{ applicationRefs?: Ref[] }> = ({ - applicationRefs, -}) => ; - const TagLabels: React.FC<{ tags?: Tag[] }> = ({ tags }) => ( ); @@ -240,3 +248,16 @@ const StakeholderGroupsLabels: React.FC<{ archetype: Archetype }> = ({ }) => ; 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}`; +}; From a302446aabf9e70662fe12d6f1221fd375f83b02 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Thu, 22 Feb 2024 11:19:48 -0500 Subject: [PATCH 10/10] :bug: Show disabled tooltip for export when no apps available for export (#1691) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves https://issues.redhat.com/browse/MTA-1845 After discussions with UXD ( @JustinXHale ), determined that this export functionality can safely be disabled when no apps are available to export. Apps that have already been exported already are assigned to a ticket and Jira and cannot be re-exported until they are unlinked. Screenshot 2024-02-16 at 3 49 30 PM Signed-off-by: Ian Bolton --- .../pages/migration-waves/migration-waves.tsx | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/client/src/app/pages/migration-waves/migration-waves.tsx b/client/src/app/pages/migration-waves/migration-waves.tsx index 19117b6f38..5dc78ca762 100644 --- a/client/src/app/pages/migration-waves/migration-waves.tsx +++ b/client/src/app/pages/migration-waves/migration-waves.tsx @@ -42,7 +42,7 @@ import { useFetchMigrationWaves, useUpdateMigrationWaveMutation, } from "@app/queries/migration-waves"; -import { MigrationWave, Ref } from "@app/api/models"; +import { MigrationWave, Ref, Ticket } from "@app/api/models"; import { FilterToolbar, FilterType } from "@app/components/FilterToolbar"; import { useLocalTableControls } from "@app/hooks/table-controls"; import { SimplePagination } from "@app/components/SimplePagination"; @@ -68,6 +68,7 @@ import { AppPlaceholder } from "@app/components/AppPlaceholder"; import { ToolbarBulkSelector } from "@app/components/ToolbarBulkSelector"; import { ConfirmDialog } from "@app/components/ConfirmDialog"; import { toRefs } from "@app/utils/model-utils"; +import { useFetchTickets } from "@app/queries/tickets"; export const MigrationWaves: React.FC = () => { const { t } = useTranslation(); @@ -76,6 +77,7 @@ export const MigrationWaves: React.FC = () => { const currentTimezone = dayjs.tz.guess(); const { migrationWaves, isFetching, fetchError } = useFetchMigrationWaves(); + const { tickets } = useFetchTickets(); const { trackers: trackers } = useFetchTrackers(); const { data: applications } = useFetchApplications(); @@ -495,16 +497,24 @@ export const MigrationWaves: React.FC = () => { setApplicationsToExport( @@ -666,3 +676,11 @@ export const MigrationWaves: React.FC = () => { ); }; + +const hasExportableApplications = (tickets: Ticket[], applicationRefs: Ref[]) => + applicationRefs.some( + (applicationRef) => + !tickets + ?.map((ticket) => ticket?.application?.id) + .includes(applicationRef.id) + );