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 <hanahm...@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" <commits@skywalking.apache.org>'].