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:06 UTC

[incubator-skywalking-ui] branch 5.0.0/beta2 created (now c19b7c8)

This is an automated email from the ASF dual-hosted git repository.

hanahmily pushed a change to branch 5.0.0/beta2
in repository https://gitbox.apache.org/repos/asf/incubator-skywalking-ui.git.


      at c19b7c8  Add login and logout

This branch includes the following new commits:

     new c19b7c8  Add login and logout

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


-- 
To stop receiving notification emails like this one, please contact
hanahmily@apache.org.

[incubator-skywalking-ui] 01/01: Add login and logout

Posted by ha...@apache.org.
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.