summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2017-12-24 17:19:24 +0100
committertomsmeding <tom.smeding@gmail.com>2017-12-24 17:19:24 +0100
commit6fbce51f49502c5ff5f45cef9e58973fa0f3a90c (patch)
tree4753eac41ec161a118f329c5284dc4e3ecd2d3e2
parent77d73b37116c44a13962cd1676ea457c37d7cf96 (diff)
Add 'save' module
-rw-r--r--modules/save/index.html41
-rw-r--r--modules/save/read.html131
-rw-r--r--modules/save/save.js84
3 files changed, 256 insertions, 0 deletions
diff --git a/modules/save/index.html b/modules/save/index.html
new file mode 100644
index 0000000..d8c55ca
--- /dev/null
+++ b/modules/save/index.html
@@ -0,0 +1,41 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Save</title>
+<script>
+function doSave(){
+ var text=document.getElementById("text").value.trim();
+ if(text==""){
+ alert("Please enter some text");
+ return;
+ }
+
+ var xhr=new XMLHttpRequest();
+ xhr.onreadystatechange=function(){
+ if(xhr.readyState==4){
+ if(xhr.status!=200){
+ alert("Error saving text\n"+xhr.responseText);
+ } else {
+ alert("Successfully saved!")
+ document.getElementById("text").value="";
+ }
+ }
+ };
+ xhr.open("POST","/save");
+ xhr.send(text);
+}
+</script>
+<style>
+body {
+ font-family: sans-serif;
+}
+</style>
+</head>
+<body>
+<h2>Save some text for Tom</h2>
+<textarea id="text" style="width:500px;height:100px"></textarea><br>
+<br>
+<input type="button" value="Save" onclick="doSave()">
+</body>
+</html>
diff --git a/modules/save/read.html b/modules/save/read.html
new file mode 100644
index 0000000..c359dd5
--- /dev/null
+++ b/modules/save/read.html
@@ -0,0 +1,131 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Save: Read</title>
+<script>
+var currentFname=null;
+
+function populateList(arr){
+ var ul=document.getElementById("ul");
+ ul.innerHTML="";
+
+ if(arr.length==0){
+ document.getElementById("nosaves").classList.remove("invisible");
+ return;
+ }
+ document.getElementById("nosaves").classList.add("invisible");
+
+ for(var i=0;i<arr.length;i++){
+ var li=document.createElement("li");
+ var a=document.createElement("a");
+ a.appendChild(document.createTextNode(arr[i]));
+ a.href="javascript:void 0";
+ a.addEventListener("click",(function(i,li){return function(){
+ var xhr=new XMLHttpRequest();
+ xhr.onreadystatechange=function(){
+ if(xhr.readyState==4){
+ if(xhr.status!=200){
+ alert("Error reading save '"+arr[i]+"'\n"+xhr.responseText);
+ } else {
+ var l=ul.getElementsByClassName("selected");
+ for(var i=0;i<l.length;i++)l[i].classList.remove("selected");
+ li.classList.add("selected");
+ displaySave(arr[i],xhr.responseText);
+ }
+ }
+ };
+ xhr.open("GET","/save/read/file/"+encodeURIComponent(arr[i]));
+ xhr.send();
+ };})(i,li));
+ li.appendChild(a);
+ ul.appendChild(li);
+ }
+}
+
+function displaySave(fname,text){
+ var e;
+ e=document.getElementById("filename");
+ e.innerHTML=""; e.appendChild(document.createTextNode(fname));
+
+ e=document.getElementById("contents");
+ e.innerHTML=""; e.appendChild(document.createTextNode(text));
+
+ document.getElementById("container").classList.remove("invisible");
+
+ currentFname=fname;
+}
+
+function deleteCurrent(){
+ if(!currentFname){
+ alert("No save selected");
+ return;
+ }
+
+ if(!confirm("Really delete this save?"))return;
+
+ var xhr=new XMLHttpRequest();
+ xhr.onreadystatechange=function(){
+ if(xhr.readyState==4){
+ if(xhr.status!=200){
+ alert("Error deleting saves\n"+xhr.responseText);
+ } else {
+ currentFname=null;
+ document.getElementById("container").classList.add("invisible");
+ loadSaves();
+ }
+ }
+ };
+ xhr.open("DELETE","/save/read/file/"+encodeURIComponent(currentFname));
+ xhr.send();
+}
+
+function loadSaves(){
+ var xhr=new XMLHttpRequest();
+ xhr.onreadystatechange=function(){
+ if(xhr.readyState==4){
+ if(xhr.status!=200){
+ alert("Error listing saves\n"+xhr.responseText);
+ } else {
+ populateList(JSON.parse(xhr.responseText));
+ }
+ }
+ };
+ xhr.open("GET","/save/read/files");
+ xhr.send();
+}
+
+window.addEventListener("load",function(){
+ loadSaves();
+});
+</script>
+<style>
+body {
+ font-family: sans-serif;
+ font-size: 16px;
+}
+#contents {
+ border: 1px gray solid;
+ padding: 5px;
+ display: inline-block;
+}
+li.selected {
+ font-weight: bold;
+}
+.invisible {
+ display: none;
+}
+</style>
+</head>
+<body>
+<h2>Save: Read</h2>
+<div id="nosaves"><i>No saves found!</i></div>
+<ul id="ul"></ul>
+<br>
+<div id="container" class="invisible">
+ <b id="filename"></b><br>
+ <a href="javascript:void 0" onclick="deleteCurrent()">Delete</a><br>
+ <pre id="contents"></pre>
+</div>
+</body>
+</html>
diff --git a/modules/save/save.js b/modules/save/save.js
new file mode 100644
index 0000000..d64e66e
--- /dev/null
+++ b/modules/save/save.js
@@ -0,0 +1,84 @@
+var cmn=require("../$common.js"),
+ fs=require("fs"),
+ mkdirp=require("mkdirp");
+
+var moddir;
+var directory;
+
+var filenameRegex=/[^a-zA-Z0-9._-]/g;
+
+function pad(s,n){
+ s=s+"";
+ var p="";
+ while(s.length+p.length<n)p+="0";
+ return p+s;
+}
+
+function makefilename(){
+ var d=new Date();
+ var s=[
+ pad(d.getFullYear(),4), pad(d.getMonth()+1,2), pad(d.getDate(),2),
+ pad(d.getHours(),2), pad(d.getMinutes(),2), pad(d.getSeconds(),2),
+ pad(d.getMilliseconds(),3)
+ ].join("-");
+ return s+".txt";
+}
+
+module.exports=function(app,io,_moddir){
+ moddir=_moddir;
+ directory=moddir+"/saves";
+
+ mkdirp.sync(directory);
+
+ app.get("/save",function(req,res){
+ res.sendFile(moddir+"/index.html");
+ });
+ app.post("/save",function(req,res){
+ var s=req.body.trim();
+ if(s=="")res.status(400).send("No text sent");
+ fs.writeFile(directory+"/"+makefilename(),s,function(err){
+ if(err){
+ console.log(err);
+ res.status(500).send("An error occurred");
+ return;
+ }
+ res.send();
+ });
+ });
+
+ app.all(["/save/read","/save/read/*"],cmn.authgen());
+
+ app.get("/save/read",function(req,res){
+ res.sendFile(moddir+"/read.html");
+ });
+ app.get("/save/read/files",function(req,res){
+ fs.readdir(directory,function(err,files){
+ if(err){
+ console.log(err);
+ res.status(500).send(err);
+ return;
+ }
+ res.send(JSON.stringify(files));
+ });
+ });
+ app.get("/save/read/file/:fname",function(req,res){
+ var fname=req.params.fname.replace(filenameRegex,"");
+ fs.readFile(directory+"/"+fname,function(err,text){
+ if(err){
+ res.status(404).send("File not found");
+ return;
+ }
+ res.send(text);
+ });
+ });
+ app.delete("/save/read/file/:fname",function(req,res){
+ var fname=req.params.fname.replace(filenameRegex,"");
+ fs.unlink(directory+"/"+fname,function(err){
+ if(err){
+ res.status(404).send("File not found");
+ return;
+ }
+ res.send();
+ });
+ });
+};