From f03c5e9858dd86ecd78e6278aa6f95d146ada270 Mon Sep 17 00:00:00 2001 From: Grégoire Aubert Date: Thu, 19 Oct 2017 11:48:26 +0200 Subject: SONAR-9947 Update handling of manual installation of commercial editions --- .../sonar-web/src/main/js/apps/marketplace/App.tsx | 55 ++++++++++++++++------ .../src/main/js/apps/marketplace/AppContainer.tsx | 3 +- .../src/main/js/apps/marketplace/EditionBoxes.tsx | 46 +++--------------- .../marketplace/__tests__/EditionBoxes-test.tsx | 15 ++---- .../marketplace/components/EditionsStatusNotif.tsx | 40 ++++++++++++++-- .../marketplace/components/LicenseEditionForm.tsx | 11 +++-- .../marketplace/components/LicenseEditionSet.tsx | 22 +-------- .../__tests__/LicenseEditionForm-test.tsx | 2 +- .../EditionsStatusNotif-test.tsx.snap | 43 ++++++++++++++++- .../__snapshots__/LicenseEditionForm-test.tsx.snap | 10 ++++ .../__snapshots__/LicenseEditionSet-test.tsx.snap | 19 -------- 11 files changed, 150 insertions(+), 116 deletions(-) (limited to 'server/sonar-web/src/main/js/apps/marketplace') 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 37cc3b1d72a..0c008e09b7c 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/App.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/App.tsx @@ -36,10 +36,10 @@ import { Plugin, PluginPending } from '../../api/plugins'; -import { EditionStatus, getEditionStatus } from '../../api/marketplace'; +import { Edition, EditionStatus, getEditionsList, getEditionStatus } from '../../api/marketplace'; import { RawQuery } from '../../helpers/query'; import { translate } from '../../helpers/l10n'; -import { filterPlugins, parseQuery, Query, serializeQuery } from './utils'; +import { getEditionsForVersion, filterPlugins, parseQuery, Query, serializeQuery } from './utils'; export interface Props { editionsUrl: string; @@ -49,8 +49,10 @@ export interface Props { } interface State { + editions?: Edition[]; editionStatus?: EditionStatus; - loading: boolean; + loadingEditions: boolean; + loadingPlugins: boolean; pending: { installing: PluginPending[]; updating: PluginPending[]; @@ -69,7 +71,8 @@ export default class App extends React.PureComponent { constructor(props: Props) { super(props); this.state = { - loading: true, + loadingEditions: true, + loadingPlugins: true, pending: { installing: [], updating: [], @@ -81,6 +84,7 @@ export default class App extends React.PureComponent { componentDidMount() { this.mounted = true; + this.fetchEditions(); this.fetchPendingPlugins(); this.fetchEditionStatus(); this.fetchQueryPlugins(); @@ -106,35 +110,35 @@ export default class App extends React.PureComponent { }; fetchAllPlugins = () => { - this.setState({ loading: true }); + this.setState({ loadingPlugins: true }); Promise.all([getInstalledPluginsWithUpdates(), getAvailablePlugins()]).then( ([installed, available]) => { if (this.mounted) { this.setState({ - loading: false, + loadingPlugins: false, plugins: sortBy(uniqBy([...installed, ...available.plugins], 'key'), 'name') }); } }, () => { if (this.mounted) { - this.setState({ loading: false }); + this.setState({ loadingPlugins: false }); } } ); }; fetchUpdatesOnly = () => { - this.setState({ loading: true }); + this.setState({ loadingPlugins: true }); getPluginUpdates().then( plugins => { if (this.mounted) { - this.setState({ loading: false, plugins }); + this.setState({ loadingPlugins: false, plugins }); } }, () => { if (this.mounted) { - this.setState({ loading: false }); + this.setState({ loadingPlugins: false }); } } ); @@ -161,6 +165,25 @@ export default class App extends React.PureComponent { () => {} ); + fetchEditions = () => { + this.setState({ loadingEditions: true }); + getEditionsList(this.props.editionsUrl).then( + editionsPerVersion => { + if (this.mounted) { + this.setState({ + editions: getEditionsForVersion(editionsPerVersion, this.props.sonarqubeVersion), + loadingEditions: false + }); + } + }, + () => { + if (this.mounted) { + this.setState({ loadingEditions: false }); + } + } + ); + }; + updateEditionStatus = (editionStatus: EditionStatus) => this.setState({ editionStatus: editionStatus }); @@ -170,15 +193,17 @@ export default class App extends React.PureComponent { }; render() { - const { editionStatus, loading, plugins, pending } = this.state; + const { editions, editionStatus, loadingPlugins, plugins, pending } = this.state; const query = parseQuery(this.props.location.query); const filteredPlugins = query.search ? filterPlugins(plugins, query.search) : plugins; + return (
{editionStatus && ( @@ -187,6 +212,8 @@ export default class App extends React.PureComponent {
{ updateCenterActive={this.props.updateCenterActive} updateQuery={this.updateQuery} /> - {loading && } - {!loading && ( + {loadingPlugins && } + {!loadingPlugins && ( { updateQuery={this.updateQuery} /> )} - {!loading &&
} + {!loadingPlugins &&
}
); } diff --git a/server/sonar-web/src/main/js/apps/marketplace/AppContainer.tsx b/server/sonar-web/src/main/js/apps/marketplace/AppContainer.tsx index 909f284fbdf..abf67e2c3d8 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/AppContainer.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/AppContainer.tsx @@ -25,7 +25,8 @@ import './style.css'; const mapStateToProps = (state: any) => ({ editionsUrl: (getGlobalSettingValue(state, 'sonar.editions.jsonUrl') || {}).value, sonarqubeVersion: getAppState(state).version, - updateCenterActive: (getGlobalSettingValue(state, 'sonar.updatecenter.activate') || {}).value + updateCenterActive: + (getGlobalSettingValue(state, 'sonar.updatecenter.activate') || {}).value === 'true' }); export default connect(mapStateToProps)(App as any); diff --git a/server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx b/server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx index 112205c8d36..95a3c96d109 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx @@ -22,58 +22,26 @@ import { FormattedMessage } from 'react-intl'; import EditionBox from './components/EditionBox'; import LicenseEditionForm from './components/LicenseEditionForm'; import UninstallEditionForm from './components/UninstallEditionForm'; -import { Edition, EditionStatus, getEditionsList } from '../../api/marketplace'; -import { getEditionsForVersion } from './utils'; +import { Edition, EditionStatus } from '../../api/marketplace'; import { translate } from '../../helpers/l10n'; export interface Props { + editions?: Edition[]; editionStatus?: EditionStatus; editionsUrl: string; + loading: boolean; sonarqubeVersion: string; updateCenterActive: boolean; updateEditionStatus: (editionStatus: EditionStatus) => void; } interface State { - editions?: Edition[]; - editionsError: boolean; - loading: boolean; installEdition?: Edition; openUninstallForm: boolean; } export default class EditionBoxes extends React.PureComponent { - mounted: boolean; - state: State = { editionsError: false, loading: true, openUninstallForm: false }; - - componentDidMount() { - this.mounted = true; - this.fetchEditions(); - } - - componentWillUnmount() { - this.mounted = false; - } - - fetchEditions = () => { - this.setState({ loading: true }); - getEditionsList(this.props.editionsUrl).then( - editionsPerVersion => { - if (this.mounted) { - this.setState({ - loading: false, - editions: getEditionsForVersion(editionsPerVersion, this.props.sonarqubeVersion), - editionsError: false - }); - } - }, - () => { - if (this.mounted) { - this.setState({ editionsError: true, loading: false }); - } - } - ); - }; + state: State = { openUninstallForm: false }; handleOpenLicenseForm = (edition: Edition) => this.setState({ installEdition: edition }); handleCloseLicenseForm = () => this.setState({ installEdition: undefined }); @@ -82,13 +50,13 @@ export default class EditionBoxes extends React.PureComponent { handleCloseUninstallForm = () => this.setState({ openUninstallForm: false }); render() { - const { editionStatus } = this.props; - const { editions, editionsError, loading, installEdition, openUninstallForm } = this.state; + const { editions, editionStatus, loading } = this.props; + const { installEdition, openUninstallForm } = this.state; if (loading) { return ; } - if (!editions || editionsError) { + if (!editions) { return (
diff --git a/server/sonar-web/src/main/js/apps/marketplace/__tests__/EditionBoxes-test.tsx b/server/sonar-web/src/main/js/apps/marketplace/__tests__/EditionBoxes-test.tsx index e64c714577f..0df72ac7f89 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/__tests__/EditionBoxes-test.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/__tests__/EditionBoxes-test.tsx @@ -48,27 +48,19 @@ const DEFAULT_EDITIONS = [ ]; it('should display the edition boxes', () => { - const wrapper = getWrapper(); + const wrapper = getWrapper({ editions: DEFAULT_EDITIONS, loading: true }); expect(wrapper).toMatchSnapshot(); - wrapper.setState({ - editions: DEFAULT_EDITIONS, - loading: false - }); + wrapper.setProps({ loading: false }); expect(wrapper).toMatchSnapshot(); }); it('should display an error message', () => { const wrapper = getWrapper(); - wrapper.setState({ loading: false, editionsError: true }); expect(wrapper).toMatchSnapshot(); }); it('should open the license form', () => { - const wrapper = getWrapper(); - wrapper.setState({ - editions: DEFAULT_EDITIONS, - loading: false - }); + const wrapper = getWrapper({ editions: DEFAULT_EDITIONS }); (wrapper.instance() as EditionBoxes).handleOpenLicenseForm(DEFAULT_EDITIONS[0]); expect(wrapper.find('LicenseEditionForm').exists()).toBeTruthy(); }); @@ -76,6 +68,7 @@ it('should open the license form', () => { function getWrapper(props = {}) { return shallow( void; } @@ -48,7 +49,10 @@ export default class EditionsStatusNotif extends React.PureComponent edition.key === nextEditionKey); + switch (installationStatus) { case 'AUTOMATIC_IN_PROGRESS': return ( @@ -61,7 +65,13 @@ export default class EditionsStatusNotif extends React.PureComponent - {translate('marketplace.status', installationStatus)} + + {nextEdition ? ( + translate('marketplace.status_x.' + installationStatus, nextEdition.name) + ) : ( + translate('marketplace.status', installationStatus) + )} + @@ -71,7 +81,27 @@ export default class EditionsStatusNotif extends React.PureComponent - {translate('marketplace.status', installationStatus)} + {nextEdition ? ( + translate('marketplace.status_x.' + installationStatus, nextEdition.name) + ) : ( + translate('marketplace.status', installationStatus) + )} +

+ {nextEdition && ( + + {translate('marketplace.download_package')} + + )} + + {translate('marketplace.how_to_install')} + +

{translate('marketplace.how_to_install')} @@ -96,7 +126,7 @@ export default class EditionsStatusNotif extends React.PureComponent
)} - {this.renderStatusAlert} + {this.renderStatusAlert()} ); } diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/LicenseEditionForm.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/LicenseEditionForm.tsx index 6971889135c..e099465dc43 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/LicenseEditionForm.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/LicenseEditionForm.tsx @@ -62,7 +62,7 @@ export default class LicenseEditionForm extends React.PureComponent) => { event.preventDefault(); const { license, status } = this.state; - if (license && status && ['AUTOMATIC_INSTALL', 'NO_INSTALL'].includes(status)) { + if (license && status) { this.setState({ submitting: true }); applyLicense({ license }).then( editionStatus => { @@ -102,10 +102,13 @@ export default class LicenseEditionForm extends React.PureComponent {submitting && } - {status && - ['NO_INSTALL', 'AUTOMATIC_INSTALL'].includes(status) && ( + {status && ( )} diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/LicenseEditionSet.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/LicenseEditionSet.tsx index 86c29fc65e9..496c5fe988d 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/LicenseEditionSet.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/LicenseEditionSet.tsx @@ -137,8 +137,7 @@ export default class LicenseEditionSet extends React.PureComponent rows={6} value={license} /> - {previewStatus && - licenseEdition && ( + {previewStatus && (

})}> {translateWithParameters( 'marketplace.license_preview_status.' + previewStatus, - licenseEdition.name - )} - {previewStatus === 'MANUAL_INSTALL' && ( -

- - {translate('marketplace.download_package')} - - - {translate('marketplace.how_to_install')} - -

+ licenseEdition ? licenseEdition.name : translate('marketplace.commercial_edition') )}

)} diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/LicenseEditionForm-test.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/LicenseEditionForm-test.tsx index f1b0952650d..2beffa70f82 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/LicenseEditionForm-test.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/LicenseEditionForm-test.tsx @@ -55,7 +55,7 @@ it('should correctly change the button based on the status', () => { wrapper.setState({ status: 'AUTOMATIC_INSTALL' }); expect(wrapper.find('button')).toMatchSnapshot(); wrapper.setState({ status: 'MANUAL_INSTALL' }); - expect(wrapper.find('button').exists()).toBeFalsy(); + expect(wrapper.find('button')).toMatchSnapshot(); }); it('should update the edition status after install', async () => { diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionsStatusNotif-test.tsx.snap b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionsStatusNotif-test.tsx.snap index 0f79649b873..70b4ce43ef0 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionsStatusNotif-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionsStatusNotif-test.tsx.snap @@ -1,10 +1,39 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should display a ready notification 1`] = `
`; +exports[`should display a ready notification 1`] = ` +
+
+ + marketplace.status.AUTOMATIC_READY + + +
+
+`; exports[`should display an error notification 1`] = `
`; -exports[`should display an in progress notif 1`] = `
`; +exports[`should display an in progress notif 1`] = ` +
+
+ + + marketplace.status.AUTOMATIC_IN_PROGRESS + +
+
+`; exports[`should display install errors 1`] = `
@@ -20,5 +49,15 @@ exports[`should display install errors 1`] = `
+
+ + + marketplace.status.AUTOMATIC_IN_PROGRESS + +
`; diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/LicenseEditionForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/LicenseEditionForm-test.tsx.snap index e657d2c1ee2..e3951bfeaff 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/LicenseEditionForm-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/LicenseEditionForm-test.tsx.snap @@ -20,6 +20,16 @@ exports[`should correctly change the button based on the status 2`] = ` `; +exports[`should correctly change the button based on the status 3`] = ` + +`; + exports[`should display correctly 1`] = ` marketplace.license_preview_status.MANUAL_INSTALL.Foo -

- - marketplace.download_package - - - marketplace.how_to_install - -

`; -- cgit v1.2.3