Skip to content
101 changes: 76 additions & 25 deletions src/components/Plugins/Plugins.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
Grid,
GridItem,
Split,
SplitItem
SplitItem,
} from "@patternfly/react-core";
import { CaretDownIcon } from '@patternfly/react-icons';

Expand All @@ -26,6 +26,7 @@ import { removeEmail } from '../../utils/common';

import './Plugins.css';


const CATEGORIES = ['FreeSurfer', 'MRI', 'Segmentation'];

/**
Expand All @@ -49,12 +50,14 @@ export class Plugins extends Component {
isSortOpen: false,
error: null,
plugins: new PluginMetaList(),
sortedPlugins: null,
paginationLimit: 0,
paginationOffset: 0,
categories,
selectedCategory: null,
starsByPlugin: {},
};

}

/**
Expand All @@ -79,6 +82,44 @@ export class Plugins extends Component {
}
}

/**
* Sort plugins by name, creation date or authors.
*
*/
handleSortPlugins = (sortType)=> {
this.setState({sortedPlugins: null})
const { plugins} = this.state;

const sortedPluginsList = [...plugins.data].sort((a,b) => {
if (typeof a[sortType] !== 'number') return a[sortType].localeCompare(b[sortType])
return b[sortType] - a[sortType]
})

this.setState({
sortedPlugins: sortedPluginsList
})
}


// eslint-disable-next-line react/sort-comp
// async tester(){
// // eslint-disable-next-line no-unused-vars
// let test;
// try {
// test = await this.client.getPlugins({
// limit: 1e6,
// offset: 0,
// name_title_category: null,
// });
// } catch (error) {
// // this.showNotifications(new HttpApiCallError(error));
// console.log(error)

// }
// return test
// }


/**
* Add a star next to the plugin visually.
* (Does not necessarily send to the backend that the plugin is a favorite).
Expand Down Expand Up @@ -107,8 +148,13 @@ export class Plugins extends Component {
* @param name name of category
*/
handleCategorySelect = (category) => {
this.setState({ loading: true, selectedCategory: category });
this.refreshPluginList({ category })
if (category !== null) {
this.refreshPluginList({ category })
this.setState({ loading: true, selectedCategory: category });
} else {
this.refreshPluginList()
this.setState({ loading: true, selectedCategory: null });
}
}

handleToggleSort = () => {
Expand All @@ -117,13 +163,6 @@ export class Plugins extends Component {
}))
}

// eslint-disable-next-line no-unused-vars
handleSortingSelect = (sort) => {
/**
* @todo sort plugins
*/
this.handleToggleSort()
}

/**
* 1. Fetch the list of plugins based on the url path OR search query.
Expand All @@ -134,7 +173,7 @@ export class Plugins extends Component {
const params = new URLSearchParams(window.location.search)
const query = params.get('q');
const { match } = this.props;

const searchParams = {
limit: 20,
offset: 0,
Expand All @@ -158,6 +197,7 @@ export class Plugins extends Component {
searchParams.name_title_category = query;

let plugins;

try {
plugins = await this.client.getPluginMetas(searchParams);
} catch (error) {
Expand Down Expand Up @@ -213,12 +253,12 @@ export class Plugins extends Component {
// count the frequency of catplugins which belong to categories
// eslint-disable-next-line no-restricted-syntax
for (const { category } of catplugins.data)
if (category)
if (category)
categories.set(
category,
categories.has(category) ?
categories.get(category) + 1 : 1);

this.setState({ categories });
}

Expand Down Expand Up @@ -305,21 +345,37 @@ export class Plugins extends Component {
}
}

render() {
render() {
// convert map into the data structure expected by <PluginsCategories />
const { categories, plugins, loading, error } = this.state;
const { categories, plugins, sortedPlugins, loading, error } = this.state;
const { paginationOffset, paginationLimit, isSortOpen, selectedCategory } = this.state;

const categoryEntries = Array.from(categories.entries(), ([name, count]) => ({
name, length: count
}));

const dropdownItems = [
<DropdownItem id="name" key="name" onClick={() => this.handleSortPlugins('name')}>Name</DropdownItem>,
<DropdownItem id="creation_date" key="creation_date" onClick={() => this.handleSortPlugins('creation_date')}>Date created</DropdownItem>,
<DropdownItem id="authors" key="authors" onClick={() => this.handleSortPlugins('authors')}>Author</DropdownItem>,
<DropdownItem id="stars" key="stars" onClick={() => this.handleSortPlugins('stars')}>Most Liked</DropdownItem>
]

const pluginList = new Map()
// eslint-disable-next-line no-restricted-syntax

if (!sortedPlugins){
// eslint-disable-next-line no-restricted-syntax
for (const plugin of plugins.data) {
plugin.authors = removeEmail(plugin.authors.split(','))
pluginList.set(plugin.name, plugin)
}
} else {
// eslint-disable-next-line no-restricted-syntax
for (const plugin of sortedPlugins) {
pluginList.set(plugin.name, plugin)
}
}


// Render the pluginList if the plugins have been fetched
const PluginListBody = () => {
Expand Down Expand Up @@ -370,7 +426,6 @@ export class Plugins extends Component {

const pluginsCount=plugins.totalCount > 0 ? plugins.totalCount : 0;


return (
<article>
{error && (
Expand Down Expand Up @@ -434,28 +489,24 @@ export class Plugins extends Component {
<SplitItem isFilled />
<SplitItem>
<Dropdown
onSelect={this.handleSortingSelect}
onSelect={this.handleToggleSort}
isOpen={isSortOpen}
toggle={
<DropdownToggle id="toggle-id"
<DropdownToggle id="dropdown-toggle"
onToggle={this.handleToggleSort}
toggleIndicator={CaretDownIcon}>
Sort by
Sort by:
</DropdownToggle>
}
dropdownItems={[
<DropdownItem key="name">Name</DropdownItem>
]}
dropdownItems={dropdownItems}
/>
</SplitItem>
<SplitItem>
<PaginationControls />
</SplitItem>
</Split>
</GridItem>

<PluginListBody />

<Split>
<SplitItem isFilled />
<SplitItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const PluginItem = ({
to={`/author/${authors}`}
className="plugin-item-author"
>
{ authors.join(', ') }
{ authors.length > 1 ?? authors.join(', ') }
</Link>
<p style={{ color: 'gray', fontWeight: '600', fontSize: 'small' }}>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const PluginsCategories = ({ categories, selected, onSelect }) => (
onClick={() => onSelect(name)}
onKeyPress={() => {}}
>
<div className="plugins-category-name">{name}</div>
<div className="plugins-category-name">{name.charAt(0).toUpperCase()}{name.substring(1)}</div>
<div className="plugins-category-length">{length}</div>
</div>
))
Expand Down