@@ -23,7 +23,10 @@ var endpoints = { | |||
//Viewer files | |||
"/viewer": "viewer/index.node.js", | |||
"/viewer/script.js": "viewer/script.js", | |||
"/viewer/style.css": "viewer/style.css" | |||
"/viewer/style.css": "viewer/style.css", | |||
//API files | |||
"/api/upload": "api/upload.node.js" | |||
} | |||
var loaded = loader.load(endpoints, conf); |
@@ -1,3 +1,5 @@ | |||
var formidable = require("formidable"); | |||
function templatify(str, args) { | |||
if (args == undefined) | |||
return str; | |||
@@ -22,6 +24,19 @@ module.exports.prototype = { | |||
this.res.end(str); | |||
}, | |||
succeed: function(obj) { | |||
obj = obj || {}; | |||
obj.success = true; | |||
this.end(JSON.stringify(obj)); | |||
}, | |||
fail: function(err) { | |||
obj = obj || {}; | |||
obj.success = false; | |||
obj.error = error; | |||
this.end(JSON.stringify(obj)); | |||
}, | |||
template: function(name, args) { | |||
var str = this.templates[name]; | |||
if (!str) | |||
@@ -39,27 +54,10 @@ module.exports.prototype = { | |||
}, | |||
getPostData: function(cb) { | |||
if (this.req.method != "POST") | |||
if (this.req.method.toUpperCase() != "POST") | |||
return cb(new Error("Expected POST request, got "+this.req.method)); | |||
if (this._postData) | |||
return cb(null, this._postData); | |||
var str = ""; | |||
this.req.on("data", function(data) { | |||
str += data; | |||
}); | |||
this.req.on("end", function() { | |||
try { | |||
var obj = JSON.parse(str); | |||
} catch (err) { | |||
return cb(err); | |||
} | |||
this._postData = obj; | |||
cb(null, obj); | |||
}); | |||
var form = new formidable.IncomingForm(); | |||
form.parse(this.req, cb); | |||
} | |||
} |
@@ -25,7 +25,9 @@ exports.load = function(endpoints, conf) { | |||
res.endpoints[i] = fs.readFileSync(conf.webroot+"/"+ep, "utf8"); | |||
//If it's an HTML file, we minify it | |||
if (/\.html$/.test(ep)) { | |||
if (!conf.minify) { | |||
//Don't minify unless the conf tells us to | |||
} else if (/\.html$/.test(ep)) { | |||
res.endpoints[i] = minify.html(res.endpoints[i]); | |||
} else if (/\.js$/.test(ep)) { | |||
res.endpoints[i] = minify.js(res.endpoints[i]); |
@@ -14,6 +14,7 @@ | |||
}, | |||
"license": "GPLv2", | |||
"dependencies": { | |||
"formidable": "^1.0.17", | |||
"html-minifier": "^0.7.2", | |||
"pg": "^4.4.0", | |||
"uglify-js": "^2.4.24", |
@@ -0,0 +1,22 @@ | |||
CREATE TABLE users ( | |||
id SERIAL PRIMARY KEY, | |||
username VARCHAR(64) UNIQUE NOT NULL, | |||
pass_hash CHAR(128) NOT NULL, | |||
date_created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT NOW() | |||
) | |||
CREATE TABLE collections ( | |||
id SERIAL PRIMARY KEY, | |||
name VARCHAR(64), | |||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE | |||
) | |||
CREATE TABLE images ( | |||
id SERIAL PRIMARY KEY, | |||
name VARCHAR(64) NOT NULL, | |||
description TEXT, | |||
extension VARCHAR(16) NOT NULL, | |||
collection_id INTEGER NOT NULL REFERENCES collections(id) ON DELETE CASCADE | |||
) |
@@ -13,7 +13,7 @@ | |||
<button class="btn btn-default" onclick="$('#uploader-input').click()"> | |||
Select Files | |||
</button> | |||
<button class="btn btn-default" id="uploader-upload"> | |||
<button class="btn btn-default" id="uploader-upload" disabled> | |||
Upload | |||
</button> | |||
@@ -0,0 +1,7 @@ | |||
module.exports = function(ctx) { | |||
ctx.getPostData(function(err, data, files) { | |||
if (err) return console.log(err); | |||
ctx.succeed(); | |||
}); | |||
} |
@@ -30,4 +30,35 @@ | |||
.replace(/>/g, "<") | |||
.replace(/"/g, """); | |||
} | |||
util.api = function(name, data, cb, getXhr) { | |||
var fd = new FormData(); | |||
for (var i in data) { | |||
console.log(i); | |||
fd.append(i, data[i]); | |||
} | |||
return $.ajax({ | |||
method: "POST", | |||
url: "/api/"+name, | |||
data: fd, | |||
processData: false, | |||
contentType: false, | |||
xhr: function() { | |||
var xhr = new XMLHttpRequest(); | |||
if (getXhr) | |||
getXhr(xhr); | |||
return xhr; | |||
} | |||
}).done(function(res) { | |||
var obj = JSON.parse(res); | |||
if (obj.success) | |||
cb(null, obj); | |||
else | |||
cb(obj.error); | |||
}); | |||
} | |||
})(); |
@@ -8,8 +8,10 @@ | |||
files.forEach(function(f, i) { | |||
output.push( | |||
'<li class="file list-group-item" data-index='+i+'>'+ | |||
'<span class="name">'+util.htmlEntities(f.name)+'</span>'+ | |||
'<div class="progress-bar"></div>'+ | |||
'<button class="btn btn-default delete" onclick="uploaderDelete(this.parentNode)">X</button>'+ | |||
'<img class="thumbnail" src="'+f.thumbnail+'">'+ | |||
'<span class="name">'+util.htmlEntities(f.name)+'</span>'+ | |||
'</li>' | |||
); | |||
}); | |||
@@ -19,11 +21,27 @@ | |||
var files = []; | |||
$("#uploader-input").on("change", function(evt) { | |||
//Enable upload button | |||
$("#uploader-upload").removeAttr("disabled") | |||
console.log("making uploader button not disabled"); | |||
var inputFiles = evt.target.files; | |||
for (var i = 0; i < inputFiles.length; ++i) { | |||
for (var i = 0; i < inputFiles.length; ++i) (function() { | |||
var f = inputFiles[i]; | |||
f.thumbnail = ""; | |||
var reader = new FileReader(); | |||
reader.readAsDataURL(f); | |||
reader.onload = function(evt) { | |||
f.thumbnail = reader.result; | |||
draw(files); | |||
} | |||
files.push(inputFiles[i]); | |||
} | |||
})(); | |||
draw(files); | |||
}); | |||
@@ -34,7 +52,40 @@ | |||
draw(files); | |||
} | |||
//Upload things when the upload button is clicked | |||
$("#uploader-upload").on("click", function(evt) { | |||
console.log(output); | |||
//First, disable all buttons | |||
$("#uploader button.btn").prop("disabled", true); | |||
console.log("making buttons disabled"); | |||
var elems = []; | |||
$("#uploader-list .file").each(function() { | |||
var elem = $(this); | |||
elems[elem.data("index")] = elem; | |||
}); | |||
files.forEach(function(f, i) { | |||
var progressBar = elems[i].children(".progress-bar"); | |||
function getXhr(xhr) { | |||
xhr.upload.addEventListener("progress", function(evt) { | |||
if (!evt.lengthComputable) | |||
return; | |||
var percent = (evt.loaded / evt.total) * 100; | |||
progressBar.css({width: percent+"%"}); | |||
}, false); | |||
} | |||
var ajax = util.api("upload", { | |||
name: f.name, | |||
data: f | |||
}, function(err, res) { | |||
console.log(res); | |||
}, getXhr); | |||
}); | |||
}); | |||
})(); |
@@ -1,11 +1,25 @@ | |||
#uploader-list .file { | |||
text-align: right !important; | |||
#uploader-list .file .delete { | |||
float: right; | |||
margin-right: -5px; | |||
} | |||
#uploader-list .file .thumbnail { | |||
display: inline; | |||
margin: 0px; | |||
margin-right: 10px; | |||
height: 100px; | |||
image-orientation: from-image; | |||
} | |||
#uploader-list .file .name { | |||
float: left; | |||
margin-top: 6px; | |||
display: inline-block; | |||
} | |||
#uploader-list .file .progress-bar { | |||
height: 0px; | |||
position: absolute; | |||
background: none; | |||
border-top: 3px solid green; | |||
margin-top: -3px; | |||
max-width: calc(100% - 25px); | |||
} | |||
#uploader-upload { | |||
float: right; | |||
} |