Skip to content

Commit

Permalink
Version History Panel (#801)
Browse files Browse the repository at this point in the history
* add controls group

* squash

* fix warning

* adjust the test

* resolve the package json conflict

* adjust the hide end to end test

* adjust the test id
  • Loading branch information
OlegMoshkovich committed Oct 14, 2023
1 parent 59bff6d commit 7c7fc3e
Show file tree
Hide file tree
Showing 23 changed files with 667 additions and 374 deletions.
3 changes: 2 additions & 1 deletion cypress/e2e/hide-feat/hide-feat.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ describe('Ifc Hide/Unhide E2E test suite', () => {
})

it('should toggle hide icon when clicked', () => {
cy.findByLabelText('Navigation Panel').realHover()
cy.findByTestId('Navigation').click()
cy.findByLabelText('Navigation Panel').click()
cy.findByTestId('hide-icon').should('exist')
cy.findByTestId('hide-icon').click()
cy.findByTestId('unhide-icon').should('exist')
Expand Down
9 changes: 5 additions & 4 deletions src/Components/BranchesControl.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,14 @@ export default function Branches() {
{branches.length > 1 && modelPath.repo !== undefined &&
<Paper elevation={0} variant='control'
sx={{
marginTop: '34px',
opacity: .8,
marginTop: '14px',
opacity: .9,
width: '100%',
}}
>
<TextField
sx={{
'width': '274px',
'width': '100%',
'& .MuiOutlinedInput-input': {
color: theme.palette.primary.contrastText,
},
Expand Down Expand Up @@ -115,7 +116,7 @@ export default function Branches() {
}}
onChange={(e) => handleSelect(e)}
variant='outlined'
label='Git Branches / Project Versions'
label={<Typography>GIT BRANCHES</Typography>}
value={selected}
select
role="button"
Expand Down
76 changes: 76 additions & 0 deletions src/Components/ControlsGroup.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React from 'react'
import ButtonGroup from '@mui/material/ButtonGroup'
import OpenModelControl from './OpenModelControl'
import useStore from '../store/useStore'
import {TooltipIconButton} from './Buttons'
import HistoryIcon from '@mui/icons-material/History'
import SearchIcon from '@mui/icons-material/Search'
import TreeIcon from '../assets/icons/Tree.svg'


/**
* OperationsGroup contains tools for sharing, notes, properties, cut
* plane, deselect, theme change and about.
*
* @property {Function} deselectItems deselects currently selected element
* @return {React.Component}
*/
export default function OperationsGroup({fileOpen, repo}) {
const isNavigationVisible = useStore((state) => state.isNavigationVisible)
const toggleIsNavigationVisible = useStore((state) => state.toggleIsNavigationVisible)
const isSearchVisible = useStore((state) => state.isSearchVisible)
const toggleIsSearchVisible = useStore((state) => state.toggleIsSearchVisible)
const isVersionHistoryVisible = useStore((state) => state.isVersionHistoryVisible)
const toggleIsVersionHistoryVisible = useStore((state) => state.toggleIsVersionHistoryVisible)


return (
<ButtonGroup
orientation='horizontal'
variant='contained'
>
<OpenModelControl fileOpen={fileOpen}/>
<TooltipIconButton
title='Search'
icon={<SearchIcon className='icon-share' color='secondary'/>}
placement='bottom'
aboutInfo={false}
selected={isSearchVisible}
onClick={toggleIsSearchVisible}
/>
<TooltipIconButton
title='Navigation'
icon={<TreeIcon className='icon-share' color='secondary' style={{width: '17px', height: '17px'}}/>}
placement='bottom'
dataTestId='Navigation'
aboutInfo={false}
selected={isNavigationVisible}
onClick={() => {
if (isVersionHistoryVisible) {
toggleIsVersionHistoryVisible()
toggleIsNavigationVisible()
} else {
toggleIsNavigationVisible()
}
}}
/>
{repo !== undefined &&
<TooltipIconButton
title='Project History'
icon={<HistoryIcon className='icon-share' color='secondary'/>}
placement='bottom'
selected={isVersionHistoryVisible}
onClick={() => {
if (isNavigationVisible) {
toggleIsVersionHistoryVisible()
toggleIsNavigationVisible()
} else {
toggleIsVersionHistoryVisible()
}
}}
/>
}

</ButtonGroup>
)
}
1 change: 1 addition & 0 deletions src/Components/Logo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default function Logo({onClick}) {
'position': 'fixed',
'bottom': '1em',
'left': '1em',
'boxShadow': theme.shadows[1],
'& svg': {
'marginBottom': '4px',
'marginTop': '4px',
Expand Down
217 changes: 118 additions & 99 deletions src/Components/NavPanel.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import React from 'react'
import AccountTreeIcon from '@mui/icons-material/AccountTree'
import Box from '@mui/material/Box'
import IconButton from '@mui/material/IconButton'
import ListIcon from '@mui/icons-material/List'
import Paper from '@mui/material/Paper'
import Stack from '@mui/material/Stack'
import ToggleButton from '@mui/material/ToggleButton'
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'
import Tooltip from '@mui/material/Tooltip'
import Typography from '@mui/material/Typography'
import TreeView from '@mui/lab/TreeView'
import {styled} from '@mui/material/styles'
import NavTree from './NavTree'
Expand All @@ -14,6 +18,7 @@ import {assertDefined} from '../utils/assert'
import {useExistInFeature} from '../hooks/useExistInFeature'
import NodeClosedIcon from '../assets/icons/NodeClosed.svg'
import NodeOpenIcon from '../assets/icons/NodeOpened.svg'
import CloseIcon from '@mui/icons-material/Close'


/**
Expand Down Expand Up @@ -42,12 +47,8 @@ export default function NavPanel({
}) {
assertDefined(...arguments)
const selectedElements = useStore((state) => state.selectedElements)
// TODO(pablo): the defaultExpanded array can contain bogus IDs with
// no error. Not sure of a better way to pre-open the first few
// nodes besides hardcoding.

const elementTypesMap = useStore((state) => state.elementTypesMap)

const toggleIsNavigationVisible = useStore((state) => state.toggleIsNavigationVisible)
const existNavTypesInFeature = useExistInFeature('navtypes')

const onTreeViewChanged = (event, value) => {
Expand All @@ -74,119 +75,137 @@ export default function NavPanel({
}))

const isNavTree = existNavTypesInFeature ? navigationMode === 'spatial-tree' : true

return (
<div style={{
width: '100%',
}}
>
<div style={{width: '100%'}}>
<Paper
elevation={0}
elevation={1}
aria-label='Navigation Panel'
variant='control'
sx={{
'marginTop': '14px',
'overflow': 'auto',
'width': '100%',
'opacity': .8,
'opacity': 0.8,
'justifyContent': 'space-around',
'alignItems': 'center',
'maxHeight': '400px',
'&:hover #togglegrp': {
visibility: 'visible !important',
},
'&:hover svg': {
visibility: 'visible !important',
},
'maxHeight': '300px',
'@media (max-width: 900px)': {
maxHeight: '292px',
maxHeight: '300PX',
top: '86px',
},
}}
>
<div>
{existNavTypesInFeature &&
<StyledToggleButtonGroup
exclusive
id={'togglegrp'}
value={navigationMode}
size="small"
<Stack direction='column'>
{/* Sticky Header */}
<Stack
direction='row'
justifyContent='space-between'
alignItems='center'
sx={{
'marginLeft': '16px',
'marginTop': '8px',
'visibility': 'hidden',
'& button': {
height: '30px',
width: '30px',
},
'& svg': {
height: '20px',
width: '20px',
},
position: 'sticky',
top: 0,
backgroundColor: 'background.paper',
zIndex: 1,
}}
onChange={onTreeViewChanged}
>
<ToggleButton value='spatial-tree' aria-label='spatial-tree'>
<Tooltip
title={'Spatial Structure'}
describeChild
placement={'bottom-end'}
PopperProps={{style: {zIndex: 0}}}
>
<AccountTreeIcon/>
</Tooltip>
</ToggleButton>
<ToggleButton value='element-types' aria-label='element-types'>
<Tooltip
title={'Element Types'}
describeChild
placement={'bottom-end'}
PopperProps={{style: {zIndex: 0}}}
<Typography variant='overline' sx={{marginLeft: '1em'}}>Spatial Navigation</Typography>
<Box sx={{marginRight: '.4em'}}>
<IconButton aria-label="close" size="small" onClick={toggleIsNavigationVisible}>
<CloseIcon fontSize="inherit"/>
</IconButton>
</Box>
</Stack>

{/* Content */}
<Box>
{existNavTypesInFeature && (
<StyledToggleButtonGroup
exclusive
id={'togglegrp'}
value={navigationMode}
size="small"
sx={{
'marginLeft': '16px',
'marginTop': '8px',
'visibility': 'hidden',
'& button': {
height: '30px',
width: '30px',
},
'& svg': {
height: '20px',
width: '20px',
},
}}
onChange={onTreeViewChanged}
>
<ListIcon/>
</Tooltip>
</ToggleButton>
</StyledToggleButtonGroup>}
<TreeView
aria-label={isNavTree ? 'IFC Navigator' : 'IFC Types Navigator'}
defaultCollapseIcon={<NodeOpenIcon className='icon-share icon-nav-caret'/>}
defaultExpandIcon={<NodeClosedIcon className='icon-share icon-nav-caret'/>}
defaultExpanded={isNavTree ? defaultExpandedElements : defaultExpandedTypes}
expanded={isNavTree ? expandedElements : expandedTypes}
selected={selectedElements}
onNodeToggle={(event, nodeIds) => {
if (isNavTree) {
setExpandedElements(nodeIds)
} else {
setExpandedTypes(nodeIds)
}
}}
key='tree'
sx={{
'padding': existNavTypesInFeature ? '7px 0 14px 0' : '14px 0',
'maxWidth': '400px',
'overflowY': 'auto',
'overflowX': 'hidden',
'flexGrow': 1,
'&:focus svg': {
visibility: 'visible !important',
},
}}
>
{isNavTree ?
<NavTree
model={model}
selectWithShiftClickEvents={selectWithShiftClickEvents}
element={element}
pathPrefix={pathPrefix}
/> :
<TypesNavTree
model={model}
types={elementTypesMap}
selectWithShiftClickEvents={selectWithShiftClickEvents}
pathPrefix={pathPrefix}
/>}
</TreeView>
</div>
<ToggleButton value='spatial-tree' aria-label='spatial-tree'>
<Tooltip
title={'Spatial Structure'}
describeChild
placement={'bottom-end'}
PopperProps={{style: {zIndex: 0}}}
>
<AccountTreeIcon/>
</Tooltip>
</ToggleButton>
<ToggleButton value='element-types' aria-label='element-types'>
<Tooltip
title={'Element Types'}
describeChild
placement={'bottom-end'}
PopperProps={{style: {zIndex: 0}}}
>
<ListIcon/>
</Tooltip>
</ToggleButton>
</StyledToggleButtonGroup>
)}
<TreeView
aria-label={isNavTree ? 'IFC Navigator' : 'IFC Types Navigator'}
defaultCollapseIcon={<NodeOpenIcon className='icon-share icon-nav-caret'/>}
defaultExpandIcon={<NodeClosedIcon className='icon-share icon-nav-caret'/>}
defaultExpanded={isNavTree ? defaultExpandedElements : defaultExpandedTypes}
expanded={isNavTree ? expandedElements : expandedTypes}
selected={selectedElements}
onNodeToggle={(event, nodeIds) => {
if (isNavTree) {
setExpandedElements(nodeIds)
} else {
setExpandedTypes(nodeIds)
}
}}
key='tree'
sx={{
'padding': existNavTypesInFeature ? '7px 0 14px 0' : '4px 0px 10px 0px',
'maxWidth': '400px',
'overflowY': 'auto',
'overflowX': 'hidden',
'flexGrow': 1,
'&:focus svg': {
visibility: 'visible !important',
},
}}
>
{isNavTree ? (
<NavTree
model={model}
selectWithShiftClickEvents={selectWithShiftClickEvents}
element={element}
pathPrefix={pathPrefix}
/>
) : (
<TypesNavTree
model={model}
types={elementTypesMap}
selectWithShiftClickEvents={selectWithShiftClickEvents}
pathPrefix={pathPrefix}
/>
)}
</TreeView>
</Box>
</Stack>
</Paper>
</div>
)
Expand Down
2 changes: 1 addition & 1 deletion src/Components/NoContent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import AttentionIcon from '../assets/icons/Attention.svg'
*/
export default function NoContent({message = 'no content'}) {
return (
<Paper variant='control' sx={{textAlign: 'center'}}>
<Paper variant='control' sx={{textAlign: 'center', padding: '20px 5px', borderRadius: '4px'}}>
<AttentionIcon className='icon-share'/>
<Typography sx={{marginTop: '1em'}}>{message}</Typography>
</Paper>
Expand Down

0 comments on commit 7c7fc3e

Please sign in to comment.