2023-04-20 05:41:34 +02:00
|
|
|
import React from "react";
|
2024-06-03 00:11:19 +02:00
|
|
|
import type { Meta, StoryObj } from "@storybook/react";
|
2024-06-09 11:53:25 +02:00
|
|
|
import { createKcPageStory } from "../KcPageStory";
|
2024-06-28 06:46:26 +02:00
|
|
|
import type { Attribute } from "../../../dist/login";
|
2023-04-20 05:41:34 +02:00
|
|
|
|
2024-06-09 11:53:25 +02:00
|
|
|
const { KcPageStory } = createKcPageStory({ pageId: "register.ftl" });
|
2023-04-20 05:41:34 +02:00
|
|
|
|
2024-06-03 00:11:19 +02:00
|
|
|
const meta = {
|
2024-06-06 07:28:34 +02:00
|
|
|
title: "login/register.ftl",
|
2024-06-09 11:53:25 +02:00
|
|
|
component: KcPageStory
|
|
|
|
} satisfies Meta<typeof KcPageStory>;
|
2023-04-20 05:41:34 +02:00
|
|
|
|
|
|
|
export default meta;
|
|
|
|
|
2024-06-03 00:11:19 +02:00
|
|
|
type Story = StoryObj<typeof meta>;
|
|
|
|
|
|
|
|
export const Default: Story = {
|
2024-06-09 11:53:25 +02:00
|
|
|
render: () => <KcPageStory />
|
2024-06-03 00:11:19 +02:00
|
|
|
};
|
2024-06-02 22:29:53 +02:00
|
|
|
|
2024-06-12 23:11:06 +02:00
|
|
|
export const WithEmailAlreadyExists: Story = {
|
2024-06-03 00:11:19 +02:00
|
|
|
render: () => (
|
2024-06-09 11:53:25 +02:00
|
|
|
<KcPageStory
|
2024-06-03 00:11:19 +02:00
|
|
|
kcContext={{
|
|
|
|
profile: {
|
2024-06-03 23:54:08 +02:00
|
|
|
attributesByName: {
|
2024-06-12 23:11:06 +02:00
|
|
|
username: {
|
|
|
|
value: "johndoe"
|
|
|
|
},
|
2024-06-03 23:54:08 +02:00
|
|
|
email: {
|
2024-06-12 23:11:06 +02:00
|
|
|
value: "jhon.doe@gmail.com"
|
|
|
|
},
|
|
|
|
firstName: {
|
|
|
|
value: "John"
|
|
|
|
},
|
|
|
|
lastName: {
|
|
|
|
value: "Doe"
|
2024-06-03 00:11:19 +02:00
|
|
|
}
|
2024-06-03 23:54:08 +02:00
|
|
|
}
|
2024-06-03 00:11:19 +02:00
|
|
|
},
|
|
|
|
messagesPerField: {
|
2024-06-12 23:11:06 +02:00
|
|
|
// NOTE: The other functions of messagesPerField are derived from get() and
|
|
|
|
// existsError() so they are the only ones that need to mock.
|
|
|
|
existsError: (fieldName: string, ...otherFieldNames: string[]) => [fieldName, ...otherFieldNames].includes("email"),
|
|
|
|
get: (fieldName: string) => (fieldName === "email" ? "Email already exists." : undefined)
|
2024-06-03 00:11:19 +02:00
|
|
|
}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
};
|
2024-06-02 22:29:53 +02:00
|
|
|
|
2024-06-28 06:46:26 +02:00
|
|
|
export const WithRestrictedToMITStudents: Story = {
|
2024-06-03 00:11:19 +02:00
|
|
|
render: () => (
|
2024-06-09 11:53:25 +02:00
|
|
|
<KcPageStory
|
2024-06-03 00:11:19 +02:00
|
|
|
kcContext={{
|
2024-06-28 06:46:26 +02:00
|
|
|
profile: {
|
|
|
|
attributesByName: {
|
|
|
|
email: {
|
|
|
|
validators: {
|
|
|
|
pattern: {
|
|
|
|
pattern: "^[^@]+@([^.]+\\.)*((mit\\.edu)|(berkeley\\.edu))$",
|
|
|
|
"error-message": "${profile.attributes.email.pattern.error}"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
annotations: {
|
|
|
|
inputHelperTextBefore: "${profile.attributes.email.inputHelperTextBefore}"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"x-keycloakify": {
|
2024-07-10 22:18:24 +02:00
|
|
|
messages: {
|
2024-07-13 09:07:11 +02:00
|
|
|
"profile.attributes.email.inputHelperTextBefore": "Please use your MIT or Berkeley email.",
|
|
|
|
"profile.attributes.email.pattern.error":
|
2024-06-28 06:46:26 +02:00
|
|
|
"This is not an MIT (<strong>@mit.edu</strong>) nor a Berkeley (<strong>@berkeley.edu</strong>) email."
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
export const WithFavoritePet: Story = {
|
|
|
|
render: () => (
|
|
|
|
<KcPageStory
|
|
|
|
kcContext={{
|
|
|
|
profile: {
|
|
|
|
attributesByName: {
|
|
|
|
favoritePet: {
|
|
|
|
name: "favorite-pet",
|
|
|
|
displayName: "${profile.attributes.favoritePet}",
|
|
|
|
validators: {
|
|
|
|
options: {
|
|
|
|
options: ["cat", "dog", "fish"]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
annotations: {
|
|
|
|
inputOptionLabelsI18nPrefix: "profile.attributes.favoritePet.options"
|
|
|
|
},
|
|
|
|
required: false,
|
|
|
|
readOnly: false
|
|
|
|
} satisfies Attribute
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"x-keycloakify": {
|
2024-07-10 22:18:24 +02:00
|
|
|
messages: {
|
2024-07-13 09:07:11 +02:00
|
|
|
"profile.attributes.favoritePet": "Favorite Pet",
|
|
|
|
"profile.attributes.favoritePet.options.cat": "Fluffy Cat",
|
|
|
|
"profile.attributes.favoritePet.options.dog": "Loyal Dog",
|
|
|
|
"profile.attributes.favoritePet.options.fish": "Peaceful Fish"
|
2024-06-28 06:46:26 +02:00
|
|
|
}
|
2024-06-03 00:11:19 +02:00
|
|
|
}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
};
|
2024-06-02 22:29:53 +02:00
|
|
|
|
2024-10-02 16:16:16 +02:00
|
|
|
export const WithNewsletter: Story = {
|
|
|
|
render: () => (
|
|
|
|
<KcPageStory
|
|
|
|
kcContext={{
|
|
|
|
profile: {
|
|
|
|
attributesByName: {
|
|
|
|
newsletter: {
|
|
|
|
name: "newsletter",
|
|
|
|
displayName: "Sign up to the newsletter",
|
|
|
|
validators: {
|
|
|
|
options: {
|
|
|
|
options: ["yes"]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
annotations: {
|
|
|
|
inputOptionLabels: {
|
2024-10-06 09:03:15 +02:00
|
|
|
yes: "I want my email inbox filled with spam"
|
2024-10-02 16:16:16 +02:00
|
|
|
},
|
|
|
|
inputType: "multiselect-checkboxes"
|
|
|
|
},
|
|
|
|
required: false,
|
|
|
|
readOnly: false
|
|
|
|
} satisfies Attribute
|
|
|
|
}
|
2024-10-06 09:03:15 +02:00
|
|
|
}
|
2024-10-02 16:16:16 +02:00
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2024-06-28 06:46:26 +02:00
|
|
|
export const WithEmailAsUsername: Story = {
|
2024-06-03 00:11:19 +02:00
|
|
|
render: () => (
|
2024-06-09 11:53:25 +02:00
|
|
|
<KcPageStory
|
2024-06-03 00:11:19 +02:00
|
|
|
kcContext={{
|
2024-06-28 06:46:26 +02:00
|
|
|
realm: {
|
|
|
|
registrationEmailAsUsername: true
|
|
|
|
},
|
|
|
|
profile: {
|
|
|
|
attributesByName: {
|
|
|
|
username: undefined
|
|
|
|
}
|
|
|
|
}
|
2024-06-03 00:11:19 +02:00
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
};
|
2024-06-02 22:29:53 +02:00
|
|
|
|
2024-06-03 00:11:19 +02:00
|
|
|
export const WithRecaptcha: Story = {
|
|
|
|
render: () => (
|
2024-06-09 11:53:25 +02:00
|
|
|
<KcPageStory
|
2024-06-03 00:11:19 +02:00
|
|
|
kcContext={{
|
2024-06-04 01:39:54 +02:00
|
|
|
scripts: ["https://www.google.com/recaptcha/api.js?hl=en"],
|
2024-06-03 00:11:19 +02:00
|
|
|
recaptchaRequired: true,
|
2024-06-04 01:39:54 +02:00
|
|
|
recaptchaSiteKey: "6LfQHvApAAAAAE73SYTd5vS0lB1Xr7zdiQ-6iBVa"
|
2024-06-03 00:11:19 +02:00
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
};
|
2024-06-02 22:29:53 +02:00
|
|
|
|
2024-06-05 01:02:17 +02:00
|
|
|
export const WithRecaptchaFrench: Story = {
|
|
|
|
render: () => (
|
2024-06-09 11:53:25 +02:00
|
|
|
<KcPageStory
|
2024-06-05 01:02:17 +02:00
|
|
|
kcContext={{
|
|
|
|
locale: {
|
|
|
|
currentLanguageTag: "fr"
|
|
|
|
},
|
|
|
|
scripts: ["https://www.google.com/recaptcha/api.js?hl=fr"],
|
|
|
|
recaptchaRequired: true,
|
|
|
|
recaptchaSiteKey: "6LfQHvApAAAAAE73SYTd5vS0lB1Xr7zdiQ-6iBVa"
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2024-06-12 23:22:21 +02:00
|
|
|
export const WithPasswordMinLength8: Story = {
|
|
|
|
render: () => (
|
|
|
|
<KcPageStory
|
|
|
|
kcContext={{
|
|
|
|
passwordPolicies: {
|
|
|
|
length: 8
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
};
|
2024-06-28 07:16:17 +02:00
|
|
|
|
|
|
|
export const WithTermsAcceptance: Story = {
|
|
|
|
render: () => (
|
|
|
|
<KcPageStory
|
|
|
|
kcContext={{
|
|
|
|
termsAcceptanceRequired: true,
|
|
|
|
"x-keycloakify": {
|
2024-07-10 22:18:24 +02:00
|
|
|
messages: {
|
|
|
|
termsText: "<a href='https://example.com/terms'>Service Terms of Use</a>"
|
|
|
|
}
|
2024-06-28 07:16:17 +02:00
|
|
|
}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
};
|
2024-09-29 04:35:02 -04:00
|
|
|
export const WithTermsNotAccepted: Story = {
|
|
|
|
render: args => (
|
|
|
|
<KcPageStory
|
|
|
|
{...args}
|
|
|
|
kcContext={{
|
|
|
|
termsAcceptanceRequired: true,
|
|
|
|
messagesPerField: {
|
|
|
|
existsError: (fieldName: string) => fieldName === "termsAccepted",
|
|
|
|
get: (fieldName: string) => (fieldName === "termsAccepted" ? "You must accept the terms." : undefined)
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
};
|
|
|
|
export const WithFieldErrors: Story = {
|
|
|
|
render: () => (
|
|
|
|
<KcPageStory
|
|
|
|
kcContext={{
|
|
|
|
profile: {
|
|
|
|
attributesByName: {
|
|
|
|
username: { value: "" },
|
|
|
|
email: { value: "invalid-email" }
|
|
|
|
}
|
|
|
|
},
|
|
|
|
messagesPerField: {
|
2024-10-08 16:50:11 -05:00
|
|
|
existsError: (fieldName: string) => ["username", "email"].includes(fieldName),
|
|
|
|
get: (fieldName: string) => {
|
2024-09-29 04:35:02 -04:00
|
|
|
if (fieldName === "username") return "Username is required.";
|
|
|
|
if (fieldName === "email") return "Invalid email format.";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
};
|
|
|
|
export const WithReadOnlyFields: Story = {
|
|
|
|
render: () => (
|
|
|
|
<KcPageStory
|
|
|
|
kcContext={{
|
|
|
|
profile: {
|
|
|
|
attributesByName: {
|
|
|
|
username: { value: "johndoe", readOnly: true },
|
|
|
|
email: { value: "jhon.doe@gmail.com", readOnly: false }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
};
|
|
|
|
export const WithAutoGeneratedUsername: Story = {
|
|
|
|
render: () => (
|
|
|
|
<KcPageStory
|
|
|
|
kcContext={{
|
|
|
|
profile: {
|
|
|
|
attributesByName: {
|
|
|
|
username: { value: "autogenerated_username" }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
};
|