mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-02 22:13:12 +00:00
fix: polish pages and validate data (#46)
This commit is contained in:
parent
61d182b986
commit
767c92c60d
@ -13,10 +13,23 @@ 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 ref="chartRef" :style="`height:${height};width:${width};`"></div>
|
<div
|
||||||
|
v-if="available"
|
||||||
|
ref="chartRef"
|
||||||
|
:style="`height:${height};width:${width};`"
|
||||||
|
></div>
|
||||||
|
<div v-else class="no-data">No Data</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { watch, ref, Ref, onMounted, onBeforeUnmount, unref } from "vue";
|
import {
|
||||||
|
watch,
|
||||||
|
ref,
|
||||||
|
Ref,
|
||||||
|
onMounted,
|
||||||
|
onBeforeUnmount,
|
||||||
|
unref,
|
||||||
|
computed,
|
||||||
|
} from "vue";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { useECharts } from "@/hooks/useEcharts";
|
import { useECharts } from "@/hooks/useEcharts";
|
||||||
import { addResizeListener, removeResizeListener } from "@/utils/event";
|
import { addResizeListener, removeResizeListener } from "@/utils/event";
|
||||||
@ -31,11 +44,16 @@ const props = defineProps({
|
|||||||
height: { type: String, default: "100%" },
|
height: { type: String, default: "100%" },
|
||||||
width: { type: String, default: "100%" },
|
width: { type: String, default: "100%" },
|
||||||
option: {
|
option: {
|
||||||
type: Object as PropType<{ [key: string]: unknown }>,
|
type: Object as PropType<{ [key: string]: any }>,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const available = computed(
|
||||||
|
() =>
|
||||||
|
Array.isArray(props.option.series) &&
|
||||||
|
props.option.series[0] &&
|
||||||
|
props.option.series[0].data
|
||||||
|
);
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await setOptions(props.option);
|
await setOptions(props.option);
|
||||||
chartRef.value && addResizeListener(unref(chartRef), resize);
|
chartRef.value && addResizeListener(unref(chartRef), resize);
|
||||||
@ -65,3 +83,14 @@ onBeforeUnmount(() => {
|
|||||||
removeResizeListener(unref(chartRef), resize);
|
removeResizeListener(unref(chartRef), resize);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.no-data {
|
||||||
|
font-size: 12px;
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: horizontal;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -26,6 +26,8 @@ export enum MetricQueryTypes {
|
|||||||
export enum Calculations {
|
export enum Calculations {
|
||||||
Percentage = "percentage",
|
Percentage = "percentage",
|
||||||
ByteToKB = "byteToKB",
|
ByteToKB = "byteToKB",
|
||||||
|
ByteToMB = "ByteToMB",
|
||||||
|
ByteToGB = "ByteToGB",
|
||||||
Apdex = "apdex",
|
Apdex = "apdex",
|
||||||
Precision = "precision",
|
Precision = "precision",
|
||||||
ConvertSeconds = "convertSeconds",
|
ConvertSeconds = "convertSeconds",
|
||||||
|
@ -28,6 +28,9 @@ export function useQueryProcessor(config: any) {
|
|||||||
if (!(config.metrics && config.metrics[0])) {
|
if (!(config.metrics && config.metrics[0])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!(config.metricTypes && config.metricTypes[0])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const selectorStore = useSelectorStore();
|
const selectorStore = useSelectorStore();
|
||||||
@ -221,13 +224,19 @@ export function useQueryPodsMetrics(
|
|||||||
config: { metrics: string[]; metricTypes: string[] },
|
config: { metrics: string[]; metricTypes: string[] },
|
||||||
scope: string
|
scope: string
|
||||||
) {
|
) {
|
||||||
|
if (!(config.metrics && config.metrics[0])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(config.metricTypes && config.metricTypes[0])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const selectorStore = useSelectorStore();
|
const selectorStore = useSelectorStore();
|
||||||
const conditions: { [key: string]: unknown } = {
|
const conditions: { [key: string]: unknown } = {
|
||||||
duration: appStore.durationTime,
|
duration: appStore.durationTime,
|
||||||
};
|
};
|
||||||
const variables: string[] = [`$duration: Duration!`];
|
const variables: string[] = [`$duration: Duration!`];
|
||||||
const { currentService } = selectorStore;
|
const currentService = selectorStore.currentService || {};
|
||||||
const fragmentList = pods.map(
|
const fragmentList = pods.map(
|
||||||
(
|
(
|
||||||
d: (Instance | Endpoint | Service) & { normal: boolean },
|
d: (Instance | Endpoint | Service) & { normal: boolean },
|
||||||
@ -324,6 +333,12 @@ export function aggregation(val: number, config: any): number | string {
|
|||||||
case Calculations.ByteToKB:
|
case Calculations.ByteToKB:
|
||||||
data = val / 1024;
|
data = val / 1024;
|
||||||
break;
|
break;
|
||||||
|
case Calculations.ByteToMB:
|
||||||
|
data = val / 1024 / 1024;
|
||||||
|
break;
|
||||||
|
case Calculations.ByteToGB:
|
||||||
|
data = val / 1024 / 1024 / 1024;
|
||||||
|
break;
|
||||||
case Calculations.Apdex:
|
case Calculations.Apdex:
|
||||||
data = val / 10000;
|
data = val / 10000;
|
||||||
break;
|
break;
|
||||||
|
@ -38,8 +38,8 @@ const msg = {
|
|||||||
health: "Health",
|
health: "Health",
|
||||||
groupName: "Group Name",
|
groupName: "Group Name",
|
||||||
topologies: "Topologies",
|
topologies: "Topologies",
|
||||||
dataPanel: "Data Panel",
|
dataPanel: "Data Plane",
|
||||||
controlPanel: "Control Panel",
|
controlPanel: "Control Plane",
|
||||||
eventList: "Event List",
|
eventList: "Event List",
|
||||||
databasePanel: "Database Panel",
|
databasePanel: "Database Panel",
|
||||||
meshServicePanel: "Service Panel",
|
meshServicePanel: "Service Panel",
|
||||||
@ -129,6 +129,7 @@ const msg = {
|
|||||||
textAlign: "Text Align",
|
textAlign: "Text Align",
|
||||||
metricLabel: "Metric Label",
|
metricLabel: "Metric Label",
|
||||||
showUnit: "Show Unit",
|
showUnit: "Show Unit",
|
||||||
|
noGraph: "No Graph",
|
||||||
hourTip: "Select Hour",
|
hourTip: "Select Hour",
|
||||||
minuteTip: "Select Minute",
|
minuteTip: "Select Minute",
|
||||||
secondTip: "Select Second",
|
secondTip: "Select Second",
|
||||||
|
@ -129,6 +129,7 @@ const msg = {
|
|||||||
textAlign: "文本对齐",
|
textAlign: "文本对齐",
|
||||||
metricLabel: "指标标签",
|
metricLabel: "指标标签",
|
||||||
showUnit: "显示单位",
|
showUnit: "显示单位",
|
||||||
|
noGraph: "无图表",
|
||||||
hourTip: "选择小时",
|
hourTip: "选择小时",
|
||||||
minuteTip: "选择分钟",
|
minuteTip: "选择分钟",
|
||||||
secondTip: "选择秒数",
|
secondTip: "选择秒数",
|
||||||
|
@ -21,14 +21,6 @@ export const NewControl = {
|
|||||||
h: 12,
|
h: 12,
|
||||||
i: "0",
|
i: "0",
|
||||||
type: "Widget",
|
type: "Widget",
|
||||||
widget: {
|
|
||||||
title: "",
|
|
||||||
},
|
|
||||||
graph: {},
|
|
||||||
standard: {},
|
|
||||||
metrics: [""],
|
|
||||||
metricTypes: [""],
|
|
||||||
metricConfig: [],
|
|
||||||
};
|
};
|
||||||
export const TextConfig = {
|
export const TextConfig = {
|
||||||
fontColor: "white",
|
fontColor: "white",
|
||||||
|
@ -28,13 +28,12 @@ export interface LayoutConfig {
|
|||||||
w: number;
|
w: number;
|
||||||
h: number;
|
h: number;
|
||||||
i: string;
|
i: string;
|
||||||
widget: WidgetConfig;
|
widget?: WidgetConfig;
|
||||||
graph: GraphConfig;
|
graph?: GraphConfig;
|
||||||
standard: StandardConfig;
|
metrics?: string[];
|
||||||
metrics: string[];
|
|
||||||
type: string;
|
type: string;
|
||||||
metricTypes: string[];
|
metricTypes?: string[];
|
||||||
children?: any;
|
children?: { name: string; children: LayoutConfig[] }[];
|
||||||
activedTabIndex?: number;
|
activedTabIndex?: number;
|
||||||
metricConfig?: MetricConfigOpt[];
|
metricConfig?: MetricConfigOpt[];
|
||||||
}
|
}
|
||||||
@ -53,20 +52,6 @@ export interface WidgetConfig {
|
|||||||
tips?: string;
|
tips?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface StandardConfig {
|
|
||||||
sortOrder?: string;
|
|
||||||
unit?: string;
|
|
||||||
labelsIndex?: string;
|
|
||||||
metricLabels?: string;
|
|
||||||
plus?: string;
|
|
||||||
minus?: string;
|
|
||||||
multiply?: string;
|
|
||||||
divide?: string;
|
|
||||||
milliseconds?: string;
|
|
||||||
seconds?: string;
|
|
||||||
maxItemNum?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type GraphConfig =
|
export type GraphConfig =
|
||||||
| BarConfig
|
| BarConfig
|
||||||
| LineConfig
|
| LineConfig
|
||||||
|
@ -91,12 +91,13 @@ import { useDashboardStore } from "@/store/modules/dashboard";
|
|||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const originConfig = dashboardStore.selectedGrid;
|
const originConfig = dashboardStore.selectedGrid;
|
||||||
|
const graph = originConfig.graph || {};
|
||||||
const url = ref(originConfig.graph.url || "");
|
const url = ref(originConfig.graph.url || "");
|
||||||
const backgroundColor = ref(originConfig.graph.backgroundColor || "green");
|
const backgroundColor = ref(graph.backgroundColor || "green");
|
||||||
const fontColor = ref(originConfig.graph.fontColor || "white");
|
const fontColor = ref(graph.fontColor || "white");
|
||||||
const content = ref<string>(originConfig.graph.content || "");
|
const content = ref<string>(graph.content || "");
|
||||||
const fontSize = ref<number>(originConfig.graph.fontSize || 12);
|
const fontSize = ref<number>(graph.fontSize || 12);
|
||||||
const textAlign = ref(originConfig.graph.textAlign || "left");
|
const textAlign = ref(graph.textAlign || "left");
|
||||||
const Colors = [
|
const Colors = [
|
||||||
{
|
{
|
||||||
label: "Green",
|
label: "Green",
|
||||||
|
@ -48,9 +48,9 @@ import { Option } from "@/types/app";
|
|||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const { selectedGrid } = dashboardStore;
|
const graph = dashboardStore.selectedGrid.graph || {};
|
||||||
const showDepth = ref<boolean>(selectedGrid.graph.showDepth);
|
const showDepth = ref<boolean>(graph.showDepth);
|
||||||
const depth = ref<number>(selectedGrid.graph.depth || 2);
|
const depth = ref<number>(graph.depth || 2);
|
||||||
|
|
||||||
function applyConfig() {
|
function applyConfig() {
|
||||||
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
||||||
|
@ -16,20 +16,20 @@ 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>{{ widget.title || "" }}</span>
|
||||||
<div class="tips" v-show="dashboardStore.selectedGrid.widget.tips">
|
<div class="tips" v-show="widget.tips">
|
||||||
<el-tooltip :content="dashboardStore.selectedGrid.widget.tips || ''">
|
<el-tooltip :content="widget.tips || ''">
|
||||||
<Icon iconName="info_outline" size="sm" />
|
<Icon iconName="info_outline" size="sm" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="render-chart">
|
<div class="render-chart">
|
||||||
<component
|
<component
|
||||||
:is="dashboardStore.selectedGrid.graph.type"
|
:is="graph.type"
|
||||||
:intervalTime="appStoreWithOut.intervalTime"
|
:intervalTime="appStoreWithOut.intervalTime"
|
||||||
:data="states.source"
|
:data="states.source"
|
||||||
:config="{
|
:config="{
|
||||||
...dashboardStore.selectedGrid.graph,
|
...graph,
|
||||||
i: dashboardStore.selectedGrid.i,
|
i: dashboardStore.selectedGrid.i,
|
||||||
metrics: dashboardStore.selectedGrid.metrics,
|
metrics: dashboardStore.selectedGrid.metrics,
|
||||||
metricTypes: dashboardStore.selectedGrid.metricTypes,
|
metricTypes: dashboardStore.selectedGrid.metricTypes,
|
||||||
@ -38,7 +38,7 @@ limitations under the License. -->
|
|||||||
:isEdit="isEdit"
|
:isEdit="isEdit"
|
||||||
@changeOpt="setStatus"
|
@changeOpt="setStatus"
|
||||||
/>
|
/>
|
||||||
<div v-show="!dashboardStore.selectedGrid.graph.type" class="no-data">
|
<div v-show="!graph.type" class="no-data">
|
||||||
{{ t("noData") }}
|
{{ t("noData") }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -56,7 +56,7 @@ limitations under the License. -->
|
|||||||
/>
|
/>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
<el-collapse-item :title="t('graphStyles')" name="2">
|
<el-collapse-item :title="t('graphStyles')" name="2">
|
||||||
<component :is="`${dashboardStore.selectedGrid.graph.type}Config`" />
|
<component :is="`${graph.type}Config`" />
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
<el-collapse-item :title="t('widgetOptions')" name="3">
|
<el-collapse-item :title="t('widgetOptions')" name="3">
|
||||||
<WidgetOptions />
|
<WidgetOptions />
|
||||||
@ -74,7 +74,7 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { reactive, defineComponent, ref } from "vue";
|
import { reactive, defineComponent, ref, computed } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
@ -111,6 +111,8 @@ export default defineComponent({
|
|||||||
visType: [],
|
visType: [],
|
||||||
});
|
});
|
||||||
const originConfig = dashboardStore.selectedGrid;
|
const originConfig = dashboardStore.selectedGrid;
|
||||||
|
const widget = computed(() => dashboardStore.selectedGrid.widget || {});
|
||||||
|
const graph = computed(() => dashboardStore.selectedGrid.graph || {});
|
||||||
|
|
||||||
function getSource(source: unknown) {
|
function getSource(source: unknown) {
|
||||||
states.source = source;
|
states.source = source;
|
||||||
@ -148,6 +150,8 @@ export default defineComponent({
|
|||||||
setLoading,
|
setLoading,
|
||||||
setStatus,
|
setStatus,
|
||||||
isEdit,
|
isEdit,
|
||||||
|
widget,
|
||||||
|
graph,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -42,12 +42,13 @@ 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 title = ref<string>(selectedGrid.widget.title || "");
|
const widget = dashboardStore.selectedGrid.widget || {};
|
||||||
const tips = ref<string>(selectedGrid.widget.tips || "");
|
const title = ref<string>(widget.title || "");
|
||||||
|
const tips = ref<string>(widget.tips || "");
|
||||||
|
|
||||||
function updateWidgetConfig(param: { [key: string]: unknown }) {
|
function updateWidgetConfig(param: { [key: string]: unknown }) {
|
||||||
const widget = {
|
const widget = {
|
||||||
...selectedGrid.widget,
|
...dashboardStore.selectedGrid.widget,
|
||||||
...param,
|
...param,
|
||||||
};
|
};
|
||||||
dashboardStore.selectWidget({ ...selectedGrid, widget });
|
dashboardStore.selectWidget({ ...selectedGrid, widget });
|
||||||
|
@ -34,7 +34,8 @@ import { useDashboardStore } from "@/store/modules/dashboard";
|
|||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const fontSize = ref(dashboardStore.selectedGrid.graph.fontSize);
|
const graph = dashboardStore.selectedGrid.graph || {};
|
||||||
|
const fontSize = ref(graph.fontSize);
|
||||||
|
|
||||||
function updateConfig(param: { [key: string]: unknown }) {
|
function updateConfig(param: { [key: string]: unknown }) {
|
||||||
const graph = {
|
const graph = {
|
||||||
|
@ -43,9 +43,7 @@ limitations under the License. -->
|
|||||||
:value="states.metricTypes[index]"
|
:value="states.metricTypes[index]"
|
||||||
:options="states.metricTypeList[index]"
|
:options="states.metricTypeList[index]"
|
||||||
size="small"
|
size="small"
|
||||||
:disabled="
|
:disabled="graph.type && !states.isList && index !== 0"
|
||||||
dashboardStore.selectedGrid.graph.type && !states.isList && index !== 0
|
|
||||||
"
|
|
||||||
@change="changeMetricType(index, $event)"
|
@change="changeMetricType(index, $event)"
|
||||||
class="selectors"
|
class="selectors"
|
||||||
/>
|
/>
|
||||||
@ -85,11 +83,11 @@ limitations under the License. -->
|
|||||||
<div>{{ t("visualization") }}</div>
|
<div>{{ t("visualization") }}</div>
|
||||||
<div class="chart-types">
|
<div class="chart-types">
|
||||||
<span
|
<span
|
||||||
v-for="(type, index) in states.visTypes"
|
v-for="(type, index) in setVisTypes"
|
||||||
:key="index"
|
:key="index"
|
||||||
@click="changeChartType(type)"
|
@click="changeChartType(type)"
|
||||||
:class="{
|
:class="{
|
||||||
active: type.value === dashboardStore.selectedGrid.graph.type,
|
active: type.value === graph.type,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
{{ type.label }}
|
{{ type.label }}
|
||||||
@ -97,7 +95,7 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, ref } from "vue";
|
import { reactive, ref, computed } from "vue";
|
||||||
import { Option } from "@/types/app";
|
import { Option } from "@/types/app";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import {
|
import {
|
||||||
@ -124,24 +122,26 @@ import Standard from "./Standard.vue";
|
|||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const emit = defineEmits(["update", "loading", "changeOpt"]);
|
const emit = defineEmits(["update", "loading", "changeOpt"]);
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const { metrics, metricTypes, graph } = dashboardStore.selectedGrid;
|
const metrics = computed(() => dashboardStore.selectedGrid.metrics || []);
|
||||||
|
const graph = computed(() => dashboardStore.selectedGrid.graph || {});
|
||||||
|
const metricTypes = computed(
|
||||||
|
() => dashboardStore.selectedGrid.metricTypes || []
|
||||||
|
);
|
||||||
const states = reactive<{
|
const states = reactive<{
|
||||||
metrics: string[];
|
metrics: string[];
|
||||||
metricTypes: string[];
|
metricTypes: string[];
|
||||||
metricTypeList: Option[][];
|
metricTypeList: Option[][];
|
||||||
visTypes: Option[];
|
|
||||||
isList: boolean;
|
isList: boolean;
|
||||||
metricList: (Option & { type: string })[];
|
metricList: (Option & { type: string })[];
|
||||||
dashboardName: string;
|
dashboardName: string;
|
||||||
dashboardList: ((DashboardItem & { label: string; value: string }) | any)[];
|
dashboardList: ((DashboardItem & { label: string; value: string }) | any)[];
|
||||||
}>({
|
}>({
|
||||||
metrics: metrics && metrics.length ? metrics : [""],
|
metrics: metrics.value.length ? metrics.value : [""],
|
||||||
metricTypes: metricTypes && metricTypes.length ? metricTypes : [""],
|
metricTypes: metricTypes.value.length ? metricTypes.value : [""],
|
||||||
metricTypeList: [],
|
metricTypeList: [],
|
||||||
visTypes: [],
|
|
||||||
isList: false,
|
isList: false,
|
||||||
metricList: [],
|
metricList: [],
|
||||||
dashboardName: graph.dashboardName,
|
dashboardName: graph.value.dashboardName,
|
||||||
dashboardList: [{ label: "", value: "" }],
|
dashboardList: [{ label: "", value: "" }],
|
||||||
});
|
});
|
||||||
const currentMetricConfig = ref<MetricConfigOpt>({
|
const currentMetricConfig = ref<MetricConfigOpt>({
|
||||||
@ -152,15 +152,33 @@ const currentMetricConfig = ref<MetricConfigOpt>({
|
|||||||
sortOrder: "DES",
|
sortOrder: "DES",
|
||||||
});
|
});
|
||||||
|
|
||||||
states.isList = ListChartTypes.includes(graph.type);
|
states.isList = ListChartTypes.includes(graph.value.type);
|
||||||
const defaultLen = ref<number>(states.isList ? 5 : 20);
|
const defaultLen = ref<number>(states.isList ? 5 : 20);
|
||||||
states.visTypes = setVisTypes();
|
|
||||||
|
|
||||||
setDashboards();
|
setDashboards();
|
||||||
setMetricType();
|
setMetricType();
|
||||||
|
|
||||||
|
const setVisTypes = computed(() => {
|
||||||
|
let graphs = [];
|
||||||
|
if (dashboardStore.entity === EntityType[0].value) {
|
||||||
|
graphs = ChartTypes.filter(
|
||||||
|
(d: Option) =>
|
||||||
|
![ChartTypes[7].value, ChartTypes[8].value].includes(d.value)
|
||||||
|
);
|
||||||
|
} else if (dashboardStore.entity === EntityType[1].value) {
|
||||||
|
graphs = ChartTypes.filter(
|
||||||
|
(d: Option) => !PodsChartTypes.includes(d.value)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
graphs = ChartTypes.filter(
|
||||||
|
(d: Option) => !ListChartTypes.includes(d.value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return graphs;
|
||||||
|
});
|
||||||
|
|
||||||
async function setMetricType(chart?: any) {
|
async function setMetricType(chart?: any) {
|
||||||
const graph = chart || dashboardStore.selectedGrid.graph;
|
const g = chart || dashboardStore.selectedGrid.graph || {};
|
||||||
const json = await dashboardStore.fetchMetricList();
|
const json = await dashboardStore.fetchMetricList();
|
||||||
if (json.errors) {
|
if (json.errors) {
|
||||||
ElMessage.error(json.errors);
|
ElMessage.error(json.errors);
|
||||||
@ -172,7 +190,7 @@ async function setMetricType(chart?: any) {
|
|||||||
if (d.type === MetricsType.REGULAR_VALUE) {
|
if (d.type === MetricsType.REGULAR_VALUE) {
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
} else if (graph.type === "Table") {
|
} else if (g.type === "Table") {
|
||||||
if (
|
if (
|
||||||
d.type === MetricsType.LABELED_VALUE ||
|
d.type === MetricsType.LABELED_VALUE ||
|
||||||
d.type === MetricsType.REGULAR_VALUE
|
d.type === MetricsType.REGULAR_VALUE
|
||||||
@ -203,7 +221,7 @@ async function setMetricType(chart?: any) {
|
|||||||
...dashboardStore.selectedGrid,
|
...dashboardStore.selectedGrid,
|
||||||
metrics: states.metrics,
|
metrics: states.metrics,
|
||||||
metricTypes: states.metricTypes,
|
metricTypes: states.metricTypes,
|
||||||
graph,
|
graph: g,
|
||||||
});
|
});
|
||||||
states.metricTypeList = [];
|
states.metricTypeList = [];
|
||||||
for (const metric of metrics) {
|
for (const metric of metrics) {
|
||||||
@ -220,7 +238,7 @@ async function setMetricType(chart?: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setDashboards(type?: string) {
|
function setDashboards(type?: string) {
|
||||||
const graph = type || dashboardStore.selectedGrid.graph;
|
const chart = type || dashboardStore.selectedGrid.graph || {};
|
||||||
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
||||||
const arr = list.reduce(
|
const arr = list.reduce(
|
||||||
(
|
(
|
||||||
@ -229,9 +247,9 @@ function setDashboards(type?: string) {
|
|||||||
) => {
|
) => {
|
||||||
if (d.layer === dashboardStore.layerId) {
|
if (d.layer === dashboardStore.layerId) {
|
||||||
if (
|
if (
|
||||||
(d.entity === EntityType[0].value && graph.type === "ServiceList") ||
|
(d.entity === EntityType[0].value && chart.type === "ServiceList") ||
|
||||||
(d.entity === EntityType[2].value && graph.type === "EndpointList") ||
|
(d.entity === EntityType[2].value && chart.type === "EndpointList") ||
|
||||||
(d.entity === EntityType[3].value && graph.type === "InstanceList")
|
(d.entity === EntityType[3].value && chart.type === "InstanceList")
|
||||||
) {
|
) {
|
||||||
prev.push({
|
prev.push({
|
||||||
...d,
|
...d,
|
||||||
@ -248,26 +266,9 @@ function setDashboards(type?: string) {
|
|||||||
states.dashboardList = arr.length ? arr : [{ label: "", value: "" }];
|
states.dashboardList = arr.length ? arr : [{ label: "", value: "" }];
|
||||||
}
|
}
|
||||||
|
|
||||||
function setVisTypes() {
|
|
||||||
let graphs = [];
|
|
||||||
if (dashboardStore.entity === EntityType[0].value) {
|
|
||||||
graphs = ChartTypes.filter((d: Option) => d.value !== ChartTypes[7].value);
|
|
||||||
} else if (dashboardStore.entity === EntityType[1].value) {
|
|
||||||
graphs = ChartTypes.filter(
|
|
||||||
(d: Option) => !PodsChartTypes.includes(d.value)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
graphs = ChartTypes.filter(
|
|
||||||
(d: Option) => !ListChartTypes.includes(d.value)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return graphs;
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeChartType(item: Option) {
|
function changeChartType(item: Option) {
|
||||||
const graph = DefaultGraphConfig[item.value];
|
const chart = DefaultGraphConfig[item.value] || {};
|
||||||
states.isList = ListChartTypes.includes(graph.type);
|
states.isList = ListChartTypes.includes(chart.type);
|
||||||
if (states.isList) {
|
if (states.isList) {
|
||||||
dashboardStore.selectWidget({
|
dashboardStore.selectWidget({
|
||||||
...dashboardStore.selectedGrid,
|
...dashboardStore.selectedGrid,
|
||||||
@ -278,8 +279,8 @@ function changeChartType(item: Option) {
|
|||||||
states.metricTypes = [""];
|
states.metricTypes = [""];
|
||||||
defaultLen.value = 5;
|
defaultLen.value = 5;
|
||||||
}
|
}
|
||||||
setMetricType(graph);
|
setMetricType(chart);
|
||||||
setDashboards(graph.type);
|
setDashboards(chart.type);
|
||||||
states.dashboardName = "";
|
states.dashboardName = "";
|
||||||
defaultLen.value = 10;
|
defaultLen.value = 10;
|
||||||
}
|
}
|
||||||
@ -415,7 +416,7 @@ function setMetricTypeList(type: string) {
|
|||||||
if (type !== MetricsType.REGULAR_VALUE) {
|
if (type !== MetricsType.REGULAR_VALUE) {
|
||||||
return MetricTypes[type];
|
return MetricTypes[type];
|
||||||
}
|
}
|
||||||
if (states.isList || dashboardStore.selectedGrid.graph.type === "Table") {
|
if (states.isList || graph.value.type === "Table") {
|
||||||
return [
|
return [
|
||||||
{ label: "read all values in the duration", value: "readMetricsValues" },
|
{ label: "read all values in the duration", value: "readMetricsValues" },
|
||||||
{
|
{
|
||||||
|
@ -56,7 +56,7 @@ limitations under the License. -->
|
|||||||
:clearable="true"
|
:clearable="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="item" v-show="isTopn">
|
<div class="item mb-10" v-show="isTopn">
|
||||||
<span class="label">{{ t("sortOrder") }}</span>
|
<span class="label">{{ t("sortOrder") }}</span>
|
||||||
<SelectSingle
|
<SelectSingle
|
||||||
:value="currentMetric.sortOrder || 'DES'"
|
:value="currentMetric.sortOrder || 'DES'"
|
||||||
@ -67,11 +67,12 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
<div class="item" v-show="isTopn">
|
<div class="item" v-show="isTopn">
|
||||||
<span class="label">{{ t("maxItemNum") }}</span>
|
<span class="label">{{ t("maxItemNum") }}</span>
|
||||||
<el-input-number
|
<el-input
|
||||||
class="selectors"
|
class="selectors"
|
||||||
v-model="currentMetric.topN"
|
v-model="currentMetric.topN"
|
||||||
size="small"
|
size="small"
|
||||||
placeholder="none"
|
placeholder="none"
|
||||||
|
type="number"
|
||||||
:min="1"
|
:min="1"
|
||||||
:max="100"
|
:max="100"
|
||||||
@change="changeConfigs(index, { topN: currentMetric.topN || 10 })"
|
@change="changeConfigs(index, { topN: currentMetric.topN || 10 })"
|
||||||
@ -102,13 +103,10 @@ const currentMetric = ref<MetricConfigOpt>({
|
|||||||
...props.currentMetricConfig,
|
...props.currentMetricConfig,
|
||||||
topN: props.currentMetricConfig.topN || 10,
|
topN: props.currentMetricConfig.topN || 10,
|
||||||
});
|
});
|
||||||
const metricType = ref<string>(
|
const metricTypes = dashboardStore.selectedGrid.metricTypes || [];
|
||||||
dashboardStore.selectedGrid.metricTypes[props.index]
|
const metricType = ref<string>(metricTypes[props.index]);
|
||||||
);
|
|
||||||
const isTopn = computed(() =>
|
const isTopn = computed(() =>
|
||||||
["sortMetrics", "readSampledRecords"].includes(
|
["sortMetrics", "readSampledRecords"].includes(metricTypes[props.index])
|
||||||
dashboardStore.selectedGrid.metricTypes[props.index]
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
function changeConfigs(
|
function changeConfigs(
|
||||||
index: number,
|
index: number,
|
||||||
|
@ -17,17 +17,17 @@ limitations under the License. -->
|
|||||||
<div class="header flex-h">
|
<div class="header flex-h">
|
||||||
<div>
|
<div>
|
||||||
<span>
|
<span>
|
||||||
{{ data.widget?.title || "" }}
|
{{ widget.title || "" }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<el-tooltip :content="data.widget?.tips">
|
<el-tooltip :content="widget.tips || ''">
|
||||||
<span>
|
<span>
|
||||||
<Icon
|
<Icon
|
||||||
iconName="info_outline"
|
iconName="info_outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
class="operation"
|
class="operation"
|
||||||
v-show="data.widget?.tips"
|
v-show="widget.tips"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
@ -51,26 +51,26 @@ limitations under the License. -->
|
|||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="body" v-if="data.graph?.type" v-loading="loading">
|
<div class="body" v-if="graph.type" v-loading="loading">
|
||||||
<component
|
<component
|
||||||
:is="data.graph.type"
|
:is="graph.type"
|
||||||
:intervalTime="appStore.intervalTime"
|
:intervalTime="appStore.intervalTime"
|
||||||
:data="state.source"
|
:data="state.source"
|
||||||
:config="{
|
:config="{
|
||||||
...data.graph,
|
...data.graph,
|
||||||
metrics: data.metrics,
|
metrics: data.metrics || [''],
|
||||||
metricTypes: data.metricTypes,
|
metricTypes: data.metricTypes || [''],
|
||||||
i: data.i,
|
i: data.i,
|
||||||
metricConfig: data.metricConfig,
|
metricConfig: data.metricConfig,
|
||||||
}"
|
}"
|
||||||
:needQuery="needQuery"
|
:needQuery="needQuery"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="no-data">{{ t("noData") }}</div>
|
<div v-else class="no-data">{{ t("noGraph") }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { toRefs, reactive, defineComponent, ref, watch } from "vue";
|
import { toRefs, reactive, defineComponent, ref, watch, computed } from "vue";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { LayoutConfig } from "@/types/dashboard";
|
import { LayoutConfig } from "@/types/dashboard";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
@ -88,7 +88,7 @@ import { EntityType, ListChartTypes } from "../data";
|
|||||||
const props = {
|
const props = {
|
||||||
data: {
|
data: {
|
||||||
type: Object as PropType<LayoutConfig>,
|
type: Object as PropType<LayoutConfig>,
|
||||||
default: () => ({ widget: {} }),
|
default: () => ({ widget: {}, graph: {} }),
|
||||||
},
|
},
|
||||||
activeIndex: { type: String, default: "" },
|
activeIndex: { type: String, default: "" },
|
||||||
needQuery: { type: Boolean, default: false },
|
needQuery: { type: Boolean, default: false },
|
||||||
@ -107,14 +107,19 @@ export default defineComponent({
|
|||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const selectorStore = useSelectorStore();
|
const selectorStore = useSelectorStore();
|
||||||
const isList = ListChartTypes.includes(props.data.graph.type || "");
|
const graph = computed(() => props.data.graph || {});
|
||||||
|
const widget = computed(() => props.data.widget || {});
|
||||||
|
const isList = ListChartTypes.includes(
|
||||||
|
(props.data.graph && props.data.graph.type) || ""
|
||||||
|
);
|
||||||
|
|
||||||
if ((props.needQuery || !dashboardStore.currentDashboard.id) && !isList) {
|
if ((props.needQuery || !dashboardStore.currentDashboard.id) && !isList) {
|
||||||
queryMetrics();
|
queryMetrics();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function queryMetrics() {
|
async function queryMetrics() {
|
||||||
const { metricTypes, metrics } = props.data;
|
const metricTypes = props.data.metricTypes || [];
|
||||||
|
const metrics = props.data.metrics || [];
|
||||||
const catalog = await useGetMetricEntity(metrics[0], metricTypes[0]);
|
const catalog = await useGetMetricEntity(metrics[0], metricTypes[0]);
|
||||||
const params = await useQueryProcessor({ ...props.data, catalog });
|
const params = await useQueryProcessor({ ...props.data, catalog });
|
||||||
|
|
||||||
@ -129,8 +134,8 @@ export default defineComponent({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const d = {
|
const d = {
|
||||||
metrics: props.data.metrics,
|
metrics: props.data.metrics || [],
|
||||||
metricTypes: props.data.metricTypes,
|
metricTypes: props.data.metricTypes || [],
|
||||||
metricConfig: props.data.metricConfig || [],
|
metricConfig: props.data.metricConfig || [],
|
||||||
};
|
};
|
||||||
state.source = useSourceProcessor(json, d);
|
state.source = useSourceProcessor(json, d);
|
||||||
@ -149,7 +154,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
watch(
|
watch(
|
||||||
() => [props.data.metricTypes, props.data.metrics, props.data.standard],
|
() => [props.data.metricTypes, props.data.metrics],
|
||||||
() => {
|
() => {
|
||||||
if (!dashboardStore.selectedGrid) {
|
if (!dashboardStore.selectedGrid) {
|
||||||
return;
|
return;
|
||||||
@ -157,11 +162,11 @@ export default defineComponent({
|
|||||||
if (props.data.i !== dashboardStore.selectedGrid.i) {
|
if (props.data.i !== dashboardStore.selectedGrid.i) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const isList = ListChartTypes.includes(props.data.graph.type || "");
|
const isList = ListChartTypes.includes(
|
||||||
if (
|
(props.data.graph && props.data.graph.type) || ""
|
||||||
ListChartTypes.includes(dashboardStore.selectedGrid.graph.type) ||
|
);
|
||||||
isList
|
const chart = dashboardStore.selectedGrid.graph || {};
|
||||||
) {
|
if (ListChartTypes.includes(chart.type) || isList) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
queryMetrics();
|
queryMetrics();
|
||||||
@ -170,7 +175,9 @@ export default defineComponent({
|
|||||||
watch(
|
watch(
|
||||||
() => [selectorStore.currentService, selectorStore.currentDestService],
|
() => [selectorStore.currentService, selectorStore.currentDestService],
|
||||||
() => {
|
() => {
|
||||||
const isList = ListChartTypes.includes(props.data.graph.type || "");
|
const isList = ListChartTypes.includes(
|
||||||
|
(props.data.graph && props.data.graph.type) || ""
|
||||||
|
);
|
||||||
if (isList) {
|
if (isList) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -209,6 +216,8 @@ export default defineComponent({
|
|||||||
loading,
|
loading,
|
||||||
dashboardStore,
|
dashboardStore,
|
||||||
t,
|
t,
|
||||||
|
graph,
|
||||||
|
widget,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -269,8 +269,10 @@ export const TextColors: { [key: string]: string } = {
|
|||||||
|
|
||||||
export const CalculationOpts = [
|
export const CalculationOpts = [
|
||||||
{ label: "Percentage", value: "percentage" },
|
{ label: "Percentage", value: "percentage" },
|
||||||
{ label: "Byte to KB", value: "byteToKB" },
|
|
||||||
{ label: "Apdex", value: "apdex" },
|
{ label: "Apdex", value: "apdex" },
|
||||||
|
{ label: "Byte to KB", value: "byteToKB" },
|
||||||
|
{ label: "Byte to MB", value: "byteToMB" },
|
||||||
|
{ label: "Byte to GB", value: "byteToGB" },
|
||||||
{
|
{
|
||||||
label: "Convert milliseconds to YYYY-MM-DD HH:mm:ss",
|
label: "Convert milliseconds to YYYY-MM-DD HH:mm:ss",
|
||||||
value: "convertMilliseconds",
|
value: "convertMilliseconds",
|
||||||
|
@ -137,13 +137,15 @@ function getOption() {
|
|||||||
color,
|
color,
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: "axis",
|
trigger: "axis",
|
||||||
// backgroundColor: "rgb(50,50,50)",
|
zlevel: 1000,
|
||||||
// textStyle: {
|
z: 60,
|
||||||
// fontSize: 13,
|
backgroundColor: "rgb(50,50,50)",
|
||||||
// color: "#ccc",
|
textStyle: {
|
||||||
// },
|
fontSize: 13,
|
||||||
// enterable: true,
|
color: "#ccc",
|
||||||
// extraCssText: "max-height: 300px; overflow: auto;",
|
},
|
||||||
|
enterable: true,
|
||||||
|
extraCssText: "max-height: 300px; overflow: auto; border: none",
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
type: "scroll",
|
type: "scroll",
|
||||||
|
@ -15,21 +15,17 @@ limitations under the License. -->
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
|
v-if="!isNaN(singleVal)"
|
||||||
class="chart-card"
|
class="chart-card"
|
||||||
:class="{ center: config.textAlign === 'center' }"
|
:class="{ center: config.textAlign === 'center' }"
|
||||||
:style="{ fontSize: `${config.fontSize}px`, textAlign: config.textAlign }"
|
:style="{ fontSize: `${config.fontSize}px`, textAlign: config.textAlign }"
|
||||||
>
|
>
|
||||||
{{
|
{{ singleVal.toFixed(2) }}
|
||||||
typeof singleVal === "string"
|
|
||||||
? singleVal
|
|
||||||
: isNaN(singleVal)
|
|
||||||
? null
|
|
||||||
: singleVal.toFixed(2)
|
|
||||||
}}
|
|
||||||
<span v-show="config.showUnit">
|
<span v-show="config.showUnit">
|
||||||
{{ metricConfig[0]?.unit }}
|
{{ metricConfig[0]?.unit }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="center no-data" v-else>No Data</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, PropType } from "vue";
|
import { computed, PropType } from "vue";
|
||||||
@ -53,7 +49,7 @@ const props = defineProps({
|
|||||||
});
|
});
|
||||||
const metricConfig = computed(() => props.config.metricConfig || []);
|
const metricConfig = computed(() => props.config.metricConfig || []);
|
||||||
const key = computed(() => Object.keys(props.data)[0]);
|
const key = computed(() => Object.keys(props.data)[0]);
|
||||||
const singleVal = computed(() => props.data[key.value]);
|
const singleVal = computed(() => Number(props.data[key.value]));
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.chart-card {
|
.chart-card {
|
||||||
@ -68,4 +64,9 @@ const singleVal = computed(() => props.data[key.value]);
|
|||||||
-webkit-box-pack: center;
|
-webkit-box-pack: center;
|
||||||
-webkit-box-align: center;
|
-webkit-box-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.no-data {
|
||||||
|
height: 100%;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -65,17 +65,6 @@ limitations under the License. -->
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
<el-pagination
|
|
||||||
class="pagination"
|
|
||||||
background
|
|
||||||
small
|
|
||||||
layout="prev, pager, next"
|
|
||||||
:page-size="pageSize"
|
|
||||||
:total="selectorStore.pods.length"
|
|
||||||
@current-change="changePage"
|
|
||||||
@prev-click="changePage"
|
|
||||||
@next-click="changePage"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -107,7 +96,13 @@ const props = defineProps({
|
|||||||
metricTypes: string[];
|
metricTypes: string[];
|
||||||
} & { metricConfig: MetricConfigOpt[] }
|
} & { metricConfig: MetricConfigOpt[] }
|
||||||
>,
|
>,
|
||||||
default: () => ({ dashboardName: "", fontSize: 12, i: "" }),
|
default: () => ({
|
||||||
|
metrics: [],
|
||||||
|
metricTypes: [],
|
||||||
|
dashboardName: "",
|
||||||
|
fontSize: 12,
|
||||||
|
i: "",
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
|
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
|
||||||
isEdit: { type: Boolean, default: false },
|
isEdit: { type: Boolean, default: false },
|
||||||
@ -117,7 +112,6 @@ 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 = 10;
|
|
||||||
const searchText = ref<string>("");
|
const searchText = ref<string>("");
|
||||||
|
|
||||||
queryEndpoints();
|
queryEndpoints();
|
||||||
@ -133,18 +127,16 @@ async function queryEndpoints() {
|
|||||||
ElMessage.error(resp.errors);
|
ElMessage.error(resp.errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
endpoints.value = selectorStore.pods.filter(
|
endpoints.value = selectorStore.pods;
|
||||||
(d: unknown, index: number) => index < pageSize
|
|
||||||
);
|
|
||||||
queryEndpointMetrics(endpoints.value);
|
queryEndpointMetrics(endpoints.value);
|
||||||
}
|
}
|
||||||
async function queryEndpointMetrics(currentPods: Endpoint[]) {
|
async function queryEndpointMetrics(currentPods: Endpoint[]) {
|
||||||
if (!currentPods.length) {
|
if (!currentPods.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const metrics = props.config.metrics.filter((d: string) => d);
|
const metrics = (props.config.metrics || []).filter((d: string) => d);
|
||||||
|
const metricTypes = props.config.metricTypes || [];
|
||||||
if (metrics.length && metrics[0]) {
|
if (metrics.length && metrics[0] && metricTypes.length && metricTypes[0]) {
|
||||||
const params = await useQueryPodsMetrics(
|
const params = await useQueryPodsMetrics(
|
||||||
currentPods,
|
currentPods,
|
||||||
props.config,
|
props.config,
|
||||||
@ -180,14 +172,6 @@ function clickEndpoint(scope: any) {
|
|||||||
`/dashboard/${d.layer}/${d.entity}/${selectorStore.currentService.id}/${scope.row.id}/${d.name}`
|
`/dashboard/${d.layer}/${d.entity}/${selectorStore.currentService.id}/${scope.row.id}/${d.name}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
function changePage(pageIndex: number) {
|
|
||||||
endpoints.value = selectorStore.pods.filter((d: unknown, index: number) => {
|
|
||||||
if (index >= (pageIndex - 1) * pageSize && index < pageIndex * pageSize) {
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
queryEndpointMetrics(endpoints.value);
|
|
||||||
}
|
|
||||||
async function searchList() {
|
async function searchList() {
|
||||||
await queryEndpoints();
|
await queryEndpoints();
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ limitations under the License. -->
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { StandardConfig } from "@/types/dashboard";
|
|
||||||
|
|
||||||
/*global defineProps */
|
/*global defineProps */
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -31,11 +30,7 @@ const props = defineProps({
|
|||||||
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
|
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
|
||||||
config: {
|
config: {
|
||||||
type: Object as PropType<any>,
|
type: Object as PropType<any>,
|
||||||
default: () => ({}),
|
default: () => ({ metrics: [] }),
|
||||||
},
|
|
||||||
standard: {
|
|
||||||
type: Object as PropType<StandardConfig>,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const option = computed(() => getOption());
|
const option = computed(() => getOption());
|
||||||
|
@ -166,9 +166,9 @@ async function queryInstanceMetrics(currentInstances: Instance[]) {
|
|||||||
if (!currentInstances.length) {
|
if (!currentInstances.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { metrics } = props.config;
|
const { metrics, metricTypes } = props.config;
|
||||||
|
|
||||||
if (metrics.length && metrics[0]) {
|
if (metrics.length && metrics[0] && metricTypes.length && metricTypes[0]) {
|
||||||
const params = await useQueryPodsMetrics(
|
const params = await useQueryPodsMetrics(
|
||||||
currentInstances,
|
currentInstances,
|
||||||
props.config,
|
props.config,
|
||||||
|
@ -153,7 +153,7 @@ function getOption() {
|
|||||||
color: "#ccc",
|
color: "#ccc",
|
||||||
},
|
},
|
||||||
enterable: true,
|
enterable: true,
|
||||||
extraCssText: "max-height: 300px; overflow: auto;",
|
extraCssText: "max-height: 300px; overflow: auto; border: none",
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
type: "scroll",
|
type: "scroll",
|
||||||
|
@ -210,9 +210,9 @@ async function queryServiceMetrics(currentServices: Service[]) {
|
|||||||
if (!currentServices.length) {
|
if (!currentServices.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { metrics } = props.config;
|
const { metrics, metricTypes } = props.config;
|
||||||
|
|
||||||
if (metrics.length && metrics[0]) {
|
if (metrics.length && metrics[0] && metricTypes.length && metricTypes[0]) {
|
||||||
const params = await useQueryPodsMetrics(
|
const params = await useQueryPodsMetrics(
|
||||||
currentServices,
|
currentServices,
|
||||||
props.config,
|
props.config,
|
||||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="top-list">
|
<div class="top-list" v-if="available">
|
||||||
<div class="chart-slow-i" v-for="(i, index) in data[key]" :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>
|
||||||
@ -35,11 +35,12 @@ limitations under the License. -->
|
|||||||
<el-progress
|
<el-progress
|
||||||
:stroke-width="6"
|
:stroke-width="6"
|
||||||
:percentage="(i.value / maxValue) * 100"
|
:percentage="(i.value / maxValue) * 100"
|
||||||
:color="TextColors[config.color]"
|
:color="TextColors[config.color || 'purple']"
|
||||||
:show-text="false"
|
:show-text="false"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="center no-data" v-else>No Data</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
@ -61,6 +62,12 @@ const props = defineProps({
|
|||||||
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 available = computed(
|
||||||
|
() =>
|
||||||
|
Array.isArray(props.data[key.value]) &&
|
||||||
|
props.data[key.value][0] &&
|
||||||
|
props.data[key.value][0].value
|
||||||
|
);
|
||||||
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;
|
||||||
@ -114,4 +121,14 @@ function handleClick(i: string) {
|
|||||||
will-change: opacity, background-color;
|
will-change: opacity, background-color;
|
||||||
transition: opacity 0.3s, background-color 0.3s;
|
transition: opacity 0.3s, background-color 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.no-data {
|
||||||
|
height: 100%;
|
||||||
|
color: #666;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: horizontal;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -24,7 +24,7 @@ limitations under the License. -->
|
|||||||
<Settings @update="updateSettings" @updateNodes="freshNodes" />
|
<Settings @update="updateSettings" @updateNodes="freshNodes" />
|
||||||
</div>
|
</div>
|
||||||
<div class="tool">
|
<div class="tool">
|
||||||
<span v-show="config.graph.showDepth">
|
<span v-show="graphConfig.showDepth">
|
||||||
<span class="label">{{ t("currentDepth") }}</span>
|
<span class="label">{{ t("currentDepth") }}</span>
|
||||||
<Selector
|
<Selector
|
||||||
class="inputs"
|
class="inputs"
|
||||||
@ -69,7 +69,14 @@ limitations under the License. -->
|
|||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { ref, onMounted, onBeforeUnmount, reactive, watch } from "vue";
|
import {
|
||||||
|
ref,
|
||||||
|
onMounted,
|
||||||
|
onBeforeUnmount,
|
||||||
|
reactive,
|
||||||
|
watch,
|
||||||
|
computed,
|
||||||
|
} from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import * as d3 from "d3";
|
import * as d3 from "d3";
|
||||||
import d3tip from "d3-tip";
|
import d3tip from "d3-tip";
|
||||||
@ -111,7 +118,7 @@ const loading = ref<boolean>(false);
|
|||||||
const simulation = ref<any>(null);
|
const simulation = ref<any>(null);
|
||||||
const svg = ref<Nullable<any>>(null);
|
const svg = ref<Nullable<any>>(null);
|
||||||
const chart = ref<Nullable<HTMLDivElement>>(null);
|
const chart = ref<Nullable<HTMLDivElement>>(null);
|
||||||
const tip = ref<any>(null);
|
const tip = ref<Nullable<HTMLDivElement>>(null);
|
||||||
const graph = ref<any>(null);
|
const graph = ref<any>(null);
|
||||||
const node = ref<any>(null);
|
const node = ref<any>(null);
|
||||||
const link = ref<any>(null);
|
const link = ref<any>(null);
|
||||||
@ -124,7 +131,8 @@ const operationsPos = reactive<{ x: number; y: number }>({ x: NaN, y: NaN });
|
|||||||
const items = ref<
|
const items = ref<
|
||||||
{ id: string; title: string; func: any; dashboard?: string }[]
|
{ id: string; title: string; func: any; dashboard?: string }[]
|
||||||
>([]);
|
>([]);
|
||||||
const depth = ref<number>(props.config.graph.depth || 2);
|
const graphConfig = computed(() => props.config.graph || {});
|
||||||
|
const depth = ref<number>(graphConfig.value.depth || 2);
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
@ -27,15 +27,15 @@ export default function topoLegend(
|
|||||||
.append("image")
|
.append("image")
|
||||||
.attr("width", 30)
|
.attr("width", 30)
|
||||||
.attr("height", 30)
|
.attr("height", 30)
|
||||||
.attr("x", clientWidth - (item === "CUBEERROR" ? 200 : 410))
|
.attr("x", clientWidth - 140)
|
||||||
.attr("y", clientHeight + 50)
|
.attr("y", clientHeight + (item === "CUBEERROR" ? 50 : 0))
|
||||||
.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" ? 170 : 380))
|
.attr("x", clientWidth - 110)
|
||||||
.attr("y", clientHeight + 70)
|
.attr("y", clientHeight + (item === "CUBEERROR" ? 70 : 20))
|
||||||
.text(() => {
|
.text(() => {
|
||||||
const desc = description || {};
|
const desc = description || {};
|
||||||
return item === "CUBEERROR" ? desc.unhealthy || "" : desc.healthy || "";
|
return item === "CUBEERROR" ? desc.unhealthy || "" : desc.healthy || "";
|
||||||
|
Loading…
Reference in New Issue
Block a user