From 1c3b8004b4f0690378b189cf6032015904629477 Mon Sep 17 00:00:00 2001 From: Stefano Ricci Date: Wed, 29 Nov 2023 22:16:32 +0100 Subject: [PATCH 1/3] tables: store visible columns --- webapp/components/Table/Header/Header.js | 8 +++++- .../VisibleColumnsMenu/VisibleColumnsMenu.js | 8 +++--- webapp/components/Table/Table.js | 2 ++ webapp/components/Table/useTable.js | 21 +++++++++++---- webapp/store/ui/reducer.js | 2 ++ webapp/store/ui/tables/actions.js | 12 +++++++++ webapp/store/ui/tables/hooks.js | 6 +++++ webapp/store/ui/tables/index.js | 6 +++++ webapp/store/ui/tables/reducer.js | 20 ++++++++++++++ webapp/store/ui/tables/state.js | 27 +++++++++++++++++++ 10 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 webapp/store/ui/tables/actions.js create mode 100644 webapp/store/ui/tables/hooks.js create mode 100644 webapp/store/ui/tables/index.js create mode 100644 webapp/store/ui/tables/reducer.js create mode 100644 webapp/store/ui/tables/state.js diff --git a/webapp/components/Table/Header/Header.js b/webapp/components/Table/Header/Header.js index 5b167820b8..e4ae1c565e 100644 --- a/webapp/components/Table/Header/Header.js +++ b/webapp/components/Table/Header/Header.js @@ -11,13 +11,18 @@ const Header = (props) => { onVisibleColumnsChange, totalCount, visibleColumnsSelectionEnabled, + visibleColumnKeys, } = props return (
{React.createElement(headerLeftComponent, { ...props, ...headerProps })} {visibleColumnsSelectionEnabled && totalCount > 0 && ( - + )}
) @@ -34,6 +39,7 @@ Header.propTypes = { onVisibleColumnsChange: PropTypes.func.isRequired, totalCount: PropTypes.number.isRequired, visibleColumnsSelectionEnabled: PropTypes.bool, + visibleColumnKeys: PropTypes.array.isRequired, } Header.defaultProps = { diff --git a/webapp/components/Table/Header/VisibleColumnsMenu/VisibleColumnsMenu.js b/webapp/components/Table/Header/VisibleColumnsMenu/VisibleColumnsMenu.js index e613571b40..9fa3d818a3 100644 --- a/webapp/components/Table/Header/VisibleColumnsMenu/VisibleColumnsMenu.js +++ b/webapp/components/Table/Header/VisibleColumnsMenu/VisibleColumnsMenu.js @@ -1,6 +1,6 @@ import './VisibleColumnsMenu.scss' -import React, { useCallback, useState } from 'react' +import React, { useCallback } from 'react' import PropTypes from 'prop-types' import { Objects } from '@openforis/arena-core' @@ -11,16 +11,13 @@ import { ButtonMenu } from '@webapp/components' import { Checkbox } from '@webapp/components/form' export const VisibleColumnsMenu = (props) => { - const { columns, onSelectionChange } = props + const { columns, onSelectionChange, selectedColumnKeys } = props const availableColumns = columns.filter((column) => !Objects.isEmpty(column.header) && column.header !== '#') - const [selectedColumnKeys, setSelectedColumnKeys] = useState(columns.map((col) => col.key)) - const onColummSelectionChange = useCallback( (key) => () => { const selectedColumnKeysNext = ArrayUtils.addOrRemoveItem({ item: key })(selectedColumnKeys) - setSelectedColumnKeys(selectedColumnKeysNext) onSelectionChange(selectedColumnKeysNext) }, [onSelectionChange, selectedColumnKeys] @@ -55,4 +52,5 @@ export const VisibleColumnsMenu = (props) => { VisibleColumnsMenu.propTypes = { columns: PropTypes.array.isRequired, onSelectionChange: PropTypes.func.isRequired, + selectedColumnKeys: PropTypes.array, } diff --git a/webapp/components/Table/Table.js b/webapp/components/Table/Table.js index 5a72685c01..cd0a096229 100644 --- a/webapp/components/Table/Table.js +++ b/webapp/components/Table/Table.js @@ -53,6 +53,7 @@ const Table = (props) => { onRowClick, onVisibleColumnsChange, selectedItems, + visibleColumnKeys, visibleColumns, } = useTable({ columns, @@ -84,6 +85,7 @@ const Table = (props) => { onVisibleColumnsChange={onVisibleColumnsChange} selectedItems={selectedItems} visibleColumnsSelectionEnabled={visibleColumnsSelectionEnabled} + visibleColumnKeys={visibleColumnKeys} /> { + const dispatch = useDispatch() + const [totalCount, setTotalCount] = useState(0) - const [visibleColumns, setVisibleColumns] = useState(columns) + + const visibleColumnKeys = useTableVisibleColumns(module) || columns.map((column) => column.key) + const visibleColumns = useMemo( + () => columns.filter((column) => visibleColumnKeys.includes(column.key)), + [columns, visibleColumnKeys] + ) const navigate = useNavigate() const surveyId = useSurveyId() @@ -118,9 +128,9 @@ export const useTable = ({ const onVisibleColumnsChange = useCallback( (visibleColumnKeys) => { - setVisibleColumns(columns.filter((column) => visibleColumnKeys.includes(column.key))) + dispatch(TablesActions.updateVisibleColumns({ module, visibleColumns: visibleColumnKeys })) }, - [columns] + [module] ) return { @@ -139,6 +149,7 @@ export const useTable = ({ onRowClick, onVisibleColumnsChange, selectedItems, + visibleColumnKeys, visibleColumns, } } diff --git a/webapp/store/ui/reducer.js b/webapp/store/ui/reducer.js index 20c137dff5..62fad5f2bb 100644 --- a/webapp/store/ui/reducer.js +++ b/webapp/store/ui/reducer.js @@ -6,6 +6,7 @@ import { LoaderReducer, LoaderState } from './loader' import { DialogConfirmReducer, DialogConfirmState } from './dialogConfirm' import { RecordReducer, RecordState } from './record' import { SurveyFormReducer, SurveyFormState } from './surveyForm' +import { TablesReducer, TablesState } from './tables' import { ChainReducer } from './chain' export default combineReducers({ @@ -15,5 +16,6 @@ export default combineReducers({ [DialogConfirmState.stateKey]: DialogConfirmReducer, [RecordState.stateKey]: RecordReducer, [SurveyFormState.stateKey]: SurveyFormReducer, + [TablesState.stateKey]: TablesReducer, chain: ChainReducer, }) diff --git a/webapp/store/ui/tables/actions.js b/webapp/store/ui/tables/actions.js new file mode 100644 index 0000000000..361af8d4ae --- /dev/null +++ b/webapp/store/ui/tables/actions.js @@ -0,0 +1,12 @@ +export const tableVisibleColumnsUpdate = 'tables/visibleColumnsUpdate' +export const tableMaxRowsUpdate = 'tables/maxRowsUpdate' + +export const updateVisibleColumns = + ({ module, visibleColumns }) => + (dispatch) => + dispatch({ type: tableVisibleColumnsUpdate, module, visibleColumns }) + +export const updateMaxRows = + ({ module, maxRows }) => + (dispatch) => + dispatch({ type: tableMaxRowsUpdate, module, maxRows }) diff --git a/webapp/store/ui/tables/hooks.js b/webapp/store/ui/tables/hooks.js new file mode 100644 index 0000000000..c364b7814f --- /dev/null +++ b/webapp/store/ui/tables/hooks.js @@ -0,0 +1,6 @@ +import { useSelector } from 'react-redux' +import * as TablesState from './state' + +export const useTableMaxRows = (module) => useSelector(TablesState.getMaxRows(module)) + +export const useTableVisibleColumns = (module) => useSelector(TablesState.getVisibleColumns(module)) diff --git a/webapp/store/ui/tables/index.js b/webapp/store/ui/tables/index.js new file mode 100644 index 0000000000..3722bb4435 --- /dev/null +++ b/webapp/store/ui/tables/index.js @@ -0,0 +1,6 @@ +import * as TablesActions from './actions' +import TablesReducer from './reducer' +import * as TablesState from './state' + +export { TablesActions, TablesReducer, TablesState } +export { useTableMaxRows, useTableVisibleColumns } from './hooks' diff --git a/webapp/store/ui/tables/reducer.js b/webapp/store/ui/tables/reducer.js new file mode 100644 index 0000000000..f8dd85780d --- /dev/null +++ b/webapp/store/ui/tables/reducer.js @@ -0,0 +1,20 @@ +import { exportReducer } from '@webapp/utils/reduxUtils' + +import { SystemActions } from '@webapp/store/system' + +import * as TablesActions from './actions' +import * as TablesState from './state' + +const actionHandlers = { + // Reset form + [SystemActions.SYSTEM_RESET]: () => ({}), + + // Tables + [TablesActions.tableVisibleColumnsUpdate]: (state, { module, visibleColumns }) => + TablesState.assocVisibleColumns({ module, visibleColumns })(state), + + [TablesActions.tableMaxRowsUpdate]: (state, { module, maxRows }) => + TablesState.assocMaxRows({ module, maxRows })(state), +} + +export default exportReducer(actionHandlers) diff --git a/webapp/store/ui/tables/state.js b/webapp/store/ui/tables/state.js new file mode 100644 index 0000000000..8a02d2ccea --- /dev/null +++ b/webapp/store/ui/tables/state.js @@ -0,0 +1,27 @@ +import * as A from '@core/arena' + +import * as UiState from '../state' +import { Objects } from '@openforis/arena-core' + +export const stateKey = 'tables' + +const getState = A.pipe(UiState.getState, A.propOr({}, stateKey)) + +const keys = { + visibleColumnKeysByModule: 'visibleColumnKeysByModule', + maxRowsByModule: 'maxRowsByModule', +} + +export const getVisibleColumns = (module) => A.pipe(getState, Objects.path([keys.visibleColumnKeysByModule, module])) + +export const getMaxRows = (module) => A.pipe(getState, Objects.path([keys.maxRowsByModule, module])) + +export const assocVisibleColumns = + ({ module, visibleColumns }) => + (state) => + Objects.assocPath({ obj: state, path: [keys.visibleColumnKeysByModule, module], value: visibleColumns }) + +export const assocMaxRows = + ({ module, maxRows }) => + (state) => + Objects.assocPath({ obj: state, path: [keys.maxRowsByModule, module], value: maxRows }) From 64cd47fc5d7f0b22b5e01baa723634ceb17a821c Mon Sep 17 00:00:00 2001 From: Stefano Ricci Date: Wed, 29 Nov 2023 22:37:03 +0100 Subject: [PATCH 2/3] store max rows --- webapp/components/Table/Footer/Footer.js | 19 +++++++++++++++++-- .../Table/Footer/Paginator/Paginator.js | 9 ++++----- webapp/components/Table/Table.js | 2 +- webapp/components/Table/constants.js | 2 +- webapp/components/Table/useTable.js | 6 ++++-- 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/webapp/components/Table/Footer/Footer.js b/webapp/components/Table/Footer/Footer.js index 3c1b0ed2cc..e1c2984605 100644 --- a/webapp/components/Table/Footer/Footer.js +++ b/webapp/components/Table/Footer/Footer.js @@ -1,15 +1,19 @@ import React from 'react' import { useNavigate } from 'react-router' +import { useDispatch } from 'react-redux' +import PropTypes from 'prop-types' import { Objects } from '@openforis/arena-core' import { updateQuery } from '@webapp/components/Table/tableLink' import Paginator from './Paginator' +import { TablesActions } from '@webapp/store/ui/tables' export const Footer = (props) => { - const { list, offset, limit, count } = props + const { count, limit, list, module, offset } = props + const dispatch = useDispatch() const navigate = useNavigate() return ( @@ -19,10 +23,21 @@ export const Footer = (props) => { offset={offset} limit={limit} count={count} - setLimit={(limitUpdated) => updateQuery(navigate)({ limit: limitUpdated })} + setLimit={(limitUpdated) => { + updateQuery(navigate)({ limit: limitUpdated }) + dispatch(TablesActions.updateMaxRows({ module, maxRows: limitUpdated })) + }} setOffset={(offsetUpdated) => updateQuery(navigate)({ offset: offsetUpdated })} /> )} ) } + +Footer.propTypes = { + count: PropTypes.number.isRequired, + limit: PropTypes.number.isRequired, + list: PropTypes.array, + module: PropTypes.string.isRequired, + offset: PropTypes.number.isRequired, +} diff --git a/webapp/components/Table/Footer/Paginator/Paginator.js b/webapp/components/Table/Footer/Paginator/Paginator.js index 1ac81270e3..bba9cccfa8 100644 --- a/webapp/components/Table/Footer/Paginator/Paginator.js +++ b/webapp/components/Table/Footer/Paginator/Paginator.js @@ -29,11 +29,10 @@ const Paginator = (props) => { itemLabel={A.identity} selection={limit} onChange={(limitUpdated) => { - if (TableConstants.itemsPerPageValues.includes(Number(limitUpdated))) { - setLimit(limitUpdated) - } else { - setLimit(TableConstants.itemsPerPageDefault) - } + const limitNext = TableConstants.itemsPerPageValues.includes(Number(limitUpdated)) + ? limitUpdated + : TableConstants.itemsPerPageDefault + setLimit(limitNext) }} /> diff --git a/webapp/components/Table/Table.js b/webapp/components/Table/Table.js index cd0a096229..b44d0dcfd7 100644 --- a/webapp/components/Table/Table.js +++ b/webapp/components/Table/Table.js @@ -116,7 +116,7 @@ const Table = (props) => { handleSortBy={handleSortBy} selectedItems={selectedItems} /> -