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/skywalking-rocketbot-ui.git


The following commit(s) were added to refs/heads/master by this push:
     new 8d54cb4  feat: multiple metrics compare (#195)
8d54cb4 is described below

commit 8d54cb46919ca20069e727f2e86963d27f07428f
Author: Fine <[email protected]>
AuthorDate: Wed Nov 13 21:19:24 2019 +0800

    feat: multiple metrics compare (#195)
    
    * feat: multiple select component
    
    * feat: multiple select component
    
    * feat: query multiple value
    
    * feat: update style
    
    * feat: update config
    
    * feat: add color
---
 src/components/rk-select.vue                       | 59 ++++++++++++++++---
 src/store/modules/comparison/comparison-const.ts   |  4 +-
 src/store/modules/comparison/comparison-store.ts   | 67 ++++++++++++++--------
 src/types/comparison.d.ts                          |  4 +-
 src/views/components/comparison/chart-line.vue     |  8 ++-
 .../components/comparison/comparison-charts.vue    | 23 +++++++-
 .../components/comparison/comparison-config.vue    | 30 +++++-----
 .../components/dashboard/charts/chart-slow.vue     |  2 +-
 src/views/containers/comparison.vue                |  1 +
 9 files changed, 145 insertions(+), 53 deletions(-)

diff --git a/src/components/rk-select.vue b/src/components/rk-select.vue
index fed32ea..6d67952 100644
--- a/src/components/rk-select.vue
+++ b/src/components/rk-select.vue
@@ -19,8 +19,13 @@
   <div class="rk-bar-select cp flex-h" v-clickout="() => { visible = 
false;search = '';}" :class="{'active':visible}">
     <div class="rk-bar-i flex-h" @click="visible = !visible">
       <div class="mr-15 rk-bar-i-text">
-        <div class="sm grey">{{title}}</div>
-        <div class="ell" v-tooltip:right.ellipsis="current.label || 
''">{{current.label}}</div>
+        <div v-if="Array.isArray(current)">
+          <span class="selected" v-for="item in current" :key="item.key">
+            <span>{{item.label}}</span>
+            <span class="remove-icon" @click="removeSelected(item)">×</span>
+          </span>
+        </div>
+        <div class="ell" v-else v-tooltip:right.ellipsis="current.label || 
''">{{current.label}}</div>
       </div>
       <svg class="icon lg trans" :style="`transform: 
rotate(${visible?180:0}deg)`">
         <use xlink:href="#arrow-down"></use>
@@ -34,7 +39,7 @@
         </svg>
       </div>
       <div class="rk-opt-wrapper scroll_hide">
-        <div class="rk-opt ell" @click="handleSelect(i)" 
:class="{'active':i.key === current.key}" v-for="i in filterData" 
:key="i.key">{{i.label}}</div>
+        <div class="rk-opt ell" @click="handleSelect(i)" 
:class="{'select-disabled': selectedOpt.includes(i.key)}" v-for="i in 
filterData" :key="i.key">{{i.label}}</div>
       </div>
     </div>
   </div>
@@ -42,37 +47,69 @@
 
 <script lang="ts">
 import { Vue, Component, Prop } from 'vue-property-decorator';
+const Multiple = 'multiple';
 @Component
 export default class RkSelect extends Vue {
+  @Prop() public mode: any;
   @Prop() public data!: any;
   @Prop() public current!: any;
-  @Prop() public title!: string;
-  @Prop() public icon!: string;
   public search: string = '';
   public visible: boolean = false;
+
   get filterData() {
     return this.data.filter((i: any) => 
i.label.toUpperCase().indexOf(this.search.toUpperCase()) !== -1);
   }
+
+  get selectedOpt() {
+    return this.mode === Multiple ? this.current.map((item: any) => item.key) 
: [this.current.key];
+  }
+
   public handleOpen() {
     this.visible = true;
   }
+
   public handleSelect(i: any) {
+    const selected = this.mode === Multiple ? this.current.map((item: any) => 
item.key) : [this.current.key];
+    if (selected.includes(i.key)) {
+      return;
+    }
     this.$emit('onChoose', i);
     this.visible = false;
   }
+
+  private removeSelected(item: any) {
+    if (this.mode === Multiple) {
+      this.$emit('onChoose', item);
+    }
+  }
 }
 </script>
 
 <style lang="scss" scoped>
 .rk-bar-select {
   position: relative;
-  height: 40px;
+  min-height: 40px;
   justify-content: space-between;
   border: 1px solid #ddd;
   background: #fff;
   border-radius: 3px;
   .sm{ line-height: 12px;}
   .icon { flex-shrink: 0};
+  .selected {
+    display: inline-block;
+    padding: 5px;
+    border-radius: 3px;
+    margin: 3px;
+    overflow: hidden;
+    color: rgba(0, 0, 0, 0.65);
+    background-color: #fafafa;
+    border: 1px solid #e8e8e8;
+  }
+  .remove-icon {
+    display: inline-block;
+    margin-left: 5px;
+    cursor: pointer;
+  }
 }
 .rk-bar-i-text{
   width: 100%;
@@ -81,10 +118,11 @@ export default class RkSelect extends Vue {
   height: 100%;
   width: 100%;
   padding: 5px 15px;
+  overflow: auto;
 }
 .rk-sel{
   position: absolute;
-  top: 39px;
+  top: 100%;
   background: #fff;
   box-shadow: 0 1px 6px rgba(99, 99, 99, 0.2);
   border: 1px solid #ddd;
@@ -102,6 +140,13 @@ export default class RkSelect extends Vue {
 }
 .rk-opt{
   padding: 7px 15px;
+  &.select-disabled {
+    color: rgba(0, 0, 0, 0.25);
+    cursor: not-allowed;
+  }
+  &:hover{
+    background-color: #f5f5f5;
+  }
 }
 .rk-sel-search{
   width: calc(100% - 4px);
diff --git a/src/store/modules/comparison/comparison-const.ts 
b/src/store/modules/comparison/comparison-const.ts
index f77cac2..391fc05 100644
--- a/src/store/modules/comparison/comparison-const.ts
+++ b/src/store/modules/comparison/comparison-const.ts
@@ -39,11 +39,11 @@ export const ComparisonOption: ICurrentOptions = {
   preService: {key: 0, label: ''},
   preType: {key: 'ServiceEndpoint', label: 'Service Endpoint'},
   preObject: {key: 0, label: '/projectB/{name}'},
-  preMetrics: {key: 0, label: ''},
+  preMetrics: [{key: 0, label: ''}],
   nextService: {key: 0, label: ''},
   nextType: {key: 'ServiceEndpoint', label: 'Service Endpoint'},
   nextObject: {key: 0, label: '/projectA/{name}'},
-  nextMetrics: {key: 0, label: ''},
+  nextMetrics: [{key: 0, label: ''}],
 };
 
 export const InitSource: DataSourceType = {
diff --git a/src/store/modules/comparison/comparison-store.ts 
b/src/store/modules/comparison/comparison-store.ts
index ae0ba6c..e55a45b 100644
--- a/src/store/modules/comparison/comparison-store.ts
+++ b/src/store/modules/comparison/comparison-store.ts
@@ -58,24 +58,33 @@ const initState: State = {
 // getters
 const getters = {
   queryPreValue(state: State) {
-    const { currentOptions } = state;
-    const preMetric = currentOptions.preMetrics.key;
-    const preParam = (fragmentAll as any)[preMetric];
-    if (!preParam) {
-      return;
-    }
+    const { preMetrics } = state.currentOptions;
+    const fragments = [];
+    let variable = null;
 
-    return `query queryData(${preParam.variable.join(',')}) 
{${preParam.fragment}}`;
+    for (const metric of preMetrics) {
+      const preMetric = metric.key;
+      const preParam = (fragmentAll as any)[preMetric];
+      if (preParam) {
+        variable = preParam.variable;
+        fragments.push(preParam.fragment);
+      }
+    }
+    return `query queryData(${variable}) {${fragments.join(',')}}`;
   },
   queryNextValue(state: State) {
-    const { currentOptions } = state;
-    const nextMetric =  currentOptions.nextMetrics.key;
-    const nextParam = (fragmentAll as any)[nextMetric];
+    const { nextMetrics } = state.currentOptions;
+    const fragments = [];
+    let variable = null;
 
-    if (!nextParam) {
-      return;
+    for (const metric of nextMetrics) {
+      const nextParam = (fragmentAll as any)[metric.key];
+      if (nextParam) {
+        variable = nextParam.variable;
+        fragments.push(nextParam.fragment);
+      }
     }
-    return `query queryData(${nextParam.variable.join(',')}) 
{${nextParam.fragment}}`;
+    return `query queryData(${variable}) {${fragments.join(',')}}`;
   },
   preConfig(state: State) {
     const { currentOptions } = state;
@@ -203,19 +212,19 @@ const mutations = {
       state.dataSource.preObjectSource = data;
       state.currentOptions.preObject = data[0];
       state.dataSource.preMetricsSource = metricSource[type];
-      state.currentOptions.preMetrics = metricSource[type][0];
+      state.currentOptions.preMetrics = [metricSource[type][0]];
     } else if (isPrevious === StatusType.Next) {
       state.dataSource.nextObjectSource = data;
       state.currentOptions.nextObject = data[0];
       state.dataSource.nextMetricsSource = metricSource[type];
-      state.currentOptions.nextMetrics = metricSource[type][1];
+      state.currentOptions.nextMetrics = [metricSource[type][1]];
     } else {
       state.currentOptions = {
         ...state.currentOptions,
         nextObject: data[0],
         preObject: data[0],
-        preMetrics: metricSource[type][0],
-        nextMetrics: metricSource[type][1],
+        preMetrics: [metricSource[type][0]],
+        nextMetrics: [metricSource[type][1]],
         preType: ComparisonType[2],
         nextType: ComparisonType[2],
       };
@@ -254,7 +263,17 @@ const mutations = {
   [types.UPDATE_CONFIG](state: any, data: ISelectConfig) {
     const {type, option} = data;
 
-    state.currentOptions[type] = option;
+    if (type === ChangeType.NextMetrics || type === ChangeType.PreMetrics) {
+      const metrics = state.currentOptions[type];
+      const item = metrics.findIndex((d: any) => d.key === option.key);
+      if (item > -1) {
+        state.currentOptions[type] = metrics.filter((d: any) => d.key !== 
option.key);
+      } else {
+        state.currentOptions[type].push(option);
+      }
+    } else {
+      state.currentOptions[type] = option;
+    }
   },
   [types.CLEAR_CHART_VAL](state: State) {
     state.chartSource = {} as any;
@@ -265,10 +284,10 @@ const mutations = {
 
     if (isPrevious === StatusType.Pre) {
       state.dataSource.preMetricsSource = metricSource[preType.key] || [];
-      state.currentOptions.preMetrics = metricSource[preType.key][0];
+      state.currentOptions.preMetrics = [metricSource[preType.key][0]];
     } else {
       state.dataSource.nextMetricsSource = metricSource[nextType.key] || [];
-      state.currentOptions.nextMetrics = metricSource[nextType.key][0];
+      state.currentOptions.nextMetrics = [metricSource[nextType.key][0]];
     }
   },
   [types.SELECT_TYPE_INSTANCE](state: State, data: any) {
@@ -277,12 +296,12 @@ const mutations = {
 
     if (isPrevious === StatusType.Pre) {
       state.dataSource.preMetricsSource = metricSource[preType.key];
-      state.currentOptions.preMetrics = metricSource[preType.key][0];
+      state.currentOptions.preMetrics = [metricSource[preType.key][0]];
       state.dataSource.preObjectSource = data;
       state.currentOptions.preObject = data[0];
     } else if (isPrevious === StatusType.Next) {
       state.dataSource.nextMetricsSource = metricSource[nextType.key];
-      state.currentOptions.nextMetrics = metricSource[nextType.key][0];
+      state.currentOptions.nextMetrics = [metricSource[nextType.key][0]];
       state.dataSource.nextObjectSource = data;
       state.currentOptions.nextObject = data[0];
     }
@@ -293,12 +312,12 @@ const mutations = {
 
     if (state.isPrevious === StatusType.Next) {
       state.dataSource.nextMetricsSource = metricSource[nextType.key];
-      state.currentOptions.nextMetrics = metricSource[nextType.key][0];
+      state.currentOptions.nextMetrics = [metricSource[nextType.key][0]];
       state.currentOptions.nextObject = data[0];
       state.dataSource.nextObjectSource = data;
     } else {
       state.dataSource.preMetricsSource = metricSource[preType.key];
-      state.currentOptions.preMetrics = metricSource[preType.key][0];
+      state.currentOptions.preMetrics = [metricSource[preType.key][0]];
       state.currentOptions.preObject = data[0];
       state.dataSource.preObjectSource = data;
     }
diff --git a/src/types/comparison.d.ts b/src/types/comparison.d.ts
index cf68c9a..8855c75 100644
--- a/src/types/comparison.d.ts
+++ b/src/types/comparison.d.ts
@@ -22,11 +22,11 @@ export interface ICurrentOptions {
   preService: IOption;
   preType: IOption;
   preObject: IOption;
-  preMetrics: IOption;
+  preMetrics: IOption[];
   nextService: IOption;
   nextType: IOption;
   nextObject: IOption;
-  nextMetrics: IOption;
+  nextMetrics: IOption[];
 }
 export interface DataSourceType {
   preServiceSource: IOption[];
diff --git a/src/views/components/comparison/chart-line.vue 
b/src/views/components/comparison/chart-line.vue
index a6cb99b..e37d851 100644
--- a/src/views/components/comparison/chart-line.vue
+++ b/src/views/components/comparison/chart-line.vue
@@ -50,9 +50,13 @@ export default class ChartLine extends Vue {
       temp.push(serie);
     });
     const color: string[] = [
+      '#30A4EB',
+      '#45BFC0',
+      '#FFCC55',
+      '#FF6A84',
+      '#a0a7e6',
       '#6be6c1',
       '#626c91',
-      '#a0a7e6',
       '#96dee8',
       '#3f96e3',
     ];
@@ -67,7 +71,7 @@ export default class ChartLine extends Vue {
         },
       },
       legend: {
-        show: true,
+        show: false,
         icon: 'circle',
         top: 0,
         left: 0,
diff --git a/src/views/components/comparison/comparison-charts.vue 
b/src/views/components/comparison/comparison-charts.vue
index def4035..2fbb5e0 100644
--- a/src/views/components/comparison/comparison-charts.vue
+++ b/src/views/components/comparison/comparison-charts.vue
@@ -17,7 +17,12 @@
 
 <template>
   <div class="rk-comparison-charts">
-    <ChartLine :intervalTime="intervalTime" :data="chartSource" />
+    <div class="component-item" v-for="item of Object.keys(chartSource)" 
:key="item">
+      <div class="title">{{item}}</div>
+      <div class="chart-item">
+        <ChartLine :intervalTime="intervalTime" :data="{[item]: 
chartSource[item]}" />
+      </div>
+    </div>
   </div>
 </template>
 
@@ -41,5 +46,21 @@
     flex-grow: 5;
     height: 100%;
     padding: 20px;
+    overflow: auto;
+    .chart-item {
+      width: 100%;
+      height: 200px;
+    }
+    .component-item {
+      width: 100%;
+      .title {
+        height: 30px;
+        line-height: 30px;
+        margin: 10px 0;
+        padding-left: 10px;
+        background-color: rgba(196,200,225,.2);
+        color: #9da5b2;
+      }
+    }
   }
 </style>
diff --git a/src/views/components/comparison/comparison-config.vue 
b/src/views/components/comparison/comparison-config.vue
index e92bc52..52337b0 100644
--- a/src/views/components/comparison/comparison-config.vue
+++ b/src/views/components/comparison/comparison-config.vue
@@ -18,6 +18,13 @@
 <template>
   <div class="rk-comparison-config" v-if="currentOptions">
     <h4>{{this.$t("previousService")}}</h4>
+    <label>{{this.$t("type")}}</label>
+    <RkSelect
+      class="mb-5"
+      :current="currentOptions.preType"
+      :data="optSource.preTypeSource"
+      @onChoose="(item) => changOption(item, changeType.PreType)"
+    />
     <div v-if="currentOptions.preType.key !== 'Database'">
       <label>{{this.$t("service")}}</label>
       <RkSelect
@@ -27,13 +34,6 @@
         @onChoose="(item) => changOption(item, changeType.PreService)"
       />
     </div>
-    <label>{{this.$t("type")}}</label>
-    <RkSelect
-      class="mb-5"
-      :current="currentOptions.preType"
-      :data="optSource.preTypeSource"
-      @onChoose="(item) => changOption(item, changeType.PreType)"
-    />
     <div v-if="currentOptions.preType.key !== 'Service'">
       <label>{{this.$t("object")}}</label>
       <RkSelect
@@ -46,11 +46,19 @@
     <label>{{this.$t("metrics")}}</label>
     <RkSelect
       class="mb-5"
+      :mode="'multiple'"
       :current="currentOptions.preMetrics"
       :data="optSource.preMetricsSource"
       @onChoose="(item) => changOption(item, changeType.PreMetrics)"
     />
     <h4>{{this.$t("nextService")}}</h4>
+    <label>{{this.$t("type")}}</label>
+    <RkSelect
+      class="mb-5"
+      :current="currentOptions.nextType"
+      :data="optSource.nextTypeSource"
+      @onChoose="(item) => changOption(item, changeType.NextType)"
+    />
     <div v-if="currentOptions.nextType.key !== 'Database'">
       <label>{{this.$t("service")}}</label>
       <RkSelect
@@ -60,13 +68,6 @@
         @onChoose="(item) => changOption(item, changeType.NextService)"
       />
     </div>
-    <label>{{this.$t("type")}}</label>
-    <RkSelect
-      class="mb-5"
-      :current="currentOptions.nextType"
-      :data="optSource.nextTypeSource"
-      @onChoose="(item) => changOption(item, changeType.NextType)"
-    />
     <div v-if="currentOptions.nextType.key !== 'Service'">
       <label>{{this.$t("object")}}</label>
       <RkSelect
@@ -79,6 +80,7 @@
     <label>{{this.$t("metrics")}}</label>
     <RkSelect
       class="mb-5"
+      :mode="'multiple'"
       :current="currentOptions.nextMetrics"
       :data="optSource.nextMetricsSource"
       @onChoose="(item) => changOption(item, changeType.NextMetrics)"
diff --git a/src/views/components/dashboard/charts/chart-slow.vue 
b/src/views/components/dashboard/charts/chart-slow.vue
index 7a3fbb9..11d4e44 100644
--- a/src/views/components/dashboard/charts/chart-slow.vue
+++ b/src/views/components/dashboard/charts/chart-slow.vue
@@ -49,7 +49,7 @@ export default class ChartSlow extends Vue {
     const temp: number[] = this.data.map((i: any) => i.value);
     return Math.max.apply(null, temp);
   }
-  getTraceId(i: any){
+  private getTraceId(i: any) {
     return i.traceIds && i.traceIds[0] ? ` - ${i.traceIds[0]}` : '';
   }
   private handleClick(i: any) {
diff --git a/src/views/containers/comparison.vue 
b/src/views/containers/comparison.vue
index fc4c9d2..f33b611 100644
--- a/src/views/containers/comparison.vue
+++ b/src/views/containers/comparison.vue
@@ -65,5 +65,6 @@
 <style lang="scss">
   .rk-comparison {
     height: 100%;
+    overflow: auto;
   }
 </style>

Reply via email to