diff --git a/packages/core/app-extensions/src/notification/modules/modal/ModalDisplay/StyledComponents.js b/packages/core/app-extensions/src/notification/modules/modal/ModalDisplay/StyledComponents.js
index e7c1c50fe4..2b04df5833 100644
--- a/packages/core/app-extensions/src/notification/modules/modal/ModalDisplay/StyledComponents.js
+++ b/packages/core/app-extensions/src/notification/modules/modal/ModalDisplay/StyledComponents.js
@@ -1,11 +1,11 @@
import styled, {createGlobalStyle} from 'styled-components'
-import {Button, scale, StyledScrollbar, StyledTether, theme} from 'tocco-ui'
+import {Button, scale, StyledScrollbar, StyledTether, themeSelector} from 'tocco-ui'
export const basePadding = scale.space(0.5)
export const StyledModalContent = styled.div`
position: relative;
- background-color: ${theme.color('paper')};
+ background-color: ${themeSelector.color('paper')};
padding: ${basePadding};
display: grid;
grid-template-rows: [header] auto [body] 1fr;
@@ -77,7 +77,6 @@ export const StyledTitleWrapper = styled.div`
export const StyledModalBody = styled.div`
grid-row-start: body;
overflow: hidden auto;
- padding-right: ${scale.space(0)};
${StyledScrollbar}
`
diff --git a/packages/core/entity-list/src/components/Table/NavigationCellHeader.js b/packages/core/entity-list/src/components/Table/NavigationCellHeader.js
index 5a66a0288f..6295fb5f30 100644
--- a/packages/core/entity-list/src/components/Table/NavigationCellHeader.js
+++ b/packages/core/entity-list/src/components/Table/NavigationCellHeader.js
@@ -1,25 +1,33 @@
import PropTypes from 'prop-types'
import {FormattedMessage} from 'react-intl'
-import {connect} from 'react-redux'
import {BallMenu, MenuItem} from 'tocco-ui'
-import {displayColumnModal, resetSorting, resetPreferences, resetColumns} from '../../modules/preferences/actions'
-
-const NavigationCellHeader = props =>
- !props.disablePreferencesMenu ? (
+const NavigationCellHeader = ({
+ disablePreferencesMenu,
+ displayColumnModal,
+ resetColumns,
+ sortable,
+ resetSorting,
+ resetPreferences,
+ displayTableRowsModal
+}) =>
+ !disablePreferencesMenu ? (
-
@@ -31,19 +39,8 @@ NavigationCellHeader.propTypes = {
resetPreferences: PropTypes.func.isRequired,
resetColumns: PropTypes.func.isRequired,
sortable: PropTypes.bool,
- disablePreferencesMenu: PropTypes.bool
+ disablePreferencesMenu: PropTypes.bool,
+ displayTableRowsModal: PropTypes.func.isRequired
}
-const mapActionCreators = {
- displayColumnModal,
- resetSorting,
- resetPreferences,
- resetColumns
-}
-
-const mapStateToProps = (state, props) => ({
- sortable: state.input.sortable,
- disablePreferencesMenu: state.list.disablePreferencesMenu
-})
-
-export default connect(mapStateToProps, mapActionCreators)(NavigationCellHeader)
+export default NavigationCellHeader
diff --git a/packages/core/entity-list/src/components/Table/NavigationCellHeaderContainer.js b/packages/core/entity-list/src/components/Table/NavigationCellHeaderContainer.js
new file mode 100644
index 0000000000..575cef5884
--- /dev/null
+++ b/packages/core/entity-list/src/components/Table/NavigationCellHeaderContainer.js
@@ -0,0 +1,27 @@
+import {connect} from 'react-redux'
+
+import {
+ displayColumnModal,
+ resetSorting,
+ resetPreferences,
+ resetColumns,
+ displayTableRowsModal
+} from '../../modules/preferences/actions'
+import NavigationCellHeader from './NavigationCellHeader'
+
+const mapActionCreators = {
+ displayColumnModal,
+ resetSorting,
+ resetPreferences,
+ resetColumns,
+ displayTableRowsModal
+}
+
+const mapStateToProps = (state, props) => {
+ return {
+ sortable: state.list.sortable,
+ disablePreferencesMenu: state.list.disablePreferencesMenu
+ }
+}
+
+export default connect(mapStateToProps, mapActionCreators)(NavigationCellHeader)
diff --git a/packages/core/entity-list/src/components/Table/SelectRowNums.js b/packages/core/entity-list/src/components/Table/SelectRowNums.js
new file mode 100644
index 0000000000..68ea5b8994
--- /dev/null
+++ b/packages/core/entity-list/src/components/Table/SelectRowNums.js
@@ -0,0 +1,47 @@
+import PropTypes from 'prop-types'
+import {useState} from 'react'
+import {injectIntl, FormattedMessage} from 'react-intl'
+import {EditableValue, Button} from 'tocco-ui'
+
+import {StyledButtonWrapper, StyledEditableValueWrapper} from './StyledComponents'
+
+const SelectNumRows = injectIntl(({intl, onOk, numOfRows}) => {
+ const msg = id => intl.formatMessage({id})
+ const options = [
+ {key: 25, display: '25'},
+ {key: 50, display: '50'},
+ {key: 100, display: '100'}
+ ]
+ const matchingValue = options.find(option => option.key === numOfRows)
+ const [value, setValue] = useState(matchingValue)
+
+ return (
+ <>
+
+
+
+
+
+
+ >
+ )
+})
+
+SelectNumRows.propTypes = {
+ intl: PropTypes.object.isRequired,
+ onOk: PropTypes.func.isRequired,
+ numOfRows: PropTypes.number
+}
+
+export default SelectNumRows
diff --git a/packages/core/entity-list/src/components/Table/StyledComponents.js b/packages/core/entity-list/src/components/Table/StyledComponents.js
index bd5e9d8247..4c5e4e7538 100644
--- a/packages/core/entity-list/src/components/Table/StyledComponents.js
+++ b/packages/core/entity-list/src/components/Table/StyledComponents.js
@@ -1,5 +1,5 @@
import styled from 'styled-components'
-import {themeSelector, declareFont} from 'tocco-ui'
+import {themeSelector, declareFont, scale, StyledButton, colorizeBorder} from 'tocco-ui'
export const StyledMarkingWrapper = styled.span`
${declareFont()}
@@ -13,3 +13,22 @@ export const StyledMarkingWrapper = styled.span`
}
${({marked, theme}) => marked && `color: ${theme.colors.secondary};`}
`
+
+export const StyledButtonWrapper = styled.div`
+ position: sticky;
+ bottom: 0;
+ padding-top: ${scale.space(0)};
+ background-color: ${themeSelector.color('paper')};
+ display: flex;
+ justify-content: flex-end;
+
+ ${StyledButton} {
+ margin-right: 0;
+ }
+`
+
+export const StyledEditableValueWrapper = styled.div`
+ border: 1px solid ${colorizeBorder.shade1};
+ padding-right: ${scale.space(-1)};
+ padding-left: ${scale.space(-1)};
+`
diff --git a/packages/core/entity-list/src/components/Table/navigationCell.js b/packages/core/entity-list/src/components/Table/navigationCell.js
index d16ff02f66..0f383d912a 100644
--- a/packages/core/entity-list/src/components/Table/navigationCell.js
+++ b/packages/core/entity-list/src/components/Table/navigationCell.js
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types'
import {Icon} from 'tocco-ui'
-import NavigationCellHeader from './NavigationCellHeader'
+import NavigationCellHeader from './NavigationCellHeaderContainer'
const CellRenderer = ({showNavigation, rowData, navigationStrategy, parent}) =>
showNavigation && navigationStrategy.DetailLinkRelative ? (
diff --git a/packages/core/entity-list/src/containers/TableContainer.js b/packages/core/entity-list/src/containers/TableContainer.js
index 397f89d17b..0bbf659938 100644
--- a/packages/core/entity-list/src/containers/TableContainer.js
+++ b/packages/core/entity-list/src/containers/TableContainer.js
@@ -6,6 +6,7 @@ import {changePage, refresh, initialize, onRowClick, setSortingInteractive} from
import {changePosition, resetSorting, changeWidth} from '../modules/preferences/actions'
import {onSelectChange, setSelection} from '../modules/selection/actions'
import {getFormDefinition, getClickable, getDisablePreferencesMenu, getSelectable} from '../util/api/forms'
+import {getActualLimit} from '../util/preferences'
import {getTableSelectionStyle} from '../util/selection'
const mapActionCreators = {
@@ -25,7 +26,7 @@ const mapStateToProps = (state, props) => ({
currentPage: state.list.currentPage,
entities: state.list.entities,
entityCount: state.list.entityCount,
- limit: state.input.limit,
+ limit: getActualLimit(state),
inProgress: state.list.inProgress,
tableSelectionStyle: getTableSelectionStyle(state.input.selectionStyle, getSelectable(getFormDefinition(state))),
clickable: getClickable(getFormDefinition(state)),
diff --git a/packages/core/entity-list/src/modules/list/sagas.js b/packages/core/entity-list/src/modules/list/sagas.js
index 5124564f55..e91cb174b9 100644
--- a/packages/core/entity-list/src/modules/list/sagas.js
+++ b/packages/core/entity-list/src/modules/list/sagas.js
@@ -16,6 +16,7 @@ import {
getSorting,
splitFormId
} from '../../util/api/forms'
+import {getActualLimit} from '../../util/preferences'
import * as preferencesActions from '../preferences/actions'
import * as searchFormActions from '../searchForm/actions'
import {getSearchFormValues} from '../searchForm/sagas'
@@ -287,7 +288,7 @@ export function* setLazyDataMarked(entityName, markings) {
export function* fetchEntitiesAndAddToStore(page) {
const state = yield select(stateSelector)
- const {entityName, scope, limit} = state.input
+ const {entityName, scope} = state.input
const {columns: columnPreferences} = state.preferences
const {entityStore, sorting} = state.list
if (!entityStore[page]) {
@@ -299,7 +300,7 @@ export function* fetchEntitiesAndAddToStore(page) {
...basicQuery,
page,
sorting,
- limit,
+ limit: getActualLimit(state),
paths
}
@@ -339,7 +340,8 @@ export function* delayedPreloadNextPage(page) {
}
export function* preloadNextPage(currentPage) {
- const {limit} = yield select(inputSelector)
+ const state = yield select(stateSelector)
+ const actualLimit = getActualLimit(state)
const list = yield select(listSelector)
const {entityStore} = list
let {entityCount} = list
@@ -350,7 +352,7 @@ export function* preloadNextPage(currentPage) {
entityCount = setCountAction.payload.entityCount
}
- if (currentPage * limit < entityCount && !entityStore[nextPage]) {
+ if (currentPage * actualLimit < entityCount && !entityStore[nextPage]) {
yield call(fetchEntitiesAndAddToStore, nextPage)
}
}
diff --git a/packages/core/entity-list/src/modules/preferences/actions.js b/packages/core/entity-list/src/modules/preferences/actions.js
index d788a379c7..e784bf4086 100644
--- a/packages/core/entity-list/src/modules/preferences/actions.js
+++ b/packages/core/entity-list/src/modules/preferences/actions.js
@@ -9,6 +9,8 @@ export const RESET_COLUMNS = 'preferences/RESET_COLUMNS'
export const RESET_PREFERENCES = 'preferences/RESET_PREFERENCES'
export const DISPLAY_COLUMN_MODAL = 'preferences/DISPLAY_COLUMN_MODAL'
export const SET_PREFERENCES_LOADED = 'preferences/SET_PREFERENCES_LOADED'
+export const SET_NUMBER_OF_TABLE_ROWS = 'preferences/SET_NUMBER_OF_TABLE_ROWS'
+export const DISPLAY_TABLE_ROWS_MODAL = 'preferences/DISPLAY_TABLE_ROWS_MODAL'
export const loadPreferences = () => ({
type: LOAD_PREFERENCES
@@ -78,3 +80,12 @@ export const resetColumns = () => ({
type: RESET_COLUMNS,
payload: {}
})
+
+export const displayTableRowsModal = () => ({
+ type: DISPLAY_TABLE_ROWS_MODAL
+})
+
+export const setNumberOfTableRows = numOfRows => ({
+ type: SET_NUMBER_OF_TABLE_ROWS,
+ payload: {numOfRows}
+})
diff --git a/packages/core/entity-list/src/modules/preferences/reducer.js b/packages/core/entity-list/src/modules/preferences/reducer.js
index f06f97de5b..5ed284890c 100644
--- a/packages/core/entity-list/src/modules/preferences/reducer.js
+++ b/packages/core/entity-list/src/modules/preferences/reducer.js
@@ -25,7 +25,13 @@ const resetPreferences = state => ({
...state,
positions: {},
sorting: [],
- columns: {}
+ columns: {},
+ numOfRows: undefined
+})
+
+const setNumberOfTableRows = (state, {payload: {numOfRows}}) => ({
+ ...state,
+ numOfRows
})
const ACTION_HANDLERS = {
@@ -36,7 +42,8 @@ const ACTION_HANDLERS = {
[actions.SET_PREFERENCES_LOADED]: reducerUtil.singleTransferReducer('preferencesLoaded'),
[actions.RESET_SORTING]: resetSorting,
[actions.RESET_COLUMNS]: resetColumns,
- [actions.RESET_PREFERENCES]: resetPreferences
+ [actions.RESET_PREFERENCES]: resetPreferences,
+ [actions.SET_NUMBER_OF_TABLE_ROWS]: setNumberOfTableRows
}
const initialState = {
@@ -44,6 +51,7 @@ const initialState = {
sorting: [],
columns: {},
widths: {},
+ numOfRows: undefined,
preferencesLoaded: false
}
diff --git a/packages/core/entity-list/src/modules/preferences/sagas.js b/packages/core/entity-list/src/modules/preferences/sagas.js
index 92806afdcf..d610348935 100644
--- a/packages/core/entity-list/src/modules/preferences/sagas.js
+++ b/packages/core/entity-list/src/modules/preferences/sagas.js
@@ -3,11 +3,12 @@ import {all, call, put, select, take, takeLatest} from 'redux-saga/effects'
import {rest, notification} from 'tocco-app-extensions'
import ColumnModal from '../../components/ColumnModal'
+import SelectNumRows from '../../components/Table/SelectRowNums'
import {getTableColumns} from '../../util/api/forms'
import * as util from '../../util/preferences'
import * as listActions from '../list/actions'
import * as listSagas from '../list/sagas'
-import {setPositions, setSorting, setColumns, setPreferencesLoaded} from './actions'
+import {setPositions, setSorting, setColumns, setPreferencesLoaded, setNumberOfTableRows} from './actions'
import * as actions from './actions'
export const inputSelector = state => state.input
@@ -22,7 +23,8 @@ export default function* sagas() {
takeLatest(actions.RESET_SORTING, resetSorting),
takeLatest(actions.RESET_COLUMNS, resetColumns),
takeLatest(actions.RESET_PREFERENCES, resetPreferences),
- takeLatest(actions.DISPLAY_COLUMN_MODAL, displayColumnModal)
+ takeLatest(actions.DISPLAY_COLUMN_MODAL, displayColumnModal),
+ takeLatest(actions.DISPLAY_TABLE_ROWS_MODAL, displayTableRowsModal)
])
}
@@ -33,6 +35,7 @@ export function* loadPreferences() {
yield put(setPositions(util.getPositions(preferences)))
yield put(setSorting(util.getSorting(preferences)))
yield put(setColumns(util.getColumns(preferences)))
+ yield put(setNumberOfTableRows(Number(preferences[`${formName}.numOfRows`])))
yield put(setPreferencesLoaded(true))
}
@@ -76,6 +79,16 @@ export function* saveSorting() {
}
}
+export function* saveNumberOfTableRows(answerChannel) {
+ const {numOfRows} = yield take(answerChannel)
+ const inputState = yield select(inputSelector)
+ const formName = `${inputState.formName}_${inputState.scope}`
+
+ yield put(setNumberOfTableRows(numOfRows))
+ yield call(listSagas.reloadData)
+ yield call(rest.savePreferences, {[`${formName}.numOfRows`]: numOfRows})
+}
+
export function* resetSorting() {
const inputState = yield select(inputSelector)
yield all([
@@ -120,6 +133,31 @@ export function* displayColumnModal() {
yield saveColumnPreferences(answerChannel, preferencesColumns, formDefinition)
}
+export function* displayTableRowsModal() {
+ const {formDefinition} = yield select(listSagas.listSelector)
+ const answerChannel = yield call(channel)
+ const {numOfRows: preferencesNumOfRows} = yield select(preferencesSelector)
+
+ yield put(
+ notification.modal(
+ `${formDefinition.id}-numOfRows-setting`,
+ 'client.entity-list.preferences.numOfRows',
+ null,
+ ({close}) => {
+ const onOk = numOfRows => {
+ close()
+ answerChannel.put({numOfRows})
+ }
+
+ return
+ },
+ true
+ )
+ )
+
+ yield call(saveNumberOfTableRows, answerChannel)
+}
+
function* saveColumnPreferences(answerChannel, preferencesColumns, formDefinition) {
const columns = (yield take(answerChannel)).reduce(
(accumulator, item) => ({
diff --git a/packages/core/entity-list/src/util/preferences.js b/packages/core/entity-list/src/util/preferences.js
index 6e46ee08af..50826d2995 100644
--- a/packages/core/entity-list/src/util/preferences.js
+++ b/packages/core/entity-list/src/util/preferences.js
@@ -96,3 +96,5 @@ export const getColumnPreferencesToSave = (formName, columns) =>
}),
{}
)
+
+export const getActualLimit = state => state.preferences.numOfRows || state.input.limit