mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-04 05:10:19 +08:00
feat(web): add lint (#875)
* feat: add lint * feat: fix lint error * chore: add ignore file * chore: close indent
This commit is contained in:
@ -13,12 +13,12 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Cascader, Col, Input, Row, Select} from 'antd';
|
||||
import {Cascader, Col, Input, Row, Select} from "antd";
|
||||
import i18next from "i18next";
|
||||
import * as UserBackend from "../backend/UserBackend";
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
const { Option } = Select;
|
||||
const {Option} = Select;
|
||||
|
||||
class AffiliationSelect extends React.Component {
|
||||
constructor(props) {
|
||||
@ -73,38 +73,38 @@ class AffiliationSelect extends React.Component {
|
||||
<React.Fragment>
|
||||
{
|
||||
this.props.application?.affiliationUrl === "" ? null : (
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={this.props.labelSpan}>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={this.props.labelSpan}>
|
||||
{Setting.getLabel(i18next.t("user:Address"), i18next.t("user:Address - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={24 - this.props.labelSpan} >
|
||||
<Cascader style={{width: '100%', maxWidth: '400px'}} value={this.props.user.address} options={this.state.addressOptions} onChange={value => {
|
||||
this.updateUserField('address', value);
|
||||
this.updateUserField('affiliation', '');
|
||||
this.updateUserField('score', 0);
|
||||
<Cascader style={{width: "100%", maxWidth: "400px"}} value={this.props.user.address} options={this.state.addressOptions} onChange={value => {
|
||||
this.updateUserField("address", value);
|
||||
this.updateUserField("affiliation", "");
|
||||
this.updateUserField("score", 0);
|
||||
this.getAffiliationOptions(this.props.application, this.props.user);
|
||||
}} placeholder={i18next.t("signup:Please input your address!")} />
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={this.props.labelSpan}>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={this.props.labelSpan}>
|
||||
{Setting.getLabel(i18next.t("user:Affiliation"), i18next.t("user:Affiliation - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
{
|
||||
this.props.application?.affiliationUrl === "" ? (
|
||||
<Input value={this.props.user.affiliation} onChange={e => {
|
||||
this.updateUserField('affiliation', e.target.value);
|
||||
this.updateUserField("affiliation", e.target.value);
|
||||
}} />
|
||||
) : (
|
||||
<Select virtual={false} style={{width: '100%'}} value={this.props.user.affiliation} onChange={(value => {
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.props.user.affiliation} onChange={(value => {
|
||||
const name = value;
|
||||
const affiliationOption = Setting.getArrayItem(this.state.affiliationOptions, "name", name);
|
||||
const id = affiliationOption.id;
|
||||
this.updateUserField('affiliation', name);
|
||||
this.updateUserField('score', id);
|
||||
this.updateUserField("affiliation", name);
|
||||
this.updateUserField("score", id);
|
||||
})}>
|
||||
{
|
||||
<Option key={0} value={""}>(empty)</Option>
|
||||
@ -118,7 +118,7 @@ class AffiliationSelect extends React.Component {
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,13 +12,13 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Button, Col, Input, Modal, Row } from "antd";
|
||||
import {Button, Col, Input, Modal, Row} from "antd";
|
||||
import React from "react";
|
||||
import i18next from "i18next";
|
||||
import * as UserBackend from "../backend/UserBackend";
|
||||
import * as ProviderBackend from "../backend/ProviderBackend";
|
||||
import { SafetyOutlined } from "@ant-design/icons";
|
||||
import { CaptchaWidget } from "./CaptchaWidget";
|
||||
import {SafetyOutlined} from "@ant-design/icons";
|
||||
import {CaptchaWidget} from "./CaptchaWidget";
|
||||
|
||||
export const CaptchaPreview = ({
|
||||
provider,
|
||||
@ -149,7 +149,7 @@ export const CaptchaPreview = ({
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Button
|
||||
style={{ fontSize: 14 }}
|
||||
style={{fontSize: 14}}
|
||||
type={"primary"}
|
||||
onClick={clickPreview}
|
||||
disabled={getButtonDisabled()}
|
||||
|
@ -12,9 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
import React, {useEffect} from "react";
|
||||
|
||||
export const CaptchaWidget = ({ captchaType, subType, siteKey, clientSecret, onChange, clientId2, clientSecret2 }) => {
|
||||
export const CaptchaWidget = ({captchaType, subType, siteKey, clientSecret, onChange, clientId2, clientSecret2}) => {
|
||||
const loadScript = (src) => {
|
||||
var tag = document.createElement("script");
|
||||
tag.async = false;
|
||||
@ -25,61 +25,60 @@ export const CaptchaWidget = ({ captchaType, subType, siteKey, clientSecret, onC
|
||||
|
||||
useEffect(() => {
|
||||
switch (captchaType) {
|
||||
case "reCAPTCHA":
|
||||
const reTimer = setInterval(() => {
|
||||
if (!window.grecaptcha) {
|
||||
loadScript("https://recaptcha.net/recaptcha/api.js");
|
||||
}
|
||||
if (window.grecaptcha && window.grecaptcha.render) {
|
||||
window.grecaptcha.render("captcha", {
|
||||
sitekey: siteKey,
|
||||
callback: onChange,
|
||||
});
|
||||
clearInterval(reTimer);
|
||||
}
|
||||
}, 300);
|
||||
break;
|
||||
case "hCaptcha":
|
||||
const hTimer = setInterval(() => {
|
||||
if (!window.hcaptcha) {
|
||||
loadScript("https://js.hcaptcha.com/1/api.js");
|
||||
}
|
||||
if (window.hcaptcha && window.hcaptcha.render) {
|
||||
window.hcaptcha.render("captcha", {
|
||||
sitekey: siteKey,
|
||||
callback: onChange,
|
||||
});
|
||||
clearInterval(hTimer);
|
||||
}
|
||||
}, 300);
|
||||
break;
|
||||
case "Aliyun Captcha":
|
||||
const AWSCTimer = setInterval(() => {
|
||||
if (!window.AWSC) {
|
||||
loadScript("https://g.alicdn.com/AWSC/AWSC/awsc.js");
|
||||
}
|
||||
case "reCAPTCHA":
|
||||
const reTimer = setInterval(() => {
|
||||
if (!window.grecaptcha) {
|
||||
loadScript("https://recaptcha.net/recaptcha/api.js");
|
||||
}
|
||||
if (window.grecaptcha && window.grecaptcha.render) {
|
||||
window.grecaptcha.render("captcha", {
|
||||
sitekey: siteKey,
|
||||
callback: onChange,
|
||||
});
|
||||
clearInterval(reTimer);
|
||||
}
|
||||
}, 300);
|
||||
break;
|
||||
case "hCaptcha":
|
||||
const hTimer = setInterval(() => {
|
||||
if (!window.hcaptcha) {
|
||||
loadScript("https://js.hcaptcha.com/1/api.js");
|
||||
}
|
||||
if (window.hcaptcha && window.hcaptcha.render) {
|
||||
window.hcaptcha.render("captcha", {
|
||||
sitekey: siteKey,
|
||||
callback: onChange,
|
||||
});
|
||||
clearInterval(hTimer);
|
||||
}
|
||||
}, 300);
|
||||
break;
|
||||
case "Aliyun Captcha":
|
||||
const AWSCTimer = setInterval(() => {
|
||||
if (!window.AWSC) {
|
||||
loadScript("https://g.alicdn.com/AWSC/AWSC/awsc.js");
|
||||
}
|
||||
|
||||
if (window.AWSC) {
|
||||
if (clientSecret2 && clientSecret2 !== "***") {
|
||||
window.AWSC.use(subType, function (state, module) {
|
||||
module.init({
|
||||
appkey: clientSecret2,
|
||||
scene: clientId2,
|
||||
renderTo: "captcha",
|
||||
success: function (data) {
|
||||
onChange(`SessionId=${data.sessionId}&AccessKeyId=${siteKey}&Scene=${clientId2}&AppKey=${clientSecret2}&Token=${data.token}&Sig=${data.sig}&RemoteIp=192.168.0.1`);
|
||||
},
|
||||
});
|
||||
if (window.AWSC) {
|
||||
if (clientSecret2 && clientSecret2 !== "***") {
|
||||
window.AWSC.use(subType, function(state, module) {
|
||||
module.init({
|
||||
appkey: clientSecret2,
|
||||
scene: clientId2,
|
||||
renderTo: "captcha",
|
||||
success: function(data) {
|
||||
onChange(`SessionId=${data.sessionId}&AccessKeyId=${siteKey}&Scene=${clientId2}&AppKey=${clientSecret2}&Token=${data.token}&Sig=${data.sig}&RemoteIp=192.168.0.1`);
|
||||
},
|
||||
});
|
||||
}
|
||||
clearInterval(AWSCTimer);
|
||||
});
|
||||
}
|
||||
}, 300);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
clearInterval(AWSCTimer);
|
||||
}
|
||||
}, 300);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [captchaType, subType, siteKey, clientSecret, clientId2, clientSecret2]);
|
||||
|
||||
return <div id="captcha"></div>;
|
||||
|
@ -18,9 +18,9 @@ import i18next from "i18next";
|
||||
import * as UserBackend from "../backend/UserBackend";
|
||||
import {SafetyOutlined} from "@ant-design/icons";
|
||||
import {authConfig} from "../auth/Auth";
|
||||
import { CaptchaWidget } from "./CaptchaWidget";
|
||||
import {CaptchaWidget} from "./CaptchaWidget";
|
||||
|
||||
const { Search } = Input;
|
||||
const {Search} = Input;
|
||||
|
||||
export const CountDownInput = (props) => {
|
||||
const {disabled, textBefore, onChange, onButtonClickArgs} = props;
|
||||
@ -38,35 +38,35 @@ export const CountDownInput = (props) => {
|
||||
const [clientSecret2, setClientSecret2] = React.useState("");
|
||||
|
||||
const handleCountDown = (leftTime = 60) => {
|
||||
let leftTimeSecond = leftTime
|
||||
setButtonLeftTime(leftTimeSecond)
|
||||
let leftTimeSecond = leftTime;
|
||||
setButtonLeftTime(leftTimeSecond);
|
||||
const countDown = () => {
|
||||
leftTimeSecond--;
|
||||
setButtonLeftTime(leftTimeSecond)
|
||||
setButtonLeftTime(leftTimeSecond);
|
||||
if (leftTimeSecond === 0) {
|
||||
return;
|
||||
}
|
||||
setTimeout(countDown, 1000);
|
||||
}
|
||||
};
|
||||
setTimeout(countDown, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
const handleOk = () => {
|
||||
setVisible(false);
|
||||
setButtonLoading(true)
|
||||
setButtonLoading(true);
|
||||
UserBackend.sendCode(checkType, checkId, key, ...onButtonClickArgs).then(res => {
|
||||
setKey("");
|
||||
setButtonLoading(false)
|
||||
setButtonLoading(false);
|
||||
if (res) {
|
||||
handleCountDown(60);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setVisible(false);
|
||||
setKey("");
|
||||
}
|
||||
};
|
||||
|
||||
const loadCaptcha = () => {
|
||||
UserBackend.getCaptcha("admin", authConfig.appName, false).then(res => {
|
||||
@ -90,8 +90,8 @@ export const CountDownInput = (props) => {
|
||||
setClientId2(res.clientId2);
|
||||
setClientSecret2(res.clientSecret2);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const renderCaptcha = () => {
|
||||
return (
|
||||
@ -108,16 +108,16 @@ export const CountDownInput = (props) => {
|
||||
}}
|
||||
/>
|
||||
<Row>
|
||||
<Input autoFocus value={key} prefix={<SafetyOutlined/>} placeholder={i18next.t("general:Captcha")} onPressEnter={handleOk} onChange={e => setKey(e.target.value)}/>
|
||||
<Input autoFocus value={key} prefix={<SafetyOutlined />} placeholder={i18next.t("general:Captcha")} onPressEnter={handleOk} onChange={e => setKey(e.target.value)} />
|
||||
</Row>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const onSubmit = (token) => {
|
||||
setButtonDisabled(false);
|
||||
setKey(token);
|
||||
}
|
||||
};
|
||||
|
||||
const renderCheck = () => {
|
||||
if (checkType === "Default") {
|
||||
@ -135,14 +135,14 @@ export const CountDownInput = (props) => {
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Search
|
||||
addonBefore={textBefore}
|
||||
disabled={disabled}
|
||||
prefix={<SafetyOutlined/>}
|
||||
prefix={<SafetyOutlined />}
|
||||
placeholder={i18next.t("code:Enter your code")}
|
||||
onChange={e => onChange(e.target.value)}
|
||||
enterButton={
|
||||
@ -171,4 +171,4 @@ export const CountDownInput = (props) => {
|
||||
</Modal>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Col, Row} from 'antd';
|
||||
import {Button, Col, Row} from "antd";
|
||||
import i18next from "i18next";
|
||||
import * as UserBackend from "../backend/UserBackend";
|
||||
import * as Setting from "../Setting";
|
||||
@ -84,7 +84,7 @@ class OAuthWidget extends React.Component {
|
||||
|
||||
getUserProperty(user, providerType, propertyName) {
|
||||
const key = `oauth_${providerType}_${propertyName}`;
|
||||
if (user.properties === null) return "";
|
||||
if (user.properties === null) {return "";}
|
||||
return user.properties[key];
|
||||
}
|
||||
|
||||
@ -94,8 +94,8 @@ class OAuthWidget extends React.Component {
|
||||
};
|
||||
AuthBackend.unlink(body)
|
||||
.then((res) => {
|
||||
if (res.status === 'ok') {
|
||||
Setting.showMessage("success", `Unlinked successfully`);
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", "Unlinked successfully");
|
||||
|
||||
this.unlinked();
|
||||
} else {
|
||||
@ -130,20 +130,20 @@ class OAuthWidget extends React.Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<Row key={provider.name} style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={this.props.labelSpan}>
|
||||
<Row key={provider.name} style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={this.props.labelSpan}>
|
||||
{
|
||||
Setting.getProviderLogo(provider)
|
||||
}
|
||||
<span style={{marginLeft: '5px'}}>
|
||||
<span style={{marginLeft: "5px"}}>
|
||||
{
|
||||
`${provider.type}:`
|
||||
}
|
||||
</span>
|
||||
</Col>
|
||||
<Col span={24 - this.props.labelSpan} >
|
||||
<img style={{marginRight: '10px'}} width={30} height={30} src={avatarUrl} alt={name} referrerPolicy="no-referrer" />
|
||||
<span style={{width: this.props.labelSpan === 3 ? '300px' : '130px', display: (Setting.isMobile()) ? 'inline' : "inline-block"}}>
|
||||
<img style={{marginRight: "10px"}} width={30} height={30} src={avatarUrl} alt={name} referrerPolicy="no-referrer" />
|
||||
<span style={{width: this.props.labelSpan === 3 ? "300px" : "130px", display: (Setting.isMobile()) ? "inline" : "inline-block"}}>
|
||||
{
|
||||
linkedValue === "" ? (
|
||||
"(empty)"
|
||||
@ -161,19 +161,19 @@ class OAuthWidget extends React.Component {
|
||||
{
|
||||
linkedValue === "" ? (
|
||||
<a key={provider.displayName} href={Provider.getAuthUrl(application, provider, "link")}>
|
||||
<Button style={{marginLeft: '20px', width: '80px'}} type="primary">{i18next.t("user:Link")}</Button>
|
||||
<Button style={{marginLeft: "20px", width: "80px"}} type="primary">{i18next.t("user:Link")}</Button>
|
||||
</a>
|
||||
) : (
|
||||
<Button disabled={!providerItem.canUnlink} style={{marginLeft: '20px', width: '80px'}} onClick={() => this.unlinkUser(provider.type)}>{i18next.t("user:Unlink")}</Button>
|
||||
<Button disabled={!providerItem.canUnlink} style={{marginLeft: "20px", width: "80px"}} onClick={() => this.unlinkUser(provider.type)}>{i18next.t("user:Unlink")}</Button>
|
||||
)
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.renderIdp(this.props.user, this.props.application, this.props.providerItem)
|
||||
return this.renderIdp(this.props.user, this.props.application, this.props.providerItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,43 +3,43 @@ import {Col, Row} from "antd";
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
class SamlWidget extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
addressOptions: [],
|
||||
affiliationOptions: [],
|
||||
};
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
addressOptions: [],
|
||||
affiliationOptions: [],
|
||||
};
|
||||
}
|
||||
|
||||
renderIdp(user, application, providerItem) {
|
||||
const provider = providerItem.provider;
|
||||
const name = user.name;
|
||||
renderIdp(user, application, providerItem) {
|
||||
const provider = providerItem.provider;
|
||||
const name = user.name;
|
||||
|
||||
return (
|
||||
<Row key={provider.name} style={{marginTop: '20px'}}>
|
||||
<Col style={{marginTop: '5px'}} span={this.props.labelSpan}>
|
||||
{
|
||||
Setting.getProviderLogo(provider)
|
||||
}
|
||||
<span style={{marginLeft: '5px'}}>
|
||||
{
|
||||
`${provider.type}:`
|
||||
}
|
||||
</span>
|
||||
</Col>
|
||||
<Col span={24 - this.props.labelSpan} style={{marginTop: '5px'}}>
|
||||
<span style={{
|
||||
width: this.props.labelSpan === 3 ? '300px' : '130px',
|
||||
display: (Setting.isMobile()) ? 'inline' : "inline-block"}}>{name}</span>
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Row key={provider.name} style={{marginTop: "20px"}}>
|
||||
<Col style={{marginTop: "5px"}} span={this.props.labelSpan}>
|
||||
{
|
||||
Setting.getProviderLogo(provider)
|
||||
}
|
||||
<span style={{marginLeft: "5px"}}>
|
||||
{
|
||||
`${provider.type}:`
|
||||
}
|
||||
</span>
|
||||
</Col>
|
||||
<Col span={24 - this.props.labelSpan} style={{marginTop: "5px"}}>
|
||||
<span style={{
|
||||
width: this.props.labelSpan === 3 ? "300px" : "130px",
|
||||
display: (Setting.isMobile()) ? "inline" : "inline-block"}}>{name}</span>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.renderIdp(this.props.user, this.props.application, this.props.providerItem)
|
||||
}
|
||||
render() {
|
||||
return this.renderIdp(this.props.user, this.props.application, this.props.providerItem);
|
||||
}
|
||||
}
|
||||
|
||||
export default SamlWidget;
|
||||
export default SamlWidget;
|
||||
|
Reference in New Issue
Block a user