Showing
22 changed files
with
1129 additions
and
0 deletions
.gitignore
0 → 100644
app.js
0 → 100644
1 | +var express = require('express'); | ||
2 | +var app = express(); | ||
3 | +var port = 3000; | ||
4 | + | ||
5 | +var mongoose = require('mongoose'); | ||
6 | +mongoose.Promise = global.Promise; | ||
7 | + | ||
8 | +//auto-increment를 위한 패키지 | ||
9 | +var path = require('path'); | ||
10 | +var logger = require('morgan'); | ||
11 | +var bodyParser = require('body-parser'); | ||
12 | +var cookieParser = require('cookie-parser'); | ||
13 | +var flash = require('connect-flash'); | ||
14 | + | ||
15 | +//passport 로그인 관련 | ||
16 | +var passport = require('passport'); | ||
17 | +var session = require('express-session'); | ||
18 | + | ||
19 | +//mongodb 연동 | ||
20 | +var db = mongoose.connection; | ||
21 | +db.on('error', console.error); | ||
22 | +db.once('open', function () { | ||
23 | + console.log('mongo db Connection'); | ||
24 | +}); | ||
25 | +var connect = mongoose.connect('mongodb://127.0.0.1:27017/test', { | ||
26 | + useMongoClient: true, | ||
27 | +}); | ||
28 | + | ||
29 | +//categori module get | ||
30 | +var categori = require('./routes/categori'); | ||
31 | +var accounts = require('./routes/accounts'); | ||
32 | +var auth = require('./routes/auth'); | ||
33 | +var connectMongo = require('connect-mongo'); | ||
34 | +var Video = require('./routes/Videos'); | ||
35 | +var MongoStore = connectMongo(session); | ||
36 | + | ||
37 | +app.set('views', path.join(__dirname, 'views')); | ||
38 | +app.set('view engine', 'ejs'); | ||
39 | +app.use(logger('dev')); | ||
40 | +app.use(bodyParser.json()); | ||
41 | +app.use(bodyParser.urlencoded({ extended: false })); | ||
42 | +app.use(cookieParser()); | ||
43 | +app.use('/uploads', express.static('uploads')); | ||
44 | + | ||
45 | +// MiddleWare 지정 | ||
46 | +var sessionMiddleWare = session({ | ||
47 | + secret: 'fastcampus', | ||
48 | + resave: false, | ||
49 | + saveUninitialized: true, | ||
50 | + cookie: { | ||
51 | + maxAge: 2000 * 60 * 60, //지속시간 2시간 | ||
52 | + }, | ||
53 | + store: new MongoStore({ | ||
54 | + mongooseConnection: mongoose.connection, | ||
55 | + ttl: 14 * 24 * 60 * 60, | ||
56 | + }), | ||
57 | +}); | ||
58 | +app.use(sessionMiddleWare); | ||
59 | + | ||
60 | +//passport 적용 | ||
61 | +app.use(passport.initialize()); | ||
62 | +app.use(passport.session()); | ||
63 | + | ||
64 | +//플래시 메시지 관련 | ||
65 | +app.use(flash()); | ||
66 | + | ||
67 | +app.use(function (req, res, next) { | ||
68 | + app.locals.isLogin = req.isAuthenticated(); | ||
69 | + //app.locals.urlparameter = req.url; //현재 url 정보를 보내고 싶으면 이와같이 셋팅 | ||
70 | + //app.locals.userData = req.user; //사용 정보를 보내고 싶으면 이와같이 셋팅 | ||
71 | + next(); | ||
72 | +}); | ||
73 | + | ||
74 | +//routes | ||
75 | +app.use('/', Video); | ||
76 | +app.use('/categori', categori); | ||
77 | +app.use('/accounts', accounts); | ||
78 | +app.use('/auth', auth); | ||
79 | + | ||
80 | +var server = app.listen(port, function () { | ||
81 | + console.log('Express listening on port', port); | ||
82 | +}); |
libs/loginRequired.js
0 → 100644
libs/passwordHash.js
0 → 100644
libs/removeByValue.js
0 → 100644
models/CategoriModel.js
0 → 100644
1 | +var mongoose = require('mongoose'); | ||
2 | +var Schema = mongoose.Schema; | ||
3 | + | ||
4 | +var CategoriSchema = new Schema({ | ||
5 | + title: { | ||
6 | + type: String, | ||
7 | + default: 'default', | ||
8 | + required: [true, '카테고리명이 비어있습니다!'], | ||
9 | + }, | ||
10 | + videoNum: String, | ||
11 | + description: String, //설명 | ||
12 | + created_at: { | ||
13 | + type: Date, | ||
14 | + default: Date.now(), | ||
15 | + }, | ||
16 | + username: String, | ||
17 | +}); | ||
18 | + | ||
19 | +CategoriSchema.virtual('getDate').get(function () { | ||
20 | + var date = new Date(this.created_at); | ||
21 | + return { | ||
22 | + year: date.getFullYear(), | ||
23 | + month: date.getMonth() + 1, | ||
24 | + day: date.getDate(), | ||
25 | + }; | ||
26 | +}); | ||
27 | + | ||
28 | +module.exports = mongoose.model('categories', CategoriSchema); |
models/UserModel.js
0 → 100644
1 | +var mongoose = require('mongoose'); | ||
2 | +var Schema = mongoose.Schema; | ||
3 | +var UserSchema = new Schema({ | ||
4 | + username: { | ||
5 | + type: String, | ||
6 | + required: [true, '아이디는 필수입니다.'], | ||
7 | + }, | ||
8 | + password: { | ||
9 | + type: String, | ||
10 | + required: [true, '패스워드는 필수입니다.'], | ||
11 | + }, | ||
12 | + displayname: String, | ||
13 | + created_at: { | ||
14 | + type: Date, | ||
15 | + default: Date.now(), | ||
16 | + }, | ||
17 | +}); | ||
18 | + | ||
19 | +module.exports = mongoose.model('user', UserSchema); |
models/VideoModel.js
0 → 100644
package.json
0 → 100644
1 | +{ | ||
2 | + "name": "node", | ||
3 | + "version": "1.0.0", | ||
4 | + "description": "my-cookbook-project", | ||
5 | + "main": "index.js", | ||
6 | + "scripts": { | ||
7 | + "test": "echo \"Error: no test specified\" && exit 1", | ||
8 | + "start": "nodemon ./app.js" | ||
9 | + }, | ||
10 | + "dependencies": { | ||
11 | + "body-parser": "^1.18.2", | ||
12 | + "connect-flash": "^0.1.1", | ||
13 | + "connect-mongo": "^2.0.0", | ||
14 | + "cookie-parser": "^1.4.3", | ||
15 | + "csurf": "^1.9.0", | ||
16 | + "ejs": "^2.5.7", | ||
17 | + "express": "^4.15.4", | ||
18 | + "express-session": "^1.15.5", | ||
19 | + "mongodb": "^2.2.36", | ||
20 | + "mongoose": "^4.13.21", | ||
21 | + "morgan": "^1.8.2", | ||
22 | + "multer": "^1.3.0", | ||
23 | + "nodemon": "^2.0.7", | ||
24 | + "passport": "^0.4.0", | ||
25 | + "passport-facebook": "^2.1.1", | ||
26 | + "passport-google-oauth20": "^2.0.0", | ||
27 | + "passport-local": "^1.0.0", | ||
28 | + "path": "^0.12.7", | ||
29 | + "socket.io": "^2.0.3", | ||
30 | + "youtube-node": "^1.3.3" | ||
31 | + } | ||
32 | +} |
routes/Search.js
0 → 100644
1 | +var Youtube = require('youtube-node'); | ||
2 | +var youtube = new Youtube(); | ||
3 | + | ||
4 | +var express = require('express'); | ||
5 | +var router = express.Router(); | ||
6 | + | ||
7 | +var word = '백종원'; // 검색어 지정 | ||
8 | +var limit = 10; // 출력 갯수 | ||
9 | +var video = []; | ||
10 | +var test = 'test'; | ||
11 | +var count = 0; | ||
12 | +youtube.setKey('AIzaSyCAaeW1qMSInEdN1OzU20FZlToIZYkb1bc'); // API 키 입력 | ||
13 | +youtube.addParam('order', 'rating'); // 평점 순으로 정렬 | ||
14 | +youtube.addParam('type', 'video'); // 타입 지정 | ||
15 | +youtube.addParam('videoLicense', 'creativeCommon'); // 크리에이티브 커먼즈 아이템만 불러옴 | ||
16 | + | ||
17 | +youtube.search(word, limit, function (err, result) { | ||
18 | + // 검색 실행 | ||
19 | + if (err) { | ||
20 | + console.log(err); | ||
21 | + } // 에러일 경우 에러공지하고 빠져나감 | ||
22 | + //console.log(JSON.stringify(result, null, 2)); // 받아온 전체 리스트 출력 | ||
23 | + var items = result['items']; // 결과 중 items 항목만 가져옴 | ||
24 | + for (var i in items) { | ||
25 | + var it = items[i]; | ||
26 | + for (var j in it) { | ||
27 | + if (it[j]['title'] != null) { | ||
28 | + var title = it[j]['title']; | ||
29 | + } | ||
30 | + if (it[j]['videoId'] != null) { | ||
31 | + var video_id = it[j]['videoId']; | ||
32 | + } | ||
33 | + var urls = 'https://www.youtube.com/watch?v=' + video_id; | ||
34 | + } | ||
35 | + var item = { | ||
36 | + id: count, | ||
37 | + title: title, | ||
38 | + video_id: video_id, | ||
39 | + urls: urls, | ||
40 | + }; | ||
41 | + count++; | ||
42 | + video.push(item); | ||
43 | + } | ||
44 | +}); | ||
45 | + | ||
46 | +router.get('/', function (req, res) { | ||
47 | + res.render( | ||
48 | + 'home', | ||
49 | + { videos: video } // DB에서 받은 videos를 videos변수명으로 내보냄 | ||
50 | + ); | ||
51 | +}); | ||
52 | + | ||
53 | +module.exports = router; |
routes/Videos.js
0 → 100644
1 | +var express = require('express'); | ||
2 | +var CategoriModel = require('../models/CategoriModel'); | ||
3 | +var VideoModel = require('../models/VideoModel'); | ||
4 | +var router = express.Router(); | ||
5 | + | ||
6 | +router.get('/', function (req, res) { | ||
7 | + CategoriModel.find(function (err, category) { | ||
8 | + VideoModel.find(function (err, video) { | ||
9 | + var item = []; // 카테고리별 비디오 목록을 담아두는 배열 | ||
10 | + for (var i in category) { | ||
11 | + var videos = []; // 비디오 목록을 담는 임시 배열 | ||
12 | + for (var j in video) { | ||
13 | + if (category[i].title == video[j].categori) { | ||
14 | + videos.push(video[j]); | ||
15 | + } | ||
16 | + } | ||
17 | + if (videos.length != 0) { | ||
18 | + // 빈 배열 체크 | ||
19 | + //console.log(videos); | ||
20 | + var items = { | ||
21 | + category: category[i], | ||
22 | + videos: videos, | ||
23 | + }; | ||
24 | + item.push(items); | ||
25 | + } | ||
26 | + } | ||
27 | + //console.log(item[2].category.title); | ||
28 | + //console.log(item[2].videos); | ||
29 | + res.render( | ||
30 | + 'home', | ||
31 | + { video: item, categories: category } // DB에서 받은 videos와 category를 videos변수명으로 내보냄 | ||
32 | + ); | ||
33 | + }); | ||
34 | + }); | ||
35 | +}); | ||
36 | + | ||
37 | +module.exports = router; |
routes/accounts.js
0 → 100644
1 | +var express = require('express'); | ||
2 | +var router = express.Router(); | ||
3 | +var UserModel = require('../models/UserModel'); | ||
4 | +var passwordHash = require('../libs/passwordHash'); | ||
5 | +var passport = require('passport'); | ||
6 | +var LocalStrategy = require('passport-local').Strategy; | ||
7 | + | ||
8 | +passport.serializeUser(function (user, done) { | ||
9 | + console.log('serializeUser'); | ||
10 | + done(null, user); | ||
11 | +}); | ||
12 | + | ||
13 | +passport.deserializeUser(function (user, done) { | ||
14 | + var result = user; | ||
15 | + result.password = ""; | ||
16 | + console.log('deserializeUser'); | ||
17 | + done(null, result); | ||
18 | +}); | ||
19 | + | ||
20 | +passport.use(new LocalStrategy({ | ||
21 | + usernameField: 'username', | ||
22 | + passwordField : 'password', | ||
23 | + passReqToCallback : true | ||
24 | + }, | ||
25 | + function (req, username, password, done) { | ||
26 | + UserModel.findOne({ username : username , password : passwordHash(password) }, function (err,user) { | ||
27 | + if (!user){ | ||
28 | + return done(null, false, { message: '아이디 또는 비밀번호 오류 입니다.' }); | ||
29 | + }else{ | ||
30 | + return done(null, user ); | ||
31 | + } | ||
32 | + }); | ||
33 | + } | ||
34 | +)); | ||
35 | + | ||
36 | +router.get('/', function(req, res){ | ||
37 | + res.send('account app'); | ||
38 | +}); | ||
39 | + | ||
40 | +router.get('/join', function(req, res){ | ||
41 | + res.render('accounts/join'); | ||
42 | +}); | ||
43 | + | ||
44 | +router.post('/join', function(req, res){ | ||
45 | + var User = new UserModel({ | ||
46 | + username : req.body.username, | ||
47 | + password : passwordHash(req.body.password), | ||
48 | + displayname : req.body.displayname | ||
49 | + }); | ||
50 | + User.save(function(err){ | ||
51 | + res.send('<script>alert("회원가입 성공");location.href="/accounts/login";</script>'); | ||
52 | + }); | ||
53 | +}); | ||
54 | + | ||
55 | +router.get('/login', function(req, res){ | ||
56 | + res.render('accounts/login', { flashMessage : req.flash().error }); | ||
57 | +}); | ||
58 | + | ||
59 | +router.post('/login' , | ||
60 | +passport.authenticate('local', { | ||
61 | + failureRedirect: '/accounts/login', | ||
62 | + failureFlash: true | ||
63 | +}), | ||
64 | +function(req, res){ | ||
65 | + res.send('<script>alert("로그인 성공");location.href="/";</script>'); | ||
66 | +} | ||
67 | +); | ||
68 | + | ||
69 | +router.get('/success', function(req, res){ | ||
70 | + res.send(req.user); | ||
71 | +}); | ||
72 | + | ||
73 | + | ||
74 | +router.get('/logout', function(req, res){ | ||
75 | + req.logout(); | ||
76 | + res.redirect('/accounts/login'); | ||
77 | +}); | ||
78 | + | ||
79 | +module.exports = router; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
routes/auth.js
0 → 100644
1 | +var express = require('express'); | ||
2 | +var router = express.Router(); | ||
3 | +var UserModel = require('../models/UserModel'); | ||
4 | +var passport = require('passport'); | ||
5 | +const GoogleStrategy = require('passport-google-oauth20').Strategy; | ||
6 | + | ||
7 | +passport.serializeUser(function (user, done) { | ||
8 | + done(null, user); | ||
9 | +}); | ||
10 | + | ||
11 | +passport.deserializeUser(function (user, done) { | ||
12 | + done(null, user); | ||
13 | +}); | ||
14 | + | ||
15 | +passport.use( | ||
16 | + new GoogleStrategy( | ||
17 | + { | ||
18 | + clientID: | ||
19 | + '912554148550-gq86jjjgc022b1eit50mboh5lq48covi.apps.googleusercontent.com', | ||
20 | + clientSecret: '_EzuXeN7eNCTbcGQUV4kY1pN', | ||
21 | + callbackURL: 'http://localhost:3000/auth/google/callback', | ||
22 | + profileFields: ['id', 'displayName', 'photos', 'email'], //받고 싶은 필드 나열 | ||
23 | + }, | ||
24 | + function (accessToken, refreshToken, profile, done) { | ||
25 | + UserModel.findOne( | ||
26 | + { username: 'goo_' + profile.id }, | ||
27 | + function (err, user) { | ||
28 | + if (!user) { | ||
29 | + //없으면 회원가입 후 로그인 성공페이지 이동 | ||
30 | + var regData = { | ||
31 | + //DB에 등록 및 세션에 등록될 데이터 | ||
32 | + username: 'goo_' + profile.id, | ||
33 | + password: 'google_login', | ||
34 | + displayname: profile.displayName, | ||
35 | + }; | ||
36 | + var User = new UserModel(regData); | ||
37 | + User.save(function (err) { | ||
38 | + //DB저장 | ||
39 | + done(null, regData); //세션 등록 | ||
40 | + }); | ||
41 | + } else { | ||
42 | + //있으면 DB에서 가져와서 세션등록 | ||
43 | + done(null, user); | ||
44 | + } | ||
45 | + } | ||
46 | + ); | ||
47 | + } | ||
48 | + ) | ||
49 | +); | ||
50 | + | ||
51 | +router.get('/google', passport.authenticate('google', { scope: ['profile'] })); | ||
52 | + | ||
53 | +//인증후 구글에서 이 주소로 리턴해줌. 상단에 적은 callbackURL과 일치 | ||
54 | +router.get( | ||
55 | + '/google/callback', | ||
56 | + passport.authenticate('google', { | ||
57 | + failureRedirect: '/auth', | ||
58 | + successRedirect: '/', | ||
59 | + }) | ||
60 | +); | ||
61 | +//로그인 성공시 이동할 주소 | ||
62 | +router.get('/google/success', function (req, res) { | ||
63 | + res.send(req.user); | ||
64 | +}); | ||
65 | + | ||
66 | +router.get('/google/fail', function (req, res) { | ||
67 | + res.send('google login fail'); | ||
68 | +}); | ||
69 | + | ||
70 | +module.exports = router; |
routes/categori.js
0 → 100644
1 | +var express = require('express'); | ||
2 | +var router = express.Router(); | ||
3 | +var CategoriModel = require('../models/CategoriModel'); | ||
4 | +var VideoModel = require('../models/VideoModel'); | ||
5 | +var Youtube = require('youtube-node'); | ||
6 | +var youtube = new Youtube(); | ||
7 | + | ||
8 | +var loginRequired = require('../libs/loginRequired'); | ||
9 | +var redirectUrls = ''; | ||
10 | +var limit = 10; // 출력 갯수 | ||
11 | +youtube.setKey('AIzaSyCAaeW1qMSInEdN1OzU20FZlToIZYkb1bc'); // API 키 입력 | ||
12 | + | ||
13 | +router.get('/', function (req, res) { | ||
14 | + res.send('categori main page'); | ||
15 | +}); | ||
16 | + | ||
17 | +router.get('/products', function (req, res) { | ||
18 | + CategoriModel.find(function (err, products) { | ||
19 | + console.log(products); | ||
20 | + res.render( | ||
21 | + 'category/products', | ||
22 | + { categories: products } | ||
23 | + //ProductModel의 products를 받아서 | ||
24 | + //categori/products로 response를 보낸다. | ||
25 | + ); | ||
26 | + }); | ||
27 | +}); | ||
28 | + | ||
29 | +router.get('/categories/write', loginRequired, function (req, res) { | ||
30 | + res.render('category/form', { categories: '' }); | ||
31 | +}); | ||
32 | + | ||
33 | +router.post('/categories/write', loginRequired, function (req, res) { | ||
34 | + var category = new CategoriModel({ | ||
35 | + title: req.body.title, | ||
36 | + description: req.body.description, | ||
37 | + username: req.user.displayname, | ||
38 | + }); | ||
39 | + // | ||
40 | + var validationError = category.validateSync(); | ||
41 | + if (validationError) { | ||
42 | + res.send(validationError); | ||
43 | + } else { | ||
44 | + category.save(function (err) { | ||
45 | + res.redirect('/categori/products'); | ||
46 | + }); | ||
47 | + } | ||
48 | + // | ||
49 | +}); | ||
50 | + | ||
51 | +router.get('/products/detail/:id', function (req, res) { | ||
52 | + //url 에서 변수 값을 받아올때 req.params.id 로 받아온다 | ||
53 | + var word = req.query.keyword; | ||
54 | + redirectUrls = req.params.id; | ||
55 | + CategoriModel.findOne({ _id: req.params.id }, function (err, product) { | ||
56 | + var video = []; | ||
57 | + //제품정보를 받고 그안에서 댓글을 받아온다. | ||
58 | + CategoriModel.find({ product_id: req.params.id }, function (err, comments) { | ||
59 | + VideoModel.find(function (err, myVideo) { | ||
60 | + var mitem = []; // 카테고리별 비디오 목록을 담아두는 배열 | ||
61 | + var videos = []; // 비디오 목록을 담는 임시 배열 | ||
62 | + for (var j in myVideo) { | ||
63 | + if (product.title == myVideo[j].categori) { | ||
64 | + var k = { | ||
65 | + title: myVideo[j].title, | ||
66 | + id: myVideo[j]._id, | ||
67 | + }; | ||
68 | + videos.push(k); | ||
69 | + } | ||
70 | + } | ||
71 | + if (videos.length != 0) { | ||
72 | + // 빈 배열 체크 | ||
73 | + //console.log(videos); | ||
74 | + var items = videos; | ||
75 | + mitem.push(items); | ||
76 | + } | ||
77 | + //console.log(item[2].category.title); | ||
78 | + //console.log(item[2].videos); | ||
79 | + if (word != null) { | ||
80 | + var count = 0; | ||
81 | + youtube.addParam('order', 'rating'); // 평점 순으로 정렬 | ||
82 | + youtube.addParam('type', 'video'); // 타입 지정 | ||
83 | + youtube.addParam('videoLicense', 'creativeCommon'); // 크리에이티브 커먼즈 아이템만 불러옴 | ||
84 | + youtube.search(word, limit, function (err, result) { | ||
85 | + // 검색 실행 | ||
86 | + //console.log(word); | ||
87 | + if (err) { | ||
88 | + console.log(err); | ||
89 | + } // 에러일 경우 에러공지하고 빠져나감 | ||
90 | + //console.log(JSON.stringify(result, null, 2)); // 받아온 전체 리스트 출력 | ||
91 | + var items = result['items']; // 결과 중 items 항목만 가져옴 | ||
92 | + for (var i in items) { | ||
93 | + var it = items[i]; | ||
94 | + for (var j in it) { | ||
95 | + if (it[j]['title'] != null) { | ||
96 | + var title = it[j]['title']; | ||
97 | + } | ||
98 | + if (it[j]['videoId'] != null) { | ||
99 | + var video_id = it[j]['videoId']; | ||
100 | + } | ||
101 | + var urls = 'https://www.youtube.com/watch?v=' + video_id; | ||
102 | + } | ||
103 | + var item = { | ||
104 | + id: count, | ||
105 | + title: title, | ||
106 | + video_id: video_id, | ||
107 | + urls: urls, | ||
108 | + categori: product.title, | ||
109 | + }; | ||
110 | + count++; | ||
111 | + video.push(item); | ||
112 | + } | ||
113 | + res.render('category/productsDetail', { | ||
114 | + product: product, | ||
115 | + comments: comments, | ||
116 | + videos: video, | ||
117 | + items: mitem, | ||
118 | + }); | ||
119 | + }); | ||
120 | + } else { | ||
121 | + //console.log(mitem); | ||
122 | + res.render('category/productsDetail', { | ||
123 | + product: product, | ||
124 | + comments: comments, | ||
125 | + videos: video, | ||
126 | + items: mitem, | ||
127 | + }); | ||
128 | + } | ||
129 | + }); | ||
130 | + }); | ||
131 | + }); | ||
132 | +}); | ||
133 | + | ||
134 | +router.post('/products/detail/:id', loginRequired, function (req, res) { | ||
135 | + var item = []; | ||
136 | + var count = 1; | ||
137 | + var temp = ''; | ||
138 | + console.log(req.body.videoNum.length); | ||
139 | + if (req.body.videoNum.length > 30) { | ||
140 | + for (var i in req.body.videoNum) { | ||
141 | + temp += req.body.videoNum[i]; | ||
142 | + } | ||
143 | + item.push(temp.split('///')); | ||
144 | + var video = new VideoModel({ | ||
145 | + categori: item[0][2], | ||
146 | + id: count, | ||
147 | + title: item[0][1], | ||
148 | + video_id: item[0][3], | ||
149 | + urls: item[0][4], | ||
150 | + }); | ||
151 | + var validationError = video.validateSync(); | ||
152 | + if (validationError) { | ||
153 | + res.send(validationError); | ||
154 | + } else { | ||
155 | + video.save(function (err) {}); | ||
156 | + } | ||
157 | + count++; | ||
158 | + } else { | ||
159 | + for (var i in req.body.videoNum) { | ||
160 | + item.push(req.body.videoNum[i].split('///')); | ||
161 | + var video = new VideoModel({ | ||
162 | + categori: item[i][2], | ||
163 | + id: count, | ||
164 | + title: item[i][1], | ||
165 | + video_id: item[i][3], | ||
166 | + urls: item[i][4], | ||
167 | + }); | ||
168 | + var validationError = video.validateSync(); | ||
169 | + if (validationError) { | ||
170 | + res.send(validationError); | ||
171 | + } else { | ||
172 | + video.save(function (err) {}); | ||
173 | + } | ||
174 | + count++; | ||
175 | + } | ||
176 | + } | ||
177 | + res.redirect('/categori/products/detail/' + req.params.id); | ||
178 | +}); | ||
179 | + | ||
180 | +router.get('/products/edit/:id', loginRequired, function (req, res) { | ||
181 | + //기존에 폼에 value안에 값을 셋팅하기 위해 만든다. | ||
182 | + CategoriModel.findOne({ _id: req.params.id }, function (err, product) { | ||
183 | + res.render('category/form', { | ||
184 | + categories: product, | ||
185 | + }); | ||
186 | + }); | ||
187 | +}); | ||
188 | + | ||
189 | +router.post('/products/edit/:id', loginRequired, function (req, res) { | ||
190 | + //그전에 지정되 있는 파일명을 받아온다 | ||
191 | + CategoriModel.findOne({ _id: req.params.id }, function (err, product) { | ||
192 | + var query = { | ||
193 | + name: req.body.name, | ||
194 | + thumbnail: req.file ? req.file.filename : product.thumbnail, | ||
195 | + price: req.body.price, | ||
196 | + description: req.body.description, | ||
197 | + }; | ||
198 | + CategoriModel.update( | ||
199 | + { id: req.params.id }, | ||
200 | + { $set: query }, | ||
201 | + function (err) { | ||
202 | + res.redirect('/categori/products/detail/' + req.params.id); | ||
203 | + } | ||
204 | + ); | ||
205 | + }); | ||
206 | +}); | ||
207 | + | ||
208 | +router.get('/products/delete/:id', function (req, res) { | ||
209 | + CategoriModel.findOne({ _id: req.params.id }, function (err, products) { | ||
210 | + CategoriModel.deleteMany({ _id: req.params.id }, function (err) { | ||
211 | + VideoModel.find(function (err, myVideo) { | ||
212 | + for (var i in myVideo) { | ||
213 | + if (products.title == myVideo[i].categori) { | ||
214 | + var deleteItem = myVideo[i].categori; | ||
215 | + } | ||
216 | + } | ||
217 | + VideoModel.deleteMany({ categori: deleteItem }, function (err) { | ||
218 | + res.redirect('/categori/products'); | ||
219 | + }); | ||
220 | + }); | ||
221 | + }); | ||
222 | + }); | ||
223 | +}); | ||
224 | + | ||
225 | +router.get('/products/detail/delete/:id', function (req, res) { | ||
226 | + VideoModel.findOne({ _id: req.params.id }, function (err, products) { | ||
227 | + VideoModel.deleteMany({ _id: products }, function (err) { | ||
228 | + res.redirect('/categori/products/detail/' + redirectUrls); | ||
229 | + }); | ||
230 | + }); | ||
231 | +}); | ||
232 | + | ||
233 | +router.post('/products/ajax_comment/insert', function (req, res) { | ||
234 | + var comment = new CategoriModel({ | ||
235 | + content: req.body.content, | ||
236 | + product_id: parseInt(req.body.product_id), | ||
237 | + }); | ||
238 | + comment.save(function (err, comment) { | ||
239 | + res.json({ | ||
240 | + id: comment.id, | ||
241 | + content: comment.content, | ||
242 | + message: 'success', | ||
243 | + }); | ||
244 | + }); | ||
245 | +}); | ||
246 | + | ||
247 | +router.post('/products/ajax_comment/delete', function (req, res) { | ||
248 | + CategoriModel.remove({ _id: req.body.comment_id }, function (err) { | ||
249 | + res.json({ message: 'success' }); | ||
250 | + }); | ||
251 | +}); | ||
252 | + | ||
253 | +module.exports = router; |
views/accounts/join.ejs
0 → 100644
1 | +<% include ../includes/header.ejs %> | ||
2 | +<div class="w-25 border border-info border-3" style="position: absolute; left: 37%; top: 17%;"> | ||
3 | + <div> | ||
4 | + <div> | ||
5 | + <div style="padding-top: 5%; padding-left: 5%;"> | ||
6 | + <h3 class="panel-title">회원가입</h3> | ||
7 | + </div> | ||
8 | + <div class="panel-body"> | ||
9 | + <form role="form" action="" id="join_form" method="post"> | ||
10 | + <fieldset> | ||
11 | + <div class="w-100" style="padding-left: 5%; padding-right: 5%;"> | ||
12 | + <input class="form-control" placeholder="ID" name="username" type="text" autofocus="" required=""> | ||
13 | + </div> | ||
14 | + <div class="w-100" style="padding-left: 5%; padding-right: 5%;padding-top: 3%"> | ||
15 | + <input class="form-control" placeholder="Password" name="password" type="password" value="" required=""> | ||
16 | + </div> | ||
17 | + <div class="w-100" style="padding-left: 5%; padding-right: 5%;padding-top: 3%"> | ||
18 | + <input class="form-control" placeholder="Password 확인" name="password2" type="password" value="" required=""> | ||
19 | + </div> | ||
20 | + <div class="w-100" style="padding-left: 5%; padding-right: 5%;padding-top: 3%"> | ||
21 | + <input class="form-control" placeholder="이름" name="displayname" type="text" value="" required=""> | ||
22 | + </div> | ||
23 | + <!-- Change this to a button or input when using this as a form --> | ||
24 | + <div class="d-grid gap-2 col-11 mx-auto p-2"> | ||
25 | + <input type="submit" class="btn btn-lg btn-success btn-block" value="가입하기"> | ||
26 | + <a href="/auth/google" class="btn btn-lg btn-danger btn-block"> | ||
27 | + <i class="fa fa-google" aria-hidden="true"></i> Google 회원가입 | ||
28 | + </a> | ||
29 | + </div> | ||
30 | + </fieldset> | ||
31 | + </form> | ||
32 | + </div> | ||
33 | + </div> | ||
34 | + </div> | ||
35 | +</div> | ||
36 | +<script type="text/javascript"> | ||
37 | +(function(){ | ||
38 | + $(document).ready(function() { | ||
39 | + $('#join_form').submit(function(){ | ||
40 | + var $usernameInput = $('#join_form input[name=username]'); | ||
41 | + var $passwordInput = $('#join_form input[name=password]'); | ||
42 | + var $passwordInput2 = $('#join_form input[name=password2]'); | ||
43 | + var $displayname = $('#join_form input[name=displayname]'); | ||
44 | + if(!$usernameInput.val()){ | ||
45 | + alert("아이디를 입력해주세요."); | ||
46 | + $usernameInput.focus(); | ||
47 | + return false; | ||
48 | + } | ||
49 | + if(!$passwordInput.val()){ | ||
50 | + alert("패스워드를 입력해주세요."); | ||
51 | + $passwordInput.focus(); | ||
52 | + return false; | ||
53 | + } | ||
54 | + if(!$passwordInput2.val()){ | ||
55 | + alert("확인 패스워드를 입력해주세요."); | ||
56 | + $passwordInput2.focus(); | ||
57 | + return false; | ||
58 | + } | ||
59 | + if(!$displayname.val()){ | ||
60 | + alert("이름을 입력해주세요."); | ||
61 | + $displayname.focus(); | ||
62 | + return false; | ||
63 | + } | ||
64 | + if($passwordInput.val() !== $passwordInput2.val()){ | ||
65 | + alert("패스워드와 확인용패스워드를 똑같이 입력해주세요."); | ||
66 | + return false; | ||
67 | + } | ||
68 | + return true; | ||
69 | + }); | ||
70 | + }); | ||
71 | +})(); | ||
72 | +</script> | ||
73 | +<% include ../includes/footer.ejs %> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
views/accounts/login.ejs
0 → 100644
1 | +<% include ../includes/header.ejs %> | ||
2 | +<div class="w-25 border border-info border-3" style="position: absolute; left: 37%; top: 17%;"> | ||
3 | + <div> | ||
4 | + <%if(typeof flashMessage !=='undefined') {%> | ||
5 | + <div class="alert alert-danger" role="alert"><%=flashMessage%></div> | ||
6 | + <%}%> | ||
7 | + <div> | ||
8 | + <div style="padding-top: 5%; padding-left: 5%;"> | ||
9 | + <h3 class="panel-title">로그인</h3> | ||
10 | + </div> | ||
11 | + <div class="panel-body"> | ||
12 | + <form role="form" action="" id="login_form" method="post"> | ||
13 | + <fieldset> | ||
14 | + <div class="w-100" style="padding-left: 5%; padding-right: 5%;"> | ||
15 | + <label for="login" class="form-label">ID</label> | ||
16 | + <input class="form-control" placeholder="ID" name="username" type="text" autofocus="" required=""> | ||
17 | + </div> | ||
18 | + <div class="w-100 p-3"> | ||
19 | + <label for="password" class="form-label">Password</label> | ||
20 | + <input class="form-control" placeholder="Password" name="password" type="password" value="" required=""> | ||
21 | + </div> | ||
22 | + <!-- Change this to a button or input when using this as a form --> | ||
23 | + <div class="d-grid gap-2 col-11 mx-auto p-2"> | ||
24 | + <input type="submit" class="btn btn-lg btn-success btn-block" value="로그인"> | ||
25 | + <a href="/auth/google" class="btn btn-lg btn-danger btn-block"> | ||
26 | + <i class="fa fa-google" aria-hidden="true"></i> Google 로그인 | ||
27 | + </a> | ||
28 | + </div> | ||
29 | + </fieldset> | ||
30 | + </form> | ||
31 | + </div> | ||
32 | + </div> | ||
33 | + </div> | ||
34 | +</div> | ||
35 | +<script type="text/javascript"> | ||
36 | +(function(){ | ||
37 | + $(document).ready(function() { | ||
38 | + $('#login_form').submit(function(){ | ||
39 | + var $usernameInput = $('#login_form input[name=username]'); | ||
40 | + var $passwordInput = $('#login_form input[name=password]'); | ||
41 | + if(!$usernameInput.val()){ | ||
42 | + alert("아이디를 입력해주세요."); | ||
43 | + $usernameInput.focus(); | ||
44 | + return false; | ||
45 | + } | ||
46 | + if(!$passwordInput.val()){ | ||
47 | + alert("패스워드를 입력해주세요."); | ||
48 | + $passwordInput.focus(); | ||
49 | + return false; | ||
50 | + } | ||
51 | + return true; | ||
52 | + }); | ||
53 | + }); | ||
54 | +})(); | ||
55 | +</script> | ||
56 | +<% include ../includes/footer.ejs %> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
views/category/form.ejs
0 → 100644
1 | +<% include ../includes/header.ejs %> | ||
2 | + <form action="" method="post" > | ||
3 | + <table class="table table-bordered"> | ||
4 | + <tr> | ||
5 | + <th>카테고리명</th> | ||
6 | + <td><input type="text" name="title" class="form-control" value="<%=categories.title%>"/></td> | ||
7 | + </tr> | ||
8 | + <tr> | ||
9 | + <th>설명</th> | ||
10 | + <td><input type="text" name="description" class="form-control" value="<%=categories.description%>"/></td> | ||
11 | + </tr> | ||
12 | + </table> | ||
13 | + <input type="submit" name="submit" value="완료" class="btn btn-primary"> | ||
14 | + </form> | ||
15 | +<% include ../includes/footer.ejs %> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
views/category/products.ejs
0 → 100644
1 | +<% include ../includes/header.ejs %> | ||
2 | + <table class="table table-bordered table-hover"> | ||
3 | + <tr class="table-info"> | ||
4 | + <th width="80px" style="text-align: center;">카테고리명</th> | ||
5 | + <th width="50px" style="text-align: center;">개설 날짜</th> | ||
6 | + <th width="550px" style="text-align: center;">내용</th> | ||
7 | + <th width="50px" style="text-align: center;">사용자명</th> | ||
8 | + <th width="30px" style="text-align: center;">삭제</th> | ||
9 | + </tr> | ||
10 | + <%categories.forEach(function(product){%> | ||
11 | + <tr> | ||
12 | + <td style="text-align: center;"> | ||
13 | + <a href="/categori/products/detail/<%=product.id%>"><%=product.title%></a> | ||
14 | + </td> | ||
15 | + <td style="text-align: center;" > | ||
16 | + <%=product.getDate.year%> - | ||
17 | + <%=product.getDate.month%> - | ||
18 | + <%=product.getDate.day%> | ||
19 | + </td> | ||
20 | + <td> | ||
21 | + <%=product.description%> | ||
22 | + </td> | ||
23 | + <td style="text-align: center;"> | ||
24 | + <%=product.username%> | ||
25 | + </td> | ||
26 | + <td style="text-align: center;"> | ||
27 | + <a href="/categori/products/delete/<%=product.id%>" class="btn btn-danger" onclick="return confirm('삭제하시겠습니까?')">삭제</a> | ||
28 | + </td> | ||
29 | + </tr> | ||
30 | + <% }); %> | ||
31 | + </table> | ||
32 | + | ||
33 | + <a href="/categori/categories/write" class="btn btn-primary">작성하기</a> | ||
34 | + | ||
35 | +<% include ../includes/footer.ejs %> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
views/category/productsDetail.ejs
0 → 100644
1 | +<% include ../includes/header.ejs %> | ||
2 | + <div class="panel panel-default"> | ||
3 | + <div class="panel-heading"> | ||
4 | + <h2 style="padding-left: 30px;"><%=product.title%></h2> | ||
5 | + <div style="padding-bottom: 10px;"> | ||
6 | + 작성일 : | ||
7 | + <%=product.getDate.year%> - | ||
8 | + <%=product.getDate.month%> - | ||
9 | + <%=product.getDate.day%> | ||
10 | + </div> | ||
11 | + <div style="padding-left: 30px"> | ||
12 | + 설명 : <%=product.description%> | ||
13 | + </div> | ||
14 | + <hr/> | ||
15 | + </div> | ||
16 | + | ||
17 | + <div> | ||
18 | + <% var count=0; %> | ||
19 | + <% if (items.length != 0) { %> | ||
20 | + <ul class="list-group" style="padding-left: 30px; padding-bottom: 30px;"> | ||
21 | + <li class="list-group-item list-group-item-info" aria-current="true">보유중인 영상</li> | ||
22 | + <% for (var i in items[0]) { %> | ||
23 | + <li class="list-group-item"><%=items[0][i].title%> <a href="/categori/products/detail/delete/<%=items[0][i].id%>" style="position: absolute; right: 1%;" class="btn btn-danger btn-sm" onclick="return confirm('삭제하시겠습니까?')">삭제</a></li> | ||
24 | + <%count++;};%> | ||
25 | + </ul> | ||
26 | + <%};%> | ||
27 | + </div> | ||
28 | + <button style="margin-left: 30px; margin-bottom: 10px;" class="btn btn-outline-primary" type="button" data-bs-toggle="collapse" data-bs-target="#collapseExample" | ||
29 | + aria-expanded="false" aria-controls="collapseExample"> | ||
30 | + 영상 추가하기 | ||
31 | + </button> | ||
32 | + <div class="collapse show" id="collapseExample" style="padding-left: 30px;"> | ||
33 | + <div class="card card-body"> | ||
34 | + <form method="get" action=""> | ||
35 | + <div class="input-group" style="padding-left: 10px;"> | ||
36 | + <input type="text" class="form-control" placeholder="검색 키워드를 입력하세요!" name="keyword" autocomplete='off'> | ||
37 | + <span class="input-group-btn"> | ||
38 | + <button class="btn btn-secondary" type="submit">찾기</button> | ||
39 | + </span> | ||
40 | + </div> | ||
41 | + </form> | ||
42 | + <form method="post" action=""> | ||
43 | + <% for (var i in videos) { %> | ||
44 | + <div style="float:left; | ||
45 | + padding: 15px; | ||
46 | + "> | ||
47 | + <input type="checkbox" name="videoNum" style=" | ||
48 | + position: absolute; | ||
49 | + margin-top: 5px; | ||
50 | + margin-left: 5px; | ||
51 | + z-index: 4; | ||
52 | + zoom:3.0; | ||
53 | + " | ||
54 | + value="<%=videos[i].id + '///' + videos[i].title +'///'+ videos[i].categori +'///'+ videos[i].video_id +'///'+ videos[i].urls%>" /> | ||
55 | + <div id="<%=videos[i].id%>" vid="<%=videos[i].video_id%>"> | ||
56 | + </div> | ||
57 | + </div> | ||
58 | + <%};%> | ||
59 | + <button class="btn btn-primary" style="margin-top: 10px; margin-left: 10px;">영상담기</button> | ||
60 | + </form> | ||
61 | + </div> | ||
62 | + </div> | ||
63 | + <div class="panel-body"> | ||
64 | + <div> | ||
65 | + <hr /> | ||
66 | + </div> | ||
67 | + </div> | ||
68 | + </div> | ||
69 | + | ||
70 | + <div style="padding-bottom: 30px;"> | ||
71 | + <a href="/categori/products" class="btn btn-dark">목록으로</a> | ||
72 | + <a href="/categori/products/edit/<%=product._id%>" class="btn btn-primary">수정</a> | ||
73 | + </div> | ||
74 | +<% include ../includes/footer.ejs %> | ||
75 | + | ||
76 | +<script> | ||
77 | +(function(){ | ||
78 | + // 영상 메모 구현 파트(아직 미구현) | ||
79 | + $(document).ready(function() { | ||
80 | + $('#commentForm').submit(function(){ | ||
81 | + var $contentVal = $(this).children('textarea[name=content]').val(); | ||
82 | + if($contentVal){ | ||
83 | + $.ajax({ | ||
84 | + url: '/admin/products/ajax_comment/insert', | ||
85 | + type: 'POST', | ||
86 | + data: $(this).serialize(), | ||
87 | + }) | ||
88 | + .done(function(args) { | ||
89 | + if(args.message==="success"){ | ||
90 | + $('#comment_area').append( | ||
91 | + '<div>' + args.content + | ||
92 | + " ( <a class='comment_delete' comment_id='"+ args._id +"'>삭제</a> ) </div>" | ||
93 | + ); | ||
94 | + $('#commentForm textarea[name=content]').val(""); | ||
95 | + } | ||
96 | + }) | ||
97 | + .fail(function(args) { | ||
98 | + console.log(args); | ||
99 | + }); | ||
100 | + }else{ | ||
101 | + alert('댓글 내용을 입력해주세요.') | ||
102 | + } | ||
103 | + return false; | ||
104 | + }); | ||
105 | + }); | ||
106 | +})(); | ||
107 | +</script> | ||
108 | + | ||
109 | +<script> | ||
110 | + var tag = document.createElement('script'); | ||
111 | + | ||
112 | + tag.src = "https://www.youtube.com/iframe_api"; | ||
113 | + var firstScriptTag = document.getElementsByTagName('script')[0]; | ||
114 | + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); | ||
115 | + | ||
116 | + var player; | ||
117 | + var players = []; | ||
118 | + var videoIds = []; | ||
119 | + for (var i = 0; i < 10; i++) { | ||
120 | + players.push(String(i)); | ||
121 | + videoIds.push($('#' + i).attr('vid')); | ||
122 | + } | ||
123 | + | ||
124 | + function onYouTubeIframeAPIReady() { | ||
125 | + for (var i = 0; i < videoIds.length; i++) { | ||
126 | + player = new YT.Player(players[i], { | ||
127 | + height: '360', | ||
128 | + width: '640', | ||
129 | + videoId: videoIds[i], | ||
130 | + events: { | ||
131 | + } | ||
132 | + }); | ||
133 | + } | ||
134 | + } | ||
135 | +</script> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
views/home.ejs
0 → 100644
1 | +<% include ./includes/header.ejs %> | ||
2 | + <div style="background-color:lavenderblush;"> | ||
3 | + <h2 style="padding: 30px;">Categories</h2> | ||
4 | + <% var count = 0; var collapseCount = 'less';%> | ||
5 | + <center> | ||
6 | + <div class="accordion w-85" id="accordionExample" style="padding-bottom: 20px;"> | ||
7 | + <% for (var i in video) { %> | ||
8 | + <div class="accordion-item" style="margin: 20px;"> | ||
9 | + <h2 class="accordion-header" id="<%=video[i].category.title%>"> | ||
10 | + <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#<%=collapseCount%>" | ||
11 | + aria-expanded="true" aria-controls="<%=collapseCount%>" style ="padding-top: 30px"> | ||
12 | + <%=video[i].category.title%> | ||
13 | + </button> | ||
14 | + </h2> | ||
15 | + <div id="<%=collapseCount%>" data-bs-parent="#accordionExample" class="accordion-collapse collapse" aria-labelledby="<%=video[i].category.title%>"> | ||
16 | + <div class="accordion-body"> | ||
17 | + <% for (var j in video[i].videos) { %> | ||
18 | + <div class="card" style="width: 55rem; margin-bottom: 15px; margin-top: 15px;"> | ||
19 | + <div class="card-top" id="<%=count%>" vid="<%=video[i].videos[j].video_id%>" style="margin: 30px;"> | ||
20 | + </div> | ||
21 | + <div class="card-body"> | ||
22 | + <h5 class="card-title"><%=video[i].videos[j].title%></h5> | ||
23 | + <p class="card-text">해당 영상에 대한 메모를 여기에 출력. | ||
24 | + </p> | ||
25 | + </div> | ||
26 | + </div> | ||
27 | + <%count++;}; %> | ||
28 | + </div> | ||
29 | + </div> | ||
30 | + </div> | ||
31 | + <%collapseCount = collapseCount+ "le";%> | ||
32 | + <%};%> | ||
33 | + </div> | ||
34 | + </center> | ||
35 | + </div> | ||
36 | + | ||
37 | + <style type="text/css"> | ||
38 | + .masonry-grid img { | ||
39 | + max-width: 260px; | ||
40 | + } | ||
41 | + </style> | ||
42 | + <script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script> | ||
43 | + <script type="text/javascript" | ||
44 | + src="https://cdnjs.cloudflare.com/ajax/libs/jquery.imagesloaded/4.1.1/imagesloaded.pkgd.min.js"></script> | ||
45 | + <script type="text/javascript"> | ||
46 | + var $masonry_container = $('#masonry_container'); | ||
47 | + $masonry_container.imagesLoaded(function () { | ||
48 | + $masonry_container.masonry({ | ||
49 | + itemSelector: '.masonry-grid', | ||
50 | + columnWidth: 270 | ||
51 | + }); | ||
52 | + }); | ||
53 | + </script> | ||
54 | + <script> | ||
55 | + var tag = document.createElement('script'); | ||
56 | + | ||
57 | + tag.src = "https://www.youtube.com/iframe_api"; | ||
58 | + var firstScriptTag = document.getElementsByTagName('script')[0]; | ||
59 | + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); | ||
60 | + var player; | ||
61 | + var players = []; | ||
62 | + var videoIds = []; | ||
63 | + for (var i = 0; i < 30; i++) { | ||
64 | + players.push(String(i)); | ||
65 | + videoIds.push($('#' + players[i]).attr('vid')); | ||
66 | + } | ||
67 | + | ||
68 | + function onYouTubeIframeAPIReady() { | ||
69 | + for (var i = 0; i < videoIds.length; i++) { | ||
70 | + player = new YT.Player(players[i], { | ||
71 | + height: '450', | ||
72 | + width: '800', | ||
73 | + videoId: videoIds[i], | ||
74 | + }); | ||
75 | + } | ||
76 | + } | ||
77 | + </script> | ||
78 | + <% include ./includes/footer.ejs %> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
views/includes/footer.ejs
0 → 100644
views/includes/header.ejs
0 → 100644
1 | +<!DOCTYPE html> | ||
2 | +<html lang="en"> | ||
3 | +<head> | ||
4 | + <meta charset="UTF-8"> | ||
5 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
6 | + <meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||
7 | + <title>MYCOOK</title> | ||
8 | + <script | ||
9 | + src="https://code.jquery.com/jquery-3.2.1.min.js" | ||
10 | + integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" | ||
11 | + crossorigin="anonymous"></script> | ||
12 | + <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> | ||
13 | + <!--bootstrap js 추가 --> | ||
14 | + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" | ||
15 | + integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous"> | ||
16 | + <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" | ||
17 | + integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4" | ||
18 | + crossorigin="anonymous"></script> | ||
19 | +</head> | ||
20 | +<body> | ||
21 | + <div class="container-fluid" style="margin-top: 15px;"> | ||
22 | + <nav class="navbar navbar-light" style="background-color: #e3f2fd;"> | ||
23 | + <div> | ||
24 | + <div class="navbar-brand" style="float: left;"> | ||
25 | + <a href="/" class="nav-link">MyCookBook</a> | ||
26 | + </div> | ||
27 | + <div class="navbar"> | ||
28 | + <ul class="nav"> | ||
29 | + <li class="nav-item"> | ||
30 | + <a class="nav-link" href="/">Home</a> | ||
31 | + </li> | ||
32 | + <li class="nav-item"><a class="nav-link" href="/categori/products">Category</a></li> | ||
33 | + <% if(isLogin){%> | ||
34 | + <li class="nav-item"><a class="nav-link" href="/accounts/logout" onclick="return confirm('로그아웃 하시겠습니까?')">LOGOUT</a></li> | ||
35 | + <%}else{%> | ||
36 | + <li class="nav-item"><a class="nav-link" href="/accounts/join">SignUp</a></li> | ||
37 | + <li class="nav-item"><a class="nav-link" href="/accounts/login">LOGIN</a></li> | ||
38 | + <%}%> | ||
39 | + </ul> | ||
40 | + </div> | ||
41 | + </div> | ||
42 | + </nav> | ||
43 | + <hr style=" border: 2px solid #4263eb" /> | ||
44 | + |
-
Please register or login to post a comment