├── .gitignore ├── .jshintrc ├── README.md ├── app ├── controller │ └── todoController.js ├── dao │ └── todoDao.js ├── domain │ └── todoDomain.js ├── model │ └── todoModel.js └── service │ └── todoService.js ├── config.js ├── config ├── dev │ └── mysql.json └── prod │ └── mysql.json ├── context.json ├── package.json ├── patch.js ├── public ├── images │ ├── doing.gif │ ├── finished.jpg │ └── webpy_ss.png └── styles │ ├── index │ ├── images │ │ ├── bg_1.png │ │ ├── email.png │ │ ├── home.png │ │ ├── msn.png │ │ ├── ok.gif │ │ ├── qq.png │ │ └── website.png │ └── style.css │ └── reset.css ├── server.js ├── todo.sql └── views ├── error.html ├── index.html ├── layout.html └── todo └── edit.html /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "predef": [ 3 | "phantom", 4 | "module", 5 | "require", 6 | "__dirname", 7 | "process", 8 | "console", 9 | "it", 10 | "describe", 11 | "before", 12 | "beforeEach", 13 | "after", 14 | "should", 15 | "rewire", 16 | "$" 17 | ], 18 | 19 | "browser": true, 20 | "node" : true, 21 | "es5": true, 22 | "bitwise": true, 23 | "curly": true, 24 | "eqeqeq": true, 25 | "forin": false, 26 | "immed": true, 27 | "latedef": true, 28 | "newcap": true, 29 | "noarg": true, 30 | "noempty": true, 31 | "nonew": true, 32 | "plusplus": false, 33 | "undef": true, 34 | "strict": false, 35 | "trailing": false, 36 | "globalstrict": true, 37 | "nonstandard": true, 38 | "white": true, 39 | "indent": 2, 40 | "expr": true, 41 | "multistr": true, 42 | "onevar": false 43 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple TODO 2 | 3 | ## Description 4 | 5 | this is a simple web application todo, it is written by [Bearcat](https://github.com/bearcatnode/bearcat) to manage business objects and enable to write simple POJOs. [Bearcat-dao](https://github.com/bearcatnode/bearcat-dao) is also used to manage database O/R mapping. This demo is easy, simple and mantainable. 6 | 7 | ## Install 8 | 9 | ``` 10 | git clone https://github.com/bearcatnode/todo.git 11 | cd todo 12 | npm install 13 | ``` 14 | 15 | ## Update Mysql 16 | 17 | create database with configuration corresponded to [dev mysql.json](https://github.com/bearcatnode/todo/blob/master/config/dev/mysql.json) 18 | execute [todo.sql](https://github.com/bearcatnode/todo/blob/master/todo.sql) 19 | 20 | ## Run 21 | 22 | ``` 23 | node server.js 24 | ``` 25 | 26 | ## Run with prod env 27 | 28 | update configuration in [prod dir](https://github.com/bearcatnode/todo/tree/master/config/prod) 29 | 30 | ``` 31 | node server.js env=prod 32 | ``` 33 | 34 | ## License 35 | 36 | (The MIT License) 37 | 38 | Copyright (c) 2011, 2012 fengmk2 . 39 | Copyright (c) 2014, fantasyni . 40 | 41 | Permission is hereby granted, free of charge, to any person obtaining 42 | a copy of this software and associated documentation files (the 43 | 'Software'), to deal in the Software without restriction, including 44 | without limitation the rights to use, copy, modify, merge, publish, 45 | distribute, sublicense, and/or sell copies of the Software, and to 46 | permit persons to whom the Software is furnished to do so, subject to 47 | the following conditions: 48 | 49 | The above copyright notice and this permission notice shall be 50 | included in all copies or substantial portions of the Software. 51 | 52 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 53 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 54 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 55 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 56 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 57 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 58 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /app/controller/todoController.js: -------------------------------------------------------------------------------- 1 | var bearcat = require('bearcat'); 2 | 3 | var TodoController = function() { 4 | this.$id = "todoController"; 5 | this.$todoService = null; 6 | } 7 | 8 | TodoController.prototype.index = function(req, res, next) { 9 | this.$todoService.getList([0, 50], function(err, results) { 10 | if (err) { 11 | console.log(err); 12 | return; 13 | } 14 | 15 | var r = []; 16 | for (var i = 0; i < results.length; i++) { 17 | r.push(results[i].toJSON()); 18 | } 19 | 20 | res.render('index.html', { 21 | todos: r 22 | }); 23 | }); 24 | } 25 | 26 | TodoController.prototype.new = function(req, res, next) { 27 | var title = req.body.title || ''; 28 | title = title.trim(); 29 | if (!title) { 30 | return res.render('error.html', { 31 | message: '标题是必须的' 32 | }); 33 | } 34 | 35 | var todoModel = bearcat.getModel("todoModel"); 36 | var r = todoModel.$pack({ 37 | title: title, 38 | post_date: Date.now() 39 | }); 40 | 41 | if (r) { 42 | console.log(r.stack); 43 | return res.render('error.html', { 44 | message: r.message 45 | }); 46 | } 47 | 48 | this.$todoService.addTodo(todoModel, function(err, result) { 49 | if (err) { 50 | return next(err); 51 | } 52 | res.redirect('/'); 53 | }) 54 | } 55 | 56 | TodoController.prototype.view = function(req, res, next) { 57 | res.redirect('/'); 58 | } 59 | 60 | TodoController.prototype.edit = function(req, res, next) { 61 | var id = req.params.id; 62 | this.$todoService.getTodoById(id, function(err, result) { 63 | if (err) { 64 | return next(err); 65 | } 66 | 67 | if (!result) { 68 | return next(); 69 | } 70 | 71 | result = result[0]; 72 | res.render('todo/edit.html', { 73 | todo: result.toJSON() 74 | }); 75 | }); 76 | } 77 | 78 | TodoController.prototype.save = function(req, res, next) { 79 | var id = req.params.id; 80 | var title = req.body.title || ''; 81 | title = title.trim(); 82 | if (!title) { 83 | return res.render('error.html', { 84 | message: '标题是必须的' 85 | }); 86 | } 87 | 88 | this.$todoService.updateTodo(title, id, function(err, result) { 89 | if (err) { 90 | return next(err); 91 | } 92 | res.redirect('/'); 93 | }); 94 | } 95 | 96 | TodoController.prototype.delete = function(req, res, next) { 97 | var id = req.params.id; 98 | 99 | this.$todoService.deleteById(id, function(err, result) { 100 | if (err) { 101 | return next(err); 102 | } 103 | res.redirect('/'); 104 | }); 105 | } 106 | 107 | TodoController.prototype.finish = function(req, res, next) { 108 | var finished = req.query.status === 'yes' ? 1 : 0; 109 | var id = req.params.id; 110 | 111 | this.$todoService.updateTodoFinished(finished, id, function(err, result) { 112 | if (err) { 113 | return next(err); 114 | } 115 | res.redirect('/'); 116 | }); 117 | } 118 | 119 | module.exports = TodoController; -------------------------------------------------------------------------------- /app/dao/todoDao.js: -------------------------------------------------------------------------------- 1 | var TodoDao = function() { 2 | this.$id = "todoDao"; 3 | this.$domainDaoSupport = null; 4 | this.$init = "init"; 5 | } 6 | 7 | TodoDao.prototype.init = function() { 8 | this.$domainDaoSupport.initConfig("todoModel"); 9 | } 10 | 11 | TodoDao.prototype.transaction = function(txStatus) { 12 | this.$domainDaoSupport.transaction(txStatus); 13 | return this; 14 | } 15 | 16 | TodoDao.prototype.getList = function(params, cb) { 17 | var sql = ' 1=1 order by finished asc, id asc limit ?,?'; 18 | return this.$domainDaoSupport.getListByWhere(sql, params, null, cb); 19 | } 20 | 21 | TodoDao.prototype.addTodo = function(obj, cb) { 22 | return this.$domainDaoSupport.add(obj, cb); 23 | } 24 | 25 | TodoDao.prototype.getTodoById = function(id, cb) { 26 | return this.$domainDaoSupport.getById(id, cb); 27 | } 28 | 29 | TodoDao.prototype.updateTodo = function(title, id, cb) { 30 | var sql = 'update bearcat_todo set title = ? where id = ?'; 31 | return this.$domainDaoSupport.update(sql, [title, id], cb); 32 | } 33 | 34 | TodoDao.prototype.updateTodoFinished = function(finished, id, cb) { 35 | var sql = 'update bearcat_todo set finished = ? where id = ?'; 36 | return this.$domainDaoSupport.update(sql, [finished, id], cb); 37 | } 38 | 39 | TodoDao.prototype.deleteById = function(id, cb) { 40 | return this.$domainDaoSupport.deleteById(id, cb); 41 | } 42 | 43 | module.exports = TodoDao; -------------------------------------------------------------------------------- /app/domain/todoDomain.js: -------------------------------------------------------------------------------- 1 | var TodoDomain = function() { 2 | this.id = null; 3 | this.title = null; 4 | this.finished = 0; 5 | this.post_date = 0; 6 | } 7 | 8 | TodoDomain.prototype.setId = function(id) { 9 | this.id = id; 10 | } 11 | 12 | TodoDomain.prototype.getId = function() { 13 | return this.id; 14 | } 15 | 16 | TodoDomain.prototype.setTitle = function(title) { 17 | this.title = title; 18 | } 19 | 20 | TodoDomain.prototype.getTitle = function() { 21 | return this.title; 22 | } 23 | 24 | TodoDomain.prototype.setFinished = function(finished) { 25 | this.finished = finished; 26 | } 27 | 28 | TodoDomain.prototype.getFinished = function() { 29 | return this.finished; 30 | } 31 | 32 | TodoDomain.prototype.setPost_date = function(post_date) { 33 | this.post_date = post_date; 34 | } 35 | 36 | TodoDomain.prototype.getPost_date = function() { 37 | return this.post_date; 38 | } 39 | 40 | module.exports = { 41 | func: TodoDomain, 42 | primary: [{ 43 | name: "id", 44 | type: "Long" 45 | }], 46 | fields: ["title", "finished", "post_date"], 47 | tableName: "bearcat_todo" 48 | } -------------------------------------------------------------------------------- /app/model/todoModel.js: -------------------------------------------------------------------------------- 1 | var TodoModel = function() { 2 | this.$mid = "todoModel"; 3 | this.$table = "bearcat_todo"; 4 | this.id = "$primary;type:Number;default:0"; 5 | this.title = "$type:String"; 6 | this.finished = "$type:Number;default:0"; 7 | this.post_date = "$type:Number;default:0"; 8 | } 9 | 10 | module.exports = TodoModel; -------------------------------------------------------------------------------- /app/service/todoService.js: -------------------------------------------------------------------------------- 1 | var TodoService = function() { 2 | this.$id = "todoService"; 3 | this.$todoDao = null; 4 | } 5 | 6 | TodoService.prototype.getList = function(params, cb) { 7 | return this.$todoDao.getList(params, cb); 8 | } 9 | 10 | TodoService.prototype.addTodo = function(obj, cb) { 11 | return this.$todoDao.addTodo(obj, cb); 12 | } 13 | 14 | TodoService.prototype.getTodoById = function(id, cb) { 15 | return this.$todoDao.getTodoById(id, cb); 16 | } 17 | 18 | TodoService.prototype.updateTodo = function(title, id, cb) { 19 | return this.$todoDao.updateTodo(title, id, cb); 20 | } 21 | 22 | TodoService.prototype.updateTodoFinished = function(finished, id, cb) { 23 | return this.$todoDao.updateTodoFinished(finished, id, cb); 24 | } 25 | 26 | TodoService.prototype.deleteById = function(id, cb) { 27 | return this.$todoDao.deleteById(id, cb); 28 | } 29 | 30 | module.exports = TodoService; -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * todo - config.js 3 | * Copyright(c) 2012 fengmk2 4 | * MIT Licensed 5 | */ 6 | 7 | "use strict"; 8 | 9 | exports.debug = true; 10 | exports.port = 3000; 11 | exports.email = 'fengmk2@gmail.com'; 12 | exports.site_name = 'Node Bearcat TODO'; 13 | exports.site_desc = 'Very simple todo, demo for connect web dev.'; 14 | exports.session_secret = 'todo session secret'; 15 | -------------------------------------------------------------------------------- /config/dev/mysql.json: -------------------------------------------------------------------------------- 1 | { 2 | "mysql.port": 5331, 3 | "mysql.host": "localhost", 4 | "mysql.user": "root", 5 | "mysql.password": "test", 6 | "mysql.database": "bearcat_todo" 7 | } -------------------------------------------------------------------------------- /config/prod/mysql.json: -------------------------------------------------------------------------------- 1 | { 2 | "mysql.port": 3306, 3 | "mysql.host": "localhost", 4 | "mysql.user": "root", 5 | "mysql.password": "test", 6 | "mysql.database": "bearcat_test" 7 | } -------------------------------------------------------------------------------- /context.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bearcat-todo", 3 | "dependencies": { 4 | "bearcat-dao": "*" 5 | }, 6 | "scan": "app", 7 | "beans": [{ 8 | "id": "mysqlConnectionManager", 9 | "func": "node_modules.bearcat-dao.lib.connection.sql.mysqlConnectionManager", 10 | "props": [{ 11 | "name": "port", 12 | "value": "${mysql.port}" 13 | }, { 14 | "name": "host", 15 | "value": "${mysql.host}" 16 | }, { 17 | "name": "user", 18 | "value": "${mysql.user}" 19 | }, { 20 | "name": "password", 21 | "value": "${mysql.password}" 22 | }, { 23 | "name": "database", 24 | "value": "${mysql.database}" 25 | }] 26 | }] 27 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "author": "fengmk2 (http://fengmk2.github.com/)", 4 | "name": "todo", 5 | "description": "Very simple todo, demo for connect web dev.", 6 | "version": "0.3.0", 7 | "homepage": "http://github.com/bearcatnode/todo", 8 | "repository": { 9 | "type": "git", 10 | "url": "git://github.com/bearcatnode/todo.git" 11 | }, 12 | "main": "server.js", 13 | "dependencies": { 14 | "connect": "1.x", 15 | "connect-render": ">=0.1.4", 16 | "urlrouter": ">=0.2.0", 17 | "bearcat": "0.4.x", 18 | "bearcat-dao": "0.2.x" 19 | }, 20 | "devDependencies": { 21 | "should": "*", 22 | "mocha": "*" 23 | }, 24 | "optionalDependencies": {}, 25 | "engines": { 26 | "node": ">= 0.6" 27 | } 28 | } -------------------------------------------------------------------------------- /patch.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * todo - lib/patch.js 3 | * Copyright(c) 2012 fengmk2 4 | * MIT Licensed 5 | */ 6 | 7 | "use strict"; 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | var http = require('http'); 14 | 15 | if (typeof http.ServerResponse.prototype.redirect === 'undefined') { 16 | http.ServerResponse.prototype.redirect = function (url, status) { 17 | this.writeHead(status || 302, { 18 | Location: url 19 | }); 20 | this.end(); 21 | }; 22 | } -------------------------------------------------------------------------------- /public/images/doing.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bearcatjs/todo/9360f217ab43f6ff2f8ad759e7c49c5fff3528c9/public/images/doing.gif -------------------------------------------------------------------------------- /public/images/finished.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bearcatjs/todo/9360f217ab43f6ff2f8ad759e7c49c5fff3528c9/public/images/finished.jpg -------------------------------------------------------------------------------- /public/images/webpy_ss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bearcatjs/todo/9360f217ab43f6ff2f8ad759e7c49c5fff3528c9/public/images/webpy_ss.png -------------------------------------------------------------------------------- /public/styles/index/images/bg_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bearcatjs/todo/9360f217ab43f6ff2f8ad759e7c49c5fff3528c9/public/styles/index/images/bg_1.png -------------------------------------------------------------------------------- /public/styles/index/images/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bearcatjs/todo/9360f217ab43f6ff2f8ad759e7c49c5fff3528c9/public/styles/index/images/email.png -------------------------------------------------------------------------------- /public/styles/index/images/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bearcatjs/todo/9360f217ab43f6ff2f8ad759e7c49c5fff3528c9/public/styles/index/images/home.png -------------------------------------------------------------------------------- /public/styles/index/images/msn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bearcatjs/todo/9360f217ab43f6ff2f8ad759e7c49c5fff3528c9/public/styles/index/images/msn.png -------------------------------------------------------------------------------- /public/styles/index/images/ok.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bearcatjs/todo/9360f217ab43f6ff2f8ad759e7c49c5fff3528c9/public/styles/index/images/ok.gif -------------------------------------------------------------------------------- /public/styles/index/images/qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bearcatjs/todo/9360f217ab43f6ff2f8ad759e7c49c5fff3528c9/public/styles/index/images/qq.png -------------------------------------------------------------------------------- /public/styles/index/images/website.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bearcatjs/todo/9360f217ab43f6ff2f8ad759e7c49c5fff3528c9/public/styles/index/images/website.png -------------------------------------------------------------------------------- /public/styles/index/style.css: -------------------------------------------------------------------------------- 1 | body { background:#EEE; } 2 | .box { margin-bottom:20px; } 3 | .clear { clear:both; } 4 | .float_left { float:left; } 5 | .float_right { float:right; } 6 | .left { text-align:left; } 7 | .right { text-align:right; } 8 | .url { background:url(images/website.png) no-repeat right; padding-right:20px; } 9 | .tips { color:#CCC; } 10 | .v_top { vertical-align:top; } 11 | .qq { background:url(images/qq.png) no-repeat right; padding-right:20px; } 12 | .msn { background:url(images/msn.png) no-repeat right; padding-right:20px; } 13 | .email { background:url(images/email.png) no-repeat right; padding-right:20px; } 14 | .tips { color:#666; } 15 | .long_txt { width:98%; } 16 | .must_be { color:red !important; } 17 | textarea { line-height:1.5em; } 18 | 19 | image { border:none; } 20 | p { line-height:1.5em; } 21 | 22 | a { color:#3366CC; text-decoration:underline; } 23 | a:hover { color:#FF3300; } 24 | 25 | .page { width:700px; margin:10px auto; background:#FFF; padding:10px 20px; border:1px solid #CCC; border-radius:5px; } 26 | 27 | .header { padding-top:10px; border-bottom:1px solid #CCC; } 28 | .header h1 { font-size:50px; } 29 | .header a { color:#333; text-decoration:none; } 30 | 31 | .main { } 32 | .main_content { } 33 | 34 | .box h2 { padding-bottom:5px; margin-bottom:10px; font-weight:400; color:green; font-size:28px;} 35 | 36 | .todos {} 37 | .todos ul li { list-style-type:none; margin-bottom:10px; padding-bottom:10px; border-bottom:1px dotted #CCC; } 38 | .todos ul li.finished { color:#666; } 39 | .todos ul li a { color:#666; } 40 | .todos ul li del { padding-left:15px; background:url(images/ok.gif) no-repeat left center; } 41 | 42 | .post { } 43 | .post p { margin-bottom:10px; } 44 | .post .submit { line-height:normal; -padding:0; } 45 | 46 | 47 | 48 | .foot { border-top:1px solid #CCC; color:#666; padding-top:10px; font-size:11px; } 49 | .foot img { vertical-align:top; } 50 | 51 | -------------------------------------------------------------------------------- /public/styles/reset.css: -------------------------------------------------------------------------------- 1 | /* 2 | KISSY CSS Reset 3 | 理念:清除和重置是紧密不可分的 4 | 特色:1.适应中文 2.基于最新主流浏览器 5 | 维护:玉伯(lifesinger@gmail.com), 正淳(ragecarrier@gmail.com) 6 | */ 7 | 8 | /* 清除内外边距 */ 9 | body, h1, h2, h3, h4, h5, h6, p, blockquote, /* structural elements 结构元素 */ 10 | dl, dt, dd, ul, ol, li, /* list elements 列表元素 */ 11 | pre, /* text formatting elements 文本格式元素 */ 12 | fieldset, lengend, button, input, textarea, /* form elements 表单元素 */ 13 | th, td { /* table elements 表格元素 */ 14 | margin: 0; 15 | padding: 0; 16 | } 17 | 18 | /* 设置默认字体 */ 19 | body, 20 | button, input, select, textarea { /* for ie */ 21 | /*font: 12px/1 Tahoma, Helvetica, Arial, "宋体", sans-serif;*/ 22 | font: 14px/1.5 Arial, sans-serif; 23 | padding:3px; 24 | } 25 | input { line-height:normal; } 26 | h1 { font-size:24px; } 27 | h2 { font-size:20px; } 28 | h3 { font-size:18px; } 29 | h4 { font-size:18px; } 30 | h5 { font-size:14px; } 31 | h1, h2, h3, h4, h5 { font-weight:normal; } 32 | 33 | address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */ 34 | small { font-size: 11px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */ 35 | 36 | /* 重置文本格式元素 */ 37 | a { color:#03C; } 38 | a:hover { color:#F30; } 39 | 40 | abbr[title], acronym[title] { /* 注:1.ie6 不支持 abbr; 2.这里用了属性选择符,ie6 下无效果 */ 41 | border-bottom: 1px dotted; 42 | cursor: help; 43 | } 44 | 45 | q:before, q:after { content: ''; } 46 | 47 | /* 重置表单元素 */ 48 | legend { color: #000; } /* for ie6 */ 49 | fieldset, img { border: none; } /* img 搭车:让链接里的 img 无边框 */ 50 | /* 注:optgroup 无法扶正 */ 51 | button, input, select, textarea { 52 | font-size: 100%; /* 使得表单元素在 ie 下能继承字体大小 */ 53 | } 54 | 55 | /* 重置表格元素 */ 56 | table { 57 | border-collapse: collapse; 58 | border-spacing: 0; 59 | } 60 | 61 | /* 让非ie浏览器默认也显示垂直滚动条,防止因滚动条引起的闪烁 */ 62 | html { overflow-y: scroll; } 63 | 64 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * todo - app.js 3 | * Copyright(c) 2012 fengmk2 4 | * MIT Licensed 5 | */ 6 | 7 | "use strict"; 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | require('./patch'); 13 | var connect = require('connect'); 14 | var render = require('connect-render'); 15 | var urlrouter = require('urlrouter'); 16 | var config = require('./config'); 17 | var Bearcat = require('bearcat'); 18 | 19 | var app = connect(); 20 | 21 | process.env.BEARCAT_DEBUG = true; 22 | 23 | app.use('/public', connect.static(__dirname + '/public', { 24 | maxAge: 3600000 * 24 * 30 25 | })); 26 | app.use(connect.cookieParser()); 27 | app.use(connect.query()); 28 | app.use(connect.bodyParser()); 29 | app.use(connect.session({ 30 | secret: config.session_secret 31 | })); 32 | // app.use(connect.csrf()); 33 | app.use(render({ 34 | root: __dirname + '/views', 35 | layout: 'layout.html', 36 | cache: config.debug, // `false` for debug 37 | helpers: { 38 | config: config, 39 | _csrf: function(req, res) { 40 | return req.session._csrf; 41 | } 42 | } 43 | })); 44 | 45 | var contextPath = require.resolve('./context.json'); 46 | 47 | var bearcat = Bearcat.createApp([contextPath]); 48 | 49 | bearcat.start(function() { 50 | /** 51 | * Routing 52 | */ 53 | // var todoController = bearcat.getBean('todoController'); 54 | 55 | /** 56 | * Routing 57 | */ 58 | var router = urlrouter(function(app) { 59 | app.get('/', bearcat.getRoute("todoController", "index")); 60 | app.post('/todo/new', bearcat.getRoute("todoController", "new")); 61 | app.get('/todo/:id', bearcat.getRoute("todoController", "view")); 62 | app.get('/todo/:id/edit', bearcat.getRoute("todoController", "edit")); 63 | app.post('/todo/:id/edit', bearcat.getRoute("todoController", "save")); 64 | app.get('/todo/:id/delete', bearcat.getRoute("todoController", "delete")); 65 | app.get('/todo/:id/finish', bearcat.getRoute("todoController", "finish")); 66 | }); 67 | app.use(router); 68 | 69 | // start app 70 | app.listen(config.port); 71 | console.log('Server start on ' + config.port); 72 | }); -------------------------------------------------------------------------------- /todo.sql: -------------------------------------------------------------------------------- 1 | SET FOREIGN_KEY_CHECKS=0; 2 | -- ---------------------------- 3 | -- Table structure for todo 4 | -- ---------------------------- 5 | DROP TABLE IF EXISTS `bearcat_todo`; 6 | CREATE TABLE `bearcat_todo` ( 7 | `id` bigint(20) NOT NULL, 8 | `title` varchar(300) default NULL, 9 | `finished` int(11) default 0, 10 | `post_date` bigint(20) default 0, 11 | PRIMARY KEY (`id`) 12 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 13 | 14 | create table IDGenerator( 15 | name varchar(50) NOT NULL, 16 | id bigint(20) unsigned NOT NULL DEFAULT 0, 17 | 18 | PRIMARY KEY (name) 19 | )ENGINE=InnoDB DEFAULT CHARSET=utf8; 20 | 21 | insert into IDGenerator (name, id) values ('bearcat_todo', 0); -------------------------------------------------------------------------------- /views/error.html: -------------------------------------------------------------------------------- 1 | 10 |
11 |

12 | <%= message %> 13 |

14 |

15 | 返回 | 16 | 首页 17 |

18 |
19 | -------------------------------------------------------------------------------- /views/index.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

待办事项

5 |
    6 | <% for (var i = 0, len = todos.length; i < len; i++) { 7 | var todo = todos[i]; 8 | var status = todo.finished ? 'class="finished"' : ''; 9 | %> 10 |
  • > 11 | <% if (!todo.finished) { %> 12 | <%= todo.title %> 13 |   14 | 完成, 15 | <% } else { %> 16 | <%= todo.title %> 17 |   18 | 恢复, 19 | <% } %> 20 | 修改, 21 | 删除 22 |
  • 23 | <% } %> 24 |
25 |
26 | 27 |
28 |

新增

29 |
30 |

31 |

32 |
33 |
34 | 35 |
36 | 37 | -------------------------------------------------------------------------------- /views/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <%= config.site_name %> 6 | 7 | 8 | 9 | 10 |
11 | 14 | 15 |
16 | <%- body %> 17 |
18 | 19 |
20 | Copyright© <%= config.site_name %> 21 | Bearcat 22 |
23 |
24 |
25 | 26 | -------------------------------------------------------------------------------- /views/todo/edit.html: -------------------------------------------------------------------------------- 1 |
2 |

修改

3 |
4 |

5 |

6 |
7 |
8 | 9 | --------------------------------------------------------------------------------