feat(xo-web/SortedTable): allow to change the number of items per page (#5355)
See xoa-support#3020
This commit is contained in:
parent
7961ff0785
commit
fbf906d97c
@ -16,6 +16,7 @@
|
||||
- [Web Hooks] `backupNg.runJob` is now triggered by scheduled runs [#5205](https://github.com/vatesfr/xen-orchestra/issues/5205) (PR [#5360](https://github.com/vatesfr/xen-orchestra/pull/5360))
|
||||
- [Licensing] Add trial end information banner (PR [#5374](https://github.com/vatesfr/xen-orchestra/pull/5374))
|
||||
- Assign custom fields on pools, hosts, SRs, and VMs in advanced tab [#4730](https://github.com/vatesfr/xen-orchestra/issues/4730) (PR [#5387](https://github.com/vatesfr/xen-orchestra/pull/5387))
|
||||
- Ability to change the number of items displayed per table or page (PR [#5355](https://github.com/vatesfr/xen-orchestra/pull/5355))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
import * as CM from 'complex-matcher'
|
||||
import _ from 'intl'
|
||||
import classNames from 'classnames'
|
||||
import cookies from 'js-cookie'
|
||||
import defined, { ifDef } from '@xen-orchestra/defined'
|
||||
import DropdownMenu from 'react-bootstrap-4/lib/DropdownMenu' // https://phabricator.babeljs.io/T6662 so Dropdown.Menu won't work like https://react-bootstrap.github.io/components.html#btn-dropdowns-custom
|
||||
import DropdownToggle from 'react-bootstrap-4/lib/DropdownToggle' // https://phabricator.babeljs.io/T6662 so Dropdown.Toggle won't work https://react-bootstrap.github.io/components.html#btn-dropdowns-custom
|
||||
import PropTypes from 'prop-types'
|
||||
import React from 'react'
|
||||
import Shortcuts from 'shortcuts'
|
||||
import { Dropdown, MenuItem } from 'react-bootstrap-4/lib'
|
||||
import { Dropdown, DropdownButton, MenuItem } from 'react-bootstrap-4/lib'
|
||||
import { Portal } from 'react-overlays'
|
||||
import { Set } from 'immutable'
|
||||
import { injectState, provideState } from 'reaclette'
|
||||
@ -38,9 +39,12 @@ import {
|
||||
createSelector,
|
||||
createSort,
|
||||
} from '../selectors'
|
||||
import { ITEMS_PER_PAGE_OPTIONS } from '../xo'
|
||||
|
||||
import styles from './index.css'
|
||||
|
||||
const DEFAULT_ITEMS_PER_PAGE = 10
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class ColumnHead extends Component {
|
||||
@ -268,7 +272,6 @@ class SortedTable extends Component {
|
||||
),
|
||||
groupedActions: actionsShape,
|
||||
individualActions: actionsShape,
|
||||
itemsPerPage: PropTypes.number,
|
||||
onSelect: PropTypes.func,
|
||||
paginationContainer: PropTypes.func,
|
||||
rowAction: PropTypes.func,
|
||||
@ -283,10 +286,6 @@ class SortedTable extends Component {
|
||||
userData: PropTypes.any,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
itemsPerPage: 10,
|
||||
}
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context)
|
||||
|
||||
@ -306,6 +305,7 @@ class SortedTable extends Component {
|
||||
|
||||
const state = (this.state = {
|
||||
all: false, // whether all items are selected (accross pages)
|
||||
itemsPerPage: +defined(cookies.get(`${props.location.pathname}-${props.stateUrlParam}`), DEFAULT_ITEMS_PER_PAGE),
|
||||
})
|
||||
|
||||
this._getSelectedColumn = () => this.props.columns[this._getSelectedColumnId()]
|
||||
@ -340,7 +340,7 @@ class SortedTable extends Component {
|
||||
this._getSortOrder
|
||||
)
|
||||
|
||||
this._getVisibleItems = createPager(this._getItems, this._getPage, () => this.props.itemsPerPage)
|
||||
this._getVisibleItems = createPager(this._getItems, this._getPage, () => this.state.itemsPerPage)
|
||||
|
||||
state.selectedItemsIds = new Set()
|
||||
|
||||
@ -468,7 +468,7 @@ class SortedTable extends Component {
|
||||
_setPage = this._setPage.bind(this)
|
||||
|
||||
goTo(id) {
|
||||
this._setPage(Math.floor(this._getItems().findIndex(item => item.id === id) / this.props.itemsPerPage) + 1)
|
||||
this._setPage(Math.floor(this._getItems().findIndex(item => item.id === id) / this.state.itemsPerPage) + 1)
|
||||
}
|
||||
|
||||
_selectAllVisibleItems = event => {
|
||||
@ -584,7 +584,7 @@ class SortedTable extends Component {
|
||||
|
||||
_getNPages = createSelector(
|
||||
() => this._getItems().length,
|
||||
() => this.props.itemsPerPage,
|
||||
() => this.state.itemsPerPage,
|
||||
(nItems, itemsPerPage) => ceil(nItems / itemsPerPage)
|
||||
)
|
||||
|
||||
@ -727,18 +727,16 @@ class SortedTable extends Component {
|
||||
)
|
||||
}
|
||||
|
||||
_setNItemsPerPage = itemsPerPage => {
|
||||
const { location, stateUrlParam } = this.props
|
||||
this.setState({ itemsPerPage })
|
||||
cookies.set(`${location.pathname}-${stateUrlParam}`, itemsPerPage)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props, state } = this
|
||||
const {
|
||||
actions,
|
||||
filterContainer,
|
||||
individualActions,
|
||||
itemsPerPage,
|
||||
onSelect,
|
||||
paginationContainer,
|
||||
shortcutsTarget,
|
||||
} = props
|
||||
const { all } = state
|
||||
const { actions, filterContainer, individualActions, onSelect, paginationContainer, shortcutsTarget } = props
|
||||
const { all, itemsPerPage } = state
|
||||
const groupedActions = this._getGroupedActions()
|
||||
|
||||
const nAllItems = this._getTotalNumberOfItems()
|
||||
@ -860,7 +858,7 @@ class SortedTable extends Component {
|
||||
</table>
|
||||
<Container>
|
||||
<SingleLineRow>
|
||||
<Col mediumSize={8}>
|
||||
<Col mediumSize={7}>
|
||||
{displayPagination &&
|
||||
(paginationContainer !== undefined ? (
|
||||
// Rebuild container function to refresh Portal component.
|
||||
@ -872,6 +870,15 @@ class SortedTable extends Component {
|
||||
<Col mediumSize={4}>
|
||||
{filterContainer ? <Portal container={() => filterContainer()}>{filterInstance}</Portal> : filterInstance}
|
||||
</Col>
|
||||
<Col mediumSize={1} className='pull-right'>
|
||||
<DropdownButton bsStyle='info' title={itemsPerPage}>
|
||||
{ITEMS_PER_PAGE_OPTIONS.map(nItems => (
|
||||
<MenuItem key={nItems} onClick={() => this._setNItemsPerPage(nItems)}>
|
||||
{nItems}
|
||||
</MenuItem>
|
||||
))}
|
||||
</DropdownButton>
|
||||
</Col>
|
||||
</SingleLineRow>
|
||||
</Container>
|
||||
</div>
|
||||
|
@ -37,6 +37,10 @@ import parseNdJson from './_parseNdJson'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export const ITEMS_PER_PAGE_OPTIONS = [10, 20, 50, 100]
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export const XEN_DEFAULT_CPU_WEIGHT = 256
|
||||
export const XEN_DEFAULT_CPU_CAP = 0
|
||||
|
||||
|
@ -64,6 +64,7 @@ import {
|
||||
subscribeResourceSets,
|
||||
subscribeServers,
|
||||
suspendVms,
|
||||
ITEMS_PER_PAGE_OPTIONS,
|
||||
} from 'xo'
|
||||
import { Container, Row, Col } from 'grid'
|
||||
import { createPredicate } from 'value-matcher'
|
||||
@ -92,7 +93,6 @@ import TemplateItem from './template-item'
|
||||
import SrItem from './sr-item'
|
||||
|
||||
const DEFAULT_ITEMS_PER_PAGE = 20
|
||||
const ITEMS_PER_PAGE_OPTIONS = [20, 50, 100]
|
||||
|
||||
const OPTIONS = {
|
||||
host: {
|
||||
|
Loading…
Reference in New Issue
Block a user