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 dce1035f feat: implement a breadcrumb component as navigation (#313)
dce1035f is described below

commit dce1035f2eabe7a5575040d6a0b9bc20aa72a6c4
Author: Fine0830 <[email protected]>
AuthorDate: Wed Aug 30 19:06:40 2023 +0800

    feat: implement a breadcrumb component as navigation (#313)
---
 src/layout/components/NavBar.vue                   | 213 +++++++++++++++++++--
 src/store/modules/app.ts                           |   5 -
 src/store/modules/selectors.ts                     |  22 +--
 src/styles/reset.scss                              |   4 +
 src/types/app.d.ts                                 |   2 +
 src/types/components.d.ts                          |   2 +
 src/types/profile.d.ts                             |   4 +-
 src/utils/arrayAlgorithm.ts                        |  31 +++
 src/views/Alarm.vue                                |   4 -
 src/views/Event.vue                                |   5 -
 src/views/Layer.vue                                |   3 -
 src/views/Settings.vue                             |   1 -
 src/views/components/ConditionTags.vue             |   6 +-
 src/views/dashboard/Edit.vue                       |   9 +-
 src/views/dashboard/List.vue                       |   3 -
 src/views/dashboard/New.vue                        |   3 -
 src/views/dashboard/data.ts                        |   1 +
 src/views/dashboard/graphs/InstanceList.vue        |   4 +
 .../related/network-profiling/components/Tasks.vue |   8 +-
 19 files changed, 267 insertions(+), 63 deletions(-)

diff --git a/src/layout/components/NavBar.vue b/src/layout/components/NavBar.vue
index 26a0285e..c2b188dd 100644
--- a/src/layout/components/NavBar.vue
+++ b/src/layout/components/NavBar.vue
@@ -14,7 +14,26 @@ See the License for the specific language governing 
permissions and
 limitations under the License. -->
 <template>
   <div class="nav-bar flex-h">
-    <div class="title">{{ route.name === "ViewWidget" ? "" : 
appStore.pageTitle || pageName }}</div>
+    <el-breadcrumb separator=">" class="title flex-h" v-if="pathNames.length">
+      <el-breadcrumb-item
+        v-for="(path, index) in pathNames"
+        :key="index"
+        :replace="true"
+        :to="{ path: getName(path).path || '' }"
+      >
+        <el-dropdown size="small" placement="bottom" :persistent="false">
+          <span class="cp name">{{ getName(path).name }}</span>
+          <template #dropdown>
+            <el-dropdown-menu>
+              <el-dropdown-item @click="setName(p)" v-for="(p, index) in path" 
:key="index">
+                <span>{{ p.name }}</span>
+              </el-dropdown-item>
+            </el-dropdown-menu>
+          </template>
+        </el-dropdown>
+      </el-breadcrumb-item>
+    </el-breadcrumb>
+    <div class="title" v-else>{{ pageTitle }}</div>
     <div class="app-config">
       <span class="red" v-show="timeRange">{{ t("timeTips") }}</span>
       <TimePicker
@@ -45,20 +64,46 @@ limitations under the License. -->
   import { useI18n } from "vue-i18n";
   import timeFormat from "@/utils/timeFormat";
   import { useAppStoreWithOut } from "@/store/modules/app";
+  import { useDashboardStore } from "@/store/modules/dashboard";
   import { ElMessage } from "element-plus";
+  import { MetricCatalog } from "@/views/dashboard/data";
+  import type { DashboardItem } from "@/types/dashboard";
+  import router from "@/router";
 
   /*global Indexable */
-  const { t } = useI18n();
+  const { t, te } = useI18n();
   const appStore = useAppStoreWithOut();
+  const dashboardStore = useDashboardStore();
   const route = useRoute();
-  const pageName = ref<string>("");
+  const pathNames = ref<{ path?: string; name: string; selected: boolean 
}[][]>([]);
   const timeRange = ref<number>(0);
+  const pageTitle = ref<string>("");
 
   resetDuration();
   getVersion();
-  const setConfig = (value: string) => {
-    pageName.value = value || "";
-  };
+  getNavPaths();
+
+  function getName(list: any[]) {
+    return list.find((d: any) => d.selected) || {};
+  }
+
+  function setName(item: any) {
+    pathNames.value = pathNames.value.map((list: { path?: string; name: 
string; selected: boolean }[]) => {
+      const p = list.find((i: any) => i.entity === item.entity && item.layer 
=== i.layer && i.name === item.name);
+      if (p) {
+        list = list.map((d: any) => {
+          d.selected = false;
+          if (d.entity === item.entity && item.layer === d.layer && d.name === 
item.name) {
+            d.selected = true;
+          }
+          return d;
+        });
+      }
+
+      return list;
+    });
+    item.path && router.push(item.path);
+  }
 
   function handleReload() {
     const gap = appStore.duration.end.getTime() - 
appStore.duration.start.getTime();
@@ -73,19 +118,138 @@ limitations under the License. -->
     }
     appStore.setDuration(timeFormat(val));
   }
-  setConfig(String(route.meta.title));
-  watch(
-    () => route.meta.title,
-    (title: unknown) => {
-      setConfig(String(title));
-    },
-  );
+
+  function getNavPaths() {
+    pathNames.value = [];
+    pageTitle.value = "";
+    const dashboard = dashboardStore.currentDashboard;
+
+    if (!(dashboard && dashboard.name)) {
+      updateNavTitle();
+      return;
+    }
+    const root =
+      dashboardStore.dashboards.filter((d: DashboardItem) => d.isRoot && 
dashboard.layer === d.layer)[0] || {};
+    for (const item of appStore.allMenus) {
+      if (item.subItems && item.subItems.length) {
+        for (const subItem of item.subItems) {
+          if (subItem.layer === root.layer) {
+            root.path = subItem.path;
+          }
+        }
+      } else {
+        if (item.layer === root.layer) {
+          root.path = item.path;
+        }
+      }
+    }
+    pathNames.value.push([{ ...root, selected: true }]);
+    if (dashboard.entity === MetricCatalog.ALL) {
+      return;
+    }
+    if (dashboard.entity === MetricCatalog.SERVICE) {
+      pathNames.value.push([
+        {
+          name: dashboard.name,
+          selected: true,
+        },
+      ]);
+      return;
+    }
+    const serviceDashboards = dashboardStore.dashboards.filter(
+      (d: DashboardItem) => MetricCatalog.SERVICE === d.entity && 
dashboard.layer === d.layer,
+    );
+    if (!serviceDashboards.length) {
+      return;
+    }
+
+    const serviceId = route.params.serviceId;
+    const list = serviceDashboards.map((d: { path: string } & DashboardItem, 
index: number) => {
+      let path = `/dashboard/${d.layer}/${d.entity}/${d.name}`;
+      if (serviceId) {
+        path = `/dashboard/${d.layer}/${d.entity}/${serviceId}/${d.name}`;
+      }
+      const selected = index === 0;
+      return {
+        ...d,
+        path,
+        selected,
+      };
+    });
+    pathNames.value.push(list);
+    const podId = route.params.podId;
+    if (dashboard.entity === MetricCatalog.ENDPOINT_RELATION) {
+      const endpointDashboards = dashboardStore.dashboards.filter(
+        (d: DashboardItem) => MetricCatalog.ENDPOINT === d.entity && 
dashboard.layer === d.layer,
+      );
+      const list = endpointDashboards.map((d: { path: string } & 
DashboardItem, index: number) => {
+        let path = `/dashboard/${d.layer}/${d.entity}/${d.name}`;
+        if (podId) {
+          path = 
`/dashboard/${d.layer}/${d.entity}/${serviceId}/${podId}/${d.name}`;
+        }
+        const selected = index === 0;
+        return {
+          ...d,
+          path,
+          selected,
+        };
+      });
+
+      pathNames.value.push(list);
+    }
+    const destServiceId = route.params.destServiceId;
+    if (dashboard.entity === MetricCatalog.SERVICE_INSTANCE_RELATION) {
+      const serviceRelationDashboards = dashboardStore.dashboards.filter(
+        (d: DashboardItem) => MetricCatalog.SERVICE_RELATION === d.entity && 
dashboard.layer === d.layer,
+      );
+      const list = serviceRelationDashboards.map((d: { path: string } & 
DashboardItem, index: number) => {
+        let path = 
`/dashboard/related/${d.layer}/${d.entity}/${serviceId}/${destServiceId}/${d.name}`;
+        if (destServiceId) {
+          path = 
`/dashboard/related/${d.layer}/${d.entity}/${serviceId}/${destServiceId}/${d.name}`;
+        }
+        const selected = index === 0;
+        return {
+          ...d,
+          path,
+          selected,
+        };
+      });
+      pathNames.value.push(list);
+    }
+    if ([MetricCatalog.Process, 
MetricCatalog.PROCESS_RELATION].includes(dashboard.entity)) {
+      const InstanceDashboards = dashboardStore.dashboards.filter(
+        (d: DashboardItem) => MetricCatalog.SERVICE_INSTANCE === d.entity && 
dashboard.layer === d.layer,
+      );
+      const list = InstanceDashboards.map((d: { path: string } & 
DashboardItem, index: number) => {
+        let path = `/dashboard/${d.layer}/${d.entity}/${d.name}`;
+        if (podId) {
+          path = 
`/dashboard/${d.layer}/${d.entity}/${serviceId}/${podId}/${d.name}`;
+        }
+        const selected = index === 0;
+        return {
+          ...d,
+          path,
+          selected,
+        };
+      });
+
+      pathNames.value.push(list);
+    }
+    pathNames.value.push([
+      {
+        name: dashboard.name,
+        selected: true,
+      },
+    ]);
+  }
+
   async function getVersion() {
     const res = await appStore.fetchVersion();
     if (res.errors) {
       ElMessage.error(res.errors);
     }
   }
+
   function resetDuration() {
     const { duration }: Indexable = route.params;
     if (duration) {
@@ -99,10 +263,22 @@ limitations under the License. -->
       appStore.updateUTC(d.utc);
     }
   }
+
+  function updateNavTitle() {
+    const key = String(route.meta.i18nKey);
+    pageTitle.value = te(key) ? t(key) : String(route.meta.title);
+  }
+
+  watch(
+    () => [dashboardStore.currentDashboard, route.name],
+    () => {
+      getNavPaths();
+    },
+  );
 </script>
 <style lang="scss" scoped>
   .nav-bar {
-    padding: 5px 10px;
+    padding: 5px;
     text-align: left;
     justify-content: space-between;
     background-color: #fafbfc;
@@ -121,10 +297,17 @@ limitations under the License. -->
     font-size: $font-size-normal;
     font-weight: 500;
     height: 28px;
-    line-height: 28px;
   }
 
   .nav-tabs {
     padding: 10px;
   }
+
+  .name {
+    display: inline-block;
+    max-width: 250px;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    overflow: hidden;
+  }
 </style>
diff --git a/src/store/modules/app.ts b/src/store/modules/app.ts
index ede73ea5..994e83a5 100644
--- a/src/store/modules/app.ts
+++ b/src/store/modules/app.ts
@@ -32,7 +32,6 @@ interface AppState {
   eventStack: (() => unknown)[];
   timer: Nullable<TimeoutHandle>;
   autoRefresh: boolean;
-  pageTitle: string;
   version: string;
   isMobile: boolean;
   reloadTimer: Nullable<IntervalHandle>;
@@ -53,7 +52,6 @@ export const appStore = defineStore({
     eventStack: [],
     timer: null,
     autoRefresh: false,
-    pageTitle: "",
     version: "",
     isMobile: false,
     reloadTimer: null,
@@ -146,9 +144,6 @@ export const appStore = defineStore({
     setAutoRefresh(auto: boolean) {
       this.autoRefresh = auto;
     },
-    setPageTitle(title: string) {
-      this.pageTitle = title;
-    },
     runEventStack() {
       if (this.timer) {
         clearTimeout(this.timer);
diff --git a/src/store/modules/selectors.ts b/src/store/modules/selectors.ts
index 74d62399..4101b850 100644
--- a/src/store/modules/selectors.ts
+++ b/src/store/modules/selectors.ts
@@ -184,7 +184,7 @@ export const selectorStore = defineStore({
         if (isRelation) {
           this.currentDestPod = res.data.data.instance || null;
           this.destPods = [res.data.data.instance];
-          return;
+          return res.data;
         }
         this.currentPod = res.data.data.instance || null;
         this.pods = [res.data.data.instance];
@@ -199,16 +199,16 @@ export const selectorStore = defineStore({
       const res: AxiosResponse = await graphql.query("queryEndpoint").params({
         endpointId,
       });
-      if (!res.data.errors) {
-        if (isRelation) {
-          this.currentDestPod = res.data.data.endpoint || null;
-          this.destPods = [res.data.data.endpoint];
-          return;
-        }
-        this.currentPod = res.data.data.endpoint || null;
-        this.pods = [res.data.data.endpoint];
+      if (res.data.errors) {
+        return res.data;
       }
-
+      if (isRelation) {
+        this.currentDestPod = res.data.data.endpoint || null;
+        this.destPods = [res.data.data.endpoint];
+        return res.data;
+      }
+      this.currentPod = res.data.data.endpoint || null;
+      this.pods = [res.data.data.endpoint];
       return res.data;
     },
     async getProcess(processId: string, isRelation?: boolean) {
@@ -222,7 +222,7 @@ export const selectorStore = defineStore({
         if (isRelation) {
           this.currentDestProcess = res.data.data.process || null;
           this.destProcesses = [res.data.data.process];
-          return;
+          return res.data;
         }
         this.currentProcess = res.data.data.process || null;
         this.processes = [res.data.data.process];
diff --git a/src/styles/reset.scss b/src/styles/reset.scss
index c447ec45..84eb228b 100644
--- a/src/styles/reset.scss
+++ b/src/styles/reset.scss
@@ -212,6 +212,10 @@ div.vis-tooltip {
 div:has(> a.menu-title) {
   display: none;
 }
+
+.el-breadcrumb {
+  line-height: 28px;
+}
 .el-input-number .el-input__inner {
   text-align: left !important;
 }
diff --git a/src/types/app.d.ts b/src/types/app.d.ts
index c759cfef..e697ae07 100644
--- a/src/types/app.d.ts
+++ b/src/types/app.d.ts
@@ -44,6 +44,8 @@ export type EventParams = {
   dataType: string;
   value: number | any[];
   color: string;
+  event: Record<string, T>;
+  dataIndex: number;
   event: any;
 };
 
diff --git a/src/types/components.d.ts b/src/types/components.d.ts
index 7e641d1c..9f9c7086 100644
--- a/src/types/components.d.ts
+++ b/src/types/components.d.ts
@@ -6,6 +6,8 @@ import '@vue/runtime-core'
 declare module '@vue/runtime-core' {
   export interface GlobalComponents {
     DateCalendar: typeof import('./../components/DateCalendar.vue')['default']
+    ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
+    ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
     ElButton: typeof import('element-plus/es')['ElButton']
     ElCard: typeof import('element-plus/es')['ElCard']
     ElCollapse: typeof import('element-plus/es')['ElCollapse']
diff --git a/src/types/profile.d.ts b/src/types/profile.d.ts
index c9d64746..ac7fb79f 100644
--- a/src/types/profile.d.ts
+++ b/src/types/profile.d.ts
@@ -55,8 +55,8 @@ export interface SegmentSpan {
   component: string;
   isError: boolean;
   layer: string;
-  tags: any[];
-  logs: any[];
+  tags: Recordable[];
+  logs: Recordable[];
 }
 
 export interface ProfileTaskCreationRequest {
diff --git a/src/utils/arrayAlgorithm.ts b/src/utils/arrayAlgorithm.ts
new file mode 100644
index 00000000..3baab512
--- /dev/null
+++ b/src/utils/arrayAlgorithm.ts
@@ -0,0 +1,31 @@
+/**
+ * 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.
+ */
+
+export function deduplication(arr: any, labels: string[]) {
+  const map = new Map();
+  for (const i of arr) {
+    const key = labels
+      .map((d: string) => {
+        return i[d];
+      })
+      .join("");
+    if (!map.has(i[key])) {
+      map.set(i[key], i);
+    }
+  }
+  return [...map.values()];
+}
diff --git a/src/views/Alarm.vue b/src/views/Alarm.vue
index 236e7e18..e541a8ed 100644
--- a/src/views/Alarm.vue
+++ b/src/views/Alarm.vue
@@ -19,12 +19,8 @@ limitations under the License. -->
   </div>
 </template>
 <script lang="ts" setup>
-  import { useAppStoreWithOut } from "@/store/modules/app";
   import Header from "./alarm/Header.vue";
   import Content from "./alarm/Content.vue";
-
-  const appStore = useAppStoreWithOut();
-  appStore.setPageTitle("Alerting");
 </script>
 <style lang="scss" scoped>
   .alarm {
diff --git a/src/views/Event.vue b/src/views/Event.vue
index 5fcd39df..fade863e 100644
--- a/src/views/Event.vue
+++ b/src/views/Event.vue
@@ -19,13 +19,8 @@ limitations under the License. -->
   </div>
 </template>
 <script lang="ts" setup>
-  import { useAppStoreWithOut } from "@/store/modules/app";
   import Header from "./event/Header.vue";
   import Content from "./event/Content.vue";
-
-  const appStore = useAppStoreWithOut();
-
-  appStore.setPageTitle("Events");
 </script>
 <style lang="scss" scoped>
   .event {
diff --git a/src/views/Layer.vue b/src/views/Layer.vue
index a8260375..3f342343 100644
--- a/src/views/Layer.vue
+++ b/src/views/Layer.vue
@@ -24,11 +24,9 @@ limitations under the License. -->
   import { useDashboardStore } from "@/store/modules/dashboard";
   import Dashboard from "./dashboard/Edit.vue";
   import { useI18n } from "vue-i18n";
-  import { useAppStoreWithOut } from "@/store/modules/app";
 
   const route = useRoute();
   const { t } = useI18n();
-  const appStore = useAppStoreWithOut();
   const dashboardStore = useDashboardStore();
   const layer = ref<string>("GENERAL");
 
@@ -44,7 +42,6 @@ limitations under the License. -->
         d.layer === dashboardStore.layerId && [EntityType[0].value, 
EntityType[1].value].includes(d.entity) && d.isRoot,
     );
     if (!item) {
-      appStore.setPageTitle(dashboardStore.layer);
       dashboardStore.setCurrentDashboard(null);
       dashboardStore.setEntity(EntityType[1].value);
       return;
diff --git a/src/views/Settings.vue b/src/views/Settings.vue
index 00beb5e1..86d71a5f 100644
--- a/src/views/Settings.vue
+++ b/src/views/Settings.vue
@@ -66,7 +66,6 @@ limitations under the License. -->
   const utcHour = ref<number>(appStore.utcHour);
   const utcMin = ref<number>(appStore.utcMin);
 
-  appStore.setPageTitle("Setting");
   const handleReload = () => {
     const gap = appStore.duration.end.getTime() - 
appStore.duration.start.getTime();
     const dates: Date[] = [
diff --git a/src/views/components/ConditionTags.vue 
b/src/views/components/ConditionTags.vue
index f62629c2..9d33d104 100644
--- a/src/views/components/ConditionTags.vue
+++ b/src/views/components/ConditionTags.vue
@@ -71,7 +71,7 @@ limitations under the License. -->
   import { ElMessage } from "element-plus";
   import { useAppStoreWithOut } from "@/store/modules/app";
 
-  /*global defineEmits, defineProps */
+  /*global defineEmits, defineProps, Recordable */
   const emit = defineEmits(["update"]);
   const props = defineProps({
     type: { type: String, default: "TRACE" },
@@ -118,7 +118,7 @@ limitations under the License. -->
     emit("update", { tagsMap, tagsList: tagsList.value });
   }
   async function fetchTagKeys() {
-    let resp: any = {};
+    let resp: Recordable = {};
     if (props.type === "TRACE") {
       resp = await traceStore.getTagKeys();
     } else {
@@ -137,7 +137,7 @@ limitations under the License. -->
 
   async function fetchTagValues() {
     const param = tags.value.split("=")[0];
-    let resp: any = {};
+    let resp: Recordable = {};
     if (props.type === "TRACE") {
       resp = await traceStore.getTagValues(param);
     } else {
diff --git a/src/views/dashboard/Edit.vue b/src/views/dashboard/Edit.vue
index 88cf5c8f..3d6d523a 100644
--- a/src/views/dashboard/Edit.vue
+++ b/src/views/dashboard/Edit.vue
@@ -41,13 +41,12 @@ limitations under the License. -->
   </div>
 </template>
 <script lang="ts">
-  import { ref, defineComponent } from "vue";
+  import { ref, defineComponent, onUnmounted } from "vue";
   import { useI18n } from "vue-i18n";
   import { useRoute } from "vue-router";
   import GridLayout from "./panel/Layout.vue";
   import Tool from "./panel/Tool.vue";
   import { useDashboardStore } from "@/store/modules/dashboard";
-  import { useAppStoreWithOut } from "@/store/modules/app";
   import Configuration from "./configuration";
   import type { LayoutConfig } from "@/types/dashboard";
   import WidgetLink from "./components/WidgetLink.vue";
@@ -57,7 +56,6 @@ limitations under the License. -->
     components: { ...Configuration, GridLayout, Tool, WidgetLink },
     setup() {
       const dashboardStore = useDashboardStore();
-      const appStore = useAppStoreWithOut();
       const { t } = useI18n();
       const p = useRoute().params;
       const layoutKey = ref<string>(`${p.layerId}_${p.entity}_${p.name}`);
@@ -77,7 +75,6 @@ limitations under the License. -->
         const layout: any = c.configuration || {};
 
         dashboardStore.setLayout(setWidgetsID(layout.children || []));
-        appStore.setPageTitle(layout.name);
         if (p.entity) {
           dashboardStore.setCurrentDashboard({
             layer: p.layerId,
@@ -114,6 +111,10 @@ limitations under the License. -->
         }
       }
 
+      onUnmounted(() => {
+        dashboardStore.setCurrentDashboard({});
+      });
+
       return {
         t,
         handleClick,
diff --git a/src/views/dashboard/List.vue b/src/views/dashboard/List.vue
index 89f9eac0..89cfface 100644
--- a/src/views/dashboard/List.vue
+++ b/src/views/dashboard/List.vue
@@ -135,7 +135,6 @@ limitations under the License. -->
   import { useI18n } from "vue-i18n";
   import { ElMessageBox, ElMessage } from "element-plus";
   import { ElTable } from "element-plus";
-  import { useAppStoreWithOut } from "@/store/modules/app";
   import { useDashboardStore } from "@/store/modules/dashboard";
   import router from "@/router";
   import type { DashboardItem, LayoutConfig } from "@/types/dashboard";
@@ -145,7 +144,6 @@ limitations under the License. -->
 
   /*global Nullable*/
   const { t } = useI18n();
-  const appStore = useAppStoreWithOut();
   const dashboardStore = useDashboardStore();
   const pageSize = 20;
   const dashboards = ref<DashboardItem[]>([]);
@@ -157,7 +155,6 @@ limitations under the License. -->
   const multipleSelection = ref<DashboardItem[]>([]);
   const dashboardFile = ref<Nullable<HTMLDivElement>>(null);
 
-  appStore.setPageTitle("Dashboard List");
   const handleSelectionChange = (val: DashboardItem[]) => {
     multipleSelection.value = val;
   };
diff --git a/src/views/dashboard/New.vue b/src/views/dashboard/New.vue
index 842232bf..d25f70fb 100644
--- a/src/views/dashboard/New.vue
+++ b/src/views/dashboard/New.vue
@@ -53,12 +53,9 @@ limitations under the License. -->
   import { useSelectorStore } from "@/store/modules/selectors";
   import { EntityType } from "./data";
   import { ElMessage } from "element-plus";
-  import { useAppStoreWithOut } from "@/store/modules/app";
   import { useDashboardStore } from "@/store/modules/dashboard";
 
-  const appStore = useAppStoreWithOut();
   const dashboardStore = useDashboardStore();
-  appStore.setPageTitle("Dashboard New");
   const { t } = useI18n();
   const selectorStore = useSelectorStore();
   const states = reactive({
diff --git a/src/views/dashboard/data.ts b/src/views/dashboard/data.ts
index 28c0affb..f30b5c15 100644
--- a/src/views/dashboard/data.ts
+++ b/src/views/dashboard/data.ts
@@ -161,6 +161,7 @@ export enum MetricCatalog {
   SERVICE_RELATION = "ServiceRelation",
   SERVICE_INSTANCE_RELATION = "ServiceInstanceRelation",
   ENDPOINT_RELATION = "EndpointRelation",
+  Process = "Process",
   PROCESS_RELATION = "ProcessRelation",
 }
 export const EntityType = [
diff --git a/src/views/dashboard/graphs/InstanceList.vue 
b/src/views/dashboard/graphs/InstanceList.vue
index d04d47ff..2e3b68cc 100644
--- a/src/views/dashboard/graphs/InstanceList.vue
+++ b/src/views/dashboard/graphs/InstanceList.vue
@@ -294,4 +294,8 @@ limitations under the License. -->
     max-height: 400px;
     overflow: auto;
   }
+
+  .link {
+    color: $active-color;
+  }
 </style>
diff --git a/src/views/dashboard/related/network-profiling/components/Tasks.vue 
b/src/views/dashboard/related/network-profiling/components/Tasks.vue
index 598350cc..a873a636 100644
--- a/src/views/dashboard/related/network-profiling/components/Tasks.vue
+++ b/src/views/dashboard/related/network-profiling/components/Tasks.vue
@@ -216,7 +216,7 @@ limitations under the License. -->
     width: 330px;
     height: calc(100% - 10px);
     overflow: auto;
-    border-right: 1px solid rgba(0, 0, 0, 0.1);
+    border-right: 1px solid rgb(0 0 0 / 10%);
   }
 
   .item span {
@@ -225,7 +225,7 @@ limitations under the License. -->
 
   .profile-td {
     padding: 10px 5px 10px 10px;
-    border-bottom: 1px solid rgba(0, 0, 0, 0.07);
+    border-bottom: 1px solid rgb(0 0 0 / 7%);
 
     &.selected {
       background-color: #ededed;
@@ -253,13 +253,13 @@ limitations under the License. -->
 
   .profile-tr {
     &:hover {
-      background-color: rgba(0, 0, 0, 0.04);
+      background-color: rgb(0 0 0 / 4%);
     }
   }
 
   .profile-t-tool {
     padding: 10px 5px 10px 10px;
-    border-bottom: 1px solid rgba(0, 0, 0, 0.07);
+    border-bottom: 1px solid rgb(0 0 0 / 7%);
     background: #f3f4f9;
     width: 100%;
   }

Reply via email to