@functionalcms/svelte-components 5.24.1 → 5.24.3
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/dist/components/form/SmartForm.svelte +46 -77
- package/dist/components/form/form.d.ts +1 -1
- package/dist/components/form/form.js +3 -2
- package/package.json +1 -1
- package/src/pages/auth/setup/[email]/+page.server.ts +15 -7
- package/src/pages/auth/setup/[email]/+page.svelte +27 -9
- package/src/pages/auth/setup/[email]/fields.ts +23 -0
|
@@ -12,12 +12,8 @@
|
|
|
12
12
|
type HiddenField,
|
|
13
13
|
type DatePickerField,
|
|
14
14
|
SubmitResult,
|
|
15
|
-
|
|
16
15
|
type MarkdownEditorField,
|
|
17
|
-
|
|
18
16
|
type HtmlEditorField
|
|
19
|
-
|
|
20
|
-
|
|
21
17
|
} from './form.js';
|
|
22
18
|
import {
|
|
23
19
|
Button,
|
|
@@ -42,6 +38,7 @@
|
|
|
42
38
|
class?: string;
|
|
43
39
|
successMessage?: string;
|
|
44
40
|
fields?: Array<Field>;
|
|
41
|
+
errors?: Map<string, string>;
|
|
45
42
|
onMessageSubmitted?: (result: SubmitResult) => void;
|
|
46
43
|
buttons: Array<ButtonConfig>;
|
|
47
44
|
}
|
|
@@ -49,6 +46,7 @@
|
|
|
49
46
|
let {
|
|
50
47
|
action,
|
|
51
48
|
fields = [],
|
|
49
|
+
errors = new Map(),
|
|
52
50
|
class: css = '',
|
|
53
51
|
successMessage,
|
|
54
52
|
onMessageSubmitted,
|
|
@@ -61,10 +59,10 @@
|
|
|
61
59
|
]
|
|
62
60
|
}: Props = $props();
|
|
63
61
|
|
|
62
|
+
let formErrors = errors ?? new Map<string, string>();
|
|
63
|
+
|
|
64
64
|
let form: HTMLFormElement;
|
|
65
65
|
let showMessage = $state(false);
|
|
66
|
-
let isSendingMessage = $state(false);
|
|
67
|
-
let loading = $state(false);
|
|
68
66
|
|
|
69
67
|
const isValid = (event: Event) => {
|
|
70
68
|
debugger;
|
|
@@ -78,36 +76,16 @@
|
|
|
78
76
|
return allValid;
|
|
79
77
|
};
|
|
80
78
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
loading = true;
|
|
85
|
-
debugger;
|
|
86
|
-
try {
|
|
87
|
-
if (isValid(event) && !isSendingMessage) {
|
|
88
|
-
isSendingMessage = true;
|
|
89
|
-
const formData = new FormData(form);
|
|
90
|
-
const response = await fetch(action, {
|
|
91
|
-
method: 'POST',
|
|
92
|
-
body: formData
|
|
93
|
-
});
|
|
94
|
-
showMessage = response.status === 200;
|
|
95
|
-
onMessageSubmitted?.(showMessage ? SubmitResult.Success : SubmitResult.Error);
|
|
96
|
-
setTimeout(() => {
|
|
97
|
-
showMessage = false;
|
|
98
|
-
}, 3000);
|
|
99
|
-
}else {
|
|
100
|
-
console.warn('Form is invalid or already sending message');
|
|
101
|
-
}
|
|
102
|
-
} catch (error) {
|
|
103
|
-
console.error('Error submitting form:', error);
|
|
104
|
-
} finally {
|
|
105
|
-
isSendingMessage = false;
|
|
106
|
-
}
|
|
107
|
-
loading = false;
|
|
108
|
-
};
|
|
79
|
+
function hasErrors(field: any, errors: Map<string, string>) {
|
|
80
|
+
return errors.has(fields?.id) ? 'error' : '';
|
|
81
|
+
}
|
|
109
82
|
</script>
|
|
110
83
|
|
|
84
|
+
{#snippet showErrors(fields: InputField, errors: Map<string, string>)}
|
|
85
|
+
{#if errors.has(fields.id)}
|
|
86
|
+
<div>errors.get(fields.id)</div>
|
|
87
|
+
{/if}
|
|
88
|
+
{/snippet}
|
|
111
89
|
{#snippet renderInput(field: InputField)}
|
|
112
90
|
{#if field.isFloat}
|
|
113
91
|
<FloatingLabelInput
|
|
@@ -255,53 +233,44 @@
|
|
|
255
233
|
<form method="POST" {action} class={css} bind:this={form}>
|
|
256
234
|
<fieldset>
|
|
257
235
|
{#each fields as field}
|
|
258
|
-
{
|
|
259
|
-
{
|
|
260
|
-
|
|
261
|
-
{
|
|
262
|
-
|
|
263
|
-
{
|
|
264
|
-
|
|
265
|
-
{
|
|
266
|
-
|
|
267
|
-
{
|
|
268
|
-
|
|
269
|
-
{
|
|
270
|
-
|
|
271
|
-
{
|
|
272
|
-
|
|
273
|
-
{
|
|
274
|
-
|
|
275
|
-
{
|
|
276
|
-
|
|
277
|
-
{
|
|
278
|
-
|
|
279
|
-
{
|
|
280
|
-
|
|
236
|
+
<div class={hasErrors(field, formErrors)}>
|
|
237
|
+
{#if field.typeOfField === 'input'}
|
|
238
|
+
{@render renderInput(field)}
|
|
239
|
+
{:else if field.typeOfField === 'textarea'}
|
|
240
|
+
{@render renderTextarea(field)}
|
|
241
|
+
{:else if field.typeOfField === 'select'}
|
|
242
|
+
{@render renderSelect(field)}
|
|
243
|
+
{:else if field.typeOfField === 'collection'}
|
|
244
|
+
{@render renderCollection(field)}
|
|
245
|
+
{:else if field.typeOfField === 'file'}
|
|
246
|
+
{@render renderFile(field)}
|
|
247
|
+
{:else if field.typeOfField === 'phoneInput'}
|
|
248
|
+
{@render renderPhoneInput(field)}
|
|
249
|
+
{:else if field.typeOfField === 'timepicker'}
|
|
250
|
+
{@render renderTimePicker(field)}
|
|
251
|
+
{:else if field.typeOfField === 'hidden'}
|
|
252
|
+
{@render renderHidden(field)}
|
|
253
|
+
{:else if field.typeOfField === 'date'}
|
|
254
|
+
{@render renderDatePicker(field)}
|
|
255
|
+
{:else if field.typeOfField === 'markdown'}
|
|
256
|
+
{@render renderMdEditory(field)}
|
|
257
|
+
{:else if field.typeOfField === 'html'}
|
|
258
|
+
{@render renderHtmlEditory(field)}
|
|
259
|
+
{/if}
|
|
260
|
+
{@render showErrors(field, formErrors)}
|
|
261
|
+
</div>
|
|
281
262
|
{/each}
|
|
282
263
|
|
|
283
264
|
<div class="buttons">
|
|
284
265
|
{#each buttons as button}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
{button.label}
|
|
294
|
-
</Button>
|
|
295
|
-
{:else} -->
|
|
296
|
-
<Button
|
|
297
|
-
type={button.type}
|
|
298
|
-
class={button.class}
|
|
299
|
-
color={button.color}
|
|
300
|
-
onclick={button.action}
|
|
301
|
-
>
|
|
302
|
-
{button.label}
|
|
303
|
-
</Button>
|
|
304
|
-
<!-- {/if} -->
|
|
266
|
+
<Button
|
|
267
|
+
type={button.type}
|
|
268
|
+
class={button.class}
|
|
269
|
+
color={button.color}
|
|
270
|
+
onclick={button.action}
|
|
271
|
+
>
|
|
272
|
+
{button.label}
|
|
273
|
+
</Button>
|
|
305
274
|
{/each}
|
|
306
275
|
</div>
|
|
307
276
|
</fieldset>
|
|
@@ -128,4 +128,4 @@ export type ButtonConfig = {
|
|
|
128
128
|
class?: string;
|
|
129
129
|
action?: (event: Event) => Promise<void>;
|
|
130
130
|
};
|
|
131
|
-
export declare function convertResponseToFields(fields: Array<Field>,
|
|
131
|
+
export declare function convertResponseToFields(fields: Array<Field>, request: Request): Promise<any>;
|
|
@@ -124,10 +124,11 @@ export function createEditorField(id, label, type, value) {
|
|
|
124
124
|
typeOfField: type,
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
|
-
export function convertResponseToFields(fields,
|
|
127
|
+
export async function convertResponseToFields(fields, request) {
|
|
128
|
+
const formData = await request.formData();
|
|
128
129
|
let result = {};
|
|
129
130
|
for (const field of fields) {
|
|
130
|
-
const value =
|
|
131
|
+
const value = formData.get(field.id);
|
|
131
132
|
result[field.id] = value;
|
|
132
133
|
}
|
|
133
134
|
return result;
|
package/package.json
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
import { DOMAIN } from '$env/static/private';
|
|
2
2
|
import { getUsersService } from '@functionalcms/svelte-components/index-server.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { convertResponseToFields } from '@functionalcms/svelte-components';
|
|
4
|
+
import { fields } from './fields';
|
|
5
5
|
/** @type {import('./$types').PageServerLoad} */
|
|
6
|
-
export async function load({ params }) {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
return { code };
|
|
6
|
+
export async function load({ params, locals, url }) {
|
|
7
|
+
const username = params.email;
|
|
8
|
+
return { username, success: false };
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
export const actions = {
|
|
13
|
-
setup: async ({ request, locals, params }) => {
|
|
12
|
+
setup: async ({ request, locals, params, url }) => {
|
|
14
13
|
const userService = getUsersService(locals);
|
|
14
|
+
const code = url.searchParams.get("code");
|
|
15
|
+
|
|
16
|
+
const data = await convertResponseToFields(fields, request);
|
|
17
|
+
|
|
18
|
+
if (data.password != data.confirm) {
|
|
19
|
+
return {
|
|
20
|
+
errors: new Map<string, string>([["confirm", m.auth_password_do_not_match()]])
|
|
21
|
+
}
|
|
22
|
+
}
|
|
15
23
|
|
|
16
24
|
const result = await userService.setup(DOMAIN, params.email);
|
|
17
25
|
|
|
@@ -1,25 +1,33 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import {
|
|
3
3
|
Button,
|
|
4
|
+
createInputField,
|
|
5
|
+
InputType,
|
|
6
|
+
SmartForm,
|
|
4
7
|
Spinner,
|
|
5
8
|
} from "@functionalcms/svelte-components";
|
|
6
9
|
import * as m from "$lib/paraglide/messages.js";
|
|
7
10
|
import { deserialize } from "$app/forms";
|
|
11
|
+
import { fields } from "./fields.js";
|
|
8
12
|
|
|
9
13
|
interface Props {
|
|
10
14
|
data: {
|
|
11
|
-
|
|
15
|
+
username: string | null;
|
|
16
|
+
errors: string
|
|
12
17
|
};
|
|
18
|
+
form: any
|
|
13
19
|
}
|
|
14
20
|
|
|
15
|
-
let { data } = $props();
|
|
21
|
+
let { data, form = {} } = $props();
|
|
16
22
|
|
|
23
|
+
let submitError = $state(false);
|
|
17
24
|
|
|
18
25
|
let isProcesing = $state(false);
|
|
19
26
|
let resultMessage = $state("");
|
|
20
27
|
|
|
21
28
|
async function resetPassword() {
|
|
22
29
|
isProcesing = true;
|
|
30
|
+
submitError = false;
|
|
23
31
|
|
|
24
32
|
const response = await fetch("?/setup", {
|
|
25
33
|
method: "POST",
|
|
@@ -42,21 +50,31 @@
|
|
|
42
50
|
class="flex flex-col justify-around items-center gap-4 w-full m-auto p-4"
|
|
43
51
|
>
|
|
44
52
|
<h1>{m.auth_setup_title()}</h1>
|
|
45
|
-
{#if !data.
|
|
53
|
+
{#if !data.username}
|
|
46
54
|
<p>{m.auth_setup_missing_code()}</p>
|
|
47
55
|
{:else}
|
|
48
56
|
<div>
|
|
49
57
|
{@html m.auth_setup_into()}
|
|
50
58
|
</div>
|
|
51
|
-
<
|
|
52
|
-
{
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
{
|
|
56
|
-
|
|
59
|
+
<SmartForm
|
|
60
|
+
{fields}
|
|
61
|
+
errors={form?.errors}
|
|
62
|
+
action="?/setup"
|
|
63
|
+
buttons={[
|
|
64
|
+
{
|
|
65
|
+
type: "submit",
|
|
66
|
+
label: m.auth_submit(),
|
|
67
|
+
color: "primary",
|
|
68
|
+
},
|
|
69
|
+
]}
|
|
70
|
+
/>
|
|
57
71
|
{#if resultMessage != ""}
|
|
58
72
|
<p>{resultMessage}</p>
|
|
59
73
|
{/if}
|
|
74
|
+
|
|
75
|
+
{#if submitError}
|
|
76
|
+
<p class="text-red-600">{m.auth_setup_error()}</p>
|
|
77
|
+
{/if}
|
|
60
78
|
{/if}
|
|
61
79
|
</main>
|
|
62
80
|
</article>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { m } from "$lib/paraglide/messages";
|
|
2
|
+
import { createInputField, InputType } from "@functionalcms/svelte-components";
|
|
3
|
+
|
|
4
|
+
export const fields = [
|
|
5
|
+
createInputField(
|
|
6
|
+
"password",
|
|
7
|
+
m.auth_password(),
|
|
8
|
+
InputType.Password,
|
|
9
|
+
"",
|
|
10
|
+
{
|
|
11
|
+
required: true,
|
|
12
|
+
},
|
|
13
|
+
),
|
|
14
|
+
createInputField(
|
|
15
|
+
"confirm",
|
|
16
|
+
m.auth_comnfirm_password(),
|
|
17
|
+
InputType.Password,
|
|
18
|
+
"",
|
|
19
|
+
{
|
|
20
|
+
required: true,
|
|
21
|
+
},
|
|
22
|
+
),
|
|
23
|
+
];
|