mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-16 05:23:50 +08:00
feat: add terms of use in signin page (#1476)
* feat: extract terms of use renderer * fix: layout * fix: form styling * fix: required state * feat: application terms of use setting * fix: refactor getTermsOfUseContent * fix: refactor renderers
This commit is contained in:
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Link} from "react-router-dom";
|
import {Link} from "react-router-dom";
|
||||||
import {Tag, Tooltip, message, theme} from "antd";
|
import {Checkbox, Form, Modal, Tag, Tooltip, message, theme} from "antd";
|
||||||
import {QuestionCircleTwoTone} from "@ant-design/icons";
|
import {QuestionCircleTwoTone} from "@ant-design/icons";
|
||||||
import {isMobile as isMobileDevice} from "react-device-detect";
|
import {isMobile as isMobileDevice} from "react-device-detect";
|
||||||
import "./i18n";
|
import "./i18n";
|
||||||
@ -509,6 +509,69 @@ export function isMobile() {
|
|||||||
return isMobileDevice;
|
return isMobileDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getTermsOfUseContent(url, setTermsOfUseContent) {
|
||||||
|
fetch(url, {
|
||||||
|
method: "GET",
|
||||||
|
}).then(r => {
|
||||||
|
r.text().then(setTermsOfUseContent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isAgreementRequired(application) {
|
||||||
|
if (application) {
|
||||||
|
const agreementItem = application.signupItems.find(item => item.name === "Agreement");
|
||||||
|
if (agreementItem.rule === "None" || !agreementItem.rule) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (agreementItem && agreementItem.required) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderAgreement(required, onClick, noStyle, layout) {
|
||||||
|
return (
|
||||||
|
<Form.Item
|
||||||
|
name="agreement"
|
||||||
|
key="agreement"
|
||||||
|
valuePropName="checked"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: required,
|
||||||
|
message: i18next.t("signup:Please accept the agreement!"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
{...layout}
|
||||||
|
noStyle={noStyle}
|
||||||
|
>
|
||||||
|
<Checkbox style={{float: "left"}}>
|
||||||
|
{i18next.t("signup:Accept")}
|
||||||
|
<a onClick={onClick}>
|
||||||
|
{i18next.t("signup:Terms of Use")}
|
||||||
|
</a>
|
||||||
|
</Checkbox>
|
||||||
|
</Form.Item>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderModal(isOpen, onOk, onCancel, doc) {
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title={i18next.t("signup:Terms of Use")}
|
||||||
|
open={isOpen}
|
||||||
|
width={"55vw"}
|
||||||
|
closable={false}
|
||||||
|
okText={i18next.t("signup:Accept")}
|
||||||
|
cancelText={i18next.t("signup:Decline")}
|
||||||
|
onOk={onOk}
|
||||||
|
onCancel={onCancel}
|
||||||
|
>
|
||||||
|
<iframe title={"terms"} style={{border: 0, width: "100%", height: "60vh"}} srcDoc={doc} />
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function getFormattedDate(date) {
|
export function getFormattedDate(date) {
|
||||||
if (date === undefined) {
|
if (date === undefined) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -186,6 +186,11 @@ class SignupTable extends React.Component {
|
|||||||
{id: "Normal", name: "Normal"},
|
{id: "Normal", name: "Normal"},
|
||||||
{id: "No verification", name: "No verification"},
|
{id: "No verification", name: "No verification"},
|
||||||
];
|
];
|
||||||
|
} else if (record.name === "Agreement") {
|
||||||
|
options = [
|
||||||
|
{id: "None", name: "None"},
|
||||||
|
{id: "Signin", name: "Signin"},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.length === 0) {
|
if (options.length === 0) {
|
||||||
|
@ -53,12 +53,16 @@ class LoginPage extends React.Component {
|
|||||||
samlResponse: "",
|
samlResponse: "",
|
||||||
relayState: "",
|
relayState: "",
|
||||||
redirectUrl: "",
|
redirectUrl: "",
|
||||||
|
isTermsOfUseVisible: false,
|
||||||
|
termsOfUseContent: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.state.type === "cas" && props.match?.params.casApplicationName !== undefined) {
|
if (this.state.type === "cas" && props.match?.params.casApplicationName !== undefined) {
|
||||||
this.state.owner = props.match?.params.owner;
|
this.state.owner = props.match?.params.owner;
|
||||||
this.state.applicationName = props.match?.params.casApplicationName;
|
this.state.applicationName = props.match?.params.casApplicationName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.form = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -122,7 +126,9 @@ class LoginPage extends React.Component {
|
|||||||
this.onUpdateApplication(application);
|
this.onUpdateApplication(application);
|
||||||
this.setState({
|
this.setState({
|
||||||
application: application,
|
application: application,
|
||||||
});
|
}, () => Setting.getTermsOfUseContent(this.state.application.termsOfUse, res => {
|
||||||
|
this.setState({termsOfUseContent: res});
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
OrganizationBackend.getDefaultApplication("admin", this.state.owner)
|
OrganizationBackend.getDefaultApplication("admin", this.state.owner)
|
||||||
@ -132,7 +138,9 @@ class LoginPage extends React.Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
application: res.data,
|
application: res.data,
|
||||||
applicationName: res.data.name,
|
applicationName: res.data.name,
|
||||||
});
|
}, () => Setting.getTermsOfUseContent(this.state.application.termsOfUse, res => {
|
||||||
|
this.setState({termsOfUseContent: res});
|
||||||
|
}));
|
||||||
} else {
|
} else {
|
||||||
this.onUpdateApplication(null);
|
this.onUpdateApplication(null);
|
||||||
Setting.showMessage("error", res.msg);
|
Setting.showMessage("error", res.msg);
|
||||||
@ -383,6 +391,7 @@ class LoginPage extends React.Component {
|
|||||||
onFinish={(values) => {this.onFinish(values);}}
|
onFinish={(values) => {this.onFinish(values);}}
|
||||||
style={{width: "300px"}}
|
style={{width: "300px"}}
|
||||||
size="large"
|
size="large"
|
||||||
|
ref={this.form}
|
||||||
>
|
>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
hidden={true}
|
hidden={true}
|
||||||
@ -456,11 +465,20 @@ class LoginPage extends React.Component {
|
|||||||
}
|
}
|
||||||
</Row>
|
</Row>
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Form.Item name="autoSignin" valuePropName="checked" noStyle>
|
{
|
||||||
<Checkbox style={{float: "left"}} disabled={!application.enablePassword}>
|
Setting.isAgreementRequired(application) ?
|
||||||
{i18next.t("login:Auto sign in")}
|
Setting.renderAgreement(true, () => {
|
||||||
</Checkbox>
|
this.setState({
|
||||||
</Form.Item>
|
isTermsOfUseVisible: true,
|
||||||
|
});
|
||||||
|
}, true) : (
|
||||||
|
<Form.Item name="autoSignin" valuePropName="checked" noStyle>
|
||||||
|
<Checkbox style={{float: "left"}} disabled={!application.enablePassword}>
|
||||||
|
{i18next.t("login:Auto sign in")}
|
||||||
|
</Checkbox>
|
||||||
|
</Form.Item>
|
||||||
|
)
|
||||||
|
}
|
||||||
{
|
{
|
||||||
Setting.renderForgetLink(application, i18next.t("login:Forgot password?"))
|
Setting.renderForgetLink(application, i18next.t("login:Forgot password?"))
|
||||||
}
|
}
|
||||||
@ -827,6 +845,19 @@ class LoginPage extends React.Component {
|
|||||||
{
|
{
|
||||||
this.renderForm(application)
|
this.renderForm(application)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
Setting.renderModal(this.state.isTermsOfUseVisible, () => {
|
||||||
|
this.form.current.setFieldsValue({agreement: true});
|
||||||
|
this.setState({
|
||||||
|
isTermsOfUseVisible: false,
|
||||||
|
});
|
||||||
|
}, () => {
|
||||||
|
this.form.current.setFieldsValue({agreement: false});
|
||||||
|
this.setState({
|
||||||
|
isTermsOfUseVisible: false,
|
||||||
|
});
|
||||||
|
}, this.state.termsOfUseContent)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,8 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Link} from "react-router-dom";
|
import {Button, Form, Input, Result} from "antd";
|
||||||
import {Button, Checkbox, Form, Input, Modal, Result} from "antd";
|
|
||||||
import * as Setting from "../Setting";
|
import * as Setting from "../Setting";
|
||||||
import * as AuthBackend from "./AuthBackend";
|
import * as AuthBackend from "./AuthBackend";
|
||||||
import * as ProviderButton from "./ProviderButton";
|
import * as ProviderButton from "./ProviderButton";
|
||||||
@ -113,7 +112,9 @@ class SignupPage extends React.Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (application !== null && application !== undefined) {
|
if (application !== null && application !== undefined) {
|
||||||
this.getTermsofuseContent(application.termsOfUse);
|
Setting.getTermsOfUseContent(application.termsOfUse, res => {
|
||||||
|
this.setState({termsOfUseContent: res});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -134,16 +135,6 @@ class SignupPage extends React.Component {
|
|||||||
return this.props.application ?? this.state.application;
|
return this.props.application ?? this.state.application;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTermsofuseContent(url) {
|
|
||||||
fetch(url, {
|
|
||||||
method: "GET",
|
|
||||||
}).then(r => {
|
|
||||||
r.text().then(res => {
|
|
||||||
this.setState({termsOfUseContent: res});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onUpdateAccount(account) {
|
onUpdateAccount(account) {
|
||||||
this.props.onUpdateAccount(account);
|
this.props.onUpdateAccount(account);
|
||||||
}
|
}
|
||||||
@ -484,58 +475,28 @@ class SignupPage extends React.Component {
|
|||||||
);
|
);
|
||||||
} else if (signupItem.name === "Agreement") {
|
} else if (signupItem.name === "Agreement") {
|
||||||
return (
|
return (
|
||||||
<Form.Item
|
Setting.renderAgreement(Setting.isAgreementRequired(application), () => {
|
||||||
name="agreement"
|
this.setState({
|
||||||
key="agreement"
|
isTermsOfUseVisible: true,
|
||||||
valuePropName="checked"
|
});
|
||||||
rules={[
|
}, false, tailFormItemLayout)
|
||||||
{
|
|
||||||
required: required,
|
|
||||||
message: i18next.t("signup:Please accept the agreement!"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
{...tailFormItemLayout}
|
|
||||||
>
|
|
||||||
<Checkbox>
|
|
||||||
{i18next.t("signup:Accept")}
|
|
||||||
<Link onClick={() => {
|
|
||||||
this.setState({
|
|
||||||
isTermsOfUseVisible: true,
|
|
||||||
});
|
|
||||||
}}>
|
|
||||||
{i18next.t("signup:Terms of Use")}
|
|
||||||
</Link>
|
|
||||||
</Checkbox>
|
|
||||||
</Form.Item>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderModal() {
|
renderModal() {
|
||||||
return (
|
return (
|
||||||
<Modal
|
Setting.renderModal(this.state.isTermsOfUseVisible, () => {
|
||||||
title={i18next.t("signup:Terms of Use")}
|
this.form.current.setFieldsValue({agreement: true});
|
||||||
open={this.state.isTermsOfUseVisible}
|
this.setState({
|
||||||
width={"55vw"}
|
isTermsOfUseVisible: false,
|
||||||
closable={false}
|
});
|
||||||
okText={i18next.t("signup:Accept")}
|
}, () => {
|
||||||
cancelText={i18next.t("signup:Decline")}
|
this.form.current.setFieldsValue({agreement: false});
|
||||||
onOk={() => {
|
this.setState({
|
||||||
this.form.current.setFieldsValue({agreement: true});
|
isTermsOfUseVisible: false,
|
||||||
this.setState({
|
});
|
||||||
isTermsOfUseVisible: false,
|
}, this.state.termsOfUseContent)
|
||||||
});
|
|
||||||
}}
|
|
||||||
onCancel={() => {
|
|
||||||
this.form.current.setFieldsValue({agreement: false});
|
|
||||||
this.setState({
|
|
||||||
isTermsOfUseVisible: false,
|
|
||||||
});
|
|
||||||
this.props.history.goBack();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<iframe title={"terms"} style={{border: 0, width: "100%", height: "60vh"}} srcDoc={this.state.termsOfUseContent} />
|
|
||||||
</Modal>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user