This is an automated email from the ASF dual-hosted git repository. wusheng pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/skywalking-rocketbot-ui.git
The following commit(s) were added to refs/heads/master by this push: new d339675 feat: implement Events in dashboard (#452) d339675 is described below commit d339675c61ff0444f101edaedb92bd8a7bbca5b0 Author: Qiuxia Fan <fine0...@outlook.com> AuthorDate: Tue Apr 6 11:43:32 2021 +0800 feat: implement Events in dashboard (#452) --- src/assets/lang/en.ts | 17 +- src/assets/lang/zh.ts | 17 +- src/components/rk-select.vue | 3 +- src/constants/constant.ts | 10 + src/graph/fragments/dashboard.ts | 25 ++ src/graph/query/dashboard.ts | 3 + src/main.ts | 1 + src/store/modules/dashboard/dashboard-data.ts | 108 ++++- src/store/modules/dashboard/mutation-types.ts | 9 + src/store/modules/global/index.ts | 40 +- src/store/modules/global/selectors.ts | 110 +++-- src/types/dashboard.d.ts | 35 +- src/utils/{dateFormatStep.ts => dateFormat.ts} | 37 ++ .../components/dashboard/charts/chart-bar.vue | 41 ++ .../charts/{chart-bar.vue => chart-heap.vue} | 101 ++--- .../components/dashboard/charts/chart-heatmap.vue | 1 + .../components/dashboard/charts/chart-line.vue | 41 ++ .../components/dashboard/charts/chart-sankey.vue | 67 +++ src/views/components/dashboard/constant.ts | 22 + src/views/components/dashboard/dashboard-comp.vue | 2 +- src/views/components/dashboard/dashboard-item.vue | 69 ++- .../dashboard/tool-bar/dashboard-events.vue | 490 +++++++++++++++++++++ .../dashboard/tool-bar/tool-bar-btns.vue | 75 ++-- .../components/dashboard/tool-bar/tool-bar.vue | 201 ++++++--- src/views/components/dashboard/tool-group.vue | 4 +- src/views/components/dashboard/tool-nav.vue | 55 +-- src/views/components/log/log-bar.vue | 7 +- src/views/components/log/log-conditions.vue | 2 +- src/views/components/log/log-service-detail.vue | 1 - src/views/components/profile/profile-task.vue | 5 +- src/views/components/topology/topo-aside.vue | 6 +- .../topology/topo-endpoint-dependency.vue | 2 +- src/views/components/trace/trace-search.vue | 2 +- src/views/containers/dashboard.vue | 14 +- src/views/containers/topology/endpoint/index.vue | 85 ++-- src/views/containers/topology/instance/index.vue | 98 +++-- vue.config.js | 1 - 37 files changed, 1426 insertions(+), 381 deletions(-) diff --git a/src/assets/lang/en.ts b/src/assets/lang/en.ts index 645d8c1..04b36fe 100644 --- a/src/assets/lang/en.ts +++ b/src/assets/lang/en.ts @@ -99,7 +99,7 @@ const m = { range: 'Range', timeRange: 'Time Range', duration: 'Duration', - startTime: 'startTime', + startTime: 'Start Time', start: 'Start', spans: 'Spans', spanInfo: 'Span Info', @@ -199,7 +199,22 @@ const m = { logsTagsTip: `Only tags defined in the core/default/searchableLogsTags are searchable. Check more details on the Configuration Vocabulary page`, keywordsOfContentLogTips: 'Current storage of SkyWalking OAP server does not support this.', + setEvent: 'Set Event', instanceAttributes: 'Instance Attributes', + serviceEvents: 'Service Events', + select: 'Select', + eventID: 'Event ID', + eventName: 'Event Name', + endTime: 'End Time', + instanceEvents: 'Instance Events', + endpointEvents: 'Endpoint Events', + enableEvents: 'Enable Events', + disableEvents: 'Disable Events', + eventSeries: 'Events Series', + eventsType: 'Event Type', + eventsMessage: 'Event Message', + eventsParameters: 'Event Parameters', + eventDetail: 'Event Detail', value: 'Value', tableHeader: 'Header Names', tableValues: 'Table Values', diff --git a/src/assets/lang/zh.ts b/src/assets/lang/zh.ts index f222588..7b4a3d7 100644 --- a/src/assets/lang/zh.ts +++ b/src/assets/lang/zh.ts @@ -197,7 +197,22 @@ const m = { viewLogs: '查看日志', logsTagsTip: '只有core/default/searchableLogsTags中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。', keywordsOfContentLogTips: 'SkyWalking OAP服务器的当前存储不支持此操作', - instanceAttributes: '查看实例属性', + setEvent: '设置事件', + instanceAttributes: '实例属性', + serviceEvents: '服务事件', + select: '选择', + eventID: '事件ID', + eventName: '事件名称', + endTime: '结束事件', + instanceEvents: '实例事件', + endpointEvents: '端点事件', + enableEvents: '启动事件', + disableEvents: '禁用事件', + eventSeries: '事件系列', + eventsType: '事件类型', + eventsMessage: '事件消息', + eventsParameters: '事件参数', + eventDetail: '事件详情', value: '数值', tableHeader: '表头名称', tableValues: '表值', diff --git a/src/components/rk-select.vue b/src/components/rk-select.vue index 4b69653..528c05a 100644 --- a/src/components/rk-select.vue +++ b/src/components/rk-select.vue @@ -46,7 +46,7 @@ limitations under the License. --> <use xlink:href="#clear"></use> </svg> </div> - <div class="rk-opt-wrapper scroll_bar_style"> + <div class="rk-opt-wrapper"> <div class="rk-opt ell" @click="handleSelect(i)" @@ -104,7 +104,6 @@ limitations under the License. --> <style lang="scss" scoped> .rk-bar-select { position: relative; - height: 30px; justify-content: space-between; border: 1px solid #ddd; background: #fff; diff --git a/src/constants/constant.ts b/src/constants/constant.ts index 022719c..f67961e 100644 --- a/src/constants/constant.ts +++ b/src/constants/constant.ts @@ -31,3 +31,13 @@ export enum TimeType { HOUR_TIME = 'HOUR', DAY_TIME = 'DAY', } + +export enum PageEventsType { + DASHBOARD_EVENTS = 'dashboardEvents', + TOPO_ENDPOINT_EVENTS = 'topoEndpointEvents', + TOPO_INSTANCE_EVENTS = 'topoInstanceEvents', +} +export enum PageTypes { + DASHBOARD = 'Dashboard', + LOG = 'Log', +} diff --git a/src/graph/fragments/dashboard.ts b/src/graph/fragments/dashboard.ts index 2b762d7..2b46e60 100644 --- a/src/graph/fragments/dashboard.ts +++ b/src/graph/fragments/dashboard.ts @@ -42,6 +42,31 @@ export const addTemplate = { `, }; +export const fetchEvents = { + variable: ['$condition: EventQueryCondition'], + query: ` + fetchEvents: queryEvents(condition: $condition) { + events { + uuid + source { + service + serviceInstance + endpoint + } + name + type + message + parameters { + key + value + } + startTime + endTime + } + total + }`, +}; + export const changeTemplate = { variable: '$setting: DashboardSetting!', query: ` diff --git a/src/graph/query/dashboard.ts b/src/graph/query/dashboard.ts index 219577e..d95f6c1 100644 --- a/src/graph/query/dashboard.ts +++ b/src/graph/query/dashboard.ts @@ -27,6 +27,7 @@ import { querySortMetrics, queryMetricsValue, queryMetricsValues, + fetchEvents, } from '../fragments/dashboard'; export const queryTypeOfMetrics = `query queryTypeOfMetrics(${TypeOfMetrics.variable}) {${TypeOfMetrics.query}}`; @@ -53,3 +54,5 @@ export const sortMetrics = `query queryData(${querySortMetrics.variable}) {${que export const readMetricsValue = `query queryData(${queryMetricsValue.variable}) {${queryMetricsValue.query}}`; export const readMetricsValues = `query queryData(${queryMetricsValues.variable}) {${queryMetricsValues.query}}`; + +export const queryEvents = `query queryData(${fetchEvents.variable}) {${fetchEvents.query}}`; diff --git a/src/main.ts b/src/main.ts index 1ee8746..0b4c5e2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -33,6 +33,7 @@ import 'echarts/lib/chart/heatmap'; import 'echarts/lib/chart/sankey'; import 'echarts/lib/component/legend'; import 'echarts/lib/component/tooltip'; +import 'echarts/lib/component/markArea'; import VModal from 'vue-js-modal'; import { queryOAPTimeInfo } from './utils/localtime'; import './assets'; diff --git a/src/store/modules/dashboard/dashboard-data.ts b/src/store/modules/dashboard/dashboard-data.ts index 1d17125..298a96c 100644 --- a/src/store/modules/dashboard/dashboard-data.ts +++ b/src/store/modules/dashboard/dashboard-data.ts @@ -16,25 +16,112 @@ */ import { ActionTree, MutationTree, Commit, Dispatch } from 'vuex'; -import { CompsTree } from '@/types/dashboard'; +import { CompsTree, Event } from '@/types/dashboard'; import { AxiosResponse } from 'axios'; import graph from '@/graph'; import dashboardLayout from './dashboard-data-layout'; import dashboardQuery from './dashboard-data-query'; +import { QueryEventCondition } from '../../../types/dashboard'; +import { dateFormatTime } from '@/utils/dateFormat'; +import { DurationTime, Option } from '@/types/global'; +import * as types from './mutation-types'; +import { PageEventsType } from '@/constants/constant'; +const EntityType = ['Service', 'ServiceInstance', 'Endpoint']; export interface State { current: number; group: number; tree: CompsTree[]; + serviceEvents: Event[]; + serviceInstanceEvents: Event[]; + endpointEvents: Event[]; + enableEvents: boolean; + eventsPageType: string; + currentSeriesType: Option[]; } const initState: State = { + serviceEvents: [], + endpointEvents: [], + serviceInstanceEvents: [], + enableEvents: false, + eventsPageType: PageEventsType.DASHBOARD_EVENTS, + currentSeriesType: [], ...dashboardLayout.state, }; // mutations const mutations: MutationTree<any> = { ...dashboardLayout.mutations, + [types.SET_DASHBOARD_EVENTS](state: State, param: { events: Event[]; type: string; duration: DurationTime }) { + const events = param.events.map((d: Event, index: number) => { + d.entityType = param.type; + d.startTime = dateFormatTime(new Date(Number(d.startTime)), param.duration.step); + d.endTime = dateFormatTime(new Date(Number(d.endTime)), param.duration.step); + if (index > 2) { + return d; + } + for (const item of state.currentSeriesType) { + if (item.key === param.type) { + d.checked = true; + } + } + return d; + }); + if (param.type === EntityType[0]) { + state.serviceEvents = events; + } else if (param.type === EntityType[1]) { + state.serviceInstanceEvents = events; + } else { + state.endpointEvents = events; + } + }, + [types.SET_CHECKED_EVENTS](state: State, selectedEvents: Event[]) { + for (const event of selectedEvents) { + if (event.entityType === EntityType[0]) { + for (const item of state.serviceEvents) { + if (event.uuid === item.uuid && event.entityType === item.entityType) { + item.checked = event.checked; + break; + } + } + } + if (event.entityType === EntityType[1]) { + for (const item of state.serviceInstanceEvents) { + if (event.uuid === item.uuid && event.entityType === item.entityType) { + item.checked = event.checked; + break; + } + } + } + if (event.entityType === EntityType[2]) { + for (const item of state.endpointEvents) { + if (event.uuid === item.uuid && event.entityType === item.entityType) { + item.checked = event.checked; + break; + } + } + } + } + }, + [types.SET_ENABLE_EVENTS](state: State, enable: boolean) { + state.enableEvents = enable; + }, + [types.SET_EVENTS_PAGE_TYPE](state: State, type: string) { + state.eventsPageType = type; + }, + [types.SET_CURRENT_SERIES_TYPE](state: State, data: { item: Option; index: number }) { + if (data.index > -1) { + state.currentSeriesType.splice(data.index, 1); + } else { + state.currentSeriesType.push(data.item); + } + }, + [types.SET_CLEAR_SELECTED_EVENTS](state: State) { + for (const item of [...state.serviceEvents, ...state.serviceInstanceEvents, ...state.endpointEvents]) { + item.checked = false; + } + }, }; // actions @@ -108,15 +195,22 @@ const actions: ActionTree<State, any> = { return res.data.data.getAllTemplates || []; }); }, - ADD_TEMPLATE(context, params) { + GET_EVENT(context: { commit: Commit }, params: { condition: QueryEventCondition; type: string }) { return graph - .query('mutationAddTemplate') - .params({ setting: params }) + .query('queryEvents') + .params({ condition: params.condition }) .then((res: AxiosResponse) => { - if (!res.data.data) { - return; + if (!(res.data.data && res.data.data.fetchEvents)) { + context.commit('SET_DASHBOARD_EVENTS', { events: [], type: params.type, duration: params.condition.time }); + return []; } - return res.data.data.addTemplate || []; + context.commit('SET_DASHBOARD_EVENTS', { + events: res.data.data.fetchEvents.events, + type: params.type, + duration: params.condition.time, + }); + + return res.data.data.fetchEvents.events || []; }); }, }; diff --git a/src/store/modules/dashboard/mutation-types.ts b/src/store/modules/dashboard/mutation-types.ts index aa18646..eef9b1c 100644 --- a/src/store/modules/dashboard/mutation-types.ts +++ b/src/store/modules/dashboard/mutation-types.ts @@ -36,6 +36,12 @@ export const SET_INSTANCE_INFO = 'SET_INSTANCE_INFO'; export const SET_TEMPLATES = 'SET_TEMPLATES'; export const UPDATE_DASHBOARD = 'UPDATE_DASHBOARD'; export const SET_PAGE_TYPE = 'SET_PAGE_TYPE'; +export const SET_ALL_ENDPOINT_EVENTS = 'SET_ALL_ENDPOINT_EVENTS'; +export const SET_ALL_SERVICE_EVENTS = 'SET_ALL_SERVICE_EVENTS'; +export const SET_ALL_INSTANCE_EVENTS = 'SET_ALL_INSTANCE_EVENTS'; +export const SET_EVENTS_PAGE_TYPE = 'SET_EVENTS_PAGE_TYPE'; +export const SET_CURRENT_SERIES_TYPE = 'SET_CURRENT_SERIES_TYPE'; +export const SET_CLEAR_SELECTED_EVENTS = 'SET_CLEAR_SELECTED_EVENTS'; // comp export const SET_CURRENT_GROUP = 'SET_CURRENT_GROUP'; @@ -55,3 +61,6 @@ export const SWICH_CURRENTCOMP = 'SWICH_CURRENTCOMP'; export const SET_GROUP_QUERY = 'SET_GROUP_QUERY'; export const EDIT_COMP_CONFIG = 'EDIT_COMP_CONFIG'; export const SET_COMPS_ID = 'SET_COMPS_ID'; +export const SET_DASHBOARD_EVENTS = 'SET_DASHBOARD_EVENTS'; +export const SET_CHECKED_EVENTS = 'SET_CHECKED_EVENTS'; +export const SET_ENABLE_EVENTS = 'SET_ENABLE_EVENTS'; diff --git a/src/store/modules/global/index.ts b/src/store/modules/global/index.ts index 68f91a3..0d7cf44 100644 --- a/src/store/modules/global/index.ts +++ b/src/store/modules/global/index.ts @@ -19,48 +19,10 @@ import * as types from '@/store/mutation-types'; import { Duration, DurationTime } from '@/types/global'; import getDurationRow from '@/utils/datetime'; import getLocalTime from '@/utils/localtime'; -import dateFormatStep from '@/utils/dateFormatStep'; +import dateFormatStep, { dateFormatTime } from '@/utils/dateFormat'; import { ActionTree, Commit, MutationTree } from 'vuex'; let timer: any = null; - -const dateFormatTime = (date: Date, step: string): string => { - const year = date.getFullYear(); - const monthTemp = date.getMonth() + 1; - let month: string = `${monthTemp}`; - if (monthTemp < 10) { - month = `0${monthTemp}`; - } - if (step === 'MONTH') { - return `${year}-${month}`; - } - const dayTemp = date.getDate(); - let day: string = `${dayTemp}`; - if (dayTemp < 10) { - day = `0${dayTemp}`; - } - if (step === 'DAY') { - return `${month}-${day}`; - } - const hourTemp = date.getHours(); - let hour: string = `${hourTemp}`; - if (hourTemp < 10) { - hour = `0${hourTemp}`; - } - if (step === 'HOUR') { - return `${month}-${day} ${hour}`; - } - const minuteTemp = date.getMinutes(); - let minute: string = `${minuteTemp}`; - if (minuteTemp < 10) { - minute = `0${minuteTemp}`; - } - if (step === 'MINUTE') { - return `${hour}:${minute}\n${month}-${day}`; - } - return ''; -}; - export interface State { durationRow: Duration; eventStack: any; diff --git a/src/store/modules/global/selectors.ts b/src/store/modules/global/selectors.ts index 84eecfb..72832f2 100644 --- a/src/store/modules/global/selectors.ts +++ b/src/store/modules/global/selectors.ts @@ -19,22 +19,20 @@ import { Commit, ActionTree, MutationTree, Dispatch } from 'vuex'; import * as types from '../dashboard/mutation-types'; import { AxiosResponse } from 'axios'; import graph from '@/graph'; -import { Duration } from '@/types/global'; +import { Duration, DurationTime, Option } from '@/types/global'; +import { PageTypes } from '@/constants/constant'; -interface Options { - key: string; - label: string; -} +const EntityType = ['Service', 'ServiceInstance', 'Endpoint']; export interface State { - services: Options[]; - currentService: Options; - databases: Options[]; - currentDatabase: Options; - endpoints: Options[]; - currentEndpoint: Options; - instances: Options[]; - currentInstance: Options; - updateDashboard: object; + services: Option[]; + currentService: Option; + databases: Option[]; + currentDatabase: Option; + endpoints: Option[]; + currentEndpoint: Option; + instances: Option[]; + currentInstance: Option; + updateDashboard: { key: string; label?: string | undefined }; pageType: string; } @@ -49,26 +47,28 @@ const initState: State = { currentInstance: { key: '', label: '' }, databases: [], currentDatabase: { key: '', label: '' }, - updateDashboard: {}, + updateDashboard: { key: '' }, pageType: '', }; // mutations const mutations: MutationTree<State> = { - [types.SET_SERVICES](state: State, data: Options[]) { + [types.SET_SERVICES](state: State, data: Option[]) { state.services = state.pageType === LOG ? [{ label: 'All', key: '' }, ...data] : data; state.currentService = state.services[0] || {}; }, - [types.SET_CURRENT_SERVICE](state: State, service: Options) { + [types.SET_CURRENT_SERVICE](state: State, service: Option) { state.currentService = service; - state.updateDashboard = service; + if (state.pageType !== PageTypes.DASHBOARD) { + state.updateDashboard = service; + } }, - [types.UPDATE_DASHBOARD](state: State) { - state.updateDashboard = { key: new Date().getTime() }; + [types.UPDATE_DASHBOARD](state: State, param?: { key: string }) { + state.updateDashboard = param || { key: String(new Date().getTime()) }; }, - [types.SET_ENDPOINTS](state: State, data: Options[]) { + [types.SET_ENDPOINTS](state: State, data: Option[]) { state.endpoints = state.pageType === LOG ? [{ label: 'All', key: '' }, ...data] : data; if (!state.endpoints.length) { state.currentEndpoint = { key: '', label: '' }; @@ -76,11 +76,11 @@ const mutations: MutationTree<State> = { } state.currentEndpoint = state.endpoints[0]; }, - [types.SET_CURRENT_ENDPOINT](state: State, endpoint: Options) { + [types.SET_CURRENT_ENDPOINT](state: State, endpoint: Option) { state.currentEndpoint = endpoint; state.updateDashboard = endpoint; }, - [types.SET_INSTANCES](state: State, data: Options[]) { + [types.SET_INSTANCES](state: State, data: Option[]) { state.instances = state.pageType === LOG ? [{ label: 'All', key: '' }, ...data] : data; if (!state.instances.length) { state.currentInstance = { key: '', label: '' }; @@ -88,11 +88,11 @@ const mutations: MutationTree<State> = { } state.currentInstance = state.instances[0]; }, - [types.SET_CURRENT_INSTANCE](state: State, instance: Options) { + [types.SET_CURRENT_INSTANCE](state: State, instance: Option) { state.currentInstance = instance; state.updateDashboard = instance; }, - [types.SET_DATABASES](state: State, data: Options[]) { + [types.SET_DATABASES](state: State, data: Option[]) { state.databases = data; if (!data.length) { state.currentDatabase = { key: '', label: '' }; @@ -100,7 +100,7 @@ const mutations: MutationTree<State> = { } state.currentDatabase = data[0]; }, - [types.SET_CURRENT_DATABASE](state: State, service: Options) { + [types.SET_CURRENT_DATABASE](state: State, service: Option) { state.currentDatabase = service; state.updateDashboard = service; }, @@ -111,7 +111,7 @@ const mutations: MutationTree<State> = { // actions const actions: ActionTree<State, any> = { - GET_SERVICES(context: { commit: Commit }, params: { duration: any; keyword: string }) { + GET_SERVICES(context: { commit: Commit }, params: { duration: DurationTime; keyword: string }) { if (!params.keyword) { params.keyword = ''; } @@ -123,7 +123,7 @@ const actions: ActionTree<State, any> = { }); }, GET_SERVICE_ENDPOINTS( - context: { commit: Commit; state: any }, + context: { commit: Commit; state: State }, params: { keyword: string; currentService?: { key: string; label: string } }, ) { if (!context.state.currentService.key) { @@ -143,7 +143,7 @@ const actions: ActionTree<State, any> = { context.commit(types.SET_ENDPOINTS, res.data.data.getEndpoints); }); }, - GET_SERVICE_INSTANCES(context: { commit: Commit; state: any }, params: any) { + GET_SERVICE_INSTANCES(context: { commit: Commit; state: State }, params: any) { if (!context.state.currentService.key) { context.commit(types.SET_INSTANCES, []); return; @@ -163,15 +163,55 @@ const actions: ActionTree<State, any> = { context.commit(types.SET_DATABASES, res.data.data.services); }); }, - SELECT_SERVICE(context: { commit: Commit; dispatch: Dispatch }, params: any) { + SELECT_SERVICE( + context: { commit: Commit; dispatch: Dispatch; state: State }, + params: { service: Option; duration: DurationTime; callback?: any }, + ) { context.commit('SET_CURRENT_SERVICE', params.service); - context.dispatch('GET_SERVICE_ENDPOINTS', {}); - context.dispatch('GET_SERVICE_INSTANCES', { duration: params.duration }); + context.dispatch('GET_SERVICE_ENDPOINTS', {}).then(() => { + if (context.state.pageType !== PageTypes.DASHBOARD || !params.callback) { + return; + } + params.callback({ + condition: { + time: params.duration, + size: 20, + source: { + service: params.service.label, + endpoint: context.state.currentEndpoint.label, + }, + }, + type: EntityType[2], + }); + }); + context.dispatch('GET_SERVICE_INSTANCES', { duration: params.duration }).then(() => { + if (context.state.pageType === PageTypes.DASHBOARD && !params.callback) { + context.commit('UPDATE_DASHBOARD', params.service); + } + if (context.state.pageType !== PageTypes.DASHBOARD || !params.callback) { + return; + } + params + .callback({ + condition: { + time: params.duration, + size: 20, + source: { + service: params.service.label, + serviceInstance: context.state.currentInstance.label, + }, + }, + type: EntityType[1], + }) + .then(() => { + context.commit('UPDATE_DASHBOARD', params.service); + }); + }); }, - SELECT_ENDPOINT(context: { commit: Commit; dispatch: Dispatch; state: any; rootState: any }, params: any) { + SELECT_ENDPOINT(context: { commit: Commit; dispatch: Dispatch; state: State; rootState: any }, params: any) { context.commit('SET_CURRENT_ENDPOINT', params.endpoint); }, - SELECT_INSTANCE(context: { commit: Commit; dispatch: Dispatch; state: any; rootState: any }, params: any) { + SELECT_INSTANCE(context: { commit: Commit; dispatch: Dispatch; state: State; rootState: any }, params: any) { context.commit('SET_CURRENT_INSTANCE', params.instance); }, SELECT_DATABASE(context: { commit: Commit; dispatch: Dispatch }, params: any) { @@ -229,7 +269,7 @@ const actions: ActionTree<State, any> = { return res.data.data.getServiceInstances; }); }, - GET_ITEM_SERVICES(context, params: { duration: any; keyword: string }) { + GET_ITEM_SERVICES(context, params: { duration: DurationTime; keyword: string }) { if (!params.keyword) { params.keyword = ''; } diff --git a/src/types/dashboard.d.ts b/src/types/dashboard.d.ts index ace8a2f..a96a432 100644 --- a/src/types/dashboard.d.ts +++ b/src/types/dashboard.d.ts @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Option } from './global'; +import { Duration } from './global'; export interface Value { value: number; } @@ -67,3 +67,36 @@ export interface DashboardTemplate { activated: boolean; disabled: boolean; } + +export interface QueryEventCondition { + uuid: string; + source: SourceInput; + name: string; + type: EventType; + time: Duration; + order: string; + size: number; +} + +type SourceInput = { + service: String; + serviceInstance: String; + endpoint: String; +}; +export enum EventType { + Normal, + Error, +} + +export type Event = { + uuid: string; + source: SourceInput; + name: string; + type: string; + message: string; + parameters: { key: string; value: string }[]; + startTime: number | string; + endTime: number | string; + entityType?: string; + checked?: boolean; +}; diff --git a/src/utils/dateFormatStep.ts b/src/utils/dateFormat.ts similarity index 66% rename from src/utils/dateFormatStep.ts rename to src/utils/dateFormat.ts index 90967d9..3ad6952 100644 --- a/src/utils/dateFormatStep.ts +++ b/src/utils/dateFormat.ts @@ -51,3 +51,40 @@ export default function dateFormatStep(date: Date, step: string, monthDayDiff?: } return ''; } + +export const dateFormatTime = (date: Date, step: string): string => { + const year = date.getFullYear(); + const monthTemp = date.getMonth() + 1; + let month: string = `${monthTemp}`; + if (monthTemp < 10) { + month = `0${monthTemp}`; + } + if (step === 'MONTH') { + return `${year}-${month}`; + } + const dayTemp = date.getDate(); + let day: string = `${dayTemp}`; + if (dayTemp < 10) { + day = `0${dayTemp}`; + } + if (step === 'DAY') { + return `${month}-${day}`; + } + const hourTemp = date.getHours(); + let hour: string = `${hourTemp}`; + if (hourTemp < 10) { + hour = `0${hourTemp}`; + } + if (step === 'HOUR') { + return `${month}-${day} ${hour}`; + } + const minuteTemp = date.getMinutes(); + let minute: string = `${minuteTemp}`; + if (minuteTemp < 10) { + minute = `0${minuteTemp}`; + } + if (step === 'MINUTE') { + return `${hour}:${minute}\n${month}-${day}`; + } + return ''; +}; diff --git a/src/views/components/dashboard/charts/chart-bar.vue b/src/views/components/dashboard/charts/chart-bar.vue index b438f81..16dbb49 100644 --- a/src/views/components/dashboard/charts/chart-bar.vue +++ b/src/views/components/dashboard/charts/chart-bar.vue @@ -18,17 +18,40 @@ limitations under the License. --> </template> <script lang="ts"> import { Vue, Component, Prop } from 'vue-property-decorator'; + import { Event } from '@/types/dashboard'; @Component export default class ChartBar extends Vue { @Prop() private data!: any; @Prop() private intervalTime!: any; + @Prop() private itemEvents!: Event[]; public resize() { const chart: any = this.$refs.chart; chart.myChart.resize(); } get option() { const keys = Object.keys(this.data || {}).filter((i: any) => Array.isArray(this.data[i]) && this.data[i].length); + const startP = keys.length > 1 ? 50 : 15; + const diff = 15; + const markAreas = (this.itemEvents || []).map((event: Event, index: number) => { + return [ + { + name: `${event.name}:${event.type}`, + xAxis: event.startTime, + y: startP + diff * index, + itemStyle: { + borderWidth: 2, + borderColor: event.type === 'Normal' ? '#5dc859' : '#FF0087', + color: event.type === 'Normal' ? '#5dc859' : '#FF0087', + }, + }, + { + name: event.message, + xAxis: event.endTime, + y: startP + diff * (index + 1), + }, + ]; + }); const temp = keys.map((i: string, index: number) => { return { data: this.data[i].map((item: any, itemIndex: number) => [this.intervalTime[itemIndex], item]), @@ -41,6 +64,23 @@ limitations under the License. --> width: 1.5, type: 'dotted', }, + markArea: + index === 0 + ? { + silent: false, + data: markAreas, + label: { + show: false, + width: 60, + }, + emphasis: { + label: { + position: 'bottom', + show: true, + }, + }, + } + : undefined, }; }); let color: string[] = []; @@ -79,6 +119,7 @@ limitations under the License. --> backgroundColor: 'rgb(50,50,50)', textStyle: { fontSize: 13, + color: '#ccc', }, enterable: true, extraCssText: 'max-height: 300px; overflow: auto;', diff --git a/src/views/components/dashboard/charts/chart-bar.vue b/src/views/components/dashboard/charts/chart-heap.vue similarity index 52% copy from src/views/components/dashboard/charts/chart-bar.vue copy to src/views/components/dashboard/charts/chart-heap.vue index b438f81..a38025f 100644 --- a/src/views/components/dashboard/charts/chart-bar.vue +++ b/src/views/components/dashboard/charts/chart-heap.vue @@ -14,85 +14,39 @@ See the License for the specific language governing permissions and limitations under the License. --> <template> - <RkEcharts ref="chart" :option="option" :autoResize="true" /> + <rk-panel :title="title"> + <RkEcharts height="215px" :option="responseConfig" /> + </rk-panel> </template> + <script lang="ts"> - import { Vue, Component, Prop } from 'vue-property-decorator'; + import Vue from 'vue'; + import { Component, Prop } from 'vue-property-decorator'; @Component - export default class ChartBar extends Vue { - @Prop() private data!: any; + export default class ChartHeap extends Vue { + @Prop() private title!: string; + @Prop() private stateDashboard!: any; @Prop() private intervalTime!: any; - public resize() { - const chart: any = this.$refs.chart; - chart.myChart.resize(); - } - get option() { - const keys = Object.keys(this.data || {}).filter((i: any) => Array.isArray(this.data[i]) && this.data[i].length); - const temp = keys.map((i: string, index: number) => { - return { - data: this.data[i].map((item: any, itemIndex: number) => [this.intervalTime[itemIndex], item]), - name: i, - type: 'bar', - symbol: 'none', - barMaxWidth: 10, - stack: '总量', - lineStyle: { - width: 1.5, - type: 'dotted', - }, - }; - }); - let color: string[] = []; - switch (keys.length) { - case 2: - color = ['#FF6A84', '#a0b1e6']; - break; - case 1: - color = ['#3f96e3']; - break; - default: - color = [ - '#30A4EB', - '#45BFC0', - '#FFCC55', - '#FF6A84', - '#a0a7e6', - '#c23531', - '#2f4554', - '#61a0a8', - '#d48265', - '#91c7ae', - '#749f83', - '#ca8622', - '#bda29a', - '#6e7074', - '#546570', - '#c4ccd3', - ]; - break; - } + get responseConfig() { return { - color, + color: ['#3f96e3', '#3fbde3'], tooltip: { trigger: 'axis', backgroundColor: 'rgb(50,50,50)', textStyle: { fontSize: 13, + color: '#ccc', }, - enterable: true, - extraCssText: 'max-height: 300px; overflow: auto;', }, legend: { - type: 'scroll', - show: keys.length === 1 ? false : true, icon: 'circle', top: 0, left: 0, itemWidth: 12, }, grid: { - top: keys.length === 1 ? 15 : 40, + top: 10, left: 0, right: 10, bottom: 5, @@ -115,7 +69,34 @@ limitations under the License. --> splitLine: { lineStyle: { color: '#c1c5ca41', type: 'dashed' } }, axisLabel: { color: '#9da5b2', fontSize: '11' }, }, - series: temp, + series: [ + { + data: this.stateDashboard.instanceInfo.heap.map((i: any, index: number) => [ + this.intervalTime[index], + (i.value / 1048576).toFixed(2), + ]), + name: this.stateDashboard.instanceInfo.heap.length ? 'Value' : null, + type: 'line', + symbol: 'none', + areaStyle: {}, + lineStyle: { + width: 1.5, + }, + }, + { + data: this.stateDashboard.instanceInfo.heap.map((i: any, index: number) => [ + this.intervalTime[index], + ((this.stateDashboard.instanceInfo.maxHeap[index].value - i.value) / 1048576).toFixed(2), + ]), + name: this.stateDashboard.instanceInfo.heap.length ? 'Free' : null, + type: 'line', + symbol: 'none', + areaStyle: {}, + lineStyle: { + width: 1.5, + }, + }, + ], }; } } diff --git a/src/views/components/dashboard/charts/chart-heatmap.vue b/src/views/components/dashboard/charts/chart-heatmap.vue index 5d95b9c..27d6c2f 100644 --- a/src/views/components/dashboard/charts/chart-heatmap.vue +++ b/src/views/components/dashboard/charts/chart-heatmap.vue @@ -64,6 +64,7 @@ limitations under the License. --> formatter: (a: any) => `${a.data[1] * 100}${this.item.unit} [ ${a.data[2]} ]`, textStyle: { fontSize: 13, + color: '#ccc', }, }, grid: { diff --git a/src/views/components/dashboard/charts/chart-line.vue b/src/views/components/dashboard/charts/chart-line.vue index feef6a4..1ba0622 100644 --- a/src/views/components/dashboard/charts/chart-line.vue +++ b/src/views/components/dashboard/charts/chart-line.vue @@ -18,18 +18,41 @@ limitations under the License. --> </template> <script lang="ts"> import { Vue, Component, Prop } from 'vue-property-decorator'; + import { Event } from '@/types/dashboard'; @Component export default class ChartLine extends Vue { @Prop() private data!: any; @Prop() private type!: string; @Prop() private intervalTime!: any; + @Prop() private itemEvents!: Event[]; public resize() { const chart: any = this.$refs.chart; chart.myChart.resize(); } get option() { const keys = Object.keys(this.data || {}).filter((i: any) => Array.isArray(this.data[i]) && this.data[i].length); + const startP = keys.length > 1 ? 50 : 15; + const diff = 10; + const markAreas = (this.itemEvents || []).map((event: Event, index: number) => { + return [ + { + name: `${event.name}:${event.type}`, + xAxis: event.startTime, + y: startP + diff * index, + itemStyle: { + borderWidth: 2, + borderColor: event.type === 'Normal' ? '#5dc859' : '#FF0087', + color: event.type === 'Normal' ? '#5dc859' : '#FF0087', + }, + }, + { + name: event.message, + xAxis: event.endTime, + y: startP + diff * (index + 1), + }, + ]; + }); const temp = keys.map((i: any, index: number) => { const serie: any = { data: this.data[i].map((item: any, itemIndex: number) => [this.intervalTime[itemIndex], item]), @@ -41,6 +64,23 @@ limitations under the License. --> width: 1.5, type: 'solid', }, + markArea: + index === 0 + ? { + silent: false, + data: markAreas, + label: { + show: false, + width: 60, + }, + emphasis: { + label: { + position: 'bottom', + show: true, + }, + }, + } + : undefined, }; if (this.type === 'areaChart') { serie.areaStyle = { @@ -85,6 +125,7 @@ limitations under the License. --> backgroundColor: 'rgb(50,50,50)', textStyle: { fontSize: 13, + color: '#ccc', }, enterable: true, extraCssText: 'max-height: 300px; overflow: auto;', diff --git a/src/views/components/dashboard/charts/chart-sankey.vue b/src/views/components/dashboard/charts/chart-sankey.vue new file mode 100644 index 0000000..13cd062 --- /dev/null +++ b/src/views/components/dashboard/charts/chart-sankey.vue @@ -0,0 +1,67 @@ +<!-- 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> + <RkEcharts ref="chart" :option="option" :autoResize="true" /> +</template> + +<script lang="ts"> + import Vue from 'vue'; + import { Component, Prop } from 'vue-property-decorator'; + + @Component + export default class ChartSankey extends Vue { + @Prop() private title!: string; + @Prop() private data!: any; + @Prop() private intervalTime!: any; + get option() { + return { + tooltip: { + trigger: 'item', + triggerOn: 'mousemove', + backgroundColor: 'rgb(50,50,50)', + textStyle: { + fontSize: 13, + color: '#ccc', + }, + formatter: (a: any) => a.data.tip, + }, + series: [ + { + type: 'sankey', + left: '30px', + top: '20px', + bottom: '20px', + label: { + formatter: (a: any) => a.data.content, + }, + animation: false, + color: ['#bf99f8', '#3fe1da', '#6be6c1', '#3fcfdc', '#626c91', '#3fbcde', '#a0a7e6', '#3fa9e1', '#96dee8'], + data: this.data.nodes, + links: this.data.calls, + itemStyle: { + borderWidth: 0, + }, + lineStyle: { + color: 'source', + opacity: 0.12, + }, + }, + ], + visualMap: this.data.visualMap, + }; + } + } +</script> diff --git a/src/views/components/dashboard/constant.ts b/src/views/components/dashboard/constant.ts index fcd3950..e104c49 100644 --- a/src/views/components/dashboard/constant.ts +++ b/src/views/components/dashboard/constant.ts @@ -29,3 +29,25 @@ export enum QueryTypes { READHEATMAP = 'readHeatMap', ReadSampledRecords = 'readSampledRecords', } +export const UpdateDashboardEvents = 'UpdateDashboardEvents'; +export const SeriesTypes = [ + { key: 'Service', label: 'Service Events' }, + { key: 'Endpoint', label: 'Service Endpoint Events' }, + { key: 'ServiceInstance', label: 'Service Instance Events' }, +]; +export const EventsHeaders = [ + { text: 'eventID', class: 'uuid' }, + { text: 'eventName', class: 'name' }, + { text: 'eventsType', class: 'type' }, + { text: 'startTime', class: 'startTime' }, + { text: 'endTime', class: 'endTime' }, +]; +export const EventsDetailHeaders = [ + { text: 'eventID', class: 'uuid' }, + { text: 'eventName', class: 'name' }, + { text: 'eventsType', class: 'type' }, + { text: 'startTime', class: 'startTime' }, + { text: 'endTime', class: 'endTime' }, + { text: 'eventsMessage', class: 'message' }, + { text: 'eventsParameters', class: 'parameters' }, +]; diff --git a/src/views/components/dashboard/dashboard-comp.vue b/src/views/components/dashboard/dashboard-comp.vue index d03d57d..6614a5f 100644 --- a/src/views/components/dashboard/dashboard-comp.vue +++ b/src/views/components/dashboard/dashboard-comp.vue @@ -17,7 +17,7 @@ limitations under the License. --> <nav class="rk-dashboard-comp-nav mb-15"> <a class="rk-dashboard-comp-nav-i b mr-20" - v-if="value.length" + v-show="value.length" @click=" current = key; configMode = false; diff --git a/src/views/components/dashboard/dashboard-item.vue b/src/views/components/dashboard/dashboard-item.vue index 8df84fc..dabf924 100644 --- a/src/views/components/dashboard/dashboard-item.vue +++ b/src/views/components/dashboard/dashboard-item.vue @@ -15,23 +15,21 @@ limitations under the License. --> <template> <div class="rk-dashboard-item" :class="`g-sm-${width}`" :style="`height:${height}px;`"> <div class="rk-dashboard-item-title ell"> - <svg class="icon cp red r" v-show="rocketGlobal.edit" @click="deleteItem(index)"> - <use xlink:href="#file-deletion"></use> - </svg> + <span v-show="rocketGlobal.edit" @click="deleteItem(index)"> + <rk-icon class="r edit red" icon="file-deletion" /> + </span> <span>{{ title }}</span> <span v-show="unit"> ( {{ unit }} ) </span> <span v-show="status === 'UNKNOWN'" class="item-status">( {{ $t('unknownMetrics') }} )</span> <span v-show="!rocketGlobal.edit && !pageTypes.includes(type)" @click="editComponentConfig"> - <svg class="icon cp r"> - <use xlink:href="#lock"></use> - </svg> + <rk-icon class="r edit" icon="keyboard_control" v-tooltip:bottom="{ content: $t('editConfig') }" /> </span> <span v-show="!rocketGlobal.edit && itemConfig.chartType === 'ChartTable'" @click="copyTable"> <rk-icon class="r cp" icon="review-list" /> </span> </div> - <div class="rk-dashboard-item-body"> - <div style="height:100%; width:100%"> + <div class="rk-dashboard-item-body" ref="chartBody"> + <div style="height:100%;width:100%"> <component :is="rocketGlobal.edit ? 'ChartEdit' : itemConfig.chartType" ref="chart" @@ -40,6 +38,7 @@ limitations under the License. --> :intervalTime="intervalTime" :data="chartSource" :type="type" + :itemEvents="itemEvents" @updateStatus="(type, value) => setStatus(type, value)" ></component> </div> @@ -70,11 +69,14 @@ limitations under the License. --> import charts from './charts'; import dayjs from 'dayjs'; - import { QueryTypes } from './constant'; + import { QueryTypes, UpdateDashboardEvents } from './constant'; import { TopologyType, ObjectsType } from '../../../constants/constant'; import { CalculationType } from './charts/constant'; import { State as globalState } from '@/store/modules/global'; import { State as optionState } from '@/store/modules/global/selectors'; + import { State as rocketData } from '@/store/modules/dashboard/dashboard-data'; + import { Event } from '@/types/dashboard'; + import { EntityType } from './charts/constant'; import copy from '@/utils/copy'; @Component({ @@ -82,6 +84,7 @@ limitations under the License. --> }) export default class DashboardItem extends Vue { @State('rocketbot') private rocketGlobal!: globalState; + @State('rocketData') private rocketData!: rocketData; @Mutation('EDIT_COMP_CONFIG') private EDIT_COMP_CONFIG: any; @Mutation('DELETE_COMP') private DELETE_COMP: any; @Mutation('rocketTopo/DELETE_TOPO_ENDPOINT') private DELETE_TOPO_ENDPOINT: any; @@ -95,7 +98,7 @@ limitations under the License. --> @Prop() private updateObjects!: string; @Prop() private rocketOption!: optionState; - private pageTypes = [TopologyType.TOPOLOGY_ENDPOINT, TopologyType.TOPOLOGY_INSTANCE] as any[]; + private pageTypes = [TopologyType.TOPOLOGY_ENDPOINT, TopologyType.TOPOLOGY_INSTANCE] as string[]; private dialogConfigVisible = false; private status = 'UNKNOWN'; private title = 'Title'; @@ -104,6 +107,7 @@ limitations under the License. --> private height = 300; private chartSource: any = {}; private itemConfig: any = {}; + private itemEvents: Event[] = []; private created() { this.status = this.item.metricType; @@ -112,6 +116,7 @@ limitations under the License. --> this.height = this.item.height; this.unit = this.item.unit; this.itemConfig = this.item; + this.itemEvents = this.eventsFilter(); const types = [ ObjectsType.UPDATE_INSTANCES, ObjectsType.UPDATE_ENDPOINTS, @@ -339,8 +344,49 @@ limitations under the License. --> } } + private eventsFilter() { + const allEvents = [ + ...this.rocketData.serviceEvents, + ...this.rocketData.serviceInstanceEvents, + ...this.rocketData.endpointEvents, + ]; + + let events = allEvents.filter( + (item) => + this.itemConfig.entityType === item.entityType && + item.checked && + ((item.source.service === this.rocketOption.currentService.label && + (item.source.serviceInstance === this.rocketOption.currentInstance.label || + item.source.endpoint === this.rocketOption.currentEndpoint.label)) || + (item.entityType === EntityType[0].key && item.source.service === this.rocketOption.currentService.label)), + ); + events = events.filter((d: Event, index: number) => index < this.setEventsLength()); + + return events; + } + + private setEventsLength() { + const body: any = this.$refs.chartBody; + if (!body) { + return 0; + } + const keys = Object.keys(this.chartSource || {}).filter( + (i: any) => Array.isArray(this.chartSource[i]) && this.chartSource[i].length, + ); + const startP = keys.length > 1 ? 50 : 15; + const endP = keys.length > 1 ? 0 : 40; + const eventNum = parseInt(String((body.offsetHeight - startP - endP) / 10), 10); + + return eventNum; + } + + // watch selectors and events @Watch('rocketOption.updateDashboard') private watchCurrentSelectors() { + this.itemEvents = this.eventsFilter(); + if (this.rocketOption.updateDashboard.key.includes(UpdateDashboardEvents)) { + return; + } setTimeout(() => { this.chartRender(); }, 1000); @@ -362,6 +408,9 @@ limitations under the License. --> flex-direction: column; padding-left: 5px; padding-right: 5px; + .edit { + cursor: pointer; + } } .dashboard-item-shadow { background-color: #448dfe15; diff --git a/src/views/components/dashboard/tool-bar/dashboard-events.vue b/src/views/components/dashboard/tool-bar/dashboard-events.vue new file mode 100644 index 0000000..2c271da --- /dev/null +++ b/src/views/components/dashboard/tool-bar/dashboard-events.vue @@ -0,0 +1,490 @@ +<!-- 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="event-list flex-h"> + <div class="rk-dashboard-tool-btn" @click="viewEventsList" v-show="enableEvents"> + <rk-icon class="lg" icon="settings" v-tooltip:left="{ content: $t('setEvent') }" /> + </div> + <div class="rk-dashboard-tool-btn" @click="setEnbleEvents"> + <rk-icon + class="lg" + :class="enableEvents ? 'blue' : ''" + icon="format_indent_increase" + v-tooltip:left="{ content: enableEvents ? $t('disableEvents') : $t('enableEvents') }" + /> + </div> + <rk-sidebox width="1000px" :fixed="true" :show.sync="dialogEventVisible" @closeSideboxCallback="updateEvents"> + <div class="config-box"> + <div class="series-type" v-show="type === pageEventsType.DASHBOARD_EVENTS"> + <label class="title">{{ $t('eventSeries') }}</label> + <RkSelect + :mode="'multiple'" + :current="rocketComps.currentSeriesType" + :data="seriesTypes" + @onChoose="(item) => changeSeriesType(item)" + /> + </div> + <div v-show="type === pageEventsType.DASHBOARD_EVENTS"> + <div class="title">{{ $t('serviceEvents') }}</div> + <ul> + <li class="header"> + <span class="check"> + <input type="checkbox" v-model="checkAllServiceEvents" @click="checkServiceEvents" /> + </span> + <span v-for="(item, index) of eventsHeaders" :class="item.class" :key="item.class + index">{{ + $t(item.text) + }}</span> + </li> + <li v-show="!rocketComps.serviceEvents.length">{{ $t('noData') }}</li> + <li v-for="event in rocketComps.serviceEvents" :key="event.uuid" @click="viewEventDetail(event)"> + <span class="check"> + <input type="checkbox" :checked="!!event.checked" @click="selectEvents(event)" /> + </span> + <span v-for="(item, index) of eventsHeaders" :class="item.class" :key="event.uuid + index">{{ + event[item.class] + }}</span> + </li> + </ul> + </div> + <div v-show="type !== pageEventsType.TOPO_ENDPOINT_EVENTS"> + <div class="title">{{ $t('instanceEvents') }}</div> + <ul> + <li class="header"> + <span class="check"> + <input type="checkbox" v-model="checkAllInstanceEvents" @click="checkInstanceEvents" /> + </span> + <span v-for="(item, index) of eventsHeaders" :class="item.class" :key="item.class + index">{{ + $t(item.text) + }}</span> + </li> + <li v-show="!rocketComps.serviceInstanceEvents.length">{{ $t('noData') }}</li> + <li v-for="event in rocketComps.serviceInstanceEvents" :key="event.uuid" @click="viewEventDetail(event)"> + <span class="check"> + <input type="checkbox" :checked="!!event.checked" @click="selectEvents(event)" /> + </span> + <span v-for="(item, index) of eventsHeaders" :class="item.class" :key="event.uuid + index">{{ + event[item.class] + }}</span> + </li> + </ul> + </div> + <div v-show="type !== pageEventsType.TOPO_INSTANCE_EVENTS"> + <div class="title">{{ $t('endpointEvents') }}</div> + <ul> + <li class="header"> + <span class="check"> + <input type="checkbox" v-model="checkAllEndpointEvents" @click="checkEndpointEvents" /> + </span> + <span v-for="(item, index) of eventsHeaders" :class="item.class" :key="item.class + index">{{ + $t(item.text) + }}</span> + </li> + <li v-show="!rocketComps.endpointEvents.length">{{ $t('noData') }}</li> + <li v-for="event in rocketComps.endpointEvents" :key="event.uuid" @click="viewEventDetail(event)"> + <span class="check"> + <input type="checkbox" :checked="!!event.checked" @click="selectEvents(event)" /> + </span> + <span v-for="(item, index) of eventsHeaders" :class="item.class" :key="event.uuid + index">{{ + event[item.class] + }}</span> + </li> + </ul> + </div> + <div class="save-btn bg-blue" @click="updateEvents">{{ $t('setEvent') }}</div> + </div> + </rk-sidebox> + <rk-sidebox :width="'1000px'" :show.sync="showEventDetail" :title="$t('eventDetail')"> + <div class="event-detail"> + <div class="mb-10 rk-flex" v-for="(item, index) in eventsDetailHeaders" :key="index"> + <span>{{ $t(item.text) }}: </span> + <span v-if="item.class === 'parameters'"> + <span v-for="(item, index) of currentEvent[item.class]" :key="index" + >{{ item.key }}={{ item.value }}; + </span> + </span> + <span v-else>{{ currentEvent[item.class] }}</span> + </div> + </div> + </rk-sidebox> + </div> +</template> +<script lang="ts"> + import { Mutation, Action } from 'vuex-class'; + import { Vue, Component, Prop, Watch } from 'vue-property-decorator'; + import { State as rocketData } from '@/store/modules/dashboard/dashboard-data'; + import { Event } from '@/types/dashboard'; + import { DurationTime, Option } from '@/types/global'; + import { UpdateDashboardEvents, SeriesTypes, EventsHeaders, EventsDetailHeaders } from '../constant'; + import { EntityType } from '../charts/constant'; + import { State as optionState } from '@/store/modules/global/selectors'; + import { PageEventsType } from '@/constants/constant'; + + @Component + export default class DashboardEvent extends Vue { + @Prop() private rocketComps!: rocketData; + @Prop() private stateDashboard!: optionState; + @Prop() private durationTime!: DurationTime; + @Prop() private type!: string; + @Mutation('SET_CHECKED_EVENTS') private SET_CHECKED_EVENTS: any; + @Mutation('UPDATE_DASHBOARD') private UPDATE_DASHBOARD: any; + @Mutation('SET_ENABLE_EVENTS') private SET_ENABLE_EVENTS: any; + @Mutation('SET_DASHBOARD_EVENTS') private SET_DASHBOARD_EVENTS: any; + @Mutation('SET_EVENTS_PAGE_TYPE') private SET_EVENTS_PAGE_TYPE!: (type: string) => void; + @Mutation('SET_CURRENT_SERIES_TYPE') private SET_CURRENT_SERIES_TYPE!: (data: { + item: Option; + index: number; + }) => void; + @Mutation('SET_CLEAR_SELECTED_EVENTS') private SET_CLEAR_SELECTED_EVENTS!: () => void; + @Mutation('SET_EVENTS') private SET_EVENTS: any; + @Action('GET_EVENT') private GET_EVENT: any; + + private dialogEventVisible: boolean = false; + private enableEvents: boolean = false; + private selectedEvents: Event[] = []; + private checkAllServiceEvents: boolean = false; + private checkAllInstanceEvents: boolean = false; + private checkAllEndpointEvents: boolean = false; + private showEventDetail: boolean = false; + private currentEvent: Event | {} = {}; + private pageEventsType = PageEventsType; + private seriesTypes = SeriesTypes; + private eventsHeaders = EventsHeaders; + private eventsDetailHeaders = EventsDetailHeaders; + + private created() { + this.initEvents(); + this.SET_EVENTS([ + () => { + if (!this.enableEvents) { + return; + } + this.fetchEvents(); + }, + ]); + } + + private initEvents() { + this.SET_EVENTS_PAGE_TYPE(this.type); + if (this.type === this.pageEventsType.DASHBOARD_EVENTS) { + this.SET_CURRENT_SERIES_TYPE({ item: this.seriesTypes[0], index: -1 }); + this.SET_CURRENT_SERIES_TYPE({ item: this.seriesTypes[2], index: -1 }); + } else if (this.type === this.pageEventsType.TOPO_ENDPOINT_EVENTS) { + this.SET_CURRENT_SERIES_TYPE({ item: this.seriesTypes[1], index: -1 }); + } else { + this.SET_CURRENT_SERIES_TYPE({ item: this.seriesTypes[2], index: -1 }); + } + this.updateAllChecked(); + } + + private viewEventsList() { + this.dialogEventVisible = true; + this.updateAllChecked(); + } + + private updateAllChecked() { + this.checkAllServiceEvents = this.checkAllEvents(this.rocketComps.serviceEvents); + this.checkAllEndpointEvents = this.checkAllEvents(this.rocketComps.endpointEvents); + this.checkAllInstanceEvents = this.checkAllEvents(this.rocketComps.serviceInstanceEvents); + } + + private checkAllEvents(events: Event[]) { + if (!events.length) { + return false; + } + const selectedServiceEvents = events.filter((item: Event) => item.checked); + if (selectedServiceEvents.length === events.length) { + return true; + } else { + return false; + } + } + + private viewEventDetail(event: Event) { + this.showEventDetail = true; + this.currentEvent = event; + } + + private changeSeriesType(item: Option) { + const index = this.rocketComps.currentSeriesType.findIndex((d: Option) => item.key === d.key); + + this.SET_CURRENT_SERIES_TYPE({ item, index }); + this.SET_CLEAR_SELECTED_EVENTS(); + const selectedEvents: Event[] = []; + for (const type of this.rocketComps.currentSeriesType) { + if (type.key === this.seriesTypes[0].key) { + selectedEvents.push(...this.rocketComps.serviceEvents.slice(0, 3)); + } else if (type.key === this.seriesTypes[1].key) { + selectedEvents.push(...this.rocketComps.endpointEvents.slice(0, 3)); + } else { + selectedEvents.push(...this.rocketComps.serviceInstanceEvents.slice(0, 3)); + } + } + this.selectedEvents = selectedEvents.map((d: Event) => { + d.checked = true; + return d; + }); + this.SET_CHECKED_EVENTS(this.selectedEvents); + this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() }); + this.selectedEvents = []; + this.updateAllChecked(); + } + + private setEnbleEvents() { + this.enableEvents = !this.enableEvents; + this.SET_ENABLE_EVENTS(this.enableEvents); + if (!this.enableEvents) { + this.clearAllEvents(); + this.checkAllServiceEvents = false; + this.checkAllInstanceEvents = false; + this.checkAllEndpointEvents = false; + this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() }); + return; + } + this.fetchEvents(); + } + + private clearAllEvents() { + this.SET_DASHBOARD_EVENTS({ events: [], type: EntityType[0].key }); + this.SET_DASHBOARD_EVENTS({ events: [], type: EntityType[2].key }); + this.SET_DASHBOARD_EVENTS({ events: [], type: EntityType[3].key }); + } + + private fetchEvents() { + if (this.type === PageEventsType.DASHBOARD_EVENTS) { + Promise.all([this.fetchServiceEvents(), this.fetchInstanceEvents(), this.fetchEndpointEvents()]).then(() => { + this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() }); + }); + return; + } + if (this.type === PageEventsType.TOPO_INSTANCE_EVENTS) { + this.fetchInstanceEvents().then(() => { + this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() }); + }); + return; + } + if (this.type === PageEventsType.TOPO_ENDPOINT_EVENTS) { + this.fetchEndpointEvents().then(() => { + this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() }); + }); + } + } + + private fetchServiceEvents() { + return this.GET_EVENT({ + condition: { + time: this.durationTime, + size: 20, + source: { + service: this.stateDashboard.currentService.label, + }, + }, + type: EntityType[0].key, + }); + } + + private fetchInstanceEvents() { + return this.GET_EVENT({ + condition: { + time: this.durationTime, + size: 20, + source: { + service: this.stateDashboard.currentService.label, + serviceInstance: this.stateDashboard.currentInstance.label, + }, + }, + type: EntityType[3].key, + }); + } + + private fetchEndpointEvents() { + return this.GET_EVENT({ + condition: { + time: this.durationTime, + size: 20, + source: { + service: this.stateDashboard.currentService.label, + endpoint: this.stateDashboard.currentEndpoint.label, + }, + }, + type: EntityType[2].key, + }).then(() => { + if (this.type === PageEventsType.DASHBOARD_EVENTS) { + return; + } + this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() }); + }); + } + + private selectEvents(data: Event, e: any) { + window.event ? (window.event.cancelBubble = true) : e.stopPropagation(); + const index = this.selectedEvents.findIndex( + (item: Event) => item.uuid === data.uuid && item.entityType === data.entityType, + ); + + data.checked = !data.checked; + if (index > -1) { + this.selectedEvents[index].checked = data.checked; + } else { + this.selectedEvents.push(data); + } + } + + private updateEvents() { + this.SET_CHECKED_EVENTS(this.selectedEvents); + this.UPDATE_DASHBOARD({ key: UpdateDashboardEvents + new Date().getTime() }); + this.selectedEvents = []; + this.dialogEventVisible = false; + } + + private checkServiceEvents() { + for (const event of this.rocketComps.serviceEvents) { + if (this.checkAllServiceEvents) { + event.checked = false; + } else { + event.checked = true; + } + this.selectedEvents = this.selectedEvents.filter( + (item: Event) => !(item.entityType === EntityType[0].label && item.uuid === event.uuid), + ); + } + if (!this.checkAllServiceEvents) { + this.selectedEvents.push(...this.rocketComps.serviceEvents); + } + } + + private checkInstanceEvents() { + for (const event of this.rocketComps.serviceInstanceEvents) { + if (this.checkAllInstanceEvents) { + event.checked = false; + } else { + event.checked = true; + } + this.selectedEvents = this.selectedEvents.filter( + (item: Event) => !(item.entityType === EntityType[3].label && item.uuid === event.uuid), + ); + } + if (!this.checkAllInstanceEvents) { + this.selectedEvents.push(...this.rocketComps.serviceInstanceEvents); + } + } + + private checkEndpointEvents() { + for (const event of this.rocketComps.endpointEvents) { + if (this.checkAllEndpointEvents) { + event.checked = false; + } else { + event.checked = true; + } + this.selectedEvents = this.selectedEvents.filter( + (item: Event) => !(item.entityType === EntityType[2].label && item.uuid === event.uuid), + ); + } + if (!this.checkAllEndpointEvents) { + this.selectedEvents.push(...this.rocketComps.endpointEvents); + } + } + + private beforeDestroy() { + this.clearAllEvents(); + this.SET_ENABLE_EVENTS(false); + this.SET_EVENTS([]); + } + + @Watch('durationTime') + private watchDurationTime() { + if (!this.enableEvents) { + return; + } + this.fetchEvents(); + } + } +</script> +<style lang="scss" scoped> + .event-list { + color: #444; + } + .rk-dashboard-tool-btn { + background-color: rgba(255, 255, 255, 0.07); + border-radius: 4px; + margin-left: 5px; + padding: 3px; + color: #efefef; + cursor: pointer; + } + .rk-sidebox-title { + color: #444; + } + .config-box { + color: #444; + .series-type { + margin-bottom: 20px; + width: 400px; + } + .title { + font-size: 14px; + font-weight: bold; + } + .save-btn { + width: 120px; + height: 30px; + line-height: 30px; + text-align: center; + border-radius: 4px; + color: #fff; + cursor: pointer; + } + ul { + max-height: 200px; + min-height: 100px; + overflow: auto; + margin-bottom: 20px; + .header { + font-weight: bold; + } + .check { + width: 30px; + input { + cursor: pointer; + } + } + .starTime, + .endTime { + width: 150px; + } + .uuid, + .parameters { + width: 280px; + } + .message { + width: 220px; + } + } + li { + cursor: pointer; + span { + width: 150px; + height: 20px; + line-height: 20px; + text-align: center; + display: inline-block; + border-bottom: 1px solid #ccc; + overflow: hidden; + } + } + } + .event-detail { + color: #444; + } +</style> diff --git a/src/views/components/dashboard/tool-bar/tool-bar-btns.vue b/src/views/components/dashboard/tool-bar/tool-bar-btns.vue index 28e9b40..8d1f5ad 100644 --- a/src/views/components/dashboard/tool-bar/tool-bar-btns.vue +++ b/src/views/components/dashboard/tool-bar/tool-bar-btns.vue @@ -15,39 +15,25 @@ limitations under the License. --> <template> <div class="flex-h btn-box"> - <div class="rk-dashboard-bar-btn"> - <span v-tooltip:bottom="{ content: rocketGlobal.edit ? 'view' : 'edit' }"> - <svg - class="icon lg vm cp rk-btn ghost" - :style="`color:${!rocketGlobal.edit ? '' : '#ffc107'}`" - @click="handleSetEdit" - > - <use :xlink:href="!rocketGlobal.edit ? '#lock' : '#lock-open'"></use> - </svg> - </span> + <div class="rk-dashboard-bar-btn" @click="handleSetEdit"> + <rk-icon + class="lg" + :style="`color:${!rocketGlobal.edit ? '' : '#ffc107'}`" + :icon="!rocketGlobal.edit ? 'lock' : 'lock-open'" + v-tooltip:bottom="{ content: rocketGlobal.edit ? 'view' : 'edit' }" + /> </div> - <div class="rk-dashboard-bar-btn"> - <span v-tooltip:bottom="{ content: 'import' }"> - <input id="tool-bar-file" type="file" name="file" title="" accept=".json" @change="importData" /> - <label class="rk-btn ghost input-label" for="tool-bar-file"> - <svg class="icon lg vm cp " :style="`marginTop: 0px`"> - <use :xlink:href="'#folder_open'"></use> - </svg> - </label> - </span> + <div class="rk-dashboard-bar-btn" v-tooltip:bottom="{ content: 'import' }"> + <input id="tool-bar-file" type="file" name="file" title="" accept=".json" @change="importData" /> + <label for="tool-bar-file"> + <rk-icon class="lg import" icon="folder_open" /> + </label> </div> - <div class="rk-dashboard-bar-btn"> - <span v-tooltip:bottom="{ content: 'export' }"> - <svg class="icon lg vm cp rk-btn ghost" @click="exportData"> - <use :xlink:href="'#save_alt'"></use> - </svg> - </span> + <div class="rk-dashboard-bar-btn" @click="exportData"> + <rk-icon class="lg" icon="save_alt" v-tooltip:bottom="{ content: 'export' }" /> </div> - - <div class="rk-dashboard-bar-btn"> - <svg class="icon lg vm cp rk-btn ghost" @click="handleOption"> - <use xlink:href="#retry"></use> - </svg> + <div class="rk-dashboard-bar-btn" @click="handleOption"> + <rk-icon class="lg" icon="retry" v-tooltip:bottom="{ content: 'auto' }" /> </div> </div> </template> @@ -57,15 +43,17 @@ limitations under the License. --> import { Action, Mutation } from 'vuex-class'; import { readFile } from '@/utils/readFile'; import { saveFile } from '@/utils/saveFile'; - @Component({}) + import { DurationTime } from '@/types/global'; + import { State as rocketData } from '@/store/modules/dashboard/dashboard-data'; + import { State as rocketGlobal } from '@/store/modules/global'; + import { PageTypes } from '@/constants/constant'; + + @Component export default class ToolBarBtns extends Vue { - @Prop() private compType!: any; - @Prop() private dashboardType!: any; - @Prop() private rocketGlobal!: any; - @Prop() private rocketComps!: any; - @Prop() private durationTime!: any; - @Prop() private rocketOption: any; - @Mutation('SET_COMPS_TREE') private SET_COMPS_TREE: any; + @Prop() private compType!: string; + @Prop() private rocketGlobal!: rocketGlobal; + @Prop() private rocketComps!: rocketData; + @Prop() private durationTime!: DurationTime; @Mutation('IMPORT_TREE') private IMPORT_TREE: any; @Action('SET_EDIT') private SET_EDIT: any; @Action('MIXHANDLE_GET_OPTION') private MIXHANDLE_GET_OPTION: any; @@ -74,13 +62,16 @@ limitations under the License. --> return this.MIXHANDLE_GET_OPTION({ compType: this.compType, duration: this.durationTime, + pageType: PageTypes.DASHBOARD, keywordServiceName: this.rocketComps.tree[this.rocketComps.group] && this.rocketComps.tree[this.rocketComps.group].serviceGroup, }); } + private handleSetEdit() { this.SET_EDIT(!this.rocketGlobal.edit); } + private async importData(event: any) { try { const data: any = await readFile(event); @@ -110,9 +101,10 @@ limitations under the License. --> <style lang="scss" scoped> .rk-dashboard-bar-btn { - padding: 0 5px; + padding: 0 8px; border-right: 2px solid #252a2f; height: 19px; + cursor: pointer; } #tool-bar-file { display: none; @@ -120,8 +112,13 @@ limitations under the License. --> .input-label { display: inline; line-height: inherit; + cursor: pointer; } .btn-box { height: 58px; } + .import { + margin-top: 0; + cursor: pointer; + } </style> diff --git a/src/views/components/dashboard/tool-bar/tool-bar.vue b/src/views/components/dashboard/tool-bar/tool-bar.vue index 3d67af7..6708612 100644 --- a/src/views/components/dashboard/tool-bar/tool-bar.vue +++ b/src/views/components/dashboard/tool-bar/tool-bar.vue @@ -18,59 +18,69 @@ limitations under the License. --> :rocketGlobal="rocketGlobal" :rocketComps="rocketComps" :compType="compType" - :dashboardType="dashboardType" :durationTime="durationTime" - :rocketOption="rocketOption" /> - <div class="flex-h" v-if="compType === dashboardType.SERVICE"> - <div class="sm grey service-search"> - <div>{{ $t('serviceGroup') }}</div> - <input - type="text" - :value="rocketComps.tree[rocketComps.group].serviceGroup" - @change="searchServices($event.target.value)" + <div class="dashboard-selectors flex-h" v-if="compType === dashboardType.SERVICE"> + <div class="flex-h"> + <div class="sm grey service-search"> + <div>{{ $t('serviceGroup') }}</div> + <input + type="text" + :value="rocketComps.tree[rocketComps.group].serviceGroup" + @change="searchServices($event.target.value)" + /> + </div> + <ToolBarSelect + @onChoose="selectService" + :title="$t('currentService')" + :current="stateDashboard.currentService" + :data="stateDashboard.services" + icon="package" + /> + <ToolBarEndpointSelect + @onChoose="selectEndpoint" + :title="$t('currentEndpoint')" + :current="stateDashboard.currentEndpoint" + :data="stateDashboard.endpoints" + :currentService="stateDashboard.currentService" + icon="code" + /> + <ToolBarSelect + @onChoose="selectInstance" + :title="$t('currentInstance')" + :current="stateDashboard.currentInstance" + :data="stateDashboard.instances" + icon="disk" /> + <a + class="rk-view-instance-attributes r" + @click="() => (dialogAttributesVisible = true)" + v-tooltip:bottom="{ content: $t('instanceAttributes') }" + > + <rk-icon icon="info_outline" /> + </a> + <rk-sidebox + width="600px" + :fixed="true" + :title="`${$t('instanceAttributes')} of ${stateDashboard.currentInstance.label}`" + :show.sync="dialogAttributesVisible" + class="instance-attributes-box" + > + <div + class="instance-attr" + v-for="(attr, index) in stateDashboard.currentInstance.attributes" + :key="attr.name + index" + > + {{ attr.name + ' : ' + attr.value }} + </div> + </rk-sidebox> </div> - <ToolBarSelect - @onChoose="selectService" - :title="$t('currentService')" - :current="stateDashboard.currentService" - :data="stateDashboard.services" - icon="package" - /> - <ToolBarEndpointSelect - @onChoose="selectEndpoint" - :title="$t('currentEndpoint')" - :current="stateDashboard.currentEndpoint" - :data="stateDashboard.endpoints" - :currentService="stateDashboard.currentService" - icon="code" + <DashboardEvent + :rocketComps="rocketComps" + :stateDashboard="stateDashboard" + :durationTime="durationTime" + :type="pageEventsType.DASHBOARD_EVENTS" /> - <ToolBarSelect - @onChoose="selectInstance" - :title="$t('currentInstance')" - :current="stateDashboard.currentInstance" - :data="stateDashboard.instances" - icon="disk" - /> - <a class="rk-view-instance-attributes r" @click="() => (dialogAttributesVisible = true)"> - <span class="vm">{{ $t('instanceAttributes') }}</span> - </a> - <rk-sidebox - width="50%" - :fixed="true" - :title="`${$t('instanceAttributes')} of ${stateDashboard.currentInstance.label}`" - :show.sync="dialogAttributesVisible" - class="instance-attributes-box" - > - <div - class="instance-attr" - v-for="(attr, index) in stateDashboard.currentInstance.attributes" - :key="attr.name + index" - > - {{ attr.name + ' : ' + attr.value }} - </div> - </rk-sidebox> </div> <div class="flex-h" v-else-if="compType === dashboardType.BROWSER"> <ToolBarSelect @@ -113,18 +123,23 @@ limitations under the License. --> import ToolBarSelect from './tool-bar-select.vue'; import ToolBarEndpointSelect from './tool-bar-endpoint-select.vue'; import ToolBarBtns from './tool-bar-btns.vue'; - import { State, Action, Mutation } from 'vuex-class'; + import { Action, Mutation } from 'vuex-class'; + import { EntityType } from '../charts/constant'; + import { DurationTime, Option } from '@/types/global'; + import { State as rocketData } from '@/store/modules/dashboard/dashboard-data'; + import { State as rocketGlobal } from '@/store/modules/global'; + import { State as optionState } from '@/store/modules/global/selectors'; + import DashboardEvent from './dashboard-events.vue'; import { DASHBOARDTYPE } from '../constant'; + import { PageEventsType, PageTypes } from '@/constants/constant'; - @Component({ components: { ToolBarSelect, ToolBarBtns, ToolBarEndpointSelect } }) + @Component({ components: { ToolBarSelect, ToolBarBtns, ToolBarEndpointSelect, DashboardEvent } }) export default class ToolBar extends Vue { - @Prop() private compType!: any; - @Prop() private stateDashboard!: any; - @Prop() private rocketGlobal!: any; - @Prop() private rocketComps!: any; - @Prop() private durationTime!: any; - @State('rocketOption') private rocketOption: any; - @Mutation('ADD_COMP') private ADD_COMP: any; + @Prop() private compType!: string; + @Prop() private stateDashboard!: optionState; + @Prop() private rocketGlobal!: rocketGlobal; + @Prop() private rocketComps!: rocketData; + @Prop() private durationTime!: DurationTime; @Mutation('SET_CURRENT_SERVICE_GROUP') private SET_CURRENT_SERVICE_GROUP: any; @Mutation('UPDATE_DASHBOARD') private UPDATE_DASHBOARD: any; @Action('SELECT_SERVICE') private SELECT_SERVICE: any; @@ -132,8 +147,10 @@ limitations under the License. --> @Action('SELECT_ENDPOINT') private SELECT_ENDPOINT: any; @Action('SELECT_INSTANCE') private SELECT_INSTANCE: any; @Action('MIXHANDLE_GET_OPTION') private MIXHANDLE_GET_OPTION: any; + @Action('GET_EVENT') private GET_EVENT: any; + private dialogAttributesVisible: boolean = false; private dashboardType = DASHBOARDTYPE; - private dialogAttributesVisible = false; + private pageEventsType = PageEventsType; get lastKey() { const current = this.rocketComps.tree[this.rocketComps.group].children[this.rocketComps.current].children; if (!current.length) { @@ -141,14 +158,60 @@ limitations under the License. --> } return current[current.length - 1].k; } - private selectService(i: any) { - this.SELECT_SERVICE({ service: i, duration: this.durationTime }); + private selectService(i: Option) { + if (!this.rocketComps.enableEvents) { + this.SELECT_SERVICE({ service: i, duration: this.durationTime }); + return; + } + this.SELECT_SERVICE({ service: i, duration: this.durationTime, callback: this.GET_EVENT }); + this.GET_EVENT({ + condition: { + time: this.durationTime, + size: 20, + source: { + service: i.label, + }, + }, + type: EntityType[0].key, + }); } - private selectEndpoint(i: any) { - this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime }); + private selectEndpoint(i: Option) { + if (!this.rocketComps.enableEvents) { + this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime }); + return; + } + this.GET_EVENT({ + condition: { + time: this.durationTime, + size: 20, + source: { + service: this.stateDashboard.currentService.label, + endpoint: i.label, + }, + }, + type: EntityType[2].key, + }).then(() => { + this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime }); + }); } - private selectInstance(i: any) { - this.SELECT_INSTANCE({ instance: i, duration: this.durationTime }); + private selectInstance(i: Option) { + if (!this.rocketComps.enableEvents) { + this.SELECT_INSTANCE({ instance: i, duration: this.durationTime }); + return; + } + this.GET_EVENT({ + condition: { + time: this.durationTime, + size: 20, + source: { + service: this.stateDashboard.currentService.label, + serviceInstance: i.label, + }, + }, + type: EntityType[3].key, + }).then(() => { + this.SELECT_INSTANCE({ instance: i, duration: this.durationTime }); + }); } private searchServices(value: string) { this.SET_CURRENT_SERVICE_GROUP(value); @@ -156,6 +219,7 @@ limitations under the License. --> compType: this.dashboardType.SERVICE, duration: this.durationTime, keywordServiceName: value, + pageType: PageTypes.DASHBOARD, }).then(() => { this.UPDATE_DASHBOARD(); }); @@ -168,6 +232,10 @@ limitations under the License. --> flex-shrink: 0; color: #efefef; background-color: #333840; + .dashboard-selectors { + width: calc(100% - 150px); + justify-content: space-between; + } .instance-attributes-box { color: #252a2f; } @@ -190,10 +258,11 @@ limitations under the License. --> } } .rk-view-instance-attributes { - background-color: #484b55; + background-color: rgba(255, 255, 255, 0.07); border-radius: 4px; margin-left: 5px; - padding: 5px 10px; + padding: 3px; + color: #efefef; } } </style> diff --git a/src/views/components/dashboard/tool-group.vue b/src/views/components/dashboard/tool-group.vue index 7e6c105..67588a3 100644 --- a/src/views/components/dashboard/tool-group.vue +++ b/src/views/components/dashboard/tool-group.vue @@ -63,8 +63,7 @@ limitations under the License. --> import { Component, Prop } from 'vue-property-decorator'; import { Mutation, Action, Getter } from 'vuex-class'; import { DASHBOARDTYPE } from './constant'; - import { readFile } from '@/utils/readFile'; - import { saveFile } from '@/utils/saveFile'; + import { PageTypes } from '@/constants/constant'; @Component({}) export default class ToolGroup extends Vue { @@ -118,6 +117,7 @@ limitations under the License. --> compType: this.compType, duration: this.durationTime, keywordServiceName: serviceGroup, + pageType: PageTypes.DASHBOARD, }); } private handleHide() { diff --git a/src/views/components/dashboard/tool-nav.vue b/src/views/components/dashboard/tool-nav.vue index 99b008c..58f903e 100644 --- a/src/views/components/dashboard/tool-nav.vue +++ b/src/views/components/dashboard/tool-nav.vue @@ -19,15 +19,9 @@ limitations under the License. --> :key="index" class="mr-20" > - <a - class="rk-dashboard-nav-i b" - @click=" - SET_CURRENT_COMPS(index); - RUN_EVENTS({}); - " - :class="{ active: rocketComps.current == index }" - >{{ i.name }}</a - > + <a class="rk-dashboard-nav-i b" @click="changeComps(index)" :class="{ active: rocketComps.current == index }">{{ + i.name + }}</a> <svg v-if="rocketGlobal.edit && rocketComps.current !== index" class="ml-5 icon cp red vm" @@ -44,50 +38,28 @@ limitations under the License. --> <div class="mb-10 vm">{{ $t('createTab') }}</div> <div class="sm grey mb-5 mr-10">{{ $t('tabName') }}</div> <input class="mb-5 rk-dashboard-nav-input" type="text" v-model="name" /> - <!-- <div class="sm grey mb-5 mr-10">{{ $t('template') }}</div> - <label class="dib mb-5 mr-10 sm" - ><input type="radio" v-model="template" value="nouse" />{{ $t('nouse') }}</label - > - <label class="dib mb-5 mr-10 sm" - ><input type="radio" v-model="template" value="global" />{{ $t('global') }}</label - > - <label class="dib mb-5 mr-10 sm" v-if="type === 'service'" - ><input type="radio" v-model="template" value="service" />{{ $t('service') }}</label - > - <label class="dib mb-5 mr-10 sm" v-if="type === 'service'" - ><input type="radio" v-model="template" value="endpoint" />{{ $t('endpoint') }}</label - > - <label class="dib mb-5 mr-10 sm" v-if="type === 'service'" - ><input type="radio" v-model="template" value="instance" />{{ $t('instance') }}</label - > - <label class="dib mb-5 mr-10 sm" v-if="type === 'database'" - ><input type="radio" v-model="template" value="database" />{{ $t('database') }}</label - > --> <a class="rk-btn r vm long tc confirm" @click="handleCreate">{{ $t('confirm') }}</a> </div> </a> <a class="rk-dashboard-import mr-10"> <input id="tool-nav-file" class="ipt" type="file" name="file" title="" accept=".json" @change="importData" /> <label for="tool-nav-file" class="input-label"> - <svg class="icon open vm"> - <use xlink:href="#folder_open"></use> - </svg> + <rk-icon class="open vm" icon="folder_open" /> </label> </a> - <a> - <svg class="icon vm" @click="exportData"> - <use xlink:href="#save_alt"></use> - </svg> + <a class="mr-10" @click="exportData"> + <rk-icon icon="save_alt" /> </a> </nav> </template> <script lang="ts"> import Vue from 'vue'; - import { Component, Prop, Model } from 'vue-property-decorator'; - import { State, Mutation, Action } from 'vuex-class'; + import { Component, Prop } from 'vue-property-decorator'; + import { Getter, Mutation, Action } from 'vuex-class'; import { readFile } from '@/utils/readFile'; import { saveFile } from '@/utils/saveFile'; + import { DASHBOARDTYPE } from './constant'; @Component export default class ToolNav extends Vue { @@ -98,9 +70,11 @@ limitations under the License. --> @Mutation('DELETE_COMPS_TREE') private DELETE_COMPS_TREE: any; @Mutation('ADD_COMPS_TREE') private ADD_COMPS_TREE: any; @Action('RUN_EVENTS') private RUN_EVENTS: any; + @Getter('durationTime') private durationTime: any; private name: string = ''; - // private template: string = 'nouse'; private show: boolean = false; + private dashboardType = DASHBOARDTYPE; + get type() { return this.rocketComps.tree[this.rocketComps.group].type; } @@ -114,7 +88,10 @@ limitations under the License. --> } this.ADD_COMPS_TREE({ name: this.name }); this.handleHide(); - // this.template = 'nouse'; + } + private changeComps(index: number) { + this.SET_CURRENT_COMPS(index); + this.RUN_EVENTS({}); } private async importData(event: any) { try { diff --git a/src/views/components/log/log-bar.vue b/src/views/components/log/log-bar.vue index 1e54f64..7de635a 100644 --- a/src/views/components/log/log-bar.vue +++ b/src/views/components/log/log-bar.vue @@ -76,7 +76,6 @@ limitations under the License. --> </template> <script lang="ts"> - import { Duration, Option } from '@/types/global'; import { Component, Vue } from 'vue-property-decorator'; import { Action, Getter, Mutation, State } from 'vuex-class'; import TraceSelect from '../common/trace-select.vue'; @@ -85,6 +84,7 @@ limitations under the License. --> import LogConditions from './log-conditions.vue'; import { State as logState } from '@/store/modules/log/index'; import { State as optionState } from '@/store/modules/global/selectors'; + import { PageTypes } from '@/constants/constant'; @Component({ components: { TraceSelect, ToolBarSelect, ToolBarEndpointSelect, LogConditions }, @@ -107,14 +107,13 @@ limitations under the License. --> private pageNum: number = 1; private cateGoryBrowser = 'browser'; private showConditionsBox = true; - private logPage = 'Log'; private pageSize = 20; private beforeMount() { this.MIXHANDLE_GET_OPTION({ compType: this.logState.type.key, duration: this.durationTime, - pageType: this.logPage, + pageType: PageTypes.LOG, }) .then(() => { this.QUERY_LOGS_BYKEYWORDS(); @@ -146,7 +145,7 @@ limitations under the License. --> this.MIXHANDLE_GET_OPTION({ compType: i.key, duration: this.durationTime, - pageType: this.logPage, + pageType: PageTypes.LOG, }).then(() => { this.queryLogs(); }); diff --git a/src/views/components/log/log-conditions.vue b/src/views/components/log/log-conditions.vue index 5035275..529743e 100644 --- a/src/views/components/log/log-conditions.vue +++ b/src/views/components/log/log-conditions.vue @@ -116,7 +116,7 @@ limitations under the License. --> import { Mutation, State } from 'vuex-class'; import { State as globalState } from '@/store/modules/global/index'; import { State as logState } from '@/store/modules/log/index'; - import dateFormatStep from '@/utils/dateFormatStep'; + import dateFormatStep from '@/utils/dateFormat'; @Component({ components: {}, diff --git a/src/views/components/log/log-service-detail.vue b/src/views/components/log/log-service-detail.vue index 08c1515..0a521a6 100644 --- a/src/views/components/log/log-service-detail.vue +++ b/src/views/components/log/log-service-detail.vue @@ -42,7 +42,6 @@ limitations under the License. --> <script lang="ts"> import { Component, Prop, Vue, Watch } from 'vue-property-decorator'; - import { Mutation, State } from 'vuex-class'; import LogTable from './log-table/log-table.vue'; import { ServiceLogDetail } from './log-table/log-constant'; import { formatJson } from '../../../utils/formatJson'; diff --git a/src/views/components/profile/profile-task.vue b/src/views/components/profile/profile-task.vue index 343c3a7..8015b21 100644 --- a/src/views/components/profile/profile-task.vue +++ b/src/views/components/profile/profile-task.vue @@ -125,10 +125,7 @@ limitations under the License. --> } </script> -<style lang="scss"> - .rk-profile-task { - margin: 20px; - } +<style lang="scss" scoped> label { display: inline-block; margin: 10px 0; diff --git a/src/views/components/topology/topo-aside.vue b/src/views/components/topology/topo-aside.vue index 22f2964..83c883e 100644 --- a/src/views/components/topology/topo-aside.vue +++ b/src/views/components/topology/topo-aside.vue @@ -16,7 +16,11 @@ limitations under the License. --> <template> <aside class="link-topo-aside"> <Radial v-if="radioStatus" :datas="{ nodes: stateTopo.nodes, calls: stateTopo.calls }" /> - <svg class="link-topo-aside-btn icon cp lg" @click="showRadial()" :style="`position:absolute;left:580px;${radioStatus ? 'background-color: #357de9;' : ''}`"> + <svg + class="link-topo-aside-btn icon cp lg" + @click="showRadial()" + :style="`position:absolute;left:580px;${radioStatus ? 'background-color: #357de9;' : ''}`" + > <use xlink:href="#issues" /> </svg> <svg diff --git a/src/views/components/topology/topo-endpoint-dependency.vue b/src/views/components/topology/topo-endpoint-dependency.vue index 54839b1..97db853 100644 --- a/src/views/components/topology/topo-endpoint-dependency.vue +++ b/src/views/components/topology/topo-endpoint-dependency.vue @@ -100,7 +100,7 @@ limitations under the License. --> height: 100%; display: flex; flex-direction: column; - overflow: scroll; + overflow: auto; .endpoint-dependency-chart { height: 80%; min-height: 500px; diff --git a/src/views/components/trace/trace-search.vue b/src/views/components/trace/trace-search.vue index 526c1e9..c144176 100644 --- a/src/views/components/trace/trace-search.vue +++ b/src/views/components/trace/trace-search.vue @@ -110,7 +110,7 @@ limitations under the License. --> import TraceSelect from '../common/trace-select.vue'; import { State as traceState } from '@/store/modules/trace/index'; import { State as globalState } from '@/store/modules/global/index'; - import dateFormatStep from '@/utils/dateFormatStep'; + import dateFormatStep from '@/utils/dateFormat'; @Component({ components: { TraceSelect } }) export default class TraceSearch extends Vue { diff --git a/src/views/containers/dashboard.vue b/src/views/containers/dashboard.vue index 51f2866..ee65932 100644 --- a/src/views/containers/dashboard.vue +++ b/src/views/containers/dashboard.vue @@ -44,7 +44,7 @@ limitations under the License. --> </template> <script lang="ts"> - import { Component, Vue, Watch } from 'vue-property-decorator'; + import { Component, Vue } from 'vue-property-decorator'; import { Action, Getter, State, Mutation } from 'vuex-class'; import ToolBar from '@/views/components/dashboard/tool-bar/tool-bar.vue'; import ToolGroup from '@/views/components/dashboard/tool-group.vue'; @@ -54,6 +54,7 @@ limitations under the License. --> import { State as globalState } from '@/store/modules/global'; import { State as optionState } from '@/store/modules/global/selectors'; import { State as dataState } from '@/store/modules/dashboard/dashboard-data'; + import { PageTypes } from '@/constants/constant'; interface ITemplate { name: string; @@ -76,7 +77,7 @@ limitations under the License. --> @State('rocketData') private rocketComps!: dataState; @Action('MIXHANDLE_GET_OPTION') private MIXHANDLE_GET_OPTION: any; @Action('GET_ALL_TEMPLATES') private GET_ALL_TEMPLATES: any; - // @Action('ADD_TEMPLATE') private ADD_TEMPLATE: any; + @Action('GET_EVENT') private GET_EVENT: any; @Getter('durationTime') private durationTime: any; @Mutation('SET_COMPS_TREE') private SET_COMPS_TREE: any; @Mutation('ADD_COMP') private ADD_COMP: any; @@ -104,17 +105,10 @@ limitations under the License. --> duration: this.durationTime, keywordServiceName: this.rocketComps.tree[this.rocketComps.group] && this.rocketComps.tree[this.rocketComps.group].serviceGroup, + pageType: PageTypes.DASHBOARD, }); } private beforeMount() { - // this.ADD_TEMPLATE({ - // name: 'Topology Instance', - // type: 'TOPOLOGY_INSTANCE', - // active: true, - // configuration: JSON.stringify(TopologyInstanceTemp), - // }).then((data: any) => { - // console.log(data); - // }); this.GET_ALL_TEMPLATES().then((allTemplate: ITemplate[]) => { const dashboardTemplate = allTemplate.filter((item: ITemplate) => item.type === 'DASHBOARD'); const templatesConfig = dashboardTemplate.map((item: ITemplate) => JSON.parse(item.configuration)).flat(1); diff --git a/src/views/containers/topology/endpoint/index.vue b/src/views/containers/topology/endpoint/index.vue index 10afc9f..4cc39bf 100644 --- a/src/views/containers/topology/endpoint/index.vue +++ b/src/views/containers/topology/endpoint/index.vue @@ -45,14 +45,24 @@ limitations under the License. --> </span> </div> </span> - <ToolBarSelect :selectable="false" :title="$t('currentService')" :current="current" icon="package" /> - <ToolBarEndpointSelect - @onChoose="selectEndpoint" - :title="$t('currentEndpoint')" - :current="stateDashboardOption.currentEndpoint" - :data="stateDashboardOption.endpoints" - icon="code" - /> + <div class="rk-dashboard-bar-tool flex-h"> + <div class="flex-h"> + <ToolBarSelect :selectable="false" :title="$t('currentService')" :current="current" icon="package" /> + <ToolBarEndpointSelect + @onChoose="selectEndpoint" + :title="$t('currentEndpoint')" + :current="stateDashboardOption.currentEndpoint" + :data="stateDashboardOption.endpoints" + icon="code" + /> + </div> + <DashboardEvent + :rocketComps="rocketComps" + :stateDashboard="stateDashboardOption" + :durationTime="durationTime" + :type="pageEventsType.TOPO_ENDPOINT_EVENTS" + /> + </div> </div> <endpoints-survey :endpointComps="endpointComps" :updateObjects="updateObjects" /> </div> @@ -60,7 +70,7 @@ limitations under the License. --> <script lang="ts"> import Vue from 'vue'; - import { Component, Watch, Prop } from 'vue-property-decorator'; + import { Component, Prop } from 'vue-property-decorator'; import { Action, Getter, State, Mutation } from 'vuex-class'; import EndpointsSurvey from './endpoints-survey.vue'; import ToolBarSelect from '@/views/components/dashboard/tool-bar/tool-bar-select.vue'; @@ -68,36 +78,57 @@ limitations under the License. --> import { readFile } from '@/utils/readFile'; import { saveFile } from '@/utils/saveFile'; import { ObjectsType } from '../../../../constants/constant'; - - interface Endpoint { - label: string; - key: string; - name?: string; - } + import DashboardEvent from '@/views/components/dashboard/tool-bar/dashboard-events.vue'; + import { State as optionState } from '@/store/modules/global/selectors'; + import { State as rocketData } from '@/store/modules/dashboard/dashboard-data'; + import { State as rocketbotGlobal } from '@/store/modules/global'; + import { DurationTime, Option } from '@/types/global'; + import { EntityType } from '@/views/components/dashboard/charts/constant'; + import { PageEventsType } from '@/constants/constant'; @Component({ components: { EndpointsSurvey, ToolBarSelect, ToolBarEndpointSelect, + DashboardEvent, }, }) export default class WindowEndpoint extends Vue { - @State('rocketOption') private stateDashboardOption!: any; - @State('rocketData') private rocketComps!: any; - @State('rocketbot') private rocketGlobal: any; - @Getter('durationTime') private durationTime: any; + @Prop() private current!: { key: number | string; label: number | string }; + @Prop() private endpointComps: any; + @Prop() private updateObjects!: string; + @State('rocketOption') private stateDashboardOption!: optionState; + @State('rocketData') private rocketComps!: rocketData; + @State('rocketbot') private rocketGlobal!: rocketbotGlobal; + @Getter('durationTime') private durationTime!: DurationTime; @Action('SELECT_ENDPOINT') private SELECT_ENDPOINT: any; @Mutation('SET_CURRENT_SERVICE') private SET_CURRENT_SERVICE: any; @Mutation('SET_EDIT') private SET_EDIT: any; @Action('GET_SERVICE_ENDPOINTS') private GET_SERVICE_ENDPOINTS: any; @Action('MIXHANDLE_CHANGE_GROUP_WITH_CURRENT') private MIXHANDLE_CHANGE_GROUP_WITH_CURRENT: any; - @Prop() private current!: { key: number | string; label: number | string }; - @Prop() private endpointComps: any; - @Prop() private updateObjects!: string; + @Action('GET_EVENT') private GET_EVENT: any; + + private pageEventsType = PageEventsType; - private selectEndpoint(i: any) { - this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime }); + private selectEndpoint(i: Option) { + if (!this.rocketComps.enableEvents) { + this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime }); + return; + } + this.GET_EVENT({ + condition: { + time: this.durationTime, + size: 20, + source: { + service: this.stateDashboardOption.currentService.label, + endpoint: i.label, + }, + }, + type: EntityType[2].key, + }).then(() => { + this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime }); + }); } private beforeMount() { @@ -135,7 +166,11 @@ limitations under the License. --> } </script> -<style lang="scss"> +<style lang="scss" scoped> + .rk-dashboard-bar-tool { + width: calc(100% - 160px); + justify-content: space-between; + } .rk-dashboard-bar { flex-shrink: 0; color: #efefef; diff --git a/src/views/containers/topology/instance/index.vue b/src/views/containers/topology/instance/index.vue index f73ab20..b0fae5b 100644 --- a/src/views/containers/topology/instance/index.vue +++ b/src/views/containers/topology/instance/index.vue @@ -16,7 +16,7 @@ limitations under the License. --> <template> <div style="height: 100%"> <div class="rk-dashboard-bar flex-h"> - <span class="flex-h"> + <div class="flex-h"> <div class="rk-dashboard-bar-btn"> <span v-tooltip:bottom="{ content: rocketGlobal.edit ? 'view' : 'edit' }"> <svg @@ -45,60 +45,91 @@ limitations under the License. --> </svg> </span> </div> - </span> - <ToolBarSelect :selectable="false" :title="$t('currentService')" :current="current" icon="package" /> - <ToolBarSelect - @onChoose="selectInstance" - :title="$t('currentInstance')" - :current="stateDashboardOption.currentInstance" - :data="stateDashboardOption.instances" - icon="disk" - /> + </div> + <div class="rk-dashboard-bar-tool flex-h"> + <div class="flex-h"> + <ToolBarSelect :selectable="false" :title="$t('currentService')" :current="current" icon="package" /> + <ToolBarSelect + @onChoose="selectInstance" + :title="$t('currentInstance')" + :current="stateDashboardOption.currentInstance" + :data="stateDashboardOption.instances" + icon="disk" + /> + </div> + <DashboardEvent + :rocketComps="rocketComps" + :stateDashboard="stateDashboardOption" + :durationTime="durationTime" + :type="pageEventsType.TOPO_INSTANCE_EVENTS" + /> + </div> </div> <instances-survey :instanceComps="instanceComps" :updateObjects="updateObjects" /> </div> </template> <script lang="ts"> + import Vue from 'vue'; + import { Component, Prop } from 'vue-property-decorator'; + import { Action, Getter, State, Mutation } from 'vuex-class'; import InstancesSurvey from './instances-survey.vue'; import ToolBarSelect from '@/views/components/dashboard/tool-bar/tool-bar-select.vue'; import ToolBarEndpointSelect from '@/views/components/dashboard/tool-bar/tool-bar-endpoint-select.vue'; - import Vue from 'vue'; - import { Component, PropSync, Watch, Prop } from 'vue-property-decorator'; - import { Action, Getter, State, Mutation } from 'vuex-class'; import { readFile } from '@/utils/readFile'; import { saveFile } from '@/utils/saveFile'; - import { ObjectsType } from '../../../../constants/constant'; - - interface Instance { - label: string; - key: string; - name?: string; - } + import { ObjectsType } from '@/constants/constant'; + import { EntityType } from '@/views/components/dashboard/charts/constant'; + import { DurationTime, Option } from '@/types/global'; + import { State as optionState } from '@/store/modules/global/selectors'; + import { State as rocketData } from '@/store/modules/dashboard/dashboard-data'; + import { State as rocketbotGlobal } from '@/store/modules/global'; + import DashboardEvent from '@/views/components/dashboard/tool-bar/dashboard-events.vue'; + import { PageEventsType } from '@/constants/constant'; @Component({ components: { InstancesSurvey, ToolBarSelect, ToolBarEndpointSelect, + DashboardEvent, }, }) export default class WindowInstance extends Vue { - @State('rocketOption') private stateDashboardOption!: any; - @State('rocketData') private rocketComps!: any; - @State('rocketbot') private rocketGlobal: any; - @Getter('durationTime') private durationTime: any; + @Prop() private current!: { key: number | string; label: number | string }; + @Prop() private instanceComps: any; + @Prop() private updateObjects!: string; + @State('rocketOption') private stateDashboardOption!: optionState; + @State('rocketData') private rocketComps!: rocketData; + @State('rocketbot') private rocketGlobal!: rocketbotGlobal; + @Getter('durationTime') private durationTime!: DurationTime; @Action('SELECT_INSTANCE') private SELECT_INSTANCE: any; @Action('GET_SERVICE_INSTANCES') private GET_SERVICE_INSTANCES: any; @Action('MIXHANDLE_CHANGE_GROUP_WITH_CURRENT') private MIXHANDLE_CHANGE_GROUP_WITH_CURRENT: any; + @Action('GET_EVENT') private GET_EVENT: any; @Mutation('SET_EDIT') private SET_EDIT: any; @Mutation('SET_CURRENT_SERVICE') private SET_CURRENT_SERVICE: any; - @Prop() private current!: { key: number | string; label: number | string }; - @Prop() private instanceComps: any; - @Prop() private updateObjects!: string; - private selectInstance(i: any) { - this.SELECT_INSTANCE({ instance: i, duration: this.durationTime }); + private pageEventsType = PageEventsType; + + private selectInstance(i: Option) { + if (!this.rocketComps.enableEvents) { + this.SELECT_INSTANCE({ instance: i, duration: this.durationTime }); + return; + } + this.GET_EVENT({ + condition: { + time: this.durationTime, + size: 20, + source: { + service: this.stateDashboardOption.currentService.label, + serviceInstance: i.label, + }, + }, + type: EntityType[3].key, + }).then(() => { + this.SELECT_INSTANCE({ instance: i, duration: this.durationTime }); + }); } private beforeMount() { @@ -136,6 +167,15 @@ limitations under the License. --> </script> <style lang="scss" scoped> + .rk-dashboard-bar-tool { + width: calc(100% - 160px); + justify-content: space-between; + } + .rk-dashboard-bar { + flex-shrink: 0; + color: #efefef; + background-color: #333840; + } .rk-dashboard-bar-btn { padding: 0 5px; border-right: 2px solid #252a2f; diff --git a/vue.config.js b/vue.config.js index 7fa74f0..ee2b28d 100644 --- a/vue.config.js +++ b/vue.config.js @@ -21,7 +21,6 @@ module.exports = { proxy: { '/graphql': { target: `${process.env.SW_PROXY_TARGET || 'http://127.0.0.1:12800'}`, - changeOrigin: true, }, },