feat: update legend

This commit is contained in:
Fine 2023-08-22 22:36:01 +08:00
parent 7a73b24587
commit f563ba59b8
5 changed files with 84 additions and 59 deletions

View File

@ -381,5 +381,6 @@ const msg = {
metricMode: "Metric Mode", metricMode: "Metric Mode",
addExpressions: "Add Expressions", addExpressions: "Add Expressions",
expressions: "Expression", expressions: "Expression",
unhealthyExpression: "Unhealthy Expression",
}; };
export default msg; export default msg;

View File

@ -381,5 +381,6 @@ const msg = {
metricMode: "Metric Mode", metricMode: "Metric Mode",
addExpressions: "Add Expressions", addExpressions: "Add Expressions",
expressions: "Expression", expressions: "Expression",
unhealthyExpression: "Unhealthy Expression",
}; };
export default msg; export default msg;

View File

@ -379,5 +379,6 @@ const msg = {
metricMode: "指标模式", metricMode: "指标模式",
addExpressions: "添加表达式", addExpressions: "添加表达式",
expressions: "表达式", expressions: "表达式",
unhealthyExpression: "非健康表达式",
}; };
export default msg; export default msg;

View File

@ -361,23 +361,27 @@ limitations under the License. -->
} }
async function initLegendMetrics() { async function initLegendMetrics() {
const names = props.config.legend.map((d: any) => d.name);
if (!names.length) {
return;
}
if (settings.value.metricMode === MetricModes.Expression) {
if (!topologyStore.nodes.length) { if (!topologyStore.nodes.length) {
return; return;
} }
const { getExpressionQuery } = useQueryTopologyExpressionsProcessor(names, topologyStore.nodes); if (settings.value.metricMode === MetricModes.Expression) {
const expression = props.config.legendMQE && props.config.legendMQE.expression;
if (!expression) {
return;
}
const { getExpressionQuery } = useQueryTopologyExpressionsProcessor([expression], topologyStore.nodes);
const param = getExpressionQuery(); const param = getExpressionQuery();
const res = await topologyStore.getNodeExpressionValue(param); const res = await topologyStore.getNodeExpressionValue(param);
if (res.errors) { if (res.errors) {
ElMessage.error(res.errors); ElMessage.error(res.errors);
} else { } else {
topologyStore.setLegendValues(names, res.data); topologyStore.setLegendValues([expression], res.data);
} }
} else { } else {
const names = props.config.legend.map((d: any) => d.name);
if (!names.length) {
return;
}
const ids = topologyStore.nodes.map((d: Node) => d.id); const ids = topologyStore.nodes.map((d: Node) => d.id);
if (ids.length) { if (ids.length) {
const param = await useQueryTopologyMetrics(names, ids); const param = await useQueryTopologyMetrics(names, ids);
@ -390,20 +394,22 @@ limitations under the License. -->
} }
function getNodeStatus(d: any) { function getNodeStatus(d: any) {
const legend = settings.value.legend; const { legend, legendMQE } = settings.value;
if (settings.value.metricMode === MetricModes.Expression) {
if (!legendMQE) {
return icons.CUBE;
}
if (!legendMQE.expression) {
return icons.CUBE;
}
return Number(d[legendMQE.expression]) && d.isReal ? icons.CUBEERROR : icons.CUBE;
}
if (!legend) { if (!legend) {
return icons.CUBE; return icons.CUBE;
} }
if (!legend.length) { if (!legend.length) {
return icons.CUBE; return icons.CUBE;
} }
if (settings.value.metricMode === MetricModes.Expression) {
let c = true;
for (const l of legend) {
c = c && !!Number(d[l.name]);
}
return c && d.isReal ? icons.CUBEERROR : icons.CUBE;
}
let c = true; let c = true;
for (const l of legend) { for (const l of legend) {
if (l.condition === "<") { if (l.condition === "<") {

View File

@ -13,11 +13,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<template> <template>
<div class="mb-10 mt-20"> <div class="mt-20">
<h5 class="title">{{ t("metricMode") }}</h5> <h5 class="title">{{ t("metricMode") }}</h5>
<el-switch <el-switch
v-model="isExpression" v-model="isExpression"
class="mb-5" class="mt-5"
active-text="Expressions" active-text="Expressions"
inactive-text="General" inactive-text="General"
size="small" size="small"
@ -196,17 +196,26 @@ limitations under the License. -->
</div> </div>
<div class="legend-settings" v-show="isService"> <div class="legend-settings" v-show="isService">
<h5 class="title">{{ t("legendSettings") }}</h5> <h5 class="title">{{ t("legendSettings") }}</h5>
<div class="label">{{ t("conditions") }}</div> <span v-if="isExpression">
<div v-for="(metric, index) of legend" :key="index"> <div class="label">Healthy Description</div>
<el-input <el-input v-model="description.healthy" placeholder="Please input description" size="small" class="mt-5" />
</span>
<div class="label">
<span>{{ t(isExpression ? "unhealthyExpression" : "conditions") }}</span>
<el-tooltip
class="cp"
v-if="isExpression" v-if="isExpression"
v-model="metric.name" content="The node would be red to indicate unhealthy status when the expression return greater than 0"
placeholder="Please input a expression" >
@change="changeLegend(LegendOpt.NAME, $event, index)" <span>
size="small" <Icon class="icon-help ml-5" iconName="help" size="small" />
class="legend-inputs" </span>
/> </el-tooltip>
<span v-else> </div>
<div v-if="isExpression">
<el-input v-model="legendMQE.expression" placeholder="Please input a expression" size="small" class="inputs" />
</div>
<div v-for="(metric, index) of legend" :key="index" v-else>
<Selector <Selector
class="item" class="item"
:value="metric.name" :value="metric.name"
@ -231,7 +240,6 @@ limitations under the License. -->
size="small" size="small"
class="item" class="item"
/> />
</span>
<span> <span>
<Icon class="cp delete" iconName="remove_circle_outline" size="middle" @click="deleteMetric(index)" /> <Icon class="cp delete" iconName="remove_circle_outline" size="middle" @click="deleteMetric(index)" />
<Icon <Icon
@ -244,8 +252,10 @@ limitations under the License. -->
</span> </span>
<div v-show="index !== legend.length - 1">&&</div> <div v-show="index !== legend.length - 1">&&</div>
</div> </div>
<span v-if="!isExpression">
<div class="label">Healthy Description</div> <div class="label">Healthy Description</div>
<el-input v-model="description.healthy" placeholder="Please input description" size="small" class="mt-5" /> <el-input v-model="description.healthy" placeholder="Please input description" size="small" class="mt-5" />
</span>
<div class="label">Unhealthy Description</div> <div class="label">Unhealthy Description</div>
<el-input v-model="description.unhealthy" placeholder="Please input description" size="small" class="mt-5" /> <el-input v-model="description.unhealthy" placeholder="Please input description" size="small" class="mt-5" />
<el-button @click="setLegend" class="legend-btn" size="small" type="primary"> <el-button @click="setLegend" class="legend-btn" size="small" type="primary">
@ -325,6 +335,7 @@ limitations under the License. -->
const legend = ref<{ name: string; condition: string; value: string }[]>( const legend = ref<{ name: string; condition: string; value: string }[]>(
l ? selectedGrid.legend : [{ name: "", condition: "", value: "" }], l ? selectedGrid.legend : [{ name: "", condition: "", value: "" }],
); );
const legendMQE = ref<{ expression: string }>(selectedGrid.legendMQE || { expression: "" });
const configType = ref<string>(""); const configType = ref<string>("");
const description = reactive<any>(selectedGrid.description || {}); const description = reactive<any>(selectedGrid.description || {});
@ -373,21 +384,26 @@ limitations under the License. -->
} }
async function setLegend() { async function setLegend() {
updateSettings(); updateSettings();
const names = dashboardStore.selectedGrid.legend.map((d: any) => d.name); if (isExpression.value) {
if (!names.length) { const expression = dashboardStore.selectedGrid.legendMQE && dashboardStore.selectedGrid.legendMQE.expression;
if (!expression) {
emit("updateNodes"); emit("updateNodes");
return; return;
} }
if (isExpression.value) { const { getExpressionQuery } = useQueryTopologyExpressionsProcessor([expression], topologyStore.nodes);
const { getExpressionQuery } = useQueryTopologyExpressionsProcessor(names, topologyStore.nodes);
const param = getExpressionQuery(); const param = getExpressionQuery();
const res = await topologyStore.getNodeExpressionValue(param); const res = await topologyStore.getNodeExpressionValue(param);
if (res.errors) { if (res.errors) {
ElMessage.error(res.errors); ElMessage.error(res.errors);
} else { } else {
topologyStore.setLegendValues(names, res.data); topologyStore.setLegendValues([expression], res.data);
} }
} else { } else {
const names = dashboardStore.selectedGrid.legend.map((d: any) => d.name && d.condition && d.value);
if (!names.length) {
emit("updateNodes");
return;
}
const ids = topologyStore.nodes.map((d: Node) => d.id); const ids = topologyStore.nodes.map((d: Node) => d.id);
const param = await useQueryTopologyMetrics(names, ids); const param = await useQueryTopologyMetrics(names, ids);
const res = await topologyStore.getLegendMetrics(param); const res = await topologyStore.getLegendMetrics(param);
@ -461,6 +477,7 @@ limitations under the License. -->
nodeExpressions: states.nodeExpressions, nodeExpressions: states.nodeExpressions,
metricMode: isExpression.value ? MetricModes.Expression : MetricModes.General, metricMode: isExpression.value ? MetricModes.Expression : MetricModes.General,
legend: metrics, legend: metrics,
legendMQE: legendMQE.value,
...metricConfig, ...metricConfig,
description, description,
}; };
@ -623,9 +640,8 @@ limitations under the License. -->
} }
.title { .title {
margin-bottom: 0;
margin-top: 0;
color: #666; color: #666;
margin-bottom: 0;
} }
.label { .label {