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.