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 })