diff options
author | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-10-27 11:26:58 +0200 |
---|---|---|
committer | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-10-27 16:03:44 +0200 |
commit | 35a5d851cedbe4fee51fe5cecb7cb3205e7713fe (patch) | |
tree | e0285271a46ceb4b41f61200e74f4860ced6ee56 /server | |
parent | e5b81bb8654d0a6ffa4aa80cbc2928410fdf1b68 (diff) | |
download | sonarqube-35a5d851cedbe4fee51fe5cecb7cb3205e7713fe.tar.gz sonarqube-35a5d851cedbe4fee51fe5cecb7cb3205e7713fe.zip |
SONAR-9936 Switch to upgrade/downgrade buttons in the editions
Diffstat (limited to 'server')
13 files changed, 348 insertions, 174 deletions
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<Props, State> { 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 ( + <LicenseEditionForm + edition={installEdition} + editions={sortedEditions} + isDowngrade={ + installedIdx !== undefined && + installEditionIdx !== undefined && + installEditionIdx < installedIdx + } + onClose={this.handleCloseLicenseForm} + updateEditionStatus={this.props.updateEditionStatus} + /> + ); + } + + if (canUninstall && openUninstallForm && editionStatus && editionStatus.currentEditionKey) { + return ( + <UninstallEditionForm + edition={sortedEditions.find(edition => 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 <i className="big-spacer-bottom spinner" />; } @@ -76,41 +113,26 @@ export default class EditionBoxes extends React.PureComponent<Props, State> { ); } + const sortedEditions = sortEditions(editions); + const installedIdx = + editionStatus && + sortedEditions.findIndex(edition => edition.key === editionStatus.currentEditionKey); return ( <div className="spacer-bottom marketplace-editions"> - {editions.map(edition => ( + {sortedEditions.map((edition, idx) => ( <EditionBox canInstall={canInstall} canUninstall={canUninstall} edition={edition} editionStatus={editionStatus} + isDowngrade={installedIdx !== undefined && idx < installedIdx} key={edition.key} onInstall={this.handleOpenLicenseForm} onUninstall={this.handleOpenUninstallForm} /> ))} - {canInstall && - installEdition && ( - <LicenseEditionForm - edition={installEdition} - editions={editions} - onClose={this.handleCloseLicenseForm} - updateEditionStatus={this.props.updateEditionStatus} - /> - )} - - {canUninstall && - openUninstallForm && - editionStatus && - editionStatus.currentEditionKey && ( - <UninstallEditionForm - edition={editions.find(edition => edition.key === editionStatus.currentEditionKey)} - editionStatus={editionStatus} - onClose={this.handleCloseUninstallForm} - updateEditionStatus={this.props.updateEditionStatus} - /> - )} + {this.renderForms(sortedEditions, installedIdx)} </div> ); } 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`] = ` </div> `; -exports[`should display the edition boxes 1`] = ` +exports[`should display the edition boxes correctly 1`] = ` <i className="big-spacer-bottom spinner" /> `; -exports[`should display the edition boxes 2`] = ` +exports[`should display the edition boxes correctly 2`] = ` <div className="spacer-bottom marketplace-editions" > @@ -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<Props> { 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 ( - <span className="marketplace-edition-badge badge badge-normal-size"> - {installReady ? translate('marketplace.pending') : translate('marketplace.installing')} - </span> + <button disabled={installInProgress || uninstallInProgress} onClick={this.handleInstall}> + {this.props.isDowngrade ? ( + translate('marketplace.downgrade') + ) : ( + translate('marketplace.upgrade') + )} + </button> ); } - if (isInstalled) { + if (canUninstall && isInstalled) { return ( - <span className="marketplace-edition-badge badge badge-normal-size"> - <CheckIcon size={14} className="little-spacer-right text-bottom" /> - {translate('marketplace.installed')} - </span> + <button + className="button-red" + disabled={installInProgress || uninstallInProgress} + onClick={this.props.onUninstall}> + {translate('marketplace.uninstall')} + </button> ); } + 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 ( <div className="boxed-group boxed-group-inner marketplace-edition"> - {this.renderBadge(isInstalled, installInProgress)} + {editionStatus && <EditionBoxBadge editionKey={edition.key} status={editionStatus} />} <div> <h3 className="spacer-bottom">{edition.name}</h3> <p>{edition.textDescription}</p> @@ -76,23 +82,7 @@ export default class EditionBox extends React.PureComponent<Props> { <a href={edition.homeUrl} target="_blank"> {translate('marketplace.learn_more')} </a> - {canUninstall && - isInstalled && ( - <button - className="button-red" - disabled={installInProgress || uninstallInProgress} - onClick={this.props.onUninstall}> - {translate('marketplace.uninstall')} - </button> - )} - {canInstall && - !isInstalled && ( - <button - disabled={installInProgress || uninstallInProgress} - onClick={this.handleInstall}> - {translate('marketplace.install')} - </button> - )} + {this.renderActions(isInstalled, installInProgress)} </div> </div> ); 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 ( + <span className="marketplace-edition-badge badge badge-normal-size"> + {installReady ? translate('marketplace.pending') : translate('marketplace.installing')} + </span> + ); + } + + const isInstalled = status.currentEditionKey === editionKey; + if (isInstalled) { + return ( + <span className="marketplace-edition-badge badge badge-normal-size"> + <CheckIcon size={14} className="little-spacer-right text-bottom" /> + {translate('marketplace.installed')} + </span> + ); + } + + 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<Props, State }; render() { - const { edition } = this.props; + const { edition, isDowngrade } = this.props; const { submitting, status } = this.state; - const header = translateWithParameters('marketplace.install_x', edition.name); + + const header = isDowngrade + ? translateWithParameters('marketplace.downgrade_to_x', edition.name) + : translateWithParameters('marketplace.upgrade_to_x', edition.name); return ( <Modal isOpen={true} diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionBox-test.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionBox-test.tsx index dbfa141f629..1fdf88ee8db 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionBox-test.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionBox-test.tsx @@ -41,31 +41,16 @@ it('should display the edition', () => { 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( <EditionBox diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionBoxBadge-test.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionBoxBadge-test.tsx new file mode 100644 index 00000000000..88a9c2c4ab0 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionBoxBadge-test.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 { shallow } from 'enzyme'; +import { EditionStatus } from '../../../../api/marketplace'; +import EditionBoxBadge from '../EditionBoxBadge'; + +const DEFAULT_STATUS: EditionStatus = { + currentEditionKey: '', + nextEditionKey: '', + installationStatus: 'NONE' +}; + +it('should display installed badge', () => { + 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(<EditionBoxBadge editionKey="foo" status={DEFAULT_STATUS} {...props} />); +} 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 = {}) { <LicenseEditionForm edition={DEFAULT_EDITION} editions={[DEFAULT_EDITION]} + isDowngrade={false} onClose={jest.fn()} updateEditionStatus={jest.fn()} {...props} diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionBox-test.tsx.snap b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionBox-test.tsx.snap index b7dbb58a562..c054a76bac9 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionBox-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionBox-test.tsx.snap @@ -1,14 +1,19 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should disable install button 1`] = ` +exports[`should correctly hide upgrade/uninstall buttons 1`] = ` <div className="boxed-group boxed-group-inner marketplace-edition" > - <span - className="marketplace-edition-badge badge badge-normal-size" - > - marketplace.installing - </span> + <EditionBoxBadge + editionKey="foo" + status={ + Object { + "currentEditionKey": "", + "installationStatus": "NONE", + "nextEditionKey": "", + } + } + /> <div> <h3 className="spacer-bottom" @@ -28,25 +33,24 @@ exports[`should disable install button 1`] = ` > marketplace.learn_more </a> - <button - disabled={true} - onClick={[Function]} - > - marketplace.install - </button> </div> </div> `; -exports[`should disable install button 2`] = ` +exports[`should correctly hide upgrade/uninstall buttons 2`] = ` <div className="boxed-group boxed-group-inner marketplace-edition" > - <span - className="marketplace-edition-badge badge badge-normal-size" - > - marketplace.pending - </span> + <EditionBoxBadge + editionKey="foo" + status={ + Object { + "currentEditionKey": "foo", + "installationStatus": "NONE", + "nextEditionKey": "", + } + } + /> <div> <h3 className="spacer-bottom" @@ -66,12 +70,6 @@ exports[`should disable install button 2`] = ` > marketplace.learn_more </a> - <button - disabled={true} - onClick={[Function]} - > - marketplace.install - </button> </div> </div> `; @@ -80,11 +78,16 @@ exports[`should disable uninstall button 1`] = ` <div className="boxed-group boxed-group-inner marketplace-edition" > - <span - className="marketplace-edition-badge badge badge-normal-size" - > - marketplace.installing - </span> + <EditionBoxBadge + editionKey="foo" + status={ + Object { + "currentEditionKey": "foo", + "installationStatus": "AUTOMATIC_IN_PROGRESS", + "nextEditionKey": "foo", + } + } + /> <div> <h3 className="spacer-bottom" @@ -115,19 +118,20 @@ exports[`should disable uninstall button 1`] = ` </div> `; -exports[`should display installed badge 1`] = ` +exports[`should disable upgrade button 1`] = ` <div className="boxed-group boxed-group-inner marketplace-edition" > - <span - className="marketplace-edition-badge badge badge-normal-size" - > - <CheckIcon - className="little-spacer-right text-bottom" - size={14} - /> - marketplace.installed - </span> + <EditionBoxBadge + editionKey="foo" + status={ + Object { + "currentEditionKey": "", + "installationStatus": "AUTOMATIC_IN_PROGRESS", + "nextEditionKey": "foo", + } + } + /> <div> <h3 className="spacer-bottom" @@ -148,25 +152,29 @@ exports[`should display installed badge 1`] = ` marketplace.learn_more </a> <button - className="button-red" - disabled={false} + disabled={true} onClick={[Function]} > - marketplace.uninstall + marketplace.upgrade </button> </div> </div> `; -exports[`should display installing badge 1`] = ` +exports[`should disable upgrade button 2`] = ` <div className="boxed-group boxed-group-inner marketplace-edition" > - <span - className="marketplace-edition-badge badge badge-normal-size" - > - marketplace.installing - </span> + <EditionBoxBadge + editionKey="foo" + status={ + Object { + "currentEditionKey": "", + "installationStatus": "AUTOMATIC_READY", + "nextEditionKey": "foo", + } + } + /> <div> <h3 className="spacer-bottom" @@ -187,25 +195,29 @@ exports[`should display installing badge 1`] = ` marketplace.learn_more </a> <button - className="button-red" disabled={true} onClick={[Function]} > - marketplace.uninstall + marketplace.upgrade </button> </div> </div> `; -exports[`should display pending badge 1`] = ` +exports[`should display a downgrade button 1`] = ` <div className="boxed-group boxed-group-inner marketplace-edition" > - <span - className="marketplace-edition-badge badge badge-normal-size" - > - marketplace.pending - </span> + <EditionBoxBadge + editionKey="foo" + status={ + Object { + "currentEditionKey": "", + "installationStatus": "NONE", + "nextEditionKey": "", + } + } + /> <div> <h3 className="spacer-bottom" @@ -226,10 +238,10 @@ exports[`should display pending badge 1`] = ` marketplace.learn_more </a> <button - disabled={true} + disabled={false} onClick={[Function]} > - marketplace.install + marketplace.downgrade </button> </div> </div> @@ -239,6 +251,16 @@ exports[`should display the edition 1`] = ` <div className="boxed-group boxed-group-inner marketplace-edition" > + <EditionBoxBadge + editionKey="foo" + status={ + Object { + "currentEditionKey": "", + "installationStatus": "NONE", + "nextEditionKey": "", + } + } + /> <div> <h3 className="spacer-bottom" @@ -262,7 +284,7 @@ exports[`should display the edition 1`] = ` disabled={false} onClick={[Function]} > - marketplace.install + marketplace.upgrade </button> </div> </div> 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" > <h2> - marketplace.install_x.Foo + marketplace.upgrade_to_x.Foo </h2> </header> <LicenseEditionSet diff --git a/server/sonar-web/src/main/js/apps/marketplace/utils.ts b/server/sonar-web/src/main/js/apps/marketplace/utils.ts index 780fafb3af8..c3979bd8802 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/utils.ts +++ b/server/sonar-web/src/main/js/apps/marketplace/utils.ts @@ -17,17 +17,16 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { memoize } from 'lodash'; +import { memoize, sortBy } from 'lodash'; import { Plugin, PluginAvailable, PluginInstalled, PluginPending } from '../../api/plugins'; import { cleanQuery, parseAsString, RawQuery, serializeString } from '../../helpers/query'; +import { Edition } from '../../api/marketplace'; export interface Query { filter: string; search?: string; } -export const DEFAULT_FILTER = 'all'; - export function isPluginAvailable(plugin: Plugin): plugin is PluginAvailable { return (plugin as any).release !== undefined; } @@ -51,6 +50,12 @@ export function filterPlugins(plugins: Plugin[], search: string): Plugin[] { }); } +const EDITIONS_ORDER = ['community', 'developer', 'enterprise', 'datacenter']; +export function sortEditions(editions: Edition[]): Edition[] { + return sortBy(editions, edition => 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']) |