Enhance PermissionsMatrix with session storage for expanded rows and scroll position
- Implemented session storage functionality to persist expanded row keys and scroll position in the PermissionsMatrix, improving user experience during navigation. - Refactored state management to utilize hooks for handling expanded rows and scroll restoration. - Added utility functions for reading and writing to session storage, ensuring data integrity and availability across user sessions. - Updated event handling for scroll events to maintain the user's scroll position, enhancing usability in the permissions matrix.
This commit is contained in:
parent
24c06c25d3
commit
0a09905f9f
@ -4,7 +4,9 @@ import {
|
||||
useState,
|
||||
createElement,
|
||||
useContext,
|
||||
useRef
|
||||
useRef,
|
||||
useEffect,
|
||||
useLayoutEffect
|
||||
} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Table, Flex, Tooltip, Button } from 'antd'
|
||||
@ -21,6 +23,30 @@ import PermissionCheckbox from './PermissionCheckbox'
|
||||
import { CaretRightOutlined } from '@ant-design/icons'
|
||||
|
||||
const DEFAULT_SCROLL_HEIGHT = 'calc(var(--unit-100vh) - 258px)'
|
||||
const PERMISSIONS_MATRIX_SESSION_KEY = 'permissionsMatrix:ui'
|
||||
|
||||
const readPermissionsMatrixSession = () => {
|
||||
try {
|
||||
const parsed = JSON.parse(
|
||||
sessionStorage.getItem(PERMISSIONS_MATRIX_SESSION_KEY)
|
||||
)
|
||||
if (!parsed || typeof parsed !== 'object') return {}
|
||||
return parsed
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
const writePermissionsMatrixSession = (patch) => {
|
||||
try {
|
||||
sessionStorage.setItem(
|
||||
PERMISSIONS_MATRIX_SESSION_KEY,
|
||||
JSON.stringify({ ...readPermissionsMatrixSession(), ...patch })
|
||||
)
|
||||
} catch {
|
||||
// sessionStorage may be unavailable
|
||||
}
|
||||
}
|
||||
|
||||
const getColumnIndexProps = (columnIndex) => ({
|
||||
'data-col': String(columnIndex),
|
||||
@ -328,9 +354,26 @@ const PermissionsMatrix = ({
|
||||
() => buildPermissionMatrixDataSource(models),
|
||||
[models]
|
||||
)
|
||||
const [expandedRowKeys, setExpandedRowKeys] = useState(null)
|
||||
const [expandedRowKeys, setExpandedRowKeys] = useState(() => {
|
||||
const stored = readPermissionsMatrixSession().expandedRowKeys
|
||||
return Array.isArray(stored) ? stored : []
|
||||
})
|
||||
const matrixRef = useRef(null)
|
||||
const scrollPositionRef = useRef(null)
|
||||
if (scrollPositionRef.current === null) {
|
||||
const storedScroll = readPermissionsMatrixSession().scroll
|
||||
scrollPositionRef.current = {
|
||||
left: Number(storedScroll?.left) || 0,
|
||||
top: Number(storedScroll?.top) || 0
|
||||
}
|
||||
}
|
||||
const hoveredColumnIndexRef = useRef(null)
|
||||
|
||||
const persistExpandedRowKeys = useCallback((keys) => {
|
||||
setExpandedRowKeys(keys)
|
||||
writePermissionsMatrixSession({ expandedRowKeys: keys })
|
||||
}, [])
|
||||
|
||||
const handleMatrixMouseOver = useCallback((event) => {
|
||||
const cell = event.target.closest('.ant-table-cell')
|
||||
if (!cell || !event.currentTarget.contains(cell)) return
|
||||
@ -345,11 +388,44 @@ const PermissionsMatrix = ({
|
||||
event.currentTarget.style.removeProperty('--permissions-hovered-col')
|
||||
}, [])
|
||||
|
||||
const resolvedExpandedRowKeys = useMemo(
|
||||
() => expandedRowKeys ?? dataSource.map((row) => row.key),
|
||||
[dataSource, expandedRowKeys]
|
||||
const resolvedExpandedRowKeys = useMemo(() => {
|
||||
const sectionKeys = new Set(dataSource.map((row) => row.key))
|
||||
return expandedRowKeys.filter((key) => sectionKeys.has(key))
|
||||
}, [dataSource, expandedRowKeys])
|
||||
|
||||
const getTableBody = useCallback(
|
||||
() => matrixRef.current?.querySelector('.ant-table-body') || null,
|
||||
[]
|
||||
)
|
||||
|
||||
const restoreTableScroll = useCallback(() => {
|
||||
const body = getTableBody()
|
||||
if (!body) return
|
||||
body.scrollLeft = scrollPositionRef.current.left
|
||||
body.scrollTop = scrollPositionRef.current.top
|
||||
}, [getTableBody])
|
||||
|
||||
useLayoutEffect(() => {
|
||||
restoreTableScroll()
|
||||
}, [restoreTableScroll, resolvedExpandedRowKeys])
|
||||
|
||||
useEffect(() => {
|
||||
const body = getTableBody()
|
||||
if (!body) return
|
||||
|
||||
const handleScroll = (event) => {
|
||||
const next = {
|
||||
left: event.currentTarget.scrollLeft,
|
||||
top: event.currentTarget.scrollTop
|
||||
}
|
||||
scrollPositionRef.current = next
|
||||
writePermissionsMatrixSession({ scroll: next })
|
||||
}
|
||||
|
||||
body.addEventListener('scroll', handleScroll, { passive: true })
|
||||
return () => body.removeEventListener('scroll', handleScroll)
|
||||
}, [getTableBody, resolvedExpandedRowKeys])
|
||||
|
||||
const isSectionExpanded = useCallback(
|
||||
(record) => resolvedExpandedRowKeys.includes(record.key),
|
||||
[resolvedExpandedRowKeys]
|
||||
@ -358,14 +434,20 @@ const PermissionsMatrix = ({
|
||||
const handleToggleSection = useCallback(
|
||||
(record) => {
|
||||
if (!record.isGroup) return
|
||||
setExpandedRowKeys((current) => {
|
||||
const keys = current ?? dataSource.map((row) => row.key)
|
||||
return keys.includes(record.key)
|
||||
? keys.filter((key) => key !== record.key)
|
||||
: [...keys, record.key]
|
||||
})
|
||||
persistExpandedRowKeys(
|
||||
expandedRowKeys.includes(record.key)
|
||||
? expandedRowKeys.filter((key) => key !== record.key)
|
||||
: [...expandedRowKeys, record.key]
|
||||
)
|
||||
},
|
||||
[dataSource]
|
||||
[expandedRowKeys, persistExpandedRowKeys]
|
||||
)
|
||||
|
||||
const handleExpandedRowsChange = useCallback(
|
||||
(keys) => {
|
||||
persistExpandedRowKeys(keys)
|
||||
},
|
||||
[persistExpandedRowKeys]
|
||||
)
|
||||
|
||||
var adjustedScrollHeight = scrollHeight
|
||||
@ -627,6 +709,7 @@ const PermissionsMatrix = ({
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={matrixRef}
|
||||
className='permissions-matrix'
|
||||
onMouseOver={handleMatrixMouseOver}
|
||||
onMouseLeave={handleMatrixMouseLeave}
|
||||
@ -645,7 +728,7 @@ const PermissionsMatrix = ({
|
||||
}
|
||||
expandable={{
|
||||
expandedRowKeys: resolvedExpandedRowKeys,
|
||||
onExpandedRowsChange: setExpandedRowKeys,
|
||||
onExpandedRowsChange: handleExpandedRowsChange,
|
||||
indentSize: 0,
|
||||
expandIcon: () => null
|
||||
}}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user