Skip to content

Commit

Permalink
Viewer: Selection of one or more elements via tree view (#597)
Browse files Browse the repository at this point in the history
* multi select from nav panel

* added test for NavTree click and shift click
  • Loading branch information
aozien committed Feb 20, 2023
1 parent af5b6a3 commit c938098
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 32 deletions.
3 changes: 2 additions & 1 deletion src/Components/NavPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default function NavPanel({
defaultExpandedElements,
expandedElements,
setExpandedElements,
selectWithShiftClickEvents,
pathPrefix,
}) {
assertDefined(...arguments)
Expand Down Expand Up @@ -71,7 +72,7 @@ export default function NavPanel({
flexGrow: 1,
}}
>
<NavTree model={model} element={element} pathPrefix={pathPrefix}/>
<NavTree model={model} selectWithShiftClickEvents={selectWithShiftClickEvents} element={element} pathPrefix={pathPrefix}/>
</TreeView>
</Paper>
)
Expand Down
21 changes: 4 additions & 17 deletions src/Components/NavTree.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import React, {useEffect, useState} from 'react'
import React from 'react'
import clsx from 'clsx'
import PropTypes from 'prop-types'
import {useNavigate} from 'react-router-dom'
import {reifyName} from '@bldrs-ai/ifclib'
import Box from '@mui/material/Box'
import Typography from '@mui/material/Typography'
import TreeItem, {useTreeItem} from '@mui/lab/TreeItem'
import {computeElementPathIds} from '../utils/TreeUtils'
import {handleBeforeUnload} from '../utils/event'


const NavTreePropTypes = {
Expand Down Expand Up @@ -53,6 +50,7 @@ export default function NavTree({
model,
element,
pathPrefix,
selectWithShiftClickEvents,
}) {
const CustomContent = React.forwardRef(function CustomContent(props, ref) {
const {
Expand Down Expand Up @@ -81,23 +79,11 @@ export default function NavTree({

const handleExpansionClick = (event) => handleExpansion(event)

const [selectedElement, setSelectedElement] = useState(null)

const handleSelectionClick = (event) => {
handleSelection(event)
setSelectedElement(element)
selectWithShiftClickEvents(event.shiftKey, element.expressID)
}

const navigate = useNavigate()

useEffect(() => {
if (selectedElement) {
const newPath =
`${pathPrefix}/${computeElementPathIds(element, (elt) => elt.expressID).join('/')}`
window.removeEventListener('beforeunload', handleBeforeUnload)
navigate(newPath)
}
}, [selectedElement, navigate])

return (
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
Expand Down Expand Up @@ -155,6 +141,7 @@ export default function NavTree({
model={model}
element={child}
pathPrefix={pathPrefix}
selectWithShiftClickEvents={selectWithShiftClickEvents}
/>
</React.Fragment>
)
Expand Down
60 changes: 50 additions & 10 deletions src/Components/NavTree.test.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,58 @@
import React from 'react'
import {render} from '@testing-library/react'
import {render, act, fireEvent} from '@testing-library/react'
import ShareMock from '../ShareMock'
import {MockViewer, newMockStringValueElt} from '../utils/IfcMock.test'
import NavTree from './NavTree'


test('NavTree for single element', () => {
const testLabel = 'Test node label'
const {getByText} = render(
<ShareMock>
jest.mock('@mui/lab/TreeItem', () => {
const original = jest.requireActual('@mui/lab/TreeItem')
return {
__esModule: true,
...original,
useTreeItem: jest.fn().mockReturnValue({
disabled: false,
expanded: false,
selected: false,
focused: false,
handleExpansion: jest.fn(),
handleSelection: jest.fn(),
}),
}
})

describe('NavTree', () => {
test('NavTree for single element', () => {
const testLabel = 'Test node label'
const {getByText} = render(
<ShareMock>
<NavTree
viewer={new MockViewer}
element={newMockStringValueElt(testLabel)}
/>
</ShareMock>)
expect(getByText(testLabel)).toBeInTheDocument()
})

it('should select element on click', async () => {
const selectElementsMock = jest.fn()
const testLabel = 'Test node label'
const ifcElementMock = newMockStringValueElt(testLabel)
const {getByText} = render(
<NavTree
viewer={new MockViewer}
element={newMockStringValueElt(testLabel)}
/>
</ShareMock>)
expect(getByText(testLabel)).toBeInTheDocument()
element={ifcElementMock}
pathPrefix={'/share/v/p/index.ifc'}
selectWithShiftClickEvents={selectElementsMock}
/>)
const root = await getByText(testLabel)
expect(getByText(testLabel)).toBeInTheDocument()
await act(async () => {
await fireEvent.click(root)
})
expect(selectElementsMock).toHaveBeenLastCalledWith(false, 1)
await act(async () => {
await fireEvent.click(root, {shiftKey: true})
})
expect(selectElementsMock).toHaveBeenLastCalledWith(true, 1)
})
})
19 changes: 15 additions & 4 deletions src/Containers/CadView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -488,19 +488,29 @@ export default function CadView({
if (!item) {
return
}
selectWithShiftClickEvents(event.shiftKey, item.id)
}

/**
* Select/Deselect items in the scene using shift+click
*
* @param {boolean} shiftKey the click event
* @param {number} expressId the express id of the element
*/
function selectWithShiftClickEvents(shiftKey, expressId) {
let newSelection = []
if (event.shiftKey) {
if (shiftKey) {
const selectedInViewer = viewer.getSelectedIds()
const indexOfItem = selectedInViewer.indexOf(item.id)
const indexOfItem = selectedInViewer.indexOf(expressId)
const alreadySelected = indexOfItem !== -1
if (alreadySelected) {
selectedInViewer.splice(indexOfItem, 1)
} else {
selectedInViewer.push(item.id)
selectedInViewer.push(expressId)
}
newSelection = selectedInViewer
} else {
newSelection = [item.id]
newSelection = [expressId]
}
selectItemsInScene(newSelection)
}
Expand Down Expand Up @@ -582,6 +592,7 @@ export default function CadView({
defaultExpandedElements={defaultExpandedElements}
expandedElements={expandedElements}
setExpandedElements={setExpandedElements}
selectWithShiftClickEvents={selectWithShiftClickEvents}
pathPrefix={
pathPrefix + (modelPath.gitpath ? modelPath.getRepoPath() : modelPath.filepath)
}
Expand Down

0 comments on commit c938098

Please sign in to comment.