mirror of
https://github.com/krateng/maloja.git
synced 2023-08-10 21:12:55 +03:00
Modularized Javascript
This commit is contained in:
parent
3f22d6bc75
commit
011b6f6d91
23
database.py
23
database.py
@ -670,17 +670,20 @@ def issues():
|
||||
@dbserver.post("/importrules")
|
||||
def import_rulemodule():
|
||||
keys = FormsDict.decode(request.forms)
|
||||
filename = keys.get("filename")
|
||||
remove = keys.get("remove") is not None
|
||||
validchars = "'-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
filename = "".join(c for c in filename if c in validchars)
|
||||
apikey = keys.pop("key",None)
|
||||
|
||||
if remove:
|
||||
log("Deactivating predefined rulefile " + filename)
|
||||
os.remove("rules/" + filename + ".tsv")
|
||||
else:
|
||||
log("Importing predefined rulefile " + filename)
|
||||
os.symlink("predefined/" + filename + ".tsv","rules/" + filename + ".tsv")
|
||||
if (checkAPIkey(apikey)):
|
||||
filename = keys.get("filename")
|
||||
remove = keys.get("remove") is not None
|
||||
validchars = "-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
filename = "".join(c for c in filename if c in validchars)
|
||||
|
||||
if remove:
|
||||
log("Deactivating predefined rulefile " + filename)
|
||||
os.remove("rules/" + filename + ".tsv")
|
||||
else:
|
||||
log("Importing predefined rulefile " + filename)
|
||||
os.symlink("predefined/" + filename + ".tsv","rules/" + filename + ".tsv")
|
||||
|
||||
|
||||
|
||||
|
@ -1,86 +1,3 @@
|
||||
<meta name="description" content='Maloja is a self-hosted music scrobble server.' />
|
||||
|
||||
|
||||
<link rel="stylesheet" href="maloja.css" />
|
||||
|
||||
<script>
|
||||
function search(searchfield) {
|
||||
txt = searchfield.value;
|
||||
if (txt == "") {
|
||||
reallyclear()
|
||||
}
|
||||
else {
|
||||
xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = searchresult
|
||||
xhttp.open("GET","/db/search?max=5&query=" + encodeURIComponent(txt), true);
|
||||
xhttp.send();
|
||||
}
|
||||
}
|
||||
function searchresult() {
|
||||
if (this.readyState == 4 && this.status == 200 && document.getElementById("searchinput").value != "") {
|
||||
// checking if field is empty in case we get an old result coming in that would overwrite our cleared result window
|
||||
result = JSON.parse(this.responseText);
|
||||
artists = result["artists"].slice(0,5)
|
||||
tracks = result["tracks"].slice(0,5)
|
||||
html = `<div class="searchresults">
|
||||
<span>Artists</span>
|
||||
<table class="searchresults_artists">`
|
||||
|
||||
for (var i=0;i<artists.length;i++) {
|
||||
name = artists[i];
|
||||
uristr = "artist=" + encodeURIComponent(name);
|
||||
uristr = uristr.replace("'","\\'");
|
||||
image = "/image?" + uristr;
|
||||
link = "/artist?" + uristr;
|
||||
|
||||
html += `<tr onclick="goto('` + link + `')">
|
||||
<td class="image" style="background-image:url('` + image + `');"></td>
|
||||
<td>
|
||||
<span>` + name + `</span><br/>
|
||||
</td>
|
||||
</tr>`
|
||||
}
|
||||
|
||||
html += `</table>
|
||||
<br/><br/>
|
||||
<span>Tracks</span>
|
||||
<table class="searchresults_tracks">`
|
||||
|
||||
for (var i=0;i<tracks.length;i++) {
|
||||
|
||||
artists = tracks[i]["artists"].join(", ");
|
||||
title = tracks[i]["title"];
|
||||
uristr = "title=" + encodeURIComponent(title) + "&" + tracks[i]["artists"].map(x => "artist=" + encodeURIComponent(x)).join("&");
|
||||
uristr = uristr.replace("'","\\'");
|
||||
image = "/image?" + uristr;
|
||||
link = "/track?" + uristr;
|
||||
|
||||
html += `<tr onclick="goto('` + link + `')">
|
||||
<td class="image" style="background-image:url('` + image + `');"></td>
|
||||
<td>
|
||||
<span>` + artists + `</span><br/>
|
||||
<span>` + title + `</span>
|
||||
</td>
|
||||
</tr>`
|
||||
|
||||
}
|
||||
|
||||
html += `</table>
|
||||
</div>`
|
||||
|
||||
|
||||
document.getElementById("resultwrap").innerHTML = html;
|
||||
}
|
||||
}
|
||||
|
||||
function clearresults() {
|
||||
window.setTimeout(reallyclear,500)
|
||||
}
|
||||
function reallyclear() {
|
||||
document.getElementById("resultwrap").innerHTML = "";
|
||||
}
|
||||
|
||||
function goto(link) {
|
||||
window.location = link
|
||||
}
|
||||
</script>
|
||||
<script src="javascript/search.js"></script>
|
||||
|
@ -4,17 +4,18 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Maloja - Issues</title>
|
||||
<script src="javascript/cookies.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<body onload="insertAPIKeyFromCookie()">
|
||||
<table class="top_info">
|
||||
<tr>
|
||||
|
||||
|
||||
<td class="text">
|
||||
<h1>Possible Issues</h1><br/>
|
||||
<span>with your library</span>
|
||||
<p class="stats">KEY_ISSUES Issues</p>
|
||||
|
||||
|
||||
<p>Maloja can identify possible problems with consistency or redundancy in your library. After making any changes, you should <a class="textlink" onclick='fullrebuild()'>rebuild your library</a>.<br/>
|
||||
Your API key is required to make any changes to the server: <input id='apikey' onchange='checkAPIkey()' style='width:300px;'/></p>
|
||||
</td>
|
||||
@ -22,21 +23,12 @@
|
||||
</table>
|
||||
|
||||
KEY_ISSUESLIST
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
cookies = decodeURIComponent(document.cookie).split(';');
|
||||
for(var i = 0; i <cookies.length; i++) {
|
||||
if (cookies[i].startsWith("apikey=")) {
|
||||
document.getElementById("apikey").value = cookies[i].replace("apikey=","")
|
||||
checkAPIkey()
|
||||
}
|
||||
}
|
||||
|
||||
apikeycorrect = false;
|
||||
|
||||
|
||||
|
||||
function newrule() {
|
||||
if (apikeycorrect) {
|
||||
keys = ""
|
||||
@ -46,8 +38,8 @@
|
||||
apikey = document.getElementById("apikey").value
|
||||
keys += "key=" + encodeURIComponent(apikey)
|
||||
console.log(keys)
|
||||
|
||||
|
||||
|
||||
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.open("POST","/db/newrule?", true);
|
||||
xhttp.send(keys);
|
||||
@ -56,47 +48,19 @@
|
||||
line.parentNode.removeChild(line)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function fullrebuild() {
|
||||
if (apikeycorrect) {
|
||||
apikey = document.getElementById("apikey").value
|
||||
|
||||
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.open("POST","/db/rebuild", true);
|
||||
xhttp.send("key=" + encodeURIComponent(apikey))
|
||||
window.location = "/wait";
|
||||
window.location = "/wait";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function saveAPIkey() {
|
||||
key = document.getElementById("apikey").value
|
||||
document.cookie = "apikey=" + encodeURIComponent(key)
|
||||
}
|
||||
|
||||
function checkAPIkey() {
|
||||
saveAPIkey()
|
||||
url = "/db/test?key=" + document.getElementById("apikey").value
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4 && (this.status == 204 || this.status == 205)) {
|
||||
document.getElementById("apikey").style.backgroundColor = "lawngreen"
|
||||
apikeycorrect = true
|
||||
}
|
||||
else {
|
||||
document.getElementById("apikey").style.backgroundColor = "red"
|
||||
apikeycorrect = false
|
||||
}
|
||||
};
|
||||
try {
|
||||
xhttp.open("GET",url,true);
|
||||
xhttp.send();
|
||||
}
|
||||
catch (e) {
|
||||
document.getElementById("apikey").style.backgroundColor = "red"
|
||||
apikeycorrect = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</html>
|
||||
|
44
website/javascript/cookies.js
Normal file
44
website/javascript/cookies.js
Normal file
@ -0,0 +1,44 @@
|
||||
apikeycorrect = false;
|
||||
|
||||
function insertAPIKeyFromCookie() {
|
||||
cookies = decodeURIComponent(document.cookie).split(';');
|
||||
for(var i = 0; i <cookies.length; i++) {
|
||||
cookies[i] = cookies[i].trim()
|
||||
if (cookies[i].startsWith("apikey=")) {
|
||||
document.getElementById("apikey").value = cookies[i].replace("apikey=","")
|
||||
checkAPIkey()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function saveAPIkey() {
|
||||
key = document.getElementById("apikey").value
|
||||
document.cookie = "apikey=" + encodeURIComponent(key)
|
||||
}
|
||||
|
||||
|
||||
|
||||
function checkAPIkey() {
|
||||
saveAPIkey()
|
||||
url = "/db/test?key=" + document.getElementById("apikey").value
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4 && (this.status == 204 || this.status == 205)) {
|
||||
document.getElementById("apikey").style.backgroundColor = "lawngreen"
|
||||
apikeycorrect = true
|
||||
}
|
||||
else {
|
||||
document.getElementById("apikey").style.backgroundColor = "red"
|
||||
apikeycorrect = false
|
||||
}
|
||||
};
|
||||
try {
|
||||
xhttp.open("GET",url,true);
|
||||
xhttp.send();
|
||||
}
|
||||
catch (e) {
|
||||
document.getElementById("apikey").style.backgroundColor = "red"
|
||||
apikeycorrect = false
|
||||
}
|
||||
}
|
79
website/javascript/search.js
Normal file
79
website/javascript/search.js
Normal file
@ -0,0 +1,79 @@
|
||||
function search(searchfield) {
|
||||
txt = searchfield.value;
|
||||
if (txt == "") {
|
||||
reallyclear()
|
||||
}
|
||||
else {
|
||||
xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = searchresult
|
||||
xhttp.open("GET","/db/search?max=5&query=" + encodeURIComponent(txt), true);
|
||||
xhttp.send();
|
||||
}
|
||||
}
|
||||
function searchresult() {
|
||||
if (this.readyState == 4 && this.status == 200 && document.getElementById("searchinput").value != "") {
|
||||
// checking if field is empty in case we get an old result coming in that would overwrite our cleared result window
|
||||
result = JSON.parse(this.responseText);
|
||||
artists = result["artists"].slice(0,5)
|
||||
tracks = result["tracks"].slice(0,5)
|
||||
html = `<div class="searchresults">
|
||||
<span>Artists</span>
|
||||
<table class="searchresults_artists">`
|
||||
|
||||
for (var i=0;i<artists.length;i++) {
|
||||
name = artists[i];
|
||||
uristr = "artist=" + encodeURIComponent(name);
|
||||
uristr = uristr.replace("'","\\'");
|
||||
image = "/image?" + uristr;
|
||||
link = "/artist?" + uristr;
|
||||
|
||||
html += `<tr onclick="goto('` + link + `')">
|
||||
<td class="image" style="background-image:url('` + image + `');"></td>
|
||||
<td>
|
||||
<span>` + name + `</span><br/>
|
||||
</td>
|
||||
</tr>`
|
||||
}
|
||||
|
||||
html += `</table>
|
||||
<br/><br/>
|
||||
<span>Tracks</span>
|
||||
<table class="searchresults_tracks">`
|
||||
|
||||
for (var i=0;i<tracks.length;i++) {
|
||||
|
||||
artists = tracks[i]["artists"].join(", ");
|
||||
title = tracks[i]["title"];
|
||||
uristr = "title=" + encodeURIComponent(title) + "&" + tracks[i]["artists"].map(x => "artist=" + encodeURIComponent(x)).join("&");
|
||||
uristr = uristr.replace("'","\\'");
|
||||
image = "/image?" + uristr;
|
||||
link = "/track?" + uristr;
|
||||
|
||||
html += `<tr onclick="goto('` + link + `')">
|
||||
<td class="image" style="background-image:url('` + image + `');"></td>
|
||||
<td>
|
||||
<span>` + artists + `</span><br/>
|
||||
<span>` + title + `</span>
|
||||
</td>
|
||||
</tr>`
|
||||
|
||||
}
|
||||
|
||||
html += `</table>
|
||||
</div>`
|
||||
|
||||
|
||||
document.getElementById("resultwrap").innerHTML = html;
|
||||
}
|
||||
}
|
||||
|
||||
function clearresults() {
|
||||
window.setTimeout(reallyclear,500)
|
||||
}
|
||||
function reallyclear() {
|
||||
document.getElementById("resultwrap").innerHTML = "";
|
||||
}
|
||||
|
||||
function goto(link) {
|
||||
window.location = link
|
||||
}
|
@ -4,8 +4,11 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Maloja - Setup</title>
|
||||
<script src="javascript/cookies.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
function replaceurls() {
|
||||
url = window.location.origin
|
||||
s = document.getElementsByName("serverurl")
|
||||
@ -20,26 +23,34 @@
|
||||
}
|
||||
|
||||
function activateRuleModule(e,filename) {
|
||||
keys = "filename=" + encodeURIComponent(filename)
|
||||
if (apikeycorrect) {
|
||||
keys = "filename=" + encodeURIComponent(filename)
|
||||
apikey = document.getElementById("apikey").value
|
||||
keys += "&key=" + encodeURIComponent(apikey)
|
||||
console.log(keys)
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.open("POST","/db/importrules", true);
|
||||
xhttp.send(keys);
|
||||
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.open("POST","/db/importrules", true);
|
||||
xhttp.send(keys);
|
||||
|
||||
e.innerHTML = e.innerHTML.replace("Add","Remove")
|
||||
e.getAttributeNode("onclick").value = e.getAttribute("onclick").replace("activate","deactivate")
|
||||
/* Nobody ever look at this code please */
|
||||
e.innerHTML = e.innerHTML.replace("Add","Remove")
|
||||
e.getAttributeNode("onclick").value = e.getAttribute("onclick").replace("activate","deactivate")
|
||||
/* Nobody ever look at this code please */
|
||||
}
|
||||
}
|
||||
|
||||
function deactivateRuleModule(e,filename) {
|
||||
keys = "remove&filename=" + encodeURIComponent(filename)
|
||||
if (apikeycorrect) {
|
||||
keys = "remove&filename=" + encodeURIComponent(filename)
|
||||
apikey = document.getElementById("apikey").value
|
||||
keys += "&key=" + encodeURIComponent(apikey)
|
||||
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.open("POST","/db/importrules", true);
|
||||
xhttp.send(keys);
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.open("POST","/db/importrules", true);
|
||||
xhttp.send(keys);
|
||||
|
||||
e.innerHTML = e.innerHTML.replace("Remove","Add")
|
||||
e.getAttributeNode("onclick").value = e.getAttribute("onclick").replace("deactivate","activate")
|
||||
e.innerHTML = e.innerHTML.replace("Remove","Add")
|
||||
e.getAttributeNode("onclick").value = e.getAttribute("onclick").replace("deactivate","activate")
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -53,7 +64,7 @@
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="replace()">
|
||||
<body onload="replace();insertAPIKeyFromCookie()">
|
||||
<table class="top_info">
|
||||
<tr>
|
||||
<td class="image">
|
||||
@ -99,7 +110,11 @@
|
||||
After you've scrobbled for a bit, you might want to check the <a class="textlink" href="/issues">Issues page</a> to see if you need to set up some rules. You can also manually add rules in your server's "rules" directory - just add your own .tsv file and read the instructions on how to declare a rule.
|
||||
<br/><br/>
|
||||
|
||||
You can also set up some predefined rulesets right away!
|
||||
You can also set up some predefined rulesets right away! Enter your API key and click the buttons.
|
||||
<br/>
|
||||
API Key:
|
||||
<input id='apikey' onchange='checkAPIkey()' style='width:300px;'/>
|
||||
|
||||
<br/><br/>
|
||||
KEY_PREDEFINED_RULESETS
|
||||
|
||||
@ -117,4 +132,6 @@
|
||||
Done! Visit <a class="textlink" href="/"><span name="serverurl">yourserver.tld</span></a> (or your public / proxy URL) to look at your overview page. Almost everything is clickable!
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
</html>
|
||||
|
@ -6,9 +6,21 @@ def instructions(keys):
|
||||
|
||||
html += "<tr><th></th><th>Module</th><th>Author</th><th>Description</th></tr>"
|
||||
|
||||
|
||||
validchars = "-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
for f in os.listdir("rules/predefined"):
|
||||
if f.endswith(".tsv"):
|
||||
|
||||
rawf = f.replace(".tsv","")
|
||||
valid = True
|
||||
for char in rawf:
|
||||
if char not in validchars:
|
||||
valid = False
|
||||
break # don't even show up invalid filenames
|
||||
|
||||
if not valid: continue
|
||||
if not "_" in rawf: continue
|
||||
|
||||
try:
|
||||
with open("rules/predefined/" + f) as tsvfile:
|
||||
line1 = tsvfile.readline()
|
||||
@ -16,21 +28,21 @@ def instructions(keys):
|
||||
|
||||
if "# NAME: " in line1:
|
||||
name = line1.replace("# NAME: ","")
|
||||
else: name = f
|
||||
else: name = rawf.split("_")[1]
|
||||
if "# DESC: " in line2:
|
||||
desc = line2.replace("# DESC: ","")
|
||||
else: desc = ""
|
||||
|
||||
author = f.split("_")[0]
|
||||
author = rawf.split("_")[0]
|
||||
except:
|
||||
continue
|
||||
|
||||
html += "<tr>"
|
||||
|
||||
if os.path.exists("rules/" + f):
|
||||
html += "<td class='interaction' onclick=deactivateRuleModule(this,'" + f.replace(".tsv","") + "')><a class='textlink'>Remove:</a></td>"
|
||||
html += "<td class='interaction' onclick=deactivateRuleModule(this,'" + rawf + "')><a class='textlink'>Remove:</a></td>"
|
||||
else:
|
||||
html += "<td class='interaction' onclick=activateRuleModule(this,'" + f.replace(".tsv","") + "')><a class='textlink'>Add:</a></td>"
|
||||
html += "<td class='interaction' onclick=activateRuleModule(this,'" + rawf + "')><a class='textlink'>Add:</a></td>"
|
||||
html += "<td>" + name + "</td>"
|
||||
html += "<td>" + author + "</td>"
|
||||
html += "<td>" + desc + "</td>"
|
||||
|
Loading…
Reference in New Issue
Block a user