Преглед изворни кода

changed framework related things, made profile and register pages work

master
mort пре 8 година
родитељ
комит
6e4d7d6caa

+ 45
- 10
lib/context.js Прегледај датотеку



var sessions = {}; var sessions = {};


function templatify(str, args, ctx) {
function templatify(str, args, ctx, env) {
env.url = ctx.req.url;

str = preprocess(str, { str = preprocess(str, {
session: ctx.session, session: ctx.session,
arg: args,
env: env,
template: function(key) { template: function(key) {
return ctx.template(key); return ctx.template(key);
} }
}); });


if (args == undefined)
return str;

for (var i in args) {
str = str.split("{{"+i+"}}").join(args[i]);
}

return str; return str;
} }


this.views = options.views; this.views = options.views;
this.db = options.db; this.db = options.db;
this.conf = options.conf; this.conf = options.conf;
this.query = this.req.url.split("?")[1] || "";
if (this.conf.debug)
this.startTime = new Date();


//Handle cookies //Handle cookies
this.cookies = {}; this.cookies = {};


module.exports.prototype = { module.exports.prototype = {
end: function(str) { end: function(str) {
if (this.conf.debug) {
var ms = (new Date().getTime() - this.startTime.getTime());
console.log(
ms+" millisecond(s)\t"+
(this.statusCode || 200)+"\t"+
this.req.url
);
} else {
conole.log(this.req.url);
}

if (this.statusCode) if (this.statusCode)
this.res.writeHead(this.statusCode); this.res.writeHead(this.statusCode);


if (!str) if (!str)
throw new Error("No such template: "+name); throw new Error("No such template: "+name);


return templatify(str, args, this);
return templatify(str, args, this, {template: name});
}, },


view: function(name, args) { view: function(name, args) {
if (!str) if (!str)
throw new Error("No such view: "+name); throw new Error("No such view: "+name);


return templatify(str, args, this);
return templatify(str, args, this, {view: name});
}, },


getPostData: function(cb) { getPostData: function(cb) {
this.session.loggedIn = false; this.session.loggedIn = false;
delete this.session.username; delete this.session.username;
delete this.session.userId; delete this.session.userId;
},

async: function(n, cb) {
if (typeof n !== "number")
throw new Error("Expected number, got "+typeof n);

if (n < 1)
return cb();

var res = {};
var errs = {};
var errnum = 0;

return function(key, val, err) {
if (key)
res[key] = val;
if (err)
errs[key] = err;

if (n === 1)
cb((errnum ? errs : null), res);
else
n -= 1;
}
} }
} }

+ 42
- 2
server.js Прегледај датотеку

"/register/style.css": "register/style.css", "/register/style.css": "register/style.css",
"/register/script.js": "register/script.js", "/register/script.js": "register/script.js",


//Profile
"/profile": "profile/index.node.js",
"/profile/style.css": "profile/style.css",
"/profile/script.js": "profile/script.js",

//Viewer //Viewer
"/view": "view/index.node.js", "/view": "view/index.node.js",
"/view/style.css": "view/style.css", "/view/style.css": "view/style.css",


//Function to run on each request //Function to run on each request
function onRequest(req, res) { function onRequest(req, res) {
console.log("Request for "+req.url);

var ctx = new Context({ var ctx = new Context({
req: req, req: req,
res: res, res: res,
console.trace(err); console.trace(err);
}); });
} }

function command(tokens) {
switch(tokens[0]) {

//Reload configuration
case "reload-conf":
var c = JSON.parse(fs.readFileSync("conf.json"));
for (var i in c)
conf[i] = c[i];
break;

//Reload HTML
case "reload-html":
var l = loader.load(endpoints, conf);
for (var i in l)
loaded[i] = l[i];
break;

//Reload everything
case "reload":
command(["reload-conf"]);
command(["reload-html"]);
break;

default: return false;
}
return true;
}

process.stdin.on("data", function(line) {
var tokens = line.toString().split(/\s+/);
if (command(tokens)) {
return console.log(tokens[0]+" completed successfully.");
} else {
return console.log("Command not found: "+tokens[0]);
}
});

templates/global.html → templates/body.html Прегледај датотеку


+ 4
- 0
templates/collection.html Прегледај датотеку

<div class="collection">
<a class="name" href="/view?{{arg#id}}">{{arg#name}}</a>
<span class="date-created">{{arg#date_created}}</span>
</div>

+ 4
- 0
templates/head.html Прегледај датотеку

<title>{{conf#title}}</title> <title>{{conf#title}}</title>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">

<link rel="stylesheet" href="/global.css"> <link rel="stylesheet" href="/global.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="/{{env#view}}/style.css">

<script src="https://code.jquery.com/jquery-2.1.4.js"></script> <script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="/global.js"></script> <script src="/global.js"></script>
<script src="/{{env#view}}/script.js"></script>

+ 4
- 4
templates/image.html Прегледај датотеку

<div class="image"> <div class="image">
<div class="title">{{title}}</div>
<img class="img-rounded" src="/i?{{id}}.{{extension}}">
<div class="description">{{description}}</div>
<input class="url" type="text" value="{{conf#base_url}}/i?{{id}}.{{extension}}" onclick="select()">
<div class="title">{{arg#title}}</div>
<img class="img-rounded" src="/i?{{arg#id}}.{{arg#extension}}">
<div class="description">{{arg#description}}</div>
<input class="url" type="text" value="{{conf#base_url}}/i?{{arg#id}}.{{arg#extension}}" onclick="select()">
</div> </div>

+ 1
- 1
templates/navbar-loggedin.html Прегледај датотеку

<li> <li>
<a href="/profile?{{session#userId}}">{{session#username}}</a>
<a id="navbar-button" href="/profile?{{session#userId}}">{{session#username}}</a>
</li> </li>

+ 1
- 1
templates/navbar-login.html Прегледај датотеку

<li class="dropdown" id="login-dropdown"> <li class="dropdown" id="login-dropdown">
<a href="#" data-toggle="dropdown" class="dropdown-toggle" style="float: right">
<a href="#" data-toggle="dropdown" class="dropdown-toggle" id="navbar-button">
Log In Log In
<b class="caret"></b> <b class="caret"></b>
</a> </a>

+ 2
- 1
views/404.html Прегледај датотеку

<meta charset="utf-8"> <meta charset="utf-8">
</head> </head>
<body> <body>
404, file not found.
404, file not found.<br>
{{env#url}}
</body> </body>
</html> </html>

+ 1
- 4
views/index.html Прегледај датотеку

<html> <html>
<head> <head>
{{template#head}} {{template#head}}
<link rel="stylesheet" href="/index/style.css">
</head> </head>
<body> <body>
{{template#global}}
{{template#body}}


<div id="uploader" class="container"> <div id="uploader" class="container">
<input type="file" accept="image/*" id="uploader-input" class="hidden" multiple> <input type="file" accept="image/*" id="uploader-input" class="hidden" multiple>


<ul class="list-group" id="uploader-list"></ul> <ul class="list-group" id="uploader-list"></ul>
</div> </div>

<script src="/index/script.js"></script>
</body> </body>
</html> </html>

+ 16
- 0
views/profile.html Прегледај датотеку

<!DOCTYPE html>
<html>
<head>
{{template#head}}
</head>
<body>
{{template#body}}

<div id="profile" class="container">
<div id="collections" class="container">
<div class="name">{{arg#username}}</div>
{{arg#collections}}
</div>
</div>
</body>
</html>

+ 2
- 5
views/register.html Прегледај датотеку

<html> <html>
<head> <head>
{{template#head}} {{template#head}}
<link rel="stylesheet" href="/register/style.css">
</head> </head>
<body> <body>
{{template#global}}
{{template#body}}


<div class="container" id="register"> <div class="container" id="register">
<form id="register-form"> <form id="register-form">
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Repeat Password<br> <label>Repeat Password<br>
<input type="psasword" id="register-password-repeat">
<input type="password" id="register-password-repeat">
</label> </label>
</div> </div>
<div class="submit-container"> <div class="submit-container">
</div> </div>
</form> </form>
</div> </div>

<script src="/index/script.js"></script>
</body> </body>
</html> </html>

+ 2
- 5
views/view.html Прегледај датотеку

<html> <html>
<head> <head>
{{template#head}} {{template#head}}
<link rel="stylesheet" href="/view/style.css">
</head> </head>
<body> <body>
{{template#global}}
{{template#body}}


<div id="viewer" class="container"> <div id="viewer" class="container">
{{images}}
{{arg#images}}
</div> </div>

<script src="/index/script.js"></script>
</body> </body>
</html> </html>

+ 1
- 1
web/api/account_create.node.js Прегледај датотеку

if (err) if (err)
return ctx.fail(err); return ctx.fail(err);


ctx.login(ctx.postData.username, res.rows[0].id);
ctx.login(ctx.postData.data.username, res.rows[0].id);


ctx.succeed({ ctx.succeed({
id: res.rows[0].id id: res.rows[0].id

+ 2
- 2
web/api/account_login.node.js Прегледај датотеку



var user = res.rows[0]; var user = res.rows[0];


ctx.login(user.username, user.id);

if (!user) if (!user)
return ctx.fail("Wrong username or password."); return ctx.fail("Wrong username or password.");


ctx.login(user.username, user.id);

scrypt.verify( scrypt.verify(
new Buffer(user.pass_hash, "hex"), new Buffer(user.pass_hash, "hex"),
new Buffer(ctx.postData.data.password), new Buffer(ctx.postData.data.password),

+ 3
- 3
web/api/collection_create.node.js Прегледај датотеку

return ctx.fail(err); return ctx.fail(err);


ctx.db.query( ctx.db.query(
"INSERT INTO collections (name) "+
"VALUES ($1) "+
"INSERT INTO collections (name, user_id) "+
"VALUES ($1, $2) "+
"RETURNING id", "RETURNING id",
[data.name],
[data.name, ctx.session.userId],
queryCallback queryCallback
); );
}); });

+ 1
- 1
web/api/template.node.js Прегледај датотеку

module.exports = function(ctx) { module.exports = function(ctx) {
var name = ctx.req.url.split("?")[1];
var name = ctx.query;
if (!name) if (!name)
return ctx.fail("You must supply a template name."); return ctx.fail("You must supply a template name.");



+ 4
- 0
web/global.css Прегледај датотеку

padding: 10px; padding: 10px;
} }


#navbar-button {
float: right;
}

#login-dropdown label, #login-dropdown label,
#login-dropdown input { #login-dropdown input {
width: 100%; width: 100%;

+ 38
- 2
web/global.js Прегледај датотеку

(function() { (function() {
var months = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
]

window.util = {}; window.util = {};


util.notify = function notify(title, body) { util.notify = function notify(title, body) {


var res = {}; var res = {};


return function(key, val) {
if (key !== undefined)
return function(key, val, err) {
if (key)
res[key] = val; res[key] = val;


if (n === 1) if (n === 1)
} }
} }


util.pad = function(str, length, padChar) {
var missing = (length - str.length) + 1;

if (missing <= 0)
return str;

return new Array(missing).join(padChar) + str;
}

util.dateToString = function(date) {
var day = util.pad(date.getDate().toString(), 2, "0");
var month = months[date.getMonth()];

return day+". of "+month+" "+
date.getFullYear()+", "+
util.pad(date.getHours().toString(), 2, "0")+":"+
util.pad(date.getMinutes().toString(), 2, "0");
}

window.display = {}; window.display = {};


window.display.loggedIn = function() { window.display.loggedIn = function() {
return util.error(err); return util.error(err);


$("#navbar-profile-container").html(res.html); $("#navbar-profile-container").html(res.html);

util.notify("Logged In", "You are now logged in.");
}); });
} }



+ 2
- 5
web/i/index.node.js Прегледај датотеку

var fs = require("fs"); var fs = require("fs");


module.exports = function(ctx) { module.exports = function(ctx) {
var id;
try {
id = ctx.req.url.split("?")[1].replace(/\..*/, "");
} catch (err) {
var id = ctx.query.replace(/\..*/, "");
if (!id)
return ctx.end(ctx.view("404")); return ctx.end(ctx.view("404"));
}


var readStream = fs.createReadStream(ctx.conf.dir.imgs+"/"+id); var readStream = fs.createReadStream(ctx.conf.dir.imgs+"/"+id);
readStream.pipe(ctx.res); readStream.pipe(ctx.res);

+ 4
- 3
web/index/script.js Прегледај датотеку

(function() {
$(document).on("ready", function() {
if (!window.File || !window.FileReader || !window.FileList || !window.Blob) { if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
notify("Your Browser Sucks."); notify("Your Browser Sucks.");
} }
var files = []; var files = [];


$("#uploader-input").on("change", function(evt) { $("#uploader-input").on("change", function(evt) {
console.log(evt);


//Enable upload button //Enable upload button
$("#uploader-upload").removeAttr("disabled")
$("#uploader-upload").removeAttr("disabled");


var inputFiles = evt.target.files; var inputFiles = evt.target.files;


}); });
}); });
}); });
})();
});

+ 44
- 0
web/profile/index.node.js Прегледај датотеку

module.exports = function(ctx) {
var id = ctx.query;

ctx.db.query(
"SELECT name, date_created, id "+
"FROM collections "+
"WHERE user_id = $1",
[id],
function(err, res) { a("collections", res.rows, err) }
);

ctx.db.query(
"SELECT username "+
"FROM users "+
"WHERE id = $1",
[id],
function(err, res) { a("users", res.rows, err) }
);

var a = ctx.async(2, function(err, res) {
if (err)
return ctx.fail(err);

var user = res.users[0];
if (!user)
return ctx.end(ctx.view("404"));

var collections = "";
res.collections.forEach(function(row) {
var d = new Date(row.date_created);

collections += ctx.template("collection", {
name: row.name,
date_created: d.toString(),
id: row.id
});
});

ctx.end(ctx.view("profile", {
username: user.username,
collections: collections
}));
});
}

+ 5
- 0
web/profile/script.js Прегледај датотеку

$(document).on("ready", function() {
$("#collections .date-created").each(function() {
this.innerHTML = util.dateToString(new Date(this.innerHTML));
});
});

+ 9
- 0
web/profile/style.css Прегледај датотеку

#profile {
text-align: center;
}

#collections {
text-align: left;
width: auto;
display: inline-block;
}

+ 34
- 0
web/register/script.js Прегледај датотеку

$(document).on("ready", function() {
$("#register-form").on("submit", function(evt) {
console.log(evt);
evt.preventDefault();
evt.stopPropagation();

var username = $("#register-username").val();
var password = $("#register-password").val();
var password2 = $("#register-password-repeat").val();

if (password !== password2)
return util.error("Paswords don't match.");

if (!username)
return util.error("You must supply a username.");

if (!password)
return util.error("You must supply a password.");

util.api("account_create", {
username: username,
password: password
}, function(err, res) {
if (err)
return util.error(err);

display.loggedIn();

setTimeout(function() {
location.href = "/profile?"+res.id;
}, 1000);
});
});
});

+ 4
- 1
web/view/index.node.js Прегледај датотеку

module.exports = function(ctx) { module.exports = function(ctx) {
var id = parseInt(ctx.req.url.split("?")[1]);
var id = parseInt(ctx.query);


if (isNaN(id)) if (isNaN(id))
return ctx.end(ctx.view("404")); return ctx.end(ctx.view("404"));
if (err) if (err)
return ctx.fail(err); return ctx.fail(err);


if (!res.rows[0])
return ctx.end(ctx.view("404"));

var images = ""; var images = "";
res.rows.forEach(function(row) { res.rows.forEach(function(row) {
images += ctx.template("image", { images += ctx.template("image", {

Loading…
Откажи
Сачувај