refactor: update legend for topology

This commit is contained in:
Qiuxia Fan 2022-02-18 17:26:03 +08:00
parent 79dfd83df7
commit 1de7f1eaaf
3 changed files with 93 additions and 86 deletions

View File

@ -110,30 +110,51 @@ limitations under the License. -->
</div> </div>
<div class="legend-settings" v-show="isServer"> <div class="legend-settings" v-show="isServer">
<h5 class="title">{{ t("legendSettings") }}</h5> <h5 class="title">{{ t("legendSettings") }}</h5>
<div class="label">{{ t("metrics") }}</div> <div class="label">{{ t("conditions") }} (&&)</div>
<div v-for="(metric, index) of legend.metric" :key="metric.name + index">
<Selector <Selector
class="item mr-5" class="item"
:value="legend.metric.name" :value="metric.name"
:options="states.nodeMetricList" :options="states.nodeMetricList"
size="small" size="small"
placeholder="Select a metric" placeholder="Select a metric"
@change="changeLegend(LegendOpt.NAME, $event)" @change="changeLegend(LegendOpt.NAME, $event, index)"
/> />
<Selector <Selector
class="input-small mr-5" class="input-small"
:value="legend.metric.condition" :value="metric.condition"
:options="MetricConditions" :options="MetricConditions"
size="small" size="small"
placeholder="Select a condition" placeholder="Select a condition"
@change="changeLegend(LegendOpt.CONDITION, $event)" @change="changeLegend(LegendOpt.CONDITION, $event, index)"
/> />
<el-input <el-input
v-model="legend.metric.value" v-model="metric.value"
placeholder="Please input a value" placeholder="Please input a value"
@change="changeLegend(LegendOpt.VALUE, $event)" @change="changeLegend(LegendOpt.VALUE, $event, index)"
size="small" size="small"
class="item" class="item"
/> />
<span>
<Icon
class="cp delete"
iconName="remove_circle_outline"
size="middle"
@click="deleteMetric(index)"
v-show="legend.metric.length > 1"
/>
<Icon
class="cp"
iconName="add_circle_outlinecontrol_point"
size="middle"
v-show="
index === legend.metric.length - 1 && legend.metric.length < 5
"
@click="addMetric"
/>
</span>
<div v-show="index !== legend.metric.length - 1">&&</div>
</div>
<!-- <div class="label">{{ t("conditions") }}</div> <!-- <div class="label">{{ t("conditions") }}</div>
<Selector <Selector
class="inputs" class="inputs"
@ -143,30 +164,6 @@ limitations under the License. -->
placeholder="Select a condition" placeholder="Select a condition"
@change="changeCondition" @change="changeCondition"
/> --> /> -->
<!-- <div class="label">{{ t("metrics") }}</div>
<Selector
class="item mr-5"
:value="legend.secondMetric.name"
:options="states.nodeMetricList"
size="small"
placeholder="Select a metric"
@change="changeLegendMetric(LegendOpt.NAME, $event)"
/>
<Selector
class="input-small mr-5"
:value="legend.secondMetric.value"
:options="states.nodeMetricList"
size="small"
placeholder="Select a metric"
@change="changeLegendMetric(LegendOpt.CONDITION, $event)"
/>
<el-input
v-model="legend.secondMetric.condidtion"
placeholder="Please input a value"
@change="changeLegendMetric(LegendOpt.VALUE, $event)"
size="small"
class="item"
/> -->
<el-button <el-button
@click="setLegend" @click="setLegend"
class="legend-btn" class="legend-btn"
@ -224,10 +221,8 @@ const isServer = [EntityType[0].value, EntityType[1].value].includes(
dashboardStore.entity dashboardStore.entity
); );
const legend = reactive<{ const legend = reactive<{
metric: any; metric: { name: string; condition: string; value: string }[];
condition: string; }>({ metric: [{ name: "", condition: "", value: "" }] });
secondMetric: any;
}>({ metric: {}, condition: "", secondMetric: {} });
getMetricList(); getMetricList();
async function getMetricList() { async function getMetricList() {
@ -257,19 +252,23 @@ async function getMetricList() {
); );
} }
async function setLegend() { async function setLegend() {
if (!legend.metric.name) { const metrics = legend.metric.filter(
return; (d: any) => d.name && d.value && d.condition
} );
if (!legend.metric.value) { const names = metrics.map((d: any) => d.name);
return;
}
if (!legend.metric.condition) {
return;
}
updateSettings(); emit("update", {
linkDashboard: states.linkDashboard,
nodeDashboard: isServer
? items.filter((d: { scope: string; dashboard: string }) => d.dashboard)
: states.nodeDashboard,
linkServerMetrics: states.linkServerMetrics,
linkClientMetrics: states.linkClientMetrics,
nodeMetrics: states.nodeMetrics,
legend: metrics,
});
const ids = topologyStore.nodes.map((d: Node) => d.id); const ids = topologyStore.nodes.map((d: Node) => d.id);
const param = await useQueryTopologyMetrics([legend.metric.name], ids); const param = await useQueryTopologyMetrics(names, ids);
const res = await topologyStore.getLegendMetrics(param); const res = await topologyStore.getLegendMetrics(param);
if (res.errors) { if (res.errors) {
@ -277,15 +276,9 @@ async function setLegend() {
} }
emit("updateNodes"); emit("updateNodes");
} }
function changeLegend(type: string, opt: any) { function changeLegend(type: string, opt: any, index: number) {
legend.metric[type] = opt[0].value || opt; (legend.metric[index] as any)[type] = opt[0].value || opt;
} }
// function changeCondition(opt: Option[]) {
// legend.condition = opt[0].value;
// }
// function changeLegendMetric(type: string, opt: any) {
// legend.secondMetric[type] = opt[0].value || opt;
// }
function changeScope(index: number, opt: Option[]) { function changeScope(index: number, opt: Option[]) {
items[index].scope = opt[0].value; items[index].scope = opt[0].value;
items[index].dashboard = ""; items[index].dashboard = "";
@ -310,7 +303,7 @@ function updateSettings() {
linkServerMetrics: states.linkServerMetrics, linkServerMetrics: states.linkServerMetrics,
linkClientMetrics: states.linkClientMetrics, linkClientMetrics: states.linkClientMetrics,
nodeMetrics: states.nodeMetrics, nodeMetrics: states.nodeMetrics,
legend, legend: legend.metric,
}); });
} }
async function changeLinkServerMetrics(options: Option[]) { async function changeLinkServerMetrics(options: Option[]) {
@ -362,6 +355,12 @@ async function changeNodeMetrics(options: Option[]) {
ElMessage.error(res.errors); ElMessage.error(res.errors);
} }
} }
function deleteMetric(index: number) {
legend.metric.splice(index, 1);
}
function addMetric() {
legend.metric.push({ name: "", condition: "", value: "" });
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.link-settings { .link-settings {
@ -374,12 +373,13 @@ async function changeNodeMetrics(options: Option[]) {
} }
.item { .item {
width: 140px; width: 130px;
margin-top: 5px; margin-top: 5px;
} }
.input-small { .input-small {
width: 45px; width: 45px;
margin: 0 3px;
} }
.title { .title {
@ -395,4 +395,8 @@ async function changeNodeMetrics(options: Option[]) {
margin: 20px 0; margin: 20px 0;
cursor: pointer; cursor: pointer;
} }
.delete {
margin: 0 1px;
}
</style> </style>

View File

@ -37,9 +37,13 @@ export default function topoLegend(
.attr("x", clientWidth - (item === "CUBEERROR" ? 310 : 410)) .attr("x", clientWidth - (item === "CUBEERROR" ? 310 : 410))
.attr("y", clientHeight - 30) .attr("y", clientHeight - 30)
.text(() => { .text(() => {
const l = config || [];
const str = l
.map((d: any) => `${d.name} ${d.condition} ${d.value}`)
.join(" and ");
return item === "CUBEERROR" return item === "CUBEERROR"
? config ? config
? `Unhealthy (${config.metric.name} ${config.metric.condition} ${config.metric.value})` ? `Unhealthy (${str})`
: "Unhealthy" : "Unhealthy"
: "Healthy"; : "Healthy";
}) })

View File

@ -50,20 +50,19 @@ export default (d3: any, graph: any, funcs: any, tip: any, legend: any) => {
if (!legend) { if (!legend) {
return icons.CUBE; return icons.CUBE;
} }
const val = legend.metric.name.includes("_sla") if (!legend.length) {
? d[legend.metric.name] / 100
: d[legend.metric.name];
if (legend.metric.condition === "<") {
return val < Number(legend.metric.value) && d.isReal
? icons.CUBEERROR
: icons.CUBE;
}
if (legend.metric.condition === ">") {
return val > Number(legend.metric.value) && d.isReal
? icons.CUBEERROR
: icons.CUBE;
}
return icons.CUBE; return icons.CUBE;
}
let c = true;
for (const l of legend) {
const val = l.name.includes("_sla") ? d[l.name] / 100 : d[l.name];
if (l.condition === "<") {
c = c && val < Number(l.value);
} else {
c = c && val > Number(l.value);
}
}
return c && d.isReal ? icons.CUBEERROR : icons.CUBE;
}); });
nodeEnter nodeEnter
.append("image") .append("image")