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" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>VisualTREE</title>
|
<title>VisualTREE</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body class="overflow-y-scroll">
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
65
src/App.vue
65
src/App.vue
@@ -1,28 +1,43 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
import Input from './components/Input.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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="bg-black">
|
<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="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="p-10 w-full text-center flex items-center justify-center">
|
<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="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">
|
<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
|
Home
|
||||||
</div>
|
</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">
|
<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>
|
||||||
<div class="px-4 py-2 dark:text-white hover:text-blue-300 dark:hover:text-white dark:hover:bg-gray-700 cursor-pointer">
|
<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>
|
||||||
<div class="px-4 py-2 dark:text-white hover:text-blue-300 dark:hover:text-white dark:hover:bg-gray-700 cursor-pointer">
|
<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
|
About
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-grow flex flex-col items-center justify-center w-full">
|
<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-1/3">
|
<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="space-y-3 text-center">
|
||||||
<div class="text-3xl font-semibold text-gray-800 dark:text-gray-100">
|
<div class="text-3xl font-semibold text-gray-800 dark:text-gray-100">
|
||||||
VisualTREE
|
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.
|
<a class="text-blue-300" href="https://linux.die.net/man/1/tree">tree</a> command.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Input />
|
<Input @file-upload="fileChanged"/>
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div class="text-gray-500 dark:text-gray-400 text-sm">
|
<div class="text-gray-500 dark:text-gray-400 text-sm">
|
||||||
Example of a valid tree command:
|
Example of a valid tree command:
|
||||||
@@ -48,6 +63,42 @@ import Input from './components/Input.vue'
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,10 +1,25 @@
|
|||||||
<script setup>
|
<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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<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">
|
<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>
|
</label>
|
||||||
|
|||||||
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 components;
|
||||||
@tailwind utilities;
|
@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