mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-23 10:45:47 +08:00
Add signup table.
This commit is contained in:
parent
7ea469e876
commit
02b1feb2e5
@ -32,6 +32,7 @@ type Application struct {
|
|||||||
EnablePassword bool `json:"enablePassword"`
|
EnablePassword bool `json:"enablePassword"`
|
||||||
EnableSignUp bool `json:"enableSignUp"`
|
EnableSignUp bool `json:"enableSignUp"`
|
||||||
Providers []*ProviderItem `xorm:"varchar(10000)" json:"providers"`
|
Providers []*ProviderItem `xorm:"varchar(10000)" json:"providers"`
|
||||||
|
SignupItems []*SignupItem `xorm:"varchar(1000)" json:"signupItems"`
|
||||||
OrganizationObj *Organization `xorm:"-" json:"organizationObj"`
|
OrganizationObj *Organization `xorm:"-" json:"organizationObj"`
|
||||||
|
|
||||||
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
||||||
|
@ -67,6 +67,7 @@ func initBuiltInApplication() {
|
|||||||
EnablePassword: true,
|
EnablePassword: true,
|
||||||
EnableSignUp: true,
|
EnableSignUp: true,
|
||||||
Providers: []*ProviderItem{},
|
Providers: []*ProviderItem{},
|
||||||
|
SignupItems: []*SignupItem{},
|
||||||
RedirectUris: []string{},
|
RedirectUris: []string{},
|
||||||
ExpireInHours: 168,
|
ExpireInHours: 168,
|
||||||
}
|
}
|
||||||
|
22
object/signup_item.go
Normal file
22
object/signup_item.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package object
|
||||||
|
|
||||||
|
type SignupItem struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Visible bool `json:"visible"`
|
||||||
|
Required bool `json:"required"`
|
||||||
|
Rule string `json:"rule"`
|
||||||
|
}
|
@ -24,6 +24,7 @@ import LoginPage from "./auth/LoginPage";
|
|||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import UrlTable from "./UrlTable";
|
import UrlTable from "./UrlTable";
|
||||||
import ProviderTable from "./ProviderTable";
|
import ProviderTable from "./ProviderTable";
|
||||||
|
import SignupTable from "./SignupTable";
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
@ -299,6 +300,18 @@ class ApplicationEditPage extends React.Component {
|
|||||||
this.renderPreview()
|
this.renderPreview()
|
||||||
}
|
}
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: '20px'}} >
|
||||||
|
<Col style={{marginTop: '5px'}} span={2}>
|
||||||
|
{i18next.t("application:Signup items")}:
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<SignupTable
|
||||||
|
title={i18next.t("application:Signup items")}
|
||||||
|
table={this.state.application.signupItems}
|
||||||
|
onUpdateTable={(value) => { this.updateApplicationField('signupItems', value)}}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {DownOutlined, DeleteOutlined, UpOutlined, LinkOutlined} from '@ant-design/icons';
|
import {DownOutlined, DeleteOutlined, UpOutlined} from '@ant-design/icons';
|
||||||
import {Button, Col, Input, Row, Select, Switch, Table, Tooltip} from 'antd';
|
import {Button, Col, Row, Select, Switch, Table, Tooltip} from 'antd';
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
@ -81,11 +81,6 @@ class ProviderTable extends React.Component {
|
|||||||
}
|
}
|
||||||
</Select>
|
</Select>
|
||||||
)
|
)
|
||||||
return (
|
|
||||||
<Input prefix={<LinkOutlined/>} value={text} onChange={e => {
|
|
||||||
this.updateField(table, index, 'name', e.target.value);
|
|
||||||
}} />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
197
web/src/SignupTable.js
Normal file
197
web/src/SignupTable.js
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import {DownOutlined, DeleteOutlined, UpOutlined} from '@ant-design/icons';
|
||||||
|
import {Button, Col, Row, Select, Switch, Table, Tooltip} from 'antd';
|
||||||
|
import * as Setting from "./Setting";
|
||||||
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
const { Option } = Select;
|
||||||
|
|
||||||
|
class SignupTable extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
classes: props,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTable(table) {
|
||||||
|
this.props.onUpdateTable(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateField(table, index, key, value) {
|
||||||
|
table[index][key] = value;
|
||||||
|
this.updateTable(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
addRow(table) {
|
||||||
|
let row = {name: "Please select a signup item", visible: true, required: true, rule: "None"};
|
||||||
|
if (table === undefined) {
|
||||||
|
table = [];
|
||||||
|
}
|
||||||
|
table = Setting.addRow(table, row);
|
||||||
|
this.updateTable(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteRow(table, i) {
|
||||||
|
table = Setting.deleteRow(table, i);
|
||||||
|
this.updateTable(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
upRow(table, i) {
|
||||||
|
table = Setting.swapRow(table, i - 1, i);
|
||||||
|
this.updateTable(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
downRow(table, i) {
|
||||||
|
table = Setting.swapRow(table, i, i + 1);
|
||||||
|
this.updateTable(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTable(table) {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: i18next.t("provider:Name"),
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
<Select virtual={false} style={{width: '100%'}}
|
||||||
|
value={text}
|
||||||
|
onChange={value => {
|
||||||
|
this.updateField(table, index, 'name', value);
|
||||||
|
}} >
|
||||||
|
{
|
||||||
|
[
|
||||||
|
{id: 'Username', name: 'Username'},
|
||||||
|
{id: 'ID', name: 'ID'},
|
||||||
|
{id: 'Display name', name: 'Display name'},
|
||||||
|
{id: 'Affiliation', name: 'Affiliation'},
|
||||||
|
{id: 'Email', name: 'Email'},
|
||||||
|
{id: 'Password', name: 'Password'},
|
||||||
|
{id: 'Confirm', name: 'Confirm'},
|
||||||
|
{id: 'Phone', name: 'Phone'},
|
||||||
|
{id: 'Agreement', name: 'Agreement'},
|
||||||
|
].map((item, index) => <Option key={index} value={item.id}>{item.name}</Option>)
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("provider:visible"),
|
||||||
|
dataIndex: 'visible',
|
||||||
|
key: 'visible',
|
||||||
|
width: '120px',
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
<Switch checked={text} onChange={checked => {
|
||||||
|
this.updateField(table, index, 'visible', checked);
|
||||||
|
if (!checked) {
|
||||||
|
this.updateField(table, index, 'required', false);
|
||||||
|
}
|
||||||
|
}} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("provider:required"),
|
||||||
|
dataIndex: 'required',
|
||||||
|
key: 'required',
|
||||||
|
width: '120px',
|
||||||
|
render: (text, record, index) => {
|
||||||
|
if (!record.visible) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Switch checked={text} onChange={checked => {
|
||||||
|
this.updateField(table, index, 'required', checked);
|
||||||
|
}} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("provider:rule"),
|
||||||
|
dataIndex: 'rule',
|
||||||
|
key: 'rule',
|
||||||
|
width: '120px',
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
<Select virtual={false} style={{width: '100%'}} value={text} onChange={(value => {
|
||||||
|
this.updateField(table, index, 'rule', value);
|
||||||
|
})}>
|
||||||
|
{
|
||||||
|
[
|
||||||
|
{id: 'None', name: 'None'},
|
||||||
|
{id: 'Random', name: 'Random'},
|
||||||
|
{id: 'Incremental', name: 'Incremental'},
|
||||||
|
].map((item, index) => <Option key={index} value={item.id}>{item.name}</Option>)
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("general:Action"),
|
||||||
|
key: 'action',
|
||||||
|
width: '100px',
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Tooltip placement="bottomLeft" title={i18next.t("general:Up")}>
|
||||||
|
<Button style={{marginRight: "5px"}} disabled={index === 0} icon={<UpOutlined />} size="small" onClick={() => this.upRow(table, index)} />
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip placement="topLeft" title={i18next.t("general:Down")}>
|
||||||
|
<Button style={{marginRight: "5px"}} disabled={index === table.length - 1} icon={<DownOutlined />} size="small" onClick={() => this.downRow(table, index)} />
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip placement="topLeft" title={i18next.t("general:Delete")}>
|
||||||
|
<Button icon={<DeleteOutlined />} size="small" onClick={() => this.deleteRow(table, index)} />
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table rowKey="index" columns={columns} dataSource={table} size="middle" bordered pagination={false}
|
||||||
|
title={() => (
|
||||||
|
<div>
|
||||||
|
{this.props.title}
|
||||||
|
<Button style={{marginRight: "5px"}} type="primary" size="small" onClick={() => this.addRow(table)}>{i18next.t("general:Add")}</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Row style={{marginTop: '20px'}} >
|
||||||
|
<Col span={24}>
|
||||||
|
{
|
||||||
|
this.renderTable(this.props.table)
|
||||||
|
}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SignupTable;
|
@ -126,6 +126,194 @@ class SignupPage extends React.Component {
|
|||||||
this.form.current.scrollToField(errorFields[0].name);
|
this.form.current.scrollToField(errorFields[0].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderFormItem(application, signupItem) {
|
||||||
|
if (!signupItem.visible) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signupItem.name === "Username") {
|
||||||
|
return (
|
||||||
|
<Form.Item
|
||||||
|
name="username"
|
||||||
|
label={i18next.t("signup:Username")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: i18next.t("login:Please input your username!"),
|
||||||
|
whitespace: true,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
)
|
||||||
|
} else if (signupItem.name === "Display name") {
|
||||||
|
return (
|
||||||
|
<Form.Item
|
||||||
|
name="name"
|
||||||
|
label={i18next.t("general:Display name")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: i18next.t("signup:Please input your display name!"),
|
||||||
|
whitespace: true,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
)
|
||||||
|
} else if (signupItem.name === "Affiliation") {
|
||||||
|
return (
|
||||||
|
<Form.Item
|
||||||
|
name="affiliation"
|
||||||
|
label={i18next.t("user:Affiliation")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: i18next.t("signup:Please input your affiliation!"),
|
||||||
|
whitespace: true,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
)
|
||||||
|
} else if (signupItem.name === "Email") {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Form.Item
|
||||||
|
name="email"
|
||||||
|
label={i18next.t("general:Email")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
type: 'email',
|
||||||
|
message: i18next.t("signup:The input is not valid Email!"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: i18next.t("signup:Please input your Email!"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input onChange={e => this.setState({email: e.target.value})} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="emailCode"
|
||||||
|
label={i18next.t("signup:Email code")}
|
||||||
|
rules={[{
|
||||||
|
required: true,
|
||||||
|
message: i18next.t("signup:Please input your verification code!"),
|
||||||
|
}]}
|
||||||
|
>
|
||||||
|
<CountDownInput
|
||||||
|
defaultButtonText={i18next.t("user:Send code")}
|
||||||
|
onButtonClick={UserBackend.sendCode}
|
||||||
|
onButtonClickArgs={[this.state.email, "email", application?.organizationObj.owner + "/" + application?.organizationObj.name]}
|
||||||
|
coolDownTime={60}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
} else if (signupItem.name === "Password") {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Form.Item
|
||||||
|
name="password"
|
||||||
|
label={i18next.t("general:Password")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: i18next.t("login:Please input your password!"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
hasFeedback
|
||||||
|
>
|
||||||
|
<Input.Password />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="confirm"
|
||||||
|
label={i18next.t("signup:Confirm")}
|
||||||
|
dependencies={['password']}
|
||||||
|
hasFeedback
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: i18next.t("signup:Please confirm your password!"),
|
||||||
|
},
|
||||||
|
({ getFieldValue }) => ({
|
||||||
|
validator(rule, value) {
|
||||||
|
if (!value || getFieldValue('password') === value) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.reject(i18next.t("signup:Your confirmed password is inconsistent with the password!"));
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input.Password />
|
||||||
|
</Form.Item>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
} else if (signupItem.name === "Phone") {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Form.Item
|
||||||
|
name="phone"
|
||||||
|
label={i18next.t("general:Phone")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: i18next.t("signup:Please input your phone number!"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
addonBefore={`+${this.state.application?.organizationObj.phonePrefix}`}
|
||||||
|
onChange={e => this.setState({phone: e.target.value})}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="phoneCode"
|
||||||
|
label={i18next.t("signup:Phone code")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: i18next.t("signup:Please input your phone verification code!"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<CountDownInput
|
||||||
|
defaultButtonText={i18next.t("user:Send code")}
|
||||||
|
onButtonClick={UserBackend.sendCode}
|
||||||
|
onButtonClickArgs={[this.state.phone, "phone", application.organizationObj.owner + "/" + application.organizationObj.name]}
|
||||||
|
coolDownTime={60}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
} else if (signupItem.name === "Agreement") {
|
||||||
|
return (
|
||||||
|
<Form.Item
|
||||||
|
name="agreement"
|
||||||
|
valuePropName="checked"
|
||||||
|
{...tailFormItemLayout}
|
||||||
|
>
|
||||||
|
<Checkbox>
|
||||||
|
{i18next.t("signup:Accept")}
|
||||||
|
<Link to={"/agreement"}>
|
||||||
|
{i18next.t("signup:Terms of Use")}
|
||||||
|
</Link>
|
||||||
|
</Checkbox>
|
||||||
|
</Form.Item>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderForm(application) {
|
renderForm(application) {
|
||||||
if (!application.enableSignUp) {
|
if (!application.enableSignUp) {
|
||||||
return (
|
return (
|
||||||
@ -146,7 +334,6 @@ class SignupPage extends React.Component {
|
|||||||
</Result>
|
</Result>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
{...formItemLayout}
|
{...formItemLayout}
|
||||||
@ -183,155 +370,9 @@ class SignupPage extends React.Component {
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
{
|
||||||
name="username"
|
application.signupItems.map(signupItem => this.renderFormItem(application, signupItem))
|
||||||
label={i18next.t("signup:Username")}
|
}
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: i18next.t("login:Please input your username!"),
|
|
||||||
whitespace: true,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
name="name"
|
|
||||||
label={i18next.t("general:Display name")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: i18next.t("signup:Please input your display name!"),
|
|
||||||
whitespace: true,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
name="affiliation"
|
|
||||||
label={i18next.t("user:Affiliation")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: i18next.t("signup:Please input your affiliation!"),
|
|
||||||
whitespace: true,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
name="email"
|
|
||||||
label={i18next.t("general:Email")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
type: 'email',
|
|
||||||
message: i18next.t("signup:The input is not valid Email!"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: i18next.t("signup:Please input your Email!"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input onChange={e => this.setState({email: e.target.value})} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
name="emailCode"
|
|
||||||
label={i18next.t("signup:Email code")}
|
|
||||||
rules={[{
|
|
||||||
required: true,
|
|
||||||
message: i18next.t("signup:Please input your verification code!"),
|
|
||||||
}]}
|
|
||||||
>
|
|
||||||
<CountDownInput
|
|
||||||
defaultButtonText={i18next.t("user:Send code")}
|
|
||||||
onButtonClick={UserBackend.sendCode}
|
|
||||||
onButtonClickArgs={[this.state.email, "email", application?.organizationObj.owner + "/" + application?.organizationObj.name]}
|
|
||||||
coolDownTime={60}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
name="password"
|
|
||||||
label={i18next.t("general:Password")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: i18next.t("login:Please input your password!"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
hasFeedback
|
|
||||||
>
|
|
||||||
<Input.Password />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
name="confirm"
|
|
||||||
label={i18next.t("signup:Confirm")}
|
|
||||||
dependencies={['password']}
|
|
||||||
hasFeedback
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: i18next.t("signup:Please confirm your password!"),
|
|
||||||
},
|
|
||||||
({ getFieldValue }) => ({
|
|
||||||
validator(rule, value) {
|
|
||||||
if (!value || getFieldValue('password') === value) {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.reject(i18next.t("signup:Your confirmed password is inconsistent with the password!"));
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input.Password />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
name="phone"
|
|
||||||
label={i18next.t("general:Phone")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: i18next.t("signup:Please input your phone number!"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
}}
|
|
||||||
addonBefore={`+${this.state.application?.organizationObj.phonePrefix}`}
|
|
||||||
onChange={e => this.setState({phone: e.target.value})}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
name="phoneCode"
|
|
||||||
label={i18next.t("signup:Phone code")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: i18next.t("signup:Please input your phone verification code!"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CountDownInput
|
|
||||||
defaultButtonText={i18next.t("user:Send code")}
|
|
||||||
onButtonClick={UserBackend.sendCode}
|
|
||||||
onButtonClickArgs={[this.state.phone, "phone", application.organizationObj.owner + "/" + application.organizationObj.name]}
|
|
||||||
coolDownTime={60}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name="agreement" valuePropName="checked" {...tailFormItemLayout}>
|
|
||||||
<Checkbox>
|
|
||||||
{i18next.t("signup:Accept")}
|
|
||||||
<Link to={"/agreement"}>
|
|
||||||
{i18next.t("signup:Terms of Use")}
|
|
||||||
</Link>
|
|
||||||
</Checkbox>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...tailFormItemLayout}>
|
<Form.Item {...tailFormItemLayout}>
|
||||||
<Button type="primary" htmlType="submit">
|
<Button type="primary" htmlType="submit">
|
||||||
{i18next.t("account:Sign Up")}
|
{i18next.t("account:Sign Up")}
|
||||||
|
@ -177,7 +177,8 @@
|
|||||||
"Test signup page..": "Test signup page..",
|
"Test signup page..": "Test signup page..",
|
||||||
"Test signin page..": "Test signin page..",
|
"Test signin page..": "Test signin page..",
|
||||||
"Redirect URL": "Redirect URL",
|
"Redirect URL": "Redirect URL",
|
||||||
"Redirect URLs": "Redirect URLs"
|
"Redirect URLs": "Redirect URLs",
|
||||||
|
"Signup items": "Signup items"
|
||||||
},
|
},
|
||||||
"forget":
|
"forget":
|
||||||
{
|
{
|
||||||
|
@ -177,7 +177,8 @@
|
|||||||
"Test signup page..": "测试注册页面..",
|
"Test signup page..": "测试注册页面..",
|
||||||
"Test signin page..": "测试登录页面..",
|
"Test signin page..": "测试登录页面..",
|
||||||
"Redirect URL": "回调URL",
|
"Redirect URL": "回调URL",
|
||||||
"Redirect URLs": "回调URLs"
|
"Redirect URLs": "回调URLs",
|
||||||
|
"Signup items": "注册项"
|
||||||
},
|
},
|
||||||
"forget":
|
"forget":
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user