| <!-- Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| 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 class="rk-endpoint-dependency" :style="`height: ${height}px`"> |
| <div class="endpoint-dependency-chart"> |
| <DependencySankey |
| v-if="stateTopo.endpointDependency.nodes.length" |
| :data="stateTopo.endpointDependency" |
| @showMetrics="showEndpointMetrics" |
| /> |
| <div v-else class="endpoint-dependency-empty"> |
| No Endpoint Dependency |
| </div> |
| </div> |
| <div class="mb-5 header" v-if="stateTopo.selectedEndpointCall"> |
| <span class="topo-tool-btn" @click="handleSetEdit"> |
| <rk-icon |
| class="lg rk-icon" |
| :style="`color:${stateTopo.editDependencyMetrics ? '#ffc107' : ''}`" |
| :icon="stateTopo.editDependencyMetrics ? 'lock-open' : 'lock'" |
| v-tooltip:bottom="{ content: stateTopo.editDependencyMetrics ? 'view' : 'edit' }" |
| /> |
| </span> |
| <span class="topo-tool-btn" v-tooltip:bottom="{ content: 'import' }"> |
| <input |
| id="endpoint-tool-bar-file" |
| type="file" |
| name="file" |
| title="" |
| accept=".json" |
| @change="importEndpointDependencyMetricsTemplate" |
| /> |
| <label for="endpoint-tool-bar-file"> |
| <rk-icon class="lg import" icon="folder_open" /> |
| </label> |
| </span> |
| <span class="topo-tool-btn" @click="exportTopoEndpointDependencyMetrics"> |
| <rk-icon class="lg" icon="save_alt" v-tooltip:bottom="{ content: 'export' }" /> |
| </span> |
| <span class="ml-5 pb-5 flex-h"> |
| <div class="type grey">{{ $t('templateType') }}</div> |
| <RkSelect |
| class="content grey" |
| :mode="'multiple'" |
| :current="currentType" |
| :data="templateNameList" |
| :theme="'dark'" |
| @onChoose="(item) => changeTemplatesType(item)" |
| /> |
| </span> |
| </div> |
| <div v-if="stateTopo.selectedEndpointCall" class="endpoint-dependency-metrics scroll_bar_style"> |
| <DashboardItem |
| v-for="(i, index) in topoEndpointDependencyMetrics || []" |
| :key="i.uuid" |
| :rocketGlobal="rocketGlobal" |
| :item="i" |
| :index="index" |
| :type="type" |
| :updateObjects="true" |
| :rocketOption="stateDashboardOption" |
| :templateTypes="templateType" |
| @setTemplates="setMetricsTemplate" |
| /> |
| <div v-show="stateTopo.editDependencyMetrics" class="rk-add-metric-item g-sm-3" @click="addMetrics"> |
| + Add An Item |
| </div> |
| </div> |
| </div> |
| </template> |
| <script lang="ts"> |
| import { Vue, Component, Watch } from 'vue-property-decorator'; |
| import { State, Getter, Mutation } from 'vuex-class'; |
| import { State as optionState } from '@/store/modules/global/selectors'; |
| import { State as rocketbotGlobal } from '@/store/modules/global'; |
| import { State as topoState } from '@/store/modules/topology'; |
| import DependencySankey from '../chart/dependency-sankey.vue'; |
| import DashboardItem from '@/views/components/dashboard/dashboard-item.vue'; |
| import { readFile } from '@/utils/readFile'; |
| import { saveFile } from '@/utils/saveFile'; |
| import { Duration } from '@/types/global'; |
| import { EndpointDependencyConidition, Call } from '@/types/topo'; |
| import { DEFAULT, TopologyType } from '@/constants/constant'; |
| import { Option } from '@/types/global'; |
| import { uuid } from '@/utils/uuid'; |
| |
| @Component({ |
| components: { |
| DependencySankey, |
| DashboardItem, |
| }, |
| }) |
| export default class TopoEndpointDependency extends Vue { |
| @Getter('durationTime') private durationTime!: Duration; |
| @Getter('intervalTime') private intervalTime: any; |
| @State('rocketTopo') private stateTopo!: topoState; |
| @State('rocketOption') private stateDashboardOption!: optionState; |
| @State('rocketbot') private rocketGlobal!: rocketbotGlobal; |
| @Mutation('rocketTopo/SET_SELECTED_ENDPOINT_CALL') private SET_SELECTED_ENDPOINT_CALL: any; |
| @Mutation('SET_ENDPOINT_DEPENDENCY') private SET_ENDPOINT_DEPENDENCY: any; |
| @Mutation('rocketTopo/EDIT_DEPENDENCY_METRICS') private EDIT_DEPENDENCY_METRICS: any; |
| @Mutation('rocketTopo/IMPORT_TREE_ENDPOINT_DEPENDENCY') private IMPORT_TREE_ENDPOINT_DEPENDENCY: any; |
| @Mutation('rocketTopo/ADD_TOPO_ENDPOINT_DEPENDENCY_COMP') private ADD_TOPO_ENDPOINT_DEPENDENCY_COMP: any; |
| @Mutation('rocketTopo/UPDATE_TOPO_TEMPLATE_TYPES') private UPDATE_TOPO_TEMPLATE_TYPES: any; |
| @Mutation('rocketTopo/SET_TOPO_ENDPOINT_DEPENDENCY') private SET_TOPO_ENDPOINT_DEPENDENCY: any; |
| |
| private templateType: string[] = []; |
| private topoEndpointDependencyMetrics: any = []; |
| private type = TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY; |
| private height = 500; |
| private templateNameList: Option[] = []; |
| private currentType: Option[] = []; |
| |
| private beforeMount() { |
| this.height = document.body.clientHeight - 103; |
| } |
| |
| private addMetrics() { |
| this.ADD_TOPO_ENDPOINT_DEPENDENCY_COMP(); |
| this.setMetricsTemplate(); |
| } |
| |
| private changeTemplatesType(item: Option) { |
| let topoTemplateTypes; |
| const types = this.stateTopo.topoTemplatesType; |
| |
| if (this.currentType.find((d) => d.key === item.key)) { |
| this.deleteTemplateTypes(item); |
| return; |
| } |
| this.currentType.push(item); |
| topoTemplateTypes = { |
| ...types, |
| [TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY]: this.currentType, |
| }; |
| this.UPDATE_TOPO_TEMPLATE_TYPES(topoTemplateTypes); |
| this.setTemplateTypes(); |
| this.setMetricsTemplate(); |
| } |
| |
| private deleteTemplateTypes(item: any) { |
| let topoTemplateTypes = null; |
| const types = this.stateTopo.topoTemplatesType; |
| const index = this.currentType.findIndex((d) => item.key === d.key); |
| |
| this.currentType.splice(index, 1); |
| topoTemplateTypes = { |
| ...types, |
| [TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY]: this.currentType, |
| }; |
| this.setTemplateTypes(); |
| this.UPDATE_TOPO_TEMPLATE_TYPES(topoTemplateTypes); |
| this.setMetricsTemplate(); |
| } |
| |
| private showEndpointMetrics(data: EndpointDependencyConidition & Call) { |
| this.SET_SELECTED_ENDPOINT_CALL(data); |
| this.SET_ENDPOINT_DEPENDENCY(data); |
| this.setTemplateTypes(); |
| this.templateNameList = Object.keys(this.stateTopo.topoEndpointDependency).map((item: string) => { |
| return { label: item, key: item }; |
| }); |
| this.setMetricsTemplate(); |
| } |
| |
| private setMetricsTemplate() { |
| this.topoEndpointDependencyMetrics = []; |
| let templates: any = {}; |
| |
| for (const type of Object.keys(this.stateTopo.topoEndpointDependency)) { |
| const metricsTemp = this.stateTopo.topoEndpointDependency[type].map((item: any) => { |
| item.uuid = item.uuid || uuid(); |
| return item; |
| }); |
| templates = { |
| ...templates, |
| [type]: metricsTemp, |
| }; |
| } |
| this.SET_TOPO_ENDPOINT_DEPENDENCY(templates); |
| for (const type of this.templateType) { |
| this.topoEndpointDependencyMetrics = [ |
| ...this.topoEndpointDependencyMetrics, |
| ...this.stateTopo.topoEndpointDependency[type], |
| ]; |
| } |
| } |
| |
| private setTemplateTypes() { |
| if (!this.stateTopo.selectedEndpointCall) { |
| return; |
| } |
| const nodeType = this.stateTopo.selectedEndpointCall.type || DEFAULT; |
| const templates = this.stateTopo.topoTemplatesType || {}; |
| let templateTypes = []; |
| |
| if (templates[TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY]) { |
| templateTypes = templates[TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY].map((item: Option) => item.key); |
| } else { |
| templateTypes = this.stateTopo.topoEndpointDependency[nodeType] ? [nodeType] : [DEFAULT]; |
| } |
| |
| this.templateType = templateTypes; |
| this.currentType = templateTypes.map((d: Option) => { |
| return { key: d, label: d }; |
| }); |
| } |
| |
| private handleSetEdit() { |
| this.EDIT_DEPENDENCY_METRICS(!this.stateTopo.editDependencyMetrics); |
| } |
| |
| private async importEndpointDependencyMetricsTemplate(event: Event) { |
| try { |
| const data: any = await readFile(event); |
| if (!Array.isArray(data)) { |
| throw new Error(); |
| } |
| this.IMPORT_TREE_ENDPOINT_DEPENDENCY(data[0]); |
| this.setMetricsTemplate(); |
| const el: any = document.getElementById('endpoint-tool-bar-file'); |
| el!.value = ''; |
| } catch (e) { |
| this.$modal.show('dialog', { text: 'ERROR' }); |
| } |
| } |
| |
| private exportTopoEndpointDependencyMetrics() { |
| const name = 'topo_endpoint_dependency_metrics.json'; |
| let group: any = {}; |
| |
| for (const type of Object.keys(this.stateTopo.topoEndpointDependency)) { |
| const metricsTemp = this.stateTopo.topoEndpointDependency[type].map((item: any) => { |
| delete item.uuid; |
| return item; |
| }); |
| group = { |
| ...group, |
| [type]: metricsTemp, |
| }; |
| } |
| |
| saveFile([group], name); |
| } |
| |
| @Watch('stateTopo.endpointDependency.nodes') |
| private updateMetrics() { |
| this.topoEndpointDependencyMetrics = []; |
| } |
| |
| private beforeDestroy() { |
| this.stateTopo.endpointDependency = { |
| calls: [], |
| nodes: [], |
| }; |
| } |
| } |
| </script> |
| <style lang="scss" scoped> |
| @import url('../styles/common.scss'); |
| .rk-endpoint-dependency { |
| background: #333840; |
| display: flex; |
| flex-direction: column; |
| .endpoint-dependency-chart { |
| height: 75%; |
| min-height: 500px; |
| } |
| .endpoint-dependency-empty { |
| color: #fff; |
| text-align: center; |
| height: 500px; |
| line-height: 500px; |
| } |
| } |
| .endpoint-dependency-metrics { |
| background: #333840; |
| height: 25%; |
| overflow: auto; |
| min-height: 210px; |
| } |
| .header { |
| z-index: 1; |
| } |
| #endpoint-tool-bar-file { |
| display: none; |
| } |
| .topo-tool-btn { |
| cursor: pointer; |
| color: #fff; |
| margin-right: 5px; |
| } |
| .rk-add-metric-item { |
| color: #eee; |
| } |
| .type { |
| width: 100px; |
| } |
| .content { |
| width: 400px; |
| } |
| </style> |