aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-web/src/main/js/api/system.ts16
-rw-r--r--server/sonar-web/src/main/js/apps/marketplace/App.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/marketplace/style.css8
-rw-r--r--server/sonar-web/src/main/js/apps/system/__tests__/utils-test.ts50
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/App.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/SystemUpgradeNotif.tsx71
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeForm.tsx89
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeIntermediate.tsx86
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeItem.tsx73
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeNotif.tsx81
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeForm-test.tsx75
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeIntermediate-test.tsx58
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeItem-test.tsx59
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeNotif-test.tsx123
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeForm-test.tsx.snap100
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeIntermediate-test.tsx.snap57
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeItem-test.tsx.snap84
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeNotif-test.tsx.snap23
-rw-r--r--server/sonar-web/src/main/js/apps/system/styles.css14
-rw-r--r--server/sonar-web/src/main/js/apps/system/utils.ts19
-rw-r--r--server/sonar-web/src/main/less/components/alerts.less10
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties14
22 files changed, 1101 insertions, 15 deletions
diff --git a/server/sonar-web/src/main/js/api/system.ts b/server/sonar-web/src/main/js/api/system.ts
index a98d8bdff8a..69aef039e66 100644
--- a/server/sonar-web/src/main/js/api/system.ts
+++ b/server/sonar-web/src/main/js/api/system.ts
@@ -58,6 +58,15 @@ export interface ClusterSysInfo extends SysInfo {
'Search Nodes': NodeInfo[];
}
+export interface SystemUpgrade {
+ version: string;
+ description: string;
+ releaseDate: string;
+ changeLogUrl: string;
+ downloadUrl: string;
+ plugins: any;
+}
+
export function setLogLevel(level: string): Promise<void | Response> {
return post('/api/system/change_log_level', { level }).catch(throwGlobalError);
}
@@ -70,6 +79,13 @@ export function getSystemStatus(): Promise<any> {
return getJSON('/api/system/status');
}
+export function getSystemUpgrades(): Promise<{
+ upgrades: SystemUpgrade[];
+ updateCenterRefresh: string;
+}> {
+ return getJSON('/api/system/upgrades');
+}
+
export function getMigrationStatus(): Promise<any> {
return getJSON('/api/system/db_migration_status');
}
diff --git a/server/sonar-web/src/main/js/apps/marketplace/App.tsx b/server/sonar-web/src/main/js/apps/marketplace/App.tsx
index 969c1c7135c..fd737dc037f 100644
--- a/server/sonar-web/src/main/js/apps/marketplace/App.tsx
+++ b/server/sonar-web/src/main/js/apps/marketplace/App.tsx
@@ -185,7 +185,7 @@ export default class App extends React.PureComponent<Props, State> {
};
updateEditionStatus = (editionStatus: EditionStatus) => {
- this.setState({ editionStatus: editionStatus });
+ this.setState({ editionStatus });
if (this.timer) {
global.clearTimeout(this.timer);
this.timer = undefined;
@@ -211,7 +211,7 @@ export default class App extends React.PureComponent<Props, State> {
return (
<div className="page page-limited" id="marketplace-page">
<Helmet title={translate('marketplace.page')} />
- <div className="marketplace-notifs">
+ <div className="page-notifs">
{editionStatus && (
<EditionsStatusNotif
editions={editions}
diff --git a/server/sonar-web/src/main/js/apps/marketplace/style.css b/server/sonar-web/src/main/js/apps/marketplace/style.css
index 6363589603f..037a0c133d9 100644
--- a/server/sonar-web/src/main/js/apps/marketplace/style.css
+++ b/server/sonar-web/src/main/js/apps/marketplace/style.css
@@ -30,11 +30,3 @@
align-items: baseline;
justify-content: space-between;
}
-
-.marketplace-notifs .alert {
- padding: 8px;
-}
-
-.marketplace-notifs .alert:last-child {
- margin-bottom: 16px;
-}
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 98cea1804e5..c95be747821 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
@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as u from '../utils';
-import { ClusterSysInfo, SysInfo } from '../../../api/system';
+import { ClusterSysInfo, SysInfo, SystemUpgrade } from '../../../api/system';
describe('parseQuery', () => {
it('should correctly parse the expand array', () => {
@@ -84,3 +84,51 @@ describe('getSystemLogsLevel', () => {
expect(u.getSystemLogsLevel({ System: {} } as SysInfo)).toBe('INFO');
});
});
+
+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/apps/system/components/App.tsx b/server/sonar-web/src/main/js/apps/system/components/App.tsx
index 38679882597..c6d333563ab 100644
--- a/server/sonar-web/src/main/js/apps/system/components/App.tsx
+++ b/server/sonar-web/src/main/js/apps/system/components/App.tsx
@@ -23,6 +23,7 @@ import Helmet from 'react-helmet';
import ClusterSysInfos from './ClusterSysInfos';
import PageHeader from './PageHeader';
import StandaloneSysInfos from './StandaloneSysInfos';
+import SystemUpgradeNotif from './system-upgrade/SystemUpgradeNotif';
import { translate } from '../../../helpers/l10n';
import { ClusterSysInfo, getSystemInfo, SysInfo } from '../../../api/system';
import { getSystemLogsLevel, isCluster, parseQuery, Query, serializeQuery } from '../utils';
@@ -117,6 +118,7 @@ export default class App extends React.PureComponent<Props, State> {
return (
<div className="page page-limited">
<Helmet title={translate('system_info.page')} />
+ <SystemUpgradeNotif />
<PageHeader
loading={loading}
isCluster={isCluster(sysInfoData)}
diff --git a/server/sonar-web/src/main/js/apps/system/components/SystemUpgradeNotif.tsx b/server/sonar-web/src/main/js/apps/system/components/SystemUpgradeNotif.tsx
new file mode 100644
index 00000000000..cdb15d71939
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/system/components/SystemUpgradeNotif.tsx
@@ -0,0 +1,71 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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 { getSystemUpgrades, SystemUpgrade } from '../../../api/system';
+import { translate } from '../../../helpers/l10n';
+
+interface State {
+ systemUpgrades?: SystemUpgrade[];
+}
+
+export default class SystemUpgradeNotif extends React.PureComponent<{}, State> {
+ mounted: boolean;
+ state: State = {};
+
+ componentDidMount() {
+ this.mounted = true;
+ this.fetchSystemUpgrades();
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ fetchSystemUpgrades = () =>
+ getSystemUpgrades().then(
+ ({ upgrades }) => {
+ if (this.mounted) {
+ this.setState({ systemUpgrades: upgrades });
+ }
+ },
+ () => {}
+ );
+
+ handleLearnMore = () => {};
+
+ render() {
+ const { systemUpgrades } = this.state;
+
+ if (!systemUpgrades || systemUpgrades.length <= 0) {
+ return null;
+ }
+
+ return (
+ <div className="page-notifs">
+ <div className="alert alert-info">
+ {translate('system.new_version_available')}
+ <button className="spacer-left" onClick={this.handleLearnMore}>
+ {translate('learn_more')}
+ </button>
+ </div>
+ </div>
+ );
+ }
+}
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
new file mode 100644
index 00000000000..9370ea4493b
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeForm.tsx
@@ -0,0 +1,89 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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 Modal from 'react-modal';
+import SystemUpgradeItem from './SystemUpgradeItem';
+import { SystemUpgrade } from '../../../../api/system';
+import { translate } from '../../../../helpers/l10n';
+
+interface Props {
+ systemUpgrades: SystemUpgrade[][];
+ onClose: () => void;
+}
+
+interface State {
+ upgrading: boolean;
+}
+
+export default class SystemUpgradeForm extends React.PureComponent<Props, State> {
+ state: State = { upgrading: false };
+
+ getBadge = (idx: number) => {
+ if (this.props.systemUpgrades.length <= 1) {
+ return undefined;
+ }
+ if (idx === 0) {
+ return translate('system.latest_version');
+ }
+ return translate('system.latest_lts_version');
+ };
+
+ handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ event.stopPropagation();
+ this.props.onClose();
+ };
+
+ render() {
+ const { upgrading } = this.state;
+ const { systemUpgrades } = this.props;
+ const header = translate('system.system_upgrade');
+ return (
+ <Modal
+ isOpen={true}
+ contentLabel={header}
+ className="modal"
+ overlayClassName="modal-overlay"
+ onRequestClose={this.props.onClose}>
+ <div className="modal-head">
+ <h2>{header}</h2>
+ </div>
+ <div className="modal-body">
+ {systemUpgrades.map((upgrades, idx) => (
+ <SystemUpgradeItem
+ key={upgrades[upgrades.length - 1].version}
+ badge={this.getBadge(idx)}
+ systemUpgrades={upgrades}
+ />
+ ))}
+ </div>
+ <div className="modal-foot">
+ {upgrading && <i className="spinner spacer-right" />}
+ <a className="pull-left" href="https://www.sonarqube.org/downloads/" target="_blank">
+ {translate('system.see_sonarqube_downloads')}
+ </a>
+ <a href="#" onClick={this.handleCancelClick}>
+ {translate('cancel')}
+ </a>
+ </div>
+ </Modal>
+ );
+ }
+}
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
new file mode 100644
index 00000000000..d428dc2310b
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeIntermediate.tsx
@@ -0,0 +1,86 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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 * as classNames from 'classnames';
+import DateFormatter from '../../../../components/intl/DateFormatter';
+import { SystemUpgrade } from '../../../../api/system';
+import { translate } from '../../../../helpers/l10n';
+
+interface Props {
+ className?: string;
+ upgrades: SystemUpgrade[];
+}
+
+interface State {
+ showMore: boolean;
+}
+
+export default class SystemUpgradeIntermediate extends React.PureComponent<Props, State> {
+ state: State = { showMore: false };
+
+ toggleIntermediatVersions = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
+ event.preventDefault();
+ event.stopPropagation();
+ this.setState(state => ({ showMore: !state.showMore }));
+ };
+
+ render() {
+ const { showMore } = this.state;
+ const { upgrades } = this.props;
+ if (upgrades.length <= 0) {
+ return null;
+ }
+
+ return (
+ <div className={this.props.className}>
+ <a
+ className="button-link little-spacer-bottom"
+ href="#"
+ onClick={this.toggleIntermediatVersions}>
+ {showMore ? (
+ translate('system.hide_intermediate_versions')
+ ) : (
+ translate('system.show_intermediate_versions')
+ )}
+ <i
+ className={classNames('little-spacer-left', {
+ 'icon-arrow-down': !showMore,
+ 'icon-arrow-up': showMore
+ })}
+ />
+ </a>
+ {showMore &&
+ upgrades.map(upgrade => (
+ <div key={upgrade.version} className="note system-upgrade-intermediate">
+ <DateFormatter date={upgrade.releaseDate} long={true}>
+ {formattedDate => (
+ <p>
+ <b className="little-spacer-right">SonarQube {upgrade.version}</b>
+ {formattedDate}
+ </p>
+ )}
+ </DateFormatter>
+ <p className="little-spacer-top">{upgrade.description}</p>
+ </div>
+ ))}
+ </div>
+ );
+ }
+}
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
new file mode 100644
index 00000000000..980cae8d2e1
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeItem.tsx
@@ -0,0 +1,73 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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 SystemUpgradeIntermediate from './SystemUpgradeIntermediate';
+import { SystemUpgrade } from '../../../../api/system';
+import { translate, translateWithParameters } from '../../../../helpers/l10n';
+
+interface Props {
+ badge?: string;
+ systemUpgrades: SystemUpgrade[];
+}
+
+export default function SystemUpgradeItem({ badge, systemUpgrades }: Props) {
+ const lastUpgrade = systemUpgrades[0];
+ return (
+ <div className="system-upgrade-version">
+ {badge && <span className="spacer-bottom badge badge-secondary">{badge}</span>}
+ <p>
+ <FormattedMessage
+ defaultMessage={translate('system.version_is_availble')}
+ id="system.version_is_availble"
+ values={{ version: <b>SonarQube {lastUpgrade.version}</b> }}
+ />
+ </p>
+ <p className="spacer-top">{lastUpgrade.description}</p>
+ <div className="big-spacer-top">
+ <DateFormatter date={lastUpgrade.releaseDate} long={true}>
+ {formattedDate => (
+ <span>{translateWithParameters('system.released_x', formattedDate)}</span>
+ )}
+ </DateFormatter>
+ <a className="spacer-left" href={lastUpgrade.changeLogUrl} target="_blank">
+ {translate('system.release_notes')}
+ </a>
+ </div>
+ <SystemUpgradeIntermediate className="spacer-top" upgrades={systemUpgrades.slice(1)} />
+ <div className="big-spacer-top">
+ <a
+ className="button"
+ download={`sonarqube-${lastUpgrade.version}.zip`}
+ href={lastUpgrade.downloadUrl}
+ target="blank">
+ {translateWithParameters('system.download_x', lastUpgrade.version)}
+ </a>
+ <a
+ className="spacer-left"
+ href="https://redirect.sonarsource.com/doc/upgrading.html"
+ target="_blank">
+ {translate('system.how_to_upgrade')}
+ </a>
+ </div>
+ </div>
+ );
+}
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
new file mode 100644
index 00000000000..42518738b3e
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeNotif.tsx
@@ -0,0 +1,81 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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 SystemUpgradeForm from './SystemUpgradeForm';
+import { getSystemUpgrades, SystemUpgrade } from '../../../../api/system';
+import { translate } from '../../../../helpers/l10n';
+import { sortUpgrades, groupUpgrades } from '../../utils';
+
+interface State {
+ systemUpgrades: SystemUpgrade[][];
+ openSystemUpgradeForm: boolean;
+}
+
+export default class SystemUpgradeNotif extends React.PureComponent<{}, State> {
+ mounted: boolean;
+ state: State = { openSystemUpgradeForm: false, systemUpgrades: [] };
+
+ componentDidMount() {
+ this.mounted = true;
+ this.fetchSystemUpgrade();
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ fetchSystemUpgrade = () =>
+ getSystemUpgrades().then(
+ ({ upgrades }) => {
+ if (this.mounted) {
+ this.setState({ systemUpgrades: groupUpgrades(sortUpgrades(upgrades)) });
+ }
+ },
+ () => {}
+ );
+
+ handleOpenSystemUpgradeForm = () => this.setState({ openSystemUpgradeForm: true });
+ handleCloseSystemUpgradeForm = () => this.setState({ openSystemUpgradeForm: false });
+
+ render() {
+ const { systemUpgrades } = this.state;
+
+ if (systemUpgrades.length <= 0) {
+ return null;
+ }
+
+ return (
+ <div className="page-notifs">
+ <div className="alert alert-info">
+ {translate('system.new_version_available')}
+ <button className="spacer-left" onClick={this.handleOpenSystemUpgradeForm}>
+ {translate('learn_more')}
+ </button>
+ </div>
+ {this.state.openSystemUpgradeForm && (
+ <SystemUpgradeForm
+ systemUpgrades={systemUpgrades}
+ onClose={this.handleCloseSystemUpgradeForm}
+ />
+ )}
+ </div>
+ );
+ }
+}
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
new file mode 100644
index 00000000000..1a8b987a230
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeForm-test.tsx
@@ -0,0 +1,75 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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 { shallow } from 'enzyme';
+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(<SystemUpgradeForm onClose={jest.fn()} systemUpgrades={UPGRADES} />)
+ ).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
new file mode 100644
index 00000000000..0718540be3b
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeIntermediate-test.tsx
@@ -0,0 +1,58 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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 { shallow } from 'enzyme';
+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(<SystemUpgradeIntermediate upgrades={UPGRADES} />);
+ expect(wrapper).toMatchSnapshot();
+ wrapper.setState({ showMore: true });
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('should allow to show and hide intermediates', () => {
+ const wrapper = shallow(<SystemUpgradeIntermediate upgrades={UPGRADES} />);
+ expect(wrapper.find('.system-upgrade-intermediate').exists()).toBeFalsy();
+ click(wrapper.find('a'));
+ expect(wrapper.find('.system-upgrade-intermediate').exists()).toBeTruthy();
+ click(wrapper.find('a'));
+ expect(wrapper.find('.system-upgrade-intermediate').exists()).toBeFalsy();
+});
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
new file mode 100644
index 00000000000..f23842f8689
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeItem-test.tsx
@@ -0,0 +1,59 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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 { shallow } from 'enzyme';
+import SystemUpgradeItem from '../SystemUpgradeItem';
+
+const UPGRADES = [
+ {
+ 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', () => {
+ const wrapper = shallow(<SystemUpgradeItem systemUpgrades={UPGRADES} />);
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('should display a badge', () => {
+ const wrapper = shallow(<SystemUpgradeItem badge="test badge" systemUpgrades={UPGRADES} />);
+ expect(wrapper.find('.badge').exists()).toBeTruthy();
+});
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
new file mode 100644
index 00000000000..e043d59c98b
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/SystemUpgradeNotif-test.tsx
@@ -0,0 +1,123 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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 { mount, shallow } from 'enzyme';
+import { click } from '../../../../../helpers/testUtils';
+import SystemUpgradeNotif from '../SystemUpgradeNotif';
+
+jest.mock('../../../../../api/system', () => ({
+ getSystemUpgrades: jest.fn(() =>
+ Promise.resolve({
+ updateCenterRefresh: '',
+ upgrades: [
+ {
+ version: '5.6.7',
+ description: 'Version 5.6.7 description',
+ releaseDate: '2017-03-01',
+ changeLogUrl: 'changelogurl',
+ downloadUrl: 'downloadurl',
+ plugins: {}
+ },
+ {
+ version: '5.6.5',
+ description: 'Version 5.6.5 description',
+ releaseDate: '2017-03-01',
+ 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.6',
+ description: 'Version 5.6.6 description',
+ releaseDate: '2017-04-02',
+ changeLogUrl: 'changelogurl',
+ downloadUrl: 'downloadurl',
+ plugins: {}
+ },
+ {
+ version: '6.4',
+ description: 'Version 6.4 description',
+ releaseDate: '2017-06-02',
+ changeLogUrl: 'changelogurl',
+ downloadUrl: 'downloadurl',
+ plugins: {}
+ }
+ ]
+ })
+ )
+}));
+
+const getSystemUpgrades = require('../../../../../api/system').getSystemUpgrades as jest.Mock<any>;
+
+beforeEach(() => {
+ getSystemUpgrades.mockClear();
+});
+
+it('should display correctly', async () => {
+ const wrapper = shallow(<SystemUpgradeNotif />);
+ expect(wrapper).toMatchSnapshot();
+
+ const instance = wrapper.instance() as SystemUpgradeNotif;
+ instance.mounted = true;
+ instance.fetchSystemUpgrade();
+
+ await new Promise(setImmediate);
+ wrapper.update();
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('should display nothing', async () => {
+ getSystemUpgrades.mockImplementationOnce(() =>
+ Promise.resolve({ updateCenterRefresh: '', upgrades: [] })
+ );
+ const wrapper = shallow(<SystemUpgradeNotif />);
+ const instance = wrapper.instance() as SystemUpgradeNotif;
+ instance.mounted = true;
+ instance.fetchSystemUpgrade();
+
+ await new Promise(setImmediate);
+ wrapper.update();
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('should fetch upgrade when mounting', () => {
+ mount(<SystemUpgradeNotif />);
+ expect(getSystemUpgrades).toHaveBeenCalled();
+});
+
+it('should open the upgrade form', async () => {
+ const wrapper = shallow(<SystemUpgradeNotif />);
+ const instance = wrapper.instance() as SystemUpgradeNotif;
+ instance.mounted = true;
+ instance.fetchSystemUpgrade();
+ await new Promise(setImmediate);
+ wrapper.update();
+
+ click(wrapper.find('button'));
+ expect(wrapper.find('SystemUpgradeForm').exists()).toBeTruthy();
+});
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
new file mode 100644
index 00000000000..3bfbebace5a
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeForm-test.tsx.snap
@@ -0,0 +1,100 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should display correctly 1`] = `
+<Modal
+ ariaHideApp={true}
+ bodyOpenClassName="ReactModal__Body--open"
+ className="modal"
+ closeTimeoutMS={0}
+ contentLabel="system.system_upgrade"
+ isOpen={true}
+ onRequestClose={[Function]}
+ overlayClassName="modal-overlay"
+ parentSelector={[Function]}
+ portalClassName="ReactModalPortal"
+ shouldCloseOnOverlayClick={true}
+>
+ <div
+ className="modal-head"
+ >
+ <h2>
+ system.system_upgrade
+ </h2>
+ </div>
+ <div
+ className="modal-body"
+ >
+ <SystemUpgradeItem
+ badge="system.latest_version"
+ systemUpgrades={
+ Array [
+ Object {
+ "changeLogUrl": "changelogurl",
+ "description": "Version 6.4 description",
+ "downloadUrl": "downloadurl",
+ "plugins": Object {},
+ "releaseDate": "2017-06-02",
+ "version": "6.4",
+ },
+ Object {
+ "changeLogUrl": "changelogurl",
+ "description": "Version 6.3 description",
+ "downloadUrl": "downloadurl",
+ "plugins": Object {},
+ "releaseDate": "2017-05-02",
+ "version": "6.3",
+ },
+ ]
+ }
+ />
+ <SystemUpgradeItem
+ badge="system.latest_lts_version"
+ systemUpgrades={
+ Array [
+ Object {
+ "changeLogUrl": "changelogurl",
+ "description": "Version 5.6.7 description",
+ "downloadUrl": "downloadurl",
+ "plugins": Object {},
+ "releaseDate": "2017-03-01",
+ "version": "5.6.7",
+ },
+ Object {
+ "changeLogUrl": "changelogurl",
+ "description": "Version 5.6.6 description",
+ "downloadUrl": "downloadurl",
+ "plugins": Object {},
+ "releaseDate": "2017-04-02",
+ "version": "5.6.6",
+ },
+ Object {
+ "changeLogUrl": "changelogurl",
+ "description": "Version 5.6.5 description",
+ "downloadUrl": "downloadurl",
+ "plugins": Object {},
+ "releaseDate": "2017-03-01",
+ "version": "5.6.5",
+ },
+ ]
+ }
+ />
+ </div>
+ <div
+ className="modal-foot"
+ >
+ <a
+ className="pull-left"
+ href="https://www.sonarqube.org/downloads/"
+ target="_blank"
+ >
+ system.see_sonarqube_downloads
+ </a>
+ <a
+ href="#"
+ onClick={[Function]}
+ >
+ cancel
+ </a>
+ </div>
+</Modal>
+`;
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
new file mode 100644
index 00000000000..9217e8cb640
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeIntermediate-test.tsx.snap
@@ -0,0 +1,57 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should display correctly 1`] = `
+<div>
+ <a
+ className="button-link little-spacer-bottom"
+ href="#"
+ onClick={[Function]}
+ >
+ system.show_intermediate_versions
+ <i
+ className="little-spacer-left icon-arrow-down"
+ />
+ </a>
+</div>
+`;
+
+exports[`should display correctly 2`] = `
+<div>
+ <a
+ className="button-link little-spacer-bottom"
+ href="#"
+ onClick={[Function]}
+ >
+ system.hide_intermediate_versions
+ <i
+ className="little-spacer-left icon-arrow-up"
+ />
+ </a>
+ <div
+ className="note system-upgrade-intermediate"
+ >
+ <DateFormatter
+ date="2017-04-02"
+ long={true}
+ />
+ <p
+ className="little-spacer-top"
+ >
+ Version 5.6.6 description
+ </p>
+ </div>
+ <div
+ className="note system-upgrade-intermediate"
+ >
+ <DateFormatter
+ date="2017-03-01"
+ long={true}
+ />
+ <p
+ className="little-spacer-top"
+ >
+ Version 5.6.5 description
+ </p>
+ </div>
+</div>
+`;
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
new file mode 100644
index 00000000000..15f11c439b6
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeItem-test.tsx.snap
@@ -0,0 +1,84 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should display correctly 1`] = `
+<div
+ className="system-upgrade-version"
+>
+ <p>
+ <FormattedMessage
+ defaultMessage="system.version_is_availble"
+ id="system.version_is_availble"
+ values={
+ Object {
+ "version": <b>
+ SonarQube
+ 5.6.7
+ </b>,
+ }
+ }
+ />
+ </p>
+ <p
+ className="spacer-top"
+ >
+ Version 5.6.7 description
+ </p>
+ <div
+ className="big-spacer-top"
+ >
+ <DateFormatter
+ date="2017-03-01"
+ long={true}
+ />
+ <a
+ className="spacer-left"
+ href="changelogurl"
+ target="_blank"
+ >
+ system.release_notes
+ </a>
+ </div>
+ <SystemUpgradeIntermediate
+ className="spacer-top"
+ upgrades={
+ Array [
+ Object {
+ "changeLogUrl": "changelogurl",
+ "description": "Version 5.6.6 description",
+ "downloadUrl": "downloadurl",
+ "plugins": Object {},
+ "releaseDate": "2017-04-02",
+ "version": "5.6.6",
+ },
+ Object {
+ "changeLogUrl": "changelogurl",
+ "description": "Version 5.6.5 description",
+ "downloadUrl": "downloadurl",
+ "plugins": Object {},
+ "releaseDate": "2017-03-01",
+ "version": "5.6.5",
+ },
+ ]
+ }
+ />
+ <div
+ className="big-spacer-top"
+ >
+ <a
+ className="button"
+ download="sonarqube-5.6.7.zip"
+ href="downloadurl"
+ target="blank"
+ >
+ system.download_x.5.6.7
+ </a>
+ <a
+ className="spacer-left"
+ href="https://redirect.sonarsource.com/doc/upgrading.html"
+ target="_blank"
+ >
+ system.how_to_upgrade
+ </a>
+ </div>
+</div>
+`;
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
new file mode 100644
index 00000000000..a750b00055d
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeNotif-test.tsx.snap
@@ -0,0 +1,23 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should display correctly 1`] = `null`;
+
+exports[`should display correctly 2`] = `
+<div
+ className="page-notifs"
+>
+ <div
+ className="alert alert-info"
+ >
+ system.new_version_available
+ <button
+ className="spacer-left"
+ onClick={[Function]}
+ >
+ learn_more
+ </button>
+ </div>
+</div>
+`;
+
+exports[`should display nothing 1`] = `null`;
diff --git a/server/sonar-web/src/main/js/apps/system/styles.css b/server/sonar-web/src/main/js/apps/system/styles.css
index 66563a4b032..6c266bec872 100644
--- a/server/sonar-web/src/main/js/apps/system/styles.css
+++ b/server/sonar-web/src/main/js/apps/system/styles.css
@@ -61,3 +61,17 @@
overflow: hidden;
text-overflow: ellipsis;
}
+
+.system-upgrade-version {
+ padding: 8px;
+}
+
+.system-upgrade-version ~ .system-upgrade-version {
+ margin-top: 10px;
+ padding-top: 18px;
+ border-top: solid 1px #e6e6e6;
+}
+
+.system-upgrade-intermediate {
+ padding: 6px 10px;
+}
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 ac7c62ee752..1f5367bd5f9 100644
--- a/server/sonar-web/src/main/js/apps/system/utils.ts
+++ b/server/sonar-web/src/main/js/apps/system/utils.ts
@@ -17,7 +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 { each, memoize, omit, omitBy, pickBy, sortBy } from 'lodash';
+import { each, groupBy, memoize, omit, omitBy, pickBy, sortBy } from 'lodash';
import {
cleanQuery,
parseAsArray,
@@ -31,7 +31,8 @@ import {
NodeInfo,
SysInfo,
SysInfoSection,
- SysValueObject
+ SysValueObject,
+ SystemUpgrade
} from '../../api/system';
import { formatMeasure } from '../../helpers/measures';
@@ -185,3 +186,17 @@ export const serializeQuery = memoize((query: Query): RawQuery =>
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/less/components/alerts.less b/server/sonar-web/src/main/less/components/alerts.less
index 65694046261..01bdc89ce1c 100644
--- a/server/sonar-web/src/main/less/components/alerts.less
+++ b/server/sonar-web/src/main/less/components/alerts.less
@@ -65,3 +65,13 @@
.alert-success {
.alert-emphasis-variant(#3c763d, #dff0d8, #d6e9c6);
}
+
+.page-notifs .alert {
+ display: flex;
+ justify-content: space-between;
+ padding: 8px 10px;
+}
+
+.page-notifs .alert:last-child {
+ margin-bottom: 16px;
+}
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 01c0355dd4c..8cdb119e68c 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -2066,7 +2066,6 @@ marketplace.all=All
marketplace.updates_only=Updates Only
marketplace.restart=Restart
marketplace.revert=Revert
-marketplace.system_upgrades=System Upgrades
marketplace.install=Install
marketplace.install_x=Install {0}
marketplace.installed=Installed
@@ -2224,7 +2223,6 @@ background_tasks.search_by_task_or_component=Search by Task or Component
background_tasks.failing_count=Count of projects where processing of most recent analysis report failed
-
#------------------------------------------------------------------------------
#
# SYSTEM
@@ -2236,14 +2234,26 @@ system.cluster_log_level.info=Changes apply to all Application nodes but not to
system.current_health_of_x=Current health status of {0}
system.download_logs=Download Logs
system.download_system_info=Download System Info
+system.download_x=Download {0}
+system.hide_intermediate_versions=Hide intermediate versions
+system.how_to_upgrade=How to upgrade?
system.is_restarting=Server is restarting. This page will be automatically refreshed.
+system.latest_version=Latest Version
+system.latest_lts_version=Latest LTS Version
system.log_level.warning=This level has performance impacts, please make sure to get back to INFO level once your investigation is done. Please note that when the server is restarted, logging will revert to the level configured in sonar.properties.
system.log_level.warning.short=Current logs level has performance impacts, get back to INFO level.
system.log_level.info=Changes don't apply to Search.
system.logs_level=Logs level
+system.new_version_available=A new version of SonarQube is available.
+system.release_notes=Release Notes
+system.released_x=Released {0}
system.restart_server=Restart Server
system.search_nodes_title=Search Nodes
+system.see_sonarqube_downloads=See All SonarQube Downloads
system.set_log_level=Set logs level
+system.show_intermediate_versions=Show intermediate versions
+system.system_upgrade=System Upgrade
+system.version_is_availble={version} is available
#------------------------------------------------------------------------------