Tutorial 5 Extending the project [mypostorm]

(continued from the previous post). Okay, now we have restructured the project as shown in the figure below.

fs

In the previous tutorial , we learned how to configure the Sequelize with MySQL. We also created some models and tested. Now, in this tutorial we will be creating the server and will put everything in place so that we can have a complete app running.

Step 1.Create the main entry point [mypostorm/server.js]

This is the main entry point of our application. Similar to the main() method for Java. The code is simple as shown below,


// Utility.
var rootAppDir = function()
{
var path = require('path');
var appDir = path.dirname(require.main.filename);
return appDir;
};

var express = require(rootAppDir().concat("/config/config.express"));
var router = require(rootAppDir().concat("/app/routes/app.route"));
// App.
var port = 1337;
var app = express.configureExpress();

// Possible routes.
router.appRouter('/', app);
router.appRouter('/registeruser',app);
router.appRouter('/home', app);
router.appRouter('/posts', app);
router.appRouter('/posts/:id', app);
router.appRouter('/logout',app);

app.listen(port);
console.log('Server running at http://localhost:' + port);

Here in the javascript code, we are importing the config.express  and app.route and calling the necessary methods. In the config.express.js , I have declared how to configure the Express Web Framework and in the app.route I have declared the necessary actions to perform for the particular URL.

Step 2.Configure the Express [mypostorm/config/config.express.js]

Here goes the code for the config.express.js. Its simple,

var express = require('express');
var bodyParser = require('body-parser');
var expressSession=require('express-session');
var cookieParser=require('cookie-parser');

exports.configureExpress = function()
{
	var app = express();
	app.set('views', rootAppDir() + '/app/views');
	app.set('view engine', 'ejs');
	app.use(express.static(rootAppDir() + '/public'));
	app.use(bodyParser.json());
	app.use(bodyParser.urlencoded({
		extended : true
	}));
	app.use(cookieParser());
	app.use(expressSession({secret:'somesecrettokenhere'}));
	console.log('Express Config Path: ' + rootAppDir());
	return app;
};

var rootAppDir = function()
{
	var path = require('path');
	var appDir = path.dirname(require.main.filename);
	return appDir;
};

I have used “expressSession” to store the Session information. “bodyParser” to parse the JSON data.

Step 3.Configure the Routes [mypostorm/app/routes/app.route.js]

Here goes the code for this javascript,

exports.appRouter = function(myurl, app)
{
	var controller = null;
	switch (myurl) {
	case '/':
		controller = require(rootAppDir().concat('/app/controllers/user.controller'));
		app.get(myurl, controller.renderLogin);
		break;
	case '/home':
		controller = require(rootAppDir().concat('/app/controllers/user.controller'));
		app.post(myurl,controller.renderHome);
		break;
	case '/registeruser':
		controller = require(rootAppDir().concat('/app/controllers/user.controller'));
		app.get(myurl,controller.renderUserRegistration);
		app.post(myurl,controller.registerUser);
		break;
	case '/posts':
		controller = require(rootAppDir().concat('/app/controllers/posts.controller'));
		app.get(myurl,controller.getPosts);
		app.post(myurl,controller.postScrap);
		break;
	case '/posts/:id':
		controller = require(rootAppDir().concat('/app/controllers/posts.controller'));
		app.delete(myurl,controller.deleteScrap);
		break;
	case '/logout':
		app.get(myurl, function (req, res) {
		    req.session.destroy(function () {
		    	console.log('I am logging out...');
		        res.redirect('/');
		    });
		});
		break;
	}
};

/* Utility */
var rootAppDir = function()
{
	var path = require('path');
	var appDir = path.dirname(require.main.filename);
	return appDir;
};

There is only one method in this script. The method appRouter() routes the calls to the specific controllers based on the URLs.Now lets see what are these controllers.

Step 4.Controller [mypostorm/app/controllers/posts.controller.js]

This Controller handles all the method calls (insert,delete,list) for users scrap. Here goes the simple script code,

exports.getPosts = function(req, res)
{
	var postDAO = require(rootAppDir() + '/app/dao/posts.dao');
	postDAO.getPosts(req,res);
};
exports.postScrap = function(req, res)
{
	var userid = req.session.loggedUser.userID;
	var scrap = req.body.scrap;
	var date = req.body.date;
	var postDAO = require(rootAppDir() + '/app/dao/posts.dao');
	postDAO.savePost(req,res, userid, scrap, date);
};
exports.deleteScrap = function(req, res)
{
	var postID=req.params.id;
	var postDAO = require(rootAppDir() + '/app/dao/posts.dao');
	postDAO.deleteScrap(req, res);
};

/* Utility */
var rootAppDir = function()
{
	var path = require('path');
	var appDir = path.dirname(require.main.filename);
	return appDir;
};

The code is straightforward. It calls the necessary DAO methods based on the user’s request.

Step 5.Controller [mypostorm/app/controllers/user.controller.js]

The controller handles all calls for example user login,logout and registration of users. Here goes the simple script code,

exports.renderLogin = function(req, res)
{

	if (req.session.loggedUser == null)
	{
		res.sendFile(rootAppDir() + '/public/pages/login.html');
	}
	else
	{
		res.sendFile(rootAppDir() + '/public/pages/index.html');
	}
};
exports.renderUserRegistration = function(req, res)
{
	console.log('Load User Registration Form');
	res.sendFile(rootAppDir() + '/public/pages/registeruser.html');
};
exports.registerUser = function(req, res)
{
	var firstName = req.body.firstName;
	var lastName = req.body.lastName;
	var login = req.body.login;
	var password = req.body.password;

	var userDAO = require(rootAppDir() + '/app/dao/user.dao');
	userDAO.saveUser(firstName, lastName,login,password,res);
};
exports.renderHome = function(req, res)
{
	var login = req.body.login;
	var password = req.body.password;
	var userDAO = require(rootAppDir() + '/app/dao/user.dao');
	userDAO.getUserByLoginPassword(login, password, req, res);
};

var rootAppDir = function()
{
	var path = require('path');
	var appDir = path.dirname(require.main.filename);
	return appDir;
};

The code is simple. It makes calls to user.dao to perform the necessary actions. Now let us look into the DAOs.

Step 6. DAO [mypostorm/app/dao/posts.dao.js]

var _this = this;
var rootAppDir = function()
{
	var path = require('path');
	var appDir = path.dirname(require.main.filename);
	return appDir;
};

exports.savePost = function(request,response, userID, scrap, date)
{
	var Sequelize = require('sequelize');
	var sql_config = require(rootAppDir() + '/config/config.mysql');
	var connection = sql_config.createMySQLConn(Sequelize);
	var TbPostVO = require(rootAppDir() + '/app/models/post').TbPostVO(connection, Sequelize);

	var post = TbPostVO.build({
	scrap : scrap,
	date : date,
	userID : userID
	});
	post.save().then(function()
	{
		console.log('Post registered.'+date);
		loadPosts(request,response);
	});
};

exports.getPosts = function(request,response)
{
	loadPosts(request,response);
};
exports.deleteScrap = function(request,response)
{
	var Sequelize = require('sequelize');
	var sql_config = require(rootAppDir() + '/config/config.mysql');
	var connection = sql_config.createMySQLConn(Sequelize);
	
	var TbPostVO = require(rootAppDir() + '/app/models/post').TbPostVO(connection, Sequelize);
	TbPostVO.destroy({
		where : {
			postID : request.params.id
		}
	}).then(function()
	{
		loadPosts(request,response);
	});
	
};

var loadPosts=function(request,response)
{
	var Sequelize = require('sequelize');
	var sql_config = require(rootAppDir() + '/config/config.mysql');
	var connection = sql_config.createMySQLConn(Sequelize);

	var TbUserVO = require(rootAppDir() + '/app/models/user').TbUserVO(connection, Sequelize);
	var TbPostVO = require(rootAppDir() + '/app/models/post').TbPostVO(connection, Sequelize);

	// One To Many.
	TbUserVO.hasMany(TbPostVO, {
	as : 'listPost',
	foreignKey : 'userID'
	});

	// One To One.
	TbPostVO.belongsTo(TbUserVO, {
		foreignKey : 'userID'
	});

	TbPostVO.findAll({
	where : {
		userID : request.session.loggedUser.userID
	},
	include : [ TbUserVO ]
	}).then(function(posts)
	{
		/*
		 * for (var i = 0; i < posts.length; i++) { var item = posts[i];
		 * console.log(item.TbUserVO.firstName); }
		 */
		response.json(posts);
	});
};

The code is straightforward. But you can see something bizarre in the method loadPosts(). I have put the mappings among the models (posts.js,user.js) only at the time of executing some method. The mapping could have been done in the very start of loading the application. But I did not find any good tutorial regarding this. But I will brush up this code in future, I promise.

Step 7.DAO [mypostorm/app/dao/user.dao.js]

/**
 * New node file
 */
var _this = this;

var rootAppDir = function()
{
	var path = require('path');
	var appDir = path.dirname(require.main.filename);
	return appDir;
};
exports.saveUser = function(firstName, lastName, login, password,response)
{
	var Sequelize = require('sequelize');
	var sql_config = require(rootAppDir() + '/config/config.mysql');
	var connection = sql_config.createMySQLConn(Sequelize);

	var TbUserVO = require(rootAppDir() + '/app/models/user')
			.TbUserVO(connection, Sequelize);

	var userToSave = TbUserVO.build({
	firstName : firstName,
	lastName : lastName,
	login : login,
	password : password
	});

	userToSave.save().then(function()
	{
		console.log('User registered.');
		response.sendFile(rootAppDir() + '/public/pages/registeruser_success.html');
	});
};

exports.getUserByLoginPassword = function(login, password, request, response)
{
	var Sequelize = require('sequelize');
	var sql_config = require(rootAppDir() + '/config/config.mysql');
	var connection = sql_config.createMySQLConn(Sequelize);

	var TbUserVO = require(rootAppDir() + '/app/models/user')
			.TbUserVO(connection, Sequelize);
	TbUserVO.findOne({
		where : {
		login : login,
		password : password
		}
	}).then(function(user)
	{
		if (user != null)
		{
			request.session.loggedUser=user;
			response.sendfile(rootAppDir() + '/public/pages/index.html');
		}
		else
		{
			response.sendfile(rootAppDir() + '/public/pages/login_fail.html');
		}
	});
};

Now lets see the models.

Step 8. Models [mypostorm/app/models/posts.js]

exports.TbPostVO = function(connection, Sequelize)
{
	var TbPostVO = connection.define('TbPostVO', {
	postID : {
	type : Sequelize.INTEGER,
	primaryKey : true
	},
	scrap : {
		type : Sequelize.STRING
	},
	date : {
		type : Sequelize.DATE
	},
	userID : {
		type : Sequelize.INTEGER
	},

	}, {
	freezeTableName : true,
	timestamps : false,
	tableName : "tb_posts"
	});

	return TbPostVO;
};

/*
 * module.exports = { abc : function() { console.log('Loggg'); } };
 */

Step 9. Models [mypostorm/app/models/user.js]

exports.TbUserVO = function(connection, Sequelize)
{
	var TbUserVO = connection.define('TbUserVO', {
	userID : {
	type : Sequelize.INTEGER,
	primaryKey : true
	},
	firstName : {
	type : Sequelize.STRING,
	get : function()
	{
		return this.getDataValue('firstName');
	}
	},
	lastName : {
		type : Sequelize.STRING
	},
	login : {
		type : Sequelize.STRING
	},
	password : {
		type : Sequelize.STRING
	},
	email : {
		type : Sequelize.STRING
	}
	}, {
	freezeTableName : true,
	timestamps : false,
	tableName : "tb_user"
	});

	return TbUserVO;
};

Step 10. Config MySQL [mypostorm/config/config.mysql.js]

exports.createMySQLConn = function(sequelize)
{
	var connection = new sequelize('attendance', 'root', 'root', {
	host : 'localhost',
	dialect : 'mysql'
	});
	
	return connection;
};

Okay we are done with the server part. Lets do the client part.

Step 1. Configure Angular.js

Download angularjs and put the file in mypostorm/public/js directory.

Step 2. Create HTML files[public/pages]

I have created 5 html files

login.html 

This is the startup page for user login.

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Monkey Login</title>
<link id="cssCommon" rel="stylesheet" type="text/css" href="/css/common.css" media="screen" />
</head>
<body class="page_size">


<div>
		<img id="imgLogin" src="/img/login.jpg" />
	</div>




<h1 align="center">Please Login to the Monkey App.</h1>




<div align="center">


<form action="/home" method="post">


<table>


<tr>


<td align="right">Login:</td>




<td align="left"><input type="text" name="login" /></td>


				</tr>




<tr>


<td align="right">Password:</td>




<td align="left"><input type="password" name="password" /></td>


				</tr>




<tr>


<td align="right"></td>




<td align="left"><a href="/pages/registeruser.html">New User</a><input type="submit" value="Login" /></td>


				</tr>


			</table>


		</form>


	</div>



</body>
</html>

login_fail.html

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Login Failed !!!</title>
</head>
<body>
<img id="imgMonkey" style="width: 100px; height: 100px" align="middle" src="/img/sheep.gif">


<div align="center">


<h1>Login failed.Please re-login !!!</h1>


		<a href="/pages/login.html">Login Now</a>
	</div>



</body>
</html>

registeruser.html

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Register User</title>
<link id="cssCommon" rel="stylesheet" type="text/css" href="/css/common.css" media="screen" />
</head>
<body class="page_size">


<div>
		<img id="imgRegister" src="/img/register.jpg" style="width: 121px; height: 97px" />
	</div>




<h1 align="center">Register your damn ass here !!!</h1>




<div align="center">


<form action="/registeruser" method="post">


<table>


<tr>


<td align="right">First Name:</td>




<td align="left"><input type="text" name="firstName" /></td>


				</tr>




<tr>


<td align="right">Last Name:</td>




<td align="left"><input type="text" name="lastName" /></td>


				</tr>




<tr>


<td align="right">Login:</td>




<td align="left"><input type="text" name="login" /></td>


				</tr>




<tr>


<td align="right">Password:</td>




<td align="left"><input type="password" name="password" /></td>


				</tr>




<tr>


<td align="right"></td>




<td align="left"><input type="submit" value="Submit" /></td>


				</tr>


			</table>


		</form>


	</div>



</body>
</html>

registeruser_success.html

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Register success</title>
</head>
<body>
	<img id="imgMonkey" style="width: 100px; height: 100px" align="middle" src="/img/monkey.gif">


<div align="center">


<h1>User has been registered successfully. Hurraayyyyy !!!</h1>


		<a href="/pages/login.html">Login Now</a>
	</div>



</body>
</html>

index.html

This is the page where users can post their scraps.

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Post it.</title>
<script id="a" src="/js/angular.min.js"></script>
<script id="b" src="/js/index.app.js"></script>
<script id="c" src="/js/index.controller.ng.js"></script>
</head>
<body ng-app="indexApp" ng-controller="index.controller" style="height: 134px; margin-left: 100px; margin-top: 20px; margin-right: 100px;">


<div style="width: 80%">


<h1 align="center">Post anything.</h1>


		<img id="monkey" src="/img/monkey.gif" style="width: 83px;" />
	</div>




<div align="center" style="width: 100%; background-color: #E2E5F4">


<form ng-submit="doSubmit()">
			<textarea ng-model="form.scrap" style="width: 30%; height: 100px; vertical-align: middle;"></textarea>
			<input type="submit" value="Post" />
			<input type="button" value="Log Out" ng-click="doLogOut()" />
		</form>


	</div>


	</br>


<div style="width: 100%">


<table border="1" style="width: 100%">


<tr>


<th style="width: 70%">Scrap</th>




<th style="width: 10%">User</th>




<th style="width: 10%">Date</th>




<th style="width: 10%">Action</th>


			</tr>




<tr ng-repeat="x in posts">


<td style="width: 10%">

{{ x.scrap}}
</td>




<td style="width: 10%">

{{ x.TbUserVO.firstName}}
</td>




<td style="width: 10%">

{{ x.date}}
</td>




<td style="width: 10%"><input type="button" value="Delete" ng-click="doDelete(x.postID)" /></td>


			</tr>


		</table>


	</div>


</body>
</html>

The index.html is kind of SPA (Single Page Application). I have used Angularjs in this page to perform CRUD operation.

Lets have a look into the angularjs code that I have used in this index.html.

Step 3. Angular JS code. The app code file[mypostorm/public/js/index.app.js]

There is only one line in this script.

 var indexApp = angular.module("indexApp", []);

This indexApp is what we are referring to in ng-app element of in index.html.

Step 4. Angular JS code. The controller[mypostorm/public/js/index.controller.js]

indexApp.controller('index.controller', function($scope, $http,$window)
{
	// Initial data.
	$scope.form = {
		scrap : 'Your first post.'
	};

	var loadPosts = $http.get('/posts').success(function(data)
	{
		$scope.posts = data;
	});

	// Save data.
	$scope.doSubmit = function()
	{
		var formData = {
		scrap : $scope.form.scrap,
		date : new Date()
		};

		var request = $http.post('/posts', formData).success(function(data)
		{
			$scope.posts = data;
		});

	};
	
	// Delete.
	$scope.doDelete=function(id)
	{
		$http.delete('/posts/' + id).success(function(data)
				{
			$scope.posts = data;
				});
	
	};
	
	// Log Out.
	$scope.doLogOut=function()
	{
		$http.get('/logout').success(function(data)
				{
					$window.location.href = '/';
				});
	};

});

This is the controller we are referring to in ng-controller element in index.html. Here there are all the actions performed in the index.html.

The final output of the app is as shown below,

Login screen.

Login

Post scrap screen

index

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s