mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-04-30 23:04:00 +00:00
feat: support ranges for Value Mappings (#421)
This commit is contained in:
parent
bddbe40974
commit
b6522f4555
@ -386,6 +386,7 @@ const msg = {
|
||||
tabExpressions: "Tab Expressions",
|
||||
hierarchyNodeMetrics: "Metrics for Hierarchy Graph Node",
|
||||
hierarchyNodeDashboard: "As dashboard for Hierarchy Graph Node",
|
||||
contentDecorations: "Content Decorations",
|
||||
valueMappings: "Value Mappings",
|
||||
mappingTip: "Notice: The mapping key is a Regex string, for instance, ^-?(0|[1-9][0-9]*|2)(\\.0+)?$",
|
||||
};
|
||||
export default msg;
|
||||
|
@ -386,6 +386,7 @@ const msg = {
|
||||
tabExpressions: "Tab Expressions",
|
||||
hierarchyNodeMetrics: "Metrics for Hierarchy Graph Node",
|
||||
hierarchyNodeDashboard: "As dashboard for Hierarchy Graph Node",
|
||||
contentDecorations: "Content Decorations",
|
||||
valueMappings: "Value Mappings",
|
||||
mappingTip: "Notice: The mapping key is a Regex string, for instance, ^-?(0|[1-9][0-9]*|2)(\\.0+)?$",
|
||||
};
|
||||
export default msg;
|
||||
|
@ -384,6 +384,7 @@ const msg = {
|
||||
tabExpressions: "Tab表达式",
|
||||
hierarchyNodeMetrics: "层次图节点的指标",
|
||||
hierarchyNodeDashboard: "作为层次图节点的dashboard",
|
||||
contentDecorations: "内容装饰",
|
||||
valueMappings: "值映射",
|
||||
mappingTip: "注意: 映射键是一个正则表达式字符串,比如 ^-?(0|[1-9][0-9]*|2)(\\.0+)?$",
|
||||
};
|
||||
export default msg;
|
||||
|
2
src/types/dashboard.d.ts
vendored
2
src/types/dashboard.d.ts
vendored
@ -123,7 +123,7 @@ export interface CardConfig {
|
||||
fontSize?: number;
|
||||
showUnit?: boolean;
|
||||
textAlign?: "center" | "right" | "left";
|
||||
decorations?: { [key: string]: string };
|
||||
valueMappings?: { [key: string]: string };
|
||||
}
|
||||
|
||||
export interface TextConfig {
|
||||
|
@ -32,7 +32,7 @@ limitations under the License. -->
|
||||
:config="{
|
||||
i: 0,
|
||||
...graph,
|
||||
decorations: graph?.decorations,
|
||||
valueMappings: graph?.valueMappings,
|
||||
metricConfig: config.metricConfig,
|
||||
expressions: config.expressions || [],
|
||||
typesOfMQE: typesOfMQE || [],
|
||||
|
@ -14,8 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License. -->
|
||||
<template>
|
||||
<div>
|
||||
<span class="label">{{ t("contentDecorations") }}</span>
|
||||
<content-decorations />
|
||||
<value-mappings />
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">{{ t("fontSize") }}</span>
|
||||
@ -39,7 +38,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";
|
||||
import ValueMappings from "./components/ValueMappings.vue";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
|
@ -14,8 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License. -->
|
||||
<template>
|
||||
<div>
|
||||
<span class="label">{{ t("contentDecorations") }}</span>
|
||||
<content-decorations />
|
||||
<value-mappings />
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="label">{{ t("showValues") }}</span>
|
||||
@ -41,7 +40,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";
|
||||
import ValueMappings from "./components/ValueMappings.vue";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
|
@ -13,13 +13,17 @@ 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("valueMappings") }}</span>
|
||||
<span class="label red">({{ t("mappingTip") }})</span>
|
||||
</div>
|
||||
<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] }}
|
||||
{{ valueMappings[key] }}
|
||||
</div>
|
||||
<div v-if="index === keys.length - 1">
|
||||
<Icon class="cp mr-5" iconName="add_circle_outlinecontrol_point" size="middle" @click="addDecoration" />
|
||||
@ -36,26 +40,28 @@ limitations under the License. -->
|
||||
<script lang="ts" setup>
|
||||
import { ref } from "vue";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
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) : [""]);
|
||||
const valueMappings = ref<{ [key: string]: string }>(graph?.valueMappings || {});
|
||||
const keys = ref<string[]>(graph.valueMappings ? Object.keys(valueMappings.value) : [""]);
|
||||
|
||||
function changeKeys(event: any, index: number) {
|
||||
const params = event.target.textContent || "";
|
||||
const list = Object.keys(decorations.value);
|
||||
const list = Object.keys(valueMappings.value);
|
||||
if (params) {
|
||||
decorations.value[params] = decorations.value[list[index]];
|
||||
valueMappings.value[params] = valueMappings.value[list[index]];
|
||||
}
|
||||
delete decorations.value[list[index]];
|
||||
keys.value = Object.keys(decorations.value);
|
||||
updateConfig({ decorations: decorations.value });
|
||||
delete valueMappings.value[list[index]];
|
||||
keys.value = Object.keys(valueMappings.value);
|
||||
updateConfig();
|
||||
}
|
||||
|
||||
function changeValues(event: any, key: string) {
|
||||
decorations.value[key] = event.target.textContent || "";
|
||||
updateConfig({ decorations: decorations.value });
|
||||
valueMappings.value[key] = event.target.textContent || "";
|
||||
updateConfig();
|
||||
}
|
||||
|
||||
function addDecoration() {
|
||||
@ -66,18 +72,15 @@ limitations under the License. -->
|
||||
if (!keys.value.length) {
|
||||
return;
|
||||
}
|
||||
if (!keys.value[index]) {
|
||||
return;
|
||||
}
|
||||
delete decorations.value[keys.value[index]];
|
||||
delete valueMappings.value[keys.value[index]];
|
||||
keys.value.splice(index, 1);
|
||||
updateConfig({ decorations: decorations.value });
|
||||
updateConfig();
|
||||
}
|
||||
|
||||
function updateConfig(param: { [key: string]: unknown }) {
|
||||
function updateConfig() {
|
||||
const graph = {
|
||||
...dashboardStore.selectedGrid.graph,
|
||||
...param,
|
||||
valueMappings: valueMappings.value,
|
||||
};
|
||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
|
||||
}
|
||||
@ -97,4 +100,10 @@ limitations under the License. -->
|
||||
border-color: $active-color;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
padding-right: 10px;
|
||||
}
|
||||
</style>
|
@ -22,7 +22,7 @@ limitations under the License. -->
|
||||
justifyContent: config.textAlign || 'center',
|
||||
}"
|
||||
>
|
||||
{{ decorations[singleVal] || singleVal }}
|
||||
{{ getValue() }}
|
||||
<span class="unit" v-show="config.showUnit && unit">
|
||||
{{ decodeURIComponent(unit) }}
|
||||
</span>
|
||||
@ -48,18 +48,31 @@ limitations under the License. -->
|
||||
showUnit: true,
|
||||
textAlign: "center",
|
||||
metricConfig: [],
|
||||
decorations: {},
|
||||
valueMappings: {},
|
||||
}),
|
||||
},
|
||||
});
|
||||
const { t } = useI18n();
|
||||
const metricConfig = computed(() => props.config.metricConfig || []);
|
||||
const decorations = computed(() => props.config.decorations || {});
|
||||
const valueMappings = computed(() => props.config.valueMappings || {});
|
||||
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],
|
||||
);
|
||||
const unit = computed(() => metricConfig.value[0] && encodeURIComponent(metricConfig.value[0].unit || ""));
|
||||
|
||||
function getValue() {
|
||||
if (valueMappings.value[singleVal.value]) {
|
||||
return valueMappings.value[singleVal.value];
|
||||
}
|
||||
const list = Object.keys(valueMappings.value);
|
||||
for (const i of list) {
|
||||
if (new RegExp(i).test(String(singleVal.value))) {
|
||||
return valueMappings.value[i] || singleVal.value;
|
||||
}
|
||||
}
|
||||
return singleVal.value;
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.chart-card {
|
||||
|
@ -58,14 +58,14 @@ limitations under the License. -->
|
||||
showTableValues: boolean;
|
||||
tableHeaderCol2: string;
|
||||
typesOfMQE: string[];
|
||||
decorations: {};
|
||||
valueMappings: {};
|
||||
}>,
|
||||
default: () => ({ showTableValues: true }),
|
||||
},
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
const decorations = computed<{ [key: number]: string }>(() => props.config.decorations || {});
|
||||
const valueMappings = computed<{ [key: string]: string }>(() => props.config.valueMappings || {});
|
||||
const nameWidth = computed(() => (props.config.showTableValues ? 80 : 100));
|
||||
const dataKeys = computed(() => {
|
||||
const keys = Object.keys(props.data || {}).filter(
|
||||
@ -75,9 +75,19 @@ 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;
|
||||
const source = props.data[(keys as string[]).join(",")][props.data[(keys as string[]).join(",")].length - 1 || 0];
|
||||
if (valueMappings.value[source]) {
|
||||
return valueMappings.value[source];
|
||||
}
|
||||
const list = Object.keys(valueMappings.value);
|
||||
for (const i of list) {
|
||||
if (new RegExp(i).test(String(source))) {
|
||||
return valueMappings.value[i] || source;
|
||||
}
|
||||
}
|
||||
return source;
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
Loading…
Reference in New Issue
Block a user