mirror of
https://github.com/sasjs/server.git
synced 2026-01-07 06:30:06 +00:00
Merge pull request #89 from sasjs/remove-deleted-file
fix: remove deleted file from directory tree in sidebar of drive
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState, useEffect, useCallback } from 'react'
|
||||||
|
import { useLocation } from 'react-router-dom'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
import CssBaseline from '@mui/material/CssBaseline'
|
import CssBaseline from '@mui/material/CssBaseline'
|
||||||
import Box from '@mui/material/Box'
|
import Box from '@mui/material/Box'
|
||||||
@@ -6,13 +8,93 @@ import Box from '@mui/material/Box'
|
|||||||
import SideBar from './sideBar'
|
import SideBar from './sideBar'
|
||||||
import Main from './main'
|
import Main from './main'
|
||||||
|
|
||||||
|
export interface TreeNode {
|
||||||
|
name: string
|
||||||
|
relativePath: string
|
||||||
|
absolutePath: string
|
||||||
|
children: Array<TreeNode>
|
||||||
|
}
|
||||||
|
|
||||||
const Drive = () => {
|
const Drive = () => {
|
||||||
|
const location = useLocation()
|
||||||
|
const baseUrl = window.location.origin
|
||||||
|
|
||||||
const [selectedFilePath, setSelectedFilePath] = useState('')
|
const [selectedFilePath, setSelectedFilePath] = useState('')
|
||||||
|
const [directoryData, setDirectoryData] = useState<TreeNode | null>(null)
|
||||||
|
|
||||||
|
const setFilePathOnMount = useCallback(() => {
|
||||||
|
const queryParams = new URLSearchParams(location.search)
|
||||||
|
setSelectedFilePath(queryParams.get('filePath') ?? '')
|
||||||
|
}, [location.search])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
axios
|
||||||
|
.get(`/SASjsApi/drive/fileTree`)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.data && res.data?.status === 'success') {
|
||||||
|
setDirectoryData(res.data.tree)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
setFilePathOnMount()
|
||||||
|
}, [setFilePathOnMount])
|
||||||
|
|
||||||
|
const handleSelect = (node: TreeNode) => {
|
||||||
|
if (node.children.length) return
|
||||||
|
|
||||||
|
if (!node.name.includes('.')) return
|
||||||
|
|
||||||
|
window.history.pushState(
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
`${baseUrl}/#/SASjsDrive?filePath=${node.relativePath}`
|
||||||
|
)
|
||||||
|
setSelectedFilePath(node.relativePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeFileFromTree = (path: string) => {
|
||||||
|
if (directoryData) {
|
||||||
|
const newTree = JSON.parse(JSON.stringify(directoryData)) as TreeNode
|
||||||
|
findAndRemoveNode(newTree, newTree, path)
|
||||||
|
setDirectoryData(newTree)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const findAndRemoveNode = (
|
||||||
|
node: TreeNode,
|
||||||
|
parentNode: TreeNode,
|
||||||
|
path: string
|
||||||
|
) => {
|
||||||
|
if (node.relativePath === path) {
|
||||||
|
removeNodeFromParent(parentNode, path)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (Array.isArray(node.children)) {
|
||||||
|
for (let i = 0; i < node.children.length; i++) {
|
||||||
|
if (findAndRemoveNode(node.children[i], node, path)) return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeNodeFromParent = (parent: TreeNode, path: string) => {
|
||||||
|
const index = parent.children.findIndex(
|
||||||
|
(node) => node.relativePath === path
|
||||||
|
)
|
||||||
|
if (index !== -1) {
|
||||||
|
parent.children.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: 'flex' }}>
|
<Box sx={{ display: 'flex' }}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<SideBar setSelectedFilePath={setSelectedFilePath} />
|
<SideBar directoryData={directoryData} handleSelect={handleSelect} />
|
||||||
<Main selectedFilePath={selectedFilePath} />
|
<Main
|
||||||
|
selectedFilePath={selectedFilePath}
|
||||||
|
removeFileFromTree={removeFileFromTree}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,12 @@ import Button from '@mui/material/Button'
|
|||||||
import Toolbar from '@mui/material/Toolbar'
|
import Toolbar from '@mui/material/Toolbar'
|
||||||
import CircularProgress from '@mui/material/CircularProgress'
|
import CircularProgress from '@mui/material/CircularProgress'
|
||||||
|
|
||||||
const Main = (props: any) => {
|
type Props = {
|
||||||
|
selectedFilePath: string
|
||||||
|
removeFileFromTree: (path: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const Main = (props: Props) => {
|
||||||
const baseUrl = window.location.origin
|
const baseUrl = window.location.origin
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
@@ -45,6 +50,7 @@ const Main = (props: any) => {
|
|||||||
.delete(`/SASjsApi/drive/file?_filePath=${filePath}`)
|
.delete(`/SASjsApi/drive/file?_filePath=${filePath}`)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setFileContent('')
|
setFileContent('')
|
||||||
|
props.removeFileFromTree(filePath)
|
||||||
window.history.pushState('', '', `${baseUrl}/#/SASjsDrive`)
|
window.history.pushState('', '', `${baseUrl}/#/SASjsDrive`)
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import React, { useState, useEffect, useCallback } from 'react'
|
import React from 'react'
|
||||||
import axios from 'axios'
|
|
||||||
import { useLocation } from 'react-router-dom'
|
|
||||||
|
|
||||||
import { makeStyles } from '@mui/styles'
|
import { makeStyles } from '@mui/styles'
|
||||||
|
|
||||||
@@ -16,12 +14,7 @@ import TreeItem from '@mui/lab/TreeItem'
|
|||||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
|
||||||
import ChevronRightIcon from '@mui/icons-material/ChevronRight'
|
import ChevronRightIcon from '@mui/icons-material/ChevronRight'
|
||||||
|
|
||||||
interface TreeNode {
|
import { TreeNode } from '.'
|
||||||
name: string
|
|
||||||
relativePath: string
|
|
||||||
absolutePath: string
|
|
||||||
children: Array<TreeNode>
|
|
||||||
}
|
|
||||||
|
|
||||||
const useStyles = makeStyles(() => ({
|
const useStyles = makeStyles(() => ({
|
||||||
root: {
|
root: {
|
||||||
@@ -36,46 +29,14 @@ const useStyles = makeStyles(() => ({
|
|||||||
|
|
||||||
const drawerWidth = 240
|
const drawerWidth = 240
|
||||||
|
|
||||||
const SideBar = (props: any) => {
|
type Props = {
|
||||||
const location = useLocation()
|
directoryData: TreeNode | null
|
||||||
const baseUrl = window.location.origin
|
handleSelect: (node: TreeNode) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const SideBar = ({ directoryData, handleSelect }: Props) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
||||||
const { setSelectedFilePath } = props
|
|
||||||
const [directoryData, setDirectoryData] = useState<TreeNode | null>(null)
|
|
||||||
|
|
||||||
const setFilePathOnMount = useCallback(() => {
|
|
||||||
const queryParams = new URLSearchParams(location.search)
|
|
||||||
setSelectedFilePath(queryParams.get('filePath'))
|
|
||||||
}, [location.search, setSelectedFilePath])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
axios
|
|
||||||
.get(`/SASjsApi/drive/fileTree`)
|
|
||||||
.then((res: any) => {
|
|
||||||
if (res.data && res.data?.status === 'success') {
|
|
||||||
setDirectoryData(res.data.tree)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err)
|
|
||||||
})
|
|
||||||
setFilePathOnMount()
|
|
||||||
}, [setFilePathOnMount])
|
|
||||||
|
|
||||||
const handleSelect = (node: TreeNode) => {
|
|
||||||
if (node.children.length) return
|
|
||||||
|
|
||||||
if (!node.name.includes('.')) return
|
|
||||||
|
|
||||||
window.history.pushState(
|
|
||||||
'',
|
|
||||||
'',
|
|
||||||
`${baseUrl}/#/SASjsDrive?filePath=${node.relativePath}`
|
|
||||||
)
|
|
||||||
setSelectedFilePath(node.relativePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderTree = (nodes: TreeNode) => (
|
const renderTree = (nodes: TreeNode) => (
|
||||||
<TreeItem
|
<TreeItem
|
||||||
classes={{ root: classes.root }}
|
classes={{ root: classes.root }}
|
||||||
@@ -107,12 +68,15 @@ const SideBar = (props: any) => {
|
|||||||
>
|
>
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
<Box sx={{ overflow: 'auto' }}>
|
<Box sx={{ overflow: 'auto' }}>
|
||||||
|
{directoryData && (
|
||||||
<TreeView
|
<TreeView
|
||||||
defaultCollapseIcon={<ExpandMoreIcon />}
|
defaultCollapseIcon={<ExpandMoreIcon />}
|
||||||
defaultExpandIcon={<ChevronRightIcon />}
|
defaultExpandIcon={<ChevronRightIcon />}
|
||||||
|
defaultExpanded={[directoryData.relativePath]}
|
||||||
>
|
>
|
||||||
{directoryData && renderTree(directoryData)}
|
{renderTree(directoryData)}
|
||||||
</TreeView>
|
</TreeView>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user