From 99e23c33dc55add382b02233b5fea725f33d74d6 Mon Sep 17 00:00:00 2001 From: Fine0830 Date: Fri, 25 Mar 2022 15:51:06 +0800 Subject: [PATCH] feat: Implement Text control and update Topology (#37) --- src/locales/lang/en.ts | 1 + src/locales/lang/zh.ts | 1 + src/store/data.ts | 9 +- src/store/modules/dashboard.ts | 17 +- src/types/dashboard.ts | 8 + src/views/Layer.vue | 5 +- src/views/dashboard/Edit.vue | 96 +++++------ src/views/dashboard/configuration/Text.vue | 149 ++++++++++++++++++ src/views/dashboard/configuration/Widget.vue | 1 - src/views/dashboard/configuration/index.ts | 26 +++ src/views/dashboard/controls/Tab.vue | 4 +- src/views/dashboard/controls/Text.vue | 129 +++++++++++++++ src/views/dashboard/controls/index.ts | 3 +- src/views/dashboard/data.ts | 18 ++- src/views/dashboard/panel/Layout.vue | 3 + src/views/dashboard/panel/Tool.vue | 6 + .../related/topology/components/Graph.vue | 14 +- .../topology/components/PodTopology.vue | 5 +- .../related/topology/components/Settings.vue | 21 ++- .../related/trace/utils/d3-trace-list.ts | 12 +- 20 files changed, 454 insertions(+), 74 deletions(-) create mode 100644 src/views/dashboard/configuration/Text.vue create mode 100644 src/views/dashboard/configuration/index.ts create mode 100644 src/views/dashboard/controls/Text.vue diff --git a/src/locales/lang/en.ts b/src/locales/lang/en.ts index 08cf4bbf..c11b198f 100644 --- a/src/locales/lang/en.ts +++ b/src/locales/lang/en.ts @@ -125,6 +125,7 @@ const msg = { kubernetesService: "Service", kubernetesCluster: "Cluster", kubernetes: "Kubernetes", + textUrl: "Text Hyperlink", hourTip: "Select Hour", minuteTip: "Select Minute", secondTip: "Select Second", diff --git a/src/locales/lang/zh.ts b/src/locales/lang/zh.ts index 3b01a719..6c1d334a 100644 --- a/src/locales/lang/zh.ts +++ b/src/locales/lang/zh.ts @@ -125,6 +125,7 @@ const msg = { kubernetesService: "服务", kubernetesCluster: "集群", kubernetes: "Kubernetes", + textUrl: "文本超链接", hourTip: "选择小时", minuteTip: "选择分钟", secondTip: "选择秒数", diff --git a/src/store/data.ts b/src/store/data.ts index 50dbbd2a..6fdfdd9b 100644 --- a/src/store/data.ts +++ b/src/store/data.ts @@ -22,10 +22,17 @@ export const NewControl = { i: "0", type: "Widget", widget: { - title: "Title", + title: "", }, graph: {}, standard: {}, metrics: [""], metricTypes: [""], }; +export const TextConfig = { + fontColor: "white", + backgroundColor: "green", + content: "Text", + fontSize: 14, + textAlign: "left", +}; diff --git a/src/store/modules/dashboard.ts b/src/store/modules/dashboard.ts index 2536a4cc..410df5d0 100644 --- a/src/store/modules/dashboard.ts +++ b/src/store/modules/dashboard.ts @@ -22,7 +22,7 @@ import query from "@/graphql/fetch"; import { DashboardItem } from "@/types/dashboard"; import { useAppStoreWithOut } from "@/store/modules/app"; import { useSelectorStore } from "@/store/modules/selectors"; -import { NewControl } from "../data"; +import { NewControl, TextConfig } from "../data"; import { Duration } from "@/types/app"; import { AxiosResponse } from "axios"; import { ElMessage } from "element-plus"; @@ -112,6 +112,10 @@ export const dashboardStore = defineStore({ if (type === "Trace" || type === "Profile" || type === "Log") { newItem.h = 36; } + if (type === "Text") { + newItem.h = 6; + newItem.graph = TextConfig; + } this.activedGridItem = newItem.i; this.selectedGrid = newItem; this.layout = this.layout.map((d: LayoutConfig) => { @@ -158,6 +162,10 @@ export const dashboardStore = defineStore({ if (type === "Trace" || type === "Profile" || type === "Log") { newItem.h = 32; } + if (type === "Text") { + newItem.h = 6; + newItem.graph = TextConfig; + } if (this.layout[idx].children) { const items = children.map((d: LayoutConfig) => { d.y = d.y + newItem.h; @@ -171,10 +179,9 @@ export const dashboardStore = defineStore({ activeGridItem(index: string) { this.activedGridItem = index; }, - setActiveTabIndex(index: number) { - const idx = this.layout.findIndex( - (d: LayoutConfig) => d.i === this.activedGridItem - ); + setActiveTabIndex(index: number, target?: number) { + const m = target || this.activedGridItem; + const idx = this.layout.findIndex((d: LayoutConfig) => d.i === m); if (idx < 0) { return; } diff --git a/src/types/dashboard.ts b/src/types/dashboard.ts index bae7588e..62d12b9d 100644 --- a/src/types/dashboard.ts +++ b/src/types/dashboard.ts @@ -91,6 +91,14 @@ export interface CardConfig { textAlign?: "center" | "right" | "left"; } +export interface TextConfig { + fontSize: number; + backgroundColor: string; + textAlign: string; + fontColor: string; + content: string; +} + export interface TableConfig { type?: string; showTableValues: boolean; diff --git a/src/views/Layer.vue b/src/views/Layer.vue index 71dbb62f..d18a0185 100644 --- a/src/views/Layer.vue +++ b/src/views/Layer.vue @@ -13,7 +13,7 @@ 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. --> - diff --git a/src/views/dashboard/configuration/Widget.vue b/src/views/dashboard/configuration/Widget.vue index 57c1184c..442e8595 100644 --- a/src/views/dashboard/configuration/Widget.vue +++ b/src/views/dashboard/configuration/Widget.vue @@ -90,7 +90,6 @@ import configs from "./widget/graph-styles"; import WidgetOptions from "./widget/WidgetOptions.vue"; import StandardOptions from "./widget/StandardOptions.vue"; import MetricOptions from "./widget/MetricOptions.vue"; -import { ListChartTypes } from "../data"; export default defineComponent({ name: "ConfigEdit", diff --git a/src/views/dashboard/configuration/index.ts b/src/views/dashboard/configuration/index.ts new file mode 100644 index 00000000..a1359eec --- /dev/null +++ b/src/views/dashboard/configuration/index.ts @@ -0,0 +1,26 @@ +/** + * 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 Text from "./Text.vue"; +import Widget from "./Widget.vue"; +import Topology from "./Topology.vue"; + +export default { + Text, + Widget, + Topology, +}; diff --git a/src/views/dashboard/controls/Tab.vue b/src/views/dashboard/controls/Tab.vue index 2582f3ba..26d1163a 100644 --- a/src/views/dashboard/controls/Tab.vue +++ b/src/views/dashboard/controls/Tab.vue @@ -121,6 +121,7 @@ import Widget from "./Widget.vue"; import Trace from "./Trace.vue"; import Profile from "./Profile.vue"; import Log from "./Log.vue"; +import Text from "./Text.vue"; const props = { data: { @@ -131,7 +132,7 @@ const props = { }; export default defineComponent({ name: "Tab", - components: { Topology, Widget, Trace, Profile, Log }, + components: { Topology, Widget, Trace, Profile, Log, Text }, props, setup(props) { const { t } = useI18n(); @@ -149,6 +150,7 @@ export default defineComponent({ dashboardStore.setCurrentTabItems( dashboardStore.layout[l].children[activeTabIndex.value].children ); + dashboardStore.setActiveTabIndex(activeTabIndex.value, props.data.i); } function clickTabs(e: Event, idx: number) { diff --git a/src/views/dashboard/controls/Text.vue b/src/views/dashboard/controls/Text.vue new file mode 100644 index 00000000..60f77ede --- /dev/null +++ b/src/views/dashboard/controls/Text.vue @@ -0,0 +1,129 @@ + + + + diff --git a/src/views/dashboard/controls/index.ts b/src/views/dashboard/controls/index.ts index 7fdcd85a..9829a0d3 100644 --- a/src/views/dashboard/controls/index.ts +++ b/src/views/dashboard/controls/index.ts @@ -20,5 +20,6 @@ import Widget from "./Widget.vue"; import Trace from "./Trace.vue"; import Profile from "./Profile.vue"; import Log from "./Log.vue"; +import Text from "./Text.vue"; -export default { Tab, Widget, Trace, Topology, Profile, Log }; +export default { Tab, Widget, Trace, Topology, Profile, Log, Text }; diff --git a/src/views/dashboard/data.ts b/src/views/dashboard/data.ts index a97fc3d9..9668d761 100644 --- a/src/views/dashboard/data.ts +++ b/src/views/dashboard/data.ts @@ -23,10 +23,10 @@ export const ChartTypes = [ { label: "Bar", value: "Bar" }, { label: "Line", value: "Line" }, { label: "Area", value: "Area" }, - // { label: "Pie", value: "Pie" }, { label: "Card", value: "Card" }, { label: "Top List", value: "TopList" }, { label: "Table", value: "Table" }, + { label: "Text", value: "Text" }, { label: "Heatmap", value: "Heatmap" }, { label: "Service List", value: "ServiceList" }, { label: "Endpoint List", value: "EndpointList" }, @@ -169,6 +169,7 @@ export const SortOrder = [ export const AllTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "library_books", content: "Add Text", id: "addText" }, { name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "merge", content: "Add Trace", id: "addTrace" }, { name: "assignment", content: "Add Log", id: "addLog" }, @@ -177,6 +178,7 @@ export const AllTools = [ export const ServiceTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "library_books", content: "Add Text", id: "addText" }, { name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "merge", content: "Add Trace", id: "addTrace" }, { name: "timeline", content: "Add Profile", id: "addProfile" }, @@ -186,6 +188,7 @@ export const ServiceTools = [ export const InstanceTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "library_books", content: "Add Text", id: "addText" }, { name: "merge", content: "Add Trace", id: "addTrace" }, { name: "assignment", content: "Add Log", id: "addLog" }, { name: "save", content: "Apply", id: "apply" }, @@ -193,6 +196,7 @@ export const InstanceTools = [ export const EndpointTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "library_books", content: "Add Text", id: "addText" }, { name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "merge", content: "Add Trace", id: "addTrace" }, { name: "assignment", content: "Add Log", id: "addLog" }, @@ -201,6 +205,7 @@ export const EndpointTools = [ export const ServiceRelationTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "library_books", content: "Add Text", id: "addText" }, { name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "save", content: "Apply", id: "apply" }, ]; @@ -208,11 +213,13 @@ export const ServiceRelationTools = [ export const EndpointRelationTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "library_books", content: "Add Text", id: "addText" }, { name: "save", content: "Apply", id: "apply" }, ]; export const InstanceRelationTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, { name: "all_inbox", content: "Add Tab", id: "addTab" }, + { name: "library_books", content: "Add Text", id: "addText" }, { name: "device_hub", content: "Add Topology", id: "addTopology" }, { name: "save", content: "Apply", id: "apply" }, ]; @@ -248,3 +255,12 @@ export const QueryOrders = [ { label: "Start Time", value: "BY_START_TIME" }, { label: "Duration", value: "BY_DURATION" }, ]; +export const TextColors: { [key: string]: string } = { + green: "#67C23A", + blue: "#409EFF", + red: "#F56C6C", + grey: "#909399", + white: "#fff", + black: "#000", + orange: "#E6A23C", +}; diff --git a/src/views/dashboard/panel/Layout.vue b/src/views/dashboard/panel/Layout.vue index 93d8ad11..cec440ac 100644 --- a/src/views/dashboard/panel/Layout.vue +++ b/src/views/dashboard/panel/Layout.vue @@ -59,6 +59,9 @@ export default defineComponent({ function clickGrid(item: LayoutConfig) { dashboardStore.activeGridItem(item.i); dashboardStore.selectWidget(item); + if (item.type === "Tab") { + dashboardStore.setActiveTabIndex(0); + } } onBeforeUnmount(() => { dashboardStore.setLayout([]); diff --git a/src/views/dashboard/panel/Tool.vue b/src/views/dashboard/panel/Tool.vue index 9c9e55c3..d5476d0a 100644 --- a/src/views/dashboard/panel/Tool.vue +++ b/src/views/dashboard/panel/Tool.vue @@ -367,6 +367,9 @@ function setTabControls(id: string) { case "addTopology": dashboardStore.addTabControls("Topology"); break; + case "addText": + dashboardStore.addTabControls("Text"); + break; default: ElMessage.info("Don't support this control"); break; @@ -393,6 +396,9 @@ function setControls(id: string) { case "addTopology": dashboardStore.addControl("Topology"); break; + case "addText": + dashboardStore.addControl("Text"); + break; default: dashboardStore.addControl("Widget"); } diff --git a/src/views/dashboard/related/topology/components/Graph.vue b/src/views/dashboard/related/topology/components/Graph.vue index b682677f..f48705a2 100644 --- a/src/views/dashboard/related/topology/components/Graph.vue +++ b/src/views/dashboard/related/topology/components/Graph.vue @@ -30,7 +30,6 @@ limitations under the License. --> class="inputs" :value="depth" :options="DepthList" - placeholder="Select a option" @change="changeDepth" /> @@ -377,10 +376,12 @@ async function handleInspect() { topologyStore.setNode(null); topologyStore.setLink(null); loading.value = true; - const resp = await topologyStore.getServicesTopology([id]); + const resp = await topologyStore.getDepthServiceTopology( + [id], + Number(depth.value) + ); loading.value = false; - - if (resp.errors) { + if (resp && resp.errors) { ElMessage.error(resp.errors); } await init(); @@ -555,17 +556,18 @@ watch( .operations-list { position: absolute; - padding: 10px; color: #333; cursor: pointer; background-color: #fff; border-radius: 3px; + padding: 10px 0; span { display: block; height: 30px; line-height: 30px; - text-align: center; + text-align: left; + padding: 0 15px; } span:hover { diff --git a/src/views/dashboard/related/topology/components/PodTopology.vue b/src/views/dashboard/related/topology/components/PodTopology.vue index b3362793..8fc4df70 100644 --- a/src/views/dashboard/related/topology/components/PodTopology.vue +++ b/src/views/dashboard/related/topology/components/PodTopology.vue @@ -324,7 +324,7 @@ watch( .operations-list { position: absolute; - padding: 10px; + padding: 10px 0; color: #333; cursor: pointer; background-color: #fff; @@ -335,7 +335,8 @@ watch( height: 30px; width: 140px; line-height: 30px; - text-align: center; + text-align: left; + padding: 0 15px; } span:hover { diff --git a/src/views/dashboard/related/topology/components/Settings.vue b/src/views/dashboard/related/topology/components/Settings.vue index 8dbe619f..21e15c8e 100644 --- a/src/views/dashboard/related/topology/components/Settings.vue +++ b/src/views/dashboard/related/topology/components/Settings.vue @@ -23,6 +23,7 @@ limitations under the License. --> placeholder="Please input a dashboard name for calls" @change="changeLinkDashboard" class="inputs" + :clearable="true" />
{{ t("linkServerMetrics") }}
iconName="remove_circle_outline" size="middle" @click="deleteMetric(index)" - v-show="legend.metric.length > 1" /> ((isService && selectedGrid.nodeDashboard) || [{ scope: "", dashboard: "" }]); +>(isService && nodeDashboard ? nodeDashboard : [{ scope: "", dashboard: "" }]); const states = reactive<{ linkDashboard: string; nodeDashboard: { @@ -229,9 +232,12 @@ const states = reactive<{ linkDashboards: [], nodeDashboards: [], }); +const l = selectedGrid.legend && selectedGrid.legend.length; const legend = reactive<{ metric: { name: string; condition: string; value: string }[]; -}>({ metric: selectedGrid.legend || [{ name: "", condition: "", value: "" }] }); +}>({ + metric: l ? selectedGrid.legend : [{ name: "", condition: "", value: "" }], +}); getMetricList(); async function getMetricList() { @@ -335,6 +341,9 @@ function addItem() { items.push({ scope: "", dashboard: "" }); } function deleteItem(index: number) { + if (items.length === 1) { + items.push({ scope: "", dashboard: "" }); + } items.splice(index, 1); updateSettings(); } @@ -384,6 +393,10 @@ async function changeNodeMetrics(options: Option[] | any) { topologyStore.queryNodeMetrics(states.nodeMetrics); } function deleteMetric(index: number) { + if (legend.metric.length === 1) { + legend.metric = [{ name: "", condition: "", value: "" }]; + return; + } legend.metric.splice(index, 1); } function addMetric() { diff --git a/src/views/dashboard/related/trace/utils/d3-trace-list.ts b/src/views/dashboard/related/trace/utils/d3-trace-list.ts index f987e1bd..dc2c16a7 100644 --- a/src/views/dashboard/related/trace/utils/d3-trace-list.ts +++ b/src/views/dashboard/related/trace/utils/d3-trace-list.ts @@ -40,14 +40,15 @@ export default class ListGraph { constructor(el: HTMLDivElement, handleSelectSpan: (i: Trace) => void) { this.handleSelectSpan = handleSelectSpan; this.el = el; - this.width = el.clientWidth - 20; + this.width = el.clientWidth - 10; this.height = el.clientHeight; this.svg = d3 .select(this.el) .append("svg") .attr("class", "trace-list-dowanload") .attr("width", this.width) - .attr("height", this.height); + .attr("height", this.height) + .attr("transform", `translate(-5, 0)`); this.tip = (d3tip as any)() .attr("class", "d3-tip") .offset([-8, 0]) @@ -220,7 +221,7 @@ export default class ListGraph { nodeEnter .transition() .duration(400) - .attr("transform", (d: any) => `translate(${d.y},${d.x})`) + .attr("transform", (d: any) => `translate(${d.y + 5},${d.x})`) .style("opacity", 1); nodeEnter .append("circle") @@ -243,7 +244,7 @@ export default class ListGraph { node .transition() .duration(400) - .attr("transform", (d: any) => `translate(${d.y},${d.x})`) + .attr("transform", (d: any) => `translate(${d.y + 5},${d.x})`) .style("opacity", 1) .select("circle") .attr("fill", (d: any) => @@ -273,8 +274,9 @@ export default class ListGraph { .attr("fill", "rgba(0,0,0,0)") .attr("stroke", "rgba(0, 0, 0, 0.1)") .attr("stroke-width", 2) + .attr("transform", `translate(5, 0)`) .attr("d", () => { - const o = { x: source.x0 + 35, y: source.y0 }; + const o = { x: source.x0 + 40, y: source.y0 }; return this.diagonal({ source: o, target: o }); }) .transition()