You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@skywalking.apache.org by ha...@apache.org on 2018/06/13 08:38:07 UTC
[incubator-skywalking-ui] 01/01: Add login and logout
This is an automated email from the ASF dual-hosted git repository.
hanahmily pushed a commit to branch 5.0.0/beta2
in repository https://gitbox.apache.org/repos/asf/incubator-skywalking-ui.git
commit c19b7c83b09238f019d81ff57088250c34630abc
Author: gaohongtao <ha...@gmail.com>
AuthorDate: Wed Jun 13 16:36:35 2018 +0800
Add login and logout
Add login page which contains username/password mode.
---
.roadhogrc.mock.js | 16 +++
public/img/icon/alarm-backgroud.png | Bin 0 -> 2294 bytes
src/common/router.js | 3 +
src/components/GlobalHeader/index.js | 19 ++-
src/components/GlobalHeader/index.less | 4 +-
src/components/Login/LoginItem.js | 121 ++++++++++++++++++
.../Login/LoginSubmit.js} | 22 +++-
.../authority.js => components/Login/LoginTab.js} | 35 ++++-
src/components/Login/index.js | 141 +++++++++++++++++++++
.../authority.js => components/Login/index.less} | 47 ++++++-
src/components/Login/map.js | 86 +++++++++++++
src/layouts/BasicLayout.js | 2 +-
src/layouts/UserLayout.js | 24 +---
src/models/login.js | 1 -
src/routes/User/Login.js | 65 ++--------
src/utils/authority.js | 4 +-
16 files changed, 488 insertions(+), 102 deletions(-)
diff --git a/.roadhogrc.mock.js b/.roadhogrc.mock.js
index 436a0e2..af5f2f1 100644
--- a/.roadhogrc.mock.js
+++ b/.roadhogrc.mock.js
@@ -25,6 +25,22 @@ const proxy = {
'POST /api/trace/options': getAllApplicationForTrace,
'POST /api/trace': getTrace,
'POST /api/spans': getSpans,
+ 'POST /api/login/account': (req, res) => {
+ const { password, userName, type } = req.body;
+ if (password === '888888' && userName === 'admin') {
+ res.send({
+ status: 'ok',
+ type,
+ currentAuthority: 'admin',
+ });
+ return;
+ }
+ res.send({
+ status: 'error',
+ type,
+ currentAuthority: 'guest',
+ });
+ },
};
export default noMock ? {} : delay(proxy, 1000);
diff --git a/public/img/icon/alarm-backgroud.png b/public/img/icon/alarm-backgroud.png
new file mode 100644
index 0000000..afde99b
Binary files /dev/null and b/public/img/icon/alarm-backgroud.png differ
diff --git a/src/common/router.js b/src/common/router.js
index 2dae774..00e3934 100644
--- a/src/common/router.js
+++ b/src/common/router.js
@@ -112,6 +112,9 @@ export const getRouterData = (app) => {
'/user': {
component: dynamicWrapper(app, [], () => import('../layouts/UserLayout')),
},
+ '/user/login': {
+ component: dynamicWrapper(app, ['login'], () => import('../routes/User/Login')),
+ },
'/exception/403': {
component: dynamicWrapper(app, [], () => import('../routes/Exception/403')),
},
diff --git a/src/components/GlobalHeader/index.js b/src/components/GlobalHeader/index.js
index f665a4c..cf6ba58 100644
--- a/src/components/GlobalHeader/index.js
+++ b/src/components/GlobalHeader/index.js
@@ -17,7 +17,7 @@
import React, { PureComponent } from 'react';
-import { Layout, Icon, Tag, Divider } from 'antd';
+import { Layout, Icon, Tag, Divider, Dropdown, Avatar, Menu } from 'antd';
import moment from 'moment';
import groupBy from 'lodash/groupBy';
import Debounce from 'lodash-decorators/debounce';
@@ -75,9 +75,17 @@ export default class GlobalHeader extends PureComponent {
collapsed, notices: { applicationAlarmList, serverAlarmList },
logo, selectedDuration, fetching, isMonitor,
onDurationToggle, onDurationReload, onRedirect: redirect,
+ onMenuClick,
} = this.props;
const applications = applicationAlarmList.items.map(_ => ({ ..._, datetime: _.startTime }));
const servers = serverAlarmList.items.map(_ => ({ ..._, datetime: _.startTime }));
+ const menu = (
+ <Menu className={styles.menu} selectedKeys={[]} onClick={onMenuClick}>
+ <Menu.Item key="logout">
+ <Icon type="logout" />Logout
+ </Menu.Item>
+ </Menu>
+ );
return (
<Header className={styles.header}>
<Link to="/" className={styles.logo} key="logo">
@@ -118,15 +126,20 @@ export default class GlobalHeader extends PureComponent {
list={applications}
title="Application"
emptyText="No alarm"
- emptyImage="https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg"
+ emptyImage="alarm-backgroud.png"
/>
<NoticeIcon.Tab
list={servers}
title="Server"
emptyText="No alarm"
- emptyImage="https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg"
+ emptyImage="alarm-backgroud.png"
/>
</NoticeIcon>
+ <Dropdown overlay={menu}>
+ <span className={`${styles.action} ${styles.account}`}>
+ <Avatar size="small" className={styles.avatar} icon="user" />
+ </span>
+ </Dropdown>
</div>
) : null}
</Header>
diff --git a/src/components/GlobalHeader/index.less b/src/components/GlobalHeader/index.less
index d91df00..98a3b6c 100644
--- a/src/components/GlobalHeader/index.less
+++ b/src/components/GlobalHeader/index.less
@@ -93,8 +93,8 @@ i.trigger {
.account {
.avatar {
margin: 20px 8px 20px 0;
- color: @primary-color;
- background: rgba(255, 255, 255, .85);
+ color: rgba(255, 255, 255, .85);
+ background: @primary-color;;
vertical-align: middle;
}
}
diff --git a/src/components/Login/LoginItem.js b/src/components/Login/LoginItem.js
new file mode 100644
index 0000000..26a4b22
--- /dev/null
+++ b/src/components/Login/LoginItem.js
@@ -0,0 +1,121 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { Form, Button, Row, Col } from 'antd';
+import omit from 'omit.js';
+import styles from './index.less';
+import map from './map';
+
+const FormItem = Form.Item;
+
+function generator({ defaultProps, defaultRules, type }) {
+ return (WrappedComponent) => {
+ return class BasicComponent extends Component {
+ static contextTypes = {
+ form: PropTypes.object,
+ updateActive: PropTypes.func,
+ };
+ constructor(props) {
+ super(props);
+ this.state = {
+ count: 0,
+ };
+ }
+ componentDidMount() {
+ if (this.context.updateActive) {
+ this.context.updateActive(this.props.name);
+ }
+ }
+ componentWillUnmount() {
+ clearInterval(this.interval);
+ }
+ onGetCaptcha = () => {
+ let count = 59;
+ this.setState({ count });
+ if (this.props.onGetCaptcha) {
+ this.props.onGetCaptcha();
+ }
+ this.interval = setInterval(() => {
+ count -= 1;
+ this.setState({ count });
+ if (count === 0) {
+ clearInterval(this.interval);
+ }
+ }, 1000);
+ };
+ render() {
+ const { getFieldDecorator } = this.context.form;
+ const options = {};
+ let otherProps = {};
+ const { onChange, defaultValue, rules, name, ...restProps } = this.props;
+ const { count } = this.state;
+ options.rules = rules || defaultRules;
+ if (onChange) {
+ options.onChange = onChange;
+ }
+ if (defaultValue) {
+ options.initialValue = defaultValue;
+ }
+ otherProps = restProps || otherProps;
+ if (type === 'Captcha') {
+ const inputProps = omit(otherProps, ['onGetCaptcha']);
+ return (
+ <FormItem>
+ <Row gutter={8}>
+ <Col span={16}>
+ {getFieldDecorator(name, options)(
+ <WrappedComponent {...defaultProps} {...inputProps} />
+ )}
+ </Col>
+ <Col span={8}>
+ <Button
+ disabled={count}
+ className={styles.getCaptcha}
+ size="large"
+ onClick={this.onGetCaptcha}
+ >
+ {count ? `${count} s` : '获取验证码'}
+ </Button>
+ </Col>
+ </Row>
+ </FormItem>
+ );
+ }
+ return (
+ <FormItem>
+ {getFieldDecorator(name, options)(
+ <WrappedComponent {...defaultProps} {...otherProps} />
+ )}
+ </FormItem>
+ );
+ }
+ };
+ };
+}
+
+const LoginItem = {};
+Object.keys(map).forEach((item) => {
+ LoginItem[item] = generator({
+ defaultProps: map[item].props,
+ defaultRules: map[item].rules,
+ type: item,
+ })(map[item].component);
+});
+
+export default LoginItem;
diff --git a/src/utils/authority.js b/src/components/Login/LoginSubmit.js
similarity index 64%
copy from src/utils/authority.js
copy to src/components/Login/LoginSubmit.js
index 25fd2a7..d6c4f29 100644
--- a/src/utils/authority.js
+++ b/src/components/Login/LoginSubmit.js
@@ -15,12 +15,20 @@
* limitations under the License.
*/
+import React from 'react';
+import classNames from 'classnames';
+import { Button, Form } from 'antd';
+import styles from './index.less';
-// use localStorage to store the authority info, which might be sent from server in actual project.
-export function getAuthority() {
- return localStorage.getItem('antd-pro-authority') || 'admin';
-}
+const FormItem = Form.Item;
-export function setAuthority(authority) {
- return localStorage.setItem('antd-pro-authority', authority);
-}
+const LoginSubmit = ({ className, ...rest }) => {
+ const clsString = classNames(styles.submit, className);
+ return (
+ <FormItem>
+ <Button size="large" className={clsString} type="primary" htmlType="submit" {...rest} />
+ </FormItem>
+ );
+};
+
+export default LoginSubmit;
diff --git a/src/utils/authority.js b/src/components/Login/LoginTab.js
similarity index 54%
copy from src/utils/authority.js
copy to src/components/Login/LoginTab.js
index 25fd2a7..6ad49a4 100644
--- a/src/utils/authority.js
+++ b/src/components/Login/LoginTab.js
@@ -15,12 +15,35 @@
* limitations under the License.
*/
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { Tabs } from 'antd';
-// use localStorage to store the authority info, which might be sent from server in actual project.
-export function getAuthority() {
- return localStorage.getItem('antd-pro-authority') || 'admin';
-}
+const { TabPane } = Tabs;
+
+const generateId = (() => {
+ let i = 0;
+ return (prefix = '') => {
+ i += 1;
+ return `${prefix}${i}`;
+ };
+})();
-export function setAuthority(authority) {
- return localStorage.setItem('antd-pro-authority', authority);
+export default class LoginTab extends Component {
+ static __ANT_PRO_LOGIN_TAB = true;
+ static contextTypes = {
+ tabUtil: PropTypes.object,
+ };
+ constructor(props) {
+ super(props);
+ this.uniqueId = generateId('login-tab-');
+ }
+ componentWillMount() {
+ if (this.context.tabUtil) {
+ this.context.tabUtil.addTab(this.uniqueId);
+ }
+ }
+ render() {
+ return <TabPane {...this.props} />;
+ }
}
diff --git a/src/components/Login/index.js b/src/components/Login/index.js
new file mode 100644
index 0000000..9dadb28
--- /dev/null
+++ b/src/components/Login/index.js
@@ -0,0 +1,141 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { Form, Tabs } from 'antd';
+import classNames from 'classnames';
+import LoginItem from './LoginItem';
+import LoginTab from './LoginTab';
+import LoginSubmit from './LoginSubmit';
+import styles from './index.less';
+
+class Login extends Component {
+ static propTypes = {
+ className: PropTypes.string,
+ defaultActiveKey: PropTypes.string,
+ onTabChange: PropTypes.func,
+ onSubmit: PropTypes.func,
+ };
+
+ static childContextTypes = {
+ tabUtil: PropTypes.object,
+ form: PropTypes.object,
+ updateActive: PropTypes.func,
+ };
+
+ static defaultProps = {
+ className: '',
+ defaultActiveKey: '',
+ onTabChange: () => {},
+ onSubmit: () => {},
+ };
+
+ state = {
+ type: this.props.defaultActiveKey,
+ tabs: [],
+ active: {},
+ };
+ getChildContext() {
+ return {
+ tabUtil: {
+ addTab: (id) => {
+ this.setState({
+ tabs: [...this.state.tabs, id],
+ });
+ },
+ removeTab: (id) => {
+ this.setState({
+ tabs: this.state.tabs.filter(currentId => currentId !== id),
+ });
+ },
+ },
+ form: this.props.form,
+ updateActive: (activeItem) => {
+ const { type, active } = this.state;
+ if (active[type]) {
+ active[type].push(activeItem);
+ } else {
+ active[type] = [activeItem];
+ }
+ this.setState({
+ active,
+ });
+ },
+ };
+ }
+ onSwitch = (type) => {
+ this.setState({
+ type,
+ });
+ this.props.onTabChange(type);
+ };
+ handleSubmit = (e) => {
+ e.preventDefault();
+ const { active, type } = this.state;
+ const activeFileds = active[type];
+ this.props.form.validateFields(activeFileds, { force: true }, (err, values) => {
+ this.props.onSubmit(err, values);
+ });
+ };
+ render() {
+ const { className, children } = this.props;
+ const { type, tabs } = this.state;
+ const TabChildren = [];
+ const otherChildren = [];
+ React.Children.forEach(children, (item) => {
+ if (!item) {
+ return;
+ }
+ // eslint-disable-next-line
+ if (item.type.__ANT_PRO_LOGIN_TAB) {
+ TabChildren.push(item);
+ } else {
+ otherChildren.push(item);
+ }
+ });
+ return (
+ <div className={classNames(className, styles.login)}>
+ <Form onSubmit={this.handleSubmit}>
+ {tabs.length ? (
+ <div>
+ <Tabs
+ animated={false}
+ className={styles.tabs}
+ activeKey={type}
+ onChange={this.onSwitch}
+ >
+ {TabChildren}
+ </Tabs>
+ {otherChildren}
+ </div>
+ ) : (
+ [...children]
+ )}
+ </Form>
+ </div>
+ );
+ }
+}
+
+Login.Tab = LoginTab;
+Login.Submit = LoginSubmit;
+Object.keys(LoginItem).forEach((item) => {
+ Login[item] = LoginItem[item];
+});
+
+export default Form.create()(Login);
diff --git a/src/utils/authority.js b/src/components/Login/index.less
similarity index 53%
copy from src/utils/authority.js
copy to src/components/Login/index.less
index 25fd2a7..6eb5463 100644
--- a/src/utils/authority.js
+++ b/src/components/Login/index.less
@@ -14,13 +14,48 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+@import '~antd/lib/style/themes/default.less';
+.login {
+ .tabs {
+ padding: 0 2px;
+ margin: 0 -2px;
+ :global {
+ .ant-tabs-tab {
+ font-size: 16px;
+ line-height: 24px;
+ }
+ .ant-input-affix-wrapper .ant-input:not(:first-child) {
+ padding-left: 34px;
+ }
+ }
+ }
-// use localStorage to store the authority info, which might be sent from server in actual project.
-export function getAuthority() {
- return localStorage.getItem('antd-pro-authority') || 'admin';
-}
+ :global {
+ .ant-tabs .ant-tabs-bar {
+ border-bottom: 0;
+ margin-bottom: 24px;
+ text-align: center;
+ }
+
+ .ant-form-item {
+ margin-bottom: 24px;
+ }
+ }
+
+ .prefixIcon {
+ font-size: @font-size-base;
+ color: @disabled-color;
+ }
+
+ .getCaptcha {
+ display: block;
+ width: 100%;
+ }
-export function setAuthority(authority) {
- return localStorage.setItem('antd-pro-authority', authority);
+ .submit {
+ width: 100%;
+ margin-top: 24px;
+ }
}
diff --git a/src/components/Login/map.js b/src/components/Login/map.js
new file mode 100644
index 0000000..3c50f5e
--- /dev/null
+++ b/src/components/Login/map.js
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 { Input, Icon } from 'antd';
+import styles from './index.less';
+
+const map = {
+ UserName: {
+ component: Input,
+ props: {
+ size: 'large',
+ prefix: <Icon type="user" className={styles.prefixIcon} />,
+ placeholder: 'admin',
+ },
+ rules: [
+ {
+ required: true,
+ message: 'Please enter username!',
+ },
+ ],
+ },
+ Password: {
+ component: Input,
+ props: {
+ size: 'large',
+ prefix: <Icon type="lock" className={styles.prefixIcon} />,
+ type: 'password',
+ placeholder: '888888',
+ },
+ rules: [
+ {
+ required: true,
+ message: 'Please enter password!',
+ },
+ ],
+ },
+ Mobile: {
+ component: Input,
+ props: {
+ size: 'large',
+ prefix: <Icon type="mobile" className={styles.prefixIcon} />,
+ placeholder: 'mobile number',
+ },
+ rules: [
+ {
+ required: true,
+ message: 'Please enter mobile number!',
+ },
+ {
+ pattern: /^1\d{10}$/,
+ message: 'Wrong mobile number format!',
+ },
+ ],
+ },
+ Captcha: {
+ component: Input,
+ props: {
+ size: 'large',
+ prefix: <Icon type="mail" className={styles.prefixIcon} />,
+ placeholder: 'captcha',
+ },
+ rules: [
+ {
+ required: true,
+ message: 'Please enter Captcha!',
+ },
+ ],
+ },
+};
+
+export default map;
diff --git a/src/layouts/BasicLayout.js b/src/layouts/BasicLayout.js
index f68b215..2bf8bc1 100644
--- a/src/layouts/BasicLayout.js
+++ b/src/layouts/BasicLayout.js
@@ -263,7 +263,7 @@ class BasicLayout extends React.PureComponent {
}]}
copyright={
<div>
- Copyright <Icon type="copyright" /> 2018 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
+ Copyright <Icon type="copyright" /> 2017 - 2018 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
</div>
}
/>
diff --git a/src/layouts/UserLayout.js b/src/layouts/UserLayout.js
index 3e68b30..986ae63 100644
--- a/src/layouts/UserLayout.js
+++ b/src/layouts/UserLayout.js
@@ -25,29 +25,15 @@ import styles from './UserLayout.less';
import logo from '../assets/sw-2.png';
import { getRoutes } from '../utils/utils';
-const links = [{
- key: 'help',
- title: 'Help',
- href: '',
-}, {
- key: 'privacy',
- title: 'Privacy',
- href: '',
-}, {
- key: 'terms',
- title: 'Terms',
- href: '',
-}];
-
-const copyright = <div>Copyright <Icon type="copyright" /> 2018 Apache SkyWalking</div>;
+const copyright = <div>Copyright <Icon type="copyright" /> 2017 - 2018 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.</div>;
class UserLayout extends React.PureComponent {
getPageTitle() {
const { routerData, location } = this.props;
const { pathname } = location;
- let title = 'Ant Design Pro';
+ let title = 'SkyWalking';
if (routerData[pathname] && routerData[pathname].name) {
- title = `${routerData[pathname].name} - Ant Design Pro`;
+ title = `${routerData[pathname].name} - SkyWalking`;
}
return title;
}
@@ -64,7 +50,7 @@ class UserLayout extends React.PureComponent {
<span className={styles.title}>Apache SkyWalking</span>
</Link>
</div>
- <div className={styles.desc}>Apache SkyWalking Opensource APM System</div>
+ <div className={styles.desc}>Apache SkyWalking APM System</div>
</div>
<Switch>
{getRoutes(match.path, routerData).map(item =>
@@ -80,7 +66,7 @@ class UserLayout extends React.PureComponent {
<Redirect exact from="/user" to="/user/login" />
</Switch>
</div>
- <GlobalFooter links={links} copyright={copyright} />
+ <GlobalFooter copyright={copyright} />
</div>
</DocumentTitle>
);
diff --git a/src/models/login.js b/src/models/login.js
index 619f272..219b853 100644
--- a/src/models/login.js
+++ b/src/models/login.js
@@ -69,7 +69,6 @@ export default {
return {
...state,
status: payload.status,
- type: payload.type,
};
},
},
diff --git a/src/routes/User/Login.js b/src/routes/User/Login.js
index 9ab354c..bd37e2a 100644
--- a/src/routes/User/Login.js
+++ b/src/routes/User/Login.js
@@ -18,46 +18,28 @@
import React, { Component } from 'react';
import { connect } from 'dva';
-import { Link } from 'dva/router';
-import { Checkbox, Alert, Icon } from 'antd';
+import { Alert } from 'antd';
import Login from '../../components/Login';
import styles from './Login.less';
-const { Tab, UserName, Password, Mobile, Captcha, Submit } = Login;
+const { UserName, Password, Submit } = Login;
@connect(({ login, loading }) => ({
login,
submitting: loading.effects['login/login'],
}))
export default class LoginPage extends Component {
- state = {
- type: 'account',
- autoLogin: true,
- }
-
- onTabChange = (type) => {
- this.setState({ type });
- }
-
handleSubmit = (err, values) => {
- const { type } = this.state;
if (!err) {
this.props.dispatch({
type: 'login/login',
payload: {
...values,
- type,
},
});
}
}
- changeAutoLogin = (e) => {
- this.setState({
- autoLogin: e.target.checked,
- });
- }
-
renderMessage = (content) => {
return (
<Alert style={{ marginBottom: 24 }} message={content} type="error" showIcon />
@@ -66,46 +48,19 @@ export default class LoginPage extends Component {
render() {
const { login, submitting } = this.props;
- const { type } = this.state;
return (
<div className={styles.main}>
<Login
- defaultActiveKey={type}
- onTabChange={this.onTabChange}
onSubmit={this.handleSubmit}
>
- <Tab key="account" tab="账户密码登录">
- {
- login.status === 'error' &&
- login.type === 'account' &&
- !login.submitting &&
- this.renderMessage('账户或密码错误(admin/888888)')
- }
- <UserName name="userName" placeholder="admin/user" />
- <Password name="password" placeholder="888888/123456" />
- </Tab>
- <Tab key="mobile" tab="手机号登录">
- {
- login.status === 'error' &&
- login.type === 'mobile' &&
- !login.submitting &&
- this.renderMessage('验证码错误')
- }
- <Mobile name="mobile" />
- <Captcha name="captcha" />
- </Tab>
- <div>
- <Checkbox checked={this.state.autoLogin} onChange={this.changeAutoLogin}>自动登录</Checkbox>
- <a style={{ float: 'right' }} href="">忘记密码</a>
- </div>
- <Submit loading={submitting}>登录</Submit>
- <div className={styles.other}>
- 其他登录方式
- <Icon className={styles.icon} type="alipay-circle" />
- <Icon className={styles.icon} type="taobao-circle" />
- <Icon className={styles.icon} type="weibo-circle" />
- <Link className={styles.register} to="/user/register">注册账户</Link>
- </div>
+ {
+ login.status === 'error' &&
+ !login.submitting &&
+ this.renderMessage('Invalid user or password')
+ }
+ <UserName name="userName" placeholder="User Name" />
+ <Password name="password" placeholder="Password" />
+ <Submit loading={submitting}>Login</Submit>
</Login>
</div>
);
diff --git a/src/utils/authority.js b/src/utils/authority.js
index 25fd2a7..48bd433 100644
--- a/src/utils/authority.js
+++ b/src/utils/authority.js
@@ -18,9 +18,9 @@
// use localStorage to store the authority info, which might be sent from server in actual project.
export function getAuthority() {
- return localStorage.getItem('antd-pro-authority') || 'admin';
+ return localStorage.getItem('skywalking-authority');
}
export function setAuthority(authority) {
- return localStorage.setItem('antd-pro-authority', authority);
+ return localStorage.setItem('skywalking-authority', authority);
}
--
To stop receiving notification emails like this one, please contact
hanahmily@apache.org.