Commit c37532c2 by 김현기

mac test ok

parent 4c1c4420
{
"editor.fontSize": 14,
"editor.accessibilityPageSize": 14
}
\ No newline at end of file
TEACHING_RESOLUTION=(3840x2160) TEACHING_RESOLUTION=(3840x2160)
TEACHING_IMAGE_PATH=/home/falinux/sds/backend/public/image/capture.jpg TEACHING_IMAGE_PATH=/home/falinux/sds/backend/public/image/capture.jpg
WPO=1003_AOI01 WPO=1003_AOI01
\ No newline at end of file PORT=3000
\ No newline at end of file
TEACHING_RESOLUTION=(3840x2160) TEACHING_RESOLUTION=(3840x2160)
TEACHING_IMAGE_PATH=/home/falinux/sds/backend/public/image/capture.jpg TEACHING_IMAGE_PATH=/home/falinux/sds/backend/public/image/capture.jpg
WPO=1003_AOI01 WPO=1003_AOI01
\ No newline at end of file PORT=3000
\ No newline at end of file
const express = require('express') const express = require("express")
const http = require('http') const history = require("connect-history-api-fallback")
const path = require('path') const path = require("path")
const fs = require('fs'); const apiRouter = require("./routes/index")
const dgram = require('dgram'); const bodyParser = require('body-parser');
const app = express();
const dotenv = require('dotenv'); const dotenv = require('dotenv');
const app = express()
const bodyParser = require('body-parser'); //
app.use(express.json({ limit : "50mb" })); dotenv.config();
app.use(express.urlencoded({ limit:"50mb", extended: false }));
dotenv.config({ const publicPath = path.resolve(__dirname, "public")
path: path.resolve(
process.cwd(),
process.env.NODE_ENV == "production" ? ".env" : ".env.dev"
)
});
const server = dgram.createSocket('udp4'); app.use(express.json({ limit : "50mb" }))
// socket 실행 app.use(express.urlencoded({ limit:"50mb", extended: false }))
server.bind(9400);
server.on('listening', function() { //post body 값을 가져오기 위함
console.log('Socket Port : 9400');
});
server.on('message', function(msg ) {
udpResultMsg = msg.toString();
console.log("케켘", udpResultMsg)
});
server.on('close', function() {
console.log('Server UDP Socket close');
});
const client = dgram.createSocket('udp4');
const clientPort= 9300;
// const clientPort= 4403;
// const clientHost = '192.168.52.122'; //inet
const clientHost ='192.168.52.38';
// Error [ERR_SOCKET_DGRAM_NOT_RUNNING]: Not running
client.on('close', function() {
console.log('Client UDP socket close')
});
// const jsonFile = fs.readFileSync('./json/projects.json', 'utf8');
// console.log(jsonFile);
// const jsonData = JSON.parse(jsonFile);
// console.table(jsonData);
//Post 방식은 Get 과 다르기 때문에 body-parser 를 설치해서 사용해야한다.
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false})) app.use(bodyParser.urlencoded({extended: false}))
//vue router 연동하기 위한 설정 app.use(express.static(publicPath))
app.use(require('connect-history-api-fallback')());
app.use(express.static(path.join(__dirname, 'public'))); app.use("/api", apiRouter); // '/api' 로 시작하는 URL은 라우터로 전송
app.set('port',process.env.PORT || 3001); app.use(history) //REST API 서버로서 사용한다면 라우터 뒤에 실행하게 한다. 그렇치 않으면 요청이 들어오지 않는다.
/* udp 통신으로 매니저에게 받는 결과값*/ app.listen(process.env.PORT, () => {
let udpResultMsg = '' console.log(`Neuromorphic web server start ${process.env.PORT}`)
/* udp 통신 기다리는 시간*/
let udpAwaitTime = 0
let newProjectNum = 0
app.get('/api/getWpoId',(req,res) => {
let id = process.env.WPO
res.send(id)
}) })
app.post('/api/projectInfo',async (req,res) => {
const dataBuffer = fs.readFileSync('./json/project.json')
const project = JSON.parse(dataBuffer.toString())
console.log('로컬 프로젝트 :' , project)
// 받아온 값이 있을경우
if(Object.keys(req.body).length !== 0 ){
project.admin = req.body.admin
project.aoiUid = req.body.aoiUid
project.counter = req.body.counter
project.createDate = req.body.createDate
project.name = req.body.name
project.state = req.body.state
project.successDate = req.body.successDate
project.uid = req.body.uid
project.user = req.body.user
project.infos = req.body.infos
project.updateDate = new Date()
fs.writeFileSync('./json/project.json',JSON.stringify(project) , (err) =>{
if ( err ) return err;
})
}
res.status(200).json(project)
})
const wrapper = asyncFn => { return (async (req, res, next) => { try { return await asyncFn(req, res, next); } catch (error) { return next(error); } }); };
//https://kjwsx23.tistory.com/199 express 와 async ,await 이슈
//express async await wrapper 함수를 써서 감싸거나 라이브러리를 써야 한다.
app.get('/api/requestManager',wrapper(async (req,res)=>{
req.query.image_path = process.env.TEACHING_IMAGE_PATH
if(req.query.cmd === "neuro_check"){
req.query.teaching = `${process.env.TEACHING_IMAGE_PATH}-${req.query.project_num}-2-${process.env.TEACHING_RESOLUTION}${req.query.teaching_info}`
}
console.log("param :",JSON.stringify(req.query) )
sendToManager (JSON.stringify(req.query))
let requestMsg = ''
switch(req.query.cmd){
case "neuro_start":
requestMsg = 'neuro_start_done'
break
case "neuro_ready":
requestMsg = 'neuro_ready_done'
break
case "neuro_capture":
requestMsg = 'capture_done'
break
case "neuro_check" :
requestMsg = 'neuro_result'
break
// case "neuro_replay" :
// requestMsg = 'neuro_result'
// break
default:
res.status(404)
}
await responseManager(requestMsg)
.then(data => {
res.status(200).json(data)
})
.catch(error =>{
res.status(404).send(error);
})
}))
//UDP 메세지 보냄 통신
function sendToManager(msg){
client.send(msg, 0, msg.length, clientPort, clientHost, function(err) {
if ( err ) return ;
console.log("UDP send Msg ")
});
}
// await Promise 응답해야됨
function responseManager (requestMsg) {
return new Promise((resolve, reject) => {
let delay = 100; //ms 단위로 체크
let waitingTime = 0 //대기 시간
let timer = setInterval(() => {
if(requestMsg === JSON.parse(udpResultMsg).cmd ){
if(requestMsg === 'capture_done'){
let base64 = fs.readFileSync('./public/image/capture.jpg' , 'base64')
let msg = JSON.parse(udpResultMsg)
msg.imageBase64 = base64
udpResultMsg = JSON.stringify(msg)
// console.log("야이 씨벌 :", JSON.parse(udpResultMsg))
// console.log("base64 :",base64)
}
resolve(udpResultMsg)
clearInterval(timer)
}else if(waitingTime === 500000){
reject('No response from Manager')
clearInterval(timer)
}else{
waitingTime = waitingTime + delay
}
},delay)
});
}
http.createServer(app).listen(app.get('port'),function(){
console.log('WebServer Port: ' +app.get('port'))
})
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"start": "node app.js" "start": "nodemon app.js"
}, },
"author": "", "author": "",
"license": "ISC", "license": "ISC",
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"connect-history-api-fallback": "^1.6.0", "connect-history-api-fallback": "^1.6.0",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"express": "^4.17.1" "express": "^4.17.1",
"nodemon": "^2.0.12"
} }
} }
const express = require("express")
const mangerRoutes = require('./manager')
const projectRoutes = require('./project')
const wpoRoutes = require('./wpo')
const router = express.Router()
router.use('/manager', mangerRoutes)
router.use('/project', projectRoutes)
router.use('/wpo', wpoRoutes)
module.exports = router;
\ No newline at end of file
const express = require('express')
const fs = require('fs');
const router = express.Router()
const dgram = require('dgram');
let udpResultMsg = ''
// socket 실행
const server = dgram.createSocket('udp4');
server.bind(9400);
server.on('listening',() => {
console.log('Socket Port : 9400');
});
server.on('message', (msg) => {
udpResultMsg = msg.toString();
console.log('받은 메시지 :',udpResultMsg)
});
server.on('close',() => {
console.log('Server UDP Socket close');
});
const manager = dgram.createSocket('udp4');
const managerPort= 9300;
const managerHost ='127.0.0.1';
const requestToManager = ((msg) => {
manager.send(msg, 0, msg.length, managerPort, managerHost, (err) => {
if ( err ) return ;
console.log("UDP send Msg : ",msg)
});
})
router.get('/', async (req,res)=>{
req.query.image_path = process.env.TEACHING_IMAGE_PATH
if(req.query.cmd === "neuro_check"){
req.query.teaching = `${process.env.TEACHING_IMAGE_PATH}-${req.query.project_num}-2-${process.env.TEACHING_RESOLUTION}${req.query.teaching_info}`
}
requestToManager(JSON.stringify(req.query))
let requestMsg = ''
switch(req.query.cmd){
case "neuro_start":
requestMsg = 'neuro_start_done'
break
case "neuro_ready":
requestMsg = 'neuro_ready_done'
break
case "neuro_capture":
requestMsg = 'capture_done'
break
case "neuro_check" :
requestMsg = 'neuro_result'
break
case "neuro_replay" :
requestMsg = 'btnpush'
break
case "network_check":
requestMsg = 'network_status'
break
case "neuro_complete":
requestMsg = 'complete_done'
break
default:
res.status(404)
}
await managerResponse(requestMsg)
.then(data => {
res.status(200).json(data)
})
.catch(error =>{
res.status(404).send(error);
})
})
const managerResponse = ((requestMsg) => {
return new Promise((resolve, reject) => {
let delay = 100; //ms 단위로 체크
let waitingTime = 0 //대기 시간
let timer = setInterval(() => {
if(udpResultMsg.length > 0 && requestMsg === JSON.parse(udpResultMsg).cmd){
if(requestMsg === 'capture_done'){
let base64 = fs.readFileSync('./public/image/capture.jpg' , 'base64')
let msg = JSON.parse(udpResultMsg)
msg.imageBase64 = base64
udpResultMsg = JSON.stringify(msg)
}
resolve(udpResultMsg)
clearInterval(timer)
}else if(waitingTime === 3_000_000){
reject('No response from Manager')
clearInterval(timer)
}else{
waitingTime = waitingTime + delay
}
},delay)
});
})
manager.on('close',() => {
console.log('Client UDP socket close')
});
module.exports = router
\ No newline at end of file
const express = require('express')
const fs = require('fs');
const router = express.Router()
router.get('/',async (req,res) => {
const project = JSON.parse( fs.readFileSync('./json/project.json').toString() )
const learning = JSON.parse( fs.readFileSync('./json/learning.json').toString() )
let result = {
'project':project,
'learning':learning
}
res.send(result)
})
router.post('/',async (req,res) => {
const project = JSON.parse( fs.readFileSync('./json/project.json').toString() )
const learning = JSON.parse( fs.readFileSync('./json/learning.json').toString() )
// 받아온 값이 있을경우
if(Object.keys(req.body).length !== 0 ){
project.admin = req.body.project.admin
project.aoiUid = req.body.project.aoiUid
project.counter = req.body.project.counter
project.createDate = req.body.project.createDate
project.name = req.body.project.name
project.state = req.body.project.state
project.successDate = req.body.project.successDate
project.uid = req.body.project.uid
project.user = req.body.project.user
project.updateDate = new Date()
project.total = req.body.project.total
project.success = req.body.project.success
project.fail = req.body.project.fail
project.result = req.body.project.result
learning.learning = req.body.learning
fs.writeFileSync('./json/project.json',JSON.stringify(project) , (err) =>{
if ( err ) return err;
})
fs.writeFileSync('./json/learning.json',JSON.stringify(learning) , (err) =>{
if ( err ) return err;
})
}else{
fs.writeFileSync('./json/project.json',JSON.stringify({}) , (err) =>{
if ( err ) return err;
})
fs.writeFileSync('./json/learning.json',JSON.stringify({}) , (err) =>{
if ( err ) return err;
})
}
let result = {
'project':project,
'learning':learning.learning
}
res.status(200).send(result)
})
module.exports = router
\ No newline at end of file
const express = require('express')
const router = express.Router()
router.get('/',async ( req , res) => {
let id = await process.env.WPO
res.send(id)
})
module.exports = router
\ No newline at end of file
.DS_Store
node_modules
/dist
/tests/e2e/reports/
selenium-debug.log
chromedriver.log
geckodriver.log
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# front-end
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Run your unit tests
```
npm run test:unit
```
### Run your end-to-end tests
```
npm run test:e2e
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e",
"lint": "vue-cli-service lint",
"start": "npm run serve",
"build2": "npm run build",
"crossbuild": "cross-env vue-cli-service build",
"crossbuild2": "cross-env npm run build"
},
"dependencies": {
"apollo-boost": "^0.4.9",
"chart.js": "^2.9.4",
"core-js": "^3.6.5",
"graphql": "^15.5.1",
"konva": "^7.1.3",
"register-service-worker": "^1.7.1",
"vue": "^2.6.11",
"vue-apollo": "^3.0.7",
"vue-chartjs": "^3.5.1",
"vue-konva": "^2.1.6",
"vue-router": "^3.2.0",
"vuetify": "^2.2.11",
"vuex": "^3.4.0",
"vuex-persistedstate": "^4.1.0"
},
"devDependencies": {
"@mdi/js": "^5.5.55",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-e2e-nightwatch": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-pwa": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-unit-jest": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/test-utils": "^1.0.3",
"graphql-tag": "^2.9.0",
"babel-eslint": "^10.1.0",
"chromedriver": "85",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"vue-cli-plugin-apollo": "^0.20.0",
"vue-cli-plugin-vuetify": "~2.0.7",
"vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.3.0"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {},
"overrides": [
{
"files": [
"**/__tests__/*.{j,t}s?(x)",
"**/tests/unit/**/*.spec.{j,t}s?(x)"
],
"env": {
"jest": true
}
}
]
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
],
"jest": {
"preset": "@vue/cli-plugin-unit-jest"
}
}
<template>
<v-app>
<v-main>
<Alert
:open="alertOpen"
:message="message"
:type="type"
/>
<Loading
:open="loadingModal"
:message="message"
/>
<Bluetooth
:open="bluetoothModal"
/>
<router-view/>
</v-main>
</v-app>
</template>
<script>
import { EventBus } from '@/event-bus'
import Alert from './components/Alert.vue'
import Loading from './components/Loading.vue'
import Bluetooth from './components/Bluetooth.vue'
export default {
name: 'App',
components: {
Alert,
Loading,
Bluetooth,
},
created() {
this.$store.dispatch('getSerial')
EventBus.$on('openAlert',( massage , type) => {
this.alertOpen = true,
this.message = massage,
this.type = type
}),
EventBus.$on('closeAlert',() => { this.alertOpen = false })
EventBus.$on('openLoading',( massage ) => {
this.loadingModal = true
this.message = massage
}),
EventBus.$on('closeLoading',() => { this.loadingModal = false })
EventBus.$on('openBluetooth',() => { this.bluetoothModal = true }),
EventBus.$on('closeBluetooth',() => { this.bluetoothModal = false })
},
data: () => ({
bluetoothModal:false,
loadingModal:false,
alertOpen: false ,
message:'',
type:'',
}),
beforeDestroy(){
EventBus.$off('openAlert');
EventBus.$off('closeAlert');
EventBus.$off('openLoading');
EventBus.$off('closeLoading');
}
};
</script>
<style lang="scss">
html,body{
padding: 0;
margin: 0;
height: 100%;
width: 100%
}
#app {
background-color:#CFD8DC;
height: 100%;
width: 100%;
}
html {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
html::-webkit-scrollbar {
display: none; /* Chrome, Safari, Opera*/
}
</style>
<template>
<v-overlay
:value="openAlert"
:z-index="20"
>
<v-alert
:type="type"
dismissible
@click="closeAlert()"
>
{{ message }}
</v-alert>
</v-overlay>
</template>
<script>
import { EventBus } from '../event-bus'
export default {
props: {
open:Boolean,
message:String,
type:String,
},
watch: {
open(newVal) {
if (newVal) {
setTimeout(() => {
this.closeAlert()
}, 2000);
}
},
},
computed: {
openAlert: {
get() {
return this.open;
},
set() {
this.closeAlert()
},
},
},
methods:{
closeAlert(){
EventBus.$emit("closeAlert");
}
}
};
</script>
\ No newline at end of file
<template>
<v-overlay v-if="open" :z-index="10">
<v-card max-width="1500" min-width="1500" color="blue-grey lighten-5" light >
<v-toolbar
color="indigo "
class="elevation-0"
>
<v-toolbar-title class="white--text">블루투스 연결 (네트워크 연결)</v-toolbar-title>
</v-toolbar>
<v-row class='px-4'>
<v-col cols="6">
<v-subheader>안드로이드</v-subheader>
<v-card>
<v-row no-gutters>
<v-col cols="6">
<v-img
src="@/../public/image/android.jpg"
height="525"
contain
></v-img>
</v-col>
<v-col cols="6" class="d-flex justify-center align-center flex-column ">
<p class="text-h5">안드로이드 연결</p>
<p>1. 블루투스를 컨다</p>
<p>2. 블루투스 목록중 <strong>'falinux'</strong> 찾는다</p>
<p>3. <strong>'falinux'</strong> 선택</p>
<p>4. 모바일에서 핫스팟을 컨다</p>
</v-col>
</v-row>
</v-card>
</v-col>
<v-col cols="6">
<v-subheader>아이폰</v-subheader>
<v-card color="">
<v-row no-gutters>
<v-col cols="6">
<v-img
src="@/../public/image/ipone.jpg"
height="525"
contain
></v-img>
</v-col>
<v-col cols="6" class="d-flex justify-center align-center flex-column ">
<p class="text-h5">아이폰 연결</p>
<p>1. 블루투스를 컨다</p>
<p>2. 블루투스 목록중 <strong>'falinux'</strong> 찾는다</p>
<p>3. <strong>'falinux'</strong> 선택</p>
<p>4. 모바일에서 핫스팟을 컨다</p>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
</v-card>
</v-overlay>
</template>
<script>
export default {
props:{
open:Boolean,
},
}
</script>
<style lang="scss">
</style>
<script>
// import VueCharts from 'vue-chartjs'
import { Doughnut,mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
//https://www.chartjs.org/docs/latest/charts/line.html 옵션
//https://www.chartjs.org/samples/latest/
export default {
extends: Doughnut, //차트 종류 ex)bar
mixins: [ reactiveProp] ,
props:{
chartdata:Object,
percent: Number,
},
data () {
return {
options: {
title: {
display: false,
// text: 'title'
},
legend: {
position: 'bottom',
display: true,
},
responsive: true,
maintainAspectRatio: false
},
}
},
mounted () {
this.addPlugin({
id: 'my-plugin',
beforeDraw: this.centerText
})
this.renderChart(this.chartData, this.options )
},
methods: {
//가운데 퍼센트 표시하기 위함
centerText(chart){
let width = chart.chart.width;
let height = chart.chart.height;
let ctx = chart.chart.ctx;
ctx.restore();
let fontSize = (height / 150).toFixed(2);
ctx.font = fontSize + "em sans-serif" ;
ctx.textBaseline = "middle";
let text = this.percent+'%';
let textX = Math.round((width - ctx.measureText(text).width) / 2);
let textY = height / 2.2;
ctx.fillText(text, textX, textY);
ctx.save();
}
}
}
</script>
\ No newline at end of file
<template>
<v-overlay
class="loading-overlay"
:z-index="20"
:value="open">
<v-progress-circular
indeterminate
:size="150"
:width="7"
class="title"
>{{message}}...</v-progress-circular>
</v-overlay>
</template>
<script>
export default {
props: {
open:Boolean,
message:String,
},
}
</script>
import Vue from 'vue'
export const EventBus = new Vue()
import gql from 'graphql-tag' // eslint-disable-line no-unused-vars
import apolloProvider from '../plugins/apollo'
// import store from '@/store'
export default {
async get(serial){
try{
const response = await apolloProvider.defaultClient.query({
query: gql`
query aoiSerial($serial:String!){
aoiSerial(serial:$serial){
uid
name
state
serial
projectUid
}
}
`,
fetchPolicy: 'no-cache',
variables: { serial: serial }
})
let aoi = response.data.aoiSerial
if (!aoi) return ''
if (aoi.errors) throw new Error(aoi.errors[0])
return aoi
}catch (e) {
console.log(e)
throw e
}
},
async update(input){
try{
const response = await apolloProvider.defaultClient.mutate({
mutation: gql`
mutation updateAoi( $name: String! ,$state: Boolean! , $serial:String! ,$updateDate:String! ,$uid:Int! , $projectUid:Int ){
updateAoi(input:{
name:$name
state:$state
serial:$serial
updateDate:$updateDate
projectUid:$projectUid
uid:$uid
})
{
aoi{
uid
name
state
serial
updateDate
projectUid
}
}
}
`,
variables: {
uid:input.uid,
name:input.name,
state:input.state,
serial:input.serial,
updateDate:new Date(),
projectUid:0
}
})
let aoi = response.data.updateAoi.aoi
if (!aoi) return ''
if (aoi.errors){
throw new Error(aoi.errors[0])
}
return aoi
}catch (e) {
console.log(e)
throw e
}
},
}
\ No newline at end of file
import gql from 'graphql-tag' // eslint-disable-line no-unused-vars
import apolloProvider from '../plugins/apollo'
export default {
async get(projectUid){
try{
const response = await apolloProvider.defaultClient.query({
query: gql`
query learning($projectUid: Int!) {
learning(projectUid: $projectUid) {
projectUid
order
type
startX
startY
lastX
lastY
width
height
goodImage
missingImage
goodPath
missingPath
}
}`,
fetchPolicy: 'no-cache',
variables: { projectUid: projectUid }
})
let learning = response.data.learning
if (!learning) return ''
if (learning.errors) throw new Error(learning.errors[0])
return learning
}catch (e) {
console.log(e)
throw e
}
},
}
\ No newline at end of file
import gql from 'graphql-tag' // eslint-disable-line no-unused-vars
import apolloProvider from '../plugins/apollo'
// import store from '@/store'
export default {
async get(uid){
try{
const response = await apolloProvider.defaultClient.query({
query: gql`
query nProject($aoiUid:Int!) {
nProject(aoiUid:$aoiUid) {
name
admin
user
createDate
successDate
counter
aoiUid
uid
state
updateDate
}
}`,
fetchPolicy: 'no-cache',
variables: { aoiUid: uid }
})
let project = response.data.nProject
if (!project) return ''
if (project.errors) throw new Error(project.errors[0])
return project
}catch (e) {
return false
}
},
async update(input){
try{
const response = await apolloProvider.defaultClient.mutate({
mutation: gql`
mutation updateNproject(
$name: String! ,
$admin: String! ,
$user: String! ,
$createDate: String! ,
$successDate: String! ,
$counter:Int ,
$aoiUid:Int! ,
$uid:Int!,
$state:Boolean!,
$updateDate:String,
$success:Int,
$fail:Int,
$total:Int,
$result:Boolean
){
updateNproject(input:{
name:$name
admin:$admin
user:$user
createDate:$createDate
successDate:$successDate
counter:$counter
aoiUid:$aoiUid
uid:$uid
state:$state
updateDate:$updateDate,
success:$success,
fail:$fail,
total:$total,
result:$result
})
{
nProject{
name
admin
user
createDate
successDate
counter
aoiUid
uid
state
updateDate
success
fail
total
result
}
}
}
`,
variables: {
name: input.name,
admin: input.admin,
user: input.user,
createDate: input.createDate,
successDate: input.successDate,
counter: input.counter,
aoiUid: 0,
uid: input.uid,
state: input.state,
updateDate: new Date(),
success:input.success,
fail:input.fail,
total:input.total,
result:input.result,
}
})
let project = response.data.updateNproject.nProject
if (!project) return ''
if (project.errors){
throw new Error(project.errors[0])
}
return true
}catch (e) {
console.log(e)
throw e
}
},
}
\ No newline at end of file
import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import router from './router'
import store from './store'
import vuetify from './plugins/vuetify';
import axios from 'axios'
import VueKonva from 'vue-konva'
import apolloProvider from './plugins/apollo'
Vue.use(VueKonva)
axios.defaults.baseURL = '/api' //모든 요청에 '/api' 붙도록 기본 설정
axios.defaults.headers.common.Accept = 'application/json'//JSON 형식으로만 받는다
axios.interceptors.response.use( //Error 전파하기 위해 인터셉터 응답을 추가한다.
response => response,
(error) => {
return Promise.reject(error)
}
)
//Vue.prototype.$http = axios //vue 컴포넌트에서 this.$http 요청할 수 있게 된다.
Vue.config.productionTip = false
new Vue({
router,
store,
vuetify,
apolloProvider,
render: h => h(App)
}).$mount('#app')
import Vue from 'vue'
import { ApolloClient } from 'apollo-client'
import { createHttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import VueApollo from 'vue-apollo'
//멑티 클라이언트 구성
//https://apollo.vuejs.org/guide/multiple-clients.html
Vue.use(VueApollo)
const httpLink = createHttpLink({
uri: 'https://www.nemopai.com/graphql',
})
const link = httpLink
const apolloClient = new ApolloClient({
// Tells Apollo to use the link chain with the http link we set up.
link,
// Handles caching of results and mutations.
cache: new InMemoryCache({ freezeResults: false }),
// Useful if you have the Apollo DevTools installed in your browser.
connectToDevTools: true
});
const apolloProvider = new VueApollo({
defaultClient: apolloClient
});
export default apolloProvider;
import Vue from 'vue';
import Vuetify from 'vuetify/lib';
Vue.use(Vuetify);
export default new Vuetify({
icons: {
iconfont: 'mdiSvg',
},
});
/* eslint-disable no-console */
import { register } from 'register-service-worker'
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
ready () {
console.log(
'App is being served from cache by a service worker.\n' +
'For more details, visit https://goo.gl/AFskqB'
)
},
registered () {
console.log('Service worker has been registered.')
},
cached () {
console.log('Content has been cached for offline use.')
},
updatefound () {
console.log('New content is downloading.')
},
updated () {
console.log('New content is available; please refresh.')
},
offline () {
console.log('No internet connection found. App is running in offline mode.')
},
error (error) {
console.error('Error during service worker registration:', error)
}
})
}
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: Home
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
import axios from 'axios'
export default {
async projectCreateNum() {
try{
const result = await axios.get('/projectCreateNum')
return result.data
} catch (error) {
return error.message
}
},
async projectCreate(data) {
try{
const result = await axios.post('/projectCreate',data)
return result
} catch (error) {
return error.message
}
},
async projectCapture (data) {
try{
const result = await axios.get('/requestManager',{ params: data })
return result
} catch (error) {
return error.message
}
},
// axios.get('/neuroCapture',{ params: param })
projectUpdate (data) {
return new Promise((resolve,reject) =>{
// axios.post('/projectModify',{ params: data })
axios.post('/projectUpdate',data)
.then(({data}) => {
resolve(data)})
.catch((error) => {
reject(new Error(`${error} 요청 실패입니다.`));
})
})
},
projectRemove (data) {
return new Promise((resolve,reject) =>{
// axios.post('/projectModify',{ params: data })
axios.post('/projectUpdate',data)
.then(({data}) => {
resolve(data)})
.catch((error) => {
reject(new Error(`${error} 요청 실패입니다.`));
})
})
}
}
\ No newline at end of file
import axios from 'axios'
/* {data} 받으면 data.data. => data. 접근 가능 */
export default{
async request(param) {
try{
let response = await axios.get('/manager',{ params: param })
return response
}catch(e){
console.error(e.message)
}
},
}
\ No newline at end of file
export default{
neuroStart (param){
return new Promise((resolve,reject) => {
JSON.parse(param).cmd === "neuro_start" ? resolve(param) : reject(new Error("요청 값이 틀립니다."))
})
},
neuroCapture (param){
return new Promise((resolve,reject) => {
JSON.parse(testJson).cmd === "capture_done" ? resolve(testJson) : reject(new Error("요청 값이 틀립니다."))
})
},
neuroCheck (param){
return new Promise((resolve,reject) => {
JSON.parse(param).cmd === "neuro_check" ? resolve("검수 성공 ") : reject(new Error("요청 값이 틀립니다."))
})
},
neuroSave (param){
return new Promise((resolve,reject) => {
JSON.parse(testJson).cmd === "capture_done" ? resolve(testJson) : reject(new Error("요청 값이 틀립니다."))
})
},
}
\ No newline at end of file
import axios from 'axios'
export default {
async get() {
try{
const response = await axios.get('/project')
return response.data
}catch (e) {
console.log(e)
throw e
}
},
async save(data) {
try{
let response = await axios.post('/project', data )
return response.data
}catch(e){
console.error(e.message)
}
}
}
\ No newline at end of file
import axios from 'axios'
export default {
async getWpoId () {
try{
let response = await axios.get('/wpo')
return response.data
}catch(e){
console.error(e.message)
}
},
}
\ No newline at end of file
import Vue from 'vue'
import Vuex from 'vuex'
// import projectStore from './modules/projectStore.js'
import aoiStore from './modules/aoiStore'
import projectStore from './modules/projectStore'
import createPersistedState from 'vuex-persistedstate';
Vue.use(Vuex)
export default new Vuex.Store({
modules:{
project:projectStore,
aoi:aoiStore
},
plugins:[
createPersistedState({
paths:['aoi' , 'project']
}),
]
})
import aoiGql from '@/gql/aoi'
import wpoService from '@/service/wpo'
const state = {
aoi: {},
serial: '',
}
const getters = {
}
const actions = {
async getSerial({commit}){
let serial = await wpoService.getWpoId() //웹서버에 지정한 WPO ID 가져오기
commit('GETSERIAL' , serial)
},
async getAoi({commit}, serial){
let aoi = await aoiGql.get(serial)
commit('GETAOI' , aoi)
},
async updateAoi({commit} , input){
let result = await aoiGql.update(input)
commit('UPDATEAOI' , result)
},
}
const mutations = {
GETSERIAL(state,payload ){
state.serial = payload
},
GETAOI(state,payload ){
state.aoi = payload
},
UPDATEAOI(state,payload){
state.aoi = { ...payload};
},
}
export default {
state: {
...state
},
getters,
mutations,
actions
}
\ No newline at end of file
import projectGql from '@/gql/project'
const state = {
project: [],
}
const getters = {
}
const actions = {
async setProject({commit}, project){
commit('SETPROJECT' , project)
},
async updateAoi({commit} , input){
let result = await projectGql.update(input)
commit('UPDATEAOI' , result)
},
}
const mutations = {
SETPROJECT(state,payload ){
state.project = payload
},
UPDATEAOI(state,payload){
state.aoi = { ...payload};
},
}
export default {
state: {
...state
},
getters,
mutations,
actions
}
\ No newline at end of file
<template>
<v-container class="home d-flex align-center justify-center" >
<v-row>
<Setting
v-if="stepper === 0"
:message="message"
/>
<Aoi
v-else-if="stepper === 1"
/>
<Teaching
v-else-if="stepper === 2"
:project="project"
:learnings="learnings"
/>
<Project
v-else-if="stepper === 3"
:project="project"
:learnings="learnings"
/>
</v-row>
</v-container>
</template>
<script>
// import wpoService from '../service/wpo'
import projectService from '../service/project'
// import learningService from '../service/learning'
// import teachingService from '@/service/teaching'
import projectGql from '@/gql/project'
import learningGql from '@/gql/learning'
import { EventBus } from '@/event-bus'
import Setting from './step/Setting.vue'
import Aoi from './step/Aoi.vue'
import Teaching from './step/Teaching.vue'
import Project from './step/Project.vue'
export default {
data () {
return {
stepper: 0,
message:'Setting ...',
projectUid: 0 ,
project:{},
learnings:[],
}
},
components:{
Setting,
Aoi,
Teaching,
Project
},
created(){
this.getProject()
EventBus.$on('setTeaching',( number , aoiUid ) => { this.setTeaching(number , aoiUid) })
EventBus.$on('setProject', ( number , project ) => { this.setProject(number , project) })
EventBus.$on('setInit', () => { this.getProject() ,this.stepper === 1 })
},
mounted(){
//
},
methods: {
async getProject(){
let local = await projectService.get()
console.log('local :',local)
if(Object.keys(local.learning).length === 0 || Object.keys(local.project).length === 0){
this.stepper = 1
}else if(local.project.result){
this.stepper = 3
this.project = local.project
this.learnings = local.learning.learning
this.$store.dispatch('setProject' ,this.project )
}else if(!local.project.result){
this.project = local.project
this.learnings = local.learning.learning
this.stepper = 2
this.$store.dispatch('setProject' ,this.project )
}
},
async setTeaching(aoiUid){
this.stepper = 0
this.message ="프로젝트 세팅..."
let gqlProject = await projectGql.get(aoiUid)
this.$store.dispatch('setProject',gqlProject)
this.message ="학습 세팅..."
let gqlLearning = await learningGql.get(gqlProject.uid)
this.message ="프로젝트 저장..."
let saveData = {
'project':gqlProject,
'learning': gqlLearning
}
if(Object.keys(gqlProject).length !== 0 && gqlLearning.length !== 0){
let response = await projectService.save(saveData)
this.project = response.project
this.learnings = response.learning
if(Object.keys(this.project).length !== 0 && this.learnings.length !== 0) this.stepper = 2
}
},
async setProject( project){
this.stepper = 3
this.project = project
}
},
beforeDestroy(){
EventBus.$off('setTeaching');
EventBus.$off('setProject');
EventBus.$off('setInit');
},
}
</script>
<style lang="scss">
.home{
height: 100vh;
}
</style>
\ No newline at end of file
<template>
<v-card
width="1280"
max-width="1280"
height="846"
max-height="846"
dark
class="elevation-0 mx-auto"
>
<v-card
v-if="captureImage === null"
height="720"
max-height="720"
width="100%"
max-width="100%"
class="elevation-0 d-flex justify-center align-center flex-column"
>
<v-row
class="fill-height"
align-content="center"
justify="center"
>
<v-col
class="text-h3 text-center"
cols="12"
>
<span><strong class="white--text success">보드</strong>를 삽입해주세요</span>
</v-col>
<v-col cols="12">
<v-progress-linear
color="blue-grey"
indeterminate
rounded
height="6"
></v-progress-linear>
</v-col>
</v-row>
</v-card>
<v-stage
v-else
class="ma-0 pa-0 "
ref="stage"
:config="stageSize"
>
<v-layer ref="layer"
:config="stageSize"
>
<v-image
:config="{
image: image,
width: 1280,
height: 720,
}"/>
<v-rect
v-for="(rec, index) in rect"
:key="index"
:config="{
x: Math.min(rec.startX , rec.lastX ),
y: Math.min(rec.startY , rec.lastY),
width: Math.abs(rec.width ),
height: Math.abs(rec.height ),
fill: rec.stroke+'4D',
stroke: rec.stroke,
dash:[8,8],
strokeWidth: 3,
}"
>
</v-rect>
</v-layer>
</v-stage>
<v-card-text>
<v-progress-linear
class="mt-10"
v-if="captureImage !== null"
color="green darken-2"
v-model="progressbar"
height="40"
dark
reactive
@click.prevent.self
>
<strong>{{ progressbar }} %</strong>
</v-progress-linear>
</v-card-text>
</v-card>
</template>
<script>
export default {
data () {
return {
loading: true,
progressbar: 0,
image: null,
rect:[],
check:[],
stageSize: {
width: 1280,
height: 720,
},
drwingColor: '#2196F3', // 선 색
thickness: 3, //선 굵기
}
},
props: {
step:Number,
learnings:Array,
project:Object,
counter:Number,
result:Array,
captureImage:String
},
watch: {
counter(current){
this.progressbar = Math.round((100 * current) / this.project.counter);
},
result(current){
if(current.length !== 0){
this.rect =[]
this.rect = [...this.learnings]
for(let i = 0; i < current.length; i++ ){
Number(current[i]) === 0 ? (this.rect[i].fill = '#0D47A1' , this.rect[i].stroke = '#0D47A1' ) : (this.rect[i].fill = '#B71C1C' , this.rect[i].stroke = '#B71C1C' )
}
}
},
step(current){
if(current === 6){
this.rect =[]
}
},
captureImage(current){
let image = new Image();
image.src = 'data:image/jpeg;base64,'+current
image.onload = () => { this.image = image};
}
}
}
</script>
<style>
</style>
\ No newline at end of file
<template>
<v-card
dense
height="400"
class="elevation-0"
>
<v-toolbar
class="elevation-0 "
dense
>
<v-toolbar-title>통계</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<div v-if="result.length !== 0" class=" pa-0 ma-0">
<DoughnutChart
class="mt-3 pa-0 ma-0"
:chart-data="totalColl"
:height="220"
:percent="percent"
/>
</div>
</v-card>
</template>
<script>
import DoughnutChart from '../../components/DoughnutChart.vue'
export default {
data () {
return {
total:0,
totalColl:{},
success:0,
fail:0,
percent:0
}
},
props: {
step:Number,
wpo:String,
infos:Array,
project:Object,
result:Array,
counter:Number
},
mounted(){
this.totalColl = {
labels: ['성공','실패'],
datasets: [
{
backgroundColor: ['#4CAF50' ,'#F44336'],
data: [ this.success ,this.fail],
}
],
}
},
components: {
DoughnutChart,
},
watch:{
result(current){
if(current.length !== 0){
this.total = this.total + current[current.length-1]['time']
current[current.length-1]['result'] === 0 ? ++ this.fail : ++this.success
this.percent = Math.round((100 * this.success ) / this.counter)
this.totalColl = {
labels: ['성공','실패'],
datasets: [
{
backgroundColor: ['#4CAF50' ,'#F44336'],
data: [ this.success ,this.fail],
}
],
}
}
},
step(current){
if(current === 1){
this.total = 0,
this.totalColl ={},
this.success = 0,
this.fail = 0,
this.percent = 0
}
}
}
}
</script>
<style>
</style>
\ No newline at end of file
<template>
<v-data-table
:disabled="loading"
height="300px"
min-height="300px"
max-height="300px"
width="100%"
max-width="100%"
dense
:headers="headers"
:items="result"
:items-per-page="100"
no-data-text="검수 이력이 없습니다."
:sort-by="['counter']"
:sort-desc="[true]"
class="elevation-0 mt-6 overflow-x-hidden overflow-y-auto"
hide-default-footer
>
<template v-slot:[`item.total`]="{ item }">
{{item.total}}
</template>
<template v-slot:[`item.state`]="{ item }">
<v-chip
:color="item.result === 0 ? 'error' : 'success'"
small
dark
>
{{ item.result === 0 ? '실패' :'성공' }}
</v-chip>
</template>
<template v-slot:[`item.time`]="{ item }">
{{item.time.toFixed(2)}}
</template>
</v-data-table>
</template>
<script>
export default {
data () {
return {
loading: true,
headers: [
{ text: '횟수', align: 'start', sortable: false, value: 'total',},
{ text: '검수 결과', align: 'center', value: 'state' },
],
}
},
props: {
step:Number,
project:Object,
result:Array
},
}
</script>
<style>
</style>
\ No newline at end of file
<template>
<v-stepper
v-model="step"
vertical
style="height:100%"
class="font-weight-black elevation-0 "
width="100%"
max-width="100%"
>
<v-toolbar
color="blue darken-1"
dark
class="elevation-0 "
>
<v-toolbar-title>{{wpo}}</v-toolbar-title>
<v-spacer></v-spacer>
<v-chip v-if="local" light color="yellow">LOCAL</v-chip>
</v-toolbar>
<v-stepper-step
:color="step > 1 ? 'primary' : 'blue lighten-3'"
:complete="step > 1"
step="1"
class="font-weight-black"
>
<small class="font-weight-bold">Step 1</small>
세팅
</v-stepper-step>
<v-stepper-content step="1" >
<div class="text-center">
<v-progress-circular
:size="100"
color="blue lighten-3"
indeterminate
></v-progress-circular>
</div>
</v-stepper-content>
<v-stepper-step
:color="step > 2 ? 'primary' : 'blue lighten-3'"
:complete="step > 2"
step="2"
class="font-weight-black"
>
<small class="font-weight-bold">Step 2 </small>
<span> 데이터 불러오기 </span>
</v-stepper-step>
<v-stepper-content step="2" >
<v-list>
<v-list-item-group
multiple
>
<v-list-item>
<v-list-item-action>
<v-checkbox
:input-value="Object.keys(project).length !== 0 ? true : false"
color="blue lighten-3"
></v-checkbox>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>프로젝트</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-action>
<v-checkbox
:input-value="infos.length !== 0 ? true : false"
color="blue lighten-3"
></v-checkbox>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>검수 정보</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-action>
<v-checkbox
:input-value="step === 2 ? true : false"
color="blue lighten-3"
></v-checkbox>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>데이터 저장</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list-item-group>
</v-list>
</v-stepper-content>
<v-stepper-step
:color="step > 3 ? 'primary' : 'blue lighten-3'"
:complete="step > 3"
step="3"
>
<small class="font-weight-bold">Step 3</small>
매니저 티칭 정보 확인
</v-stepper-step>
<v-stepper-content step="3">
<div class="text-center">
<v-progress-circular
:size="100"
color="blue lighten-3"
indeterminate
></v-progress-circular>
</div>
</v-stepper-content>
<v-stepper-step
:color="step > 4 ? 'primary' : 'blue lighten-3'"
:complete="step > 4"
step="4"
>
<small class="font-weight-bold">Step 4</small>
보드 사진 촬영
</v-stepper-step>
<v-stepper-content step="4">
<div class="text-center">
<v-progress-circular
:size="100"
color="blue lighten-3"
indeterminate
></v-progress-circular>
</div>
</v-stepper-content>
<v-stepper-step
:color="step > 5 ? 'primary' : 'blue lighten-3'"
:complete="step > 5"
step="5"
>
<small class="font-weight-bold">Step 5</small>
검수
</v-stepper-step>
<v-stepper-content step="5">
<div class="text-center">
<v-progress-circular
:size="100"
color="blue lighten-3"
indeterminate
></v-progress-circular>
</div>
</v-stepper-content>
<v-stepper-step
:color="step === 6 ? 'primary' : 'blue lighten-3'"
:complete="step === 6"
step="6"
>
<small class="font-weight-bold">Step 6</small>
결과
</v-stepper-step>
<v-stepper-content step="6">
<div class="text-center">
<v-btn
class="elevation-3 mt-5 "
x-large
fab
color="yellow"
>
<v-icon>mdi-replay</v-icon>
</v-btn>
<div class="mt-3">상단 버튼을 누르면 재검수</div>
</div>
</v-stepper-content>
</v-stepper>
</template>
<script>
export default {
props: {
step:Number,
wpo:String,
infos:Array,
project:Object,
local:Boolean
},
}
</script>
<style>
</style>
\ No newline at end of file
<template>
<v-card
width="100%"
height="850px"
class="elevation-0 "
>
<v-card-title class="blue-grey white--text ">AOI</v-card-title>
<v-container>
<v-row>
<v-col cols="4">
<v-card
:class="step === 0 ?'elevation-12':'elevation-0'"
:color="step === 0 ? '' : 'grey lighten-2'"
class="d-flex justify-center align-center"
height="740"
>
<v-row
class="fill-height"
align-content="center"
justify="center"
>
<v-col
class="text-center"
cols="12"
>
<span v-if="step > 0" class="text-h4">블루투스 연결 <v-icon color="success" class="pb-4" x-large>mdi-check-bold</v-icon> </span>
<span v-else class="text-h4 "><strong>블루투스</strong>를 연결해주세요</span>
</v-col>
<v-col v-if="step === 0" cols="8">
<v-progress-linear
color="blue-grey"
indeterminate
rounded
height="8"
></v-progress-linear>
</v-col>
</v-row>
</v-card>
</v-col>
<v-col cols="4">
<v-card
:class="step === 1 ?'elevation-12':'elevation-0'"
:color="step === 1 ? '' : 'grey lighten-2'"
class="d-flex justify-center align-center "
height="740"
>
<v-row
class="fill-height"
align-content="center"
justify="center"
>
<v-col
class="text-center"
cols="12"
>
<span v-if="step > 1" class="text-h4">AOI 연결 <v-icon color="success" class="pb-4" x-large>mdi-check-bold</v-icon> </span>
<div v-else class="text-h4 "><strong>AOI 장비</strong>와 연결해주세요
<p class="text-h4 "><strong>S/N : {{serial}}</strong></p></div>
</v-col>
<v-col v-if="step === 1" cols="8">
<v-progress-linear
color="blue-grey"
indeterminate
rounded
height="8"
></v-progress-linear>
</v-col>
</v-row>
</v-card>
</v-col>
<v-col cols="4">
<v-card
:class="step === 2 ?'elevation-12':'elevation-0'"
:color="step === 2 ? '' : 'grey lighten-2'"
class="d-flex justify-center align-center"
height="740"
>
<v-row
class="fill-height"
align-content="center"
justify="center"
>
<v-col
class="text-center"
cols="12"
>
<span v-if="step > 2" class="text-h4">프로젝트 연동 완료 <v-icon color="success" class="pb-4" x-large>mdi-check-bold</v-icon> </span>
<span v-else class="text-h4 "><strong>프로젝트</strong>를 생성해주세요</span>
</v-col>
<v-col v-if="step === 2" cols="8">
<v-progress-linear
color="blue-grey"
indeterminate
rounded
height="8"
></v-progress-linear>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
</v-container>
</v-card>
</template>
<script>
import managerService from '@/service/manager'
import { EventBus } from '@/event-bus'
export default {
data () {
return {
message: '준비중...',
step:1, //테스트로 실행
// step:0,
id:'',
}
},
computed: {
serial() {
return this.$store.state.aoi.serial
},
aoi(){
return this.$store.state.aoi.aoi
}
},
created(){
// this.network()
this.getAoi() // 테스트로 실행
},
methods: {
async network(){
EventBus.$emit('openBluetooth')
try{
const msg = new Object()
msg.cmd = "network_check"
let response = await managerService.request(msg)
if(JSON.parse(response.data).status){
EventBus.$emit('closeBluetooth')
setTimeout(() => {
this.step = 1
}, 1000);
}else{
this.network()
}
}catch(e){
// EventBus.$emit('openAlert',`${e.message}`, 'error')
}
},
getAoi(){
this.$store.dispatch('getAoi',this.serial)
let delay = 1000;
let timer = setInterval(()=> {
if(this.aoi.serial === this.serial){
clearInterval(timer)
setTimeout(() => {
this.step = 2
}, 2000);
}else{
this.$store.dispatch('getAoi',this.serial)
}
},delay)
},
getAoiProject(){
let delay = 1000;
let timer = setInterval(()=> {
if(this.aoi.projectUid !== 0){
clearInterval(timer)
this.step = 3
setTimeout(() => {
setTimeout(EventBus.$emit('setTeaching' , this.aoi.uid ), 3000);
}, 2000);
}else{
this.$store.dispatch('getAoi',this.serial)
}
},delay)
}
},
watch:{
async step(current) {
switch(current) {
case 1:
this.getAoi()
break;
case 2:
this.getAoiProject()
break;
}
}
}
}
</script>
<style>
</style>
\ No newline at end of file
<template>
<v-card
width="100%"
height="850px"
class="elevation-0 "
>
<v-card-title class="blue-grey white--text ">PROJECT</v-card-title>
<v-container>
<v-row>
<v-col cols="4">
<v-card
:class="step === 0 ?'elevation-12':'elevation-0'"
:color="step === 0 ? '' : 'grey lighten-2'"
class="d-flex justify-center align-center"
height="740"
>
<v-row
class="fill-height"
align-content="center"
justify="center"
>
<v-col
class="text-center"
cols="12"
>
<span v-if="step > 0" class="text-h4">블루투스 연결 <v-icon color="success" class="pb-4" x-large>mdi-check-bold</v-icon> </span>
<span v-else class="text-h4 "><strong>블루투스</strong>를 연결해주세요</span>
</v-col>
<v-col v-if="step === 0" cols="8">
<v-progress-linear
color="blue-grey"
indeterminate
rounded
height="8"
></v-progress-linear>
</v-col>
</v-row>
</v-card>
</v-col>
<v-col cols="4">
<v-card
:class="step === 1 ?'elevation-12':'elevation-0'"
:color="step === 1 ? '' : 'grey lighten-2'"
class="d-flex justify-center align-center "
height="740"
>
<v-row
class="fill-height"
align-content="center"
justify="center"
>
<v-col
class="text-center"
cols="12"
>
<span v-if="step > 1" class="text-h4">데이터 연동<v-icon color="success" class="pb-4" x-large>mdi-check-bold</v-icon> </span>
<div v-else class="text-h4 "><strong>서버</strong>와 DB 연동</div>
<!-- <p class="text-h4 "><strong>S/N : {{id}}</strong></p></div> -->
</v-col>
<v-col v-if="step === 1" cols="8">
<v-progress-linear
color="blue-grey"
indeterminate
rounded
height="8"
></v-progress-linear>
</v-col>
</v-row>
</v-card>
</v-col>
<v-col cols="4">
<v-card
:class="step === 2 ?'elevation-12':'elevation-0'"
:color="step === 2 ? '' : 'grey lighten-2'"
class="d-flex justify-center align-center"
height="740"
>
<v-row
class="fill-height"
align-content="center"
justify="center"
>
<v-col
class="text-center"
cols="12"
>
<span v-if="step > 2" class="text-h4">세팅 초기화<v-icon color="success" class="pb-4" x-large>mdi-check-bold</v-icon> </span>
<span v-else class="text-h4 "><strong>세팅</strong> 초기화</span>
</v-col>
<v-col v-if="step === 2" cols="8">
<v-progress-linear
color="blue-grey"
indeterminate
rounded
height="8"
></v-progress-linear>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
</v-container>
</v-card>
</template>
<script>
import managerService from '@/service/manager'
import projectService from '@/service/project'
import projectGQL from '@/gql/project'
import aoiGQL from '@/gql/aoi'
import { EventBus } from '@/event-bus'
export default {
data () {
return {
message: '준비중...',
step:0,
id:'',
}
},
props: {
project: Object,
},
computed: {
aoi(){
return this.$store.state.aoi.aoi
}
},
created(){
this.network()
},
methods: {
async network(){
EventBus.$emit('openBluetooth')
try{
const msg = new Object()
msg.cmd = "network_check"
let response = await managerService.request(msg)
if(JSON.parse(response.data).status){
EventBus.$emit('closeBluetooth')
setTimeout(() => {
this.step = 1
}, 1000);
}else{
this.network()
}
}catch(e){
// EventBus.$emit('openAlert',`${e.message}`, 'error')
}
},
async projectUpdate(){
let result = await projectGQL.update(this.project)
if(result){
projectService.save({})
setTimeout(() => {
this.step = 2
}, 3000);
}
},
async aoiInit(){
let result = await aoiGQL.update(this.aoi)
if(Object.keys(result).length !== 0){
setTimeout(() => {
this.step = 2
EventBus.$emit('setInit')
}, 3000);
}
},
},
watch:{
async step(current) {
switch(current) {
case 1:
this.projectUpdate()
break;
case 2:
this.aoiInit()
break;
}
}
}
}
</script>
<style>
</style>
\ No newline at end of file
<template>
<v-card
width="100%"
height="850px"
class="elevation-0 d-flex justify-center align-center flex-column"
>
<v-progress-circular
color="blue-grey"
indeterminate
rounded
:size="500"
:width="30"
>
<span class="text-h3 font-weight-bold"> {{message}}</span>
</v-progress-circular>
</v-card>
</template>
<script>
export default {
data () {
return {
}
},
props: {
message: String,
},
}
</script>
<style>
</style>
\ No newline at end of file
module.exports = {
rules: {
'no-unused-expressions': 'off'
}
}
/**
* A custom Nightwatch assertion. The assertion name is the filename.
*
* Example usage:
* browser.assert.elementCount(selector, count)
*
* For more information on custom assertions see:
* https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-assertions
*
*
* @param {string|object} selectorOrObject
* @param {number} count
*/
exports.assertion = function elementCount (selectorOrObject, count) {
let selector
// when called from a page object element or section
if (typeof selectorOrObject === 'object' && selectorOrObject.selector) {
// eslint-disable-next-line prefer-destructuring
selector = selectorOrObject.selector
} else {
selector = selectorOrObject
}
this.message = `Testing if element <${selector}> has count: ${count}`
this.expected = count
this.pass = val => val === count
this.value = res => res.value
function evaluator (_selector) {
return document.querySelectorAll(_selector).length
}
this.command = cb => this.api.execute(evaluator, [selector], cb)
}
/**
* A very basic Nightwatch custom command. The command name is the filename and the
* exported "command" function is the command.
*
* Example usage:
* browser.customExecute(function() {
* console.log('Hello from the browser window')
* });
*
* For more information on writing custom commands see:
* https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-commands
*
* @param {*} data
*/
exports.command = function command (data) {
// Other Nightwatch commands are available via "this"
// .execute() inject a snippet of JavaScript into the page for execution.
// the executed script is assumed to be synchronous.
//
// See https://nightwatchjs.org/api/execute.html for more info.
//
this.execute(
// The function argument is converted to a string and sent to the browser
function (argData) { return argData },
// The arguments for the function to be sent to the browser are specified in this array
[data],
function (result) {
// The "result" object contains the result of what we have sent back from the browser window
console.log('custom execute result:', result.value)
}
)
return this
}
/**
* A basic Nightwatch custom command
* which demonstrates usage of ES6 async/await instead of using callbacks.
* The command name is the filename and the exported "command" function is the command.
*
* Example usage:
* browser.openHomepage();
*
* For more information on writing custom commands see:
* https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-commands
*
*/
module.exports = {
command: async function () {
// Other Nightwatch commands are available via "this"
// .init() simply calls .url() command with the value of the "launch_url" setting
this.init()
this.waitForElementVisible('#app')
const result = await this.elements('css selector', '#app ul')
this.assert.strictEqual(result.value.length, 3)
}
}
/**
* A class-based Nightwatch custom command which is a variation of the openHomepage.js command.
* The command name is the filename and class needs to contain a "command" method.
*
* Example usage:
* browser.openHomepageClass();
*
* For more information on writing custom commands see:
* https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-commands
*
*/
const assert = require('assert')
module.exports = class {
async command () {
// Other Nightwatch commands are available via "this.api"
this.api.init()
this.api.waitForElementVisible('#app')
const result = await this.api.elements('css selector', '#app ul')
assert.strictEqual(result.value.length, 3)
}
}
///////////////////////////////////////////////////////////////////////////////////
// Refer to the entire list of global config settings here:
// https://github.com/nightwatchjs/nightwatch/blob/master/lib/settings/defaults.js#L16
//
// More info on test globals:
// https://nightwatchjs.org/gettingstarted/configuration/#test-globals
//
///////////////////////////////////////////////////////////////////////////////////
module.exports = {
// this controls whether to abort the test execution when an assertion failed and skip the rest
// it's being used in waitFor commands and expect assertions
abortOnAssertionFailure: true,
// this will overwrite the default polling interval (currently 500ms) for waitFor commands
// and expect assertions that use retry
waitForConditionPollInterval: 500,
// default timeout value in milliseconds for waitFor commands and implicit waitFor value for
// expect assertions
waitForConditionTimeout: 5000,
'default': {
/*
The globals defined here are available everywhere in any test env
*/
/*
myGlobal: function() {
return 'I\'m a method';
}
*/
},
'firefox': {
/*
The globals defined here are available only when the chrome testing env is being used
i.e. when running with --env firefox
*/
/*
* myGlobal: function() {
* return 'Firefox specific global';
* }
*/
},
/////////////////////////////////////////////////////////////////
// Global hooks
// - simple functions which are executed as part of the test run
// - take a callback argument which can be called when an async
// async operation is finished
/////////////////////////////////////////////////////////////////
/**
* executed before the test run has started, so before a session is created
*/
/*
before(cb) {
//console.log('global before')
cb();
},
*/
/**
* executed before every test suite has started
*/
/*
beforeEach(browser, cb) {
//console.log('global beforeEach')
cb();
},
*/
/**
* executed after every test suite has ended
*/
/*
afterEach(browser, cb) {
browser.perform(function() {
//console.log('global afterEach')
cb();
});
},
*/
/**
* executed after the test run has finished
*/
/*
after(cb) {
//console.log('global after')
cb();
},
*/
/////////////////////////////////////////////////////////////////
// Global reporter
// - define your own custom reporter
/////////////////////////////////////////////////////////////////
/*
reporter(results, cb) {
cb();
}
*/
}
/**
* A Nightwatch page object. The page object name is the filename.
*
* Example usage:
* browser.page.homepage.navigate()
*
* For more information on working with page objects see:
* https://nightwatchjs.org/guide/working-with-page-objects/
*
*/
module.exports = {
url: '/',
commands: [],
// A page object can have elements
elements: {
appContainer: '#app'
},
// Or a page objects can also have sections
sections: {
app: {
selector: '#app',
elements: {
logo: 'img'
},
// - a page object section can also have sub-sections
// - elements or sub-sections located here are retrieved using the "app" section as the base
sections: {
headline: {
selector: 'h1'
},
welcome: {
// the equivalent css selector for the "welcome" sub-section would be:
// '#app div.hello'
selector: 'div.hello',
elements: {
cliPluginLinks: {
selector: 'ul',
index: 0
}
}
}
}
}
}
}
////////////////////////////////////////////////////////////////
// For authoring Nightwatch tests, see
// https://nightwatchjs.org/guide
//
// For more information on working with page objects see:
// https://nightwatchjs.org/guide/working-with-page-objects/
////////////////////////////////////////////////////////////////
module.exports = {
beforeEach: (browser) => browser.init(),
'e2e tests using page objects': (browser) => {
const homepage = browser.page.homepage()
homepage.waitForElementVisible('@appContainer')
const app = homepage.section.app
app.assert.elementCount('@logo', 1)
app.expect.section('@welcome').to.be.visible
app.expect.section('@headline').text.to.match(/^Welcome to Your Vue\.js (.*)App$/)
browser.end()
},
'verify if string "e2e-nightwatch" is within the cli plugin links': (browser) => {
const homepage = browser.page.homepage()
const welcomeSection = homepage.section.app.section.welcome
welcomeSection.expect.element('@cliPluginLinks').text.to.contain('e2e-nightwatch')
}
}
// For authoring Nightwatch tests, see
// https://nightwatchjs.org/guide
module.exports = {
'default e2e tests': browser => {
browser
.init()
.waitForElementVisible('#app')
.assert.elementPresent('.hello')
.assert.containsText('h1', 'Welcome to Your Vue.js App')
.assert.elementCount('img', 1)
.end()
},
'example e2e test using a custom command': browser => {
browser
.openHomepage()
.assert.elementPresent('.hello')
.end()
}
}
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'
describe('HelloWorld.vue', () => {
it('renders props.msg when passed', () => {
const msg = 'new message'
const wrapper = shallowMount(HelloWorld, {
propsData: { msg }
})
expect(wrapper.text()).toMatch(msg)
})
})
module.exports = {
"transpileDependencies": [
"vuetify"
],
devServer: {
proxy: {
'/api/*': {
// target: 'http://192.168.53.34:3000' // 개발/서버
target: 'http://localhost:3000' // 개발서버
}
}
},
//npm run build 하면 지정된 경로로 생성한다.
outputDir: '../backend/public' ,
}
\ No newline at end of file
#!/bin/bash #!/bin/bash
docker rmi base/home-main-ds:0.3 #docker rmi base/home-main-ds:0.3
docker-compose build --no-cache base-vue-cli-3-ds docker-compose build --no-cache base-vue-cli-3-ds
FROM node:14.18.1 FROM node:14.18.1
MAINTAINER David You <frog@falinux.com> LABEL org.opencontainers.image.authors="khkraining@falinux.com"
ENV DEBIAN_FRONTEND noninteractive ENV DEBIAN_FRONTEND noninteractive
......
...@@ -8,7 +8,7 @@ services: ...@@ -8,7 +8,7 @@ services:
container_name : base-home-main-ds container_name : base-home-main-ds
volumes: volumes:
- ../apps/:/apps - ../apps/:/apps
network_mode: "host" # network_mode: "host"
privileged: true privileged: true
environment: environment:
CYPRESS_CACHE_FOLDER: /apps/.cypress-cache CYPRESS_CACHE_FOLDER: /apps/.cypress-cache
......
...@@ -12,10 +12,13 @@ ...@@ -12,10 +12,13 @@
#echo -e "kcert2-home-$target dev sever" #echo -e "kcert2-home-$target dev sever"
touch ../apps/frontend/src/vue-apollo.js touch ../apps/frontend/src/vue-apollo.js
docker-compose run --name neuro-home-dev-backend \ docker-compose run \
--publish 3000:3000 \
--publish 9400:9400 \
--name neuro-home-dev-backend \
--rm \ --rm \
-u $(id -u ${USER}):$(id -g ${USER}) \
--workdir /apps/backend/ \ --workdir /apps/backend/ \
-e AS_SERVICE=yes \ -e AS_SERVICE=yes \
base-home-main-ds \ base-home-main-ds \
npm start npm start
# -u $(id -u ${USER}):$(id -g ${USER}) \
...@@ -12,10 +12,12 @@ ...@@ -12,10 +12,12 @@
#echo -e "kcert2-home-$target dev sever" #echo -e "kcert2-home-$target dev sever"
# #
touch ../apps/frontend/src/vue-apollo.js touch ../apps/frontend/src/vue-apollo.js
docker-compose run --name neuro-home-dev-frontend \ docker-compose run \
--publish 8080:8080 \
--name neuro-home-dev-frontend \
--rm \ --rm \
-u $(id -u ${USER}):$(id -g ${USER}) \
--workdir /apps/frontend/ \ --workdir /apps/frontend/ \
-e AS_SERVICE=yes \ -e AS_SERVICE=yes \
base-home-main-ds \ base-home-main-ds \
npm run serve npm run serve
# -u $(id -u ${USER}):$(id -g ${USER}) \
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment