diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/registration/registration.js | 70 | ||||
| -rw-r--r-- | src/components/registration/registration.vue | 79 | ||||
| -rw-r--r-- | src/modules/users.js | 44 | ||||
| -rw-r--r-- | src/mutation_types.js | 7 |
4 files changed, 142 insertions, 58 deletions
diff --git a/src/components/registration/registration.js b/src/components/registration/registration.js index 7e8b1848..ba3561a0 100644 --- a/src/components/registration/registration.js +++ b/src/components/registration/registration.js @@ -1,12 +1,27 @@ -import oauthApi from '../../services/new_api/oauth.js' -import { humanizeErrors } from '../../modules/errors' +import { validationMixin } from 'vuelidate' +import { required } from 'vuelidate/lib/validators' +import { mapActions, mapState } from 'vuex' +import { SIGN_UP } from "../../mutation_types" const registration = { + mixins: [validationMixin], data: () => ({ - user: {}, - errors: [], - registering: false + user: { + email: '', + username: '', + password: '', + confirm: '' + }, + clientValidationFailed: false }), + validations: { + user: { + email: { required }, + username: { required }, + password: { required }, + confirm: { required } + } + }, created () { if ((!this.$store.state.instance.registrationOpen && !this.token) || !!this.$store.state.users.currentUser) { this.$router.push('/main/all') @@ -17,43 +32,24 @@ const registration = { } }, computed: { - termsofservice () { return this.$store.state.instance.tos }, - token () { return this.$route.params.token } + token () { return this.$route.params.token }, + ...mapState({ + isPending: (state) => state.users[SIGN_UP.isPending], + serverValidationErrors: (state) => state.users[SIGN_UP.errors], + termsofservice: 'instance.tos', + }) }, methods: { + ...mapActions(['signUp']), submit () { - this.registering = true this.user.nickname = this.user.username this.user.token = this.token - this.$store.state.api.backendInteractor.register(this.user).then( - (response) => { - if (response.ok) { - const data = { - oauth: this.$store.state.oauth, - instance: this.$store.state.instance.server - } - oauthApi.getOrCreateApp(data).then((app) => { - oauthApi.getTokenWithCredentials( - { - app, - instance: data.instance, - username: this.user.username, - password: this.user.password - }) - .then((result) => { - this.$store.commit('setToken', result.access_token) - this.$store.dispatch('loginUser', result.access_token) - this.$router.push('/main/friends') - }) - }) - } else { - this.registering = false - response.json().then((data) => { - this.errors = humanizeErrors(JSON.parse(data.error)) - }) - } - }, - ) + + this.$v.$touch() + + if (!this.$v.$invalid) { + this.signUp(this.user) + } } } } diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue index 867e26f0..73200990 100644 --- a/src/components/registration/registration.vue +++ b/src/components/registration/registration.vue @@ -7,29 +7,46 @@ <form v-on:submit.prevent='submit(user)' class='registration-form'> <div class='container'> <div class='text-fields'> - <div class='form-group'> - <label for='username'>{{$t('login.username')}}</label> - <input :disabled="registering" v-model='user.username' class='form-control' id='username' placeholder='e.g. lain'> + <div class='form-group' :class="{ 'form-group--error': $v.user.username.$error }"> + <label class='form--label' for='sign-up-username'>{{$t('login.username')}}</label> + <input :disabled="isPending" v-model.trim='$v.user.username.$model' class='form-control' id='sign-up-username' placeholder='e.g. lain'> </div> - <div class='form-group'> - <label for='fullname'>{{$t('registration.fullname')}}</label> - <input :disabled="registering" v-model='user.fullname' class='form-control' id='fullname' placeholder='e.g. Lain Iwakura'> + <div class="form-error" v-if="$v.user.username.$dirty"> + <span class="error-required" v-if="!$v.user.username.required">Username is required.</span> </div> + <div class='form-group'> - <label for='email'>{{$t('registration.email')}}</label> - <input :disabled="registering" v-model='user.email' class='form-control' id='email' type="email"> + <label class='form--label' for='sign-up-fullname'>{{$t('registration.fullname')}}</label> + <input :disabled="isPending" v-model='user.fullname' class='form-control' id='sign-up-fullname' placeholder='e.g. Lain Iwakura'> </div> - <div class='form-group'> - <label for='bio'>{{$t('registration.bio')}}</label> - <input :disabled="registering" v-model='user.bio' class='form-control' id='bio'> + + <div class='form-group' :class="{ 'form-group--error': $v.user.email.$error }"> + <label class='form--label' for='email'>{{$t('registration.email')}}</label> + <input :disabled="isPending" v-model='$v.user.email.$model' class='form-control' id='email' type="email"> </div> - <div class='form-group'> - <label for='password'>{{$t('login.password')}}</label> - <input :disabled="registering" v-model='user.password' class='form-control' id='password' type='password'> + <div class="form-error" v-if="$v.user.email.$dirty"> + <span class="error-required" v-if="!$v.user.email.required">Email is required.</span> </div> + <div class='form-group'> - <label for='password_confirmation'>{{$t('registration.password_confirm')}}</label> - <input :disabled="registering" v-model='user.confirm' class='form-control' id='password_confirmation' type='password'> + <label class='form--label' for='bio'>{{$t('registration.bio')}}</label> + <input :disabled="isPending" v-model='user.bio' class='form-control' id='bio'> + </div> + + <div class='form-group' :class="{ 'form-group--error': $v.user.password.$error }"> + <label class='form--label' for='sign-up-password'>{{$t('login.password')}}</label> + <input :disabled="isPending" v-model='user.password' class='form-control' id='sign-up-password' type='password'> + </div> + <div class="form-error" v-if="$v.user.password.$dirty"> + <span class="error-required" v-if="!$v.user.password.required">Password is required.</span> + </div> + + <div class='form-group' :class="{ 'form-group--error': $v.user.confirm.$error }"> + <label class='form--label' for='sign-up-password-confirmation'>{{$t('registration.password_confirm')}}</label> + <input :disabled="isPending" v-model='user.confirm' class='form-control' id='sign-up-password-confirmation' type='password'> + </div> + <div class="form-error" v-if="$v.user.confirm.$dirty"> + <span class="error-required" v-if="!$v.user.confirm.required">Password confirmation is required.</span> </div> <!-- <div class='form-group'> @@ -43,15 +60,18 @@ <input disabled='true' v-model='token' class='form-control' id='token' type='text'> </div> <div class='form-group'> - <button :disabled="registering" type='submit' class='btn btn-default'>{{$t('general.submit')}}</button> + <button :disabled="isPending" type='submit' class='btn btn-default'>{{$t('general.submit')}}</button> </div> </div> <div class='terms-of-service' v-html="termsofservice"> </div> </div> - <div v-if="errors.length" class='form-group'> + <div v-if="clientValidationFailed"> + <span>Form is invalid</span> + </div> + <div v-if="serverValidationErrors.length" class='form-group'> <div class='alert error'> - <span v-for="error in errors">{{error}}</span> + <span v-for="error in serverValidationErrors">{{error}}</span> </div> </div> </form> @@ -91,6 +111,27 @@ flex-direction: column; padding: 0.3em 0.0em 0.3em; line-height:24px; + margin-bottom: 1em; + } + + .form-group--error { + animation-name: shakeError; + animation-duration: .6s; + animation-timing-function: ease-in-out; + } + + .form-group--error .form--label { + color: #f04124; + } + + .form-error { + margin-top: -0.7em; + margin-bottom: 0.5em; + + text-align: left; + span { + font-size: 12px; + } } form textarea { diff --git a/src/modules/users.js b/src/modules/users.js index 8630ee0d..572a62c6 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -1,6 +1,9 @@ import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js' import { compact, map, each, merge } from 'lodash' import { set } from 'vue' +import { SIGN_UP } from '../mutation_types' +import oauthApi from '../services/new_api/oauth' +import {humanizeErrors} from './errors' // TODO: Unify with mergeOrAdd in statuses.js export const mergeOrAdd = (arr, obj, item) => { @@ -46,15 +49,26 @@ export const mutations = { setColor (state, { user: {id}, highlighted }) { const user = state.usersObject[id] set(user, 'highlight', highlighted) + }, + [SIGN_UP.PENDING] (state) { + state[SIGN_UP.isPending] = true + }, + [SIGN_UP.SUCCESS] (state) { + state[SIGN_UP.isPending] = false + }, + [SIGN_UP.FAILURE] (state, errors) { + state[SIGN_UP.isPending] = false + state[SIGN_UP.errors] = [...state[SIGN_UP.errors], ...errors] } } export const defaultState = { lastLoginName: false, currentUser: false, - loggingIn: false, users: [], - usersObject: {} + usersObject: {}, + sign_up_pending: false, + sign_up_errors: [] } const users = { @@ -80,6 +94,32 @@ const users = { store.commit('setUserForStatus', status) }) }, + async signUp (store, userInfo) { + store.commit(SIGN_UP.PENDING) + + let response = await store.rootState.api.backendInteractor.register(userInfo) + if (response.ok) { + const data = { + oauth: store.state.oauth, + instance: store.state.instance.server + } + let app = await oauthApi.getOrCreateApp(data) + let result = await oauthApi.getTokenWithCredentials({ + app, + instance: data.instance, + username: this.user.username, + password: this.user.password + }) + store.commit(SIGN_UP.SUCCESS) + store.commit('setToken', result.access_token) + store.dispatch('loginUser', result.access_token) + this.$router.push('/main/friends') + } else { + let data = await response.json() + let errors = humanizeErrors(JSON.parse(data.error)) + store.commit(SIGN_UP.FAILURE, errors) + } + }, logout (store) { store.commit('clearCurrentUser') store.commit('setToken', false) diff --git a/src/mutation_types.js b/src/mutation_types.js new file mode 100644 index 00000000..026c5540 --- /dev/null +++ b/src/mutation_types.js @@ -0,0 +1,7 @@ +export const SIGN_UP = { + SUCCESS: 'SIGN_UP_SUCCESS', + FAILURE: 'SIGN_UP_FAILURE', + PENDING: 'SIGN_UP_PENDING', + isPending: 'sign_up_pending', + errors: 'sign_up_errors' +} |
