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 2017/12/22 15:08:45 UTC

[incubator-skywalking-ui] 03/03: First version of demo is finished

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

commit 1080608e0dba0b2e1e4ce4e31e1e502580b2e4f2
Author: gaohongtao <ha...@gmail.com>
AuthorDate: Fri Dec 22 23:08:11 2017 +0800

    First version of demo is finished
---
 src/main/frontend/src/common/nav.js                |  12 ++
 .../frontend/src/components/Charts/Line/index.js   | 144 +++++++++++++++++
 src/main/frontend/src/components/Charts/index.js   |   2 +
 .../src/components/DescriptionList/Description.js  |  17 ++
 .../components/DescriptionList/DescriptionList.js  |  21 +++
 .../src/components/DescriptionList/demo/basic.md   |  35 +++++
 .../components/DescriptionList/demo/vertical.md    |  35 +++++
 .../src/components/DescriptionList/index.d.ts      |  22 +++
 .../src/components/DescriptionList/index.js        |   5 +
 .../src/components/DescriptionList/index.less      |  75 +++++++++
 .../src/components/DescriptionList/index.md        |  39 +++++
 .../src/components/DescriptionList/responsive.js   |   6 +
 src/main/frontend/src/models/alert.js              |  17 ++
 src/main/frontend/src/models/server.js             |  16 ++
 src/main/frontend/src/routes/Alert/Alert.js        |  84 ++++++++++
 src/main/frontend/src/routes/Alert/Alert.less      |  50 ++++++
 src/main/frontend/src/routes/Server/Server.js      | 172 +++++++++++++++++++++
 17 files changed, 752 insertions(+)

diff --git a/src/main/frontend/src/common/nav.js b/src/main/frontend/src/common/nav.js
index 7677c3d..cb40d40 100644
--- a/src/main/frontend/src/common/nav.js
+++ b/src/main/frontend/src/common/nav.js
@@ -28,11 +28,23 @@ export const getNavData = app => [
         component: dynamicWrapper(app, ['application'], () => import('../routes/Application/Application')),
       },
       {
+        name: 'Server',
+        icon: 'server',
+        path: 'server',
+        component: dynamicWrapper(app, ['server'], () => import('../routes/Server/Server')),
+      },
+      {
         name: 'Service',
         icon: 'service',
         path: 'service',
         component: dynamicWrapper(app, ['service'], () => import('../routes/Service/Service')),
       },
+      {
+        name: 'Alert',
+        icon: 'alert',
+        path: 'alert',
+        component: dynamicWrapper(app, ['alert'], () => import('../routes/Alert/Alert')),
+      },
     ],
   },
 ];
diff --git a/src/main/frontend/src/components/Charts/Line/index.js b/src/main/frontend/src/components/Charts/Line/index.js
new file mode 100644
index 0000000..1a9c9f0
--- /dev/null
+++ b/src/main/frontend/src/components/Charts/Line/index.js
@@ -0,0 +1,144 @@
+import React, { PureComponent } from 'react';
+import G2 from 'g2';
+import Debounce from 'lodash-decorators/debounce';
+import Bind from 'lodash-decorators/bind';
+import equal from '../equal';
+import styles from '../index.less';
+
+class Line extends PureComponent {
+  state = {
+    autoHideXLabels: false,
+  }
+
+  componentDidMount() {
+    this.renderChart(this.props.data);
+
+    window.addEventListener('resize', this.resize);
+  }
+
+  componentWillReceiveProps(nextProps) {
+    if (!equal(this.props, nextProps)) {
+      this.renderChart(nextProps.data);
+    }
+  }
+
+  componentWillUnmount() {
+    window.removeEventListener('resize', this.resize);
+    if (this.chart) {
+      this.chart.destroy();
+    }
+    this.resize.cancel();
+  }
+
+  @Bind()
+  @Debounce(200)
+  resize() {
+    if (!this.node) {
+      return;
+    }
+    const canvasWidth = this.node.parentNode.clientWidth;
+    const { data = [], autoLabel = true } = this.props;
+    if (!autoLabel) {
+      return;
+    }
+    const minWidth = data.length * 30;
+    const { autoHideXLabels } = this.state;
+
+    if (canvasWidth <= minWidth) {
+      if (!autoHideXLabels) {
+        this.setState({
+          autoHideXLabels: true,
+        });
+        this.renderChart(data);
+      }
+    } else if (autoHideXLabels) {
+      this.setState({
+        autoHideXLabels: false,
+      });
+      this.renderChart(data);
+    }
+  }
+
+  handleRef = (n) => {
+    this.node = n;
+  }
+
+  renderChart(data) {
+    const { autoHideXLabels } = this.state;
+    const {
+      height = 0,
+      fit = true,
+      margin = [32, 0, (autoHideXLabels ? 8 : 32), 40],
+    } = this.props;
+
+
+    if (!data || (data && data.length < 1)) {
+      return;
+    }
+
+    // clean
+    this.node.innerHTML = '';
+
+    const { Frame } = G2;
+    const frame = new Frame(data);
+
+    const chart = new G2.Chart({
+      container: this.node,
+      forceFit: fit,
+      legend: null,
+      height: height - 22,
+      plotCfg: {
+        margin,
+      },
+    });
+    if (autoHideXLabels) {
+      chart.axis('x', {
+        title: false,
+        tickLine: false,
+        labels: false,
+      });
+    } else {
+      chart.axis('x', {
+        title: false,
+      });
+    }
+    chart.axis('y', {
+      title: false,
+      line: false,
+      tickLine: false,
+    });
+    chart.source(frame, {
+      x: {
+        type: 'cat',
+      },
+      y: {
+        min: 0,
+      },
+    });
+    chart.tooltip({
+      title: null,
+      crosshairs: {
+        type: 'line',
+      },
+    });
+    chart.line().position('x*y');
+    chart.render();
+
+    this.chart = chart;
+  }
+
+  render() {
+    const { height, title } = this.props;
+
+    return (
+      <div className={styles.chart} style={{ height }}>
+        <div>
+          { title && <h4>{title}</h4>}
+          <div ref={this.handleRef} />
+        </div>
+      </div>
+    );
+  }
+}
+
+export default Line;
diff --git a/src/main/frontend/src/components/Charts/index.js b/src/main/frontend/src/components/Charts/index.js
index cea9949..bed2e72 100644
--- a/src/main/frontend/src/components/Charts/index.js
+++ b/src/main/frontend/src/components/Charts/index.js
@@ -1,6 +1,7 @@
 import numeral from 'numeral';
 import ChartCard from './ChartCard';
 import Bar from './Bar';
+import Line from './Line';
 import Pie from './Pie';
 import Radar from './Radar';
 import Gauge from './Gauge';
@@ -17,6 +18,7 @@ const yuan = val => `&yen; ${numeral(val).format('0,0')}`;
 export default {
   yuan,
   Bar,
+  Line,
   Pie,
   Gauge,
   Radar,
diff --git a/src/main/frontend/src/components/DescriptionList/Description.js b/src/main/frontend/src/components/DescriptionList/Description.js
new file mode 100644
index 0000000..2aae62b
--- /dev/null
+++ b/src/main/frontend/src/components/DescriptionList/Description.js
@@ -0,0 +1,17 @@
+import React from 'react';
+import classNames from 'classnames';
+import { Col } from 'antd';
+import styles from './index.less';
+import responsive from './responsive';
+
+const Description = ({ term, column, className, children, ...restProps }) => {
+  const clsString = classNames(styles.description, className);
+  return (
+    <Col className={clsString} {...responsive[column]} {...restProps}>
+      {term && <div className={styles.term}>{term}</div>}
+      {children && <div className={styles.detail}>{children}</div>}
+    </Col>
+  );
+};
+
+export default Description;
diff --git a/src/main/frontend/src/components/DescriptionList/DescriptionList.js b/src/main/frontend/src/components/DescriptionList/DescriptionList.js
new file mode 100644
index 0000000..7eca3a7
--- /dev/null
+++ b/src/main/frontend/src/components/DescriptionList/DescriptionList.js
@@ -0,0 +1,21 @@
+import React from 'react';
+import classNames from 'classnames';
+import { Row } from 'antd';
+import styles from './index.less';
+
+export default ({ className, title, col = 3, layout = 'horizontal', gutter = 32,
+  children, size, ...restProps }) => {
+  const clsString = classNames(styles.descriptionList, styles[layout], className, {
+    [styles.descriptionListSmall]: size === 'small',
+    [styles.descriptionListLarge]: size === 'large',
+  });
+  const column = col > 4 ? 4 : col;
+  return (
+    <div className={clsString} {...restProps}>
+      {title ? <div className={styles.title}>{title}</div> : null}
+      <Row gutter={gutter}>
+        {React.Children.map(children, child => React.cloneElement(child, { column }))}
+      </Row>
+    </div>
+  );
+};
diff --git a/src/main/frontend/src/components/DescriptionList/demo/basic.md b/src/main/frontend/src/components/DescriptionList/demo/basic.md
new file mode 100644
index 0000000..8dd8534
--- /dev/null
+++ b/src/main/frontend/src/components/DescriptionList/demo/basic.md
@@ -0,0 +1,35 @@
+---
+order: 0
+title: Basic
+---
+
+基本描述列表。
+
+````jsx
+import DescriptionList from 'ant-design-pro/lib/DescriptionList';
+
+const { Description } = DescriptionList;
+
+ReactDOM.render(
+  <DescriptionList size="large" title="title">
+    <Description term="Firefox">
+      A free, open source, cross-platform,
+      graphical web browser developed by the
+      Mozilla Corporation and hundreds of
+      volunteers.
+    </Description>
+    <Description term="Firefox">
+      A free, open source, cross-platform,
+      graphical web browser developed by the
+      Mozilla Corporation and hundreds of
+      volunteers.
+    </Description>
+    <Description term="Firefox">
+      A free, open source, cross-platform,
+      graphical web browser developed by the
+      Mozilla Corporation and hundreds of
+      volunteers.
+    </Description>
+  </DescriptionList>
+, mountNode);
+````
diff --git a/src/main/frontend/src/components/DescriptionList/demo/vertical.md b/src/main/frontend/src/components/DescriptionList/demo/vertical.md
new file mode 100644
index 0000000..a304f94
--- /dev/null
+++ b/src/main/frontend/src/components/DescriptionList/demo/vertical.md
@@ -0,0 +1,35 @@
+---
+order: 1
+title: Vertical
+---
+
+垂直布局。
+
+````jsx
+import DescriptionList from 'ant-design-pro/lib/DescriptionList';
+
+const { Description } = DescriptionList;
+
+ReactDOM.render(
+  <DescriptionList size="large" title="title" layout="vertical">
+    <Description term="Firefox">
+      A free, open source, cross-platform,
+      graphical web browser developed by the
+      Mozilla Corporation and hundreds of
+      volunteers.
+    </Description>
+    <Description term="Firefox">
+      A free, open source, cross-platform,
+      graphical web browser developed by the
+      Mozilla Corporation and hundreds of
+      volunteers.
+    </Description>
+    <Description term="Firefox">
+      A free, open source, cross-platform,
+      graphical web browser developed by the
+      Mozilla Corporation and hundreds of
+      volunteers.
+    </Description>
+  </DescriptionList>
+, mountNode);
+````
diff --git a/src/main/frontend/src/components/DescriptionList/index.d.ts b/src/main/frontend/src/components/DescriptionList/index.d.ts
new file mode 100644
index 0000000..b13c630
--- /dev/null
+++ b/src/main/frontend/src/components/DescriptionList/index.d.ts
@@ -0,0 +1,22 @@
+import * as React from "react";
+export interface DescriptionListProps {
+  layout?: "horizontal" | "vertical";
+  col?: number;
+  title: React.ReactNode;
+  gutter?: number;
+  size?: "large" | "small";
+}
+
+declare class Description extends React.Component<
+  {
+    term: React.ReactNode;
+  },
+  any
+> {}
+
+export default class DescriptionList extends React.Component<
+  DescriptionListProps,
+  any
+> {
+  static Description: typeof Description;
+}
diff --git a/src/main/frontend/src/components/DescriptionList/index.js b/src/main/frontend/src/components/DescriptionList/index.js
new file mode 100644
index 0000000..357f479
--- /dev/null
+++ b/src/main/frontend/src/components/DescriptionList/index.js
@@ -0,0 +1,5 @@
+import DescriptionList from './DescriptionList';
+import Description from './Description';
+
+DescriptionList.Description = Description;
+export default DescriptionList;
diff --git a/src/main/frontend/src/components/DescriptionList/index.less b/src/main/frontend/src/components/DescriptionList/index.less
new file mode 100644
index 0000000..067144e
--- /dev/null
+++ b/src/main/frontend/src/components/DescriptionList/index.less
@@ -0,0 +1,75 @@
+@import "~antd/lib/style/themes/default.less";
+
+.descriptionList {
+  // offset the padding-bottom of last row
+  :global {
+    .ant-row {
+      margin-bottom: -16px;
+      overflow: hidden;
+    }
+  }
+
+  .title {
+    font-size: 14px;
+    color: @heading-color;
+    font-weight: 500;
+    margin-bottom: 16px;
+  }
+
+  .term {
+    line-height: 22px;
+    padding-bottom: 16px;
+    margin-right: 8px;
+    color: @heading-color;
+    white-space: nowrap;
+    display: table-cell;
+
+    &:after {
+      content: ":";
+      margin: 0 8px 0 2px;
+      position: relative;
+      top: -.5px;
+    }
+  }
+
+  .detail {
+    line-height: 22px;
+    width: 100%;
+    padding-bottom: 16px;
+    color: @text-color;
+    display: table-cell;
+  }
+
+  &.vertical {
+
+    .term {
+      padding-bottom: 8px;
+      display: block;
+    }
+
+    .detail {
+      display: block;
+    }
+  }
+}
+
+.descriptionListSmall {
+  // offset the padding-bottom of last row
+  :global {
+    .ant-row {
+      margin-bottom: -8px;
+    }
+  }
+  .title {
+    margin-bottom: 12px;
+    color: @text-color;
+  }
+  .term, .detail {
+    padding-bottom: 8px;
+  }
+}
+.descriptionListLarge {
+  .title {
+    font-size: 16px;
+  }
+}
diff --git a/src/main/frontend/src/components/DescriptionList/index.md b/src/main/frontend/src/components/DescriptionList/index.md
new file mode 100644
index 0000000..bfa60cb
--- /dev/null
+++ b/src/main/frontend/src/components/DescriptionList/index.md
@@ -0,0 +1,39 @@
+---
+title:
+  en-US: DescriptionList
+  zh-CN: DescriptionList
+subtitle: 描述列表
+cols: 1
+order: 4
+---
+
+成组展示多个只读字段,常见于详情页的信息展示。
+
+## API
+
+### DescriptionList
+
+| 参数      | 说明                                      | 类型         | 默认值 |
+|----------|------------------------------------------|-------------|-------|
+| layout    | 布局方式                                 | Enum{'horizontal', 'vertical'}  | 'horizontal' |
+| col       | 指定信息最多分几列展示,最终一行几列由 col 配置结合[响应式规则](/components/DescriptionList#响应式规则)决定          | number(0 < col <= 4)  | 3 |
+| title     | 列表标题                                 | ReactNode  | - |
+| gutter    | 列表项间距,单位为 `px`                    | number  | 32 |
+| size     | 列表型号,可以设置为 `large` `small`        | Enum{'large', 'small'}  | - |
+
+#### 响应式规则
+
+| 窗口宽度             | 展示列数                                      | 
+|---------------------|---------------------------------------------|
+| `≥768px`           |  `col`                                       |
+| `≥576px`           |  `col < 2 ? col : 2`                         |
+| `<576px`           |  `1`                                         |
+
+### DescriptionList.Description
+
+| 参数      | 说明                                      | 类型         | 默认值 |
+|----------|------------------------------------------|-------------|-------|
+| term     | 列表项标题                                 | ReactNode  | - |
+
+
+
diff --git a/src/main/frontend/src/components/DescriptionList/responsive.js b/src/main/frontend/src/components/DescriptionList/responsive.js
new file mode 100644
index 0000000..a5aa73f
--- /dev/null
+++ b/src/main/frontend/src/components/DescriptionList/responsive.js
@@ -0,0 +1,6 @@
+export default {
+  1: { xs: 24 },
+  2: { xs: 24, sm: 12 },
+  3: { xs: 24, sm: 12, md: 8 },
+  4: { xs: 24, sm: 12, md: 6 },
+};
diff --git a/src/main/frontend/src/models/alert.js b/src/main/frontend/src/models/alert.js
new file mode 100644
index 0000000..ccd3380
--- /dev/null
+++ b/src/main/frontend/src/models/alert.js
@@ -0,0 +1,17 @@
+// import { xxx } from '../services/xxx';
+export default {
+  namespace: "alert",
+  state: {},
+  effects: {
+    *fetch({ payload }, { call, put }) {
+    },
+  },
+  reducers: {
+    save(state, action) {
+      return {
+        ...state,
+      };
+    },
+  },
+};
+
diff --git a/src/main/frontend/src/models/server.js b/src/main/frontend/src/models/server.js
new file mode 100644
index 0000000..241cd05
--- /dev/null
+++ b/src/main/frontend/src/models/server.js
@@ -0,0 +1,16 @@
+// import { xxx } from '../services/xxx';
+export default {
+  namespace: "server",
+  state: {},
+  effects: {
+    *fetch({ payload }, { call, put }) {
+    },
+  },
+  reducers: {
+    save(state, action) {
+      return {
+        ...state,
+      };
+    },
+  },
+};
diff --git a/src/main/frontend/src/routes/Alert/Alert.js b/src/main/frontend/src/routes/Alert/Alert.js
new file mode 100644
index 0000000..34ea5b3
--- /dev/null
+++ b/src/main/frontend/src/routes/Alert/Alert.js
@@ -0,0 +1,84 @@
+import React, { PureComponent } from 'react';
+import { connect } from 'dva';
+import { Card, Table, Input } from 'antd';
+import styles from './Alert.less';
+
+const { Search } = Input;
+
+@connect(state => ({
+  alert: state.alert,
+}))
+export default class Alert extends PureComponent {
+  render() {
+    const columns = [{
+      title: 'Content',
+      dataIndex: 'content',
+    }, {
+      title: 'Start Time',
+      dataIndex: 'time',
+    }, {
+      title: 'Alert Type',
+      dataIndex: 'type',
+      filters: [{
+        text: 'Application',
+        value: 'Application',
+      }, {
+        text: 'Server',
+        value: 'Server',
+      }, {
+        text: 'Service',
+        value: 'Service',
+      }],
+      filterMultiple: false,
+      onFilter: (value, record) => record.type.indexOf(value) === 0,
+    }];
+
+    const data = [{
+      key: '1',
+      content: 'Application alert',
+      time: '19:30',
+      type: 'Application',
+    }, {
+      key: '2',
+      content: 'Server is down',
+      time: '13:30',
+      type: 'Server',
+    }, {
+      key: '3',
+      content: 'Server is slow',
+      time: '8:30',
+      type: 'Service',
+    }, {
+      key: '4',
+      content: 'Service sla is low',
+      time: '3:30',
+      type: 'Service',
+    }];
+
+    function onChange(pagination, filters, sorter) {
+      console.log('params', pagination, filters, sorter);
+    }
+
+    const extraContent = (
+      <div className={styles.extraContent}>
+        <Search
+          className={styles.extraContentSearch}
+          placeholder="Search..."
+          onSearch={() => ({})}
+        />
+      </div>
+    );
+
+    return (
+      <Card
+        title="Alert List"
+        bordered={false}
+        extra={extraContent}
+      >
+        <div className={styles.tableList}>
+          <Table columns={columns} dataSource={data} onChange={onChange} />
+        </div>
+      </Card>
+    );
+  }
+}
diff --git a/src/main/frontend/src/routes/Alert/Alert.less b/src/main/frontend/src/routes/Alert/Alert.less
new file mode 100644
index 0000000..b10d030
--- /dev/null
+++ b/src/main/frontend/src/routes/Alert/Alert.less
@@ -0,0 +1,50 @@
+@import "~antd/lib/style/themes/default.less";
+@import "../../utils/utils.less";
+
+.tableList {
+  .tableListOperator {
+    margin-bottom: 16px;
+    button {
+      margin-right: 8px;
+    }
+  }
+}
+
+.tableListForm {
+  :global {
+    .ant-form-item {
+      margin-bottom: 24px;
+      margin-right: 0;
+      display: flex;
+      > .ant-form-item-label {
+        width: auto;
+        line-height: 32px;
+        padding-right: 8px;
+      }
+    }
+    .ant-form-item-control-wrapper {
+      flex: 1;
+    }
+  }
+  .submitButtons {
+    white-space: nowrap;
+    margin-bottom: 24px;
+  }
+}
+
+@media screen and (max-width: @screen-lg) {
+  .tableListForm :global(.ant-form-item) {
+    margin-right: 24px;
+  }
+}
+
+@media screen and (max-width: @screen-md) {
+  .tableListForm :global(.ant-form-item) {
+    margin-right: 8px;
+  }
+}
+
+.extraContentSearch {
+  margin-left: 16px;
+  width: 272px;
+}
diff --git a/src/main/frontend/src/routes/Server/Server.js b/src/main/frontend/src/routes/Server/Server.js
new file mode 100644
index 0000000..707fe8f
--- /dev/null
+++ b/src/main/frontend/src/routes/Server/Server.js
@@ -0,0 +1,172 @@
+import React, { PureComponent } from 'react';
+import { connect } from 'dva';
+import { Row, Col, Select, Card, Tooltip, Icon, Table } from 'antd';
+import moment from 'moment';
+import {
+  ChartCard, MiniArea, MiniBar, Line,
+} from '../../components/Charts';
+import DescriptionList from '../../components/DescriptionList';
+
+const { Description } = DescriptionList;
+
+@connect(state => ({
+  service: state.service,
+}))
+export default class Dashboard extends PureComponent {
+  render() {
+    const visitData = [];
+    const beginDay = new Date().getTime();
+
+    const fakeY = [7, 5, 4, 2, 4, 7, 5, 6, 5, 9, 6, 3, 1, 5, 3, 6, 5];
+    for (let i = 0; i < fakeY.length; i += 1) {
+      visitData.push({
+        x: moment(new Date(beginDay + (1000 * 60 * 60 * 24 * i))).format('YYYY-MM-DD'),
+        y: fakeY[i],
+      });
+    }
+    function handleChange(value) {
+      console.log(`selected ${value}`);
+    }
+    function handleBlur() {
+      console.log('blur');
+    }
+
+    function handleFocus() {
+      console.log('focus');
+    }
+    const tableColumns = [{
+      title: 'Time',
+      dataIndex: 'time',
+      key: 'time',
+    }, {
+      title: 'Entry',
+      dataIndex: 'name',
+      key: 'name',
+    }, {
+      title: 'Duration',
+      dataIndex: 'duration',
+      key: 'duration',
+    }];
+    const { Option } = Select;
+    const slowServiceData = [{
+      key: '1',
+      name: 'ServiceA',
+      time: '2017/12/11 19:22:32',
+      duration: '5000ms',
+    }, {
+      key: '1',
+      name: 'ServiceA',
+      time: '2017/12/11 19:22:32',
+      duration: '5000ms',
+    }, {
+      key: '1',
+      name: 'ServiceA',
+      time: '2017/12/11 19:22:32',
+      duration: '5000ms',
+    }, {
+      key: '1',
+      name: 'ServiceA',
+      time: '2017/12/11 19:22:32',
+      duration: '5000ms',
+    }, {
+      key: '1',
+      name: 'ServiceA',
+      time: '2017/12/11 19:22:32',
+      duration: '5000ms',
+    }];
+    return (
+      <div>
+        <Select
+          showSearch
+          style={{ width: 200 }}
+          placeholder="Select a server"
+          optionFilterProp="children"
+          onChange={handleChange}
+          onFocus={handleFocus}
+          onBlur={handleBlur}
+        >
+          <Option value="Server1">Server1</Option>
+          <Option value="Server1">Server1</Option>
+          <Option value="Server1">Server1</Option>
+        </Select>
+        <Card title="Info" style={{ marginTop: 24 }} bordered={false}>
+          <DescriptionList>
+            <Description term="OS Name">Mac OS X</Description>
+            <Description term="Host Name">hanahmily</Description>
+            <Description term="Process Id">21144</Description>
+            <Description term="IPv4">192.168.1.4</Description>
+          </DescriptionList>
+        </Card>
+        <Row gutter={24}>
+          <Col xs={24} sm={24} md={24} lg={12} xl={12} style={{ marginTop: 24 }}>
+            <ChartCard
+              title="Avg Response Time"
+              action={<Tooltip title="Tip"><Icon type="info-circle-o" /></Tooltip>}
+              total="300 ms"
+            >
+              <MiniArea
+                color="#975FE4"
+                height={46}
+                data={visitData}
+              />
+            </ChartCard>
+          </Col>
+          <Col xs={24} sm={24} md={24} lg={12} xl={12} style={{ marginTop: 24 }}>
+            <ChartCard
+              title="Avg TPS"
+              action={<Tooltip title="Tip"><Icon type="info-circle-o" /></Tooltip>}
+              total="500"
+            >
+              <MiniBar
+                height={46}
+                data={visitData}
+              />
+            </ChartCard>
+          </Col>
+        </Row>
+        <Row gutter={24}>
+          <Col xs={24} sm={24} md={24} lg={24} xl={24} style={{ marginTop: 24 }}>
+            <Card
+              title="CPU"
+              bordered={false}
+              bodyStyle={{ padding: 0 }}
+            >
+              <Line
+                height={250}
+                data={visitData}
+              />
+            </Card>
+          </Col>
+        </Row>
+        <Row gutter={24}>
+          <Col xs={24} sm={24} md={24} lg={24} xl={24} style={{ marginTop: 24 }}>
+            <Card
+              title="MEMORY"
+              bordered={false}
+              bodyStyle={{ padding: 0 }}
+            >
+              <Line
+                height={250}
+                data={visitData}
+              />
+            </Card>
+          </Col>
+        </Row>
+        <Row gutter={24}>
+          <Col xs={24} sm={24} md={24} lg={24} xl={24} style={{ marginTop: 24 }}>
+            <Card
+              title="GC"
+              bordered={false}
+              bodyStyle={{ padding: 0 }}
+            >
+              <Line
+                height={250}
+                data={visitData}
+              />
+            </Card>
+          </Col>
+        </Row>
+      </div>
+    );
+  }
+}

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