Skip to content

Commit e3e3942

Browse files
Merge pull request #48 from nafundi/reset-password
Reset password
2 parents fbeb435 + 1c6dd80 commit e3e3942

24 files changed

+625
-218
lines changed

lib/components/account/claim.vue

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<!--
2+
Copyright 2017 Super Adventure Developers
3+
See the NOTICE file at the top-level directory of this distribution and at
4+
https://github.com/nafundi/super-adventure/blob/master/NOTICE.
5+
6+
This file is part of Super Adventure. It is subject to the license terms in
7+
the LICENSE file found in the top-level directory of this distribution and at
8+
https://www.apache.org/licenses/LICENSE-2.0. No part of Super Adventure,
9+
including this file, may be copied, modified, propagated, or distributed
10+
except according to the terms contained in the LICENSE file.
11+
-->
12+
<template>
13+
<div id="account-claim" class="row">
14+
<div class="col-xs-12 col-sm-offset-3 col-sm-6">
15+
<div class="panel panel-default panel-main">
16+
<div class="panel-heading">
17+
<h1 class="panel-title">
18+
Set Password
19+
</h1>
20+
</div>
21+
<div class="panel-body">
22+
<alert v-bind="alert" @close="alert.state = false"/>
23+
<app-form @submit="submit">
24+
<label class="form-group">
25+
<input type="password" v-model="password" class="form-control"
26+
placeholder="New Password *" required>
27+
<span class="form-label">New Password *</span>
28+
</label>
29+
<div class="panel-footer">
30+
<button type="submit" class="btn btn-primary" :disabled="awaitingResponse">
31+
Set Password <spinner :state="awaitingResponse"/>
32+
</button>
33+
</div>
34+
</app-form>
35+
</div>
36+
</div>
37+
</div>
38+
</div>
39+
</template>
40+
41+
<script>
42+
import alert from '../../mixins/alert';
43+
import request from '../../mixins/request';
44+
45+
export default {
46+
name: 'AccountClaim',
47+
mixins: [alert(), request()],
48+
data() {
49+
return {
50+
alert: alert.blank(),
51+
requestId: null,
52+
password: ''
53+
};
54+
},
55+
computed: {
56+
token() {
57+
const { token } = this.$route.query;
58+
// Vue interprets + characters in tokens as spaces, so we have to change
59+
// them back.
60+
return token != null ? token.replace(/ /g, '+') : '';
61+
}
62+
},
63+
methods: {
64+
submit() {
65+
const headers = { Authorization: `Bearer ${this.token}` };
66+
this
67+
.post('/users/reset/verify', { new: this.password }, { headers })
68+
.then(() => {
69+
this.$alert = alert.success('The password was reset successfully.');
70+
this.$router.push('/login');
71+
})
72+
.catch(() => {});
73+
}
74+
}
75+
};
76+
</script>

lib/components/session/login.vue renamed to lib/components/account/login.vue

Lines changed: 33 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,31 @@ including this file, may be copied, modified, propagated, or distributed
1010
except according to the terms contained in the LICENSE file.
1111
-->
1212
<template>
13-
<div id="session-login" class="row">
13+
<div id="account-login" class="row">
1414
<div class="col-xs-12 col-sm-offset-3 col-sm-6">
15-
<div class="panel panel-default">
16-
<div id="session-login-heading" class="panel-heading">
17-
<h1 class="panel-title">Log in</h1>
18-
</div>
15+
<div class="panel panel-default panel-main">
16+
<div class="panel-heading"><h1 class="panel-title">Log in</h1></div>
1917
<div class="panel-body">
2018
<alert v-bind="alert" @close="alert.state = false"/>
21-
<app-form id="session-login-form" @submit="submit">
19+
<app-form @submit="submit">
2220
<label class="form-group">
23-
<input type="email" v-model.trim="email" id="session-login-email"
24-
class="form-control" placeholder="Email address *" required autocomplete="off">
21+
<input type="email" v-model.trim="email" class="form-control"
22+
placeholder="Email address *" required autocomplete="off">
2523
<span class="form-label">Email address *</span>
2624
</label>
2725
<label class="form-group">
28-
<input type="password" v-model="password" id="session-login-password"
29-
class="form-control" placeholder="Password *" required>
26+
<input type="password" v-model="password" class="form-control"
27+
placeholder="Password *" required>
3028
<span class="form-label">Password *</span>
3129
</label>
3230
<div class="panel-footer">
3331
<button type="submit" class="btn btn-primary" :disabled="disabled">
3432
Log in <spinner :state="disabled"/>
3533
</button>
34+
<router-link :to="resetPasswordLocation" tag="button"
35+
type="button" class="btn btn-link">
36+
Reset Password
37+
</router-link>
3638
</div>
3739
</app-form>
3840
</div>
@@ -46,8 +48,10 @@ import alert from '../../mixins/alert';
4648
import request from '../../mixins/request';
4749
import { logIn } from '../../session';
4850

51+
const DEFAULT_NEXT_PATH = '/forms';
52+
4953
export default {
50-
name: 'SessionLogin',
54+
name: 'AccountLogin',
5155
mixins: [alert(), request()],
5256
data() {
5357
return {
@@ -58,9 +62,13 @@ export default {
5862
password: ''
5963
};
6064
},
61-
created() {
62-
if (this.$session.changedSinceLastPoll())
63-
this.alert = alert.success('You have logged out successfully.');
65+
computed: {
66+
resetPasswordLocation() {
67+
return {
68+
path: '/reset-password',
69+
query: Object.assign({}, this.$route.query)
70+
};
71+
}
6472
},
6573
methods: {
6674
problemToAlert(problem) {
@@ -74,17 +82,20 @@ export default {
7482
.get('/users/current', { headers })
7583
.then(user => ({ session, user }));
7684
},
77-
routeToNext() {
78-
let path = '/forms';
85+
nextPath() {
7986
const { next } = this.$route.query;
80-
if (next != null) {
81-
const link = document.createElement('a');
82-
link.href = next;
83-
if (link.host === window.location.host) path = link.pathname;
84-
}
87+
if (next == null) return DEFAULT_NEXT_PATH;
88+
const link = document.createElement('a');
89+
link.href = next;
90+
return link.host === window.location.host
91+
? link.pathname
92+
: DEFAULT_NEXT_PATH;
93+
},
94+
routeToNext() {
95+
this.$alert = alert.success('You have logged in successfully.');
8596
const query = Object.assign({}, this.$route.query);
8697
delete query.next;
87-
this.$router.push({ path, query });
98+
this.$router.push({ path: this.nextPath(), query });
8899
},
89100
submit() {
90101
this.disabled = true;
@@ -100,39 +111,3 @@ export default {
100111
}
101112
};
102113
</script>
103-
104-
<style lang="sass">
105-
@import '../../../assets/scss/variables';
106-
107-
#session-login {
108-
margin-top: 70px;
109-
110-
.panel {
111-
border: none;
112-
border-radius: 0;
113-
box-shadow: 0 0 24px rgba(0, 0, 0, 0.25), 0 35px 115px rgba(0, 0, 0, 0.28);
114-
}
115-
.panel-body {
116-
padding: 25px 15px;
117-
}
118-
.panel-footer {
119-
background: $color-subpanel-background;
120-
border-top-color: $color-subpanel-border;
121-
margin: -15px;
122-
margin-bottom: -25px;
123-
margin-top: 20px;
124-
}
125-
}
126-
127-
#session-login-heading {
128-
background-color: $color-accent-primary;
129-
border-radius: 0;
130-
color: #fff;
131-
132-
h1 {
133-
font-size: 18px;
134-
font-weight: bold;
135-
letter-spacing: -0.02em;
136-
}
137-
}
138-
</style>
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<!--
2+
Copyright 2017 Super Adventure Developers
3+
See the NOTICE file at the top-level directory of this distribution and at
4+
https://github.com/nafundi/super-adventure/blob/master/NOTICE.
5+
6+
This file is part of Super Adventure. It is subject to the license terms in
7+
the LICENSE file found in the top-level directory of this distribution and at
8+
https://www.apache.org/licenses/LICENSE-2.0. No part of Super Adventure,
9+
including this file, may be copied, modified, propagated, or distributed
10+
except according to the terms contained in the LICENSE file.
11+
-->
12+
<template>
13+
<div id="account-reset-password" class="row">
14+
<div class="col-xs-12 col-sm-offset-3 col-sm-6">
15+
<div class="panel panel-default panel-main">
16+
<div class="panel-heading">
17+
<h1 class="panel-title">
18+
Reset Password
19+
</h1>
20+
</div>
21+
<div class="panel-body">
22+
<alert v-bind="alert" @close="alert.state = false"/>
23+
<app-form @submit="submit">
24+
<label class="form-group">
25+
<input type="email" v-model.trim="email" class="form-control"
26+
placeholder="Email address *" required autocomplete="off">
27+
<span class="form-label">Email address *</span>
28+
</label>
29+
<div class="panel-footer">
30+
<button type="submit" class="btn btn-primary" :disabled="awaitingResponse">
31+
Reset Password <spinner :state="awaitingResponse"/>
32+
</button>
33+
<button type="button" class="btn btn-link" @click="routeToLogin">
34+
Cancel
35+
</button>
36+
</div>
37+
</app-form>
38+
</div>
39+
</div>
40+
</div>
41+
</div>
42+
</template>
43+
44+
<script>
45+
import alert from '../../mixins/alert';
46+
import request from '../../mixins/request';
47+
48+
export default {
49+
name: 'AccountResetPassword',
50+
mixins: [alert(), request()],
51+
data() {
52+
return {
53+
alert: alert.blank(),
54+
requestId: null,
55+
email: ''
56+
};
57+
},
58+
methods: {
59+
routeToLogin() {
60+
this.$router.push({
61+
path: '/login',
62+
query: Object.assign({}, this.$route.query)
63+
});
64+
},
65+
submit() {
66+
this
67+
.post('/users/reset/initiate', { email: this.email })
68+
.then(() => {
69+
this.$alert = alert.success(`An email has been sent to ${this.email} with further instructions.`);
70+
this.routeToLogin();
71+
})
72+
.catch(() => {});
73+
}
74+
}
75+
};
76+
</script>

lib/components/app.vue

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,18 @@ body {
6262
padding: 6px 10px 5px;
6363
position: relative;
6464
}
65+
6566
.btn-primary {
6667
background-color: $color-action-background;
6768
&:hover, &:focus {
6869
background-color: $color-action-background-hover;
6970
}
7071
}
7172

73+
.btn-link {
74+
color: $color-action-foreground;
75+
}
76+
7277
.form-group {
7378
display: block;
7479
font-weight: normal;
@@ -122,4 +127,38 @@ body {
122127
}
123128
}
124129
}
130+
131+
.panel {
132+
border: none;
133+
border-radius: 0;
134+
box-shadow: 0 0 24px rgba(0, 0, 0, 0.25), 0 35px 115px rgba(0, 0, 0, 0.28);
135+
136+
.panel-heading {
137+
background-color: $color-accent-primary;
138+
border-radius: 0;
139+
color: #fff;
140+
141+
.panel-title {
142+
font-size: 18px;
143+
font-weight: bold;
144+
letter-spacing: -0.02em;
145+
}
146+
}
147+
148+
.panel-body {
149+
padding: 25px 15px;
150+
}
151+
152+
.panel-footer {
153+
background: $color-subpanel-background;
154+
border-top-color: $color-subpanel-border;
155+
margin: -15px;
156+
margin-bottom: -25px;
157+
margin-top: 20px;
158+
}
159+
}
160+
161+
.panel-main {
162+
margin-top: 70px;
163+
}
125164
</style>

lib/components/form/list.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ import request from '../../mixins/request';
7676
export default {
7777
name: 'FormList',
7878
components: { FormNew },
79-
mixins: [alert({ login: true }), request(), highlight()],
79+
mixins: [alert(), request(), highlight()],
8080
data() {
8181
return {
8282
alert: alert.blank(),

lib/components/form/show.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ import request from '../../mixins/request';
8888

8989
export default {
9090
name: 'FormShow',
91-
mixins: [alert({ login: true }), request()],
91+
mixins: [alert(), request()],
9292
data() {
9393
return {
9494
alert: alert.blank(),

lib/components/modal.vue

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,7 @@ export default {
138138
margin: -15px;
139139
margin-top: 20px;
140140
padding: 10px 15px;
141-
142-
.btn-default {
143-
background-color: transparent;
144-
color: $color-action-foreground;
145-
}
146141
}
147142
}
148143
}
149144
</style>
150-

0 commit comments

Comments
 (0)