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>'].