diff options
author | Wouter Admiraal <wouter.admiraal@sonarsource.com> | 2020-06-15 13:06:06 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2020-06-19 20:04:42 +0000 |
commit | b66618cf03868a56c3fee751a82c1de13c674e79 (patch) | |
tree | aba2679c2de36bfd306950219db3049634641c4e /server/sonar-web/src/main/js/apps/marketplace | |
parent | 8cbfbbe99dab20d6ecf3477d64888e474dbe6428 (diff) | |
download | sonarqube-b66618cf03868a56c3fee751a82c1de13c674e79.tar.gz sonarqube-b66618cf03868a56c3fee751a82c1de13c674e79.zip |
SONAR-13386 Don't show 'plugin will get installed' if it's already installed
Diffstat (limited to 'server/sonar-web/src/main/js/apps/marketplace')
19 files changed, 665 insertions, 55 deletions
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 6f54f90f4c8..be0278ceb20 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/App.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/App.tsx @@ -25,13 +25,12 @@ import { getAvailablePlugins, getInstalledPlugins, getInstalledPluginsWithUpdates, - getPluginUpdates, - Plugin, - PluginPendingResult + getPluginUpdates } from '../../api/plugins'; import Suggestions from '../../app/components/embed-docs-modal/Suggestions'; import { Location, Router, withRouter } from '../../components/hoc/withRouter'; import { EditionKey } from '../../types/editions'; +import { PendingPluginResult, Plugin } from '../../types/plugins'; import EditionBoxes from './EditionBoxes'; import Footer from './Footer'; import Header from './Header'; @@ -43,7 +42,7 @@ import { filterPlugins, parseQuery, Query, serializeQuery } from './utils'; interface Props { currentEdition?: EditionKey; fetchPendingPlugins: () => void; - pendingPlugins: PluginPendingResult; + pendingPlugins: PendingPluginResult; location: Location; router: Pick<Router, 'push'>; standaloneMode?: boolean; diff --git a/server/sonar-web/src/main/js/apps/marketplace/PluginsList.tsx b/server/sonar-web/src/main/js/apps/marketplace/PluginsList.tsx index 8d864fcdf59..4c1933ac587 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/PluginsList.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/PluginsList.tsx @@ -18,17 +18,22 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { Plugin, PluginPending } from '../../api/plugins'; +import { + InstalledPlugin, + isAvailablePlugin, + isInstalledPlugin, + PendingPlugin, + Plugin +} from '../../types/plugins'; import PluginAvailable from './components/PluginAvailable'; import PluginInstalled from './components/PluginInstalled'; -import { isPluginAvailable, isPluginInstalled } from './utils'; interface Props { plugins: Plugin[]; pending: { - installing: PluginPending[]; - updating: PluginPending[]; - removing: PluginPending[]; + installing: PendingPlugin[]; + updating: PendingPlugin[]; + removing: PendingPlugin[]; }; readOnly: boolean; refreshPending: () => void; @@ -49,9 +54,9 @@ export default class PluginsList extends React.PureComponent<Props> { return undefined; }; - renderPlugin = (plugin: Plugin) => { + renderPlugin = (plugin: Plugin, installedPlugins: InstalledPlugin[]) => { const status = this.getPluginStatus(plugin); - if (isPluginInstalled(plugin)) { + if (isInstalledPlugin(plugin)) { return ( <PluginInstalled plugin={plugin} @@ -61,9 +66,10 @@ export default class PluginsList extends React.PureComponent<Props> { /> ); } - if (isPluginAvailable(plugin)) { + if (isAvailablePlugin(plugin)) { return ( <PluginAvailable + installedPlugins={installedPlugins} plugin={plugin} readOnly={this.props.readOnly} refreshPending={this.props.refreshPending} @@ -75,13 +81,14 @@ export default class PluginsList extends React.PureComponent<Props> { }; render() { + const installedPlugins = this.props.plugins.filter(isInstalledPlugin); return ( <div className="boxed-group boxed-group-inner" id="marketplace-plugins"> <ul> {this.props.plugins.map(plugin => ( <li className="panel panel-vertical" key={plugin.key}> <table className="marketplace-plugin-table"> - <tbody>{this.renderPlugin(plugin)}</tbody> + <tbody>{this.renderPlugin(plugin, installedPlugins)}</tbody> </table> </li> ))} diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/PluginActions.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/PluginActions.tsx index 57b237d965f..06319354ad5 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/PluginActions.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/PluginActions.tsx @@ -22,8 +22,8 @@ import { Button } from 'sonar-ui-common/components/controls/buttons'; import Checkbox from 'sonar-ui-common/components/controls/Checkbox'; import CheckIcon from 'sonar-ui-common/components/icons/CheckIcon'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { installPlugin, Plugin, uninstallPlugin, updatePlugin } from '../../../api/plugins'; -import { isPluginAvailable, isPluginInstalled } from '../utils'; +import { installPlugin, uninstallPlugin, updatePlugin } from '../../../api/plugins'; +import { isAvailablePlugin, isInstalledPlugin, Plugin } from '../../../types/plugins'; import PluginUpdateButton from './PluginUpdateButton'; interface Props { @@ -75,7 +75,7 @@ export default class PluginActions extends React.PureComponent<Props, State> { return ( <div className="js-actions"> - {isPluginAvailable(plugin) && ( + {isAvailablePlugin(plugin) && ( <div> <p className="little-spacer-bottom"> {translate('marketplace.available_under_commercial_license')} @@ -85,13 +85,13 @@ export default class PluginActions extends React.PureComponent<Props, State> { </a> </div> )} - {isPluginInstalled(plugin) && ( + {isInstalledPlugin(plugin) && ( <p> <CheckIcon className="little-spacer-right" /> {translate('marketplace.installed')} </p> )} - {isPluginInstalled(plugin) && plugin.updates && plugin.updates.length > 0 && ( + {isInstalledPlugin(plugin) && plugin.updates && plugin.updates.length > 0 && ( <div className="spacer-top"> {plugin.updates.map((update, idx) => ( <PluginUpdateButton @@ -117,7 +117,7 @@ export default class PluginActions extends React.PureComponent<Props, State> { const { loading } = this.state; return ( <div className="js-actions"> - {isPluginAvailable(plugin) && plugin.termsAndConditionsUrl && ( + {isAvailablePlugin(plugin) && plugin.termsAndConditionsUrl && ( <p className="little-spacer-bottom"> <Checkbox checked={this.state.acceptTerms} @@ -138,7 +138,7 @@ export default class PluginActions extends React.PureComponent<Props, State> { </p> )} {loading && <i className="spinner spacer-right little-spacer-top little-spacer-bottom" />} - {isPluginInstalled(plugin) && ( + {isInstalledPlugin(plugin) && ( <div className="display-inlin-block"> {plugin.updates && plugin.updates.map((update, idx) => ( @@ -157,7 +157,7 @@ export default class PluginActions extends React.PureComponent<Props, State> { </Button> </div> )} - {isPluginAvailable(plugin) && ( + {isAvailablePlugin(plugin) && ( <Button className="js-install" disabled={loading || (plugin.termsAndConditionsUrl != null && !this.state.acceptTerms)} diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/PluginAvailable.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/PluginAvailable.tsx index 6b166a46eba..985e4212f9e 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/PluginAvailable.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/PluginAvailable.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { translateWithParameters } from 'sonar-ui-common/helpers/l10n'; -import { PluginAvailable as IPluginAvailable } from '../../../api/plugins'; +import { AvailablePlugin, InstalledPlugin } from '../../../types/plugins'; import PluginChangeLogButton from './PluginChangeLogButton'; import PluginDescription from './PluginDescription'; import PluginLicense from './PluginLicense'; @@ -27,14 +27,17 @@ import PluginOrganization from './PluginOrganization'; import PluginStatus from './PluginStatus'; import PluginUrls from './PluginUrls'; -interface Props { - plugin: IPluginAvailable; +export interface PluginAvailableProps { + installedPlugins: InstalledPlugin[]; + plugin: AvailablePlugin; readOnly: boolean; refreshPending: () => void; status?: string; } -export default function PluginAvailable({ plugin, readOnly, refreshPending, status }: Props) { +export default function PluginAvailable(props: PluginAvailableProps) { + const { installedPlugins, plugin, readOnly, status } = props; + const installedPluginKeys = installedPlugins.map(({ key }) => key); return ( <tr> <PluginDescription plugin={plugin} /> @@ -52,7 +55,10 @@ export default function PluginAvailable({ plugin, readOnly, refreshPending, stat <strong> {translateWithParameters( 'marketplace.installing_this_plugin_will_also_install_x', - plugin.update.requires.map(requiredPlugin => requiredPlugin.name).join(', ') + plugin.update.requires + .filter(({ key }) => !installedPluginKeys.includes(key)) + .map(requiredPlugin => requiredPlugin.name) + .join(', ') )} </strong> </p> @@ -71,7 +77,7 @@ export default function PluginAvailable({ plugin, readOnly, refreshPending, stat </td> {!readOnly && ( - <PluginStatus plugin={plugin} refreshPending={refreshPending} status={status} /> + <PluginStatus plugin={plugin} refreshPending={props.refreshPending} status={status} /> )} </tr> ); diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/PluginChangeLog.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/PluginChangeLog.tsx index 95fff94e48e..9891560e82d 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/PluginChangeLog.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/PluginChangeLog.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { Release, Update } from '../../../api/plugins'; +import { Release, Update } from '../../../types/plugins'; import PluginChangeLogItem from './PluginChangeLogItem'; export interface Props { diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/PluginChangeLogButton.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/PluginChangeLogButton.tsx index 5824380100a..402a4665ed4 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/PluginChangeLogButton.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/PluginChangeLogButton.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import { ButtonLink } from 'sonar-ui-common/components/controls/buttons'; import Dropdown from 'sonar-ui-common/components/controls/Dropdown'; import EllipsisIcon from 'sonar-ui-common/components/icons/EllipsisIcon'; -import { Release, Update } from '../../../api/plugins'; +import { Release, Update } from '../../../types/plugins'; import PluginChangeLog from './PluginChangeLog'; interface Props { diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/PluginChangeLogItem.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/PluginChangeLogItem.tsx index 7e0da5e02ee..0e45bc31d72 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/PluginChangeLogItem.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/PluginChangeLogItem.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import Tooltip from 'sonar-ui-common/components/controls/Tooltip'; import DateFormatter from 'sonar-ui-common/components/intl/DateFormatter'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { Release, Update } from '../../../api/plugins'; +import { Release, Update } from '../../../types/plugins'; interface Props { release: Release; diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/PluginDescription.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/PluginDescription.tsx index e964a0a0e71..a099350e7a7 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/PluginDescription.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/PluginDescription.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { Plugin } from '../../../api/plugins'; +import { Plugin } from '../../../types/plugins'; interface Props { plugin: Plugin; diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/PluginInstalled.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/PluginInstalled.tsx index 7c3070e9804..e3859f7c25b 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/PluginInstalled.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/PluginInstalled.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { PluginInstalled as IPluginInstalled } from '../../../api/plugins'; +import { InstalledPlugin } from '../../../types/plugins'; import PluginDescription from './PluginDescription'; import PluginLicense from './PluginLicense'; import PluginOrganization from './PluginOrganization'; @@ -28,7 +28,7 @@ import PluginUpdates from './PluginUpdates'; import PluginUrls from './PluginUrls'; interface Props { - plugin: IPluginInstalled; + plugin: InstalledPlugin; readOnly: boolean; refreshPending: () => void; status?: string; diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/PluginOrganization.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/PluginOrganization.tsx index 204fbb5c216..b889cbd82bd 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/PluginOrganization.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/PluginOrganization.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { Plugin } from '../../../api/plugins'; +import { Plugin } from '../../../types/plugins'; export interface PluginOrganizationProps { plugin: Plugin; diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/PluginStatus.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/PluginStatus.tsx index 41b4ddf0ee7..a7a603336d8 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/PluginStatus.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/PluginStatus.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { Plugin } from '../../../api/plugins'; +import { Plugin } from '../../../types/plugins'; import PluginActions from './PluginActions'; interface Props { diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/PluginUpdateButton.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/PluginUpdateButton.tsx index a7d094504b2..e34e3f37bad 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/PluginUpdateButton.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/PluginUpdateButton.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import { Button } from 'sonar-ui-common/components/controls/buttons'; import { translateWithParameters } from 'sonar-ui-common/helpers/l10n'; -import { Update } from '../../../api/plugins'; +import { Update } from '../../../types/plugins'; interface Props { disabled: boolean; diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/PluginUpdateItem.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/PluginUpdateItem.tsx index a1e1e36cfcb..f6ef8eff74e 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/PluginUpdateItem.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/PluginUpdateItem.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import Tooltip from 'sonar-ui-common/components/controls/Tooltip'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { Release, Update } from '../../../api/plugins'; +import { Release, Update } from '../../../types/plugins'; import PluginChangeLogButton from './PluginChangeLogButton'; interface Props { diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/PluginUpdates.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/PluginUpdates.tsx index ab76582882a..0d6064d7e33 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/PluginUpdates.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/PluginUpdates.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { Update } from '../../../api/plugins'; +import { Update } from '../../../types/plugins'; import PluginUpdateItem from './PluginUpdateItem'; interface Props { diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/PluginUrls.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/PluginUrls.tsx index 6a13802c3f9..f5e20c2fdc7 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/PluginUrls.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/PluginUrls.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { Plugin } from '../../../api/plugins'; +import { Plugin } from '../../../types/plugins'; interface Props { plugin: Plugin; diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/PluginActions-test.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/PluginActions-test.tsx index b549e44431c..2d2c245a9fa 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/PluginActions-test.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/PluginActions-test.tsx @@ -19,10 +19,10 @@ */ import { shallow } from 'enzyme'; import * as React from 'react'; -import { PluginAvailable, PluginInstalled } from '../../../../api/plugins'; +import { AvailablePlugin, InstalledPlugin } from '../../../../types/plugins'; import PluginActions from '../PluginActions'; -const installedPlugin: PluginInstalled = { +const installedPlugin: InstalledPlugin = { key: 'foo', name: 'Foo', filename: 'foo.zip', @@ -35,7 +35,7 @@ const installedPlugin: PluginInstalled = { version: '7.7' }; -const availablePlugin: PluginAvailable = { +const availablePlugin: AvailablePlugin = { key: 'foo', name: 'Foo', release: { version: '7.7', date: 'date' }, diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/PluginAvailable-test.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/PluginAvailable-test.tsx new file mode 100644 index 00000000000..360592ea24c --- /dev/null +++ b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/PluginAvailable-test.tsx @@ -0,0 +1,64 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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 { shallow } from 'enzyme'; +import * as React from 'react'; +import { + mockAvailablePlugin, + mockInstalledPlugin, + mockPlugin, + mockUpdate +} from '../../../../helpers/mocks/plugins'; +import PluginAvailable, { PluginAvailableProps } from '../PluginAvailable'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot('default'); + expect(shallowRender({ readOnly: true })).toMatchSnapshot('read only'); + expect( + shallowRender({ + plugin: mockAvailablePlugin({ + update: mockUpdate({ requires: [mockPlugin()] }) + }) + }) + ).toMatchSnapshot('has requirements'); + const installed = mockInstalledPlugin({ key: 'sonar-bar', name: 'Sonar Bar' }); + expect( + shallowRender({ + installedPlugins: [installed], + plugin: mockAvailablePlugin({ + update: mockUpdate({ + requires: [mockPlugin(), installed] + }) + }) + }) + ).toMatchSnapshot('has requirements, some of them already met'); +}); + +function shallowRender(props: Partial<PluginAvailableProps> = {}) { + return shallow<PluginAvailableProps>( + <PluginAvailable + installedPlugins={[]} + plugin={mockAvailablePlugin()} + readOnly={false} + refreshPending={jest.fn()} + {...props} + /> + ); +} diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/PluginAvailable-test.tsx.snap b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/PluginAvailable-test.tsx.snap new file mode 100644 index 00000000000..9222f0091d3 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/PluginAvailable-test.tsx.snap @@ -0,0 +1,546 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly: default 1`] = ` +<tr> + <PluginDescription + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [], + "status": "available", + }, + } + } + /> + <td + className="text-top big-spacer-right" + > + <ul> + <li + className="display-flex-row little-spacer-bottom" + > + <div + className="pull-left spacer-right" + > + <span + className="badge badge-success" + > + 8.2 + </span> + </div> + <div> + <PluginChangeLogButton + release={ + Object { + "date": "2020-01-01", + "version": "8.2", + } + } + update={ + Object { + "requires": Array [], + "status": "available", + } + } + /> + </div> + </li> + </ul> + </td> + <td + className="text-top width-20" + > + <ul> + <PluginUrls + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [], + "status": "available", + }, + } + } + /> + <PluginLicense /> + <PluginOrganization + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [], + "status": "available", + }, + } + } + /> + </ul> + </td> + <PluginStatus + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [], + "status": "available", + }, + } + } + refreshPending={[MockFunction]} + /> +</tr> +`; + +exports[`should render correctly: has requirements 1`] = ` +<tr> + <PluginDescription + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + }, + ], + "status": "available", + }, + } + } + /> + <td + className="text-top big-spacer-right" + > + <ul> + <li + className="display-flex-row little-spacer-bottom" + > + <div + className="pull-left spacer-right" + > + <span + className="badge badge-success" + > + 8.2 + </span> + </div> + <div> + <PluginChangeLogButton + release={ + Object { + "date": "2020-01-01", + "version": "8.2", + } + } + update={ + Object { + "requires": Array [ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + }, + ], + "status": "available", + } + } + /> + <p + className="little-spacer-top" + > + <strong> + marketplace.installing_this_plugin_will_also_install_x.Sonar Foo + </strong> + </p> + </div> + </li> + </ul> + </td> + <td + className="text-top width-20" + > + <ul> + <PluginUrls + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + }, + ], + "status": "available", + }, + } + } + /> + <PluginLicense /> + <PluginOrganization + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + }, + ], + "status": "available", + }, + } + } + /> + </ul> + </td> + <PluginStatus + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + }, + ], + "status": "available", + }, + } + } + refreshPending={[MockFunction]} + /> +</tr> +`; + +exports[`should render correctly: has requirements, some of them already met 1`] = ` +<tr> + <PluginDescription + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + }, + Object { + "filename": "sonar-bar-1.0.jar", + "hash": "hash", + "implementationBuild": "1.0.0.1234", + "key": "sonar-bar", + "name": "Sonar Bar", + "sonarLintSupported": false, + "updatedAt": 100, + "version": "1.0", + }, + ], + "status": "available", + }, + } + } + /> + <td + className="text-top big-spacer-right" + > + <ul> + <li + className="display-flex-row little-spacer-bottom" + > + <div + className="pull-left spacer-right" + > + <span + className="badge badge-success" + > + 8.2 + </span> + </div> + <div> + <PluginChangeLogButton + release={ + Object { + "date": "2020-01-01", + "version": "8.2", + } + } + update={ + Object { + "requires": Array [ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + }, + Object { + "filename": "sonar-bar-1.0.jar", + "hash": "hash", + "implementationBuild": "1.0.0.1234", + "key": "sonar-bar", + "name": "Sonar Bar", + "sonarLintSupported": false, + "updatedAt": 100, + "version": "1.0", + }, + ], + "status": "available", + } + } + /> + <p + className="little-spacer-top" + > + <strong> + marketplace.installing_this_plugin_will_also_install_x.Sonar Foo + </strong> + </p> + </div> + </li> + </ul> + </td> + <td + className="text-top width-20" + > + <ul> + <PluginUrls + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + }, + Object { + "filename": "sonar-bar-1.0.jar", + "hash": "hash", + "implementationBuild": "1.0.0.1234", + "key": "sonar-bar", + "name": "Sonar Bar", + "sonarLintSupported": false, + "updatedAt": 100, + "version": "1.0", + }, + ], + "status": "available", + }, + } + } + /> + <PluginLicense /> + <PluginOrganization + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + }, + Object { + "filename": "sonar-bar-1.0.jar", + "hash": "hash", + "implementationBuild": "1.0.0.1234", + "key": "sonar-bar", + "name": "Sonar Bar", + "sonarLintSupported": false, + "updatedAt": 100, + "version": "1.0", + }, + ], + "status": "available", + }, + } + } + /> + </ul> + </td> + <PluginStatus + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + }, + Object { + "filename": "sonar-bar-1.0.jar", + "hash": "hash", + "implementationBuild": "1.0.0.1234", + "key": "sonar-bar", + "name": "Sonar Bar", + "sonarLintSupported": false, + "updatedAt": 100, + "version": "1.0", + }, + ], + "status": "available", + }, + } + } + refreshPending={[MockFunction]} + /> +</tr> +`; + +exports[`should render correctly: read only 1`] = ` +<tr> + <PluginDescription + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [], + "status": "available", + }, + } + } + /> + <td + className="text-top big-spacer-right" + > + <ul> + <li + className="display-flex-row little-spacer-bottom" + > + <div + className="pull-left spacer-right" + > + <span + className="badge badge-success" + > + 8.2 + </span> + </div> + <div> + <PluginChangeLogButton + release={ + Object { + "date": "2020-01-01", + "version": "8.2", + } + } + update={ + Object { + "requires": Array [], + "status": "available", + } + } + /> + </div> + </li> + </ul> + </td> + <td + className="text-top width-20" + > + <ul> + <PluginUrls + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [], + "status": "available", + }, + } + } + /> + <PluginLicense /> + <PluginOrganization + plugin={ + Object { + "key": "sonar-foo", + "name": "Sonar Foo", + "release": Object { + "date": "2020-01-01", + "version": "8.2", + }, + "update": Object { + "requires": Array [], + "status": "available", + }, + } + } + /> + </ul> + </td> +</tr> +`; 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 4aa1ad8b878..db6ed4743ee 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/utils.ts +++ b/server/sonar-web/src/main/js/apps/marketplace/utils.ts @@ -19,7 +19,7 @@ */ import { memoize } from 'lodash'; import { cleanQuery, parseAsString, serializeString } from 'sonar-ui-common/helpers/query'; -import { Plugin, PluginAvailable, PluginInstalled, PluginPending } from '../../api/plugins'; +import { Plugin } from '../../types/plugins'; export interface Query { filter: string; @@ -43,18 +43,6 @@ export function filterPlugins(plugins: Plugin[], search?: string): Plugin[] { }); } -export function isPluginAvailable(plugin: Plugin): plugin is PluginAvailable { - return (plugin as any).release !== undefined; -} - -export function isPluginInstalled(plugin: Plugin): plugin is PluginInstalled { - return isPluginPending(plugin) && (plugin as any).updatedAt !== undefined; -} - -export function isPluginPending(plugin: Plugin): plugin is PluginPending { - return (plugin as any).version !== undefined; -} - export const DEFAULT_FILTER = 'all'; export const parseQuery = memoize( (urlQuery: T.RawQuery): Query => ({ |