feat: open dashboards with selector ids of link url

This commit is contained in:
Qiuxia Fan 2022-01-24 18:31:33 +08:00
parent 21fb053bda
commit e314f45874
13 changed files with 177 additions and 47 deletions

View File

@ -13,7 +13,7 @@ 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>
<router-view /> <router-view :key="$route.fullPath" />
</template> </template>
<style> <style>

View File

@ -59,3 +59,49 @@ export const Endpoints = {
} }
`, `,
}; };
export const getService = {
variable: "$serviceId: String!",
query: `
service: getService(serviceId: $serviceId) {
id
value: name
label: name
group
layers
normal
}
`,
};
export const getInstance = {
variable: "$instanceId: String!",
query: `
instance: getInstance(instanceId: $instanceId) {
id
value: name
label: name
language
instanceUUID
layer
attributes {
name
value
}
}
`,
};
export const getEndpoint = {
variable: "$endpointId: String!",
query: `
endpoint: getEndpointInfo(endpointId: $endpointId) {
id
value: name
label: name
serviceId
serviceName
}
}
`,
};

View File

@ -14,10 +14,20 @@
* 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.
*/ */
import { Services, Layers, Endpoints, Instances } from "../fragments/selector"; import {
Services,
Layers,
Endpoints,
Instances,
getService,
getInstance,
getEndpoint,
} from "../fragments/selector";
export const queryServices = `query queryServices(${Services.variable}) {${Services.query}}`; export const queryServices = `query queryServices(${Services.variable}) {${Services.query}}`;
export const queryEndpoints = `query queryEndpoints(${Endpoints.variable}) {${Endpoints.query}}`; export const queryEndpoints = `query queryEndpoints(${Endpoints.variable}) {${Endpoints.query}}`;
export const queryInstances = `query queryInstances(${Instances.variable}) {${Instances.query}}`; export const queryInstances = `query queryInstances(${Instances.variable}) {${Instances.query}}`;
export const queryLayers = `query listLayer {${Layers.query}}`; export const queryLayers = `query listLayer {${Layers.query}}`;
export const queryService = `query queryService(${getService.variable}) {${getService.query}}`;
export const queryInstance = `query queryInstance(${getInstance.variable}) {${getInstance.query}}`;
export const queryEndpoint = `query queryInstance(${getEndpoint.variable}) {${getEndpoint.query}}`;

View File

@ -28,6 +28,9 @@ export function useQueryProcessor(config: any) {
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const selectorStore = useSelectorStore(); const selectorStore = useSelectorStore();
if (!selectorStore.currentService) {
return;
}
const conditions: { [key: string]: unknown } = { const conditions: { [key: string]: unknown } = {
duration: appStore.durationTime, duration: appStore.durationTime,
}; };
@ -76,10 +79,10 @@ export function useQueryProcessor(config: any) {
? undefined ? undefined
: selectorStore.currentService.normal, : selectorStore.currentService.normal,
serviceInstanceName: dashboardStore.entity.includes("ServiceInstance") serviceInstanceName: dashboardStore.entity.includes("ServiceInstance")
? selectorStore.currentPod ? selectorStore.currentPod.value
: undefined, : undefined,
endpointName: dashboardStore.entity.includes("Endpoint") endpointName: dashboardStore.entity.includes("Endpoint")
? selectorStore.currentPod ? selectorStore.currentPod.value
: undefined, : undefined,
destNormal: isRelation destNormal: isRelation
? selectorStore.currentDestService.normal ? selectorStore.currentDestService.normal
@ -89,11 +92,11 @@ export function useQueryProcessor(config: any) {
: undefined, : undefined,
destServiceInstanceName: destServiceInstanceName:
dashboardStore.entity === "ServiceInstanceRelation" dashboardStore.entity === "ServiceInstanceRelation"
? selectorStore.currentDestPod ? selectorStore.currentDestPod.value
: undefined, : undefined,
destEndpointName: destEndpointName:
dashboardStore.entity === "EndpointRelation" dashboardStore.entity === "EndpointRelation"
? selectorStore.currentDestPod ? selectorStore.currentDestPod.value
: undefined, : undefined,
}, },
}; };

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<template> <template>
<section class="app-main"> <section class="app-main">
<router-view v-slot="{ Component }"> <router-view v-slot="{ Component }" :key="$route.fullPath">
<keep-alive> <keep-alive>
<component :is="Component" /> <component :is="Component" />
</keep-alive> </keep-alive>

View File

@ -15,8 +15,8 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { Option, Duration } from "@/types/app"; import { Duration } from "@/types/app";
import { Service } from "@/types/selector"; import { Service, Instance, Endpoint } from "@/types/selector";
import { store } from "@/store"; import { store } from "@/store";
import graph from "@/graph"; import graph from "@/graph";
import { AxiosResponse } from "axios"; import { AxiosResponse } from "axios";
@ -24,13 +24,11 @@ import { useAppStoreWithOut } from "@/store/modules/app";
interface SelectorState { interface SelectorState {
services: Service[]; services: Service[];
instances: Option[]; pods: Array<Instance | Endpoint>;
pods: Option[];
endpoints: Option[];
currentService: Nullable<Service>; currentService: Nullable<Service>;
currentPod: string; currentPod: Nullable<Instance | Endpoint>;
currentDestService: Nullable<Service>; currentDestService: Nullable<Service>;
currentDestPod: string; currentDestPod: Nullable<Instance | Endpoint>;
durationTime: Duration; durationTime: Duration;
} }
@ -38,20 +36,18 @@ export const selectorStore = defineStore({
id: "selector", id: "selector",
state: (): SelectorState => ({ state: (): SelectorState => ({
services: [], services: [],
instances: [],
pods: [], pods: [],
endpoints: [],
currentService: null, currentService: null,
currentPod: "", currentPod: null,
currentDestService: null, currentDestService: null,
currentDestPod: "", currentDestPod: null,
durationTime: useAppStoreWithOut().durationTime, durationTime: useAppStoreWithOut().durationTime,
}), }),
actions: { actions: {
setCurrentService(service: Service) { setCurrentService(service: Service) {
this.currentService = service; this.currentService = service;
}, },
setCurrentPod(pod: string) { setCurrentPod(pod: Nullable<Instance | Endpoint>) {
this.currentPod = pod; this.currentPod = pod;
}, },
async fetchLayers(): Promise<AxiosResponse> { async fetchLayers(): Promise<AxiosResponse> {
@ -82,9 +78,8 @@ export const selectorStore = defineStore({
duration: this.durationTime, duration: this.durationTime,
}); });
if (!res.data.errors) { if (!res.data.errors) {
this.instances = res.data.data.pods || []; this.pods = res.data.data.pods || [];
this.pods = this.instances; this.currentPod = this.pods.length ? this.pods[0] : null;
this.currentPod = this.pods.length ? this.pods[0].value : "";
} }
return res.data; return res.data;
}, },
@ -108,12 +103,50 @@ export const selectorStore = defineStore({
keyword: params.keyword, keyword: params.keyword,
}); });
if (!res.data.errors) { if (!res.data.errors) {
this.endpoints = res.data.data.pods || []; this.pods = res.data.data.pods || [];
this.pods = this.endpoints; this.currentPod = this.pods.length ? this.pods[0] : null;
this.currentPod = this.pods.length ? this.pods[0].value : "";
} }
return res.data; return res.data;
}, },
async getService(serviceId: string) {
if (!serviceId) {
return;
}
const res: AxiosResponse = await graph.query("queryService").params({
serviceId,
});
if (!res.data.errors) {
this.currentService = res.data.data.service || {};
}
return res.data;
},
async getInstance(instanceId: string) {
if (!instanceId) {
return;
}
const res: AxiosResponse = await graph.query("queryInstance").params({
instanceId,
});
if (!res.data.errors) {
this.currentPod = res.data.data.instance || null;
}
return res.data;
},
async getEndpoint(endpointId: string) {
if (!endpointId) {
return;
}
const res: AxiosResponse = await graph.query("queryEndpoint").params({
endpointId,
});
if (!res.data.errors) {
this.currentPod = res.data.data.endpoint || null;
}
return res.data;
},
}, },
}); });

View File

@ -194,9 +194,13 @@ async function queryMetrics() {
} }
function changeDashboard(item: Option[]) { function changeDashboard(item: Option[]) {
const graph = {
...dashboardStore.selectedGrid.graph,
dashboardName: item[0].value,
};
dashboardStore.selectWidget({ dashboardStore.selectWidget({
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
...{ dashboardName: item[0].value }, graph,
}); });
} }
function addMetric() { function addMetric() {

View File

@ -61,6 +61,7 @@ limitations under the License. -->
<script lang="ts"> <script lang="ts">
import { toRefs, reactive, defineComponent, ref, watch } from "vue"; import { toRefs, reactive, defineComponent, ref, watch } from "vue";
import type { PropType } from "vue"; import type { PropType } from "vue";
import { useRoute } from "vue-router";
import { LayoutConfig } from "@/types/dashboard"; import { LayoutConfig } from "@/types/dashboard";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
@ -82,6 +83,7 @@ export default defineComponent({
props, props,
setup(props) { setup(props) {
const { t } = useI18n(); const { t } = useI18n();
const params = useRoute().params;
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
const state = reactive<{ source: { [key: string]: unknown } }>({ const state = reactive<{ source: { [key: string]: unknown } }>({
source: {}, source: {},
@ -91,6 +93,10 @@ export default defineComponent({
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const selectorStore = useSelectorStore(); const selectorStore = useSelectorStore();
if (params.serviceId) {
queryMetrics();
}
async function queryMetrics() { async function queryMetrics() {
const params = await useQueryProcessor(props.data); const params = await useQueryProcessor(props.data);
if (!params) { if (!params) {

View File

@ -39,7 +39,7 @@ limitations under the License. -->
<router-link <router-link
target="_blank" target="_blank"
class="link" class="link"
:to="`/dashboard/${scope.row.layer}/endpoint/${selectorStore.currentService.value}/${scope.row.value}/${config.dashboardName}`" :to="`/dashboard/${scope.row.layer}/Endpoint/${selectorStore.currentService.id}/${scope.row.id}/${config.dashboardName}`"
:style="{ fontSize: `${config.fontSize}px` }" :style="{ fontSize: `${config.fontSize}px` }"
> >
{{ scope.row.label }} {{ scope.row.label }}
@ -67,7 +67,7 @@ limitations under the License. -->
background background
layout="prev, pager, next" layout="prev, pager, next"
:page-size="pageSize" :page-size="pageSize"
:total="selectorStore.endpoints.length" :total="selectorStore.pods.length"
@current-change="changePage" @current-change="changePage"
@prev-click="changePage" @prev-click="changePage"
@next-click="changePage" @next-click="changePage"
@ -115,8 +115,8 @@ async function queryEndpoints() {
ElMessage.error(resp.errors); ElMessage.error(resp.errors);
return; return;
} }
searchEndpoints.value = selectorStore.endpoints; searchEndpoints.value = selectorStore.pods;
endpoints.value = selectorStore.endpoints.splice(0, pageSize); endpoints.value = selectorStore.pods.splice(0, pageSize);
queryEndpointMetrics(endpoints.value); queryEndpointMetrics(endpoints.value);
} }
async function queryEndpointMetrics(currentPods: Endpoint[]) { async function queryEndpointMetrics(currentPods: Endpoint[]) {
@ -147,8 +147,8 @@ function changePage(pageIndex: number) {
endpoints.value = searchEndpoints.value.splice(pageIndex - 1, pageSize); endpoints.value = searchEndpoints.value.splice(pageIndex - 1, pageSize);
} }
function searchList() { function searchList() {
const currentEndpoints = selectorStore.instances.filter( const currentEndpoints = selectorStore.pods.filter((d: { label: string }) =>
(d: { label: string }) => d.label.includes(searchText.value) d.label.includes(searchText.value)
); );
searchEndpoints.value = currentEndpoints; searchEndpoints.value = currentEndpoints;
endpoints.value = currentEndpoints.splice(0, pageSize); endpoints.value = currentEndpoints.splice(0, pageSize);

View File

@ -37,9 +37,8 @@ limitations under the License. -->
<el-table-column label="Service Instances"> <el-table-column label="Service Instances">
<template #default="scope"> <template #default="scope">
<router-link <router-link
target="_blank"
class="link" class="link"
:to="`/dashboard/${scope.row.layer}/serviceInstance/${selectorStore.currentService.value}/${scope.row.value}/${config.dashboardName}`" :to="`/dashboard/${scope.row.layer}/ServiceInstance/${selectorStore.currentService.id}/${scope.row.id}/${config.dashboardName}`"
:style="{ fontSize: `${config.fontSize}px` }" :style="{ fontSize: `${config.fontSize}px` }"
> >
{{ scope.row.label }} {{ scope.row.label }}
@ -96,7 +95,7 @@ defineProps({
const selectorStore = useSelectorStore(); const selectorStore = useSelectorStore();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const chartLoading = ref<boolean>(false); const chartLoading = ref<boolean>(false);
const instances = ref<(Instance | any)[]>([]); // current instances const instances = ref<Instance[]>([]); // current instances
const searchInstances = ref<Instance[]>([]); // all instances const searchInstances = ref<Instance[]>([]); // all instances
const pageSize = 5; const pageSize = 5;
const searchText = ref<string>(""); const searchText = ref<string>("");
@ -112,7 +111,7 @@ async function queryInstance() {
ElMessage.error(resp.errors); ElMessage.error(resp.errors);
return; return;
} }
searchInstances.value = selectorStore.instances; searchInstances.value = selectorStore.pods;
const currentInstances = searchInstances.value.splice(0, pageSize); const currentInstances = searchInstances.value.splice(0, pageSize);
queryInstanceMetrics(currentInstances); queryInstanceMetrics(currentInstances);
@ -147,8 +146,8 @@ function changePage(pageIndex: number) {
instances.value = searchInstances.value.splice(pageIndex - 1, pageSize); instances.value = searchInstances.value.splice(pageIndex - 1, pageSize);
} }
function searchList() { function searchList() {
searchInstances.value = selectorStore.instances.filter( searchInstances.value = selectorStore.pods.filter((d: { label: string }) =>
(d: { label: string }) => d.label.includes(searchText.value) d.label.includes(searchText.value)
); );
instances.value = searchInstances.value.splice(0, pageSize); instances.value = searchInstances.value.splice(0, pageSize);
} }

View File

@ -39,7 +39,8 @@ limitations under the License. -->
<router-link <router-link
target="_blank" target="_blank"
class="link" class="link"
:to="`/dashboard/${scope.row.layer}/service/${selectorStore.currentService.value}/${config.dashboardName}`" :to="`/dashboard/${scope.row.layer}/Service/${selectorStore.currentService.value}/${config.dashboardName}`"
:key="1"
:style="{ fontSize: `${config.fontSize}px` }" :style="{ fontSize: `${config.fontSize}px` }"
> >
{{ scope.row.label }} {{ scope.row.label }}
@ -144,8 +145,8 @@ function changePage(pageIndex: number) {
services.value = selectorStore.services.splice(pageIndex - 1, pageSize); services.value = selectorStore.services.splice(pageIndex - 1, pageSize);
} }
function searchList() { function searchList() {
searchServices.value = selectorStore.instances.filter( searchServices.value = selectorStore.services.filter((d: { label: string }) =>
(d: { label: string }) => d.label.includes(searchText.value) d.label.includes(searchText.value)
); );
services.value = searchServices.value.splice(0, pageSize); services.value = searchServices.value.splice(0, pageSize);
} }

View File

@ -16,6 +16,8 @@
*/ */
.table { .table {
height: 100%; height: 100%;
overflow: auto;
padding: 0 10px 5px 0;
} }
.pagination { .pagination {

View File

@ -14,7 +14,8 @@ 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">
<div class="flex-h" v-if="!params.serviceId"> <div v-if="params.serviceId"></div>
<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
@ -35,7 +36,7 @@ limitations under the License. -->
}} }}
</span> </span>
<Selector <Selector
v-model="selectorStore.currentPod" v-model="states.currentPod"
:options="selectorStore.pods" :options="selectorStore.pods"
size="mini" size="mini"
placeholder="Select a data" placeholder="Select a data"
@ -57,7 +58,7 @@ limitations under the License. -->
<div class="selectors-item" v-if="states.key === 4"> <div class="selectors-item" v-if="states.key === 4">
<span class="label">$DestinationServiceInstance</span> <span class="label">$DestinationServiceInstance</span>
<Selector <Selector
v-model="selectorStore.currentPod" v-model="states.currentPod"
:options="selectorStore.pods" :options="selectorStore.pods"
size="mini" size="mini"
placeholder="Select a data" placeholder="Select a data"
@ -96,21 +97,43 @@ import { Service } from "@/types/selector";
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const selectorStore = useSelectorStore(); const selectorStore = useSelectorStore();
const params = useRoute().params; const params = useRoute().params;
const type = EntityType.filter((d: Option) => d.value === params.entity)[0];
const states = reactive<{ const states = reactive<{
destService: string; destService: string;
destPod: string; destPod: string;
key: number; key: number;
currentService: string; currentService: string;
currentPod: string;
}>({ }>({
destService: "", destService: "",
destPod: "", destPod: "",
key: EntityType.filter((d: Option) => d.value === params.entity)[0].key || 0, key: (type && type.key) || 0,
currentService: "", currentService: "",
currentPod: "",
}); });
dashboardStore.setLayer(String(params.layerId)); dashboardStore.setLayer(String(params.layerId));
dashboardStore.setEntity(String(params.entity)); dashboardStore.setEntity(String(params.entity));
getServices(); if (params.serviceId) {
setSelector();
} else {
getServices();
}
async function setSelector() {
await selectorStore.getService(String(params.serviceId));
states.currentService = selectorStore.currentService.value;
if (params.podId) {
if (String(params.entity) === EntityType[2].value) {
await selectorStore.getEndpoint(String(params.podId));
}
if (String(params.entity) === EntityType[3].value) {
await selectorStore.getInstance(String(params.podId));
}
states.currentPod = selectorStore.currentPod.label;
}
}
async function getServices() { async function getServices() {
if (!dashboardStore.layerId) { if (!dashboardStore.layerId) {
@ -167,15 +190,18 @@ async function fetchPods(type: string) {
switch (type) { switch (type) {
case "Endpoint": case "Endpoint":
resp = await selectorStore.getEndpoints(); resp = await selectorStore.getEndpoints();
states.currentPod = selectorStore.currentPod.label;
break; break;
case "ServiceInstance": case "ServiceInstance":
resp = await selectorStore.getServiceInstances(); resp = await selectorStore.getServiceInstances();
states.currentPod = selectorStore.currentPod.label;
break; break;
default: default:
resp = {}; resp = {};
} }
if (resp.errors) { if (resp.errors) {
ElMessage.error(resp.errors); ElMessage.error(resp.errors);
return;
} }
} }
</script> </script>