refactor: update MetricOptions

This commit is contained in:
Qiuxia Fan 2022-01-24 21:19:57 +08:00
parent e314f45874
commit 655c4c41e9
11 changed files with 137 additions and 139 deletions

View File

@ -93,7 +93,7 @@ export const getInstance = {
}; };
export const getEndpoint = { export const getEndpoint = {
variable: "$endpointId: String!", variable: "$endpointId: ID!",
query: ` query: `
endpoint: getEndpointInfo(endpointId: $endpointId) { endpoint: getEndpointInfo(endpointId: $endpointId) {
id id
@ -102,6 +102,5 @@ export const getEndpoint = {
serviceId serviceId
serviceName serviceName
} }
}
`, `,
}; };

View File

@ -22,7 +22,7 @@ import { useAppStoreWithOut } from "@/store/modules/app";
import { Instance, Endpoint } from "@/types/selector"; import { Instance, Endpoint } from "@/types/selector";
export function useQueryProcessor(config: any) { export function useQueryProcessor(config: any) {
if (!(config.metrics && config.metrics.length)) { if (!(config.metrics && config.metrics[0])) {
return; return;
} }
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();

View File

@ -30,7 +30,7 @@ const msg = {
events: "Events", events: "Events",
alerts: "Alerts", alerts: "Alerts",
settings: "Settings", settings: "Settings",
dashboards: "Dashboards", dashboards: "Dashboard",
profiles: "Profiles", profiles: "Profiles",
database: "Database", database: "Database",
serviceName: "Service Name", serviceName: "Service Name",
@ -53,7 +53,8 @@ const msg = {
instance: "Instance", instance: "Instance",
create: "Create", create: "Create",
loading: "Loading", loading: "Loading",
selectVisualization: "Select your visualization", selectVisualization: "Visualize your metrics",
visualization: "Visualization",
graphStyles: "Graph styles", graphStyles: "Graph styles",
widgetOptions: "Widget options", widgetOptions: "Widget options",
standardOptions: "Standard options", standardOptions: "Standard options",

View File

@ -51,7 +51,8 @@ const msg = {
endpoint: "端点", endpoint: "端点",
create: "新建", create: "新建",
loading: "加载中", loading: "加载中",
selectVisualization: "选择你的可视化", selectVisualization: "可视化指标",
visualization: "可视化",
graphStyles: "图形样式", graphStyles: "图形样式",
widgetOptions: "组件选项", widgetOptions: "组件选项",
standardOptions: "标准选项", standardOptions: "标准选项",

View File

@ -40,30 +40,16 @@ limitations under the License. -->
v-model="states.activeNames" v-model="states.activeNames"
:style="{ '--el-collapse-header-font-size': '15px' }" :style="{ '--el-collapse-header-font-size': '15px' }"
> >
<el-collapse-item :title="t('metricName')" name="1"> <el-collapse-item :title="t('selectVisualization')" name="1">
<MetricOptions @update="getSource" @loading="setLoading" /> <MetricOptions @update="getSource" @loading="setLoading" />
</el-collapse-item> </el-collapse-item>
<el-collapse-item :title="t('selectVisualization')" name="2"> <el-collapse-item :title="t('graphStyles')" name="2">
<div class="chart-types">
<span
v-for="(type, index) in states.visType"
:key="index"
@click="changeChartType(type)"
:class="{
active: type.value === dashboardStore.selectedGrid.graph.type,
}"
>
{{ type.label }}
</span>
</div>
</el-collapse-item>
<el-collapse-item :title="t('graphStyles')" name="3">
<component :is="`${dashboardStore.selectedGrid.graph.type}Config`" /> <component :is="`${dashboardStore.selectedGrid.graph.type}Config`" />
</el-collapse-item> </el-collapse-item>
<el-collapse-item :title="t('widgetOptions')" name="4"> <el-collapse-item :title="t('widgetOptions')" name="3">
<WidgetOptions /> <WidgetOptions />
</el-collapse-item> </el-collapse-item>
<el-collapse-item :title="t('standardOptions')" name="5"> <el-collapse-item :title="t('standardOptions')" name="4">
<StandardOptions /> <StandardOptions />
</el-collapse-item> </el-collapse-item>
</el-collapse> </el-collapse>
@ -83,13 +69,6 @@ import { reactive, defineComponent, ref } 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";
import {
ChartTypes,
DefaultGraphConfig,
PodsChartTypes,
TableChartTypes,
EntityType,
} from "../data";
import { Option } from "@/types/app"; import { Option } from "@/types/app";
import graphs from "../graphs"; import graphs from "../graphs";
import configs from "./graph-styles"; import configs from "./graph-styles";
@ -117,37 +96,12 @@ export default defineComponent({
source: any; source: any;
index: string; index: string;
visType: Option[]; visType: Option[];
isTable: boolean;
}>({ }>({
activeNames: "1", activeNames: "1",
source: {}, source: {},
index: dashboardStore.selectedGrid.i, index: dashboardStore.selectedGrid.i,
visType: [], visType: [],
isTable: false,
}); });
states.isTable = TableChartTypes.includes(
dashboardStore.selectedGrid.graph.type || ""
);
if (dashboardStore.entity === EntityType[0].value) {
states.visType = ChartTypes.filter(
(d: Option) => d.value !== "serviceList"
);
} else if (dashboardStore.entity === EntityType[1].value) {
states.visType = ChartTypes.filter(
(d: Option) => !PodsChartTypes.includes(d.value)
);
} else {
states.visType = ChartTypes.filter(
(d: Option) => !TableChartTypes.includes(d.value)
);
}
function changeChartType(item: Option) {
const graph = DefaultGraphConfig[item.value];
states.isTable = TableChartTypes.includes(graph.type);
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
}
function getSource(source: unknown) { function getSource(source: unknown) {
states.source = source; states.source = source;
@ -160,12 +114,12 @@ export default defineComponent({
function applyConfig() { function applyConfig() {
dashboardStore.setConfigs(dashboardStore.selectedGrid); dashboardStore.setConfigs(dashboardStore.selectedGrid);
dashboardStore.setConfigPanel(false); dashboardStore.setConfigPanel(false);
dashboardStore.selectWidget(null);
} }
return { return {
states, states,
loading, loading,
changeChartType,
t, t,
appStoreWithOut, appStoreWithOut,
configHeight, configHeight,
@ -226,32 +180,12 @@ export default defineComponent({
min-width: 1280px; min-width: 1280px;
} }
.chart-types {
span {
display: inline-block;
padding: 5px 10px;
border: 1px solid #ccc;
background-color: #fff;
border-right: 0;
cursor: pointer;
}
span:nth-last-child(1) {
border-right: 1px solid #ccc;
}
}
.no-data { .no-data {
font-size: 14px; font-size: 14px;
text-align: center; text-align: center;
line-height: 400px; line-height: 400px;
} }
span.active {
background-color: #409eff;
color: #fff;
}
.footer { .footer {
position: fixed; position: fixed;
bottom: 0; bottom: 0;

View File

@ -14,17 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<template> <template>
<div v-show="states.isTable" class="ds-name"> <div v-show="states.isTable" class="ds-name">
<div>Dashboard</div> <div>{{ t("dashboards") }}</div>
<Selector <el-input
:value="dashboardStore.selectedGrid.graph.dashboardName" v-model="states.dashboardName"
:options="states.metricList" placeholder="Please input dashboard name"
size="mini"
placeholder="Select a dashboard"
@change="changeDashboard" @change="changeDashboard"
class="selectors" class="selectors"
/> />
</div> </div>
<div>Metrics</div> <div>{{ t("metrics") }}</div>
<div <div
v-for="(metric, index) in states.metrics" v-for="(metric, index) in states.metrics"
:key="index" :key="index"
@ -69,17 +67,40 @@ limitations under the License. -->
/> />
</span> </span>
</div> </div>
<div>{{ t("visualization") }}</div>
<div class="chart-types">
<span
v-for="(type, index) in states.visTypes"
:key="index"
@click="changeChartType(type)"
:class="{
active: type.value === dashboardStore.selectedGrid.graph.type,
}"
>
{{ type.label }}
</span>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, watch } from "vue"; import { reactive } 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 { MetricTypes, TableChartTypes, MetricCatalog } from "../data"; import {
MetricTypes,
TableChartTypes,
MetricCatalog,
DefaultGraphConfig,
EntityType,
ChartTypes,
PodsChartTypes,
} from "../data";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import Icon from "@/components/Icon.vue"; import Icon from "@/components/Icon.vue";
import { useQueryProcessor, useSourceProcessor } from "@/hooks/useProcessor"; import { useQueryProcessor, useSourceProcessor } from "@/hooks/useProcessor";
import { useI18n } from "vue-i18n";
/*global defineEmits */ /*global defineEmits */
const { t } = useI18n();
const emit = defineEmits(["update", "loading"]); const emit = defineEmits(["update", "loading"]);
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const { metrics, metricTypes, graph } = dashboardStore.selectedGrid; const { metrics, metricTypes, graph } = dashboardStore.selectedGrid;
@ -87,19 +108,22 @@ const states = reactive<{
metrics: string[]; metrics: string[];
metricTypes: string[]; metricTypes: string[];
metricTypeList: Option[][]; metricTypeList: Option[][];
visType: Option[]; visTypes: Option[];
isTable: boolean; isTable: boolean;
metricList: (Option & { type: string })[]; metricList: (Option & { type: string })[];
dashboardName: string;
}>({ }>({
metrics: metrics && metrics.length ? metrics : [""], metrics: metrics && metrics.length ? metrics : [""],
metricTypes: metricTypes && metricTypes.length ? metricTypes : [""], metricTypes: metricTypes && metricTypes.length ? metricTypes : [""],
metricTypeList: [], metricTypeList: [],
visType: [], visTypes: [],
isTable: false, isTable: false,
metricList: [], metricList: [],
dashboardName: graph.dashboardName,
}); });
states.isTable = TableChartTypes.includes(graph.type);
states.isTable = TableChartTypes.includes(graph.type);
states.visTypes = setVisTypes();
setMetricType(); setMetricType();
async function setMetricType(catalog?: string) { async function setMetricType(catalog?: string) {
@ -128,6 +152,47 @@ async function setMetricType(catalog?: string) {
} }
} }
function setVisTypes() {
let graphs = [];
if (dashboardStore.entity === EntityType[0].value) {
graphs = ChartTypes.filter((d: Option) => d.value !== ChartTypes[8].value);
} else if (dashboardStore.entity === EntityType[1].value) {
graphs = ChartTypes.filter(
(d: Option) => !PodsChartTypes.includes(d.value)
);
} else {
graphs = ChartTypes.filter(
(d: Option) => !TableChartTypes.includes(d.value)
);
}
return graphs;
}
function changeChartType(item: Option) {
const graph = DefaultGraphConfig[item.value];
states.isTable = TableChartTypes.includes(graph.type);
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, graph });
states.isTable = TableChartTypes.includes(graph.type);
if (states.isTable) {
dashboardStore.selectWidget({
...dashboardStore.selectedGrid,
metrics: [""],
metricTypes: [""],
});
states.metrics = [""];
states.metricTypes = [""];
}
const catalog: { [key: string]: string } = {
InstanceList: EntityType[3].value,
EndpointList: EntityType[2].value,
ServiceList: EntityType[0].value,
};
if (catalog[graph.type] || dashboardStore.entity) {
setMetricType(catalog[graph.type]);
}
}
function changeMetrics(index: number, arr: (Option & { type: string })[]) { function changeMetrics(index: number, arr: (Option & { type: string })[]) {
if (!arr.length) { if (!arr.length) {
states.metricTypeList = []; states.metricTypeList = [];
@ -193,10 +258,10 @@ async function queryMetrics() {
emit("update", source); emit("update", source);
} }
function changeDashboard(item: Option[]) { function changeDashboard() {
const graph = { const graph = {
...dashboardStore.selectedGrid.graph, ...dashboardStore.selectedGrid.graph,
dashboardName: item[0].value, dashboardName: states.dashboardName,
}; };
dashboardStore.selectWidget({ dashboardStore.selectWidget({
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
@ -216,20 +281,6 @@ function deleteMetric(index: number) {
states.metrics.splice(index, 1); states.metrics.splice(index, 1);
states.metricTypes.splice(index, 1); states.metricTypes.splice(index, 1);
} }
watch(
() => dashboardStore.selectedGrid.graph.type,
(type: string) => {
states.isTable = TableChartTypes.includes(type);
const catalog: { [key: string]: string } = {
InstanceList: "ServiceInstance",
EndpointList: "Endpoint",
ServiceList: "Service",
};
if (catalog[type] || dashboardStore.entity) {
setMetricType(catalog[type]);
}
}
);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.ds-name { .ds-name {
@ -244,4 +295,24 @@ watch(
.metric-item { .metric-item {
margin-bottom: 10px; margin-bottom: 10px;
} }
.chart-types {
span {
display: inline-block;
padding: 5px 10px;
border: 1px solid #ccc;
background-color: #fff;
border-right: 0;
cursor: pointer;
}
span:nth-last-child(1) {
border-right: 1px solid #ccc;
}
}
span.active {
background-color: #409eff;
color: #fff;
}
</style> </style>

View File

@ -32,6 +32,18 @@ export const ChartTypes = [
{ label: "Endpoint List", value: "EndpointList" }, { label: "Endpoint List", value: "EndpointList" },
{ label: "Instance List", value: "InstanceList" }, { label: "Instance List", value: "InstanceList" },
]; ];
export const MetricChartType: any = {
readMetricsValue: [{ label: "Card", value: "Card" }],
readMetricsValues: [
{ label: "Bar", value: "Bar" },
{ label: "Line", value: "Line" },
{ label: "Area", value: "Area" },
],
sortMetrics: [{ label: "Top List", value: "TopList" }],
readLabeledMetricsValues: [{ label: "Line", value: "Line" }],
readHeatMap: [{ label: "Heatmap", value: "Heatmap" }],
readSampledRecords: [{ label: "Top List", value: "TopList" }],
};
export const DefaultGraphConfig: { [key: string]: any } = { export const DefaultGraphConfig: { [key: string]: any } = {
Bar: { Bar: {
type: "Bar", type: "Bar",
@ -113,14 +125,6 @@ export const MetricTypes: {
{ label: "get sorted topN values", value: "readSampledRecords" }, { label: "get sorted topN values", value: "readSampledRecords" },
], ],
}; };
export const MetricChartType: { [key: string]: string } = {
readMetricsValue: "ChartNum",
readMetricsValues: "ChartLine",
sortMetrics: "ChartSlow",
readLabeledMetricsValues: "ChartLine",
readHeatMap: "ChartHeatmap",
readSampledRecords: "ChartSlow",
};
export enum MetricCatalog { export enum MetricCatalog {
SERVICE = "Service", SERVICE = "Service",

View File

@ -29,17 +29,12 @@ limitations under the License. -->
</template> </template>
</el-input> </el-input>
</div> </div>
<el-table <el-table v-loading="chartLoading" :data="endpoints" style="width: 100%">
v-loading="chartLoading"
:data="endpoints"
style="width: 100%; height: 320px; overflow: auto"
>
<el-table-column label="Endpoints"> <el-table-column label="Endpoints">
<template #default="scope"> <template #default="scope">
<router-link <router-link
target="_blank"
class="link" class="link"
:to="`/dashboard/${scope.row.layer}/Endpoint/${selectorStore.currentService.id}/${scope.row.id}/${config.dashboardName}`" :to="`/dashboard/${dashboardStore.layerId}/${EntityType[2].value}/${selectorStore.currentService.id}/${scope.row.id}/${config.dashboardName}`"
:style="{ fontSize: `${config.fontSize}px` }" :style="{ fontSize: `${config.fontSize}px` }"
> >
{{ scope.row.label }} {{ scope.row.label }}
@ -84,6 +79,7 @@ import { Endpoint } from "@/types/selector";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { useQueryPodsMetrics, usePodsSource } from "@/hooks/useProcessor"; import { useQueryPodsMetrics, usePodsSource } from "@/hooks/useProcessor";
import Line from "./Line.vue"; import Line from "./Line.vue";
import { EntityType } from "../data";
/*global defineProps */ /*global defineProps */
defineProps({ defineProps({
@ -126,7 +122,7 @@ async function queryEndpointMetrics(currentPods: Endpoint[]) {
const params = await useQueryPodsMetrics( const params = await useQueryPodsMetrics(
currentPods, currentPods,
dashboardStore.selectedGrid, dashboardStore.selectedGrid,
"Endpoint" EntityType[2].value
); );
const json = await dashboardStore.fetchMetricValue(params); const json = await dashboardStore.fetchMetricValue(params);

View File

@ -29,16 +29,12 @@ limitations under the License. -->
</template> </template>
</el-input> </el-input>
</div> </div>
<el-table <el-table v-loading="chartLoading" :data="instances" style="width: 100%">
v-loading="chartLoading"
:data="instances"
style="width: 100%; height: 320px; overflow: auto"
>
<el-table-column label="Service Instances"> <el-table-column label="Service Instances">
<template #default="scope"> <template #default="scope">
<router-link <router-link
class="link" class="link"
:to="`/dashboard/${scope.row.layer}/ServiceInstance/${selectorStore.currentService.id}/${scope.row.id}/${config.dashboardName}`" :to="`/dashboard/${dashboardStore.layerId}/${EntityType[2].value}/${selectorStore.currentService.id}/${scope.row.id}/${config.dashboardName}`"
:style="{ fontSize: `${config.fontSize}px` }" :style="{ fontSize: `${config.fontSize}px` }"
> >
{{ scope.row.label }} {{ scope.row.label }}
@ -83,6 +79,7 @@ import { useDashboardStore } from "@/store/modules/dashboard";
import { InstanceListConfig } from "@/types/dashboard"; import { InstanceListConfig } from "@/types/dashboard";
import { Instance } from "@/types/selector"; import { Instance } from "@/types/selector";
import { useQueryPodsMetrics, usePodsSource } from "@/hooks/useProcessor"; import { useQueryPodsMetrics, usePodsSource } from "@/hooks/useProcessor";
import { EntityType } from "../data";
/*global defineProps */ /*global defineProps */
defineProps({ defineProps({
@ -124,7 +121,7 @@ async function queryInstanceMetrics(currentInstances: Instance[]) {
const params = await useQueryPodsMetrics( const params = await useQueryPodsMetrics(
currentInstances, currentInstances,
dashboardStore.selectedGrid, dashboardStore.selectedGrid,
"ServiceInstance" EntityType[3].value
); );
const json = await dashboardStore.fetchMetricValue(params); const json = await dashboardStore.fetchMetricValue(params);

View File

@ -29,17 +29,12 @@ limitations under the License. -->
</template> </template>
</el-input> </el-input>
</div> </div>
<el-table <el-table v-loading="chartLoading" :data="services" style="width: 100%">
v-loading="chartLoading"
:data="services"
style="width: 100%; height: 320px; overflow: auto"
>
<el-table-column label="Services"> <el-table-column label="Services">
<template #default="scope"> <template #default="scope">
<router-link <router-link
target="_blank"
class="link" class="link"
:to="`/dashboard/${scope.row.layer}/Service/${selectorStore.currentService.value}/${config.dashboardName}`" :to="`/dashboard/${dashboardStore.layerId}/${EntityType[0].value}/${selectorStore.currentService.id}/${config.dashboardName}`"
:key="1" :key="1"
:style="{ fontSize: `${config.fontSize}px` }" :style="{ fontSize: `${config.fontSize}px` }"
> >
@ -85,6 +80,7 @@ import { useSelectorStore } from "@/store/modules/selectors";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { Service } from "@/types/selector"; import { Service } from "@/types/selector";
import { useQueryPodsMetrics, usePodsSource } from "@/hooks/useProcessor"; import { useQueryPodsMetrics, usePodsSource } from "@/hooks/useProcessor";
import { EntityType } from "../data";
/*global defineProps */ /*global defineProps */
defineProps({ defineProps({
@ -124,7 +120,7 @@ async function queryServiceMetrics(currentServices: Service[]) {
const params = await useQueryPodsMetrics( const params = await useQueryPodsMetrics(
currentServices, currentServices,
dashboardStore.selectedGrid, dashboardStore.selectedGrid,
"Service" EntityType[0].value
); );
const json = await dashboardStore.fetchMetricValue(params); const json = await dashboardStore.fetchMetricValue(params);

View File

@ -13,9 +13,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<template> <template>
<div class="dashboard-tool flex-h"> <div class="dashboard-tool flex-h" v-if="!params.serviceId">
<div v-if="params.serviceId"></div> <div class="flex-h">
<div class="flex-h" v-else>
<div class="selectors-item" v-if="states.key !== 10"> <div class="selectors-item" v-if="states.key !== 10">
<span class="label">$Service</span> <span class="label">$Service</span>
<Selector <Selector