Changeset View
Changeset View
Standalone View
Standalone View
src/resources/vue/Signup.vue
Show All 14 Lines | <div class="container"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="card d-none" id="step1" v-if="!invitation"> | <div class="card d-none" id="step1" v-if="!invitation"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<h4 class="card-title">{{ $t('signup.title') }} - {{ $t('nav.step', { i: 1, n: 3 }) }}</h4> | <h4 class="card-title">{{ $t('signup.title') }} - {{ $t('nav.step', { i: 1, n: steps }) }}</h4> | ||||
<p class="card-text"> | <p class="card-text"> | ||||
{{ $t('signup.step1') }} | {{ $t('signup.step1') }} | ||||
</p> | </p> | ||||
<form @submit.prevent="submitStep1" data-validation-prefix="signup_"> | <form @submit.prevent="submitStep1" data-validation-prefix="signup_"> | ||||
<div class="mb-3"> | <div class="mb-3"> | ||||
<div class="input-group"> | <div class="input-group"> | ||||
<input type="text" class="form-control" id="signup_first_name" :placeholder="$t('form.firstname')" autofocus v-model="first_name"> | <input type="text" class="form-control" id="signup_first_name" :placeholder="$t('form.firstname')" autofocus v-model="first_name"> | ||||
<input type="text" class="form-control rounded-end" id="signup_last_name" :placeholder="$t('form.surname')" v-model="last_name"> | <input type="text" class="form-control rounded-end" id="signup_last_name" :placeholder="$t('form.surname')" v-model="last_name"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="mb-3"> | <div v-if="mode == 'token'" class="mb-3"> | ||||
<label for="signup_token" class="visually-hidden">{{ $t('signup.token') }}</label> | |||||
<input type="text" class="form-control" id="signup_token" :placeholder="$t('signup.token')" required v-model="token"> | |||||
</div> | |||||
<div v-else class="mb-3"> | |||||
<label for="signup_email" class="visually-hidden">{{ $t('signup.email') }}</label> | <label for="signup_email" class="visually-hidden">{{ $t('signup.email') }}</label> | ||||
<input type="text" class="form-control" id="signup_email" :placeholder="$t('signup.email')" required v-model="email"> | <input type="text" class="form-control" id="signup_email" :placeholder="$t('signup.email')" required v-model="email"> | ||||
</div> | </div> | ||||
<btn class="btn-secondary" @click="stepBack">{{ $t('btn.back') }}</btn> | <btn class="btn-secondary" @click="stepBack">{{ $t('btn.back') }}</btn> | ||||
<btn class="btn-primary ms-2" type="submit" icon="check">{{ $t('btn.continue') }}</btn> | <btn class="btn-primary ms-2" type="submit" icon="check">{{ $t('btn.continue') }}</btn> | ||||
</form> | </form> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="card d-none" id="step2" v-if="!invitation"> | <div class="card d-none" id="step2" v-if="!invitation"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<h4 class="card-title">{{ $t('signup.title') }} - {{ $t('nav.step', { i: 2, n: 3 }) }}</h4> | <h4 class="card-title">{{ $t('signup.title') }} - {{ $t('nav.step', { i: 2, n: steps }) }}</h4> | ||||
<p class="card-text"> | <p class="card-text"> | ||||
{{ $t('signup.step2') }} | {{ $t('signup.step2') }} | ||||
</p> | </p> | ||||
<form @submit.prevent="submitStep2" data-validation-prefix="signup_"> | <form @submit.prevent="submitStep2" data-validation-prefix="signup_"> | ||||
<div class="mb-3"> | <div class="mb-3"> | ||||
<label for="signup_short_code" class="visually-hidden">{{ $t('form.code') }}</label> | <label for="signup_short_code" class="visually-hidden">{{ $t('form.code') }}</label> | ||||
<input type="text" class="form-control" id="signup_short_code" :placeholder="$t('form.code')" required v-model="short_code"> | <input type="text" class="form-control" id="signup_short_code" :placeholder="$t('form.code')" required v-model="short_code"> | ||||
</div> | </div> | ||||
<btn class="btn-secondary" @click="stepBack">{{ $t('btn.back') }}</btn> | <btn class="btn-secondary" @click="stepBack">{{ $t('btn.back') }}</btn> | ||||
<btn class="btn-primary ms-2" type="submit" icon="check">{{ $t('btn.continue') }}</btn> | <btn class="btn-primary ms-2" type="submit" icon="check">{{ $t('btn.continue') }}</btn> | ||||
<input type="hidden" id="signup_code" v-model="code" /> | <input type="hidden" id="signup_code" v-model="code" /> | ||||
</form> | </form> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="card d-none" id="step3"> | <div class="card d-none" id="step3"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<h4 v-if="!invitation" class="card-title">{{ $t('signup.title') }} - {{ $t('nav.step', { i: 3, n: 3 }) }}</h4> | <h4 v-if="!invitation" class="card-title">{{ $t('signup.title') }} - {{ $t('nav.step', { i: steps, n: steps }) }}</h4> | ||||
<p class="card-text"> | <p class="card-text"> | ||||
{{ $t('signup.step3') }} | {{ $t('signup.step3') }} | ||||
</p> | </p> | ||||
<form @submit.prevent="submitStep3" data-validation-prefix="signup_"> | <form @submit.prevent="submitStep3" data-validation-prefix="signup_"> | ||||
<div class="mb-3" v-if="invitation"> | <div class="mb-3" v-if="invitation"> | ||||
<div class="input-group"> | <div class="input-group"> | ||||
<input type="text" class="form-control" id="signup_first_name" :placeholder="$t('form.firstname')" autofocus v-model="first_name"> | <input type="text" class="form-control" id="signup_first_name" :placeholder="$t('form.firstname')" autofocus v-model="first_name"> | ||||
<input type="text" class="form-control rounded-end" id="signup_last_name" :placeholder="$t('form.surname')" v-model="last_name"> | <input type="text" class="form-control rounded-end" id="signup_last_name" :placeholder="$t('form.surname')" v-model="last_name"> | ||||
Show All 27 Lines | |||||
</template> | </template> | ||||
<script> | <script> | ||||
import PasswordInput from './Widgets/PasswordInput' | import PasswordInput from './Widgets/PasswordInput' | ||||
import { library } from '@fortawesome/fontawesome-svg-core' | import { library } from '@fortawesome/fontawesome-svg-core' | ||||
library.add( | library.add( | ||||
require('@fortawesome/free-solid-svg-icons/faUsers').definition, | require('@fortawesome/free-solid-svg-icons/faMobileRetro').definition, | ||||
require('@fortawesome/free-solid-svg-icons/faUsers').definition | |||||
) | ) | ||||
export default { | export default { | ||||
components: { | components: { | ||||
PasswordInput | PasswordInput | ||||
}, | }, | ||||
data() { | data() { | ||||
return { | return { | ||||
email: '', | email: '', | ||||
first_name: '', | first_name: '', | ||||
last_name: '', | last_name: '', | ||||
code: '', | code: '', | ||||
short_code: '', | short_code: '', | ||||
login: '', | login: '', | ||||
pass: {}, | pass: {}, | ||||
domain: '', | domain: '', | ||||
domains: [], | domains: [], | ||||
invitation: null, | invitation: null, | ||||
is_domain: false, | is_domain: false, | ||||
mode: 'email', | |||||
plan: null, | plan: null, | ||||
plan_icons: { | plan_icons: { | ||||
individual: 'user', | individual: 'user', | ||||
group: 'users' | group: 'users', | ||||
phone: 'mobile-retro' | |||||
}, | }, | ||||
plans: [], | plans: [], | ||||
token: '', | |||||
voucher: '' | voucher: '' | ||||
} | } | ||||
}, | }, | ||||
computed: { | |||||
steps() { | |||||
return this.mode == 'token' ? 2 : 3 | |||||
} | |||||
}, | |||||
mounted() { | mounted() { | ||||
let param = this.$route.params.param; | let param = this.$route.params.param; | ||||
if (this.$route.name == 'signup-invite') { | if (this.$route.name == 'signup-invite') { | ||||
axios.get('/api/auth/signup/invitations/' + param, { loader: true }) | axios.get('/api/auth/signup/invitations/' + param, { loader: true }) | ||||
.then(response => { | .then(response => { | ||||
this.invitation = response.data | this.invitation = response.data | ||||
this.login = response.data.login | this.login = response.data.login | ||||
Show All 15 Lines | export default { | ||||
this.displayForm(0) | this.displayForm(0) | ||||
} else if (/^([A-Z0-9]+)-([a-zA-Z0-9]+)$/.test(param)) { | } else if (/^([A-Z0-9]+)-([a-zA-Z0-9]+)$/.test(param)) { | ||||
// Verification code provided, auto-submit Step 2 | // Verification code provided, auto-submit Step 2 | ||||
this.short_code = RegExp.$1 | this.short_code = RegExp.$1 | ||||
this.code = RegExp.$2 | this.code = RegExp.$2 | ||||
this.submitStep2(true) | this.submitStep2(true) | ||||
} else if (/^([a-zA-Z_]+)$/.test(param)) { | } else if (/^([a-zA-Z_]+)$/.test(param)) { | ||||
// Plan title provided, save it and display Step 1 | // Plan title provided, save it and display Step 1 | ||||
this.plan = param | this.step0(param) | ||||
this.displayForm(1, true) | |||||
} else { | } else { | ||||
this.$root.errorPage(404) | this.$root.errorPage(404) | ||||
} | } | ||||
} else { | } else { | ||||
this.displayForm(0) | this.displayForm(0) | ||||
} | } | ||||
}, | }, | ||||
methods: { | methods: { | ||||
selectPlan(plan) { | selectPlan(plan) { | ||||
this.$router.push({path: '/signup/' + plan}) | this.$router.push({path: '/signup/' + plan}) | ||||
this.plan = plan | this.selectPlanByTitle(plan) | ||||
this.displayForm(1, true) | |||||
}, | }, | ||||
// Composes plan selection page | // Composes plan selection page | ||||
step0() { | selectPlanByTitle(title) { | ||||
const plan = this.plans.filter(plan => plan.title == title)[0] | |||||
if (plan) { | |||||
this.plan = title | |||||
this.mode = plan.mode | |||||
this.displayForm(1, true) | |||||
} | |||||
}, | |||||
step0(plan) { | |||||
if (!this.plans.length) { | if (!this.plans.length) { | ||||
axios.get('/api/auth/signup/plans', { loader: true }).then(response => { | axios.get('/api/auth/signup/plans', { loader: true }).then(response => { | ||||
this.plans = response.data.plans | this.plans = response.data.plans | ||||
this.selectPlanByTitle(plan) | |||||
}) | }) | ||||
.catch(error => { | .catch(error => { | ||||
this.$root.errorHandler(error) | this.$root.errorHandler(error) | ||||
}) | }) | ||||
} else { | |||||
this.selectPlanByTitle(plan) | |||||
} | } | ||||
}, | }, | ||||
// Submits data to the API, validates and gets verification code | // Submits data to the API, validates and gets verification code | ||||
submitStep1() { | submitStep1() { | ||||
this.$root.clearFormValidation($('#step1 form')) | this.$root.clearFormValidation($('#step1 form')) | ||||
const post = this.$root.pick(this, ['email', 'last_name', 'first_name', 'plan', 'voucher']) | const post = this.$root.pick(this, ['email', 'last_name', 'first_name', 'plan', 'token', 'voucher']) | ||||
axios.post('/api/auth/signup/init', post) | axios.post('/api/auth/signup/init', post) | ||||
.then(response => { | .then(response => { | ||||
this.displayForm(2, true) | |||||
this.code = response.data.code | this.code = response.data.code | ||||
this.short_code = response.data.short_code | |||||
this.mode = response.data.mode | |||||
this.is_domain = response.data.is_domain | |||||
this.displayForm(this.mode == 'token' ? 3 : 2, true) | |||||
// Fill the domain selector with available domains | |||||
if (!this.is_domain) { | |||||
this.setDomain(response.data) | |||||
} | |||||
}) | }) | ||||
}, | }, | ||||
// Submits the code to the API for verification | // Submits the code to the API for verification | ||||
submitStep2(bylink) { | submitStep2(bylink) { | ||||
if (bylink === true) { | if (bylink === true) { | ||||
this.displayForm(2, false) | this.displayForm(2, false) | ||||
} | } | ||||
this.$root.clearFormValidation($('#step2 form')) | this.$root.clearFormValidation($('#step2 form')) | ||||
const post = this.$root.pick(this, ['code', 'short_code']) | const post = this.$root.pick(this, ['code', 'short_code']) | ||||
axios.post('/api/auth/signup/verify', post) | axios.post('/api/auth/signup/verify', post) | ||||
.then(response => { | .then(response => { | ||||
this.displayForm(3, true) | this.displayForm(3, true) | ||||
// Reset user name/email/plan, we don't have them if user used a verification link | // Reset user name/email/plan, we don't have them if user used a verification link | ||||
this.first_name = response.data.first_name | this.first_name = response.data.first_name | ||||
this.last_name = response.data.last_name | this.last_name = response.data.last_name | ||||
this.email = response.data.email | this.email = response.data.email | ||||
this.is_domain = response.data.is_domain | this.is_domain = response.data.is_domain | ||||
this.voucher = response.data.voucher | this.voucher = response.data.voucher | ||||
this.domain = '' | |||||
// Fill the domain selector with available domains | // Fill the domain selector with available domains | ||||
if (!this.is_domain) { | if (!this.is_domain) { | ||||
this.setDomain(response.data) | this.setDomain(response.data) | ||||
} | } | ||||
}) | }) | ||||
.catch(error => { | .catch(error => { | ||||
if (bylink === true) { | if (bylink === true) { | ||||
Show All 24 Lines | export default { | ||||
axios.post('/api/auth/signup', post).then(response => { | axios.post('/api/auth/signup', post).then(response => { | ||||
// auto-login and goto dashboard | // auto-login and goto dashboard | ||||
this.$root.loginUser(response.data) | this.$root.loginUser(response.data) | ||||
}) | }) | ||||
}, | }, | ||||
// Moves the user a step back in registration form | // Moves the user a step back in registration form | ||||
stepBack(e) { | stepBack(e) { | ||||
var card = $(e.target).closest('.card') | const card = $(e.target).closest('.card') | ||||
let step = card.attr('id').replace('step', '') | |||||
card.prev().removeClass('d-none').find('input').first().focus() | |||||
card.addClass('d-none').find('form')[0].reset() | card.addClass('d-none').find('form')[0].reset() | ||||
if (card.attr('id') == 'step1') { | step -= 1 | ||||
if (step == 2 && this.mode == 'token') { | |||||
step = 1 | |||||
} | |||||
$('#step' + step).removeClass('d-none').find('input').first().focus() | |||||
if (!step) { | |||||
this.step0() | this.step0() | ||||
this.$router.replace({path: '/signup'}) | this.$router.replace({path: '/signup'}) | ||||
} | } | ||||
}, | }, | ||||
displayForm(step, focus) { | displayForm(step, focus) { | ||||
[0, 1, 2, 3].filter(value => value != step).forEach(value => { | [0, 1, 2, 3].filter(value => value != step).forEach(value => { | ||||
$('#step' + value).addClass('d-none') | $('#step' + value).addClass('d-none') | ||||
}) | }) | ||||
if (!step) { | if (!step) { | ||||
return this.step0() | return this.step0() | ||||
} | } | ||||
$('#step' + step).removeClass('d-none') | $('#step' + step).removeClass('d-none').find('form')[0].reset() | ||||
if (focus) { | if (focus) { | ||||
$('#step' + step).find('input').first().focus() | $('#step' + step).find('input').first().focus() | ||||
} | } | ||||
}, | }, | ||||
setDomain(response) { | setDomain(response) { | ||||
if (response.domains) { | if (response.domains) { | ||||
this.domains = response.domains | this.domains = response.domains | ||||
} | } | ||||
this.domain = response.domain || window.config['app.domain'] | this.domain = response.domain || window.config['app.domain'] | ||||
} | } | ||||
} | } | ||||
} | } | ||||
</script> | </script> |