윤준현

init project and add basic web

.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
## 이 프로젝트는 박광훈 교수님의 주관하시는 주제인 유튜브 동영상 분류를 위한 자동 태깅 방법에 대한 연구에 관한 서비스를 개발하는 것입니다.
### 프로젝트 참가 인원은 다음과 같습니다.
*윤영빈(컴퓨터공학과, 2015104192)
*윤준현(컴퓨터공학과, 2015104193)
*이현규(컴퓨터공학과, 2015104209)
*이태현(컴퓨터공학과, 2015104208)
### 진행할 연구는 다음과 같습니다
*Video Classification
*Auto Tagging
### 만들고자하는 서비스 : 영상 분류를 통하여 자동으로 사용자에게 태그 추천해주는 서비스 개발
\ No newline at end of file
var createError = require('http-errors');
var express = require('express');
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 app = express();
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());
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));
});
// 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 : {};
// 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')
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
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('backend: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);
}
module.exports =
{
db : 'mongodb://nu_manager:nu_manager@18.178.164.245:10002/nu_light_db',
sessionSecret: 'thisissessionSecret',
}
\ No newline at end of file
const mongoose = require('mongoose')
mongoose.set('useCreateIndex', true)
const Tag = new mongoose.Schema({
tag: [],
})
const tag = mongoose.model('tag', Tag)
module.exports = tag
\ No newline at end of file
const mongoose = require('mongoose')
mongoose.set('useCreateIndex', true)
const postSchema = new mongoose.Schema({
tag: [],
videoUrl: { type: String, default: '',},
title: { type: String, default: '' },
})
const Post = mongoose.model('post', postSchema)
module.exports = Post
\ No newline at end of file
{
"name": "backend",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"connect-history-api-fallback": "^1.6.0",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"debug": "~2.6.9",
"express": "~4.16.1",
"http-errors": "~1.6.3",
"moment": "^2.24.0",
"mongoose": "^5.9.6",
"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')
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 })
})
})
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 })
})
})
router.all('*', function (req, res, next) {
next(new Error ('Wrong Url!'));
});
module.exports = router;
\ No newline at end of file
var createError = require('http-errors');
var express = require('express');
var router = express.Router();
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
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')
// event post
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 })
});
})
router.all('*', function(req, res, next) {
next(createError(404, 'This page is not exisit'))
})
module.exports = router
This diff is collapsed. Click to expand it.
# frontend
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
```
yarn serve
```
### Compiles and minifies for production
```
yarn build
```
### Lints and fixes files
```
yarn lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"]
};
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@mdi/font": "^5.0.45",
"axios": "^0.19.2",
"core-js": "^3.6.4",
"filepond": "^4.13.0",
"filepond-plugin-file-validate-type": "^1.2.5",
"filepond-plugin-image-preview": "^4.6.1",
"moment": "^2.24.0",
"roboto-fontface": "*",
"vee-validate": "^3.2.5",
"vue": "^2.6.11",
"vue-filepond": "^6.0.2",
"vue-infinite-scroll": "^2.0.2",
"vue-router": "^3.1.5",
"vue-video-player": "^5.0.2",
"vuetify": "^2.2.11",
"vuex": "^3.1.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.2.0",
"@vue/cli-plugin-eslint": "~4.2.0",
"@vue/cli-plugin-router": "~4.2.0",
"@vue/cli-plugin-vuex": "~4.2.0",
"@vue/cli-service": "~4.2.0",
"@vue/eslint-config-prettier": "^6.0.0",
"babel-eslint": "^10.0.3",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-vue": "^6.1.2",
"node-sass": "^4.12.0",
"prettier": "^1.19.1",
"sass": "^1.19.0",
"sass-loader": "^8.0.2",
"vue-cli-plugin-vuetify": "~2.0.5",
"vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.3.0"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended",
"@vue/prettier"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions"
]
}
No preview for this file type
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<v-app>
<v-app-bar app color="#ffffff" elevation="1">
<v-tabs grow v-model="tab">
<v-tab @click="$router.push('/')">Home</v-tab>
<v-tab @click="$router.push('/upload')">Upload</v-tab>
</v-tabs>
</v-app-bar>
<v-content>
<router-view />
</v-content>
<v-footer>
<v-row justify="center" @click="exDialog = true">
<v-avatar size="25" tile style="border-radius: 4px">
<v-img src="./assets/logo.png"></v-img>
</v-avatar>
<div>
<span
style="margin-left: 2px; font-size: 15px; color: #5a5a5a; font-weight: 400"
>
Profit-Hunter
</span>
<div
style="margin-left: 4px; margin-top: -1px; font-size: 10px; color: #888; font-weight: 400"
>
Used OpenSource
</div>
</div>
</v-row>
</v-footer>
</v-app>
</template>
<script>
export default {
name: "App",
data: () => ({
tab: null,
search: "",
exDialog: false
}),
mounted() {
console.log(window.location.href.substring(22));
if (window.location.href.substring(22) === "") {
this.tab = 0;
} else if (window.location.href.substring(22) === "upload") {
this.tab = 1;
} else {
this.tab = null;
}
}
};
</script>
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.5 100"><defs><style>.cls-1{fill:#1697f6;}.cls-2{fill:#7bc6ff;}.cls-3{fill:#1867c0;}.cls-4{fill:#aeddff;}</style></defs><title>Artboard 46</title><polyline class="cls-1" points="43.75 0 23.31 0 43.75 48.32"/><polygon class="cls-2" points="43.75 62.5 43.75 100 0 14.58 22.92 14.58 43.75 62.5"/><polyline class="cls-3" points="43.75 0 64.19 0 43.75 48.32"/><polygon class="cls-4" points="64.58 14.58 87.5 14.58 43.75 100 43.75 62.5 64.58 14.58"/></svg>
<template>
<div>
<file-pond
name="bin"
ref="pond"
allow-multiple="false"
max-files="1"
:server="server"
v-bind:files="myFiles"
v-on:init="handleFilePondInit"
v-on:processfile="onload"
/>
</div>
</template>
<script>
// Import Vue FilePond
import vueFilePond from "vue-filepond";
// Import FilePond styles
import "filepond/dist/filepond.min.css";
// Import FilePond plugins
// Please note that you need to install these plugins separately
// Import image preview plugin styles
import "filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css";
// Import image preview and file type validation plugins
import FilePondPluginFileValidateType from "filepond-plugin-file-validate-type";
import FilePondPluginImagePreview from "filepond-plugin-image-preview";
// Create component
const FilePond = vueFilePond(
FilePondPluginFileValidateType,
FilePondPluginImagePreview
);
export default {
name: "app",
data() {
return {
myFiles: [],
server: {
url: `${this.$apiRootPath}upload/video`,
process: {}
}
};
},
methods: {
handleFilePondInit() {
console.log("FilePond has initialized");
// FilePond instance methods are available on `this.$refs.pond`
},
onload(e, r) {
console.log(r);
// this.$store.dispatch(r);
}
},
components: {
FilePond
}
};
</script>
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");
import Vue from "vue";
import Vuetify from "vuetify/lib";
import ko from "vuetify/es5/locale/ko";
Vue.use(Vuetify);
export default new Vuetify({
theme: {
options: {
customProperties: true
},
themes: {
light: {
primary: "#7DC1E8",
secondary: "#EBC478",
accent: "#82B1FF",
error: "#FF5252",
info: "#2196F3",
success: "#4CAF50",
warning: "#FFC107",
grey300: "#eceeef",
grey500: "#aaaaaa",
grey700: "#5a5a5a",
grey900: "#212529"
}
}
},
lang: {
locales: { ko },
current: "ko"
}
});
import Vue from "vue";
import VueRouter from "vue-router";
import axios from "axios";
Vue.prototype.$axios = axios;
const apiRootPath =
process.env.NODE_ENV !== "production"
? "http://localhost:3000/api/"
: "/api/";
Vue.prototype.$apiRootPath = apiRootPath;
axios.defaults.baseURL = apiRootPath;
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: () => import("../views/Home.vue")
},
{
path: "/upload",
name: "upload",
component: () => import("../views/Upload.vue")
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
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: {}
});
import { required, max, min } from "vee-validate/dist/rules";
import { extend } from "vee-validate";
extend("required", {
...required,
message: "This field is required"
});
extend("max", {
...max,
message: "This field must be {length} characters or less"
});
extend("min", {
...min,
message: "This field must have at least {length} characters"
});
<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-card class="mx-2 my-1">
<div>{{ post.title }}1</div>
</v-card>
</v-flex>
</v-row>
</v-layout>
</v-sheet>
</template>
<script>
// @ is an alias to /src
export default {
name: "Home",
components: {},
data() {
return {
postList: [],
search: "",
params: {
tag: ["", ""],
skip: 0
}
};
},
mounted() {
this.getPost();
},
methods: {
getPost() {
this.$axios
.get("/home/list", { params: this.params })
.then(r => {
this.postList = r.data.d;
console.log(this.postList);
})
.catch(e => {
console.log(e);
});
}
}
};
</script>
<template>
<v-sheet>
<v-layout justify-center>
<v-flex xs12 sm8 md6>
<v-row justify="center" class="mx-0 mt-10">
<v-icon color="grey500">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>
</v-row>
<v-card elevation="0">
<v-text-field
class="mx-10 mt-8 mb-6"
prepend-inner-icon="mdi-pen"
v-model="form.title"
:counter="40"
label="Title"
placeholder="Please input Title"
type="text"
>
</v-text-field>
<!-- file upload -->
<div class="mx-10">
<video-upload />
</div>
<v-card outlined class="pa-2 mx-10" elevation="0" min-height="67">
<v-chip-group column>
<v-chip
color="secondary"
v-for="(tag, index) in form.tags"
:key="index"
@click="deleteTags(index)"
>
{{ tag }}
</v-chip>
</v-chip-group>
</v-card>
<v-text-field
class="mx-10 mt-3 mb-5"
prepend-inner-icon="mdi-shape"
v-model="tag"
:counter="20"
label="Tag"
placeholder="Type to add Tag"
append-icon="mdi-arrow-up-bold"
@click:append="addTags(tag)"
@keydown.enter="addTags(tag)"
type="text"
>
</v-text-field>
</v-card>
<v-row justify="center" style="margin-bottom: 30px">
<v-btn elevation="0" large color="primary" @click="submit()">
<span style="font-size: 24px; font-weight: 300; letter-spacing: 2px"
>Upload</span
>
</v-btn>
</v-row>
</v-flex>
</v-layout>
</v-sheet>
</template>
<script>
import videoUpload from "../components/uploadFile";
export default {
name: "Upload",
components: {
videoUpload
},
data() {
return {
myFiles: [],
tag: "",
form: {
title: "",
videoUrl: "",
tags: [
"Work",
"Home Improvement",
"Vacation",
"Food",
"Drawers",
"Shopping",
"Art",
"Tech",
"Creative Writing"
]
},
successDialog: false,
errorDialog: false
};
},
mounted() {
this.form.tags = this.$store.getters.getTags;
},
methods: {
submit() {
if (this.form.tags.length || this.form.title) {
this.errorDialog = true;
} else {
this.$axios
.post("/upload/post", this.form)
.then(r => {
console.log(r);
this.successDialog = true;
})
.catch(e => {
console.log(e);
this.errorDialog = true;
});
}
},
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];
break;
}
}
this.form.tags.pop();
},
addTags(tag) {
let i;
let check = true;
for (i = 0; i < this.form.tags.length; i++) {
const element = this.form.tags[i];
if (tag === element) {
check = false;
}
}
if (tag && check) this.form.tags.push(tag);
this.tag = "";
}
}
};
</script>
module.exports = {
transpileDependencies: ["vuetify"]
};
This diff could not be displayed because it is too large.