Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -15,82 +15,79 @@ HTML_TEMPLATE = """
|
|
15 |
<html lang="en">
|
16 |
<head>
|
17 |
<meta charset="UTF-8">
|
18 |
-
<title>
|
19 |
<style>
|
20 |
body {
|
21 |
-
margin: 0;
|
22 |
font-family: 'Segoe UI', sans-serif;
|
23 |
-
background-color: #
|
24 |
-
color: #
|
|
|
25 |
}
|
26 |
header {
|
|
|
27 |
padding: 16px;
|
28 |
-
background-color: #202124;
|
29 |
font-size: 20px;
|
30 |
font-weight: bold;
|
|
|
31 |
}
|
32 |
.container {
|
33 |
padding: 20px;
|
34 |
}
|
|
|
|
|
|
|
35 |
.folder {
|
36 |
color: #8ab4f8;
|
37 |
cursor: pointer;
|
38 |
-
|
39 |
}
|
40 |
-
.file {
|
41 |
-
margin-left: 20px;
|
42 |
-
margin: 4px 0;
|
43 |
-
}
|
44 |
-
a {
|
45 |
color: #9cdcfe;
|
46 |
text-decoration: none;
|
47 |
margin-left: 10px;
|
48 |
}
|
49 |
-
a:hover {
|
50 |
text-decoration: underline;
|
51 |
}
|
52 |
.upload-box {
|
53 |
margin-top: 30px;
|
54 |
-
background: #
|
55 |
padding: 20px;
|
56 |
-
border-radius:
|
57 |
}
|
58 |
input[type="file"], input[type="text"], input[type="submit"] {
|
59 |
-
margin-top: 10px;
|
60 |
padding: 8px;
|
|
|
61 |
font-size: 14px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
}
|
63 |
</style>
|
64 |
<script>
|
65 |
-
function
|
66 |
-
|
67 |
-
|
68 |
-
el.style.display = "block";
|
69 |
-
} else {
|
70 |
-
el.style.display = "none";
|
71 |
-
}
|
72 |
}
|
73 |
</script>
|
74 |
</head>
|
75 |
<body>
|
76 |
<header>π Hugging Face Drive β {{ repo_id }}</header>
|
77 |
<div class="container">
|
78 |
-
{
|
79 |
-
<div class="folder" onclick="toggleFolder('{{ loop.index }}')">π {{ folder }}</div>
|
80 |
-
<div id="{{ loop.index }}" style="display:none; padding-left: 20px;">
|
81 |
-
{% for file in contents %}
|
82 |
-
<div class="file">
|
83 |
-
{{ file }}
|
84 |
-
<a href="{{ url_for('download_file', filename=folder + '/' + file) }}">Download</a>
|
85 |
-
</div>
|
86 |
-
{% endfor %}
|
87 |
-
</div>
|
88 |
-
{% endfor %}
|
89 |
|
90 |
<div class="upload-box">
|
91 |
<h3>Upload File</h3>
|
92 |
<form method="POST" action="/upload" enctype="multipart/form-data">
|
93 |
-
Folder path (optional): <input type="text" name="folder" placeholder="e.g.
|
94 |
File: <input type="file" name="file"><br>
|
95 |
<input type="submit" value="Upload">
|
96 |
</form>
|
@@ -100,21 +97,37 @@ HTML_TEMPLATE = """
|
|
100 |
</html>
|
101 |
"""
|
102 |
|
103 |
-
def
|
104 |
tree = {}
|
105 |
-
for path in
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
return tree
|
112 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
@app.route("/")
|
114 |
def index():
|
115 |
files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset", token=TOKEN)
|
116 |
-
|
117 |
-
|
|
|
118 |
|
119 |
@app.route("/download/<path:filename>")
|
120 |
def download_file(filename):
|
@@ -135,7 +148,6 @@ def download_file(filename):
|
|
135 |
def upload():
|
136 |
file = request.files["file"]
|
137 |
folder = request.form.get("folder", "").strip().strip("/")
|
138 |
-
|
139 |
if file:
|
140 |
filename = file.filename
|
141 |
path_in_repo = f"{folder}/{filename}" if folder else filename
|
|
|
15 |
<html lang="en">
|
16 |
<head>
|
17 |
<meta charset="UTF-8">
|
18 |
+
<title>{{ repo_id }} - Drive</title>
|
19 |
<style>
|
20 |
body {
|
|
|
21 |
font-family: 'Segoe UI', sans-serif;
|
22 |
+
background-color: #121212;
|
23 |
+
color: #eee;
|
24 |
+
margin: 0;
|
25 |
}
|
26 |
header {
|
27 |
+
background-color: #1f1f1f;
|
28 |
padding: 16px;
|
|
|
29 |
font-size: 20px;
|
30 |
font-weight: bold;
|
31 |
+
color: #fff;
|
32 |
}
|
33 |
.container {
|
34 |
padding: 20px;
|
35 |
}
|
36 |
+
.folder, .file {
|
37 |
+
margin: 4px 0;
|
38 |
+
}
|
39 |
.folder {
|
40 |
color: #8ab4f8;
|
41 |
cursor: pointer;
|
42 |
+
user-select: none;
|
43 |
}
|
44 |
+
.file a {
|
|
|
|
|
|
|
|
|
45 |
color: #9cdcfe;
|
46 |
text-decoration: none;
|
47 |
margin-left: 10px;
|
48 |
}
|
49 |
+
.file a:hover {
|
50 |
text-decoration: underline;
|
51 |
}
|
52 |
.upload-box {
|
53 |
margin-top: 30px;
|
54 |
+
background: #222;
|
55 |
padding: 20px;
|
56 |
+
border-radius: 6px;
|
57 |
}
|
58 |
input[type="file"], input[type="text"], input[type="submit"] {
|
|
|
59 |
padding: 8px;
|
60 |
+
margin-top: 10px;
|
61 |
font-size: 14px;
|
62 |
+
background: #333;
|
63 |
+
color: #fff;
|
64 |
+
border: none;
|
65 |
+
border-radius: 4px;
|
66 |
+
}
|
67 |
+
input[type="submit"] {
|
68 |
+
background: #4caf50;
|
69 |
+
cursor: pointer;
|
70 |
+
}
|
71 |
+
.indent {
|
72 |
+
margin-left: 20px;
|
73 |
}
|
74 |
</style>
|
75 |
<script>
|
76 |
+
function toggle(id) {
|
77 |
+
let el = document.getElementById(id);
|
78 |
+
el.style.display = (el.style.display === 'none') ? 'block' : 'none';
|
|
|
|
|
|
|
|
|
79 |
}
|
80 |
</script>
|
81 |
</head>
|
82 |
<body>
|
83 |
<header>π Hugging Face Drive β {{ repo_id }}</header>
|
84 |
<div class="container">
|
85 |
+
{{ folder_html|safe }}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
|
87 |
<div class="upload-box">
|
88 |
<h3>Upload File</h3>
|
89 |
<form method="POST" action="/upload" enctype="multipart/form-data">
|
90 |
+
Folder path (optional): <input type="text" name="folder" placeholder="e.g. world_the_end/DIM1/data"><br>
|
91 |
File: <input type="file" name="file"><br>
|
92 |
<input type="submit" value="Upload">
|
93 |
</form>
|
|
|
97 |
</html>
|
98 |
"""
|
99 |
|
100 |
+
def build_tree(paths):
|
101 |
tree = {}
|
102 |
+
for path in paths:
|
103 |
+
parts = path.strip("/").split("/")
|
104 |
+
current = tree
|
105 |
+
for part in parts[:-1]:
|
106 |
+
current = current.setdefault(part, {})
|
107 |
+
current.setdefault("_files", []).append(parts[-1])
|
108 |
return tree
|
109 |
|
110 |
+
def render_tree(tree, prefix="", depth=0, idx=0):
|
111 |
+
html = ""
|
112 |
+
for name, content in tree.items():
|
113 |
+
if name == "_files":
|
114 |
+
for file in content:
|
115 |
+
full_path = f"{prefix}/{file}".strip("/")
|
116 |
+
html += f'<div class="file indent" style="margin-left:{depth * 20}px;">π {file} <a href="/download/{full_path}">Download</a></div>'
|
117 |
+
else:
|
118 |
+
folder_id = f"f{idx}"
|
119 |
+
html += f'<div class="folder" onclick="toggle(\'{folder_id}\')" style="margin-left:{depth * 20}px;">π {name}</div>'
|
120 |
+
html += f'<div id="{folder_id}" style="display:none;">'
|
121 |
+
html += render_tree(content, f"{prefix}/{name}".strip("/"), depth + 1, idx + 1)
|
122 |
+
html += '</div>'
|
123 |
+
return html
|
124 |
+
|
125 |
@app.route("/")
|
126 |
def index():
|
127 |
files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset", token=TOKEN)
|
128 |
+
tree = build_tree(files)
|
129 |
+
folder_html = render_tree(tree)
|
130 |
+
return render_template_string(HTML_TEMPLATE, repo_id=REPO_ID, folder_html=folder_html)
|
131 |
|
132 |
@app.route("/download/<path:filename>")
|
133 |
def download_file(filename):
|
|
|
148 |
def upload():
|
149 |
file = request.files["file"]
|
150 |
folder = request.form.get("folder", "").strip().strip("/")
|
|
|
151 |
if file:
|
152 |
filename = file.filename
|
153 |
path_in_repo = f"{folder}/{filename}" if folder else filename
|