sortable shared files table

This commit is contained in:
Zlatin Balevsky
2019-12-13 08:04:19 +00:00
parent 8ae0a16b8a
commit d395475727
3 changed files with 113 additions and 35 deletions

View File

@@ -5,6 +5,9 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
@@ -68,9 +71,24 @@ public class FilesServlet extends HttpServlet {
fileManager.list(current, cb);
sb.append("</Files>");
} else if (section.equals("fileTable")) {
List<FilesTableEntry> entries = new ArrayList<>();
fileManager.getAllFiles().forEach(sf -> {
String comment = null;
if (sf.getComment() != null)
comment = DataUtil.readi18nString(Base64.decode(sf.getComment()));
FilesTableEntry entry = new FilesTableEntry(sf.getFile().getName(),
sf.getCachedPath(),
sf.getCachedLength(),
comment,
core.getCertificateManager().hasLocalCertificate(sf.getInfoHash()));
entries.add(entry);
});
COMPARATORS.sort(entries, req);
sb.append("<Files>");
sb.append("<Revision>").append(fileManager.getRevision()).append("</Revision>");
fileManager.getAllFiles().forEach(sf -> sharedFileToXML(sf, sb, core.getCertificateManager()));
entries.forEach(entry -> entry.toXML(sb));
sb.append("</Files>");
}
@@ -164,5 +182,47 @@ public class FilesServlet extends HttpServlet {
fileManager.comment(file, comment);
}
}
private static class FilesTableEntry {
private final String name;
private final String path;
private final long size;
private final String comment;
private final boolean certified;
FilesTableEntry(String name, String path, long size, String comment, boolean certified) {
this.name = name;
this.path = path;
this.size = size;
this.comment = comment;
this.certified = certified;
}
void toXML(StringBuilder sb) {
sb.append("<File>");
sb.append("<Name>").append(Util.escapeHTMLinXML(name)).append("</Name>");
sb.append("<Path>").append(Util.escapeHTMLinXML(path)).append("</Path>");
sb.append("<Size>").append(DataHelper.formatSize2Decimal(size, false)).append("B").append("</Size>");
if (comment != null) {
sb.append("<Comment>").append(Util.escapeHTMLinXML(comment)).append("</Comment>");
}
sb.append("<Certified>").append(certified).append("</Certified>");
sb.append("</File>");
}
}
private static final Comparator<FilesTableEntry> BY_PATH = (l, r) -> {
return l.path.compareTo(r.path);
};
private static final Comparator<FilesTableEntry> BY_SIZE = (l, r) -> {
return Long.compare(l.size, r.size);
};
private static final ColumnComparators<FilesTableEntry> COMPARATORS = new ColumnComparators<>();
static {
COMPARATORS.add("File", BY_PATH);
COMPARATORS.add("Size", BY_SIZE);
}
}

View File

@@ -1,10 +1,29 @@
class SharedFile {
constructor(name, size, comment, certified) {
constructor(name, path, size, comment, certified) {
this.name = name
this.path = path
this.size = size
this.comment = comment
this.certified = certified
}
getMapping() {
var mapping = new Map()
var unshareLink = new Link(_t("Unshare"), "unshare", [this.path])
var certifyLink = new Link(_t("Certify"), "certify", [this.path])
var certifyHtml = certifyLink.render()
if (this.certified == "true")
certifyHtml += " " + _t("Certified")
var showCommentHtml = ""
var showCommentLink = new Link(_t("Comment"), "showCommentForm", [this.path])
showCommentHtml = "<span id='comment-link-" + this.path + "'>" + showCommentLink.render() + "</span>"
showCommentHtml += "<div id='comment-" + this.path + "'></div>"
mapping.set("File", this.name + " " + unshareLink.render() + " " + certifyHtml + " " + showCommentHtml)
mapping.set("Size", this.size)
return mapping
}
}
function refreshStatus() {
@@ -27,7 +46,7 @@ function refreshStatus() {
var newRevision = xmlDoc.getElementsByTagName("Revision")[0].childNodes[0].nodeValue
var refreshDiv = document.getElementById("refresh-link")
if (newRevision > tableRevision) {
tableRevision = newRevision
tableRevision = newRevision // TODO: auto-refresh
refreshDiv.innerHTML = "<a href='#' onclick='refreshTable();return false;'>" + _t("Refresh") + "</a>"
} else
refreshDiv.innerHTML = ""
@@ -39,6 +58,14 @@ function refreshStatus() {
var tableRevision = -1
var filesByPath = new Map()
var sortKey
var sortOrder
function sort(key, order) {
sortKey = key
sortOrder = order
refreshTable()
}
function refreshTable() {
var xmlhttp = new XMLHttpRequest()
@@ -46,8 +73,7 @@ function refreshTable() {
if (this.readyState == 4 && this.status == 200) {
var xmlDoc = this.responseXML
var tableHtml = "<table><thead><tr><th>File</th><th>Size</th><th>Comment</th></tr></thead><tbody>"
var filesList = []
var files = xmlDoc.getElementsByTagName("File")
var i
for(i = 0; i < files.length; i++) {
@@ -60,37 +86,29 @@ function refreshTable() {
comment = null
var certified = files[i].getElementsByTagName("Certified")[0].childNodes[0].nodeValue
var nodeId = Base64.encode(fileName)
var newSharedFile = new SharedFile(fileName, size, comment, certified)
filesByPath.set(nodeId, newSharedFile)
var path = Base64.encode(fileName)
var newSharedFile = new SharedFile(fileName, path, size, comment, certified)
filesByPath.set(path, newSharedFile)
filesList.push(newSharedFile)
}
for (var [path, file] of filesByPath) {
var unshareLink = "<a href='#' onclick='window.unshare(\"" + path + "\");return false;'>" + _t("Unshare") + "</a>"
var certifyLink = "<a href='#' onclick='window.certify(\"" + path + "\");return false;'>" + _t("Certify") + "</a>"
var certified = ""
if (file.certified == "true")
certified = _t("Certified")
var commentLink = "<span id='comment-link-"+ path +"'>" + generateCommentLink(path) + "</span>"
tableHtml += "<tr>"
tableHtml += "<td>"+file.name+"<br/>" + unshareLink + " " + certifyLink + " " + certified + " " +
commentLink + "<div id='comment-" + path + "'></div></td>"
tableHtml += "<td>"+file.size+"</td>"
tableHtml += "<td>"+(file.comment != null)+"</td>"
tableHtml += "</tr>"
}
var newOrder
if (sortOrder == "descending")
newOrder = "ascending"
else if (sortOrder == "ascending")
newOrder = "descending"
var table = new Table(["File","Size"], "sort", sortKey, newOrder)
tableHtml += "</tbody></table>"
for (i = 0; i < filesList.length; i++) {
table.addRow(filesList[i].getMapping())
}
var tableDiv = document.getElementById("filesTable")
tableDiv.innerHTML = tableHtml
tableDiv.innerHTML = table.render()
}
}
xmlhttp.open("GET", "/MuWire/Files?section=fileTable", true)
var sortParam = "&key=" + sortKey + "&order=" + sortOrder
xmlhttp.open("GET", "/MuWire/Files?section=fileTable" + sortParam, true)
xmlhttp.send()
}
@@ -135,8 +153,11 @@ function showCommentForm(nodeId) {
function cancelComment(nodeId) {
var commentDiv = document.getElementById("comment-"+nodeId)
commentDiv.innerHTML = ""
var commentLink = new Link(_t("Comment"), "showCommentForm", [nodeId])
var linkSpan = document.getElementById("comment-link-"+nodeId)
linkSpan.innerHTML = generateCommentLink(nodeId)
linkSpan.innerHTML = commentLink.render()
}
function saveComment(fileId) {
@@ -154,10 +175,6 @@ function saveComment(fileId) {
xmlhttp.send(encodeURI("action=comment&path="+fileId+ "&comment="+comment))
}
function generateCommentLink(nodeId) {
return "<a href='#' onclick='showCommentForm(\"" + nodeId + "\");return false;'>" + _t("Comment") + "</a>"
}
function certify(path) {
var xmlhttp = new XMLHttpRequest()
xmlhttp.onreadystatechange = function() {

View File

@@ -16,6 +16,7 @@ if (viewAs == null)
<head>
<%@ include file="css.jsi"%>
<script src="js/util.js?<%=version%>" type="text/javascript"></script>
<script src="js/tables.js?<%=version%>" type="text/javascript"></script>
<% if (viewAs.equals("tree")) { %>
<script src="js/files.js?<%=version%>" type="text/javascript"></script>
<% } else { %>