fix: polish pages and bugs fix (#36)

This commit is contained in:
Fine0830
2022-03-24 21:35:22 +08:00
committed by GitHub
parent 33365f2a14
commit 4380a874de
26 changed files with 314 additions and 134 deletions

View File

@@ -35,7 +35,7 @@ const dashboardStore = useDashboardStore();
const routesMap: { [key: string]: string } = {
GeneralServices: "GENERAL",
Database: "VIRTUAL_DATABASE",
MESH: "MESH",
MeshServices: "MESH",
ControlPanel: "MESH_CP",
DataPanel: "MESH_DP",
Linux: "OS_LINUX",
@@ -43,7 +43,8 @@ const routesMap: { [key: string]: string } = {
Satellite: "SO11Y_SATELLITE",
Functions: "FAAS",
Browser: "BROWSER",
Kubernetes: "K8S",
KubernetesCluster: "K8S",
KubernetesService: "K8S_SERVICE",
};
const layer = ref<string>("GENERAL");
@@ -51,6 +52,7 @@ getDashboard();
async function getDashboard() {
layer.value = routesMap[String(route.name)];
console.log(layer.value);
dashboardStore.setLayer(layer.value);
dashboardStore.setEntity(EntityType[1].value);
dashboardStore.setMode(false);

View File

@@ -203,6 +203,9 @@ async function importTemplates(event: any) {
dashboardFile.value = null;
}
function exportTemplates() {
if (!multipleSelection.value.length) {
return;
}
const arr = multipleSelection.value.sort(
(a: DashboardItem, b: DashboardItem) => {
return a.name.localeCompare(b.name);

View File

@@ -37,8 +37,9 @@ limitations under the License. -->
metrics: dashboardStore.selectedGrid.metrics,
metricTypes: dashboardStore.selectedGrid.metricTypes,
standard: dashboardStore.selectedGrid.standard,
isEdit: true,
}"
:isEdit="isEdit"
@changeOpt="setStatus"
/>
<div v-show="!dashboardStore.selectedGrid.graph.type" class="no-data">
{{ t("noData") }}
@@ -51,7 +52,11 @@ limitations under the License. -->
:style="{ '--el-collapse-header-font-size': '15px' }"
>
<el-collapse-item :title="t('selectVisualization')" name="1">
<MetricOptions @update="getSource" @loading="setLoading" />
<MetricOptions
@update="getSource"
@changeOpt="setStatus"
@loading="setLoading"
/>
</el-collapse-item>
<el-collapse-item :title="t('graphStyles')" name="2">
<component :is="`${dashboardStore.selectedGrid.graph.type}Config`" />
@@ -85,6 +90,7 @@ import configs from "./widget/graph-styles";
import WidgetOptions from "./widget/WidgetOptions.vue";
import StandardOptions from "./widget/StandardOptions.vue";
import MetricOptions from "./widget/MetricOptions.vue";
import { ListChartTypes } from "../data";
export default defineComponent({
name: "ConfigEdit",
@@ -101,6 +107,7 @@ export default defineComponent({
const dashboardStore = useDashboardStore();
const appStoreWithOut = useAppStoreWithOut();
const loading = ref<boolean>(false);
const isEdit = ref<boolean>(false);
const states = reactive<{
activeNames: string;
source: unknown;
@@ -123,8 +130,13 @@ export default defineComponent({
}
function applyConfig() {
dashboardStore.setConfigs(dashboardStore.selectedGrid);
dashboardStore.setConfigPanel(false);
setStatus();
dashboardStore.setConfigs(dashboardStore.selectedGrid);
}
function setStatus() {
isEdit.value = true;
}
function cancelConfig() {
@@ -143,6 +155,8 @@ export default defineComponent({
cancelConfig,
getSource,
setLoading,
setStatus,
isEdit,
};
},
});

View File

@@ -13,15 +13,16 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<div v-if="states.isList && states.dashboardList.length" class="ds-name">
<div v-if="states.isList" class="ds-name">
<div>{{ t("dashboards") }}</div>
<Selector
:value="states.dashboardName"
:value="states.dashboardName || ''"
:options="states.dashboardList"
size="small"
placeholder="Please select a dashboard name"
@change="changeDashboard"
class="selectors"
:clearable="true"
/>
</div>
<div>{{ t("metrics") }}</div>
@@ -63,7 +64,6 @@ limitations under the License. -->
/>
<Icon
class="cp"
v-show="states.metrics.length > 1"
iconName="remove_circle_outline"
size="middle"
@click="deleteMetric(index)"
@@ -105,7 +105,7 @@ import { DashboardItem } from "@/types/dashboard";
/*global defineEmits */
const { t } = useI18n();
const emit = defineEmits(["update", "loading"]);
const emit = defineEmits(["update", "loading", "changeOpt"]);
const dashboardStore = useDashboardStore();
const { metrics, metricTypes, graph } = dashboardStore.selectedGrid;
const states = reactive<{
@@ -116,7 +116,7 @@ const states = reactive<{
isList: boolean;
metricList: (Option & { type: string })[];
dashboardName: string;
dashboardList: (DashboardItem & { label: string; value: string })[];
dashboardList: ((DashboardItem & { label: string; value: string }) | any)[];
}>({
metrics: metrics && metrics.length ? metrics : [""],
metricTypes: metricTypes && metricTypes.length ? metricTypes : [""],
@@ -125,11 +125,11 @@ const states = reactive<{
isList: false,
metricList: [],
dashboardName: graph.dashboardName,
dashboardList: [],
dashboardList: [{ label: "", value: "" }],
});
states.isList = ListChartTypes.includes(graph.type);
const defaultLen = ref<number>(states.isList ? 5 : 10);
const defaultLen = ref<number>(states.isList ? 5 : 20);
states.visTypes = setVisTypes();
setDashboards();
@@ -197,7 +197,7 @@ async function setMetricType() {
function setDashboards() {
const { graph } = dashboardStore.selectedGrid;
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
states.dashboardList = list.reduce(
const arr = list.reduce(
(
prev: (DashboardItem & { label: string; value: string })[],
d: DashboardItem
@@ -219,6 +219,8 @@ function setDashboards() {
},
[]
);
states.dashboardList = arr.length ? arr : [{ label: "", value: "" }];
}
function setVisTypes() {
@@ -281,6 +283,7 @@ function changeMetrics(
...{ metricTypes: states.metricTypes, metrics: states.metrics },
});
if (states.isList) {
emit("changeOpt");
return;
}
queryMetrics();
@@ -311,6 +314,7 @@ function changeMetricType(index: number, opt: Option[] | any) {
...{ metricTypes: states.metricTypes },
});
if (states.isList) {
emit("changeOpt");
return;
}
queryMetrics();
@@ -338,7 +342,11 @@ async function queryMetrics() {
}
function changeDashboard(opt: any) {
states.dashboardName = opt[0].value;
if (!opt[0]) {
states.dashboardName = "";
} else {
states.dashboardName = opt[0].value;
}
const graph = {
...dashboardStore.selectedGrid.graph,
dashboardName: states.dashboardName,
@@ -358,6 +366,15 @@ function addMetric() {
states.metricTypes.push("");
}
function deleteMetric(index: number) {
if (states.metrics.length === 1) {
states.metrics = [""];
states.metricTypes = [""];
dashboardStore.selectWidget({
...dashboardStore.selectedGrid,
...{ metricTypes: states.metricTypes, metrics: states.metrics },
});
return;
}
states.metrics.splice(index, 1);
states.metricTypes.splice(index, 1);
}

View File

@@ -104,26 +104,24 @@ const props = defineProps({
i: string;
metrics: string[];
metricTypes: string[];
isEdit: boolean;
}
>,
default: () => ({ dashboardName: "", fontSize: 12, i: "" }),
},
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
needQuery: { type: Boolean, default: false },
isEdit: { type: Boolean, default: false },
});
// const emit = defineEmits(["changeOpt"]);
const selectorStore = useSelectorStore();
const dashboardStore = useDashboardStore();
const chartLoading = ref<boolean>(false);
const endpoints = ref<Endpoint[]>([]);
const searchEndpoints = ref<Endpoint[]>([]);
const pageSize = 5;
const total = 10;
const searchText = ref<string>("");
if (props.needQuery) {
queryEndpoints(total);
}
queryEndpoints(total);
async function queryEndpoints(limit?: number) {
chartLoading.value = true;
const resp = await selectorStore.getEndpoints({
@@ -136,15 +134,14 @@ async function queryEndpoints(limit?: number) {
ElMessage.error(resp.errors);
return;
}
searchEndpoints.value = selectorStore.pods;
endpoints.value = selectorStore.pods.splice(0, pageSize);
if (props.config.isEdit || !endpoints.value.length) {
return;
}
queryEndpointMetrics(endpoints.value);
await queryEndpointMetrics(endpoints.value);
}
async function queryEndpointMetrics(currentPods: Endpoint[]) {
const { metrics } = props.config;
if (!currentPods.length) {
return;
}
const metrics = props.config.metrics.filter((d: string) => d);
if (metrics.length && metrics[0]) {
const params = await useQueryPodsMetrics(
@@ -178,7 +175,7 @@ function clickEndpoint(scope: any) {
);
}
function changePage(pageIndex: number) {
endpoints.value = searchEndpoints.value.splice(
endpoints.value = selectorStore.pods.splice(
(pageIndex - 1 || 0) * pageSize,
pageSize * (pageIndex || 1)
);
@@ -189,10 +186,11 @@ async function searchList() {
}
watch(
() => [props.config.metricTypes, props.config.metrics],
() => {
if (dashboardStore.showConfig) {
async () => {
if (props.isEdit) {
queryEndpointMetrics(endpoints.value);
}
// emit("changeOpt", false);
}
);
watch(

View File

@@ -42,20 +42,6 @@ limitations under the License. -->
</span>
</template>
</el-table-column>
<el-table-column label="Service Instances">
<template #default="scope">
<div class="attributes" v-if="scope.row.attributes.length">
<div
v-for="(attr, index) in scope.row.attributes"
:key="attr.name + index"
:style="{ fontSize: `${config.fontSize}px` }"
>
{{ attr.name }}: {{ attr.value || null }}
</div>
</div>
<div v-else>No Data</div>
</template>
</el-table-column>
<el-table-column
v-for="(metric, index) in config.metrics"
:label="metric"
@@ -77,6 +63,25 @@ limitations under the License. -->
</div>
</template>
</el-table-column>
<el-table-column label="Attributes" :width="100">
<template #default="scope">
<el-popover placement="left" :width="400" trigger="click">
<template #reference>
<span class="link">{{ t("viewAttributes") }}</span>
</template>
<div class="attributes" v-if="scope.row.attributes.length">
<div
v-for="(attr, index) in scope.row.attributes"
:key="attr.name + index"
:style="{ fontSize: `${config.fontSize}px` }"
class="mt-5"
>
{{ attr.name }}: {{ attr.value || null }}
</div>
</div>
</el-popover>
</template>
</el-table-column>
</el-table>
</div>
<el-pagination
@@ -94,6 +99,7 @@ limitations under the License. -->
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
import { useI18n } from "vue-i18n";
import { ElMessage } from "element-plus";
import type { PropType } from "vue";
import Line from "./Line.vue";
@@ -128,7 +134,9 @@ const props = defineProps({
},
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
needQuery: { type: Boolean, default: false },
isEdit: { type: Boolean, default: false },
});
const { t } = useI18n();
const selectorStore = useSelectorStore();
const dashboardStore = useDashboardStore();
const chartLoading = ref<boolean>(false);
@@ -137,9 +145,7 @@ const searchInstances = ref<Instance[]>([]); // all instances
const pageSize = 5;
const searchText = ref<string>("");
if (props.needQuery) {
queryInstance();
}
queryInstance();
async function queryInstance() {
chartLoading.value = true;
const resp = await selectorStore.getServiceInstances();
@@ -153,13 +159,13 @@ async function queryInstance() {
}
searchInstances.value = selectorStore.pods;
instances.value = searchInstances.value.splice(0, pageSize);
if (props.config.isEdit) {
return;
}
queryInstanceMetrics(instances.value);
}
async function queryInstanceMetrics(currentInstances: Instance[]) {
if (!currentInstances.length) {
return;
}
const { metrics } = props.config;
if (metrics.length && metrics[0]) {
@@ -186,6 +192,10 @@ function clickInstance(scope: any) {
layer: dashboardStore.layerId,
entity: EntityType[3].value,
});
if (!d) {
ElMessage.error("No this dashboard");
return;
}
router.push(
`/dashboard/${d.layer}/${d.entity}/${selectorStore.currentService.id}/${
scope.row.id
@@ -207,9 +217,7 @@ function searchList() {
watch(
() => [props.config.metricTypes, props.config.metrics],
() => {
if (dashboardStore.showConfig) {
queryInstanceMetrics(instances.value);
}
queryInstanceMetrics(instances.value);
}
);
watch(
@@ -231,7 +239,7 @@ watch(
}
.attributes {
max-height: 80px;
max-height: 400px;
overflow: auto;
}
</style>

View File

@@ -122,15 +122,16 @@ const props = defineProps({
default: () => ({ dashboardName: "", fontSize: 12 }),
},
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
isEdit: { type: Boolean, default: false },
});
const selectorStore = useSelectorStore();
const dashboardStore = useDashboardStore();
const chartLoading = ref<boolean>(false);
const pageSize = 5;
const services = ref<Service[]>([]);
const searchServices = ref<Service[]>([]);
const searchText = ref<string>("");
const groups = ref<any>({});
const sortServices = ref<(Service & { merge: boolean })[]>([]);
queryServices();
@@ -142,7 +143,13 @@ async function queryServices() {
if (resp.errors) {
ElMessage.error(resp.errors);
}
const map: { [key: string]: any[] } = selectorStore.services.reduce(
setServices(selectorStore.services);
queryServiceMetrics(services.value);
}
function setServices(arr: (Service & { merge: boolean })[]) {
groups.value = {};
const map: { [key: string]: any[] } = arr.reduce(
(result: { [key: string]: any[] }, item: any) => {
item.group = item.group || "";
if (result[item.group]) {
@@ -156,21 +163,23 @@ async function queryServices() {
},
{}
);
services.value = Object.values(map).flat(1).splice(0, pageSize);
sortServices.value = Object.values(map).flat(1);
const obj = {} as any;
for (const s of services.value) {
for (const s of sortServices.value) {
s.group = s.group || "";
if (!obj[s.group]) {
obj[s.group] = 1;
} else {
if (obj[s.group] % 5 === 0) {
s.merge = false;
}
obj[s.group]++;
}
groups.value[s.group] = obj[s.group];
}
if (props.config.isEdit) {
return;
}
queryServiceMetrics(services.value);
services.value = sortServices.value.filter(
(d: Service, index: number) => index < pageSize
);
}
function clickService(scope: any) {
@@ -188,6 +197,9 @@ function clickService(scope: any) {
router.push(path);
}
async function queryServiceMetrics(currentServices: Service[]) {
if (!currentServices.length) {
return;
}
const { metrics } = props.config;
if (metrics.length && metrics[0]) {
@@ -219,28 +231,29 @@ function objectSpanMethod(param: any): any {
rowspan: 0,
colspan: 0,
};
} else {
return { rowspan: groups.value[param.row.group], colspan: 1 };
}
return { rowspan: groups.value[param.row.group], colspan: 1 };
}
function changePage(pageIndex: number) {
services.value = services.value.splice(
(pageIndex - 1 || 0) * pageSize,
pageSize * (pageIndex || 1)
);
services.value = sortServices.value.filter((d: Service, index: number) => {
if (
index >= (pageIndex - 1 || 0) * pageSize &&
index < pageSize * (pageIndex || 1)
) {
return d;
}
});
}
function searchList() {
searchServices.value = selectorStore.services.filter((d: { label: string }) =>
const searchServices = sortServices.value.filter((d: { label: string }) =>
d.label.includes(searchText.value)
);
services.value = searchServices.value.splice(0, pageSize);
services.value = searchServices.splice(0, pageSize);
}
watch(
() => [props.config.metricTypes, props.config.metrics],
() => {
if (dashboardStore.showConfig) {
queryServiceMetrics(services.value);
}
queryServiceMetrics(services.value);
}
);
</script>

View File

@@ -127,6 +127,7 @@ const params = useRoute().params;
const toolIcons = ref<{ name: string; content: string; id: string }[]>(
EndpointRelationTools
);
const limit = ref<number>(10);
const loading = ref<boolean>(false);
const states = reactive<{
destService: string;
@@ -401,7 +402,7 @@ async function fetchPods(type: string, serviceId: string, setPod: boolean) {
let resp;
switch (type) {
case EntityType[2].value:
resp = await selectorStore.getEndpoints({ serviceId });
resp = await selectorStore.getEndpoints({ serviceId, limit });
if (setPod) {
selectorStore.setCurrentPod(
selectorStore.pods.length ? selectorStore.pods[0] : null
@@ -419,7 +420,11 @@ async function fetchPods(type: string, serviceId: string, setPod: boolean) {
}
break;
case EntityType[6].value:
resp = await selectorStore.getEndpoints({ serviceId, isRelation: true });
resp = await selectorStore.getEndpoints({
serviceId,
isRelation: true,
limit,
});
if (setPod) {
selectorStore.setCurrentDestPod(
selectorStore.destPods.length ? selectorStore.destPods[0] : null

View File

@@ -114,6 +114,7 @@ function setCurrentLog(log: any) {
}
.serviceInstanceName,
.endpointName,
.serviceName {
width: 200px;
}

View File

@@ -82,6 +82,7 @@ function showSelectSpan() {
}
.serviceInstanceName,
.endpointName,
.serviceName {
width: 200px;
}
@@ -98,6 +99,7 @@ function showSelectSpan() {
border: 1px solid transparent;
border-right: 1px dotted silver;
overflow: hidden;
height: 30px;
line-height: 30px;
text-overflow: ellipsis;
white-space: nowrap;

View File

@@ -24,6 +24,10 @@ export const ServiceLogConstants = [
label: "serviceInstanceName",
value: "instance",
},
{
label: "endpointName",
value: "endpoint",
},
{
label: "timestamp",
value: "time",

View File

@@ -143,7 +143,7 @@ const isBrowser = ref<boolean>(dashboardStore.layerId === "BROWSER");
const state = reactive<any>({
instance: { value: "0", label: "All" },
endpoint: { value: "0", label: "All" },
service: { value: "0", label: "All" },
service: { value: "", label: "" },
});
init();
@@ -154,11 +154,10 @@ async function init() {
ElMessage.error(resp.errors);
return;
}
await fetchSelectors();
await searchLogs();
state.instance = { value: "0", label: "All" };
state.endpoint = { value: "0", label: "All" };
state.service = { value: "0", label: "All" };
searchLogs();
fetchSelectors();
}
function fetchSelectors() {
@@ -187,18 +186,20 @@ async function getServices() {
return;
}
state.service = logStore.services[0];
getInstances(state.service.id);
getEndpoints(state.service.id);
}
async function getEndpoints() {
const resp = await logStore.getEndpoints();
async function getEndpoints(id?: string) {
const resp = await logStore.getEndpoints(id);
if (resp.errors) {
ElMessage.error(resp.errors);
return;
}
state.endpoint = logStore.endpoints[0];
}
async function getInstances() {
const resp = await logStore.getInstances();
async function getInstances(id?: string) {
const resp = await logStore.getInstances(id);
if (resp.errors) {
ElMessage.error(resp.errors);
return;
@@ -238,8 +239,8 @@ async function queryLogs() {
function changeField(type: string, opt: any) {
state[type] = opt[0];
if (type === "service") {
getEndpoints();
getInstances();
getEndpoints(state.service.id);
getInstances(state.service.id);
}
}
function updateTags(data: { tagsMap: Array<Option>; tagsList: string[] }) {

View File

@@ -113,7 +113,7 @@ const state = reactive<any>({
status: { label: "All", value: "ALL" },
instance: { value: "0", label: "All" },
endpoint: { value: "0", label: "All" },
service: { value: "0", label: "All" },
service: { value: "", label: "" },
});
// const dateTime = computed(() => [
@@ -121,24 +121,21 @@ const state = reactive<any>({
// appStore.durationRow.end,
// ]);
init();
function init() {
searchTraces();
async function init() {
if (dashboardStore.entity === EntityType[1].value) {
getServices();
return;
await getServices();
}
if (dashboardStore.entity === EntityType[2].value) {
getInstances();
return;
await getInstances();
}
if (dashboardStore.entity === EntityType[3].value) {
getEndpoints();
return;
await getEndpoints();
}
if (dashboardStore.entity === EntityType[0].value) {
getInstances();
getEndpoints();
await getInstances();
await getEndpoints();
}
await searchTraces();
}
async function getServices() {
@@ -148,18 +145,20 @@ async function getServices() {
return;
}
state.service = traceStore.services[0];
getEndpoints(state.service.id);
getInstances(state.service.id);
}
async function getEndpoints() {
const resp = await traceStore.getEndpoints();
async function getEndpoints(id?: string) {
const resp = await traceStore.getEndpoints(id);
if (resp.errors) {
ElMessage.error(resp.errors);
return;
}
state.endpoint = traceStore.endpoints[0];
}
async function getInstances() {
const resp = await traceStore.getInstances();
async function getInstances(id?: string) {
const resp = await traceStore.getInstances(id);
if (resp.errors) {
ElMessage.error(resp.errors);
return;
@@ -201,8 +200,8 @@ async function queryTraces() {
function changeField(type: string, opt: any) {
state[type] = opt[0];
if (type === "service") {
getEndpoints();
getInstances();
getEndpoints(state.service.id);
getInstances(state.service.id);
}
}
function updateTags(data: { tagsMap: Array<Option>; tagsList: string[] }) {