feat: add content decorations to Table and Card widgets (#419)

This commit is contained in:
Fine0830 2024-10-15 16:25:21 +08:00 committed by GitHub
parent a92365efcf
commit 61449f4b17
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 128 additions and 4 deletions

View File

@ -386,5 +386,6 @@ const msg = {
tabExpressions: "Tab Expressions",
hierarchyNodeMetrics: "Metrics for Hierarchy Graph Node",
hierarchyNodeDashboard: "As dashboard for Hierarchy Graph Node",
contentDecorations: "Content Decorations",
};
export default msg;

View File

@ -386,5 +386,6 @@ const msg = {
tabExpressions: "Tab Expressions",
hierarchyNodeMetrics: "Metrics for Hierarchy Graph Node",
hierarchyNodeDashboard: "As dashboard for Hierarchy Graph Node",
contentDecorations: "Content Decorations",
};
export default msg;

View File

@ -384,5 +384,6 @@ const msg = {
tabExpressions: "Tab表达式",
hierarchyNodeMetrics: "层次图节点的指标",
hierarchyNodeDashboard: "作为层次图节点的dashboard",
contentDecorations: "内容装饰",
};
export default msg;

View File

@ -123,6 +123,7 @@ export interface CardConfig {
fontSize?: number;
showUnit?: boolean;
textAlign?: "center" | "right" | "left";
decorations?: { [key: string]: string };
}
export interface TextConfig {

View File

@ -32,6 +32,7 @@ limitations under the License. -->
:config="{
i: 0,
...graph,
decorations: graph?.decorations,
metricConfig: config.metricConfig,
expressions: config.expressions || [],
typesOfMQE: typesOfMQE || [],

View File

@ -32,7 +32,8 @@ limitations under the License. -->
:data="states.source"
:config="{
...graph,
legend: (dashboardStore.selectedGrid.graph || {}).legend,
decorations: dashboardStore.selectedGrid.graph?.decorations,
legend: dashboardStore.selectedGrid.graph?.legend,
i: dashboardStore.selectedGrid.i,
metricConfig: dashboardStore.selectedGrid.metricConfig,
relatedTrace: dashboardStore.selectedGrid.relatedTrace,

View File

@ -13,6 +13,10 @@ 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("contentDecorations") }}</span>
<content-decorations />
</div>
<div>
<span class="label">{{ t("fontSize") }}</span>
<el-slider
@ -26,7 +30,7 @@ limitations under the License. -->
@change="updateConfig({ fontSize })"
/>
</div>
<div class="item">
<div>
<span class="label">{{ t("showUnit") }}</span>
<el-switch v-model="showUnit" active-text="Yes" inactive-text="No" @change="updateConfig({ showUnit })" />
</div>
@ -35,6 +39,7 @@ limitations under the License. -->
import { ref } from "vue";
import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard";
import ContentDecorations from "./components/ContentDecorations.vue";
const { t } = useI18n();
const dashboardStore = useDashboardStore();

View File

@ -14,6 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<div>
<span class="label">{{ t("contentDecorations") }}</span>
<content-decorations />
</div>
<div class="item">
<span class="label">{{ t("showValues") }}</span>
<el-switch
v-model="showTableValues"
@ -37,6 +41,7 @@ limitations under the License. -->
import { ref } from "vue";
import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard";
import ContentDecorations from "./components/ContentDecorations.vue";
const { t } = useI18n();
const dashboardStore = useDashboardStore();

View File

@ -0,0 +1,100 @@
<!-- 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 v-for="(key, index) in keys" :key="index" class="mb-10 flex-h">
<div class="content-decoration" contenteditable="true" @blur="changeKeys($event, index)">
{{ key }}
</div>
<div class="ml-5 mr-10">:</div>
<div class="content-decoration" contenteditable="true" @blur="changeValues($event, key)">
{{ decorations[key] }}
</div>
<div v-if="index === keys.length - 1">
<Icon class="cp mr-5" iconName="add_circle_outlinecontrol_point" size="middle" @click="addDecoration" />
<Icon
v-if="index !== 0"
class="cp"
iconName="remove_circle_outline"
size="middle"
@click="deleteDecoration(index)"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import { useDashboardStore } from "@/store/modules/dashboard";
const dashboardStore = useDashboardStore();
const graph = dashboardStore.selectedGrid.graph;
const decorations = ref<{ [key: string]: string }>(graph?.decorations || {});
const keys = ref<string[]>(graph.decorations ? Object.keys(decorations.value) : [""]);
function changeKeys(event: any, index: number) {
const params = event.target.textContent || "";
const list = Object.keys(decorations.value);
if (params) {
decorations.value[params] = decorations.value[list[index]];
}
delete decorations.value[list[index]];
keys.value = Object.keys(decorations.value);
updateConfig({ decorations: decorations.value });
}
function changeValues(event: any, key: string) {
decorations.value[key] = event.target.textContent || "";
updateConfig({ decorations: decorations.value });
}
function addDecoration() {
keys.value.push("");
}
function deleteDecoration(index: number) {
if (!keys.value.length) {
return;
}
if (!keys.value[index]) {
return;
}
delete decorations.value[keys.value[index]];
keys.value.splice(index, 1);
updateConfig({ decorations: decorations.value });
}
function updateConfig(param: { [key: string]: unknown }) {
const graph = {
...dashboardStore.selectedGrid.graph,
...param,
};
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
}
</script>
<style lang="scss" scoped>
.content-decoration {
width: 200px;
border: 1px solid $border-color;
cursor: text;
padding: 0 5px;
border-radius: 3px;
outline: none;
margin-right: 5px;
min-height: 26px;
&:focus {
border-color: $active-color;
}
}
</style>

View File

@ -22,7 +22,7 @@ limitations under the License. -->
justifyContent: config.textAlign || 'center',
}"
>
{{ singleVal }}
{{ decorations[singleVal] || singleVal }}
<span class="unit" v-show="config.showUnit && unit">
{{ decodeURIComponent(unit) }}
</span>
@ -48,11 +48,13 @@ limitations under the License. -->
showUnit: true,
textAlign: "center",
metricConfig: [],
decorations: {},
}),
},
});
const { t } = useI18n();
const metricConfig = computed(() => props.config.metricConfig || []);
const decorations = computed(() => props.config.decorations || {});
const key = computed(() => Object.keys(props.data)[0]);
const singleVal = computed(() =>
Array.isArray(props.data[key.value]) ? props.data[key.value][0] : props.data[key.value],

View File

@ -37,7 +37,7 @@ limitations under the License. -->
>{{ k.split("=")[1] }}</div
>
<div class="value-col" v-if="config.showTableValues">
{{ data[(keys as string[]).join(",")][data[(keys as string[]).join(",")].length - 1 || 0] }}
{{ getColValue(keys) }}
</div>
</div>
</div>
@ -58,12 +58,14 @@ limitations under the License. -->
showTableValues: boolean;
tableHeaderCol2: string;
typesOfMQE: string[];
decorations: {};
}>,
default: () => ({ showTableValues: true }),
},
});
const { t } = useI18n();
const decorations = computed<{ [key: number]: string }>(() => props.config.decorations || {});
const nameWidth = computed(() => (props.config.showTableValues ? 80 : 100));
const dataKeys = computed(() => {
const keys = Object.keys(props.data || {}).filter(
@ -73,6 +75,10 @@ limitations under the License. -->
return list;
});
function getColValue(keys: string[]) {
const val = props.data[(keys as string[]).join(",")][props.data[(keys as string[]).join(",")].length - 1 || 0];
return decorations.value[val] || val;
}
</script>
<style lang="scss" scoped>
.chart-table {