Commit d95a0f77 authored by Jean Rabreau's avatar Jean Rabreau
Browse files

馃攢Merge branch 'feature/sr5' into develop

parents 97f02c71 5d64f84e
Pipeline #60185 passed with stages
in 5 minutes and 17 seconds
......@@ -30,3 +30,30 @@ export default {
},
}
</script>
<style lang="scss">
h1 {
font-weight: 400;
@media all and (max-width: 800px) {
font-size: 1.6rem;
line-height: 1.8rem;
letter-spacing: normal;
}
}
h2 {
font-weight: 400;
@media all and (max-width: 800px) {
font-size: 1.4rem;
line-height: 1.6rem;
letter-spacing: normal;
}
}
h3 {
font-weight: 400;
@media all and (max-width: 800px) {
font-size: 1.2rem;
line-height: 1.5rem;
letter-spacing: normal;
}
}
</style>
......@@ -119,9 +119,7 @@ export default {
},
methods: {
onLogOut() {
this.$store.dispatch('contrib/logOut').then(() => {
this.$router.push({name: 'logout'})
})
this.$store.dispatch('contrib/logOut')
},
},
}
......
......@@ -45,6 +45,7 @@
<script>
import {mapActions} from 'vuex'
import authority from '@/assets/authAxios'
export default {
name: "ProfileFormInternalRefresh",
......@@ -54,9 +55,17 @@ export default {
}
},
methods: {
...mapActions('contrib', ['refreshProfile']),
...mapActions('contrib', ['logOut']),
...mapActions('dialog', ['displayError']),
onRefresh() {
this.refreshProfile()
authority.patch('/users/profile/ldap-refresh/')
.then(() => {this.logOut(this.$route.fullPath)})
.catch(error => {
this.displayError({
message: this.$t('profile.update.wanted.failed'),
error: error
})
})
},
}
}
......
<template>
<iframe
id="frame"
ref="frame"
title="titre"
:data-url="file.url"
src="/3dhop.html"
>
</iframe>
<div id="hop__container" class="d-flex" @contextmenu.prevent="()=>{}">
<HopTools v-if="initialized" :presenter="presenter" :open.sync="toolAccess"/>
<transition name="slide">
<v-list-item
v-if="!toolAccess"
id="toolbar"
@click="toolAccess = !toolAccess"
dense
shaped
>
<v-icon>mdi-tools</v-icon><v-icon>mdi-chevron-right</v-icon>
</v-list-item>
</transition>
<div id="3dhop" class="tdhop" onmousedown="if (event.preventDefault) event.preventDefault()">
<div id="tdhlg" @click="followCredits">
Powered by 3DHOP<br/>CNR &nbsp;&ndash;&nbsp; ISTI
</div>
<canvas id="draw-canvas" :class="canvasClasses"/>
</div>
</div>
</template>
<script>
import SphereTrackball from '@/assets/3dhop/trackball_sphere'
import { Presenter } from '@/assets/3dhop/presenter'
import MobileMixin from '@/mixins/MobileMixin'
import HopTools from '@/components/renderer/file/model/HopTools'
export default {
name: "Hopla",
name: "Model",
mixins: [MobileMixin],
components: {HopTools},
props: {
file: Object
file: Object,
decimals: {
type: Number,
default: 3
}
},
data() {
return {
/**
* @type {string}
* One of 'grey', 'cyan', 'light', 'dark'
*/
bgClass: 'dark',
initialized: false,
presenter: {},
toolAccess: false,
}
},
computed: {
canvasClasses() {
return {
measuring: this.presenter._isMeasuringDistance
|| this.presenter._isMeasuringPickpoint,
[this.theme]: true
}
},
theme() {
return this.$vuetify.theme.dark ? 'dark' : 'light'
},
},
mounted() {
this.presenter = new Presenter("draw-canvas");
this.presenter.init3dhop();
this.setup3dhop()
},
// data() {
// return {
// fileUrl: // "https://s3.unistra.fr/pount-trials/items/gargo.nxz?AWSAccessKeyId=1K0YDMOZXSJYFGCJ28LL&Signature=ibNACVURrj7NG%2F0bLh06kk6EpWo%3D&Expires=1611827365"
// "https://s3.unistra.fr/pount-trials/items/gargo.ply?AWSAccessKeyId=1K0YDMOZXSJYFGCJ28LL&Signature=5or7Japh7QfqoJU8ejRrqoONmHA%3D&Expires=1614331804"
// // "models/gargo.nxz"
// }
// }
methods: {
followCredits() {
window.open('http://vcg.isti.cnr.it/3dhop/', '_blank')
},
setup3dhop() {
this.presenter.setScene({
meshes: {
"mesh_1" : { url: this.file.url }
},
modelInstances : {
"model_1" : {
mesh : "mesh_1",
}
},
trackball: {
type: SphereTrackball,
trackOptions : {
startDistance : 2.5,
minMaxDist: [0, 3.0]
}
}
})
this.initialized = true
},
}
}
</script>
<style lang="scss" scoped>
iframe {
min-height: 710px;
height: 100%;
width: 100%;
#hop__container {
min-height: 710px;
height: calc(100vh - 112px);
width: 100%;
position: relative;
}
.tdhop { position:relative; width:100%; height:100%; -webkit-user-select:none; -webkit-touch-callout:none; -khtml-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none; touch-action:none; -ms-touch-action:none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-tap-highlight-color: transparent; }
#tdhlg {
position:absolute;
width:105px;
height:13px;
right: 2px;
bottom: 2px;
overflow:hidden;
cursor:pointer;
color:#909090;
text-align:center;
text-decoration:none;
font-family:verdana;
font-style:italic;
font-size:10px;
line-height:13px;
-webkit-user-select:none;
-webkit-touch-callout:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
touch-action:none;
-ms-touch-action:none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-tap-highlight-color: transparent;
transition-property: height;
transition-duration: 2s;
&:hover {
height: 25px;
transition-duration: 200ms;
}
}
#toolbar {
position:absolute;
top:8px;
left: 0px;
-webkit-user-select:none;
-webkit-touch-callout:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
touch-action:none;
-ms-touch-action:none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-tap-highlight-color: transparent;
z-index: 1;
background: rgba(255,255,255,0.3);
&.theme--dark {
background: rgba(0,0,0,0.3);
}
}
//#toolbar img { margin-bottom:8px; width:50px; height:50px; opacity:0.5; cursor:pointer; -webkit-user-select:none; -webkit-touch-callout:none; -khtml-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none; touch-action:none; -ms-touch-action:none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-tap-highlight-color: transparent; }
#draw-canvas {
width:100%;
height:100%;
background-repeat:no-repeat;
background-position:center center;
-webkit-background-size:cover;
-moz-background-size:cover;
-o-background-size:cover;
background-size:cover;
outline:none;
-webkit-user-select:none;
-webkit-touch-callout:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
touch-action:none;
-ms-touch-action:none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-tap-highlight-color: transparent;
&.cyan {
background-image: radial-gradient(circle, #7FFDFC, #0C1A1A );
}
&.grey {
background-image: linear-gradient(#F2F2F2, #645B5C);
}
&.light {
background-image: url("/static/skins/backgrounds/light.jpg");
}
&.dark {
background-image: url("/static/skins/backgrounds/dark.jpg");
}
&.measuring {
cursor: crosshair;
}
}
.slide-enter-active {
animation: slide-in 1s;
}
.slide-leave-active {
animation: slide-out .3s;
}
@keyframes slide-out {
0% {
margin-left: 0px;
opacity: 1;
background: transparent;
}
70%{
opacity: 0.7;
}
100% {
margin-left: 56px;
opacity: 0;
}
}
@keyframes slide-in {
0% {
left: -56px;
}
100% {
left: 0px;
}
}
</style>
......@@ -535,6 +535,8 @@ export const en_US = {
failure: "Your profile has not been updated",
wanted: {
button: "Update my profile",
deco: "You will be disconnected",
failed: "Your request aborted",
next: "My profile will be updated on next connexion"
}
},
......
......@@ -550,6 +550,7 @@ export const fr_FR = {
wanted: {
button: "Mettre 脿 jour",
deco: "Vous allez 锚tre d茅connect茅",
failed: "Votre demande n'a pas pu aboutir",
next: "Vos informations seront mises 脿 jour 脿 la prochaine connexion, cette op茅ration n茅cessite de se reconnecter."
}
},
......
......@@ -2,6 +2,7 @@ import i18n from '@/plugins/vue-i18n'
import router from '@/router'
import authority from '@/assets/authAxios'
import { pick, cloneDeep } from 'lodash/fp'
import {setLocation} from '@/store/helpers'
/**
* @typedef {Object} Password
......@@ -241,21 +242,10 @@ const Contrib = {
dispatch('dialog/displayError', {message, error}, {root: true})
})
},
logOut({commit}){
logOut({commit}, path = ''){
authority.logOut()
commit('LOGIN', false)
},
refreshProfile({dispatch}) {
dispatch('updateProfile', {
settings: {
...this.settings,
refreshInfo: true
}
}).then(succeed => {
if (succeed) {
dispatch('logOut').then(() => document.location.reload())
}
})
setLocation(`${process.env.VUE_APP_AXIOS_BASE_URL}logout/?redirect=${appOrigin}${path}`)
},
/**
*
......
......@@ -71,10 +71,15 @@ const thumbnailDelete = (rootApi) => ({ commit, dispatch }, objectId) => {
{ root: true },
)
})
};
}
const setLocation = newUrl => {
window.location = newUrl
}
export {
getPaginatedResult,
setLocation,
thumbnailPost,
thumbnailDelete,
THUMBNAILS_UPDATE,
......
<template>
<v-container>
<v-row no-gutters>
<v-row class="pa-5" align="center" justify="center">
<crud-list-public
id="crud-list-public"
:items="crudListItems"
......@@ -12,44 +12,36 @@
:length="projectList.pageCount"
/>
</v-row>
<v-row no-gutters class="pa-5">
<v-row class="mb-5">
<h2>
<span class="primary--text text--darken-2">Chercheuses, Chercheurs, personnel</span> de l鈥橴niversit茅 de Strasbourg, <span class="primary--text">visualisez</span> et <span class="primary--text">d茅crivez</span>
vos donn茅es avec <span class="primary--text">POUNT</span>.
</h2>
<v-row class="pa-5">
<h1>
<span class="primary--text text--darken-2">Chercheuses, Chercheurs, personnel</span> de l鈥橴niversit茅 de Strasbourg, <span class="primary--text">visualisez</span> et <span class="primary--text">d茅crivez</span>
vos donn茅es avec <span class="primary--text">POUNT</span>.
<br/>
<router-link :to="{name: 'about'}" class="secondary--text">Pour plus d鈥檌nformations.</router-link>
</v-row>
<v-row class="mb-5 d-flex flex-column justify-md-space-between align-center flex-lg-row-reverse">
<v-col class="px-16">
<h3><span class="primary--text">D茅finissez</span> vous-m锚me
</h1>
<section>
<div class="preview">
<h2><span class="primary--text">Visualisez</span> vos mod猫les
3D, images, son, vid茅o鈥.
</h2>
<Hopla/>
</div>
<div class="preview">
<h2><span class="primary--text">D茅finissez</span> vous-m锚me
la finesse des
informations de
description de vos
donn茅es.
</h3>
</v-col>
<v-col>
</h2>
<usf-renderer
class="mt-2"
:fields="fields"
:messages="messages"
:is-submit-button-displayed="false"
/>
</v-col>
</v-row>
<v-row no-gutters class="d-flex flex-column justify-md-space-between flex-lg-row">
<v-col class="pa-16">
<h3><span class="primary--text">Visualisez</span> vos mod猫les
3D, images, son, vid茅o鈥.
</h3>
</v-col>
<v-col>
<Hopla/>
</v-col>
</v-row>
</div>
</section>
</v-row>
</v-container>
</template>
......@@ -374,3 +366,31 @@ export default {
},
};
</script>
<style lang="scss" scoped>
h1 {
margin: auto;
text-align: center;
line-height: 1;
a {
font-size: initial;
font-weight: initial;
}
}
section {
display: grid;
grid-template-columns: 3fr 2fr;
gap: 2rem;
div.preview {
h2 {
padding: 2rem 1rem;
text-align: center;
}
}
@media all and (max-width: 1000px) {
grid-template-columns: unset;
grid-template-rows: 1fr 1fr;
}
}
</style>
......@@ -45,11 +45,6 @@ describe('ProfileMenu', () => {
expect(dispatchStub.calledOnce).to.be.true
expect(dispatchStub.getCall(0).args[0]).to.equal('contrib/logOut')
})
it('should route to log out page', async () => {
await wrapper.vm.onLogOut()
expect(routerStub.calledOnce).to.be.true
expect(routerStub.getCall(0).args[0]).to.eql({name: 'logout'})
})
})
})
})
......@@ -3,6 +3,7 @@ import sinon from 'sinon'
import {cloneDeep} from 'lodash/fp'
import store from '@/store'
import {userInfoInit, userProfileInit} from '@/store/contrib'
import * as helpers from '@/store/helpers'
import i18n from '@/plugins/vue-i18n'
import authority from '@/assets/authAxios'
......@@ -301,21 +302,45 @@ describe('store/contrib', () => {
})
})
describe('logOut', () => {
let logOutStub
const logoutUrl = `${process.env.VUE_APP_AXIOS_BASE_URL}logout/`
const redirectParam = `redirect=${window.location.origin}`
let logOutStub, locationStub
beforeEach(() => {
logOutStub = sinon.stub(authority, 'logOut')
locationStub = sinon.stub(helpers, 'setLocation')
})
afterEach(() => {
logOutStub.restore()
locationStub.restore()
})
it('should call authority logIn method', async () => {
store.dispatch('contrib/logOut')
it('should call authority logOut method', async () => {
await store.dispatch('contrib/logOut')
expect(logOutStub.calledOnce).to.be.true
})
it('should log user out', async () => {
store.dispatch('contrib/logOut')
await store.dispatch('contrib/logOut')
expect(store.state.contrib.isLogged).to.be.false
})
describe('redirection', () => {
beforeEach(async () => {
await store.dispatch('contrib/logOut')
})
it('should set window location to logout api', async () => {
expect(locationStub.calledOnce, 'location changed').to.be.true
expect(locationStub.firstCall.args[0])
.to.match(new RegExp(`^${logoutUrl}`))
})
it('should set a redirection url', () => {
expect(locationStub.firstCall.args[0])
.to.match(new RegExp(`${redirectParam}$`))
})
})
it('should redirect to a given path', async () => {
const desiredPath = '/my/custom/path'
await store.dispatch('contrib/logOut', desiredPath)
expect(locationStub.firstCall.args[0])
.to.match(new RegExp(`${redirectParam}${desiredPath}$`))
})
})
describe('updateProfile', () => {
it('should should call user detail api', async () => {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment