윤준현

frontEnd add home screen / chaning backend

......@@ -4,42 +4,45 @@ var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var history = require('connect-history-api-fallback');
var cors = require('cors')
var cors = require('cors');
var app = express();
var mongoDB = require('./lib/db_info')
var mongoDB = require('./lib/db_info');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
if (process.env.NODE_ENV !== 'production')
app.use(cors());
if (process.env.NODE_ENV !== 'production') app.use(cors());
app.use('/api', require('./routes/api'));
app.use(history());
app.use(express.static(path.join(__dirname, '../frontend', 'dist')));
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.send({ msg: err.message });
console.error(err.message);
// render the error page
res.status(err.status || 500);
res.send({ msg: err.message });
console.error(err.message);
});
module.exports = app;
const mongoose = require('mongoose')
const mongoose = require('mongoose');
mongoose.connect(mongoDB.db, { useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: true }, (err) => {
if (err) return console.error(err)
console.log('mongoose connected')
})
\ No newline at end of file
mongoose.connect(
mongoDB.db,
{ useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: true },
(err) => {
if (err) return console.error(err);
console.log('mongoose connected');
}
);
......
......@@ -13,7 +13,7 @@
"express": "~4.16.1",
"http-errors": "~1.6.3",
"moment": "^2.24.0",
"mongoose": "^5.9.6",
"mongoose": "^5.9.7",
"morgan": "~1.9.1",
"multer": "^1.4.2",
"pug": "2.0.0-beta11"
......
var express = require('express');
var createError = require('http-errors');
var router = express.Router();
const post = require('../../../model/video')
const post = require('../../../model/video');
const tags = require('../../../model/tagList');
router.get('/list', (req, res, next) => {
let { tag, skip } = req.query
let joinedTag = tag.join("|")
let regexsearch = { tag: { $regex: joinedTag, $options: 'si' } }
skip = parseInt(skip)
post.find()
.sort({'_id': -1})
.limit(12)
.skip(skip)
.then(rs => {
console.log(rs)
res.send({ success: true, d: rs, })
})
.catch(e => {
console.log(e)
res.send({ success: false, msg: e.message })
})
})
let { tags, skip } = req.query;
let joinedTag;
console.log(tags);
if (tags) joinedTag = tags.join('|');
else {
joinedTag = '';
}
let regexsearch = { tag: { $regex: joinedTag, $options: 'si' } };
skip = parseInt(skip);
post
.find(regexsearch)
.sort({ _id: -1 })
.limit(10)
.skip(skip)
.then((rs) => {
res.send({ success: true, d: rs });
})
.catch((e) => {
console.log(e);
res.send({ success: false, msg: e.message });
});
});
router.get('/tag', (req, res, next) => {
tags
.find()
.then((rs) => {
var temp = [];
rs.forEach((element) => {
element.tag.forEach((element) => {
temp.push(element);
});
});
var uniqArray = Array.from(new Set(temp));
res.send({ success: true, d: uniqArray });
})
.catch((e) => {
console.log(e);
res.send({ success: false, msg: e.message });
});
});
router.delete('/:_id', (req, res, next) => {
const _id = req.params._id
post.findOne({ _id })
.then(r => {
console.log(r)
return post.deleteOne({ _id })
})
.then(r => {
res.send({ success: true, d: r})
})
.catch(e => {
console.log(e)
res.send({ success: false, msg: e.message })
})
})
const _id = req.params._id;
post
.findOne({ _id })
.then((r) => {
console.log(r);
return post.deleteOne({ _id });
})
.then((r) => {
res.send({ success: true, d: r });
})
.catch((e) => {
console.log(e);
res.send({ success: false, msg: e.message });
});
});
router.all('*', function (req, res, next) {
next(new Error ('Wrong Url!'));
next(new Error('Wrong Url!'));
});
module.exports = router;
\ No newline at end of file
module.exports = router;
......
......@@ -2,12 +2,11 @@ var createError = require('http-errors');
var express = require('express');
var router = express.Router();
router.use('/home', require('./home'))
router.use('/upload', require('./upload'))
router.use('/home', require('./home'));
router.use('/upload', require('./upload'));
router.all('*', function(req, res, next) {
next(createError(404, 'This page is not exisit'))
})
module.exports = router
router.all('*', function (req, res, next) {
next(createError(404, 'This page is not exisit'));
});
module.exports = router;
......
var express = require('express');
var createError = require('http-errors');
var router = express.Router();
const post = require('../../../model/video')
const multer = require('multer')
var moment = require('moment')
var fs = require('fs')
const post = require('../../../model/video');
const tags = require('../../../model/tagList');
const multer = require('multer');
var moment = require('moment');
var fs = require('fs');
// event post
router.post('/video', multer({dest: 'videos/'}).single('bin'), (req, res, next) => {
console.log(req.file)
router.post(
'/video',
multer({ dest: 'videos/' }).single('bin'),
(req, res, next) => {
console.log(req.file);
fs.rename(`../../../videos/${req.file.filename}`, `../../../videos/${req.file.originalname}`, (r) => {
console.log(r)
})
var atc = {
videoUrl : req.file.location,
title : req.body.title,
tag: req.body.tag
}
// post.create(atc)
// .then( r => {
// res.send({ success: true, d: r, token: req.token })
// })
// .catch((err) => {
// console.log(err);
// res.send({ success: false, msg: err.message })
// });
})
router.post('/post', (req,res,next) => {
console.log(req.body)
var atc = {
title : req.body.title,
tag: req.body.tag
}
post.create(atc)
.then( r => {
res.send({ success: true, d: r, token: req.token })
})
.catch((err) => {
console.log(err);
res.send({ success: false, msg: err.message })
});
})
fs.rename(
`../../../videos/${req.file.filename}`,
`../../../videos/${req.file.originalname}`,
(r) => {
console.log(r);
}
);
var atc = {
videoUrl: req.file.location,
title: req.body.title,
tag: req.body.tag,
};
// post.create(atc)
// .then( r => {
// res.send({ success: true, d: r, token: req.token })
// })
// .catch((err) => {
// console.log(err);
// res.send({ success: false, msg: err.message })
// });
}
);
router.post('/post', (req, res, next) => {
console.log(req.body);
var atc = {
title: req.body.title,
tag: req.body.tag,
};
tags
.create({ tag: req.body.tag })
.then(() => {
return post.create(atc);
})
.then((r) => {
res.send({ success: true, d: r, token: req.token });
})
.catch((err) => {
console.log(err);
res.send({ success: false, msg: err.message });
});
});
router.all('*', function(req, res, next) {
next(createError(404, 'This page is not exisit'))
})
router.all('*', function (req, res, next) {
next(createError(404, 'This page is not exisit'));
});
module.exports = router
module.exports = router;
......
This file is too large to display.
......@@ -597,10 +597,10 @@ mongoose-legacy-pluralize@1.0.2:
resolved "https://registry.yarnpkg.com/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz#3ba9f91fa507b5186d399fb40854bff18fb563e4"
integrity sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==
mongoose@^5.9.6:
version "5.9.6"
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.9.6.tgz#47e2e234638eede4caa52d961e3a7459b55530ef"
integrity sha512-EfFGO2QUoenf/4eFeF5y2R8aBLKHtqwrMk1pVGgl3OyNWufP5XLLPIuihP006YqR1+6xM1YsBzGpgBjMZkINGA==
mongoose@^5.9.7:
version "5.9.7"
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.9.7.tgz#03c581860d0e2f60f6008f9457ab0c2905609875"
integrity sha512-WJOBh9WMvivqBK8my9HFtSzSySKdUxJPNGAwswEakAasWUcPXJl3yHMtZ4ngGnKbwTT9KnAr75xamlt/PouR9w==
dependencies:
bson "~1.1.1"
kareem "2.3.1"
......
<template>
<div>
<v-layout></v-layout>
<v-card></v-card>
</div>
</template>
<script>
export default {};
</script>
<style scoped></style>
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import vuetify from "./plugins/vuetify";
import "roboto-fontface/css/roboto/roboto-fontface.css";
import "@mdi/font/css/materialdesignicons.css";
import * as VeeValidate from "vee-validate";
import "./vee-validate";
import infiniteScroll from "vue-infinite-scroll";
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import vuetify from './plugins/vuetify';
import 'roboto-fontface/css/roboto/roboto-fontface.css';
import '@mdi/font/css/materialdesignicons.css';
import * as VeeValidate from 'vee-validate';
import './vee-validate';
import infiniteScroll from 'vue-infinite-scroll';
Vue.config.productionTip = false;
Vue.use(infiniteScroll);
Vue.use(VeeValidate);
new Vue({
router,
store,
vuetify,
render: h => h(App)
}).$mount("#app");
router,
store,
vuetify,
render: (h) => h(App),
}).$mount('#app');
......
......@@ -12,12 +12,14 @@ export default new Vuetify({
themes: {
light: {
primary: "#7DC1E8",
secondary: "#EBC478",
accent: "#82B1FF",
secondary: "#FFCE67",
accent: "#ddeefc",
error: "#FF5252",
info: "#2196F3",
success: "#4CAF50",
warning: "#FFC107",
blue: "#173f5f",
lightblue: "#72b1e4",
success: "#2779bd",
warning: "#12283a",
grey300: "#eceeef",
grey500: "#aaaaaa",
grey700: "#5a5a5a",
......
import Vue from "vue";
import Vuex from "vuex";
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
tags: []
},
mutations: {
setTags(state, tags) {
state.tags = tags;
}
},
getters: {
getTags: state => {
return state.tags;
}
},
actions: {
commitSetTags: context => {
return context.commit("setTags");
}
},
modules: {}
state: {
tags: [],
videoList: [],
},
mutations: {
setTags(state, tags) {
state.tags = tags;
},
setVideoList(state, list) {
state.videoList = list;
},
},
getters: {
getTags: (state) => {
return state.tags;
},
getList: (state) => {
return state.videoList;
},
},
actions: {
LoadTags: (context) => {
return context.commit('setTags');
},
},
modules: {},
});
......
<template>
<v-sheet>
<!-- autocomplete에 저장된 tag 넣어서(동영상 업로드 할 때마다 tag가 저장됨) 자동완성 되게끔.-->
<v-text-field
class="mx-10 mt-4 mb-5"
prepend-inner-icon="mdi-shape"
v-model="search"
label="Tag"
placeholder="Search Tag"
type="text"
>
</v-text-field>
<!-- 동영상 리스트 -->
<v-layout justify-center>
<v-row class="mx-5">
<v-flex
xs12
sm6
v-for="(post, index) in postList"
:key="index"
class="mx-0"
<v-flex xs12 sm8 md8 lg6>
<v-row class="mx-0 mt-10 mb-8" justify="center">
<v-icon color="lightblue">mdi-power-on</v-icon>
<div
style="text-align: center; font-size: 22px; font-weight: 400; color: #343a40; "
>Video List</div>
<v-icon color="lightblue">mdi-power-on</v-icon>
</v-row>
<v-autocomplete
class="mx-5"
v-model="params.tags"
:items="tagsList"
placeholder="Click to search Tags"
prepend-inner-icon="mdi-shape"
chips
multiple
deletable-chips
item-color="primary"
></v-autocomplete>
<!-- 동영상 리스트 -->
<div
v-infinite-scroll="getPost"
infinite-scroll-disabled="busy"
infinite-scroll-distance="10"
class="mb-2"
>
<v-card class="mx-2 my-1">
<div>{{ post.title }}1</div>
</v-card>
</v-flex>
</v-row>
<v-row class="mx-5">
<v-flex xs12 md6 v-for="(post, index) in postList" :key="index" class="mx-0">
<v-card class="mx-1 my-1" elevation="0" outlined>
<div class="mx-2 my-1" style="font-size: 18px; color: #5a5a5a">{{ post.title }}</div>
<v-img height="250" style="border-top: 1px solid; solid;;border-color: #e0e0e0">
<div style="background-color: #7DC1E8; height: 250px">
<v-row justify="end" class="mx-0">
<v-avatar @click="delte()" size="30" color="#888" class="mt-1 mr-1">
<v-icon color="white">mdi-delete</v-icon>
</v-avatar>
</v-row>
<div
style="margin-left: 130px; margin-top: 70px; color: #ffff; font-size: 20px"
>Sample</div>
</div>
</v-img>
<v-divider></v-divider>
<v-chip-group column class="mx-1">
<v-chip color="secondary" v-for="(tag, index) in post.tag" :key="index">#{{ tag }}</v-chip>
</v-chip-group>
</v-card>
</v-flex>
</v-row>
</div>
</v-flex>
</v-layout>
</v-sheet>
</template>
......@@ -36,23 +64,69 @@ export default {
data() {
return {
postList: [],
search: "",
tagsList: [],
busy: false,
params: {
tag: ["", ""],
skip: 0
tags: [],
skip: 0,
page: 1
}
};
},
mounted() {
watch: {
"params.tags"(newValue, oldValue) {
console.log(newValue, oldValue);
this.postList = [];
this.params.page = 1;
this.getPost();
}
},
computed: {
setSkip() {
if (this.params.page <= 0) return 0;
return (this.params.page - 1) * 10;
}
},
created() {
this.getPost();
this.getTags();
},
methods: {
getPost() {
this.busy = true;
this.params.skip = this.setSkip;
if (this.postList.length !== (this.params.page - 1) * 10) {
return;
}
this.$axios
.get("/home/list", { params: this.params })
.then(r => {
this.postList = r.data.d;
console.log(this.postList);
for (let i = 0; i < r.data.d.length; i++) {
this.postList.push(r.data.d[i]);
}
this.busy = false;
this.params.page++;
})
.catch(e => {
console.log(e);
});
},
getTags() {
this.$axios
.get("/home/tag")
.then(r => {
this.tagsList = r.data.d;
})
.catch(e => {
console.log(e);
});
},
delete(atc) {
this.$axios
.delete(`/home/${atc._id}`)
.then(() => {
window.location.reload();
})
.catch(e => {
console.log(e);
......
<template>
<v-sheet>
<v-layout justify-center>
<v-overlay :value="loading">
<v-progress-circular indeterminate size="80"></v-progress-circular>
</v-overlay>
<v-flex xs12 sm8 md6>
<v-row justify="center" class="mx-0 mt-10">
<v-icon color="grey500">mdi-power-on</v-icon>
<v-row justify="center" class="mx-0 my-12">
<v-icon color="lightblue">mdi-power-on</v-icon>
<div
style="text-align: center; font-size: 22px; font-weight: 400; color: #343a40; "
>
Upload Video
</div>
<v-icon color="grey500">mdi-power-on</v-icon>
>Upload Video</div>
<v-icon color="lightblue">mdi-power-on</v-icon>
</v-row>
<v-card elevation="0">
<v-text-field
class="mx-10 mt-8 mb-6"
class="mx-10 mt-12 mb-6"
prepend-inner-icon="mdi-pen"
v-model="form.title"
:counter="40"
label="Title"
placeholder="Please input Title"
type="text"
>
</v-text-field>
></v-text-field>
<!-- file upload -->
<div class="mx-10">
<div class="mx-10 mb-6">
<video-upload />
</div>
<v-dialog max-width="400" v-model="successDialog">
<v-card max-width="400" class="pt-3">
<div
style="text-align: center; font-size: 20px;color: #5a5a5a; font-weight: 400"
>Notice</div>
<v-divider class="mt-2 mb-3"></v-divider>
<div
style="margin-left: 10px; margin-right: 10px; text-align: center; font-size: 18px; font-weight: 400"
>Your Video's tags are successfully extracted</div>
<v-btn class="mt-4" elevation="0" block color="primary">Close</v-btn>
</v-card>
</v-dialog>
<v-card outlined class="pa-2 mx-10" elevation="0" min-height="67">
<div
style="margin-left: 5px; margin-top: -18px; background-color: #fff; width: 95px; text-align: center;font-size: 14px; color: #5a5a5a; font-weight: 500"
>Selected Tags</div>
<v-chip-group column>
<v-chip
color="secondary"
v-for="(tag, index) in form.tags"
v-for="(tag, index) in form.tag"
:key="index"
@click="deleteTags(index)"
>
{{ tag }}
<v-icon small style="margin-left: 3px; margin-top: -2px">mdi-close-circle</v-icon>
</v-chip>
</v-chip-group>
</v-card>
<v-text-field
class="mx-10 mt-3 mb-5"
class="mx-10 my-7"
prepend-inner-icon="mdi-shape"
v-model="tag"
:counter="20"
......@@ -49,14 +65,11 @@
@click:append="addTags(tag)"
@keydown.enter="addTags(tag)"
type="text"
>
</v-text-field>
></v-text-field>
</v-card>
<v-row justify="center" style="margin-bottom: 30px">
<v-row justify="center" style="margin-top: 30px">
<v-btn elevation="0" large color="primary" @click="submit()">
<span style="font-size: 24px; font-weight: 300; letter-spacing: 2px"
>Upload</span
>
<span style="font-size: 24px; font-weight: 300; letter-spacing: 2px">Upload</span>
</v-btn>
</v-row>
</v-flex>
......@@ -77,7 +90,7 @@ export default {
form: {
title: "",
videoUrl: "",
tags: [
tag: [
"Work",
"Home Improvement",
"Vacation",
......@@ -90,20 +103,24 @@ export default {
]
},
successDialog: false,
errorDialog: false
errorDialog: false,
loading: false
};
},
mounted() {
this.form.tags = this.$store.getters.getTags;
created() {
this.form.tag = [];
},
methods: {
submit() {
if (this.form.tags.length || this.form.title) {
if (!(this.form.tag.length && this.form.title)) {
this.errorDialog = true;
return;
} else {
this.$axios
.post("/upload/post", this.form)
.then(r => {
window.location.reload();
console.log(r);
this.successDialog = true;
})
......@@ -114,25 +131,25 @@ export default {
}
},
deleteTags(index) {
for (let i = 0; i < this.form.tags.length; i++) {
const element = this.form.tags[i];
if (this.form.tags[index] === element) {
this.form.tags[i] = this.form.tags[this.form.tags.length - 1];
for (let i = 0; i < this.form.tag.length; i++) {
const element = this.form.tag[i];
if (this.form.tag[index] === element) {
this.form.tag[i] = this.form.tag[this.form.tag.length - 1];
break;
}
}
this.form.tags.pop();
this.form.tag.pop();
},
addTags(tag) {
let i;
let check = true;
for (i = 0; i < this.form.tags.length; i++) {
const element = this.form.tags[i];
for (i = 0; i < this.form.tag.length; i++) {
const element = this.form.tag[i];
if (tag === element) {
check = false;
}
}
if (tag && check) this.form.tags.push(tag);
if (tag && check) this.form.tag.push(tag);
this.tag = "";
}
}
......
module.exports = {
transpileDependencies: ["vuetify"]
transpileDependencies: ['vuetify'],
transpileDependencies: ['vuex-persist'],
};
......