From 35a5d851cedbe4fee51fe5cecb7cb3205e7713fe Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gr=C3=A9goire=20Aubert?= Date: Fri, 27 Oct 2017 11:26:58 +0200 Subject: [PATCH] SONAR-9936 Switch to upgrade/downgrade buttons in the editions --- .../main/js/apps/marketplace/EditionBoxes.tsx | 68 ++++++--- .../__tests__/EditionBoxes-test.tsx | 16 +- .../__snapshots__/EditionBoxes-test.tsx.snap | 22 +-- .../marketplace/components/EditionBox.tsx | 62 ++++---- .../components/EditionBoxBadge.tsx | 56 +++++++ .../components/LicenseEditionForm.tsx | 8 +- .../components/__tests__/EditionBox-test.tsx | 44 ++---- .../__tests__/EditionBoxBadge-test.tsx | 81 ++++++++++ .../__tests__/LicenseEditionForm-test.tsx | 1 + .../__snapshots__/EditionBox-test.tsx.snap | 140 ++++++++++-------- .../EditionBoxBadge-test.tsx.snap | 9 ++ .../LicenseEditionForm-test.tsx.snap | 4 +- .../src/main/js/apps/marketplace/utils.ts | 11 +- .../resources/org/sonar/l10n/core.properties | 5 +- 14 files changed, 352 insertions(+), 175 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/marketplace/components/EditionBoxBadge.tsx create mode 100644 server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionBoxBadge-test.tsx create mode 100644 server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionBoxBadge-test.tsx.snap 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 d8a0a5e3533..ddba3af1b72 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx @@ -24,6 +24,7 @@ import LicenseEditionForm from './components/LicenseEditionForm'; import UninstallEditionForm from './components/UninstallEditionForm'; import { Edition, EditionStatus } from '../../api/marketplace'; import { translate } from '../../helpers/l10n'; +import { sortEditions } from './utils'; export interface Props { canInstall: boolean; @@ -49,9 +50,45 @@ export default class EditionBoxes extends React.PureComponent { handleOpenUninstallForm = () => this.setState({ openUninstallForm: true }); handleCloseUninstallForm = () => this.setState({ openUninstallForm: false }); + renderForms(sortedEditions: Edition[], installedIdx?: number) { + const { canInstall, canUninstall, editionStatus } = this.props; + const { installEdition, openUninstallForm } = this.state; + const installEditionIdx = + installEdition && sortedEditions.findIndex(edition => edition.key === installEdition.key); + + if (canInstall && installEdition) { + return ( + + ); + } + + if (canUninstall && openUninstallForm && editionStatus && editionStatus.currentEditionKey) { + return ( + edition.key === editionStatus.currentEditionKey)} + editionStatus={editionStatus} + onClose={this.handleCloseUninstallForm} + updateEditionStatus={this.props.updateEditionStatus} + /> + ); + } + + return null; + } + render() { const { canInstall, canUninstall, editions, editionStatus, loading } = this.props; - const { installEdition, openUninstallForm } = this.state; + if (loading) { return ; } @@ -76,41 +113,26 @@ export default class EditionBoxes extends React.PureComponent { ); } + const sortedEditions = sortEditions(editions); + const installedIdx = + editionStatus && + sortedEditions.findIndex(edition => edition.key === editionStatus.currentEditionKey); return (
- {editions.map(edition => ( + {sortedEditions.map((edition, idx) => ( ))} - {canInstall && - installEdition && ( - - )} - - {canUninstall && - openUninstallForm && - editionStatus && - editionStatus.currentEditionKey && ( - edition.key === editionStatus.currentEditionKey)} - editionStatus={editionStatus} - onClose={this.handleCloseUninstallForm} - updateEditionStatus={this.props.updateEditionStatus} - /> - )} + {this.renderForms(sortedEditions, installedIdx)}
); } 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 fe3880cc9f0..0201372b086 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 @@ -23,31 +23,31 @@ import EditionBoxes from '../EditionBoxes'; import { EditionStatus } from '../../../api/marketplace'; const DEFAULT_STATUS: EditionStatus = { - currentEditionKey: 'foo', + currentEditionKey: 'developer', nextEditionKey: '', installationStatus: 'NONE' }; const DEFAULT_EDITIONS = [ { - key: 'foo', - name: 'Foo', - textDescription: 'Foo desc', + key: 'developer', + name: 'Developer Edition', + textDescription: 'foo', downloadUrl: 'download_url', homeUrl: 'more_url', requestUrl: 'license_url' }, { - key: 'bar', - name: 'Bar', - textDescription: 'Bar desc', + key: 'comunity', + name: 'Comunity Edition', + textDescription: 'bar', downloadUrl: 'download_url', homeUrl: 'more_url', requestUrl: 'license_url' } ]; -it('should display the edition boxes', () => { +it('should display the edition boxes correctly', () => { const wrapper = getWrapper({ editions: DEFAULT_EDITIONS, loading: true }); expect(wrapper).toMatchSnapshot(); wrapper.setProps({ loading: false }); diff --git a/server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/EditionBoxes-test.tsx.snap b/server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/EditionBoxes-test.tsx.snap index f9b86d68f00..952e8dc78c1 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/EditionBoxes-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/EditionBoxes-test.tsx.snap @@ -25,13 +25,13 @@ exports[`should display an error message 1`] = ` `; -exports[`should display the edition boxes 1`] = ` +exports[`should display the edition boxes correctly 1`] = ` `; -exports[`should display the edition boxes 2`] = ` +exports[`should display the edition boxes correctly 2`] = `
@@ -42,19 +42,20 @@ exports[`should display the edition boxes 2`] = ` Object { "downloadUrl": "download_url", "homeUrl": "more_url", - "key": "foo", - "name": "Foo", + "key": "comunity", + "name": "Comunity Edition", "requestUrl": "license_url", - "textDescription": "Foo desc", + "textDescription": "bar", } } editionStatus={ Object { - "currentEditionKey": "foo", + "currentEditionKey": "developer", "installationStatus": "NONE", "nextEditionKey": "", } } + isDowngrade={true} onInstall={[Function]} onUninstall={[Function]} /> @@ -65,19 +66,20 @@ exports[`should display the edition boxes 2`] = ` Object { "downloadUrl": "download_url", "homeUrl": "more_url", - "key": "bar", - "name": "Bar", + "key": "developer", + "name": "Developer Edition", "requestUrl": "license_url", - "textDescription": "Bar desc", + "textDescription": "foo", } } editionStatus={ Object { - "currentEditionKey": "foo", + "currentEditionKey": "developer", "installationStatus": "NONE", "nextEditionKey": "", } } + isDowngrade={false} onInstall={[Function]} onUninstall={[Function]} /> diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/EditionBox.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/EditionBox.tsx index ca8457fe4d1..6f90fda970e 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/EditionBox.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/EditionBox.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import CheckIcon from '../../../components/icons-components/CheckIcon'; +import EditionBoxBadge from './EditionBoxBadge'; import { Edition, EditionStatus } from '../../../api/marketplace'; import { translate } from '../../../helpers/l10n'; @@ -27,6 +27,7 @@ interface Props { canUninstall: boolean; edition: Edition; editionStatus?: EditionStatus; + isDowngrade?: boolean; onInstall: (edition: Edition) => void; onUninstall: () => void; } @@ -34,40 +35,45 @@ interface Props { export default class EditionBox extends React.PureComponent { handleInstall = () => this.props.onInstall(this.props.edition); - renderBadge(isInstalled?: boolean, installInProgress?: boolean) { - const { edition, editionStatus } = this.props; - const installReady = editionStatus && editionStatus.installationStatus === 'AUTOMATIC_READY'; - const isInstalling = - installInProgress && editionStatus && editionStatus.nextEditionKey === edition.key; - if (isInstalling) { + renderActions(isInstalled?: boolean, installInProgress?: boolean) { + const { canInstall, canUninstall, editionStatus } = this.props; + const uninstallInProgress = + editionStatus && editionStatus.installationStatus === 'UNINSTALL_IN_PROGRESS'; + + if (canInstall && !isInstalled) { return ( - - {installReady ? translate('marketplace.pending') : translate('marketplace.installing')} - + ); } - if (isInstalled) { + if (canUninstall && isInstalled) { return ( - - - {translate('marketplace.installed')} - + ); } + return null; } render() { - const { canInstall, canUninstall, edition, editionStatus } = this.props; + const { edition, editionStatus } = this.props; const isInstalled = editionStatus && editionStatus.currentEditionKey === edition.key; - const uninstallInProgress = - editionStatus && editionStatus.installationStatus === 'UNINSTALL_IN_PROGRESS'; const installInProgress = editionStatus && ['AUTOMATIC_IN_PROGRESS', 'AUTOMATIC_READY'].includes(editionStatus.installationStatus); return (
- {this.renderBadge(isInstalled, installInProgress)} + {editionStatus && }

{edition.name}

{edition.textDescription}

@@ -76,23 +82,7 @@ export default class EditionBox extends React.PureComponent { {translate('marketplace.learn_more')} - {canUninstall && - isInstalled && ( - - )} - {canInstall && - !isInstalled && ( - - )} + {this.renderActions(isInstalled, installInProgress)}
); diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/EditionBoxBadge.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/EditionBoxBadge.tsx new file mode 100644 index 00000000000..47b3e767fe2 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/marketplace/components/EditionBoxBadge.tsx @@ -0,0 +1,56 @@ +/* + * 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 CheckIcon from '../../../components/icons-components/CheckIcon'; +import { EditionStatus } from '../../../api/marketplace'; +import { translate } from '../../../helpers/l10n'; + +interface Props { + editionKey: string; + status: EditionStatus; +} + +export default function EditionBoxBadge({ editionKey, status }: Props) { + const inProgress = ['AUTOMATIC_IN_PROGRESS', 'AUTOMATIC_READY'].includes( + status.installationStatus + ); + const isInstalling = inProgress && status.nextEditionKey === editionKey; + + if (isInstalling) { + const installReady = status.installationStatus === 'AUTOMATIC_READY'; + return ( + + {installReady ? translate('marketplace.pending') : translate('marketplace.installing')} + + ); + } + + const isInstalled = status.currentEditionKey === editionKey; + if (isInstalled) { + return ( + + + {translate('marketplace.installed')} + + ); + } + + return null; +} 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 e099465dc43..abab7c84ed4 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 @@ -26,6 +26,7 @@ import { translate, translateWithParameters } from '../../../helpers/l10n'; export interface Props { edition: Edition; editions: Edition[]; + isDowngrade: boolean; onClose: () => void; updateEditionStatus: (editionStatus: EditionStatus) => void; } @@ -79,9 +80,12 @@ export default class LicenseEditionForm extends React.PureComponent { expect(getWrapper()).toMatchSnapshot(); }); -it('should display installed badge', () => { +it('should disable upgrade button', () => { expect( getWrapper({ editionStatus: { - currentEditionKey: 'foo', - nextEditionKey: '', - installationStatus: 'NONE' - } - }) - ).toMatchSnapshot(); -}); - -it('should display installing badge', () => { - expect( - getWrapper({ - editionStatus: { - currentEditionKey: 'foo', + currentEditionKey: '', nextEditionKey: 'foo', installationStatus: 'AUTOMATIC_IN_PROGRESS' } }) ).toMatchSnapshot(); -}); - -it('should display pending badge', () => { expect( getWrapper({ editionStatus: { @@ -77,39 +62,36 @@ it('should display pending badge', () => { ).toMatchSnapshot(); }); -it('should disable install button', () => { +it('should disable uninstall button', () => { expect( getWrapper({ editionStatus: { - currentEditionKey: '', + currentEditionKey: 'foo', nextEditionKey: 'foo', installationStatus: 'AUTOMATIC_IN_PROGRESS' } }) ).toMatchSnapshot(); - expect( - getWrapper({ - editionStatus: { - currentEditionKey: '', - nextEditionKey: 'foo', - installationStatus: 'AUTOMATIC_READY' - } - }) - ).toMatchSnapshot(); }); -it('should disable uninstall button', () => { +it('should correctly hide upgrade/uninstall buttons', () => { + expect(getWrapper({ canInstall: false })).toMatchSnapshot(); expect( getWrapper({ + canUninstall: false, editionStatus: { currentEditionKey: 'foo', - nextEditionKey: 'foo', - installationStatus: 'AUTOMATIC_IN_PROGRESS' + nextEditionKey: '', + installationStatus: 'NONE' } }) ).toMatchSnapshot(); }); +it('should display a downgrade button', () => { + expect(getWrapper({ isDowngrade: true })).toMatchSnapshot(); +}); + function getWrapper(props = {}) { return shallow( { + expect( + getWrapper({ + editionStatus: { + currentEditionKey: 'foo', + nextEditionKey: '', + installationStatus: 'NONE' + } + }) + ).toMatchSnapshot(); +}); + +it('should display installing badge', () => { + expect( + getWrapper({ + editionStatus: { + currentEditionKey: 'foo', + nextEditionKey: 'foo', + installationStatus: 'AUTOMATIC_IN_PROGRESS' + } + }) + ).toMatchSnapshot(); +}); + +it('should display pending badge', () => { + expect( + getWrapper({ + editionStatus: { + currentEditionKey: '', + nextEditionKey: 'foo', + installationStatus: 'AUTOMATIC_READY' + } + }) + ).toMatchSnapshot(); +}); + +it('should not display a badge', () => { + expect( + getWrapper({ + editionStatus: { + currentEditionKey: '', + nextEditionKey: 'bar', + installationStatus: 'AUTOMATIC_READY' + } + }) + ).toMatchSnapshot(); +}); + +function getWrapper(props = {}) { + return shallow(); +} 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 bb6e8d213ee..133ac464913 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 @@ -78,6 +78,7 @@ function getWrapper(props = {}) { - - marketplace.installing - +

marketplace.learn_more -

`; -exports[`should disable install button 2`] = ` +exports[`should correctly hide upgrade/uninstall buttons 2`] = `
- - marketplace.pending - +

marketplace.learn_more -

`; @@ -80,11 +78,16 @@ exports[`should disable uninstall button 1`] = `
- - marketplace.installing - +

`; -exports[`should display installed badge 1`] = ` +exports[`should disable upgrade button 1`] = `
- - - marketplace.installed - +

`; -exports[`should display installing badge 1`] = ` +exports[`should disable upgrade button 2`] = `
- - marketplace.installing - +

`; -exports[`should display pending badge 1`] = ` +exports[`should display a downgrade button 1`] = `
- - marketplace.pending - +

@@ -239,6 +251,16 @@ exports[`should display the edition 1`] = `
+

- marketplace.install + marketplace.upgrade

diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionBoxBadge-test.tsx.snap b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionBoxBadge-test.tsx.snap new file mode 100644 index 00000000000..7e824591e02 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionBoxBadge-test.tsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should display installed badge 1`] = `null`; + +exports[`should display installing badge 1`] = `null`; + +exports[`should display pending badge 1`] = `null`; + +exports[`should not display a badge 1`] = `null`; 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 382c562bb02..9e07155c292 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 @@ -36,7 +36,7 @@ exports[`should display correctly 1`] = ` bodyOpenClassName="ReactModal__Body--open" className="modal" closeTimeoutMS={0} - contentLabel="marketplace.install_x.Foo" + contentLabel="marketplace.upgrade_to_x.Foo" isOpen={true} onRequestClose={[Function]} overlayClassName="modal-overlay" @@ -48,7 +48,7 @@ exports[`should display correctly 1`] = ` className="modal-head" >

- marketplace.install_x.Foo + marketplace.upgrade_to_x.Foo

EDITIONS_ORDER.indexOf(edition.key)); +} + +export const DEFAULT_FILTER = 'all'; export const parseQuery = memoize((urlQuery: RawQuery): Query => ({ filter: parseAsString(urlQuery['filter']) || DEFAULT_FILTER, search: parseAsString(urlQuery['search']) 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 f3f98744441..764787f4ee0 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -2068,9 +2068,12 @@ marketplace.updates_only=Updates Only marketplace.restart=Restart marketplace.revert=Revert marketplace.install=Install -marketplace.install_x=Install {0} +marketplace.upgrade_to_x=Upgrade to {0} +marketplace.downgrade_to_x=Downgrade to {0} marketplace.installed=Installed marketplace.installing=Installing... +marketplace.upgrade=Upgrade +marketplace.downgrade=Downgrade marketplace.uninstall_x=Uninstall {0} marketplace.uninstall_x_confirmation=Are you sure you want to uninstall {0} and get back to the Community Edition? marketplace.pending=Pending... -- 2.39.5