add tree.js

This commit is contained in:
Jack Liao 2020-07-15 14:38:34 +08:00
parent c8cc23b90e
commit 29f23d5594
1 changed files with 115 additions and 0 deletions

115
src/tree.js Normal file
View File

@ -0,0 +1,115 @@
module.exports = { gen_tree_html }
function gen_tree_html (arr) {
const data = gen_tree_data(arr, is_gd_folder)
return tree_tpl(JSON.stringify(data))
}
function tree_tpl (str) {
return `<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<title>Folder Tree</title>
<link href="https://cdn.jsdelivr.net/gh/iwestlin/gd-utils/static/tree.min.css" rel="stylesheet">
</head>
<body>
<!-- source code: https://github.com/iwestlin/foldertree/blob/master/app.jsx -->
<div id="root"></div>
<script type="text/javascript">
var treedata = ${str}
</script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/iwestlin/gd-utils/static/tree.min.js"></script>
</body>
</html>`
}
function is_gd_folder (data) {
return data.mimeType === 'application/vnd.google-apps.folder'
}
function gen_tree_data (data, is_folder) {
if (!data || !data.length) return []
const folders = data.filter(is_folder)
const files = data.filter(v => !is_folder(v))
const total_size = sum(files.map(v => v.size))
const root = {
title: `/根目錄 [共${files.length} 個檔案(不包括資料夾), ${format_size(total_size)}]`,
key: data[0].parent
}
if (!folders.length) return [root]
const sub_folders = folders.filter(v => v.parent === folders[0].parent)
sub_folders.forEach(v => {
sum_files(v, data, is_folder)
count_files(v, data, is_folder)
})
sort_folders(folders, 'count')
sort_folders(sub_folders, 'count')
folders.forEach(v => {
let {name, size, count, id} = v
if (name.length > 50) name = name.slice(0, 48) + '...'
v.title = `${name} | [共${count}個檔案 ${format_size(size)}]`
})
root.children = sub_folders.map(v => gen_node(v, folders))
return [root]
}
function sort_folders (folders, type) {
if (!folders || !folders.length) return
if (type === 'size') return folders.sort((a, b) => b.size - a.size)
if (type === 'count') return folders.sort((a, b) => b.count - a.count)
}
function gen_node (v, folders) {
const {id, title, node} = v
if (node) return node
return v.node = {
title,
key: id,
children: v.children || folders.filter(vv => vv.parent === id).map(vv => gen_node(vv, folders))
}
}
function count_files (folder, arr, is_folder) {
if (folder.count) return folder.count
const children = arr.filter(v => v.parent === folder.id)
return folder.count = sum(children.map(v => {
if (is_folder(v)) return count_files(v, arr, is_folder)
return 1
}))
}
function sum_files (folder, arr, is_folder) {
if (folder.size) return folder.size
const children = arr.filter(v => v.parent === folder.id)
return folder.size = sum(children.map(v => {
if (is_folder(v)) return sum_files(v, arr, is_folder)
return v.size
}))
}
function sum (arr) {
let result = 0
for (const v of arr) {
result += Number(v) || 0
}
return result
}
function format_size (n) {
n = Number(n)
if (Number.isNaN(n)) return ''
if (n < 0) return 'invalid size'
const units = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
let flag = 0
while (n >= 1024) {
n = n / 1024
flag++
}
return n.toFixed(2) + ' ' + units[flag]
}