Refactor: move registration modal into its own component

The registration modal, where you set your password for the first time, is now in its own component and included in the Setting component.
parent ee36b883
<template>
<!-- Buefy docs recommend adding has-modal-card property for better
mobile handling but it makes the modal very wide. Keep an eye on this -->
<b-modal :active.sync='modalIsActive' :canCancel='false' scroll='keep'>
<div class='modal-card' style='width: auto'>
<header class='modal-card-head'>
<p class='modal-card-title'>Welcome to your Indie Site!</p>
</header>
<form @submit.prevent='submitPasswordForm'>
<section class='modal-card-body'>
<div class='instructions'>
<p>To start, please pick a strong password to protect yourself.</p>
<p>Please don’t lose this. Your site will not store your password to protect your privacy and you can’t recover it if you forget it. If possible, generate and store your password using a password manager like <a href='https://1password.com'>1Password</a> or <a href='https://keepass.info'>KeePass</a>.</p>
</div>
<b-field label='Password'>
<div id='password-field' class='control'>
<no-ssr>
<vue-password
placeholder='Choose a strong password'
v-model='password'
classes='input'
:disabled='isLoading || registrationIsSuccessful'
@strength='validatePasswordStrength'
>
<template slot='password-toggle' slot-scope='props'>
<button
class='button VuePassword__Toggle'
type='button'
@click='props.toggle'
:disabled='isLoading || registrationIsSuccessful'
>{{ props.type === 'password' ? 'Show' : 'Hide' }}</button>
</template>
</vue-password>
</no-ssr>
</div>
</b-field>
</section>
<footer class='modal-card-foot'>
<button :class='setPasswordButtonClasses' type='submit' :disabled='!passwordIsStrongEnough || isLoading || registrationIsSuccessful'>
<span v-if='registrationIsSuccessful' id='success-icon' class='icon is-medium'><i class='fa fa-check'></i></span>
{{ setPasswordButtonText }}</button>
</footer>
</form>
</div>
</b-modal>
</template>
<script>
import vuePassword from '~/components/vuePassword'
export default {
props: {
isActive: {
type: Boolean,
required: true,
default: false
}
},
components: {
vuePassword
},
data () {
return {
password: '',
passwordIsStrongEnough: false,
isLoading: false,
registrationIsSuccessful: false
}
},
computed: {
// Use a computed property so we don’t bind :active.sync to the
// isActive prop directly (as Vue complains about props if they’re
// written to from within components).
modalIsActive: {
get: function () { return this.isActive },
set: function () { /* do nothing; required to silence Vue warning */ }
},
setPasswordButtonText () {
let text = this.registrationIsSuccessful ? 'Done' : 'Set password'
if (this.isLoading) text = 'Registering'
return text
},
setPasswordButtonClasses () {
let classes = {
'button': true,
'is-fullwidth': true,
}
classes['is-success'] = this.registrationIsSuccessful
classes['is-primary'] = !this.registrationIsSuccessful
classes['is-loading'] = this.isLoading
return classes
},
configured: {
get () { return this.$store.state.configured },
set (value) { this.$store.commit('configured', value) }
},
signedIn: {
get () { return this.$store.state.signedIn },
set (value) { this.$store.commit('signedIn', value) }
}
},
methods: {
onClose () {
this.$emit('close')
},
// Called when the input in the password form changes with the current strength.
validatePasswordStrength (strength) {
// We will only accept passwords that are “strong” or “very strong” on
// the zxcvbn scale.
this.passwordIsStrongEnough = (strength.score >= 3)
},
submitPasswordForm () {
console.log('⚠️ Settings screen password form submit is currently unimplemented.')
this.isLoading = true
// Mock a successful registration.
setTimeout(() => {
this.isLoading = false
this.registrationIsSuccessful = true
// After the person has had a chance to see that the registration
// was successful, remove the modal dialog.
setTimeout(() => {
this.signedIn = true
this.configured = true
}, 1000);
}, 1250);
}
}
}
</script>
<style>
.button {
/* Fix the text centering in the button. */
padding-top: 0.15em;
}
/* Put a min-width on the Show/Hide password toggle button in the Settings
tab so that it doesn’t jump around due to the differing amount of space
taken up by the different labels. The class name is set by the component
and has other styles that act on it so do not change that. */
button.button.VuePassword__Toggle {
min-width: 80px;
}
.instructions {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
.instructions p:first-of-type {
font-weight: bold;
}
div.VuePassword__Message {
min-height: 2rem;
}
.VuePassword__Meter {
margin-top: .5rem;
}
.VuePassword__Message {
padding-top: .5rem;
}
#password-field {
margin-bottom: 0;
}
#success-icon {
/* display: inline-block; */
margin-right: 0.25em;
}
</style>
......@@ -31,84 +31,23 @@
</form>
<!-- Buefy docs recommend adding has-modal-card property for better
mobile handling but it makes the modal very wide. Keep an eye on this -->
<b-modal :active.sync='modalIsActive' :canCancel='false' scroll='keep'>
<div class='modal-card' style='width: auto'>
<header class='modal-card-head'>
<p class='modal-card-title'>Welcome to your Indie Site!</p>
</header>
<form @submit.prevent='submitPasswordForm'>
<section class='modal-card-body'>
<div class='instructions'>
<p>To start, please pick a strong password to protect yourself.</p>
<p>Please don’t lose this. Your site will not store your password to protect your privacy and you can’t recover it if you forget it. If possible, generate and store your password using a password manager like <a href='https://1password.com'>1Password</a> or <a href='https://keepass.info'>KeePass</a>.</p>
</div>
<b-field label='Password'>
<div id='password-field' class='control'>
<no-ssr>
<vue-password
placeholder='Choose a strong password'
v-model='password'
classes='input'
:disabled='isLoading || registrationIsSuccessful'
@strength='validatePasswordStrength'
>
<template slot='password-toggle' slot-scope='props'>
<button
class='button VuePassword__Toggle'
type='button'
@click='props.toggle'
:disabled='isLoading || registrationIsSuccessful'
>{{ props.type === 'password' ? 'Show' : 'Hide' }}</button>
</template>
</vue-password>
</no-ssr>
</div>
</b-field>
</section>
<footer class="modal-card-foot">
<button :class='setPasswordButtonClasses' type='submit' :disabled='!passwordIsStrongEnough || isLoading || registrationIsSuccessful'>
<span v-if='registrationIsSuccessful' id='success-icon' class='icon is-medium'><i class='fa fa-check'></i></span>
{{ setPasswordButtonText }}</button>
</footer>
</form>
</div>
</b-modal>
<registrationModal :isActive='registrationModalActive' />
</div>
</template>
<script>
import vuePassword from '~/components/vuePassword'
import vueColorCompact from '~/../node_modules/vue-color/src/components/Compact.vue'
import registrationModal from '~/components/registrationModal'
export default {
components: {
vueColorCompact,
vuePassword
registrationModal
},
computed: {
modalIsActive () { return !this.configured },
setPasswordButtonText () {
let text = this.registrationIsSuccessful ? 'Done' : 'Set password'
if (this.isLoading) text = 'Registering'
return text
},
setPasswordButtonClasses () {
let classes = {
'button': true,
'is-fullwidth': true,
}
classes['is-success'] = this.registrationIsSuccessful
classes['is-primary'] = !this.registrationIsSuccessful
classes['is-loading'] = this.isLoading
return classes
},
registrationModalActive () { return !this.configured },
name: {
get () { return this.$store.state.name },
......@@ -148,46 +87,15 @@
configured: {
get () { return this.$store.state.configured },
set (value) { this.$store.commit('configured', value) }
},
signedIn: {
get () { return this.$store.state.signedIn },
set (value) { this.$store.commit('signedIn', value) }
}
},
data () {
return {
password: '',
passwordIsStrongEnough: false,
isLoading: false,
registrationIsSuccessful: false
}
},
methods: {
// Called when the input in the password form changes with the current strength.
validatePasswordStrength (strength) {
// We will only accept passwords that are “strong” or “very strong” on
// the zxcvbn scale.
this.passwordIsStrongEnough = (strength.score >= 3)
},
submitPasswordForm () {
console.log('⚠️ Settings screen password form submit is currently unimplemented.')
this.isLoading = true
// Mock a successful registration.
setTimeout(() => {
this.isLoading = false
this.registrationIsSuccessful = true
// After the person has had a chance to see that the registration
// was successful, remove the modal dialog.
setTimeout(() => {
this.signedIn = true
this.configured = true
}, 1000);
}, 1250);
}
}
}
</script>
......@@ -208,27 +116,7 @@
border: 1px solid #333;
}
.button {
/* Fix the text centering in the button. */
padding-top: 0.15em;
}
/* Put a min-width on the Show/Hide password toggle button in the Settings
tab so that it doesn’t jump around due to the differing amount of space
taken up by the different labels. The class name is set by the component
and has other styles that act on it so do not change that. */
button.button.VuePassword__Toggle {
min-width: 80px;
}
.instructions {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
.instructions p:first-of-type {
font-weight: bold;
}
div.control {
margin-bottom: 1em;
......@@ -251,21 +139,6 @@
width: 246px;
}
div.VuePassword__Message {
min-height: 2rem;
}
.VuePassword__Meter {
margin-top: .5rem;
}
.VuePassword__Message {
padding-top: .5rem;
}
#password-field {
margin-bottom: 0;
}
.profile-image-preview {
width: 100px;
......@@ -274,8 +147,5 @@
border: 1px solid #333;
}
#success-icon {
/* display: inline-block; */
margin-right: 0.25em;
}
</style>
......@@ -70,8 +70,8 @@ export const actions = {
const siteConfiguration = await _app.service('site-configuration').find()
// Mock: sign-in and site configuration state
commit('configured', true)
commit('signedIn', true)
commit('configured', false)
commit('signedIn', false)
// TODO: There must be a better way to do this; explore. []
commit('name', siteConfiguration.name)
......
Markdown is supported
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