home · contact · privacy
Add sorting buttons to /files view. master
authorChristian Heller <c.heller@plomlompom.de>
Tue, 18 Feb 2025 15:18:11 +0000 (16:18 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Tue, 18 Feb 2025 15:18:11 +0000 (16:18 +0100)
src/templates/files.tmpl

index c8365e76cbdba870935a7ce8207bd10234b9e310..2338cf84f121083243e2fbfce031c59c9a39de0b 100644 (file)
@@ -7,6 +7,7 @@ const PATH_FILES_JSON = "/{{page_names.files_json}}";
 const all_tags = {{showable_tags|tojson|safe}};
 var needed_tags = {{needed_tags|tojson|safe}};
 var filtered_files = [];
+var sort_key = "rel_path";
 
 function select_tag() {
   if (tags_select.selectedIndex < 1) {
@@ -45,13 +46,16 @@ function update_filter_inputs() {
   update_files_list();
 }
 
-async function update_files_list() {
-    const filter_path = encodeURIComponent(document.getElementById("input_filter_path").value);
-    let target = `${PATH_FILES_JSON}?filter_path=${filter_path}`;
-    if (document.getElementById("input_show_absent").checked) { target = `${target}&show_absent=1`; }
-    needed_tags.forEach((tag) => target = `${target}&needed_tag=${encodeURIComponent(tag)}`);
-    filtered_files = await wrapped_fetch(target).then((response) => response.json());
-    document.getElementById("files_count").textContent = `${filtered_files.length}`;
+function draw_files_table() {
+    filtered_files.sort((a, b) => {
+        let inverter = 1;
+        let _sort_key = sort_key;
+        if (sort_key[0] == '-') {
+            inverter = -1;
+            _sort_key = sort_key.substring(1);
+        }
+        return inverter * ((a[_sort_key] > b[_sort_key]) ? 1 : -1);
+    });
     const table = document.getElementById("files_table");
     Array.from(document.getElementsByClassName("file_row")).forEach((row) => row.remove());
     filtered_files.forEach((file) => {
@@ -71,14 +75,45 @@ async function update_files_list() {
     });
 }
 
+async function update_files_list() {
+    const filter_path = encodeURIComponent(document.getElementById("input_filter_path").value);
+    let target = `${PATH_FILES_JSON}?filter_path=${filter_path}`;
+    if (document.getElementById("input_show_absent").checked) { target = `${target}&show_absent=1`; }
+    needed_tags.forEach((tag) => target = `${target}&needed_tag=${encodeURIComponent(tag)}`);
+    filtered_files = await wrapped_fetch(target).then((response) => response.json());
+    document.getElementById("files_count").textContent = `${filtered_files.length}`;
+    draw_files_table();
+}
+
 function inject_all() {
     filtered_files.forEach((file) => { player_command(`inject_${file.digest}`) });
 }
 
+function sort_by(button, key) {
+    Array.from(document.getElementsByClassName("sorting")).forEach((btn_i) => {
+       if (btn_i != button) {
+           btn_i.classList.remove("sorting");
+           btn_i.classList.remove("reverse");
+       } else if (btn_i.classList.contains("sorting")) {
+           btn_i.classList.toggle("reverse");
+       }
+    });
+    button.classList.add("sorting");
+    sort_key = button.classList.contains("reverse") ? `-${key}` : key;
+    draw_files_table();
+}
+
 window.addEventListener('load', update_filter_inputs);
 {% endblock %}
 
 
+{% block css %}
+button.sorter { background-color: transparent; }
+button.sorting { background-color: white; color: black; }
+button.reverse { background-color: black; color: white; }
+{% endblock %}
+
+
 {% block body %}
 filename pattern: <input id="input_filter_path" oninput="update_files_list()"  /><br />
 show absent: <input id="input_show_absent" type="checkbox" onclick="update_files_list()" /><br />
@@ -90,6 +125,12 @@ known files (shown: <span id="files_count">?</span>):
 <button onclick="inject_all();">inject all</button>
 </p>
 <table id="files_table">
-<tr><th>size</th><th>duration</th><th>actions</th><th>tags</th><th>path</th></tr>
+<tr>
+<th><button class="sorter" onclick="sort_by(this, 'size'); ">size</button></th>
+<th><button class="sorter" onclick="sort_by(this, 'duration'); ">duration</button></th>
+<th>actions</th>
+<th>tags</th>
+<th><button class="sorter" onclick="sort_by(this, 'rel_path'); ">path</button></th>
+</tr>
 </table>
 {% endblock %}