Compare commits
No commits in common. 'develop' and 'master' have entirely different histories.
@ -1,8 +0,0 @@ |
|||||||
VUE_APP_BACK_URL=http://localhost/covid |
|
||||||
VUE_APP_BACK_USER=http://localhost/user |
|
||||||
VUE_APP_IMAGE_STORE=http://localhost/apache/public/uploads/ |
|
||||||
VUE_APP_TEMPERATURE_HUB=http://localhost/covid/batchExecutionHub |
|
||||||
VUE_APP_TIMEOUT_TEMPERATURE_HUB=5000 |
|
||||||
VUE_APP_MSG_TEMPERATURE_HUB=temperature |
|
||||||
VUE_APP_EMIT_MSG_TEMPERATURE=received-temperature |
|
||||||
VUE_APP_MAX_CHART=30 |
|
@ -1,8 +0,0 @@ |
|||||||
VUE_APP_BACK_URL=http://localhost/covid |
|
||||||
VUE_APP_BACK_USER=http://localhost/user |
|
||||||
VUE_APP_IMAGE_STORE=http://localhost/apache/public/uploads/ |
|
||||||
VUE_APP_TEMPERATURE_HUB=http://localhost/covid/batchExecutionHub |
|
||||||
VUE_APP_TIMEOUT_TEMPERATURE_HUB=5000 |
|
||||||
VUE_APP_MSG_TEMPERATURE_HUB=temperature |
|
||||||
VUE_APP_EMIT_MSG_TEMPERATURE=received-temperature |
|
||||||
VUE_APP_MAX_CHART=30 |
|
@ -1,21 +0,0 @@ |
|||||||
.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? |
|
@ -1,13 +0,0 @@ |
|||||||
# étape de build |
|
||||||
FROM node:lts-alpine as build-stage |
|
||||||
WORKDIR /app |
|
||||||
COPY package*.json ./ |
|
||||||
RUN npm install |
|
||||||
COPY . . |
|
||||||
RUN npm run build |
|
||||||
|
|
||||||
# étape de production |
|
||||||
FROM nginx:stable-alpine as production-stage |
|
||||||
COPY --from=build-stage /app/dist /usr/share/nginx/html |
|
||||||
EXPOSE 80 |
|
||||||
CMD ["nginx", "-g", "daemon off;"] |
|
@ -1,6 +0,0 @@ |
|||||||
module.exports = { |
|
||||||
presets: [ |
|
||||||
'@vue/cli-plugin-babel/preset' |
|
||||||
], |
|
||||||
|
|
||||||
} |
|
@ -1,34 +0,0 @@ |
|||||||
.corps { |
|
||||||
height: 80vh; |
|
||||||
display: block; |
|
||||||
position: relative; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
.bg-passageOk |
|
||||||
{ |
|
||||||
background-color: seagreen; |
|
||||||
} |
|
||||||
|
|
||||||
.corps::after { |
|
||||||
content: ""; |
|
||||||
background-repeat:no-repeat; |
|
||||||
background-position:center center; |
|
||||||
background-attachment:fixed; |
|
||||||
background-size: 50vh auto; |
|
||||||
background-image: url("../src/assets/logo.png"); |
|
||||||
opacity: 0.5; |
|
||||||
top: 0; |
|
||||||
left: 0; |
|
||||||
bottom: 0; |
|
||||||
right: 0; |
|
||||||
position: absolute; |
|
||||||
z-index: -1; |
|
||||||
} |
|
||||||
|
|
||||||
.fade-enter-active{ |
|
||||||
transition: opacity .5s; |
|
||||||
} |
|
||||||
.fade-enter /* .fade-leave-active below version 2.1.8 */ { |
|
||||||
opacity: 0; |
|
||||||
} |
|
@ -1,296 +0,0 @@ |
|||||||
@charset "UTF-8"; |
|
||||||
@import url("https://fonts.googleapis.com/css?family=Ubuntu:400,700|Cabin+Condensed:400,600"); |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
body { |
|
||||||
background-color: #FFF; |
|
||||||
margin: 0px; |
|
||||||
font-family: Ubuntu, sans-serif; |
|
||||||
color: #1e1e1e; |
|
||||||
font-weight: normal; |
|
||||||
padding-top: 0; |
|
||||||
} |
|
||||||
|
|
||||||
h1, h2, h3, h4 { |
|
||||||
font-family: "Cabin Condensed", sans-serif; |
|
||||||
} |
|
||||||
|
|
||||||
header { |
|
||||||
padding: 1em; |
|
||||||
} |
|
||||||
|
|
||||||
header .headline { |
|
||||||
max-width: 640px; |
|
||||||
margin: 0 auto; |
|
||||||
} |
|
||||||
|
|
||||||
header .headline h1 { |
|
||||||
font-size: 3em; |
|
||||||
margin-bottom: 0; |
|
||||||
} |
|
||||||
|
|
||||||
header .headline h2 { |
|
||||||
margin-top: 0.2em; |
|
||||||
} |
|
||||||
|
|
||||||
footer { |
|
||||||
padding: 1em 2em 2em; |
|
||||||
} |
|
||||||
|
|
||||||
#container { |
|
||||||
width: 640px; |
|
||||||
margin: 20px auto; |
|
||||||
padding: 10px; |
|
||||||
} |
|
||||||
|
|
||||||
#interactive.viewport { |
|
||||||
width: 640px; |
|
||||||
height: 480px; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
#interactive.viewport canvas, video { |
|
||||||
float: left; |
|
||||||
width: 640px; |
|
||||||
height: 480px; |
|
||||||
} |
|
||||||
|
|
||||||
#interactive.viewport canvas.drawingBuffer, video.drawingBuffer { |
|
||||||
margin-left: -640px; |
|
||||||
} |
|
||||||
|
|
||||||
.controls fieldset { |
|
||||||
border: none; |
|
||||||
margin: 0; |
|
||||||
padding: 5px; |
|
||||||
} |
|
||||||
|
|
||||||
.controls .input-group { |
|
||||||
float: left; |
|
||||||
} |
|
||||||
|
|
||||||
.controls .input-group input, .controls .input-group button { |
|
||||||
display: block; |
|
||||||
} |
|
||||||
|
|
||||||
.controls .reader-config-group { |
|
||||||
float: right; |
|
||||||
} |
|
||||||
|
|
||||||
.controls .reader-config-group label { |
|
||||||
display: block; |
|
||||||
} |
|
||||||
|
|
||||||
.controls .reader-config-group label span { |
|
||||||
width: 9rem; |
|
||||||
display: inline-block; |
|
||||||
text-align: right; |
|
||||||
} |
|
||||||
|
|
||||||
.controls:after { |
|
||||||
content: ''; |
|
||||||
display: block; |
|
||||||
clear: both; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
#result_strip { |
|
||||||
margin: 10px 0; |
|
||||||
border-top: 1px solid #EEE; |
|
||||||
border-bottom: 1px solid #EEE; |
|
||||||
padding: 10px 0; |
|
||||||
} |
|
||||||
|
|
||||||
#result_strip > ul { |
|
||||||
padding: 0; |
|
||||||
margin: 0; |
|
||||||
list-style-type: none; |
|
||||||
width: auto; |
|
||||||
overflow-x: auto; |
|
||||||
overflow-y: hidden; |
|
||||||
white-space: nowrap; |
|
||||||
} |
|
||||||
|
|
||||||
#result_strip > ul > li { |
|
||||||
display: inline-block; |
|
||||||
vertical-align: middle; |
|
||||||
width: 160px; |
|
||||||
} |
|
||||||
|
|
||||||
#result_strip > ul > li .thumbnail { |
|
||||||
padding: 5px; |
|
||||||
margin: 4px; |
|
||||||
border: 1px dashed #CCC; |
|
||||||
} |
|
||||||
|
|
||||||
#result_strip > ul > li .thumbnail img { |
|
||||||
max-width: 140px; |
|
||||||
} |
|
||||||
|
|
||||||
#result_strip > ul > li .thumbnail .caption { |
|
||||||
white-space: normal; |
|
||||||
} |
|
||||||
|
|
||||||
#result_strip > ul > li .thumbnail .caption h4 { |
|
||||||
text-align: center; |
|
||||||
word-wrap: break-word; |
|
||||||
height: 40px; |
|
||||||
margin: 0px; |
|
||||||
} |
|
||||||
|
|
||||||
#result_strip > ul:after { |
|
||||||
content: ""; |
|
||||||
display: table; |
|
||||||
clear: both; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
.scanner-overlay { |
|
||||||
display: none; |
|
||||||
width: 640px; |
|
||||||
height: 510px; |
|
||||||
position: absolute; |
|
||||||
padding: 20px; |
|
||||||
top: 50%; |
|
||||||
margin-top: -275px; |
|
||||||
left: 50%; |
|
||||||
margin-left: -340px; |
|
||||||
background-color: #FFF; |
|
||||||
-moz-box-shadow: #333333 0px 4px 10px; |
|
||||||
-webkit-box-shadow: #333333 0px 4px 10px; |
|
||||||
box-shadow: #333333 0px 4px 10px; |
|
||||||
} |
|
||||||
|
|
||||||
.scanner-overlay > .header { |
|
||||||
position: relative; |
|
||||||
margin-bottom: 14px; |
|
||||||
} |
|
||||||
|
|
||||||
.scanner-overlay > .header h4, .scanner-overlay > .header .close { |
|
||||||
line-height: 16px; |
|
||||||
} |
|
||||||
|
|
||||||
.scanner-overlay > .header h4 { |
|
||||||
margin: 0px; |
|
||||||
padding: 0px; |
|
||||||
} |
|
||||||
|
|
||||||
.scanner-overlay > .header .close { |
|
||||||
position: absolute; |
|
||||||
right: 0px; |
|
||||||
top: 0px; |
|
||||||
height: 16px; |
|
||||||
width: 16px; |
|
||||||
text-align: center; |
|
||||||
font-weight: bold; |
|
||||||
font-size: 14px; |
|
||||||
cursor: pointer; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
i.icon-24-scan { |
|
||||||
width: 24px; |
|
||||||
height: 24px; |
|
||||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QzFFMjMzNTBFNjcwMTFFMkIzMERGOUMzMzEzM0E1QUMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QzFFMjMzNTFFNjcwMTFFMkIzMERGOUMzMzEzM0E1QUMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDMUUyMzM0RUU2NzAxMUUyQjMwREY5QzMzMTMzQTVBQyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDMUUyMzM0RkU2NzAxMUUyQjMwREY5QzMzMTMzQTVBQyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtQr90wAAAUuSURBVHjanFVLbFRVGP7ua97T9DGPthbamAYYBNSMVbBpjCliWWGIEBMWsnDJxkh8RDeEDW5MDGticMmGBWnSlRSCwgLFNkqmmrRIqzjTznTazkxn5s7c6/efzm0G0Jhwkj/nP+d/nv91tIWFBTQaDQWapkGW67p4ltUub5qmAi0UCqF/a/U2m81tpmddotwwDGSz2dzi4uKSaOucnJycGhsbe1XXdQiIIcdxEAgEtgXq9brySHCht79UXi/8QheawN27d385fPjwuEl6XyKR6LdtW7t06RLK5TKOHj2K/fv3Q87Dw8OYn5/HiRMnMDs7i5mZGQwODiqlPp8PuVwO6XRaOXb16lXl1OnTp5FMJvtosF8M+MWLarWqGJaWlpBKpRRcu3YN4+PjmJ6exsTEhDJw5coVjI6OKgPhcBiZTAbxeBx+vx+XL19Gd3c3Tp48Ka9zqDYgBlTQxYNgMIhIJKLCILkQb+TZsgvdsiyFi+feWRR7oRNZyanQtvW2V4DEUUBiK2eJpeDirSyhCe7F2QPh8fiEp72i9PbsC5G52DbiKZA771yr1dTuGfJ4PQNPFoAyQNR1aNEmsS5eyB3PgjeooMZd2AWvNmzYci/Gea7TeFOcI93jV/K67noGmi4vdRI9gPSDeMLSdKUBZZczlWm1rTtHjLZ24d+WER2tc8N1m+Y+ID74wx0zGYvhg9UNrJdtHJyZRdQfwPsrq9g99xsGlgsYmr6BNzO/IVwsYfjBQ6XYz6JI/72MV366B5/lw0elOkJWGUM3bmKtWjXSLuLaBWhnPnnp0FfoiFi4+TMfVAb2poBkDLjO845uYLEAjL4ALGWBP5YAOsP4AJYBFDaB1HOSVWD2PuV95H2RdV93Lv74/cf6p6Zxq/h6OofeOPJBC39JtONdwOAAViOs4p4OFGTf0Uc8iiyrr9YdQrUnDLsngrVOC0jQib44HlF2RafRZBz1Qy+vfhgK3NJZBlrm+LEm9qWwzFgLU7Ozg0JxZP06jQSRpQ7EerAWDSt6PuhHPmChEAog56fCLvJT5hHTm3OZkz3DyLx7XNWTGEA1GkV14gjWgwbW0ESVjYRwCOuai03L5E7OUBAV4kXSS4auoGIaKOma4m8EA5R1sMEGLh95C+XuLph0WJWpxepYYLtfT0RRgY1KgNODY6BoaChRuEhDCIZQYseuki5KN6hcQHiq7OZNv4/Zq2O6P4Lfkwn46vZjjaYZrIpvWbpzjLErrc4xUGE4avRedpYJalRcIl5hQius/SrPm9xrNOQYJhao6BvNUeWqtY8KaWuNjHOFAr7mM9f4NA4UbKysoUJ8PV9UzVOx6wxDDWUOxnK1pmCD07fOMAvtIsM3l89Dl3HRGhVma9AZMqjOnz2LQqWCxs6dqr3T7x1DTzKJaG8SekcHhg4cgI/56uKdlKnBV/WndqN3YAB/7tyBd3oT6GBIOzs7kc/nDfFdDFT5bS73cp06dQoaPa/Rw/rtO/resTHxxE2m9rCrbSR27UJCcMf1BpiA5rAAGgdfc868fUR1sMwj0cm9Iu9IctweisViB3hhKTHDcHc5jv/LspbyaZrR1OD82/fIlOkuB9LnEWRmDX2TsddUPg3D5gvuc0je0rZaD5EW6G3yjS+A3eeBEWq3XW/Abw1HhUspXADufQb86oW7tZytkYCN//3hHwBvDALPi8EnSOYK8DAOfCc2h4aGcO7cuafkzampqf9UripH12/DtOZbx8ciVGzYy5OO40o25ascGRl5Ssc/AgwAjW3JwqIUjSYAAAAASUVORK5CYII="); |
|
||||||
display: inline-block; |
|
||||||
background-repeat: no-repeat; |
|
||||||
line-height: 24px; |
|
||||||
margin-top: 1px; |
|
||||||
vertical-align: text-top; |
|
||||||
} |
|
||||||
|
|
||||||
@media (max-width: 603px) { |
|
||||||
|
|
||||||
#container { |
|
||||||
width: 300px; |
|
||||||
margin: 10px auto; |
|
||||||
-moz-box-shadow: none; |
|
||||||
-webkit-box-shadow: none; |
|
||||||
box-shadow: none; |
|
||||||
} |
|
||||||
|
|
||||||
#container form.voucher-form input.voucher-code { |
|
||||||
width: 180px; |
|
||||||
} |
|
||||||
} |
|
||||||
@media (max-width: 603px) { |
|
||||||
|
|
||||||
.reader-config-group { |
|
||||||
width: 100%; |
|
||||||
} |
|
||||||
|
|
||||||
.reader-config-group label > span { |
|
||||||
width: 50%; |
|
||||||
} |
|
||||||
|
|
||||||
.reader-config-group label > select, .reader-config-group label > input { |
|
||||||
max-width: calc(50% - 2px); |
|
||||||
} |
|
||||||
|
|
||||||
#interactive.viewport { |
|
||||||
width: 300px; |
|
||||||
height: 300px; |
|
||||||
overflow: hidden; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
#interactive.viewport canvas, video { |
|
||||||
margin-top: -50px; |
|
||||||
width: 300px; |
|
||||||
height: 400px; |
|
||||||
} |
|
||||||
|
|
||||||
#interactive.viewport canvas.drawingBuffer, video.drawingBuffer { |
|
||||||
margin-left: -300px; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
#result_strip { |
|
||||||
margin-top: 5px; |
|
||||||
padding-top: 5px; |
|
||||||
} |
|
||||||
|
|
||||||
#result_strip ul.thumbnails > li { |
|
||||||
width: 150px; |
|
||||||
} |
|
||||||
|
|
||||||
#result_strip ul.thumbnails > li .thumbnail .imgWrapper { |
|
||||||
width: 130px; |
|
||||||
height: 130px; |
|
||||||
overflow: hidden; |
|
||||||
} |
|
||||||
|
|
||||||
#result_strip ul.thumbnails > li .thumbnail .imgWrapper img { |
|
||||||
margin-top: -25px; |
|
||||||
width: 130px; |
|
||||||
height: 180px; |
|
||||||
} |
|
||||||
} |
|
||||||
@media (max-width: 603px) { |
|
||||||
|
|
||||||
.overlay.scanner { |
|
||||||
width: 640px; |
|
||||||
height: 510px; |
|
||||||
padding: 20px; |
|
||||||
margin-top: -275px; |
|
||||||
margin-left: -340px; |
|
||||||
background-color: #FFF; |
|
||||||
-moz-box-shadow: none; |
|
||||||
-webkit-box-shadow: none; |
|
||||||
box-shadow: none; |
|
||||||
} |
|
||||||
|
|
||||||
.overlay.scanner > .header { |
|
||||||
margin-bottom: 14px; |
|
||||||
} |
|
||||||
|
|
||||||
.overlay.scanner > .header h4, .overlay.scanner > .header .close { |
|
||||||
line-height: 16px; |
|
||||||
} |
|
||||||
|
|
||||||
.overlay.scanner > .header .close { |
|
||||||
height: 16px; |
|
||||||
width: 16px; |
|
||||||
} |
|
||||||
} |
|
@ -1 +0,0 @@ |
|||||||
tempfront |
|
@ -1,64 +0,0 @@ |
|||||||
{ |
|
||||||
"name": "coviiiiid", |
|
||||||
"version": "0.1.0", |
|
||||||
"private": true, |
|
||||||
"scripts": { |
|
||||||
"serve": "node_modules/.bin/vue-cli-service serve", |
|
||||||
"build": "node_modules/.bin/vue-cli-service build", |
|
||||||
"lint": "node_modules/.bin/vue-cli-service lint" |
|
||||||
}, |
|
||||||
"dependencies": { |
|
||||||
"@aspnet/signalr": "^1.1.4", |
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.28", |
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.13.0", |
|
||||||
"@fortawesome/vue-fontawesome": "^0.1.9", |
|
||||||
"axios": "^0.19.2", |
|
||||||
"bootstrap-vue": "^2.15.0", |
|
||||||
"chart.js": "^2.9.3", |
|
||||||
"commander": "^4.0.1", |
|
||||||
"core-js": "^3.4.3", |
|
||||||
"debounce": "^1.2.0", |
|
||||||
"es6-promise": "^4.2.8", |
|
||||||
"jquery": "^1.9.1", |
|
||||||
"keycloak-js": "^10.0.2", |
|
||||||
"nimble": "0.0.2", |
|
||||||
"node-datetime": "^2.1.2", |
|
||||||
"request-digest": "^1.0.13", |
|
||||||
"socket.io": "^2.3.0", |
|
||||||
"vue": "^2.6.10", |
|
||||||
"vue-chartjs": "^3.5.0", |
|
||||||
"vue-i18n": "^8.18.1", |
|
||||||
"vue-infinite-loading": "^2.4.5", |
|
||||||
"vue-js-toggle-button": "^1.3.3", |
|
||||||
"vue-router": "^3.3.2", |
|
||||||
"vuex": "^3.4.0", |
|
||||||
"xml2js": "^0.4.22" |
|
||||||
}, |
|
||||||
"devDependencies": { |
|
||||||
"@vue/cli-plugin-babel": "^4.1.0", |
|
||||||
"@vue/cli-plugin-eslint": "^4.1.0", |
|
||||||
"@vue/cli-service": "^4.1.0", |
|
||||||
"babel-eslint": "^10.0.3", |
|
||||||
"eslint": "^5.16.0", |
|
||||||
"eslint-plugin-vue": "^5.0.0", |
|
||||||
"vue-template-compiler": "^2.6.10" |
|
||||||
}, |
|
||||||
"eslintConfig": { |
|
||||||
"root": true, |
|
||||||
"env": { |
|
||||||
"node": true |
|
||||||
}, |
|
||||||
"extends": [ |
|
||||||
"plugin:vue/essential", |
|
||||||
"eslint:recommended" |
|
||||||
], |
|
||||||
"rules": {}, |
|
||||||
"parserOptions": { |
|
||||||
"parser": "babel-eslint" |
|
||||||
} |
|
||||||
}, |
|
||||||
"browserslist": [ |
|
||||||
"> 1%", |
|
||||||
"last 2 versions" |
|
||||||
] |
|
||||||
} |
|
Before Width: | Height: | Size: 4.2 KiB |
@ -1,17 +0,0 @@ |
|||||||
<!DOCTYPE html> |
|
||||||
<html lang="en"> |
|
||||||
<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>covid finder</title> |
|
||||||
</head> |
|
||||||
<body> |
|
||||||
<noscript> |
|
||||||
<strong>We're sorry but clientapp 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> |
|
@ -1,10 +0,0 @@ |
|||||||
{ |
|
||||||
"realm": "Test", |
|
||||||
"auth-server-url": "https://oauth.apsidetop-devel.net/auth", |
|
||||||
"ssl-required": "external", |
|
||||||
"resource": "test", |
|
||||||
"credentials": { |
|
||||||
"secret": "5cf010f0-b4a9-4db9-a9f2-102bc703c448" |
|
||||||
}, |
|
||||||
"confidential-port": 0 |
|
||||||
} |
|
@ -1,59 +0,0 @@ |
|||||||
<template> |
|
||||||
<b-container fluid id="app"> |
|
||||||
<Menu class="header" /> |
|
||||||
<div style="margin-top:60px"> |
|
||||||
<router-view > </router-view> |
|
||||||
</div> |
|
||||||
</b-container> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script> |
|
||||||
import Menu from './components/Menu.vue' |
|
||||||
import Vue from 'vue' |
|
||||||
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue' |
|
||||||
import 'bootstrap/dist/css/bootstrap.css' |
|
||||||
import 'bootstrap-vue/dist/bootstrap-vue.css' |
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core' |
|
||||||
import { faUserSecret } from '@fortawesome/free-solid-svg-icons' |
|
||||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' |
|
||||||
|
|
||||||
library.add(faUserSecret) |
|
||||||
|
|
||||||
Vue.component('font-awesome-icon', FontAwesomeIcon) |
|
||||||
|
|
||||||
// Install BootstrapVue |
|
||||||
Vue.use(BootstrapVue) |
|
||||||
// Optionally install the BootstrapVue icon components plugin |
|
||||||
Vue.use(IconsPlugin) |
|
||||||
|
|
||||||
export default { |
|
||||||
name: 'app', |
|
||||||
components: { |
|
||||||
Menu |
|
||||||
} |
|
||||||
} |
|
||||||
</script> |
|
||||||
|
|
||||||
<style> |
|
||||||
#app { |
|
||||||
font-family: Avenir, Helvetica, Arial, sans-serif; |
|
||||||
-webkit-font-smoothing: antialiased; |
|
||||||
-moz-osx-font-smoothing: grayscale; |
|
||||||
text-align: center; |
|
||||||
color: #2c3e50; |
|
||||||
margin-top: 0px; |
|
||||||
padding-left: 0; |
|
||||||
padding-right: 0 |
|
||||||
} |
|
||||||
.header { |
|
||||||
position:fixed; /* fixing the position takes it out of html flow - knows |
|
||||||
nothing about where to locate itself except by browser |
|
||||||
coordinates */ |
|
||||||
left:0; /* top left corner should start at leftmost spot */ |
|
||||||
top:0; /* top left corner should start at topmost spot */ |
|
||||||
width:100vw; /* take up the full browser width */ |
|
||||||
z-index:100; /* high z index so other content scrolls underneath */ |
|
||||||
height:50px; /* define height for content */ |
|
||||||
} |
|
||||||
</style> |
|
Before Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 19 KiB |
@ -1,91 +0,0 @@ |
|||||||
<template> |
|
||||||
<div id="videoapp"> |
|
||||||
<b-button v-b-modal.modal-2 > |
|
||||||
<font-awesome-icon icon="camera" /> |
|
||||||
{{$t('user_detail_photo')}} |
|
||||||
</b-button> |
|
||||||
<b-modal static size="xl" id="modal-2" :hide-footer="true" > |
|
||||||
<template v-slot:modal-header> |
|
||||||
Title |
|
||||||
<b-button size="sm" variant="danger" @click="close()"> |
|
||||||
Cancel |
|
||||||
</b-button> |
|
||||||
|
|
||||||
</template> |
|
||||||
<template v-slot:default> |
|
||||||
<div> |
|
||||||
<div><video ref="video" id="video" width="640" height="480" autoplay ></video></div> |
|
||||||
<div><button id="snap" v-on:click="capture()">Snap Photo</button></div> |
|
||||||
<canvas ref="canvas" id="canvas" width="640" height="480"></canvas> |
|
||||||
<ul> |
|
||||||
<li v-for="c in captures" v-bind:key="c.id"> |
|
||||||
<img v-bind:src="c.photo" alt="Photo" height="50" /> |
|
||||||
</li> |
|
||||||
</ul> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
</b-modal> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script> |
|
||||||
export default { |
|
||||||
name: "CapturePhoto", |
|
||||||
mounted() { |
|
||||||
this.video = this.$refs.video; |
|
||||||
let video = document.querySelector('video'); |
|
||||||
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { |
|
||||||
navigator.mediaDevices.getUserMedia({ video: true }).then(stream => { |
|
||||||
video.srcObject = stream |
|
||||||
}); |
|
||||||
} |
|
||||||
}, |
|
||||||
data () { |
|
||||||
return { |
|
||||||
video: {}, |
|
||||||
canvas: {}, |
|
||||||
compteur:0, |
|
||||||
captures: [], |
|
||||||
snapshot:{} |
|
||||||
} |
|
||||||
}, |
|
||||||
methods: { |
|
||||||
close() |
|
||||||
{ |
|
||||||
this.snapshot= null; |
|
||||||
this.$bvModal.hide("modal-2"); |
|
||||||
}, |
|
||||||
capture() { |
|
||||||
this.canvas = this.$refs.canvas; |
|
||||||
this.canvas.getContext("2d").drawImage(this.video, 0, 0, 640, 480); |
|
||||||
|
|
||||||
this.compteur++; |
|
||||||
this.snapshot = {photo:this.canvas.toDataURL("image/png"), id:this.compteur++} |
|
||||||
// this.captures.push(this.snapshot); |
|
||||||
this.$emit('update:snapshot', this.snapshot); |
|
||||||
this.$bvModal.hide("modal-2"); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
</script> |
|
||||||
|
|
||||||
<style> |
|
||||||
body: { |
|
||||||
background-color: #F0F0F0; |
|
||||||
} |
|
||||||
/* #app { |
|
||||||
text-align: center; |
|
||||||
color: #2c3e50; |
|
||||||
margin-top: 60px; |
|
||||||
}*/ |
|
||||||
#video { |
|
||||||
background-color: #000000; |
|
||||||
} |
|
||||||
#canvas { |
|
||||||
display: none; |
|
||||||
} |
|
||||||
li { |
|
||||||
display: inline; |
|
||||||
padding: 5px; |
|
||||||
} |
|
||||||
</style> |
|
@ -1,160 +0,0 @@ |
|||||||
<template> |
|
||||||
<div class="MenuNavBar"> |
|
||||||
<b-navbar toggleable="lg" type="dark" variant="info" style="min-height:60px; padding: 0px 0px 0px 0px"> |
|
||||||
|
|
||||||
<b-navbar-brand class="nav-link d-flex align-items-center justify-content-center" @click="doLogin"> |
|
||||||
<b-avatar variant="info" v-bind:src="img" size="3rem" > |
|
||||||
</b-avatar> |
|
||||||
</b-navbar-brand> |
|
||||||
|
|
||||||
<b-navbar-brand class="nav-link d-flex align-items-center justify-content-center" to="/" > |
|
||||||
{{$t('title')}} |
|
||||||
</b-navbar-brand> |
|
||||||
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle> |
|
||||||
<b-collapse id="nav-collapse" is-nav> |
|
||||||
<b-navbar-nav> |
|
||||||
<b-nav-item v-if="isAdmin" active-class="active" class="nav-link d-flex align-items-center justify-content-center" to="/users" >{{$t('user_title')}}</b-nav-item> |
|
||||||
<b-nav-item active-class="active" class="nav-link d-flex align-items-center justify-content-center" @click="logout" >{{$t('logout')}}</b-nav-item> |
|
||||||
</b-navbar-nav> |
|
||||||
|
|
||||||
</b-collapse> |
|
||||||
|
|
||||||
</b-navbar> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script> |
|
||||||
|
|
||||||
import { BNavbar, BNavbarBrand, BNavbarToggle } from 'bootstrap-vue' |
|
||||||
import { BAvatar } from 'bootstrap-vue' |
|
||||||
import UserService from "../services/UserService"; |
|
||||||
import Vue from "vue"; |
|
||||||
import axios from "axios"; |
|
||||||
|
|
||||||
Vue.component('b-avatar', BAvatar) |
|
||||||
|
|
||||||
export default { |
|
||||||
name: "Menu", |
|
||||||
components : |
|
||||||
{ |
|
||||||
BNavbar,BNavbarBrand, BNavbarToggle, BAvatar |
|
||||||
}, |
|
||||||
data:function(){ |
|
||||||
return { |
|
||||||
} |
|
||||||
}, |
|
||||||
computed : |
|
||||||
{ |
|
||||||
user(){ |
|
||||||
return this.$store.state.user; |
|
||||||
}, |
|
||||||
img() |
|
||||||
{ |
|
||||||
return this.$store.state.user != null && this.$store.state.user.image != null ? |
|
||||||
process.env.VUE_APP_IMAGE_STORE + this.$store.state.user.image : |
|
||||||
''; |
|
||||||
}, |
|
||||||
isAdmin() { |
|
||||||
return this.$store.state.roles.find(l => l.name == 'Administrators' && l.isActived) != null; |
|
||||||
}, |
|
||||||
isClient() { |
|
||||||
return this.$store.state.roles.find(l => l.name == 'customer' && l.isActived) != null; |
|
||||||
}, |
|
||||||
isLivreur() { |
|
||||||
return this.$store.state.roles.find(l => l.name == 'delivery' && l.isActived) != null; |
|
||||||
}, |
|
||||||
isManager() { |
|
||||||
return this.$store.state.roles.find(l => l.name == 'manager' && l.isActived) != null; |
|
||||||
}, |
|
||||||
}, |
|
||||||
mounted() { |
|
||||||
let that = this; |
|
||||||
UserService.initKeycloak( function () { |
|
||||||
sessionStorage.setItem("react-token", UserService.getToken()); |
|
||||||
sessionStorage.setItem("react-refresh-token", UserService.getRefreshToken()); |
|
||||||
|
|
||||||
let axiosConfig = { |
|
||||||
withCredentials: true, |
|
||||||
headers: { |
|
||||||
'Authorization': 'Bearer ' + sessionStorage.getItem("react-token"), |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
axios.get(process.env.VUE_APP_BACK_USER + "/api/users/bykeycloakid?guid=" + UserService.getUsername().sub, |
|
||||||
axiosConfig |
|
||||||
).then(result => { |
|
||||||
if( result.data.keycloakId !== null) |
|
||||||
that.$store.commit("updateUser", result.data); |
|
||||||
else |
|
||||||
UserService.doLogout(); |
|
||||||
}); |
|
||||||
|
|
||||||
axios.get(process.env.VUE_APP_BACK_USER + "/api/roles/bykeycloakid?keycloakid=" + UserService.getUsername().sub, |
|
||||||
axiosConfig |
|
||||||
).then(result => { |
|
||||||
that.$store.commit("updateRole", result.data); |
|
||||||
}); |
|
||||||
|
|
||||||
}, |
|
||||||
function(){ |
|
||||||
that.$store.commit("updateUser", null); |
|
||||||
that.$store.commit("updateRole", []); |
|
||||||
if(that.$router.currentRoute.path !== "/") |
|
||||||
that.$router.push({path:"/"}); |
|
||||||
}); |
|
||||||
|
|
||||||
}, |
|
||||||
methods : { |
|
||||||
logout: function () |
|
||||||
{ |
|
||||||
UserService.doLogout(); |
|
||||||
sessionStorage.setItem("react-token", ""); |
|
||||||
sessionStorage.setItem("react-refresh-token", ""); |
|
||||||
|
|
||||||
|
|
||||||
}, |
|
||||||
doLogin : function() |
|
||||||
{ |
|
||||||
|
|
||||||
let that = this; |
|
||||||
UserService.initKeycloak( function () { |
|
||||||
|
|
||||||
sessionStorage.setItem("react-token", UserService.getToken()); |
|
||||||
sessionStorage.setItem("react-refresh-token", UserService.getRefreshToken()); |
|
||||||
|
|
||||||
let axiosConfig = { |
|
||||||
withCredentials: true, |
|
||||||
headers: { |
|
||||||
'Authorization': 'Bearer ' + sessionStorage.getItem("react-token"), |
|
||||||
|
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
axios.get(process.env.VUE_APP_BACK_USER + "/api/users/bykeycloakid?guid=" + UserService.getUsername().sub, |
|
||||||
axiosConfig |
|
||||||
).then(result => { |
|
||||||
if( result.data.keycloakId !== null) |
|
||||||
that.$store.commit("updateUser", result.data); |
|
||||||
else |
|
||||||
UserService.doLogout(); |
|
||||||
}); |
|
||||||
|
|
||||||
axios.get(process.env.VUE_APP_BACK_USER + "/api/roles/bykeycloakid?keycloakid=" + UserService.getUsername().sub, |
|
||||||
axiosConfig |
|
||||||
).then(result => { |
|
||||||
that.$store.commit("updateRole", result.data); |
|
||||||
}); |
|
||||||
|
|
||||||
}, |
|
||||||
UserService.doLogin()) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
</script> |
|
||||||
|
|
||||||
<style scoped> |
|
||||||
|
|
||||||
</style> |
|
@ -1,271 +0,0 @@ |
|||||||
<template> |
|
||||||
<b-container fluid id="temperature"> |
|
||||||
<b-row style="padding-top: 10px"> |
|
||||||
<b-col> |
|
||||||
<b-avatar |
|
||||||
v-if="!acquirementInprogress" |
|
||||||
v-b-tooltip.hover :title="$t('sub_title')" |
|
||||||
variant="info" :src="image_avatar" |
|
||||||
size="10rem" style="margin-right: 5px" |
|
||||||
> |
|
||||||
</b-avatar> |
|
||||||
|
|
||||||
<div><video |
|
||||||
v-if="acquirementInprogress" |
|
||||||
ref="video" |
|
||||||
id="video" width="160" height="160" style="border-radius: 80px;" |
|
||||||
:srcObject.prop="stream" |
|
||||||
autoplay /> |
|
||||||
</div> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
<b-row> |
|
||||||
|
|
||||||
</b-row> |
|
||||||
<b-row> |
|
||||||
<b-col> |
|
||||||
<label style="font-size: 10px;font-style: italic">{{message}}</label> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
<b-row v-if="result != null"> |
|
||||||
<b-col> |
|
||||||
{{result.temperature | formatFloat}} {{$t('temperature_unit')}} |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
<b-row style="padding-top: 10px"> |
|
||||||
<b-col cols="6" class="d-flex justify-content-start"> |
|
||||||
{{$t('object_temperature')}} : {{received.Element | formatFloat}} {{$t('temperature_unit')}} |
|
||||||
</b-col> |
|
||||||
<b-col cols="6" class="d-flex justify-content-start"> |
|
||||||
{{$t('ambient_temperature')}} : {{received.Ambient | formatFloat}} {{$t('temperature_unit')}} |
|
||||||
</b-col> |
|
||||||
<b-col cols="12" class="d-flex justify-content-start" v-if="isAdmin"> |
|
||||||
{{$t('emissivity')}} : {{received.Emissivity | formatFloat}} |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
<b-row v-if="isAuth"> |
|
||||||
<test-chart |
|
||||||
:options="options" |
|
||||||
:styles="myStyles" |
|
||||||
:chart-data="datacollection"></test-chart> |
|
||||||
</b-row> |
|
||||||
<b-row> |
|
||||||
<b-col> |
|
||||||
<b-button @click="acquireTemp" variant="danger" :disabled="acquirementInprogress" v-if="isAuth"> |
|
||||||
{{$t('temperature_acq')}} |
|
||||||
<font-awesome-icon icon="question" /> |
|
||||||
|
|
||||||
<b-spinner v-if="acquirementInprogress" type="border" :label="$t('inprogress')"/> |
|
||||||
</b-button> |
|
||||||
</b-col> |
|
||||||
|
|
||||||
</b-row> |
|
||||||
|
|
||||||
</b-container> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script> |
|
||||||
import axios from "axios"; |
|
||||||
import TestChart from "./TestChart"; |
|
||||||
import Vue from "vue"; |
|
||||||
import '../services/TemperatureHub.js' |
|
||||||
import TemperatureHub from "../services/TemperatureHub"; |
|
||||||
|
|
||||||
Vue.use(TestChart); |
|
||||||
|
|
||||||
|
|
||||||
export default { |
|
||||||
name: 'Temperature', |
|
||||||
components: { |
|
||||||
TestChart |
|
||||||
}, |
|
||||||
|
|
||||||
props: { |
|
||||||
msg: String |
|
||||||
}, |
|
||||||
data:function(){ |
|
||||||
return { |
|
||||||
stream:{}, |
|
||||||
datacollection: {}, |
|
||||||
received : {}, |
|
||||||
|
|
||||||
acquirementInprogress:false, |
|
||||||
result: null, |
|
||||||
x:'', |
|
||||||
options: { |
|
||||||
responsive: true, |
|
||||||
maintainAspectRatio: false, |
|
||||||
}, |
|
||||||
roles:[], |
|
||||||
temperatureHub : null |
|
||||||
} |
|
||||||
}, |
|
||||||
computed: { |
|
||||||
image() |
|
||||||
{ |
|
||||||
return this.$store.state.user != null && this.$store.state.user.image != null ? |
|
||||||
process.env.VUE_APP_IMAGE_STORE + this.$store.state.user.image : |
|
||||||
require('@/assets/coviiiiiid.jpg'); |
|
||||||
}, |
|
||||||
myStyles() { |
|
||||||
return { |
|
||||||
height: `300px`, |
|
||||||
width:'100%', |
|
||||||
position: 'relative' |
|
||||||
} |
|
||||||
}, |
|
||||||
message() |
|
||||||
{ |
|
||||||
if(this.result == null) |
|
||||||
return ""; |
|
||||||
else |
|
||||||
return this.result.message; |
|
||||||
}, |
|
||||||
image_avatar() |
|
||||||
{ |
|
||||||
if(this.result == null) |
|
||||||
{ |
|
||||||
if(this.acquirementInprogress) |
|
||||||
return require('@/assets/waiting.jpg'); |
|
||||||
else |
|
||||||
return this.image; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
|
|
||||||
if(this.result.fever === null) |
|
||||||
return require('@/assets/out_of_range.jpg'); |
|
||||||
else if(this.result.fever) |
|
||||||
return require('@/assets/fever_ok.jpg'); |
|
||||||
else |
|
||||||
return this.image; |
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
}, |
|
||||||
isAdmin() { |
|
||||||
|
|
||||||
return this.$store.state.roles.find(l => l.name == 'Administrators' && l.isActived) != null; |
|
||||||
}, |
|
||||||
isAuth() { |
|
||||||
|
|
||||||
return this.$store.state.roles !== undefined && this.$store.state.roles.find(l => l.isActived) != null; |
|
||||||
}, |
|
||||||
}, |
|
||||||
filters: { |
|
||||||
formatFloat : function(value) { |
|
||||||
if (value) { |
|
||||||
return parseFloat(value).toFixed(2); |
|
||||||
} |
|
||||||
} |
|
||||||
}, |
|
||||||
|
|
||||||
created () { |
|
||||||
this.temperatureHub = new TemperatureHub(); |
|
||||||
Vue.prototype.$questionHub = this.temperatureHub.startHub(); |
|
||||||
this.$questionHub.$on(process.env.VUE_APP_EMIT_MSG_TEMPERATURE, this.onChanged); |
|
||||||
|
|
||||||
// Listen to score changes coming from SignalR events |
|
||||||
|
|
||||||
}, |
|
||||||
mounted() { |
|
||||||
|
|
||||||
this.fillData (); |
|
||||||
|
|
||||||
}, |
|
||||||
methods : { |
|
||||||
fillData () { |
|
||||||
this.datacollection = { |
|
||||||
labels: [], |
|
||||||
datasets: [ |
|
||||||
{ |
|
||||||
label: this.$t('temperature_chart_label'), |
|
||||||
backgroundColor: '#f87979', |
|
||||||
data: [] |
|
||||||
}] |
|
||||||
} |
|
||||||
}, |
|
||||||
|
|
||||||
onChanged: function(msg) { |
|
||||||
this.received = msg; |
|
||||||
|
|
||||||
let datacollection = { |
|
||||||
labels: [], |
|
||||||
datasets: [ |
|
||||||
{ |
|
||||||
label: this.$t('temperature_chart_label'), |
|
||||||
backgroundColor: '#f87979', |
|
||||||
data: [] |
|
||||||
}] |
|
||||||
} |
|
||||||
|
|
||||||
if(this.datacollection.labels.length > process.env.VUE_APP_MAX_CHART) |
|
||||||
{ |
|
||||||
this.datacollection.labels.shift(); |
|
||||||
this.datacollection.datasets[0].data.shift(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
datacollection.labels.push(...this.datacollection.labels); |
|
||||||
datacollection.datasets[0].data.push(...this.datacollection.datasets[0].data); |
|
||||||
|
|
||||||
datacollection.labels.push(this.x); |
|
||||||
datacollection.datasets[0].data.push(this.received.Element); |
|
||||||
this.datacollection = datacollection; |
|
||||||
|
|
||||||
}, |
|
||||||
acquireTemp : async function() |
|
||||||
{ |
|
||||||
try { |
|
||||||
this.acquirementInprogress = true; |
|
||||||
let that = this; |
|
||||||
this.video = this.$refs.video; |
|
||||||
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { |
|
||||||
navigator.mediaDevices.getUserMedia({ video: true }).then(stream => { |
|
||||||
that.stream = stream |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
this.result = null; |
|
||||||
let axiosConfig = { |
|
||||||
withCredentials: true, |
|
||||||
headers:{'Authorization': 'Bearer ' + sessionStorage.getItem("react-token"), |
|
||||||
} |
|
||||||
}; |
|
||||||
let result = await axios.get(process.env.VUE_APP_BACK_URL + "/api/temperature", axiosConfig); |
|
||||||
window.console.log(result); |
|
||||||
this.result = result.data; |
|
||||||
|
|
||||||
} |
|
||||||
finally { |
|
||||||
this.acquirementInprogress = false; |
|
||||||
this.stream = null; |
|
||||||
} |
|
||||||
} |
|
||||||
}, |
|
||||||
beforeDestroy : async function() { |
|
||||||
|
|
||||||
// Make sure to cleanup SignalR event handlers when removing the component |
|
||||||
this.$questionHub.$off(process.env.VUE_APP_EMIT_MSG_TEMPERATURE, this.onChanged); |
|
||||||
await this.temperatureHub.stopHub(); |
|
||||||
} |
|
||||||
} |
|
||||||
</script> |
|
||||||
|
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only --> |
|
||||||
<style scoped> |
|
||||||
h3 { |
|
||||||
margin: 40px 0 0; |
|
||||||
} |
|
||||||
ul { |
|
||||||
list-style-type: none; |
|
||||||
padding: 0; |
|
||||||
} |
|
||||||
li { |
|
||||||
display: inline-block; |
|
||||||
margin: 0 10px; |
|
||||||
} |
|
||||||
a { |
|
||||||
color: #42b983; |
|
||||||
} |
|
||||||
</style> |
|
@ -1,17 +0,0 @@ |
|||||||
import { Line, mixins } from 'vue-chartjs' |
|
||||||
const { reactiveProp } = mixins |
|
||||||
|
|
||||||
export default { |
|
||||||
extends: Line, |
|
||||||
mixins: [reactiveProp], |
|
||||||
props: ['options'], |
|
||||||
options: { |
|
||||||
responsive: true, |
|
||||||
maintainAspectRatio: false, |
|
||||||
}, |
|
||||||
mounted () { |
|
||||||
// this.chartData is created in the mixin.
|
|
||||||
// If you want to pass options please create a local options object
|
|
||||||
this.renderChart(this.chartData, this.options) |
|
||||||
} |
|
||||||
} |
|
@ -1,183 +0,0 @@ |
|||||||
<template> |
|
||||||
<div> |
|
||||||
<b-card v-if="user.isNew == undefined" no-body class="overflow-hidden cardUser" |
|
||||||
> |
|
||||||
<b-row no-gutters style="height: 200px" > |
|
||||||
<b-col md="8" cols="7" class="border-right" style=";background-color: #EEEEEE"> |
|
||||||
<b-row align-h="center" v-if="user.image !== null"> |
|
||||||
<router-link |
|
||||||
:to="{name: 'User', params: {id: user.id } }" |
|
||||||
v-slot="{ href, route, navigate}" |
|
||||||
v-if="user.image !== '' && user.image !== null" |
|
||||||
> |
|
||||||
<div class="mb-2 imageUser"> |
|
||||||
<b-avatar :href="href" @click="navigate" |
|
||||||
:title="user.nom + ' ' + user.prenom" |
|
||||||
variant="light" |
|
||||||
v-bind:src="img" size="6rem" |
|
||||||
> |
|
||||||
</b-avatar> |
|
||||||
</div> |
|
||||||
</router-link> |
|
||||||
</b-row> |
|
||||||
<b-row align-h="center"> |
|
||||||
<b-col> |
|
||||||
<h4> {{user.prenom}} {{user.nom}}</h4> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
<b-row v-for="role in user.roles" v-bind:key="role.id"> |
|
||||||
<b-col class="d-flex justify-content-center align-items-center"> |
|
||||||
<h5> {{role.libelle}}</h5> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
</b-col> |
|
||||||
<b-col md="4" cols="5" class="d-flex flex-column justify-content-between"> |
|
||||||
|
|
||||||
<b-row > |
|
||||||
<b-col style="padding-bottom: 15px; padding-top: 15px"> |
|
||||||
<router-link |
|
||||||
:to="{name: 'User', params: {id: user.id } }" |
|
||||||
v-slot="{ href, route, navigate}" |
|
||||||
> |
|
||||||
|
|
||||||
<b-button :href="href" @click="navigate" class="actionButton" > |
|
||||||
<font-awesome-icon icon="edit" /> |
|
||||||
{{$t('edit')}}</b-button> |
|
||||||
</router-link> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
<b-row> |
|
||||||
<b-col style="padding-bottom: 15px; padding-top: 15px"> |
|
||||||
<b-button @click="deleteUser(user)" class="actionButton" > |
|
||||||
<font-awesome-icon icon="trash" /> |
|
||||||
{{$t('delete')}} |
|
||||||
</b-button> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
</b-card> |
|
||||||
|
|
||||||
<b-card v-if="user.isNew" no-body |
|
||||||
class="overflow-hidden rounded Desktopbutton cardUser"> |
|
||||||
<router-link |
|
||||||
:to="{name: 'User', params: {id: 0 } }" |
|
||||||
v-slot="{ href, route, navigate}"> |
|
||||||
<b-button :href="href" @click="navigate" |
|
||||||
style="width:100%; height: 100%" |
|
||||||
class="d-flex justify-content-center align-items-center"> |
|
||||||
<font-awesome-icon icon="plus-circle" style="width: 64px; height:64px" /> |
|
||||||
</b-button> |
|
||||||
</router-link> |
|
||||||
</b-card> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script> |
|
||||||
import axios from "axios"; |
|
||||||
|
|
||||||
export default { |
|
||||||
name: "CardUser", |
|
||||||
props: |
|
||||||
{ |
|
||||||
method: {type: Function}, |
|
||||||
user: { |
|
||||||
type: Object |
|
||||||
} |
|
||||||
}, |
|
||||||
mounted() |
|
||||||
{ |
|
||||||
|
|
||||||
}, |
|
||||||
computed : |
|
||||||
{ |
|
||||||
img() |
|
||||||
{ |
|
||||||
return this.user != null && this.user.image!= null ? |
|
||||||
process.env.VUE_APP_IMAGE_STORE + this.user.image : |
|
||||||
''; |
|
||||||
}, |
|
||||||
}, |
|
||||||
methods: |
|
||||||
{ |
|
||||||
deleteUser : function(user) |
|
||||||
{ |
|
||||||
|
|
||||||
let axiosConfig = { |
|
||||||
withCredentials: true, |
|
||||||
headers:{'Authorization': 'Bearer ' + sessionStorage.getItem("react-token"), |
|
||||||
} |
|
||||||
}; |
|
||||||
this.$bvModal.msgBoxConfirm('Vous allez supprimer l\'utilisateur \'' + user.login + '\'. Voulez-vous continuer ?', |
|
||||||
{ |
|
||||||
title: 'Suppression Utilisateur', |
|
||||||
size: 'sm', |
|
||||||
buttonSize: 'sm', |
|
||||||
okVariant: 'success', |
|
||||||
okTitle: 'Oui', |
|
||||||
cancelVariant: 'danger', |
|
||||||
cancelTitle: 'Non', |
|
||||||
footerClass: 'p-2', |
|
||||||
hideHeaderClose: false, |
|
||||||
centered: true |
|
||||||
}) |
|
||||||
.then(value => { |
|
||||||
if(value) { |
|
||||||
axios.delete(process.env.VUE_APP_BACK_USER+ "/api/users/" + user.id, |
|
||||||
axiosConfig |
|
||||||
).then(() => { |
|
||||||
this.$emit('send-message'); |
|
||||||
}); |
|
||||||
} |
|
||||||
}) |
|
||||||
.catch(err => { |
|
||||||
window.console.error(err.messages); |
|
||||||
}) |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
</script> |
|
||||||
|
|
||||||
<style scoped> |
|
||||||
.card-body |
|
||||||
{ |
|
||||||
padding-right: 0px; |
|
||||||
padding-left: 0px; |
|
||||||
padding-top: 0px; |
|
||||||
} |
|
||||||
.cardUser { |
|
||||||
max-width: 540px; |
|
||||||
height: 175px |
|
||||||
} |
|
||||||
.actionButton{ |
|
||||||
width:125px |
|
||||||
} |
|
||||||
|
|
||||||
.imageUser { |
|
||||||
width:96px; |
|
||||||
height:96px |
|
||||||
} |
|
||||||
|
|
||||||
.headerUser { |
|
||||||
position:fixed; /* fixing the position takes it out of html flow - knows |
|
||||||
nothing about where to locate itself except by browser |
|
||||||
coordinates */ |
|
||||||
left:0; /* top left corner should start at leftmost spot */ |
|
||||||
/*top:0; /* top left corner should start at topmost spot */ |
|
||||||
width:100vw; /* take up the full browser width */ |
|
||||||
z-index:50; /* high z index so other content scrolls underneath */ |
|
||||||
height: 100px; |
|
||||||
background-color: white; |
|
||||||
} |
|
||||||
@media (min-width: 50em) { |
|
||||||
.Desktopbutton { display: block; } |
|
||||||
.Mobilebutton { display: none; } |
|
||||||
} |
|
||||||
|
|
||||||
@media (max-width: 50em) { |
|
||||||
.Desktopbutton { display: none; } |
|
||||||
.Mobilebutton { display: block; } |
|
||||||
.MobileEntete {margin-top: 35px;} |
|
||||||
} |
|
||||||
</style> |
|
@ -1,228 +0,0 @@ |
|||||||
<template> |
|
||||||
<b-container fluid id="ListeUser" > |
|
||||||
<div class="headerUser" variant="dark"> |
|
||||||
<b-row align-h="center" |
|
||||||
style="padding-top: 15px;" |
|
||||||
> |
|
||||||
<h2>{{$t('user_title')}} </h2> |
|
||||||
</b-row> |
|
||||||
|
|
||||||
<b-row align-v="center"> |
|
||||||
<b-col cols="8" lg="3" > |
|
||||||
<b-form-input v-model="search" |
|
||||||
@input="debounceInput" |
|
||||||
v-bind:placeholder="$t('search')" style="max-width: 400px"></b-form-input> |
|
||||||
</b-col> |
|
||||||
<b-col cols="1" lg="1"> |
|
||||||
<b-button @click="display"> |
|
||||||
<font-awesome-icon icon="search" /> |
|
||||||
</b-button> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
|
|
||||||
<b-row> |
|
||||||
<router-link |
|
||||||
:to="{name: 'User', params: {id: 0 } }" |
|
||||||
v-slot="{ href, route, navigate}"> |
|
||||||
<b-button :href="href" @click="navigate" class="Mobilebutton" |
|
||||||
style="width:100%"> |
|
||||||
<font-awesome-icon icon="plus-circle" /> |
|
||||||
</b-button> |
|
||||||
</router-link> |
|
||||||
</b-row> |
|
||||||
|
|
||||||
</div> |
|
||||||
<div style="padding-top: 135px" class="MobileEntete"> |
|
||||||
|
|
||||||
<b-row v-if="!isLoaded" class="text-center d-flex justify-content-center"> |
|
||||||
<b-spinner type="border" label="chargement en cours..."></b-spinner> |
|
||||||
</b-row> |
|
||||||
|
|
||||||
<b-row v-if="isLoaded && users.length > 0" > |
|
||||||
<b-col cols="12" md="4" lg="4" v-for="user in users" v-bind:key="user.id" |
|
||||||
style="padding-right: 5px; padding-left: 5px; padding-top: 5px; padding-bottom: 5px"> |
|
||||||
<div> |
|
||||||
<card-user :user="user" @send-message="handleSendMessage"/> |
|
||||||
</div> |
|
||||||
</b-col> |
|
||||||
|
|
||||||
<infinite-loading @infinite="infiniteHandler" :identifier="infiniteId"> |
|
||||||
<div slot="no-more"></div> |
|
||||||
<div slot="no-results"></div> |
|
||||||
</infinite-loading> |
|
||||||
</b-row> |
|
||||||
<b-row class="mb-4" v-else> |
|
||||||
<p v-if="isLoaded">{{$t('user_list_empty')}} </p> |
|
||||||
</b-row> |
|
||||||
</div> |
|
||||||
</b-container> |
|
||||||
|
|
||||||
|
|
||||||
</template> |
|
||||||
|
|
||||||
<script> |
|
||||||
import axios from 'axios'; |
|
||||||
import InfiniteLoading from 'vue-infinite-loading'; |
|
||||||
import CardUser from "./CardUser"; |
|
||||||
import { debounce } from "debounce"; |
|
||||||
|
|
||||||
export default { |
|
||||||
name: "ListeUser", |
|
||||||
props:['value'], |
|
||||||
components: { |
|
||||||
CardUser, |
|
||||||
InfiniteLoading, |
|
||||||
}, |
|
||||||
|
|
||||||
data:function(){ |
|
||||||
return { |
|
||||||
page: 1, |
|
||||||
pageSize:4, |
|
||||||
search:'', |
|
||||||
infiniteId: + new Date(), |
|
||||||
users: [ |
|
||||||
], |
|
||||||
isLoaded: false |
|
||||||
} |
|
||||||
}, |
|
||||||
methods : |
|
||||||
{ |
|
||||||
handleSendMessage() { |
|
||||||
this.display(); |
|
||||||
}, |
|
||||||
debounceInput: debounce(function () { |
|
||||||
this.display(); |
|
||||||
}, 500,false), |
|
||||||
infiniteHandler : function($state) |
|
||||||
{ |
|
||||||
let that = this; |
|
||||||
let axiosConfig = { |
|
||||||
withCredentials: true, |
|
||||||
headers:{'Authorization': 'Bearer ' + sessionStorage.getItem("react-token"), |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
axios.get(process.env.VUE_APP_BACK_USER + "/api/users?page=" + that.page |
|
||||||
+ "&pageSize=" + that.pageSize |
|
||||||
+ "&search=" + that.search, |
|
||||||
axiosConfig |
|
||||||
).then(result => { |
|
||||||
if (result.data.length) { |
|
||||||
this.page += 1; |
|
||||||
this.users.push(...result.data); |
|
||||||
$state.loaded(); |
|
||||||
} else { |
|
||||||
$state.complete(); |
|
||||||
} |
|
||||||
}); |
|
||||||
}, |
|
||||||
display : async function() |
|
||||||
{ |
|
||||||
this.isLoaded = false; |
|
||||||
|
|
||||||
let axiosConfig = { |
|
||||||
withCredentials: true, |
|
||||||
headers:{'Authorization': 'Bearer ' + sessionStorage.getItem("react-token"), |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
this.page = 1; |
|
||||||
|
|
||||||
let result = await axios.get(process.env.VUE_APP_BACK_USER + "/api/users?page=" + this.page |
|
||||||
+ "&pageSize=" + this.pageSize |
|
||||||
+ "&search=" + this.search, |
|
||||||
axiosConfig |
|
||||||
); |
|
||||||
|
|
||||||
this.isLoaded = true; |
|
||||||
this.page += 1; |
|
||||||
this.users = [ {isNew:true}]; |
|
||||||
this.users.push(...result.data); |
|
||||||
this.infiniteId += 1; |
|
||||||
}, |
|
||||||
|
|
||||||
deleteUser : function(user) |
|
||||||
{ |
|
||||||
let that = this; |
|
||||||
|
|
||||||
let axiosConfig = { |
|
||||||
withCredentials: true, |
|
||||||
headers:{'Authorization': 'Bearer ' + sessionStorage.getItem("react-token"), |
|
||||||
} |
|
||||||
}; |
|
||||||
this.$bvModal.msgBoxConfirm('Vous allez supprimer l\'utilisateur \'' + user.nom + '\'. Voulez-vous continuer ?', |
|
||||||
{ |
|
||||||
title: 'Suppression Utilisateur', |
|
||||||
size: 'sm', |
|
||||||
buttonSize: 'sm', |
|
||||||
okVariant: 'success', |
|
||||||
okTitle: 'Oui', |
|
||||||
cancelVariant: 'danger', |
|
||||||
cancelTitle: 'Non', |
|
||||||
footerClass: 'p-2', |
|
||||||
hideHeaderClose: false, |
|
||||||
centered: true |
|
||||||
}) |
|
||||||
.then(value => { |
|
||||||
if(value) { |
|
||||||
axios.delete(process.env.VUE_APP_BACK_USER+ "/api/users/" + user.id, |
|
||||||
axiosConfig |
|
||||||
).then(() => { |
|
||||||
that.display(); |
|
||||||
}); |
|
||||||
} |
|
||||||
}) |
|
||||||
.catch(err => { |
|
||||||
window.console.error(err.messages); |
|
||||||
}) |
|
||||||
|
|
||||||
} |
|
||||||
}, |
|
||||||
mounted() { |
|
||||||
this.display(); |
|
||||||
} |
|
||||||
} |
|
||||||
</script> |
|
||||||
|
|
||||||
<style scoped> |
|
||||||
.card-body |
|
||||||
{ |
|
||||||
padding-right: 0px; |
|
||||||
padding-left: 0px; |
|
||||||
padding-top: 0px; |
|
||||||
} |
|
||||||
.cardUser { |
|
||||||
max-width: 540px; |
|
||||||
height: 175px |
|
||||||
} |
|
||||||
.actionButton{ |
|
||||||
width:125px |
|
||||||
} |
|
||||||
|
|
||||||
.imageUser { |
|
||||||
width:96px; |
|
||||||
height:96px |
|
||||||
} |
|
||||||
|
|
||||||
.headerUser { |
|
||||||
position:fixed; /* fixing the position takes it out of html flow - knows |
|
||||||
nothing about where to locate itself except by browser |
|
||||||
coordinates */ |
|
||||||
left:0; /* top left corner should start at leftmost spot */ |
|
||||||
/*top:0; /* top left corner should start at topmost spot */ |
|
||||||
width:100vw; /* take up the full browser width */ |
|
||||||
z-index:50; /* high z index so other content scrolls underneath */ |
|
||||||
height: 100px; |
|
||||||
background-color: white; |
|
||||||
} |
|
||||||
@media (min-width: 50em) { |
|
||||||
.Desktopbutton { display: block; } |
|
||||||
.Mobilebutton { display: none; } |
|
||||||
} |
|
||||||
|
|
||||||
@media (max-width: 50em) { |
|
||||||
.Desktopbutton { display: none; } |
|
||||||
.Mobilebutton { display: block; } |
|
||||||
.MobileEntete {margin-top: 35px;} |
|
||||||
} |
|
||||||
</style> |
|
@ -1,328 +0,0 @@ |
|||||||
<template> |
|
||||||
|
|
||||||
<b-container fluid id="User" > |
|
||||||
<!-- <b-row class="d-flex justify-content-center" style="padding-top: 15px;"> |
|
||||||
<h2>{{titre}} </h2> |
|
||||||
</b-row>--> |
|
||||||
|
|
||||||
<b-row v-if="!isLoaded" class="text-center d-flex justify-content-center"> |
|
||||||
<b-spinner type="border" label="chargement en cours..."></b-spinner> |
|
||||||
</b-row> |
|
||||||
|
|
||||||
<b-row v-if="isLoaded && user !== null"> |
|
||||||
<b-col cols="12" md="2"> |
|
||||||
<b-row align-v="center"> |
|
||||||
<b-col > |
|
||||||
<b-avatar |
|
||||||
variant="light" |
|
||||||
v-bind:src="img" size="10rem" |
|
||||||
> |
|
||||||
</b-avatar> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
<b-row align-v="center"> |
|
||||||
<b-col class="d-flex justify-content-center align-items-center"> |
|
||||||
<b-button v-if="hasImage" variant="danger" class="Desktop" @click="clearImage">{{$t('clear')}}</b-button> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
</b-col> |
|
||||||
<b-col cols="12" md="10"> |
|
||||||
<b-row align-v="center" style="padding-top: 5px"> |
|
||||||
<b-col md="1" cols="4"> |
|
||||||
<label>{{$t('user_detail_prenom')}}</label> |
|
||||||
</b-col> |
|
||||||
<b-col md="5" cols="8"> |
|
||||||
<b-form-input v-model="user.prenom" |
|
||||||
:state="validFirstName" |
|
||||||
v-bind:placeholder="$t('user_detail_prenom')"></b-form-input> |
|
||||||
</b-col> |
|
||||||
<b-col md="1" cols="4"> |
|
||||||
<label>{{$t('user_detail_nom')}}</label> |
|
||||||
</b-col> |
|
||||||
<b-col md="5" cols="8"> |
|
||||||
<b-form-input number v-model="user.nom" |
|
||||||
:state="validName" |
|
||||||
v-bind:placeholder="$t('user_detail_nom')"></b-form-input> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
<b-row> |
|
||||||
<b-col md="1" cols="4"> |
|
||||||
<label>{{$t('user_detail_username')}}</label> |
|
||||||
</b-col> |
|
||||||
<b-col md="5" cols="8"> |
|
||||||
<b-form-input v-model="user.userName" |
|
||||||
:state="validUserName" |
|
||||||
v-bind:placeholder="$t('user_detail_username')"></b-form-input> |
|
||||||
</b-col> |
|
||||||
<!-- <b-col md="1" cols="4"> |
|
||||||
<label>{{$t('user_detail_mail')}}</label> |
|
||||||
</b-col> |
|
||||||
<b-col md="5" cols="8"> |
|
||||||
<b-form-input mail v-model="user.email" v-bind:placeholder="$t('user_detail_mail')"></b-form-input> |
|
||||||
</b-col>--> |
|
||||||
</b-row> |
|
||||||
<b-row align-v="center" style="padding-top: 5px"> |
|
||||||
<b-col md="1" cols="4"> |
|
||||||
<label> {{$t('user_detail_id_keycloak')}}</label> |
|
||||||
</b-col> |
|
||||||
<b-col md="5" cols="8"> |
|
||||||
<b-form-input :disabled="!isAdmin" v-model="user.keycloakId" v-bind:placeholder="$t('user_detail_id_keycloak')"></b-form-input> |
|
||||||
</b-col> |
|
||||||
<b-col md="1" class="Desktop"> |
|
||||||
<label>{{$t('user_detail_image')}}</label> |
|
||||||
</b-col> |
|
||||||
<b-col md="5" class="Desktop"> |
|
||||||
<b-form-file |
|
||||||
v-model="file" |
|
||||||
plain |
|
||||||
></b-form-file> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
<b-row class="d-flex justify-content-center align-items-center" style="padding-top: 10px"> |
|
||||||
<h5>{{$t('user_detail_roles')}}</h5> |
|
||||||
</b-row> |
|
||||||
<b-row> |
|
||||||
<b-col> |
|
||||||
<b-row v-for="role in roles" v-bind:key="role.id"> |
|
||||||
<b-col> |
|
||||||
{{role.name}} |
|
||||||
</b-col> |
|
||||||
<b-col> |
|
||||||
<toggle-button |
|
||||||
v-model="role.isActived" |
|
||||||
:value="false" |
|
||||||
:font-size="16" |
|
||||||
:sync="true" |
|
||||||
/> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
|
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
|
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
<b-row v-if="isLoaded" > |
|
||||||
<b-col class="d-flex justify-content-between align-items-center"> |
|
||||||
<router-link |
|
||||||
:to="{name: 'ListeUser' }" |
|
||||||
v-slot="{ href, route, navigate}" |
|
||||||
> |
|
||||||
<b-button :href="href" @click="navigate" variant="danger"><font-awesome-icon icon="arrow-alt-circle-left" /> {{$t('back')}}</b-button> |
|
||||||
</router-link> |
|
||||||
|
|
||||||
<photo v-bind:snapshot.sync="photo"></photo> |
|
||||||
|
|
||||||
<b-button @click="saveAndQuit" variant="success" v-bind:disabled="!isValid"><font-awesome-icon icon="check" /> {{$t('valid')}}</b-button> |
|
||||||
</b-col> |
|
||||||
</b-row> |
|
||||||
</b-container> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script> |
|
||||||
import axios from 'axios'; |
|
||||||
import photo from '../Capture/CapturePhoto'; |
|
||||||
import Vue from "vue"; |
|
||||||
|
|
||||||
|
|
||||||
Vue.use(photo); |
|
||||||
|
|
||||||
const base64Encode = data => |
|
||||||
new Promise((resolve, reject) => { |
|
||||||
const reader = new FileReader(); |
|
||||||
reader.readAsDataURL(data); |
|
||||||
reader.onload = () => resolve(reader.result); |
|
||||||
reader.onerror = error => reject(error); |
|
||||||
}); |
|
||||||
|
|
||||||
export default { |
|
||||||
name: "User", |
|
||||||
components: { photo}, |
|
||||||
data:function(){ |
|
||||||
return { |
|
||||||
user: null, |
|
||||||
id: null, |
|
||||||
componentKey:0, |
|
||||||
file : null, |
|
||||||
photo: null, |
|
||||||
img:null, |
|
||||||
roles: null, |
|
||||||
isLoaded : false |
|
||||||
} |
|
||||||
}, |
|
||||||
computed: { |
|
||||||
isAdmin() { |
|
||||||
|
|
||||||
return this.$store.state.roles.find(l => l.name == 'Administrators' && l.isActived) != null; |
|
||||||
}, |
|
||||||
isValid() |
|
||||||
{ |
|
||||||
return this.validFirstName && this.validName && this.validUserName; |
|
||||||
}, |
|
||||||
validFirstName(){ |
|
||||||
return this.user != null && this.user.prenom !== '' && this.user.prenom !== null; |
|
||||||
}, |
|
||||||
validName(){ |
|
||||||
|
|
||||||
return this.user != null && this.user.nom !== '' && this.user.nom !== null; |
|
||||||
}, |
|
||||||
validUserName(){ |
|
||||||
|
|
||||||
return this.user != null && this.user.userName !== '' && this.user.userName !== null && this.user.userName !== undefined; |
|
||||||
}, |
|
||||||
hasImage() { |
|
||||||
return !!this.img; |
|
||||||
}, |
|
||||||
titre(){ |
|
||||||
return (this.user != null) ? this.user.prenom + ' ' + this.user.nom : this.$i18n.t('user_detail_title'); |
|
||||||
} |
|
||||||
}, |
|
||||||
watch : |
|
||||||
{ |
|
||||||
file : function (newValue, oldValue) { |
|
||||||
if (newValue !== oldValue) { |
|
||||||
if (newValue) { |
|
||||||
base64Encode(newValue) |
|
||||||
.then(value => { |
|
||||||
this.user.image= newValue.name; |
|
||||||
this.img = value; |
|
||||||
}) |
|
||||||
.catch(() => { |
|
||||||
this.img = null; |
|
||||||
}); |
|
||||||
} else { |
|
||||||
this.img = null; |
|
||||||
} |
|
||||||
} |
|
||||||
}, |
|
||||||
photo: function(val) |
|
||||||
{ |
|
||||||
this.img =val.photo; |
|
||||||
}, |
|
||||||
|
|
||||||
}, |
|
||||||
methods : |
|
||||||
{ |
|
||||||
clearImage() { |
|
||||||
this.img = null; |
|
||||||
this.file = null; |
|
||||||
this.photo = null; |
|
||||||
|
|
||||||
this.user.image="user_unknown.png"; |
|
||||||
}, |
|
||||||
saveAndQuit : async function() |
|
||||||
{ |
|
||||||
await this.save(); |
|
||||||
await this.$router.push({name: 'ListeUser'}); |
|
||||||
}, |
|
||||||
save : async function() |
|
||||||
{ |
|
||||||
let that = this; |
|
||||||
|
|
||||||
let axiosConfig = { |
|
||||||
withCredentials: true, |
|
||||||
headers:{'Authorization': 'Bearer ' + sessionStorage.getItem("react-token"), |
|
||||||
} |
|
||||||
}; |
|
||||||
let result = await axios.put(process.env.VUE_APP_BACK_USER + "/api/users/" + this.id, this.user, axiosConfig); |
|
||||||
that.user = result.data; |
|
||||||
let data = new FormData(); |
|
||||||
|
|
||||||
if(that.file !== null) { |
|
||||||
data.set('file', that.file) |
|
||||||
await axios.post(process.env.VUE_APP_BACK_USER + '/api/users/' + that.id + '/loadimage', data, { |
|
||||||
headers: { |
|
||||||
'Content-Type': 'multipart/form-data', |
|
||||||
'Authorization': 'Bearer ' + sessionStorage.getItem("react-token"), |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
else if(that.photo != null) |
|
||||||
{ |
|
||||||
data.set('base64', that.img.split(",")[1]); |
|
||||||
await axios.post(process.env.VUE_APP_BACK_USER + "/api/users/" + that.id + '/loadimage64',data, |
|
||||||
{ |
|
||||||
headers: { |
|
||||||
'Content-Type': 'multipart/form-data', |
|
||||||
'Authorization': 'Bearer ' + sessionStorage.getItem("react-token"), |
|
||||||
} |
|
||||||
} |
|
||||||
); |
|
||||||
that.componentKey += 1; |
|
||||||
} |
|
||||||
|
|
||||||
await axios.put(process.env.VUE_APP_BACK_USER + "/api/roles/" + this.user.keycloakId, this.roles, axiosConfig); |
|
||||||
} |
|
||||||
}, |
|
||||||
mounted() { |
|
||||||
this.id = this.$route.params.id; |
|
||||||
|
|
||||||
let axiosConfig = { |
|
||||||
withCredentials: true, |
|
||||||
headers: { |
|
||||||
'Authorization': 'Bearer ' + sessionStorage.getItem("react-token"), |
|
||||||
} |
|
||||||
}; |
|
||||||
this.isLoaded = false; |
|
||||||
if(this.id !== 0) { |
|
||||||
axios.get(process.env.VUE_APP_BACK_USER + "/api/users/" + this.id, |
|
||||||
axiosConfig |
|
||||||
).then(result => { |
|
||||||
this.user = result.data; |
|
||||||
this.img = process.env.VUE_APP_IMAGE_STORE + this.user.image; |
|
||||||
|
|
||||||
axios.get(process.env.VUE_APP_BACK_USER + "/api/roles/bykeycloakid?keycloakid=" + this.user.keycloakId, |
|
||||||
axiosConfig |
|
||||||
).then(result => { |
|
||||||
this.isLoaded = true; |
|
||||||
this.roles = result.data; |
|
||||||
}); |
|
||||||
|
|
||||||
}); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
this.user = {id:0, nom:'', prenom:'', keycloakId:''} |
|
||||||
|
|
||||||
axios.get(process.env.VUE_APP_BACK_USER + "/api/roles", |
|
||||||
axiosConfig |
|
||||||
).then(result => { |
|
||||||
this.isLoaded = true; |
|
||||||
this.roles = result.data; |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
</script> |
|
||||||
|
|
||||||
<style scoped> |
|
||||||
.row |
|
||||||
{ |
|
||||||
padding-top: 5px |
|
||||||
} |
|
||||||
.card-body |
|
||||||
{ |
|
||||||
padding-right: 0px; |
|
||||||
padding-left: 0px; |
|
||||||
padding-top: 0px; |
|
||||||
padding-bottom: 0px; |
|
||||||
} |
|
||||||
|
|
||||||
.collapsed > .when-opened, |
|
||||||
:not(.collapsed) > .when-closed { |
|
||||||
display: none; |
|
||||||
} |
|
||||||
|
|
||||||
@media (min-width: 50em) { |
|
||||||
.Desktop { display: block; } |
|
||||||
.Mobile { display: none; } |
|
||||||
} |
|
||||||
|
|
||||||
@media (max-width: 50em) { |
|
||||||
.Desktop { display: none; } |
|
||||||
.Mobile { display: block; } |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
</style> |
|
@ -1,41 +0,0 @@ |
|||||||
export default { |
|
||||||
en: { |
|
||||||
}, |
|
||||||
'fr-FR': { |
|
||||||
edit:"Editer", |
|
||||||
delete:"Supprimer", |
|
||||||
add:"ajouter", |
|
||||||
logout:"Logout", |
|
||||||
login:"Login", |
|
||||||
save:"Sauvegarder", |
|
||||||
back:"Retour", |
|
||||||
valid:"Valider", |
|
||||||
unload:"Décharge", |
|
||||||
search:"Recherche", |
|
||||||
clear:"Effacer", |
|
||||||
inprogress:"chargement en cours...", |
|
||||||
|
|
||||||
title:"Coviiiid", |
|
||||||
sub_title:"Coviiiid !!!!! Je sais où tu t'caches ! Viens là que j'te bute !", |
|
||||||
object_temperature : "T° objet", |
|
||||||
ambient_temperature : "T° ambiante", |
|
||||||
emissivity:"Emissivité", |
|
||||||
temperature_unit : "°C", |
|
||||||
temperature_acq:"Coviiiid", |
|
||||||
temperature_chart_label:"Température", |
|
||||||
|
|
||||||
user_title : "Utilisateurs", |
|
||||||
user_list_empty: "Aucun utilisateur", |
|
||||||
|
|
||||||
user_detail_title: "Utilisateur", |
|
||||||
user_detail_nom: "Nom", |
|
||||||
user_detail_prenom: "Prénom", |
|
||||||
user_detail_image:"Image", |
|
||||||
user_detail_id_keycloak:'idKeycloak', |
|
||||||
user_detail_username : 'login', |
|
||||||
user_detail_mail : 'Email', |
|
||||||
user_detail_roles : 'Rôles', |
|
||||||
user_detail_photo:"photo", |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -1,78 +0,0 @@ |
|||||||
import Vue from 'vue' |
|
||||||
import App from './App.vue' |
|
||||||
import router from './router/index' |
|
||||||
import VueI18n from 'vue-i18n' |
|
||||||
import messages from './lang/messages' |
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core' |
|
||||||
import { fas } from '@fortawesome/free-solid-svg-icons' |
|
||||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' |
|
||||||
import axios from "axios"; |
|
||||||
import UserService from "./services/UserService"; |
|
||||||
|
|
||||||
|
|
||||||
import ToggleButton from 'vue-js-toggle-button' |
|
||||||
import Vuex from 'vuex' |
|
||||||
|
|
||||||
|
|
||||||
library.add(fas) |
|
||||||
Vue.component('font-awesome-icon', FontAwesomeIcon) |
|
||||||
Vue.config.productionTip = false; |
|
||||||
Vue.use(VueI18n) |
|
||||||
Vue.use(ToggleButton); |
|
||||||
|
|
||||||
let locale = navigator.language; |
|
||||||
const i18n = new VueI18n({ |
|
||||||
fallbackLocale: 'fr', |
|
||||||
locale: locale, |
|
||||||
messages |
|
||||||
}) |
|
||||||
|
|
||||||
Vue.use(Vuex) |
|
||||||
const store = new Vuex.Store({ |
|
||||||
state : { |
|
||||||
roles: [], |
|
||||||
user:null, |
|
||||||
}, |
|
||||||
mutations: { |
|
||||||
updateRole (state, roles) { |
|
||||||
this.state.roles = roles; |
|
||||||
}, |
|
||||||
updateUser (state, user) { |
|
||||||
this.state.user = user; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
new Vue({ |
|
||||||
router, |
|
||||||
i18n, |
|
||||||
store, |
|
||||||
mounted(){ |
|
||||||
axios.interceptors.response.use( (response) => { |
|
||||||
// Return a successful response back to the calling service
|
|
||||||
return response; |
|
||||||
}, (error) => { |
|
||||||
// Return any error which is not due to authentication back to the calling service
|
|
||||||
if (error.response.status !== 401) { |
|
||||||
return new Promise((resolve, reject) => { |
|
||||||
reject(error); |
|
||||||
}); |
|
||||||
} |
|
||||||
else if (error.response.status === 401) { |
|
||||||
return new Promise((resolve, reject) => { |
|
||||||
UserService.doLogout(); |
|
||||||
UserService.initKeycloak( function () { |
|
||||||
|
|
||||||
sessionStorage.setItem("react-token", UserService.getToken()); |
|
||||||
sessionStorage.setItem("react-refresh-token", UserService.getRefreshToken()); |
|
||||||
}, UserService.doLogin); |
|
||||||
reject(error); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
}) |
|
||||||
}, |
|
||||||
render: h => h(App), |
|
||||||
}).$mount('#app') |
|
@ -1,33 +0,0 @@ |
|||||||
import Vue from 'vue' |
|
||||||
import Router from 'vue-router' |
|
||||||
import Temperature from "../components/Temperature"; |
|
||||||
import User from "../components/User/User"; |
|
||||||
import ListeUser from "../components/User/ListeUser"; |
|
||||||
|
|
||||||
Vue.use(Router) |
|
||||||
|
|
||||||
export default new Router({ |
|
||||||
routes: [ |
|
||||||
{ |
|
||||||
path: '*', |
|
||||||
name: 'Temperature', |
|
||||||
component: Temperature |
|
||||||
}, |
|
||||||
{ |
|
||||||
path: '/', |
|
||||||
name: 'Temperature', |
|
||||||
component: Temperature |
|
||||||
}, |
|
||||||
|
|
||||||
{ |
|
||||||
path: '/user/:id', |
|
||||||
name: 'User', |
|
||||||
component: User |
|
||||||
}, |
|
||||||
{ |
|
||||||
path: '/users', |
|
||||||
name: 'ListeUser', |
|
||||||
component: ListeUser |
|
||||||
}, |
|
||||||
] |
|
||||||
}) |
|
@ -1,52 +0,0 @@ |
|||||||
import {HubConnectionBuilder, LogLevel} from "@aspnet/signalr"; |
|
||||||
import Vue from "vue"; |
|
||||||
|
|
||||||
export default class TemperatureHub |
|
||||||
{ |
|
||||||
hubConnection; |
|
||||||
|
|
||||||
constructor() { |
|
||||||
this.hubConnection = new HubConnectionBuilder() |
|
||||||
.withUrl(process.env.VUE_APP_TEMPERATURE_HUB) |
|
||||||
.configureLogging(LogLevel.Information) |
|
||||||
.build(); |
|
||||||
} |
|
||||||
|
|
||||||
start() { |
|
||||||
let startedPromise = null; |
|
||||||
let that = this; |
|
||||||
startedPromise = this.hubConnection.start().catch(() => { |
|
||||||
return new Promise((resolve, reject) => |
|
||||||
setTimeout(() => that.start().then(resolve).catch(reject), process.env.VUE_APP_TIMEOUT_TEMPERATURE_HUB)) |
|
||||||
}) |
|
||||||
return startedPromise; |
|
||||||
} |
|
||||||
|
|
||||||
startHub() |
|
||||||
{ |
|
||||||
let that = this; |
|
||||||
this.hubConnection.onclose(() => |
|
||||||
{ |
|
||||||
that.start(); |
|
||||||
}/**/); |
|
||||||
|
|
||||||
this.start(); |
|
||||||
|
|
||||||
// use new Vue instance as an event bus
|
|
||||||
let questionHub = new Vue() |
|
||||||
// every component will use this.$questionHub to access the event bus
|
|
||||||
|
|
||||||
// Forward server side SignalR events through $questionHub, where components will listen to them
|
|
||||||
this.hubConnection.on(process.env.VUE_APP_MSG_TEMPERATURE_HUB, (msg) => { |
|
||||||
questionHub.$emit(process.env.VUE_APP_EMIT_MSG_TEMPERATURE, JSON.parse(msg) ) |
|
||||||
}) |
|
||||||
|
|
||||||
return questionHub; |
|
||||||
} |
|
||||||
|
|
||||||
async stopHub() |
|
||||||
{ |
|
||||||
await this.hubConnection.stop(); |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -1,50 +0,0 @@ |
|||||||
import Keycloak from "keycloak-js"; |
|
||||||
|
|
||||||
const _kc = new Keycloak('/keycloak.json'); |
|
||||||
|
|
||||||
/** |
|
||||||
* Initializes Keycloak instance and calls the provided callback function if successfully authenticated. |
|
||||||
* |
|
||||||
* @param onAuthenticatedCallback |
|
||||||
*/ |
|
||||||
const initKeycloak = (onAuthenticatedCallback, onUnAuthentificatedCallback) => { |
|
||||||
_kc.init({ |
|
||||||
onLoad: 'check-sso', |
|
||||||
flow: 'implicit', |
|
||||||
promiseType: 'native', |
|
||||||
}) |
|
||||||
.then((authenticated) => { |
|
||||||
if (authenticated) { |
|
||||||
onAuthenticatedCallback(); |
|
||||||
} else { |
|
||||||
window.console.warn("not authenticated!"); |
|
||||||
onUnAuthentificatedCallback(); |
|
||||||
} |
|
||||||
}) |
|
||||||
}; |
|
||||||
|
|
||||||
const doLogin = _kc.login; |
|
||||||
|
|
||||||
const doLogout = _kc.logout; |
|
||||||
|
|
||||||
const getToken = () => _kc.token; |
|
||||||
|
|
||||||
const getRefreshToken = () => _kc.refreshToken; |
|
||||||
|
|
||||||
const updateToken = (successCallback) => { |
|
||||||
return _kc.updateToken(5) |
|
||||||
.then(successCallback) |
|
||||||
.catch(doLogin) |
|
||||||
}; |
|
||||||
|
|
||||||
const getUsername = () => _kc.tokenParsed; |
|
||||||
|
|
||||||
export default { |
|
||||||
initKeycloak, |
|
||||||
doLogin, |
|
||||||
doLogout, |
|
||||||
getToken, |
|
||||||
getRefreshToken, |
|
||||||
updateToken, |
|
||||||
getUsername, |
|
||||||
} |
|
@ -1,18 +0,0 @@ |
|||||||
import axios from 'axios'; |
|
||||||
import { Promise } from "es6-promise"; |
|
||||||
|
|
||||||
|
|
||||||
export default () => { |
|
||||||
|
|
||||||
axios.interceptors.response.use( (response) => { |
|
||||||
// Return a successful response back to the calling service
|
|
||||||
return response; |
|
||||||
}, (error) => { |
|
||||||
// Return any error which is not due to authentication back to the calling service
|
|
||||||
if (error.response.status !== 401) { |
|
||||||
return new Promise((resolve, reject) => { |
|
||||||
reject(error); |
|
||||||
}); |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
@ -1,6 +0,0 @@ |
|||||||
module.exports = { |
|
||||||
devServer: { |
|
||||||
https: false, |
|
||||||
port:8080 |
|
||||||
} |
|
||||||
} |
|