mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-10-14 11:21:29 +00:00
feat: support collapsing and expanding for the event widget (#503)
This commit is contained in:
@@ -413,5 +413,6 @@ const msg = {
|
|||||||
spanName: "Span name",
|
spanName: "Span name",
|
||||||
parentId: "Parent ID",
|
parentId: "Parent ID",
|
||||||
shareTrace: "Share This Trace",
|
shareTrace: "Share This Trace",
|
||||||
|
eventDefaultCollapse: "Default Collapse",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@@ -413,5 +413,6 @@ const msg = {
|
|||||||
spanName: "Nombre de Lapso",
|
spanName: "Nombre de Lapso",
|
||||||
parentId: "ID Padre",
|
parentId: "ID Padre",
|
||||||
shareTrace: "Compartir Traza",
|
shareTrace: "Compartir Traza",
|
||||||
|
eventDefaultCollapse: "Default Collapse",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@@ -411,5 +411,6 @@ const msg = {
|
|||||||
spanName: "跨度名称",
|
spanName: "跨度名称",
|
||||||
parentId: "父ID",
|
parentId: "父ID",
|
||||||
shareTrace: "分享Trace",
|
shareTrace: "分享Trace",
|
||||||
|
eventDefaultCollapse: "默认折叠",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@@ -253,9 +253,13 @@ export const dashboardStore = defineStore({
|
|||||||
setTopology(show: boolean) {
|
setTopology(show: boolean) {
|
||||||
this.showTopology = show;
|
this.showTopology = show;
|
||||||
},
|
},
|
||||||
setConfigs(param: LayoutConfig) {
|
setLayouts(param: LayoutConfig[]) {
|
||||||
const actived = this.activedGridItem.split("-");
|
this.layout = param;
|
||||||
|
},
|
||||||
|
setConfigs(param: LayoutConfig, gridIndex?: string) {
|
||||||
|
const actived = gridIndex || this.activedGridItem.split("-");
|
||||||
const index = this.layout.findIndex((d: LayoutConfig) => actived[0] === d.i);
|
const index = this.layout.findIndex((d: LayoutConfig) => actived[0] === d.i);
|
||||||
|
|
||||||
if (actived.length === 3) {
|
if (actived.length === 3) {
|
||||||
const tabIndex = Number(actived[1]);
|
const tabIndex = Number(actived[1]);
|
||||||
const itemIndex = (this.layout[index].children || [])[tabIndex].children.findIndex(
|
const itemIndex = (this.layout[index].children || [])[tabIndex].children.findIndex(
|
||||||
@@ -270,11 +274,13 @@ export const dashboardStore = defineStore({
|
|||||||
this.setCurrentTabItems((this.layout[index].children || [])[tabIndex].children);
|
this.setCurrentTabItems((this.layout[index].children || [])[tabIndex].children);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.layout[index] = {
|
const layout = JSON.parse(JSON.stringify(this.layout));
|
||||||
...this.layout[index],
|
layout[index] = {
|
||||||
|
...layout[index],
|
||||||
...param,
|
...param,
|
||||||
};
|
};
|
||||||
this.selectedGrid = this.layout[index];
|
this.setLayouts(layout);
|
||||||
|
this.selectedGrid = layout[index];
|
||||||
},
|
},
|
||||||
setWidget(param: LayoutConfig) {
|
setWidget(param: LayoutConfig) {
|
||||||
for (let i = 0; i < this.layout.length; i++) {
|
for (let i = 0; i < this.layout.length; i++) {
|
||||||
|
@@ -36,8 +36,8 @@ export const eventStore = defineStore({
|
|||||||
state: (): eventState => ({
|
state: (): eventState => ({
|
||||||
loading: false,
|
loading: false,
|
||||||
events: [],
|
events: [],
|
||||||
instances: [{ value: "", label: "All" }],
|
instances: [{ value: "0", label: "All" }],
|
||||||
endpoints: [{ value: "", label: "All" }],
|
endpoints: [{ value: "0", label: "All" }],
|
||||||
condition: null,
|
condition: null,
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
@@ -58,7 +58,7 @@ export const eventStore = defineStore({
|
|||||||
if (response.errors) {
|
if (response.errors) {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
this.instances = [{ value: "", label: "All" }, ...response.data.pods];
|
this.instances = [{ value: "0", label: "All" }, ...response.data.pods];
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
async getEndpoints(keyword?: string) {
|
async getEndpoints(keyword?: string) {
|
||||||
@@ -75,7 +75,7 @@ export const eventStore = defineStore({
|
|||||||
if (response.errors) {
|
if (response.errors) {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
this.endpoints = [{ value: "", label: "All" }, ...response.data.pods];
|
this.endpoints = [{ value: "0", label: "All" }, ...response.data.pods];
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
async getEvents() {
|
async getEvents() {
|
||||||
|
@@ -48,6 +48,7 @@ export interface LayoutConfig {
|
|||||||
id?: string;
|
id?: string;
|
||||||
associate?: { widgetId: string }[];
|
associate?: { widgetId: string }[];
|
||||||
eventAssociate?: boolean;
|
eventAssociate?: boolean;
|
||||||
|
eventDefaultCollapse?: boolean;
|
||||||
filters?: Filters;
|
filters?: Filters;
|
||||||
relatedTrace?: RelatedTrace;
|
relatedTrace?: RelatedTrace;
|
||||||
subExpressions?: string[];
|
subExpressions?: string[];
|
||||||
|
@@ -15,6 +15,10 @@ limitations under the License. -->
|
|||||||
<div class="config-label flex-h mr-20">{{ t("enableAssociate") }}</div>
|
<div class="config-label flex-h mr-20">{{ t("enableAssociate") }}</div>
|
||||||
<el-switch v-model="eventAssociate" active-text="Yes" inactive-text="No" @change="updateConfig" />
|
<el-switch v-model="eventAssociate" active-text="Yes" inactive-text="No" @change="updateConfig" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="config-item flex-h">
|
||||||
|
<div class="config-label flex-h mr-20">{{ t("eventDefaultCollapse") }}</div>
|
||||||
|
<el-switch v-model="eventDefaultCollapse" active-text="Yes" inactive-text="No" @change="updateConfig" />
|
||||||
|
</div>
|
||||||
<ConfigurationFooter />
|
<ConfigurationFooter />
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -28,10 +32,19 @@ limitations under the License. -->
|
|||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const eventAssociate = ref(dashboardStore.selectedGrid?.eventAssociate || false);
|
const eventAssociate = ref(dashboardStore.selectedGrid?.eventAssociate || false);
|
||||||
|
const eventDefaultCollapse = ref(
|
||||||
|
dashboardStore.selectedGrid?.eventDefaultCollapse === undefined
|
||||||
|
? true
|
||||||
|
: dashboardStore.selectedGrid?.eventDefaultCollapse,
|
||||||
|
);
|
||||||
|
|
||||||
function updateConfig() {
|
function updateConfig() {
|
||||||
const { selectedGrid } = dashboardStore;
|
const { selectedGrid } = dashboardStore;
|
||||||
|
|
||||||
dashboardStore.selectWidget({ ...selectedGrid, eventAssociate: eventAssociate.value } as LayoutConfig);
|
dashboardStore.selectWidget({
|
||||||
|
...selectedGrid,
|
||||||
|
eventAssociate: eventAssociate.value,
|
||||||
|
eventDefaultCollapse: eventDefaultCollapse.value,
|
||||||
|
} as LayoutConfig);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@@ -14,28 +14,37 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div class="event-wrapper flex-v">
|
<div class="event-wrapper flex-v">
|
||||||
<el-popover placement="bottom" trigger="click" :width="100" v-if="dashboardStore.editMode">
|
<div class="operations">
|
||||||
<template #reference>
|
<span class="cp" @click="handleCollapse">
|
||||||
<span class="delete cp">
|
<Icon iconName="sort" size="middle" />
|
||||||
<Icon iconName="ellipsis_v" size="middle" class="operation" />
|
</span>
|
||||||
</span>
|
<el-popover placement="bottom" trigger="click" :width="100" v-if="dashboardStore.editMode">
|
||||||
</template>
|
<template #reference>
|
||||||
<div class="tools" @click="editConfig">
|
<span class="cp">
|
||||||
<span>{{ t("edit") }}</span>
|
<Icon iconName="ellipsis_v" size="middle" />
|
||||||
</div>
|
</span>
|
||||||
<div class="tools" @click="removeWidget">
|
</template>
|
||||||
<span>{{ t("delete") }}</span>
|
<div class="tools" @click="editConfig">
|
||||||
</div>
|
<span>{{ t("edit") }}</span>
|
||||||
</el-popover>
|
</div>
|
||||||
<div class="header">
|
<div class="tools" @click="removeWidget">
|
||||||
<Header :needQuery="needQuery" />
|
<span>{{ t("delete") }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="event">
|
</el-popover>
|
||||||
<Content :data="data" />
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="event-inspector" v-if="collapsedState"> Event Timeline Inspector </div>
|
||||||
|
<Transition name="collapse" v-else>
|
||||||
|
<div class="timeline">
|
||||||
|
<Header :needQuery="needQuery" />
|
||||||
|
<div class="event mt-10">
|
||||||
|
<Content :data="data" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch, onMounted, nextTick } from "vue";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
@@ -54,6 +63,17 @@ limitations under the License. -->
|
|||||||
});
|
});
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
|
const collapsedState = ref(true);
|
||||||
|
const originalState = ref({ h: props.data.h });
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
collapsedState.value = props.data.eventDefaultCollapse === undefined ? true : props.data.eventDefaultCollapse;
|
||||||
|
if (collapsedState.value) {
|
||||||
|
dashboardStore.setConfigs({ ...props.data, ...{ h: 3 } }, props.data.i);
|
||||||
|
} else {
|
||||||
|
dashboardStore.setConfigs({ ...props.data, ...originalState.value }, props.data.i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function removeWidget() {
|
function removeWidget() {
|
||||||
dashboardStore.removeControls(props.data);
|
dashboardStore.removeControls(props.data);
|
||||||
@@ -62,6 +82,24 @@ limitations under the License. -->
|
|||||||
dashboardStore.setConfigPanel(true);
|
dashboardStore.setConfigPanel(true);
|
||||||
dashboardStore.selectWidget(props.data);
|
dashboardStore.selectWidget(props.data);
|
||||||
}
|
}
|
||||||
|
function handleCollapse() {
|
||||||
|
dashboardStore.activeGridItem(props.data.i);
|
||||||
|
collapsedState.value = !collapsedState.value;
|
||||||
|
if (collapsedState.value) {
|
||||||
|
dashboardStore.setConfigs({ ...props.data, ...{ h: 3 } });
|
||||||
|
} else {
|
||||||
|
dashboardStore.setConfigs({ ...props.data, ...originalState.value });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.data.h,
|
||||||
|
(newHeight) => {
|
||||||
|
if (!collapsedState.value) {
|
||||||
|
originalState.value = { h: newHeight };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.event-wrapper {
|
.event-wrapper {
|
||||||
@@ -72,14 +110,14 @@ limitations under the License. -->
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete {
|
.operations {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 5px;
|
top: 5px;
|
||||||
right: 3px;
|
right: 3px;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.timeline {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
font-size: $font-size-smaller;
|
font-size: $font-size-smaller;
|
||||||
border-bottom: 1px solid $border-color;
|
border-bottom: 1px solid $border-color;
|
||||||
@@ -103,4 +141,31 @@ limitations under the License. -->
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100% - 80px);
|
height: calc(100% - 80px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.collapse-enter-active,
|
||||||
|
.collapse-leave-active {
|
||||||
|
transition: all 0.8s ease;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse-enter-from,
|
||||||
|
.collapse-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
max-height: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse-enter-to,
|
||||||
|
.collapse-leave-from {
|
||||||
|
opacity: 1;
|
||||||
|
max-height: 1000px;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-inspector {
|
||||||
|
text-align: center;
|
||||||
|
line-height: 45px;
|
||||||
|
font-size: $font-size-normal;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -95,6 +95,8 @@ limitations under the License. -->
|
|||||||
:is-draggable="dashboardStore.editMode"
|
:is-draggable="dashboardStore.editMode"
|
||||||
:is-resizable="dashboardStore.editMode"
|
:is-resizable="dashboardStore.editMode"
|
||||||
@layout-updated="layoutUpdatedEvent"
|
@layout-updated="layoutUpdatedEvent"
|
||||||
|
:vertical-compact="true"
|
||||||
|
:auto-size="true"
|
||||||
>
|
>
|
||||||
<grid-item
|
<grid-item
|
||||||
v-for="item in dashboardStore.currentTabItems"
|
v-for="item in dashboardStore.currentTabItems"
|
||||||
|
@@ -122,10 +122,10 @@ limitations under the License. -->
|
|||||||
};
|
};
|
||||||
const metrics: { [key: string]: { source: { [key: string]: unknown }; typesOfMQE: string[] } } =
|
const metrics: { [key: string]: { source: { [key: string]: unknown }; typesOfMQE: string[] } } =
|
||||||
(await useDashboardQueryProcessor([config])) || {};
|
(await useDashboardQueryProcessor([config])) || {};
|
||||||
const params = metrics[data.value.i];
|
const params = metrics[data.value.i] || {};
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
state.source = params.source || {};
|
state.source = params.source || {};
|
||||||
typesOfMQE.value = params.typesOfMQE;
|
typesOfMQE.value = params.typesOfMQE || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeWidget() {
|
function removeWidget() {
|
||||||
|
@@ -23,6 +23,8 @@ limitations under the License. -->
|
|||||||
v-loading.fullscreen.lock="loading"
|
v-loading.fullscreen.lock="loading"
|
||||||
element-loading-text="Loading..."
|
element-loading-text="Loading..."
|
||||||
element-loading-background="rgba(122, 122, 122, 0.8)"
|
element-loading-background="rgba(122, 122, 122, 0.8)"
|
||||||
|
:vertical-compact="true"
|
||||||
|
:auto-size="true"
|
||||||
>
|
>
|
||||||
<grid-item
|
<grid-item
|
||||||
v-for="item in dashboardStore.layout"
|
v-for="item in dashboardStore.layout"
|
||||||
|
@@ -51,6 +51,7 @@ limitations under the License. -->
|
|||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
};
|
};
|
||||||
|
visTimeline();
|
||||||
useThrottleFn(resize, 500)();
|
useThrottleFn(resize, 500)();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -86,8 +86,8 @@ limitations under the License. -->
|
|||||||
const pageSize = 20;
|
const pageSize = 20;
|
||||||
const pageNum = ref<number>(1);
|
const pageNum = ref<number>(1);
|
||||||
const state = reactive<any>({
|
const state = reactive<any>({
|
||||||
instance: { value: "", label: "All", id: "" },
|
instance: { value: "0", label: "All" },
|
||||||
endpoint: { value: "", label: "All", id: "" },
|
endpoint: { value: "0", label: "All" },
|
||||||
eventType: { value: "", label: "All" },
|
eventType: { value: "", label: "All" },
|
||||||
});
|
});
|
||||||
const total = computed(() =>
|
const total = computed(() =>
|
||||||
@@ -99,8 +99,8 @@ limitations under the License. -->
|
|||||||
async function init() {
|
async function init() {
|
||||||
fetchSelectors();
|
fetchSelectors();
|
||||||
await queryEvents();
|
await queryEvents();
|
||||||
state.instance = { value: "", label: "All" };
|
state.instance = { value: "0", label: "All" };
|
||||||
state.endpoint = { value: "", label: "All" };
|
state.endpoint = { value: "0", label: "All" };
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchSelectors() {
|
function fetchSelectors() {
|
||||||
@@ -138,13 +138,13 @@ limitations under the License. -->
|
|||||||
state.instance = eventStore.instances[0];
|
state.instance = eventStore.instances[0];
|
||||||
}
|
}
|
||||||
async function queryEvents() {
|
async function queryEvents() {
|
||||||
let endpoint = state.endpoint.value,
|
let endpoint = state.endpoint.value === "0" ? undefined : state.endpoint.value,
|
||||||
instance = state.instance.value;
|
instance = state.instance.value === "0" ? undefined : state.instance.value;
|
||||||
if (dashboardStore.entity === EntityType[2].value) {
|
if (dashboardStore.entity === EntityType[2].value) {
|
||||||
endpoint = selectorStore.currentPod && selectorStore.currentPod.id;
|
endpoint = selectorStore.currentPod?.id;
|
||||||
}
|
}
|
||||||
if (dashboardStore.entity === EntityType[3].value) {
|
if (dashboardStore.entity === EntityType[3].value) {
|
||||||
instance = selectorStore.currentPod && selectorStore.currentPod.id;
|
instance = selectorStore.currentPod?.id;
|
||||||
}
|
}
|
||||||
if (!selectorStore.currentService) {
|
if (!selectorStore.currentService) {
|
||||||
return;
|
return;
|
||||||
|
Reference in New Issue
Block a user