2022-02-13 23:39:27 +08:00
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
2021-03-26 21:57:41 +08:00
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2022-07-10 15:45:55 +08:00
import React from "react" ;
2024-09-24 16:08:50 +08:00
import { Button , Form , Input , Radio , Result , Row , Select , message } from "antd" ;
2021-03-26 21:57:41 +08:00
import * as Setting from "../Setting" ;
import * as AuthBackend from "./AuthBackend" ;
2022-08-05 18:59:56 +08:00
import * as ProviderButton from "./ProviderButton" ;
2021-04-28 00:47:12 +08:00
import i18next from "i18next" ;
2021-04-28 15:54:50 +08:00
import * as Util from "./Util" ;
import { authConfig } from "./Auth" ;
import * as ApplicationBackend from "../backend/ApplicationBackend" ;
2023-03-26 18:44:47 +08:00
import * as AgreementModal from "../common/modal/AgreementModal" ;
2023-02-12 18:56:56 +08:00
import { SendCodeInput } from "../common/SendCodeInput" ;
2023-03-26 18:44:47 +08:00
import RegionSelect from "../common/select/RegionSelect" ;
import CustomGithubCorner from "../common/CustomGithubCorner" ;
import LanguageSelect from "../common/select/LanguageSelect" ;
2022-11-13 05:16:49 +01:00
import { withRouter } from "react-router-dom" ;
2023-03-26 18:44:47 +08:00
import { CountryCodeSelect } from "../common/select/CountryCodeSelect" ;
2023-06-17 00:01:20 +08:00
import * as PasswordChecker from "../common/PasswordChecker" ;
2024-02-02 21:12:56 +08:00
import * as InvitationBackend from "../backend/InvitationBackend" ;
2021-03-26 21:57:41 +08:00
const formItemLayout = {
labelCol : {
xs : {
span : 24 ,
} ,
sm : {
2021-07-31 16:02:48 +08:00
span : 8 ,
2021-03-26 21:57:41 +08:00
} ,
} ,
wrapperCol : {
xs : {
span : 24 ,
} ,
sm : {
2022-12-06 00:50:17 +08:00
span : 16 ,
2021-03-26 21:57:41 +08:00
} ,
} ,
} ;
2023-03-26 18:44:47 +08:00
export const tailFormItemLayout = {
2021-03-26 21:57:41 +08:00
wrapperCol : {
xs : {
span : 24 ,
offset : 0 ,
} ,
sm : {
span : 16 ,
offset : 8 ,
} ,
} ,
} ;
2021-04-27 22:47:44 +08:00
class SignupPage extends React . Component {
2021-03-26 21:57:41 +08:00
constructor ( props ) {
super ( props ) ;
this . state = {
classes : props ,
2023-04-25 16:00:24 +08:00
applicationName : ( props . applicationName ? ? props . match ? . params ? . applicationName ) ? ? null ,
2021-05-18 20:11:03 +08:00
email : "" ,
2021-05-20 21:09:12 +08:00
phone : "" ,
2024-03-29 09:07:37 +08:00
emailOrPhoneMode : "" ,
2023-02-16 22:53:28 +08:00
countryCode : "" ,
2021-05-20 21:09:12 +08:00
emailCode : "" ,
2021-06-23 11:41:21 +08:00
phoneCode : "" ,
validEmail : false ,
validPhone : false ,
2021-07-31 16:02:48 +08:00
region : "" ,
2021-08-03 21:00:07 +08:00
isTermsOfUseVisible : false ,
2021-08-10 10:43:33 +08:00
termsOfUseContent : "" ,
2021-03-26 21:57:41 +08:00
} ;
this . form = React . createRef ( ) ;
}
2023-02-27 20:10:59 +08:00
componentDidMount ( ) {
2022-07-19 23:31:17 +08:00
const oAuthParams = Util . getOAuthGetParameters ( ) ;
if ( oAuthParams !== null ) {
2024-02-24 12:59:09 +08:00
const signinUrl = window . location . pathname . replace ( "/signup/oauth/authorize" , "/login/oauth/authorize" ) ;
sessionStorage . setItem ( "signinUrl" , signinUrl + window . location . search ) ;
2022-07-19 23:31:17 +08:00
}
2023-03-24 23:17:54 +08:00
if ( this . getApplicationObj ( ) === undefined ) {
if ( this . state . applicationName !== null ) {
this . getApplication ( this . state . applicationName ) ;
2024-02-02 21:12:56 +08:00
const sp = new URLSearchParams ( window . location . search ) ;
if ( sp . has ( "invitationCode" ) ) {
const invitationCode = sp . get ( "invitationCode" ) ;
this . setState ( { invitationCode : invitationCode } ) ;
if ( invitationCode !== "" ) {
this . getInvitationCodeInfo ( invitationCode , "admin/" + this . state . applicationName ) ;
}
}
2023-04-22 18:20:45 +08:00
} else if ( oAuthParams !== null ) {
this . getApplicationLogin ( oAuthParams ) ;
2022-12-22 23:39:02 +08:00
} else {
2023-03-24 23:17:54 +08:00
Setting . showMessage ( "error" , ` Unknown application name: ${ this . state . applicationName } ` ) ;
2023-04-22 18:20:45 +08:00
this . onUpdateApplication ( null ) ;
2022-12-22 23:39:02 +08:00
}
2021-04-28 15:54:50 +08:00
}
}
2022-07-19 23:31:17 +08:00
getApplication ( applicationName ) {
if ( applicationName === undefined ) {
2021-04-28 15:54:50 +08:00
return ;
}
2022-07-19 23:31:17 +08:00
ApplicationBackend . getApplication ( "admin" , applicationName )
2023-06-27 20:33:47 +07:00
. then ( ( res ) => {
if ( res . status === "error" ) {
Setting . showMessage ( "error" , res . msg ) ;
return ;
}
2023-07-23 09:49:16 +08:00
this . onUpdateApplication ( res . data ) ;
2021-04-28 15:54:50 +08:00
} ) ;
}
2023-04-22 18:20:45 +08:00
getApplicationLogin ( oAuthParams ) {
AuthBackend . getApplicationLogin ( oAuthParams )
. then ( ( res ) => {
if ( res . status === "ok" ) {
const application = res . data ;
this . onUpdateApplication ( application ) ;
} else {
this . onUpdateApplication ( null ) ;
this . setState ( {
msg : res . msg ,
} ) ;
}
} ) ;
}
2024-02-02 21:12:56 +08:00
getInvitationCodeInfo ( invitationCode , application ) {
InvitationBackend . getInvitationCodeInfo ( invitationCode , application )
. then ( ( res ) => {
if ( res . status === "error" ) {
Setting . showMessage ( "error" , res . msg ) ;
return ;
}
this . setState ( { invitation : res . data } ) ;
} ) ;
}
2023-08-24 23:20:50 +08:00
getResultPath ( application , signupParams ) {
if ( signupParams ? . plan && signupParams ? . pricing ) {
// the prompt page needs the user to be signed in, so for paid-user sign up, just go to buy-plan page
return ` /buy-plan/ ${ application . organization } / ${ signupParams ? . pricing } ?user= ${ signupParams . username } &plan= ${ signupParams . plan } ` ;
}
2021-04-28 22:40:21 +08:00
if ( authConfig . appName === application . name ) {
return "/result" ;
} else {
2021-06-20 09:46:06 +08:00
if ( Setting . hasPromptPage ( application ) ) {
return ` /prompt/ ${ application . name } ` ;
} else {
return ` /result/ ${ application . name } ` ;
}
2021-04-28 22:40:21 +08:00
}
}
2021-06-14 13:13:39 +08:00
getApplicationObj ( ) {
2023-03-24 23:17:54 +08:00
return this . props . application ;
2021-06-14 13:13:39 +08:00
}
2021-06-20 13:27:26 +08:00
onUpdateAccount ( account ) {
this . props . onUpdateAccount ( account ) ;
}
2022-12-22 23:39:02 +08:00
onUpdateApplication ( application ) {
this . props . onUpdateApplication ( application ) ;
}
2022-10-22 21:43:41 +08:00
parseOffset ( offset ) {
if ( offset === 2 || offset === 4 || Setting . inIframe ( ) || Setting . isMobile ( ) ) {
return "0 auto" ;
}
if ( offset === 1 ) {
return "0 10%" ;
}
if ( offset === 3 ) {
return "0 60%" ;
}
}
2021-03-26 21:57:41 +08:00
onFinish ( values ) {
2021-06-14 13:13:39 +08:00
const application = this . getApplicationObj ( ) ;
2023-05-20 10:56:21 +03:00
2024-09-24 16:08:50 +08:00
if ( Array . isArray ( values . gender ) ) {
values . gender = values . gender . join ( ", " ) ;
}
2023-05-20 10:56:21 +03:00
const params = new URLSearchParams ( window . location . search ) ;
2023-08-24 23:20:50 +08:00
values . plan = params . get ( "plan" ) ;
values . pricing = params . get ( "pricing" ) ;
2021-04-27 22:47:44 +08:00
AuthBackend . signup ( values )
2021-03-26 21:57:41 +08:00
. then ( ( res ) => {
2022-07-10 15:45:55 +08:00
if ( res . status === "ok" ) {
2023-09-08 21:03:30 +08:00
// the user's id will be returned by `signup()`, if user signup by phone, the `username` in `values` is undefined.
values . username = res . data . split ( "/" ) [ 1 ] ;
2023-08-24 23:20:50 +08:00
if ( Setting . hasPromptPage ( application ) && ( ! values . plan || ! values . pricing ) ) {
2021-08-01 00:16:13 +08:00
AuthBackend . getAccount ( "" )
. then ( ( res ) => {
let account = null ;
if ( res . status === "ok" ) {
account = res . data ;
account . organization = res . data2 ;
this . onUpdateAccount ( account ) ;
2023-08-24 23:20:50 +08:00
Setting . goToLinkSoft ( this , this . getResultPath ( application , values ) ) ;
2021-08-01 00:16:13 +08:00
} else {
2023-03-18 20:42:02 +08:00
Setting . showMessage ( "error" , ` ${ i18next . t ( "application:Failed to sign in" ) } : ${ res . msg } ` ) ;
2021-06-20 13:27:26 +08:00
}
2021-08-01 00:16:13 +08:00
} ) ;
} else {
2023-08-24 23:20:50 +08:00
Setting . goToLinkSoft ( this , this . getResultPath ( application , values ) ) ;
2021-08-01 00:16:13 +08:00
}
2021-03-26 21:57:41 +08:00
} else {
2024-02-27 22:48:33 +08:00
Setting . showMessage ( "error" , res . msg ) ;
2021-03-26 21:57:41 +08:00
}
} ) ;
}
onFinishFailed ( values , errorFields , outOfDate ) {
this . form . current . scrollToField ( errorFields [ 0 ] . name ) ;
}
2022-08-05 18:59:56 +08:00
isProviderVisible ( providerItem ) {
2023-04-22 18:20:45 +08:00
return Setting . isProviderVisibleForSignUp ( providerItem ) ;
2022-08-05 18:59:56 +08:00
}
2021-06-16 14:06:41 +08:00
renderFormItem ( application , signupItem ) {
if ( ! signupItem . visible ) {
return null ;
2021-05-08 00:23:08 +08:00
}
2021-06-16 15:25:54 +08:00
const required = signupItem . required ;
2021-06-16 14:06:41 +08:00
if ( signupItem . name === "Username" ) {
return (
2021-03-26 21:57:41 +08:00
< Form . Item
2021-04-28 00:47:12 +08:00
name = "username"
2024-04-21 11:56:18 +08:00
className = "signup-username"
2023-10-15 17:24:38 +08:00
label = { signupItem . label ? signupItem . label : i18next . t ( "signup:Username" ) }
2021-03-26 21:57:41 +08:00
rules = { [
{
2021-06-16 15:25:54 +08:00
required : required ,
2021-06-17 22:43:30 +08:00
message : i18next . t ( "forget:Please input your username!" ) ,
2021-03-26 21:57:41 +08:00
whitespace : true ,
} ,
] }
>
2024-04-21 11:56:18 +08:00
< Input className = "signup-username-input" placeholder = { signupItem . placeholder }
disabled = { this . state . invitation !== undefined && this . state . invitation . username !== "" } / >
2021-03-26 21:57:41 +08:00
< / F o r m . I t e m >
2022-07-10 15:45:55 +08:00
) ;
2021-06-16 14:06:41 +08:00
} else if ( signupItem . name === "Display name" ) {
2022-02-27 14:02:52 +08:00
if ( signupItem . rule === "First, last" && Setting . getLanguage ( ) !== "zh" ) {
return (
< React . Fragment >
< Form . Item
name = "firstName"
2024-04-21 11:56:18 +08:00
className = "signup-first-name"
2023-10-15 17:24:38 +08:00
label = { signupItem . label ? signupItem . label : i18next . t ( "general:First name" ) }
2022-02-27 14:02:52 +08:00
rules = { [
{
required : required ,
message : i18next . t ( "signup:Please input your first name!" ) ,
whitespace : true ,
} ,
] }
>
2024-04-21 11:56:18 +08:00
< Input className = "signup-first-name-input" placeholder = { signupItem . placeholder } / >
2022-02-27 14:02:52 +08:00
< / F o r m . I t e m >
< Form . Item
name = "lastName"
2024-04-21 11:56:18 +08:00
className = "signup-last-name"
2023-10-15 17:24:38 +08:00
label = { signupItem . label ? signupItem . label : i18next . t ( "general:Last name" ) }
2022-02-27 14:02:52 +08:00
rules = { [
{
required : required ,
message : i18next . t ( "signup:Please input your last name!" ) ,
whitespace : true ,
} ,
] }
>
2024-04-21 11:56:18 +08:00
< Input className = "signup-last-name-input" placeholder = { signupItem . placeholder } / >
2022-02-27 14:02:52 +08:00
< / F o r m . I t e m >
< / R e a c t . F r a g m e n t >
2022-07-10 15:45:55 +08:00
) ;
2022-02-27 14:02:52 +08:00
}
2021-06-16 14:06:41 +08:00
return (
2021-03-26 21:57:41 +08:00
< Form . Item
2021-04-28 21:25:58 +08:00
name = "name"
2024-04-21 11:56:18 +08:00
className = "signup-name"
2023-10-15 17:24:38 +08:00
label = { ( signupItem . label ? signupItem . label : ( signupItem . rule === "Real name" || signupItem . rule === "First, last" ) ? i18next . t ( "general:Real name" ) : i18next . t ( "general:Display name" ) ) }
2021-03-26 21:57:41 +08:00
rules = { [
{
2021-06-16 15:25:54 +08:00
required : required ,
2022-02-27 14:02:52 +08:00
message : ( signupItem . rule === "Real name" || signupItem . rule === "First, last" ) ? i18next . t ( "signup:Please input your real name!" ) : i18next . t ( "signup:Please input your display name!" ) ,
2021-03-26 21:57:41 +08:00
whitespace : true ,
} ,
] }
>
2024-04-21 11:56:18 +08:00
< Input className = "signup-name-input" placeholder = { signupItem . placeholder } / >
2021-03-26 21:57:41 +08:00
< / F o r m . I t e m >
2022-07-10 15:45:55 +08:00
) ;
2021-06-16 14:06:41 +08:00
} else if ( signupItem . name === "Affiliation" ) {
return (
2021-03-26 21:57:41 +08:00
< Form . Item
2021-04-27 22:35:14 +08:00
name = "affiliation"
2024-04-21 11:56:18 +08:00
className = "signup-affiliation"
2023-10-15 17:24:38 +08:00
label = { signupItem . label ? signupItem . label : i18next . t ( "user:Affiliation" ) }
2021-03-26 21:57:41 +08:00
rules = { [
{
2021-06-16 15:25:54 +08:00
required : required ,
2021-04-28 00:47:12 +08:00
message : i18next . t ( "signup:Please input your affiliation!" ) ,
2021-03-26 21:57:41 +08:00
whitespace : true ,
} ,
] }
>
2024-04-21 11:56:18 +08:00
< Input className = "signup-affiliation-input" placeholder = { signupItem . placeholder } / >
2021-03-26 21:57:41 +08:00
< / F o r m . I t e m >
2022-07-10 15:45:55 +08:00
) ;
2021-12-28 17:48:24 +08:00
} else if ( signupItem . name === "ID card" ) {
return (
< Form . Item
name = "idCard"
2024-04-21 11:56:18 +08:00
className = "signup-idcard"
2023-10-15 17:24:38 +08:00
label = { signupItem . label ? signupItem . label : i18next . t ( "user:ID card" ) }
2021-12-28 17:48:24 +08:00
rules = { [
{
required : required ,
message : i18next . t ( "signup:Please input your ID card number!" ) ,
whitespace : true ,
} ,
{
required : required ,
pattern : new RegExp ( /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9X]$/ , "g" ) ,
message : i18next . t ( "signup:Please input the correct ID card number!" ) ,
} ,
] }
>
2024-04-21 11:56:18 +08:00
< Input className = "signup-idcard-input" placeholder = { signupItem . placeholder } / >
2021-12-28 17:48:24 +08:00
< / F o r m . I t e m >
2022-07-10 15:45:55 +08:00
) ;
2021-07-31 16:02:48 +08:00
} else if ( signupItem . name === "Country/Region" ) {
return (
< Form . Item
2022-07-10 15:45:55 +08:00
name = "country_region"
2024-04-21 11:56:18 +08:00
className = "signup-country-region"
2023-10-15 17:24:38 +08:00
label = { signupItem . label ? signupItem . label : i18next . t ( "user:Country/Region" ) }
2022-07-10 15:45:55 +08:00
rules = { [
{
required : required ,
message : i18next . t ( "signup:Please select your country/region!" ) ,
} ,
] }
2021-07-31 16:02:48 +08:00
>
2024-09-24 16:08:50 +08:00
< RegionSelect className = "signup-region-select" onChange = { ( value ) => {
this . setState ( { region : value } ) ;
} } / >
2021-07-31 16:02:48 +08:00
< / F o r m . I t e m >
2022-07-10 15:45:55 +08:00
) ;
2024-03-29 09:07:37 +08:00
} else if ( signupItem . name === "Email" || signupItem . name === "Phone" || signupItem . name === "Email or Phone" || signupItem . name === "Phone or Email" ) {
const renderEmailItem = ( ) => {
return (
< React . Fragment >
2022-05-02 17:19:40 +08:00
< Form . Item
2024-03-29 09:07:37 +08:00
name = "email"
2024-04-21 11:56:18 +08:00
className = "signup-email"
2024-03-29 09:07:37 +08:00
label = { signupItem . label ? signupItem . label : i18next . t ( "general:Email" ) }
rules = { [
{
required : required ,
message : i18next . t ( "signup:Please input your Email!" ) ,
} ,
{
validator : ( _ , value ) => {
if ( this . state . email !== "" && ! Setting . isValidEmail ( this . state . email ) ) {
this . setState ( { validEmail : false } ) ;
return Promise . reject ( i18next . t ( "signup:The input is not valid Email!" ) ) ;
}
2024-05-19 22:07:34 +08:00
if ( signupItem . regex ) {
const reg = new RegExp ( signupItem . regex ) ;
if ( ! reg . test ( this . state . email ) ) {
this . setState ( { validEmail : false } ) ;
return Promise . reject ( i18next . t ( "signup:The input Email doesn't match the signup item regex!" ) ) ;
}
}
2024-03-29 09:07:37 +08:00
this . setState ( { validEmail : true } ) ;
return Promise . resolve ( ) ;
} ,
} ,
] }
2022-05-02 17:19:40 +08:00
>
2024-09-24 16:08:50 +08:00
< Input className = "signup-email-input" placeholder = { signupItem . placeholder }
disabled = { this . state . invitation !== undefined && this . state . invitation . email !== "" }
onChange = { e => this . setState ( { email : e . target . value } ) } / >
2022-05-02 17:19:40 +08:00
< / F o r m . I t e m >
2024-03-29 09:07:37 +08:00
{
signupItem . rule !== "No verification" &&
2024-09-24 16:08:50 +08:00
< Form . Item
name = "emailCode"
className = "signup-email-code"
label = { signupItem . label ? signupItem . label : i18next . t ( "code:Email code" ) }
rules = { [ {
required : required ,
message : i18next . t ( "code:Please input your verification code!" ) ,
} ] }
>
< SendCodeInput
className = "signup-email-code-input"
disabled = { ! this . state . validEmail }
method = { "signup" }
onButtonClickArgs = { [ this . state . email , "email" , Setting . getApplicationName ( application ) ] }
application = { application }
/ >
< / F o r m . I t e m >
2024-03-29 09:07:37 +08:00
}
< / R e a c t . F r a g m e n t >
) ;
} ;
const renderPhoneItem = ( ) => {
return (
< React . Fragment >
2024-09-24 16:08:50 +08:00
< Form . Item className = "signup-phone"
label = { signupItem . label ? signupItem . label : i18next . t ( "general:Phone" ) } required = { required } >
2024-03-29 09:07:37 +08:00
< Input . Group compact >
< Form . Item
name = "countryCode"
noStyle
rules = { [
{
required : required ,
message : i18next . t ( "signup:Please select your country code!" ) ,
} ,
] }
>
< CountryCodeSelect
style = { { width : "35%" } }
countryCodes = { this . getApplicationObj ( ) . organizationObj . countryCodes }
/ >
< / F o r m . I t e m >
< Form . Item
name = "phone"
dependencies = { [ "countryCode" ] }
noStyle
rules = { [
{
required : required ,
message : i18next . t ( "signup:Please input your phone number!" ) ,
} ,
( { getFieldValue } ) => ( {
validator : ( _ , value ) => {
if ( ! required && ! value ) {
return Promise . resolve ( ) ;
}
if ( value && ! Setting . isValidPhone ( value , getFieldValue ( "countryCode" ) ) ) {
this . setState ( { validPhone : false } ) ;
return Promise . reject ( i18next . t ( "signup:The input is not valid Phone!" ) ) ;
}
this . setState ( { validPhone : true } ) ;
return Promise . resolve ( ) ;
} ,
} ) ,
] }
>
< Input
2024-04-21 11:56:18 +08:00
className = "signup-phone-input"
2024-03-29 09:07:37 +08:00
placeholder = { signupItem . placeholder }
style = { { width : "65%" } }
disabled = { this . state . invitation !== undefined && this . state . invitation . phone !== "" }
onChange = { e => this . setState ( { phone : e . target . value } ) }
/ >
< / F o r m . I t e m >
< / I n p u t . G r o u p >
< / F o r m . I t e m >
{
signupItem . rule !== "No verification" &&
2024-09-24 16:08:50 +08:00
< Form . Item
name = "phoneCode"
className = "phone-code"
label = { signupItem . label ? signupItem . label : i18next . t ( "code:Phone code" ) }
rules = { [
{
required : required ,
message : i18next . t ( "code:Please input your phone verification code!" ) ,
} ,
] }
>
< SendCodeInput
className = "signup-phone-code-input"
disabled = { ! this . state . validPhone }
method = { "signup" }
onButtonClickArgs = { [ this . state . phone , "phone" , Setting . getApplicationName ( application ) ] }
application = { application }
countryCode = { this . form . current ? . getFieldValue ( "countryCode" ) }
/ >
< / F o r m . I t e m >
2024-03-29 09:07:37 +08:00
}
< / R e a c t . F r a g m e n t >
) ;
} ;
if ( signupItem . name === "Email" ) {
return renderEmailItem ( ) ;
} else if ( signupItem . name === "Phone" ) {
return renderPhoneItem ( ) ;
} else if ( signupItem . name === "Email or Phone" || signupItem . name === "Phone or Email" ) {
let emailOrPhoneMode = this . state . emailOrPhoneMode ;
if ( emailOrPhoneMode === "" ) {
emailOrPhoneMode = signupItem . name === "Email or Phone" ? "Email" : "Phone" ;
}
return (
< React . Fragment >
2024-09-24 16:08:50 +08:00
< Row style = { { marginTop : "30px" , marginBottom : "20px" } } >
2024-03-29 09:07:37 +08:00
< Radio . Group style = { { width : "400px" } } buttonStyle = "solid" onChange = { e => {
this . setState ( {
emailOrPhoneMode : e . target . value ,
} ) ;
} } value = { emailOrPhoneMode } >
2023-04-16 20:34:06 +08:00
{
2024-03-29 09:07:37 +08:00
signupItem . name === "Email or Phone" ? (
< React . Fragment >
< Radio . Button value = { "Email" } > { i18next . t ( "general:Email" ) } < / R a d i o . B u t t o n >
< Radio . Button value = { "Phone" } > { i18next . t ( "general:Phone" ) } < / R a d i o . B u t t o n >
< / R e a c t . F r a g m e n t >
) : (
< React . Fragment >
< Radio . Button value = { "Phone" } > { i18next . t ( "general:Phone" ) } < / R a d i o . B u t t o n >
< Radio . Button value = { "Email" } > { i18next . t ( "general:Email" ) } < / R a d i o . B u t t o n >
< / R e a c t . F r a g m e n t >
)
}
< / R a d i o . G r o u p >
< / R o w >
{
emailOrPhoneMode === "Email" ? renderEmailItem ( ) : renderPhoneItem ( )
}
< / R e a c t . F r a g m e n t >
) ;
} else {
return null ;
}
2021-09-21 14:04:17 +08:00
} else if ( signupItem . name === "Password" ) {
return (
< Form . Item
name = "password"
2024-04-21 11:56:18 +08:00
className = "signup-password"
2023-10-15 17:24:38 +08:00
label = { signupItem . label ? signupItem . label : i18next . t ( "general:Password" ) }
2021-09-21 14:04:17 +08:00
rules = { [
{
required : required ,
2023-06-17 00:01:20 +08:00
validateTrigger : "onChange" ,
validator : ( rule , value ) => {
const errorMsg = PasswordChecker . checkPasswordComplexity ( value , application . organizationObj . passwordOptions ) ;
if ( errorMsg === "" ) {
return Promise . resolve ( ) ;
} else {
return Promise . reject ( errorMsg ) ;
}
} ,
2021-09-21 14:04:17 +08:00
} ,
] }
hasFeedback
>
2024-04-21 11:56:18 +08:00
< Input . Password className = "signup-password-input" placeholder = { signupItem . placeholder } / >
2021-09-21 14:04:17 +08:00
< / F o r m . I t e m >
2022-07-10 15:45:55 +08:00
) ;
2021-09-21 14:04:17 +08:00
} else if ( signupItem . name === "Confirm password" ) {
return (
< Form . Item
name = "confirm"
2024-04-21 11:56:18 +08:00
className = "signup-confirm"
2023-10-15 17:24:38 +08:00
label = { signupItem . label ? signupItem . label : i18next . t ( "signup:Confirm" ) }
2022-07-10 15:45:55 +08:00
dependencies = { [ "password" ] }
2021-09-21 14:04:17 +08:00
hasFeedback
rules = { [
{
required : required ,
message : i18next . t ( "signup:Please confirm your password!" ) ,
} ,
2022-07-10 15:45:55 +08:00
( { getFieldValue } ) => ( {
2021-09-21 14:04:17 +08:00
validator ( rule , value ) {
2022-07-10 15:45:55 +08:00
if ( ! value || getFieldValue ( "password" ) === value ) {
2021-09-21 14:04:17 +08:00
return Promise . resolve ( ) ;
}
return Promise . reject ( i18next . t ( "signup:Your confirmed password is inconsistent with the password!" ) ) ;
} ,
} ) ,
] }
>
2023-10-15 17:24:38 +08:00
< Input . Password placeholder = { signupItem . placeholder } / >
2021-09-21 14:04:17 +08:00
< / F o r m . I t e m >
2022-07-10 15:45:55 +08:00
) ;
2023-08-24 13:42:17 +08:00
} else if ( signupItem . name === "Invitation code" ) {
return (
< Form . Item
name = "invitationCode"
2024-04-21 11:56:18 +08:00
className = "signup-invitation-code"
2023-10-15 17:24:38 +08:00
label = { signupItem . label ? signupItem . label : i18next . t ( "application:Invitation code" ) }
2023-08-24 13:42:17 +08:00
rules = { [
{
required : required ,
message : i18next . t ( "signup:Please input your invitation code!" ) ,
} ,
] }
>
2024-09-24 16:08:50 +08:00
< Input className = "signup-invitation-code-input" placeholder = { signupItem . placeholder }
disabled = { this . state . invitation !== undefined && this . state . invitation !== "" } / >
2023-08-24 13:42:17 +08:00
< / F o r m . I t e m >
) ;
2021-06-16 14:06:41 +08:00
} else if ( signupItem . name === "Agreement" ) {
2023-03-26 18:44:47 +08:00
return AgreementModal . renderAgreementFormItem ( application , required , tailFormItemLayout , this ) ;
2023-10-15 17:37:33 +08:00
} else if ( signupItem . name . startsWith ( "Text " ) ) {
2024-09-24 12:58:17 +08:00
if ( signupItem . type ) {
if ( ! signupItem . type || signupItem . type === "Input" ) {
return (
< Form . Item
name = { signupItem . name . toLowerCase ( ) . replace ( " " , "_" ) }
label = { signupItem . label ? signupItem . label : signupItem . name }
rules = { [
{
required : signupItem . required ,
message : i18next . t ( ` signup:Please input your ${ signupItem . label } ! ` ) ,
} ,
] }
>
< Input placeholder = { signupItem . placeholder } / >
< / F o r m . I t e m >
) ;
} else if ( signupItem . type === "Single Choice" || signupItem . type === "Multiple Choices" ) {
return (
< Form . Item
name = { signupItem . name . toLowerCase ( ) . replace ( " " , "_" ) }
label = { signupItem . label ? signupItem . label : signupItem . name }
rules = { [
{
required : signupItem . required ,
message : i18next . t ( ` Please select your ${ signupItem . label } ! ` ) ,
} ,
] }
>
< Select
mode = { signupItem . type === "Multiple Choices" ? "multiple" : "single" }
placeholder = { signupItem . placeholder }
options = { signupItem . options . map ( option => ( { label : option , value : option } ) ) }
/ >
< / F o r m . I t e m >
) ;
}
}
2024-04-21 11:56:18 +08:00
} else if ( signupItem . name === "Signup button" ) {
return (
< Form . Item { ... tailFormItemLayout } >
< Button type = "primary" htmlType = "submit" className = "signup-button" >
{ i18next . t ( "account:Sign Up" ) }
< / B u t t o n >
2024-09-24 16:08:50 +08:00
& nbsp ; & nbsp ; { i18next . t ( "signup:Have account?" ) } & nbsp ;
2024-04-21 11:56:18 +08:00
< a className = "signup-link" onClick = { ( ) => {
const linkInStorage = sessionStorage . getItem ( "signinUrl" ) ;
if ( linkInStorage !== null && linkInStorage !== "" ) {
Setting . goToLinkSoft ( this , linkInStorage ) ;
} else {
Setting . redirectToLoginPage ( application , this . props . history ) ;
}
} } >
{ i18next . t ( "signup:sign in now" ) }
< / a >
< / F o r m . I t e m >
) ;
} else if ( signupItem . name === "Providers" ) {
const showForm = Setting . isPasswordEnabled ( application ) || Setting . isCodeSigninEnabled ( application ) || Setting . isWebAuthnEnabled ( application ) || Setting . isLdapEnabled ( application ) ;
if ( signupItem . rule === "None" || signupItem . rule === "" ) {
signupItem . rule = showForm ? "small" : "big" ;
}
return (
2024-07-29 17:22:48 +08:00
application . providers . filter ( providerItem => this . isProviderVisible ( providerItem ) ) . map ( ( providerItem , id ) => {
return (
< span key = { id } onClick = { ( e ) => {
2024-07-30 14:04:03 +08:00
const agreementChecked = this . form . current . getFieldValue ( "agreement" ) ;
if ( agreementChecked !== undefined && typeof agreementChecked === "boolean" && ! agreementChecked ) {
2024-07-29 17:22:48 +08:00
e . preventDefault ( ) ;
message . error ( i18next . t ( "signup:Please accept the agreement!" ) ) ;
}
} } >
{
ProviderButton . renderProviderLogo ( providerItem . provider , application , null , null , signupItem . rule , this . props . location )
}
< / s p a n >
) ;
2024-04-21 11:56:18 +08:00
} )
) ;
2024-09-24 16:08:50 +08:00
} else if ( signupItem . name === "Gender" ) {
if ( ! signupItem . type ) {
return (
< Form . Item
name = { signupItem . name . toLowerCase ( ) }
label = { signupItem . label ? signupItem . label : signupItem . name }
rules = { [
{
required : signupItem . required ,
message : i18next . t ( ` signup:Please input your ${ signupItem . label || signupItem . name } ! ` ) ,
} ,
] }
>
< Input placeholder = { signupItem . placeholder } / >
< / F o r m . I t e m >
) ;
}
if ( ! signupItem . type || signupItem . type === "Input" ) {
return (
< Form . Item
name = { signupItem . name . toLowerCase ( ) }
label = { signupItem . label ? signupItem . label : signupItem . name }
rules = { [
{
required : signupItem . required ,
message : i18next . t ( ` signup:Please input your ${ signupItem . label } ! ` ) ,
} ,
] }
>
< Input placeholder = { signupItem . placeholder } / >
< / F o r m . I t e m >
) ;
} else if ( signupItem . type === "Single Choice" || signupItem . type === "Multiple Choices" ) {
return (
< Form . Item
name = { signupItem . name . toLowerCase ( ) }
label = { signupItem . label ? signupItem . label : signupItem . name }
rules = { [
{
required : signupItem . required ,
message : i18next . t ( ` Please select your ${ signupItem . label || signupItem . name } ! ` ) ,
} ,
] }
>
< Select
mode = { signupItem . type === "Multiple Choices" ? "multiple" : "single" }
placeholder = { signupItem . placeholder }
showSearch = { false }
options = { signupItem . options . map ( option => ( { label : option , value : option } ) ) }
/ >
< / F o r m . I t e m >
) ;
}
2021-06-16 14:06:41 +08:00
}
}
2021-03-26 21:57:41 +08:00
2021-06-16 14:06:41 +08:00
renderForm ( application ) {
if ( ! application . enableSignUp ) {
return (
< Result
status = "error"
2022-11-27 14:04:45 +01:00
title = { i18next . t ( "application:Sign Up Error" ) }
subTitle = { i18next . t ( "application:The application does not allow to sign up new account" ) }
2021-06-16 14:06:41 +08:00
extra = { [
2022-11-13 05:16:49 +01:00
< Button type = "primary" key = "signin" onClick = { ( ) => Setting . redirectToLoginPage ( application , this . props . history ) } >
2022-10-27 20:23:57 +02:00
{
i18next . t ( "login:Sign In" )
}
2022-08-06 23:54:56 +08:00
< / B u t t o n > ,
2021-03-26 21:57:41 +08:00
] }
>
2021-06-16 14:06:41 +08:00
< / R e s u l t >
2022-07-10 15:45:55 +08:00
) ;
2021-06-16 14:06:41 +08:00
}
2024-02-02 21:12:56 +08:00
if ( this . state . invitation !== undefined ) {
if ( this . state . invitation . username !== "" ) {
this . form . current ? . setFieldValue ( "username" , this . state . invitation . username ) ;
}
if ( this . state . invitation . email !== "" ) {
this . form . current ? . setFieldValue ( "email" , this . state . invitation . email ) ;
}
if ( this . state . invitation . phone !== "" ) {
this . form . current ? . setFieldValue ( "phone" , this . state . invitation . phone ) ;
}
if ( this . state . invitationCode !== "" ) {
this . form . current ? . setFieldValue ( "invitationCode" , this . state . invitationCode ) ;
}
}
2021-06-16 14:06:41 +08:00
return (
< Form
{ ... formItemLayout }
ref = { this . form }
name = "signup"
onFinish = { ( values ) => this . onFinish ( values ) }
onFinishFailed = { ( errorInfo ) => this . onFinishFailed ( errorInfo . values , errorInfo . errorFields , errorInfo . outOfDate ) }
initialValues = { {
application : application . name ,
organization : application . organization ,
2023-02-27 22:07:28 +08:00
countryCode : application . organizationObj . countryCodes ? . [ 0 ] ,
2021-06-16 14:06:41 +08:00
} }
size = "large"
2022-12-06 00:50:17 +08:00
layout = { Setting . isMobile ( ) ? "vertical" : "horizontal" }
style = { { width : Setting . isMobile ( ) ? "300px" : "400px" } }
2021-06-16 14:06:41 +08:00
>
2021-03-26 21:57:41 +08:00
< Form . Item
2021-06-16 14:06:41 +08:00
name = "application"
2022-12-06 00:50:17 +08:00
hidden = { true }
2021-03-26 21:57:41 +08:00
rules = { [
{
required : true ,
2022-07-10 15:45:55 +08:00
message : "Please input your application!" ,
2021-03-26 21:57:41 +08:00
} ,
] }
>
< / F o r m . I t e m >
2021-05-18 20:11:03 +08:00
< Form . Item
2021-06-16 14:06:41 +08:00
name = "organization"
2022-12-06 00:50:17 +08:00
hidden = { true }
2021-05-18 20:11:03 +08:00
rules = { [
{
required : true ,
2022-07-10 15:45:55 +08:00
message : "Please input your organization!" ,
2021-05-18 20:11:03 +08:00
} ,
] }
>
2021-03-26 21:57:41 +08:00
< / F o r m . I t e m >
2021-06-16 14:06:41 +08:00
{
2024-04-21 11:56:18 +08:00
application . signupItems ? . map ( ( signupItem , idx ) => {
return (
< div key = { idx } >
< div dangerouslySetInnerHTML = { { _ _html : ( "<style>" + signupItem . customCss + "</style>" ) } } / >
{ this . renderFormItem ( application , signupItem ) }
< / d i v >
) ;
2022-08-05 18:59:56 +08:00
} )
}
2021-03-26 21:57:41 +08:00
< / F o r m >
2022-07-10 15:45:55 +08:00
) ;
2021-03-26 21:57:41 +08:00
}
render ( ) {
2021-06-14 13:13:39 +08:00
const application = this . getApplicationObj ( ) ;
2023-03-24 23:17:54 +08:00
if ( application === undefined || application === null ) {
2021-04-28 15:54:50 +08:00
return null ;
}
2024-04-21 11:56:18 +08:00
let existSignupButton = false ;
application . signupItems ? . map ( item => {
item . name === "Signup button" ? existSignupButton = true : null ;
} ) ;
if ( ! existSignupButton ) {
application . signupItems ? . push ( {
customCss : "" ,
label : "" ,
name : "Signup button" ,
placeholder : "" ,
visible : true ,
} ) ;
}
2021-10-26 13:11:21 +08:00
if ( application . signupHtml !== "" ) {
return (
2022-07-10 15:45:55 +08:00
< div dangerouslySetInnerHTML = { { _ _html : application . signupHtml } } / >
) ;
2021-10-26 13:11:21 +08:00
}
2021-03-26 21:57:41 +08:00
return (
2022-12-22 23:39:02 +08:00
< React . Fragment >
2021-11-06 22:04:20 +08:00
< CustomGithubCorner / >
2022-12-24 17:47:05 +08:00
< div className = "login-content" style = { { margin : this . props . preview ? ? this . parseOffset ( application . formOffset ) } } >
2022-12-04 15:53:46 +08:00
{ Setting . inIframe ( ) || Setting . isMobile ( ) ? null : < div dangerouslySetInnerHTML = { { _ _html : application . formCss } } / > }
2023-05-12 12:16:03 +08:00
{ Setting . inIframe ( ) || ! Setting . isMobile ( ) ? null : < div dangerouslySetInnerHTML = { { _ _html : application . formCssMobile } } / > }
2022-10-22 21:43:41 +08:00
< div className = "login-panel" >
< div className = "side-image" style = { { display : application . formOffset !== 4 ? "none" : null } } >
< div dangerouslySetInnerHTML = { { _ _html : application . formSideHtml } } / >
< / d i v >
< div className = "login-form" >
2022-12-06 00:50:17 +08:00
{
Setting . renderHelmet ( application )
}
{
Setting . renderLogo ( application )
}
2023-03-26 18:44:47 +08:00
< LanguageSelect languages = { application . organizationObj . languages } style = { { top : "55px" , right : "5px" , position : "absolute" } } / >
2022-12-06 00:50:17 +08:00
{
this . renderForm ( application )
}
2021-04-28 15:54:50 +08:00
< / d i v >
2022-10-22 21:43:41 +08:00
< / d i v >
< / d i v >
2022-12-22 23:39:02 +08:00
< / R e a c t . F r a g m e n t >
2022-07-10 15:45:55 +08:00
) ;
2021-03-26 21:57:41 +08:00
}
}
2022-11-13 05:16:49 +01:00
export default withRouter ( SignupPage ) ;