feat(xo-web): basic plugins filtering (#3871)
This commit is contained in:
parent
df809baaaf
commit
0fd22b9fd8
@ -5,6 +5,7 @@
|
|||||||
### Enhancements
|
### Enhancements
|
||||||
|
|
||||||
- [VM migration] Display hosts' free memory [#3264](https://github.com/vatesfr/xen-orchestra/issues/3264) (PR [#3832](https://github.com/vatesfr/xen-orchestra/pull/3832))
|
- [VM migration] Display hosts' free memory [#3264](https://github.com/vatesfr/xen-orchestra/issues/3264) (PR [#3832](https://github.com/vatesfr/xen-orchestra/pull/3832))
|
||||||
|
- [Plugins] New field to filter displayed plugins (PR [#3832](https://github.com/vatesfr/xen-orchestra/pull/3871))
|
||||||
|
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
|
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
|
import * as ComplexMatcher from 'complex-matcher'
|
||||||
import _ from 'intl'
|
import _ from 'intl'
|
||||||
import ActionButton from 'action-button'
|
import ActionButton from 'action-button'
|
||||||
import ActionToggle from 'action-toggle'
|
import ActionToggle from 'action-toggle'
|
||||||
import Button from 'button'
|
import Button from 'button'
|
||||||
import Component from 'base-component'
|
import Component from 'base-component'
|
||||||
|
import decorate from 'apply-decorators'
|
||||||
import GenericInput from 'json-schema-input'
|
import GenericInput from 'json-schema-input'
|
||||||
import Icon from 'icon'
|
import Icon from 'icon'
|
||||||
import isEmpty from 'lodash/isEmpty'
|
import isEmpty from 'lodash/isEmpty'
|
||||||
import map from 'lodash/map'
|
import map from 'lodash/map'
|
||||||
|
import orderBy from 'lodash/orderBy'
|
||||||
import pFinally from 'promise-toolbox/finally'
|
import pFinally from 'promise-toolbox/finally'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import size from 'lodash/size'
|
import size from 'lodash/size'
|
||||||
@ -14,6 +17,7 @@ import { addSubscriptions } from 'utils'
|
|||||||
import { alert } from 'modal'
|
import { alert } from 'modal'
|
||||||
import { createSelector } from 'reselect'
|
import { createSelector } from 'reselect'
|
||||||
import { generateUiSchema } from 'xo-json-schema-input'
|
import { generateUiSchema } from 'xo-json-schema-input'
|
||||||
|
import { injectState, provideState } from 'reaclette'
|
||||||
import { Row, Col } from 'grid'
|
import { Row, Col } from 'grid'
|
||||||
import {
|
import {
|
||||||
configurePlugin,
|
configurePlugin,
|
||||||
@ -251,29 +255,75 @@ class Plugin extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@addSubscriptions({
|
export default decorate([
|
||||||
plugins: subscribePlugins,
|
addSubscriptions({
|
||||||
})
|
plugins: subscribePlugins,
|
||||||
export default class Plugins extends Component {
|
}),
|
||||||
render() {
|
provideState({
|
||||||
if (isEmpty(this.props.plugins)) {
|
effects: {
|
||||||
return (
|
onSearchChange(
|
||||||
<p>
|
_,
|
||||||
<em>{_('noPlugins')}</em>
|
{
|
||||||
</p>
|
target: { value },
|
||||||
)
|
}
|
||||||
}
|
) {
|
||||||
|
const { location, router } = this.props
|
||||||
|
router.replace({
|
||||||
|
...location,
|
||||||
|
query: {
|
||||||
|
...location.query,
|
||||||
|
s: value,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
search: (
|
||||||
|
_,
|
||||||
|
{
|
||||||
|
location: {
|
||||||
|
query: { s = '' },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
) => s,
|
||||||
|
filteredPlugins: ({ predicate }, { plugins }) =>
|
||||||
|
predicate === undefined ? plugins : plugins.filter(predicate),
|
||||||
|
predicate: ({ search }) => {
|
||||||
|
if (search.trim() === '') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
try {
|
||||||
|
return ComplexMatcher.parse(search).createPredicate()
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sortedPlugins: ({ filteredPlugins }) => orderBy(filteredPlugins, 'name'),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
injectState,
|
||||||
|
({ effects, state, plugins }) =>
|
||||||
|
isEmpty(plugins) ? (
|
||||||
|
<p>
|
||||||
|
<em>{_('noPlugins')}</em>
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
<div>
|
<div>
|
||||||
|
<p>
|
||||||
|
<input
|
||||||
|
className='form-control'
|
||||||
|
onChange={effects.onSearchChange}
|
||||||
|
value={state.search}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
<ul style={{ paddingLeft: 0 }}>
|
<ul style={{ paddingLeft: 0 }}>
|
||||||
{map(this.props.plugins, (plugin, key) => (
|
{state.sortedPlugins.map(plugin => (
|
||||||
<li key={key} className='list-group-item clearfix'>
|
<li key={plugin.id} className='list-group-item clearfix'>
|
||||||
<Plugin {...plugin} />
|
<Plugin {...plugin} />
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
),
|
||||||
}
|
])
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user