You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2022/07/19 03:57:30 UTC
[skywalking-booster-ui] branch main updated: feat: Enhance associations for the Event widget (#120)
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 42ead4a feat: Enhance associations for the Event widget (#120)
42ead4a is described below
commit 42ead4a572c6499fa281b08bb7f38ab6dcb72e8f
Author: Fine0830 <fi...@outlook.com>
AuthorDate: Tue Jul 19 11:57:26 2022 +0800
feat: Enhance associations for the Event widget (#120)
---
package-lock.json | 22 +-----
package.json | 3 +-
src/components/Graph.vue | 64 ++++++++++++++++-
src/hooks/useEcharts.ts | 2 -
src/locales/lang/en.ts | 1 +
src/locales/lang/es.ts | 1 +
src/locales/lang/zh.ts | 1 +
src/store/modules/event.ts | 3 +
src/types/dashboard.d.ts | 11 ++-
src/utils/echarts.ts | 11 +--
src/views/dashboard/configuration/Event.vue | 82 ++++++++++++++++++++++
src/views/dashboard/configuration/index.ts | 2 +
.../configuration/widget/AssociateOptions.vue | 35 +++------
src/views/dashboard/controls/Event.vue | 7 ++
src/views/dashboard/graphs/Area.vue | 8 ++-
src/views/dashboard/graphs/Bar.vue | 52 ++------------
src/views/dashboard/graphs/Line.vue | 52 ++------------
src/views/dashboard/related/event/Content.vue | 48 +++++++++++--
18 files changed, 247 insertions(+), 158 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 217941f..59d7203 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -22,8 +22,7 @@
"vue-grid-layout": "^3.0.0-beta1",
"vue-i18n": "^9.1.9",
"vue-router": "^4.0.0-0",
- "vue-types": "^4.1.1",
- "vuex": "^4.0.0-0"
+ "vue-types": "^4.1.1"
},
"devDependencies": {
"@types/d3": "^7.1.0",
@@ -27338,17 +27337,6 @@
"vue": "^2.0.0 || ^3.0.0"
}
},
- "node_modules/vuex": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
- "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
- "dependencies": {
- "@vue/devtools-api": "^6.0.0-beta.11"
- },
- "peerDependencies": {
- "vue": "^3.0.2"
- }
- },
"node_modules/w3c-hr-time": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
@@ -50552,14 +50540,6 @@
"is-plain-object": "5.0.0"
}
},
- "vuex": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
- "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
- "requires": {
- "@vue/devtools-api": "^6.0.0-beta.11"
- }
- },
"w3c-hr-time": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
diff --git a/package.json b/package.json
index 040092a..2877874 100644
--- a/package.json
+++ b/package.json
@@ -24,8 +24,7 @@
"vue-grid-layout": "^3.0.0-beta1",
"vue-i18n": "^9.1.9",
"vue-router": "^4.0.0-0",
- "vue-types": "^4.1.1",
- "vuex": "^4.0.0-0"
+ "vue-types": "^4.1.1"
},
"devDependencies": {
"@types/d3": "^7.1.0",
diff --git a/src/components/Graph.vue b/src/components/Graph.vue
index 85638ba..0222dca 100644
--- a/src/components/Graph.vue
+++ b/src/components/Graph.vue
@@ -46,8 +46,12 @@ const props = defineProps({
},
filters: {
type: Object as PropType<{
- value: number | string;
- dataIndex: number;
+ duration: {
+ startTime: string;
+ endTime: string;
+ };
+ isRange: boolean;
+ dataIndex?: number;
sourceId: string;
}>,
},
@@ -73,7 +77,7 @@ onMounted(async () => {
});
document.addEventListener(
"click",
- () => {
+ (event: Event) => {
if (instance.isDisposed()) {
return;
}
@@ -84,6 +88,27 @@ onMounted(async () => {
type: "updateAxisPointer",
currTrigger: "leave",
});
+ if (
+ ["vis-item-overflow", "vis-item-content"].includes(
+ (event.target as HTMLDivElement).className
+ )
+ ) {
+ return;
+ }
+ const series = (window as any).structuredClone(props.option.series);
+ for (const temp of series) {
+ if (temp.markArea) {
+ delete temp.markArea;
+ }
+ }
+ const options = {
+ ...props.option,
+ series,
+ };
+ if (JSON.stringify(options) === JSON.stringify(props.option)) {
+ return;
+ }
+ setOptions(options);
},
true
);
@@ -110,6 +135,39 @@ watch(
return;
}
if (props.filters) {
+ if (props.filters.isRange) {
+ const markArea = {
+ silent: true,
+ itemStyle: {
+ opacity: 0.3,
+ },
+ data: [
+ [
+ {
+ xAxis: props.filters.duration.startTime,
+ },
+ {
+ xAxis: props.filters.duration.endTime,
+ },
+ ],
+ ],
+ };
+ const series = (window as any).structuredClone(props.option.series);
+ for (const [key, temp] of series.entries()) {
+ if (key === 0) {
+ temp.markArea = markArea;
+ }
+ }
+ const options = {
+ ...props.option,
+ series,
+ };
+ if (JSON.stringify(options) === JSON.stringify(props.option)) {
+ return;
+ }
+ setOptions(options);
+ return;
+ }
instance.dispatchAction({
type: "showTip",
dataIndex: props.filters.dataIndex,
diff --git a/src/hooks/useEcharts.ts b/src/hooks/useEcharts.ts
index 01f7d7e..2469865 100644
--- a/src/hooks/useEcharts.ts
+++ b/src/hooks/useEcharts.ts
@@ -18,7 +18,6 @@ import {
BarSeriesOption,
LineSeriesOption,
HeatmapSeriesOption,
- PieSeriesOption,
SankeySeriesOption,
} from "echarts/charts";
import {
@@ -46,7 +45,6 @@ export type ECOption = echarts.ComposeOption<
| DatasetComponentOption
| LegendComponentOption
| HeatmapSeriesOption
- | PieSeriesOption
| SankeySeriesOption
>;
diff --git a/src/locales/lang/en.ts b/src/locales/lang/en.ts
index f2a9037..3b4af09 100644
--- a/src/locales/lang/en.ts
+++ b/src/locales/lang/en.ts
@@ -147,6 +147,7 @@ const msg = {
nameTip:
"The name only supports Chinese and English, horizontal lines and underscores. The length of the name is limited to 300 characters",
duplicateName: "Duplicate name",
+ enableAssociate: "Enable association",
seconds: "Seconds",
hourTip: "Select Hour",
minuteTip: "Select Minute",
diff --git a/src/locales/lang/es.ts b/src/locales/lang/es.ts
index 2da5283..d65c1e4 100644
--- a/src/locales/lang/es.ts
+++ b/src/locales/lang/es.ts
@@ -147,6 +147,7 @@ const msg = {
duplicateName: "Nombre duplicado",
nameTip:
"El nombre sólo admite chino e inglés, líneas horizontales y subrayado, y la longitud del nombre no excederá de 300 caracteres",
+ enableAssociate: "Activar asociación",
seconds: "Segundos",
hourTip: "Seleccione Hora",
minuteTip: "Seleccione Minuto",
diff --git a/src/locales/lang/zh.ts b/src/locales/lang/zh.ts
index 7a63626..6c05e54 100644
--- a/src/locales/lang/zh.ts
+++ b/src/locales/lang/zh.ts
@@ -142,6 +142,7 @@ const msg = {
begin: "开始",
associateOptions: "关联选项",
widget: "部件",
+ enableAssociate: "启用关联",
nameTip: "该名称仅支持中文和英文、横线和下划线, 并且限制长度为300个字符",
duplicateName: "重复的名称",
seconds: "秒",
diff --git a/src/store/modules/event.ts b/src/store/modules/event.ts
index fed1fa7..82c8a82 100644
--- a/src/store/modules/event.ts
+++ b/src/store/modules/event.ts
@@ -104,6 +104,9 @@ export const eventStore = defineStore({
scope = "Endpoint";
}
item.scope = scope;
+ if (!item.endTime || item.endTime === item.startTime) {
+ item.endTime = Number(item.startTime) + 60000;
+ }
return item;
}
);
diff --git a/src/types/dashboard.d.ts b/src/types/dashboard.d.ts
index 4bb9aa3..1f3ecac 100644
--- a/src/types/dashboard.d.ts
+++ b/src/types/dashboard.d.ts
@@ -38,7 +38,16 @@ export interface LayoutConfig {
metricConfig?: MetricConfigOpt[];
id?: string;
associate?: { widgetId: string }[];
- filters?: { dataIndex: number; sourceId: string };
+ eventAssociate?: boolean;
+ filters?: {
+ dataIndex: number;
+ sourceId: string;
+ isRange?: boolean;
+ duration?: {
+ startTime: string;
+ endTime: string;
+ };
+ };
}
export type MetricConfigOpt = {
diff --git a/src/utils/echarts.ts b/src/utils/echarts.ts
index 9103f91..db786a0 100644
--- a/src/utils/echarts.ts
+++ b/src/utils/echarts.ts
@@ -16,13 +16,7 @@
*/
import * as echarts from "echarts/core";
-import {
- BarChart,
- LineChart,
- PieChart,
- HeatmapChart,
- SankeyChart,
-} from "echarts/charts";
+import { BarChart, LineChart, HeatmapChart, SankeyChart } from "echarts/charts";
import {
TitleComponent,
@@ -32,6 +26,7 @@ import {
DataZoomComponent,
VisualMapComponent,
TimelineComponent,
+ MarkAreaComponent,
} from "echarts/components";
import { SVGRenderer } from "echarts/renderers";
@@ -43,13 +38,13 @@ echarts.use([
GridComponent,
BarChart,
LineChart,
- PieChart,
HeatmapChart,
SankeyChart,
SVGRenderer,
DataZoomComponent,
VisualMapComponent,
TimelineComponent,
+ MarkAreaComponent,
]);
export default echarts;
diff --git a/src/views/dashboard/configuration/Event.vue b/src/views/dashboard/configuration/Event.vue
new file mode 100644
index 0000000..a5d9b66
--- /dev/null
+++ b/src/views/dashboard/configuration/Event.vue
@@ -0,0 +1,82 @@
+<!-- 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>
+ <span class="label">{{ t("enableAssociate") }}</span>
+ <el-switch
+ v-model="eventAssociate"
+ active-text="Yes"
+ inactive-text="No"
+ @change="updateConfig"
+ />
+ </div>
+ <div class="footer">
+ <el-button size="small" @click="cancelConfig">
+ {{ t("cancel") }}
+ </el-button>
+ <el-button size="small" type="primary" @click="applyConfig">
+ {{ t("apply") }}
+ </el-button>
+ </div>
+</template>
+<script lang="ts" setup>
+import { useI18n } from "vue-i18n";
+import { ref } from "vue";
+import { useDashboardStore } from "@/store/modules/dashboard";
+
+const { t } = useI18n();
+const dashboardStore = useDashboardStore();
+const originConfig = dashboardStore.selectedGrid;
+const eventAssociate = ref(dashboardStore.selectedGrid.eventAssociate || false);
+
+function updateConfig() {
+ dashboardStore.selectedGrid = {
+ ...dashboardStore.selectedGrid,
+ eventAssociate,
+ };
+ dashboardStore.selectWidget(dashboardStore.selectedGrid);
+}
+
+function applyConfig() {
+ dashboardStore.setConfigPanel(false);
+ dashboardStore.setConfigs(dashboardStore.selectedGrid);
+}
+
+function cancelConfig() {
+ dashboardStore.selectWidget(originConfig);
+ dashboardStore.setConfigPanel(false);
+}
+</script>
+<style lang="scss" scoped>
+.label {
+ font-size: 13px;
+ font-weight: 500;
+ display: block;
+ margin-bottom: 5px;
+}
+
+.item {
+ margin: 10px 0;
+}
+
+.footer {
+ position: fixed;
+ bottom: 0;
+ right: 0;
+ border-top: 1px solid #eee;
+ padding: 10px;
+ text-align: right;
+ width: 100%;
+ background-color: #fff;
+}
+</style>
diff --git a/src/views/dashboard/configuration/index.ts b/src/views/dashboard/configuration/index.ts
index a1359ee..6d39f19 100644
--- a/src/views/dashboard/configuration/index.ts
+++ b/src/views/dashboard/configuration/index.ts
@@ -18,9 +18,11 @@
import Text from "./Text.vue";
import Widget from "./Widget.vue";
import Topology from "./Topology.vue";
+import Event from "./Event.vue";
export default {
Text,
Widget,
Topology,
+ Event,
};
diff --git a/src/views/dashboard/configuration/widget/AssociateOptions.vue b/src/views/dashboard/configuration/widget/AssociateOptions.vue
index 0e7aab9..feae770 100644
--- a/src/views/dashboard/configuration/widget/AssociateOptions.vue
+++ b/src/views/dashboard/configuration/widget/AssociateOptions.vue
@@ -41,32 +41,16 @@ const widgetIds = ref<string[]>(
associate.map((d: { widgetId: string }) => d.widgetId)
);
const widgets = computed(() => {
- const isLinear = ["Bar", "Line", "Area"].includes(
- dashboardStore.selectedGrid.graph && dashboardStore.selectedGrid.graph.type
- );
- // const isRank = ["TopList"].includes(
- // dashboardStore.selectedGrid.graph && dashboardStore.selectedGrid.graph.type
- // );
- const { widgets } = getDashboard(dashboardStore.currentDashboard);
- const items = widgets.filter(
+ const all = getDashboard(dashboardStore.currentDashboard).widgets;
+ const items = all.filter(
(d: { value: string; label: string } & LayoutConfig) => {
- if (dashboardStore.selectedGrid.id !== d.id) {
- if (
- isLinear &&
- d.type === "Widget" &&
- d.widget &&
- d.widget.name &&
- d.id
- ) {
- d.value = d.id;
- d.label = d.widget.name;
- return d;
- }
- // if (isRank && d.type !== "Widget" && d.widget && d.id) {
- // d.value = d.id;
- // d.label = d.widget.name || d.id;
- // return d;
- // }
+ const isLinear = ["Bar", "Line", "Area"].includes(
+ (d.graph && d.graph.type) || ""
+ );
+ if (isLinear && d.id && dashboardStore.selectedGrid.id !== d.id) {
+ d.value = d.id;
+ d.label = (d.widget && d.widget.name) || d.id;
+ return d;
}
}
);
@@ -84,6 +68,7 @@ function updateWidgetConfig(options: Option[]) {
associate: opt,
};
dashboardStore.selectWidget({ ...widget });
+
// remove unuse association widget option
for (const id of widgetIds.value) {
if (!newVal.includes(id)) {
diff --git a/src/views/dashboard/controls/Event.vue b/src/views/dashboard/controls/Event.vue
index e510a13..c4cc16a 100644
--- a/src/views/dashboard/controls/Event.vue
+++ b/src/views/dashboard/controls/Event.vue
@@ -25,6 +25,9 @@ limitations under the License. -->
<Icon iconName="ellipsis_v" size="middle" class="operation" />
</span>
</template>
+ <div class="tools" @click="editConfig">
+ <span>{{ t("edit") }}</span>
+ </div>
<div class="tools" @click="removeWidget">
<span>{{ t("delete") }}</span>
</div>
@@ -58,6 +61,10 @@ const dashboardStore = useDashboardStore();
function removeWidget() {
dashboardStore.removeControls(props.data);
}
+function editConfig() {
+ dashboardStore.setConfigPanel(true);
+ dashboardStore.selectWidget(props.data);
+}
</script>
<style lang="scss" scoped>
.event-wrapper {
diff --git a/src/views/dashboard/graphs/Area.vue b/src/views/dashboard/graphs/Area.vue
index aaf5a5c..66c1fb4 100644
--- a/src/views/dashboard/graphs/Area.vue
+++ b/src/views/dashboard/graphs/Area.vue
@@ -38,9 +38,13 @@ defineProps({
type: Object as PropType<
AreaConfig & {
filters: {
- value: number | string;
- dataIndex: number;
sourceId: string;
+ duration: {
+ startTime: string;
+ endTime: string;
+ };
+ isRange: boolean;
+ dataIndex?: number;
};
} & { id: string }
>,
diff --git a/src/views/dashboard/graphs/Bar.vue b/src/views/dashboard/graphs/Bar.vue
index 70e2def..e6d9da1 100644
--- a/src/views/dashboard/graphs/Bar.vue
+++ b/src/views/dashboard/graphs/Bar.vue
@@ -18,7 +18,6 @@ limitations under the License. -->
<script lang="ts" setup>
import { computed } from "vue";
import type { PropType } from "vue";
-import { Event } from "@/types/events";
import { BarConfig, EventParams } from "@/types/dashboard";
/*global defineProps, defineEmits */
@@ -30,14 +29,17 @@ const props = defineProps({
},
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
theme: { type: String, default: "light" },
- itemEvents: { type: Array as PropType<Event[]>, default: () => [] },
config: {
type: Object as PropType<
BarConfig & {
filters: {
- value: number | string;
- dataIndex: number;
sourceId: string;
+ duration: {
+ startTime: string;
+ endTime: string;
+ };
+ isRange: boolean;
+ dataIndex?: number;
};
} & { id: string }
>,
@@ -50,30 +52,7 @@ function getOption() {
const keys = Object.keys(props.data || {}).filter(
(i: any) => Array.isArray(props.data[i]) && props.data[i].length
);
- const startP = keys.length > 1 ? 50 : 15;
- const diff = 15;
- const markAreas = (props.itemEvents || []).map(
- (event: Event, index: number) => {
- return [
- {
- name: `${event.name}:${event.type}`,
- xAxis: event.startTime,
- y: startP + diff * index,
- itemStyle: {
- borderWidth: 2,
- borderColor: event.type === "Normal" ? "#5dc859" : "#FF0087",
- color: event.type === "Normal" ? "#5dc859" : "#FF0087",
- },
- },
- {
- name: event.message,
- xAxis: event.endTime,
- y: startP + diff * (index + 1),
- },
- ];
- }
- );
- const temp = keys.map((i: string, index: number) => {
+ const temp = keys.map((i: string) => {
if (!props.intervalTime) {
return;
}
@@ -94,23 +73,6 @@ function getOption() {
backgroundStyle: {
color: "rgba(180, 180, 180, 0.1)",
},
- markArea:
- index === 0
- ? {
- silent: false,
- data: markAreas,
- label: {
- show: false,
- width: 60,
- },
- emphasis: {
- label: {
- position: "bottom",
- show: true,
- },
- },
- }
- : undefined,
};
});
let color: string[] = [];
diff --git a/src/views/dashboard/graphs/Line.vue b/src/views/dashboard/graphs/Line.vue
index 3017903..286a633 100644
--- a/src/views/dashboard/graphs/Line.vue
+++ b/src/views/dashboard/graphs/Line.vue
@@ -18,7 +18,6 @@ limitations under the License. -->
<script lang="ts" setup>
import { computed } from "vue";
import type { PropType } from "vue";
-import { Event } from "@/types/events";
import { LineConfig, EventParams } from "@/types/dashboard";
/*global defineProps, defineEmits */
@@ -30,14 +29,17 @@ const props = defineProps({
},
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
theme: { type: String, default: "light" },
- itemEvents: { type: Array as PropType<Event[]>, default: () => [] },
config: {
type: Object as PropType<
LineConfig & {
filters: {
- value: number | string;
- dataIndex: number;
sourceId: string;
+ duration: {
+ startTime: string;
+ endTime: string;
+ };
+ isRange: boolean;
+ dataIndex?: number;
};
} & { id: string }
>,
@@ -58,30 +60,7 @@ function getOption() {
const keys = Object.keys(props.data || {}).filter(
(i: any) => Array.isArray(props.data[i]) && props.data[i].length
);
- const startP = keys.length > 1 ? 50 : 15;
- const diff = 10;
- const markAreas = (props.itemEvents || []).map(
- (event: Event, index: number) => {
- return [
- {
- name: `${event.name}:${event.type}`,
- xAxis: event.startTime,
- y: startP + diff * index,
- itemStyle: {
- borderWidth: 2,
- borderColor: event.type === "Normal" ? "#5dc859" : "#FF0087",
- color: event.type === "Normal" ? "#5dc859" : "#FF0087",
- },
- },
- {
- name: event.message,
- xAxis: event.endTime,
- y: startP + diff * (index + 1),
- },
- ];
- }
- );
- const temp = keys.map((i: any, index: number) => {
+ const temp = keys.map((i: any) => {
const serie: any = {
data: props.data[i].map((item: any, itemIndex: number) => [
props.intervalTime[itemIndex],
@@ -98,23 +77,6 @@ function getOption() {
width: 1.5,
type: "solid",
},
- markArea:
- index === 0
- ? {
- silent: false,
- data: markAreas,
- label: {
- show: false,
- width: 60,
- },
- emphasis: {
- label: {
- position: "bottom",
- show: true,
- },
- },
- }
- : undefined,
};
if (props.config.type === "Area") {
serie.areaStyle = {
diff --git a/src/views/dashboard/related/event/Content.vue b/src/views/dashboard/related/event/Content.vue
index d502375..4786e7b 100644
--- a/src/views/dashboard/related/event/Content.vue
+++ b/src/views/dashboard/related/event/Content.vue
@@ -19,15 +19,23 @@ limitations under the License. -->
import { ref, watch, onMounted } from "vue";
import dayjs from "dayjs";
import { useThrottleFn } from "@vueuse/core";
+import { Event } from "@/types/events";
+import { LayoutConfig } from "@/types/dashboard";
import { useEventStore } from "@/store/modules/event";
import { DataSet, Timeline } from "vis-timeline/standalone";
import "vis-timeline/styles/vis-timeline-graph2d.css";
+import { useDashboardStore } from "@/store/modules/dashboard";
+import getDashboard from "@/hooks/useDashboardsSession";
+import { dateFormatTime } from "@/utils/dateFormat";
+import { useAppStoreWithOut } from "@/store/modules/app";
const eventStore = useEventStore();
/*global Nullable */
const timeline = ref<Nullable<HTMLDivElement>>(null);
const visGraph = ref<Nullable<any>>(null);
const oldVal = ref<{ width: number; height: number }>({ width: 0, height: 0 });
+const dashboardStore = useDashboardStore();
+const appStore = useAppStoreWithOut();
const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
new Date(dayjs(date).format(pattern));
const visDate = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
@@ -49,12 +57,12 @@ function visTimeline() {
visGraph.value.destroy();
}
const h = timeline.value.getBoundingClientRect().height;
- const events = eventStore.events.map((d, index) => {
+ const events = eventStore.events.map((d: Event, index: number) => {
return {
id: index + 1,
content: d.name,
- start: dateFormat(d.startTime),
- end: dateFormat(d.endTime),
+ start: dateFormat(Number(d.startTime)),
+ end: dateFormat(Number(d.endTime)),
data: d,
className: d.type,
};
@@ -68,7 +76,7 @@ function visTimeline() {
autoResize: false,
tooltip: {
overflowMethod: "cap",
- template(item) {
+ template(item: Event | any) {
const data = item.data || {};
let tmp = `<div>ID: ${data.uuid || ""}</div>
<div>Name: ${data.name || ""}</div>
@@ -88,6 +96,38 @@ function visTimeline() {
},
};
visGraph.value = new Timeline(timeline.value, items, options);
+ visGraph.value.on("select", (properties: { items: number[] }) => {
+ if (!dashboardStore.selectedGrid.eventAssociate) {
+ return;
+ }
+ const all = getDashboard(dashboardStore.currentDashboard).widgets;
+ const widgets = all.filter(
+ (d: { value: string; label: string } & LayoutConfig) => {
+ const isLinear = ["Bar", "Line", "Area"].includes(
+ (d.graph && d.graph.type) || ""
+ );
+ if (isLinear) {
+ return d;
+ }
+ }
+ );
+ const index = properties.items[0];
+ const i = events[index - 1 || 0];
+
+ for (const widget of widgets) {
+ const startTime = dateFormatTime(i.start, appStore.duration.step);
+ const endTime = dateFormatTime(i.end, appStore.duration.step);
+ widget.filters = {
+ sourceId: dashboardStore.selectedGrid.id || "",
+ isRange: true,
+ duration: {
+ startTime,
+ endTime,
+ },
+ };
+ dashboardStore.setWidget(widget);
+ }
+ });
}
function resize() {
const observer = new ResizeObserver((entries) => {