= (props
{props.useEmail &&
(showEmailForm ? (
-
- {!fider.session.tenant.isEmailAuthAllowed && (
-
- Currently only allowed to sign in to an administrator account
-
- )}
) : (
@@ -116,4 +213,86 @@ export const SignInControl: React.FunctionComponent = (props
))}
)
+
+ function renderNameField() {
+ return (
+
+ )
+ }
+
+ function renderEmailField(): React.ReactNode {
+ return (
+ <>
+
+ {!fider.session.tenant.isEmailAuthAllowed && (
+
+ Currently only allowed to sign in to an administrator account
+
+ )}
+ >
+ )
+ }
+
+ function renderCodeField(): React.ReactNode {
+ return (
+ <>
+
+
+ Please type in the code we just sent to {email}
+ {" "}
+ {
+ e.preventDefault()
+ editEmail()
+ }}
+ >
+ Edit
+
+
+
+ {resendMessage && {resendMessage}
}
+
+ {
+ e.preventDefault()
+ resendCode()
+ }}
+ >
+ Get a new code
+
+
+ >
+ )
+ }
}
diff --git a/public/components/common/form/Form.tsx b/public/components/common/form/Form.tsx
index 1096b5cdc..9a532207c 100644
--- a/public/components/common/form/Form.tsx
+++ b/public/components/common/form/Form.tsx
@@ -13,6 +13,8 @@ interface FormProps {
children?: React.ReactNode
className?: string
error?: Failure
+ autoComplete?: string
+ onSubmit?: (e: React.FormEvent) => void
}
export const ValidationContext = React.createContext({
@@ -45,8 +47,15 @@ export const Form: React.FunctionComponent = (props) => {
}
}
+ const handleSubmit = (e: React.FormEvent) => {
+ if (props.onSubmit) {
+ e.preventDefault()
+ props.onSubmit(e)
+ }
+ }
+
return (
-
diff --git a/public/components/common/form/Input.tsx b/public/components/common/form/Input.tsx
index eb77ecb8b..516bca7bd 100644
--- a/public/components/common/form/Input.tsx
+++ b/public/components/common/form/Input.tsx
@@ -22,6 +22,7 @@ interface InputProps {
disabled?: boolean
suffix?: string | JSX.Element
placeholder?: string
+ inputMode?: "text" | "numeric" | "decimal" | "tel" | "search" | "email" | "url"
onIconClick?: () => void
onFocus?: () => void
inputRef?: React.MutableRefObject
@@ -80,6 +81,7 @@ export const Input: React.FunctionComponent = (props) => {
id={`input-${props.field}`}
type="text"
autoComplete={props.autoComplete}
+ inputMode={props.inputMode}
tabIndex={props.noTabFocus ? -1 : undefined}
ref={props.inputRef}
autoFocus={props.autoFocus}
diff --git a/public/pages/Home/components/ShareFeedback.tsx b/public/pages/Home/components/ShareFeedback.tsx
index 7b453e532..c13ae6314 100644
--- a/public/pages/Home/components/ShareFeedback.tsx
+++ b/public/pages/Home/components/ShareFeedback.tsx
@@ -200,8 +200,9 @@ export const ShareFeedback: React.FC = (props) => {
}
}
- const onEmailSent = (email: string) => {
- window.location.href = "/loginemailsent?email=" + encodeURIComponent(email)
+ const onCodeVerified = (): void => {
+ // User is authenticated - finalize the feedback submission
+ finaliseFeedback()
}
const handleEditorFocus = () => {
@@ -274,7 +275,7 @@ export const ShareFeedback: React.FC = (props) => {
{
export const SignInPage = () => {
const fider = useFider()
- const onEmailSent = (email: string) => {
- notify.success(
-
-
- We have just sent a confirmation link to {email}. Click the link and you’ll be signed in.
-
-
- )
+ const onCodeVerified = () => {
+ // User is authenticated - redirect to the appropriate URL
+ const redirect = new URLSearchParams(window.location.search).get("redirect")
+ if (redirect && redirect.startsWith("/")) {
+ location.href = fider.settings.baseURL + redirect
+ } else {
+ location.href = fider.settings.baseURL
+ }
}
const getRedirectToUrl = () => {
@@ -63,7 +62,7 @@ export const SignInPage = () => {
{fider.session.tenant.isPrivate ?
:
}
-
+
)
diff --git a/public/services/actions/tenant.ts b/public/services/actions/tenant.ts
index 8e71231c6..58e5d62d9 100644
--- a/public/services/actions/tenant.ts
+++ b/public/services/actions/tenant.ts
@@ -54,11 +54,20 @@ export const checkAvailability = async (subdomain: string): Promise(`/_api/tenants/${subdomain}/availability`)
}
-export const signIn = async (email: string, code?: string): Promise => {
- return await http.post("/_api/signin", {
- email,
- code,
- })
+export const signIn = async (email: string): Promise => {
+ return await http.post("/_api/signin", { email })
+}
+
+export const signInNewUser = async (email: string, name: string): Promise => {
+ return await http.post("/_api/signin/newuser", { email, name })
+}
+
+export const verifySignInCode = async (email: string, code: string): Promise => {
+ return await http.post("/_api/signin/verify", { email, code })
+}
+
+export const resendSignInCode = async (email: string): Promise => {
+ return await http.post("/_api/signin/resend", { email })
}
export const completeProfile = async (kind: EmailVerificationKind, key: string, name: string): Promise => {
diff --git a/views/email/signin_email.html b/views/email/signin_email.html
index 63d17b932..45af3795d 100644
--- a/views/email/signin_email.html
+++ b/views/email/signin_email.html
@@ -1,4 +1,4 @@
-{{define "subject"}}{{ translate "email.signin_email.subject" (dict "siteName" .siteName) }}{{end}}
+{{define "subject"}}{{ translate "email.signin_email.subject" (dict "siteName" .siteName "code" .code) }}{{end}}
{{define "body"}}
@@ -6,7 +6,16 @@
{{ "email.greetings" | translate }}
{{ "email.signin_email.text" | translate }}
{{ translate "email.signin_email.confirmation" (dict "siteName" (.siteName | stripHtml)) | html }}
- {{ .link | html }}
+
+
+
{{ "email.signin_email.your_code" | translate }}
+
+
{{ "email.signin_email.code_expires" | translate }}
+
+
+ {{ "email.signin_email.alternative" | translate }}
{{ .link | html }}
{{end}}
\ No newline at end of file