mirror of
https://gitee.com/dcren/cloud-native-app-initializer.git
synced 2026-08-25 10:56:30 +08:00
123 lines
3.4 KiB
JavaScript
123 lines
3.4 KiB
JavaScript
import PropTypes from 'prop-types'
|
|
import get from 'lodash.get'
|
|
import React, {useEffect, useState} from 'react'
|
|
|
|
import {IconCaretDown, IconFile, IconFolder} from '../icons'
|
|
|
|
function Tree({ tree, selected, onClickItem }) {
|
|
const [folders, setFolders] = useState([])
|
|
|
|
useEffect(() => {
|
|
const treeToArray = map => {
|
|
const recursive = (mapRec, acc) => {
|
|
mapRec.forEach(item => {
|
|
if (item.type === 'folder') {
|
|
acc.push({
|
|
filename: get(item, 'filename'),
|
|
path: get(item, 'path'),
|
|
hidden: get(item, 'hidden', false),
|
|
})
|
|
if (get(item, 'children')) {
|
|
recursive(item.children, acc)
|
|
}
|
|
}
|
|
})
|
|
return acc
|
|
}
|
|
return recursive(map, [])
|
|
}
|
|
setFolders(treeToArray(tree.children))
|
|
}, [tree, setFolders])
|
|
|
|
const renderItem = (item, depth = 0) => {
|
|
if (item.type === 'folder') {
|
|
const folder = folders.find(f => f.path === item.path)
|
|
const isHidden = get(folder, `hidden`, true)
|
|
return (
|
|
<li
|
|
key={`li${item.path}`}
|
|
className={`li-folder ${isHidden ? 'folder-hide' : ''}`}
|
|
>
|
|
<a
|
|
href='/#'
|
|
key={`s1${item.path}`}
|
|
className={`folder level-${depth}`}
|
|
onClick={e => {
|
|
e.preventDefault()
|
|
const newFolders = [...folders]
|
|
const newFolder = newFolders.find(f => f.path === item.path)
|
|
if (newFolder) {
|
|
newFolder.hidden = !get(newFolder, `hidden`, true)
|
|
setFolders(newFolders)
|
|
}
|
|
}}
|
|
>
|
|
<span key={`s2${item.path}`} className='text'>
|
|
{get(item, 'children.length', 0) > 0 && <IconCaretDown />}
|
|
<span key={`s3${item.path}`} className='icon'>
|
|
<IconFolder key={`s4${item.path}`} />
|
|
</span>
|
|
{item.filename}
|
|
</span>
|
|
</a>
|
|
{get(item, 'children') && (
|
|
<ul className='ul' key={`ul${item.path}`}>
|
|
{item.children.map(it => renderItem(it, depth + 1))}
|
|
</ul>
|
|
)}
|
|
</li>
|
|
)
|
|
}
|
|
// File
|
|
const isDisabled = get(item, 'language') === null
|
|
const isSelected = get(selected, 'path') === get(item, 'path')
|
|
return (
|
|
<li key={`li${item.path}`} className='li-file'>
|
|
<a
|
|
href='/#'
|
|
key={`s1${item.path}`}
|
|
tabIndex={`${isDisabled ? -1 : ''}`}
|
|
className={`file level-${depth} ${isDisabled ? 'disabled' : ''} ${
|
|
isSelected ? 'selected' : ''
|
|
}`}
|
|
onClick={e => {
|
|
e.preventDefault()
|
|
if (!isDisabled) {
|
|
onClickItem(item)
|
|
}
|
|
}}
|
|
>
|
|
<span key={`s2${item.path}`} className='text'>
|
|
<span key={`s3${item.path}`} className='icon'>
|
|
<IconFile key={`s4${item.path}`} />
|
|
</span>
|
|
{item.filename}
|
|
</span>
|
|
</a>
|
|
</li>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<ul className='explorer-ul'>
|
|
{tree.children.map(item => renderItem(item, 0))}
|
|
</ul>
|
|
)
|
|
}
|
|
|
|
Tree.propTypes = {
|
|
tree: PropTypes.shape({
|
|
children: PropTypes.arrayOf(
|
|
PropTypes.shape({
|
|
type: PropTypes.string,
|
|
})
|
|
),
|
|
}).isRequired,
|
|
selected: PropTypes.shape({
|
|
path: PropTypes.string.isRequired,
|
|
}).isRequired,
|
|
onClickItem: PropTypes.func.isRequired,
|
|
}
|
|
|
|
export default Tree
|