feat: set links for topology

This commit is contained in:
Qiuxia Fan 2022-02-12 15:33:18 +08:00
parent d7c42fe2cb
commit 078f1bc042
8 changed files with 139 additions and 54 deletions

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<template> <template>
<el-select <el-select
:size="size" size
v-model="selected" v-model="selected"
:placeholder="placeholder" :placeholder="placeholder"
@change="changeSelected" @change="changeSelected"
@ -55,7 +55,7 @@ const props = defineProps({
type: [Array, String] as PropType<string[] | string>, type: [Array, String] as PropType<string[] | string>,
default: () => [], default: () => [],
}, },
size: { type: String, default: "default" }, size: { type: String },
placeholder: { type: String, default: "Select a option" }, placeholder: { type: String, default: "Select a option" },
borderRadius: { type: Number, default: 3 }, borderRadius: { type: Number, default: 3 },
multiple: { type: Boolean, default: false }, multiple: { type: Boolean, default: false },

43
src/router/alarm.ts Normal file
View File

@ -0,0 +1,43 @@
/**
* 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.
*/
import { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
export const routesAlarm: Array<RouteRecordRaw> = [
{
path: "",
name: "Alarm",
meta: {
title: "alarm",
icon: "spam",
hasGroup: false,
exact: true,
},
component: Layout,
children: [
{
path: "/alarm",
name: "Alarm",
meta: {
title: "alarmList",
exact: false,
},
component: () => import("@/views/Log.vue"),
},
],
},
];

View File

@ -60,7 +60,7 @@ export const routesDashboard: Array<RouteRecordRaw> = [
{ {
path: "/dashboard/:layerId/:entity/:serviceId/:name", path: "/dashboard/:layerId/:entity/:serviceId/:name",
component: () => import("@/views/dashboard/Edit.vue"), component: () => import("@/views/dashboard/Edit.vue"),
name: "CreateService", name: "View",
meta: { meta: {
title: "dashboardEdit", title: "dashboardEdit",
exact: false, exact: false,
@ -70,7 +70,7 @@ export const routesDashboard: Array<RouteRecordRaw> = [
{ {
path: "/dashboard/:layerId/:entity/:serviceId/:destServiceId/:name", path: "/dashboard/:layerId/:entity/:serviceId/:destServiceId/:name",
component: () => import("@/views/dashboard/Edit.vue"), component: () => import("@/views/dashboard/Edit.vue"),
name: "CreateServiceRelation", name: "ViewServiceRelation",
meta: { meta: {
title: "dashboardEdit", title: "dashboardEdit",
exact: false, exact: false,

View File

@ -152,6 +152,7 @@ export const EntityType = [
}, },
{ value: "EndpointRelation", label: "Endpoint Relation", key: 4 }, { value: "EndpointRelation", label: "Endpoint Relation", key: 4 },
]; ];
export const hasTopology = ["All", "Service", "ServiceRelation", "Endpoint"];
export const TableEntity: any = { export const TableEntity: any = {
InstanceList: EntityType[3].value, InstanceList: EntityType[3].value,
EndpointList: EntityType[2].value, EndpointList: EntityType[2].value,

View File

@ -69,13 +69,20 @@ limitations under the License. -->
</div> </div>
<div class="tool-icons"> <div class="tool-icons">
<span <span
class="icon-btn"
@click="clickIcons(t)" @click="clickIcons(t)"
v-for="(t, index) in ToolIcons" v-for="(t, index) in ToolIcons"
:key="index" :key="index"
:title="t.content" :title="t.content"
> >
<Icon size="sm" :iconName="t.name" /> <Icon
class="icon-btn"
size="sm"
:iconName="t.name"
v-if="
t.id !== 'topology' ||
(t.id === 'topology' && hasTopology.includes(dashboardStore.entity))
"
/>
</span> </span>
</div> </div>
</div> </div>
@ -86,7 +93,7 @@ import { reactive, watch } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import { EntityType, ToolIcons } from "../data"; import { EntityType, ToolIcons, hasTopology } from "../data";
import { useSelectorStore } from "@/store/modules/selectors"; import { useSelectorStore } from "@/store/modules/selectors";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { Option } from "@/types/app"; import { Option } from "@/types/app";
@ -288,7 +295,7 @@ watch(
.icon-btn { .icon-btn {
display: inline-block; display: inline-block;
padding: 0 5px 2px 5px; padding: 3px;
text-align: center; text-align: center;
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 3px; border-radius: 3px;

View File

@ -39,7 +39,7 @@ import zoom from "./utils/zoom";
import { simulationInit, simulationSkip } from "./utils/simulation"; import { simulationInit, simulationSkip } from "./utils/simulation";
import nodeElement from "./utils/nodeElement"; import nodeElement from "./utils/nodeElement";
import { linkElement, anchorElement, arrowMarker } from "./utils/linkElement"; import { linkElement, anchorElement, arrowMarker } from "./utils/linkElement";
// import tool from "./utils/tool"; import tool from "./utils/tool";
import topoLegend from "./utils/legend"; import topoLegend from "./utils/legend";
import { Node, Call } from "@/types/topology"; import { Node, Call } from "@/types/topology";
import { useTopologyStore } from "@/store/modules/topology"; import { useTopologyStore } from "@/store/modules/topology";
@ -48,7 +48,6 @@ import { EntityType } from "../../data";
import router from "@/router"; import router from "@/router";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import Settings from "./Settings.vue"; import Settings from "./Settings.vue";
// import { Option } from "@/types/app";
/*global Nullable */ /*global Nullable */
const { t } = useI18n(); const { t } = useI18n();
@ -99,48 +98,23 @@ onMounted(async () => {
anchor.value = graph.value.append("g").selectAll(".topo-line-anchor"); anchor.value = graph.value.append("g").selectAll(".topo-line-anchor");
arrow.value = graph.value.append("g").selectAll(".topo-line-arrow"); arrow.value = graph.value.append("g").selectAll(".topo-line-arrow");
svg.value.call(zoom(d3, graph.value)); svg.value.call(zoom(d3, graph.value));
// tools.value = tool(graph.value, [ tools.value = tool(graph.value, tip.value, [
// { icon: "API", click: handleGoEndpoint }, { icon: "API", title: "Endpoint", func: handleGoEndpoint },
// { icon: "INSTANCE", click: handleGoInstance }, { icon: "INSTANCE", title: "Instance", func: handleGoInstance },
// { icon: "TRACE", click: handleGoTrace }, { icon: "TRACE", title: "Dashboard", func: handleGoDashboard },
// { icon: "ALARM", click: handleGoAlarm }, { icon: "ALARM", title: "Alarm", func: handleGoAlarm },
// { icon: "ENDPOINT", click: handleGoEndpointDependency }, { icon: "" },
// { icon: "" }, { icon: "" },
// ]); ]);
// legend // legend
legend.value = graph.value.append("g").attr("class", "topo-legend"); legend.value = graph.value.append("g").attr("class", "topo-legend");
topoLegend(legend.value, height.value, width.value); topoLegend(legend.value, height.value, width.value);
svg.value.on("click", (event: any) => { svg.value.on("click", (event: any) => {
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
tools.value.attr("style", "display: none");
}); });
}); });
async function getTopology() {
let resp;
switch (dashboardStore.entity) {
case EntityType[0].value:
resp = await topologyStore.getServiceTopology();
break;
case EntityType[1].value:
resp = await topologyStore.getGlobalTopology();
break;
case EntityType[2].value:
resp = await topologyStore.getEndpointTopology();
break;
case EntityType[3].value:
resp = await topologyStore.getInstanceTopology();
break;
}
return resp;
}
function setConfig() {
showSetting.value = !showSetting.value;
}
function resize() {
height.value = document.body.clientHeight - 90;
width.value = document.body.clientWidth - 40;
svg.value.attr("height", height.value).attr("width", width.value);
}
function ticked() { function ticked() {
link.value.attr( link.value.attr(
"d", "d",
@ -268,6 +242,59 @@ function update() {
} }
} }
} }
function handleGoEndpoint() {
const node = topologyStore.node;
const path = `/dashboard/${dashboardStore.layerId}/Endpoint/${node.id}/${settings.value.nodeDashboard}`;
const routeUrl = router.resolve({ path });
window.open(routeUrl.href, "_blank");
}
function handleGoInstance() {
const node = topologyStore.node;
const path = `/dashboard/${dashboardStore.layerId}/ServiceInstance/${node.id}/${settings.value.nodeDashboard}`;
const routeUrl = router.resolve({ path });
window.open(routeUrl.href, "_blank");
}
function handleGoDashboard() {
const node = topologyStore.node;
const path = `/dashboard/${dashboardStore.layerId}/Service/${node.id}/${settings.value.nodeDashboard}`;
const routeUrl = router.resolve({ path });
window.open(routeUrl.href, "_blank");
}
function handleGoAlarm() {
const path = `/alarm`;
const routeUrl = router.resolve({ path });
window.open(routeUrl.href, "_blank");
}
async function getTopology() {
let resp;
switch (dashboardStore.entity) {
case EntityType[0].value:
resp = await topologyStore.getServiceTopology();
break;
case EntityType[1].value:
resp = await topologyStore.getGlobalTopology();
break;
case EntityType[2].value:
resp = await topologyStore.getEndpointTopology();
break;
case EntityType[3].value:
resp = await topologyStore.getInstanceTopology();
break;
}
return resp;
}
function setConfig() {
showSetting.value = !showSetting.value;
}
function resize() {
height.value = document.body.clientHeight - 90;
width.value = document.body.clientWidth - 40;
svg.value.attr("height", height.value).attr("width", width.value);
}
function updateSettings(config: any) { function updateSettings(config: any) {
settings.value = config; settings.value = config;
} }

View File

@ -56,16 +56,16 @@ export default (
.on("mouseout", function () { .on("mouseout", function () {
tip.hide(this); tip.hide(this);
}) })
.on("click", (event: any, d: unknown) => { .on("click", (event: any, d: Node | any) => {
event.stopPropagation(); event.stopPropagation();
// event.preventDefault(); event.preventDefault();
// tool.attr("style", "display: none"); tool.attr("style", "display: none");
funcs.handleNodeClick(d); funcs.handleNodeClick(d);
// if (d.isReal) { if (d.isReal) {
// tool tool
// .attr("transform", `translate(${d.x},${d.y - 20})`) .attr("transform", `translate(${d.x},${d.y - 20})`)
// .attr("style", "display: block"); .attr("style", "display: block");
// } }
}); });
nodeEnter nodeEnter
.append("image") .append("image")

View File

@ -15,6 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import icons from "./icons"; import icons from "./icons";
import { Node } from "@/types/topology";
const Hexagon = (side: number, r: number, cx: number, cy: number) => { const Hexagon = (side: number, r: number, cx: number, cy: number) => {
let path = ""; let path = "";
@ -27,7 +28,7 @@ const Hexagon = (side: number, r: number, cx: number, cy: number) => {
return path; return path;
}; };
export default (graph: any, data: any) => { export default (graph: any, tip: any, data: any) => {
const tool = graph.append("g").attr("class", "topo-tool"); const tool = graph.append("g").attr("class", "topo-tool");
const side = 6; const side = 6;
for (let i = 0; i < data.length; i += 1) { for (let i = 0; i < data.length; i += 1) {
@ -36,7 +37,13 @@ export default (graph: any, data: any) => {
const tool_g = tool const tool_g = tool
.append("g") .append("g")
.attr("class", "topo-tool-i") .attr("class", "topo-tool-i")
.on("click", data[i].click); .on("mouseover", function (event: any, d: Node) {
tip.html(() => data[i].title).show(d, this);
})
.on("mouseout", function () {
tip.hide(this);
})
.on("click", data[i].func);
tool_g tool_g
.append("path") .append("path")
.attr("class", "tool-hexagon") .attr("class", "tool-hexagon")