mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-01 22:14:28 +00:00
fix: update pagination for service list, endpoint list, instance list and add legend configs (#45)
This commit is contained in:
parent
355fe215a3
commit
61d182b986
@ -66,7 +66,7 @@ export function useQueryProcessor(config: any) {
|
|||||||
? selectorStore.currentService.normal
|
? selectorStore.currentService.normal
|
||||||
: true,
|
: true,
|
||||||
scope: config.catalog || dashboardStore.entity,
|
scope: config.catalog || dashboardStore.entity,
|
||||||
topN: 10,
|
topN: c.topN || 10,
|
||||||
order: c.sortOrder || "DES",
|
order: c.sortOrder || "DES",
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
@ -217,12 +217,10 @@ export const dashboardStore = defineStore({
|
|||||||
}
|
}
|
||||||
if (actived.length === 3) {
|
if (actived.length === 3) {
|
||||||
const tabIndex = Number(actived[1]);
|
const tabIndex = Number(actived[1]);
|
||||||
const itemIndex = this.layout[index].children[
|
this.currentTabItems = this.currentTabItems.filter(
|
||||||
tabIndex
|
(d: LayoutConfig) => actived[2] !== d.i
|
||||||
].children.findIndex((d: LayoutConfig) => actived[2] === d.i);
|
);
|
||||||
|
this.layout[index].children[tabIndex].children = this.currentTabItems;
|
||||||
this.layout[index].children[tabIndex].children.splice(itemIndex, 1);
|
|
||||||
this.setCurrentTabItems(this.layout[index].children[tabIndex].children);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.layout = this.layout.filter((d: LayoutConfig) => d.i !== item.i);
|
this.layout = this.layout.filter((d: LayoutConfig) => d.i !== item.i);
|
||||||
@ -260,7 +258,6 @@ export const dashboardStore = defineStore({
|
|||||||
const index = this.layout.findIndex(
|
const index = this.layout.findIndex(
|
||||||
(d: LayoutConfig) => actived[0] === d.i
|
(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[
|
const itemIndex = this.layout[index].children[
|
||||||
|
@ -45,6 +45,7 @@ export type MetricConfigOpt = {
|
|||||||
calculation: string;
|
calculation: string;
|
||||||
labelsIndex: string;
|
labelsIndex: string;
|
||||||
sortOrder: string;
|
sortOrder: string;
|
||||||
|
topN?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface WidgetConfig {
|
export interface WidgetConfig {
|
||||||
|
@ -16,9 +16,9 @@ limitations under the License. -->
|
|||||||
<div class="widget-config flex-v">
|
<div class="widget-config flex-v">
|
||||||
<div class="graph" v-loading="loading">
|
<div class="graph" v-loading="loading">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<span>{{ dashboardStore.selectedGrid.widget.title }}</span>
|
<span>{{ dashboardStore.selectedGrid.widget.title || "" }}</span>
|
||||||
<div class="tips" v-show="dashboardStore.selectedGrid.widget.tips">
|
<div class="tips" v-show="dashboardStore.selectedGrid.widget.tips">
|
||||||
<el-tooltip :content="dashboardStore.selectedGrid.widget.tips">
|
<el-tooltip :content="dashboardStore.selectedGrid.widget.tips || ''">
|
||||||
<Icon iconName="info_outline" size="sm" />
|
<Icon iconName="info_outline" size="sm" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,17 +13,15 @@ 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>
|
<div class="item">
|
||||||
<span class="label">{{ t("maxItemNum") }}</span>
|
<span class="label">{{ t("backgroundColors") }}</span>
|
||||||
<el-input
|
<Selector
|
||||||
class="input"
|
:value="color"
|
||||||
v-model="topN"
|
:options="Colors"
|
||||||
size="small"
|
size="small"
|
||||||
placeholder="none"
|
placeholder="Select a color"
|
||||||
type="number"
|
class="input"
|
||||||
:min="1"
|
@change="updateConfig({ color: $event[0].value })"
|
||||||
:max="100"
|
|
||||||
@change="updateConfig({ topN })"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -35,14 +33,24 @@ import { useDashboardStore } from "@/store/modules/dashboard";
|
|||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const { selectedGrid } = dashboardStore;
|
const { selectedGrid } = dashboardStore;
|
||||||
const topN = ref(selectedGrid.graph.topN);
|
const color = ref(selectedGrid.graph.color || "purple");
|
||||||
|
const Colors = [
|
||||||
|
{ label: "Purple", value: "purple" },
|
||||||
|
{
|
||||||
|
label: "Green",
|
||||||
|
value: "green",
|
||||||
|
},
|
||||||
|
{ label: "Blue", value: "blue" },
|
||||||
|
{ label: "Red", value: "red" },
|
||||||
|
{ label: "Orange", value: "orange" },
|
||||||
|
];
|
||||||
|
|
||||||
function updateConfig(param: { [key: string]: unknown }) {
|
function updateConfig(param: { [key: string]: unknown }) {
|
||||||
const graph = {
|
const graph = {
|
||||||
...selectedGrid.graph,
|
...dashboardStore.selectedGrid.graph,
|
||||||
...param,
|
...param,
|
||||||
};
|
};
|
||||||
dashboardStore.selectWidget({ ...selectedGrid, graph });
|
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@ -52,4 +60,8 @@ function updateConfig(param: { [key: string]: unknown }) {
|
|||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -410,7 +410,6 @@ function deleteMetric(index: number) {
|
|||||||
...{ metricTypes: states.metricTypes, metrics: states.metrics },
|
...{ metricTypes: states.metricTypes, metrics: states.metrics },
|
||||||
metricConfig,
|
metricConfig,
|
||||||
});
|
});
|
||||||
console.log(dashboardStore.selectedGrid);
|
|
||||||
}
|
}
|
||||||
function setMetricTypeList(type: string) {
|
function setMetricTypeList(type: string) {
|
||||||
if (type !== MetricsType.REGULAR_VALUE) {
|
if (type !== MetricsType.REGULAR_VALUE) {
|
||||||
|
@ -56,10 +56,7 @@ limitations under the License. -->
|
|||||||
:clearable="true"
|
:clearable="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="item" v-show="isTopn">
|
||||||
class="item"
|
|
||||||
v-show="['sortMetrics', 'readSampledRecords'].includes(metricType)"
|
|
||||||
>
|
|
||||||
<span class="label">{{ t("sortOrder") }}</span>
|
<span class="label">{{ t("sortOrder") }}</span>
|
||||||
<SelectSingle
|
<SelectSingle
|
||||||
:value="currentMetric.sortOrder || 'DES'"
|
:value="currentMetric.sortOrder || 'DES'"
|
||||||
@ -68,10 +65,22 @@ limitations under the License. -->
|
|||||||
@change="changeConfigs(index, { sortOrder: $event })"
|
@change="changeConfigs(index, { sortOrder: $event })"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="item" v-show="isTopn">
|
||||||
|
<span class="label">{{ t("maxItemNum") }}</span>
|
||||||
|
<el-input-number
|
||||||
|
class="selectors"
|
||||||
|
v-model="currentMetric.topN"
|
||||||
|
size="small"
|
||||||
|
placeholder="none"
|
||||||
|
:min="1"
|
||||||
|
:max="100"
|
||||||
|
@change="changeConfigs(index, { topN: currentMetric.topN || 10 })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch, computed } from "vue";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { SortOrder, CalculationOpts } from "../../../data";
|
import { SortOrder, CalculationOpts } from "../../../data";
|
||||||
@ -89,12 +98,22 @@ const props = defineProps({
|
|||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const emit = defineEmits(["update"]);
|
const emit = defineEmits(["update"]);
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const currentMetric = ref<MetricConfigOpt>(props.currentMetricConfig);
|
const currentMetric = ref<MetricConfigOpt>({
|
||||||
|
...props.currentMetricConfig,
|
||||||
|
topN: props.currentMetricConfig.topN || 10,
|
||||||
|
});
|
||||||
const metricType = ref<string>(
|
const metricType = ref<string>(
|
||||||
dashboardStore.selectedGrid.metricTypes[props.index]
|
dashboardStore.selectedGrid.metricTypes[props.index]
|
||||||
);
|
);
|
||||||
|
const isTopn = computed(() =>
|
||||||
function changeConfigs(index: number, param: { [key: string]: string }) {
|
["sortMetrics", "readSampledRecords"].includes(
|
||||||
|
dashboardStore.selectedGrid.metricTypes[props.index]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
function changeConfigs(
|
||||||
|
index: number,
|
||||||
|
param: { [key: string]: string | number }
|
||||||
|
) {
|
||||||
const metricConfig = dashboardStore.selectedGrid.metricConfig || [];
|
const metricConfig = dashboardStore.selectedGrid.metricConfig || [];
|
||||||
metricConfig[index] = { ...metricConfig[index], ...param };
|
metricConfig[index] = { ...metricConfig[index], ...param };
|
||||||
|
|
||||||
@ -107,7 +126,10 @@ function changeConfigs(index: number, param: { [key: string]: string }) {
|
|||||||
watch(
|
watch(
|
||||||
() => props.currentMetricConfig,
|
() => props.currentMetricConfig,
|
||||||
() => {
|
() => {
|
||||||
currentMetric.value = props.currentMetricConfig;
|
currentMetric.value = {
|
||||||
|
...props.currentMetricConfig,
|
||||||
|
topN: props.currentMetricConfig.topN || 10,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
@ -77,6 +77,7 @@ export const DefaultGraphConfig: { [key: string]: any } = {
|
|||||||
},
|
},
|
||||||
TopList: {
|
TopList: {
|
||||||
type: "TopList",
|
type: "TopList",
|
||||||
|
color: "purple",
|
||||||
},
|
},
|
||||||
InstanceList: {
|
InstanceList: {
|
||||||
type: "InstanceList",
|
type: "InstanceList",
|
||||||
@ -263,6 +264,7 @@ export const TextColors: { [key: string]: string } = {
|
|||||||
white: "#fff",
|
white: "#fff",
|
||||||
black: "#000",
|
black: "#000",
|
||||||
orange: "#E6A23C",
|
orange: "#E6A23C",
|
||||||
|
purple: "#bf99f8",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CalculationOpts = [
|
export const CalculationOpts = [
|
||||||
|
@ -117,16 +117,14 @@ const selectorStore = useSelectorStore();
|
|||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const chartLoading = ref<boolean>(false);
|
const chartLoading = ref<boolean>(false);
|
||||||
const endpoints = ref<Endpoint[]>([]);
|
const endpoints = ref<Endpoint[]>([]);
|
||||||
const pageSize = 15;
|
const pageSize = 10;
|
||||||
const total = 15;
|
|
||||||
const searchText = ref<string>("");
|
const searchText = ref<string>("");
|
||||||
|
|
||||||
queryEndpoints(total);
|
queryEndpoints();
|
||||||
|
|
||||||
async function queryEndpoints(limit?: number) {
|
async function queryEndpoints() {
|
||||||
chartLoading.value = true;
|
chartLoading.value = true;
|
||||||
const resp = await selectorStore.getEndpoints({
|
const resp = await selectorStore.getEndpoints({
|
||||||
limit,
|
|
||||||
keyword: searchText.value,
|
keyword: searchText.value,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -135,8 +133,10 @@ async function queryEndpoints(limit?: number) {
|
|||||||
ElMessage.error(resp.errors);
|
ElMessage.error(resp.errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
endpoints.value = selectorStore.pods.splice(0, pageSize);
|
endpoints.value = selectorStore.pods.filter(
|
||||||
await queryEndpointMetrics(endpoints.value);
|
(d: unknown, index: number) => index < pageSize
|
||||||
|
);
|
||||||
|
queryEndpointMetrics(endpoints.value);
|
||||||
}
|
}
|
||||||
async function queryEndpointMetrics(currentPods: Endpoint[]) {
|
async function queryEndpointMetrics(currentPods: Endpoint[]) {
|
||||||
if (!currentPods.length) {
|
if (!currentPods.length) {
|
||||||
@ -181,14 +181,15 @@ function clickEndpoint(scope: any) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
function changePage(pageIndex: number) {
|
function changePage(pageIndex: number) {
|
||||||
endpoints.value = selectorStore.pods.splice(
|
endpoints.value = selectorStore.pods.filter((d: unknown, index: number) => {
|
||||||
(pageIndex - 1 || 0) * pageSize,
|
if (index >= (pageIndex - 1) * pageSize && index < pageIndex * pageSize) {
|
||||||
pageSize * (pageIndex || 1)
|
return d;
|
||||||
);
|
}
|
||||||
|
});
|
||||||
|
queryEndpointMetrics(endpoints.value);
|
||||||
}
|
}
|
||||||
async function searchList() {
|
async function searchList() {
|
||||||
const limit = searchText.value ? undefined : total;
|
await queryEndpoints();
|
||||||
await queryEndpoints(limit);
|
|
||||||
}
|
}
|
||||||
function getUnit(index: number) {
|
function getUnit(index: number) {
|
||||||
const u =
|
const u =
|
||||||
@ -211,7 +212,7 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
() => selectorStore.currentService,
|
() => selectorStore.currentService,
|
||||||
() => {
|
() => {
|
||||||
queryEndpoints(total);
|
queryEndpoints();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
@ -90,7 +90,7 @@ limitations under the License. -->
|
|||||||
small
|
small
|
||||||
layout="prev, pager, next"
|
layout="prev, pager, next"
|
||||||
:page-size="pageSize"
|
:page-size="pageSize"
|
||||||
:total="searchInstances.length"
|
:total="selectorStore.pods.length"
|
||||||
@current-change="changePage"
|
@current-change="changePage"
|
||||||
@prev-click="changePage"
|
@prev-click="changePage"
|
||||||
@next-click="changePage"
|
@next-click="changePage"
|
||||||
@ -142,8 +142,7 @@ const selectorStore = useSelectorStore();
|
|||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const chartLoading = ref<boolean>(false);
|
const chartLoading = ref<boolean>(false);
|
||||||
const instances = ref<Instance[]>([]); // current instances
|
const instances = ref<Instance[]>([]); // current instances
|
||||||
const searchInstances = ref<Instance[]>([]); // all instances
|
const pageSize = 10;
|
||||||
const pageSize = 15;
|
|
||||||
const searchText = ref<string>("");
|
const searchText = ref<string>("");
|
||||||
|
|
||||||
queryInstance();
|
queryInstance();
|
||||||
@ -154,12 +153,12 @@ async function queryInstance() {
|
|||||||
chartLoading.value = false;
|
chartLoading.value = false;
|
||||||
if (resp && resp.errors) {
|
if (resp && resp.errors) {
|
||||||
ElMessage.error(resp.errors);
|
ElMessage.error(resp.errors);
|
||||||
searchInstances.value = [];
|
|
||||||
instances.value = [];
|
instances.value = [];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
searchInstances.value = selectorStore.pods;
|
instances.value = selectorStore.pods.filter(
|
||||||
instances.value = searchInstances.value.splice(0, pageSize);
|
(d: unknown, index: number) => index < pageSize
|
||||||
|
);
|
||||||
queryInstanceMetrics(instances.value);
|
queryInstanceMetrics(instances.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,14 +208,22 @@ function clickInstance(scope: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function changePage(pageIndex: number) {
|
function changePage(pageIndex: number) {
|
||||||
instances.value = searchInstances.value.splice(pageIndex - 1, pageSize);
|
instances.value = selectorStore.pods.filter((d: unknown, index: number) => {
|
||||||
|
if (index >= (pageIndex - 1) * pageSize && index < pageIndex * pageSize) {
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
queryInstanceMetrics(instances.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchList() {
|
function searchList() {
|
||||||
searchInstances.value = selectorStore.pods.filter((d: { label: string }) =>
|
const searchInstances = selectorStore.pods.filter((d: { label: string }) =>
|
||||||
d.label.includes(searchText.value)
|
d.label.includes(searchText.value)
|
||||||
);
|
);
|
||||||
instances.value = searchInstances.value.splice(0, pageSize);
|
instances.value = searchInstances.filter(
|
||||||
|
(d: unknown, index: number) => index < pageSize
|
||||||
|
);
|
||||||
|
queryInstanceMetrics(instances.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUnit(index: number) {
|
function getUnit(index: number) {
|
||||||
|
@ -128,7 +128,7 @@ const props = defineProps({
|
|||||||
const selectorStore = useSelectorStore();
|
const selectorStore = useSelectorStore();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const chartLoading = ref<boolean>(false);
|
const chartLoading = ref<boolean>(false);
|
||||||
const pageSize = 15;
|
const pageSize = 10;
|
||||||
const services = ref<Service[]>([]);
|
const services = ref<Service[]>([]);
|
||||||
const searchText = ref<string>("");
|
const searchText = ref<string>("");
|
||||||
const groups = ref<any>({});
|
const groups = ref<any>({});
|
||||||
@ -144,8 +144,21 @@ async function queryServices() {
|
|||||||
if (resp.errors) {
|
if (resp.errors) {
|
||||||
ElMessage.error(resp.errors);
|
ElMessage.error(resp.errors);
|
||||||
}
|
}
|
||||||
setServices(selectorStore.services);
|
sortServices.value = selectorStore.services.sort((a: any, b: any) => {
|
||||||
queryServiceMetrics(services.value);
|
const groupA = a.group.toUpperCase();
|
||||||
|
const groupB = b.group.toUpperCase();
|
||||||
|
if (groupA < groupB) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (groupA > groupB) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
const s = sortServices.value.filter(
|
||||||
|
(d: Service, index: number) => index < pageSize
|
||||||
|
);
|
||||||
|
setServices(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setServices(arr: (Service & { merge: boolean })[]) {
|
function setServices(arr: (Service & { merge: boolean })[]) {
|
||||||
@ -164,23 +177,19 @@ function setServices(arr: (Service & { merge: boolean })[]) {
|
|||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
sortServices.value = Object.values(map).flat(1);
|
const list = Object.values(map).flat(1);
|
||||||
const obj = {} as any;
|
const obj = {} as any;
|
||||||
for (const s of sortServices.value) {
|
for (const s of list) {
|
||||||
s.group = s.group || "";
|
s.group = s.group || "";
|
||||||
if (!obj[s.group]) {
|
if (!obj[s.group]) {
|
||||||
obj[s.group] = 1;
|
obj[s.group] = 1;
|
||||||
} else {
|
} else {
|
||||||
if (obj[s.group] % 5 === 0) {
|
|
||||||
s.merge = false;
|
|
||||||
}
|
|
||||||
obj[s.group]++;
|
obj[s.group]++;
|
||||||
}
|
}
|
||||||
groups.value[s.group] = obj[s.group];
|
groups.value[s.group] = obj[s.group];
|
||||||
}
|
}
|
||||||
services.value = sortServices.value.filter(
|
services.value = list;
|
||||||
(d: Service, index: number) => index < pageSize
|
queryServiceMetrics(services.value);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function clickService(scope: any) {
|
function clickService(scope: any) {
|
||||||
@ -240,20 +249,22 @@ function objectSpanMethod(param: any): any {
|
|||||||
return { rowspan: groups.value[param.row.group], colspan: 1 };
|
return { rowspan: groups.value[param.row.group], colspan: 1 };
|
||||||
}
|
}
|
||||||
function changePage(pageIndex: number) {
|
function changePage(pageIndex: number) {
|
||||||
services.value = sortServices.value.filter((d: Service, index: number) => {
|
const arr = sortServices.value.filter((d: Service, index: number) => {
|
||||||
if (
|
if (index >= (pageIndex - 1) * pageSize && index < pageSize * pageIndex) {
|
||||||
index >= (pageIndex - 1 || 0) * pageSize &&
|
|
||||||
index < pageSize * (pageIndex || 1)
|
|
||||||
) {
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setServices(arr);
|
||||||
}
|
}
|
||||||
function searchList() {
|
function searchList() {
|
||||||
const searchServices = sortServices.value.filter((d: { label: string }) =>
|
const searchServices = sortServices.value.filter((d: { label: string }) =>
|
||||||
d.label.includes(searchText.value)
|
d.label.includes(searchText.value)
|
||||||
);
|
);
|
||||||
services.value = searchServices.splice(0, pageSize);
|
const services = searchServices.filter(
|
||||||
|
(d: unknown, index: number) => index < pageSize
|
||||||
|
);
|
||||||
|
setServices(services);
|
||||||
}
|
}
|
||||||
function getUnit(index: number) {
|
function getUnit(index: number) {
|
||||||
const u =
|
const u =
|
||||||
|
@ -15,12 +15,12 @@ limitations under the License. -->
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="top-list">
|
<div class="top-list">
|
||||||
<div class="chart-slow-i" v-for="(i, index) in datas" :key="index">
|
<div class="chart-slow-i" v-for="(i, index) in data[key]" :key="index">
|
||||||
<div class="ell tools flex-h">
|
<div class="ell tools flex-h">
|
||||||
<div>
|
<div>
|
||||||
<span class="calls mr-10">{{ i.value }}</span>
|
<span class="calls mr-10">{{ i.value }}</span>
|
||||||
<span class="cp mr-20">
|
<span class="cp mr-20">
|
||||||
{{ i.name + getTraceId(i) }}
|
{{ i.name }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -28,14 +28,14 @@ limitations under the License. -->
|
|||||||
iconName="review-list"
|
iconName="review-list"
|
||||||
size="middle"
|
size="middle"
|
||||||
class="cp"
|
class="cp"
|
||||||
@click="handleClick((i.traceIds && i.traceIds[0]) || i.name)"
|
@click="handleClick(i.name)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-progress
|
<el-progress
|
||||||
:stroke-width="6"
|
:stroke-width="6"
|
||||||
:percentage="(i.value / maxValue) * 100"
|
:percentage="(i.value / maxValue) * 100"
|
||||||
color="#bf99f8"
|
:color="TextColors[config.color]"
|
||||||
:show-text="false"
|
:show-text="false"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -45,6 +45,7 @@ limitations under the License. -->
|
|||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import copy from "@/utils/copy";
|
import copy from "@/utils/copy";
|
||||||
|
import { TextColors } from "@/views/dashboard/data";
|
||||||
/*global defineProps */
|
/*global defineProps */
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
@ -54,12 +55,12 @@ const props = defineProps({
|
|||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
type: Object as PropType<{ sortOrder: string }>,
|
type: Object as PropType<{ color: string }>,
|
||||||
default: () => ({}),
|
default: () => ({ color: "purple" }),
|
||||||
},
|
},
|
||||||
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
|
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
|
||||||
});
|
});
|
||||||
const key = computed(() => Object.keys(props.data)[0]);
|
const key = computed(() => Object.keys(props.data)[0] || "");
|
||||||
const maxValue = computed(() => {
|
const maxValue = computed(() => {
|
||||||
if (!(props.data[key.value] && props.data[key.value].length)) {
|
if (!(props.data[key.value] && props.data[key.value].length)) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -67,30 +68,6 @@ const maxValue = computed(() => {
|
|||||||
const temp: number[] = props.data[key.value].map((i: any) => i.value);
|
const temp: number[] = props.data[key.value].map((i: any) => i.value);
|
||||||
return Math.max.apply(null, temp);
|
return Math.max.apply(null, temp);
|
||||||
});
|
});
|
||||||
const getTraceId = (i: { [key: string]: (number | string)[] }): string => {
|
|
||||||
return i.traceIds && i.traceIds[0] ? ` - ${i.traceIds[0]}` : "";
|
|
||||||
};
|
|
||||||
const datas = computed(() => {
|
|
||||||
if (!(props.data[key.value] && props.data[key.value].length)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
const { sortOrder } = props.config;
|
|
||||||
const val: any = props.data[key.value];
|
|
||||||
|
|
||||||
switch (sortOrder) {
|
|
||||||
case "DES":
|
|
||||||
val.sort((a: any, b: any) => b.value - a.value);
|
|
||||||
break;
|
|
||||||
case "ASC":
|
|
||||||
val.sort((a: any, b: any) => a.value - b.value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
val.sort((a: any, b: any) => b.value - a.value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
|
||||||
});
|
|
||||||
function handleClick(i: string) {
|
function handleClick(i: string) {
|
||||||
copy(i);
|
copy(i);
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,12 @@ async function init() {
|
|||||||
svg.value.call(zoom(d3, graph.value));
|
svg.value.call(zoom(d3, graph.value));
|
||||||
// legend
|
// legend
|
||||||
legend.value = graph.value.append("g").attr("class", "topo-legend");
|
legend.value = graph.value.append("g").attr("class", "topo-legend");
|
||||||
topoLegend(legend.value, height.value, width.value, settings.value.legend);
|
topoLegend(
|
||||||
|
legend.value,
|
||||||
|
height.value,
|
||||||
|
width.value,
|
||||||
|
settings.value.description
|
||||||
|
);
|
||||||
svg.value.on("click", (event: any) => {
|
svg.value.on("click", (event: any) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -192,6 +192,7 @@ limitations under the License. -->
|
|||||||
<el-input
|
<el-input
|
||||||
v-model="metric.value"
|
v-model="metric.value"
|
||||||
placeholder="Please input a value"
|
placeholder="Please input a value"
|
||||||
|
type="number"
|
||||||
@change="changeLegend(LegendOpt.VALUE, $event, index)"
|
@change="changeLegend(LegendOpt.VALUE, $event, index)"
|
||||||
size="small"
|
size="small"
|
||||||
class="item"
|
class="item"
|
||||||
@ -215,6 +216,20 @@ limitations under the License. -->
|
|||||||
</span>
|
</span>
|
||||||
<div v-show="index !== legend.metric.length - 1">&&</div>
|
<div v-show="index !== legend.metric.length - 1">&&</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="label">Healthy Description</div>
|
||||||
|
<el-input
|
||||||
|
v-model="description.healthy"
|
||||||
|
placeholder="Please input description"
|
||||||
|
size="small"
|
||||||
|
class="mt-5"
|
||||||
|
/>
|
||||||
|
<div class="label">Unhealthy Description</div>
|
||||||
|
<el-input
|
||||||
|
v-model="description.unhealthy"
|
||||||
|
placeholder="Please input description"
|
||||||
|
size="small"
|
||||||
|
class="mt-5"
|
||||||
|
/>
|
||||||
<el-button
|
<el-button
|
||||||
@click="setLegend"
|
@click="setLegend"
|
||||||
class="legend-btn"
|
class="legend-btn"
|
||||||
@ -289,6 +304,7 @@ const legend = reactive<{
|
|||||||
metric: l ? selectedGrid.legend : [{ name: "", condition: "", value: "" }],
|
metric: l ? selectedGrid.legend : [{ name: "", condition: "", value: "" }],
|
||||||
});
|
});
|
||||||
const configType = ref<string>("");
|
const configType = ref<string>("");
|
||||||
|
const description = reactive<any>(selectedGrid.description || {});
|
||||||
|
|
||||||
getMetricList();
|
getMetricList();
|
||||||
async function getMetricList() {
|
async function getMetricList() {
|
||||||
@ -347,6 +363,10 @@ async function setLegend() {
|
|||||||
updateSettings();
|
updateSettings();
|
||||||
const ids = topologyStore.nodes.map((d: Node) => d.id);
|
const ids = topologyStore.nodes.map((d: Node) => d.id);
|
||||||
const names = dashboardStore.selectedGrid.legend.map((d: any) => d.name);
|
const names = dashboardStore.selectedGrid.legend.map((d: any) => d.name);
|
||||||
|
if (!names.length) {
|
||||||
|
emit("updateNodes");
|
||||||
|
return;
|
||||||
|
}
|
||||||
const param = await useQueryTopologyMetrics(names, ids);
|
const param = await useQueryTopologyMetrics(names, ids);
|
||||||
const res = await topologyStore.getLegendMetrics(param);
|
const res = await topologyStore.getLegendMetrics(param);
|
||||||
|
|
||||||
@ -413,6 +433,7 @@ function updateSettings(metricConfig?: { [key: string]: MetricConfigOpt[] }) {
|
|||||||
nodeMetrics: states.nodeMetrics,
|
nodeMetrics: states.nodeMetrics,
|
||||||
legend: metrics,
|
legend: metrics,
|
||||||
...metricConfig,
|
...metricConfig,
|
||||||
|
description,
|
||||||
};
|
};
|
||||||
dashboardStore.selectWidget(param);
|
dashboardStore.selectWidget(param);
|
||||||
dashboardStore.setConfigs(param);
|
dashboardStore.setConfigs(param);
|
||||||
@ -509,7 +530,7 @@ function setConfigType(type: string) {
|
|||||||
|
|
||||||
.inputs {
|
.inputs {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
width: 370px;
|
width: 355px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
|
@ -20,32 +20,25 @@ export default function topoLegend(
|
|||||||
graph: any,
|
graph: any,
|
||||||
clientHeight: number,
|
clientHeight: number,
|
||||||
clientWidth: number,
|
clientWidth: number,
|
||||||
config: any
|
description: any
|
||||||
) {
|
) {
|
||||||
for (const item of ["CUBE", "CUBEERROR"]) {
|
for (const item of ["CUBE", "CUBEERROR"]) {
|
||||||
graph
|
graph
|
||||||
.append("image")
|
.append("image")
|
||||||
.attr("width", 30)
|
.attr("width", 30)
|
||||||
.attr("height", 30)
|
.attr("height", 30)
|
||||||
.attr("x", clientWidth - (item === "CUBEERROR" ? 340 : 440))
|
.attr("x", clientWidth - (item === "CUBEERROR" ? 200 : 410))
|
||||||
.attr("y", clientHeight + 50)
|
.attr("y", clientHeight + 50)
|
||||||
.attr("xlink:href", () =>
|
.attr("xlink:href", () =>
|
||||||
item === "CUBEERROR" ? icons.CUBEERROR : icons.CUBE
|
item === "CUBEERROR" ? icons.CUBEERROR : icons.CUBE
|
||||||
);
|
);
|
||||||
graph
|
graph
|
||||||
.append("text")
|
.append("text")
|
||||||
.attr("x", clientWidth - (item === "CUBEERROR" ? 310 : 410))
|
.attr("x", clientWidth - (item === "CUBEERROR" ? 170 : 380))
|
||||||
.attr("y", clientHeight + 70)
|
.attr("y", clientHeight + 70)
|
||||||
.text(() => {
|
.text(() => {
|
||||||
const l = config || [];
|
const desc = description || {};
|
||||||
const str = l
|
return item === "CUBEERROR" ? desc.unhealthy || "" : desc.healthy || "";
|
||||||
.map((d: any) => `${d.name} ${d.condition} ${d.value}`)
|
|
||||||
.join(" and ");
|
|
||||||
return item === "CUBEERROR"
|
|
||||||
? config
|
|
||||||
? `Unhealthy (${str})`
|
|
||||||
: "Unhealthy"
|
|
||||||
: "Healthy";
|
|
||||||
})
|
})
|
||||||
.style("fill", "#efeff1")
|
.style("fill", "#efeff1")
|
||||||
.style("font-size", "11px");
|
.style("font-size", "11px");
|
||||||
|
@ -55,11 +55,10 @@ export default (d3: any, graph: any, funcs: any, tip: any, legend: any) => {
|
|||||||
}
|
}
|
||||||
let c = true;
|
let c = true;
|
||||||
for (const l of legend) {
|
for (const l of legend) {
|
||||||
const val = l.name.includes("_sla") ? d[l.name] / 100 : d[l.name];
|
|
||||||
if (l.condition === "<") {
|
if (l.condition === "<") {
|
||||||
c = c && val < Number(l.value);
|
c = c && d[l.name] < Number(l.value);
|
||||||
} else {
|
} else {
|
||||||
c = c && val > Number(l.value);
|
c = c && d[l.name] > Number(l.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return c && d.isReal ? icons.CUBEERROR : icons.CUBE;
|
return c && d.isReal ? icons.CUBEERROR : icons.CUBE;
|
||||||
|
Loading…
Reference in New Issue
Block a user