이승윤

Merge branch 'feat/Video' into 'develop'

Feat/video



See merge request !6
...@@ -28,7 +28,7 @@ var categori = require('./routes/categori'); ...@@ -28,7 +28,7 @@ var categori = require('./routes/categori');
28 var accounts = require('./routes/accounts'); 28 var accounts = require('./routes/accounts');
29 var auth = require('./routes/auth'); 29 var auth = require('./routes/auth');
30 var connectMongo = require('connect-mongo'); 30 var connectMongo = require('connect-mongo');
31 -var Search = require('./routes/Search'); 31 +var Video = require('./routes/Videos');
32 var MongoStore = connectMongo(session); 32 var MongoStore = connectMongo(session);
33 33
34 app.set('views', path.join(__dirname, 'views')); 34 app.set('views', path.join(__dirname, 'views'));
...@@ -68,7 +68,7 @@ app.use(function (req, res, next) { ...@@ -68,7 +68,7 @@ app.use(function (req, res, next) {
68 }); 68 });
69 69
70 //routes add 70 //routes add
71 -app.use('/', Search); 71 +app.use('/', Video);
72 app.use('/categori', categori); 72 app.use('/categori', categori);
73 app.use('/accounts', accounts); 73 app.use('/accounts', accounts);
74 app.use('/auth', auth); 74 app.use('/auth', auth);
......
1 -var mongoose = require('mongoose');
2 -var Schema = mongoose.Schema;
3 -
4 -//생성될 필드명을 정한다.
5 -var ProductsSchema = new Schema({
6 - name: {
7 - //제품명
8 - type: String,
9 - required: [true, '제목은 입력해주세요'],
10 - },
11 - thumbnail: String, //이미지 파일명
12 - price: Number, //가격
13 - description: String, //설명
14 - created_at: {
15 - //작성일
16 - type: Date,
17 - default: Date.now(),
18 - },
19 - username: String, //작성자추가
20 -});
21 -
22 -ProductsSchema.virtual('getDate').get(function () {
23 - var date = new Date(this.created_at);
24 - return {
25 - year: date.getFullYear(),
26 - month: date.getMonth() + 1,
27 - day: date.getDate(),
28 - };
29 -});
30 -
31 -// 1씩 증가하는 primary Key를 만든다
32 -// model : 생성할 document 이름
33 -// field : primary key , startAt : 1부터 시작
34 -
35 -module.exports = mongoose.model('products', ProductsSchema);
...\ No newline at end of file ...\ No newline at end of file
1 var mongoose = require('mongoose'); 1 var mongoose = require('mongoose');
2 var Schema = mongoose.Schema; 2 var Schema = mongoose.Schema;
3 var VideoSchema = new Schema({ 3 var VideoSchema = new Schema({
4 - username: { 4 + categori: String,
5 - type: String, 5 + id: Number,
6 - required: [true, '아이디는 필수입니다.'], 6 + title: String,
7 - }, 7 + video_id: String,
8 - password: { 8 + urls: String,
9 - type: String,
10 - required: [true, '패스워드는 필수입니다.'],
11 - },
12 - displayname: String,
13 - created_at: {
14 - type: Date,
15 - default: Date.now(),
16 - },
17 }); 9 });
18 10
19 module.exports = mongoose.model('videos', VideoSchema); 11 module.exports = mongoose.model('videos', VideoSchema);
......
...@@ -9,7 +9,7 @@ var limit = 10; // 출력 갯수 ...@@ -9,7 +9,7 @@ var limit = 10; // 출력 갯수
9 var video = []; 9 var video = [];
10 var test = 'test'; 10 var test = 'test';
11 var count = 0; 11 var count = 0;
12 -youtube.setKey('AIzaSyAsKr_oWGZIBbL5tLdIl98Lf9Pzqj8jX4o'); // API 키 입력 12 +youtube.setKey('AIzaSyCAaeW1qMSInEdN1OzU20FZlToIZYkb1bc'); // API 키 입력
13 youtube.addParam('order', 'rating'); // 평점 순으로 정렬 13 youtube.addParam('order', 'rating'); // 평점 순으로 정렬
14 youtube.addParam('type', 'video'); // 타입 지정 14 youtube.addParam('type', 'video'); // 타입 지정
15 youtube.addParam('videoLicense', 'creativeCommon'); // 크리에이티브 커먼즈 아이템만 불러옴 15 youtube.addParam('videoLicense', 'creativeCommon'); // 크리에이티브 커먼즈 아이템만 불러옴
...@@ -19,9 +19,7 @@ youtube.search(word, limit, function (err, result) { ...@@ -19,9 +19,7 @@ youtube.search(word, limit, function (err, result) {
19 if (err) { 19 if (err) {
20 console.log(err); 20 console.log(err);
21 } // 에러일 경우 에러공지하고 빠져나감 21 } // 에러일 경우 에러공지하고 빠져나감
22 -
23 //console.log(JSON.stringify(result, null, 2)); // 받아온 전체 리스트 출력 22 //console.log(JSON.stringify(result, null, 2)); // 받아온 전체 리스트 출력
24 -
25 var items = result['items']; // 결과 중 items 항목만 가져옴 23 var items = result['items']; // 결과 중 items 항목만 가져옴
26 for (var i in items) { 24 for (var i in items) {
27 var it = items[i]; 25 var it = items[i];
......
1 -var Youtube = require('youtube-node');
2 -var youtube = new Youtube();
3 -
4 var express = require('express'); 1 var express = require('express');
2 +var CategoriModel = require('../models/CategoriModel');
3 +var VideoModel = require('../models/VideoModel');
5 var router = express.Router(); 4 var router = express.Router();
6 5
7 -var word = '백종원'; // 검색어 지정 6 +router.get('/', function (req, res) {
8 -var limit = 10; // 출력 갯수 7 + CategoriModel.find(function (err, category) {
9 -var video = []; 8 + VideoModel.find(function (err, video) {
10 -var test = 'test'; 9 + var item = []; // 카테고리별 비디오 목록을 담아두는 배열
11 -var count = 0; 10 + for (var i in category) {
12 -youtube.setKey('AIzaSyAsKr_oWGZIBbL5tLdIl98Lf9Pzqj8jX4o'); // API 키 입력 11 + var videos = []; // 비디오 목록을 담는 임시 배열
13 - 12 + for (var j in video) {
14 -youtube.addParam('order', 'rating'); // 평점 순으로 정렬 13 + if (category[i].title == video[j].categori) {
15 -youtube.addParam('type', 'video'); // 타입 지정 14 + videos.push(video[j]);
16 -youtube.addParam('videoLicense', 'creativeCommon'); // 크리에이티브 커먼즈 아이템만 불러옴
17 -
18 -youtube.search(word, limit, function (err, result) {
19 - // 검색 실행
20 - if (err) {
21 - console.log(err);
22 - } // 에러일 경우 에러공지하고 빠져나감
23 -
24 - //console.log(JSON.stringify(result, null, 2)); // 받아온 전체 리스트 출력
25 -
26 - var items = result['items']; // 결과 중 items 항목만 가져옴
27 - for (var i in items) {
28 - var it = items[i];
29 - for (var j in it) {
30 - if (it[j]['title'] != null) {
31 - var title = it[j]['title'];
32 - }
33 - if (it[j]['videoId'] != null) {
34 - var video_id = it[j]['videoId'];
35 } 15 }
36 - var urls = 'https://www.youtube.com/watch?v=' + video_id;
37 } 16 }
38 - var item = { 17 + if (videos.length != 0) {
39 - id: count, 18 + // 빈 배열 체크
40 - title: title, 19 + console.log(videos);
41 - video_id: video_id, 20 + var items = {
42 - urls: urls, 21 + category: category[i],
22 + videos: videos,
43 }; 23 };
44 - count++; 24 + item.push(items);
45 - video.push(item);
46 } 25 }
47 -}); 26 + }
48 - 27 + //console.log(item[2].category.title);
49 -router.get('/', function (req, res) { 28 + //console.log(item[2].videos);
50 res.render( 29 res.render(
51 'home', 30 'home',
52 - { videos: video } // DB에서 받은 videos를 videos변수명으로 내보냄 31 + { video: item, categories: category } // DB에서 받은 videos와 category를 videos변수명으로 내보냄
53 ); 32 );
33 + });
34 + });
54 }); 35 });
55 36
56 module.exports = router; 37 module.exports = router;
......
1 var express = require('express'); 1 var express = require('express');
2 var router = express.Router(); 2 var router = express.Router();
3 var CategoriModel = require('../models/CategoriModel'); 3 var CategoriModel = require('../models/CategoriModel');
4 -//var csrf = require('csurf'); 4 +var VideoModel = require('../models/VideoModel');
5 -//var csrfProtection = csrf({ cookie: true }); 5 +var Youtube = require('youtube-node');
6 -var loginRequired = require('../libs/loginRequired'); 6 +var youtube = new Youtube();
7 -
8 -var path = require('path');
9 -var uploadDir = path.join(__dirname, '../uploads'); // 루트의 uploads위치에 저장한다.
10 -var fs = require('fs');
11 7
12 -//multer 셋팅 8 +var loginRequired = require('../libs/loginRequired');
13 -var multer = require('multer');
14 -var storage = multer.diskStorage({
15 - destination: function (req, file, callback) {
16 - //이미지가 저장되는 도착지 지정
17 - callback(null, uploadDir);
18 - },
19 - filename: function (req, file, callback) {
20 - // products-날짜.jpg(png) 저장
21 - callback(
22 - null,
23 - 'products-' + Date.now() + '.' + file.mimetype.split('/')[1]
24 - );
25 - },
26 -});
27 9
28 -var upload = multer({ storage: storage }); 10 +var limit = 10; // 출력 갯수
11 +youtube.setKey('AIzaSyCAaeW1qMSInEdN1OzU20FZlToIZYkb1bc'); // API 키 입력
29 12
30 router.get('/', function (req, res) { 13 router.get('/', function (req, res) {
31 res.send('categori main page'); 14 res.send('categori main page');
...@@ -43,7 +26,6 @@ router.get('/products', function (req, res) { ...@@ -43,7 +26,6 @@ router.get('/products', function (req, res) {
43 }); 26 });
44 27
45 router.get('/categories/write', loginRequired, function (req, res) { 28 router.get('/categories/write', loginRequired, function (req, res) {
46 - //edit에서도 같은 form을 사용하므로 빈 변수( product )를 넣어서 에러를 피해준다
47 res.render('category/form', { categories: '' }); 29 res.render('category/form', { categories: '' });
48 }); 30 });
49 31
...@@ -67,15 +49,83 @@ router.post('/categories/write', loginRequired, function (req, res) { ...@@ -67,15 +49,83 @@ router.post('/categories/write', loginRequired, function (req, res) {
67 49
68 router.get('/products/detail/:id', function (req, res) { 50 router.get('/products/detail/:id', function (req, res) {
69 //url 에서 변수 값을 받아올떈 req.params.id 로 받아온다 51 //url 에서 변수 값을 받아올떈 req.params.id 로 받아온다
52 + var word = req.query.keyword;
70 CategoriModel.findOne({ _id: req.params.id }, function (err, product) { 53 CategoriModel.findOne({ _id: req.params.id }, function (err, product) {
54 + var video = [];
71 //제품정보를 받고 그안에서 댓글을 받아온다. 55 //제품정보를 받고 그안에서 댓글을 받아온다.
72 CategoriModel.find({ product_id: req.params.id }, function (err, comments) { 56 CategoriModel.find({ product_id: req.params.id }, function (err, comments) {
57 + if (word != null) {
58 + var count = 0;
59 + youtube.addParam('order', 'rating'); // 평점 순으로 정렬
60 + youtube.addParam('type', 'video'); // 타입 지정
61 + youtube.addParam('videoLicense', 'creativeCommon'); // 크리에이티브 커먼즈 아이템만 불러옴
62 + youtube.search(word, limit, function (err, result) {
63 + // 검색 실행
64 + console.log(word);
65 + if (err) {
66 + console.log(err);
67 + } // 에러일 경우 에러공지하고 빠져나감
68 + //console.log(JSON.stringify(result, null, 2)); // 받아온 전체 리스트 출력
69 + var items = result['items']; // 결과 중 items 항목만 가져옴
70 + for (var i in items) {
71 + var it = items[i];
72 + for (var j in it) {
73 + if (it[j]['title'] != null) {
74 + var title = it[j]['title'];
75 + }
76 + if (it[j]['videoId'] != null) {
77 + var video_id = it[j]['videoId'];
78 + }
79 + var urls = 'https://www.youtube.com/watch?v=' + video_id;
80 + }
81 + var item = {
82 + id: count,
83 + title: title,
84 + video_id: video_id,
85 + urls: urls,
86 + categori: product.title,
87 + };
88 + count++;
89 + video.push(item);
90 + }
73 res.render('category/productsDetail', { 91 res.render('category/productsDetail', {
74 product: product, 92 product: product,
75 comments: comments, 93 comments: comments,
94 + videos: video,
76 }); 95 });
77 }); 96 });
97 + } else {
98 + res.render('category/productsDetail', {
99 + product: product,
100 + comments: comments,
101 + videos: video,
78 }); 102 });
103 + }
104 + });
105 + });
106 +});
107 +
108 +router.post('/products/detail/:id', loginRequired, function (req, res) {
109 + var item = [];
110 + var count = 1;
111 + for (var i in req.body.videoNum) {
112 + item.push(req.body.videoNum[i].split('///'));
113 + var video = new VideoModel({
114 + categori: item[i][2],
115 + id: count,
116 + title: item[i][1],
117 + video_id: item[i][3],
118 + urls: item[i][4],
119 + });
120 + var validationError = video.validateSync();
121 + if (validationError) {
122 + res.send(validationError);
123 + } else {
124 + video.save(function (err) {});
125 + }
126 + count++;
127 + }
128 + res.redirect('/categori/products');
79 }); 129 });
80 130
81 router.get('/products/edit/:id', loginRequired, function (req, res) { 131 router.get('/products/edit/:id', loginRequired, function (req, res) {
...@@ -87,21 +137,9 @@ router.get('/products/edit/:id', loginRequired, function (req, res) { ...@@ -87,21 +137,9 @@ router.get('/products/edit/:id', loginRequired, function (req, res) {
87 }); 137 });
88 }); 138 });
89 139
90 -router.post( 140 +router.post('/products/edit/:id', loginRequired, function (req, res) {
91 - '/products/edit/:id',
92 - loginRequired,
93 - upload.single('thumbnail'),
94 - // csrfProtection,
95 - function (req, res) {
96 //그전에 지정되 있는 파일명을 받아온다 141 //그전에 지정되 있는 파일명을 받아온다
97 CategoriModel.findOne({ _id: req.params.id }, function (err, product) { 142 CategoriModel.findOne({ _id: req.params.id }, function (err, product) {
98 - //아래의 코드만 추가되면 된다.
99 - if (req.file && product.thumbnail) {
100 - //요청중에 파일이 존재 할시 이전이미지 지운다.
101 - fs.unlinkSync(uploadDir + '/' + product.thumbnail);
102 - }
103 - //위의 코드만 추가되면 된다.
104 - //넣을 변수 값을 셋팅한다
105 var query = { 143 var query = {
106 name: req.body.name, 144 name: req.body.name,
107 thumbnail: req.file ? req.file.filename : product.thumbnail, 145 thumbnail: req.file ? req.file.filename : product.thumbnail,
...@@ -112,12 +150,11 @@ router.post( ...@@ -112,12 +150,11 @@ router.post(
112 { id: req.params.id }, 150 { id: req.params.id },
113 { $set: query }, 151 { $set: query },
114 function (err) { 152 function (err) {
115 - res.redirect('/category/products/detail/' + req.params.id); 153 + res.redirect('/categori/products/detail/' + req.params.id);
116 } 154 }
117 ); 155 );
118 }); 156 });
119 - } 157 +});
120 -);
121 158
122 router.get('/products/delete/:id', function (req, res) { 159 router.get('/products/delete/:id', function (req, res) {
123 CategoriModel.deleteMany({ _id: req.params.id }, function (err) { 160 CategoriModel.deleteMany({ _id: req.params.id }, function (err) {
......
...@@ -10,6 +10,6 @@ ...@@ -10,6 +10,6 @@
10 <td><input type="text" name="description" class="form-control" value="<%=categories.description%>"/></td> 10 <td><input type="text" name="description" class="form-control" value="<%=categories.description%>"/></td>
11 </tr> 11 </tr>
12 </table> 12 </table>
13 - <input type="submit" name="submit" value="submit" class="btn btn-primary"> 13 + <input type="submit" name="submit" value="완료" class="btn btn-primary">
14 </form> 14 </form>
15 <% include ../includes/footer.ejs %> 15 <% include ../includes/footer.ejs %>
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -3,6 +3,32 @@ ...@@ -3,6 +3,32 @@
3 <div class="panel-heading"> 3 <div class="panel-heading">
4 <%=product.title%> 4 <%=product.title%>
5 </div> 5 </div>
6 + <form method="get" action="">
7 + <div class="input-group">
8 + <input type="text" class="form-control" placeholder="검색 키워드를 입력하세요!" name="keyword" autocomplete='off'>
9 + <span class="input-group-btn">
10 + <button class="btn btn-secondary" type="submit">찾기</button>
11 + </span>
12 + </div>
13 + </form>
14 + <form method="post" action="">
15 + <% for (var i in videos) { %>
16 + <div style="float:left;
17 + padding: 15px;
18 + ">
19 + <input type="checkbox" name="videoNum" style="
20 + position: absolute;
21 + margin-top: 5px;
22 + margin-left: 5px;
23 + z-index: 4;
24 + zoom:3.0;
25 + " value="<%=videos[i].id + '///' + videos[i].title +'///'+ videos[i].categori +'///'+ videos[i].video_id +'///'+ videos[i].urls%>"/>
26 + <div id="<%=videos[i].id%>" vid="<%=videos[i].video_id%>">
27 + </div>
28 + </div>
29 + <%};%>
30 + <button class="btn btn-primary" style="margin-top: 10px; margin-left: 15px;" >영상담기</button>
31 + </form>
6 <div class="panel-body"> 32 <div class="panel-body">
7 <div style="padding-bottom: 10px"> 33 <div style="padding-bottom: 10px">
8 작성일 : 34 작성일 :
...@@ -20,9 +46,9 @@ ...@@ -20,9 +46,9 @@
20 <div> 46 <div>
21 댓글작성하기 47 댓글작성하기
22 <form id="commentForm" action="" method="post"> 48 <form id="commentForm" action="" method="post">
23 - <input type="hidden" name="product_id" value="<%=product._id%>" /> 49 + <input type="hidden" name="product_id" value="<%=product.id%>" />
24 <textarea class="form-control" name="content"></textarea> 50 <textarea class="form-control" name="content"></textarea>
25 - <button class="btn btn-primary" style="margin-top: 10px">댓글작성</button> 51 + <button class="btn btn-primary" style="margin-top: 10px" type="submit">댓글작성</button>
26 </form> 52 </form>
27 </div> 53 </div>
28 <!-- 댓글영역 --> 54 <!-- 댓글영역 -->
...@@ -91,3 +117,44 @@ $(document).on('click' , '.comment_delete' , function(){ ...@@ -91,3 +117,44 @@ $(document).on('click' , '.comment_delete' , function(){
91 } 117 }
92 }); 118 });
93 </script> 119 </script>
120 +<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>
121 +<script type="text/javascript"
122 + src="https://cdnjs.cloudflare.com/ajax/libs/jquery.imagesloaded/4.1.1/imagesloaded.pkgd.min.js"></script>
123 +<script type="text/javascript">
124 + var $masonry_container = $('#masonry_container');
125 + $masonry_container.imagesLoaded(function () {
126 + $masonry_container.masonry({
127 + itemSelector: '.masonry-grid',
128 + columnWidth: 270
129 + });
130 + });
131 +</script>
132 +<script>
133 + var tag = document.createElement('script');
134 +
135 + tag.src = "https://www.youtube.com/iframe_api";
136 + var firstScriptTag = document.getElementsByTagName('script')[0];
137 + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
138 +
139 + var player;
140 + var players = [];
141 + var videoIds = [];
142 + for (var i = 0; i < 10; i++) {
143 + players.push(String(i));
144 + videoIds.push($('#' + i).attr('vid'));
145 + }
146 +
147 + function onYouTubeIframeAPIReady() {
148 + for (var i = 0; i < videoIds.length; i++) {
149 + player = new YT.Player(players[i], {
150 + height: '300',
151 + width: '500',
152 + videoId: videoIds[i],
153 + events: {
154 + // 'onReady': onPlayerReady,
155 + // 'onStateChange': onPlayerStateChange
156 + }
157 + });
158 + }
159 + }
160 +</script>
...\ No newline at end of file ...\ No newline at end of file
......