From 629cb61234b0f0d8897841bf603d835dc84af027 Mon Sep 17 00:00:00 2001 From: Scott Dickerson Date: Thu, 18 Jan 2024 15:11:51 -0500 Subject: [PATCH 01/53] :seedling: Refactor patternfly, i18n, and dayjs initialization (#1665) Refactoring: - Explicitly add `i18n` initialization on the root `index.tsx`. - Move `dayjs` initialization to its own file `dayjs.ts` referenced from `index.tsx`. This follows the `i18n` init style. - Move PF css includes from `App.tsx` to `index.tsx` Signed-off-by: Scott J Dickerson --- client/src/app/App.tsx | 3 --- client/src/app/dayjs.ts | 10 ++++++++++ client/src/index.tsx | 14 +++++--------- 3 files changed, 15 insertions(+), 12 deletions(-) create mode 100644 client/src/app/dayjs.ts diff --git a/client/src/app/App.tsx b/client/src/app/App.tsx index 6b7409777d..3414477eda 100644 --- a/client/src/app/App.tsx +++ b/client/src/app/App.tsx @@ -5,9 +5,6 @@ import { AppRoutes } from "./Routes"; import { DefaultLayout } from "./layout"; import { NotificationsProvider } from "./components/NotificationsContext"; -import "@patternfly/patternfly/patternfly.css"; -import "@patternfly/patternfly/patternfly-addons.css"; - import "./app.css"; const App: React.FC = () => { diff --git a/client/src/app/dayjs.ts b/client/src/app/dayjs.ts new file mode 100644 index 0000000000..a86cf31f90 --- /dev/null +++ b/client/src/app/dayjs.ts @@ -0,0 +1,10 @@ +import dayjs from "dayjs"; +import isSameOrBefore from "dayjs/plugin/isSameOrBefore"; +import utc from "dayjs/plugin/utc"; +import timezone from "dayjs/plugin/timezone"; +import customParseFormat from "dayjs/plugin/customParseFormat"; + +dayjs.extend(utc); +dayjs.extend(timezone); +dayjs.extend(customParseFormat); +dayjs.extend(isSameOrBefore); diff --git a/client/src/index.tsx b/client/src/index.tsx index 29774a8cb8..ce826f80d9 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -1,3 +1,6 @@ +import "@patternfly/patternfly/patternfly.css"; +import "@patternfly/patternfly/patternfly-addons.css"; + import React from "react"; import ReactDOM from "react-dom"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; @@ -7,16 +10,9 @@ import ENV from "@app/env"; import App from "@app/App"; import reportWebVitals from "@app/reportWebVitals"; import { KeycloakProvider } from "@app/components/KeycloakProvider"; -import dayjs from "dayjs"; -import isSameOrBefore from "dayjs/plugin/isSameOrBefore"; -import utc from "dayjs/plugin/utc"; -import timezone from "dayjs/plugin/timezone"; -import customParseFormat from "dayjs/plugin/customParseFormat"; -dayjs.extend(utc); -dayjs.extend(timezone); -dayjs.extend(customParseFormat); -dayjs.extend(isSameOrBefore); +import "@app/dayjs"; +import "@app/i18n"; const queryClient = new QueryClient(); From 17e7eda83e2268eeca05107eb298f35ef7351d11 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Thu, 18 Jan 2024 16:52:42 -0500 Subject: [PATCH 02/53] :bug: Handle wrap of long file paths (#1655) https://issues.redhat.com/browse/MTA-1961 Signed-off-by: ibolton336 --- .../issue-detail-drawer/issue-affected-files-table.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/src/app/pages/issues/issue-detail-drawer/issue-affected-files-table.tsx b/client/src/app/pages/issues/issue-detail-drawer/issue-affected-files-table.tsx index e480de9f63..9ae5637c20 100644 --- a/client/src/app/pages/issues/issue-detail-drawer/issue-affected-files-table.tsx +++ b/client/src/app/pages/issues/issue-detail-drawer/issue-affected-files-table.tsx @@ -152,7 +152,11 @@ export const IssueAffectedFilesTable: React.FC< item={fileReport} rowIndex={rowIndex} > - + + )} + {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 14/53] :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 15/53] :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 16/53] :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 17/53] :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) + ); From 81ad682b64c95da3dfd18a06bb81bbfa8a887108 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Thu, 22 Feb 2024 15:32:44 -0500 Subject: [PATCH 18/53] :bug: Reuse toggle component for apps table (#1692) https://issues.redhat.com/browse/MTA-1807 Signed-off-by: Ian Bolton --- client/src/app/components/KebabDropdown.tsx | 1 + .../applications-table/applications-table.tsx | 33 ++++--------------- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/client/src/app/components/KebabDropdown.tsx b/client/src/app/components/KebabDropdown.tsx index 3224c6fe06..bf0d2412ec 100644 --- a/client/src/app/components/KebabDropdown.tsx +++ b/client/src/app/components/KebabDropdown.tsx @@ -24,6 +24,7 @@ export const KebabDropdown: React.FC = ({ popperProps={{ position: "right" }} isOpen={isOpen} onOpenChange={(isOpen) => setIsOpen(isOpen)} + shouldFocusToggleOnSelect toggle={(toggleRef: React.Ref) => ( { const { t } = useTranslation(); @@ -115,8 +113,6 @@ export const ApplicationsTable: React.FC = () => { const { pushNotification } = React.useContext(NotificationsContext); const { identities } = useFetchIdentities(); - const [isToolbarKebabOpen, setIsToolbarKebabOpen] = - React.useState(false); const [saveApplicationModalState, setSaveApplicationModalState] = React.useState<"create" | Application | null>(null); @@ -799,27 +795,10 @@ export const ApplicationsTable: React.FC = () => { {dropdownItems.length ? ( - setIsToolbarKebabOpen(false)} - onOpenChange={(_isOpen) => setIsToolbarKebabOpen(false)} - toggle={(toggleRef: React.Ref) => ( - - setIsToolbarKebabOpen(!isToolbarKebabOpen) - } - isExpanded={isToolbarKebabOpen} - > - - - )} - shouldFocusToggleOnSelect - > - {dropdownItems} - + ) : ( <> From 228abc4574c41ac3d2df6c8641e1b93a50f66e6b Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Mon, 26 Feb 2024 09:21:59 -0500 Subject: [PATCH 19/53] :bug: Do not show the code viewer when no code snippet available (#1685) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves https://github.com/konveyor/tackle2-ui/issues/1472 - Adds an empty state to the codeviewer when the codesnip is not populated / is an empty string or whitespace characters. Screenshot 2024-02-13 at 12 43 05 PM Signed-off-by: Ian Bolton --- client/public/locales/en/translation.json | 2 ++ .../incident-code-snip-viewer.tsx | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/client/public/locales/en/translation.json b/client/public/locales/en/translation.json index c7b1c840ac..7b3c3993c2 100644 --- a/client/public/locales/en/translation.json +++ b/client/public/locales/en/translation.json @@ -198,6 +198,8 @@ "noDataAvailableTitle": "No data available", "noResultsFoundBody": "No results match the filter criteria. Remove all filters or clear all filters to show results.", "noResultsFoundTitle": "No results found", + "noCodesSnippetAvailableTitle": "No code snippet available", + "noCodesSnippetAvailableBody": "No code snippet was created for this incident.", "overrideAssessmentDescription": "The application {{name}} already is associated with archetypes: {{what}}.", "overrideAssessmentConfirmation": "Do you want to create a dedicated assessment for this application and override the inherited archetype assessment(s)?", "overrideArchetypeReviewDescription": "The application {{name}} already is associated with archetypes: {{what}}.", diff --git a/client/src/app/pages/issues/issue-detail-drawer/file-incidents-detail-modal/incident-code-snip-viewer.tsx b/client/src/app/pages/issues/issue-detail-drawer/file-incidents-detail-modal/incident-code-snip-viewer.tsx index e67085ba9e..f6f6467138 100644 --- a/client/src/app/pages/issues/issue-detail-drawer/file-incidents-detail-modal/incident-code-snip-viewer.tsx +++ b/client/src/app/pages/issues/issue-detail-drawer/file-incidents-detail-modal/incident-code-snip-viewer.tsx @@ -4,6 +4,15 @@ import { AnalysisIncident } from "@app/api/models"; import "./incident-code-snip-viewer.css"; import { LANGUAGES_BY_FILE_EXTENSION } from "config/monacoConstants"; +import { + EmptyState, + EmptyStateBody, + EmptyStateHeader, + EmptyStateIcon, + EmptyStateVariant, +} from "@patternfly/react-core"; +import { CubesIcon } from "@patternfly/react-icons"; +import { useTranslation } from "react-i18next"; const codeLineRegex = /^\s*([0-9]+)( {2})?(.*)$/; // Pattern: leading whitespace (line number) (2 spaces)? (code) @@ -16,6 +25,22 @@ export const IncidentCodeSnipViewer: React.FC = ({ issueTitle, incident, }) => { + const { t } = useTranslation(); + + if (!incident?.codeSnip.trim()) { + return ( + + } + /> + + {t("message.noCodesSnippetAvailableBody")} + + + ); + } const codeSnipNumberedLines = incident.codeSnip.split("\n"); const codeSnipTrimmedLines: string[] = []; let codeSnipStartLine = 1; From d07b30d71758d0ca6460a1a4ab7ae4817b84dfe9 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Mon, 26 Feb 2024 09:59:47 -0500 Subject: [PATCH 20/53] :sparkles: Add url filter to drawer results for dependency apps (#1698) Resolves https://issues.redhat.com/browse/MTA-2008 && https://github.com/konveyor/tackle2-ui/issues/1498 Signed-off-by: Ian Bolton --- .../filtering/useFilterState.ts | 20 +++++++++++++--- .../dependencies/dependency-apps-table.tsx | 23 +++++++++++++++++-- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/client/src/app/hooks/table-controls/filtering/useFilterState.ts b/client/src/app/hooks/table-controls/filtering/useFilterState.ts index 890f9dd686..2de43e1f7c 100644 --- a/client/src/app/hooks/table-controls/filtering/useFilterState.ts +++ b/client/src/app/hooks/table-controls/filtering/useFilterState.ts @@ -4,6 +4,7 @@ import { usePersistentState } from "@app/hooks/usePersistentState"; import { serializeFilterUrlParams } from "./helpers"; import { deserializeFilterUrlParams } from "./helpers"; import { DiscriminatedArgs } from "@app/utils/type-utils"; +import { useEffect, useState } from "react"; /** * The "source of truth" state for the filter feature. @@ -64,9 +65,22 @@ export const useFilterState = < ): IFilterState => { const { isFilterEnabled, persistTo = "state", persistenceKeyPrefix } = args; - const initialFilterValues: IFilterValues = isFilterEnabled - ? args?.initialFilterValues ?? {} - : {}; + // We need to know if it's the initial load to avoid overwriting changes to the filter values + const [isInitialLoad, setIsInitialLoad] = useState(true); + + let initialFilterValues = {}; + + if (isInitialLoad) { + initialFilterValues = isFilterEnabled + ? args?.initialFilterValues ?? {} + : {}; + } + + useEffect(() => { + if (isInitialLoad) { + setIsInitialLoad(false); + } + }, [isInitialLoad]); // 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 diff --git a/client/src/app/pages/dependencies/dependency-apps-table.tsx b/client/src/app/pages/dependencies/dependency-apps-table.tsx index 793db71824..0efcf836bb 100644 --- a/client/src/app/pages/dependencies/dependency-apps-table.tsx +++ b/client/src/app/pages/dependencies/dependency-apps-table.tsx @@ -15,6 +15,7 @@ import { useTableControlState, useTableControlProps, getHubRequestParams, + deserializeFilterUrlParams, } from "@app/hooks/table-controls"; import { TablePersistenceKeyPrefix } from "@app/Constants"; import { @@ -30,6 +31,7 @@ import { useFetchBusinessServices } from "@app/queries/businessservices"; import { useFetchTagsWithTagItems } from "@app/queries/tags"; import { getParsedLabel } from "@app/utils/rules-utils"; import { extractFirstSha } from "@app/utils/utils"; +import { useHistory } from "react-router-dom"; export interface IDependencyAppsTableProps { dependency: AnalysisDependency; @@ -39,9 +41,15 @@ export const DependencyAppsTable: React.FC = ({ dependency, }) => { const { t } = useTranslation(); + const history = useHistory(); + const { businessServices } = useFetchBusinessServices(); const { tagItems } = useFetchTagsWithTagItems(); + const urlParams = new URLSearchParams(window.location.search); + const filters = urlParams.get("filters"); + const deserializedFilterValues = deserializeFilterUrlParams({ filters }); + const tableControlState = useTableControlState({ persistTo: "urlParams", persistenceKeyPrefix: TablePersistenceKeyPrefix.dependencyApplications, @@ -56,9 +64,10 @@ export const DependencyAppsTable: React.FC = ({ isPaginationEnabled: true, sortableColumns: ["name", "version"], initialSort: { columnKey: "name", direction: "asc" }, + initialFilterValues: deserializedFilterValues, filterCategories: [ { - key: "name", + key: "application.name", title: "Application Name", type: FilterType.search, placeholderText: @@ -147,9 +156,19 @@ export const DependencyAppsTable: React.FC = ({ }, } = tableControls; + const clearFilters = () => { + const currentPath = history.location.pathname; + const newSearch = new URLSearchParams(history.location.search); + newSearch.delete("filters"); + history.push(`${currentPath}`); + }; return ( <> - + From 2febd180a328a415297cef700e7a2d67d2e5ab6c Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Tue, 27 Feb 2024 10:57:39 -0500 Subject: [PATCH 21/53] :bug: Add parser for custom rule file label title in manual upload flow (#1702) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves https://issues.redhat.com/browse/MTA-2004 Screenshot 2024-02-27 at 9 59 25 AM --------- Signed-off-by: Ian Bolton --- .../applications/analysis-wizard/custom-rules.tsx | 8 +++++--- client/src/app/utils/rules-utils.ts | 11 ++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/client/src/app/pages/applications/analysis-wizard/custom-rules.tsx b/client/src/app/pages/applications/analysis-wizard/custom-rules.tsx index 24508ac368..e839cf4b2b 100644 --- a/client/src/app/pages/applications/analysis-wizard/custom-rules.tsx +++ b/client/src/app/pages/applications/analysis-wizard/custom-rules.tsx @@ -163,6 +163,10 @@ export const CustomRules: React.FC = () => { filteredItems?.forEach((item) => { const { source, target, total } = parseRules(item); + const sourceLabelName = getParsedLabel(source)?.labelValue ?? ""; + const targetLabelName = getParsedLabel(target)?.labelValue ?? ""; + const sourceTargetLabel = `${sourceLabelName} / ${targetLabelName}`; + rows.push({ entity: item, cells: [ @@ -171,9 +175,7 @@ export const CustomRules: React.FC = () => { }, { title: ( - - {source} / {target} - + {sourceTargetLabel} ), }, { diff --git a/client/src/app/utils/rules-utils.ts b/client/src/app/utils/rules-utils.ts index a04dc88583..3c460d6587 100644 --- a/client/src/app/utils/rules-utils.ts +++ b/client/src/app/utils/rules-utils.ts @@ -104,16 +104,25 @@ interface ParsedLabel { labelValue: string; } -export const getParsedLabel = (label: string): ParsedLabel => { +export const getParsedLabel = (label: string | null): ParsedLabel => { + if (label === null) { + return { + labelType: "", + labelValue: "", + }; + } + const char1 = label.indexOf("/") + 1; const char2 = label.lastIndexOf("="); const type = label.substring(char1, char2); const value = label.split("=").pop(); + return { labelType: type || "", labelValue: value || "", }; }; + export const getLabels = (labels: string[]) => labels.reduce( (map: ILabelMap, label) => { From 59ad200adc36237a2a26bfc7405b26b9d508ec16 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Tue, 27 Feb 2024 19:14:51 -0500 Subject: [PATCH 22/53] :bug: Handle case when application.archetypes is passed but null (#1707) Resolves https://issues.redhat.com/browse/MTA-2320 - Missed a case when calculating associated assessed archetypes to an application. If application is passed to the useFetchArchetypes query but application.archetypes is null, still returning all archetypes instead of an empty list. --------- Signed-off-by: Ian Bolton --- client/src/app/queries/archetypes.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/app/queries/archetypes.ts b/client/src/app/queries/archetypes.ts index e2d6efc470..7cd3b45051 100644 --- a/client/src/app/queries/archetypes.ts +++ b/client/src/app/queries/archetypes.ts @@ -26,11 +26,12 @@ export const useFetchArchetypes = (forApplication?: Application | null) => { const { isLoading, isSuccess, error, refetch, data } = useQuery({ initialData: [], queryKey: [ARCHETYPES_QUERY_KEY, forApplication?.id], - queryFn: getArchetypes, refetchInterval: 5000, onSuccess: (fetchedArchetypes) => { - if (forApplication && forApplication.archetypes) { + if (!forApplication) { + setFilteredArchetypes(fetchedArchetypes); + } else if (Array.isArray(forApplication.archetypes)) { const archetypeIds = forApplication.archetypes.map( (archetype) => archetype.id ); @@ -39,18 +40,17 @@ export const useFetchArchetypes = (forApplication?: Application | null) => { ); setFilteredArchetypes(filtered); } else { - setFilteredArchetypes(fetchedArchetypes); + setFilteredArchetypes([]); } queryClient.invalidateQueries([reviewsQueryKey]); queryClient.invalidateQueries([assessmentsQueryKey]); queryClient.invalidateQueries([assessmentsByItemIdQueryKey]); }, - onError: (error: AxiosError) => console.log(error), }); return { - archetypes: filteredArchetypes || [], + archetypes: filteredArchetypes, isFetching: isLoading, isSuccess, error, From 6040a5d8c6f85b2cf99e284304fe52e358fc6597 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Wed, 28 Feb 2024 13:47:01 -0500 Subject: [PATCH 23/53] :bug: Add tooltip for migration wave delete option in app table (#1705) Resolves https://issues.redhat.com/browse/MTA-1958 - Also adds translation entry for other similar message in toolbar --------- Signed-off-by: Ian Bolton Co-authored-by: Scott Dickerson --- client/public/locales/en/translation.json | 1 + .../applications-table/applications-table.tsx | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/client/public/locales/en/translation.json b/client/public/locales/en/translation.json index 7b3c3993c2..32f0ae1e7b 100644 --- a/client/public/locales/en/translation.json +++ b/client/public/locales/en/translation.json @@ -176,6 +176,7 @@ "blockedDeleteApplication": "Cannot delete {{what}} because it is associated with an application.", "blockedDeleteTarget": "Cannot delete {{what}} because it is associated with a target.", "defaultBlockedDelete": "Cannot delete {{what}} because it is associated with another object.", + "cannotDeleteApplicationsAssignedToMigrationWave": "Cannot delete applications that are assigned to a migration wave.", "continueConfirmation": "Yes, continue", "copyAssessmentAndReviewBody": "Some of the selected target applications have an in-progress or complete assessment/review. By continuing, the existing assessment(s)/review(s) will be replaced by the copied assessment/review. Do you wish to continue?", "copyAssessmentAndReviewQuestion": "Copy assessment and review?", 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 09ae2e7d9d..796d9f316b 100644 --- a/client/src/app/pages/applications/applications-table/applications-table.tsx +++ b/client/src/app/pages/applications/applications-table/applications-table.tsx @@ -573,15 +573,12 @@ export const ApplicationsTable: React.FC = () => { , ] : []; - const applicationDropdownItems = applicationWriteAccess ? [ { ...(applicationWriteAccess ? [ { + isAriaDisabled: + application.migrationWave !== null, + tooltipProps: { + content: + application.migrationWave !== null + ? t( + "message.cannotDeleteApplicationsAssignedToMigrationWave" + ) + : "", + }, + title: t("actions.delete"), onClick: () => setApplicationsToDelete([application]), - isDisabled: - application.migrationWave !== null, }, ] : []), From 5a30824daf7a8e3f30bff9c313cd1634a4e2ecc6 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Wed, 28 Feb 2024 17:06:48 -0500 Subject: [PATCH 24/53] :bug: Address style issues on assessment summary / questionnaire view (#1706) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves https://issues.redhat.com/browse/MTA-1880 - Adds spacing for vertical tabs to align with question table - Adds spacing for expanded section to meet PF standards as outlined in above issue comments from UXD - Adds Explanation term for explanation previously not labeled. Screenshot 2024-02-27 at 2 48 46 PM --------- Signed-off-by: Ian Bolton Co-authored-by: Scott Dickerson --- client/public/locales/en/translation.json | 1 + .../questionnaire-summary/questionnaire-summary.tsx | 1 + .../components/questions-table/questions-table.tsx | 13 ++++++++----- .../questionnaire/questionnaire-page.css | 5 +++++ .../assessment-summary/assessment-summary-page.css | 11 ----------- .../assessment-summary/assessment-summary-page.tsx | 1 - 6 files changed, 15 insertions(+), 17 deletions(-) delete mode 100644 client/src/app/pages/assessment/components/assessment-summary/assessment-summary-page.css diff --git a/client/public/locales/en/translation.json b/client/public/locales/en/translation.json index 32f0ae1e7b..29f0802aaf 100644 --- a/client/public/locales/en/translation.json +++ b/client/public/locales/en/translation.json @@ -323,6 +323,7 @@ "email": "Email", "error": "Error", "errorReport": "Error report", + "explanation": "Explanation", "exclude": "Exclude", "exportToIssue": "Export to Issue Manager", "facts": "Facts", diff --git a/client/src/app/components/questionnaire-summary/questionnaire-summary.tsx b/client/src/app/components/questionnaire-summary/questionnaire-summary.tsx index d9b44830a0..0fded78200 100644 --- a/client/src/app/components/questionnaire-summary/questionnaire-summary.tsx +++ b/client/src/app/components/questionnaire-summary/questionnaire-summary.tsx @@ -166,6 +166,7 @@ const QuestionnaireSummary: React.FC = ({ isVertical aria-label="Tabs for summaryData sections" role="region" + className="tabs-vertical-container__tabs" > {[ - {question.explanation} - +
+ {t("terms.explanation")}:   + {question.explanation} + +
diff --git a/client/src/app/pages/assessment-management/questionnaire/questionnaire-page.css b/client/src/app/pages/assessment-management/questionnaire/questionnaire-page.css index 52420e3fe3..597d206106 100644 --- a/client/src/app/pages/assessment-management/questionnaire/questionnaire-page.css +++ b/client/src/app/pages/assessment-management/questionnaire/questionnaire-page.css @@ -1,5 +1,10 @@ .tabs-vertical-container { display: flex; + margin-top: 1.5em; +} + +.tabs-vertical-container__tabs { + margin-top: 1.5em; } .tabs-vertical-container .pf-v5-c-tabs { diff --git a/client/src/app/pages/assessment/components/assessment-summary/assessment-summary-page.css b/client/src/app/pages/assessment/components/assessment-summary/assessment-summary-page.css deleted file mode 100644 index 52420e3fe3..0000000000 --- a/client/src/app/pages/assessment/components/assessment-summary/assessment-summary-page.css +++ /dev/null @@ -1,11 +0,0 @@ -.tabs-vertical-container { - display: flex; -} - -.tabs-vertical-container .pf-v5-c-tabs { - width: 20%; -} - -.tabs-vertical-container .pf-v5-c-tab-content { - width: 80%; -} diff --git a/client/src/app/pages/assessment/components/assessment-summary/assessment-summary-page.tsx b/client/src/app/pages/assessment/components/assessment-summary/assessment-summary-page.tsx index 8a840c8e06..1325284d24 100644 --- a/client/src/app/pages/assessment/components/assessment-summary/assessment-summary-page.tsx +++ b/client/src/app/pages/assessment/components/assessment-summary/assessment-summary-page.tsx @@ -1,6 +1,5 @@ import React from "react"; import { useParams } from "react-router-dom"; -import "./assessment-summary-page.css"; import QuestionnaireSummary, { SummaryType, } from "@app/components/questionnaire-summary/questionnaire-summary"; From e9304fae78fd855fefaddcc35400ad3bcf45e749 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Wed, 28 Feb 2024 18:30:04 -0500 Subject: [PATCH 25/53] :bug: Optimize assessment fetching (#1716) Resolves https://issues.redhat.com/browse/MTA-2296 Resolves https://issues.redhat.com/browse/MTA-1973 --------- Signed-off-by: Ian Bolton --- .../application-assessment-status.tsx | 109 +++++++++++++----- .../components/assessed-archetypes.tsx | 46 ++++---- client/src/app/queries/archetypes.ts | 2 +- client/src/app/queries/assessments.ts | 32 ----- 4 files changed, 100 insertions(+), 89 deletions(-) diff --git a/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx b/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx index 56b6cf738f..cf05a18ba5 100644 --- a/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx +++ b/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx @@ -2,9 +2,9 @@ import React from "react"; import { useTranslation } from "react-i18next"; import { Spinner } from "@patternfly/react-core"; import { EmptyTextMessage } from "@app/components/EmptyTextMessage"; -import { Application } from "@app/api/models"; +import { Application, Assessment } from "@app/api/models"; import { IconedStatus, IconedStatusPreset } from "@app/components/IconedStatus"; -import { useFetchAssessmentsByItemId } from "@app/queries/assessments"; +import { useFetchAssessments } from "@app/queries/assessments"; import { useFetchArchetypes } from "@app/queries/archetypes"; interface ApplicationAssessmentStatusProps { application: Application; @@ -16,58 +16,103 @@ export const ApplicationAssessmentStatus: React.FC< > = ({ application }) => { const { t } = useTranslation(); - const { archetypes, isFetching } = useFetchArchetypes(); + const { archetypes, isFetching } = useFetchArchetypes(application); + const { assessments, fetchError } = useFetchAssessments(); - const applicationArchetypes = application.archetypes?.map((archetypeRef) => { - return archetypes?.find((archetype) => archetype.id === archetypeRef.id); - }); - - const someArchetypesAssessed = applicationArchetypes?.some( - (archetype) => !!archetype?.assessments?.length ?? 0 > 0 + const filteredAssessments = assessments?.filter( + (assessment: Assessment) => assessment.application?.id === application.id ); - const areAllArchetypesAssessed = - applicationArchetypes?.every( - (archetype) => archetype?.assessments?.length ?? 0 > 0 - ) ?? false; + const assessmentStatusInfo = React.useMemo(() => { + const assessmentsWithArchetypes = archetypes.map((archetype) => ({ + archetype, + assessments: assessments.filter( + (assessment) => assessment.archetype?.id === archetype.id + ), + })); - const { - assessments, - isFetching: isFetchingAssessmentsById, - fetchError, - } = useFetchAssessmentsByItemId(false, application.id); + const someArchetypesAssessed = assessmentsWithArchetypes.some( + ({ assessments }) => assessments.length > 0 + ); + + const allArchetypesAssessed = + assessmentsWithArchetypes.length > 0 && + assessmentsWithArchetypes.every(({ archetype, assessments }) => { + const requiredAssessments = assessments.filter( + (assessment) => assessment.required + ); + return ( + archetype.assessed && + assessments.length > 0 && + requiredAssessments.length > 0 && + requiredAssessments.every( + (assessment) => assessment.status === "complete" + ) + ); + }); + + const hasInProgressOrNotStartedRequiredAssessments = + assessmentsWithArchetypes.some(({ assessments }) => + assessments.some( + (assessment) => + assessment.required && + ["empty", "started"].includes(assessment.status) + ) + ); + + const assessedArchetypesWithARequiredAssessment = + assessmentsWithArchetypes.filter(({ assessments, archetype }) => + assessments.some( + (assessment) => + assessment.required && + assessment.status === "complete" && + archetype.assessed + ) + ); + const assessedArchetypeCount = + archetypes?.filter( + (archetype) => + archetype?.assessments?.length ?? (0 > 0 && archetype.assessed) + ).length || 0; + + return { + assessmentsWithArchetypes, + someArchetypesAssessed, + allArchetypesAssessed, + hasInProgressOrNotStartedRequiredAssessments, + assessedArchetypesWithARequiredAssessment, + assessedArchetypeCount, + }; + }, [archetypes, assessments]); if (fetchError) { return ; } - if (isFetching || isFetchingAssessmentsById) { + if (isFetching || isFetching) { return ; } let statusPreset: IconedStatusPreset = "NotStarted"; // Default status let tooltipCount: number = 0; - const assessedArchetypeCount = - applicationArchetypes?.filter( - (archetype) => archetype?.assessments?.length ?? 0 > 0 - ).length || 0; - const isDirectlyAssessed = application.assessed && (application.assessments?.length ?? 0) > 0; + const { + allArchetypesAssessed, + assessedArchetypesWithARequiredAssessment, + hasInProgressOrNotStartedRequiredAssessments, + } = assessmentStatusInfo; if (isDirectlyAssessed) { statusPreset = "Completed"; - } else if (areAllArchetypesAssessed) { + } else if (allArchetypesAssessed) { statusPreset = "InheritedAssessments"; - tooltipCount = assessedArchetypeCount; - } else if (someArchetypesAssessed) { + tooltipCount = assessedArchetypesWithARequiredAssessment.length; + } else if (hasInProgressOrNotStartedRequiredAssessments) { statusPreset = "InProgressInheritedAssessments"; - tooltipCount = assessedArchetypeCount; + tooltipCount = assessedArchetypesWithARequiredAssessment.length; } else if ( - assessments?.some( - (assessment) => - assessment.status === "started" || assessment.status === "complete" - ) + filteredAssessments?.some((assessment) => assessment.status === "started") ) { statusPreset = "InProgress"; } diff --git a/client/src/app/pages/applications/components/application-detail-drawer/components/assessed-archetypes.tsx b/client/src/app/pages/applications/components/application-detail-drawer/components/assessed-archetypes.tsx index 89503af756..03da85083e 100644 --- a/client/src/app/pages/applications/components/application-detail-drawer/components/assessed-archetypes.tsx +++ b/client/src/app/pages/applications/components/application-detail-drawer/components/assessed-archetypes.tsx @@ -1,10 +1,10 @@ import React from "react"; -import { Application } from "@app/api/models"; +import { Application, AssessmentWithSectionOrder } from "@app/api/models"; import { Label, LabelGroup, Spinner } from "@patternfly/react-core"; import { EmptyTextMessage } from "@app/components/EmptyTextMessage"; import { useTranslation } from "react-i18next"; import { useFetchArchetypes } from "@app/queries/archetypes"; -import { useFetchAllAssessmentsWithArchetypes } from "@app/queries/assessments"; +import { useFetchAssessments } from "@app/queries/assessments"; interface IAssessedArchetypesProps { application: Application | null; @@ -14,35 +14,33 @@ export const AssessedArchetypes: React.FC = ({ application, }) => { const { t } = useTranslation(); - const { - archetypes: applicationArchetypes, - isFetching: isFetchingArchetypes, - } = useFetchArchetypes(application); + const { archetypes, isFetching: isFetchingArchetypes } = + useFetchArchetypes(application); + const { assessments, isFetching: isFetchingAssessments } = + useFetchAssessments(); - const { - assessmentsWithArchetypes, - isLoading: isFetchingAllAssessmentsWithArchetypesLoading, - } = useFetchAllAssessmentsWithArchetypes(applicationArchetypes); + const assessedArchetypes = React.useMemo(() => { + if (!archetypes || !assessments) return []; - const assessedArchetypesWithARequiredAssessment = assessmentsWithArchetypes - ?.filter((assessmentsWithArchetype) => { - return ( - assessmentsWithArchetype.archetype.assessed && - assessmentsWithArchetype.assessments.some( - (assessment) => assessment?.required === true - ) - ); - }) - .map((assessmentsWithArchetype) => assessmentsWithArchetype.archetype); + return archetypes.filter((archetype) => + assessments.some( + (assessment: AssessmentWithSectionOrder) => + assessment.archetype?.id === archetype.id && + assessment.required && + archetype.assessed + ) + ); + }, [archetypes, assessments]); - if (isFetchingArchetypes || isFetchingAllAssessmentsWithArchetypesLoading) { + if (isFetchingArchetypes || isFetchingAssessments) { return ; } + return ( - {assessedArchetypesWithARequiredAssessment?.length ? ( - assessedArchetypesWithARequiredAssessment?.map((archetype) => ( - + {assessedArchetypes.length ? ( + assessedArchetypes.map((archetype) => ( + )) ) : ( diff --git a/client/src/app/queries/archetypes.ts b/client/src/app/queries/archetypes.ts index 7cd3b45051..a740d564d2 100644 --- a/client/src/app/queries/archetypes.ts +++ b/client/src/app/queries/archetypes.ts @@ -27,7 +27,6 @@ export const useFetchArchetypes = (forApplication?: Application | null) => { initialData: [], queryKey: [ARCHETYPES_QUERY_KEY, forApplication?.id], queryFn: getArchetypes, - refetchInterval: 5000, onSuccess: (fetchedArchetypes) => { if (!forApplication) { setFilteredArchetypes(fetchedArchetypes); @@ -42,6 +41,7 @@ export const useFetchArchetypes = (forApplication?: Application | null) => { } else { setFilteredArchetypes([]); } + queryClient.invalidateQueries([reviewsQueryKey]); queryClient.invalidateQueries([assessmentsQueryKey]); queryClient.invalidateQueries([assessmentsByItemIdQueryKey]); diff --git a/client/src/app/queries/assessments.ts b/client/src/app/queries/assessments.ts index 77cd04d579..8b6cfab07b 100644 --- a/client/src/app/queries/assessments.ts +++ b/client/src/app/queries/assessments.ts @@ -17,11 +17,9 @@ import { } from "@app/api/rest"; import { AxiosError } from "axios"; import { - Archetype, Assessment, AssessmentWithArchetypeApplications, AssessmentWithSectionOrder, - AssessmentsWithArchetype, InitialAssessment, } from "@app/api/models"; import { QuestionnairesQueryKey } from "./questionnaires"; @@ -264,33 +262,3 @@ export const useFetchAssessmentsWithArchetypeApplications = () => { isLoading: assessmentsLoading || isArchetypesLoading, }; }; - -export const useFetchAllAssessmentsWithArchetypes = ( - archetypes: Archetype[] = [] -) => { - const assessmentQueries = useQueries({ - queries: archetypes.map((archetype) => ({ - queryKey: ["assessmentsForArchetype", archetype.id], - queryFn: () => getAssessmentsByItemId(true, archetype.id), - })), - }); - - const assessmentsWithArchetypes: AssessmentsWithArchetype[] = - assessmentQueries - .map((query, index) => { - if (query.isSuccess) { - return { - archetype: archetypes[index], - assessments: query.data, - }; - } - return null; - }) - .filter(Boolean); - - return { - assessmentsWithArchetypes, - isLoading: assessmentQueries.some((query) => query.isLoading), - isError: assessmentQueries.some((query) => query.isError), - }; -}; From d346801824340e240226d158b6620be1e56b0cc8 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Wed, 28 Feb 2024 19:12:19 -0500 Subject: [PATCH 26/53] :bug: Load filter values for multiselect before input (#1713) Resolves https://issues.redhat.com/browse/MTA-2322 - Need to load the select options into the dropdown state in cases where category.selectOptions is async --------- Signed-off-by: Ian Bolton --- .../components/FilterToolbar/MultiselectFilterControl.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx b/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx index f88511099e..1d2297ee7b 100644 --- a/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx +++ b/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx @@ -49,6 +49,12 @@ export const MultiselectFilterControl = ({ FilterSelectOptionProps[] >(Array.isArray(category.selectOptions) ? category.selectOptions : []); + React.useEffect(() => { + setSelectOptions( + Array.isArray(category.selectOptions) ? category.selectOptions : [] + ); + }, [category.selectOptions]); + const hasGroupings = !Array.isArray(selectOptions); const flatOptions: FilterSelectOptionProps[] = !hasGroupings From ccb8dfd0f704fef24ffcd57a2f697cb9903ad73d Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Wed, 28 Feb 2024 20:08:31 -0500 Subject: [PATCH 27/53] :bug: Adjust risk values displayed based on questionnaire filter (#1711) Resolves https://issues.redhat.com/browse/MTA-2093 - Uses the assessment risk when a specific questionnaire is selected in the landscape filter rather than the application risk. --------- Signed-off-by: Ian Bolton --- .../application-landscape.tsx | 13 ++++-- client/src/app/queries/assessments.ts | 42 +++++++++---------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/client/src/app/pages/reports/components/application-landscape/application-landscape.tsx b/client/src/app/pages/reports/components/application-landscape/application-landscape.tsx index 6637c350e8..cdc88f04e7 100644 --- a/client/src/app/pages/reports/components/application-landscape/application-landscape.tsx +++ b/client/src/app/pages/reports/components/application-landscape/application-landscape.tsx @@ -29,7 +29,8 @@ interface IAggregateRiskData { const aggregateRiskData = ( assessments: AssessmentWithArchetypeApplications[], - applications: Application[] + applications: Application[], + questionnaire: Questionnaire | null ): IAggregateRiskData => { let low = 0; let medium = 0; @@ -61,8 +62,12 @@ const aggregateRiskData = ( const fullApp = findFullApplication(appRef); if (fullApp && fullApp.risk && !processedAppIds.has(fullApp.id)) { processedAppIds.add(fullApp.id); + let risk = fullApp.risk; + if (questionnaire?.id === assessment.questionnaire.id) { + risk = assessment.risk; + } - switch (fullApp.risk) { + switch (risk) { case "green": low++; break; @@ -119,8 +124,8 @@ export const ApplicationLandscape: React.FC = ({ ); const landscapeData = useMemo( - () => aggregateRiskData(filteredAssessments, applications), - [filteredAssessments, applications] + () => aggregateRiskData(filteredAssessments, applications, questionnaire), + [filteredAssessments, applications, questionnaire] ); return ( diff --git a/client/src/app/queries/assessments.ts b/client/src/app/queries/assessments.ts index 8b6cfab07b..44508dc353 100644 --- a/client/src/app/queries/assessments.ts +++ b/client/src/app/queries/assessments.ts @@ -18,7 +18,6 @@ import { import { AxiosError } from "axios"; import { Assessment, - AssessmentWithArchetypeApplications, AssessmentWithSectionOrder, InitialAssessment, } from "@app/api/models"; @@ -222,18 +221,21 @@ const removeSectionOrderFromQuestions = ( export const useFetchAssessmentsWithArchetypeApplications = () => { const { assessments, isFetching: assessmentsLoading } = useFetchAssessments(); + const archetypeQueries = useMemo(() => { + const uniqueArchetypeIds = new Set( + assessments.map((assessment) => assessment?.archetype?.id).filter(Boolean) + ); + return Array.from(uniqueArchetypeIds).map((archetypeId) => ({ + queryKey: ["archetype", archetypeId], + queryFn: async () => { + const data = await getArchetypeById(archetypeId); + return { archetypeId, applications: data.applications }; + }, + })); + }, [assessments]); + const archetypesUsedInAnAssessmentQueries = useQueries({ - queries: - [ - ...new Set( - assessments - .map((assessment) => assessment?.archetype?.id) - .filter(Boolean) - ), - ].map((archetypeId) => ({ - queryKey: ["archetype", archetypeId], - queryFn: () => getArchetypeById(archetypeId), - })) || [], + queries: archetypeQueries, }); const isArchetypesLoading = archetypesUsedInAnAssessmentQueries.some( @@ -241,21 +243,19 @@ export const useFetchAssessmentsWithArchetypeApplications = () => { ); const archetypeApplicationsMap = new Map(); - archetypesUsedInAnAssessmentQueries.forEach((query, index) => { - if (query.data && assessments[index].archetype?.id) { - archetypeApplicationsMap.set( - assessments[index]?.archetype?.id, - query.data.applications - ); + archetypesUsedInAnAssessmentQueries.forEach(({ data }) => { + if (data) { + archetypeApplicationsMap.set(data.archetypeId, data.applications); } }); - const assessmentsWithArchetypeApplications: AssessmentWithArchetypeApplications[] = - assessments.map((assessment) => ({ + const assessmentsWithArchetypeApplications = assessments.map( + (assessment) => ({ ...assessment, archetypeApplications: archetypeApplicationsMap.get(assessment?.archetype?.id) ?? [], - })); + }) + ); return { assessmentsWithArchetypeApplications, From cbd66f9817e3d541cee93d6ce02d6034afaf6f04 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Thu, 29 Feb 2024 09:38:55 -0500 Subject: [PATCH 28/53] :sparkles: Reduce assessment calls in effort to reduce network overhead (#1724) - Reduce assessment fetch calls resulting from unnecessary hook calls & query invalidations. - Passes assessments down from app table into sub components Signed-off-by: Ian Bolton --- .../applications-table/applications-table.tsx | 12 +++++++++++- .../application-assessment-status.tsx | 18 +++++------------- .../application-detail-drawer.tsx | 17 +++++++++++++---- .../components/assessed-archetypes.tsx | 7 +++---- client/src/app/queries/applications.ts | 6 +----- client/src/app/queries/archetypes.ts | 6 +----- 6 files changed, 34 insertions(+), 32 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 796d9f316b..ff7c364c1b 100644 --- a/client/src/app/pages/applications/applications-table/applications-table.tsx +++ b/client/src/app/pages/applications/applications-table/applications-table.tsx @@ -80,7 +80,10 @@ import { useFetchApplications, } from "@app/queries/applications"; import { useCancelTaskMutation, useFetchTasks } from "@app/queries/tasks"; -import { useDeleteAssessmentMutation } from "@app/queries/assessments"; +import { + useDeleteAssessmentMutation, + useFetchAssessments, +} from "@app/queries/assessments"; import { useDeleteReviewMutation } from "@app/queries/reviews"; import { useFetchIdentities } from "@app/queries/identities"; import { useFetchTagsWithTagItems } from "@app/queries/tags"; @@ -104,6 +107,7 @@ import { TaskGroupProvider } from "../analysis-wizard/components/TaskGroupContex import { ApplicationIdentityForm } from "../components/application-identity-form/application-identity-form"; import { ApplicationReviewStatus } from "../components/application-review-status/application-review-status"; import { KebabDropdown } from "@app/components/KebabDropdown"; +import { useFetchArchetypes } from "@app/queries/archetypes"; export const ApplicationsTable: React.FC = () => { const { t } = useTranslation(); @@ -207,6 +211,9 @@ export const ApplicationsTable: React.FC = () => { refetch: fetchApplications, } = useFetchApplications(); + const { assessments } = useFetchAssessments(); + const { archetypes } = useFetchArchetypes(); + const onDeleteApplicationSuccess = (appIDCount: number) => { pushNotification({ title: t("toastr.success.applicationDeleted", { @@ -885,6 +892,8 @@ export const ApplicationsTable: React.FC = () => { > @@ -1059,6 +1068,7 @@ export const ApplicationsTable: React.FC = () => { setSaveApplicationModalState(activeItem)} task={activeItem ? getTask(activeItem) : null} diff --git a/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx b/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx index cf05a18ba5..8f2314f032 100644 --- a/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx +++ b/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx @@ -1,24 +1,20 @@ import React from "react"; import { useTranslation } from "react-i18next"; -import { Spinner } from "@patternfly/react-core"; import { EmptyTextMessage } from "@app/components/EmptyTextMessage"; -import { Application, Assessment } from "@app/api/models"; +import { Application, Archetype, Assessment } from "@app/api/models"; import { IconedStatus, IconedStatusPreset } from "@app/components/IconedStatus"; -import { useFetchAssessments } from "@app/queries/assessments"; -import { useFetchArchetypes } from "@app/queries/archetypes"; interface ApplicationAssessmentStatusProps { application: Application; + assessments: Assessment[]; + archetypes: Archetype[]; isLoading?: boolean; } export const ApplicationAssessmentStatus: React.FC< ApplicationAssessmentStatusProps -> = ({ application }) => { +> = ({ application, assessments, archetypes }) => { const { t } = useTranslation(); - const { archetypes, isFetching } = useFetchArchetypes(application); - const { assessments, fetchError } = useFetchAssessments(); - const filteredAssessments = assessments?.filter( (assessment: Assessment) => assessment.application?.id === application.id ); @@ -84,14 +80,10 @@ export const ApplicationAssessmentStatus: React.FC< }; }, [archetypes, assessments]); - if (fetchError) { + if (archetypes?.length === 0 || assessments?.length === 0) { return ; } - if (isFetching || isFetching) { - return ; - } - let statusPreset: IconedStatusPreset = "NotStarted"; // Default status let tooltipCount: number = 0; 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 7a127d3435..b721a02478 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 @@ -31,6 +31,7 @@ import { MimeType, Ref, Archetype, + AssessmentWithSectionOrder, } from "@app/api/models"; import { IPageDrawerContentProps, @@ -64,6 +65,7 @@ export interface IApplicationDetailDrawerProps application: Application | null; task: Task | undefined | null; applications?: Application[]; + assessments?: AssessmentWithSectionOrder[]; onEditClick: () => void; } @@ -77,7 +79,7 @@ enum TabKey { export const ApplicationDetailDrawer: React.FC< IApplicationDetailDrawerProps -> = ({ onCloseClick, application, task, onEditClick }) => { +> = ({ onCloseClick, application, assessments, task, onEditClick }) => { const { t } = useTranslation(); const [activeTabKey, setActiveTabKey] = React.useState( TabKey.Details @@ -212,9 +214,16 @@ export const ApplicationDetailDrawer: React.FC< {t("terms.archetypesAssessed")} - - - + {assessments && assessments.length ? ( + + + + ) : ( + + )}
diff --git a/client/src/app/pages/applications/components/application-detail-drawer/components/assessed-archetypes.tsx b/client/src/app/pages/applications/components/application-detail-drawer/components/assessed-archetypes.tsx index 03da85083e..6136bd73a6 100644 --- a/client/src/app/pages/applications/components/application-detail-drawer/components/assessed-archetypes.tsx +++ b/client/src/app/pages/applications/components/application-detail-drawer/components/assessed-archetypes.tsx @@ -4,20 +4,19 @@ import { Label, LabelGroup, Spinner } from "@patternfly/react-core"; import { EmptyTextMessage } from "@app/components/EmptyTextMessage"; import { useTranslation } from "react-i18next"; import { useFetchArchetypes } from "@app/queries/archetypes"; -import { useFetchAssessments } from "@app/queries/assessments"; interface IAssessedArchetypesProps { application: Application | null; + assessments: AssessmentWithSectionOrder[] | null; } export const AssessedArchetypes: React.FC = ({ application, + assessments, }) => { const { t } = useTranslation(); const { archetypes, isFetching: isFetchingArchetypes } = useFetchArchetypes(application); - const { assessments, isFetching: isFetchingAssessments } = - useFetchAssessments(); const assessedArchetypes = React.useMemo(() => { if (!archetypes || !assessments) return []; @@ -32,7 +31,7 @@ export const AssessedArchetypes: React.FC = ({ ); }, [archetypes, assessments]); - if (isFetchingArchetypes || isFetchingAssessments) { + if (isFetchingArchetypes) { return ; } diff --git a/client/src/app/queries/applications.ts b/client/src/app/queries/applications.ts index 1adf91d17f..8e5fc98eb8 100644 --- a/client/src/app/queries/applications.ts +++ b/client/src/app/queries/applications.ts @@ -21,10 +21,7 @@ import { updateApplication, } from "@app/api/rest"; import { reviewsQueryKey } from "./reviews"; -import { - assessmentsByItemIdQueryKey, - assessmentsQueryKey, -} from "./assessments"; +import { assessmentsByItemIdQueryKey } from "./assessments"; import saveAs from "file-saver"; export const ApplicationDependencyQueryKey = "applicationdependencies"; @@ -45,7 +42,6 @@ export const useFetchApplications = (refetchDisabled: boolean = false) => { refetchInterval: !refetchDisabled ? 5000 : false, onSuccess: () => { queryClient.invalidateQueries([reviewsQueryKey]); - queryClient.invalidateQueries([assessmentsQueryKey]); queryClient.invalidateQueries([assessmentsByItemIdQueryKey]); }, onError: (error: AxiosError) => console.log(error), diff --git a/client/src/app/queries/archetypes.ts b/client/src/app/queries/archetypes.ts index a740d564d2..2dc818c4db 100644 --- a/client/src/app/queries/archetypes.ts +++ b/client/src/app/queries/archetypes.ts @@ -9,10 +9,7 @@ import { getArchetypes, updateArchetype, } from "@app/api/rest"; -import { - assessmentsQueryKey, - assessmentsByItemIdQueryKey, -} from "./assessments"; +import { assessmentsByItemIdQueryKey } from "./assessments"; import { reviewsQueryKey } from "./reviews"; import { useState } from "react"; @@ -43,7 +40,6 @@ export const useFetchArchetypes = (forApplication?: Application | null) => { } queryClient.invalidateQueries([reviewsQueryKey]); - queryClient.invalidateQueries([assessmentsQueryKey]); queryClient.invalidateQueries([assessmentsByItemIdQueryKey]); }, onError: (error: AxiosError) => console.log(error), From d77a79f874bb56549c857cc8a6cd845e41902137 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Mon, 4 Mar 2024 14:06:34 -0500 Subject: [PATCH 29/53] :bug: Adds spinner for isLoading prop in asessment status component (#1727) - Replaces erroneous not available status that is shown when no assessments are available on an app Signed-off-by: Ian Bolton --- .../applications-table/applications-table.tsx | 10 ++++++++-- .../application-assessment-status.tsx | 8 ++++---- 2 files changed, 12 insertions(+), 6 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 ff7c364c1b..26c9b4d4dc 100644 --- a/client/src/app/pages/applications/applications-table/applications-table.tsx +++ b/client/src/app/pages/applications/applications-table/applications-table.tsx @@ -211,8 +211,9 @@ export const ApplicationsTable: React.FC = () => { refetch: fetchApplications, } = useFetchApplications(); - const { assessments } = useFetchAssessments(); - const { archetypes } = useFetchArchetypes(); + const { assessments, isFetching: isFetchingAssesments } = + useFetchAssessments(); + const { archetypes, isFetching: isFetchingArchetypes } = useFetchArchetypes(); const onDeleteApplicationSuccess = (appIDCount: number) => { pushNotification({ @@ -894,6 +895,11 @@ export const ApplicationsTable: React.FC = () => { application={application} assessments={assessments} archetypes={archetypes} + isLoading={ + isFetchingApplications || + isFetchingArchetypes || + isFetchingAssesments + } key={`${application?.id}-assessment-status`} /> diff --git a/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx b/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx index 8f2314f032..b6fba08f30 100644 --- a/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx +++ b/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx @@ -1,8 +1,8 @@ import React from "react"; import { useTranslation } from "react-i18next"; -import { EmptyTextMessage } from "@app/components/EmptyTextMessage"; import { Application, Archetype, Assessment } from "@app/api/models"; import { IconedStatus, IconedStatusPreset } from "@app/components/IconedStatus"; +import { Spinner } from "@patternfly/react-core"; interface ApplicationAssessmentStatusProps { application: Application; assessments: Assessment[]; @@ -12,7 +12,7 @@ interface ApplicationAssessmentStatusProps { export const ApplicationAssessmentStatus: React.FC< ApplicationAssessmentStatusProps -> = ({ application, assessments, archetypes }) => { +> = ({ application, assessments, archetypes, isLoading }) => { const { t } = useTranslation(); const filteredAssessments = assessments?.filter( @@ -80,8 +80,8 @@ export const ApplicationAssessmentStatus: React.FC< }; }, [archetypes, assessments]); - if (archetypes?.length === 0 || assessments?.length === 0) { - return ; + if (isLoading) { + return ; } let statusPreset: IconedStatusPreset = "NotStarted"; // Default status From 95b6ebc0200d2b0fbf894242f5b7bb53961ff00d Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Mon, 4 Mar 2024 16:44:55 -0500 Subject: [PATCH 30/53] :sparkles: Optimize polling to only occur when a task is active (#1715) Addresses part of https://issues.redhat.com/browse/MTA-2359 Signed-off-by: Ian Bolton --- .../applications/applications-table/applications-table.tsx | 7 +++++-- client/src/app/queries/tasks.ts | 2 ++ 2 files changed, 7 insertions(+), 2 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 26c9b4d4dc..4f44be86ea 100644 --- a/client/src/app/pages/applications/applications-table/applications-table.tsx +++ b/client/src/app/pages/applications/applications-table/applications-table.tsx @@ -147,7 +147,10 @@ export const ApplicationsTable: React.FC = () => { const getTask = (application: Application) => tasks.find((task: Task) => task.application?.id === application.id); - const { tasks } = useFetchTasks({ addon: "analyzer" }, isAnalyzeModalOpen); + const { tasks, hasActiveTasks } = useFetchTasks( + { addon: "analyzer" }, + isAnalyzeModalOpen + ); const isTaskCancellable = (application: Application) => { const task = getTask(application); @@ -209,7 +212,7 @@ export const ApplicationsTable: React.FC = () => { isFetching: isFetchingApplications, error: applicationsFetchError, refetch: fetchApplications, - } = useFetchApplications(); + } = useFetchApplications(!hasActiveTasks); const { assessments, isFetching: isFetchingAssesments } = useFetchAssessments(); diff --git a/client/src/app/queries/tasks.ts b/client/src/app/queries/tasks.ts index 23d107a911..c2532f1ace 100644 --- a/client/src/app/queries/tasks.ts +++ b/client/src/app/queries/tasks.ts @@ -42,12 +42,14 @@ export const useFetchTasks = ( }, onError: (err) => console.log(err), }); + const hasActiveTasks = data && data.length > 0; return { tasks: data || [], isFetching: isLoading, fetchError: error, refetch, + hasActiveTasks, }; }; From 55fa63118ede47d0b4f668e308f3f7ab0dc65482 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Mon, 4 Mar 2024 16:45:30 -0500 Subject: [PATCH 31/53] :bug: Consider only inherited archetypes when computing status (#1733) [App 'Assessment' status shows Completed and Inheritance indicator icon even when not associated with archetypes](https://issues.redhat.com/browse/MTA-2354) Signed-off-by: Ian Bolton --- .../application-assessment-status.tsx | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx b/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx index b6fba08f30..a6a0df6ab7 100644 --- a/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx +++ b/client/src/app/pages/applications/components/application-assessment-status/application-assessment-status.tsx @@ -15,16 +15,22 @@ export const ApplicationAssessmentStatus: React.FC< > = ({ application, assessments, archetypes, isLoading }) => { const { t } = useTranslation(); - const filteredAssessments = assessments?.filter( + const applicationAssessments = assessments?.filter( (assessment: Assessment) => assessment.application?.id === application.id ); + const inheritedArchetypes = archetypes?.filter( + (archetype: Archetype) => + archetype.applications?.map((app) => app.id).includes(application.id) + ); const assessmentStatusInfo = React.useMemo(() => { - const assessmentsWithArchetypes = archetypes.map((archetype) => ({ - archetype, - assessments: assessments.filter( - (assessment) => assessment.archetype?.id === archetype.id - ), - })); + const assessmentsWithArchetypes = inheritedArchetypes.map( + (inheritedArchetype) => ({ + inheritedArchetype, + assessments: assessments.filter( + (assessment) => assessment.archetype?.id === inheritedArchetype.id + ), + }) + ); const someArchetypesAssessed = assessmentsWithArchetypes.some( ({ assessments }) => assessments.length > 0 @@ -32,12 +38,12 @@ export const ApplicationAssessmentStatus: React.FC< const allArchetypesAssessed = assessmentsWithArchetypes.length > 0 && - assessmentsWithArchetypes.every(({ archetype, assessments }) => { + assessmentsWithArchetypes.every(({ inheritedArchetype, assessments }) => { const requiredAssessments = assessments.filter( (assessment) => assessment.required ); return ( - archetype.assessed && + inheritedArchetype.assessed && assessments.length > 0 && requiredAssessments.length > 0 && requiredAssessments.every( @@ -56,18 +62,19 @@ export const ApplicationAssessmentStatus: React.FC< ); const assessedArchetypesWithARequiredAssessment = - assessmentsWithArchetypes.filter(({ assessments, archetype }) => + assessmentsWithArchetypes.filter(({ assessments, inheritedArchetype }) => assessments.some( (assessment) => assessment.required && assessment.status === "complete" && - archetype.assessed + inheritedArchetype.assessed ) ); const assessedArchetypeCount = - archetypes?.filter( - (archetype) => - archetype?.assessments?.length ?? (0 > 0 && archetype.assessed) + inheritedArchetypes?.filter( + (inheritedArchetype) => + inheritedArchetype?.assessments?.length ?? + (0 > 0 && inheritedArchetype.assessed) ).length || 0; return { @@ -78,7 +85,7 @@ export const ApplicationAssessmentStatus: React.FC< assessedArchetypesWithARequiredAssessment, assessedArchetypeCount, }; - }, [archetypes, assessments]); + }, [inheritedArchetypes, assessments]); if (isLoading) { return ; @@ -89,6 +96,7 @@ export const ApplicationAssessmentStatus: React.FC< const isDirectlyAssessed = application.assessed && (application.assessments?.length ?? 0) > 0; + const { allArchetypesAssessed, assessedArchetypesWithARequiredAssessment, @@ -104,7 +112,9 @@ export const ApplicationAssessmentStatus: React.FC< statusPreset = "InProgressInheritedAssessments"; tooltipCount = assessedArchetypesWithARequiredAssessment.length; } else if ( - filteredAssessments?.some((assessment) => assessment.status === "started") + applicationAssessments?.some( + (assessment) => assessment.status === "started" + ) ) { statusPreset = "InProgress"; } From 8870bf677969ffd298c500e86b1030d6ac45049b Mon Sep 17 00:00:00 2001 From: Scott Dickerson Date: Mon, 4 Mar 2024 21:33:54 -0500 Subject: [PATCH 32/53] :seedling: Setup branding to be configurable during the build (#1664) ## Summary Refactor and enhance branding capabilities. Now branding is included from a single directory that contains at least `strings.json`, `manifest.json`, and `favicon.ico`. Any other assets may be placed in the directory and will be copied to the bundled app. Running the build as normal should show no difference. Running the build with `BRANDING=./some-other-brand npm run start:dev` will try to use a branding from the specified directory (that is relative to the project's source root). See `BRANDING.md` for more details. Resolves: #1682 ## Details Branding changes: - Move Konveyor branding assets to a project top-level branding directory - Remove MTA branding assets - Remove profile/branding constants from `env` and client module - Embed branding strings and assets in the common module - `strings.json` is templated to allow the build to adjust asset URL path roots as necessary - `brandingAssetPath()` - server's index.html generation sources the template strings from the common module's branding strings - `HeaderApp` and `AppAboutModal` components support branding by using the `useBranding` hook - `BRANDING` as a relative path is computed from the project root - webpack build source branding assets directly from the common module - Unit tests, snapshots and jest configs updated as necessary Jest changes: - Use `react-i18next` mock from `client/__mocks__` as a more robust mock borrowed from react-i18n repos - Move `setupTests.ts` into `client/src/app/test-config` to keep jest test config code all in the same directory Related changes: - Upgrade rollup to v4, add new rollup plugins (copy, virtual) --------- Signed-off-by: Scott J Dickerson Co-authored-by: Ian Bolton --- BRANDING.md | 151 +++++++ .../favicon.ico | Bin {client/public => branding/images}/logo.png | Bin .../public => branding/images}/logo192.png | Bin .../public => branding/images}/logo512.png | Bin .../images/masthead-logo.svg | 0 {client/public => branding}/manifest.json | 4 +- branding/strings.json | 21 + client/__mocks__/react-i18next.js | 68 +++ client/config/jest.config.ts | 5 +- client/config/webpack.common.ts | 31 +- client/config/webpack.dev.ts | 14 +- client/config/webpack.prod.ts | 11 +- client/public/index.html.ejs | 12 +- client/public/locales/en/translation.json | 4 +- client/public/mta-favicon.ico | Bin 15086 -> 0 bytes client/src/app/Constants.ts | 6 - client/src/app/hooks/useBranding.ts | 12 + client/src/app/images/avatar.svg | 33 -- .../app/images/konveyor-logo-white-text.png | Bin 10564 -> 0 bytes .../src/app/images/logo-navbar-patternfly.svg | 33 -- client/src/app/images/logo-navbar.svg | 1 - client/src/app/images/logo.svg | 13 - client/src/app/images/logoRedHat.svg | 1 - client/src/app/images/tackle.png | Bin 7948 -> 0 bytes .../layout/AppAboutModal/AppAboutModal.tsx | 77 ++-- .../tests/AppAboutModal.test.tsx | 2 +- .../__snapshots__/AppAboutModal.test.tsx.snap | 9 +- client/src/app/layout/HeaderApp/HeaderApp.tsx | 41 +- client/src/app/layout/HeaderApp/header.css | 7 - .../__snapshots__/HeaderApp.test.tsx.snap | 4 +- client/src/app/logo.svg | 1 - client/src/app/setupTests.ts | 50 --- client/src/app/test-config/setupTests.ts | 18 + common/package.json | 3 +- common/rollup.config.js | 41 +- common/src/branding-strings-stub.json | 21 + common/src/branding.ts | 48 ++ common/src/environment.ts | 11 +- common/src/index.ts | 1 + common/tsconfig.json | 11 +- package-lock.json | 419 ++++++++++++++++-- package.json | 14 +- server/src/index.js | 8 +- 44 files changed, 899 insertions(+), 307 deletions(-) create mode 100644 BRANDING.md rename client/public/konveyor-favicon.ico => branding/favicon.ico (100%) rename {client/public => branding/images}/logo.png (100%) rename {client/public => branding/images}/logo192.png (100%) rename {client/public => branding/images}/logo512.png (100%) rename client/src/app/images/Konveyor-white-logo.svg => branding/images/masthead-logo.svg (100%) rename {client/public => branding}/manifest.json (81%) create mode 100644 branding/strings.json create mode 100644 client/__mocks__/react-i18next.js delete mode 100644 client/public/mta-favicon.ico create mode 100644 client/src/app/hooks/useBranding.ts delete mode 100644 client/src/app/images/avatar.svg delete mode 100644 client/src/app/images/konveyor-logo-white-text.png delete mode 100644 client/src/app/images/logo-navbar-patternfly.svg delete mode 100644 client/src/app/images/logo-navbar.svg delete mode 100644 client/src/app/images/logo.svg delete mode 100644 client/src/app/images/logoRedHat.svg delete mode 100644 client/src/app/images/tackle.png delete mode 100644 client/src/app/logo.svg delete mode 100644 client/src/app/setupTests.ts create mode 100644 client/src/app/test-config/setupTests.ts create mode 100644 common/src/branding-strings-stub.json create mode 100644 common/src/branding.ts diff --git a/BRANDING.md b/BRANDING.md new file mode 100644 index 0000000000..b2043dd9a8 --- /dev/null +++ b/BRANDING.md @@ -0,0 +1,151 @@ +# Branding + +The UI supports static branding at build time. Dynamically switching brands is not +possible with the current implementation. + +## Summary + +Each of the project modules need to do some branding enablement. + +- `@konveyor-ui/common` pulls in the branding assets and packages the configuration, + strings and assets within the common package. The other modules pull branding + from the common module. + +- `@konveyor-ui/client` uses branding from the common package: + + - The location of `favicon.ico`, `manifest.json` and any other branding + assets that may be referenced in the `brandingStrings` are sourced from the + common package. + + - The `brandingStrings` are used by the dev-server runtime, to fill out the + `index.html` template. + + - The about modal and application masthead components use the branding strings + provided by the common module to display brand appropriate logos, titles and + about information. Since the common module provides all the information, it + is packaged directly into the app at build time. + +- `@konveyor-ui/server` uses the `brandingStrings` from the common package to fill + out the `index.html` template. + +## Providing alternate branding + +To provide an alternate branding to the build, specify the path to the branding assets +with the `BRANDING` environment variable. Relative paths in `BRANDING` are computed +from the project source root. + +Each brand requires the presence of at least the following files: + +- `strings.json` +- `favicon.ico` +- `manifest.json` + +With a file path of `/alt/custom-branding`, a build that uses an alternate branding +is run as: + +```sh +> BRANDING=/alt/custom-branding npm run build +``` + +The dev server can also be run this way. Since file watching of the branding assets +is not implemented in the common module's build watch mode, it may be necessary to +manually build the common module before running the dev server. When working on a +brand, it is useful to run the dev server like this: + +```sh +> export BRANDING=/alt/custom-branding +> npm run build -w common +> npm run start:dev +> unset BRANDING # when you don't want to use the custom branding path anymore +``` + +### File details + +#### strings.json + +The expected shape of `strings.json` is defined in [branding.ts](./common/src/branding.ts). + +The default version of the file is [branding/strings.json](./branding/strings.json). + +A minimal viable example of the file is: + +```json +{ + "application": { + "title": "Konveyor" + }, + "about": { + "displayName": "Konveyor" + }, + "masthead": {} +} +``` + +At build time, the json file is processed as an [ejs](https://ejs.co/) template. The +variable `brandingRoot` is provided as the relative root of the branding +assets within the build of the common module. Consider the location of `strings.json` +in your branding directory as the base `brandingRoot` when creating a new brand. + +For example, to properly reference a logo within this branding structure: + +``` + special-brand/ + images/ + masthead-logo.svg + about-logo.svg + strings.json +``` + +Use a url string like this: + +```json +{ + "about": { + "imageSrc": "<%= brandingRoot %>/images/about-logo.svg" + } +} +``` + +and in the output of `BRANDING=special-brand npm run build -w common`, the `imageSrc` +will be `branding/images/about-logo.svg` with all of the files in `special-branding/*` +copied to and available to the client and server modules from +`@konveyor-ui/common/branding/*`. + +#### favicon.ico + +A standard favorite icon file `favicon.ico` is required to be in the same directory +as `strings.json` + +#### manifest.json + +A standard [web app manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) +file `manifest.json` is required to be in the same directory as `strings.json`. + +## Technical details + +All branding strings and assets are pulled in to the common module. The client and +server modules access the branding from the common module build. + +The `common` module relies on rollup packaging to embed all of the brand for easy +use. The use of branding strings in `client` and `server` modules is straight forward. +Pulling in `strings.json` and providing the base path to the brand assets is a +more complicated. + +The `common` module provides the `brandingAssetPath()` function to let the build time +code find the root path to all brand assets. Webpack configuration files use this +function to source the favicon.ico, manifest.json and other brand assets to be copied +to the application bundle. + +The `brandingStrings` is typed and sourced from a json file. To pass typescript builds, +a stub json file needs to be available at transpile time. By using a typescript paths +of `@branding/strings.json`, the stub json is found at transpile time. The generated +javascript will still import the path alias. The +[virtual rollup plugin](https://github.com/rollup/plugins/tree/master/packages/virtual) +further transform the javascript output by replacing the `@branding/strings.json` import +with a dynamically built module containing the contents of the brand's `strings.json`. +The brand json becomes a virtual module embedded in the common module. + +A build for a custom brand will fail (1) if the expected files cannot be read, or (2) +if `strings.json` is not a valid JSON file. **Note:** The context of `stings.json` is +not currently validated. If something is missing or a url is malformed, it will only +be visible as a runtime error. diff --git a/client/public/konveyor-favicon.ico b/branding/favicon.ico similarity index 100% rename from client/public/konveyor-favicon.ico rename to branding/favicon.ico diff --git a/client/public/logo.png b/branding/images/logo.png similarity index 100% rename from client/public/logo.png rename to branding/images/logo.png diff --git a/client/public/logo192.png b/branding/images/logo192.png similarity index 100% rename from client/public/logo192.png rename to branding/images/logo192.png diff --git a/client/public/logo512.png b/branding/images/logo512.png similarity index 100% rename from client/public/logo512.png rename to branding/images/logo512.png diff --git a/client/src/app/images/Konveyor-white-logo.svg b/branding/images/masthead-logo.svg similarity index 100% rename from client/src/app/images/Konveyor-white-logo.svg rename to branding/images/masthead-logo.svg diff --git a/client/public/manifest.json b/branding/manifest.json similarity index 81% rename from client/public/manifest.json rename to branding/manifest.json index 2a98b57f08..eb8ffec956 100644 --- a/client/public/manifest.json +++ b/branding/manifest.json @@ -1,6 +1,6 @@ { - "short_name": "tackle-ui", - "name": "Tackle UI", + "short_name": "konveyor-ui", + "name": "Konveyor UI", "icons": [ { "src": "favicon.ico", diff --git a/branding/strings.json b/branding/strings.json new file mode 100644 index 0000000000..116aa41ce5 --- /dev/null +++ b/branding/strings.json @@ -0,0 +1,21 @@ +{ + "application": { + "title": "Konveyor", + "name": "Konveyor Tackle UI", + "description": "Konveyor/Tackle UI" + }, + "about": { + "displayName": "Konveyor", + "imageSrc": "<%= brandingRoot %>/images/masthead-logo.svg", + "documentationUrl": "https://konveyor.github.io/konveyor/" + }, + "masthead": { + "leftBrand": { + "src": "<%= brandingRoot %>/images/masthead-logo.svg", + "alt": "brand", + "height": "60px" + }, + "leftTitle": null, + "rightBrand": null + } +} diff --git a/client/__mocks__/react-i18next.js b/client/__mocks__/react-i18next.js new file mode 100644 index 0000000000..60f67f05ea --- /dev/null +++ b/client/__mocks__/react-i18next.js @@ -0,0 +1,68 @@ +/* eslint-env node */ + +// Adapted from https://github.com/i18next/react-i18next/blob/master/example/test-jest/src/__mocks__/react-i18next.js +import React from "react"; +import * as reactI18next from "react-i18next"; + +const hasChildren = (node) => + node && (node.children || (node.props && node.props.children)); + +const getChildren = (node) => + node && node.children ? node.children : node.props && node.props.children; + +const renderNodes = (reactNodes) => { + if (typeof reactNodes === "string") { + return reactNodes; + } + + return Object.keys(reactNodes).map((key, i) => { + const child = reactNodes[key]; + const isElement = React.isValidElement(child); + + if (typeof child === "string") { + return child; + } + if (hasChildren(child)) { + const inner = renderNodes(getChildren(child)); + return React.cloneElement(child, { ...child.props, key: i }, inner); + } + if (typeof child === "object" && !isElement) { + return Object.keys(child).reduce( + (str, childKey) => `${str}${child[childKey]}`, + "" + ); + } + + return child; + }); +}; + +const useMock = [(k) => k, { changeLanguage: () => new Promise(() => {}) }]; +useMock.t = (k) => k; +useMock.i18n = { changeLanguage: () => new Promise(() => {}) }; + +module.exports = { + Trans: ({ children, i18nKey }) => + !children + ? i18nKey + : Array.isArray(children) + ? renderNodes(children) + : renderNodes([children]), + + Translation: ({ children }) => children((k) => k, { i18n: {} }), + + useTranslation: () => useMock, + + initReactI18next: { + type: "3rdParty", + init: () => {}, + }, + + // mock if needed + withTranslation: reactI18next.withTranslation, + I18nextProvider: reactI18next.I18nextProvider, + setDefaults: reactI18next.setDefaults, + getDefaults: reactI18next.getDefaults, + setI18n: reactI18next.setI18n, + getI18n: reactI18next.getI18n, +}; diff --git a/client/config/jest.config.ts b/client/config/jest.config.ts index 202a284ba7..6d683a6023 100644 --- a/client/config/jest.config.ts +++ b/client/config/jest.config.ts @@ -23,6 +23,9 @@ const config: JestConfigWithTsJest = { "@patternfly/react-icons/dist/esm/icons/": "/__mocks__/fileMock.js", + // other mocks + "react-i18next": "/__mocks__/react-i18next.js", + // match the paths in tsconfig.json "@app/(.*)": "/src/app/$1", "@assets/(.*)": @@ -44,7 +47,7 @@ const config: JestConfigWithTsJest = { }, // Code to set up the testing framework before each test file in the suite is executed - setupFilesAfterEnv: ["/src/app/setupTests.ts"], + setupFilesAfterEnv: ["/src/app/test-config/setupTests.ts"], }; export default config; diff --git a/client/config/webpack.common.ts b/client/config/webpack.common.ts index ffaa95c5ca..637b943652 100644 --- a/client/config/webpack.common.ts +++ b/client/config/webpack.common.ts @@ -1,15 +1,18 @@ import path from "path"; import { Configuration } from "webpack"; -// import CaseSensitivePathsWebpackPlugin from "case-sensitive-paths-webpack-plugin"; import CopyPlugin from "copy-webpack-plugin"; import Dotenv from "dotenv-webpack"; import { TsconfigPathsPlugin } from "tsconfig-paths-webpack-plugin"; import MonacoWebpackPlugin from "monaco-editor-webpack-plugin"; +import { brandingAssetPath } from "@konveyor-ui/common"; import { LANGUAGES_BY_FILE_EXTENSION } from "./monacoConstants"; -const BG_IMAGES_DIRNAME = "images"; const pathTo = (relativePath: string) => path.resolve(__dirname, relativePath); +const brandingPath = brandingAssetPath(); +const manifestPath = path.resolve(brandingPath, "manifest.json"); + +const BG_IMAGES_DIRNAME = "images"; const config: Configuration = { entry: { @@ -150,22 +153,26 @@ const config: Configuration = { exports: "xmllint", }, }, - // For monaco-editor-webpack-plugin + { + test: /\.yaml$/, + use: "raw-loader", + }, + + // For monaco-editor-webpack-plugin ---> { test: /\.css$/, include: [pathTo("../../node_modules/monaco-editor")], use: ["style-loader", "css-loader"], }, - // For monaco-editor-webpack-plugin { test: /\.ttf$/, type: "asset/resource", }, + // <--- For monaco-editor-webpack-plugin ], }, plugins: [ - // new CaseSensitivePathsWebpackPlugin(), new Dotenv({ systemvars: true, silent: true, @@ -174,15 +181,19 @@ const config: Configuration = { patterns: [ { from: pathTo("../public/locales"), - to: pathTo("../dist/locales"), + to: "./locales/", }, { - from: pathTo("../public/manifest.json"), - to: pathTo("../dist/manifest.json"), + from: pathTo("../public/templates"), + to: "./templates/", }, { - from: pathTo("../public/templates"), - to: pathTo("../dist/templates"), + from: manifestPath, + to: ".", + }, + { + from: brandingPath, + to: "./branding/", }, ], }), diff --git a/client/config/webpack.dev.ts b/client/config/webpack.dev.ts index d935f8d63a..9c0c367e34 100644 --- a/client/config/webpack.dev.ts +++ b/client/config/webpack.dev.ts @@ -2,7 +2,6 @@ import path from "path"; import { mergeWithRules } from "webpack-merge"; import type { Configuration as WebpackConfiguration } from "webpack"; import type { Configuration as DevServerConfiguration } from "webpack-dev-server"; - import CopyPlugin from "copy-webpack-plugin"; import HtmlWebpackPlugin from "html-webpack-plugin"; import ReactRefreshTypeScript from "react-refresh-typescript"; @@ -14,12 +13,14 @@ import { KONVEYOR_ENV, SERVER_ENV_KEYS, proxyMap, + brandingStrings, + brandingAssetPath, } from "@konveyor-ui/common"; import { stylePaths } from "./stylePaths"; import commonWebpackConfiguration from "./webpack.common"; -const brandType = KONVEYOR_ENV.PROFILE; const pathTo = (relativePath: string) => path.resolve(__dirname, relativePath); +const faviconPath = path.resolve(brandingAssetPath(), "favicon.ico"); interface Configuration extends WebpackConfiguration { devServer?: DevServerConfiguration; @@ -75,10 +76,6 @@ const config: Configuration = mergeWithRules({ include: [...stylePaths], use: ["style-loader", "css-loader"], }, - { - test: /\.yaml$/, - use: "raw-loader", - }, ], }, @@ -96,15 +93,16 @@ const config: Configuration = mergeWithRules({ }, ], }), + // index.html generated at compile time to inject `_env` new HtmlWebpackPlugin({ filename: "index.html", template: pathTo("../public/index.html.ejs"), templateParameters: { _env: encodeEnv(KONVEYOR_ENV, SERVER_ENV_KEYS), - brandType, + branding: brandingStrings, }, - favicon: pathTo(`../public/${brandType}-favicon.ico`), + favicon: faviconPath, minify: { collapseWhitespace: false, keepClosingSlash: true, diff --git a/client/config/webpack.prod.ts b/client/config/webpack.prod.ts index 5b1f667e36..db3978e741 100644 --- a/client/config/webpack.prod.ts +++ b/client/config/webpack.prod.ts @@ -5,12 +5,12 @@ import MiniCssExtractPlugin from "mini-css-extract-plugin"; import CssMinimizerPlugin from "css-minimizer-webpack-plugin"; import HtmlWebpackPlugin from "html-webpack-plugin"; -import { KONVEYOR_ENV } from "@konveyor-ui/common"; +import { brandingAssetPath } from "@konveyor-ui/common"; import { stylePaths } from "./stylePaths"; import commonWebpackConfiguration from "./webpack.common"; -const brandType = KONVEYOR_ENV.PROFILE; const pathTo = (relativePath: string) => path.resolve(__dirname, relativePath); +const faviconPath = path.resolve(brandingAssetPath(), "favicon.ico"); const config = merge(commonWebpackConfiguration, { mode: "production", @@ -36,10 +36,6 @@ const config = merge(commonWebpackConfiguration, { include: [...stylePaths], use: [MiniCssExtractPlugin.loader, "css-loader"], }, - { - test: /\.yaml$/, - use: "raw-loader", - }, ], }, @@ -56,11 +52,12 @@ const config = merge(commonWebpackConfiguration, { new webpack.EnvironmentPlugin({ NODE_ENV: "production", }), + // index.html generated at runtime via the express server to inject `_env` new HtmlWebpackPlugin({ filename: "index.html.ejs", template: `!!raw-loader!${pathTo("../public/index.html.ejs")}`, - favicon: pathTo(`../public/${brandType}-favicon.ico`), + favicon: faviconPath, minify: { collapseWhitespace: false, keepClosingSlash: true, diff --git a/client/public/index.html.ejs b/client/public/index.html.ejs index 632b99ed8f..0db08e3428 100644 --- a/client/public/index.html.ejs +++ b/client/public/index.html.ejs @@ -1,15 +1,9 @@ - <% if (brandType == 'mta') { %> - Migration Toolkit for Applications - - - <% } else { %> - Konveyor - - - <% } %> + <%= branding.application.title %> + + diff --git a/client/public/locales/en/translation.json b/client/public/locales/en/translation.json index 29f0802aaf..161c2e055f 100644 --- a/client/public/locales/en/translation.json +++ b/client/public/locales/en/translation.json @@ -1,8 +1,8 @@ { "about": { "about": "About", - "bottom1": "{{brandType}} is a project within the", - "bottom2": "For more information, refer to", + "bottom1": "{{brandType}} is a project within the <2>Konveyor community.", + "bottom2": "For more information, refer to <1>{{brandType}} documentation.", "description": "{{brandType}} allows users to maintain their portfolio of applications with a full set of metadata and to assess their suitability for modernization leveraging a questionnaire based approach.", "iconLibrary": "The Icon Library used in this project is a derivative of the <2>Standard Icons library by <5>Red Hat, used under <8>CC BY 4.0", "introduction": "{{brandType}} is a collection of tools that supports large-scale application modernization and migration projects to Kubernetes." diff --git a/client/public/mta-favicon.ico b/client/public/mta-favicon.ico deleted file mode 100644 index 7fe9dd26e2733706420ebc55427ed228abd30980..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 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 diff --git a/client/src/app/Constants.ts b/client/src/app/Constants.ts index 81954b6c0f..2633f1e29f 100644 --- a/client/src/app/Constants.ts +++ b/client/src/app/Constants.ts @@ -12,14 +12,8 @@ import { import { EffortEstimate, ProposedAction, Risk } from "@app/api/models"; import { ENV } from "./env"; -export enum BrandType { - Konveyor = "konveyor", - MTA = "mta", -} - export const isAuthRequired = ENV.AUTH_REQUIRED !== "false"; export const uploadLimit = ENV.UI_INGRESS_PROXY_BODY_SIZE || "500m"; -export const APP_BRAND = ENV.PROFILE as BrandType; export const isRWXSupported = ENV.RWX_SUPPORTED === "true"; export const DEFAULT_SELECT_MAX_HEIGHT = 200; diff --git a/client/src/app/hooks/useBranding.ts b/client/src/app/hooks/useBranding.ts new file mode 100644 index 0000000000..cb90e35112 --- /dev/null +++ b/client/src/app/hooks/useBranding.ts @@ -0,0 +1,12 @@ +import { BrandingStrings, brandingStrings } from "@konveyor-ui/common"; + +/** + * Wrap the branding strings in a hook so components access it in a standard + * React way instead of a direct import. This allows the branding implementation + * to change in future with a minimal amount of refactoring in existing components. + */ +export const useBranding = (): BrandingStrings => { + return brandingStrings; +}; + +export default useBranding; diff --git a/client/src/app/images/avatar.svg b/client/src/app/images/avatar.svg deleted file mode 100644 index 11c80b85ff..0000000000 --- a/client/src/app/images/avatar.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/client/src/app/images/konveyor-logo-white-text.png b/client/src/app/images/konveyor-logo-white-text.png deleted file mode 100644 index 7fb562747c9183b90c6b08acac7406d2127d5d13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10564 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 Ay#N3J diff --git a/client/src/app/images/logo-navbar-patternfly.svg b/client/src/app/images/logo-navbar-patternfly.svg deleted file mode 100644 index 232a493d1c..0000000000 --- a/client/src/app/images/logo-navbar-patternfly.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - PatternFly Logo - Created with Sketch. - - - - - - - - - - - - \ No newline at end of file diff --git a/client/src/app/images/logo-navbar.svg b/client/src/app/images/logo-navbar.svg deleted file mode 100644 index 61bf32f4ff..0000000000 --- a/client/src/app/images/logo-navbar.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/client/src/app/images/logo.svg b/client/src/app/images/logo.svg deleted file mode 100644 index 099049afb0..0000000000 --- a/client/src/app/images/logo.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - diff --git a/client/src/app/images/logoRedHat.svg b/client/src/app/images/logoRedHat.svg deleted file mode 100644 index 679f697999..0000000000 --- a/client/src/app/images/logoRedHat.svg +++ /dev/null @@ -1 +0,0 @@ -RedHat-Logo-A-Reverse \ No newline at end of file diff --git a/client/src/app/images/tackle.png b/client/src/app/images/tackle.png deleted file mode 100644 index 6e61e7a5a1f3af54d1227e4ebc6e01d146fe9b52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7948 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 diff --git a/client/src/app/layout/AppAboutModal/AppAboutModal.tsx b/client/src/app/layout/AppAboutModal/AppAboutModal.tsx index d1ff977436..9e466a16e0 100644 --- a/client/src/app/layout/AppAboutModal/AppAboutModal.tsx +++ b/client/src/app/layout/AppAboutModal/AppAboutModal.tsx @@ -9,71 +9,74 @@ import { TextList, TextListItem, } from "@patternfly/react-core"; - -import konveyorBrandImage from "@app/images/Konveyor-white-logo.svg"; -import mtaBrandImage from "@app/images/logoRedHat.svg"; -import { APP_BRAND, BrandType } from "@app/Constants"; import { ENV } from "@app/env"; +import useBranding from "@app/hooks/useBranding"; export interface AppAboutModalProps { isOpen: boolean; onClose: () => void; } +const TRANSPARENT_1x1_GIF = + "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw== "; + export const AppAboutModal: React.FC = ({ isOpen, onClose, }) => { const { t } = useTranslation(); - const brandName = - APP_BRAND === BrandType.Konveyor - ? "Konveyor" - : "Migration Toolkit for Applications"; + const { about } = useBranding(); + return ( {t("about.about")} + - {t("about.introduction", { brandType: brandName })} + {t("about.introduction", { brandType: about.displayName })} + - {t("about.description", { brandType: brandName })} + {t("about.description", { brandType: about.displayName })} + - {t("about.bottom1", { brandType: brandName })}{" "} - - Konveyor community - - . + + {{ brandType: about.displayName }} is a project within the + + Konveyor community + + . + - - {t("about.bottom2")}{" "} - - {brandName} documentation + + {about.documentationUrl ? ( + + + For more information, refer to + + {{ brandType: about.displayName }} documentation + + . + - . - + ) : null} + The Icon Library used in this project is a derivative of the{" "} diff --git a/client/src/app/layout/AppAboutModal/tests/AppAboutModal.test.tsx b/client/src/app/layout/AppAboutModal/tests/AppAboutModal.test.tsx index db7d749b3e..6b173e1205 100644 --- a/client/src/app/layout/AppAboutModal/tests/AppAboutModal.test.tsx +++ b/client/src/app/layout/AppAboutModal/tests/AppAboutModal.test.tsx @@ -1,4 +1,4 @@ -import { render } from "@testing-library/react"; +import { render } from "@app/test-config/test-utils"; import React from "react"; import { AppAboutModal } from "../AppAboutModal"; diff --git a/client/src/app/layout/AppAboutModal/tests/__snapshots__/AppAboutModal.test.tsx.snap b/client/src/app/layout/AppAboutModal/tests/__snapshots__/AppAboutModal.test.tsx.snap index d876d1c24f..d78b2a383f 100644 --- a/client/src/app/layout/AppAboutModal/tests/__snapshots__/AppAboutModal.test.tsx.snap +++ b/client/src/app/layout/AppAboutModal/tests/__snapshots__/AppAboutModal.test.tsx.snap @@ -36,7 +36,7 @@ exports[`AppAboutModal 1`] = ` Logo
- about.bottom1 - + Konveyor + is a project within the - about.bottom2 - + For more information, refer to { + const { + masthead: { leftBrand, leftTitle, rightBrand }, + } = useBranding(); + const toolbar = ( @@ -69,16 +72,21 @@ export const HeaderApp: React.FC = () => { - {APP_BRAND === BrandType.MTA && ( + {rightBrand ? ( - Logo + - )} + ) : null} ); + return ( @@ -88,17 +96,22 @@ export const HeaderApp: React.FC = () => { - {APP_BRAND === BrandType.Konveyor ? ( + {leftBrand ? ( - ) : ( - - Migration Toolkit for Applications + ) : null} + {leftTitle ? ( + <Title + className="logo-pointer" + headingLevel={leftTitle?.heading ?? "h1"} + size={leftTitle?.size ?? "2xl"} + > + {leftTitle.text} - )} + ) : null} {toolbar} diff --git a/client/src/app/layout/HeaderApp/header.css b/client/src/app/layout/HeaderApp/header.css index 1585cdb0c4..4bda787c48 100644 --- a/client/src/app/layout/HeaderApp/header.css +++ b/client/src/app/layout/HeaderApp/header.css @@ -1,10 +1,3 @@ .logo-pointer { cursor: default !important; } -.pf-v5-c-page__header-brand-link { - all: unset !important; -} -.redhat-logo-style { - height: 30px; - vertical-align: middle; -} diff --git a/client/src/app/layout/HeaderApp/tests/__snapshots__/HeaderApp.test.tsx.snap b/client/src/app/layout/HeaderApp/tests/__snapshots__/HeaderApp.test.tsx.snap index 880956053b..8517bcbd8c 100644 --- a/client/src/app/layout/HeaderApp/tests/__snapshots__/HeaderApp.test.tsx.snap +++ b/client/src/app/layout/HeaderApp/tests/__snapshots__/HeaderApp.test.tsx.snap @@ -46,7 +46,7 @@ exports[`Test snapshot 1`] = ` brand @@ -170,7 +170,7 @@ exports[`Test snapshot 1`] = ` brand diff --git a/client/src/app/logo.svg b/client/src/app/logo.svg deleted file mode 100644 index 9dfc1c058c..0000000000 --- a/client/src/app/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/client/src/app/setupTests.ts b/client/src/app/setupTests.ts deleted file mode 100644 index 99dfb8bca1..0000000000 --- a/client/src/app/setupTests.ts +++ /dev/null @@ -1,50 +0,0 @@ -import "@testing-library/jest-dom"; - -let mockInitialized = false; - -jest.mock("@react-keycloak/web", () => { - const originalModule = jest.requireActual("@react-keycloak/web"); - return { - ...originalModule, - useKeycloak: () => [mockInitialized], - }; -}); - -jest.mock("react-i18next", () => ({ - Trans: ({ children }: { children: any }) => { - return children; - }, - useTranslation: () => { - return { - t: (str: any) => str, - i18n: { - changeLanguage: () => new Promise(() => {}), - }, - }; - }, -})); - -jest.mock("react-router-dom", () => ({ - ...jest.requireActual("react-router-dom"), - useLocation: () => ({ - pathname: "localhost:3000/example/path", - }), -})); - -jest.mock("react-i18next", () => ({ - Trans: ({ children }: { children: any }) => { - return children; - }, - useTranslation: () => { - return { - t: (str: any) => str, - i18n: { - changeLanguage: () => new Promise(() => {}), - }, - }; - }, - initReactI18next: { - type: "3rdParty", - init: jest.fn(), - }, -})); diff --git a/client/src/app/test-config/setupTests.ts b/client/src/app/test-config/setupTests.ts new file mode 100644 index 0000000000..0618b987c9 --- /dev/null +++ b/client/src/app/test-config/setupTests.ts @@ -0,0 +1,18 @@ +import "@testing-library/jest-dom"; + +const mockInitialized = false; + +jest.mock("@react-keycloak/web", () => { + const originalModule = jest.requireActual("@react-keycloak/web"); + return { + ...originalModule, + useKeycloak: () => [mockInitialized], + }; +}); + +jest.mock("react-router-dom", () => ({ + ...jest.requireActual("react-router-dom"), + useLocation: () => ({ + pathname: "localhost:3000/example/path", + }), +})); diff --git a/common/package.json b/common/package.json index fd763c7684..7292b10912 100644 --- a/common/package.json +++ b/common/package.json @@ -10,7 +10,8 @@ "types": "./dist/index.d.ts", "import": "./dist/index.mjs", "require": "./dist/index.cjs" - } + }, + "./package.json": "./package.json" }, "types": "./dist", "main": "./dist/index.cjs", diff --git a/common/rollup.config.js b/common/rollup.config.js index 8ca573c280..d6fbad60b2 100644 --- a/common/rollup.config.js +++ b/common/rollup.config.js @@ -1,5 +1,35 @@ +/* eslint-env node */ + +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { readFileSync } from "node:fs"; +import util from "node:util"; + +import copy from "rollup-plugin-copy"; import nodeResolve from "@rollup/plugin-node-resolve"; import typescript from "@rollup/plugin-typescript"; +import virtual from "@rollup/plugin-virtual"; +import ejs from "ejs"; + +const __dirname = fileURLToPath(new URL(".", import.meta.url)); +const pathTo = (...relativePath) => path.resolve(__dirname, ...relativePath); + +const baseBrandingPath = process.env.BRANDING ?? "./branding"; +const brandingPath = pathTo("../", baseBrandingPath); +const jsonStrings = JSON.parse( + readFileSync(path.resolve(brandingPath, "./strings.json"), "utf8") +); +const stringModule = ejs.render( + ` + export const strings = ${util.inspect(jsonStrings)}; + export default strings; +`, + { + brandingRoot: "branding", + } +); + +console.log("Using branding assets from:", brandingPath); const config = { input: "src/index.ts", @@ -21,7 +51,16 @@ const config = { clearScreen: false, }, - plugins: [nodeResolve(), typescript()], + plugins: [ + copy({ + targets: [{ src: `${brandingPath}/**/*`, dest: "dist/branding" }], + }), + nodeResolve(), + typescript(), + virtual({ + "@branding/strings.json": stringModule, + }), + ], }; export default config; diff --git a/common/src/branding-strings-stub.json b/common/src/branding-strings-stub.json new file mode 100644 index 0000000000..8477bd9037 --- /dev/null +++ b/common/src/branding-strings-stub.json @@ -0,0 +1,21 @@ +{ + "application": { + "title": "Stub to allow package build to work", + "name": "", + "description": "" + }, + "about": { + "displayName": "", + "image": "", + "documentationUrl": "" + }, + "masthead": { + "leftBrand": { + "src": "", + "alt": "", + "height": "" + }, + "leftTitle": null, + "rightBrand": null + } +} diff --git a/common/src/branding.ts b/common/src/branding.ts new file mode 100644 index 0000000000..059051f76b --- /dev/null +++ b/common/src/branding.ts @@ -0,0 +1,48 @@ +export interface MastheadBrand { + src: string; + alt: string; + height: string; +} + +export interface MastheadTitle { + text: string; + heading?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6"; + size?: "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl"; +} + +export interface BrandingStrings { + application: { + title: string; + name?: string; + description?: string; + }; + + about: { + displayName: string; + imageSrc?: string; + documentationUrl?: string; + }; + + masthead: { + leftBrand?: MastheadBrand; + leftTitle?: MastheadTitle; + rightBrand?: MastheadBrand; + }; +} + +// Note: Typescript will look at the `paths` definition to resolve this import +// to a stub JSON file. In the next rollup build step, that import will +// be replaced by the rollup virtual plugin with a dynamically generated +// JSON import with the actual branding information. +import * as stringsJson from "@branding/strings.json"; + +export const brandingStrings = + stringsJson.default as unknown as BrandingStrings; + +/** + * Return the `node_modules/` resolved path for the branding assets. + */ +export const brandingAssetPath = () => + require + .resolve("@konveyor-ui/common/package.json") + .replace(/(.)\/package.json$/, "$1") + "/dist/branding"; diff --git a/common/src/environment.ts b/common/src/environment.ts index 06309a33ba..060f2b3e94 100644 --- a/common/src/environment.ts +++ b/common/src/environment.ts @@ -25,9 +25,6 @@ export type KonveyorEnvType = { /** SSO / Keycloak client id */ KEYCLOAK_CLIENT_ID: string; - /** Branding to apply to the UI */ - PROFILE: "konveyor" | "mta"; - /** UI upload file size limit in megabytes (MB), suffixed with "m" */ UI_INGRESS_PROXY_BODY_SIZE: string; @@ -42,6 +39,9 @@ export type KonveyorEnvType = { /** Target URL for the UI server's `/hub` proxy */ TACKLE_HUB_URL?: string; + + /** Location of branding files (relative paths computed from the project source root) */ + BRANDING?: string; }; /** @@ -52,6 +52,7 @@ export const SERVER_ENV_KEYS = [ "PORT", "KEYCLOAK_SERVER_URL", "TACKLE_HUB_URL", + "BRANDING", ]; /** @@ -68,10 +69,10 @@ export const buildKonveyorEnv = ({ KEYCLOAK_REALM = "tackle", KEYCLOAK_CLIENT_ID = "tackle-ui", - PROFILE = "konveyor", UI_INGRESS_PROXY_BODY_SIZE = "500m", RWX_SUPPORTED = "true", TACKLE_HUB_URL, + BRANDING, }: Partial = {}): KonveyorEnvType => ({ NODE_ENV, PORT, @@ -83,10 +84,10 @@ export const buildKonveyorEnv = ({ KEYCLOAK_REALM, KEYCLOAK_CLIENT_ID, - PROFILE, UI_INGRESS_PROXY_BODY_SIZE, RWX_SUPPORTED, TACKLE_HUB_URL, + BRANDING, }); /** diff --git a/common/src/index.ts b/common/src/index.ts index 12f839c15f..fd048162a6 100644 --- a/common/src/index.ts +++ b/common/src/index.ts @@ -1,5 +1,6 @@ export * from "./environment.js"; export * from "./proxies.js"; +export * from "./branding.js"; /** * Return a base64 encoded JSON string containing the given `env` object. diff --git a/common/tsconfig.json b/common/tsconfig.json index e6785502ec..c65dfdab80 100644 --- a/common/tsconfig.json +++ b/common/tsconfig.json @@ -6,13 +6,18 @@ "compilerOptions": { "strict": true, "target": "es2020", - "module": "Node16", - "moduleResolution": "Node16", + "module": "node16", + "moduleResolution": "node16", "outDir": "./dist", "declaration": true, "declarationMap": true, "sourceMap": true, - "inlineSources": true + "inlineSources": true, + "resolveJsonModule": true, + + "paths": { + "@branding/strings.json": ["./src/branding-strings-stub.json"] + } } } diff --git a/package-lock.json b/package-lock.json index 6ed9531d8d..e6b4957ec2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,11 +15,12 @@ "client" ], "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.3", - "@rollup/plugin-json": "^6.0.0", - "@rollup/plugin-node-resolve": "^15.1.0", - "@rollup/plugin-run": "^3.0.1", - "@rollup/plugin-typescript": "^11.1.2", + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-run": "^3.0.2", + "@rollup/plugin-typescript": "^11.1.6", + "@rollup/plugin-virtual": "^3.0.2", "@tanstack/eslint-plugin-query": "^4.34.1", "@types/jest": "^29.5.4", "@types/node": "^18.14.2", @@ -41,7 +42,8 @@ "lint-staged": "^14.0.1", "prettier": "^3.0.2", "rimraf": "^4.4.1", - "rollup": "^3.27.2", + "rollup": "^4.9.5", + "rollup-plugin-copy": "^3.5.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", "type-fest": "^3.13.0", @@ -1905,9 +1907,9 @@ } }, "node_modules/@rollup/plugin-commonjs": { - "version": "25.0.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.4.tgz", - "integrity": "sha512-L92Vz9WUZXDnlQQl3EwbypJR4+DM2EbsO+/KOcEkP4Mc6Ct453EeDB2uH9lgRwj4w5yflgNpq9pHOiY8aoUXBQ==", + "version": "25.0.7", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz", + "integrity": "sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==", "dev": true, "dependencies": { "@rollup/pluginutils": "^5.0.1", @@ -1915,13 +1917,13 @@ "estree-walker": "^2.0.2", "glob": "^8.0.3", "is-reference": "1.2.1", - "magic-string": "^0.27.0" + "magic-string": "^0.30.3" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^2.68.0||^3.0.0" + "rollup": "^2.68.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -1930,18 +1932,18 @@ } }, "node_modules/@rollup/plugin-json": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.0.0.tgz", - "integrity": "sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", "dev": true, "dependencies": { - "@rollup/pluginutils": "^5.0.1" + "@rollup/pluginutils": "^5.1.0" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -1950,9 +1952,9 @@ } }, "node_modules/@rollup/plugin-node-resolve": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.1.tgz", - "integrity": "sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz", + "integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==", "dev": true, "dependencies": { "@rollup/pluginutils": "^5.0.1", @@ -1966,7 +1968,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^2.78.0||^3.0.0" + "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -1975,9 +1977,9 @@ } }, "node_modules/@rollup/plugin-run": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-run/-/plugin-run-3.0.1.tgz", - "integrity": "sha512-wbYR1Ahz8ohYnlyXzpBTwhGWfs+OO/uZMjgpDGr8AgnL/XfoTbO7BuNYY8ncR/j/1dhCJo+NDuTRkIeCxE434Q==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-run/-/plugin-run-3.0.2.tgz", + "integrity": "sha512-pgQcDA34u6C+8Yr0FSd2T7iN2UTQe8zJ+1pbceNJ9MkvGrN0sz4D6Mzg3eYkGrbV4zC7H5QvwlzC1GqH4PrSrg==", "dev": true, "dependencies": { "@types/node": "14.18.30" @@ -1986,7 +1988,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^2.0.0||^3.0.0" + "rollup": "^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -2001,19 +2003,19 @@ "dev": true }, "node_modules/@rollup/plugin-typescript": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.3.tgz", - "integrity": "sha512-8o6cNgN44kQBcpsUJTbTXMTtb87oR1O0zgP3Dxm71hrNgparap3VujgofEilTYJo+ivf2ke6uy3/E5QEaiRlDA==", + "version": "11.1.6", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.6.tgz", + "integrity": "sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==", "dev": true, "dependencies": { - "@rollup/pluginutils": "^5.0.1", + "@rollup/pluginutils": "^5.1.0", "resolve": "^1.22.1" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^2.14.0||^3.0.0", + "rollup": "^2.14.0||^3.0.0||^4.0.0", "tslib": "*", "typescript": ">=3.7.0" }, @@ -2026,10 +2028,27 @@ } } }, + "node_modules/@rollup/plugin-virtual": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz", + "integrity": "sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/pluginutils": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.4.tgz", - "integrity": "sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", "dev": true, "dependencies": { "@types/estree": "^1.0.0", @@ -2040,7 +2059,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -2048,6 +2067,175 @@ } } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.5.tgz", + "integrity": "sha512-idWaG8xeSRCfRq9KpRysDHJ/rEHBEXcHuJ82XY0yYFIWnLMjZv9vF/7DOq8djQ2n3Lk6+3qfSH8AqlmHlmi1MA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.5.tgz", + "integrity": "sha512-f14d7uhAMtsCGjAYwZGv6TwuS3IFaM4ZnGMUn3aCBgkcHAYErhV1Ad97WzBvS2o0aaDv4mVz+syiN0ElMyfBPg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.5.tgz", + "integrity": "sha512-ndoXeLx455FffL68OIUrVr89Xu1WLzAG4n65R8roDlCoYiQcGGg6MALvs2Ap9zs7AHg8mpHtMpwC8jBBjZrT/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.5.tgz", + "integrity": "sha512-UmElV1OY2m/1KEEqTlIjieKfVwRg0Zwg4PLgNf0s3glAHXBN99KLpw5A5lrSYCa1Kp63czTpVll2MAqbZYIHoA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.5.tgz", + "integrity": "sha512-Q0LcU61v92tQB6ae+udZvOyZ0wfpGojtAKrrpAaIqmJ7+psq4cMIhT/9lfV6UQIpeItnq/2QDROhNLo00lOD1g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.5.tgz", + "integrity": "sha512-dkRscpM+RrR2Ee3eOQmRWFjmV/payHEOrjyq1VZegRUa5OrZJ2MAxBNs05bZuY0YCtpqETDy1Ix4i/hRqX98cA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.5.tgz", + "integrity": "sha512-QaKFVOzzST2xzY4MAmiDmURagWLFh+zZtttuEnuNn19AiZ0T3fhPyjPPGwLNdiDT82ZE91hnfJsUiDwF9DClIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.5.tgz", + "integrity": "sha512-HeGqmRJuyVg6/X6MpE2ur7GbymBPS8Np0S/vQFHDmocfORT+Zt76qu+69NUoxXzGqVP1pzaY6QIi0FJWLC3OPA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.5.tgz", + "integrity": "sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.5.tgz", + "integrity": "sha512-ezyFUOwldYpj7AbkwyW9AJ203peub81CaAIVvckdkyH8EvhEIoKzaMFJj0G4qYJ5sw3BpqhFrsCc30t54HV8vg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.5.tgz", + "integrity": "sha512-aHSsMnUw+0UETB0Hlv7B/ZHOGY5bQdwMKJSzGfDfvyhnpmVxLMGnQPGNE9wgqkLUs3+gbG1Qx02S2LLfJ5GaRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.5.tgz", + "integrity": "sha512-AiqiLkb9KSf7Lj/o1U3SEP9Zn+5NuVKgFdRIZkvd4N0+bYrTOovVd0+LmYCPQGbocT4kvFyK+LXCDiXPBF3fyA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.5.tgz", + "integrity": "sha512-1q+mykKE3Vot1kaFJIDoUFv5TuW+QQVaf2FmTT9krg86pQrGStOSJJ0Zil7CFagyxDuouTepzt5Y5TVzyajOdQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -2546,9 +2734,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "node_modules/@types/express": { @@ -2581,6 +2769,25 @@ "integrity": "sha512-zv9kNf3keYegP5oThGLaPk8E081DFDuwfqjtiTzm6PoxChdJ1raSuADf2YGCVIyrSynLrgc8JWv296s7Q7pQSQ==", "dev": true }, + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, "node_modules/@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", @@ -2706,6 +2913,12 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", "devOptional": true }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, "node_modules/@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -11040,12 +11253,12 @@ } }, "node_modules/magic-string": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", - "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "version": "0.30.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", + "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", "dev": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.13" + "@jridgewell/sourcemap-codec": "^1.4.15" }, "engines": { "node": ">=12" @@ -14128,21 +14341,139 @@ } }, "node_modules/rollup": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.1.tgz", - "integrity": "sha512-c+ebvQz0VIH4KhhCpDsI+Bik0eT8ZFEVZEYw0cGMVqIP8zc+gnwl7iXCamTw7vzv2MeuZFZfdx5JJIq+ehzDlg==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.5.tgz", + "integrity": "sha512-E4vQW0H/mbNMw2yLSqJyjtkHY9dslf/p0zuT1xehNRqUTBOFMqEjguDvqhXr7N7r/4ttb2jr4T41d3dncmIgbQ==", "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=14.18.0", + "node": ">=18.0.0", "npm": ">=8.0.0" }, "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.9.5", + "@rollup/rollup-android-arm64": "4.9.5", + "@rollup/rollup-darwin-arm64": "4.9.5", + "@rollup/rollup-darwin-x64": "4.9.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.5", + "@rollup/rollup-linux-arm64-gnu": "4.9.5", + "@rollup/rollup-linux-arm64-musl": "4.9.5", + "@rollup/rollup-linux-riscv64-gnu": "4.9.5", + "@rollup/rollup-linux-x64-gnu": "4.9.5", + "@rollup/rollup-linux-x64-musl": "4.9.5", + "@rollup/rollup-win32-arm64-msvc": "4.9.5", + "@rollup/rollup-win32-ia32-msvc": "4.9.5", + "@rollup/rollup-win32-x64-msvc": "4.9.5", "fsevents": "~2.3.2" } }, + "node_modules/rollup-plugin-copy": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.5.0.tgz", + "integrity": "sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==", + "dev": true, + "dependencies": { + "@types/fs-extra": "^8.0.1", + "colorette": "^1.1.0", + "fs-extra": "^8.1.0", + "globby": "10.0.1", + "is-plain-object": "^3.0.0" + }, + "engines": { + "node": ">=8.3" + } + }, + "node_modules/rollup-plugin-copy/node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true + }, + "node_modules/rollup-plugin-copy/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/rollup-plugin-copy/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup-plugin-copy/node_modules/globby": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", + "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/rollup-plugin-copy/node_modules/is-plain-object": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup-plugin-copy/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/rollup-plugin-copy/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/run-applescript": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", diff --git a/package.json b/package.json index 574a135ae3..e65f3f6fa6 100644 --- a/package.json +++ b/package.json @@ -39,11 +39,12 @@ "npm": ">=9.5.0" }, "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.3", - "@rollup/plugin-json": "^6.0.0", - "@rollup/plugin-node-resolve": "^15.1.0", - "@rollup/plugin-run": "^3.0.1", - "@rollup/plugin-typescript": "^11.1.2", + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-run": "^3.0.2", + "@rollup/plugin-typescript": "^11.1.6", + "@rollup/plugin-virtual": "^3.0.2", "@tanstack/eslint-plugin-query": "^4.34.1", "@types/jest": "^29.5.4", "@types/node": "^18.14.2", @@ -65,7 +66,8 @@ "lint-staged": "^14.0.1", "prettier": "^3.0.2", "rimraf": "^4.4.1", - "rollup": "^3.27.2", + "rollup": "^4.9.5", + "rollup-plugin-copy": "^3.5.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", "type-fest": "^3.13.0", diff --git a/server/src/index.js b/server/src/index.js index 44081efc1a..161a59231d 100644 --- a/server/src/index.js +++ b/server/src/index.js @@ -1,7 +1,7 @@ /* eslint-env node */ -import path from "path"; -import { fileURLToPath } from "url"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; import express from "express"; import ejs from "ejs"; @@ -14,12 +14,12 @@ import { KONVEYOR_ENV, SERVER_ENV_KEYS, proxyMap, + brandingStrings, } from "@konveyor-ui/common"; const __dirname = fileURLToPath(new URL(".", import.meta.url)); const pathToClientDist = path.join(__dirname, "../../client/dist"); -const brandType = KONVEYOR_ENV.PROFILE; const port = parseInt(KONVEYOR_ENV.PORT, 10) || 8080; const app = express(); @@ -48,7 +48,7 @@ app.get("*", (_, res) => { } else { res.render("index.html.ejs", { _env: encodeEnv(KONVEYOR_ENV, SERVER_ENV_KEYS), - brandType, + branding: brandingStrings, }); } }); From 4cdf7ca604a92ddeb246c8dfb0906bb026dde76e Mon Sep 17 00:00:00 2001 From: Scott Dickerson Date: Mon, 4 Mar 2024 23:02:27 -0500 Subject: [PATCH 33/53] :seedling: Swap to @rollup/wasm-node for multiarch builds (#1739) On merge to main, #1664 showed that the normal rollup package does not support the linux-ppc64 platform. This was not caught earlier as building on github actions always worked with the standard `rollup` package. The error message displayed on the multiarch build attempt is: > Error: Your current platform "linux" and architecture "ppc64" combination is not yet supported by the native Rollup build. Please use the WASM build "@rollup/wasm-node" instead. Swapping the package `rollup` to `@rollup/wasm-node` should enable the ppc64 build. Signed-off-by: Scott J Dickerson --- package-lock.json | 62 ++++++++++++++++++++++++++++++++++++----------- package.json | 2 +- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index e6b4957ec2..f427685b9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@rollup/plugin-run": "^3.0.2", "@rollup/plugin-typescript": "^11.1.6", "@rollup/plugin-virtual": "^3.0.2", + "@rollup/wasm-node": "^4.12.0", "@tanstack/eslint-plugin-query": "^4.34.1", "@types/jest": "^29.5.4", "@types/node": "^18.14.2", @@ -42,7 +43,6 @@ "lint-staged": "^14.0.1", "prettier": "^3.0.2", "rimraf": "^4.4.1", - "rollup": "^4.9.5", "rollup-plugin-copy": "^3.5.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", @@ -2078,7 +2078,8 @@ "optional": true, "os": [ "android" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-android-arm64": { "version": "4.9.5", @@ -2091,7 +2092,8 @@ "optional": true, "os": [ "android" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-darwin-arm64": { "version": "4.9.5", @@ -2104,7 +2106,8 @@ "optional": true, "os": [ "darwin" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-darwin-x64": { "version": "4.9.5", @@ -2117,7 +2120,8 @@ "optional": true, "os": [ "darwin" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { "version": "4.9.5", @@ -2130,7 +2134,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-arm64-gnu": { "version": "4.9.5", @@ -2143,7 +2148,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-arm64-musl": { "version": "4.9.5", @@ -2156,7 +2162,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { "version": "4.9.5", @@ -2169,7 +2176,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.9.5", @@ -2182,7 +2190,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-x64-musl": { "version": "4.9.5", @@ -2195,7 +2204,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-win32-arm64-msvc": { "version": "4.9.5", @@ -2208,7 +2218,8 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-win32-ia32-msvc": { "version": "4.9.5", @@ -2221,7 +2232,8 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-win32-x64-msvc": { "version": "4.9.5", @@ -2234,7 +2246,27 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true + }, + "node_modules/@rollup/wasm-node": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/wasm-node/-/wasm-node-4.12.0.tgz", + "integrity": "sha512-sqy3+YvV/uWX6bPZOR5PlEdH6xyMPXoelllRQ/uZ13tzy9f4pXZTbajnoWN8IHHXwTNKPiLzsePLiDEVmkxMNw==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } }, "node_modules/@sinclair/typebox": { "version": "0.27.8", @@ -14345,6 +14377,8 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.5.tgz", "integrity": "sha512-E4vQW0H/mbNMw2yLSqJyjtkHY9dslf/p0zuT1xehNRqUTBOFMqEjguDvqhXr7N7r/4ttb2jr4T41d3dncmIgbQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "@types/estree": "1.0.5" }, diff --git a/package.json b/package.json index e65f3f6fa6..28f1b2be9c 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@rollup/plugin-run": "^3.0.2", "@rollup/plugin-typescript": "^11.1.6", "@rollup/plugin-virtual": "^3.0.2", + "@rollup/wasm-node": "^4.12.0", "@tanstack/eslint-plugin-query": "^4.34.1", "@types/jest": "^29.5.4", "@types/node": "^18.14.2", @@ -66,7 +67,6 @@ "lint-staged": "^14.0.1", "prettier": "^3.0.2", "rimraf": "^4.4.1", - "rollup": "^4.9.5", "rollup-plugin-copy": "^3.5.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", From 6bbca51226ec53d40dc8696d565ae6f0a3011ec4 Mon Sep 17 00:00:00 2001 From: Ian Bolton Date: Tue, 5 Mar 2024 08:49:23 -0500 Subject: [PATCH 34/53] :bug: Remove unnecessary query invalidations for reviews (#1735) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://issues.redhat.com/browse/MTA-2359 - Removes query invalidation & additional archetypes / reviews api calls inside each instance of a rendered (but hidden) drawer. This was causing a huge performance hit. - Adds margin at top of reviews tab Screenshot 2024-03-04 at 2 46 40 PM Signed-off-by: Ian Bolton --- .../applications-table/applications-table.tsx | 5 ++++- .../application-detail-drawer.tsx | 22 ++++++++++++++----- .../review-fields.tsx | 13 ++++++----- .../components/archetype-detail-drawer.tsx | 6 +++-- .../components/review-form/review-form.tsx | 1 - client/src/app/queries/applications.ts | 2 -- client/src/app/queries/archetypes.ts | 2 -- 7 files changed, 31 insertions(+), 20 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 4f44be86ea..70a85bf7e5 100644 --- a/client/src/app/pages/applications/applications-table/applications-table.tsx +++ b/client/src/app/pages/applications/applications-table/applications-table.tsx @@ -84,7 +84,7 @@ import { useDeleteAssessmentMutation, useFetchAssessments, } from "@app/queries/assessments"; -import { useDeleteReviewMutation } from "@app/queries/reviews"; +import { useDeleteReviewMutation, useFetchReviews } from "@app/queries/reviews"; import { useFetchIdentities } from "@app/queries/identities"; import { useFetchTagsWithTagItems } from "@app/queries/tags"; @@ -117,6 +117,7 @@ export const ApplicationsTable: React.FC = () => { const { pushNotification } = React.useContext(NotificationsContext); const { identities } = useFetchIdentities(); + const { reviews, isFetching: isFetchingReviews } = useFetchReviews(); const [saveApplicationModalState, setSaveApplicationModalState] = React.useState<"create" | Application | null>(null); @@ -1078,6 +1079,8 @@ export const ApplicationsTable: React.FC = () => { application={activeItem} applications={applications} assessments={assessments} + archetypes={archetypes} + reviews={reviews} onCloseClick={clearActiveItem} onEditClick={() => setSaveApplicationModalState(activeItem)} task={activeItem ? getTask(activeItem) : null} 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 b721a02478..d32f14fad8 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 @@ -32,6 +32,7 @@ import { Ref, Archetype, AssessmentWithSectionOrder, + Review, } from "@app/api/models"; import { IPageDrawerContentProps, @@ -57,7 +58,6 @@ import { ReviewFields } from "./review-fields"; import { LabelsFromItems } from "@app/components/labels/labels-from-items/labels-from-items"; import { RiskLabel } from "@app/components/RiskLabel"; import { ApplicationDetailFields } from "./application-detail-fields"; -import { useFetchArchetypes } from "@app/queries/archetypes"; import { AssessedArchetypes } from "./components/assessed-archetypes"; export interface IApplicationDetailDrawerProps @@ -66,6 +66,8 @@ export interface IApplicationDetailDrawerProps task: Task | undefined | null; applications?: Application[]; assessments?: AssessmentWithSectionOrder[]; + reviews?: Review[]; + archetypes?: Archetype[]; onEditClick: () => void; } @@ -79,7 +81,15 @@ enum TabKey { export const ApplicationDetailDrawer: React.FC< IApplicationDetailDrawerProps -> = ({ onCloseClick, application, assessments, task, onEditClick }) => { +> = ({ + onCloseClick, + application, + assessments, + reviews, + archetypes, + task, + onEditClick, +}) => { const { t } = useTranslation(); const [activeTabKey, setActiveTabKey] = React.useState( TabKey.Details @@ -88,7 +98,6 @@ export const ApplicationDetailDrawer: React.FC< const isTaskRunning = task?.state === "Running"; const { identities } = useFetchIdentities(); - const { archetypes } = useFetchArchetypes(); const { facts, isFetching } = useFetchFacts(application?.id); const [taskIdToView, setTaskIdToView] = React.useState(); @@ -106,8 +115,9 @@ export const ApplicationDetailDrawer: React.FC< const reviewedArchetypes = application?.archetypes - ?.map((archetypeRef) => - archetypes.find((archetype) => archetype.id === archetypeRef.id) + ?.map( + (archetypeRef) => + archetypes?.find((archetype) => archetype.id === archetypeRef.id) ) .filter((fullArchetype) => fullArchetype?.review) .filter(Boolean) || []; @@ -445,7 +455,7 @@ export const ApplicationDetailDrawer: React.FC< eventKey={TabKey.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 f40fdfce1c..c14d13e74c 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 @@ -6,11 +6,12 @@ import { DescriptionListDescription, } from "@patternfly/react-core"; import { Application, Archetype, Review } from "@app/api/models"; -import { useFetchReviewById, useFetchReviews } from "@app/queries/reviews"; +import { useFetchReviewById } from "@app/queries/reviews"; import { useFetchArchetypes } from "@app/queries/archetypes"; import { EmptyTextMessage } from "@app/components/EmptyTextMessage"; import { PROPOSED_ACTION_LIST, EFFORT_ESTIMATE_LIST } from "@app/Constants"; import { ReviewLabel } from "./review-label"; +import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing"; export type ReviewDrawerLabelItem = { review?: Review | null; @@ -21,9 +22,9 @@ export type ReviewDrawerLabelItem = { export const ReviewFields: React.FC<{ application?: Application | null; archetype?: Archetype | null; -}> = ({ application, archetype }) => { + reviews?: Review[]; +}> = ({ application, archetype, reviews }) => { const { archetypes } = useFetchArchetypes(); - const { reviews } = useFetchReviews(); const { t } = useTranslation(); const { review: appReview } = useFetchReviewById(application?.review?.id); @@ -41,7 +42,7 @@ export const ReviewFields: React.FC<{ const matchedArchetypeReviews: Review[] = (applicationArchetypes || []) .map((archetype) => { - return reviews.find((review) => review.id === archetype?.review?.id); + return reviews?.find((review) => review.id === archetype?.review?.id); }) .filter(Boolean); @@ -71,7 +72,7 @@ export const ReviewFields: React.FC<{ ].filter((item) => item.review?.proposedAction); return ( - <> +
{t("terms.proposedAction")} @@ -150,6 +151,6 @@ export const ReviewFields: React.FC<{ })} - +
); }; 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 90b85d0574..d6f2f80832 100644 --- a/client/src/app/pages/archetypes/components/archetype-detail-drawer.tsx +++ b/client/src/app/pages/archetypes/components/archetype-detail-drawer.tsx @@ -18,7 +18,7 @@ import { } from "@patternfly/react-core"; import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing"; -import { Archetype, Ref, Tag, TagRef } from "@app/api/models"; +import { Archetype, Ref, Review, Tag, TagRef } from "@app/api/models"; import { EmptyTextMessage } from "@app/components/EmptyTextMessage"; import { PageDrawerContent } from "@app/components/PageDrawerContext"; @@ -34,6 +34,7 @@ import { Link } from "react-router-dom"; export interface IArchetypeDetailDrawerProps { onCloseClick: () => void; archetype: Archetype | null; + reviews?: Review[]; } enum TabKey { @@ -44,6 +45,7 @@ enum TabKey { const ArchetypeDetailDrawer: React.FC = ({ onCloseClick, archetype, + reviews, }) => { const { t } = useTranslation(); @@ -226,7 +228,7 @@ const ArchetypeDetailDrawer: React.FC = ({ eventKey={TabKey.Reviews} title={{t("terms.review")}} > - + diff --git a/client/src/app/pages/review/components/review-form/review-form.tsx b/client/src/app/pages/review/components/review-form/review-form.tsx index 7b6100d4e2..3ebcfecb63 100644 --- a/client/src/app/pages/review/components/review-form/review-form.tsx +++ b/client/src/app/pages/review/components/review-form/review-form.tsx @@ -55,7 +55,6 @@ export const ReviewForm: React.FC = ({ application, review, }) => { - console.log("existing review", review); const { t } = useTranslation(); const history = useHistory(); const { pushNotification } = React.useContext(NotificationsContext); diff --git a/client/src/app/queries/applications.ts b/client/src/app/queries/applications.ts index 8e5fc98eb8..12639b102e 100644 --- a/client/src/app/queries/applications.ts +++ b/client/src/app/queries/applications.ts @@ -20,7 +20,6 @@ import { updateAllApplications, updateApplication, } from "@app/api/rest"; -import { reviewsQueryKey } from "./reviews"; import { assessmentsByItemIdQueryKey } from "./assessments"; import saveAs from "file-saver"; @@ -41,7 +40,6 @@ export const useFetchApplications = (refetchDisabled: boolean = false) => { queryFn: getApplications, refetchInterval: !refetchDisabled ? 5000 : false, onSuccess: () => { - queryClient.invalidateQueries([reviewsQueryKey]); queryClient.invalidateQueries([assessmentsByItemIdQueryKey]); }, onError: (error: AxiosError) => console.log(error), diff --git a/client/src/app/queries/archetypes.ts b/client/src/app/queries/archetypes.ts index 2dc818c4db..b64c191064 100644 --- a/client/src/app/queries/archetypes.ts +++ b/client/src/app/queries/archetypes.ts @@ -10,7 +10,6 @@ import { updateArchetype, } from "@app/api/rest"; import { assessmentsByItemIdQueryKey } from "./assessments"; -import { reviewsQueryKey } from "./reviews"; import { useState } from "react"; export const ARCHETYPES_QUERY_KEY = "archetypes"; @@ -39,7 +38,6 @@ export const useFetchArchetypes = (forApplication?: Application | null) => { setFilteredArchetypes([]); } - queryClient.invalidateQueries([reviewsQueryKey]); queryClient.invalidateQueries([assessmentsByItemIdQueryKey]); }, onError: (error: AxiosError) => console.log(error), From ddcbccf2a8d6328943bb1eaf2e37109dd047c7d4 Mon Sep 17 00:00:00 2001 From: Scott Dickerson Date: Tue, 5 Mar 2024 16:24:29 -0500 Subject: [PATCH 35/53] :seedling: Downgrade to rollup v3 for multiarch builds (#1742) Following up on PRs #1664 and #1739, downgrade to `rollup@^3.0`. The v4 of rollup has "native" code that runs the build, and that code does not currently work with s390 builds [1]. Since konveyor is built for x86, arm, ppc, and s390, all of those need to work. When the s390 builds can work with the wasm bits, we can upgrade to `rollup@^4.0` again. [1] - https://github.com/rollup/rollup/issues/5354 Signed-off-by: Scott J Dickerson --- package-lock.json | 229 +--------------------------------------------- package.json | 2 +- 2 files changed, 6 insertions(+), 225 deletions(-) diff --git a/package-lock.json b/package-lock.json index f427685b9d..6ccdc97416 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,6 @@ "@rollup/plugin-run": "^3.0.2", "@rollup/plugin-typescript": "^11.1.6", "@rollup/plugin-virtual": "^3.0.2", - "@rollup/wasm-node": "^4.12.0", "@tanstack/eslint-plugin-query": "^4.34.1", "@types/jest": "^29.5.4", "@types/node": "^18.14.2", @@ -43,6 +42,7 @@ "lint-staged": "^14.0.1", "prettier": "^3.0.2", "rimraf": "^4.4.1", + "rollup": "^3.29.4", "rollup-plugin-copy": "^3.5.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", @@ -2067,207 +2067,6 @@ } } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.5.tgz", - "integrity": "sha512-idWaG8xeSRCfRq9KpRysDHJ/rEHBEXcHuJ82XY0yYFIWnLMjZv9vF/7DOq8djQ2n3Lk6+3qfSH8AqlmHlmi1MA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "peer": true - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.5.tgz", - "integrity": "sha512-f14d7uhAMtsCGjAYwZGv6TwuS3IFaM4ZnGMUn3aCBgkcHAYErhV1Ad97WzBvS2o0aaDv4mVz+syiN0ElMyfBPg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "peer": true - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.5.tgz", - "integrity": "sha512-ndoXeLx455FffL68OIUrVr89Xu1WLzAG4n65R8roDlCoYiQcGGg6MALvs2Ap9zs7AHg8mpHtMpwC8jBBjZrT/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "peer": true - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.5.tgz", - "integrity": "sha512-UmElV1OY2m/1KEEqTlIjieKfVwRg0Zwg4PLgNf0s3glAHXBN99KLpw5A5lrSYCa1Kp63czTpVll2MAqbZYIHoA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.5.tgz", - "integrity": "sha512-Q0LcU61v92tQB6ae+udZvOyZ0wfpGojtAKrrpAaIqmJ7+psq4cMIhT/9lfV6UQIpeItnq/2QDROhNLo00lOD1g==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.5.tgz", - "integrity": "sha512-dkRscpM+RrR2Ee3eOQmRWFjmV/payHEOrjyq1VZegRUa5OrZJ2MAxBNs05bZuY0YCtpqETDy1Ix4i/hRqX98cA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.5.tgz", - "integrity": "sha512-QaKFVOzzST2xzY4MAmiDmURagWLFh+zZtttuEnuNn19AiZ0T3fhPyjPPGwLNdiDT82ZE91hnfJsUiDwF9DClIQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.5.tgz", - "integrity": "sha512-HeGqmRJuyVg6/X6MpE2ur7GbymBPS8Np0S/vQFHDmocfORT+Zt76qu+69NUoxXzGqVP1pzaY6QIi0FJWLC3OPA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.5.tgz", - "integrity": "sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.5.tgz", - "integrity": "sha512-ezyFUOwldYpj7AbkwyW9AJ203peub81CaAIVvckdkyH8EvhEIoKzaMFJj0G4qYJ5sw3BpqhFrsCc30t54HV8vg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.5.tgz", - "integrity": "sha512-aHSsMnUw+0UETB0Hlv7B/ZHOGY5bQdwMKJSzGfDfvyhnpmVxLMGnQPGNE9wgqkLUs3+gbG1Qx02S2LLfJ5GaRQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.5.tgz", - "integrity": "sha512-AiqiLkb9KSf7Lj/o1U3SEP9Zn+5NuVKgFdRIZkvd4N0+bYrTOovVd0+LmYCPQGbocT4kvFyK+LXCDiXPBF3fyA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.5.tgz", - "integrity": "sha512-1q+mykKE3Vot1kaFJIDoUFv5TuW+QQVaf2FmTT9krg86pQrGStOSJJ0Zil7CFagyxDuouTepzt5Y5TVzyajOdQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, - "node_modules/@rollup/wasm-node": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/wasm-node/-/wasm-node-4.12.0.tgz", - "integrity": "sha512-sqy3+YvV/uWX6bPZOR5PlEdH6xyMPXoelllRQ/uZ13tzy9f4pXZTbajnoWN8IHHXwTNKPiLzsePLiDEVmkxMNw==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -14373,36 +14172,18 @@ } }, "node_modules/rollup": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.5.tgz", - "integrity": "sha512-E4vQW0H/mbNMw2yLSqJyjtkHY9dslf/p0zuT1xehNRqUTBOFMqEjguDvqhXr7N7r/4ttb2jr4T41d3dncmIgbQ==", + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@types/estree": "1.0.5" - }, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=18.0.0", + "node": ">=14.18.0", "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.9.5", - "@rollup/rollup-android-arm64": "4.9.5", - "@rollup/rollup-darwin-arm64": "4.9.5", - "@rollup/rollup-darwin-x64": "4.9.5", - "@rollup/rollup-linux-arm-gnueabihf": "4.9.5", - "@rollup/rollup-linux-arm64-gnu": "4.9.5", - "@rollup/rollup-linux-arm64-musl": "4.9.5", - "@rollup/rollup-linux-riscv64-gnu": "4.9.5", - "@rollup/rollup-linux-x64-gnu": "4.9.5", - "@rollup/rollup-linux-x64-musl": "4.9.5", - "@rollup/rollup-win32-arm64-msvc": "4.9.5", - "@rollup/rollup-win32-ia32-msvc": "4.9.5", - "@rollup/rollup-win32-x64-msvc": "4.9.5", "fsevents": "~2.3.2" } }, diff --git a/package.json b/package.json index 28f1b2be9c..10e5f67dbc 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ "@rollup/plugin-run": "^3.0.2", "@rollup/plugin-typescript": "^11.1.6", "@rollup/plugin-virtual": "^3.0.2", - "@rollup/wasm-node": "^4.12.0", "@tanstack/eslint-plugin-query": "^4.34.1", "@types/jest": "^29.5.4", "@types/node": "^18.14.2", @@ -67,6 +66,7 @@ "lint-staged": "^14.0.1", "prettier": "^3.0.2", "rimraf": "^4.4.1", + "rollup": "^3.29.4", "rollup-plugin-copy": "^3.5.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", From 8ec80833dcaa5d48efda0b963ac3fa6f563f0036 Mon Sep 17 00:00:00 2001 From: Radoslaw Szwajkowski <64194103+rszwajko@users.noreply.github.com> Date: Wed, 6 Mar 2024 17:46:48 +0100 Subject: [PATCH 36/53] :bug: Count custom rules imported from yaml file (#1748) Reference-Url: https://issues.redhat.com/browse/MTA-2003 ### Before ![Screenshot from 2024-03-06 13-39-40](https://github.com/konveyor/tackle2-ui/assets/64194103/915742f9-94da-4ab9-8229-e22e974e72e7) ### After ![Screenshot from 2024-03-06 15-17-17](https://github.com/konveyor/tackle2-ui/assets/64194103/e74f76ee-0a86-489a-a0fc-753c4cd96035) Signed-off-by: Radoslaw Szwajkowski --- client/src/app/utils/rules-utils.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/app/utils/rules-utils.ts b/client/src/app/utils/rules-utils.ts index 3c460d6587..e9bdb5f6ea 100644 --- a/client/src/app/utils/rules-utils.ts +++ b/client/src/app/utils/rules-utils.ts @@ -21,8 +21,8 @@ export const parseRules = (file: IReadFile): ParsedRule => { const yamlList = Array.isArray(yamlDoc) ? yamlDoc : [yamlDoc]; const yamlLabels = Array.from( new Set( - yamlList?.flatMap((parsedLine) => { - return parsedLine?.labels ? parsedLine?.labels : []; + yamlList?.flatMap((parsedRule) => { + return parsedRule?.labels ? parsedRule?.labels : []; }) || [] ) ); @@ -32,7 +32,8 @@ export const parseRules = (file: IReadFile): ParsedRule => { target: allLabels?.targetLabel, otherLabels: allLabels?.otherLabels, allLabels: allLabels?.allLabels, - total: 0, + total: + yamlList?.filter((parsedRule) => parsedRule?.ruleID)?.length ?? 0, ...(file.responseID && { fileID: file.responseID, }), From 3e3d6904964fd4085bdfddd3e7530368a0022b10 Mon Sep 17 00:00:00 2001 From: Scott Dickerson Date: Wed, 6 Mar 2024 16:28:14 -0500 Subject: [PATCH 37/53] :seedling: Increase ulimit nofiles on image-build.yaml (#1746) Builds keep failing with EMFILE errors, so follow the advice from a similar issue work around: https://github.com/npm/cli/issues/4783#issuecomment-1908016260 --------- Signed-off-by: Scott Dickerson --- .github/workflows/image-build.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/image-build.yaml b/.github/workflows/image-build.yaml index 261d01674a..3e67b3fcf2 100644 --- a/.github/workflows/image-build.yaml +++ b/.github/workflows/image-build.yaml @@ -21,6 +21,7 @@ jobs: image_name: "tackle2-ui" containerfile: "./Dockerfile" architectures: '[ "amd64", "arm64", "ppc64le", "s390x" ]' + extra-args: "--ulimit nofile=4096:4096" secrets: registry_username: ${{ secrets.QUAY_PUBLISH_ROBOT }} registry_password: ${{ secrets.QUAY_PUBLISH_TOKEN }} From ad90cd5cb3839316997fb21298897a760053d911 Mon Sep 17 00:00:00 2001 From: Radoslaw Szwajkowski <64194103+rszwajko@users.noreply.github.com> Date: Mon, 11 Mar 2024 20:47:24 +0100 Subject: [PATCH 38/53] :sparkles: Add deleteChipGroup handler (#1750) Resolves: #1744 Signed-off-by: Radoslaw Szwajkowski --- .../app/components/FilterToolbar/MultiselectFilterControl.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx b/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx index 1d2297ee7b..bbc0c0fce5 100644 --- a/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx +++ b/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx @@ -81,6 +81,7 @@ export const MultiselectFilterControl = ({ const textInputRef = React.useRef(); const [inputValue, setInputValue] = React.useState(""); + const onFilterClearAll = () => setFilterValue([]); const onFilterClear = (chip: string | ToolbarChip) => { const displayValue = typeof chip === "string" ? chip : chip.key; const optionKey = getOptionKeyFromChip(displayValue); @@ -357,6 +358,7 @@ export const MultiselectFilterControl = ({ id={`filter-control-${category.key}`} chips={chips} deleteChip={(_, chip) => onFilterClear(chip)} + deleteChipGroup={onFilterClearAll} categoryName={category.title} showToolbarItem={showToolbarItem} > From 6b805b53293206b908317390b939659fdb314dbb Mon Sep 17 00:00:00 2001 From: Radoslaw Szwajkowski <64194103+rszwajko@users.noreply.github.com> Date: Mon, 11 Mar 2024 21:46:11 +0100 Subject: [PATCH 39/53] :book: Update developer documentation (#1726) Changes: 1. fix dead links i.e. to PF4 components or refactored code 2. in README 1. OLM addon issue 2. be more general about minikube drivers i.e. rootless or without VMs 3. prefer port forwarding to proxy when accessing dashboard (seems safer) 3. in INTERNATIONALIZATION - comment that questionnaire is data imported from YAML files --------- Signed-off-by: Radoslaw Szwajkowski Signed-off-by: Radoslaw Szwajkowski <64194103+rszwajko@users.noreply.github.com> Co-authored-by: Ian Bolton --- INTERNATIONALIZATION.md | 8 ++++---- README.md | 41 ++++++++++++++++++++++++++--------------- development.md | 16 ++++++++-------- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/INTERNATIONALIZATION.md b/INTERNATIONALIZATION.md index 8f9f4b5423..1fc9282fec 100644 --- a/INTERNATIONALIZATION.md +++ b/INTERNATIONALIZATION.md @@ -25,17 +25,17 @@ locales: ["en", "es", "myLanguageCode"] npm extract ``` -The previous command created a file `public/locales/{myLanguageCode}/translation.json`; the content of this file should be the translated new language. As a reference you can use the english version of the translation located at [public/locales/en/translation.json](https://github.com/konveyor/tackle-ui/blob/main/public/locales/en/translation.json) +The previous command created a file `public/locales/{myLanguageCode}/translation.json`; the content of this file should be the translated new language. As a reference you can use the english version of the translation located at [public/locales/en/translation.json](https://github.com/konveyor/tackle2-ui/blob/main/client/public/locales/en/translation.json) > As soon as you feel confident, open a new Pull Request with your changes and make it part of the official repository. ## How to see the new translation in action? -To see your changes in action you will need to start Tackle UI in development mode. For starting Tackle UI in development mode follow the instruction at [Starting the UI](https://github.com/konveyor/tackle-ui#starting-the-ui) +To see your changes in action you will need to start Tackle UI in development mode. For starting Tackle UI in development mode follow the instruction at [Development section](https://github.com/konveyor/tackle2-ui/blob/main/README.md#development) Steps: -- Start Tackle UI in dev mode following [Starting the UI](https://github.com/konveyor/tackle-ui#starting-the-ui) instructions. +- Start Tackle UI in dev mode following the instructions in the [Development section](https://github.com/konveyor/tackle2-ui/blob/main/README.md#development). - Go to Keycloak http://localhost:8180/auth/admin/ and use `username=admin, password=admin`. Go to `Realm settings > themes > Supported locales` and select the new language you are adding. Finally click on `Save`. - Go to http://localhost:3000/ and you should be redirected to the Login page where you are able to select your new language. @@ -45,4 +45,4 @@ At this point you should be able to see your new language already translated int ## Why the questionnaire (assessment process) is not translated? -The questionnaire is data comming from https://github.com/konveyor/tackle-pathfinder hence the translation to a new language of the questionnaire should be done in that repository. +To accommodate diverse user needs, including internationalization, our custom assessment module supports the uploading of YAML files. This flexibility allows for the easy adaptation of assessments to different languages or specific requirements. If you're looking to offer assessments in a new language, simply create and upload a YAML file tailored to that language. diff --git a/README.md b/README.md index 9f57be6499..202674095a 100644 --- a/README.md +++ b/README.md @@ -49,13 +49,25 @@ $ minikube config set memory 10240 $ minikube config set cpus 4 ``` -From a terminal with administrator access (but not logged in as root), run: +Note: Depending on your driver, administrator access may be required. Common choices include Docker for container-based virtualization and KVM for hardware-assisted virtualization on Linux systems. If you're not sure which driver is best for you or if you're encountering compatibility issues, Minikube also supports auto-selecting a driver based on your system's capabilities and installed software. + +From a terminal run: + +```sh +$ minikube start --addons=dashboard --addons=ingress +``` + +Note: We need to enable the dashboard and ingress addons. The dashboard addon installs the dashboard service that exposes the Kubernetes objects in a user interface. The ingress addon allows us to create Ingress CRs to expose the Tackle UI and Tackle Hub API. + +Since the olm addon is disabled until OLM issue [2534](https://github.com/operator-framework/operator-lifecycle-manager/issues/2534) is resolved we need to install the [OLM manually](https://github.com/operator-framework/operator-lifecycle-manager/releases) i.e. for version `v0.27.0` we can use: ```sh -$ minikube start --addons=dashboard --addons=ingress --addons=olm +curl -L https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.27.0/install.sh -o install.sh +chmod +x install.sh +./install.sh v0.27.0 ``` -Note: We need to enable the dashboard, ingress and olm addons. The dashboard addon installs the dashboard service that exposes the Kubernetes objects in a user interface. The ingress addon allows us to create Ingress CRs to expose the Tackle UI and Tackle Hub API. The olm addon allows us to use an operator to deploy Tackle. +See also official Konveyor instructions for [Provisioning Minikube](https://konveyor.github.io/konveyor/installation/#provisioning-minikube). ### Configuring kubectl for minikube @@ -83,7 +95,9 @@ You will need `kubectl` on your PATH and configured to control minikube in order ### Installing the Konveyor operator -The [konveyor/operator git repository](https://github.com/konveyor/operator) provides a script to install Tackle locally using `kubectl`. You can [inspect its source here](https://github.com/konveyor/operator/blob/main/hack/install-tackle.sh). This script creates the `konveyor-tackle` namespace, CatalogSource, OperatorGroup, Subscription and Tackle CR, then waits for deployments to be ready. +Follow the official instructions for [Installing Konveyor Operator](https://konveyor.github.io/konveyor/installation/#installing-konveyor-operator) + +Alternatively, the [konveyor/operator git repository](https://github.com/konveyor/operator) provides a script to install Tackle locally using `kubectl`. You can [inspect its source here](https://github.com/konveyor/operator/blob/main/hack/install-tackle.sh). This script creates the `konveyor-tackle` namespace, CatalogSource, OperatorGroup, Subscription and Tackle CR, then waits for deployments to be ready. #### Customizing the install script (optional) @@ -126,7 +140,7 @@ $ npm run start:dev ## Understanding the local development environment -Tackle2 runs in a Kubernetes compatible environment (Openshift, Kubernetes or minikube) and is usually deployed with Tackle2 Operator (OLM). +Tackle2 runs in a Kubernetes compatible environment (i.e. Openshift, Kubernetes or minikube) and is usually deployed with Tackle2 Operator (OLM). Although the UI pod has access to tackle2 APIs from within the cluster, the UI can also be executed outside the cluster and access Tackle APIs endpoints by proxy. The React and Patternfly based UI is composed of web pages served by an http server with proxy capabilities. @@ -182,26 +196,23 @@ port and only show the URL instead of opening the default browser directly: $ minikube dashboard --port=18080 --url=true ``` -Second, we can use the `kubectl proxy` command to enable access to the dashboard. The following -command sets up the proxy to listen on any network interface (useful for remote access), to the -18080/tcp port (easy to remember), and with requests filtering disabled (less secure, but necessary): +Second, we can use the `kubectl port-forward` command to enable access to the dashboard: ```sh -$ kubectl proxy --address=0.0.0.0 --port 18080 --disable-filter=true +$ kubectl port-forward svc/kubernetes-dashboard -n kubernetes-dashboard 30090:80 ``` -We can now access the minikube dashboard through the proxy. Use the following URL as a template, -replacing the IP address with your workstation IP address: -`http://192.168.0.1:18080/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/#/` +We can now access the minikube dashboard on `http://localhost:30090` ## Troubleshooting -Note - The steps described are executed on a Fedora 35 workstation, but will likely work on any recent Linux distribution. -The only prerequisites are to enable virtualization extensions in the BIOS/EFI of the machine, to install libvirt and to add our user to the libvirt group. +Note - The steps described are executed on a Fedora 38 workstation, but will likely work on any recent Linux distribution. + +- For minikube setups that rely on virtualization, the only prerequisites are to enable virtualization extensions in the BIOS/EFI of the machine, to install libvirt and to add our user to the libvirt group. - Ensure that your minikube installation directory is available in your `$PATH` environment variable. This is usually `/usr/local/bin/` or something similar depending on your OS of choice. -- The following command gives us the IP address assigned to the virtual machine created by Minikube. +- The following command gives us the IP address assigned to the node created by Minikube. It's used when interacting with tackle UI image installed on the minikube cluster. ```sh diff --git a/development.md b/development.md index 3d2ebc9273..3ec657c916 100644 --- a/development.md +++ b/development.md @@ -13,11 +13,11 @@ Our project utilizes [Hooks](https://reactjs.org/docs/hooks-intro.html) wherever ## Styling components For any custom styles, we use standard css with no preprocessors. If a custom style is needed, create a css file and import it within the component. -For handling spacing/layout requirements that do not fit the standard PF mold, we are able to use the [Patternfly spacing utility classes](https://www.patternfly.org/v4/utilities/spacing). +For handling spacing/layout requirements that do not fit the standard PF mold, we are able to use the [Patternfly spacing utility classes](https://www.patternfly.org/utility-classes/spacing/). ## Form development -We are using [react-hook-form](https://react-hook-form.com) in tandem with [patternfly](https://www.patternfly.org/v4/). Custom wrapper components have been developed to aid with this integration and their usage can be referenced in the [proxy-form](./client/src/app/pages/proxies/proxy-form.tsx) component. +We are using [react-hook-form](https://react-hook-form.com) in tandem with [patternfly](https://www.patternfly.org). Custom wrapper components have been developed to aid with this integration and their usage can be referenced in the [proxy-form](./client/src/app/pages/proxies/proxy-form.tsx) component. ### Steps to create a form @@ -41,22 +41,22 @@ export interface FormValues { - Note: `watch` will not be needed if you are using least one controlled input field via our controller components below since the presence of a controlled input will cause RHF to auto-watch the form values anyway. -- Write an onSubmit function of type `SubmitHandler`. Wrap your form fields in a PF `
` component with `onSubmit={handleSubmit(onSubmit)}` where `handleSubmit` came from your `useForm` call. That's where you'll eventually want to do the submit logic, probably using [mutations](https://tanstack.com/query/v4/docs/guides/mutations) from react-query. +- Write an onSubmit function of type `SubmitHandler`. Wrap your form fields in a PF `` component with `onSubmit={handleSubmit(onSubmit)}` where `handleSubmit` came from your `useForm` call. That's where you'll eventually want to do the submit logic, probably using [mutations](https://tanstack.com/query/v4/docs/framework/react/guides/mutations) from react-query. ### react-hook-form / wrapper component usage - Now you can use our new components for the fields themselves. They will take care of rendering the PF FormGroups and properly styled validation errors. Pass them the `control` prop from your `useForm` call and a name string prop matching the field name key from your form values object. TS is smart enough to infer the right field value type from those 2 props. - - If you're rendering a basic text input, you can use `HookFormPFTextInput` ([source](https://github.com/konveyor/tackle2-ui/blob/main/client/src/app/shared/components/hook-form-pf-fields/hook-form-pf-text-area.tsx), [example](https://github.com/konveyor/tackle2-ui/blob/main/client/src/app/pages/proxies/proxy-form.tsx#L372-L378)). It extends the props of PatternFly's [TextInput](https://www.patternfly.org/v4/components/text-input), so you can pass whatever extra stuff you need directly into it. + - If you're rendering a basic text input, you can use `HookFormPFTextInput` ([source](https://github.com/konveyor/tackle2-ui/blob/main/client/src/app/components/HookFormPFFields/HookFormPFTextInput.tsx), [example](https://github.com/konveyor/tackle2-ui/blob/main/client/src/app/pages/proxies/proxy-form.tsx)). It extends the props of PatternFly's [TextInput](https://www.patternfly.org/components/forms/text-input/#textinput), so you can pass whatever extra stuff you need directly into it. - - Same for a multi-line textarea, you can use `HookFormPFTextArea` ([source](https://github.com/konveyor/tackle2-ui/blob/main/client/src/app/shared/components/hook-form-pf-fields/hook-form-pf-group-controller.tsx), [example](https://github.com/konveyor/tackle2-ui/blob/main/client/src/app/pages/proxies/proxy-form.tsx#L257-L282)) which extends the props of PF [TextArea](https://www.patternfly.org/v4/components/text-area). + - Same for a multi-line textarea, you can use `HookFormPFTextArea` ([source](https://github.com/konveyor/tackle2-ui/blob/main/client/src/app/components/HookFormPFFields/HookFormPFTextArea.tsx), [example](https://github.com/konveyor/tackle2-ui/blob/main/client/src/app/pages/proxies/proxy-form.tsx)) which extends the props of PF [TextArea](https://www.patternfly.org/components/forms/text-area). - - For any other type of field that requires a PF `FormGroup` (label, error messages under the field) you can use the `HookFormPFGroupController` that is used internally by those 2 components, and pass it your own `renderField` function. (source, example). For select dropdowns we have a simplified abstraction called [SimpleSelect](https://github.com/konveyor/tackle2-ui/blob/main/client/src/app/shared/components/simple-select/simple-select.tsx). + - For any other type of field that requires a PF `FormGroup` (label, error messages under the field) you can use the `HookFormPFGroupController` that is used internally by those 2 components, and pass it your own `renderField` function. (source, example). For select dropdowns we have a simplified abstraction called [SimpleSelect](https://github.com/konveyor/tackle2-ui/blob/main/client/src/app/components/SimpleSelect.tsx). - These all use the Controller pattern from react-hook-form (docs [here](https://react-hook-form.com/get-started#IntegratingwithUIlibraries) and [here](https://react-hook-form.com/api/usecontroller/controller)). You generally don't want to use the `{...register('fieldName')}` approach that is all over their docs, it is for uncontrolled inputs (we need controlled inputs to render errors on change). - - All of the above components include a formGroupProps prop in case you need to override any of the [props for PF's FormGroup](https://www.patternfly.org/v4/components/form#formgroup) that aren't taken care of for you. + - All of the above components include a formGroupProps prop in case you need to override any of the [props for PF's FormGroup](https://www.patternfly.org/components/forms/form#field-groups) that aren't taken care of for you. -- If you don't need a `FormGroup` around your field (no external label or errors), you can just render a for it yourself. That's what we do for [Switch](https://www.patternfly.org/v4/components/switch) fields (because switch has a built in right-aligned label). ([example](https://github.com/konveyor/tackle2-ui/blob/main/client/src/app/pages/proxies/proxy-form.tsx#L286-L300)) +- If you don't need a `FormGroup` around your field (no external label or errors), you can just render a for it yourself. That's what we do for [Switch](https://www.patternfly.org/components/switch) fields (because switch has a built in right-aligned label). ([example](https://github.com/konveyor/tackle2-ui/blob/main/client/src/app/pages/proxies/proxy-form.tsx)) ## READMEs From 333cc04991c98c186491ebbee2307577a00ce9bd Mon Sep 17 00:00:00 2001 From: Scott Dickerson Date: Mon, 11 Mar 2024 16:46:21 -0400 Subject: [PATCH 40/53] :seedling: Refactor `ReviewFields` (#1752) Refactor the `ReviewFields` component in advance of #1745: - The component is used on the Review tab of application and archetype details drawer - The input prop `reviews` was not used in any current containing component. Push the `useFetchReviews()` hook down to the component itself. This keeps the data fetch as close as possible to where it is used. - Move the component to `@app/components/detail-drawer` folder since it is used in more than one page grouping Signed-off-by: Scott J Dickerson Co-authored-by: Ian Bolton --- .../detail-drawer}/review-fields.tsx | 8 +++- .../detail-drawer}/review-label.tsx | 0 .../applications-table/applications-table.tsx | 4 +- .../application-detail-drawer.tsx | 41 ++++++++++--------- .../components/archetype-detail-drawer.tsx | 15 ++++--- 5 files changed, 35 insertions(+), 33 deletions(-) rename client/src/app/{pages/applications/components/application-detail-drawer => components/detail-drawer}/review-fields.tsx (97%) rename client/src/app/{pages/applications/components/application-detail-drawer => components/detail-drawer}/review-label.tsx (100%) diff --git a/client/src/app/pages/applications/components/application-detail-drawer/review-fields.tsx b/client/src/app/components/detail-drawer/review-fields.tsx similarity index 97% rename from client/src/app/pages/applications/components/application-detail-drawer/review-fields.tsx rename to client/src/app/components/detail-drawer/review-fields.tsx index c14d13e74c..07580febd9 100644 --- a/client/src/app/pages/applications/components/application-detail-drawer/review-fields.tsx +++ b/client/src/app/components/detail-drawer/review-fields.tsx @@ -5,13 +5,16 @@ import { DescriptionListTerm, DescriptionListDescription, } from "@patternfly/react-core"; +import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing"; + import { Application, Archetype, Review } from "@app/api/models"; import { useFetchReviewById } from "@app/queries/reviews"; import { useFetchArchetypes } from "@app/queries/archetypes"; +import { useFetchReviews } from "@app/queries/reviews"; + import { EmptyTextMessage } from "@app/components/EmptyTextMessage"; import { PROPOSED_ACTION_LIST, EFFORT_ESTIMATE_LIST } from "@app/Constants"; import { ReviewLabel } from "./review-label"; -import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing"; export type ReviewDrawerLabelItem = { review?: Review | null; @@ -23,10 +26,11 @@ export const ReviewFields: React.FC<{ application?: Application | null; archetype?: Archetype | null; reviews?: Review[]; -}> = ({ application, archetype, reviews }) => { +}> = ({ application, archetype }) => { const { archetypes } = useFetchArchetypes(); const { t } = useTranslation(); + const { reviews } = useFetchReviews(); const { review: appReview } = useFetchReviewById(application?.review?.id); const { review: archetypeReview } = useFetchReviewById(archetype?.review?.id); diff --git a/client/src/app/pages/applications/components/application-detail-drawer/review-label.tsx b/client/src/app/components/detail-drawer/review-label.tsx similarity index 100% rename from client/src/app/pages/applications/components/application-detail-drawer/review-label.tsx rename to client/src/app/components/detail-drawer/review-label.tsx 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 70a85bf7e5..40024f3a50 100644 --- a/client/src/app/pages/applications/applications-table/applications-table.tsx +++ b/client/src/app/pages/applications/applications-table/applications-table.tsx @@ -84,7 +84,7 @@ import { useDeleteAssessmentMutation, useFetchAssessments, } from "@app/queries/assessments"; -import { useDeleteReviewMutation, useFetchReviews } from "@app/queries/reviews"; +import { useDeleteReviewMutation } from "@app/queries/reviews"; import { useFetchIdentities } from "@app/queries/identities"; import { useFetchTagsWithTagItems } from "@app/queries/tags"; @@ -117,7 +117,6 @@ export const ApplicationsTable: React.FC = () => { const { pushNotification } = React.useContext(NotificationsContext); const { identities } = useFetchIdentities(); - const { reviews, isFetching: isFetchingReviews } = useFetchReviews(); const [saveApplicationModalState, setSaveApplicationModalState] = React.useState<"create" | Application | null>(null); @@ -1080,7 +1079,6 @@ export const ApplicationsTable: React.FC = () => { applications={applications} assessments={assessments} archetypes={archetypes} - reviews={reviews} onCloseClick={clearActiveItem} onEditClick={() => setSaveApplicationModalState(activeItem)} task={activeItem ? getTask(activeItem) : null} 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 d32f14fad8..5634ad0854 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 @@ -1,6 +1,7 @@ import * as React from "react"; import { Link } from "react-router-dom"; import { useTranslation } from "react-i18next"; + import { TextContent, Text, @@ -24,6 +25,9 @@ import { LabelGroup, } from "@patternfly/react-core"; import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing"; +import CheckCircleIcon from "@patternfly/react-icons/dist/esm/icons/check-circle-icon"; +import ExclamationCircleIcon from "@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon"; + import { Application, Identity, @@ -32,33 +36,32 @@ import { Ref, Archetype, AssessmentWithSectionOrder, - Review, } from "@app/api/models"; -import { - IPageDrawerContentProps, - PageDrawerContent, -} from "@app/components/PageDrawerContext"; +import { COLOR_HEX_VALUES_BY_NAME } from "@app/Constants"; +import { useFetchFacts } from "@app/queries/facts"; +import { useFetchIdentities } from "@app/queries/identities"; +import { useSetting } from "@app/queries/settings"; +import { getKindIdByRef } from "@app/utils/model-utils"; + import { getDependenciesUrlFilteredByAppName, getIssuesSingleAppSelectedLocation, } from "@app/pages/issues/helpers"; -import { ApplicationTags } from "../application-tags"; -import { COLOR_HEX_VALUES_BY_NAME } from "@app/Constants"; +import { + IPageDrawerContentProps, + PageDrawerContent, +} from "@app/components/PageDrawerContext"; import { EmptyTextMessage } from "@app/components/EmptyTextMessage"; import { SimpleDocumentViewerModal } from "@app/components/SimpleDocumentViewer"; -import { useFetchFacts } from "@app/queries/facts"; -import { useFetchIdentities } from "@app/queries/identities"; -import { useSetting } from "@app/queries/settings"; -import { getKindIdByRef } from "@app/utils/model-utils"; -import DownloadButton from "./components/download-button"; -import CheckCircleIcon from "@patternfly/react-icons/dist/esm/icons/check-circle-icon"; -import ExclamationCircleIcon from "@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon"; -import { ApplicationFacts } from "./application-facts"; -import { ReviewFields } from "./review-fields"; import { LabelsFromItems } from "@app/components/labels/labels-from-items/labels-from-items"; import { RiskLabel } from "@app/components/RiskLabel"; -import { ApplicationDetailFields } from "./application-detail-fields"; +import { ReviewFields } from "@app/components/detail-drawer/review-fields"; + +import { ApplicationTags } from "../application-tags"; import { AssessedArchetypes } from "./components/assessed-archetypes"; +import DownloadButton from "./components/download-button"; +import { ApplicationDetailFields } from "./application-detail-fields"; +import { ApplicationFacts } from "./application-facts"; export interface IApplicationDetailDrawerProps extends Pick { @@ -66,7 +69,6 @@ export interface IApplicationDetailDrawerProps task: Task | undefined | null; applications?: Application[]; assessments?: AssessmentWithSectionOrder[]; - reviews?: Review[]; archetypes?: Archetype[]; onEditClick: () => void; } @@ -85,7 +87,6 @@ export const ApplicationDetailDrawer: React.FC< onCloseClick, application, assessments, - reviews, archetypes, task, onEditClick, @@ -455,7 +456,7 @@ export const ApplicationDetailDrawer: React.FC< eventKey={TabKey.Reviews} title={{t("terms.review")}} > - + 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 d6f2f80832..0965f74ec2 100644 --- a/client/src/app/pages/archetypes/components/archetype-detail-drawer.tsx +++ b/client/src/app/pages/archetypes/components/archetype-detail-drawer.tsx @@ -1,6 +1,7 @@ import "./archetype-detail-drawer.css"; import React, { useMemo } from "react"; import { useTranslation } from "react-i18next"; +import { Link } from "react-router-dom"; import { TextContent, @@ -17,19 +18,17 @@ import { TabTitleText, } from "@patternfly/react-core"; import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing"; - +import { dedupeArrayOfObjects } from "@app/utils/utils"; +import { Paths } from "@app/Paths"; +import { serializeFilterUrlParams } from "@app/hooks/table-controls"; import { Archetype, Ref, Review, Tag, TagRef } from "@app/api/models"; + import { EmptyTextMessage } from "@app/components/EmptyTextMessage"; import { PageDrawerContent } from "@app/components/PageDrawerContext"; - -import { dedupeArrayOfObjects } from "@app/utils/utils"; -import { LabelsFromItems } from "@app/components/labels/labels-from-items/labels-from-items"; -import { ReviewFields } from "@app/pages/applications/components/application-detail-drawer/review-fields"; +import { ReviewFields } from "@app/components/detail-drawer/review-fields"; import { RiskLabel } from "@app/components/RiskLabel"; +import { LabelsFromItems } from "@app/components/labels/labels-from-items/labels-from-items"; 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; From 26955b1912703ff2bba6876d45afc260a55cdda3 Mon Sep 17 00:00:00 2001 From: Maayan Hadasi <60384172+mguetta1@users.noreply.github.com> Date: Tue, 12 Mar 2024 00:27:16 +0200 Subject: [PATCH 41/53] :bug: Changed column name to 'Total Effort' (#1687) Resolves: https://issues.redhat.com/browse/MTA-1970 Signed-off-by: Maayan Hadasi Co-authored-by: Ian Bolton Co-authored-by: Scott Dickerson --- .../issues/affected-applications/affected-applications.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/app/pages/issues/affected-applications/affected-applications.tsx b/client/src/app/pages/issues/affected-applications/affected-applications.tsx index e26c6f63a4..deebaaa4fb 100644 --- a/client/src/app/pages/issues/affected-applications/affected-applications.tsx +++ b/client/src/app/pages/issues/affected-applications/affected-applications.tsx @@ -59,7 +59,7 @@ export const AffectedApplications: React.FC = () => { name: "Name", description: "Description", businessService: "Business service", - effort: "Effort", + effort: "Total Effort", incidents: "Incidents", }, isFilterEnabled: true, From c2ef03c0293eac23d3e38e29caaf28a83de943a4 Mon Sep 17 00:00:00 2001 From: David Zager Date: Tue, 12 Mar 2024 09:38:20 -0400 Subject: [PATCH 42/53] :seedling: use gh app for cherry pick (#1759) Signed-off-by: David Zager Co-authored-by: Ian Bolton --- .github/workflows/pr-closed.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr-closed.yaml b/.github/workflows/pr-closed.yaml index 41afa19e6c..f200e88927 100644 --- a/.github/workflows/pr-closed.yaml +++ b/.github/workflows/pr-closed.yaml @@ -13,4 +13,5 @@ jobs: pull-requests: write contents: write if: github.event.pull_request.merged == true + secrets: inherit uses: konveyor/release-tools/.github/workflows/cherry-pick.yml@main From 63f85013f8687edfab6c5679387a4725914ab715 Mon Sep 17 00:00:00 2001 From: Radoslaw Szwajkowski Date: Thu, 14 Mar 2024 21:00:34 +0100 Subject: [PATCH 43/53] :seedling: Use placeholder styling for 'No results' option (#1775) Resolves: #1773 Signed-off-by: Radoslaw Szwajkowski --- .../app/components/FilterToolbar/MultiselectFilterControl.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx b/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx index bbc0c0fce5..4662b656c1 100644 --- a/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx +++ b/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx @@ -238,7 +238,8 @@ export const MultiselectFilterControl = ({ newSelectOptions = [ { key: "no-results", - isDisabled: false, + isDisabled: true, + hasCheckbox: false, children: `No results found for "${inputValue}"`, value: "No results", }, From 36ca73894d94594e334385cdd01bd8f428c26ce8 Mon Sep 17 00:00:00 2001 From: Radoslaw Szwajkowski Date: Thu, 14 Mar 2024 21:53:47 +0100 Subject: [PATCH 44/53] :seedling: Use multi select filter for application names (#1771) Resolves: #1754 Signed-off-by: Radoslaw Szwajkowski Co-authored-by: Ian Bolton --- client/src/app/pages/issues/helpers.ts | 16 ++++++++++++++-- client/src/app/utils/utils.ts | 11 +++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/client/src/app/pages/issues/helpers.ts b/client/src/app/pages/issues/helpers.ts index a78958e5e8..9beb0aad7b 100644 --- a/client/src/app/pages/issues/helpers.ts +++ b/client/src/app/pages/issues/helpers.ts @@ -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. @@ -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", diff --git a/client/src/app/utils/utils.ts b/client/src/app/utils/utils.ts index 607dc0d1c3..0e57049095 100644 --- a/client/src/app/utils/utils.ts +++ b/client/src/app/utils/utils.ts @@ -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 }); From 161fba8feecc4ce1bb0412dc887de0cd91256ada Mon Sep 17 00:00:00 2001 From: Radoslaw Szwajkowski Date: Fri, 15 Mar 2024 14:09:44 +0100 Subject: [PATCH 45/53] :sparkles: Add assessment/review status to archetype table (#1755) Review states: 1. Completed - a review exists 2. NotStarted Assessment states: 1. Completed - all required assessments done (based on 'assessed' flag) 2. InProgress - some assessments done 3. NotStarted Resolves: https://github.com/konveyor/tackle2-ui/issues/1751 Signed-off-by: Radoslaw Szwajkowski Co-authored-by: Ian Bolton --- .../app/pages/archetypes/archetypes-page.tsx | 125 ++++++++++++------ 1 file changed, 85 insertions(+), 40 deletions(-) diff --git a/client/src/app/pages/archetypes/archetypes-page.tsx b/client/src/app/pages/archetypes/archetypes-page.tsx index 0f44e8f1ca..b11e247497 100644 --- a/client/src/app/pages/archetypes/archetypes-page.tsx +++ b/client/src/app/pages/archetypes/archetypes-page.tsx @@ -43,6 +43,8 @@ import { useLocalTableControls, } from "@app/hooks/table-controls"; import { + ARCHETYPES_QUERY_KEY, + ARCHETYPE_QUERY_KEY, useDeleteArchetypeMutation, useFetchArchetypes, } from "@app/queries/archetypes"; @@ -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(false); @@ -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) => { @@ -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"); @@ -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, @@ -380,6 +394,11 @@ const Archetypes: React.FC = () => { + + @@ -427,6 +446,32 @@ const Archetypes: React.FC = () => { + + + + + + {(archetypeWriteAccess || assessmentWriteAccess || From 94a04a39b5f1b8449a41b8e8edc6bce1e4773b6e Mon Sep 17 00:00:00 2001 From: Scott Dickerson Date: Mon, 18 Mar 2024 11:58:17 -0400 Subject: [PATCH 46/53] :seedling: Refactor CI github actions, Dockerfile (#1780) Refactoring: - Split CI, one for repo tests and one for global tests - Only enable global CI on main (with a note) - Global CI configured like the multiarch build to cancel in progress runs if a new run starts - Repo CI bump the version of action `codecov/codecov-action` based on runtime warnings - Add `--ignoreScripts` to the `npm clean-install` in the Dockerfile to avoid running unnecessary postinstall scripts with the build running directly after the install. Signed-off-by: Scott J Dickerson --- .github/workflows/ci-actions.yml | 78 -------------------------------- .github/workflows/ci-global.yml | 54 ++++++++++++++++++++++ .github/workflows/ci-repo.yml | 55 ++++++++++++++++++++++ Dockerfile | 2 +- 4 files changed, 110 insertions(+), 79 deletions(-) delete mode 100644 .github/workflows/ci-actions.yml create mode 100644 .github/workflows/ci-global.yml create mode 100644 .github/workflows/ci-repo.yml diff --git a/.github/workflows/ci-actions.yml b/.github/workflows/ci-actions.yml deleted file mode 100644 index eeed592731..0000000000 --- a/.github/workflows/ci-actions.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: CI - -on: - push: - branches: - - main - - "release-*" - pull_request: - branches: - - main - - "release-*" - -jobs: - unit-test: - runs-on: ubuntu-latest - strategy: - matrix: - # Note: This should match the node version(s) used in the base Dockerfile - node-version: [18.x] - - steps: - - uses: actions/checkout@v4 - - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - - name: Verify package-lock.json - run: ./scripts/verify_lock.mjs - - - name: Install - run: npm clean-install --ignore-scripts - - - name: Lint sources - run: npm run lint - - - name: Build - run: npm run build - - - name: Test - run: npm run test -- --coverage --watchAll=false - - - name: Upload to codecov (client) - uses: codecov/codecov-action@v3 - with: - flags: client - directory: ./*/coverage - - - name: Upload to codecov (server) - uses: codecov/codecov-action@v3 - with: - flags: server - directory: ./*/coverage - - build-and-upload-for-global-ci: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: save tackle2-ui image - run: | - docker build . -t quay.io/konveyor/tackle2-ui:latest - docker save -o /tmp/tackle2-ui.tar quay.io/konveyor/tackle2-ui:latest - - - name: Upload tackle2-ui image as artifact - uses: actions/upload-artifact@v3 - with: - name: tackle2-ui - path: /tmp/tackle2-ui.tar - retention-days: 1 - - test-integration: - needs: build-and-upload-for-global-ci - uses: konveyor/ci/.github/workflows/global-ci.yml@main - with: - component_name: tackle2-ui - run_api_tests: false diff --git a/.github/workflows/ci-global.yml b/.github/workflows/ci-global.yml new file mode 100644 index 0000000000..508f1a5f89 --- /dev/null +++ b/.github/workflows/ci-global.yml @@ -0,0 +1,54 @@ +name: CI (global konveyor CI) + +on: + push: + branches: + - "main" + pull_request: + branches: + - "main" + +### +# The global CI settings need to be adjusted for the `release-*`` branches such that: +# 1. The operator uses the correct `:release-*` images +# 2. The `*-tests_ref` use the correct branches +# +# on: +# push: +# branches: +# - 'main' +# - 'release-*' +# pull_request: +# branches: +# - 'main' +# - 'release-*' +## + +concurrency: + group: ci-global-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-and-upload-for-global-ci: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: save tackle2-ui image + run: | + docker build . -t quay.io/konveyor/tackle2-ui:latest + docker save -o /tmp/tackle2-ui.tar quay.io/konveyor/tackle2-ui:latest + + - name: Upload tackle2-ui image as artifact + uses: actions/upload-artifact@v3 + with: + name: tackle2-ui + path: /tmp/tackle2-ui.tar + retention-days: 1 + + run-global-ci: + needs: build-and-upload-for-global-ci + uses: konveyor/ci/.github/workflows/global-ci.yml@main + with: + component_name: tackle2-ui + run_api_tests: false diff --git a/.github/workflows/ci-repo.yml b/.github/workflows/ci-repo.yml new file mode 100644 index 0000000000..e06d93da75 --- /dev/null +++ b/.github/workflows/ci-repo.yml @@ -0,0 +1,55 @@ +name: CI (repo level) + +on: + push: + branches: + - "main" + - "release-*" + pull_request: + branches: + - "main" + - "release-*" + +env: + # Note: This should match the node version(s) used in the base Dockerfile + node-version: "18" + +jobs: + unit-test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Use Node.js (version "${{ env.node-version }}") + uses: actions/setup-node@v4 + with: + node-version: ${{ env.node-version }} + cache: "npm" + + - name: Verify package-lock.json + run: ./scripts/verify_lock.mjs + + - name: Install + run: npm clean-install --ignore-scripts + + - name: Lint sources + run: npm run lint + + - name: Build + run: npm run build + + - name: Test + run: npm run test -- --coverage --watchAll=false + + - name: Upload to codecov (client) + uses: codecov/codecov-action@v4 + with: + flags: client + directory: ./*/coverage + + - name: Upload to codecov (server) + uses: codecov/codecov-action@v4 + with: + flags: server + directory: ./*/coverage diff --git a/Dockerfile b/Dockerfile index 9cc6be7c9a..17edb1680c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ FROM registry.access.redhat.com/ubi9/nodejs-18:latest as builder USER 1001 COPY --chown=1001 . . -RUN npm clean-install && npm run build && npm run dist +RUN npm clean-install --ignore-scripts && npm run build && npm run dist # Runner image FROM registry.access.redhat.com/ubi9/nodejs-18-minimal:latest From 984fbca215484d5b16bd5f0b9c6554f37baba369 Mon Sep 17 00:00:00 2001 From: Maayan Hadasi <60384172+mguetta1@users.noreply.github.com> Date: Tue, 19 Mar 2024 17:37:04 +0200 Subject: [PATCH 47/53] :bug: sso-actions-toggle: Adding onBlur event (#1766) Resolves: https://issues.redhat.com/browse/MTA-1578 Signed-off-by: Maayan Hadasi Co-authored-by: Scott Dickerson --- client/src/app/layout/HeaderApp/SSOMenu.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/app/layout/HeaderApp/SSOMenu.tsx b/client/src/app/layout/HeaderApp/SSOMenu.tsx index 1279947f9b..7630154c5b 100644 --- a/client/src/app/layout/HeaderApp/SSOMenu.tsx +++ b/client/src/app/layout/HeaderApp/SSOMenu.tsx @@ -44,6 +44,7 @@ export const SSOMenu: React.FC = () => { ref={toggleRef} id="sso-actions-toggle" onClick={() => onDropdownToggle(!isDropdownOpen)} + onBlur={() => onDropdownToggle(false)} > {(keycloak?.idTokenParsed as any)?.["preferred_username"] ?? "DefaultUsername"} From ca0b8a477a885d1e3ebd17476ceca7bf99722bdf Mon Sep 17 00:00:00 2001 From: Scott J Dickerson Date: Thu, 8 Feb 2024 17:56:39 -0500 Subject: [PATCH 48/53] :seedling: Upgrade to Patternfly 5.2 Update to the 5.2 release of the patternfly libraries. See release notes https://www.patternfly.org/get-started/release-highlights/#patternfly-5.2 Signed-off-by: Scott J Dickerson --- client/package.json | 16 +- .../__snapshots__/HeaderApp.test.tsx.snap | 16 - package-lock.json | 498 ++++++++---------- 3 files changed, 234 insertions(+), 296 deletions(-) diff --git a/client/package.json b/client/package.json index 787060b79c..92ea7241c2 100644 --- a/client/package.json +++ b/client/package.json @@ -25,13 +25,13 @@ "@hookform/resolvers": "^2.9.11", "@hot-loader/react-dom": "^17.0.2", "@migtools/lib-ui": "^10.0.1", - "@patternfly/patternfly": "^5.0.2", - "@patternfly/react-charts": "^7.1.0", - "@patternfly/react-code-editor": "^5.1.0", - "@patternfly/react-core": "^5.1.0", - "@patternfly/react-table": "^5.1.0", - "@patternfly/react-tokens": "^5.1.0", - "@react-keycloak/web": "^3.4.0", + "@patternfly/patternfly": "^5.2.0", + "@patternfly/react-charts": "^7.2.0", + "@patternfly/react-code-editor": "^5.2.0", + "@patternfly/react-core": "^5.2.0", + "@patternfly/react-table": "^5.2.0", + "@patternfly/react-tokens": "^5.2.0", + "@react-keycloak/web": "3.4.0", "@tanstack/react-query": "^4.22.0", "@tanstack/react-query-devtools": "^4.22.0", "axios": "^0.21.2", @@ -49,10 +49,8 @@ "react-i18next": "^11.8.5", "react-markdown": "^8.0.7", "react-measure": "^2.5.2", - "react-monaco-editor": "0.51.0", "react-router-dom": "^5.2.0", "tinycolor2": "^1.6.0", - "typesafe-actions": "^5.1.0", "web-vitals": "^0.2.4", "xmllint": "^0.1.1", "yaml": "^1.10.2", diff --git a/client/src/app/layout/HeaderApp/tests/__snapshots__/HeaderApp.test.tsx.snap b/client/src/app/layout/HeaderApp/tests/__snapshots__/HeaderApp.test.tsx.snap index 8517bcbd8c..364f5996ac 100644 --- a/client/src/app/layout/HeaderApp/tests/__snapshots__/HeaderApp.test.tsx.snap +++ b/client/src/app/layout/HeaderApp/tests/__snapshots__/HeaderApp.test.tsx.snap @@ -106,14 +106,6 @@ exports[`Test snapshot 1`] = ` -
-
-
-
-
-
= 0.21.0 < 1" + } + }, + "node_modules/@monaco-editor/react": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz", + "integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==", + "dependencies": { + "@monaco-editor/loader": "^1.4.0" + }, + "peerDependencies": { + "monaco-editor": ">= 0.25.0 < 1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/@mswjs/cookies": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-0.2.2.tgz", @@ -1641,37 +1663,37 @@ "dev": true }, "node_modules/@patternfly/patternfly": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-5.0.4.tgz", - "integrity": "sha512-8akdWzFpG384Q6Es8lzkfuhAlzVGrNK7TJqXGecHDAg8u1JsYn3+Nw6gLRviI88z8Kjxmg5YKirILjpclGxkIA==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-5.2.0.tgz", + "integrity": "sha512-phdsXcCRO+JICFXIKtORxSbOWoBr9zRCgtFTKTJ8hAIzm6wEUCdcHZrvsd+SXNR3q/4b/+KlmHUC4Q4KGUiuYw==" }, "node_modules/@patternfly/react-charts": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-charts/-/react-charts-7.1.0.tgz", - "integrity": "sha512-ROBRs/MuDHNTSe6pWhPYbNbMdjbNmShCVpYBDGQJMNLb0ojy8dZoiyp9/UoyEPRxZnt3vqAkjPSSCpGxXsjEgg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@patternfly/react-charts/-/react-charts-7.2.0.tgz", + "integrity": "sha512-IDg5KfF4VK/4C8qXfnFz9Tsq041RFJlHOGAH5Blb2ZTzTXp7ssZtuPxZvqqKxnIfAoMO+sy9DM8+vgvYPeH0aw==", "dependencies": { - "@patternfly/react-styles": "^5.1.0", - "@patternfly/react-tokens": "^5.1.0", + "@patternfly/react-styles": "^5.2.0", + "@patternfly/react-tokens": "^5.2.0", "hoist-non-react-statics": "^3.3.0", - "lodash": "^4.17.19", + "lodash": "^4.17.21", "tslib": "^2.5.0", - "victory-area": "^36.6.11", - "victory-axis": "^36.6.11", - "victory-bar": "^36.6.11", - "victory-box-plot": "^36.6.11", - "victory-chart": "^36.6.11", - "victory-core": "^36.6.11", - "victory-create-container": "^36.6.11", - "victory-cursor-container": "^36.6.11", - "victory-group": "^36.6.11", - "victory-legend": "^36.6.11", - "victory-line": "^36.6.11", - "victory-pie": "^36.6.11", - "victory-scatter": "^36.6.11", - "victory-stack": "^36.6.11", - "victory-tooltip": "^36.6.11", - "victory-voronoi-container": "^36.6.11", - "victory-zoom-container": "^36.6.11" + "victory-area": "^36.8.1", + "victory-axis": "^36.8.1", + "victory-bar": "^36.8.1", + "victory-box-plot": "^36.8.1", + "victory-chart": "^36.8.1", + "victory-core": "^36.8.1", + "victory-create-container": "^36.8.1", + "victory-cursor-container": "^36.8.1", + "victory-group": "^36.8.1", + "victory-legend": "^36.8.1", + "victory-line": "^36.8.1", + "victory-pie": "^36.8.1", + "victory-scatter": "^36.8.1", + "victory-stack": "^36.8.1", + "victory-tooltip": "^36.8.1", + "victory-voronoi-container": "^36.8.1", + "victory-zoom-container": "^36.8.1" }, "peerDependencies": { "react": "^17 || ^18", @@ -1679,32 +1701,31 @@ } }, "node_modules/@patternfly/react-code-editor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-code-editor/-/react-code-editor-5.1.0.tgz", - "integrity": "sha512-8Jn2yrfJ2ti04yuxi9ED++ZC2u8HVLlQvc7gZFKLWNwZO7KK2GK3O9GcmnlqcztIiOKKML1/YIFq+3Hz4tM89A==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@patternfly/react-code-editor/-/react-code-editor-5.2.0.tgz", + "integrity": "sha512-+VDGxNPJvKq3zDvCWZZYHx6wzle1yZ0WILQMZ9+HZyxzmjJmFJWv39VEwicDGrbPg8k+JfSwCL/PC6DAwx9pDA==", "dependencies": { - "@patternfly/react-core": "^5.1.0", - "@patternfly/react-icons": "^5.1.0", - "@patternfly/react-styles": "^5.1.0", + "@monaco-editor/react": "^4.6.0", + "@patternfly/react-core": "^5.2.0", + "@patternfly/react-icons": "^5.2.0", + "@patternfly/react-styles": "^5.2.0", "react-dropzone": "14.2.3", "tslib": "^2.5.0" }, "peerDependencies": { "react": "^17 || ^18", - "react-dom": "^17 || ^18", - "react-monaco-editor": "^0.51.0" + "react-dom": "^17 || ^18" } }, "node_modules/@patternfly/react-core": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-5.1.0.tgz", - "integrity": "sha512-m6MtCQsWiyGM40L4oLc2aEFlxT8egdoz/58Q2oW1fMkqUaosuNUiwy9/e8zOM3SLOPOo/Qo9cetQkIHVQppCvw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-5.2.0.tgz", + "integrity": "sha512-AUd7jccCgE2ZRwVtpEbJNF2Sq1A//ZhRaEQ/QHZiiq8mQRQM0Bkpnx0HdefToZT+TgUIjmPW4AXO3ooRJmt26w==", "dependencies": { - "@patternfly/patternfly": "5.0.2", - "@patternfly/react-icons": "^5.1.0", - "@patternfly/react-styles": "^5.1.0", - "@patternfly/react-tokens": "^5.1.0", - "focus-trap": "7.4.3", + "@patternfly/react-icons": "^5.2.0", + "@patternfly/react-styles": "^5.2.0", + "@patternfly/react-tokens": "^5.2.0", + "focus-trap": "7.5.2", "react-dropzone": "^14.2.3", "tslib": "^2.5.0" }, @@ -1713,50 +1734,29 @@ "react-dom": "^17 || ^18" } }, - "node_modules/@patternfly/react-core/node_modules/@patternfly/patternfly": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-5.0.2.tgz", - "integrity": "sha512-PB8+MLdYVgF1hIOxGmnVsZG+YHUX3RePe5W1oMS4gS00EmSgw1cobr1Qbpy/BqqS8/R9DRN4hZ2FKDT0d5tkFQ==" - }, "node_modules/@patternfly/react-icons": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-5.1.0.tgz", - "integrity": "sha512-mSFAJMrT6QUQ10DifYYGSXOPlFob88lWPZXeOyPdstJ8cJRRRVTMYgoR/VnXsUO/vthwFbViY+sS6+/jL8pl9w==", - "dependencies": { - "@patternfly/patternfly": "5.0.2" - }, + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-5.2.0.tgz", + "integrity": "sha512-vklAF2unvtK0trwx9Kk8nf4Xa2+nie4zxaIaQdnjIL7kX6a5SdsewDjlavOC3cRxnibZLQ5HQtpDZ4EmuXm8DQ==", "peerDependencies": { "react": "^17 || ^18", "react-dom": "^17 || ^18" } }, - "node_modules/@patternfly/react-icons/node_modules/@patternfly/patternfly": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-5.0.2.tgz", - "integrity": "sha512-PB8+MLdYVgF1hIOxGmnVsZG+YHUX3RePe5W1oMS4gS00EmSgw1cobr1Qbpy/BqqS8/R9DRN4hZ2FKDT0d5tkFQ==" - }, "node_modules/@patternfly/react-styles": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-5.1.0.tgz", - "integrity": "sha512-RnVS/v1PZuvnXXmPtJamuAprq1lg6tqw6dbeYbm9KmBNXSuB1Iu5fc6kjzrdoSLKBmf6rzpRmafYm2HRwFcrLw==", - "dependencies": { - "@patternfly/patternfly": "5.0.2" - } - }, - "node_modules/@patternfly/react-styles/node_modules/@patternfly/patternfly": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-5.0.2.tgz", - "integrity": "sha512-PB8+MLdYVgF1hIOxGmnVsZG+YHUX3RePe5W1oMS4gS00EmSgw1cobr1Qbpy/BqqS8/R9DRN4hZ2FKDT0d5tkFQ==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-5.2.0.tgz", + "integrity": "sha512-u8in9RSU8YzcT0npgVeiIHi1Bdp7UdER9azWGi7vlJWooRI1hgQjIDpm22wopGFg0h8VOqhfIFWIyvqxuzhW6A==" }, "node_modules/@patternfly/react-table": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-5.1.0.tgz", - "integrity": "sha512-lVMHx/VEcRNcthMPY9710GUaWcERQBZZRg6+PU/u6Ap0h3I5paFwkf7kTN692hUkqzUgCeWjH5mw1qFLD9Chwg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-5.2.0.tgz", + "integrity": "sha512-Pd+llSuAU9i1dvteQL1keEXmsQv6d8x4+F2arqGQS1umeOR3lvvycyFac1OboJ4oV2rAX97GVmtZdoJjaqxdhg==", "dependencies": { - "@patternfly/react-core": "^5.1.0", - "@patternfly/react-icons": "^5.1.0", - "@patternfly/react-styles": "^5.1.0", - "@patternfly/react-tokens": "^5.1.0", + "@patternfly/react-core": "^5.2.0", + "@patternfly/react-icons": "^5.2.0", + "@patternfly/react-styles": "^5.2.0", + "@patternfly/react-tokens": "^5.2.0", "lodash": "^4.17.19", "tslib": "^2.5.0" }, @@ -1766,17 +1766,9 @@ } }, "node_modules/@patternfly/react-tokens": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-5.1.0.tgz", - "integrity": "sha512-HRBoS3JMbW8vWqz91oW2NGUdLndC40TXvMnEaORNd/I25czOquxnx/HxVh+/bdSkNqByj6+fiTwH2X3fL2Cajg==", - "dependencies": { - "@patternfly/patternfly": "5.0.2" - } - }, - "node_modules/@patternfly/react-tokens/node_modules/@patternfly/patternfly": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-5.0.2.tgz", - "integrity": "sha512-PB8+MLdYVgF1hIOxGmnVsZG+YHUX3RePe5W1oMS4gS00EmSgw1cobr1Qbpy/BqqS8/R9DRN4hZ2FKDT0d5tkFQ==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-5.2.0.tgz", + "integrity": "sha512-ZsrLpStHJQfvUJLIXT+cObJbA3jM4r9iWwULLva0s7DzznXJ6iIACQQfgwDtcSVyM95z5S1a/LHPj/wYgaqUIg==" }, "node_modules/@pkgr/utils": { "version": "2.4.2", @@ -2466,58 +2458,58 @@ "dev": true }, "node_modules/@types/d3-array": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.7.tgz", - "integrity": "sha512-4/Q0FckQ8TBjsB0VdGFemJOG8BLXUB2KKlL0VmZ+eOYeOnTb/wDRQqYWpBmQ6IlvWkXwkYiot+n9Px2aTJ7zGQ==" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==" }, "node_modules/@types/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" }, "node_modules/@types/d3-ease": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.0.tgz", - "integrity": "sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==" }, "node_modules/@types/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", "dependencies": { "@types/d3-color": "*" } }, "node_modules/@types/d3-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.0.0.tgz", - "integrity": "sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" }, "node_modules/@types/d3-scale": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.4.tgz", - "integrity": "sha512-eq1ZeTj0yr72L8MQk6N6heP603ubnywSDRfNpi5enouR112HzGLS6RIvExCzZTraFF4HdzNpJMwA/zGiMoHUUw==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", "dependencies": { "@types/d3-time": "*" } }, "node_modules/@types/d3-shape": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.2.tgz", - "integrity": "sha512-NN4CXr3qeOUNyK5WasVUV8NCSAx/CRVcwcb0BuuS1PiTqwIm6ABi1SyasLZ/vsVCFDArF+W4QiGzSry1eKYQ7w==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", + "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", "dependencies": { "@types/d3-path": "*" } }, "node_modules/@types/d3-time": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.0.tgz", - "integrity": "sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" }, "node_modules/@types/d3-timer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.0.tgz", - "integrity": "sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" }, "node_modules/@types/debug": { "version": "4.1.8", @@ -7582,11 +7574,11 @@ "dev": true }, "node_modules/focus-trap": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.4.3.tgz", - "integrity": "sha512-BgSSbK4GPnS2VbtZ50VtOv1Sti6DIkj3+LkVjiWMNjLeAp1SH1UlLx3ULu/DCu4vq5R4/uvTm+zrvsMsuYmGLg==", + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.2.tgz", + "integrity": "sha512-p6vGNNWLDGwJCiEjkSK6oERj/hEyI9ITsSwIUICBoKLlWiTWXJRfQibCwcoi50rTZdbi87qDtUlMCmQwsGSgPw==", "dependencies": { - "tabbable": "^6.1.2" + "tabbable": "^6.2.0" } }, "node_modules/follow-redirects": { @@ -13715,19 +13707,6 @@ "react-dom": ">0.13.0" } }, - "node_modules/react-monaco-editor": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/react-monaco-editor/-/react-monaco-editor-0.51.0.tgz", - "integrity": "sha512-6jx1V8p6gHVKJHFaTvicOtmlhFjOJhekobeNd92ZAo7F5UvAin1cF7bxWLCKgtxClYZ7CB3Ar284Kpbhj22FpQ==", - "dependencies": { - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "@types/react": ">=17 <= 18", - "monaco-editor": "^0.34.1", - "react": ">=17 <= 18" - } - }, "node_modules/react-refresh": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", @@ -15113,6 +15092,11 @@ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", "dev": true }, + "node_modules/state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==" + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -16133,14 +16117,6 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "dev": true }, - "node_modules/typesafe-actions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/typesafe-actions/-/typesafe-actions-5.1.0.tgz", - "integrity": "sha512-bna6Yi1pRznoo6Bz1cE6btB/Yy8Xywytyfrzu/wc+NFW3ZF0I+2iCGImhBsoYYCOWuICtRO4yHcnDlzgo1AdNg==", - "engines": { - "node": ">= 4" - } - }, "node_modules/typescript": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", @@ -16511,277 +16487,259 @@ } }, "node_modules/victory-area": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-area/-/victory-area-36.6.11.tgz", - "integrity": "sha512-M/wQ0ryms6WpqGzpv+BMNfCLy0dlOtIxAuYgXJYwwDu55noAMbWlFahIzfllpjTmFOyCpCXF7EDraC3n2xRRFQ==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-area/-/victory-area-36.9.1.tgz", + "integrity": "sha512-rElzHXJBXZ6sFkYs10aFUoUikFI48XZLbFIfL1tzdA74T426fTRQZNlKvjb2s3XL4fcecqVpvlg1I2dkaAszIQ==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", - "victory-core": "^36.6.11", - "victory-vendor": "^36.6.11" + "victory-core": "^36.9.1", + "victory-vendor": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-axis": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-axis/-/victory-axis-36.6.11.tgz", - "integrity": "sha512-f2PUbEsE5wYXKRrgSYdoPRV6QXKNrZjTcd8YlymVGWsouJEFRZFOig8N3yU5lM7OuP98tOdurk4I91Py6NlXrA==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-axis/-/victory-axis-36.9.1.tgz", + "integrity": "sha512-s23wAFlE2KFSb6pRlmY4GXL7ZC2poL7jfUJbVWovBDkIUiz5G020ba2+RfMBL4tBTK006OPzQ3GeUPASG7qejA==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", - "victory-core": "^36.6.11" + "victory-core": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-bar": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-bar/-/victory-bar-36.6.11.tgz", - "integrity": "sha512-ANXZIYiDcvC1k3fvGbE8qHOi0POGOsYbzTgP/SBHXh9VQYa/NaYGZT3RO1mxp8wgpwaF+NZYZNC8mMO1pvcB2w==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-bar/-/victory-bar-36.9.1.tgz", + "integrity": "sha512-XCPKgeSBFItux1dBFpTZD90uqMw0wgd4+xD+sRgagVthTdppS3JV4YPNo1MxC/Gdm6XQfBFckcFpNG1qm3Noqw==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", - "victory-core": "^36.6.11", - "victory-vendor": "^36.6.11" + "victory-core": "^36.9.1", + "victory-vendor": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-box-plot": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-box-plot/-/victory-box-plot-36.6.11.tgz", - "integrity": "sha512-+J7Hb0Vf6cQe+qZyRhm6sM7V7AMS43jSTXnrFtRP7Bn+HdAb7p2S7h8abtgUhg3uVeTQa9UUqJBmC/maP8V3Nw==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-box-plot/-/victory-box-plot-36.9.1.tgz", + "integrity": "sha512-+dSHrA1naP5xEuVeIEoRadE8VL0+QmobJ6qwTxhZyjSwR9CGOelFZEgK4oVzWb7pfSa3dYUlXQRc+UWG02zFVw==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", - "victory-core": "^36.6.11", - "victory-vendor": "^36.6.11" + "victory-core": "^36.9.1", + "victory-vendor": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-brush-container": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-brush-container/-/victory-brush-container-36.6.11.tgz", - "integrity": "sha512-o0pPKzfQhKRlYNYUx3tHjuv9iTXqvgRtmu59L/h6l11DPaRo+jcHDBKEDRuoZxTinR/a1yqfLEJ1i9QgSE8o6w==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-brush-container/-/victory-brush-container-36.9.1.tgz", + "integrity": "sha512-XyLqCQ1LV1QbnWJh1ZlNxzk5Yp8PHqzGH6HLcnnKodZE8FBWTSREgELMQCrcT9NczI2GAA7XNkhGkZcJ4SuBMw==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", "react-fast-compare": "^3.2.0", - "victory-core": "^36.6.11" + "victory-core": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-chart": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-chart/-/victory-chart-36.6.11.tgz", - "integrity": "sha512-t4RIeLT6PJxZaDqNeawtIPxuA48k98kBvYbEV9XEPrS3TPAYsrB6lgXjZKLoItYLh63Ry4nqZAnPti4RD0uTfQ==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-chart/-/victory-chart-36.9.1.tgz", + "integrity": "sha512-i87Ok1vAeY9LirQt6T7B8tSr7d1vAuZvVv7f1MTTlRLHEAvifBNiGrhZho5ETzvTOXOAM7UjwqzPZze0Gk66cA==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", "react-fast-compare": "^3.2.0", - "victory-axis": "^36.6.11", - "victory-core": "^36.6.11", - "victory-polar-axis": "^36.6.11", - "victory-shared-events": "^36.6.11" + "victory-axis": "^36.9.1", + "victory-core": "^36.9.1", + "victory-polar-axis": "^36.9.1", + "victory-shared-events": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-core": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-core/-/victory-core-36.6.11.tgz", - "integrity": "sha512-aYhFIRu8NQMwW/JbgqoAG7w0lUYbTB1Achx4mmBc6aL8RMkv6LhD/PFwjT3TLpH0AoEs3Rpty2g0UQ+7ulE7dA==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-core/-/victory-core-36.9.1.tgz", + "integrity": "sha512-voPTyOyyVipzJPjelxvszVixiI98ApMNb6X9qfaFYK7fHyavF/Hy4sf/Hwq1otatLI7zpr2hC4wF+af6HDELqA==", "dependencies": { "lodash": "^4.17.21", - "prop-types": "^15.8.1", "react-fast-compare": "^3.2.0", - "victory-vendor": "^36.6.11" + "victory-vendor": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-create-container": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-create-container/-/victory-create-container-36.6.11.tgz", - "integrity": "sha512-Ve96DE9XDifmT2Bh/6Ptz7cgIV5DC2GYsr0Rl6I0sF6S02IH3V02NLpkcTthTRJHAvC9MkHwjiBlvFEZsXHOtg==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-create-container/-/victory-create-container-36.9.1.tgz", + "integrity": "sha512-L1c66whZAFnChVQdU2E0aYiTy3Wc1cM58V2vZPo1ORea/W9h3ojOW2bpYkG/XLf67PgnFZ299i23UzuC16Z5uw==", "dependencies": { "lodash": "^4.17.19", - "victory-brush-container": "^36.6.11", - "victory-core": "^36.6.11", - "victory-cursor-container": "^36.6.11", - "victory-selection-container": "^36.6.11", - "victory-voronoi-container": "^36.6.11", - "victory-zoom-container": "^36.6.11" + "victory-brush-container": "^36.9.1", + "victory-core": "^36.9.1", + "victory-cursor-container": "^36.9.1", + "victory-selection-container": "^36.9.1", + "victory-voronoi-container": "^36.9.1", + "victory-zoom-container": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-cursor-container": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-cursor-container/-/victory-cursor-container-36.6.11.tgz", - "integrity": "sha512-rdQAZb3RGYfijjqIQkuPGLNY5UOhuqyzlxQFaVtkpkDSZKiPMtbfLvR7F0Yfa9cs8OeQU0KAtAiK8R33o7su/Q==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-cursor-container/-/victory-cursor-container-36.9.1.tgz", + "integrity": "sha512-jAxlHbebVjIvmyUBf2AVbfk3rpQNyWPSVoozcBAzjDKhrUn5GIPvytg8QvFsShwdCtSob1eSyBEsGkb16F6xnw==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", - "victory-core": "^36.6.11" + "victory-core": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-group": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-group/-/victory-group-36.6.11.tgz", - "integrity": "sha512-PTRrH31gsGk3KFzeTzAkyvgjtilWYHWkx06oouh70KuAJ7f+9pRMrRMal8v+npH6a8Wp0KKW198AqpkPaZqHyQ==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-group/-/victory-group-36.9.1.tgz", + "integrity": "sha512-FJwZbrwMJSR/ucj4rYXKYJ+R6oDNsHPG2OvVs4KWkMSSp1Ld/0/V42qFqFNixcLAEcD5ACYtyigZOmS8VEnSnA==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", "react-fast-compare": "^3.2.0", - "victory-core": "^36.6.11", - "victory-shared-events": "^36.6.11" + "victory-core": "^36.9.1", + "victory-shared-events": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-legend": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-legend/-/victory-legend-36.6.11.tgz", - "integrity": "sha512-eL310Qh3WcZyjFI18hABVodwHpgZtokHD3r5HKpgZVY8MWkMD9mXErphWbkNHTVi5ya+I3QbRQ7ToRbPUl/Jog==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-legend/-/victory-legend-36.9.1.tgz", + "integrity": "sha512-NVWJzEJgm2+LH94b6aUQ96M58TzAgKP9wXlQC/CuYLMqK45RiLwg7pkSNuXBdtQiJgpD3W6d6klHQmUP2JkNzA==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", - "victory-core": "^36.6.11" + "victory-core": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-line": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-line/-/victory-line-36.6.11.tgz", - "integrity": "sha512-SDQCS6qDSixnYPB1kHEQsue06N6x2cxkIA6uqL45LRFMkKWG4OtwTBORVhtK6lfKzq1OvJs3msoZ+uoRIW1gaA==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-line/-/victory-line-36.9.1.tgz", + "integrity": "sha512-WfnDMI5mYN+7rC21yG3IXLIkGL+xNPAFDYikCwtKD9MnHUqk1k/HMGTH0BCVPgXagwIzd8aGpbJGlvcfRr1Kvg==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", - "victory-core": "^36.6.11", - "victory-vendor": "^36.6.11" + "victory-core": "^36.9.1", + "victory-vendor": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-pie": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-pie/-/victory-pie-36.6.11.tgz", - "integrity": "sha512-vQPAzrubo3BX/1pujSlKKTBGNSj/8fxUJ0vSZPZ6EE1y6SRnPJoLYi2OkDQVT1s3rM9xvW00SflCD3GO/Z3xWA==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-pie/-/victory-pie-36.9.1.tgz", + "integrity": "sha512-TjfGe1Wd8cWaV7Ldd2AgPstAT0qbxY8EHYj2YyB93qfZCwdLQqxEmDobl+T+BmnRtCodXUWdghkLvVggf4N0bQ==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", - "victory-core": "^36.6.11", - "victory-vendor": "^36.6.11" + "victory-core": "^36.9.1", + "victory-vendor": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-polar-axis": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-polar-axis/-/victory-polar-axis-36.6.11.tgz", - "integrity": "sha512-wDkyY1rKQTRUVt4+e0QNQgSIJCqXazNhkjWXla8ZWj52GzPP/QSDuzr8SO1oHA3++1jOpdD0R2FTxm+pAea/Yw==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-polar-axis/-/victory-polar-axis-36.9.1.tgz", + "integrity": "sha512-C7oPeRzG0Mn+Veu8qI1lVgiBMyZwdrvnplUi6AnFvYf9wURoFjyC+DQ7Eh5IH4TeVQz9rr9ksiliFtXPOHCwvg==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", - "victory-core": "^36.6.11" + "victory-core": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-scatter": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-scatter/-/victory-scatter-36.6.11.tgz", - "integrity": "sha512-x46AfmhiKijXe59kqm7xI0CCjbY8J0VB02HUN3TynMx7xzhW2yOP+QQqgyk+C4im/MS33HKU402Q7cUfF3pgtw==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-scatter/-/victory-scatter-36.9.1.tgz", + "integrity": "sha512-n5h/PUW2pHwiBJi0gLt5D5/jM3ZNXnFqZyjFkiKP6nztUtLRQfjcDMwmRWFOF/WZS/e2C7qMYizuXmxuU5ZVOw==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", - "victory-core": "^36.6.11" + "victory-core": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-selection-container": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-selection-container/-/victory-selection-container-36.6.11.tgz", - "integrity": "sha512-pRQz++0ERZVuIgxpmqLkDgf6hiCAS2m8iGcox8tryWzE1NpADG/IJiHh3AeJgGeiLNMeoJ48hsOZP1C9CCxwrQ==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-selection-container/-/victory-selection-container-36.9.1.tgz", + "integrity": "sha512-yugHpsS+JHmhJdhduuDHIBVg0mJ60Nge52CCHdiqM7hitcK1+hJgeEPt9zyCDYivQrBimRCGjNYfXhjjCbxzrg==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", - "victory-core": "^36.6.11" + "victory-core": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-shared-events": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-shared-events/-/victory-shared-events-36.6.11.tgz", - "integrity": "sha512-ia6ijfgfYMb+gGFPEq4F6rqzB9p5EkjKpjvmEv4Ww7VjrtdORu7PPfAgTxXw/9QgFSq4iOUnDtzjObABua09fQ==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-shared-events/-/victory-shared-events-36.9.1.tgz", + "integrity": "sha512-U+iDeuv17qYbigMivQcYmZPrvCMHQ8oHFprrlmF9K9cby3q9NFuZ6bbZUngm8kB61P0L6gR0BbYSWvdT9QUEbA==", "dependencies": { "json-stringify-safe": "^5.0.1", "lodash": "^4.17.19", - "prop-types": "^15.8.1", "react-fast-compare": "^3.2.0", - "victory-core": "^36.6.11" + "victory-core": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-stack": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-stack/-/victory-stack-36.6.11.tgz", - "integrity": "sha512-kE/915RdcKes69WpxZ5j6MyCIJqdzIZnzIg6OArBeDlD+LuinNb2oNxYpMXzur1KFSyk5PCUckHgEbR2XLoXrw==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-stack/-/victory-stack-36.9.1.tgz", + "integrity": "sha512-yTSLyq3PShJIIsHFjRZcWJvJsZU0+kZ6OhYawqnE133XkaQFdA6C4nhMGCAs6VzFT9PofzFuU0OY4geZ70G1TQ==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", "react-fast-compare": "^3.2.0", - "victory-core": "^36.6.11", - "victory-shared-events": "^36.6.11" + "victory-core": "^36.9.1", + "victory-shared-events": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-tooltip": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-tooltip/-/victory-tooltip-36.6.11.tgz", - "integrity": "sha512-YxAPkGAqTYOIW4aE5InGFABmYjiBfuQFjCe9hwFGvIC/Uqn202xgs5kYVEZXUX3vc9W8XOl7plaQJzmtr2ZZBQ==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-tooltip/-/victory-tooltip-36.9.1.tgz", + "integrity": "sha512-/ICZ4jaYFplSgK1HkFikEN9d4xlRm7dI7MouYTC1m74q869nMPycLJeVjUo9RsiPnUDeiJLAnKZnXb0oICyYsQ==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", - "victory-core": "^36.6.11" + "victory-core": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-vendor": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.6.11.tgz", - "integrity": "sha512-nT8kCiJp8dQh8g991J/R5w5eE2KnO8EAIP0xocWlh9l2okngMWglOPoMZzJvek8Q1KUc4XE/mJxTZnvOB1sTYg==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.1.tgz", + "integrity": "sha512-+pZIP+U3pEJdDCeFmsXwHzV7vNHQC/eIbHklfe2ZCZqayYRH7lQbHcVgsJ0XOOv27hWs4jH4MONgXxHMObTMSA==", "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", @@ -16800,29 +16758,27 @@ } }, "node_modules/victory-voronoi-container": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-voronoi-container/-/victory-voronoi-container-36.6.11.tgz", - "integrity": "sha512-KNB814e5uhs00oNFdkPucXMlpNILnWabHM7iKLBz26nlgqiu6dctZZoWU+HKjxbPkHdic6JQsg28Nk5bThaulw==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-voronoi-container/-/victory-voronoi-container-36.9.1.tgz", + "integrity": "sha512-F/ZWvhF/JkRxFT1UPGf4HgPnBAhUmbRIBssAvsIRer4cr3p7RieMNTMcTYHtVwR9kTKClfmJKgn1T7imBGt2BA==", "dependencies": { "delaunay-find": "0.0.6", "lodash": "^4.17.19", - "prop-types": "^15.8.1", "react-fast-compare": "^3.2.0", - "victory-core": "^36.6.11", - "victory-tooltip": "^36.6.11" + "victory-core": "^36.9.1", + "victory-tooltip": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" } }, "node_modules/victory-zoom-container": { - "version": "36.6.11", - "resolved": "https://registry.npmjs.org/victory-zoom-container/-/victory-zoom-container-36.6.11.tgz", - "integrity": "sha512-DRS12HZEmy5oJanlnSK9Wtp/6HQQbwvK0idVU+Lhf2lw3r9gauWp/ymWwWzaHd7Mn5cCODuNW1le2bqb71j3wg==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-zoom-container/-/victory-zoom-container-36.9.1.tgz", + "integrity": "sha512-2G+2iUsmTCpt1ItUWVOzK0CCRYCFf+/rH4uXuvXqipHjRnotz5bxOkuW68Fdx1MzGoexIc8DfQoKxKd/q0HkZA==", "dependencies": { "lodash": "^4.17.19", - "prop-types": "^15.8.1", - "victory-core": "^36.6.11" + "victory-core": "^36.9.1" }, "peerDependencies": { "react": ">=16.6.0" From 6ef12e25ef8ffcc8c95d68919f613a0d731b4966 Mon Sep 17 00:00:00 2001 From: Scott J Dickerson Date: Mon, 4 Mar 2024 14:07:20 -0500 Subject: [PATCH 49/53] Bump from 5.2.0 to 5.2.1 Signed-off-by: Scott J Dickerson --- client/package.json | 12 ++--- package-lock.json | 118 ++++++++++++++++++++++---------------------- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/client/package.json b/client/package.json index 92ea7241c2..80541a7249 100644 --- a/client/package.json +++ b/client/package.json @@ -25,12 +25,12 @@ "@hookform/resolvers": "^2.9.11", "@hot-loader/react-dom": "^17.0.2", "@migtools/lib-ui": "^10.0.1", - "@patternfly/patternfly": "^5.2.0", - "@patternfly/react-charts": "^7.2.0", - "@patternfly/react-code-editor": "^5.2.0", - "@patternfly/react-core": "^5.2.0", - "@patternfly/react-table": "^5.2.0", - "@patternfly/react-tokens": "^5.2.0", + "@patternfly/patternfly": "^5.2.1", + "@patternfly/react-charts": "^7.2.1", + "@patternfly/react-code-editor": "^5.2.1", + "@patternfly/react-core": "^5.2.1", + "@patternfly/react-table": "^5.2.1", + "@patternfly/react-tokens": "^5.2.1", "@react-keycloak/web": "3.4.0", "@tanstack/react-query": "^4.22.0", "@tanstack/react-query-devtools": "^4.22.0", diff --git a/package-lock.json b/package-lock.json index 5af0c18c31..e66c9d8d45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -64,12 +64,12 @@ "@hookform/resolvers": "^2.9.11", "@hot-loader/react-dom": "^17.0.2", "@migtools/lib-ui": "^10.0.1", - "@patternfly/patternfly": "^5.2.0", - "@patternfly/react-charts": "^7.2.0", - "@patternfly/react-code-editor": "^5.2.0", - "@patternfly/react-core": "^5.2.0", - "@patternfly/react-table": "^5.2.0", - "@patternfly/react-tokens": "^5.2.0", + "@patternfly/patternfly": "^5.2.1", + "@patternfly/react-charts": "^7.2.1", + "@patternfly/react-code-editor": "^5.2.1", + "@patternfly/react-core": "^5.2.1", + "@patternfly/react-table": "^5.2.1", + "@patternfly/react-tokens": "^5.2.1", "@react-keycloak/web": "3.4.0", "@tanstack/react-query": "^4.22.0", "@tanstack/react-query-devtools": "^4.22.0", @@ -1663,37 +1663,37 @@ "dev": true }, "node_modules/@patternfly/patternfly": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-5.2.0.tgz", - "integrity": "sha512-phdsXcCRO+JICFXIKtORxSbOWoBr9zRCgtFTKTJ8hAIzm6wEUCdcHZrvsd+SXNR3q/4b/+KlmHUC4Q4KGUiuYw==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-5.2.1.tgz", + "integrity": "sha512-n5xFjyj1J4eIFZ7XeU6K44POKRAuDlO5yALPbn084y+jPy1j861AaQ+zIUbzCi4IzBlHrvoXVKij7p1zy7Ditg==" }, "node_modules/@patternfly/react-charts": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-charts/-/react-charts-7.2.0.tgz", - "integrity": "sha512-IDg5KfF4VK/4C8qXfnFz9Tsq041RFJlHOGAH5Blb2ZTzTXp7ssZtuPxZvqqKxnIfAoMO+sy9DM8+vgvYPeH0aw==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@patternfly/react-charts/-/react-charts-7.2.1.tgz", + "integrity": "sha512-ln24zv08JF7tFWY/SXlV5vKInqBU/2o4DuPg5bVhy/V6X3BjPY1aUn/Yrwqw/9H0NTMZPdIpqVt8066zWHAu8g==", "dependencies": { - "@patternfly/react-styles": "^5.2.0", - "@patternfly/react-tokens": "^5.2.0", + "@patternfly/react-styles": "^5.2.1", + "@patternfly/react-tokens": "^5.2.1", "hoist-non-react-statics": "^3.3.0", "lodash": "^4.17.21", "tslib": "^2.5.0", - "victory-area": "^36.8.1", - "victory-axis": "^36.8.1", - "victory-bar": "^36.8.1", - "victory-box-plot": "^36.8.1", - "victory-chart": "^36.8.1", - "victory-core": "^36.8.1", - "victory-create-container": "^36.8.1", - "victory-cursor-container": "^36.8.1", - "victory-group": "^36.8.1", - "victory-legend": "^36.8.1", - "victory-line": "^36.8.1", - "victory-pie": "^36.8.1", - "victory-scatter": "^36.8.1", - "victory-stack": "^36.8.1", - "victory-tooltip": "^36.8.1", - "victory-voronoi-container": "^36.8.1", - "victory-zoom-container": "^36.8.1" + "victory-area": "^36.9.1", + "victory-axis": "^36.9.1", + "victory-bar": "^36.9.1", + "victory-box-plot": "^36.9.1", + "victory-chart": "^36.9.1", + "victory-core": "^36.9.1", + "victory-create-container": "^36.9.1", + "victory-cursor-container": "^36.9.1", + "victory-group": "^36.9.1", + "victory-legend": "^36.9.1", + "victory-line": "^36.9.1", + "victory-pie": "^36.9.1", + "victory-scatter": "^36.9.1", + "victory-stack": "^36.9.1", + "victory-tooltip": "^36.9.1", + "victory-voronoi-container": "^36.9.1", + "victory-zoom-container": "^36.9.1" }, "peerDependencies": { "react": "^17 || ^18", @@ -1701,14 +1701,14 @@ } }, "node_modules/@patternfly/react-code-editor": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-code-editor/-/react-code-editor-5.2.0.tgz", - "integrity": "sha512-+VDGxNPJvKq3zDvCWZZYHx6wzle1yZ0WILQMZ9+HZyxzmjJmFJWv39VEwicDGrbPg8k+JfSwCL/PC6DAwx9pDA==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@patternfly/react-code-editor/-/react-code-editor-5.2.1.tgz", + "integrity": "sha512-waehn8842z/yCqpN9ZEE4/RxTm3j5uFscGQ6eroC94fy6LbK+S2eiHfk1bXwTyWi0gd6FEU75S43zN4Vz9y+8A==", "dependencies": { "@monaco-editor/react": "^4.6.0", - "@patternfly/react-core": "^5.2.0", - "@patternfly/react-icons": "^5.2.0", - "@patternfly/react-styles": "^5.2.0", + "@patternfly/react-core": "^5.2.1", + "@patternfly/react-icons": "^5.2.1", + "@patternfly/react-styles": "^5.2.1", "react-dropzone": "14.2.3", "tslib": "^2.5.0" }, @@ -1718,13 +1718,13 @@ } }, "node_modules/@patternfly/react-core": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-5.2.0.tgz", - "integrity": "sha512-AUd7jccCgE2ZRwVtpEbJNF2Sq1A//ZhRaEQ/QHZiiq8mQRQM0Bkpnx0HdefToZT+TgUIjmPW4AXO3ooRJmt26w==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-5.2.1.tgz", + "integrity": "sha512-SWQHALhcjxjmwcIJ6V3tG6V7a2M0WkkUbc6F8mSPk6l9q6j3f+WvZ9HqgzVA+h+Q12UbtIrlQvgUx7pAxZekkg==", "dependencies": { - "@patternfly/react-icons": "^5.2.0", - "@patternfly/react-styles": "^5.2.0", - "@patternfly/react-tokens": "^5.2.0", + "@patternfly/react-icons": "^5.2.1", + "@patternfly/react-styles": "^5.2.1", + "@patternfly/react-tokens": "^5.2.1", "focus-trap": "7.5.2", "react-dropzone": "^14.2.3", "tslib": "^2.5.0" @@ -1735,28 +1735,28 @@ } }, "node_modules/@patternfly/react-icons": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-5.2.0.tgz", - "integrity": "sha512-vklAF2unvtK0trwx9Kk8nf4Xa2+nie4zxaIaQdnjIL7kX6a5SdsewDjlavOC3cRxnibZLQ5HQtpDZ4EmuXm8DQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-5.2.1.tgz", + "integrity": "sha512-aeJ0X+U2NDe8UmI5eQiT0iuR/wmUq97UkDtx3HoZcpRb9T6eUBfysllxjRqHS8rOOspdU8OWq+CUhQ/E2ZDibg==", "peerDependencies": { "react": "^17 || ^18", "react-dom": "^17 || ^18" } }, "node_modules/@patternfly/react-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-5.2.0.tgz", - "integrity": "sha512-u8in9RSU8YzcT0npgVeiIHi1Bdp7UdER9azWGi7vlJWooRI1hgQjIDpm22wopGFg0h8VOqhfIFWIyvqxuzhW6A==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-5.2.1.tgz", + "integrity": "sha512-GT96hzI1QenBhq6Pfc51kxnj9aVLjL1zSLukKZXcYVe0HPOy0BFm90bT1Fo4e/z7V9cDYw4SqSX1XLc3O4jsTw==" }, "node_modules/@patternfly/react-table": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-5.2.0.tgz", - "integrity": "sha512-Pd+llSuAU9i1dvteQL1keEXmsQv6d8x4+F2arqGQS1umeOR3lvvycyFac1OboJ4oV2rAX97GVmtZdoJjaqxdhg==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-5.2.1.tgz", + "integrity": "sha512-Kcuxhh8RjcHBwLMxdnhIAGsHKjh2t5OSC8BvRSaz2hlLCFqsQf73SALjs2w8IHHnzwSZ1fTBo4js2vPPjML3gg==", "dependencies": { - "@patternfly/react-core": "^5.2.0", - "@patternfly/react-icons": "^5.2.0", - "@patternfly/react-styles": "^5.2.0", - "@patternfly/react-tokens": "^5.2.0", + "@patternfly/react-core": "^5.2.1", + "@patternfly/react-icons": "^5.2.1", + "@patternfly/react-styles": "^5.2.1", + "@patternfly/react-tokens": "^5.2.1", "lodash": "^4.17.19", "tslib": "^2.5.0" }, @@ -1766,9 +1766,9 @@ } }, "node_modules/@patternfly/react-tokens": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-5.2.0.tgz", - "integrity": "sha512-ZsrLpStHJQfvUJLIXT+cObJbA3jM4r9iWwULLva0s7DzznXJ6iIACQQfgwDtcSVyM95z5S1a/LHPj/wYgaqUIg==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-5.2.1.tgz", + "integrity": "sha512-8GYz/jnJTGAWUJt5eRAW5dtyiHPKETeFJBPGHaUQnvi/t1ZAkoy8i4Kd/RlHsDC7ktiu813SKCmlzwBwldAHKg==" }, "node_modules/@pkgr/utils": { "version": "2.4.2", From 37f3f1929d83987e19a6e5e2a8d77f0f936de608 Mon Sep 17 00:00:00 2001 From: Scott J Dickerson Date: Wed, 6 Mar 2024 09:54:33 -0500 Subject: [PATCH 50/53] Bump @patternfly/react-charts to 7.2.2 Signed-off-by: Scott J Dickerson --- client/package.json | 2 +- package-lock.json | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/package.json b/client/package.json index 80541a7249..12df05b406 100644 --- a/client/package.json +++ b/client/package.json @@ -26,7 +26,7 @@ "@hot-loader/react-dom": "^17.0.2", "@migtools/lib-ui": "^10.0.1", "@patternfly/patternfly": "^5.2.1", - "@patternfly/react-charts": "^7.2.1", + "@patternfly/react-charts": "^7.2.2", "@patternfly/react-code-editor": "^5.2.1", "@patternfly/react-core": "^5.2.1", "@patternfly/react-table": "^5.2.1", diff --git a/package-lock.json b/package-lock.json index e66c9d8d45..215acf0025 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,7 +65,7 @@ "@hot-loader/react-dom": "^17.0.2", "@migtools/lib-ui": "^10.0.1", "@patternfly/patternfly": "^5.2.1", - "@patternfly/react-charts": "^7.2.1", + "@patternfly/react-charts": "^7.2.2", "@patternfly/react-code-editor": "^5.2.1", "@patternfly/react-core": "^5.2.1", "@patternfly/react-table": "^5.2.1", @@ -1668,9 +1668,9 @@ "integrity": "sha512-n5xFjyj1J4eIFZ7XeU6K44POKRAuDlO5yALPbn084y+jPy1j861AaQ+zIUbzCi4IzBlHrvoXVKij7p1zy7Ditg==" }, "node_modules/@patternfly/react-charts": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@patternfly/react-charts/-/react-charts-7.2.1.tgz", - "integrity": "sha512-ln24zv08JF7tFWY/SXlV5vKInqBU/2o4DuPg5bVhy/V6X3BjPY1aUn/Yrwqw/9H0NTMZPdIpqVt8066zWHAu8g==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@patternfly/react-charts/-/react-charts-7.2.2.tgz", + "integrity": "sha512-1PFuvXz3mm/o/O+BQ2/2e66ncvtV8XIYxFaimurslCLTygodOvjBDDu/D/5tNa3HLxvA+fm2Q58893POGZi+bw==", "dependencies": { "@patternfly/react-styles": "^5.2.1", "@patternfly/react-tokens": "^5.2.1", From 5fb8283e9297dd9137d076f597ad28ea9bed43af Mon Sep 17 00:00:00 2001 From: Scott J Dickerson Date: Wed, 13 Mar 2024 09:41:46 -0400 Subject: [PATCH 51/53] Bump packages to 5.2.2 Bumped: @patternfly/react-code-editor @patternfly/react-core @patternfly/react-table Signed-off-by: Scott J Dickerson --- client/package.json | 6 +++--- package-lock.json | 28 ++++++++++++++-------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/client/package.json b/client/package.json index 12df05b406..38f0553f57 100644 --- a/client/package.json +++ b/client/package.json @@ -27,9 +27,9 @@ "@migtools/lib-ui": "^10.0.1", "@patternfly/patternfly": "^5.2.1", "@patternfly/react-charts": "^7.2.2", - "@patternfly/react-code-editor": "^5.2.1", - "@patternfly/react-core": "^5.2.1", - "@patternfly/react-table": "^5.2.1", + "@patternfly/react-code-editor": "^5.2.2", + "@patternfly/react-core": "^5.2.2", + "@patternfly/react-table": "^5.2.2", "@patternfly/react-tokens": "^5.2.1", "@react-keycloak/web": "3.4.0", "@tanstack/react-query": "^4.22.0", diff --git a/package-lock.json b/package-lock.json index 215acf0025..9ace3ac0e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,9 +66,9 @@ "@migtools/lib-ui": "^10.0.1", "@patternfly/patternfly": "^5.2.1", "@patternfly/react-charts": "^7.2.2", - "@patternfly/react-code-editor": "^5.2.1", - "@patternfly/react-core": "^5.2.1", - "@patternfly/react-table": "^5.2.1", + "@patternfly/react-code-editor": "^5.2.2", + "@patternfly/react-core": "^5.2.2", + "@patternfly/react-table": "^5.2.2", "@patternfly/react-tokens": "^5.2.1", "@react-keycloak/web": "3.4.0", "@tanstack/react-query": "^4.22.0", @@ -1701,12 +1701,12 @@ } }, "node_modules/@patternfly/react-code-editor": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@patternfly/react-code-editor/-/react-code-editor-5.2.1.tgz", - "integrity": "sha512-waehn8842z/yCqpN9ZEE4/RxTm3j5uFscGQ6eroC94fy6LbK+S2eiHfk1bXwTyWi0gd6FEU75S43zN4Vz9y+8A==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@patternfly/react-code-editor/-/react-code-editor-5.2.2.tgz", + "integrity": "sha512-7ZRYkTuf9VN7brml5+HTWbXytMcYmYFPob2K+A5xHkaOP6LSEaH3c6/XXdXdFSktR183ssdi2aZdwOW47gHVSw==", "dependencies": { "@monaco-editor/react": "^4.6.0", - "@patternfly/react-core": "^5.2.1", + "@patternfly/react-core": "^5.2.2", "@patternfly/react-icons": "^5.2.1", "@patternfly/react-styles": "^5.2.1", "react-dropzone": "14.2.3", @@ -1718,9 +1718,9 @@ } }, "node_modules/@patternfly/react-core": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-5.2.1.tgz", - "integrity": "sha512-SWQHALhcjxjmwcIJ6V3tG6V7a2M0WkkUbc6F8mSPk6l9q6j3f+WvZ9HqgzVA+h+Q12UbtIrlQvgUx7pAxZekkg==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-5.2.2.tgz", + "integrity": "sha512-8dCERIVT+/ESRZ7w7UvFz3w96189W8zU+6mqbkWMG/kO6ay4o1pxIoktUT67BMMtHQNZCA+onO6+SYJrl93I0Q==", "dependencies": { "@patternfly/react-icons": "^5.2.1", "@patternfly/react-styles": "^5.2.1", @@ -1749,11 +1749,11 @@ "integrity": "sha512-GT96hzI1QenBhq6Pfc51kxnj9aVLjL1zSLukKZXcYVe0HPOy0BFm90bT1Fo4e/z7V9cDYw4SqSX1XLc3O4jsTw==" }, "node_modules/@patternfly/react-table": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-5.2.1.tgz", - "integrity": "sha512-Kcuxhh8RjcHBwLMxdnhIAGsHKjh2t5OSC8BvRSaz2hlLCFqsQf73SALjs2w8IHHnzwSZ1fTBo4js2vPPjML3gg==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-5.2.2.tgz", + "integrity": "sha512-Ah696FVch0lCoyslIigGgMg9ujsffXzURRaX7DYP1LyiKKVTe2ZnS9J2vSn/d/LuIEmTSsSOxbIeyzMZZEYOmg==", "dependencies": { - "@patternfly/react-core": "^5.2.1", + "@patternfly/react-core": "^5.2.2", "@patternfly/react-icons": "^5.2.1", "@patternfly/react-styles": "^5.2.1", "@patternfly/react-tokens": "^5.2.1", From 7f6363641affb4e22414c1c9f2bd4ee34a6a48c7 Mon Sep 17 00:00:00 2001 From: Scott J Dickerson Date: Tue, 19 Mar 2024 10:58:48 -0400 Subject: [PATCH 52/53] Bump to most current z-stream versions Signed-off-by: Scott J Dickerson --- client/package.json | 6 +++--- package-lock.json | 28 ++++++++++++++-------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/client/package.json b/client/package.json index 38f0553f57..dba03235a2 100644 --- a/client/package.json +++ b/client/package.json @@ -27,9 +27,9 @@ "@migtools/lib-ui": "^10.0.1", "@patternfly/patternfly": "^5.2.1", "@patternfly/react-charts": "^7.2.2", - "@patternfly/react-code-editor": "^5.2.2", - "@patternfly/react-core": "^5.2.2", - "@patternfly/react-table": "^5.2.2", + "@patternfly/react-code-editor": "^5.2.3", + "@patternfly/react-core": "^5.2.3", + "@patternfly/react-table": "^5.2.4", "@patternfly/react-tokens": "^5.2.1", "@react-keycloak/web": "3.4.0", "@tanstack/react-query": "^4.22.0", diff --git a/package-lock.json b/package-lock.json index 9ace3ac0e0..4b0263fbb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,9 +66,9 @@ "@migtools/lib-ui": "^10.0.1", "@patternfly/patternfly": "^5.2.1", "@patternfly/react-charts": "^7.2.2", - "@patternfly/react-code-editor": "^5.2.2", - "@patternfly/react-core": "^5.2.2", - "@patternfly/react-table": "^5.2.2", + "@patternfly/react-code-editor": "^5.2.3", + "@patternfly/react-core": "^5.2.3", + "@patternfly/react-table": "^5.2.4", "@patternfly/react-tokens": "^5.2.1", "@react-keycloak/web": "3.4.0", "@tanstack/react-query": "^4.22.0", @@ -1701,12 +1701,12 @@ } }, "node_modules/@patternfly/react-code-editor": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@patternfly/react-code-editor/-/react-code-editor-5.2.2.tgz", - "integrity": "sha512-7ZRYkTuf9VN7brml5+HTWbXytMcYmYFPob2K+A5xHkaOP6LSEaH3c6/XXdXdFSktR183ssdi2aZdwOW47gHVSw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@patternfly/react-code-editor/-/react-code-editor-5.2.3.tgz", + "integrity": "sha512-aO9BrWOMVu5vxCEnV66XmWHTWGLThfe4WYBpgytmy8kMbEd/qi5y3quJb8HRWP+osUfa+2m/+1fWAn9qgA2pQg==", "dependencies": { "@monaco-editor/react": "^4.6.0", - "@patternfly/react-core": "^5.2.2", + "@patternfly/react-core": "^5.2.3", "@patternfly/react-icons": "^5.2.1", "@patternfly/react-styles": "^5.2.1", "react-dropzone": "14.2.3", @@ -1718,9 +1718,9 @@ } }, "node_modules/@patternfly/react-core": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-5.2.2.tgz", - "integrity": "sha512-8dCERIVT+/ESRZ7w7UvFz3w96189W8zU+6mqbkWMG/kO6ay4o1pxIoktUT67BMMtHQNZCA+onO6+SYJrl93I0Q==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-5.2.3.tgz", + "integrity": "sha512-MJeOLyJFbZPV+cj4LjL15nUuhJUwFuqLFiv6f2YubRqHl/+z05oM0byhwfm/qu2VnKByY6X6lu3Hp+hMTZcbOA==", "dependencies": { "@patternfly/react-icons": "^5.2.1", "@patternfly/react-styles": "^5.2.1", @@ -1749,11 +1749,11 @@ "integrity": "sha512-GT96hzI1QenBhq6Pfc51kxnj9aVLjL1zSLukKZXcYVe0HPOy0BFm90bT1Fo4e/z7V9cDYw4SqSX1XLc3O4jsTw==" }, "node_modules/@patternfly/react-table": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-5.2.2.tgz", - "integrity": "sha512-Ah696FVch0lCoyslIigGgMg9ujsffXzURRaX7DYP1LyiKKVTe2ZnS9J2vSn/d/LuIEmTSsSOxbIeyzMZZEYOmg==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-5.2.4.tgz", + "integrity": "sha512-WCt4I6XYKRHXcasDqcOX70ctkgPVBAvlOv67KhaZsedxUU+B2NT1kiI7Jr7tD4SrR+jQs0MCF/bbRk1QM+rBqg==", "dependencies": { - "@patternfly/react-core": "^5.2.2", + "@patternfly/react-core": "^5.2.3", "@patternfly/react-icons": "^5.2.1", "@patternfly/react-styles": "^5.2.1", "@patternfly/react-tokens": "^5.2.1", From 55a739e80accf0cd542444657375e29889496768 Mon Sep 17 00:00:00 2001 From: Scott J Dickerson Date: Tue, 19 Mar 2024 11:12:43 -0400 Subject: [PATCH 53/53] Convert from ^ versions to pinned versions Signed-off-by: Scott J Dickerson --- client/package.json | 14 +++++++------- package-lock.json | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/client/package.json b/client/package.json index dba03235a2..c99d132317 100644 --- a/client/package.json +++ b/client/package.json @@ -25,13 +25,13 @@ "@hookform/resolvers": "^2.9.11", "@hot-loader/react-dom": "^17.0.2", "@migtools/lib-ui": "^10.0.1", - "@patternfly/patternfly": "^5.2.1", - "@patternfly/react-charts": "^7.2.2", - "@patternfly/react-code-editor": "^5.2.3", - "@patternfly/react-core": "^5.2.3", - "@patternfly/react-table": "^5.2.4", - "@patternfly/react-tokens": "^5.2.1", - "@react-keycloak/web": "3.4.0", + "@patternfly/patternfly": "5.2.1", + "@patternfly/react-charts": "7.2.2", + "@patternfly/react-code-editor": "5.2.3", + "@patternfly/react-core": "5.2.3", + "@patternfly/react-table": "5.2.4", + "@patternfly/react-tokens": "5.2.1", + "@react-keycloak/web": "^3.4.0", "@tanstack/react-query": "^4.22.0", "@tanstack/react-query-devtools": "^4.22.0", "axios": "^0.21.2", diff --git a/package-lock.json b/package-lock.json index 4b0263fbb1..7f3cf2b362 100644 --- a/package-lock.json +++ b/package-lock.json @@ -64,13 +64,13 @@ "@hookform/resolvers": "^2.9.11", "@hot-loader/react-dom": "^17.0.2", "@migtools/lib-ui": "^10.0.1", - "@patternfly/patternfly": "^5.2.1", - "@patternfly/react-charts": "^7.2.2", - "@patternfly/react-code-editor": "^5.2.3", - "@patternfly/react-core": "^5.2.3", - "@patternfly/react-table": "^5.2.4", - "@patternfly/react-tokens": "^5.2.1", - "@react-keycloak/web": "3.4.0", + "@patternfly/patternfly": "5.2.1", + "@patternfly/react-charts": "7.2.2", + "@patternfly/react-code-editor": "5.2.3", + "@patternfly/react-core": "5.2.3", + "@patternfly/react-table": "5.2.4", + "@patternfly/react-tokens": "5.2.1", + "@react-keycloak/web": "^3.4.0", "@tanstack/react-query": "^4.22.0", "@tanstack/react-query-devtools": "^4.22.0", "axios": "^0.21.2",