You've already forked visualtree
Display files and recursive node
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>VisualTREE</title>
|
||||
</head>
|
||||
<body>
|
||||
<body class="overflow-y-scroll">
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
|
||||
65
src/App.vue
65
src/App.vue
@@ -1,28 +1,43 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
import Input from './components/Input.vue'
|
||||
import Node from './components/Node.vue'
|
||||
|
||||
|
||||
const fileUploaded = ref(false)
|
||||
const fileInfo = ref(null)
|
||||
const fileData = ref(null)
|
||||
|
||||
const fileChanged = (file) => {
|
||||
fileInfo.value = file[1]
|
||||
fileData.value = file[0]
|
||||
fileUploaded.value = true
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bg-black">
|
||||
<div class="min-h-screen min-w-screen flex flex-col items-center bg-blue-100 dark:bg-blue-800/10">
|
||||
<div class="p-10 w-full text-center flex items-center justify-center">
|
||||
<div class="min-h-screen min-w-screen flex flex-col items-center bg-blue-100 dark:bg-blue-800/10 gap-10 py-10">
|
||||
<div class="w-full text-center flex items-center justify-center">
|
||||
<div class="flex items-center justify-center bg-white dark:bg-gray-900 rounded-lg overflow-hidden text-sm">
|
||||
<div class="px-4 py-2 dark:text-white hover:text-blue-300 dark:hover:text-white dark:hover:bg-gray-700 cursor-pointer">
|
||||
Home
|
||||
</div>
|
||||
<div class="px-4 py-2 dark:text-white hover:text-blue-300 dark:hover:text-white dark:hover:bg-gray-700 cursor-pointer">
|
||||
Source Code
|
||||
Guide
|
||||
</div>
|
||||
<div class="px-4 py-2 dark:text-white hover:text-blue-300 dark:hover:text-white dark:hover:bg-gray-700 cursor-pointer">
|
||||
Guide
|
||||
Code
|
||||
</div>
|
||||
<div class="px-4 py-2 dark:text-white hover:text-blue-300 dark:hover:text-white dark:hover:bg-gray-700 cursor-pointer">
|
||||
About
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-grow flex flex-col items-center justify-center w-full">
|
||||
<div class="flex flex-col items-center justify-center bg-white dark:bg-gray-900 gap-8 p-12 rounded-xl border-gray-200 shadow w-1/3">
|
||||
<div v-if="!fileUploaded" class="flex-grow flex flex-col items-center justify-center w-full">
|
||||
<div class="flex flex-col items-center justify-center bg-white dark:bg-gray-900 gap-8 p-12 rounded-xl border-gray-200 shadow w-[500px]">
|
||||
<div class="space-y-3 text-center">
|
||||
<div class="text-3xl font-semibold text-gray-800 dark:text-gray-100">
|
||||
VisualTREE
|
||||
@@ -32,7 +47,7 @@ import Input from './components/Input.vue'
|
||||
<a class="text-blue-300" href="https://linux.die.net/man/1/tree">tree</a> command.
|
||||
</div>
|
||||
</div>
|
||||
<Input />
|
||||
<Input @file-upload="fileChanged"/>
|
||||
<div class="space-y-4">
|
||||
<div class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
Example of a valid tree command:
|
||||
@@ -48,6 +63,42 @@ import Input from './components/Input.vue'
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex-grow flex flex-col items-center justify-start w-full">
|
||||
<div class="text-white flex items-center justify-center w-full px-12">
|
||||
<div class="w-full space-y-4">
|
||||
<div v-if="fileInfo" class="text-center">
|
||||
<div class="flex items-center justify-center gap-4 text-sm">
|
||||
<div class="flex items-center gap-2 bg-gray-900 px-4 py-2 rounded cursor-pointer"
|
||||
@click="fileUploaded = false">
|
||||
<div class="text-gray-200" >
|
||||
Upload another file
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 bg-gray-900 px-4 py-2 rounded">
|
||||
<div class="font-medium text-gray-500">
|
||||
Number of directories:
|
||||
</div>
|
||||
<span class="text-gray-400">
|
||||
{{ fileInfo.directories }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 bg-gray-900 px-4 py-2 rounded">
|
||||
<div class="font-medium text-gray-500">
|
||||
Number of files:
|
||||
</div>
|
||||
<span class="text-gray-400">
|
||||
{{ fileInfo.files }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="fileData" class="bg-gray-900 p-10 rounded-lg text-center">
|
||||
<Node :node="fileData" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -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>
|
||||
@@ -2,3 +2,26 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
.node-list > .node {
|
||||
@apply ml-5;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
@apply bg-transparent w-2;
|
||||
}
|
||||
|
||||
/* Track */
|
||||
::-webkit-scrollbar-track {
|
||||
@apply bg-gray-900;
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
::-webkit-scrollbar-thumb {
|
||||
@apply bg-gray-800 rounded;
|
||||
}
|
||||
|
||||
/* Handle on hover */
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
@apply bg-gray-700 rounded;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user