@ -0,0 +1,3 @@ |
||||
VUE_APP_BACK_URL=http://localhost:5001 |
||||
VUE_APP_BACK_USER=http://localhost/user |
||||
VUE_APP_IMAGE_STORE= |
@ -0,0 +1 @@ |
||||
VUE_APP_BACK_URL=http://localhost:5000 |
@ -0,0 +1,21 @@ |
||||
.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,2 +1,29 @@ |
||||
# TemperatureCheckerFront |
||||
# clientapp |
||||
|
||||
## Project setup |
||||
``` |
||||
npm install |
||||
``` |
||||
|
||||
### Compiles and hot-reloads for development |
||||
``` |
||||
npm run serve |
||||
``` |
||||
|
||||
### Compiles and minifies for production |
||||
``` |
||||
npm run build |
||||
``` |
||||
|
||||
### Run your tests |
||||
``` |
||||
npm run test |
||||
``` |
||||
|
||||
### Lints and fixes files |
||||
``` |
||||
npm run lint |
||||
``` |
||||
|
||||
### Customize configuration |
||||
See [Configuration Reference](https://cli.vuejs.org/config/). |
||||
|
@ -0,0 +1,5 @@ |
||||
module.exports = { |
||||
presets: [ |
||||
'@vue/cli-plugin-babel/preset' |
||||
] |
||||
} |
@ -0,0 +1,62 @@ |
||||
{ |
||||
"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", |
||||
"core-js": "^3.4.3", |
||||
"es6-promise": "^4.2.8", |
||||
"keycloak-js": "^10.0.2", |
||||
"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", |
||||
"commander": "^4.0.1", |
||||
"nimble": "0.0.2", |
||||
"node-datetime": "^2.1.2", |
||||
"request-digest": "^1.0.13", |
||||
"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" |
||||
] |
||||
} |
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1,17 @@ |
||||
<!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> |
@ -0,0 +1,10 @@ |
||||
{ |
||||
"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 |
||||
} |
@ -0,0 +1,59 @@ |
||||
<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> |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 1.5 MiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 19 KiB |
@ -0,0 +1,91 @@ |
||||
<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" 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> |
@ -0,0 +1,154 @@ |
||||
<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="/temperature" > |
||||
{{$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 ? |
||||
'http://localhost/image/' + 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 () { |
||||
window.console.log("dologin"); |
||||
sessionStorage.setItem("react-token", UserService.getToken()); |
||||
sessionStorage.setItem("react-refresh-token", UserService.getRefreshToken()); |
||||
|
||||
let axiosConfig = { |
||||
withCredentials: true, |
||||
headers: { |
||||
'Authorization': 'Bearer ' + sessionStorage.getItem("react-token"), |
||||
} |
||||
}; |
||||
window.console.log(process.env.VUE_APP_BACK_USER); |
||||
axios.get(process.env.VUE_APP_BACK_USER + "/api/users/bykeycloakid?guid=" + UserService.getUsername().sub, |
||||
axiosConfig |
||||
).then(result => { |
||||
that.$store.commit("updateUser", result.data); |
||||
}); |
||||
|
||||
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", []); |
||||
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 () { |
||||
window.console.log("dologin"); |
||||
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 => { |
||||
that.$store.commit("updateUser", result.data); |
||||
}); |
||||
|
||||
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> |
@ -0,0 +1,220 @@ |
||||
<template> |
||||
<b-container fluid id="temperature"> |
||||
<b-row style="padding-top: 10px"> |
||||
<b-col> |
||||
<b-avatar |
||||
v-b-tooltip.hover :title="$t('sub_title')" |
||||
variant="info" :src="image_avatar" |
||||
size="10rem" style="margin-right: 5px" |
||||
> |
||||
</b-avatar> |
||||
</b-col> |
||||
</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"> |
||||
Emissivité : {{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"> |
||||
Coviiiiid |
||||
<font-awesome-icon icon="question" /> |
||||
|
||||
<b-spinner v-if="acquirementInprogress" type="border" label="chargement en cours..."/> |
||||
</b-button> |
||||
</b-col> |
||||
</b-row> |
||||
|
||||
</b-container> |
||||
</template> |
||||
|
||||
<script> |
||||
import axios from "axios"; |
||||
import TestChart from "./TestChart"; |
||||
import Vue from "vue"; |
||||
|
||||
Vue.use(TestChart); |
||||
|
||||
export default { |
||||
name: 'Temperature', |
||||
components: { |
||||
TestChart |
||||
}, |
||||
|
||||
props: { |
||||
msg: String |
||||
}, |
||||
data:function(){ |
||||
return { |
||||
datacollection: {}, |
||||
received : {}, |
||||
image: require('@/assets/coviiiiiid.jpg'), |
||||
acquirementInprogress:false, |
||||
result: null, |
||||
x:'', |
||||
options: { |
||||
responsive: true, |
||||
maintainAspectRatio: false, |
||||
}, |
||||
roles:[], |
||||
} |
||||
}, |
||||
computed: { |
||||
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 require('@/assets/coviiiiiid.jpg'); |
||||
} |
||||
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 require('@/assets/coviiiiiid.jpg'); |
||||
|
||||
|
||||
} |
||||
}, |
||||
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 () { |
||||
// Listen to score changes coming from SignalR events |
||||
this.$questionHub.$on('received-temperature', this.onChanged) |
||||
}, |
||||
mounted() { |
||||
this.fillData (); |
||||
|
||||
|
||||
}, |
||||
methods : { |
||||
fillData () { |
||||
this.datacollection = { |
||||
labels: [], |
||||
datasets: [ |
||||
{ |
||||
label: 'Température objet', |
||||
backgroundColor: '#f87979', |
||||
data: [] |
||||
}] |
||||
} |
||||
}, |
||||
|
||||
onChanged: function(msg) { |
||||
this.received = msg; |
||||
|
||||
let datacollection = { |
||||
labels: [], |
||||
datasets: [ |
||||
{ |
||||
label: 'Température objet', |
||||
backgroundColor: '#f87979', |
||||
data: [] |
||||
}] |
||||
} |
||||
|
||||
if(this.datacollection.labels.length > 30) |
||||
{ |
||||
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; |
||||
this.result = null; |
||||
let result = await axios.get(process.env.VUE_APP_BACK_URL + "/api/temperature"); |
||||
this.result = result.data; |
||||
} |
||||
finally { |
||||
this.acquirementInprogress = false; |
||||
} |
||||
} |
||||
}, |
||||
beforeDestroy () { |
||||
// Make sure to cleanup SignalR event handlers when removing the component |
||||
this.$questionHub.$off('received-temperature', this.onChanged) |
||||
} |
||||
} |
||||
</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> |
@ -0,0 +1,17 @@ |
||||
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) |
||||
} |
||||
} |
@ -0,0 +1,284 @@ |
||||
<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" 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="3" v-for="user in users" v-bind:key="user.id" |
||||
style="padding-right: 5px; padding-left: 5px; padding-top: 5px; padding-bottom: 5px"> |
||||
<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=" 'http://localhost/image/' + user.image" 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> |
||||
</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'; |
||||
|
||||
export default { |
||||
name: "ListeUser", |
||||
props:['value'], |
||||
components: { |
||||
InfiniteLoading, |
||||
}, |
||||
data:function(){ |
||||
return { |
||||
page: 1, |
||||
pageSize:4, |
||||
search:'', |
||||
infiniteId: + new Date(), |
||||
users: [ |
||||
], |
||||
isLoaded: false |
||||
} |
||||
}, |
||||
methods : |
||||
{ |
||||
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> |
@ -0,0 +1,325 @@ |
||||
<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="3" md="2"> |
||||
<b-row align-v="center"> |
||||
<b-col > |
||||
<img v-if="hasImage" loading="lazy" v-bind:src="img" style="width:128px;height:128px"/> |
||||
</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="9"> |
||||
<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 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> |
||||
<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> |
||||
</b-col> |
||||
<b-col> |
||||
<photo v-bind:snapshot.sync="photo"></photo> |
||||
</b-col> |
||||
<b-col> |
||||
<b-button @click="save" v-bind:disabled="!isValid"><font-awesome-icon icon="save" /> {{$t('save')}}</b-button> |
||||
</b-col> |
||||
<b-col> |
||||
<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: { |
||||
|
||||
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 = 'http://localhost/image/' + 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> |
@ -0,0 +1,38 @@ |
||||
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", |
||||
|
||||
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", |
||||
|
||||
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", |
||||
|
||||
} |
||||
} |
@ -0,0 +1,79 @@ |
||||
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 QuestionHub from './services/temperature-hub' |
||||
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(QuestionHub); |
||||
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 () { |
||||
window.console.log("main"); |
||||
sessionStorage.setItem("react-token", UserService.getToken()); |
||||
sessionStorage.setItem("react-refresh-token", UserService.getRefreshToken()); |
||||
}, UserService.doLogin); |
||||
reject(error); |
||||
}); |
||||
} |
||||
|
||||
|
||||
}) |
||||
}, |
||||
render: h => h(App), |
||||
}).$mount('#app') |
@ -0,0 +1,37 @@ |
||||
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: '/temperature', |
||||
name: 'Temperature', |
||||
component: Temperature |
||||
}, |
||||
{ |
||||
path: '/user/:id', |
||||
name: 'User', |
||||
component: User |
||||
}, |
||||
{ |
||||
path: '/users', |
||||
name: 'ListeUser', |
||||
component: ListeUser |
||||
}, |
||||
] |
||||
}) |
@ -0,0 +1,51 @@ |
||||
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) { |
||||
window.console.info("Philiiiippe!"); |
||||
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, |
||||
} |
@ -0,0 +1,20 @@ |
||||
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
|
||||
console.log(response); |
||||
return response; |
||||
}, (error) => { |
||||
console.log(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); |
||||
}); |
||||
} |
||||
}) |
||||
} |