@@ -104,6 +104,13 @@ function addChangelog(update: Update, updates?: Update[]) { | |||
return { ...update, previousUpdates }; | |||
} | |||
export function getInstalledPlugins(): Promise<PluginInstalled[]> { | |||
return getJSON('/api/plugins/installed', { f: 'category' }).then( | |||
({ plugins }) => plugins, | |||
throwGlobalError | |||
); | |||
} | |||
export function getInstalledPluginsWithUpdates(): Promise<PluginInstalled[]> { | |||
return Promise.all([ | |||
getJSON('/api/plugins/installed', { f: 'category' }), |
@@ -34,7 +34,8 @@ import { | |||
getPendingPlugins, | |||
getPluginUpdates, | |||
Plugin, | |||
PluginPending | |||
PluginPending, | |||
getInstalledPlugins | |||
} from '../../api/plugins'; | |||
import { Edition, EditionStatus } from '../../api/marketplace'; | |||
import { RawQuery } from '../../helpers/query'; | |||
@@ -100,37 +101,32 @@ export default class App extends React.PureComponent<Props, State> { | |||
fetchQueryPlugins = () => { | |||
const query = parseQuery(this.props.location.query); | |||
let fetchFunction = this.fetchAllPlugins; | |||
if (query.filter === 'updates') { | |||
this.fetchUpdatesOnly(); | |||
} else { | |||
this.fetchAllPlugins(); | |||
fetchFunction = getPluginUpdates; | |||
} else if (query.filter === 'installed') { | |||
fetchFunction = getInstalledPlugins; | |||
} | |||
}; | |||
fetchAllPlugins = () => { | |||
this.setState({ loadingPlugins: true }); | |||
Promise.all([getInstalledPluginsWithUpdates(), getAvailablePlugins()]).then( | |||
([installed, available]) => { | |||
if (this.mounted) { | |||
this.setState({ | |||
loadingPlugins: false, | |||
plugins: sortBy(uniqBy([...installed, ...available.plugins], 'key'), 'name') | |||
}); | |||
} | |||
}, | |||
this.stopLoadingPlugins | |||
); | |||
}; | |||
fetchUpdatesOnly = () => { | |||
this.setState({ loadingPlugins: true }); | |||
getPluginUpdates().then(plugins => { | |||
fetchFunction().then((plugins: Plugin[]) => { | |||
if (this.mounted) { | |||
this.setState({ loadingPlugins: false, plugins }); | |||
this.setState({ | |||
loadingPlugins: false, | |||
plugins: sortBy(plugins, 'name') | |||
}); | |||
} | |||
}, this.stopLoadingPlugins); | |||
}; | |||
fetchAllPlugins = (): Promise<Plugin[] | void> => { | |||
return Promise.all([getInstalledPluginsWithUpdates(), getAvailablePlugins()]).then( | |||
([installed, available]) => uniqBy([...installed, ...available.plugins], 'key'), | |||
this.stopLoadingPlugins | |||
); | |||
}; | |||
fetchPendingPlugins = () => | |||
getPendingPlugins().then( | |||
pending => { | |||
@@ -163,16 +159,16 @@ export default class App extends React.PureComponent<Props, State> { | |||
<Helmet title={translate('marketplace.page')} /> | |||
<div className="page-notifs"> | |||
{standaloneMode && ( | |||
<PendingActions refreshPending={this.fetchPendingPlugins} pending={pending} /> | |||
<PendingActions pending={pending} refreshPending={this.fetchPendingPlugins} /> | |||
)} | |||
</div> | |||
<Header /> | |||
<EditionBoxes | |||
canInstall={standaloneMode && !this.props.editionsReadOnly} | |||
canUninstall={standaloneMode} | |||
editionStatus={editionStatus} | |||
editions={editions} | |||
loading={this.props.loadingEditions} | |||
editionStatus={editionStatus} | |||
updateCenterActive={this.props.updateCenterActive} | |||
updateEditionStatus={this.props.setEditionStatus} | |||
/> | |||
@@ -184,8 +180,8 @@ export default class App extends React.PureComponent<Props, State> { | |||
{loadingPlugins && <i className="spinner" />} | |||
{!loadingPlugins && ( | |||
<PluginsList | |||
plugins={filteredPlugins} | |||
pending={pending} | |||
plugins={filteredPlugins} | |||
readOnly={!standaloneMode} | |||
refreshPending={this.fetchPendingPlugins} | |||
updateQuery={this.updateQuery} |
@@ -56,9 +56,9 @@ export default class PluginsList extends React.PureComponent<Props> { | |||
return ( | |||
<PluginInstalled | |||
plugin={plugin} | |||
status={status} | |||
readOnly={this.props.readOnly} | |||
refreshPending={this.props.refreshPending} | |||
status={status} | |||
updateQuery={this.props.updateQuery} | |||
/> | |||
); | |||
@@ -67,9 +67,9 @@ export default class PluginsList extends React.PureComponent<Props> { | |||
return ( | |||
<PluginAvailable | |||
plugin={plugin} | |||
status={status} | |||
readOnly={this.props.readOnly} | |||
refreshPending={this.props.refreshPending} | |||
status={status} | |||
updateQuery={this.props.updateQuery} | |||
/> | |||
); | |||
@@ -82,7 +82,7 @@ export default class PluginsList extends React.PureComponent<Props> { | |||
<div className="boxed-group boxed-group-inner" id="marketplace-plugins"> | |||
<ul> | |||
{this.props.plugins.map(plugin => ( | |||
<li key={plugin.key} className="panel panel-vertical"> | |||
<li className="panel panel-vertical" key={plugin.key}> | |||
<table className="marketplace-plugin-table"> | |||
<tbody>{this.renderPlugin(plugin)}</tbody> | |||
</table> |
@@ -40,6 +40,7 @@ export default class Search extends React.PureComponent<Props> { | |||
const { query, updateCenterActive } = this.props; | |||
const radioOptions = [ | |||
{ label: translate('marketplace.all'), value: 'all' }, | |||
{ label: translate('marketplace.installed'), value: 'installed' }, | |||
{ | |||
disabled: !updateCenterActive, | |||
label: translate('marketplace.updates_only'), | |||
@@ -48,8 +49,8 @@ export default class Search extends React.PureComponent<Props> { | |||
} | |||
]; | |||
return ( | |||
<div id="marketplace-search" className="big-spacer-bottom"> | |||
<div className="display-inline-block text-top nowrap abs-width-150 spacer-right"> | |||
<div className="big-spacer-bottom" id="marketplace-search"> | |||
<div className="display-inline-block text-top nowrap abs-width-240 spacer-right"> | |||
<RadioToggle | |||
name="marketplace-filter" | |||
onCheck={this.handleFilterChange} |
@@ -96,10 +96,10 @@ export default class PluginActions extends React.PureComponent<Props, State> { | |||
<div className="spacer-top"> | |||
{plugin.updates.map((update, idx) => ( | |||
<PluginUpdateButton | |||
disabled={this.state.loading} | |||
key={idx} | |||
onClick={this.handleUpdate} | |||
update={update} | |||
disabled={this.state.loading} | |||
/> | |||
))} | |||
</div> | |||
@@ -138,22 +138,23 @@ export default class PluginActions extends React.PureComponent<Props, State> { | |||
</a> | |||
</p> | |||
)} | |||
{loading && <i className="spinner spacer-right" />} | |||
{loading && <i className="spinner spacer-right little-spacer-top little-spacer-bottom" />} | |||
{isPluginInstalled(plugin) && ( | |||
<div className="display-inlin-block"> | |||
{plugin.updates && | |||
plugin.updates.map((update, idx) => ( | |||
<PluginUpdateButton | |||
disabled={loading} | |||
key={idx} | |||
onClick={this.handleUpdate} | |||
update={update} | |||
disabled={loading} | |||
/> | |||
))} | |||
<button | |||
className="js-uninstall button-red little-spacer-left" | |||
disabled={loading} | |||
onClick={this.handleUninstall}> | |||
onClick={this.handleUninstall} | |||
type="button"> | |||
{translate('marketplace.uninstall')} | |||
</button> | |||
</div> | |||
@@ -162,7 +163,8 @@ export default class PluginActions extends React.PureComponent<Props, State> { | |||
<button | |||
className="js-install" | |||
disabled={loading || (plugin.termsAndConditionsUrl != null && !this.state.acceptTerms)} | |||
onClick={this.handleInstall}> | |||
onClick={this.handleInstall} | |||
type="button"> | |||
{translate('marketplace.install')} | |||
</button> | |||
)} |
@@ -38,8 +38,9 @@ export default class PluginUpdateButton extends React.PureComponent<Props> { | |||
return ( | |||
<button | |||
className="js-update little-spacer-bottom" | |||
disabled={disabled} | |||
onClick={this.handleClick} | |||
disabled={disabled}> | |||
type="button"> | |||
{translateWithParameters('marketplace.update_to_x', update.release.version)} | |||
</button> | |||
); |
@@ -2115,6 +2115,7 @@ marketplace.update_x_plugins=update {nb} plugins | |||
marketplace.uninstall_x_plugins=uninstall {nb} plugins | |||
marketplace.not_activated=Update Center is not activated. | |||
marketplace.all=All | |||
marketplace.installed=Installed | |||
marketplace.updates_only=Updates Only | |||
marketplace.restart=Restart | |||
marketplace.revert=Revert |