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/01/07 15:47:26 UTC

[incubator-skywalking-ui] branch feature/5.0.0 updated: Time-Select component finish

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

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


The following commit(s) were added to refs/heads/feature/5.0.0 by this push:
     new 546e414  Time-Select component finish
546e414 is described below

commit 546e414ccdf88a3c6007076885bd471e1612db18
Author: gaohongtao <ha...@gmail.com>
AuthorDate: Sun Jan 7 23:45:53 2018 +0800

    Time-Select component finish
---
 .../src/components/Time/TimeSelect/index.js        | 238 +++++++++++++++++++++
 .../src/components/Time/TimeSelect/index.less      |   3 +
 src/main/frontend/src/layouts/BasicLayout.js       |  66 ++++--
 src/main/frontend/src/layouts/BasicLayout.less     |   4 +
 src/main/frontend/src/models/global.js             |  22 ++
 .../frontend/src/routes/Dashboard/Dashboard.js     |  18 +-
 .../skywalking/apm/ui/ApplicationStartUp.java      |  15 +-
 .../Dashboard.java}                                |  22 +-
 8 files changed, 338 insertions(+), 50 deletions(-)

diff --git a/src/main/frontend/src/components/Time/TimeSelect/index.js b/src/main/frontend/src/components/Time/TimeSelect/index.js
new file mode 100644
index 0000000..041a4a5
--- /dev/null
+++ b/src/main/frontend/src/components/Time/TimeSelect/index.js
@@ -0,0 +1,238 @@
+import React, { PureComponent } from 'react';
+import { Button, Row, Col, Divider, Form, DatePicker, Select } from 'antd';
+import moment from 'moment';
+import styles from './index.less';
+
+const { Option } = Select;
+const FormItem = Form.Item;
+const { RangePicker } = DatePicker;
+
+@Form.create({
+  mapPropsToFields(props) {
+    if (!props.duration) return null;
+    const result = {
+      step: Form.createFormField({
+        value: props.duration.step,
+      }),
+    };
+    if (props.duration.label) {
+      return result;
+    }
+    result['range-time-picker'] = Form.createFormField({
+      value: [props.duration.from(), props.duration.to()],
+    });
+    return result;
+  },
+})
+class TimeSelect extends PureComponent {
+  constructor(props) {
+    super(props);
+
+    const now = {
+      to() {
+        return moment();
+      },
+    };
+    this.shortcuts = [
+      { ...now,
+        from() {
+          return moment().subtract('minutes', 5);
+        },
+        label: 'Last 5 minutes',
+      },
+      { ...now,
+        from() {
+          return moment().subtract('minutes', 15);
+        },
+        label: 'Last 15 minutes',
+      },
+      { ...now,
+        from() {
+          return moment().subtract('minutes', 30);
+        },
+        label: 'Last 30 minutes',
+      },
+      { ...now,
+        from() {
+          return moment().subtract('hours', 1);
+        },
+        label: 'Last 1 hour',
+      },
+      { ...now,
+        from() {
+          return moment().subtract('hours', 3);
+        },
+        label: 'Last 3 hours',
+      },
+      { ...now,
+        from() {
+          return moment().subtract('hours', 6);
+        },
+        label: 'Last 6 hours',
+      },
+      { ...now,
+        from() {
+          return moment().subtract('hours', 12);
+        },
+        label: 'Last 12 hours',
+      },
+      { ...now,
+        from() {
+          return moment().subtract('hours', 24);
+        },
+        label: 'Last 24 hours',
+      },
+    ];
+    this.shortcutsDays = [
+      { ...now,
+        from() {
+          return moment().subtract('days', 2);
+        },
+        label: 'Last 2 days',
+      },
+      { ...now,
+        from() {
+          return moment().subtract('days', 7);
+        },
+        label: 'Last 7 days',
+      },
+      { ...now,
+        from() {
+          return moment().subtract('days', 14);
+        },
+        label: 'Last 14 days',
+      },
+    ];
+  }
+  componentDidMount() {
+    const { onSelected } = this.props;
+    onSelected(this.shortcuts[0]);
+  }
+  disabledDate = (current) => {
+    return current && current.valueOf() >= Date.now();
+  }
+  handleSubmit = (e) => {
+    e.preventDefault();
+
+    const { form } = this.props;
+
+    form.validateFields((err, fieldsValue) => {
+      if (err) return;
+      const duration = {};
+      for (const key of Object.keys(fieldsValue)) {
+        if (fieldsValue[key]) {
+          if (key === 'range-time-picker') {
+            duration.from = () => fieldsValue[key][0];
+            duration.to = () => fieldsValue[key][1];
+          } else {
+            duration[key] = fieldsValue[key];
+          }
+        }
+      }
+      if (duration.from && duration.to) {
+        this.select({ ...duration, label: null });
+      } else {
+        this.select(duration);
+      }
+    });
+  }
+  select = (newDuration) => {
+    const { onSelected, duration } = this.props;
+    onSelected({ ...duration, ...newDuration });
+  }
+  render() {
+    const { isShow, form } = this.props;
+    if (!isShow) {
+      return null;
+    }
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 7 },
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 12 },
+        md: { span: 10 },
+      },
+    };
+    const { getFieldDecorator } = form;
+    const content = (
+      <Row type="flex" justify="end">
+        <Col xs={24} sm={24} md={24} lg={15} xl={14}>
+          <Form
+            onSubmit={this.handleSubmit}
+            hideRequiredMark
+          >
+            <FormItem
+              {...formItemLayout}
+              label="Time Range"
+            >
+              {getFieldDecorator('range-time-picker')(
+                <RangePicker showTime disabledDate={this.disabledDate} format="YYYY-MM-DD HH:mm:ss" />
+              )}
+            </FormItem>
+            <FormItem
+              {...formItemLayout}
+              label="Reloading every "
+            >
+              {getFieldDecorator('step')(
+                <Select style={{ width: 170 }}>
+                  <Option value="0">off</Option>
+                  <Option value="5000">5s</Option>
+                  <Option value="10000">10s</Option>
+                  <Option value="30000">30s</Option>
+                </Select>
+              )}
+            </FormItem>
+            <FormItem>
+              <Button
+                type="primary"
+                htmlType="submit"
+              >
+                Apply
+              </Button>
+            </FormItem>
+          </Form>
+        </Col>
+        <Col xs={0} sm={0} md={0} lg={0} xl={1}><Divider type="vertical" style={{ height: 200 }} /></Col>
+        <Col xs={24} sm={24} md={4} lg={4} xl={4}>
+          <ul className={styles.list}>
+            {this.shortcutsDays.map(d => (
+              <li key={d.label}>
+                <a onClick={this.select.bind(this, d)}>
+                  {d.label}
+                </a>
+              </li>))
+            }
+          </ul>
+        </Col>
+        <Col xs={24} sm={24} md={4} lg={4} xl={4}>
+          <ul className={styles.list}>
+            {this.shortcuts.map(d => (
+              <li key={d.label}>
+                <a onClick={this.select.bind(this, d)}>
+                  {d.label}
+                </a>
+              </li>))
+            }
+          </ul>
+        </Col>
+      </Row>
+    );
+    return (
+      <div className="antd-pro-page-header-pageHeader">
+        <div className="antd-pro-page-header-detail">
+          <div className="antd-pro-page-header-main">
+            <div className="antd-pro-page-header-row">
+              <div className="antd-pro-page-header-content">
+                {content}
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    );
+  }
+}
+export default TimeSelect;
diff --git a/src/main/frontend/src/components/Time/TimeSelect/index.less b/src/main/frontend/src/components/Time/TimeSelect/index.less
new file mode 100644
index 0000000..cfda2a2
--- /dev/null
+++ b/src/main/frontend/src/components/Time/TimeSelect/index.less
@@ -0,0 +1,3 @@
+.list {
+  list-style: none;
+}
diff --git a/src/main/frontend/src/layouts/BasicLayout.js b/src/main/frontend/src/layouts/BasicLayout.js
index f3d0627..3050087 100644
--- a/src/main/frontend/src/layouts/BasicLayout.js
+++ b/src/main/frontend/src/layouts/BasicLayout.js
@@ -4,7 +4,7 @@ import DocumentTitle from 'react-document-title';
 
 import { connect } from 'dva';
 import { Link, Route, Redirect, Switch } from 'dva/router';
-import { Layout, Menu, Icon, Dropdown, Tag } from 'antd';
+import { Layout, Menu, Icon, Tag } from 'antd';
 
 import NoticeIcon from 'ant-design-pro/lib/NoticeIcon';
 import GlobalFooter from 'ant-design-pro/lib/GlobalFooter';
@@ -16,9 +16,12 @@ import { ContainerQuery } from 'react-container-query';
 
 import styles from './BasicLayout.less';
 
+import TimeSelect from '../components/Time/TimeSelect';
+
 const { Header, Sider, Content } = Layout;
 const { SubMenu } = Menu;
 
+
 const query = {
   'screen-xs': {
     maxWidth: 575,
@@ -221,19 +224,46 @@ class BasicLayout extends React.PureComponent {
       window.dispatchEvent(event);
     }, 600);
   }
+  handleTimeSelected = (duration) => {
+    this.props.dispatch({
+      type: 'global/changeSelectedTime',
+      payload: duration,
+    });
+    if (this.intervalId) {
+      clearInterval(this.intervalId);
+    }
+    const { step = 0 } = duration;
+    if (step < 1) {
+      return;
+    }
+    this.intervalId = setInterval(this.reload, duration.step);
+  }
+  reload = () => {
+    this.props.dispatch({
+      type: 'global/reload',
+    });
+  }
+  toggleSelectTime = () => {
+    this.props.dispatch({
+      type: 'global/toggleSelectTime',
+    });
+  }
   render() {
     const { collapsed, getRouteData } = this.props;
-
-    const menu = (
-      <Menu selectedKeys={['1']} onClick={this.onMenuClick}>
-        <Menu.Item key="1">Last 15 minutes</Menu.Item>
-        <Menu.Item key="2">Last 1 hour</Menu.Item>
-      </Menu>
-    );
     // Don't show popup menu when it is been collapsed
     const menuProps = collapsed ? {} : {
       openKeys: this.state.openKeys,
     };
+    const { duration = {
+      from() {
+        return moment();
+      },
+      to() {
+        return moment();
+      },
+      lable: 'Nan',
+    } } = this.props;
+    const timeFormat = 'YYYY-MM-DD HH:mm:ss';
 
     const layout = (
       <Layout>
@@ -270,11 +300,14 @@ class BasicLayout extends React.PureComponent {
               onClick={this.toggle}
             />
             <div className={styles.right}>
-              <Dropdown overlay={menu}>
-                <span className={`${styles.action}`}>
-                  Last 15 minutes
-                </span>
-              </Dropdown>
+              <span
+                className={styles.action}
+                onClick={this.toggleSelectTime}
+              >
+                {duration.label ? duration.label : `${duration.from().format(timeFormat)} ~ ${duration.to().format(timeFormat)}`}
+                {duration.step > 0 ? ` Reloading every ${duration.step / 1000} seconds` : null }
+              </span>
+              <span className={styles.action} onClick={this.reload}> <Icon type="reload" /> </span>
               <NoticeIcon
                 className={styles.action}
                 count={3}
@@ -341,6 +374,11 @@ class BasicLayout extends React.PureComponent {
               </NoticeIcon>
             </div>
           </Header>
+          <TimeSelect
+            duration={this.props.duration}
+            onSelected={this.handleTimeSelected}
+            isShow={this.props.isShowSelectTime}
+          />
           <Content style={{ margin: '24px 24px 0', height: '100%' }}>
             <Switch>
               {
@@ -393,4 +431,6 @@ export default connect(state => ({
   collapsed: state.global.collapsed,
   fetchingNotices: state.global.fetchingNotices,
   notices: state.global.notices,
+  duration: state.global.duration,
+  isShowSelectTime: state.global.isShowSelectTime,
 }))(BasicLayout);
diff --git a/src/main/frontend/src/layouts/BasicLayout.less b/src/main/frontend/src/layouts/BasicLayout.less
index 6ab937a..2d40068 100644
--- a/src/main/frontend/src/layouts/BasicLayout.less
+++ b/src/main/frontend/src/layouts/BasicLayout.less
@@ -111,3 +111,7 @@
   position: relative;
   z-index: 10;
 }
+
+.selecttime-hide {
+  display: none;
+}
diff --git a/src/main/frontend/src/models/global.js b/src/main/frontend/src/models/global.js
index 91127ed..bb2640f 100644
--- a/src/main/frontend/src/models/global.js
+++ b/src/main/frontend/src/models/global.js
@@ -61,6 +61,28 @@ export default {
         fetchingNotices: payload,
       };
     },
+    changeSelectedTime(state, { payload }) {
+      const { from, to } = payload;
+      return {
+        ...state,
+        duration: { ...payload, fromValue: from(), toValue: to() },
+        isShowSelectTime: false,
+      };
+    },
+    toggleSelectTime(state) {
+      return {
+        ...state,
+        isShowSelectTime: !state.isShowSelectTime,
+      };
+    },
+    reload(state) {
+      const { duration } = state;
+      const { from, to } = duration;
+      return {
+        ...state,
+        duration: { ...duration, fromValue: from(), toValue: to() },
+      };
+    },
   },
 
   subscriptions: {
diff --git a/src/main/frontend/src/routes/Dashboard/Dashboard.js b/src/main/frontend/src/routes/Dashboard/Dashboard.js
index dc4da92..896c9b6 100644
--- a/src/main/frontend/src/routes/Dashboard/Dashboard.js
+++ b/src/main/frontend/src/routes/Dashboard/Dashboard.js
@@ -55,22 +55,22 @@ export default class Dashboard extends PureComponent {
       time: '2017/12/11 19:22:32',
       duration: '5000ms',
     }, {
-      key: '1',
+      key: '2',
       name: 'ServiceA',
       time: '2017/12/11 19:22:32',
       duration: '5000ms',
     }, {
-      key: '1',
+      key: '3',
       name: 'ServiceA',
       time: '2017/12/11 19:22:32',
       duration: '5000ms',
     }, {
-      key: '1',
+      key: '4',
       name: 'ServiceA',
       time: '2017/12/11 19:22:32',
       duration: '5000ms',
     }, {
-      key: '1',
+      key: '5',
       name: 'ServiceA',
       time: '2017/12/11 19:22:32',
       duration: '5000ms',
@@ -91,19 +91,19 @@ export default class Dashboard extends PureComponent {
       name: 'App1',
       tps: '500',
     }, {
-      key: '1',
+      key: '2',
       name: 'App1',
       tps: '500',
     }, {
-      key: '1',
+      key: '3',
       name: 'App1',
       tps: '500',
     }, {
-      key: '1',
+      key: '4',
       name: 'App1',
       tps: '500',
     }, {
-      key: '1',
+      key: '5',
       name: 'App1',
       tps: '500',
     }];
@@ -164,7 +164,7 @@ export default class Dashboard extends PureComponent {
           bordered={false}
           bodyStyle={{ padding: 0 }}
         >
-          <div Style="height: 480px">Topoloy</div>
+          <div style={{ height: 480 }}>Topoloy</div>
         </Card>
         <Row gutter={24}>
           <Col xs={24} sm={24} md={24} lg={24} xl={24} style={{ marginTop: 24 }}>
diff --git a/src/main/java/org/apache/skywalking/apm/ui/ApplicationStartUp.java b/src/main/java/org/apache/skywalking/apm/ui/ApplicationStartUp.java
index cd00839..e608701 100644
--- a/src/main/java/org/apache/skywalking/apm/ui/ApplicationStartUp.java
+++ b/src/main/java/org/apache/skywalking/apm/ui/ApplicationStartUp.java
@@ -33,20 +33,7 @@ public class ApplicationStartUp extends SpringBootServletInitializer {
 
     public static void main(String[] args) throws Exception {
         ApplicationContext applicationContext = SpringApplication.run(ApplicationStartUp.class, args);
-        CollectorUIServerGetterTimer.INSTANCE.start(applicationContext);
+//        CollectorUIServerGetterTimer.INSTANCE.start(applicationContext);
     }
     
-    @Bean
-    GraphQLSchema schema() {
-        return GraphQLSchema.newSchema()
-                .query(GraphQLObjectType.newObject()
-                        .name("query")
-                        .field(field -> field
-                                .name("test")
-                                .type(Scalars.GraphQLString)
-                                .dataFetcher(environment -> "response")
-                        )
-                        .build())
-                .build();
-    }
 }
diff --git a/src/main/java/org/apache/skywalking/apm/ui/ApplicationStartUp.java b/src/main/java/org/apache/skywalking/apm/ui/schema/Dashboard.java
similarity index 67%
copy from src/main/java/org/apache/skywalking/apm/ui/ApplicationStartUp.java
copy to src/main/java/org/apache/skywalking/apm/ui/schema/Dashboard.java
index cd00839..3b03cab 100644
--- a/src/main/java/org/apache/skywalking/apm/ui/ApplicationStartUp.java
+++ b/src/main/java/org/apache/skywalking/apm/ui/schema/Dashboard.java
@@ -16,26 +16,20 @@
  *
  */
 
-package org.apache.skywalking.apm.ui;
+package org.apache.skywalking.apm.ui.schema;
 
 import graphql.Scalars;
 import graphql.schema.GraphQLObjectType;
 import graphql.schema.GraphQLSchema;
-import org.apache.skywalking.apm.ui.tools.CollectorUIServerGetterTimer;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
-import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Bean;
 
-@SpringBootApplication
-public class ApplicationStartUp extends SpringBootServletInitializer {
-
-    public static void main(String[] args) throws Exception {
-        ApplicationContext applicationContext = SpringApplication.run(ApplicationStartUp.class, args);
-        CollectorUIServerGetterTimer.INSTANCE.start(applicationContext);
-    }
-    
+/**
+ * The schema of dashboard
+ * 
+ * @author gaohongtao
+ */
+@GraphQLSchema
+public class Dashboard {
     @Bean
     GraphQLSchema schema() {
         return GraphQLSchema.newSchema()

-- 
To stop receiving notification emails like this one, please contact
['"commits@skywalking.apache.org" <co...@skywalking.apache.org>'].