Browse Source

SONAR-13385 Sort plugins on Marketplace alphabetically

tags/8.4.0.35506
Wouter Admiraal 4 years ago
parent
commit
e70a984bb2

+ 50
- 63
server/sonar-web/src/main/js/apps/marketplace/PluginsList.tsx View File

@@ -17,18 +17,13 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { sortBy } from 'lodash';
import * as React from 'react';
import {
InstalledPlugin,
isAvailablePlugin,
isInstalledPlugin,
PendingPlugin,
Plugin
} from '../../types/plugins';
import { isAvailablePlugin, isInstalledPlugin, PendingPlugin, Plugin } from '../../types/plugins';
import PluginAvailable from './components/PluginAvailable';
import PluginInstalled from './components/PluginInstalled';

interface Props {
export interface PluginsListProps {
plugins: Plugin[];
pending: {
installing: PendingPlugin[];
@@ -39,61 +34,53 @@ interface Props {
refreshPending: () => void;
}

export default class PluginsList extends React.PureComponent<Props> {
getPluginStatus = (plugin: Plugin): string | undefined => {
const { installing, updating, removing } = this.props.pending;
if (installing.find(p => p.key === plugin.key)) {
return 'installing';
}
if (updating.find(p => p.key === plugin.key)) {
return 'updating';
}
if (removing.find(p => p.key === plugin.key)) {
return 'removing';
}
return undefined;
};
function getPluginStatus(plugin: Plugin, pending: PluginsListProps['pending']): string | undefined {
const { installing, updating, removing } = pending;
if (installing.find(p => p.key === plugin.key)) {
return 'installing';
}
if (updating.find(p => p.key === plugin.key)) {
return 'updating';
}
if (removing.find(p => p.key === plugin.key)) {
return 'removing';
}
return undefined;
}

renderPlugin = (plugin: Plugin, installedPlugins: InstalledPlugin[]) => {
const status = this.getPluginStatus(plugin);
if (isInstalledPlugin(plugin)) {
return (
<PluginInstalled
plugin={plugin}
readOnly={this.props.readOnly}
refreshPending={this.props.refreshPending}
status={status}
/>
);
}
if (isAvailablePlugin(plugin)) {
return (
<PluginAvailable
installedPlugins={installedPlugins}
plugin={plugin}
readOnly={this.props.readOnly}
refreshPending={this.props.refreshPending}
status={status}
/>
);
}
return null;
};
export default function PluginsList(props: PluginsListProps) {
const { pending, plugins, readOnly } = props;
const installedPlugins = plugins.filter(isInstalledPlugin);
return (
<div className="boxed-group boxed-group-inner" id="marketplace-plugins">
<ul>
{sortBy(plugins, ({ name }) => name).map(plugin => (
<li className="panel panel-vertical" key={plugin.key}>
<table className="marketplace-plugin-table">
<tbody>
{isInstalledPlugin(plugin) && (
<PluginInstalled
plugin={plugin}
readOnly={readOnly}
refreshPending={props.refreshPending}
status={getPluginStatus(plugin, pending)}
/>
)}

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, installedPlugins)}</tbody>
</table>
</li>
))}
</ul>
</div>
);
}
{isAvailablePlugin(plugin) && (
<PluginAvailable
installedPlugins={installedPlugins}
plugin={plugin}
readOnly={readOnly}
refreshPending={props.refreshPending}
status={getPluginStatus(plugin, pending)}
/>
)}
</tbody>
</table>
</li>
))}
</ul>
</div>
);
}

+ 53
- 0
server/sonar-web/src/main/js/apps/marketplace/__tests__/PluginsList-test.tsx View File

@@ -0,0 +1,53 @@
/*
* 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, mockPendingPlugin } from '../../../helpers/mocks/plugins';
import PluginsList, { PluginsListProps } from '../PluginsList';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
expect(
shallowRender({
pending: {
installing: [mockPendingPlugin({ key: 'sonar-foo' })],
updating: [mockPendingPlugin({ key: 'sonar-bar' })],
removing: [mockPendingPlugin({ key: 'sonar-baz' })]
}
})
).toMatchSnapshot('with status');
});

function shallowRender(props: Partial<PluginsListProps> = {}) {
return shallow<PluginsListProps>(
<PluginsList
plugins={[
mockAvailablePlugin({ key: 'sonar-foo' }),
mockAvailablePlugin({ key: 'sonar-bar', name: 'Sonar Bar' }),
mockAvailablePlugin({ key: 'sonar-baz', name: 'Sonar Baz' })
]}
pending={{ installing: [], updating: [], removing: [] }}
readOnly={false}
refreshPending={jest.fn()}
{...props}
/>
);
}

+ 204
- 0
server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/PluginsList-test.tsx.snap View File

@@ -0,0 +1,204 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly: default 1`] = `
<div
className="boxed-group boxed-group-inner"
id="marketplace-plugins"
>
<ul>
<li
className="panel panel-vertical"
key="sonar-bar"
>
<table
className="marketplace-plugin-table"
>
<tbody>
<PluginAvailable
installedPlugins={Array []}
plugin={
Object {
"key": "sonar-bar",
"name": "Sonar Bar",
"release": Object {
"date": "2020-01-01",
"version": "8.2",
},
"update": Object {
"requires": Array [],
"status": "available",
},
}
}
readOnly={false}
refreshPending={[MockFunction]}
/>
</tbody>
</table>
</li>
<li
className="panel panel-vertical"
key="sonar-baz"
>
<table
className="marketplace-plugin-table"
>
<tbody>
<PluginAvailable
installedPlugins={Array []}
plugin={
Object {
"key": "sonar-baz",
"name": "Sonar Baz",
"release": Object {
"date": "2020-01-01",
"version": "8.2",
},
"update": Object {
"requires": Array [],
"status": "available",
},
}
}
readOnly={false}
refreshPending={[MockFunction]}
/>
</tbody>
</table>
</li>
<li
className="panel panel-vertical"
key="sonar-foo"
>
<table
className="marketplace-plugin-table"
>
<tbody>
<PluginAvailable
installedPlugins={Array []}
plugin={
Object {
"key": "sonar-foo",
"name": "Sonar Foo",
"release": Object {
"date": "2020-01-01",
"version": "8.2",
},
"update": Object {
"requires": Array [],
"status": "available",
},
}
}
readOnly={false}
refreshPending={[MockFunction]}
/>
</tbody>
</table>
</li>
</ul>
</div>
`;

exports[`should render correctly: with status 1`] = `
<div
className="boxed-group boxed-group-inner"
id="marketplace-plugins"
>
<ul>
<li
className="panel panel-vertical"
key="sonar-bar"
>
<table
className="marketplace-plugin-table"
>
<tbody>
<PluginAvailable
installedPlugins={Array []}
plugin={
Object {
"key": "sonar-bar",
"name": "Sonar Bar",
"release": Object {
"date": "2020-01-01",
"version": "8.2",
},
"update": Object {
"requires": Array [],
"status": "available",
},
}
}
readOnly={false}
refreshPending={[MockFunction]}
status="updating"
/>
</tbody>
</table>
</li>
<li
className="panel panel-vertical"
key="sonar-baz"
>
<table
className="marketplace-plugin-table"
>
<tbody>
<PluginAvailable
installedPlugins={Array []}
plugin={
Object {
"key": "sonar-baz",
"name": "Sonar Baz",
"release": Object {
"date": "2020-01-01",
"version": "8.2",
},
"update": Object {
"requires": Array [],
"status": "available",
},
}
}
readOnly={false}
refreshPending={[MockFunction]}
status="removing"
/>
</tbody>
</table>
</li>
<li
className="panel panel-vertical"
key="sonar-foo"
>
<table
className="marketplace-plugin-table"
>
<tbody>
<PluginAvailable
installedPlugins={Array []}
plugin={
Object {
"key": "sonar-foo",
"name": "Sonar Foo",
"release": Object {
"date": "2020-01-01",
"version": "8.2",
},
"update": Object {
"requires": Array [],
"status": "available",
},
}
}
readOnly={false}
refreshPending={[MockFunction]}
status="installing"
/>
</tbody>
</table>
</li>
</ul>
</div>
`;

+ 18
- 1
server/sonar-web/src/main/js/helpers/mocks/plugins.ts View File

@@ -18,7 +18,14 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

import { AvailablePlugin, InstalledPlugin, Plugin, Release, Update } from '../../types/plugins';
import {
AvailablePlugin,
InstalledPlugin,
PendingPlugin,
Plugin,
Release,
Update
} from '../../types/plugins';

export function mockPlugin(overrides: Partial<Plugin> = {}): Plugin {
return {
@@ -28,6 +35,16 @@ export function mockPlugin(overrides: Partial<Plugin> = {}): Plugin {
};
}

export function mockPendingPlugin(overrides: Partial<PendingPlugin> = {}): PendingPlugin {
return {
key: 'sonar-foo',
name: 'Sonar Foo',
version: '1.0',
implementationBuild: '1.0.0.1234',
...overrides
};
}

export function mockInstalledPlugin(overrides: Partial<InstalledPlugin> = {}): InstalledPlugin {
return {
key: 'sonar-bar',

Loading…
Cancel
Save