Spaces:
Runtime error
Runtime error
Commit ·
bf5c835
1
Parent(s): 01ffc0c
feat :ability to drag and drop
Browse files- app/templates/upload.html +70 -7
app/templates/upload.html
CHANGED
|
@@ -53,8 +53,12 @@
|
|
| 53 |
<!-- File Input -->
|
| 54 |
<div id="file_input" style="display: none;">
|
| 55 |
<label class="block font-mono text-sm text-gray-400 mb-2">Files (Multiple allowed)</label>
|
| 56 |
-
<
|
| 57 |
-
class="
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
</div>
|
| 59 |
|
| 60 |
<!-- Link Input -->
|
|
@@ -77,18 +81,77 @@
|
|
| 77 |
</div>
|
| 78 |
|
| 79 |
<script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
function toggleInputType() {
|
| 81 |
-
const type =
|
| 82 |
-
|
| 83 |
-
const linkInput = document.getElementById('link_input');
|
| 84 |
-
|
| 85 |
if (type === 'file') {
|
| 86 |
fileInput.style.display = 'block';
|
| 87 |
linkInput.style.display = 'none';
|
| 88 |
} else if (type === 'link') {
|
| 89 |
fileInput.style.display = 'none';
|
| 90 |
linkInput.style.display = 'block';
|
|
|
|
|
|
|
|
|
|
| 91 |
}
|
| 92 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
</script>
|
| 94 |
-
{% endblock %}
|
|
|
|
| 53 |
<!-- File Input -->
|
| 54 |
<div id="file_input" style="display: none;">
|
| 55 |
<label class="block font-mono text-sm text-gray-400 mb-2">Files (Multiple allowed)</label>
|
| 56 |
+
<div id="file_dropzone" class="w-full border-2 border-dashed border-white/20 bg-white/5 rounded-xl px-4 py-8 text-center transition cursor-pointer hover:border-blue-500/60 hover:bg-blue-500/5">
|
| 57 |
+
<p class="font-mono text-sm text-gray-300">Drop files here or click to browse</p>
|
| 58 |
+
<p id="selected_file_count" class="font-mono text-xs text-gray-500 mt-2">No files selected</p>
|
| 59 |
+
<input id="files" type="file" name="files" multiple
|
| 60 |
+
class="hidden w-full bg-white/5 border border-white/10 rounded-xl px-4 py-3 font-mono focus:outline-none focus:border-blue-500 transition file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0 file:bg-blue-500/20 file:text-blue-400 file:font-mono file:text-sm hover:file:bg-blue-500/30">
|
| 61 |
+
</div>
|
| 62 |
</div>
|
| 63 |
|
| 64 |
<!-- Link Input -->
|
|
|
|
| 81 |
</div>
|
| 82 |
|
| 83 |
<script>
|
| 84 |
+
const noteTypeInput = document.getElementById('note_type');
|
| 85 |
+
const fileInput = document.getElementById('file_input');
|
| 86 |
+
const linkInput = document.getElementById('link_input');
|
| 87 |
+
const dropzone = document.getElementById('file_dropzone');
|
| 88 |
+
const filesField = document.getElementById('files');
|
| 89 |
+
const fileCount = document.getElementById('selected_file_count');
|
| 90 |
+
|
| 91 |
+
function updateSelectedFileText(files) {
|
| 92 |
+
if (!files || files.length === 0) {
|
| 93 |
+
fileCount.textContent = 'No files selected';
|
| 94 |
+
return;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
fileCount.textContent = files.length === 1
|
| 98 |
+
? `Selected: ${files[0].name}`
|
| 99 |
+
: `${files.length} files selected`;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
function toggleInputType() {
|
| 103 |
+
const type = noteTypeInput.value;
|
| 104 |
+
|
|
|
|
|
|
|
| 105 |
if (type === 'file') {
|
| 106 |
fileInput.style.display = 'block';
|
| 107 |
linkInput.style.display = 'none';
|
| 108 |
} else if (type === 'link') {
|
| 109 |
fileInput.style.display = 'none';
|
| 110 |
linkInput.style.display = 'block';
|
| 111 |
+
} else {
|
| 112 |
+
fileInput.style.display = 'none';
|
| 113 |
+
linkInput.style.display = 'none';
|
| 114 |
}
|
| 115 |
}
|
| 116 |
+
|
| 117 |
+
dropzone.addEventListener('click', () => filesField.click());
|
| 118 |
+
|
| 119 |
+
filesField.addEventListener('change', () => {
|
| 120 |
+
updateSelectedFileText(filesField.files);
|
| 121 |
+
});
|
| 122 |
+
|
| 123 |
+
['dragenter', 'dragover'].forEach((eventName) => {
|
| 124 |
+
dropzone.addEventListener(eventName, (event) => {
|
| 125 |
+
event.preventDefault();
|
| 126 |
+
event.stopPropagation();
|
| 127 |
+
dropzone.classList.add('border-blue-500', 'bg-blue-500/10');
|
| 128 |
+
});
|
| 129 |
+
});
|
| 130 |
+
|
| 131 |
+
['dragleave', 'drop'].forEach((eventName) => {
|
| 132 |
+
dropzone.addEventListener(eventName, (event) => {
|
| 133 |
+
event.preventDefault();
|
| 134 |
+
event.stopPropagation();
|
| 135 |
+
dropzone.classList.remove('border-blue-500', 'bg-blue-500/10');
|
| 136 |
+
});
|
| 137 |
+
});
|
| 138 |
+
|
| 139 |
+
dropzone.addEventListener('drop', (event) => {
|
| 140 |
+
if (!event.dataTransfer || !event.dataTransfer.files.length) {
|
| 141 |
+
return;
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
try {
|
| 145 |
+
filesField.files = event.dataTransfer.files;
|
| 146 |
+
} catch (error) {
|
| 147 |
+
const dt = new DataTransfer();
|
| 148 |
+
Array.from(event.dataTransfer.files).forEach((file) => dt.items.add(file));
|
| 149 |
+
filesField.files = dt.files;
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
updateSelectedFileText(filesField.files);
|
| 153 |
+
});
|
| 154 |
+
|
| 155 |
+
toggleInputType();
|
| 156 |
</script>
|
| 157 |
+
{% endblock %}
|