@nymphjs/tilmeld-components 1.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/LICENSE +202 -0
- package/README.md +31 -0
- package/dist/index.js +3 -0
- package/dist/index.js.LICENSE.txt +47 -0
- package/dist/index.js.map +1 -0
- package/jest.config.js +6 -0
- package/package.json +57 -0
- package/src/Account.svelte +317 -0
- package/src/ChangePassword.svelte +176 -0
- package/src/Login.svelte +314 -0
- package/src/Recover.svelte +309 -0
- package/src/global.d.ts +1 -0
- package/src/index.d.ts +6 -0
- package/src/index.ts +6 -0
- package/tsconfig.json +10 -0
- package/webpack.config.js +35 -0
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nymphjs/tilmeld-components",
|
|
3
|
+
"version": "1.0.0-alpha.2",
|
|
4
|
+
"description": "NymphJS - Tilmeld Front End Components",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "src/index.d.ts",
|
|
8
|
+
"svelte": "src/index.ts",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"nymph",
|
|
11
|
+
"ORM",
|
|
12
|
+
"object relational mapper"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"clean": "test -d dist && rm -r dist || true",
|
|
16
|
+
"build": "webpack",
|
|
17
|
+
"watch": "webpack --watch",
|
|
18
|
+
"prepare": "npm run clean && npm run build",
|
|
19
|
+
"test": "jest",
|
|
20
|
+
"test:watch": "jest --watch"
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/sciactive/nymphjs.git"
|
|
28
|
+
},
|
|
29
|
+
"author": "Hunter Perrin <hperrin@gmail.com>",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/sciactive/nymphjs/issues"
|
|
32
|
+
},
|
|
33
|
+
"license": "Apache-2.0",
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@nymphjs/tilmeld-client": "^1.0.0-alpha.2",
|
|
36
|
+
"@smui/button": "^5.0.0-beta.5",
|
|
37
|
+
"@smui/circular-progress": "^5.0.0-beta.5",
|
|
38
|
+
"@smui/dialog": "^5.0.0-beta.5",
|
|
39
|
+
"@smui/form-field": "^5.0.0-beta.5",
|
|
40
|
+
"@smui/radio": "^5.0.0-beta.5",
|
|
41
|
+
"@smui/textfield": "^5.0.0-beta.5",
|
|
42
|
+
"@tsconfig/recommended": "^1.0.1",
|
|
43
|
+
"@tsconfig/svelte": "^2.0.1",
|
|
44
|
+
"@types/jest": "^27.0.1",
|
|
45
|
+
"jest": "^27.0.6",
|
|
46
|
+
"svelte": "^3.42.4",
|
|
47
|
+
"svelte-check": "^2.2.5",
|
|
48
|
+
"svelte-loader": "^3.1.2",
|
|
49
|
+
"svelte-preprocess": "^4.8.0",
|
|
50
|
+
"ts-jest": "^27.0.5",
|
|
51
|
+
"ts-loader": "^9.2.5",
|
|
52
|
+
"typescript": "^4.3.5",
|
|
53
|
+
"webpack": "^5.51.1",
|
|
54
|
+
"webpack-cli": "^4.8.0"
|
|
55
|
+
},
|
|
56
|
+
"gitHead": "9596354bffaa484f3002f3063f0963f6261040be"
|
|
57
|
+
}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
{#if clientConfig != null && user != null}
|
|
2
|
+
<Dialog
|
|
3
|
+
bind:open
|
|
4
|
+
aria-labelledby="tilmeld-account-title"
|
|
5
|
+
aria-describedby="tilmeld-account-content"
|
|
6
|
+
surface$class="tilmeld-account-dialog-surface"
|
|
7
|
+
>
|
|
8
|
+
<!-- Title cannot contain leading whitespace due to mdc-typography-baseline-top() -->
|
|
9
|
+
<Title id="tilmeld-account-title">Your Account</Title>
|
|
10
|
+
<Content id="tilmeld-account-content">
|
|
11
|
+
{#if !clientConfig.emailUsernames && clientConfig.allowUsernameChange}
|
|
12
|
+
<div>
|
|
13
|
+
<Textfield
|
|
14
|
+
bind:value={user.username}
|
|
15
|
+
label="Username"
|
|
16
|
+
type="text"
|
|
17
|
+
style="width: 100%;"
|
|
18
|
+
helperLine$style="width: 100%;"
|
|
19
|
+
invalid={usernameVerified === false}
|
|
20
|
+
input$autocomplete="username"
|
|
21
|
+
input$autocapitalize="off"
|
|
22
|
+
input$spellcheck="false"
|
|
23
|
+
>
|
|
24
|
+
<HelperText persistent slot="helper">
|
|
25
|
+
{usernameVerifiedMessage ?? ''}
|
|
26
|
+
</HelperText>
|
|
27
|
+
</Textfield>
|
|
28
|
+
</div>
|
|
29
|
+
{/if}
|
|
30
|
+
|
|
31
|
+
{#if clientConfig.emailUsernames || clientConfig.userFields.indexOf('email') !== -1}
|
|
32
|
+
<div>
|
|
33
|
+
<Textfield
|
|
34
|
+
bind:value={user.email}
|
|
35
|
+
label="Email"
|
|
36
|
+
type="email"
|
|
37
|
+
style="width: 100%;"
|
|
38
|
+
helperLine$style="width: 100%;"
|
|
39
|
+
invalid={emailVerified === false}
|
|
40
|
+
input$autocomplete="email"
|
|
41
|
+
input$autocapitalize="off"
|
|
42
|
+
input$spellcheck="false"
|
|
43
|
+
>
|
|
44
|
+
<HelperText persistent slot="helper">
|
|
45
|
+
{emailVerifiedMessage ?? ''}
|
|
46
|
+
</HelperText>
|
|
47
|
+
</Textfield>
|
|
48
|
+
</div>
|
|
49
|
+
{/if}
|
|
50
|
+
|
|
51
|
+
{#if clientConfig.userFields.indexOf('name') !== -1}
|
|
52
|
+
<div>
|
|
53
|
+
<Textfield
|
|
54
|
+
bind:value={user.nameFirst}
|
|
55
|
+
label="First Name"
|
|
56
|
+
type="text"
|
|
57
|
+
style="width: 100%;"
|
|
58
|
+
input$autocomplete="given-name"
|
|
59
|
+
/>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div>
|
|
63
|
+
<Textfield
|
|
64
|
+
bind:value={user.nameMiddle}
|
|
65
|
+
label="Middle Name"
|
|
66
|
+
type="text"
|
|
67
|
+
style="width: 100%;"
|
|
68
|
+
input$autocomplete="additional-name"
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<div>
|
|
73
|
+
<Textfield
|
|
74
|
+
bind:value={user.nameLast}
|
|
75
|
+
label="Last Name"
|
|
76
|
+
type="text"
|
|
77
|
+
style="width: 100%;"
|
|
78
|
+
input$autocomplete="family-name"
|
|
79
|
+
/>
|
|
80
|
+
</div>
|
|
81
|
+
{/if}
|
|
82
|
+
|
|
83
|
+
{#if clientConfig.userFields.indexOf('phone') !== -1}
|
|
84
|
+
<div>
|
|
85
|
+
<Textfield
|
|
86
|
+
bind:value={user.phone}
|
|
87
|
+
label="Phone Number"
|
|
88
|
+
type="tel"
|
|
89
|
+
style="width: 100%;"
|
|
90
|
+
input$autocomplete="tel"
|
|
91
|
+
input$name="phone"
|
|
92
|
+
/>
|
|
93
|
+
</div>
|
|
94
|
+
{/if}
|
|
95
|
+
|
|
96
|
+
<div class="tilmeld-account-action">
|
|
97
|
+
<a
|
|
98
|
+
href="javascript:void(0);"
|
|
99
|
+
on:click={() => {
|
|
100
|
+
open = false;
|
|
101
|
+
changePasswordOpen = true;
|
|
102
|
+
}}
|
|
103
|
+
>
|
|
104
|
+
Change your password.
|
|
105
|
+
</a>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
{#if failureMessage}
|
|
109
|
+
<div class="tilmeld-account-failure">
|
|
110
|
+
{failureMessage}
|
|
111
|
+
</div>
|
|
112
|
+
{/if}
|
|
113
|
+
|
|
114
|
+
{#if saving}
|
|
115
|
+
<div class="tilmeld-account-loading">
|
|
116
|
+
<CircularProgress style="height: 24px; width: 24px;" indeterminate />
|
|
117
|
+
</div>
|
|
118
|
+
{/if}
|
|
119
|
+
</Content>
|
|
120
|
+
<Actions>
|
|
121
|
+
<Button disabled={saving}>
|
|
122
|
+
<Label>Close</Label>
|
|
123
|
+
</Button>
|
|
124
|
+
<Button on:click$preventDefault$stopPropagation={save} disabled={saving}>
|
|
125
|
+
<Label>Save Changes</Label>
|
|
126
|
+
</Button>
|
|
127
|
+
</Actions>
|
|
128
|
+
</Dialog>
|
|
129
|
+
<ChangePassword bind:open={changePasswordOpen} />
|
|
130
|
+
{/if}
|
|
131
|
+
|
|
132
|
+
<script lang="ts">
|
|
133
|
+
import { onMount, onDestroy } from 'svelte';
|
|
134
|
+
import CircularProgress from '@smui/circular-progress';
|
|
135
|
+
import Dialog, { Title, Content, Actions } from '@smui/dialog';
|
|
136
|
+
import Textfield from '@smui/textfield';
|
|
137
|
+
import HelperText from '@smui/textfield/helper-text/index';
|
|
138
|
+
import Button, { Label } from '@smui/button';
|
|
139
|
+
import { ClientConfig, CurrentUserData, User } from '@nymphjs/tilmeld-client';
|
|
140
|
+
import ChangePassword from './ChangePassword.svelte';
|
|
141
|
+
|
|
142
|
+
export let open = false;
|
|
143
|
+
|
|
144
|
+
let clientConfig: ClientConfig | undefined = undefined;
|
|
145
|
+
let user: (User & CurrentUserData) | undefined = undefined;
|
|
146
|
+
let saving = false;
|
|
147
|
+
let originalUsername: string | undefined = undefined;
|
|
148
|
+
let originalEmail: string | undefined = undefined;
|
|
149
|
+
let failureMessage: string | undefined = undefined;
|
|
150
|
+
let usernameTimer: NodeJS.Timeout | undefined = undefined;
|
|
151
|
+
let usernameVerified: boolean | undefined = undefined;
|
|
152
|
+
let usernameVerifiedMessage: string | undefined = undefined;
|
|
153
|
+
let emailTimer: NodeJS.Timeout | undefined = undefined;
|
|
154
|
+
let emailVerified: boolean | undefined = undefined;
|
|
155
|
+
let emailVerifiedMessage: string | undefined = undefined;
|
|
156
|
+
let changePasswordOpen = false;
|
|
157
|
+
|
|
158
|
+
const onLogin = (currentUser: User & CurrentUserData) => {
|
|
159
|
+
user = currentUser;
|
|
160
|
+
readyEntity();
|
|
161
|
+
originalUsername = user?.username;
|
|
162
|
+
originalEmail = user?.email;
|
|
163
|
+
};
|
|
164
|
+
const onLogout = () => {
|
|
165
|
+
user = undefined;
|
|
166
|
+
originalUsername = undefined;
|
|
167
|
+
originalEmail = undefined;
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
$: if (user && user.username !== originalUsername) {
|
|
171
|
+
checkUsername();
|
|
172
|
+
} else {
|
|
173
|
+
if (usernameTimer) {
|
|
174
|
+
clearTimeout(usernameTimer);
|
|
175
|
+
}
|
|
176
|
+
usernameVerified = true;
|
|
177
|
+
usernameVerifiedMessage = undefined;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
$: if (user && user.email !== originalEmail) {
|
|
181
|
+
checkEmail();
|
|
182
|
+
} else {
|
|
183
|
+
if (emailTimer) {
|
|
184
|
+
clearTimeout(emailTimer);
|
|
185
|
+
}
|
|
186
|
+
emailVerified = true;
|
|
187
|
+
emailVerifiedMessage = undefined;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
onMount(async () => {
|
|
191
|
+
User.on('login', onLogin);
|
|
192
|
+
User.on('logout', onLogout);
|
|
193
|
+
user = (await User.current()) ?? undefined;
|
|
194
|
+
readyEntity();
|
|
195
|
+
originalUsername = user?.username;
|
|
196
|
+
originalEmail = user?.email;
|
|
197
|
+
});
|
|
198
|
+
onMount(async () => {
|
|
199
|
+
clientConfig = await User.getClientConfig();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
onDestroy(() => {
|
|
203
|
+
User.off('login', onLogin);
|
|
204
|
+
User.off('logout', onLogout);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
function readyEntity() {
|
|
208
|
+
// Make sure all fields are defined.
|
|
209
|
+
if (user != null && user.username == null) {
|
|
210
|
+
user.username = '';
|
|
211
|
+
}
|
|
212
|
+
if (user != null && user.email == null) {
|
|
213
|
+
user.email = '';
|
|
214
|
+
}
|
|
215
|
+
if (user != null && user.nameFirst == null) {
|
|
216
|
+
user.nameFirst = '';
|
|
217
|
+
}
|
|
218
|
+
if (user != null && user.nameMiddle == null) {
|
|
219
|
+
user.nameMiddle = '';
|
|
220
|
+
}
|
|
221
|
+
if (user != null && user.nameLast == null) {
|
|
222
|
+
user.nameLast = '';
|
|
223
|
+
}
|
|
224
|
+
if (user != null && user.avatar == null) {
|
|
225
|
+
user.avatar = '';
|
|
226
|
+
}
|
|
227
|
+
if (user != null && user.phone == null) {
|
|
228
|
+
user.phone = '';
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async function save() {
|
|
233
|
+
if (user == null) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
failureMessage = undefined;
|
|
238
|
+
saving = true;
|
|
239
|
+
|
|
240
|
+
if (clientConfig?.emailUsernames) {
|
|
241
|
+
user.username = user.email;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
try {
|
|
245
|
+
if (await user.$save()) {
|
|
246
|
+
readyEntity();
|
|
247
|
+
originalEmail = user.email;
|
|
248
|
+
open = false;
|
|
249
|
+
usernameVerifiedMessage = undefined;
|
|
250
|
+
emailVerifiedMessage = undefined;
|
|
251
|
+
} else {
|
|
252
|
+
failureMessage = 'Error saving account changes.';
|
|
253
|
+
}
|
|
254
|
+
} catch (e: any) {
|
|
255
|
+
failureMessage = e?.message;
|
|
256
|
+
}
|
|
257
|
+
saving = false;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function checkUsername() {
|
|
261
|
+
usernameVerified = undefined;
|
|
262
|
+
usernameVerifiedMessage = undefined;
|
|
263
|
+
if (usernameTimer) {
|
|
264
|
+
clearTimeout(usernameTimer);
|
|
265
|
+
usernameTimer = undefined;
|
|
266
|
+
}
|
|
267
|
+
usernameTimer = setTimeout(async () => {
|
|
268
|
+
try {
|
|
269
|
+
const data = await user?.$checkUsername();
|
|
270
|
+
usernameVerified = data?.result ?? false;
|
|
271
|
+
usernameVerifiedMessage =
|
|
272
|
+
data?.message ?? 'Error getting verification.';
|
|
273
|
+
} catch (e: any) {
|
|
274
|
+
usernameVerified = false;
|
|
275
|
+
usernameVerifiedMessage = e?.message;
|
|
276
|
+
}
|
|
277
|
+
}, 400);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function checkEmail() {
|
|
281
|
+
emailVerified = undefined;
|
|
282
|
+
emailVerifiedMessage = undefined;
|
|
283
|
+
if (emailTimer) {
|
|
284
|
+
clearTimeout(emailTimer);
|
|
285
|
+
emailTimer = undefined;
|
|
286
|
+
}
|
|
287
|
+
emailTimer = setTimeout(async () => {
|
|
288
|
+
try {
|
|
289
|
+
const data = await user?.$checkEmail();
|
|
290
|
+
emailVerified = data?.result ?? false;
|
|
291
|
+
emailVerifiedMessage = data?.message ?? 'Error getting verification.';
|
|
292
|
+
} catch (e: any) {
|
|
293
|
+
emailVerified = false;
|
|
294
|
+
emailVerifiedMessage = e?.message;
|
|
295
|
+
}
|
|
296
|
+
}, 400);
|
|
297
|
+
}
|
|
298
|
+
</script>
|
|
299
|
+
|
|
300
|
+
<style>
|
|
301
|
+
:global(.mdc-dialog .mdc-dialog__surface.tilmeld-account-dialog-surface) {
|
|
302
|
+
width: 360px;
|
|
303
|
+
max-width: calc(100vw - 32px);
|
|
304
|
+
}
|
|
305
|
+
.tilmeld-account-failure {
|
|
306
|
+
margin-top: 1em;
|
|
307
|
+
color: var(--mdc-theme-error, #f00);
|
|
308
|
+
}
|
|
309
|
+
.tilmeld-account-action {
|
|
310
|
+
margin-top: 1em;
|
|
311
|
+
}
|
|
312
|
+
.tilmeld-account-loading {
|
|
313
|
+
display: flex;
|
|
314
|
+
justify-content: center;
|
|
315
|
+
align-items: center;
|
|
316
|
+
}
|
|
317
|
+
</style>
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
{#if user != null}
|
|
2
|
+
<Dialog
|
|
3
|
+
bind:open
|
|
4
|
+
aria-labelledby="tilmeld-password-title"
|
|
5
|
+
aria-describedby="tilmeld-password-content"
|
|
6
|
+
surface$class="tilmeld-password-dialog-surface"
|
|
7
|
+
>
|
|
8
|
+
<!-- Title cannot contain leading whitespace due to mdc-typography-baseline-top() -->
|
|
9
|
+
<Title id="tilmeld-password-title">Change Your Password</Title>
|
|
10
|
+
<Content id="tilmeld-password-content">
|
|
11
|
+
<div>
|
|
12
|
+
<Textfield
|
|
13
|
+
bind:value={currentPassword}
|
|
14
|
+
label="Current Password"
|
|
15
|
+
type="password"
|
|
16
|
+
style="width: 100%;"
|
|
17
|
+
input$autocomplete="current-password"
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div>
|
|
22
|
+
<Textfield
|
|
23
|
+
bind:value={newPassword}
|
|
24
|
+
label="New Password"
|
|
25
|
+
type="password"
|
|
26
|
+
style="width: 100%;"
|
|
27
|
+
input$autocomplete="new-password"
|
|
28
|
+
/>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div>
|
|
32
|
+
<Textfield
|
|
33
|
+
bind:value={newPassword2}
|
|
34
|
+
label="Re-enter New Password"
|
|
35
|
+
type="password"
|
|
36
|
+
style="width: 100%;"
|
|
37
|
+
input$autocomplete="new-password"
|
|
38
|
+
/>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
{#if failureMessage}
|
|
42
|
+
<div class="tilmeld-password-failure">
|
|
43
|
+
{failureMessage}
|
|
44
|
+
</div>
|
|
45
|
+
{/if}
|
|
46
|
+
|
|
47
|
+
{#if changing}
|
|
48
|
+
<div class="tilmeld-password-loading">
|
|
49
|
+
<CircularProgress style="height: 24px; width: 24px;" indeterminate />
|
|
50
|
+
</div>
|
|
51
|
+
{/if}
|
|
52
|
+
</Content>
|
|
53
|
+
<Actions>
|
|
54
|
+
<Button disabled={changing}>
|
|
55
|
+
<Label>Close</Label>
|
|
56
|
+
</Button>
|
|
57
|
+
<Button
|
|
58
|
+
on:click$preventDefault$stopPropagation={changePassword}
|
|
59
|
+
disabled={changing}
|
|
60
|
+
>
|
|
61
|
+
<Label>Change Password</Label>
|
|
62
|
+
</Button>
|
|
63
|
+
</Actions>
|
|
64
|
+
</Dialog>
|
|
65
|
+
{/if}
|
|
66
|
+
|
|
67
|
+
<script lang="ts">
|
|
68
|
+
import { onMount, onDestroy } from 'svelte';
|
|
69
|
+
import CircularProgress from '@smui/circular-progress';
|
|
70
|
+
import Dialog, { Title, Content, Actions } from '@smui/dialog';
|
|
71
|
+
import Textfield from '@smui/textfield';
|
|
72
|
+
import Button, { Label } from '@smui/button';
|
|
73
|
+
import { ClientConfig, CurrentUserData, User } from '@nymphjs/tilmeld-client';
|
|
74
|
+
|
|
75
|
+
export let open = false;
|
|
76
|
+
|
|
77
|
+
let clientConfig: ClientConfig | undefined = undefined;
|
|
78
|
+
let user: (User & CurrentUserData) | undefined = undefined;
|
|
79
|
+
let changing = false;
|
|
80
|
+
let failureMessage: string | undefined = undefined;
|
|
81
|
+
|
|
82
|
+
/** User provided. You can bind to it if you need to. */
|
|
83
|
+
export let currentPassword = '';
|
|
84
|
+
/** User provided. You can bind to it if you need to. */
|
|
85
|
+
export let newPassword = '';
|
|
86
|
+
/** User provided. You can bind to it if you need to. */
|
|
87
|
+
export let newPassword2 = '';
|
|
88
|
+
|
|
89
|
+
$: {
|
|
90
|
+
if (!open) {
|
|
91
|
+
changing = false;
|
|
92
|
+
failureMessage = undefined;
|
|
93
|
+
currentPassword = '';
|
|
94
|
+
newPassword = '';
|
|
95
|
+
newPassword2 = '';
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const onLogin = (currentUser: User & CurrentUserData) => {
|
|
100
|
+
user = currentUser;
|
|
101
|
+
};
|
|
102
|
+
const onLogout = () => {
|
|
103
|
+
user = undefined;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
onMount(async () => {
|
|
107
|
+
User.on('login', onLogin);
|
|
108
|
+
User.on('logout', onLogout);
|
|
109
|
+
user = (await User.current()) ?? undefined;
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
onDestroy(() => {
|
|
113
|
+
User.off('login', onLogin);
|
|
114
|
+
User.off('logout', onLogout);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
async function changePassword() {
|
|
118
|
+
if (currentPassword === '') {
|
|
119
|
+
failureMessage = 'You need to enter your current password';
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (newPassword !== newPassword2) {
|
|
123
|
+
failureMessage = 'Your passwords do not match.';
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (newPassword === '') {
|
|
127
|
+
failureMessage = 'You need to enter a new password';
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
failureMessage = undefined;
|
|
132
|
+
changing = true;
|
|
133
|
+
|
|
134
|
+
// Get the current user again, in case their data has changed.
|
|
135
|
+
user = (await User.current()) ?? undefined;
|
|
136
|
+
|
|
137
|
+
if (user == null) {
|
|
138
|
+
failureMessage = 'You must be logged in.';
|
|
139
|
+
changing = false;
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
// Change the user's password.
|
|
145
|
+
const data = await user.$changePassword({
|
|
146
|
+
currentPassword,
|
|
147
|
+
newPassword,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
if (!data.result) {
|
|
151
|
+
failureMessage = data.message;
|
|
152
|
+
} else {
|
|
153
|
+
open = false;
|
|
154
|
+
}
|
|
155
|
+
} catch (e: any) {
|
|
156
|
+
failureMessage = e?.message;
|
|
157
|
+
}
|
|
158
|
+
changing = false;
|
|
159
|
+
}
|
|
160
|
+
</script>
|
|
161
|
+
|
|
162
|
+
<style>
|
|
163
|
+
:global(.mdc-dialog .mdc-dialog__surface.tilmeld-password-dialog-surface) {
|
|
164
|
+
width: 360px;
|
|
165
|
+
max-width: calc(100vw - 32px);
|
|
166
|
+
}
|
|
167
|
+
.tilmeld-password-failure {
|
|
168
|
+
margin-top: 1em;
|
|
169
|
+
color: var(--mdc-theme-error, #f00);
|
|
170
|
+
}
|
|
171
|
+
.tilmeld-password-loading {
|
|
172
|
+
display: flex;
|
|
173
|
+
justify-content: center;
|
|
174
|
+
align-items: center;
|
|
175
|
+
}
|
|
176
|
+
</style>
|