@nymphjs/tilmeld-components 1.0.0-beta.13 → 1.0.0-beta.130
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 +490 -0
- package/README.md +6 -4
- package/dist/Account.svelte +516 -0
- package/dist/ChangePassword.svelte +309 -0
- package/dist/Login.svelte +603 -0
- package/dist/Recover.svelte +463 -0
- package/dist/RevokeTokens.svelte +236 -0
- package/dist/TwoFactor.svelte +544 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/{lib → dist}/index.js.map +1 -1
- package/jest.config.js +32 -0
- package/package.json +54 -43
- package/src/Account.svelte +280 -113
- package/src/ChangePassword.svelte +147 -51
- package/src/Login.svelte +328 -115
- package/src/Recover.svelte +180 -78
- package/src/RevokeTokens.svelte +236 -0
- package/src/TwoFactor.svelte +544 -0
- package/src/index.d.ts +3 -1
- package/src/index.ts +3 -1
- package/tsconfig.json +8 -4
- package/typedoc.json +4 -0
- package/dist/index.cjs +0 -3
- package/dist/index.cjs.LICENSE.txt +0 -45
- package/dist/index.cjs.map +0 -1
- package/jest.config.cjs +0 -6
- package/lib/Account.svelte +0 -333
- package/lib/Account.svelte.map +0 -1
- package/lib/ChangePassword.svelte +0 -188
- package/lib/ChangePassword.svelte.map +0 -1
- package/lib/Login.svelte +0 -353
- package/lib/Login.svelte.map +0 -1
- package/lib/Recover.svelte +0 -339
- package/lib/Recover.svelte.map +0 -1
- package/lib/index.d.ts +0 -5
- package/lib/index.js +0 -6
- package/webpack.config.cjs +0 -35
package/src/Account.svelte
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
{#if $clientConfig != null && $user != null}
|
|
2
4
|
<Dialog
|
|
3
|
-
use
|
|
5
|
+
{use}
|
|
4
6
|
bind:open
|
|
5
7
|
aria-labelledby="tilmeld-account-title"
|
|
6
8
|
aria-describedby="tilmeld-account-content"
|
|
7
9
|
surface$class="tilmeld-account-dialog-surface"
|
|
8
|
-
{...exclude(
|
|
10
|
+
{...exclude(restProps, [
|
|
9
11
|
'username$',
|
|
10
12
|
'email$',
|
|
11
13
|
'nameFirst$',
|
|
@@ -13,19 +15,22 @@
|
|
|
13
15
|
'nameLast$',
|
|
14
16
|
'phone$',
|
|
15
17
|
'changePasswordLink$',
|
|
18
|
+
'revokeTokensLink$',
|
|
16
19
|
'closeButton$',
|
|
17
20
|
'saveButton$',
|
|
18
21
|
'changePassword$',
|
|
22
|
+
'revokeTokens$',
|
|
23
|
+
'twoFactor$',
|
|
19
24
|
'progress$',
|
|
20
25
|
])}
|
|
21
26
|
>
|
|
22
27
|
<!-- Title cannot contain leading whitespace due to mdc-typography-baseline-top() -->
|
|
23
28
|
<Title id="tilmeld-account-title">{title}</Title>
|
|
24
29
|
<Content id="tilmeld-account-content">
|
|
25
|
-
{#if
|
|
30
|
+
{#if !$clientConfig.emailUsernames && $clientConfig.allowUsernameChange}
|
|
26
31
|
<div>
|
|
27
32
|
<Textfield
|
|
28
|
-
bind:value={user.username}
|
|
33
|
+
bind:value={$user.username}
|
|
29
34
|
label="Username"
|
|
30
35
|
type="text"
|
|
31
36
|
style="width: 100%;"
|
|
@@ -35,19 +40,21 @@
|
|
|
35
40
|
input$autocapitalize="off"
|
|
36
41
|
input$spellcheck="false"
|
|
37
42
|
input$emptyValueUndefined
|
|
38
|
-
{...prefixFilter(
|
|
43
|
+
{...prefixFilter(restProps, 'username$')}
|
|
39
44
|
>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
{#snippet helper()}
|
|
46
|
+
<HelperText persistent>
|
|
47
|
+
{usernameVerifiedMessage || ''}
|
|
48
|
+
</HelperText>
|
|
49
|
+
{/snippet}
|
|
43
50
|
</Textfield>
|
|
44
51
|
</div>
|
|
45
52
|
{/if}
|
|
46
53
|
|
|
47
|
-
{#if clientConfig.emailUsernames || clientConfig.userFields.
|
|
54
|
+
{#if $clientConfig.emailUsernames || $clientConfig.userFields.includes('email')}
|
|
48
55
|
<div>
|
|
49
56
|
<Textfield
|
|
50
|
-
bind:value={user.email}
|
|
57
|
+
bind:value={$user.email}
|
|
51
58
|
label="Email"
|
|
52
59
|
type="email"
|
|
53
60
|
style="width: 100%;"
|
|
@@ -57,203 +64,366 @@
|
|
|
57
64
|
input$autocapitalize="off"
|
|
58
65
|
input$spellcheck="false"
|
|
59
66
|
input$emptyValueUndefined
|
|
60
|
-
{...prefixFilter(
|
|
67
|
+
{...prefixFilter(restProps, 'email$')}
|
|
61
68
|
>
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
{#snippet helper()}
|
|
70
|
+
<HelperText persistent>
|
|
71
|
+
{emailVerifiedMessage || ''}
|
|
72
|
+
</HelperText>
|
|
73
|
+
{/snippet}
|
|
65
74
|
</Textfield>
|
|
66
75
|
</div>
|
|
67
76
|
{/if}
|
|
68
77
|
|
|
69
|
-
{#if clientConfig.userFields.
|
|
78
|
+
{#if $clientConfig.userFields.includes('name')}
|
|
70
79
|
<div>
|
|
71
80
|
<Textfield
|
|
72
|
-
bind:value={user.nameFirst}
|
|
81
|
+
bind:value={$user.nameFirst}
|
|
73
82
|
label="First Name"
|
|
74
83
|
type="text"
|
|
75
84
|
style="width: 100%;"
|
|
76
85
|
input$autocomplete="given-name"
|
|
77
86
|
input$emptyValueUndefined
|
|
78
|
-
{...prefixFilter(
|
|
87
|
+
{...prefixFilter(restProps, 'nameFirst$')}
|
|
79
88
|
/>
|
|
80
89
|
</div>
|
|
81
90
|
|
|
82
91
|
<div>
|
|
83
92
|
<Textfield
|
|
84
|
-
bind:value={user.nameMiddle}
|
|
93
|
+
bind:value={$user.nameMiddle}
|
|
85
94
|
label="Middle Name"
|
|
86
95
|
type="text"
|
|
87
96
|
style="width: 100%;"
|
|
88
97
|
input$autocomplete="additional-name"
|
|
89
98
|
input$emptyValueUndefined
|
|
90
|
-
{...prefixFilter(
|
|
99
|
+
{...prefixFilter(restProps, 'nameMiddle$')}
|
|
91
100
|
/>
|
|
92
101
|
</div>
|
|
93
102
|
|
|
94
103
|
<div>
|
|
95
104
|
<Textfield
|
|
96
|
-
bind:value={user.nameLast}
|
|
105
|
+
bind:value={$user.nameLast}
|
|
97
106
|
label="Last Name"
|
|
98
107
|
type="text"
|
|
99
108
|
style="width: 100%;"
|
|
100
109
|
input$autocomplete="family-name"
|
|
101
110
|
input$emptyValueUndefined
|
|
102
|
-
{...prefixFilter(
|
|
111
|
+
{...prefixFilter(restProps, 'nameLast$')}
|
|
103
112
|
/>
|
|
104
113
|
</div>
|
|
105
114
|
{/if}
|
|
106
115
|
|
|
107
|
-
{#if clientConfig.userFields.
|
|
116
|
+
{#if $clientConfig.userFields.includes('phone')}
|
|
108
117
|
<div>
|
|
109
118
|
<Textfield
|
|
110
|
-
bind:value={user.phone}
|
|
119
|
+
bind:value={$user.phone}
|
|
111
120
|
label="Phone Number"
|
|
112
121
|
type="tel"
|
|
113
122
|
style="width: 100%;"
|
|
114
123
|
input$autocomplete="tel"
|
|
115
124
|
input$name="phone"
|
|
116
125
|
input$emptyValueUndefined
|
|
117
|
-
{...prefixFilter(
|
|
126
|
+
{...prefixFilter(restProps, 'phone$')}
|
|
118
127
|
/>
|
|
119
128
|
</div>
|
|
120
129
|
{/if}
|
|
121
130
|
|
|
122
|
-
|
|
131
|
+
{@render additional?.()}
|
|
123
132
|
|
|
124
133
|
<div class="tilmeld-account-action">
|
|
125
134
|
<a
|
|
126
|
-
href=
|
|
127
|
-
|
|
135
|
+
href={'javascript:void(0);'}
|
|
136
|
+
onclick={() => {
|
|
128
137
|
open = false;
|
|
129
138
|
changePasswordOpen = true;
|
|
130
139
|
}}
|
|
131
|
-
{...prefixFilter(
|
|
140
|
+
{...prefixFilter(restProps, 'changePasswordLink$')}
|
|
132
141
|
>
|
|
133
142
|
Change your password.
|
|
134
143
|
</a>
|
|
135
144
|
</div>
|
|
136
145
|
|
|
137
|
-
|
|
138
|
-
<
|
|
139
|
-
{
|
|
140
|
-
|
|
141
|
-
|
|
146
|
+
<div class="tilmeld-account-action">
|
|
147
|
+
<a
|
|
148
|
+
href={'javascript:void(0);'}
|
|
149
|
+
onclick={() => {
|
|
150
|
+
open = false;
|
|
151
|
+
revokeTokensOpen = true;
|
|
152
|
+
}}
|
|
153
|
+
{...prefixFilter(restProps, 'revokeTokensLink$')}
|
|
154
|
+
>
|
|
155
|
+
Log out of other sessions.
|
|
156
|
+
</a>
|
|
142
157
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
158
|
+
<div class="tilmeld-account-action">
|
|
159
|
+
<a
|
|
160
|
+
href={'javascript:void(0);'}
|
|
161
|
+
onclick={() => {
|
|
162
|
+
open = false;
|
|
163
|
+
twoFactorOpen = true;
|
|
164
|
+
}}
|
|
165
|
+
{...prefixFilter(restProps, 'twoFactor$')}
|
|
166
|
+
>
|
|
167
|
+
{#if hasTOTPSecret === false}
|
|
168
|
+
Enable two factor authentication (2FA).
|
|
169
|
+
{:else}
|
|
170
|
+
Manage two factor authentication (2FA).
|
|
171
|
+
{/if}
|
|
172
|
+
</a>
|
|
150
173
|
</div>
|
|
151
|
-
|
|
174
|
+
|
|
175
|
+
{#if failureMessage}
|
|
176
|
+
<div class="tilmeld-account-failure">
|
|
177
|
+
{failureMessage}
|
|
178
|
+
</div>
|
|
179
|
+
{/if}
|
|
180
|
+
|
|
181
|
+
{#if loading}
|
|
182
|
+
<div class="tilmeld-account-loading">
|
|
183
|
+
<CircularProgress
|
|
184
|
+
style="height: 24px; width: 24px;"
|
|
185
|
+
indeterminate
|
|
186
|
+
{...prefixFilter(restProps, 'progress$')}
|
|
187
|
+
/>
|
|
188
|
+
</div>
|
|
189
|
+
{/if}
|
|
190
|
+
</div>
|
|
152
191
|
</Content>
|
|
153
192
|
<Actions>
|
|
154
|
-
<Button disabled={
|
|
193
|
+
<Button disabled={loading} {...prefixFilter(restProps, 'closeButton$')}>
|
|
155
194
|
<Label>Close</Label>
|
|
156
195
|
</Button>
|
|
157
196
|
<Button
|
|
158
|
-
|
|
159
|
-
disabled={
|
|
160
|
-
{...prefixFilter(
|
|
197
|
+
onclick={preventDefault(stopPropagation(save))}
|
|
198
|
+
disabled={loading}
|
|
199
|
+
{...prefixFilter(restProps, 'saveButton$')}
|
|
161
200
|
>
|
|
162
201
|
<Label>Save Changes</Label>
|
|
163
202
|
</Button>
|
|
164
203
|
</Actions>
|
|
165
204
|
</Dialog>
|
|
205
|
+
|
|
166
206
|
<ChangePassword
|
|
167
207
|
{User}
|
|
168
208
|
bind:open={changePasswordOpen}
|
|
169
209
|
bind:user
|
|
170
|
-
{...prefixFilter(
|
|
210
|
+
{...prefixFilter(restProps, 'changePassword$')}
|
|
211
|
+
/>
|
|
212
|
+
|
|
213
|
+
<RevokeTokens
|
|
214
|
+
{User}
|
|
215
|
+
bind:open={revokeTokensOpen}
|
|
216
|
+
bind:user
|
|
217
|
+
{...prefixFilter(restProps, 'revokeTokens$')}
|
|
218
|
+
/>
|
|
219
|
+
|
|
220
|
+
<TwoFactor
|
|
221
|
+
{User}
|
|
222
|
+
bind:open={twoFactorOpen}
|
|
223
|
+
bind:user
|
|
224
|
+
bind:hasTOTPSecret
|
|
225
|
+
{...prefixFilter(restProps, 'twoFactor$')}
|
|
171
226
|
/>
|
|
172
227
|
{/if}
|
|
173
228
|
|
|
174
229
|
<script lang="ts">
|
|
230
|
+
import type { ComponentProps, Snippet } from 'svelte';
|
|
175
231
|
import { onMount, onDestroy } from 'svelte';
|
|
176
|
-
import {
|
|
232
|
+
import type { Writable } from 'svelte/store';
|
|
233
|
+
import { writable } from 'svelte/store';
|
|
177
234
|
import CircularProgress from '@smui/circular-progress';
|
|
178
235
|
import Dialog, { Title, Content, Actions } from '@smui/dialog';
|
|
179
236
|
import Textfield from '@smui/textfield';
|
|
180
237
|
import HelperText from '@smui/textfield/helper-text';
|
|
181
238
|
import Button, { Label } from '@smui/button';
|
|
182
239
|
import type { ActionArray } from '@smui/common/internal';
|
|
183
|
-
import {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
prefixFilter,
|
|
187
|
-
} from '@smui/common/internal';
|
|
240
|
+
import { exclude, prefixFilter } from '@smui/common/internal';
|
|
241
|
+
import { preventDefault, stopPropagation } from '@smui/common/events';
|
|
242
|
+
import type { SmuiElementPropMap } from '@smui/common';
|
|
188
243
|
import type { ClientConfig, CurrentUserData } from '@nymphjs/tilmeld-client';
|
|
189
244
|
import type { User as UserClass } from '@nymphjs/tilmeld-client';
|
|
190
245
|
import ChangePassword from './ChangePassword.svelte';
|
|
246
|
+
import RevokeTokens from './RevokeTokens.svelte';
|
|
247
|
+
import TwoFactor from './TwoFactor.svelte';
|
|
191
248
|
|
|
192
|
-
|
|
249
|
+
type OwnProps = {
|
|
250
|
+
/**
|
|
251
|
+
* An array of Action or [Action, ActionProps] to be applied to the element.
|
|
252
|
+
*/
|
|
253
|
+
use?: ActionArray;
|
|
254
|
+
/**
|
|
255
|
+
* Whether the dialog is open.
|
|
256
|
+
*/
|
|
257
|
+
open?: boolean;
|
|
258
|
+
/**
|
|
259
|
+
* The title of the dialog.
|
|
260
|
+
*/
|
|
261
|
+
title?: string;
|
|
262
|
+
/**
|
|
263
|
+
* A writable store of the Nymph client config.
|
|
264
|
+
*
|
|
265
|
+
* It will be retrieved from the server if not provided.
|
|
266
|
+
*/
|
|
267
|
+
clientConfig?: Writable<ClientConfig | undefined>;
|
|
268
|
+
/**
|
|
269
|
+
* The User class from Nymph.
|
|
270
|
+
*/
|
|
271
|
+
User: typeof UserClass;
|
|
272
|
+
/**
|
|
273
|
+
* A writable store of the current user.
|
|
274
|
+
*
|
|
275
|
+
* It will be retrieved from the server if not provided.
|
|
276
|
+
*/
|
|
277
|
+
user?: Writable<(UserClass & CurrentUserData) | null | undefined>;
|
|
193
278
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
279
|
+
/**
|
|
280
|
+
* A spot for additional content.
|
|
281
|
+
*/
|
|
282
|
+
additional?: Snippet;
|
|
283
|
+
};
|
|
284
|
+
let {
|
|
285
|
+
use = [],
|
|
286
|
+
open = $bindable(false),
|
|
287
|
+
title = 'Your Account',
|
|
288
|
+
clientConfig = $bindable(writable(false as unknown as undefined)),
|
|
289
|
+
User,
|
|
290
|
+
user = $bindable(writable(false as unknown as undefined)),
|
|
291
|
+
additional,
|
|
292
|
+
...restProps
|
|
293
|
+
}: OwnProps & {
|
|
294
|
+
[
|
|
295
|
+
k in keyof ComponentProps<typeof Textfield> as `username\$${k}`
|
|
296
|
+
]?: ComponentProps<typeof Textfield>[k];
|
|
297
|
+
} & {
|
|
298
|
+
[
|
|
299
|
+
k in keyof ComponentProps<typeof Textfield> as `email\$${k}`
|
|
300
|
+
]?: ComponentProps<typeof Textfield>[k];
|
|
301
|
+
} & {
|
|
302
|
+
[
|
|
303
|
+
k in keyof ComponentProps<typeof Textfield> as `nameFirst\$${k}`
|
|
304
|
+
]?: ComponentProps<typeof Textfield>[k];
|
|
305
|
+
} & {
|
|
306
|
+
[
|
|
307
|
+
k in keyof ComponentProps<typeof Textfield> as `nameMiddle\$${k}`
|
|
308
|
+
]?: ComponentProps<typeof Textfield>[k];
|
|
309
|
+
} & {
|
|
310
|
+
[
|
|
311
|
+
k in keyof ComponentProps<typeof Textfield> as `nameLast\$${k}`
|
|
312
|
+
]?: ComponentProps<typeof Textfield>[k];
|
|
313
|
+
} & {
|
|
314
|
+
[
|
|
315
|
+
k in keyof ComponentProps<typeof Textfield> as `phone\$${k}`
|
|
316
|
+
]?: ComponentProps<typeof Textfield>[k];
|
|
317
|
+
} & {
|
|
318
|
+
[
|
|
319
|
+
k in keyof SmuiElementPropMap['a'] as `changePasswordLink\$${k}`
|
|
320
|
+
]?: SmuiElementPropMap['a'][k];
|
|
321
|
+
} & {
|
|
322
|
+
[
|
|
323
|
+
k in keyof SmuiElementPropMap['a'] as `revokeTokensLink\$${k}`
|
|
324
|
+
]?: SmuiElementPropMap['a'][k];
|
|
325
|
+
} & {
|
|
326
|
+
[
|
|
327
|
+
k in keyof ComponentProps<typeof CircularProgress> as `progress\$${k}`
|
|
328
|
+
]?: ComponentProps<typeof CircularProgress>[k];
|
|
329
|
+
} & {
|
|
330
|
+
[
|
|
331
|
+
k in keyof ComponentProps<
|
|
332
|
+
typeof Button<undefined, 'button'>
|
|
333
|
+
> as `closeButton\$${k}`
|
|
334
|
+
]?: ComponentProps<typeof Button<undefined, 'button'>>[k];
|
|
335
|
+
} & {
|
|
336
|
+
[
|
|
337
|
+
k in keyof ComponentProps<
|
|
338
|
+
typeof Button<undefined, 'button'>
|
|
339
|
+
> as `saveButton\$${k}`
|
|
340
|
+
]?: ComponentProps<typeof Button<undefined, 'button'>>[k];
|
|
341
|
+
} & {
|
|
342
|
+
[
|
|
343
|
+
k in keyof ComponentProps<typeof ChangePassword> as `changePassword\$${k}`
|
|
344
|
+
]?: ComponentProps<typeof ChangePassword>[k];
|
|
345
|
+
} & {
|
|
346
|
+
[
|
|
347
|
+
k in keyof ComponentProps<typeof RevokeTokens> as `revokeTokens\$${k}`
|
|
348
|
+
]?: ComponentProps<typeof RevokeTokens>[k];
|
|
349
|
+
} & {
|
|
350
|
+
[
|
|
351
|
+
k in keyof ComponentProps<typeof TwoFactor> as `twoFactor\$${k}`
|
|
352
|
+
]?: ComponentProps<typeof TwoFactor>[k];
|
|
353
|
+
} = $props();
|
|
201
354
|
|
|
202
|
-
let
|
|
203
|
-
let originalUsername: string | undefined =
|
|
204
|
-
let originalEmail: string | undefined =
|
|
205
|
-
let failureMessage: string | undefined =
|
|
206
|
-
let usernameTimer:
|
|
207
|
-
let usernameVerified: boolean | undefined =
|
|
208
|
-
let usernameVerifiedMessage: string | undefined =
|
|
209
|
-
let emailTimer:
|
|
210
|
-
let emailVerified: boolean | undefined =
|
|
211
|
-
let emailVerifiedMessage: string | undefined =
|
|
212
|
-
let
|
|
355
|
+
let loading = $state(false);
|
|
356
|
+
let originalUsername: string | undefined = $user?.username;
|
|
357
|
+
let originalEmail: string | undefined = $user?.email;
|
|
358
|
+
let failureMessage: string | undefined = $state();
|
|
359
|
+
let usernameTimer: number | undefined = undefined;
|
|
360
|
+
let usernameVerified: boolean | undefined = $state();
|
|
361
|
+
let usernameVerifiedMessage: string | undefined = $state();
|
|
362
|
+
let emailTimer: number | undefined = undefined;
|
|
363
|
+
let emailVerified: boolean | undefined = $state();
|
|
364
|
+
let emailVerifiedMessage: string | undefined = $state();
|
|
365
|
+
let hasTOTPSecret: boolean | null = $state(null);
|
|
366
|
+
let changePasswordOpen = $state(false);
|
|
367
|
+
let revokeTokensOpen = $state(false);
|
|
368
|
+
let twoFactorOpen = $state(false);
|
|
213
369
|
|
|
214
370
|
const onLogin = (currentUser: UserClass & CurrentUserData) => {
|
|
215
|
-
user = currentUser;
|
|
216
|
-
originalUsername = user?.username;
|
|
217
|
-
originalEmail = user?.email;
|
|
371
|
+
$user = currentUser;
|
|
372
|
+
originalUsername = $user?.username;
|
|
373
|
+
originalEmail = $user?.email;
|
|
218
374
|
};
|
|
219
375
|
const onLogout = () => {
|
|
220
|
-
user =
|
|
376
|
+
$user = null;
|
|
221
377
|
originalUsername = undefined;
|
|
222
378
|
originalEmail = undefined;
|
|
223
379
|
};
|
|
224
380
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
381
|
+
$effect(() => {
|
|
382
|
+
if ($user && $user.username !== originalUsername) {
|
|
383
|
+
if ($user.$isDirty('username')) {
|
|
384
|
+
checkUsername();
|
|
385
|
+
} else {
|
|
386
|
+
originalUsername = $user.username;
|
|
387
|
+
}
|
|
388
|
+
} else {
|
|
389
|
+
if (usernameTimer) {
|
|
390
|
+
clearTimeout(usernameTimer);
|
|
391
|
+
}
|
|
392
|
+
usernameVerified = true;
|
|
393
|
+
usernameVerifiedMessage = undefined;
|
|
230
394
|
}
|
|
231
|
-
|
|
232
|
-
usernameVerifiedMessage = undefined;
|
|
233
|
-
}
|
|
395
|
+
});
|
|
234
396
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
397
|
+
$effect(() => {
|
|
398
|
+
if ($user && $user.email !== originalEmail) {
|
|
399
|
+
if ($user.$isDirty('email')) {
|
|
400
|
+
checkEmail();
|
|
401
|
+
} else {
|
|
402
|
+
originalEmail = $user.email;
|
|
403
|
+
}
|
|
404
|
+
} else {
|
|
405
|
+
if (emailTimer) {
|
|
406
|
+
clearTimeout(emailTimer);
|
|
407
|
+
}
|
|
408
|
+
emailVerified = true;
|
|
409
|
+
emailVerifiedMessage = undefined;
|
|
240
410
|
}
|
|
241
|
-
|
|
242
|
-
emailVerifiedMessage = undefined;
|
|
243
|
-
}
|
|
411
|
+
});
|
|
244
412
|
|
|
245
413
|
onMount(async () => {
|
|
246
414
|
User.on('login', onLogin);
|
|
247
415
|
User.on('logout', onLogout);
|
|
248
|
-
if (user === undefined) {
|
|
249
|
-
user =
|
|
416
|
+
if ($user === (false as unknown as undefined)) {
|
|
417
|
+
$user = undefined;
|
|
418
|
+
$user = await User.current();
|
|
250
419
|
}
|
|
251
|
-
originalUsername = user?.username;
|
|
252
|
-
originalEmail = user?.email;
|
|
420
|
+
originalUsername = $user?.username;
|
|
421
|
+
originalEmail = $user?.email;
|
|
253
422
|
});
|
|
254
423
|
onMount(async () => {
|
|
255
|
-
if (clientConfig === undefined) {
|
|
256
|
-
clientConfig =
|
|
424
|
+
if ($clientConfig === (false as unknown as undefined)) {
|
|
425
|
+
$clientConfig = undefined;
|
|
426
|
+
$clientConfig = await User.getClientConfig();
|
|
257
427
|
}
|
|
258
428
|
});
|
|
259
429
|
|
|
@@ -263,30 +433,27 @@
|
|
|
263
433
|
});
|
|
264
434
|
|
|
265
435
|
async function save() {
|
|
266
|
-
if (user == null) {
|
|
436
|
+
if ($user == null) {
|
|
267
437
|
return;
|
|
268
438
|
}
|
|
269
439
|
|
|
270
440
|
failureMessage = undefined;
|
|
271
|
-
|
|
441
|
+
loading = true;
|
|
272
442
|
|
|
273
|
-
if (clientConfig?.emailUsernames) {
|
|
274
|
-
user.username = user.email;
|
|
443
|
+
if ($clientConfig?.emailUsernames) {
|
|
444
|
+
$user.username = $user.email;
|
|
275
445
|
}
|
|
276
446
|
|
|
277
447
|
try {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
} else {
|
|
284
|
-
failureMessage = 'Error saving account changes.';
|
|
285
|
-
}
|
|
448
|
+
await $user.$save();
|
|
449
|
+
originalEmail = $user.email;
|
|
450
|
+
open = false;
|
|
451
|
+
usernameVerifiedMessage = undefined;
|
|
452
|
+
emailVerifiedMessage = undefined;
|
|
286
453
|
} catch (e: any) {
|
|
287
454
|
failureMessage = e?.message;
|
|
288
455
|
}
|
|
289
|
-
|
|
456
|
+
loading = false;
|
|
290
457
|
}
|
|
291
458
|
|
|
292
459
|
function checkUsername() {
|
|
@@ -298,7 +465,7 @@
|
|
|
298
465
|
}
|
|
299
466
|
usernameTimer = setTimeout(async () => {
|
|
300
467
|
try {
|
|
301
|
-
const data = await user?.$checkUsername();
|
|
468
|
+
const data = await $user?.$checkUsername();
|
|
302
469
|
usernameVerified = data?.result ?? false;
|
|
303
470
|
usernameVerifiedMessage =
|
|
304
471
|
data?.message ?? 'Error getting verification.';
|
|
@@ -318,7 +485,7 @@
|
|
|
318
485
|
}
|
|
319
486
|
emailTimer = setTimeout(async () => {
|
|
320
487
|
try {
|
|
321
|
-
const data = await user?.$checkEmail();
|
|
488
|
+
const data = await $user?.$checkEmail();
|
|
322
489
|
emailVerified = data?.result ?? false;
|
|
323
490
|
emailVerifiedMessage = data?.message ?? 'Error getting verification.';
|
|
324
491
|
} catch (e: any) {
|