From: Jeremy Davis Date: Wed, 17 Jan 2024 15:35:15 +0000 (+0100) Subject: SONAR-21421 System page adopts the new UI X-Git-Tag: 10.4.0.87286~142 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=e608a535ede1786dffff2b1771b5ff7bb13ee15b;p=sonarqube.git SONAR-21421 System page adopts the new UI --- diff --git a/server/sonar-web/design-system/src/components/index.ts b/server/sonar-web/design-system/src/components/index.ts index 85fb6dfe6ee..92661b36e23 100644 --- a/server/sonar-web/design-system/src/components/index.ts +++ b/server/sonar-web/design-system/src/components/index.ts @@ -87,7 +87,7 @@ export * from './TutorialStepList'; export * from './avatar/Avatar'; export * from './avatar/GenericAvatar'; export * from './buttons'; -export { ClipboardIconButton } from './clipboard'; +export { ClipboardButton, ClipboardIconButton } from './clipboard'; export * from './code-line/LineCoverage'; export * from './code-line/LineFinding'; export * from './code-line/LineIssuesIndicatorIcon'; diff --git a/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx b/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx index 62382535dea..9e7b58e11f7 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx @@ -79,6 +79,7 @@ const TEMP_PAGELIST_WITH_NEW_BACKGROUND_WHITE = [ '/project/background_tasks', '/admin/background_tasks', '/admin/groups', + '/admin/system', '/admin/users', '/admin/settings/encryption', '/admin/extension/license/support', diff --git a/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.tsx b/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.tsx index 9b186130f03..04cc3b0c81a 100644 --- a/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.tsx +++ b/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.tsx @@ -17,10 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { Variant } from 'design-system'; import { groupBy, isEmpty, mapValues } from 'lodash'; import * as React from 'react'; import { getSystemUpgrades } from '../../../api/system'; -import { Alert, AlertVariant } from '../../../components/ui/Alert'; +import { Alert } from '../../../components/ui/Alert'; import DismissableAlert from '../../../components/ui/DismissableAlert'; import SystemUpgradeButton from '../../../components/upgrade/SystemUpgradeButton'; import { UpdateUseCase, sortUpgrades } from '../../../components/upgrade/utils'; @@ -41,7 +42,7 @@ type GroupedSystemUpdate = { [x: string]: Dict; }; -const MAP_VARIANT: Dict = { +const MAP_VARIANT: Dict = { [UpdateUseCase.NewMinorVersion]: 'info', [UpdateUseCase.NewPatch]: 'warning', [UpdateUseCase.PreLTS]: 'warning', diff --git a/server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx b/server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx index 19d92519d18..cf638be0286 100644 --- a/server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx @@ -17,11 +17,9 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { ButtonPrimary, FlagMessage, Modal, RadioButton } from 'design-system'; import * as React from 'react'; import { setLogLevel } from '../../../api/system'; -import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons'; -import Modal from '../../../components/controls/Modal'; -import { Alert } from '../../../components/ui/Alert'; import { translate } from '../../../helpers/l10n'; import { LOGS_LEVELS } from '../utils'; @@ -37,6 +35,7 @@ interface State { updating: boolean; } +const FORM_ID = 'set-log-level-form'; export default class ChangeLogLevelForm extends React.PureComponent { constructor(props: Props) { super(props); @@ -55,55 +54,50 @@ export default class ChangeLogLevelForm extends React.PureComponent) => - this.setState({ newLevel: event.currentTarget.value }); + handleLevelChange = (value: string) => this.setState({ newLevel: value }); render() { const { updating, newLevel } = this.state; const header = translate('system.set_log_level'); return ( - -
-
-

{header}

-
-
+ {LOGS_LEVELS.map((level) => ( -

- + -

+ ))} - + {this.props.infoMsg} - + {newLevel !== 'INFO' && ( - + {translate('system.log_level.warning')} - + )} -
-
- {updating && } - - {translate('save')} - - - {translate('cancel')} - -
- -
+ + } + primaryButton={ + + {translate('save')} + + } + secondaryButtonLabel={translate('cancel')} + loading={updating} + /> ); } } diff --git a/server/sonar-web/src/main/js/apps/system/components/ClusterSysInfos.tsx b/server/sonar-web/src/main/js/apps/system/components/ClusterSysInfos.tsx index 09bf3fbb782..67a7e68d375 100644 --- a/server/sonar-web/src/main/js/apps/system/components/ClusterSysInfos.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/ClusterSysInfos.tsx @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { Note, UnorderedList } from 'design-system'; import { sortBy } from 'lodash'; import * as React from 'react'; import { translate } from '../../../helpers/l10n'; @@ -38,12 +39,15 @@ interface Props { toggleCard: (toggledCard: string) => void; } -export default function ClusterSysInfos({ expandedCards, sysInfoData, toggleCard }: Props) { +export default function ClusterSysInfos({ + expandedCards, + sysInfoData, + toggleCard, +}: Readonly) { const mainCardName = 'System'; return ( -
    + -
  • - {translate('system.application_nodes_title')} +
  • + {translate('system.application_nodes_title')}
  • {sortBy(getAppNodes(sysInfoData), getNodeName).map((node: SysInfoAppNode) => ( ))} -
  • {translate('system.search_nodes_title')}
  • +
  • + {translate('system.search_nodes_title')} +
  • {sortBy(getSearchNodes(sysInfoData), getNodeName).map((node: SysInfoSearchNode) => ( ))} -
+ ); } diff --git a/server/sonar-web/src/main/js/apps/system/components/PageActions.tsx b/server/sonar-web/src/main/js/apps/system/components/PageActions.tsx index 26150d57b20..09cb66272d4 100644 --- a/server/sonar-web/src/main/js/apps/system/components/PageActions.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/PageActions.tsx @@ -17,10 +17,16 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { + ButtonPrimary, + ChevronDownIcon, + DownloadButton, + Dropdown, + InteractiveIcon, + ItemDownload, + PencilIcon, +} from 'design-system'; import * as React from 'react'; -import { Button, EditButton } from '../../../components/controls/buttons'; -import Dropdown from '../../../components/controls/Dropdown'; -import DropdownIcon from '../../../components/icons/DropdownIcon'; import { translate } from '../../../helpers/l10n'; import { getBaseUrl } from '../../../helpers/system'; import { getFileNameSuffix } from '../utils'; @@ -67,101 +73,60 @@ export default class PageActions extends React.PureComponent { const infoUrl = getBaseUrl() + '/api/system/info'; const logsUrl = getBaseUrl() + '/api/system/logs'; return ( -
- - +
+
+ {translate('system.logs_level')} - {':'} - {this.props.logLevel} + {': '} + {this.props.logLevel} - - +
{this.props.canDownloadLogs && ( -
  • - - Main Process - -
  • -
  • - - Compute Engine - -
  • -
  • - - Search Engine - -
  • -
  • - - Web Server - -
  • -
  • - - Access Logs - -
  • -
  • - - Deprecation Logs - -
  • - + <> + + Main Process + + + Compute Engine + + + Search Engine + + + + Web Server + + + + Access Logs + + + + Deprecation Logs + + } > - + +
    )} - { target="_blank" > {translate('system.download_system_info')} - + {this.state.openLogsLevelForm && ( ) { const { isCluster, loading, logLevel, serverId, version, appState } = props; return ( -
    -

    {translate('system_info.page')}

    - - {loading && ( -
    - +
    +
    + {translate('system_info.page')} + +
    + + +
    - )} +
    + {serverId && version && ( -
    + {!appState.productionDatabase && ( - + {translate('system.not_production_database_warning')} - + )} -
    -
    - - - - - - - - - - - -
    - {translate('system.server_id')} - - {serverId} -
    - {translate('system.version')} - {version}
    +
    +
    +
    + {translate('system.server_id')} + {serverId} +
    +
    + {translate('system.version')} + {version} +
    - {translate('system.copy_id_info')} + + {translate('system.copy_id_info')} +
    -
    + )}
    ); diff --git a/server/sonar-web/src/main/js/apps/system/components/StandaloneSysInfos.tsx b/server/sonar-web/src/main/js/apps/system/components/StandaloneSysInfos.tsx index 4807d2fa763..6a8acbe7f7a 100644 --- a/server/sonar-web/src/main/js/apps/system/components/StandaloneSysInfos.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/StandaloneSysInfos.tsx @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { UnorderedList } from 'design-system'; import { map } from 'lodash'; import * as React from 'react'; import { SysInfoStandalone } from '../../../types/types'; @@ -35,12 +36,16 @@ interface Props { toggleCard: (toggledCard: string) => void; } -export default function StandAloneSysInfos({ expandedCards, sysInfoData, toggleCard }: Props) { - const mainCardName = 'System'; +const mainCardName = 'System'; + +export default function StandAloneSysInfos({ + expandedCards, + sysInfoData, + toggleCard, +}: Readonly) { return ( -
      + ))} -
    + ); } diff --git a/server/sonar-web/src/main/js/apps/system/components/SystemApp.tsx b/server/sonar-web/src/main/js/apps/system/components/SystemApp.tsx index 30baa93cd47..2d8b6493349 100644 --- a/server/sonar-web/src/main/js/apps/system/components/SystemApp.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/SystemApp.tsx @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { LargeCenteredLayout, PageContentFontWrapper } from 'design-system'; import * as React from 'react'; import { Helmet } from 'react-helmet-async'; import { getSystemInfo } from '../../../api/system'; @@ -27,13 +28,13 @@ import { translate } from '../../../helpers/l10n'; import { SysInfoCluster, SysInfoStandalone } from '../../../types/types'; import '../styles.css'; import { + Query, getClusterVersion, getServerId, getSystemLogsLevel, getVersion, isCluster, parseQuery, - Query, serializeQuery, } from '../utils'; import ClusterSysInfos from './ClusterSysInfos'; @@ -123,26 +124,28 @@ class SystemApp extends React.PureComponent { render() { const { loading, sysInfoData } = this.state; return ( -
    + -
    - -
    - {sysInfoData && ( - - )} - {this.renderSysInfo()} -
    + +
    + +
    + {sysInfoData && ( + + )} + {this.renderSysInfo()} +
    + ); } } diff --git a/server/sonar-web/src/main/js/apps/system/components/__tests__/SystemApp-it.tsx b/server/sonar-web/src/main/js/apps/system/components/__tests__/SystemApp-it.tsx index d2b885e1355..fc45c6112b6 100644 --- a/server/sonar-web/src/main/js/apps/system/components/__tests__/SystemApp-it.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/__tests__/SystemApp-it.tsx @@ -76,8 +76,8 @@ describe('System Info Standalone', () => { 'Web Server', 'Access Logs', 'Deprecation Logs', - ].forEach((link) => { - expect(screen.getByRole('link', { name: link })).toBeInTheDocument(); + ].forEach((name) => { + expect(screen.getByRole('menuitem', { name })).toBeInTheDocument(); }); expect(ui.downloadSystemInfoButton.get()).toBeInTheDocument(); }); @@ -122,7 +122,7 @@ function getPageObjects() { pageHeading: byRole('heading', { name: 'system_info.page' }), downloadLogsButton: byRole('button', { name: 'system.download_logs' }), downloadSystemInfoButton: byRole('link', { name: 'system.download_system_info' }), - copyIdInformation: byRole('button', { name: 'copy_to_clipboard' }), + copyIdInformation: byRole('button', { name: 'system.copy_id_info' }), sectionButton: (name: string) => byRole('button', { name }), changeLogLevelButton: byRole('button', { name: 'system.logs_level.change' }), logLevelsRadioButton: (name: LogsLevels) => byRole('radio', { name }), diff --git a/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCard.tsx b/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCard.tsx index a7857689da4..73551380dc5 100644 --- a/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCard.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCard.tsx @@ -17,18 +17,16 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { Accordion, FlagMessage, SubHeadingHighlight } from 'design-system'; import { map } from 'lodash'; import * as React from 'react'; -import BoxedGroupAccordion from '../../../../components/controls/BoxedGroupAccordion'; -import { Alert } from '../../../../components/ui/Alert'; import { translate } from '../../../../helpers/l10n'; import { HealthTypes, SysInfoValueObject } from '../../../../types/types'; -import { getLogsLevel, groupSections, LogsLevels } from '../../utils'; +import { LogsLevels, getLogsLevel, groupSections } from '../../utils'; import HealthItem from './HealthItem'; import Section from './Section'; interface Props { - biggerHealth?: boolean; health?: HealthTypes; healthCauses?: string[]; onClick: (toggledCard: string) => void; @@ -38,50 +36,44 @@ interface Props { } export default function HealthCard({ - biggerHealth, health, healthCauses, onClick, open, name, sysInfoData, -}: Props) { +}: Readonly) { const { mainSection, sections } = groupSections(sysInfoData); const showFields = open && mainSection && Object.keys(mainSection).length > 0; const showSections = open && sections; const logLevel = getLogsLevel(sysInfoData); const showLogLevelWarning = logLevel && logLevel !== LogsLevels.INFO; + return ( - ( + header={ <> - {showLogLevelWarning && ( - - {translate('system.log_level.warning.short')} - - )} - {health && ( - - )} +
    + + {name} + + {showLogLevelWarning && ( + + {translate('system.log_level.warning.short')} + + )} +
    + {health && } - )} - title={name} + } + ariaLabel={name} > {showFields &&
    } {showSections && map(sections, (section, name) =>
    )} - + ); } diff --git a/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCauseItem.tsx b/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCauseItem.tsx index 08fc16e80e2..f41956f8013 100644 --- a/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCauseItem.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCauseItem.tsx @@ -18,8 +18,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import classNames from 'classnames'; +import { FlagMessage } from 'design-system'; import * as React from 'react'; -import { Alert } from '../../../../components/ui/Alert'; import { HealthTypes } from '../../../../types/types'; interface Props { @@ -28,14 +28,13 @@ interface Props { healthCause: string; } -export default function HealthCauseItem({ className, health, healthCause }: Props) { +export default function HealthCauseItem({ className, health, healthCause }: Readonly) { return ( - {healthCause} - + ); } diff --git a/server/sonar-web/src/main/js/apps/system/components/info-items/HealthItem.tsx b/server/sonar-web/src/main/js/apps/system/components/info-items/HealthItem.tsx index 90b3352a8be..357e8dca6fc 100644 --- a/server/sonar-web/src/main/js/apps/system/components/info-items/HealthItem.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/info-items/HealthItem.tsx @@ -26,32 +26,28 @@ import { HealthTypes } from '../../../../types/types'; import HealthCauseItem from './HealthCauseItem'; interface Props { - biggerHealth?: boolean; name?: string; className?: string; health: HealthTypes; healthCauses?: string[]; } -export default function HealthItem({ biggerHealth, className, name, health, healthCauses }: Props) { +export default function HealthItem({ className, name, health, healthCauses }: Readonly) { const hasHealthCauses = healthCauses && healthCauses.length > 0 && health !== HealthTypes.GREEN; - const statusIndicator = ( - - ); + const statusIndicator = ; return ( -
    +
    {hasHealthCauses && - healthCauses.map((cause, idx) => ( - + healthCauses.map((cause) => ( + ))} - {name ? ( - - {statusIndicator} - - ) : ( - statusIndicator - )} + + + {statusIndicator} +
    ); } diff --git a/server/sonar-web/src/main/js/apps/system/components/info-items/Section.tsx b/server/sonar-web/src/main/js/apps/system/components/info-items/Section.tsx index 1b1d3de69a8..6c333478732 100644 --- a/server/sonar-web/src/main/js/apps/system/components/info-items/Section.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/info-items/Section.tsx @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { ContentCell, SubHeading, Table, TableRow } from 'design-system'; import { map } from 'lodash'; import * as React from 'react'; import { SysInfoValueObject } from '../../../../types/types'; @@ -27,26 +28,26 @@ interface Props { items: SysInfoValueObject; } -export default function Section({ name, items }: Props) { +const COLUMNS = ['0', 'auto']; + +export default function Section({ name, items }: Readonly) { return ( -
    - {name &&

    {name}

    } - - - {map(items, (value, name) => { - return ( - - -
    -
    {name}
    -
    +
    + {name !== undefined && {name}} + + {map(items, (value, name) => { + return ( + + {name} + + - - - ); - })} - -
    + + + + ); + })} +
    ); } diff --git a/server/sonar-web/src/main/js/apps/system/components/info-items/SysInfoItem.tsx b/server/sonar-web/src/main/js/apps/system/components/info-items/SysInfoItem.tsx index fa880ca83c1..bbbeef434a4 100644 --- a/server/sonar-web/src/main/js/apps/system/components/info-items/SysInfoItem.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/info-items/SysInfoItem.tsx @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { ContentCell, Table, TableRow } from 'design-system'; import { map } from 'lodash'; import * as React from 'react'; import { translate } from '../../../../helpers/l10n'; @@ -29,32 +30,32 @@ export interface Props { value: SysInfoValue; } -export default function SysInfoItem({ name, value }: Props) { +const COLUMNS = [0, 'auto']; + +export default function SysInfoItem({ name, value }: Readonly) { if (name === HEALTH_FIELD || name === STATE_FIELD) { - return ; + return ; } if (value instanceof Array) { - return {JSON.stringify(value)}; + return {JSON.stringify(value)}; } switch (typeof value) { case 'boolean': return <>{translate(value ? 'yes' : 'no')}; case 'object': return ( - - - {map(value, (v, n) => ( - - - - - ))} - -
    {n} - -
    + + {map(value, (v, n) => ( + + {n} + + + + + ))} +
    ); default: - return {value}; + return {value}; } } diff --git a/server/sonar-web/src/main/js/components/common/StatusIndicator.tsx b/server/sonar-web/src/main/js/components/common/StatusIndicator.tsx index 8f7964bd8f4..c6cac3e2379 100644 --- a/server/sonar-web/src/main/js/components/common/StatusIndicator.tsx +++ b/server/sonar-web/src/main/js/components/common/StatusIndicator.tsx @@ -17,33 +17,29 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import classNames from 'classnames'; +import { CheckIcon, FlagErrorIcon, FlagWarningIcon } from 'design-system'; import * as React from 'react'; import { translate } from '../../helpers/l10n'; +import { HealthTypes } from '../../types/types'; import './StatusIndicator.css'; export interface StatusIndicatorProps { - className?: string; - color?: string; - size?: string; + color: HealthTypes; } -export default function StatusIndicator({ className, color, size }: StatusIndicatorProps) { +const ICON_MAP = { + [HealthTypes.GREEN]: CheckIcon, + [HealthTypes.YELLOW]: FlagWarningIcon, + [HealthTypes.RED]: FlagErrorIcon, +}; + +export default function StatusIndicator({ color }: Readonly) { + const Icon = ICON_MAP[color]; + return ( <> - {color ? translate('system.current_health', color) : undefined} - + {translate('system.current_health', color.toLowerCase())} + ); } diff --git a/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeButton.tsx b/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeButton.tsx index ed1b3573c3b..b028aa6c3c6 100644 --- a/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeButton.tsx +++ b/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeButton.tsx @@ -30,38 +30,32 @@ interface Props { updateUseCase?: UpdateUseCase; } -interface State { - openSystemUpgradeForm: boolean; -} +export default function SystemUpgradeButton(props: Readonly) { + const { latestLTS, systemUpgrades, updateUseCase } = props; -export default class SystemUpgradeButton extends React.PureComponent { - state: State = { openSystemUpgradeForm: false }; + const [isSystemUpgradeFormOpen, setSystemUpgradeFormOpen] = React.useState(false); - handleOpenSystemUpgradeForm = () => { - this.setState({ openSystemUpgradeForm: true }); - }; + const openSystemUpgradeForm = React.useCallback(() => { + setSystemUpgradeFormOpen(true); + }, [setSystemUpgradeFormOpen]); - handleCloseSystemUpgradeForm = () => { - this.setState({ openSystemUpgradeForm: false }); - }; + const closeSystemUpgradeForm = React.useCallback(() => { + setSystemUpgradeFormOpen(false); + }, [setSystemUpgradeFormOpen]); - render() { - const { latestLTS, systemUpgrades, updateUseCase } = this.props; - const { openSystemUpgradeForm } = this.state; - return ( - <> - - {openSystemUpgradeForm && ( - - )} - - ); - } + return ( + <> + + {isSystemUpgradeFormOpen && ( + + )} + + ); } diff --git a/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgrade-test.tsx b/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgrade-test.tsx index 1e571b1d5dd..29a1c4d35f2 100644 --- a/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgrade-test.tsx +++ b/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgrade-test.tsx @@ -69,7 +69,7 @@ it('should render properly for new patch', async () => { }); function renderSystemUpgradeButton( - props: Partial = {}, + props: Partial> = {}, version = '9.7', ) { renderComponent(