From 001fa25a3be7720f93b672dedea25a9d0552d2cc Mon Sep 17 00:00:00 2001 From: Fine0830 Date: Wed, 20 Dec 2023 17:58:00 +0800 Subject: [PATCH] feat: support Tabs in the widget visiable when MQE expressions (#353) --- src/assets/icons/add_iframe.svg | 2 +- src/assets/icons/demand.svg | 2 +- src/assets/icons/event.svg | 2 +- src/components/Graph.vue | 3 +- src/hooks/useExpressionsProcessor.ts | 2 + src/layout/components/NavBar.vue | 3 +- src/locales/lang/en.ts | 1 + src/locales/lang/es.ts | 1 + src/locales/lang/zh.ts | 1 + src/store/data.ts | 22 +-- src/store/modules/dashboard.ts | 26 ++-- src/styles/theme.scss | 2 +- src/types/dashboard.d.ts | 2 +- src/views/dashboard/List.vue | 16 ++- src/views/dashboard/configuration/Tab.vue | 110 ++++++++++++++ src/views/dashboard/configuration/index.ts | 2 + src/views/dashboard/controls/Tab.vue | 135 ++++++++++++++---- src/views/dashboard/data.ts | 135 ++++++++++-------- src/views/dashboard/graphs/TopList.vue | 3 +- src/views/dashboard/panel/Layout.vue | 7 +- src/views/dashboard/panel/Tool.vue | 113 ++------------- src/views/dashboard/related/event/Content.vue | 5 +- .../related/log/LogTable/LogService.vue | 3 +- src/views/dashboard/related/trace/Detail.vue | 3 +- tsconfig.app.json | 1 - tsconfig.vitest.json | 1 - 26 files changed, 379 insertions(+), 224 deletions(-) create mode 100644 src/views/dashboard/configuration/Tab.vue diff --git a/src/assets/icons/add_iframe.svg b/src/assets/icons/add_iframe.svg index 5fa776c0..a24b9967 100644 --- a/src/assets/icons/add_iframe.svg +++ b/src/assets/icons/add_iframe.svg @@ -12,4 +12,4 @@ 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. --> - \ No newline at end of file + \ No newline at end of file diff --git a/src/assets/icons/demand.svg b/src/assets/icons/demand.svg index 4b1b60db..1d4861fd 100644 --- a/src/assets/icons/demand.svg +++ b/src/assets/icons/demand.svg @@ -13,4 +13,4 @@ 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. --> - \ No newline at end of file + \ No newline at end of file diff --git a/src/assets/icons/event.svg b/src/assets/icons/event.svg index 93bf25ec..b4cedb14 100644 --- a/src/assets/icons/event.svg +++ b/src/assets/icons/event.svg @@ -12,4 +12,4 @@ 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. --> - \ No newline at end of file + \ No newline at end of file diff --git a/src/components/Graph.vue b/src/components/Graph.vue index 5ed35d1d..174d6de4 100644 --- a/src/components/Graph.vue +++ b/src/components/Graph.vue @@ -53,6 +53,7 @@ limitations under the License. --> import { addResizeListener, removeResizeListener } from "@/utils/event"; import Trace from "@/views/dashboard/related/trace/Index.vue"; import associateProcessor from "@/hooks/useAssociateProcessor"; + import { WidgetType } from "@/views/dashboard/data"; /*global Nullable, defineProps, defineEmits, Indexable*/ const emits = defineEmits(["select"]); @@ -63,7 +64,7 @@ limitations under the License. --> const currentParams = ref>(null); const showTrace = ref(false); const traceOptions = ref<{ type: string; filters?: unknown }>({ - type: "Trace", + type: WidgetType.Trace, }); const menuPos = reactive<{ x: number; y: number }>({ x: NaN, y: NaN }); const props = defineProps({ diff --git a/src/hooks/useExpressionsProcessor.ts b/src/hooks/useExpressionsProcessor.ts index fb7f4a3c..e237cb0d 100644 --- a/src/hooks/useExpressionsProcessor.ts +++ b/src/hooks/useExpressionsProcessor.ts @@ -141,6 +141,7 @@ export async function useExpressionsQueryProcessor(config: Indexable) { return { source, tips, typesOfMQE }; } + const params = await expressionsGraphqlPods(); if (!params) { return { source: {}, tips: [], typesOfMQE: [] }; @@ -301,6 +302,7 @@ export async function useExpressionsQueryPodsMetrics( return { data, names, subNames, metricConfigArr, metricTypesArr, expressionsTips, subExpressionsTips }; } + const dashboardStore = useDashboardStore(); const params = await expressionsGraphqlPods(); const json = await dashboardStore.fetchMetricValue(params); diff --git a/src/layout/components/NavBar.vue b/src/layout/components/NavBar.vue index f7f253e0..51c7e96d 100644 --- a/src/layout/components/NavBar.vue +++ b/src/layout/components/NavBar.vue @@ -93,7 +93,8 @@ limitations under the License. --> const savedTheme = window.localStorage.getItem("theme-is-dark"); if (savedTheme === "false") { theme.value = false; - } else if (savedTheme === "") { + } + if (savedTheme === "") { // read the theme preference from system setting if there is no user setting theme.value = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; } diff --git a/src/locales/lang/en.ts b/src/locales/lang/en.ts index 43987752..797b463f 100644 --- a/src/locales/lang/en.ts +++ b/src/locales/lang/en.ts @@ -384,5 +384,6 @@ const msg = { unhealthyExpression: "Unhealthy Expression", traceDesc: "The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.", + tabExpressions: "Tab Expressions", }; export default msg; diff --git a/src/locales/lang/es.ts b/src/locales/lang/es.ts index 801c2ca3..18a2d46f 100644 --- a/src/locales/lang/es.ts +++ b/src/locales/lang/es.ts @@ -384,5 +384,6 @@ const msg = { unhealthyExpression: "Unhealthy Expression", traceDesc: "The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.", + tabExpressions: "Tab Expressions", }; export default msg; diff --git a/src/locales/lang/zh.ts b/src/locales/lang/zh.ts index 3225a3ac..36962afc 100644 --- a/src/locales/lang/zh.ts +++ b/src/locales/lang/zh.ts @@ -382,5 +382,6 @@ const msg = { unhealthyExpression: "非健康表达式", traceDesc: "Trace Segment代表在单一操作系统进程(例如JVM)中执行的追踪部分。它包含了一组跨度(spans),这些跨度通常与单一请求或执行上下文关联。", + tabExpressions: "Tab表达式", }; export default msg; diff --git a/src/store/data.ts b/src/store/data.ts index 43d0d4d2..24749b4d 100644 --- a/src/store/data.ts +++ b/src/store/data.ts @@ -14,13 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { WidgetType } from "@/views/dashboard/data"; + export const NewControl = { x: 0, y: 0, w: 24, h: 12, i: "0", - type: "Widget", + type: WidgetType.Widget, }; export const TextConfig = { fontColor: "white", @@ -39,15 +41,15 @@ export const TimeRangeConfig = { }; export const ControlsTypes = [ - "Trace", - "Profile", - "Log", - "DemandLog", - "Ebpf", - "NetworkProfiling", - "ThirdPartyApp", - "ContinuousProfiling", - "TaskTimeline", + WidgetType.Trace, + WidgetType.Profile, + WidgetType.Log, + WidgetType.DemandLog, + WidgetType.Ebpf, + WidgetType.NetworkProfiling, + WidgetType.ThirdPartyApp, + WidgetType.ContinuousProfiling, + WidgetType.TaskTimeline, ]; export enum EBPFProfilingTriggerType { FIXED_TIME = "FIXED_TIME", diff --git a/src/store/modules/dashboard.ts b/src/store/modules/dashboard.ts index 5fd55921..6aa3da63 100644 --- a/src/store/modules/dashboard.ts +++ b/src/store/modules/dashboard.ts @@ -25,7 +25,7 @@ import { NewControl, TextConfig, TimeRangeConfig, ControlsTypes } from "../data" import type { AxiosResponse } from "axios"; import { ElMessage } from "element-plus"; import { useI18n } from "vue-i18n"; -import { EntityType, MetricModes } from "@/views/dashboard/data"; +import { EntityType, MetricModes, WidgetType } from "@/views/dashboard/data"; interface DashboardState { showConfig: boolean; layout: LayoutConfig[]; @@ -78,7 +78,7 @@ export const dashboardStore = defineStore({ setCurrentDashboard(item: DashboardItem) { this.currentDashboard = item; }, - addControl(type: string) { + addControl(type: WidgetType) { const arr = this.layout.map((d: Recordable) => Number(d.i)); let index = String(Math.max(...arr) + 1); if (!this.layout.length) { @@ -93,10 +93,10 @@ export const dashboardStore = defineStore({ metrics: [""], }; - if (type === "Widget") { + if (type === WidgetType.Widget) { newItem.metricMode = MetricModes.Expression; } - if (type === "Tab") { + if (type === WidgetType.Tab) { newItem.h = 36; newItem.activedTabIndex = 0; newItem.children = [ @@ -110,7 +110,7 @@ export const dashboardStore = defineStore({ }, ]; } - if (type === "Topology") { + if (type === WidgetType.Topology) { newItem.h = 36; newItem.graph = { showDepth: true, @@ -120,11 +120,11 @@ export const dashboardStore = defineStore({ if (ControlsTypes.includes(type)) { newItem.h = 36; } - if (type === "Text") { + if (type === WidgetType.Text) { newItem.h = 6; newItem.graph = TextConfig; } - if (type === "TimeRange") { + if (type === WidgetType.TimeRange) { newItem.w = 8; newItem.h = 6; newItem.graph = TimeRangeConfig; @@ -149,7 +149,7 @@ export const dashboardStore = defineStore({ }; this.layout[idx].children?.push(i); }, - addTabControls(type: string) { + addTabControls(type: WidgetType) { const activedGridItem = this.activedGridItem.split("-")[0]; const idx = this.layout.findIndex((d: LayoutConfig) => d.i === activedGridItem); if (idx < 0) { @@ -171,10 +171,10 @@ export const dashboardStore = defineStore({ metricTypes: [""], metrics: [""], }; - if (type === "Widget") { + if (type === WidgetType.Widget) { newItem.metricMode = MetricModes.Expression; } - if (type === "Topology") { + if (type === WidgetType.Topology) { newItem.h = 32; newItem.graph = { showDepth: true, @@ -184,11 +184,11 @@ export const dashboardStore = defineStore({ if (ControlsTypes.includes(type)) { newItem.h = 32; } - if (type === "Text") { + if (type === WidgetType.Text) { newItem.h = 6; newItem.graph = TextConfig; } - if (type === "TimeRange") { + if (type === WidgetType.TimeRange) { newItem.w = 8; newItem.h = 6; newItem.graph = TextConfig; @@ -292,7 +292,7 @@ export const dashboardStore = defineStore({ }, setWidget(param: LayoutConfig) { for (let i = 0; i < this.layout.length; i++) { - if (this.layout[i].type === "Tab") { + if (this.layout[i].type === WidgetType.Tab) { if ((this.layout[i].children || []).length) { for (const child of this.layout[i].children || []) { if (child.children && child.children.length) { diff --git a/src/styles/theme.scss b/src/styles/theme.scss index 12b1bbed..e17ab4bb 100644 --- a/src/styles/theme.scss +++ b/src/styles/theme.scss @@ -65,7 +65,7 @@ html.dark { --el-color-primary: #409eff; --theme-background: #212224; --font-color: #fafbfc; - --disabled-color: #ccc; + --disabled-color: #999; --dashboard-tool-bg: #000; --text-color-placeholder: #ccc; --border-color: #262629; diff --git a/src/types/dashboard.d.ts b/src/types/dashboard.d.ts index 8612c10e..400ccd0b 100644 --- a/src/types/dashboard.d.ts +++ b/src/types/dashboard.d.ts @@ -36,7 +36,7 @@ export interface LayoutConfig { expressions?: string[]; metricTypes?: string[]; typesOfMQE?: string[]; - children?: { name: string; children: LayoutConfig[] }[]; + children?: { name: string; children: LayoutConfig[]; expression?: string; enable?: boolean }[]; activedTabIndex?: number; metricConfig?: MetricConfigOpt[]; id?: string; diff --git a/src/views/dashboard/List.vue b/src/views/dashboard/List.vue index 25b4997a..d1c372dd 100644 --- a/src/views/dashboard/List.vue +++ b/src/views/dashboard/List.vue @@ -139,6 +139,7 @@ limitations under the License. --> import { saveFile, readFile } from "@/utils/file"; import { EntityType } from "./data"; import { isEmptyObject } from "@/utils/is"; + import { WidgetType } from "@/views/dashboard/data"; /*global Nullable*/ const { t } = useI18n(); @@ -271,12 +272,23 @@ limitations under the License. --> if (!(child.metricConfig && child.metricConfig.length)) { delete child.metricConfig; } - if (child.type === "Tab") { + if (child.type === WidgetType.Tab) { for (const item of child.children || []) { optimizeTemplate(item.children); } } - if (["Trace", "Topology", "Tab", "Profile", "Ebpf", "Log"].includes(child.type)) { + if ( + ( + [ + WidgetType.Trace, + WidgetType.Topology, + WidgetType.Tab, + WidgetType.Profile, + WidgetType.Ebpf, + WidgetType.Log, + ] as string[] + ).includes(child.type) + ) { delete child.widget; } } diff --git a/src/views/dashboard/configuration/Tab.vue b/src/views/dashboard/configuration/Tab.vue new file mode 100644 index 00000000..4bf394af --- /dev/null +++ b/src/views/dashboard/configuration/Tab.vue @@ -0,0 +1,110 @@ + + + + diff --git a/src/views/dashboard/configuration/index.ts b/src/views/dashboard/configuration/index.ts index aadb8f33..aa4b8c85 100644 --- a/src/views/dashboard/configuration/index.ts +++ b/src/views/dashboard/configuration/index.ts @@ -22,8 +22,10 @@ import Event from "./Event.vue"; import TimeRange from "./TimeRange.vue"; import ThirdPartyApp from "./ThirdPartyApp.vue"; import ContinuousProfiling from "./ContinuousProfiling.vue"; +import Tab from "./Tab.vue"; export default { + Tab, Text, Widget, Topology, diff --git a/src/views/dashboard/controls/Tab.vue b/src/views/dashboard/controls/Tab.vue index 18977897..2460defb 100644 --- a/src/views/dashboard/controls/Tab.vue +++ b/src/views/dashboard/controls/Tab.vue @@ -15,29 +15,41 @@ limitations under the License. --> + @@ -56,10 +68,13 @@ limitations under the License. -->
- +