You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@skywalking.apache.org by wu...@apache.org on 2018/03/08 12:45:20 UTC

[incubator-skywalking-ui] branch master updated: Enhancement components (#144)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 1780590  Enhancement components (#144)
1780590 is described below

commit 178059096be011229975b546519c7326c844d34c
Author: Gao Hongtao <ha...@gmail.com>
AuthorDate: Thu Mar 8 20:45:19 2018 +0800

    Enhancement components (#144)
    
    * Rename favicon
    
    * Amend topology
    
    * Add default value to Search component
    
    * Rename favicon path
    
    * Fix #138 add a new avg function to filter 0 value
    
    * Fix #137 typo in Server and Service
    
    * Fix #141 render dependency map error
    
    * Fix #142 the default value of applicationId should be 'All application'
    
    * Fix #133 progressive rendering topology map
    
    * Fix #136 refresh icon
---
 src/components/Duration/Icon/index.js  | 30 +++++++++++++++++++++++++++---
 src/components/GlobalHeader/index.js   |  5 +++--
 src/components/Topology/AppTopology.js |  6 +++---
 src/components/Topology/Base.js        | 14 +++++++++++++-
 src/components/Topology/conf.js        |  6 ++++--
 src/layouts/BasicLayout.js             |  7 ++++---
 src/models/global.js                   |  3 +++
 src/utils/models.js                    |  2 +-
 8 files changed, 58 insertions(+), 15 deletions(-)

diff --git a/src/components/Duration/Icon/index.js b/src/components/Duration/Icon/index.js
index 03becc0..8305127 100644
--- a/src/components/Duration/Icon/index.js
+++ b/src/components/Duration/Icon/index.js
@@ -19,10 +19,34 @@
 import React, { PureComponent } from 'react';
 import { Icon } from 'antd';
 import moment from 'moment';
+import lodash from 'lodash';
 
 export default class DurationIcon extends PureComponent {
+  state = {
+    // noLoading: -1, loading: 1, loadingFinish: 0
+    innerLoading: -1,
+  }
+  handleToggle = () => {
+    const { loading, onToggle } = this.props;
+    if (loading) {
+      return;
+    }
+    onToggle();
+  }
+  renderLoad() {
+    const { loading, className, onReload } = this.props;
+    if (!loading && this.state.innerLoading < 1) {
+      this.state.innerLoading = -1;
+      return <span className={className} onClick={onReload}> <Icon type="reload" /> </span>;
+    }
+    if (this.state.innerLoading < 0) {
+      this.state.innerLoading = 1;
+      lodash.delay(() => this.setState({ innerLoading: 0 }), 1000);
+    }
+    return <span className={className}> <Icon type="loading" /> </span>;
+  }
   render() {
-    const { className, onToggle, onReload, selectedDuration = {
+    const { className, selectedDuration = {
       from() {
         return moment();
       },
@@ -36,12 +60,12 @@ export default class DurationIcon extends PureComponent {
       <span>
         <span
           className={className}
-          onClick={onToggle}
+          onClick={this.handleToggle}
         >
           {selectedDuration.label ? selectedDuration.label : `${selectedDuration.from().format(timeFormat)} ~ ${selectedDuration.to().format(timeFormat)}`}
           {selectedDuration.step > 0 ? ` Reloading every ${selectedDuration.step / 1000} seconds` : null }
         </span>
-        <span className={className} onClick={onReload}> <Icon type="reload" /> </span>
+        {this.renderLoad()}
       </span>
     );
   }
diff --git a/src/components/GlobalHeader/index.js b/src/components/GlobalHeader/index.js
index f6c08fb..7b02449 100644
--- a/src/components/GlobalHeader/index.js
+++ b/src/components/GlobalHeader/index.js
@@ -73,7 +73,7 @@ export default class GlobalHeader extends PureComponent {
   render() {
     const {
       collapsed, notices: { applicationAlarmList, serverAlarmList },
-      isMobile, logo, selectedDuration,
+      isMobile, logo, selectedDuration, fetching,
       onDurationToggle, onDurationReload, onRedirect: redirect,
     } = this.props;
     const applications = applicationAlarmList.items.map(_ => ({ ..._, datetime: _.startTime }));
@@ -97,6 +97,7 @@ export default class GlobalHeader extends PureComponent {
         />
         <div className={styles.right}>
           <DurationIcon
+            loading={fetching}
             className={styles.action}
             selectedDuration={selectedDuration}
             onToggle={onDurationToggle}
@@ -111,7 +112,7 @@ export default class GlobalHeader extends PureComponent {
             onClear={(tabTitle) => {
               redirect({ pathname: '/alarm', state: { type: tabTitle } });
             }}
-            loading={false}
+            loading={fetching}
             popupAlign={{ offset: [20, -16] }}
             locale={{
               emptyText: 'No alert',
diff --git a/src/components/Topology/AppTopology.js b/src/components/Topology/AppTopology.js
index 1779a30..7ba8139 100644
--- a/src/components/Topology/AppTopology.js
+++ b/src/components/Topology/AppTopology.js
@@ -60,9 +60,10 @@ export default class AppTopology extends Base {
           'curve-style': 'bezier',
           'control-point-step-size': 100,
           'target-arrow-shape': 'triangle',
+          'arrow-scale': 1.7,
           'target-arrow-color': ele => (ele.data('isAlert') ? 'rgb(204, 0, 51)' : 'rgb(147, 198, 174)'),
           'line-color': ele => (ele.data('isAlert') ? 'rgb(204, 0, 51)' : 'rgb(147, 198, 174)'),
-          width: 2,
+          width: 3,
           label: ele => `${ele.data('callType')} \n ${ele.data('callsPerSec')} tps / ${ele.data('avgResponseTime')} ms`,
           'text-wrap': 'wrap',
           color: 'rgb(110, 112, 116)',
@@ -84,13 +85,12 @@ export default class AppTopology extends Base {
           return `
           <div class="${styles.circle}">
             <div class="node-percentage">${data.sla}%</div>
-            <div>${data.callsPerSec} calls/s</div>
             <div>
               <img src="img/icon/data.png" class="${styles.logo}"/>${data.numOfServer}
               <img src="img/icon/alert.png" class="${styles.logo}"/>
               <span class="${styles.alert}">${data.numOfServerAlarm}</span>
             </div>
-            <div>${data.apdex} Apdex</div>
+            <div>${data.callsPerSec} calls/s</div>
           </div>`;
         },
       },
diff --git a/src/components/Topology/Base.js b/src/components/Topology/Base.js
index ae4560e..a5c96a7 100644
--- a/src/components/Topology/Base.js
+++ b/src/components/Topology/Base.js
@@ -42,13 +42,18 @@ export default class Base extends Component {
     if (nextProps.elements === this.elements) {
       return;
     }
+    const nodes = this.cy.nodes();
+    const nextElements = this.transform(nextProps.elements);
+    this.cy.json({ elements: nextElements, style: this.getStyle() });
+    if (this.isSame(nodes, this.cy.nodes())) {
+      return;
+    }
     const { layout: layoutConfig = {
       name: 'cose-bilkent',
       animate: false,
       idealEdgeLength: 200,
       edgeElasticity: 0.1,
     } } = this.props;
-    this.cy.json({ elements: this.transform(nextProps.elements), style: this.getStyle() });
     const layout = this.cy.layout(layoutConfig);
     layout.pon('layoutstop').then(() => {
       this.cy.minZoom(this.cy.zoom() - 0.3);
@@ -64,6 +69,13 @@ export default class Base extends Component {
   getCy() {
     return this.cy;
   }
+  isSame = (nodes, nextNodes) => {
+    if (nodes.length !== nextNodes.length) {
+      return false;
+    }
+    const diff = nextNodes.diff(nodes);
+    return diff.left.length < 1 && diff.right.length < 1;
+  }
   transform(elements) {
     if (!elements) {
       return [];
diff --git a/src/components/Topology/conf.js b/src/components/Topology/conf.js
index cd1c707..d50d020 100644
--- a/src/components/Topology/conf.js
+++ b/src/components/Topology/conf.js
@@ -21,10 +21,12 @@ const conf = {
   maxZoom: 1,
   boxSelectionEnabled: true,
   autounselectify: true,
+  wheelSensitivity: 0.2,
   layout: {
     name: 'cose-bilkent',
-    animate: true,
-    idealEdgeLength: 100,
+    animate: false,
+    idealEdgeLength: 200,
+    edgeElasticity: 0.1,
   },
 };
 
diff --git a/src/layouts/BasicLayout.js b/src/layouts/BasicLayout.js
index cf1b900..2503113 100644
--- a/src/layouts/BasicLayout.js
+++ b/src/layouts/BasicLayout.js
@@ -25,6 +25,7 @@ import { Route, Redirect, Switch, routerRedux } from 'dva/router';
 import { ContainerQuery } from 'react-container-query';
 import classNames from 'classnames';
 import { enquireScreen } from 'enquire-js';
+import lodash from 'lodash';
 import GlobalHeader from '../components/GlobalHeader';
 import GlobalFooter from '../components/GlobalFooter';
 import SiderMenu from '../components/SiderMenu';
@@ -197,7 +198,7 @@ class BasicLayout extends React.PureComponent {
   }
   render() {
     const {
-      collapsed, fetchingNotices, notices, routerData, match, location,
+      collapsed, fetching, notices, routerData, match, location,
       duration: { selected: dSelected, collapsed: dCollapsed },
     } = this.props;
     const bashRedirect = this.getBashRedirect();
@@ -217,7 +218,7 @@ class BasicLayout extends React.PureComponent {
         <Layout>
           <GlobalHeader
             logo={logo}
-            fetchingNotices={fetchingNotices}
+            fetching={fetching}
             notices={notices}
             collapsed={collapsed}
             isMobile={this.state.isMobile}
@@ -294,7 +295,7 @@ class BasicLayout extends React.PureComponent {
 
 export default connect(({ global, loading }) => ({
   collapsed: global.collapsed,
-  fetchingNotices: loading.effects['global/fetchNotices'],
+  fetching: lodash.values(loading.models).findIndex(_ => _) > -1,
   notices: global.notices,
   duration: global.duration,
   globalVariables: global.globalVariables,
diff --git a/src/models/global.js b/src/models/global.js
index 6f40181..05e3c6c 100644
--- a/src/models/global.js
+++ b/src/models/global.js
@@ -101,6 +101,9 @@ export default {
     },
     reloadDuration(state) {
       const { duration } = state;
+      if (!duration.collapsed) {
+        return state;
+      }
       const { selected } = duration;
       const value = generateDuration(selected);
       return {
diff --git a/src/utils/models.js b/src/utils/models.js
index 82a67bd..66c64cd 100644
--- a/src/utils/models.js
+++ b/src/utils/models.js
@@ -76,7 +76,7 @@ export function generateModal({ namespace, dataQuery, optionsQuery, defaultOptio
         Object.keys(allOptions).forEach((_) => {
           const thisOptions = allOptions[_];
           if (!values[_]) {
-            if (defaultOption[_]) {
+            if (defaultOption && defaultOption[_]) {
               defaultValues[_] = defaultOption[_].key;
               defaultLabels[_] = defaultOption[_].label;
               amendOptions[_] = [defaultOption[_], ...thisOptions];

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