From: Mathieu Suen Date: Thu, 14 Oct 2021 16:06:41 +0000 (+0200) Subject: SONAR-15507 Add a prompt to warn when SonarQube need an update X-Git-Tag: 9.2.0.49834~136 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=667542fa30857ee17c1317e19d67f62e62e44b44;p=sonarqube.git SONAR-15507 Add a prompt to warn when SonarQube need an update --- diff --git a/server/sonar-web/src/main/js/api/system.ts b/server/sonar-web/src/main/js/api/system.ts index 9adf55ea9dc..7a613374ec3 100644 --- a/server/sonar-web/src/main/js/api/system.ts +++ b/server/sonar-web/src/main/js/api/system.ts @@ -35,6 +35,7 @@ export function getSystemStatus(): Promise<{ id: string; version: string; status export function getSystemUpgrades(): Promise<{ upgrades: SystemUpgrade[]; + latestLTS: string; updateCenterRefresh: string; }> { return getJSON('/api/system/upgrades'); 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 68763f336ea..e31bf86e066 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx @@ -28,6 +28,7 @@ import IndexationContextProvider from './indexation/IndexationContextProvider'; import IndexationNotification from './indexation/IndexationNotification'; import GlobalNav from './nav/global/GlobalNav'; import StartupModal from './StartupModal'; +import UpdateNotification from './update-notification/UpdateNotification'; export interface Props { children: React.ReactNode; @@ -52,6 +53,7 @@ export default function GlobalContainer(props: Props) { + {props.children} diff --git a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap index cf87ae0d4f2..7f04cba74c2 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap @@ -32,6 +32,7 @@ exports[`should render correctly 1`] = ` /> + diff --git a/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.css b/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.css new file mode 100644 index 00000000000..fc23a2cb9f8 --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.css @@ -0,0 +1,29 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +.promote-update-notification.dismissable-alert-wrapper { + height: 42px; +} + +.promote-update-notification .dismissable-alert-banner { + margin-bottom: 0 !important; + position: fixed; + width: 100%; + z-index: var(--globalBannerZIndex); +} 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 new file mode 100644 index 00000000000..1a3a23b4f5f --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.tsx @@ -0,0 +1,241 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { groupBy, isEmpty, mapValues } from 'lodash'; +import * as React from 'react'; +import { getSystemUpgrades } from '../../../api/system'; +import { withAppState } from '../../../components/hoc/withAppState'; +import { withCurrentUser } from '../../../components/hoc/withCurrentUser'; +import { AlertVariant } from '../../../components/ui/Alert'; +import DismissableAlert from '../../../components/ui/DismissableAlert'; +import SystemUpgradeButton from '../../../components/upgrade/SystemUpgradeButton'; +import { sortUpgrades } from '../../../components/upgrade/utils'; +import { translate } from '../../../helpers/l10n'; +import { hasGlobalPermission, isLoggedIn } from '../../../helpers/users'; +import { Permissions } from '../../../types/permissions'; +import { SystemUpgrade } from '../../../types/system'; +import './UpdateNotification.css'; + +const MONTH_BEFOR_PREVIOUS_LTS_NOTIFICATION = 6; + +type GroupedSystemUpdate = { + [x: string]: T.Dict; +}; + +enum UseCase { + NewMinorVersion = 'new_minor_version', + NewPatch = 'new_patch', + PreLTS = 'pre_lts', + PreviousLTS = 'previous_lts' +} + +const MAP_VARIANT: T.Dict = { + [UseCase.NewMinorVersion]: 'info', + [UseCase.NewPatch]: 'warning', + [UseCase.PreLTS]: 'warning', + [UseCase.PreviousLTS]: 'error' +}; + +interface Props { + appState: Pick; + currentUser: T.CurrentUser; +} + +interface State { + dismissKey: string; + useCase: UseCase; + systemUpgrades: SystemUpgrade[]; + canSeeNotification: boolean; +} + +export class UpdateNotification extends React.PureComponent { + mounted = false; + versionParser = /^(\d+)\.(\d+)(\.(\d+))?/; + + constructor(props: Props) { + super(props); + this.state = { + dismissKey: '', + systemUpgrades: [], + canSeeNotification: false, + useCase: UseCase.NewMinorVersion + }; + this.fetchSystemUpgradeInformation(); + } + + componentDidMount() { + this.mounted = true; + } + + componentDidUpdate(prevProps: Props) { + if ( + prevProps.currentUser !== this.props.currentUser || + this.props.appState.version !== prevProps.appState.version + ) { + this.fetchSystemUpgradeInformation(); + } + } + + componentWillUnmount() { + this.mounted = false; + } + + isPreLTSUpdate(parsedVersion: number[], latestLTS: string) { + const [currentMajor, currentMinor] = parsedVersion; + const [ltsMajor, ltsMinor] = latestLTS.split('.').map(Number); + return currentMajor < ltsMajor || (currentMajor === ltsMajor && currentMinor < ltsMinor); + } + + isPreviousLTSUpdate( + parsedVersion: number[], + latestLTS: string, + systemUpgrades: GroupedSystemUpdate + ) { + const [ltsMajor, ltsMinor] = latestLTS.split('.').map(Number); + let ltsOlderThan6Month = false; + const beforeLts = this.isPreLTSUpdate(parsedVersion, latestLTS); + if (beforeLts) { + const allLTS = sortUpgrades(systemUpgrades[ltsMajor][ltsMinor]); + const ltsReleaseDate = new Date(allLTS[allLTS.length - 1]?.releaseDate || ''); + if (isNaN(ltsReleaseDate.getTime())) { + // We can not parse the LTS date. + // It is unlikly that this could happen but consider LTS to be old. + return true; + } + ltsOlderThan6Month = + ltsReleaseDate.setMonth(ltsReleaseDate.getMonth() + MONTH_BEFOR_PREVIOUS_LTS_NOTIFICATION) - + Date.now() < + 0; + } + return ltsOlderThan6Month && beforeLts; + } + + isMinorUpdate(parsedVersion: number[], systemUpgrades: GroupedSystemUpdate) { + const [currentMajor, currentMinor] = parsedVersion; + const allMinor = systemUpgrades[currentMajor]; + return Object.keys(allMinor) + .map(Number) + .some(minor => minor > currentMinor); + } + + isPatchUpdate(parsedVersion: number[], systemUpgrades: GroupedSystemUpdate) { + const [currentMajor, currentMinor, currentPatch] = parsedVersion; + const allMinor = systemUpgrades[currentMajor]; + const allPatch = sortUpgrades(allMinor[currentMinor] || []); + + if (!isEmpty(allPatch)) { + const [, , latestPatch] = allPatch[0].version.split('.').map(Number); + const effectiveCurrentPatch = isNaN(currentPatch) ? 0 : currentPatch; + const effectiveLatestPatch = isNaN(latestPatch) ? 0 : latestPatch; + return effectiveCurrentPatch < effectiveLatestPatch; + } + return false; + } + + async fetchSystemUpgradeInformation() { + if ( + !isLoggedIn(this.props.currentUser) || + !hasGlobalPermission(this.props.currentUser, Permissions.Admin) + ) { + this.noPromptToShow(); + return; + } + + const regExpParsedVersion = this.versionParser.exec(this.props.appState.version); + if (regExpParsedVersion === null) { + this.noPromptToShow(); + return; + } + regExpParsedVersion.shift(); + const parsedVersion = regExpParsedVersion.map(Number).map(n => (isNaN(n) ? 0 : n)); + + const { upgrades, latestLTS } = await getSystemUpgrades(); + + if (isEmpty(upgrades)) { + // No new upgrades + this.noPromptToShow(); + return; + } + const systemUpgrades = mapValues( + groupBy(upgrades, upgrade => { + const [major] = upgrade.version.split('.'); + return major; + }), + upgrades => + groupBy(upgrades, upgrade => { + const [, minor] = upgrade.version.split('.'); + return minor; + }) + ); + + let useCase = UseCase.NewMinorVersion; + + if (this.isPreviousLTSUpdate(parsedVersion, latestLTS, systemUpgrades)) { + useCase = UseCase.PreviousLTS; + } else if (this.isPreLTSUpdate(parsedVersion, latestLTS)) { + useCase = UseCase.PreLTS; + } else if (this.isPatchUpdate(parsedVersion, systemUpgrades)) { + useCase = UseCase.NewPatch; + } else if (this.isMinorUpdate(parsedVersion, systemUpgrades)) { + useCase = UseCase.NewMinorVersion; + } + + const latest = [...upgrades].sort( + (upgrade1, upgrade2) => + new Date(upgrade2.releaseDate || '').getTime() - + new Date(upgrade1.releaseDate || '').getTime() + )[0]; + + const dismissKey = useCase + latest.version; + + if (this.mounted) { + this.setState({ + useCase, + dismissKey, + systemUpgrades: upgrades, + canSeeNotification: true + }); + } + } + + noPromptToShow() { + if (this.mounted) { + this.setState({ canSeeNotification: false }); + } + } + + render() { + const { systemUpgrades, canSeeNotification, useCase, dismissKey } = this.state; + if (!canSeeNotification) { + return null; + } + return ( + + {translate('admin_notification.update', useCase)} + + + ); + } +} + +export default withCurrentUser(withAppState(UpdateNotification)); diff --git a/server/sonar-web/src/main/js/app/components/update-notification/__tests__/UpdateNotification-test.tsx b/server/sonar-web/src/main/js/app/components/update-notification/__tests__/UpdateNotification-test.tsx new file mode 100644 index 00000000000..6c284a04610 --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/update-notification/__tests__/UpdateNotification-test.tsx @@ -0,0 +1,153 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { getSystemUpgrades } from '../../../../api/system'; +import DismissableAlert from '../../../../components/ui/DismissableAlert'; +import { mockUpgrades } from '../../../../helpers/mocks/system-upgrades'; +import { mockAppState, mockCurrentUser, mockLoggedInUser } from '../../../../helpers/testMocks'; +import { waitAndUpdate } from '../../../../helpers/testUtils'; +import { Permissions } from '../../../../types/permissions'; +import { UpdateNotification } from '../UpdateNotification'; + +jest.mock('../../../../api/system', () => { + const { mockUpgrades } = jest.requireActual('../../../../helpers/mocks/system-upgrades'); + return { + getSystemUpgrades: jest.fn().mockResolvedValue({ upgrades: [mockUpgrades()], latestLTS: '8.9' }) + }; +}); + +function formatDate(date: Date): string { + return `${date.getFullYear()}-${date.getMonth()}-${date.getDay()}`; +} + +it('should not show prompt when not admin', async () => { + //As anonymous + const wrapper = shallowRender(); + await waitAndUpdate(wrapper); + expect(wrapper.type()).toBeNull(); + + // As non admin user + wrapper.setProps({ currentUser: mockLoggedInUser() }); + await waitAndUpdate(wrapper); + expect(wrapper.type()).toBeNull(); +}); + +it('should not show prompt when no current version', async () => { + const wrapper = shallowRender({ appState: mockAppState({ version: 'NOVERSION' }) }); + await waitAndUpdate(wrapper); + expect(wrapper.type()).toBeNull(); +}); + +it('should not show prompt when no upgrade', async () => { + (getSystemUpgrades as jest.Mock).mockResolvedValueOnce({ upgrades: [], latestLTS: '8.9' }); + const wrapper = shallowRender({ + appState: mockAppState({ version: '9.1' }), + currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }) + }); + await waitAndUpdate(wrapper); + expect(wrapper.type()).toBeNull(); +}); + +it('should show prompt when no lts date', async () => { + (getSystemUpgrades as jest.Mock).mockResolvedValueOnce({ + upgrades: [mockUpgrades({ version: '8.9', releaseDate: 'INVALID' })], + latestLTS: '8.9' + }); + const wrapper = shallowRender({ + appState: mockAppState({ version: '8.1' }), + currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }) + }); + await waitAndUpdate(wrapper); + expect(wrapper.find(DismissableAlert).props().alertKey).toBe('previous_lts8.9'); + expect(wrapper.contains('admin_notification.update.previous_lts')).toBe(true); +}); + +it('should show prompt when minor upgrade', async () => { + (getSystemUpgrades as jest.Mock).mockResolvedValueOnce({ + upgrades: [mockUpgrades({ version: '9.2' }), mockUpgrades({ version: '9.1' })], + latestLTS: '8.9' + }); + const wrapper = shallowRender({ + appState: mockAppState({ version: '9.1' }), + currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }) + }); + await waitAndUpdate(wrapper); + expect(wrapper.find(DismissableAlert).props().alertKey).toBe('new_minor_version9.2'); + expect(wrapper.contains('admin_notification.update.new_minor_version')).toBe(true); +}); + +it('should show prompt when patch upgrade', async () => { + (getSystemUpgrades as jest.Mock).mockResolvedValueOnce({ + upgrades: [mockUpgrades({ version: '9.2' }), mockUpgrades({ version: '9.1.1' })], + latestLTS: '8.9' + }); + const wrapper = shallowRender({ + appState: mockAppState({ version: '9.1' }), + currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }) + }); + await waitAndUpdate(wrapper); + expect(wrapper.find(DismissableAlert).props().alertKey).toBe('new_patch9.2'); + expect(wrapper.contains('admin_notification.update.new_patch')).toBe(true); +}); + +it('should show prompt when lts upgrade', async () => { + (getSystemUpgrades as jest.Mock).mockResolvedValueOnce({ + upgrades: [ + mockUpgrades({ version: '8.9', releaseDate: formatDate(new Date(Date.now())) }), + mockUpgrades({ version: '9.2' }), + mockUpgrades({ version: '9.1.1' }) + ], + latestLTS: '8.9' + }); + const wrapper = shallowRender({ + appState: mockAppState({ version: '8.8' }), + currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }) + }); + await waitAndUpdate(wrapper); + expect(wrapper.find(DismissableAlert).props().alertKey).toBe('pre_lts8.9'); + expect(wrapper.contains('admin_notification.update.pre_lts')).toBe(true); +}); + +it('should show prompt when lts upgrade is more than 6 month', async () => { + const ltsDate = new Date(Date.now()); + ltsDate.setMonth(ltsDate.getMonth() - 7); + (getSystemUpgrades as jest.Mock).mockResolvedValueOnce({ + upgrades: [ + mockUpgrades({ version: '8.9', releaseDate: formatDate(ltsDate) }), + mockUpgrades({ version: '9.2' }), + mockUpgrades({ version: '9.1.1' }) + ], + latestLTS: '8.9' + }); + const wrapper = shallowRender({ + appState: mockAppState({ version: '8.8' }), + currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }) + }); + await waitAndUpdate(wrapper); + expect(wrapper.find(DismissableAlert).props().alertKey).toBe('previous_lts8.9'); + expect(wrapper.contains('admin_notification.update.previous_lts')).toBe(true); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/apps/system/__tests__/utils-test.ts b/server/sonar-web/src/main/js/apps/system/__tests__/utils-test.ts index 331497b902d..3194894a6ab 100644 --- a/server/sonar-web/src/main/js/apps/system/__tests__/utils-test.ts +++ b/server/sonar-web/src/main/js/apps/system/__tests__/utils-test.ts @@ -19,7 +19,6 @@ */ import { mockClusterSysInfo, mockStandaloneSysInfo } from '../../../helpers/testMocks'; -import { SystemUpgrade } from '../../../types/system'; import * as u from '../utils'; describe('parseQuery', () => { @@ -73,54 +72,6 @@ describe('getSystemLogsLevel', () => { }); }); -describe('sortUpgrades', () => { - it('should sort correctly versions', () => { - expect( - u.sortUpgrades([ - { version: '5.4.2' }, - { version: '5.10' }, - { version: '5.1' }, - { version: '5.4' } - ] as SystemUpgrade[]) - ).toEqual([{ version: '5.10' }, { version: '5.4.2' }, { version: '5.4' }, { version: '5.1' }]); - expect( - u.sortUpgrades([ - { version: '5.10' }, - { version: '5.1.2' }, - { version: '6.0' }, - { version: '6.9' } - ] as SystemUpgrade[]) - ).toEqual([{ version: '6.9' }, { version: '6.0' }, { version: '5.10' }, { version: '5.1.2' }]); - }); -}); - -describe('groupUpgrades', () => { - it('should group correctly', () => { - expect( - u.groupUpgrades([ - { version: '5.10' }, - { version: '5.4.2' }, - { version: '5.4' }, - { version: '5.1' } - ] as SystemUpgrade[]) - ).toEqual([ - [{ version: '5.10' }, { version: '5.4.2' }, { version: '5.4' }, { version: '5.1' }] - ]); - expect( - u.groupUpgrades([ - { version: '6.9' }, - { version: '6.7' }, - { version: '6.0' }, - { version: '5.10' }, - { version: '5.4.2' } - ] as SystemUpgrade[]) - ).toEqual([ - [{ version: '6.9' }, { version: '6.7' }, { version: '6.0' }], - [{ version: '5.10' }, { version: '5.4.2' }] - ]); - }); -}); - describe('isCluster', () => { it('should return the correct information', () => { expect(u.isCluster(mockClusterSysInfo())).toBe(true); diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeForm.tsx b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeForm.tsx deleted file mode 100644 index b4a25a71963..00000000000 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeForm.tsx +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { ResetButtonLink } from '../../../../components/controls/buttons'; -import Modal from '../../../../components/controls/Modal'; -import { withAppState } from '../../../../components/hoc/withAppState'; -import { translate } from '../../../../helpers/l10n'; -import { EditionKey } from '../../../../types/editions'; -import { SystemUpgrade } from '../../../../types/system'; -import SystemUpgradeItem from './SystemUpgradeItem'; - -interface Props { - appState: Pick; - onClose: () => void; - systemUpgrades: SystemUpgrade[][]; -} - -interface State { - upgrading: boolean; -} - -export class SystemUpgradeForm extends React.PureComponent { - state: State = { upgrading: false }; - - render() { - const { upgrading } = this.state; - const { appState, systemUpgrades } = this.props; - const header = translate('system.system_upgrade'); - return ( - -
-

{header}

-
-
- {systemUpgrades.map((upgrades, idx) => ( - - ))} -
-
- {upgrading && } - - {translate('system.see_sonarqube_downloads')} - - {translate('cancel')} -
-
- ); - } -} - -export default withAppState(SystemUpgradeForm); diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeIntermediate.tsx b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeIntermediate.tsx deleted file mode 100644 index b059fe41805..00000000000 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeIntermediate.tsx +++ /dev/null @@ -1,86 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { ButtonLink } from '../../../../components/controls/buttons'; -import DropdownIcon from '../../../../components/icons/DropdownIcon'; -import DateFormatter from '../../../../components/intl/DateFormatter'; -import { translate } from '../../../../helpers/l10n'; -import { SystemUpgrade } from '../../../../types/system'; - -interface Props { - className?: string; - upgrades: SystemUpgrade[]; -} - -interface State { - showMore: boolean; -} - -export default class SystemUpgradeIntermediate extends React.PureComponent { - state: State = { showMore: false }; - - toggleIntermediatVersions = () => { - this.setState(state => ({ showMore: !state.showMore })); - }; - - render() { - const { showMore } = this.state; - const { upgrades } = this.props; - if (upgrades.length <= 0) { - return null; - } - - return ( -
- - {showMore - ? translate('system.hide_intermediate_versions') - : translate('system.show_intermediate_versions')} - - - {showMore && - upgrades.map(upgrade => ( -
- {upgrade.releaseDate && ( - - {formattedDate => ( -

- SonarQube {upgrade.version} - {formattedDate} - {upgrade.changeLogUrl && ( - - {translate('system.release_notes')} - - )} -

- )} -
- )} - {upgrade.description &&

{upgrade.description}

} -
- ))} -
- ); - } -} diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeItem.tsx b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeItem.tsx deleted file mode 100644 index d5c605cbc4b..00000000000 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeItem.tsx +++ /dev/null @@ -1,109 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { FormattedMessage } from 'react-intl'; -import DateFormatter from '../../../../components/intl/DateFormatter'; -import { - getEdition, - getEditionDownloadFilename, - getEditionDownloadUrl -} from '../../../../helpers/editions'; -import { translate, translateWithParameters } from '../../../../helpers/l10n'; -import { EditionKey } from '../../../../types/editions'; -import { SystemUpgrade } from '../../../../types/system'; -import SystemUpgradeIntermediate from './SystemUpgradeIntermediate'; - -export interface SystemUpgradeItemProps { - edition: EditionKey | undefined; - isLatestVersion: boolean; - systemUpgrades: SystemUpgrade[]; -} - -export default function SystemUpgradeItem(props: SystemUpgradeItemProps) { - const { edition, isLatestVersion, systemUpgrades } = props; - const lastUpgrade = systemUpgrades[0]; - const downloadUrl = getEditionDownloadUrl( - getEdition(edition || EditionKey.community), - lastUpgrade - ); - - return ( -
-

- - {isLatestVersion ? translate('system.latest_version') : translate('system.lts_version')} - - {isLatestVersion && ( - - {translate('system.see_whats_new')} - - )} -

-

- SonarQube {lastUpgrade.version} }} - /> -

-

{lastUpgrade.description}

-
- {lastUpgrade.releaseDate && ( - - {formattedDate => ( - {translateWithParameters('system.released_x', formattedDate)} - )} - - )} - {lastUpgrade.changeLogUrl && ( - - {translate('system.release_notes')} - - )} -
- - -
- ); -} diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeNotif.tsx b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeNotif.tsx index 5655488d6d8..e6f7c4c0903 100644 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeNotif.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeNotif.tsx @@ -19,21 +19,18 @@ */ import * as React from 'react'; import { getSystemUpgrades } from '../../../../api/system'; -import { Button } from '../../../../components/controls/buttons'; import { Alert } from '../../../../components/ui/Alert'; +import SystemUpgradeButton from '../../../../components/upgrade/SystemUpgradeButton'; import { translate } from '../../../../helpers/l10n'; import { SystemUpgrade } from '../../../../types/system'; -import { groupUpgrades, sortUpgrades } from '../../utils'; -import SystemUpgradeForm from './SystemUpgradeForm'; interface State { - systemUpgrades: SystemUpgrade[][]; - openSystemUpgradeForm: boolean; + systemUpgrades: SystemUpgrade[]; } export default class SystemUpgradeNotif extends React.PureComponent<{}, State> { mounted = false; - state: State = { openSystemUpgradeForm: false, systemUpgrades: [] }; + state: State = { systemUpgrades: [] }; componentDidMount() { this.mounted = true; @@ -48,20 +45,12 @@ export default class SystemUpgradeNotif extends React.PureComponent<{}, State> { getSystemUpgrades().then( ({ upgrades }) => { if (this.mounted) { - this.setState({ systemUpgrades: groupUpgrades(sortUpgrades(upgrades)) }); + this.setState({ systemUpgrades: upgrades }); } }, () => {} ); - handleOpenSystemUpgradeForm = () => { - this.setState({ openSystemUpgradeForm: true }); - }; - - handleCloseSystemUpgradeForm = () => { - this.setState({ openSystemUpgradeForm: false }); - }; - render() { const { systemUpgrades } = this.state; @@ -73,16 +62,8 @@ export default class SystemUpgradeNotif extends React.PureComponent<{}, State> {
{translate('system.new_version_available')} - + - {this.state.openSystemUpgradeForm && ( - - )}
); } diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeForm-test.tsx b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeForm-test.tsx deleted file mode 100644 index 02bf8a136bb..00000000000 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeForm-test.tsx +++ /dev/null @@ -1,82 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { EditionKey } from '../../../../../types/editions'; -import { SystemUpgradeForm } from '../SystemUpgradeForm'; - -const UPGRADES = [ - [ - { - version: '6.4', - description: 'Version 6.4 description', - releaseDate: '2017-06-02', - changeLogUrl: 'changelogurl', - downloadUrl: 'downloadurl', - plugins: {} - }, - { - version: '6.3', - description: 'Version 6.3 description', - releaseDate: '2017-05-02', - changeLogUrl: 'changelogurl', - downloadUrl: 'downloadurl', - plugins: {} - } - ], - [ - { - version: '5.6.7', - description: 'Version 5.6.7 description', - releaseDate: '2017-03-01', - changeLogUrl: 'changelogurl', - downloadUrl: 'downloadurl', - plugins: {} - }, - { - version: '5.6.6', - description: 'Version 5.6.6 description', - releaseDate: '2017-04-02', - changeLogUrl: 'changelogurl', - downloadUrl: 'downloadurl', - plugins: {} - }, - { - version: '5.6.5', - description: 'Version 5.6.5 description', - releaseDate: '2017-03-01', - changeLogUrl: 'changelogurl', - downloadUrl: 'downloadurl', - plugins: {} - } - ] -]; - -it('should display correctly', () => { - expect( - shallow( - - ) - ).toMatchSnapshot(); -}); diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeIntermediate-test.tsx b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeIntermediate-test.tsx deleted file mode 100644 index c2d05b1853f..00000000000 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeIntermediate-test.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { click } from '../../../../../helpers/testUtils'; -import SystemUpgradeIntermediate from '../SystemUpgradeIntermediate'; - -const UPGRADES = [ - { - version: '5.6.6', - description: 'Version 5.6.6 description', - releaseDate: '2017-04-02', - changeLogUrl: 'changelogurl', - downloadUrl: 'downloadurl', - plugins: {} - }, - { - version: '5.6.5', - description: 'Version 5.6.5 description', - releaseDate: '2017-03-01', - changeLogUrl: 'changelogurl', - downloadUrl: 'downloadurl', - plugins: {} - } -]; - -it('should display correctly', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - wrapper.setState({ showMore: true }); - expect(wrapper).toMatchSnapshot(); -}); - -it('should allow to show and hide intermediates', () => { - const wrapper = shallow(); - expect(wrapper.find('.system-upgrade-intermediate').exists()).toBe(false); - click(wrapper.find('ButtonLink')); - expect(wrapper.find('.system-upgrade-intermediate').exists()).toBe(true); - click(wrapper.find('ButtonLink')); - expect(wrapper.find('.system-upgrade-intermediate').exists()).toBe(false); -}); diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeItem-test.tsx b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeItem-test.tsx deleted file mode 100644 index 6b775f034df..00000000000 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeItem-test.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { EditionKey } from '../../../../../types/editions'; -import SystemUpgradeItem, { SystemUpgradeItemProps } from '../SystemUpgradeItem'; - -it('should display correctly', () => { - expect(shallowRender()).toMatchSnapshot(); - expect(shallowRender({ isLatestVersion: false })).toMatchSnapshot(); - expect(shallowRender({ edition: EditionKey.developer })).toMatchSnapshot(); - expect(shallowRender({ edition: EditionKey.enterprise })).toMatchSnapshot(); - expect(shallowRender({ edition: EditionKey.datacenter })).toMatchSnapshot(); - // Fallback to Community. - expect( - shallowRender({ - systemUpgrades: [ - { - version: '5.6.7', - description: 'Version 5.6.7 description', - releaseDate: '2017-03-01', - changeLogUrl: 'http://changelog.url/', - downloadUrl: 'http://download.url/community' - } - ] - }) - ).toMatchSnapshot(); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeNotif-test.tsx b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeNotif-test.tsx index 7ad1e031157..61673af52a2 100644 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeNotif-test.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeNotif-test.tsx @@ -20,7 +20,7 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import { getSystemUpgrades } from '../../../../../api/system'; -import { click, waitAndUpdate } from '../../../../../helpers/testUtils'; +import { waitAndUpdate } from '../../../../../helpers/testUtils'; import SystemUpgradeNotif from '../SystemUpgradeNotif'; jest.mock('../../../../../api/system', () => ({ @@ -83,9 +83,6 @@ it('should render correctly', async () => { expect(getSystemUpgrades).toHaveBeenCalled(); expect(wrapper).toMatchSnapshot(); - - click(wrapper.find('Button')); - expect(wrapper).toMatchSnapshot(); }); it('should display nothing', async () => { diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeForm-test.tsx.snap deleted file mode 100644 index e1c80419910..00000000000 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeForm-test.tsx.snap +++ /dev/null @@ -1,95 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should display correctly 1`] = ` - -
-

- system.system_upgrade -

-
-
- - -
- -
-`; diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeIntermediate-test.tsx.snap b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeIntermediate-test.tsx.snap deleted file mode 100644 index 763ab35301a..00000000000 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeIntermediate-test.tsx.snap +++ /dev/null @@ -1,63 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should display correctly 1`] = ` -
- - system.show_intermediate_versions - - -
-`; - -exports[`should display correctly 2`] = ` -
- - system.hide_intermediate_versions - - -
- - - -

- Version 5.6.6 description -

-
-
- - - -

- Version 5.6.5 description -

-
-
-`; diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeItem-test.tsx.snap b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeItem-test.tsx.snap deleted file mode 100644 index 51d35d94dc6..00000000000 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeItem-test.tsx.snap +++ /dev/null @@ -1,592 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should display correctly 1`] = ` -
-

- - system.latest_version - - - system.see_whats_new - -

-

- - SonarQube - 5.6.7 - , - } - } - /> -

-

- Version 5.6.7 description -

- - - -
-`; - -exports[`should display correctly 2`] = ` -
-

- - system.lts_version - -

-

- - SonarQube - 5.6.7 - , - } - } - /> -

-

- Version 5.6.7 description -

- - - -
-`; - -exports[`should display correctly 3`] = ` -
-

- - system.latest_version - - - system.see_whats_new - -

-

- - SonarQube - 5.6.7 - , - } - } - /> -

-

- Version 5.6.7 description -

- - - -
-`; - -exports[`should display correctly 4`] = ` -
-

- - system.latest_version - - - system.see_whats_new - -

-

- - SonarQube - 5.6.7 - , - } - } - /> -

-

- Version 5.6.7 description -

- - - -
-`; - -exports[`should display correctly 5`] = ` -
-

- - system.latest_version - - - system.see_whats_new - -

-

- - SonarQube - 5.6.7 - , - } - } - /> -

-

- Version 5.6.7 description -

- - - -
-`; - -exports[`should display correctly 6`] = ` -
-

- - system.latest_version - - - system.see_whats_new - -

-

- - SonarQube - 5.6.7 - , - } - } - /> -

-

- Version 5.6.7 description -

- - - -
-`; diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeNotif-test.tsx.snap b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeNotif-test.tsx.snap index 88e3fa2d032..3e3d05a2f7b 100644 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeNotif-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeNotif-test.tsx.snap @@ -8,61 +8,32 @@ exports[`should render correctly 1`] = ` variant="info" > system.new_version_available - - - -`; - -exports[`should render correctly 2`] = ` -
- - system.new_version_available - - - + ] + } + /> +
`; diff --git a/server/sonar-web/src/main/js/apps/system/utils.ts b/server/sonar-web/src/main/js/apps/system/utils.ts index 4a4c7f28242..a9857503449 100644 --- a/server/sonar-web/src/main/js/apps/system/utils.ts +++ b/server/sonar-web/src/main/js/apps/system/utils.ts @@ -17,10 +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 { each, groupBy, memoize, omit, omitBy, pickBy, sortBy } from 'lodash'; +import { each, memoize, omit, omitBy, pickBy, sortBy } from 'lodash'; import { formatMeasure } from '../../helpers/measures'; import { cleanQuery, parseAsArray, parseAsString, serializeStringArray } from '../../helpers/query'; -import { SystemUpgrade } from '../../types/system'; export interface Query { expandedCards: string[]; @@ -229,17 +228,3 @@ export const serializeQuery = memoize( expand: serializeStringArray(query.expandedCards) }) ); - -export function sortUpgrades(upgrades: SystemUpgrade[]): SystemUpgrade[] { - return sortBy(upgrades, [ - (upgrade: SystemUpgrade) => -Number(upgrade.version.split('.')[0]), - (upgrade: SystemUpgrade) => -Number(upgrade.version.split('.')[1] || 0), - (upgrade: SystemUpgrade) => -Number(upgrade.version.split('.')[2] || 0) - ]); -} - -export function groupUpgrades(upgrades: SystemUpgrade[]): SystemUpgrade[][] { - const groupedVersions = groupBy(upgrades, upgrade => upgrade.version.split('.')[0]); - const sortedMajor = sortBy(Object.keys(groupedVersions), key => -Number(key)); - return sortedMajor.map(key => groupedVersions[key]); -} diff --git a/server/sonar-web/src/main/js/components/ui/Alert.tsx b/server/sonar-web/src/main/js/components/ui/Alert.tsx index 0c7f2435632..5ed07a1d665 100644 --- a/server/sonar-web/src/main/js/components/ui/Alert.tsx +++ b/server/sonar-web/src/main/js/components/ui/Alert.tsx @@ -30,7 +30,7 @@ import InfoIcon from '../icons/InfoIcon'; import DeferredSpinner from './DeferredSpinner'; type AlertDisplay = 'banner' | 'inline' | 'block'; -type AlertVariant = 'error' | 'warning' | 'success' | 'info' | 'loading'; +export type AlertVariant = 'error' | 'warning' | 'success' | 'info' | 'loading'; export interface AlertProps { display?: AlertDisplay; diff --git a/server/sonar-web/src/main/js/components/ui/DismissableAlert.tsx b/server/sonar-web/src/main/js/components/ui/DismissableAlert.tsx index b6f5e08fb33..2d3ae9f0a30 100644 --- a/server/sonar-web/src/main/js/components/ui/DismissableAlert.tsx +++ b/server/sonar-web/src/main/js/components/ui/DismissableAlert.tsx @@ -45,25 +45,25 @@ export default function DismissableAlert(props: DismissableAlertProps) { }, [alertKey]); const hideAlert = () => { + window.dispatchEvent(new Event('resize')); save(DISMISSED_ALERT_STORAGE_KEY, 'true', alertKey); }; return !show ? null : ( - -
-
{children}
- { - hideAlert(); - setShow(false); - }}> - - -
-
+
+ +
+
{children}
+ { + hideAlert(); + setShow(false); + }}> + + +
+
+
); } diff --git a/server/sonar-web/src/main/js/components/ui/__tests__/__snapshots__/DismissableAlert-test.tsx.snap b/server/sonar-web/src/main/js/components/ui/__tests__/__snapshots__/DismissableAlert-test.tsx.snap index 7583076acd6..4c3e6bb89e7 100644 --- a/server/sonar-web/src/main/js/components/ui/__tests__/__snapshots__/DismissableAlert-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/ui/__tests__/__snapshots__/DismissableAlert-test.tsx.snap @@ -1,59 +1,67 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`should render correctly 1`] = ` - -
-
- My content +
+
+ My content +
+ + +
- - - -
- + +
`; exports[`should render correctly with a non-default display 1`] = ` - -
-
- My content +
+
+ My content +
+ + +
- - - -
- + +
`; diff --git a/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeButton.tsx b/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeButton.tsx new file mode 100644 index 00000000000..cd3a527ef9b --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeButton.tsx @@ -0,0 +1,63 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { translate } from '../../helpers/l10n'; +import { SystemUpgrade } from '../../types/system'; +import { Button } from '../controls/buttons'; +import SystemUpgradeForm from './SystemUpgradeForm'; +import { groupUpgrades, sortUpgrades } from './utils'; + +interface Props { + systemUpgrades: SystemUpgrade[]; +} + +interface State { + openSystemUpgradeForm: boolean; +} + +export default class SystemUpgradeButton extends React.PureComponent { + state: State = { openSystemUpgradeForm: false }; + + handleOpenSystemUpgradeForm = () => { + this.setState({ openSystemUpgradeForm: true }); + }; + + handleCloseSystemUpgradeForm = () => { + this.setState({ openSystemUpgradeForm: false }); + }; + + render() { + const { systemUpgrades } = this.props; + const { openSystemUpgradeForm } = this.state; + return ( + <> + + {openSystemUpgradeForm && ( + + )} + + ); + } +} diff --git a/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeForm.tsx b/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeForm.tsx new file mode 100644 index 00000000000..9a845dbc573 --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeForm.tsx @@ -0,0 +1,79 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { translate } from '../../helpers/l10n'; +import { EditionKey } from '../../types/editions'; +import { SystemUpgrade } from '../../types/system'; +import { ResetButtonLink } from '../controls/buttons'; +import Modal from '../controls/Modal'; +import { withAppState } from '../hoc/withAppState'; +import SystemUpgradeItem from './SystemUpgradeItem'; + +interface Props { + appState: Pick; + onClose: () => void; + systemUpgrades: SystemUpgrade[][]; +} + +interface State { + upgrading: boolean; +} + +export class SystemUpgradeForm extends React.PureComponent { + state: State = { upgrading: false }; + + render() { + const { upgrading } = this.state; + const { appState, systemUpgrades } = this.props; + const header = translate('system.system_upgrade'); + return ( + +
+

{header}

+
+
+ {systemUpgrades.map((upgrades, idx) => ( + + ))} +
+
+ {upgrading && } + + {translate('system.see_sonarqube_downloads')} + + {translate('cancel')} +
+
+ ); + } +} + +export default withAppState(SystemUpgradeForm); diff --git a/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeIntermediate.tsx b/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeIntermediate.tsx new file mode 100644 index 00000000000..db09a7ef8ce --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeIntermediate.tsx @@ -0,0 +1,86 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { translate } from '../../helpers/l10n'; +import { SystemUpgrade } from '../../types/system'; +import { ButtonLink } from '../controls/buttons'; +import DropdownIcon from '../icons/DropdownIcon'; +import DateFormatter from '../intl/DateFormatter'; + +interface Props { + className?: string; + upgrades: SystemUpgrade[]; +} + +interface State { + showMore: boolean; +} + +export default class SystemUpgradeIntermediate extends React.PureComponent { + state: State = { showMore: false }; + + toggleIntermediatVersions = () => { + this.setState(state => ({ showMore: !state.showMore })); + }; + + render() { + const { showMore } = this.state; + const { upgrades } = this.props; + if (upgrades.length <= 0) { + return null; + } + + return ( +
+ + {showMore + ? translate('system.hide_intermediate_versions') + : translate('system.show_intermediate_versions')} + + + {showMore && + upgrades.map(upgrade => ( +
+ {upgrade.releaseDate && ( + + {formattedDate => ( +

+ SonarQube {upgrade.version} + {formattedDate} + {upgrade.changeLogUrl && ( + + {translate('system.release_notes')} + + )} +

+ )} +
+ )} + {upgrade.description &&

{upgrade.description}

} +
+ ))} +
+ ); + } +} diff --git a/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeItem.tsx b/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeItem.tsx new file mode 100644 index 00000000000..756455472c6 --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/SystemUpgradeItem.tsx @@ -0,0 +1,109 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { + getEdition, + getEditionDownloadFilename, + getEditionDownloadUrl +} from '../../helpers/editions'; +import { translate, translateWithParameters } from '../../helpers/l10n'; +import { EditionKey } from '../../types/editions'; +import { SystemUpgrade } from '../../types/system'; +import DateFormatter from '../intl/DateFormatter'; +import SystemUpgradeIntermediate from './SystemUpgradeIntermediate'; + +export interface SystemUpgradeItemProps { + edition: EditionKey | undefined; + isLatestVersion: boolean; + systemUpgrades: SystemUpgrade[]; +} + +export default function SystemUpgradeItem(props: SystemUpgradeItemProps) { + const { edition, isLatestVersion, systemUpgrades } = props; + const lastUpgrade = systemUpgrades[0]; + const downloadUrl = getEditionDownloadUrl( + getEdition(edition || EditionKey.community), + lastUpgrade + ); + + return ( +
+

+ + {isLatestVersion ? translate('system.latest_version') : translate('system.lts_version')} + + {isLatestVersion && ( + + {translate('system.see_whats_new')} + + )} +

+

+ SonarQube {lastUpgrade.version} }} + /> +

+

{lastUpgrade.description}

+
+ {lastUpgrade.releaseDate && ( + + {formattedDate => ( + {translateWithParameters('system.released_x', formattedDate)} + )} + + )} + {lastUpgrade.changeLogUrl && ( + + {translate('system.release_notes')} + + )} +
+ + +
+ ); +} diff --git a/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgradeButton-test.tsx b/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgradeButton-test.tsx new file mode 100644 index 00000000000..df853f7207c --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgradeButton-test.tsx @@ -0,0 +1,38 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { click } from '../../../helpers/testUtils'; +import { Button } from '../../controls/buttons'; +import SystemUpgradeButton from '../SystemUpgradeButton'; +import SystemUpgradeForm from '../SystemUpgradeForm'; + +it('should open modal correctly', () => { + const wrapper = shallowRender(); + expect(wrapper).toMatchSnapshot(); + click(wrapper.find(Button)); + expect(wrapper.find(SystemUpgradeForm)).toBeDefined(); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgradeForm-test.tsx b/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgradeForm-test.tsx new file mode 100644 index 00000000000..7e33af49609 --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgradeForm-test.tsx @@ -0,0 +1,82 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { EditionKey } from '../../../types/editions'; +import { SystemUpgradeForm } from '../SystemUpgradeForm'; + +const UPGRADES = [ + [ + { + version: '6.4', + description: 'Version 6.4 description', + releaseDate: '2017-06-02', + changeLogUrl: 'changelogurl', + downloadUrl: 'downloadurl', + plugins: {} + }, + { + version: '6.3', + description: 'Version 6.3 description', + releaseDate: '2017-05-02', + changeLogUrl: 'changelogurl', + downloadUrl: 'downloadurl', + plugins: {} + } + ], + [ + { + version: '5.6.7', + description: 'Version 5.6.7 description', + releaseDate: '2017-03-01', + changeLogUrl: 'changelogurl', + downloadUrl: 'downloadurl', + plugins: {} + }, + { + version: '5.6.6', + description: 'Version 5.6.6 description', + releaseDate: '2017-04-02', + changeLogUrl: 'changelogurl', + downloadUrl: 'downloadurl', + plugins: {} + }, + { + version: '5.6.5', + description: 'Version 5.6.5 description', + releaseDate: '2017-03-01', + changeLogUrl: 'changelogurl', + downloadUrl: 'downloadurl', + plugins: {} + } + ] +]; + +it('should display correctly', () => { + expect( + shallow( + + ) + ).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgradeIntermediate-test.tsx b/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgradeIntermediate-test.tsx new file mode 100644 index 00000000000..23d79ea71d5 --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgradeIntermediate-test.tsx @@ -0,0 +1,58 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { click } from '../../../helpers/testUtils'; +import SystemUpgradeIntermediate from '../SystemUpgradeIntermediate'; + +const UPGRADES = [ + { + version: '5.6.6', + description: 'Version 5.6.6 description', + releaseDate: '2017-04-02', + changeLogUrl: 'changelogurl', + downloadUrl: 'downloadurl', + plugins: {} + }, + { + version: '5.6.5', + description: 'Version 5.6.5 description', + releaseDate: '2017-03-01', + changeLogUrl: 'changelogurl', + downloadUrl: 'downloadurl', + plugins: {} + } +]; + +it('should display correctly', () => { + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); + wrapper.setState({ showMore: true }); + expect(wrapper).toMatchSnapshot(); +}); + +it('should allow to show and hide intermediates', () => { + const wrapper = shallow(); + expect(wrapper.find('.system-upgrade-intermediate').exists()).toBe(false); + click(wrapper.find('ButtonLink')); + expect(wrapper.find('.system-upgrade-intermediate').exists()).toBe(true); + click(wrapper.find('ButtonLink')); + expect(wrapper.find('.system-upgrade-intermediate').exists()).toBe(false); +}); diff --git a/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgradeItem-test.tsx b/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgradeItem-test.tsx new file mode 100644 index 00000000000..ba705ab5238 --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgradeItem-test.tsx @@ -0,0 +1,83 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { EditionKey } from '../../../types/editions'; +import SystemUpgradeItem, { SystemUpgradeItemProps } from '../SystemUpgradeItem'; + +it('should display correctly', () => { + expect(shallowRender()).toMatchSnapshot(); + expect(shallowRender({ isLatestVersion: false })).toMatchSnapshot(); + expect(shallowRender({ edition: EditionKey.developer })).toMatchSnapshot(); + expect(shallowRender({ edition: EditionKey.enterprise })).toMatchSnapshot(); + expect(shallowRender({ edition: EditionKey.datacenter })).toMatchSnapshot(); + // Fallback to Community. + expect( + shallowRender({ + systemUpgrades: [ + { + version: '5.6.7', + description: 'Version 5.6.7 description', + releaseDate: '2017-03-01', + changeLogUrl: 'http://changelog.url/', + downloadUrl: 'http://download.url/community' + } + ] + }) + ).toMatchSnapshot(); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeButton-test.tsx.snap b/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeButton-test.tsx.snap new file mode 100644 index 00000000000..037b14bb219 --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeButton-test.tsx.snap @@ -0,0 +1,12 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should open modal correctly 1`] = ` + + + +`; diff --git a/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeForm-test.tsx.snap b/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeForm-test.tsx.snap new file mode 100644 index 00000000000..e1c80419910 --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeForm-test.tsx.snap @@ -0,0 +1,95 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should display correctly 1`] = ` + +
+

+ system.system_upgrade +

+
+
+ + +
+ +
+`; diff --git a/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeIntermediate-test.tsx.snap b/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeIntermediate-test.tsx.snap new file mode 100644 index 00000000000..763ab35301a --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeIntermediate-test.tsx.snap @@ -0,0 +1,63 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should display correctly 1`] = ` +
+ + system.show_intermediate_versions + + +
+`; + +exports[`should display correctly 2`] = ` +
+ + system.hide_intermediate_versions + + +
+ + + +

+ Version 5.6.6 description +

+
+
+ + + +

+ Version 5.6.5 description +

+
+
+`; diff --git a/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeItem-test.tsx.snap b/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeItem-test.tsx.snap new file mode 100644 index 00000000000..51d35d94dc6 --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeItem-test.tsx.snap @@ -0,0 +1,592 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should display correctly 1`] = ` +
+

+ + system.latest_version + + + system.see_whats_new + +

+

+ + SonarQube + 5.6.7 + , + } + } + /> +

+

+ Version 5.6.7 description +

+ + + +
+`; + +exports[`should display correctly 2`] = ` +
+

+ + system.lts_version + +

+

+ + SonarQube + 5.6.7 + , + } + } + /> +

+

+ Version 5.6.7 description +

+ + + +
+`; + +exports[`should display correctly 3`] = ` +
+

+ + system.latest_version + + + system.see_whats_new + +

+

+ + SonarQube + 5.6.7 + , + } + } + /> +

+

+ Version 5.6.7 description +

+ + + +
+`; + +exports[`should display correctly 4`] = ` +
+

+ + system.latest_version + + + system.see_whats_new + +

+

+ + SonarQube + 5.6.7 + , + } + } + /> +

+

+ Version 5.6.7 description +

+ + + +
+`; + +exports[`should display correctly 5`] = ` +
+

+ + system.latest_version + + + system.see_whats_new + +

+

+ + SonarQube + 5.6.7 + , + } + } + /> +

+

+ Version 5.6.7 description +

+ + + +
+`; + +exports[`should display correctly 6`] = ` +
+

+ + system.latest_version + + + system.see_whats_new + +

+

+ + SonarQube + 5.6.7 + , + } + } + /> +

+

+ Version 5.6.7 description +

+ + + +
+`; diff --git a/server/sonar-web/src/main/js/components/upgrade/__tests__/utils-test.ts b/server/sonar-web/src/main/js/components/upgrade/__tests__/utils-test.ts new file mode 100644 index 00000000000..34d19105097 --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/__tests__/utils-test.ts @@ -0,0 +1,69 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { SystemUpgrade } from '../../../types/system'; +import * as u from '../utils'; + +describe('sortUpgrades', () => { + it('should sort correctly versions', () => { + expect( + u.sortUpgrades([ + { version: '5.4.2' }, + { version: '5.10' }, + { version: '5.1' }, + { version: '5.4' } + ] as SystemUpgrade[]) + ).toEqual([{ version: '5.10' }, { version: '5.4.2' }, { version: '5.4' }, { version: '5.1' }]); + expect( + u.sortUpgrades([ + { version: '5.10' }, + { version: '5.1.2' }, + { version: '6.0' }, + { version: '6.9' } + ] as SystemUpgrade[]) + ).toEqual([{ version: '6.9' }, { version: '6.0' }, { version: '5.10' }, { version: '5.1.2' }]); + }); +}); + +describe('groupUpgrades', () => { + it('should group correctly', () => { + expect( + u.groupUpgrades([ + { version: '5.10' }, + { version: '5.4.2' }, + { version: '5.4' }, + { version: '5.1' } + ] as SystemUpgrade[]) + ).toEqual([ + [{ version: '5.10' }, { version: '5.4.2' }, { version: '5.4' }, { version: '5.1' }] + ]); + expect( + u.groupUpgrades([ + { version: '6.9' }, + { version: '6.7' }, + { version: '6.0' }, + { version: '5.10' }, + { version: '5.4.2' } + ] as SystemUpgrade[]) + ).toEqual([ + [{ version: '6.9' }, { version: '6.7' }, { version: '6.0' }], + [{ version: '5.10' }, { version: '5.4.2' }] + ]); + }); +}); diff --git a/server/sonar-web/src/main/js/components/upgrade/utils.ts b/server/sonar-web/src/main/js/components/upgrade/utils.ts new file mode 100644 index 00000000000..e58b76a2bc0 --- /dev/null +++ b/server/sonar-web/src/main/js/components/upgrade/utils.ts @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { groupBy, sortBy } from 'lodash'; +import { SystemUpgrade } from '../../types/system'; + +export function sortUpgrades(upgrades: SystemUpgrade[]): SystemUpgrade[] { + return sortBy(upgrades, [ + (upgrade: SystemUpgrade) => -Number(upgrade.version.split('.')[0]), + (upgrade: SystemUpgrade) => -Number(upgrade.version.split('.')[1] || 0), + (upgrade: SystemUpgrade) => -Number(upgrade.version.split('.')[2] || 0) + ]); +} + +export function groupUpgrades(upgrades: SystemUpgrade[]): SystemUpgrade[][] { + const groupedVersions = groupBy(upgrades, upgrade => upgrade.version.split('.')[0]); + const sortedMajor = sortBy(Object.keys(groupedVersions), key => -Number(key)); + return sortedMajor.map(key => groupedVersions[key]); +} diff --git a/server/sonar-web/src/main/js/helpers/mocks/system-upgrades.ts b/server/sonar-web/src/main/js/helpers/mocks/system-upgrades.ts new file mode 100644 index 00000000000..ba1249c30cf --- /dev/null +++ b/server/sonar-web/src/main/js/helpers/mocks/system-upgrades.ts @@ -0,0 +1,31 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { SystemUpgrade } from '../../types/system'; + +export function mockUpgrades(override: Partial): SystemUpgrade { + return { + version: '5.6.7', + description: 'Version 5.6.7 description', + releaseDate: '2017-03-01', + changeLogUrl: 'changelogurl', + downloadUrl: 'downloadurl', + ...override + }; +} diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 79260f4b39a..6d422fa42e7 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -451,6 +451,17 @@ qualifier.description.VW=Potentially multi-level, management-oriented overview a qualifier.description.SVW=Potentially multi-level, management-oriented overview aggregation. qualifier.description.APP=Single-level aggregation with a technical focus and a project-like homepage. + +#------------------------------------------------------------------------------ +# +# Admin notification +# +#------------------------------------------------------------------------------ +admin_notification.update.new_minor_version=There’s a new version of SonarQube available. Update to enjoy the latest updates and features. +admin_notification.update.new_patch=There’s an update available for your SonarQube instance. Please update to make sure you benefit from the latest security and bug fixes. +admin_notification.update.pre_lts=You’re running a version of SonarQube that has reached end of life. Please upgrade to a supported version at your earliest convenience. +admin_notification.update.previous_lts=You’re running a version of SonarQube that is past end of life. Please upgrade to a supported version immediately. + #------------------------------------------------------------------------------ # # PROJECT LINKS