aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/registration/registration.js70
-rw-r--r--src/components/registration/registration.vue79
-rw-r--r--src/modules/users.js44
-rw-r--r--src/mutation_types.js7
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'
+}