정소현

new file: app.js

	new file:   bin/www
	new file:   models/boardsSchema.js
	new file:   package.json
	new file:   public/images/noImage.jpg
	new file:   "public/images/\352\263\240\354\247\204\353\247\216\353\217\204\354\213\234\353\235\2751\355\216\270.jpg"
	new file:   "public/images/\352\263\240\354\266\224\354\260\270\354\271\230\354\202\274\352\260\201\352\271\200\353\260\245.jpg"
	new file:   "public/images/\353\215\224\355\201\260)\353\266\210\352\263\240\352\270\260\354\243\274\353\250\271\353\260\2451\355\216\270.jpg"
	new file:   "public/images/\353\215\224\355\201\260)\353\266\210\355\203\200\353\212\224\353\252\205\353\236\200\353\247\210\354\232\2241\355\216\270.jpg"
	new file:   "public/images/\353\221\220\355\210\274\355\225\234\353\223\261\354\213\254\353\217\210\352\260\200\354\212\244.jpg"
	new file:   "public/images/\353\247\245\354\225\244\354\271\230\354\246\210\355\225\240\353\235\274\355\224\274\353\207\250\354\203\214\353\223\2341\355\216\270.jpg"
	new file:   "public/images/\353\260\224\353\262\240\355\201\220\355\217\255\353\246\275\353\217\204\354\213\234\353\235\275.jpg"
	new file:   "public/images/\353\271\204\353\271\224\355\226\204\354\260\270\354\271\230\354\243\274\353\250\271\353\260\245.jpg"
	new file:   "public/images/\354\212\244\355\214\270\354\203\214\353\223\234\354\234\204\354\271\230.jpg"
	new file:   "public/images/\354\225\274\354\261\204\354\260\270\354\271\230\354\202\274\352\260\201\352\271\200\353\260\245.jpg"
	new file:   "public/images/\354\226\221\353\205\220\354\210\257\353\266\210\352\260\210\353\271\204\353\247\233.jpg"
	new file:   "public/images/\354\230\254\355\217\254\354\234\2401\355\216\270.jpg"
	new file:   "public/images/\354\260\270\354\271\230\352\271\200\354\271\230\353\263\266\354\235\214.jpg"
	new file:   "public/images/\354\271\230\354\246\210\352\260\220\355\212\200\354\203\214\353\223\234\354\234\204\354\271\230.jpg"
	new file:   "public/images/\355\206\265\354\203\210\354\232\260&\354\227\220\352\267\270\354\203\220\353\237\254\353\223\234\354\203\214\353\223\234.jpg"
	new file:   "public/images/\355\230\234\353\246\254)New11\354\260\254\353\217\204\354\213\234\353\235\275.jpg"
	new file:   "public/images/\355\230\234\353\246\254)\353\202\250\353\217\204\353\226\241\352\260\210\353\271\204\353\217\204\354\213\234\353\235\275.jpg"
	new file:   "public/images/\355\230\234\353\246\254)\354\255\210\352\276\270\353\257\270\353\266\210\352\263\240\352\270\260\353\271\204\353\271\224\353\260\245.jpg"
	new file:   public/stylesheets/style.css
	new file:   routes/contents.js
	new file:   routes/index.js
	new file:   views/.DS_Store
	new file:   views/board.ejs
	new file:   views/boardDetail.ejs
	new file:   views/error.ejs
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose'); //**** mongodb를 연결하기 위함 ****/
var routes = require('./routes/index'); // 기본 설정
var boards = require('./routes/contents'); //**** board는 contents.js 파일로 연결하여 라우팅 ****/
var app = express();
//***** connect mongodb *****/
mongoose.connect('mongodb://2014104145:pw@ds163301.mlab.com:63301/foodrank/food');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log("connected");
});
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/boards', boards); //*** '/boards' 주소로 들어오면 var boards = require('./routes/contents');에서 설정한 주소로 넘어가게 됨 ***/
// file upload multer
//app.use(upload.array('UploadFile',10));
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('foodrank:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
/*** 게시물 db 스키마 ***/
var mongoose = require('mongoose');
var boardSchema = mongoose.Schema({
name: String,
company: String,
category: String,
price: String,
average:Number,
comments: [{
grade: Number,
memo: String
}]
});
module.exports = mongoose.model('BoardContents', boardSchema);
{
"name": "foodrank",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.17.1",
"cookie-parser": "~1.4.3",
"debug": "~2.6.3",
"ejs": "~2.5.6",
"express": "~4.15.2",
"mongoose": "^4.10.5",
"morgan": "~1.8.1",
"multer": "^1.3.0",
"serve-favicon": "~2.4.2"
}
}
This diff is collapsed. Click to expand it.
var express = require('express');
var BoardContents = require('../models/boardsSchema'); //db를 사용하기 위한 변수
var fs = require('fs');
var router = express.Router();
router.get('/', function(req,res){
// 처음 index로 접속 했을시 나오는 부분
// db에서 게시글 리스트 가져와서 출력
// pagination 추가 -> 11/17
// page는 1-5까지 보여줌 -> db에서 총 갯수 잡아와서 10으로 나눠서 올림해야함
// 한페이지에 10개의 게시글: limit: 10, skip: (page-1)*10 이면 될 듯
// page number는 param으로 받아오기 가장 처음엔 param 없으니까 그땐 자동 1로 설정
var page = req.param('page');
if(page == null) {page = 1;}
var skipSize = (page-1)*10;
var limitSize = 10;
var pageNum = 1;
BoardContents.count({},function(err, totalCount){
// db에서 날짜 순으로 데이터들을 가져옴
if(err) throw err;
pageNum = Math.ceil(totalCount/limitSize);
BoardContents.find({}).sort({average:-1}).skip(skipSize).limit(limitSize).exec(function(err, pageContents) {
if(err) throw err;
res.render('board', {title: "Board", page : page, contents: pageContents, pagination: pageNum, searchWord: ''});
});
});
});
router.get('/search', function(req, res){
// 글 검색하는 부분
var search_word = req.param('searchWord');
var search_company = req.param('company');
var search_category = req.param('category');
var searchCondition = {$regex:''};
var searchCompany = {$regex:''};
var searchCategory = {$regex:''};
if(search_word!='')
searchCondition = {$regex:search_word};
if(search_company!='all')
searchCompany = {$regex:search_company};
if(search_category!='all')
searchCategory = {$regex:search_category};
var page = req.param('page');
if(page == null) {page = 1;}
var skipSize = (page-1)*10;
var limitSize = 10;
var pageNum = 1;
BoardContents.count({$and:[{name:searchCondition},{company:searchCompany},{category:searchCategory}]},function(err, searchCount){
if(err) throw err;
pageNum = Math.ceil(searchCount/limitSize);
BoardContents.find({$and:[{name:searchCondition},{company:searchCompany},{category:searchCategory}]}).sort({average:-1}).skip(skipSize).limit(limitSize).exec(function(err, searchContents){
if(err) throw err;
res.render('board', {title: "Board", page : page,contents: searchContents, pagination: pageNum, searchWord: search_word});
});
});
});
router.post('/', function(req, res){
//field name은 form의 input file의 name과 같아야함
// 글 작성하고 submit하게 되면 저장이 되는 부분
// 글 수정하고 submit하면 수정된 결과가 저장되는 부분
var mode = req.param('mode');
var addNewName = req.body.addContentName;
var addNewCompany = req.body.addContentCompany;
var addNewCategory = req.body.addContentCategory;
var addNewPrice = req.body.addContentPrice;
if(mode == 'add') {
addBoard(addNewName, addNewCompany, addNewCategory, addNewPrice);
res.redirect('/boards');
}
});
router.post('/reply', function(req, res){
// 댓글 다는 부분
var reply_grade = req.body.replyGrade;
var reply_comment= req.body.replyComment;
var reply_id = req.body.replyId;
addComment(reply_id, reply_grade, reply_comment,function(){
res.redirect('/boards/view?id='+reply_id);
});
});
router.get('/view', function(req, res){
// 글 보는 부분. 글 내용을 출력하고 조회수를 늘려줘야함
// 댓글 페이지 추가 해줌, 5개씩 출력함
var contentId = req.param('id');
BoardContents.findOne({_id:contentId}, function(err, rawContent){
if(err) throw err;
rawContent.save(function(err){
if(err) throw err;
res.render('boardDetail',{title: "Board", content:rawContent});
});
})
});
module.exports = router;
function addComment(id, grade, comment,callback) {
BoardContents.findOne({_id: id}, function(err, rawContent){
if(err) throw err;
var sum = 0;
rawContent.comments.unshift({grade:grade, memo: comment});
for(var j = 0;j<rawContent.comments.length;j++)
{
sum += rawContent.comments[j].grade;
}
rawContent.average = sum/rawContent.comments.length;
rawContent.save(function(err){
if(err) throw err;
else callback();
});
});
}
function addBoard(name, company, category, price){
var newBoardContents = new BoardContents;
newBoardContents.name = name;
newBoardContents.company = company;
newBoardContents.category = category;
newBoardContents.price = price;
newBoardContents.average = 0;
newBoardContents.save(function (err) {
if (err) throw err;
BoardContents.findOne({_id: newBoardContents._id}, {_id: 1}, function (err, newBoardId) {
if (err) throw err;
})
});
}
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
No preview for this file type
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$(function(){ // pagination 현재 페이지 활성화 시킴
var page = location.href.split("page=")[1]; // url에 page 넘버로 구분
var index = page-1; // 0부터 시작이므로 1 빼줌
if(page == null) { // 메인화면에서는 page 쿼리가 없으므로 빈값일 때
$(".pagination a:eq(0)").attr('class', 'current-page');
}
$(".pagination a:eq(" + index + ")").attr('class', 'current-page');
});
function searchContent() {
if($('#searchWord').val == ''){
alert("검색어를 입력해주세요!!!");
} else {
$('#searchAction').submit();
}
}
function submitContents() {
var name = $('#addContentName').val();
var company = $('#addContentCompany').val();
var category = $('#addContentCategory').val();
var price = $('#addContentPrice').val();
// 새 글 등록 시
if(name == '' || company == '' || category == '' || price == '') {
alert("이름, 회사, 카테고리, 가격 모두 있어야합니다.");
return;
} else {
$('#writeAction').submit();
}
}
</script>
</head>
<body>
<div class="main">
<a href="/boards"><h2>게시판</h2></a>
<table class="board_list">
<tr>
<th>Rank</th>
<th>Name</th>
<th>Company</th>
<th>Category</th>
<th>Price</th>
</tr>
<%if(contents.length>0){%>
<%var i = 0;%>
<%contents.forEach(function(item){%>
<%i++;%>
<tr>
<td class="number"><%=(page-1)*10+i%></td>
<td class="name"><a href="/boards/view?id=<%=item._id%>"><%=item.name%> [<%=item.comments.length%>]&nbsp;&nbsp;</a></td>
<td class="company"><%=item.company%></td>
<td class="category"><%=item.category%></td>
<td class="average"><%=item.average%></td>
</tr>
<%})%>
<%} else {%>
<tr>
<td colspan="5">게시물이 없습니다.</td>
</tr>
<%}%>
</table>
<div class="pagination">
<%
if(searchWord != '') {
for(var i=1; i<=pagination; i++){
%>
<a href="/boards/search?searchWord=<%=searchWord%>&page=<%=i%>" class="next-page"><%=i%></a>
<%
}
} else {
for(var i=1; i<=pagination; i++){
%>
<a href="/boards?page=<%=i%>" class="next-page"><%=i%></a>
<%}}%>
</div>
<div class="btn_group">
<div class="search">
<form action="/boards/search" method="get" id="searchAction" name="searchAction">
<input type="text" class="search_word" id="searchWord" name="searchWord">
<input type="radio" name="company" value="CU">CU</input>
<input type="radio" name="company" value="GS25">GS25</input>
<input type="radio" name="company" value="SevenEleven">SevenEleven</input>
<input type="radio" name="company" value="all" style="visibility:hidden" checked="true"></input>
<br>
<input type="radio" name="category" value="주먹밥">주먹밥</input>
<input type="radio" name="category" value="샌드위치">샌드위치</input>
<input type="radio" name="category" value="도시락">도시락</input>
<input type="radio" name="category" value="all" style="visibility:hidden" checked="true"></input>
<a href="#" onclick="searchContent();"><div class="search_btn">검색</div></a>
</form>
</div>
</div>
<!-- new content write form-->
<div class="write_form">
<form id="writeAction" action="/boards?mode=add" method="post">
<input type="text" class="inputName" id="addContentName" name="addContentName" placeholder="name">
<input type="text" class="inputCompany" id="addContentCompany" name="addContentCompany" placeholder="company">
<input type="text" class="inputCategory" id="addContentCategory" name="addContentCategory" placeholder="category">
<input type="text" class="inputPrice" id="addContentPrice" name="addContentPrice" placeholder="price"></textarea>
<div id = "new" class="addBtngroup">
<a onclick="submitContents();"><div>SUBMIT</div></a>
<a onclick="cancelWriteForm('cancel');"><div>CANCEL</div></a>
</div>
</form>
</div>
<!-- write form end-->
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title><%=title%></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<body>
<div class="main">
<a href="/boards"><h2>게시판</h2></a>
<div class="content_box">
<!-- content box-->
<div class="content_detail">
<div class="content-pic"><img src='../images/<%=content.name%>.jpg' width="340" height="340" onError="this.src='../images/noImage.jpg';"></div>
<div class="content-title"><%=content.name%></div>
<div class="content-info">
<%=content.company%> / <%=content.category%>
</div>
<div class="content-text">
<%=content.price%>
</div>
<div class="addBtngroup" style="margin-left:450px;">
<a href="/boards">확인</a>
</div>
</div>
<!-- content box end -->
<!-- 혁신의 끝을 달리는 옆에서 달아주는 댓글 창-->
<div class="reply">
<div class="reply_form">
<form id="replyAction" action="/boards/reply" method="post">
<div class="reply_grade">
<SELECT size=1 class="replyGrade" id="replyGrade" name="replyGrade">
<OPTION VALUE=1>1</OPTION>
<OPTION VALUE=2>2</OPTION>
<OPTION VALUE=3>3</OPTION>
<OPTION VALUE=4>4</OPTION>
<OPTION VALUE=5>5</OPTION>
</SELECT></div>
<div class="reply_comment">
<textarea class="replyComment" id="replyComment" name="replyComment" rows="3" cols="30"></textarea>
</div>
<input type="hidden" name="replyId" id="replyId" value="<%=content._id%>">
<button type="submit">댓글 작성</button>
</form>
</div>
<div class="reply_list">
<%if(content.comments.length>0){%>
<%var commentsList = content.comments;%>
<%for(var i=0; i<commentsList.length; i++){%>
%>
<div class="reply_content">
<div class="reply_info"><%=commentsList[i].grade%> / <%=commentsList[i].memo%></div>
</div>
<%}%>
<%} else {%>
<div class="reply_content">
<div class="reply_info">댓글이 없습니다</div>
</div>
<%}%>
</div>
</div>
<!-- end -->
</div>
</body>
</html>
<h1><%= message %></h1>
<h2><%= error.status %></h2>
<pre><%= error.stack %></pre>