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

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


The following commit(s) were added to refs/heads/main by this push:
     new 42d8e90  feat:  Move topology to widgets (#29)
42d8e90 is described below

commit 42d8e909f6195ed49afe5b5e2a79972b61f8b022
Author: Fine0830 <[email protected]>
AuthorDate: Sun Mar 20 19:45:31 2022 +0800

    feat:  Move topology to widgets (#29)
---
 src/components/Selector.vue                        |   2 +-
 src/locales/lang/en.ts                             |   1 +
 src/locales/lang/zh.ts                             |   1 +
 src/store/modules/dashboard.ts                     |  25 ++--
 src/types/dashboard.ts                             |   2 +-
 src/views/dashboard/Edit.vue                       |  14 +-
 src/views/dashboard/List.vue                       |  15 +-
 src/views/dashboard/configuration/Topology.vue     |  54 +++++++-
 src/views/dashboard/configuration/Widget.vue       |   2 +-
 .../configuration/topology/StyleOptions.vue        | 151 ---------------------
 .../{components => widget}/WidgetOptions.vue       |   0
 src/views/dashboard/controls/Tab.vue               |   1 +
 src/views/dashboard/controls/Topology.vue          | 109 +++++----------
 src/views/dashboard/controls/Widget.vue            |  20 +--
 src/views/dashboard/data.ts                        |  12 +-
 src/views/dashboard/graphs/EndpointList.vue        |   6 +-
 src/views/dashboard/graphs/InstanceList.vue        |   6 +-
 src/views/dashboard/panel/Layout.vue               |   2 +-
 src/views/dashboard/related/log/Header.vue         |   8 ++
 src/views/dashboard/related/profile/Header.vue     |  13 ++
 src/views/dashboard/related/topology/Index.vue     |  14 +-
 .../related/topology/components/Graph.vue          |  84 ++++++++----
 .../related/topology/components/PodTopology.vue    |  60 ++++++--
 .../dashboard/related/topology/utils/legend.ts     |   4 +-
 src/views/dashboard/related/trace/Filter.vue       |  19 ++-
 25 files changed, 278 insertions(+), 347 deletions(-)

diff --git a/src/components/Selector.vue b/src/components/Selector.vue
index 5fbfdb6..c40867e 100644
--- a/src/components/Selector.vue
+++ b/src/components/Selector.vue
@@ -49,7 +49,7 @@ const props = defineProps({
     default: () => [],
   },
   value: {
-    type: [Array, String] as PropType<string[] | string>,
+    type: [Array, String, Number] as PropType<any>,
     default: () => [],
   },
   size: { type: null, default: "default" },
diff --git a/src/locales/lang/en.ts b/src/locales/lang/en.ts
index 2c56f8b..56a8dc2 100644
--- a/src/locales/lang/en.ts
+++ b/src/locales/lang/en.ts
@@ -112,6 +112,7 @@ const msg = {
   showGroup: "Show Group",
   noRoot: "Please set a root dashboard for",
   noWidget: "Please add widgets.",
+  rename: "Rename",
   hourTip: "Select Hour",
   minuteTip: "Select Minute",
   secondTip: "Select Second",
diff --git a/src/locales/lang/zh.ts b/src/locales/lang/zh.ts
index 36c4a19..3cec3c1 100644
--- a/src/locales/lang/zh.ts
+++ b/src/locales/lang/zh.ts
@@ -112,6 +112,7 @@ const msg = {
   noRoot: "请设置根仪表板,为",
   showGroup: "显示分组",
   noWidget: "请添加组件",
+  rename: "重命名",
   hourTip: "选择小时",
   minuteTip: "选择分钟",
   secondTip: "选择秒数",
diff --git a/src/store/modules/dashboard.ts b/src/store/modules/dashboard.ts
index 30a465c..4839296 100644
--- a/src/store/modules/dashboard.ts
+++ b/src/store/modules/dashboard.ts
@@ -27,6 +27,7 @@ import { Duration } from "@/types/app";
 import { AxiosResponse } from "axios";
 import { ElMessage } from "element-plus";
 import { useI18n } from "vue-i18n";
+import { EntityType } from "@/views/dashboard/data";
 interface DashboardState {
   showConfig: boolean;
   layout: LayoutConfig[];
@@ -92,15 +93,15 @@ export const dashboardStore = defineStore({
         ];
       }
       if (type === "Topology") {
-        newItem.w = 4;
-        newItem.h = 6;
+        newItem.h = 36;
         newItem.graph = {
-          fontColor: "white",
-          backgroundColor: "green",
-          iconTheme: true,
-          content: "Topology",
-          fontSize: 18,
           showDepth: true,
+          depth:
+            this.entity === EntityType[1].value
+              ? 1
+              : this.entity === EntityType[0].value
+              ? 2
+              : 3,
         };
       }
       if (type === "Trace" || type === "Profile" || type === "Log") {
@@ -144,19 +145,13 @@ export const dashboardStore = defineStore({
         metrics: [""],
       };
       if (type === "Topology") {
-        newItem.w = 4;
-        newItem.h = 6;
+        newItem.h = 32;
         newItem.graph = {
-          fontColor: "white",
-          backgroundColor: "green",
-          iconTheme: true,
-          content: "Topology",
-          fontSize: 18,
           showDepth: true,
         };
       }
       if (type === "Trace" || type === "Profile" || type === "Log") {
-        newItem.h = 24;
+        newItem.h = 32;
       }
       if (this.layout[idx].children) {
         const items = children.map((d: LayoutConfig) => {
diff --git a/src/types/dashboard.ts b/src/types/dashboard.ts
index eb70d28..bae7588 100644
--- a/src/types/dashboard.ts
+++ b/src/types/dashboard.ts
@@ -129,6 +129,6 @@ export interface TopologyConfig {
   iconTheme?: boolean;
   content?: string;
   fontSize?: number;
-  depth?: string;
+  depth?: number;
   showDepth?: boolean;
 }
diff --git a/src/views/dashboard/Edit.vue b/src/views/dashboard/Edit.vue
index 3da6c97..99a7fae 100644
--- a/src/views/dashboard/Edit.vue
+++ b/src/views/dashboard/Edit.vue
@@ -28,16 +28,7 @@ limitations under the License. -->
       @closed="dashboardStore.setConfigPanel(false)"
     >
       <TopologyConfig v-if="dashboardStore.selectedGrid.type === 'Topology'" />
-      <Widget v-else />
-    </el-dialog>
-    <el-dialog
-      v-model="dashboardStore.showTopology"
-      :destroy-on-close="true"
-      fullscreen
-      @closed="dashboardStore.setTopology(false)"
-      custom-class="dark-dialog"
-    >
-      <Topology />
+      <WidgetConfig v-else />
     </el-dialog>
   </div>
 </template>
@@ -47,9 +38,8 @@ import { useI18n } from "vue-i18n";
 import { useRoute } from "vue-router";
 import GridLayout from "./panel/Layout.vue";
 import Tool from "./panel/Tool.vue";
-import Widget from "./configuration/Widget.vue";
 import TopologyConfig from "./configuration/Topology.vue";
-import Topology from "./related/topology/Index.vue";
+import WidgetConfig from "./configuration/Widget.vue";
 import { useDashboardStore } from "@/store/modules/dashboard";
 import { useAppStoreWithOut } from "@/store/modules/app";
 
diff --git a/src/views/dashboard/List.vue b/src/views/dashboard/List.vue
index 08f0377..8760849 100644
--- a/src/views/dashboard/List.vue
+++ b/src/views/dashboard/List.vue
@@ -60,7 +60,7 @@ limitations under the License. -->
               {{ t("view") }}
             </el-button>
             <el-button size="small" @click="handleEdit(scope.row)">
-              {{ t("edit") }}
+              {{ t("rename") }}
             </el-button>
             <el-popconfirm
               title="Are you sure to delete this?"
@@ -122,7 +122,6 @@ import router from "@/router";
 import { DashboardItem } from "@/types/dashboard";
 import { saveFile, readFile } from "@/utils/file";
 import { EntityType } from "./data";
-import { findLastKey } from "lodash";
 
 /*global Nullable*/
 const { t } = useI18n();
@@ -134,17 +133,7 @@ const loading = ref<boolean>(false);
 const multipleTableRef = ref<InstanceType<typeof ElTable>>();
 const multipleSelection = ref<DashboardItem[]>([]);
 const dashboardFile = ref<Nullable<HTMLDivElement>>(null);
-//  # - os-linux
-//  # - k8s
-//  # - general(agent-installed)
-//  # - faas
-//  # - mesh
-//  # - mesh-cp
-//  # - mesh-dp
-//  # - database
-//  # - cache
-//  # - browser
-//  # - skywalking
+
 appStore.setPageTitle("Dashboard List");
 const handleSelectionChange = (val: DashboardItem[]) => {
   multipleSelection.value = val;
diff --git a/src/views/dashboard/configuration/Topology.vue 
b/src/views/dashboard/configuration/Topology.vue
index cfd87a7..e9b2800 100644
--- a/src/views/dashboard/configuration/Topology.vue
+++ b/src/views/dashboard/configuration/Topology.vue
@@ -4,17 +4,32 @@ this work for additional information regarding copyright 
ownership.
 The ASF licenses this file to You under the Apache License, Version 2.0
 (the "License"); you may not use this file except in compliance with
 the License.  You may obtain a copy of the License at
-
   http://www.apache.org/licenses/LICENSE-2.0
-
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License. -->
 <template>
-  <WidgetOptions />
-  <StyleOptions />
+  <div class="item">
+    <span class="label">{{ t("showDepth") }}</span>
+    <el-switch
+      v-model="showDepth"
+      active-text="Yes"
+      inactive-text="No"
+      @change="changeConfig({ showDepth })"
+    />
+  </div>
+  <div class="item" v-show="showDepth">
+    <span class="label">{{ t("defaultDepth") }}</span>
+    <Selector
+      class="input"
+      size="small"
+      :value="depth"
+      :options="DepthList"
+      @change="changeDepth($event)"
+    />
+  </div>
   <div class="footer">
     <el-button size="small">
       {{ t("cancel") }}
@@ -25,18 +40,34 @@ limitations under the License. -->
   </div>
 </template>
 <script lang="ts" setup>
+import { ref } from "vue";
 import { useI18n } from "vue-i18n";
-import WidgetOptions from "./components/WidgetOptions.vue";
-import StyleOptions from "./topology/StyleOptions.vue";
 import { useDashboardStore } from "@/store/modules/dashboard";
+import { DepthList } from "../data";
+import { Option } from "@/types/app";
 
 const { t } = useI18n();
 const dashboardStore = useDashboardStore();
+const { selectedGrid } = dashboardStore;
+const showDepth = ref<boolean>(selectedGrid.graph.showDepth);
+const depth = ref<number>(selectedGrid.graph.depth || 2);
 
 function applyConfig() {
   dashboardStore.setConfigs(dashboardStore.selectedGrid);
   dashboardStore.setConfigPanel(false);
 }
+function changeConfig(param: { [key: string]: unknown }) {
+  const { selectedGrid } = dashboardStore;
+  const graph = {
+    ...selectedGrid.graph,
+    ...param,
+  };
+  dashboardStore.selectWidget({ ...selectedGrid, graph });
+}
+function changeDepth(opt: Option[] | any) {
+  const val = opt[0].value;
+  changeConfig({ depth: val });
+}
 </script>
 <style lang="scss" scoped>
 .footer {
@@ -49,4 +80,15 @@ function applyConfig() {
   width: 100%;
   background-color: #fff;
 }
+
+.label {
+  font-size: 13px;
+  font-weight: 500;
+  display: block;
+  margin-bottom: 5px;
+}
+
+.item {
+  margin: 10px 0;
+}
 </style>
diff --git a/src/views/dashboard/configuration/Widget.vue 
b/src/views/dashboard/configuration/Widget.vue
index 28ada4c..dd21b36 100644
--- a/src/views/dashboard/configuration/Widget.vue
+++ b/src/views/dashboard/configuration/Widget.vue
@@ -82,7 +82,7 @@ import { useAppStoreWithOut } from "@/store/modules/app";
 import { Option } from "@/types/app";
 import graphs from "../graphs";
 import configs from "./widget/graph-styles";
-import WidgetOptions from "./components/WidgetOptions.vue";
+import WidgetOptions from "./widget/WidgetOptions.vue";
 import StandardOptions from "./widget/StandardOptions.vue";
 import MetricOptions from "./widget/MetricOptions.vue";
 
diff --git a/src/views/dashboard/configuration/topology/StyleOptions.vue 
b/src/views/dashboard/configuration/topology/StyleOptions.vue
deleted file mode 100644
index 52f73ea..0000000
--- a/src/views/dashboard/configuration/topology/StyleOptions.vue
+++ /dev/null
@@ -1,151 +0,0 @@
-<!-- Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License. -->
-<template>
-  <div class="item">
-    <span class="label">{{ t("backgroundColors") }}</span>
-    <Selector
-      :value="backgroundColor"
-      :options="colors"
-      size="small"
-      placeholder="Select a color"
-      class="input"
-      @change="changeConfig({ backgroundColor: $event[0].value })"
-    />
-  </div>
-  <div class="item">
-    <span class="label">{{ t("fontSize") }}</span>
-    <el-slider
-      class="slider"
-      v-model="fontSize"
-      show-input
-      input-size="small"
-      :min="12"
-      :max="30"
-      :step="1"
-      @change="changeConfig({ fontSize })"
-    />
-  </div>
-  <div class="item">
-    <span class="label">{{ t("fontColors") }}</span>
-    <Selector
-      :value="fontColor"
-      :options="colors"
-      size="small"
-      placeholder="Select a color"
-      class="input"
-      @change="changeConfig({ fontColor: $event[0].value })"
-    />
-  </div>
-  <div class="item">
-    <span class="label">{{ t("iconTheme") }}</span>
-    <el-switch
-      v-model="iconTheme"
-      active-text="Light"
-      inactive-text="Dark"
-      @change="changeConfig({ iconTheme })"
-    />
-  </div>
-  <div class="item">
-    <span class="label">{{ t("content") }}</span>
-    <el-input
-      class="input"
-      v-model="content"
-      size="small"
-      @change="changeConfig({ content })"
-    />
-  </div>
-  <div class="item">
-    <span class="label">{{ t("showDepth") }}</span>
-    <el-switch
-      v-model="showDepth"
-      active-text="Yes"
-      inactive-text="No"
-      @change="changeConfig({ showDepth })"
-    />
-  </div>
-  <div class="item" v-show="showDepth">
-    <span class="label">{{ t("defaultDepth") }}</span>
-    <Selector
-      class="input"
-      size="small"
-      :value="depth"
-      :options="DepthList"
-      @change="changeDepth($event)"
-    />
-  </div>
-</template>
-<script lang="ts" setup>
-import { useI18n } from "vue-i18n";
-import { ref } from "vue";
-import { useDashboardStore } from "@/store/modules/dashboard";
-import { DepthList } from "../../data";
-import { Option } from "@/types/app";
-
-const { t } = useI18n();
-const dashboardStore = useDashboardStore();
-const { selectedGrid } = dashboardStore;
-const iconTheme = ref(selectedGrid.graph.iconTheme || true);
-const backgroundColor = ref(selectedGrid.graph.backgroundColor || "green");
-const fontColor = ref(selectedGrid.graph.fontColor || "white");
-const content = ref<string>(selectedGrid.graph.content);
-const fontSize = ref<number>(selectedGrid.graph.fontSize);
-const depth = ref<string>(selectedGrid.graph.depth || "2");
-const showDepth = ref<boolean>(selectedGrid.graph.showDepth);
-const colors = [
-  {
-    label: "Green",
-    value: "green",
-  },
-  { label: "Blue", value: "blue" },
-  { label: "Red", value: "red" },
-  { label: "Grey", value: "grey" },
-  { label: "White", value: "white" },
-  { label: "Black", value: "black" },
-  { label: "Orange", value: "orange" },
-];
-function changeConfig(param: { [key: string]: unknown }) {
-  const { selectedGrid } = dashboardStore;
-  const graph = {
-    ...selectedGrid.graph,
-    ...param,
-  };
-  dashboardStore.selectWidget({ ...selectedGrid, graph });
-}
-function changeDepth(opt: Option[]) {
-  const val = opt[0].value;
-  changeConfig({ depth: val });
-}
-</script>
-<style lang="scss" scoped>
-.slider {
-  width: 500px;
-  margin-top: -3px;
-}
-
-.label {
-  font-size: 13px;
-  font-weight: 500;
-  display: block;
-  margin-bottom: 5px;
-}
-
-.input {
-  width: 500px;
-}
-
-.item {
-  margin-bottom: 10px;
-}
-</style>
diff --git a/src/views/dashboard/configuration/components/WidgetOptions.vue 
b/src/views/dashboard/configuration/widget/WidgetOptions.vue
similarity index 100%
rename from src/views/dashboard/configuration/components/WidgetOptions.vue
rename to src/views/dashboard/configuration/widget/WidgetOptions.vue
diff --git a/src/views/dashboard/controls/Tab.vue 
b/src/views/dashboard/controls/Tab.vue
index 90f3534..bb77acd 100644
--- a/src/views/dashboard/controls/Tab.vue
+++ b/src/views/dashboard/controls/Tab.vue
@@ -97,6 +97,7 @@ limitations under the License. -->
         :key="item.i"
         @click="clickTabGrid($event, item)"
         :class="{ active: activeTabWidget === item.i }"
+        drag-ignore-from="svg.d3-trace-tree, .dragger, .micro-topo-chart"
       >
         <component
           :is="item.type"
diff --git a/src/views/dashboard/controls/Topology.vue 
b/src/views/dashboard/controls/Topology.vue
index 56bd796..27a7bdd 100644
--- a/src/views/dashboard/controls/Topology.vue
+++ b/src/views/dashboard/controls/Topology.vue
@@ -13,58 +13,28 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.
 See the License for the specific language governing permissions and
 limitations under the License. -->
 <template>
-  <div class="topology">
-    <div class="header flex-h">
-      <div>{{ data.widget?.title || "" }}</div>
-      <div>
-        <el-tooltip :content="data.widget?.tips">
+  <div class="topology flex-v">
+    <div class="operation">
+      <el-popover
+        placement="bottom"
+        trigger="click"
+        :width="100"
+        v-if="routeParams.entity"
+      >
+        <template #reference>
           <span>
-            <Icon
-              iconName="info_outline"
-              size="sm"
-              class="operation"
-              v-show="data.widget?.tips"
-            />
+            <Icon iconName="ellipsis_v" size="middle" />
           </span>
-        </el-tooltip>
-        <el-popover
-          placement="bottom"
-          trigger="click"
-          :width="100"
-          v-if="routeParams.entity"
-        >
-          <template #reference>
-            <span>
-              <Icon iconName="ellipsis_v" size="middle" class="operation" />
-            </span>
-          </template>
-          <div class="tools" @click="editConfig">
-            <span>{{ t("edit") }}</span>
-          </div>
-          <div class="tools" @click="removeTopo">
-            <span>{{ t("delete") }}</span>
-          </div>
-        </el-popover>
-      </div>
-    </div>
-    <div
-      class="body"
-      @click="ViewTopology"
-      :style="{ backgroundColor: Colors[data.graph.backgroundColor] }"
-    >
-      <Icon
-        :iconName="data.graph.iconTheme ? 'topology-light' : 'topology-dark'"
-        size="middle"
-      />
-      <div
-        :style="{
-          color: Colors[data.graph.fontColor],
-          fontSize: data.graph.fontSize + 'px',
-        }"
-      >
-        {{ data.graph.content }}
-      </div>
+        </template>
+        <div class="tools" @click="editConfig">
+          <span>{{ t("edit") }}</span>
+        </div>
+        <div class="tools" @click="removeTopo">
+          <span>{{ t("delete") }}</span>
+        </div>
+      </el-popover>
     </div>
+    <Topology :config="props.data" />
   </div>
 </template>
 <script lang="ts" setup>
@@ -72,7 +42,8 @@ import type { PropType } from "vue";
 import { useRoute } from "vue-router";
 import { useI18n } from "vue-i18n";
 import { useDashboardStore } from "@/store/modules/dashboard";
-import { Colors } from "../data";
+import Topology from "../related/topology/Index.vue";
+
 /*global defineProps */
 const props = defineProps({
   data: {
@@ -85,32 +56,27 @@ const { t } = useI18n();
 const routeParams = useRoute().params;
 const dashboardStore = useDashboardStore();
 
+function removeTopo() {
+  dashboardStore.removeControls(props.data);
+}
 function editConfig() {
   dashboardStore.setConfigPanel(true);
   dashboardStore.selectWidget(props.data);
 }
-function ViewTopology() {
-  dashboardStore.setTopology(true);
-}
-function removeTopo() {
-  dashboardStore.removeControls(props.data);
-}
 </script>
 <style lang="scss" scoped>
 .topology {
-  font-size: 12px;
-  height: 100%;
-}
-
-.header {
-  height: 30px;
-  padding: 5px;
+  background-color: #333840;
   width: 100%;
-  border-bottom: 1px solid #eee;
-  justify-content: space-between;
+  height: 100%;
+  font-size: 12px;
+  position: relative;
 }
 
 .operation {
+  position: absolute;
+  top: 5px;
+  right: 3px;
   cursor: pointer;
 }
 
@@ -127,19 +93,6 @@ function removeTopo() {
   }
 }
 
-.body {
-  text-align: center;
-  width: 100%;
-  height: calc(100% - 30px);
-  cursor: pointer;
-  box-sizing: border-box;
-  color: #333;
-  display: -webkit-box;
-  -webkit-box-orient: horizontal;
-  -webkit-box-pack: center;
-  -webkit-box-align: center;
-}
-
 .no-data {
   font-size: 14px;
   color: #888;
diff --git a/src/views/dashboard/controls/Widget.vue 
b/src/views/dashboard/controls/Widget.vue
index 3a21969..e183824 100644
--- a/src/views/dashboard/controls/Widget.vue
+++ b/src/views/dashboard/controls/Widget.vue
@@ -108,11 +108,7 @@ export default defineComponent({
     const dashboardStore = useDashboardStore();
     const selectorStore = useSelectorStore();
 
-    if (
-      dashboardStore.entity === EntityType[1].value ||
-      props.needQuery ||
-      !dashboardStore.currentDashboard.id
-    ) {
+    if (props.needQuery || !dashboardStore.currentDashboard.id) {
       queryMetrics();
     }
 
@@ -165,11 +161,7 @@ export default defineComponent({
       }
     );
     watch(
-      () => [
-        selectorStore.currentService,
-        selectorStore.currentDestService,
-        appStore.durationTime,
-      ],
+      () => [selectorStore.currentService, selectorStore.currentDestService],
       () => {
         if (
           dashboardStore.entity === EntityType[0].value ||
@@ -188,6 +180,14 @@ export default defineComponent({
         queryMetrics();
       }
     );
+    watch(
+      () => appStore.durationTime,
+      () => {
+        if (dashboardStore.entity === EntityType[1].value) {
+          queryMetrics();
+        }
+      }
+    );
 
     return {
       state,
diff --git a/src/views/dashboard/data.ts b/src/views/dashboard/data.ts
index 5be86e6..da2d671 100644
--- a/src/views/dashboard/data.ts
+++ b/src/views/dashboard/data.ts
@@ -186,7 +186,6 @@ export const ServiceTools = [
 export const InstanceTools = [
   { name: "playlist_add", content: "Add Widget", id: "addWidget" },
   { name: "all_inbox", content: "Add Tab", id: "addTab" },
-  { name: "device_hub", content: "Add Topology", id: "addTopology" },
   { name: "merge", content: "Add Trace", id: "addTrace" },
   { name: "assignment", content: "Add Log", id: "addLog" },
   { name: "save", content: "Apply", id: "apply" },
@@ -229,19 +228,10 @@ export enum LegendOpt {
   VALUE = "value",
   CONDITION = "condition",
 }
-export const DepthList = ["1", "2", "3", "4", "5"].map((item: string) => ({
+export const DepthList = [1, 2, 3, 4, 5].map((item: number) => ({
   value: item,
   label: item,
 }));
-export const Colors: any = {
-  green: "#67C23A",
-  blue: "#409EFF",
-  red: "#F56C6C",
-  grey: "#909399",
-  white: "#fff",
-  black: "#000",
-  orange: "#E6A23C",
-};
 export const Status = [
   { label: "All", value: "ALL" },
   { label: "Success", value: "SUCCESS" },
diff --git a/src/views/dashboard/graphs/EndpointList.vue 
b/src/views/dashboard/graphs/EndpointList.vue
index 38b01fc..27fbd7e 100644
--- a/src/views/dashboard/graphs/EndpointList.vue
+++ b/src/views/dashboard/graphs/EndpointList.vue
@@ -35,7 +35,11 @@ limitations under the License. -->
           <template #default="scope">
             <router-link
               class="link"
-              
:to="`/dashboard/${dashboardStore.layerId}/${EntityType[2].value}/${selectorStore.currentService.id}/${scope.row.id}/${config.dashboardName}`"
+              :to="`/dashboard/${dashboardStore.layerId}/${
+                EntityType[2].value
+              }/${selectorStore.currentService.id}/${
+                scope.row.id
+              }/${config.dashboardName.split(' ').join('-')}`"
               :style="{ fontSize: `${config.fontSize}px` }"
             >
               {{ scope.row.label }}
diff --git a/src/views/dashboard/graphs/InstanceList.vue 
b/src/views/dashboard/graphs/InstanceList.vue
index 4d844b6..06e7a23 100644
--- a/src/views/dashboard/graphs/InstanceList.vue
+++ b/src/views/dashboard/graphs/InstanceList.vue
@@ -35,7 +35,11 @@ limitations under the License. -->
           <template #default="scope">
             <router-link
               class="link"
-              
:to="`/dashboard/${dashboardStore.layerId}/${EntityType[3].value}/${selectorStore.currentService.id}/${scope.row.id}/${config.dashboardName}`"
+              :to="`/dashboard/${dashboardStore.layerId}/${
+                EntityType[3].value
+              }/${selectorStore.currentService.id}/${
+                scope.row.id
+              }/${config.dashboardName.split(' ').join('-')}`"
               :style="{ fontSize: `${config.fontSize}px` }"
             >
               {{ scope.row.label }}
diff --git a/src/views/dashboard/panel/Layout.vue 
b/src/views/dashboard/panel/Layout.vue
index 4188e49..f740d66 100644
--- a/src/views/dashboard/panel/Layout.vue
+++ b/src/views/dashboard/panel/Layout.vue
@@ -31,7 +31,7 @@ limitations under the License. -->
       :key="item.i"
       @click="clickGrid(item)"
       :class="{ active: dashboardStore.activedGridItem === item.i }"
-      drag-ignore-from="svg.d3-trace-tree, .dragger"
+      drag-ignore-from="svg.d3-trace-tree, .dragger, .micro-topo-chart"
     >
       <component :is="item.type" :data="item" />
     </grid-item>
diff --git a/src/views/dashboard/related/log/Header.vue 
b/src/views/dashboard/related/log/Header.vue
index 5051aa9..71d6d92 100644
--- a/src/views/dashboard/related/log/Header.vue
+++ b/src/views/dashboard/related/log/Header.vue
@@ -299,6 +299,14 @@ watch(
     init();
   }
 );
+watch(
+  () => appStore.durationTime,
+  () => {
+    if (dashboardStore.entity === EntityType[1].value) {
+      init();
+    }
+  }
+);
 </script>
 <style lang="scss" scoped>
 .inputs {
diff --git a/src/views/dashboard/related/profile/Header.vue 
b/src/views/dashboard/related/profile/Header.vue
index 80fc323..6fd3333 100644
--- a/src/views/dashboard/related/profile/Header.vue
+++ b/src/views/dashboard/related/profile/Header.vue
@@ -56,9 +56,14 @@ import { useProfileStore } from "@/store/modules/profile";
 import { useSelectorStore } from "@/store/modules/selectors";
 import { ElMessage } from "element-plus";
 import NewTask from "./components/NewTask.vue";
+import { useDashboardStore } from "@/store/modules/dashboard";
+import { useAppStoreWithOut } from "@/store/modules/app";
+import { EntityType } from "../../data";
 
 const profileStore = useProfileStore();
+const appStore = useAppStoreWithOut();
 const selectorStore = useSelectorStore();
+const dashboardStore = useDashboardStore();
 const { t } = useI18n();
 // const service = ref<any>({});
 const endpointName = ref<string>("");
@@ -104,6 +109,14 @@ watch(
     searchTasks();
   }
 );
+watch(
+  () => appStore.durationTime,
+  () => {
+    if (dashboardStore.entity === EntityType[1].value) {
+      searchTasks();
+    }
+  }
+);
 </script>
 <style lang="scss" scoped>
 .header {
diff --git a/src/views/dashboard/related/topology/Index.vue 
b/src/views/dashboard/related/topology/Index.vue
index 83ef190..087e834 100644
--- a/src/views/dashboard/related/topology/Index.vue
+++ b/src/views/dashboard/related/topology/Index.vue
@@ -13,18 +13,26 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.
 See the License for the specific language governing permissions and
 limitations under the License. -->
 <template>
-  <PodTopology v-if="isSankey" />
-  <Graph v-else />
+  <PodTopology :config="config" v-if="isSankey" />
+  <Graph :config="config" v-else />
 </template>
 <script lang="ts" setup>
+import type { PropType } from "vue";
 import { ref } from "vue";
 import Graph from "./components/Graph.vue";
 import PodTopology from "./components/PodTopology.vue";
 import { EntityType } from "../../data";
 import { useDashboardStore } from "@/store/modules/dashboard";
 
+/*global defineProps */
+defineProps({
+  config: {
+    type: Object as PropType<any>,
+    default: () => ({ graph: {} }),
+  },
+});
 const dashboardStore = useDashboardStore();
 const isSankey = ref<boolean>(
-  [EntityType[2].value, EntityType[4].value].includes(dashboardStore.entity)
+  [EntityType[2].value, EntityType[3].value].includes(dashboardStore.entity)
 );
 </script>
diff --git a/src/views/dashboard/related/topology/components/Graph.vue 
b/src/views/dashboard/related/topology/components/Graph.vue
index d62607d..2058640 100644
--- a/src/views/dashboard/related/topology/components/Graph.vue
+++ b/src/views/dashboard/related/topology/components/Graph.vue
@@ -17,13 +17,14 @@ limitations under the License. -->
     ref="chart"
     class="micro-topo-chart"
     v-loading="loading"
+    element-loading-background="rgba(0, 0, 0, 0)"
     :style="`height: ${height}px`"
   >
     <div class="setting" v-show="showSetting">
       <Settings @update="updateSettings" @updateNodes="freshNodes" />
     </div>
     <div class="tool">
-      <span v-show="dashboardStore.selectedGrid.showDepth">
+      <span v-show="config.graph.showDepth">
         <span class="label">{{ t("currentDepth") }}</span>
         <Selector
           class="inputs"
@@ -63,7 +64,8 @@ limitations under the License. -->
   </div>
 </template>
 <script lang="ts" setup>
-import { ref, onMounted, onBeforeUnmount, reactive } from "vue";
+import type { PropType } from "vue";
+import { ref, onMounted, onBeforeUnmount, reactive, watch } from "vue";
 import { useI18n } from "vue-i18n";
 import * as d3 from "d3";
 import d3tip from "d3-tip";
@@ -82,14 +84,22 @@ import { ElMessage } from "element-plus";
 import Settings from "./Settings.vue";
 import { Option } from "@/types/app";
 import { Service } from "@/types/selector";
+import { useAppStoreWithOut } from "@/store/modules/app";
 
-/*global Nullable */
+/*global Nullable, defineProps */
+const props = defineProps({
+  config: {
+    type: Object as PropType<any>,
+    default: () => ({ graph: {} }),
+  },
+});
 const { t } = useI18n();
 const selectorStore = useSelectorStore();
 const topologyStore = useTopologyStore();
 const dashboardStore = useDashboardStore();
-const height = ref<number>(document.body.clientHeight - 90);
-const width = ref<number>(document.body.clientWidth - 40);
+const appStore = useAppStoreWithOut();
+const height = ref<number>(100);
+const width = ref<number>(100);
 const loading = ref<boolean>(false);
 const simulation = ref<any>(null);
 const svg = ref<Nullable<any>>(null);
@@ -110,7 +120,7 @@ const items = ref<
   { id: "inspect", title: "Inspect", func: handleInspect },
   { id: "alarm", title: "Alarm", func: handleGoAlarm },
 ]);
-const depth = ref<string>(dashboardStore.selectedGrid.depth || "2");
+const depth = ref<number>(props.config.graph.depth || 2);
 
 onMounted(async () => {
   loading.value = true;
@@ -119,19 +129,23 @@ onMounted(async () => {
   if (resp && resp.errors) {
     ElMessage.error(resp.errors);
   }
+  const dom = document.querySelector(".topology")?.getBoundingClientRect() || {
+    height: 40,
+    width: 0,
+  };
+  height.value = dom.height - 40;
+  width.value = dom.width;
   window.addEventListener("resize", resize);
-  svg.value = d3
-    .select(chart.value)
-    .append("svg")
-    .attr("class", "topo-svg")
-    .attr("height", height.value)
-    .attr("width", width.value);
+  svg.value = d3.select(chart.value).append("svg").attr("class", "topo-svg");
   await init();
   update();
 });
 async function init() {
   tip.value = (d3tip as any)().attr("class", "d3-tip").offset([-8, 0]);
-  graph.value = svg.value.append("g").attr("class", "topo-svg-graph");
+  graph.value = svg.value
+    .append("g")
+    .attr("class", "topo-svg-graph")
+    .attr("transform", `translate(0, -100)`);
   graph.value.call(tip.value);
   simulation.value = simulationInit(
     d3,
@@ -410,8 +424,8 @@ function setConfig() {
   showSetting.value = !showSetting.value;
 }
 function resize() {
-  height.value = document.body.clientHeight - 90;
-  width.value = document.body.clientWidth - 40;
+  height.value = document.body.clientHeight;
+  width.value = document.body.clientWidth;
   svg.value.attr("height", height.value).attr("width", width.value);
 }
 function updateSettings(config: any) {
@@ -453,7 +467,7 @@ async function freshNodes() {
   update();
 }
 
-async function changeDepth(opt: Option[]) {
+async function changeDepth(opt: Option[] | any) {
   depth.value = opt[0].value;
   await getTopology();
   freshNodes();
@@ -461,17 +475,40 @@ async function changeDepth(opt: Option[]) {
 onBeforeUnmount(() => {
   window.removeEventListener("resize", resize);
 });
+watch(
+  () => [selectorStore.currentService, selectorStore.currentDestService],
+  () => {
+    freshNodes();
+  }
+);
+watch(
+  () => appStore.durationTime,
+  () => {
+    if (dashboardStore.entity === EntityType[1].value) {
+      init();
+    }
+  }
+);
 </script>
 <style lang="scss">
+.topo-svg {
+  width: 100%;
+  height: calc(100% - 5px);
+  cursor: move;
+}
+
 .micro-topo-chart {
   position: relative;
+  height: calc(100% - 30px);
+  overflow: auto;
+  margin-top: 30px;
 
   .setting {
     position: absolute;
-    top: 70px;
-    right: 0;
+    top: 80px;
+    right: 10px;
     width: 400px;
-    height: 700px;
+    height: 600px;
     background-color: #2b3037;
     overflow: auto;
     padding: 0 15px;
@@ -510,8 +547,8 @@ onBeforeUnmount(() => {
 
   .tool {
     position: absolute;
-    top: 22px;
-    right: 0;
+    top: 35px;
+    right: 10px;
   }
 
   .switch-icon {
@@ -524,11 +561,6 @@ onBeforeUnmount(() => {
     border-radius: 3px;
   }
 
-  .topo-svg {
-    display: block;
-    width: 100%;
-  }
-
   .topo-line {
     stroke-linecap: round;
     stroke-width: 3px;
diff --git a/src/views/dashboard/related/topology/components/PodTopology.vue 
b/src/views/dashboard/related/topology/components/PodTopology.vue
index 9ca7e14..e9a36bc 100644
--- a/src/views/dashboard/related/topology/components/PodTopology.vue
+++ b/src/views/dashboard/related/topology/components/PodTopology.vue
@@ -16,8 +16,7 @@ limitations under the License. -->
   <div class="tool">
     <span
       v-show="
-        dashboardStore.entity === EntityType[2].value &&
-        dashboardStore.selectedGrid.showDepth
+        dashboardStore.entity === EntityType[2].value && config.graph.showDepth
       "
     >
       <span class="label">{{ t("currentDepth") }}</span>
@@ -47,6 +46,7 @@ limitations under the License. -->
     class="sankey"
     :style="`height:${height}px;width:${width}px;`"
     v-loading="loading"
+    element-loading-background="rgba(0, 0, 0, 0)"
     @click="handleClick"
   >
     <Sankey @click="selectNodeLink" />
@@ -72,36 +72,47 @@ limitations under the License. -->
   </div>
 </template>
 <script lang="ts" setup>
+import { watch } from "vue";
+import type { PropType } from "vue";
 import { useI18n } from "vue-i18n";
 import { ref, onMounted, reactive } from "vue";
 import { Option } from "@/types/app";
 import { useTopologyStore } from "@/store/modules/topology";
 import { useDashboardStore } from "@/store/modules/dashboard";
 import { useSelectorStore } from "@/store/modules/selectors";
+import { useAppStoreWithOut } from "@/store/modules/app";
 import { EntityType, DepthList } from "../../../data";
 import { ElMessage } from "element-plus";
 import Sankey from "./Sankey.vue";
 import Settings from "./Settings.vue";
 import router from "@/router";
 
+/*global defineProps */
+const props = defineProps({
+  config: {
+    type: Object as PropType<any>,
+    default: () => ({ graph: {} }),
+  },
+});
 const { t } = useI18n();
 const dashboardStore = useDashboardStore();
 const selectorStore = useSelectorStore();
 const topologyStore = useTopologyStore();
+const appStore = useAppStoreWithOut();
 const loading = ref<boolean>(false);
-const height = ref<number>(document.body.clientHeight - 150);
-const width = ref<number>(document.body.clientWidth - 40);
+const height = ref<number>(100);
+const width = ref<number>(100);
 const showSettings = ref<boolean>(false);
 const settings = ref<any>({});
 const operationsPos = reactive<{ x: number; y: number }>({ x: NaN, y: NaN });
-const depth = ref<string>(dashboardStore.selectedGrid.depth || "3");
+const depth = ref<number>(props.config.graph.depth || 3);
 const items = [
   { id: "inspect", title: "Inspect", func: inspect },
   { id: "dashboard", title: "View Dashboard", func: goDashboard },
   { id: "alarm", title: "View Alarm", func: goAlarm },
 ];
 
-onMounted(async () => {
+onMounted(() => {
   loadTopology(selectorStore.currentPod && selectorStore.currentPod.id);
 });
 
@@ -112,6 +123,12 @@ async function loadTopology(id: string) {
   if (resp && resp.errors) {
     ElMessage.error(resp.errors);
   }
+  const dom = document.querySelector(".topology")?.getBoundingClientRect() || {
+    height: 70,
+    width: 5,
+  };
+  height.value = dom.height - 70;
+  width.value = dom.width - 5;
 }
 
 function inspect() {
@@ -176,7 +193,7 @@ function selectNodeLink(d: any) {
   operationsPos.y = d.event.event.clientY;
 }
 
-async function changeDepth(opt: Option[]) {
+async function changeDepth(opt: Option[] | any) {
   depth.value = opt[0].value;
   loadTopology(selectorStore.currentPod.id);
 }
@@ -190,7 +207,7 @@ async function getTopology(id: string) {
         Number(depth.value)
       );
       break;
-    case EntityType[4].value:
+    case EntityType[3].value:
       resp = await topologyStore.getInstanceTopology();
       break;
   }
@@ -202,20 +219,36 @@ function handleClick(event: any) {
     topologyStore.setLink(null);
   }
 }
+watch(
+  () => [selectorStore.currentPod],
+  () => {
+    loadTopology(selectorStore.currentPod.id);
+    topologyStore.setNode(null);
+    topologyStore.setLink(null);
+  }
+);
+watch(
+  () => appStore.durationTime,
+  () => {
+    loadTopology(selectorStore.currentPod.id);
+    topologyStore.setNode(null);
+    topologyStore.setLink(null);
+  }
+);
 </script>
 <style lang="scss" scoped>
 .sankey {
   margin-top: 10px;
-  background-color: #333840;
+  background-color: #333840 !important;
   color: #ddd;
 }
 
 .settings {
   position: absolute;
-  top: 40px;
-  right: 0;
+  top: 60px;
+  right: 10px;
   width: 400px;
-  height: 700px;
+  height: 500px;
   background-color: #2b3037;
   overflow: auto;
   padding: 0 15px;
@@ -228,7 +261,8 @@ function handleClick(event: any) {
 
 .tool {
   text-align: right;
-  margin-top: 10px;
+  margin-top: 40px;
+  margin-right: 10px;
   position: relative;
 }
 
diff --git a/src/views/dashboard/related/topology/utils/legend.ts 
b/src/views/dashboard/related/topology/utils/legend.ts
index a5b0c95..b3550af 100644
--- a/src/views/dashboard/related/topology/utils/legend.ts
+++ b/src/views/dashboard/related/topology/utils/legend.ts
@@ -28,14 +28,14 @@ export default function topoLegend(
       .attr("width", 30)
       .attr("height", 30)
       .attr("x", clientWidth - (item === "CUBEERROR" ? 340 : 440))
-      .attr("y", clientHeight - 50)
+      .attr("y", clientHeight + 50)
       .attr("xlink:href", () =>
         item === "CUBEERROR" ? icons.CUBEERROR : icons.CUBE
       );
     graph
       .append("text")
       .attr("x", clientWidth - (item === "CUBEERROR" ? 310 : 410))
-      .attr("y", clientHeight - 30)
+      .attr("y", clientHeight + 70)
       .text(() => {
         const l = config || [];
         const str = l
diff --git a/src/views/dashboard/related/trace/Filter.vue 
b/src/views/dashboard/related/trace/Filter.vue
index 7c72741..251b7e6 100644
--- a/src/views/dashboard/related/trace/Filter.vue
+++ b/src/views/dashboard/related/trace/Filter.vue
@@ -210,7 +210,16 @@ function updateTags(data: { tagsMap: Array<Option>; 
tagsList: string[] }) {
   tagsMap.value = data.tagsMap;
 }
 watch(
-  () => selectorStore.currentService,
+  () => [selectorStore.currentPod],
+  () => {
+    if (dashboardStore.entity === EntityType[0].value) {
+      return;
+    }
+    init();
+  }
+);
+watch(
+  () => [selectorStore.currentService],
   () => {
     if (dashboardStore.entity !== EntityType[0].value) {
       return;
@@ -218,6 +227,14 @@ watch(
     init();
   }
 );
+watch(
+  () => appStore.durationTime,
+  () => {
+    if (dashboardStore.entity === EntityType[1].value) {
+      init();
+    }
+  }
+);
 </script>
 <style lang="scss" scoped>
 .inputs {

Reply via email to