You've already forked visualtree
Display files and recursive node
This commit is contained in:
@@ -1,12 +1,27 @@
|
||||
<script setup>
|
||||
|
||||
const emit = defineEmits(['fileUpload'])
|
||||
|
||||
const generateJSONFile = (e) => {
|
||||
const contents = e.target.result
|
||||
const json = JSON.parse(contents)
|
||||
emit('fileUpload', json)
|
||||
};
|
||||
|
||||
const openJSONFile = (e) => {
|
||||
const file = e.target.files[0]
|
||||
const reader = new FileReader()
|
||||
reader.onload = generateJSONFile
|
||||
reader.readAsText(file)
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<input type="file" id="treeFile" class="hidden">
|
||||
<input type="file" id="treeFile" class="hidden" @change="openJSONFile" accept=".json">
|
||||
<label for="treeFile" class="p-12 border border-blue-500 bg-blue-100/30 dark:bg-blue-900/20 border-dashed rounded-xl text-blue-400 text cursor-pointer block">
|
||||
Drop a file here or click to select a file
|
||||
Drop a file here or click to select a file
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
81
src/components/Node.vue
Normal file
81
src/components/Node.vue
Normal file
@@ -0,0 +1,81 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import Node from './Node.vue'
|
||||
|
||||
const open = ref(false)
|
||||
|
||||
const toggleOpen = () => {
|
||||
open.value = !open.value
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
node: Object
|
||||
})
|
||||
|
||||
const format = computed(() => {
|
||||
if (props.node.type === 'file'){
|
||||
const filename = props.node.name.split('.')
|
||||
return filename[filename.length - 1]
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-3 node">
|
||||
<div class="bg-gray-800 flex items-center justify-between px-3 py-3 rounded gap-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<div v-if="node.type === 'directory'" class="p-2 bg-gray-900 rounded h-5 w-5 text-xs flex items-center justify-center">
|
||||
D
|
||||
</div>
|
||||
<div v-if="node.type === 'file'" class="p-2 bg-gray-900 rounded h-5 w-5 text-xs flex items-center justify-center">
|
||||
F
|
||||
</div>
|
||||
<div class="text-xs select-none">
|
||||
{{ node.name }}
|
||||
</div>
|
||||
<div v-if="node.size" class="bg-gray-900 rounded px-2 py-1">
|
||||
<div class="text-xs flex items-center gap-1">
|
||||
<div class="font-medium text-gray-400">
|
||||
Size:
|
||||
</div>
|
||||
<div class="text-gray-500">
|
||||
{{ node.size }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="node.contents" class="bg-gray-900 rounded px-2 py-1">
|
||||
<div class="text-xs flex items-center gap-1">
|
||||
<div class="font-medium text-gray-400">
|
||||
Items:
|
||||
</div>
|
||||
<div class="text-gray-500">
|
||||
{{ node.contents.length }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="format" class="bg-gray-900 rounded px-2 py-1">
|
||||
<div class="text-xs flex items-center gap-1 font-semibold text-gray-400">
|
||||
{{ format }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="node.type === 'directory' && node.contents.length" @click="toggleOpen">
|
||||
<div v-if="!open" class="text-xs bg-gray-900 rounded flex items-center justify-center cursor-pointer px-2 py-1">
|
||||
Open
|
||||
</div>
|
||||
<div v-else class="text-xs bg-red-900 rounded flex items-center justify-center cursor-pointer px-2 py-1">
|
||||
Close
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="open">
|
||||
<div v-if="node.type === 'directory'" class="node-list space-y-3">
|
||||
<Node v-for="node in node.contents" :node="node" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user