Skip to content

Commit

Permalink
fix(web): use mui treeView instead of custom implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
sabhas committed Nov 5, 2022
1 parent e10a055 commit c51b504
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 84 deletions.
16 changes: 13 additions & 3 deletions web/src/components/deleteConfirmationModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,24 @@ const DeleteConfirmationModal = ({
message,
_delete
}: DeleteConfirmationModalProps) => {
const handleDeleteClick = (event: React.MouseEvent) => {
event.stopPropagation()
_delete()
}

const handleClose = (event: any) => {
event.stopPropagation()
setOpen(false)
}

return (
<BootstrapDialog onClose={() => setOpen(false)} open={open}>
<BootstrapDialog onClose={handleClose} open={open}>
<DialogContent dividers>
<Typography gutterBottom>{message}</Typography>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpen(false)}>Cancel</Button>
<Button color="error" onClick={() => _delete()}>
<Button onClick={handleClose}>Cancel</Button>
<Button color="error" onClick={handleDeleteClick}>
Delete
</Button>
</DialogActions>
Expand Down
16 changes: 13 additions & 3 deletions web/src/components/nameInputModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,18 @@ const NameInputModal = ({
action(name)
}

const handleActionClick = (event: React.MouseEvent) => {
event.stopPropagation()
action(name)
}

const handleClose = (event: any) => {
event.stopPropagation()
setOpen(false)
}

return (
<BootstrapDialog fullWidth onClose={() => setOpen(false)} open={open}>
<BootstrapDialog fullWidth onClose={handleClose} open={open}>
<BootstrapDialogTitle id="abort-modal" handleOpen={setOpen}>
{title}
</BootstrapDialogTitle>
Expand All @@ -91,12 +101,12 @@ const NameInputModal = ({
</form>
</DialogContent>
<DialogActions>
<Button variant="contained" onClick={() => setOpen(false)}>
<Button variant="contained" onClick={handleClose}>
Cancel
</Button>
<Button
variant="contained"
onClick={() => action(name)}
onClick={handleActionClick}
disabled={hasError || !name}
>
{actionLabel}
Expand Down
136 changes: 59 additions & 77 deletions web/src/components/tree.tsx
Original file line number Diff line number Diff line change
@@ -1,67 +1,79 @@
import React, { useEffect, useState } from 'react'
import { Menu, MenuItem } from '@mui/material'
import React, { useState } from 'react'
import { Menu, MenuItem, Typography } from '@mui/material'
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import ChevronRightIcon from '@mui/icons-material/ChevronRight'
import MuiTreeView from '@mui/lab/TreeView'
import MuiTreeItem from '@mui/lab/TreeItem'

import DeleteConfirmationModal from './deleteConfirmationModal'
import NameInputModal from './nameInputModal'

import { TreeNode } from '../utils/types'

type Props = {
interface Props {
node: TreeNode
selectedFilePath: string
handleSelect: (filePath: string) => void
deleteNode: (path: string, isFolder: boolean) => void
addFile: (path: string) => void
addFolder: (path: string) => void
rename: (oldPath: string, newPath: string) => void
}

interface TreeViewProps extends Props {
defaultExpanded?: string[]
}

const TreeView = ({
node,
selectedFilePath,
handleSelect,
deleteNode,
addFile,
addFolder,
rename,
defaultExpanded
}: Props) => {
}: TreeViewProps) => {
const renderTree = (nodes: TreeNode) => (
<MuiTreeItem
key={nodes.relativePath}
nodeId={nodes.relativePath}
label={
<TreeItemWithContextMenu
node={nodes}
handleSelect={handleSelect}
deleteNode={deleteNode}
addFile={addFile}
addFolder={addFolder}
rename={rename}
/>
}
>
{Array.isArray(nodes.children)
? nodes.children.map((node) => renderTree(node))
: null}
</MuiTreeItem>
)

return (
<ul
style={{
listStyle: 'none',
padding: '0.25rem 0.85rem',
width: 'max-content'
}}
<MuiTreeView
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
defaultExpanded={defaultExpanded}
sx={{ flexGrow: 1, maxWidth: 400, overflowY: 'auto' }}
>
<TreeViewNode
node={node}
selectedFilePath={selectedFilePath}
handleSelect={handleSelect}
deleteNode={deleteNode}
addFile={addFile}
addFolder={addFolder}
rename={rename}
defaultExpanded={defaultExpanded}
/>
</ul>
{renderTree(node)}
</MuiTreeView>
)
}

export default TreeView

const TreeViewNode = ({
const TreeItemWithContextMenu = ({
node,
selectedFilePath,
handleSelect,
deleteNode,
addFile,
addFolder,
rename,
defaultExpanded
rename
}: Props) => {
const [deleteConfirmationModalOpen, setDeleteConfirmationModalOpen] =
useState(false)
Expand All @@ -72,18 +84,19 @@ const TreeViewNode = ({
const [nameInputModalTitle, setNameInputModalTitle] = useState('')
const [nameInputModalActionLabel, setNameInputModalActionLabel] = useState('')
const [nameInputModalForFolder, setNameInputModalForFolder] = useState(false)
const [childVisible, setChildVisibility] = useState(false)
const [contextMenu, setContextMenu] = useState<{
mouseX: number
mouseY: number
} | null>(null)

const launchProgram = () => {
const launchProgram = (event: React.MouseEvent) => {
event.stopPropagation()
const baseUrl = window.location.origin
window.open(`${baseUrl}/SASjsApi/stp/execute?_program=${node.relativePath}`)
}

const launchProgramWithDebug = () => {
const launchProgramWithDebug = (event: React.MouseEvent) => {
event.stopPropagation()
const baseUrl = window.location.origin
window.open(
`${baseUrl}/SASjsApi/stp/execute?_program=${node.relativePath}&_debug=131`
Expand All @@ -103,25 +116,18 @@ const TreeViewNode = ({
)
}

const hasChild = node.children.length ? true : false

const handleItemClick = () => {
if (node.children.length) {
setChildVisibility((v) => !v)
return
}
const handleClose = (event: any) => {
event.stopPropagation()
setContextMenu(null)
}

const handleItemClick = (event: React.MouseEvent) => {
if (node.children.length) return
handleSelect(node.relativePath)
}

useEffect(() => {
if (defaultExpanded && defaultExpanded[0] === node.relativePath) {
setChildVisibility(true)
defaultExpanded.shift()
}
}, [defaultExpanded, node.relativePath])

const handleDeleteItemClick = () => {
const handleDeleteItemClick = (event: React.MouseEvent) => {
event.stopPropagation()
setContextMenu(null)
setDeleteConfirmationModalOpen(true)
setDeleteConfirmationModalMessage(
Expand All @@ -136,7 +142,8 @@ const TreeViewNode = ({
deleteNode(node.relativePath, node.isFolder)
}

const handleNewFolderItemClick = () => {
const handleNewFolderItemClick = (event: React.MouseEvent) => {
event.stopPropagation()
setContextMenu(null)
setNameInputModalOpen(true)
setNameInputModalTitle('Add Folder')
Expand All @@ -145,7 +152,8 @@ const TreeViewNode = ({
setDefaultInputModalName('')
}

const handleNewFileItemClick = () => {
const handleNewFileItemClick = (event: React.MouseEvent) => {
event.stopPropagation()
setContextMenu(null)
setNameInputModalOpen(true)
setNameInputModalTitle('Add File')
Expand All @@ -161,7 +169,8 @@ const TreeViewNode = ({
else addFile(path)
}

const handleRenameItemClick = () => {
const handleRenameItemClick = (event: React.MouseEvent) => {
event.stopPropagation()
setContextMenu(null)
setNameInputModalOpen(true)
setNameInputModalTitle('Rename')
Expand All @@ -181,34 +190,7 @@ const TreeViewNode = ({

return (
<div onContextMenu={handleContextMenu} style={{ cursor: 'context-menu' }}>
<li style={{ display: 'list-item' }}>
<div
className={`tree-item-label ${
selectedFilePath === node.relativePath ? 'selected' : ''
}`}
onClick={() => handleItemClick()}
>
{hasChild &&
(childVisible ? <ExpandMoreIcon /> : <ChevronRightIcon />)}
<div>{node.name}</div>
</div>

{hasChild &&
childVisible &&
node.children.map((child, index) => (
<TreeView
key={node.relativePath + '-' + index}
node={child}
selectedFilePath={selectedFilePath}
handleSelect={handleSelect}
deleteNode={deleteNode}
addFile={addFile}
addFolder={addFolder}
rename={rename}
defaultExpanded={defaultExpanded}
/>
))}
</li>
<Typography onClick={handleItemClick}>{node.name}</Typography>
<DeleteConfirmationModal
open={deleteConfirmationModalOpen}
setOpen={setDeleteConfirmationModalOpen}
Expand All @@ -228,7 +210,7 @@ const TreeViewNode = ({
/>
<Menu
open={contextMenu !== null}
onClose={() => setContextMenu(null)}
onClose={handleClose}
anchorReference="anchorPosition"
anchorPosition={
contextMenu !== null
Expand Down
1 change: 0 additions & 1 deletion web/src/containers/Studio/sideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ const SideBar = ({
{directoryData && (
<TreeView
node={directoryData}
selectedFilePath={selectedFilePath}
handleSelect={handleFileSelect}
deleteNode={deleteNode}
addFile={addFile}
Expand Down

0 comments on commit c51b504

Please sign in to comment.