Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MOSIP-32336 created error message screen #108

Merged
merged 5 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ import Fallback, { type PageProps } from "keycloakify/login";
import type { KcContext } from "./kcContext";
import { useI18n } from "./i18n";
import Template from "./Template";
import LoginResetPassword from "./pages/LoginResetPassword";
import LoginUpdatePassword from "./pages/LoginUpdatePassword";
import LoginVerifyEmail from "./pages/LoginVerifyEmail";


const Login = lazy(() => import("./pages/Login"));
// If you can, favor register-user-profile.ftl over register.ftl, see: https://docs.keycloakify.dev/realtime-input-validation
const Register = lazy(() => import("./pages/Register"));
const RegisterUserProfile = lazy(() => import("./pages/RegisterUserProfile"));
const Terms = lazy(() => import("./pages/Terms"));
const Info = lazy(() => import("keycloakify/login/pages/Info"));

const LoginResetPassword = lazy(() => import("./pages/LoginResetPassword"));
const LoginUpdatePassword = lazy(() => import("./pages/LoginUpdatePassword"));
const LoginVerifyEmail = lazy(() => import("./pages/LoginVerifyEmail"));
const Error = lazy(() => import("./pages/Error"));
const Info = lazy(() => import("./pages/Info"));

// This is like adding classes to theme.properties
// https://github.com/keycloak/keycloak/blob/11.0.3/themes/src/main/resources/theme/keycloak/login/theme.properties
Expand Down Expand Up @@ -50,20 +53,22 @@ export default function KcApp(props: { kcContext: KcContext; }) {
case "login-update-password.ftl": return <LoginUpdatePassword {...{ kcContext, i18n, Template, classes }} doUseDefaultCss={true} />;
case "register-user-profile.ftl": return <RegisterUserProfile {...{ kcContext, i18n, Template, classes }} doUseDefaultCss={true} />;
case "login-verify-email.ftl": return <LoginVerifyEmail {...{ kcContext, i18n, Template, classes }} doUseDefaultCss={true} />;
case "error.ftl": return <Error {...{ kcContext, i18n, Template, classes }} doUseDefaultCss={true} />;
case "terms.ftl": return <Terms {...{ kcContext, i18n, Template, classes }} doUseDefaultCss={true} />;
case "info.ftl": return <Info {...{ kcContext, i18n, Template, classes }} doUseDefaultCss={true} />;
// Removes those pages in you project. They are included to show you how to implement keycloak pages
// that are not yes implemented by Keycloakify.
// See: https://docs.keycloakify.dev/limitations#some-pages-still-have-the-default-theme.-why

// We choose to use the default Template for the Info page and to download the theme resources.
// This is just an example to show you what is possible. You likely don't want to keep this as is.
case "info.ftl": return (
<Info
{...{ kcContext, i18n, classes }}
Template={lazy(() => import("keycloakify/login/Template"))}
doUseDefaultCss={true}
/>
);
// case "info.ftl": return (
// <Info
// {...{ kcContext, i18n, classes }}
// Template={lazy(() => import("keycloakify/login/Template"))}
// doUseDefaultCss={true}
// />
// );
default: return <Fallback {...{ kcContext, i18n, classes }} Template={Template} doUseDefaultCss={true} />;
}
})()}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ export const { useI18n } = createUseI18n({
emailVerifyTitle: "Email Verification link sent!",
emailVerifyText: "You need to verify your email address to activate your account. An email with instruction to verify your email address has been sent to you.",
notReceviedText: "Haven’t received the email in your inbox yet?",
resentEmail: "Resend Email"
resentEmail: "Resend Email",
expiredActionMessage: "Looks like you have already reset password or this action is no longer valid.",
sryText: "We are sorry!"

},
fr: {
/* spell-checker: disable */
Expand Down Expand Up @@ -107,7 +110,9 @@ export const { useI18n } = createUseI18n({
emailVerifyTitle:"Email Verification link sent!",
emailVerifyText:"You need to verify your email address to activate your account. An email with instruction to verify your email address has been sent to you.",
notReceviedText: "Haven’t received the email in your inbox yet?",
resentEmail: "Resend Email"
resentEmail: "Resend Email",
expiredActionMessage: "Looks like you have already reset password or this action is no longer valid.",
sryText: "We are sorry!"
/* spell-checker: enable */
}
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Meta, StoryObj } from '@storybook/react';
import { createPageStory } from "../createPageStory";

const { PageStory } = createPageStory({
pageId: "error.ftl"
});

const meta = {
title: "login/error",
component: PageStory,
} satisfies Meta<typeof PageStory>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
render: () => <PageStory />
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { PageProps } from "keycloakify/login/pages/PageProps";
import type { KcContext } from "../kcContext";
import type { I18n } from "../i18n";
import errorIcon from '../assets/error_message_icon.svg'

export default function Error(props: PageProps<Extract<KcContext, { pageId: "error.ftl" }>, I18n>) {
const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;

const { message } = kcContext;

const { msg } = i18n;

return (
<Template {...{ kcContext, i18n, doUseDefaultCss, classes }} displayMessage={false} headerNode={
<div className="flex flex-col justify-center items-center">
<img className="w-36" alt="" src={errorIcon} />
<h4 className="font-bold text-[#000000] text-xl">{msg("sryText")}</h4>
</div>
// msg("errorTitle")
}>
<div id="kc-error-message" className="text-center">
<p className="instruction">{message.summary}</p>
{/* {client !== undefined && client.baseUrl !== undefined && (
<p>
<a id="backToApplication" href={client.baseUrl}>
{msg("backToApplication")}
</a>
</p>
)} */}
</div>
</Template>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Meta, StoryObj } from '@storybook/react';
import { createPageStory } from "../createPageStory";

const { PageStory } = createPageStory({
pageId: "info.ftl"
});

const meta = {
title: "login/Info",
component: PageStory,
} satisfies Meta<typeof PageStory>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
render: () => <PageStory />
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// import { assert } from "keycloakify/tools/assert";
import type { PageProps } from "keycloakify/login/pages/PageProps";
import type { KcContext } from "../kcContext";
import type { I18n } from "../i18n";

export default function Info(props: PageProps<Extract<KcContext, { pageId: "info.ftl" }>, I18n>) {
const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;

const { msgStr, msg } = i18n;

// assert(
// kcContext.message !== undefined,
// "No message in kcContext.message, there will always be a message in production context, add it in your mock"
// );

const { messageHeader, message, requiredActions, skipLink, pageRedirectUri, actionUri, client } = kcContext;

return (
<Template
{...{ kcContext, i18n, doUseDefaultCss, classes }}
displayMessage={false}
headerNode={messageHeader !== undefined ? <>{messageHeader}</> : <>{message?.summary}</>}
>
<div id="kc-info-message">
<p className="instruction">
{message?.type}

{requiredActions !== undefined && (
<b>{requiredActions.map(requiredAction => msgStr(`requiredAction.${requiredAction}` as const)).join(",")}</b>
)}
</p>
{!skipLink && pageRedirectUri !== undefined ? (
<p>
<a href={pageRedirectUri}>{msg("backToApplication")}</a>
</p>
) : actionUri !== undefined ? (
<p>
<a href={actionUri}>{msg("proceedWithAction")}</a>
</p>
) : (
client.baseUrl !== undefined && (
<p>
<a href={client.baseUrl}>{msg("backToApplication")}</a>
</p>
)
)}
</div>
</Template>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default function LoginUpdatePassword(props: PageProps<Extract<KcContext,
}
const { msg, msgStr } = i18n;

const { url, messagesPerField, isAppInitiatedAction, username } = kcContext;
const { url, messagesPerField, isAppInitiatedAction, username, message } = kcContext;

return (
<Template {...{ kcContext, i18n, doUseDefaultCss, classes }}
Expand All @@ -41,6 +41,18 @@ export default function LoginUpdatePassword(props: PageProps<Extract<KcContext,
}
>
<form id="kc-passwd-update-form" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
{message !== undefined && (
<div className='bg-errorBg min-h-11 p-2 text-center text-errorColor font-semibold mb-3'>
{/* {message.type === "success" && <span className={getClassName("kcFeedbackSuccessIcon")}></span>}
{message.type === "warning" && <span className={getClassName("kcFeedbackWarningIcon")}></span>}
{message.type === "info" && <span className={getClassName("kcFeedbackInfoIcon")}></span>} */}
<span className="kc-feedback-text"
dangerouslySetInnerHTML={{
"__html": message.summary
}}
/>
</div>
)}
<input
type="text"
id="username"
Expand Down
Loading