]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9936 Switch to upgrade/downgrade buttons in the editions
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Fri, 27 Oct 2017 09:26:58 +0000 (11:26 +0200)
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>
Fri, 27 Oct 2017 14:03:44 +0000 (16:03 +0200)
14 files changed:
server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx
server/sonar-web/src/main/js/apps/marketplace/__tests__/EditionBoxes-test.tsx
server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/EditionBoxes-test.tsx.snap
server/sonar-web/src/main/js/apps/marketplace/components/EditionBox.tsx
server/sonar-web/src/main/js/apps/marketplace/components/EditionBoxBadge.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/marketplace/components/LicenseEditionForm.tsx
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionBox-test.tsx
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionBoxBadge-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/LicenseEditionForm-test.tsx
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionBox-test.tsx.snap
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionBoxBadge-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/LicenseEditionForm-test.tsx.snap
server/sonar-web/src/main/js/apps/marketplace/utils.ts
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index d8a0a5e353368598f63eb4da4e20584018b4eb6b..ddba3af1b7240509b60b32f885fa70d7a14cea60 100644 (file)
@@ -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>
     );
   }
index fe3880cc9f0bcea1a0889b53b4f56dd1e0760f9f..0201372b08642b53c7bad194acda88589ce16717 100644 (file)
@@ -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 });
index f9b86d68f00b550b2080198d25bfc7bc95e6a268..952e8dc78c165d1e4f1f407cb967af06932e1502 100644 (file)
@@ -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]}
   />
index ca8457fe4d137e6fc531ea3dcad2bd0a5ace4c31..6f90fda970e528436485f21e36a030c956c3a6d4 100644 (file)
@@ -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 (file)
index 0000000..47b3e76
--- /dev/null
@@ -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;
+}
index e099465dc4334d1511792851421b918eef87636c..abab7c84ed4a8858a6f6c9f1945936498702e502 100644 (file)
@@ -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}
index dbfa141f629f5dd510f09aeb6fd75b27413877d3..1fdf88ee8db11976f3ee7a1d0a5df094e5579145 100644 (file)
@@ -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 (file)
index 0000000..88a9c2c
--- /dev/null
@@ -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} />);
+}
index bb6e8d213ee431b3264006a58e7e4a45129c1c21..133ac46491342be575676acae5f7195f4bb38a63 100644 (file)
@@ -78,6 +78,7 @@ function getWrapper(props = {}) {
     <LicenseEditionForm
       edition={DEFAULT_EDITION}
       editions={[DEFAULT_EDITION]}
+      isDowngrade={false}
       onClose={jest.fn()}
       updateEditionStatus={jest.fn()}
       {...props}
index b7dbb58a5627c8cfd39a6b6e4045834aff206648..c054a76bac9bf8d72bfdefaea5a764f296737073 100644 (file)
@@ -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 (file)
index 0000000..7e82459
--- /dev/null
@@ -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`;
index 382c562bb02926b03df0f046bf2a75244c08c234..9e07155c2924b563661a27bdbfe560a5601b9c3f 100644 (file)
@@ -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
index 780fafb3af81126ba8404d7c03731bd63cfc009c..c3979bd8802a5ec7a5cacf132ae9a3c04ed63cd2 100644 (file)
  * 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'])
index f3f98744441d0985316cd1887f8c684f51d3648d..764787f4ee0f4cca6259c902e9af3da465bf67a7 100644 (file)
@@ -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...