diff options
author | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-10-19 17:25:23 +0200 |
---|---|---|
committer | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-10-23 08:01:13 -0700 |
commit | 9538f9ae5502b33651f1d916ee69aaf74c121231 (patch) | |
tree | c050fe8f85aca1eac6d3fc916d318760aec89d43 /server/sonar-web/src/main/js/apps/system | |
parent | 2d568ff3830cef88392656119bd2485a9ae9c8e1 (diff) | |
download | sonarqube-9538f9ae5502b33651f1d916ee69aaf74c121231.tar.gz sonarqube-9538f9ae5502b33651f1d916ee69aaf74c121231.zip |
SONAR-9953 SONAR-9354 SONAR-7663 Redesign and move system upgrade in the system info page
Diffstat (limited to 'server/sonar-web/src/main/js/apps/system')
17 files changed, 1061 insertions, 3 deletions
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]); +} |