diff --git a/src/assets/resources/semantic-ui-2.4.2/semantic.min.css b/src/assets/resources/semantic-ui-2.4.2/semantic.min.css index 9b65ec01786f777114e4a3e90901b19738630a56..a9922b28f713187e679568a345d4295d764c9fcd 100644 --- a/src/assets/resources/semantic-ui-2.4.2/semantic.min.css +++ b/src/assets/resources/semantic-ui-2.4.2/semantic.min.css @@ -20033,10 +20033,10 @@ ol.ui.list li[value]:before { padding: 1em 1.5em; line-height: 1.4285em; color: #252525; - -webkit-transition: opacity .5s ease, color .5s ease, background .5s ease, -webkit-box-shadow .5s ease; - transition: opacity .5s ease, color .5s ease, background .5s ease, -webkit-box-shadow .5s ease; - transition: opacity .5s ease, color .5s ease, background .5s ease, box-shadow .5s ease; - transition: opacity .5s ease, color .5s ease, background .5s ease, box-shadow .5s ease, -webkit-box-shadow .5s ease; + -webkit-transition: padding .5s ease, max-height .5s ease, opacity .5s ease, color .5s ease, background .5s ease, -webkit-box-shadow .5s ease; + transition: padding .5s ease, max-height .5s ease, opacity .5s ease, color .5s ease, background .5s ease, -webkit-box-shadow .5s ease; + transition: padding .5s ease, max-height .5s ease, opacity .5s ease, color .5s ease, background .5s ease, box-shadow .5s ease; + transition: padding .5s ease, max-height .5s ease, opacity .5s ease, color .5s ease, background .5s ease, box-shadow .5s ease, -webkit-box-shadow .5s ease; border-radius: .07142857rem; -webkit-box-shadow: 0 0 0 1px rgba(34, 36, 38, .22) inset, 0 0 0 0 transparent; box-shadow: 0 0 0 1px rgba(34, 36, 38, .22) inset, 0 0 0 0 transparent diff --git a/src/store/index.js b/src/store/index.js index 0f35dd98b56e2153a54b90714b37104435035003..773883a447ee36b3b1b0fbe874825ca597a9c79c 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -149,26 +149,16 @@ export default new Vuex.Store({ }, SIGNUP({ commit }, payload) { - if (payload.first_name && payload.last_name && payload.username && - payload.email && payload.password && payload.siret) { - console.log('payload', payload); + if (payload.first_name && payload.last_name && payload.username && payload.email && payload.password) { return axios - .post('https://fenigs.neogeo.fr/fr/login/signup/', { - first_name: payload.first_name, - last_name: payload.last_name, - username: payload.username, - email: payload.email, - password: payload.password, - comments: payload.siret, - }) + .post('https://fenigs.neogeo.fr/fr/login/signup/', payload) .then((response) => { - console.log('response', response); if (response.status === 201 && response.data) { console.log('response.data', response.data); } }) .catch((err) => { - console.error(err) + console.error(err); commit('SET_USER', false); return 'error'; }); diff --git a/src/views/Login.vue b/src/views/Login.vue index bc5d2aa97228cd8a8d2c270670429c70a549a98f..aa37555c71a3963a22799d852fc2c243a7fc36b8 100644 --- a/src/views/Login.vue +++ b/src/views/Login.vue @@ -26,10 +26,7 @@ CONNEXION </h3> - <div - v-if="form.errors" - class="ui warning message" - > + <div :class="['ui warning message', {'closed': !errors.global}]"> <div class="header"> Les informations d'identification sont incorrectes. </div> @@ -43,28 +40,28 @@ @submit.prevent="login" > <div class="ui secondary segment"> - <div class="six field required"> + <div class="six field"> <div class="ui left icon input"> <i class="user icon" aria-hidden="true" /> <input - v-model="form.username" + v-model="loginForm.username" type="text" name="username" placeholder="Utilisateur" > </div> </div> - <div class="six field required"> + <div class="six field"> <div class="ui left icon input"> <i class="lock icon" aria-hidden="true" /> <input - v-model="form.password" + v-model="loginForm.password" type="password" name="password" placeholder="Mot de passe" @@ -88,14 +85,8 @@ INSCRIPTION </h3> - <div - v-if="form.errors" - class="ui warning message" - > - <div class="header"> - Un compte associé à cette adresse courriel existe déjà . - </div> - Veuillez utiliser une adresse email différente ou vous connecter avec le compte associé à cette adresse courriel. + <div :class="['ui warning message', {'closed': !error}]"> + {{ error }} </div> <form @@ -105,60 +96,62 @@ @submit.prevent="signup" > <div class="ui secondary segment"> - - <div class="six field required"> + <div class="six field"> <div class="ui left icon input"> <i class="user outline icon" aria-hidden="true" /> <input - v-model="form.first_name" + v-model="signupForm.first_name" type="text" name="first_name" placeholder="Prénom" + required > </div> </div> - <div class="six field required"> + <div class="six field"> <div class="ui left icon input"> <i class="id card icon" aria-hidden="true" /> <input - v-model="form.last_name" + v-model="signupForm.last_name" type="text" name="last_name" placeholder="Nom" + required > </div> </div> - <div class="six field required"> + <div class="six field"> <div class="ui left icon input"> <i class="envelope icon" aria-hidden="true" /> <input - v-model="form.email" + v-model="signupForm.email" type="email" name="email" placeholder="Adresse courriel" + required > </div> </div> - <div class="six field required"> + <div class="six field"> <div class="ui left icon input"> <i class="user icon" aria-hidden="true" /> <input - v-model="form.username" + v-model="signupForm.username" type="text" name="username" placeholder="Utilisateur" @@ -167,37 +160,50 @@ </div> </div> - <div class="six field required"> - <div class="ui left icon input"> + <div :class="['six field', {'error': errors.passwd}]"> + <div class="ui action left icon input"> <i class="lock icon" aria-hidden="true" /> <input - v-model="form.password" - type="password" + v-model="signupForm.password" + :type="showPwd ? 'text' : 'password'" name="password" placeholder="Mot de passe" + required + @blur="checkPwd" + > + <button + class="ui icon button" + @click="showPwd = !showPwd" > + <i :class="[showPwd ? 'eye slash' : 'eye', 'icon']" /> + </button> </div> </div> - <div class="six field required"> - <div class="ui labeled left icon input"> - <label for="amount" class="ui label">SIRET</label> + <div :class="['six field', {'error': errors.comments}]"> + <div class="ui left icon input"> + <i + class="pencil icon" + aria-hidden="true" + /> <input - v-model="form.siret" - type="number" - name="siret" + v-model="signupForm.comments" + type="text" + name="comments" + :placeholder="commentsFieldLabel || `Commentaires (optionnel)`" + :required="commentsFieldRequired" > </div> </div> - - <div class="six field required"> + <div class="ui divider" /> + <div class="six field"> <Multiselect - v-if="usersGroupsOptions" - v-model="form.usersgroups" - :options="usersGroupsOptions || []" + v-if="usersGroupsOptions.length > 0" + v-model="signupForm.usersgroups" + :options="usersGroupsOptions" :multiple="true" track-by="value" label="name" @@ -206,21 +212,15 @@ deselect-label="" :searchable="false" :placeholder="'Sélectionez un ou plusieurs groupe de la liste ...'" - /> - </div> - <!-- - :options-limit="10" - :reset-after="false" - :loading="loadingPrerecordedListValues" - :show-no-results="true" - :clear-on-select="false" - :preserve-search="false" - @search-change="search" - @select="selectPrerecordedValue" - --> + /> + </div> + <p v-if="adminMail"> + Si le groupe d'utilisateurs recherché n'apparaît pas, vous pouvez demander à un + <a :href="'mailto:'+adminMail">administrateur</a> de le créer + </p> <button - class="ui fluid large teal submit button" + :class="['ui fluid large teal submit button', {'disabled': !allFilled || error}]" type="submit" > Valider @@ -246,17 +246,26 @@ export default { data() { return { logged: false, - form: { - errors: null, + loginForm: { + username: null, + password: null, + }, + signupForm: { + username: null, + password: null, first_name: null, last_name: null, - username: null, email: null, - password: null, - password2: null, - siret: null, + comments: null, usersgroups: null, }, + errors: { + global: null, + passwd: null, + comments: null, + }, + showPwd: false, + allFilled: false, }; }, @@ -265,19 +274,41 @@ export default { appLogo: state => state.configuration.VUE_APP_LOGO_PATH, appName: state => state.configuration.VUE_APP_APPLICATION_NAME, appAbstract: state => state.configuration.VUE_APP_APPLICATION_ABSTRACT, + adminMail: state => state.configuration.VUE_APP_ADMIN_MAIL, + commentsFieldLabel: state => state.configuration.VUE_APP_SIGNUP_COMMENTS_FIELD_LABEL, + commentsFieldRequired: state => state.configuration.VUE_APP_SIGNUP_COMMENTS_FIELD_REQUIRED, }), ...mapGetters(['usersGroupsOptions']), + + error() { + return this.errors.global || this.errors.passwd || this.errors.comments; + } }, watch: { - 'form.first_name': function(newValue, oldValue) { - if (newValue && newValue !== oldValue && this.form.last_name) { - this.form.username = `${newValue.charAt(0)}${this.form.last_name}`.toLowerCase(); + 'signupForm.first_name': function (newValue, oldValue) { + if (newValue !== oldValue) { + this.signupForm.username = `${newValue.charAt(0)}${this.signupForm.last_name}`.toLowerCase(); + } + }, + 'signupForm.last_name': function (newValue, oldValue) { + if (newValue !== oldValue) { + this.signupForm.username = `${this.signupForm.first_name.charAt(0)}${newValue}`.toLowerCase(); + } + }, + 'signupForm.password': function (newValue, oldValue) { + if (newValue.length >= 8) { + if (newValue !== oldValue) { + this.checkPwd(); + } + } else { + this.errors.passwd = null; } }, - 'form.last_name': function(newValue, oldValue) { - if (newValue && newValue !== oldValue && this.form.first_name) { - this.form.username = `${this.form.first_name.charAt(0)}${newValue}`.toLowerCase(); + signupForm: { + deep: true, + handler() { + this.allFilled = this.checkRequiredFields(); } } }, @@ -289,7 +320,7 @@ export default { }, mounted() { - if (this.$store.state.user) { + if (this.$route.name === 'login' && this.$store.state.user) { this.$store.commit( 'DISPLAY_MESSAGE', { comment: 'Vous êtes déjà connecté, vous allez être redirigé vers la page précédente.' } @@ -297,46 +328,63 @@ export default { setTimeout(() => this.$store.dispatch('REDIRECT_AFTER_LOGIN'), 3100); } }, - + methods: { login() { this.$store .dispatch('LOGIN', { - username: this.form.username, - password: this.form.password, + username: this.loginForm.username, + password: this.loginForm.password, }) .then((status) => { if (status === 200) { - this.form.errors = null; + this.errors.global = null; } else if (status === 'error') { - this.form.errors = status; + this.errors.global = status; } }) .catch(); }, + signup() { - this.form.errors = null; + this.errors.global = null; this.$store .dispatch('SIGNUP', { - first_name: this.form.first_name, - last_name: this.form.last_name, - username: this.form.username, - email: this.form.email, - password: this.form.password, - siret: this.form.siret, + first_name: this.signupForm.first_name, + last_name: this.signupForm.last_name, + username: this.signupForm.username, + email: this.signupForm.email, + password: this.signupForm.password, + comments: this.signupForm.comments, }) .then((status) => { if (status === 200) { - this.form.errors = null; + this.errors.global = null; } else if (status === 'error') { - this.form.errors = status; + this.errors.global = status; } }) .catch(); }, - checkPwdCreation() { - if (this.form.password !== this.form.password2) { - this.form.errors = 'Les mots de passe doivent être identique' + + checkPwd() { + const regPwd = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[A-Za-z\d/$&+,:;=?#|'<>.^*()%!-]{8,}$/; + if (!regPwd.test(this.signupForm.password)) { + this.errors.passwd = `Le mot de passe doit comporter au moins 8 caractères, dont 1 majuscule, 1 minuscule et 1 chiffre. + Vous pouvez utiliser les caractères spéciaux suivants : /$ & + , : ; = ? # | ' < > . ^ * ( ) % ! -.`; + return false; + } + this.errors.passwd = null; + return true; + }, + + checkRequiredFields() { + if (this.signupForm.first_name && this.signupForm.last_name && this.signupForm.email + && this.signupForm.password && this.signupForm.password.length > 8) { + if (this.commentsFieldRequired && !this.signupForm.comments) { + return false; + } + return true; } } }, @@ -348,6 +396,24 @@ export default { max-width: 500px; min-width: 200px; margin: 3em auto; + + .ui.message { + min-height: 0px; + + &.closed { + overflow: hidden; + opacity: 0; + padding: 0; + max-height: 0px; + } + } + + input[required] { + background-image: linear-gradient(45deg, transparent, transparent 50%, rgb(209, 0, 0) 50%, rgb(209, 0, 0) 100%); + background-position: top right; + background-size: .5em .5em; + background-repeat: no-repeat; + } } </style> @@ -364,18 +430,23 @@ export default { } /* keep font-weight from overide of semantic classes */ -.multiselect__placeholder, .multiselect__content, .multiselect__tags { +.multiselect__placeholder, +.multiselect__content, +.multiselect__tags { font-weight: initial !important; } + /* keep placeholder eigth */ .multiselect .multiselect__placeholder { margin-bottom: 9px !important; padding-top: 1px; } + /* keep placeholder height when opening dropdown without selection */ input.multiselect__input { padding: 3px 0 0 0 !important; } + /* keep placeholder height when opening dropdown with already a value selected */ .multiselect__tags .multiselect__single { padding: 1px 0 0 0 !important;