├── .gitignore ├── Procfile ├── README.md ├── app.js ├── bin └── www ├── image.png ├── models ├── toDoModel.js └── userModel.js ├── package.json ├── public ├── bower.json ├── css │ └── style.css ├── img │ └── Thumbs.db ├── js │ ├── app.js │ ├── controllers │ │ ├── aboutController.js │ │ ├── addNewTaskController.js │ │ ├── bottomGridSheetController.js │ │ ├── editTaskController.js │ │ ├── homeController.js │ │ ├── signInController.js │ │ └── signUpController.js │ └── services │ │ ├── actionService.js │ │ └── userService.js ├── partials │ ├── about.html │ ├── addNewTaskDialog.html │ ├── bottomGridSheet.html │ ├── editTaskDialog.html │ ├── home.html │ ├── signIn.html │ └── signUp.html └── stylesheets │ └── style.css ├── routes ├── index.js └── users.js └── views ├── error.ejs └── index.ejs /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | npm-debug.log -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: node bin/www -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Material-ToDo 2 | 3 | The MEAN Stack ToDo App on the New Angular Material Design. 4 | 5 | - Sign Up 6 | - Sign In 7 | - Start.. 8 | - Write Edit Delete and Check If Complete.. 9 | 10 | 11 | # Live Project Demo - https://materialtodo.herokuapp.com/ 12 | 13 | Thanks. 14 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('serve-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var bodyParser = require('body-parser'); 7 | var session = require("express-session"); 8 | 9 | var routes = require('./routes'); 10 | var users = require('./routes/users'); 11 | 12 | var app = express(); 13 | 14 | // view engine setup 15 | app.set('views', path.join(__dirname, 'views')); 16 | app.set('view engine', 'ejs'); 17 | 18 | //Allow Cross Origin Access MiddleWare 19 | app.use(function(req, res, next) { 20 | res.header("Access-Control-Allow-Origin", "*"); 21 | res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); 22 | res.header("'Access-Control-Allow-Methods',['OPTIONS', 'GET', 'POST', 'DELETE']"); 23 | res.header("'Access-Control-Allow-Headers','Content-Type'"); 24 | next(); 25 | }); 26 | 27 | // uncomment after placing your favicon in /public 28 | //app.use(favicon(__dirname + '/public/favicon.ico')); 29 | app.use(logger('dev')); 30 | app.use(bodyParser.json()); 31 | app.use(bodyParser.urlencoded({ extended: false })); 32 | app.use(cookieParser()); 33 | app.use(express.static(path.join(__dirname, 'public'))); 34 | 35 | app.use(session({ 36 | saveUninitialized: true, 37 | resave: true, 38 | secret: "my Custom Secret" 39 | })); 40 | 41 | //app.use('/users', users); 42 | app.use('/', routes); 43 | 44 | // catch 404 and forward to error handler 45 | app.use(function(req, res, next) { 46 | var err = new Error('Not Found'); 47 | err.status = 404; 48 | next(err); 49 | }); 50 | 51 | // error handlers 52 | 53 | // development error handler 54 | // will print stacktrace 55 | if (app.get('env') === 'development') { 56 | app.use(function(err, req, res, next) { 57 | res.status(err.status || 500); 58 | res.render('error', { 59 | message: err.message, 60 | error: err 61 | }); 62 | }); 63 | } 64 | 65 | // production error handler 66 | // no stacktraces leaked to user 67 | app.use(function(err, req, res, next) { 68 | res.status(err.status || 500); 69 | res.render('error', { 70 | message: err.message, 71 | error: {} 72 | }); 73 | }); 74 | 75 | 76 | module.exports = app; 77 | -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('server:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '7000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JSalaat/Material-ToDo/4efb8e40eb0bbf477a96d31cdb2685dc2c8aaa10/image.png -------------------------------------------------------------------------------- /models/toDoModel.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by M.JUNAID on 2015-04-03. 3 | */ 4 | 5 | var mongoose = require("mongoose"); 6 | var q = require("q"); 7 | 8 | 9 | var ToDoSchema = mongoose.Schema({ 10 | UiD:{ type :String}, 11 | Task:String, 12 | Desc:String, 13 | Priority:String, 14 | DueDate:Date, 15 | IsDone:Boolean, 16 | CreatedOn:{type : Date, default: Date.now()} 17 | }); 18 | 19 | var ToDoModel = mongoose.model('todo',ToDoSchema); 20 | 21 | 22 | exports.saveToDoToDb = function(toDoObj){ 23 | var defered = q.defer(); 24 | var todo = new ToDoModel(toDoObj); 25 | todo.save(function(err,data){ 26 | if(err){ 27 | console.log("Error in insertion of new user"); 28 | console.log(err); 29 | defered.reject(err); 30 | }else{ 31 | console.log("Successfully Inserted User"); 32 | defered.resolve(); 33 | } 34 | }); 35 | return defered.promise; 36 | }; 37 | 38 | exports.ToDoFromDbByUid = function(Uid){ 39 | var defered = q.defer(); 40 | 41 | ToDoModel.find({UiD:Uid},function(err,data){ 42 | if(err){ 43 | console.log("Error in Finding ToDo's"); 44 | console.log(err); 45 | defered.reject(err); 46 | }else if(data){ 47 | console.log("Successfully retrieved ToDo's "); 48 | defered.resolve(data); 49 | }else{ 50 | console.log("No Todo's Found of user id :"+Uid); 51 | defered.resolve(data); 52 | } 53 | }); 54 | return defered.promise; 55 | }; 56 | 57 | exports.editToDo = function(uid,obj){ 58 | var defered = q.defer(); 59 | 60 | ToDoModel.update({_id:uid},obj,function(err,data){ 61 | if(err){ 62 | console.log("Error ToDo's"); 63 | console.log(err); 64 | defered.reject(err); 65 | }else if(data){ 66 | console.log("Successfully Edited ToDo "); 67 | defered.resolve(data); 68 | }else{ 69 | console.log("No Todo Found of user id :"+uid); 70 | defered.resolve(data); 71 | } 72 | }); 73 | return defered.promise; 74 | }; 75 | 76 | exports.updateToDo = function(uid,obj){ 77 | var defered = q.defer(); 78 | 79 | ToDoModel.update({_id:uid},obj,function(err,data){ 80 | if(err){ 81 | console.log("Error in updating ToDo's"); 82 | console.log(err); 83 | defered.reject(err); 84 | }else if(data){ 85 | console.log("Successfully updated ToDo "); 86 | defered.resolve(data); 87 | }else{ 88 | console.log("No Todo Found of user id :"+uid); 89 | defered.resolve(data); 90 | } 91 | }); 92 | return defered.promise; 93 | }; 94 | 95 | exports.deleteToDo = function(uid){ 96 | var defered = q.defer(); 97 | 98 | ToDoModel.remove({_id:uid},function(err,data){ 99 | if(err){ 100 | console.log("Error in deleting ToDo's"); 101 | console.log(err); 102 | defered.reject(err); 103 | }else if(data){ 104 | console.log("Successfully deleted ToDo "); 105 | defered.resolve(data); 106 | }else{ 107 | console.log("No Todo Found of user id :"+uid); 108 | defered.resolve(data); 109 | } 110 | }); 111 | return defered.promise; 112 | }; 113 | -------------------------------------------------------------------------------- /models/userModel.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by M.JUNAID on 2015-04-03. 3 | */ 4 | 5 | var mongoose = require("mongoose"); 6 | var q = require("q"); 7 | var db = mongoose.connect("<<- replace your mongo db key here ->>", function(err){ 8 | if(err){ 9 | console.log("Error in connecting check your db key"); 10 | console.log(err); 11 | } else { 12 | console.log("Connected to database successfully"); 13 | } 14 | }); 15 | 16 | var UserSchema = mongoose.Schema({ 17 | UserName:String, 18 | FirstName:String, 19 | LastName:String, 20 | Email:String, 21 | Password:String, 22 | CreatedOn:{type : Date, default: Date.now()} 23 | }); 24 | 25 | var UserModel = mongoose.model('user',UserSchema); 26 | 27 | 28 | exports.saveUserToDb = function(userObj){ 29 | var defered = q.defer(); 30 | var user = new UserModel(userObj); 31 | user.save(function(err,data){ 32 | if(err){ 33 | console.log("Error in insertion of new user"); 34 | console.log(err); 35 | defered.reject(err); 36 | }else{ 37 | console.log("Successfully Inserted User"); 38 | defered.resolve(); 39 | } 40 | }); 41 | return defered.promise; 42 | }; 43 | 44 | exports.signInUserFromDb = function(userData){ 45 | var defered = q.defer(); 46 | //var user = new UserModel(userObj); 47 | 48 | UserModel.findOne({UserName:userData.userName,Password:userData.password},function(err,data){ 49 | if(err){ 50 | console.log("Error in Finding user data"); 51 | console.log(err); 52 | defered.reject(err); 53 | }else if(data){ 54 | console.log("Successfully Signed In User"); 55 | defered.resolve(data); 56 | }else{ 57 | console.log("No User Found of username :"+userData.userName); 58 | defered.resolve(data); 59 | } 60 | }); 61 | return defered.promise; 62 | }; 63 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Material-ToDo-Server", 3 | "version": "1.0.1", 4 | "private": false, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.12.0", 10 | "cookie-parser": "~1.3.4", 11 | "debug": "~2.1.1", 12 | "ejs": "~2.3.1", 13 | "express": "~4.12.2", 14 | "express-session": "^1.10.4", 15 | "mongoose": "^4.0.1", 16 | "morgan": "~1.5.1", 17 | "q": "^1.2.0", 18 | "serve-favicon": "~2.2.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /public/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Material-ToDo", 3 | "homepage": "https://github.com/mjunaidsalaat/Material-ToDo", 4 | "authors": [ 5 | "M. Junaid Salaat " 6 | ], 7 | "description": "To Do App", 8 | "main": "app.js", 9 | "moduleType": [], 10 | "license": "MIT", 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ], 18 | "dependencies": { 19 | "angular-material": "master", 20 | "angular-ui-router": "~0.2.15" 21 | }, 22 | "resolutions": { 23 | "angular-material": "~0.11.4" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /public/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font: 16px "Lucida Grande", RobotoDraft, Helvetica, Arial, sans-serif; 3 | 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | .positionCenter { 10 | position: relative; 11 | bottom: 130px; 12 | } 13 | 14 | .marginCenter{ 15 | margin-top: 52px; 16 | } 17 | 18 | 19 | .menuBtn { 20 | background-color: transparent; 21 | border: none; 22 | height: 38px; 23 | margin: 16px; 24 | position: absolute; 25 | width: 36px; 26 | } 27 | md-toolbar h1 { 28 | font-size: 1.250em; 29 | font-weight: 400; 30 | margin: auto; 31 | } 32 | md-list .md-button { 33 | color: inherit; 34 | font-weight: 500; 35 | text-align: left; 36 | width: 100%; 37 | } 38 | .visually-hidden { 39 | border: 0; 40 | clip: rect(0 0 0 0); 41 | height: 1px; 42 | margin: -1px; 43 | overflow: hidden; 44 | padding: 0; 45 | position: absolute; 46 | width: 1px; 47 | } 48 | 49 | /* Using Data-URI converted from svg until becomes available 50 | https://github.com/google/material-design-icons 51 | */ 52 | .menuBtn { 53 | background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIyNHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDI0IDI0IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPGcgaWQ9IkhlYWRlciI+CiAgICA8Zz4KICAgICAgICA8cmVjdCB4PSItNjE4IiB5PSItMjIzMiIgZmlsbD0ibm9uZSIgd2lkdGg9IjE0MDAiIGhlaWdodD0iMzYwMCIvPgogICAgPC9nPgo8L2c+CjxnIGlkPSJMYWJlbCI+CjwvZz4KPGcgaWQ9Ikljb24iPgogICAgPGc+CiAgICAgICAgPHJlY3QgZmlsbD0ibm9uZSIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ii8+CiAgICAgICAgPHBhdGggZD0iTTMsMThoMTh2LTJIM1YxOHogTTMsMTNoMTh2LTJIM1YxM3ogTTMsNnYyaDE4VjZIM3oiIHN0eWxlPSJmaWxsOiNmM2YzZjM7Ii8+CiAgICA8L2c+CjwvZz4KPGcgaWQ9IkdyaWQiIGRpc3BsYXk9Im5vbmUiPgogICAgPGcgZGlzcGxheT0iaW5saW5lIj4KICAgIDwvZz4KPC9nPgo8L3N2Zz4=) no-repeat center center; 54 | } 55 | 56 | .face { 57 | border-radius: 30px; 58 | border: 1px solid #ddd; 59 | width: 48px; 60 | margin: 16px; 61 | } 62 | 63 | .bottomRightAlign{ 64 | align-self: flex-end; 65 | position: relative; 66 | bottom: 50px; 67 | right: 15px; 68 | } 69 | 70 | .redColor{ 71 | color: red; 72 | /*position: relative;*/ 73 | /*top: 25px;*/ 74 | } 75 | .orangeColor{ 76 | color: orange; 77 | /*position: relative;*/ 78 | /*top: 25px;*/ 79 | } 80 | .greenColor{ 81 | color: green; 82 | /*position: relative;*/ 83 | /*top: 25px;*/ 84 | } 85 | 86 | .docs-menus{ 87 | border-radius: 0; 88 | color: inherit; 89 | cursor: pointer; 90 | font-weight: 400; 91 | line-height: 40px; 92 | margin: 0; 93 | max-height: 40px; 94 | overflow: hidden; 95 | padding: 0px 16px; 96 | text-align: left; 97 | text-decoration: none; 98 | white-space: normal; 99 | width: 100%; 100 | } 101 | 102 | .gridIcon{ 103 | font-size: xx-large; 104 | padding: 10px; 105 | } 106 | 107 | .marginBottom{ 108 | margin-bottom: 10px; 109 | } -------------------------------------------------------------------------------- /public/img/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JSalaat/Material-ToDo/4efb8e40eb0bbf477a96d31cdb2685dc2c8aaa10/public/img/Thumbs.db -------------------------------------------------------------------------------- /public/js/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by M.JUNAID on 2015-03-09. 3 | */ 4 | var materialToDo = angular.module('materialToDo', ['ngMaterial','ui.router']); 5 | 6 | materialToDo.constant("basePath", "https://materialtodo.herokuapp.com"); 7 | 8 | materialToDo.config(function($stateProvider,$urlRouterProvider,$locationProvider,$mdThemingProvider){ 9 | 10 | $mdThemingProvider 11 | .theme('docs-dark', 'default') 12 | .primaryPalette('yellow'); 13 | //.dark() 14 | //.theme('default') 15 | //.primaryPalette('yellow') 16 | //.accentPalette('pink'); 17 | //.warnPalette('red') 18 | //.backgroundPalette('blue'); 19 | 20 | $stateProvider 21 | .state('signUp',{ 22 | url: "/signUp", 23 | templateUrl:'partials/signUp.html', 24 | controller:'signUpController' 25 | }).state('signIn',{ 26 | url: "/signIn", 27 | templateUrl:'partials/signIn.html', 28 | controller:'signInController' 29 | }).state('home',{ 30 | url: "/home", 31 | templateUrl:'partials/home.html', 32 | controller:'homeController', 33 | cache: false 34 | }).state('about',{ 35 | url: "/about", 36 | templateUrl:'partials/about.html', 37 | controller:'aboutController', 38 | cache: false 39 | }); 40 | 41 | if(window.localStorage['toDoUser']){ 42 | $urlRouterProvider.otherwise('/home'); 43 | }else{ 44 | $urlRouterProvider.otherwise('/signIn'); 45 | } 46 | 47 | $locationProvider.html5Mode({ 48 | enabled : true, 49 | requireBase : false 50 | }); 51 | 52 | 53 | }); 54 | -------------------------------------------------------------------------------- /public/js/controllers/aboutController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by M.JUNAID on 2015-03-09. 3 | */ 4 | 5 | materialToDo.controller('aboutController', function($scope,$mdToast){ 6 | 7 | 8 | }); -------------------------------------------------------------------------------- /public/js/controllers/addNewTaskController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by M.JUNAID on 2015-03-12. 3 | */ 4 | 5 | materialToDo.controller('addNewTaskController', function(userService,basePath,$scope,$mdDialog ,$http) { 6 | 7 | $scope.newTask={ 8 | isDone:false, 9 | Uid:userService.UserUid.get()._id 10 | }; 11 | 12 | $scope.cancel = function () { 13 | $mdDialog.cancel(); 14 | }; 15 | 16 | $scope.done = function () { 17 | console.log($scope.newTask); 18 | $http.post((basePath+'/saveNewTodo'),$scope.newTask) 19 | .success(function(data){ 20 | $mdDialog.hide(); 21 | }) 22 | .error(function(err){ 23 | console.log(err) 24 | 25 | }); 26 | 27 | }; 28 | 29 | }); 30 | 31 | 32 | -------------------------------------------------------------------------------- /public/js/controllers/bottomGridSheetController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by M.JUNAID on 2015-03-12. 3 | */ 4 | 5 | materialToDo.controller('bottomGridSheetController', function($scope, $mdBottomSheet, $mdDialog,actionService) { 6 | 7 | $scope.listItemClick = function(action) { 8 | $mdBottomSheet.hide(); 9 | actionService.clickedAction.set(action) 10 | }; 11 | 12 | 13 | }); -------------------------------------------------------------------------------- /public/js/controllers/editTaskController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by M.JUNAID on 2015-03-12. 3 | */ 4 | 5 | materialToDo.controller('editTaskController', function($scope,$mdDialog,actionService,$http,basePath) { 6 | 7 | 8 | $scope.taskToEdit = actionService.clickedTask.get(); 9 | $scope.taskToEdit.DueDate = new Date($scope.taskToEdit.DueDate); 10 | 11 | $scope.cancel = function () { 12 | $mdDialog.cancel(); 13 | }; 14 | 15 | $scope.done = function () { 16 | $http.post((basePath+'/editTodo'),$scope.taskToEdit) 17 | .success(function(data){ 18 | console.log(data); 19 | $mdDialog.hide(); 20 | }) 21 | .error(function(err){ 22 | console.log(err) 23 | }); 24 | }; 25 | 26 | }); 27 | 28 | 29 | -------------------------------------------------------------------------------- /public/js/controllers/homeController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by M.JUNAID on 2015-03-09. 3 | */ 4 | 5 | materialToDo.controller('homeController', function($scope,$state,$mdSidenav,$mdDialog,$mdBottomSheet,$timeout,actionService,$mdToast,$http,userService,basePath){ 6 | 7 | $scope.toastPosition = { 8 | bottom: true, 9 | top: false, 10 | left: false, 11 | right: true 12 | }; 13 | $scope.getToastPosition = function () { 14 | return Object.keys($scope.toastPosition) 15 | .filter(function (pos) { 16 | return $scope.toastPosition[pos]; 17 | }) 18 | .join(' '); 19 | }; 20 | 21 | $scope.showSimpleToast = function (message) { 22 | $mdToast.show( 23 | $mdToast.simple() 24 | .content(message) 25 | .position($scope.getToastPosition()) 26 | .hideDelay(2000) 27 | ); 28 | }; 29 | 30 | $scope.toggleSidenav = function (menuId) { 31 | $mdSidenav(menuId).toggle(); 32 | }; 33 | 34 | $scope.changeState = function(state){ 35 | $state.go(state) 36 | }; 37 | 38 | $scope.logOut=function(){ 39 | userService.UserUid.set(''); 40 | localStorage.removeItem('toDoUser'); 41 | $scope.changeState('signIn') 42 | }; 43 | 44 | if(window.localStorage['toDoUser']) { 45 | 46 | $scope.todos = []; 47 | $scope.currentUser = userService.UserUid.get(); 48 | if($scope.currentUser==''){ 49 | $scope.currentUser=JSON.parse(localStorage.getItem('toDoUser')); 50 | userService.UserUid.set($scope.currentUser); 51 | } 52 | 53 | $scope.getTasksBy_uId = function () { 54 | $http.post((basePath+'/getTasks'),$scope.currentUser) 55 | .success(function (data) { 56 | console.log(data); 57 | $scope.remaining=0; 58 | $scope.todos = data.resObj; 59 | $scope.todos.forEach(function(a){ 60 | a.DueDate = new Date(a.DueDate) 61 | }); 62 | for(var i=0;i<$scope.todos.length;i++){ 63 | if($scope.todos[i].IsDone==false){ 64 | $scope.remaining++ 65 | } 66 | } 67 | }) 68 | .error(function (err) { 69 | console.log(err) 70 | }) 71 | }; 72 | 73 | $scope.getTasksBy_uId(); 74 | 75 | 76 | $scope.currentStateOfTasks = function(index){ 77 | //actionService.clickedTask.set($scope.todos[index]) 78 | $http.post((basePath+'/updateToDo'),$scope.todos[index]) 79 | .success(function (data) { 80 | console.log(data); 81 | $scope.remaining=0; 82 | for(var i=0;i<$scope.todos.length;i++){ 83 | if($scope.todos[i].IsDone==false){ 84 | $scope.remaining++ 85 | } 86 | } 87 | //$scope.todos = data.resObj; 88 | }) 89 | .error(function (err) { 90 | console.log(err) 91 | }) 92 | }; 93 | 94 | 95 | $scope.showAddNewTaskDialog = function (ev) { 96 | //$scope.currentStateOfTasks(); 97 | $mdDialog.show({ 98 | controller: 'addNewTaskController', 99 | templateUrl: 'partials/addNewTaskDialog.html', 100 | targetEvent: ev 101 | }).then(function () { 102 | $scope.getTasksBy_uId(); 103 | $scope.showSimpleToast('Task Added Success'); 104 | }); 105 | }; 106 | 107 | $scope.showEditTaskDialog = function (ev) { 108 | //$scope.currentStateOfTasks(); 109 | $mdDialog.show({ 110 | controller: 'editTaskController', 111 | templateUrl: 'partials/editTaskDialog.html', 112 | targetEvent: ev 113 | }).then(function () { 114 | $scope.getTasksBy_uId(); 115 | $scope.showSimpleToast('Task Edited Success'); 116 | }); 117 | }; 118 | 119 | $scope.showDeleteTaskDialog = function () { 120 | var confirm = $mdDialog.confirm() 121 | .title('Would you like to delete this Task?') 122 | .ok('Yes, Delete It.') 123 | .cancel('No'); 124 | 125 | $mdDialog.show(confirm) 126 | .then(function () { 127 | 128 | $scope.taskToDelete = actionService.clickedTask.get(); 129 | 130 | $http.post((basePath+'/deleteTodo'),$scope.taskToDelete) 131 | .success(function(data){ 132 | console.log(data); 133 | $mdDialog.hide(); 134 | $scope.getTasksBy_uId(); 135 | }) 136 | .error(function(err){ 137 | console.log(err) 138 | }); 139 | 140 | $mdDialog.show( 141 | $mdDialog.alert() 142 | .title('The Task has been deleted') 143 | .ok('Got it!') 144 | ); 145 | 146 | }, function () { 147 | console.log("Canceled Deleting"); 148 | }); 149 | }; 150 | 151 | $scope.showGridBottomSheet = function (index, ev) { 152 | $mdBottomSheet.show({ 153 | templateUrl: 'partials/bottomGridSheet.html', 154 | controller: 'bottomGridSheetController' 155 | }).then(function () { 156 | var clickedAction = actionService.clickedAction.get(); 157 | actionService.clickedTask.set($scope.todos[index]); 158 | 159 | if (clickedAction == 'edit') { 160 | $scope.showEditTaskDialog(ev) 161 | } 162 | else if (clickedAction == 'delete') { 163 | $scope.showDeleteTaskDialog() 164 | } 165 | else { 166 | console.log(clickedAction); 167 | } 168 | }); 169 | }; 170 | }else{ 171 | $scope.showSimpleToast("Please Sign In to Start"); 172 | $scope.changeState('signIn') 173 | } 174 | 175 | 176 | }); 177 | -------------------------------------------------------------------------------- /public/js/controllers/signInController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by M.JUNAID on 2015-03-09. 3 | */ 4 | 5 | materialToDo.controller('signInController', function(userService,$scope,$mdToast,$http,basePath,$state){ 6 | 7 | 8 | $scope.user={ 9 | userName:"", 10 | password:"" 11 | }; 12 | $scope.toastMessage = ''; 13 | $scope.isSignInClicked=false; 14 | 15 | $scope.changeState = function(state){ 16 | $state.go(state) 17 | }; 18 | 19 | $scope.signInCheck = function(){ 20 | if($scope.user.userName==''){ 21 | $scope.toastMessage = "UserName Cannot be Empty"; 22 | $scope.showSimpleToast() 23 | } else if($scope.user.password==''){ 24 | $scope.toastMessage = "Password Cannot be Empty"; 25 | $scope.showSimpleToast() 26 | } 27 | else{ 28 | $scope.signIn(); 29 | } 30 | }; 31 | 32 | $scope.signIn = function(){ 33 | $scope.isSignInClicked=true; 34 | console.log($scope.user); 35 | $http.post((basePath+'/signIn'),$scope.user) 36 | .success(function(data){ 37 | if(data.status==true){ 38 | console.log(data); 39 | userService.UserUid.set(data.resObj); 40 | localStorage.setItem('toDoUser',JSON.stringify(data.resObj)); 41 | $scope.toastMessage = 'User Sign In Successfully'; 42 | $scope.showSimpleToast(); 43 | $scope.changeState('home') 44 | }else{ 45 | if(data.err=="Username not found"){ 46 | $scope.toastMessage = data.err; 47 | $scope.showSimpleToast(); 48 | console.log(data); 49 | } 50 | else{ 51 | console.log(data); 52 | $scope.toastMessage = 'UserName Not Found'; 53 | $scope.showSimpleToast() 54 | } 55 | } 56 | }) 57 | .error(function (err) { 58 | console.log(err); 59 | $scope.toastMessage = 'Error in Signing In'; 60 | $scope.showSimpleToast() 61 | }); 62 | }; 63 | 64 | $scope.toastPosition = { 65 | bottom: true, 66 | top: false , 67 | left: false, 68 | right: true 69 | }; 70 | 71 | $scope.getToastPosition = function() { 72 | return Object.keys($scope.toastPosition) 73 | .filter(function(pos) { return $scope.toastPosition[pos]; }) 74 | .join(' '); 75 | }; 76 | 77 | $scope.showSimpleToast = function() { 78 | $mdToast.show( 79 | $mdToast.simple() 80 | .content($scope.toastMessage) 81 | .position($scope.getToastPosition()) 82 | .hideDelay(3000) 83 | ); 84 | }; 85 | }); -------------------------------------------------------------------------------- /public/js/controllers/signUpController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by M.JUNAID on 2015-03-09. 3 | */ 4 | 5 | materialToDo.controller('signUpController', function($scope,$http,basePath,$location,$mdToast){ 6 | 7 | $scope.user={ 8 | userName:"", 9 | firstName:"", 10 | lastName:"", 11 | email:"", 12 | password:"" 13 | }; 14 | 15 | $scope.cPassword=""; 16 | $scope.isSignUpClicked=false; 17 | 18 | $scope.signUp = function(){ 19 | if($scope.user.password==$scope.cPassword&&$scope.user.userName!==''&&$scope.user.firstName!==''&&$scope.user.email!==''){ 20 | $scope.isSignUpClicked=true; 21 | console.log($scope.user,$scope.cPassword); 22 | $http.post((basePath+'/signUp'),$scope.user) 23 | .success(function(data){ 24 | console.log(data); 25 | $scope.toastMessage = 'User Created Successfully'; 26 | $scope.showSimpleToast(); 27 | $location.path( "/signIn" ); 28 | }) 29 | .error(function (err) { 30 | console.log(err); 31 | $scope.toastMessage = 'Error in User Creation'+err; 32 | $scope.showSimpleToast() 33 | }) 34 | }else{ 35 | $scope.toastMessage = 'Please Fill the required fields'; 36 | $scope.showSimpleToast() 37 | } 38 | 39 | } 40 | 41 | 42 | $scope.toastPosition = { 43 | bottom: true, 44 | top: false , 45 | left: false, 46 | right: true 47 | }; 48 | 49 | $scope.getToastPosition = function() { 50 | return Object.keys($scope.toastPosition) 51 | .filter(function(pos) { return $scope.toastPosition[pos]; }) 52 | .join(' '); 53 | }; 54 | 55 | $scope.showSimpleToast = function() { 56 | $mdToast.show( 57 | $mdToast.simple() 58 | .content($scope.toastMessage) 59 | .position($scope.getToastPosition()) 60 | .hideDelay(3000) 61 | ); 62 | }; 63 | }); -------------------------------------------------------------------------------- /public/js/services/actionService.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by M.JUNAID on 2015-03-29. 3 | */ 4 | 5 | materialToDo.factory('actionService',function(){ 6 | var _clickedAction = ''; 7 | var _task = null; 8 | 9 | var _setAction = function(action){ 10 | _clickedAction = action 11 | 12 | }; 13 | 14 | var _getAction = function(){ 15 | return _clickedAction 16 | }; 17 | 18 | var _setTaskForAction = function(index){ 19 | _task = index 20 | 21 | }; 22 | 23 | var _getTaskForAction = function(){ 24 | return _task 25 | }; 26 | 27 | return{ 28 | clickedAction:{ 29 | set:_setAction, 30 | get:_getAction 31 | }, 32 | clickedTask:{ 33 | set:_setTaskForAction, 34 | get:_getTaskForAction 35 | } 36 | } 37 | 38 | }); -------------------------------------------------------------------------------- /public/js/services/userService.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by M.JUNAID on 2015-03-29. 3 | */ 4 | 5 | materialToDo.factory('userService',function(){ 6 | var _signedInUserUid = ''; 7 | 8 | var _setUserUid = function(Uid){ 9 | _signedInUserUid = Uid 10 | 11 | }; 12 | 13 | var _getUserUid = function(){ 14 | return _signedInUserUid 15 | }; 16 | 17 | 18 | return{ 19 | UserUid:{ 20 | set:_setUserUid, 21 | get:_getUserUid 22 | } 23 | } 24 | 25 | }); -------------------------------------------------------------------------------- /public/partials/about.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | About the Developer 6 |
7 |
8 | 9 | 10 | 11 |
12 |
13 |

Muhammad Junaid Salaat

14 |
15 |

16 | As a Web Developer and a UI Designer, I am excellent at building SPA (Single Page Applications) using the following: Javascript, Angularjs, Ionic, Node.js, Express.js, MongoDB, PhoneGap, Firebase, Parse. Bootstrap, CSS3, HTML5 and ejs templates. 17 |

18 |
19 |

20 | If you like this project . Please Star it here. You can view it complete here. MaterialToDo 21 |

22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 |
30 | 31 |
32 |
33 |
34 | 35 | 36 | 37 | 38 |
mjunaidsalaat@gmail.com
39 |
/in/mjunaidsalaat
40 |
/muhammadjunaid.mj
41 |
m.junaid_mj
42 | 43 | 44 |
45 |
46 |
47 |
48 |
-------------------------------------------------------------------------------- /public/partials/addNewTaskDialog.html: -------------------------------------------------------------------------------- 1 | 2 |

Add a ToDo

3 | 4 |
5 |
6 | 7 | 8 | 9 | 10 |
11 |
12 | 13 |
14 | 15 | 16 | 17 | 18 |
19 |
20 | 21 |
22 |

Priority

23 | 24 | High 25 | Medium 26 | Low 27 | 28 |
29 | 30 |
31 |
32 | 33 | 34 | 35 | 36 |
37 |
38 | 39 |
40 | 41 |
42 | 43 | 44 | Cancel 45 | 46 | 47 | 48 | Done 49 | 50 |
51 |
52 | 53 | -------------------------------------------------------------------------------- /public/partials/bottomGridSheet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 |
8 |

Edit

9 |
10 |
11 | 12 | 13 | 14 |
15 | 16 |
17 |

Delete

18 |
19 |
20 | 21 | 22 | 23 |
24 | 25 |
26 |

Nothing

27 |
28 |
29 |
30 |
-------------------------------------------------------------------------------- /public/partials/editTaskDialog.html: -------------------------------------------------------------------------------- 1 | 2 |

Edit ToDo

3 | 4 |
5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 |
15 | 16 |

Priority

17 | 18 | High 19 | Medium 20 | Low 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 |
32 | 33 | 34 | Cancel 35 | 36 | 37 | 38 | Done 39 | 40 |
41 |
42 | 43 | -------------------------------------------------------------------------------- /public/partials/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 |

Material ToDo

7 | 8 |
9 |
10 | 11 | 12 |

Welcome  {{currentUser.FirstName}} {{currentUser.LastName}}

13 |
14 | 15 | 36 | 37 |
38 |
39 |
40 | 41 | Status : You have {{todos.length}} Tasks from which {{remaining}} remains. 42 | 43 |
44 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 52 | 53 | Actions 54 | 55 | 56 |
57 |
58 |

Due Date

59 |
60 |
61 | 62 | 63 |
64 | 65 | 66 |
67 |
68 |

{{item.Task}}

69 |

Description: {{item.Desc}}

70 | 71 | Priority : 72 | {{item.Priority}} 73 | 74 | 75 | {{item.Priority}} 76 | 77 | 78 | {{item.Priority}} 79 | 80 | 81 |
82 |
83 |
84 | 85 |
86 |
87 | 88 |
89 |
90 | 91 | 92 | 93 | Add New 94 | 95 | 96 | 97 |
98 | -------------------------------------------------------------------------------- /public/partials/signIn.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 |
6 | Sign In 7 |
8 |
9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | Sign In 30 |
31 |
32 |
33 |
34 |
Don't have an Account?
35 |
36 | Create an Account 37 |
38 |
39 | 40 |
41 |
42 |
43 |
44 |
45 |
46 | 47 |
48 |
49 | 50 |
51 | 52 |
53 | -------------------------------------------------------------------------------- /public/partials/signUp.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | Sign Up 6 |
7 |
8 | 9 |
10 | 11 | 12 |
13 | 14 | 15 | 16 |
17 |
User name is required.
18 |
19 |
20 |
21 |
22 | 23 | 24 | 25 |
26 |
First name is required.
27 |
28 |
29 | 30 | 31 | 32 | 33 |
34 |
35 | 36 | 37 | 38 |
39 |
Email is required.
40 |
41 |
42 |
43 |
44 | 45 | 46 | 47 |
48 |
Set some password
49 |
50 |
51 | 52 | 53 | 54 |
55 |
Confirm it here
56 |
57 |
58 |
59 | 60 |
61 |
62 |
63 | Sign Up 64 |
65 |
66 | 67 |
68 | 69 |
70 |
71 | 72 |
73 |
74 |
75 | 76 | 77 | 78 |
79 |
80 |
81 | 82 |
83 | -------------------------------------------------------------------------------- /public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | var userModel = require("../models/userModel.js"); 5 | var toDoModel = require("../models/toDoModel.js"); 6 | 7 | /* GET home page. */ 8 | 9 | router.get('*', function(req, res, next) { 10 | res.render('index', {}); 11 | }); 12 | 13 | 14 | /* POST home listings. */ 15 | 16 | router.post('/signUp',function(req,res){ 17 | console.log(req.body); 18 | 19 | var userData = { 20 | UserName : req.body.userName, 21 | FirstName:req.body.firstName, 22 | LastName:req.body.lastName, 23 | Email:req.body.email, 24 | Password:req.body.password 25 | }; 26 | 27 | userModel.saveUserToDb(userData) 28 | .then(function (){ 29 | res.send({status:true}); 30 | }, function (err){ 31 | res.send({status: false, err : err}); 32 | }) 33 | }); 34 | 35 | router.post('/signIn',function(req,res){ 36 | console.log(req.body); 37 | 38 | var userData = { 39 | userName : req.body.userName, 40 | password : req.body.password 41 | }; 42 | 43 | userModel.signInUserFromDb(userData) 44 | .then(function (data){ 45 | if(data!==null){ 46 | res.send({status:true, resObj : data._doc}); 47 | } 48 | else{ 49 | res.send({status:false, resObj : "Username not found"}); 50 | } 51 | }, function (err){ 52 | res.send({status: false, resObj : err}); 53 | }) 54 | }); 55 | 56 | router.post('/getTasks', function(req,res){ 57 | //console.log(req.body); 58 | var UiD = req.body._id; 59 | 60 | toDoModel.ToDoFromDbByUid(UiD) 61 | .then(function (data){ 62 | if(data!==null){ 63 | res.send({status:true, resObj : data}); 64 | } 65 | else{ 66 | res.send({status:false, resObj : "ToDo's not found"}); 67 | } 68 | }, function (err){ 69 | res.send({status: false, resObj : err}); 70 | }) 71 | 72 | }); 73 | 74 | router.post('/saveNewTodo', function(req,res){ 75 | var newTodo = { 76 | UiD: req.body.Uid, 77 | Task: req.body.task, 78 | Desc: req.body.desc, 79 | IsDone: req.body.isDone, 80 | Priority: req.body.priority, 81 | DueDate: req.body.dueDate 82 | }; 83 | toDoModel.saveToDoToDb(newTodo) 84 | .then(function (){ 85 | res.send({status:true}); 86 | }, function (err){ 87 | res.send({status: false, err : err}); 88 | }) 89 | }); 90 | 91 | router.post('/editTodo', function(req,res){ 92 | //console.log(req.body); 93 | var todoToEdit = { 94 | Task: req.body.Task, 95 | Desc: req.body.Desc, 96 | IsDone: req.body.IsDone, 97 | Priority: req.body.Priority, 98 | DueDate: req.body.DueDate 99 | }; 100 | var idToEdit = req.body._id; 101 | 102 | toDoModel.editToDo(idToEdit,todoToEdit) 103 | .then(function (data){ 104 | res.send({status:true , resObj: data}); 105 | }, function (err){ 106 | res.send({status: false, err : err}); 107 | }) 108 | }); 109 | 110 | router.post('/updateToDo', function(req,res){ 111 | console.log(req.body); 112 | var todoToUpdate = { 113 | IsDone: req.body.IsDone 114 | }; 115 | var idToEdit = req.body._id; 116 | 117 | toDoModel.editToDo(idToEdit,todoToUpdate) 118 | .then(function (data){ 119 | res.send({status:true , resObj: data}); 120 | }, function (err){ 121 | res.send({status: false, err : err}); 122 | }) 123 | }); 124 | 125 | router.post('/deleteTodo', function(req,res){ 126 | var idToEdit = req.body._id; 127 | 128 | toDoModel.deleteToDo(idToEdit) 129 | .then(function (data){ 130 | res.send({status:true , resObj: data}); 131 | }, function (err){ 132 | res.send({status: false, err : err}); 133 | }) 134 | }); 135 | 136 | module.exports = router; 137 | -------------------------------------------------------------------------------- /routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | -------------------------------------------------------------------------------- /views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular To Do App 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | --------------------------------------------------------------------------------